diff --git a/.idea/misc.xml b/.idea/misc.xml index a210768..2bb228a 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -4,33 +4,37 @@ diff --git a/README.md b/README.md index 673e87e..efcd314 100644 --- a/README.md +++ b/README.md @@ -7,3 +7,6 @@ Native Android Application to show the data on https://islamqa.org/. + +Islamic graphic vector created by +rawpixel.com - www.freepik.com \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index aae6a32..dccada3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -99,4 +99,7 @@ dependencies { implementation 'androidx.preference:preference:1.2.0' implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.2" + + implementation 'com.github.bumptech.glide:glide:4.13.2' + annotationProcessor 'com.github.bumptech.glide:compiler:4.13.2' } diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 481bb43..a8c234f 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -18,4 +18,16 @@ # If you keep the line number information, uncomment this to # hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file +#-renamesourcefileattribute SourceFile + +-keep public class * implements com.bumptech.glide.module.GlideModule +-keep class * extends com.bumptech.glide.module.AppGlideModule { + (...); +} +-keep public enum com.bumptech.glide.load.ImageHeaderParser$** { + **[] $VALUES; + public *; +} +-keep class com.bumptech.glide.load.data.ParcelFileDescriptorRewinder$InternalRewinder { + *** rewind(); +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1b0b5e5..e40c787 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -13,14 +13,14 @@ android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" - android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" tools:targetApi="31"> + android:exported="true" + android:theme="@style/StartTheme"> diff --git a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/common/utility/ktx/View.kt b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/common/utility/ktx/View.kt index 8af0a89..5b84c57 100644 --- a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/common/utility/ktx/View.kt +++ b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/common/utility/ktx/View.kt @@ -1,6 +1,9 @@ package io.github.kabirnayeem99.islamqaorg.common.utility.ktx import android.view.View +import android.view.animation.AccelerateDecelerateInterpolator +import android.view.animation.Animation +import android.view.animation.RotateAnimation import com.google.android.material.snackbar.Snackbar fun View.showUserMessage(userMessage: String) { @@ -16,4 +19,18 @@ fun View.showUserMessage(userMessage: String) { */ fun View.viewVisibility(visibility: Int) { this.visibility = visibility +} + +fun View.rotateViewOneEighty(duration: Long = 5000L) { + val rotate = RotateAnimation( + 0F, + 180F, + Animation.RELATIVE_TO_SELF, + 0.5f, + Animation.RELATIVE_TO_SELF, + 0.5f + ) + rotate.duration = duration + rotate.interpolator = AccelerateDecelerateInterpolator() + startAnimation(rotate) } \ No newline at end of file diff --git a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dataSource/IslamQaLocalDataSource.kt b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dataSource/IslamQaLocalDataSource.kt index 781bf00..ec312ce 100644 --- a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dataSource/IslamQaLocalDataSource.kt +++ b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dataSource/IslamQaLocalDataSource.kt @@ -79,19 +79,22 @@ class IslamQaLocalDataSource @Inject constructor( return withContext(Dispatchers.IO) { try { - val dto = questionDetailDao.getQuestionByLink(url) + var detail: QuestionDetail? = null - val detail = QuestionDetail( - questionTitle = dto.questionTitle, - detailedQuestion = dto.detailedQuestion, - detailedAnswer = dto.detailedAnswer, - fiqh = dto.fiqh, - source = dto.source, - originalLink = dto.originalLink, - nextQuestionLink = dto.nextQuestionLink, - previousQuestionLink = dto.previousQuestionLink, - relevantQuestions = getQuestionList(), - ) + questionDetailDao.getQuestionByLink(url)?.let { dto -> + + detail = QuestionDetail( + questionTitle = dto.questionTitle, + detailedQuestion = dto.detailedQuestion, + detailedAnswer = dto.detailedAnswer, + fiqh = dto.fiqh, + source = dto.source, + originalLink = dto.originalLink, + nextQuestionLink = dto.nextQuestionLink, + previousQuestionLink = dto.previousQuestionLink, + relevantQuestions = getQuestionList(), + ) + } Timber.d(detail.toString()) diff --git a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dataSource/IslamQaRemoteDataSource.kt b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dataSource/IslamQaRemoteDataSource.kt index 84d5767..62586c9 100644 --- a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dataSource/IslamQaRemoteDataSource.kt +++ b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dataSource/IslamQaRemoteDataSource.kt @@ -64,7 +64,7 @@ class IslamQaRemoteDataSource @Inject constructor(private val scrapingService: S val questionAnswer = mutableListOf() qList.questions.forEachIndexed { index, question -> val answerLink = qList.questionLinks[index] - questionAnswer.add(Question(index, question, answerLink)) + questionAnswer.add(Question(index, question, answerLink, fiqh.displayName)) } questionAnswer.ifEmpty { throw Exception("Failed to parse links of the questions") } } @@ -96,7 +96,7 @@ class IslamQaRemoteDataSource @Inject constructor(private val scrapingService: S relevantQuestions = dto.relevantQuestions, ) - Timber.d(detail.toString()) + Timber.d("getDetailedQuestionAndAnswer -> $detail") detail } diff --git a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dataSource/localDb/QuestionDetailDao.kt b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dataSource/localDb/QuestionDetailDao.kt index 0df6c84..ca48626 100644 --- a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dataSource/localDb/QuestionDetailDao.kt +++ b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dataSource/localDb/QuestionDetailDao.kt @@ -23,6 +23,6 @@ interface QuestionDetailDao { * @param link String */ @Query("SELECT * FROM questiondetailentity WHERE originalLink=:link") - suspend fun getQuestionByLink(link: String): QuestionDetailEntity + suspend fun getQuestionByLink(link: String): QuestionDetailEntity? } \ No newline at end of file diff --git a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dataSource/service/ScrapingService.kt b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dataSource/service/ScrapingService.kt index 1ea1616..8bb00ef 100644 --- a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dataSource/service/ScrapingService.kt +++ b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dataSource/service/ScrapingService.kt @@ -5,8 +5,6 @@ import io.github.kabirnayeem99.islamqaorg.data.dto.islamQa.QuestionDetailScreenD import io.github.kabirnayeem99.islamqaorg.data.dto.islamQa.RandomQuestionListDto import io.github.kabirnayeem99.islamqaorg.domain.entity.Fiqh import io.github.kabirnayeem99.islamqaorg.domain.entity.Question -import io.github.serpro69.kfaker.Faker -import io.github.serpro69.kfaker.faker import it.skrape.core.document import it.skrape.fetcher.HttpFetcher import it.skrape.fetcher.Result @@ -35,7 +33,7 @@ class ScrapingService { val islamQaHomeDto = skrape(HttpFetcher) { request { url = homeScreenUrl } - response { getIslamQaHomeDtoOutOfResponse() } + response { getRandomQuestionListDtoOutOfResponse() } } Timber.d(islamQaHomeDto.toString()) @@ -47,7 +45,7 @@ class ScrapingService { /** * Parses the HTML response and returns [RandomQuestionListDto] class. */ - private fun Result.getIslamQaHomeDtoOutOfResponse() = RandomQuestionListDto( + private fun Result.getRandomQuestionListDtoOutOfResponse() = RandomQuestionListDto( httpStatusCode = status { code }, httpStatusMessage = status { message }, questions = document.findAll("li") @@ -55,6 +53,7 @@ class ScrapingService { questionLinks = document.li { a { findAll { filter { it.className == "arpw-title" }.eachHref } } } ) + /** * Fetches the details of a specific question from islamqa.org, parses it, and converts it to a * [QuestionDetailScreenDto] object. @@ -91,12 +90,17 @@ class ScrapingService { /** * Parses the detailed answer from IslamQA.org, if it exists */ - private fun Result.getDetailedAnswer() = document.div { - findAll { - filter { it.className == "ddb-answer" }.eachText.joinToString( - "\n" - ) + private fun Result.getDetailedAnswer() = try { + document.div { + findAll { + filter { it.className == "ddb-answer" }.eachText.joinToString( + "\n" + ) + } } + } catch (e: Exception) { + Timber.e(e, "Failed to get detailed answer") + "" } /** @@ -107,11 +111,16 @@ class ScrapingService { * @receiver Result * @return String */ - private fun Result.getDetailedQuestionAsHtmlText() = document.div { - findAll { - "" + filter { it.id == "qna_only" }.html.removePrefix("
") - .removeSuffix("
") + "" + private fun Result.getDetailedQuestionAsHtmlText() = try { + document.div { + findAll { + "" + filter { it.id == "qna_only" }.html.removePrefix("
") + .removeSuffix("
") + "" + } } + } catch (e: Exception) { + Timber.e(e, "Failed to parse the detailed question -> ${e.message}") + "

No Questions found.

" } enum class Page { @@ -130,21 +139,26 @@ class ScrapingService { */ private fun Result.getPrevOrNextLink(prevOrNext: Page): String { - val classNameForPrevOrNext = when (prevOrNext) { - Page.PREV -> "nav-previous" - Page.NEXT -> "nav-next" - } + try { + val classNameForPrevOrNext = when (prevOrNext) { + Page.PREV -> "nav-previous" + Page.NEXT -> "nav-next" + } - return document.div { - findAll { - span { - findAll { - first { it.className == classNameForPrevOrNext }.a { - findAll { eachHref.firstOrNull() ?: "" } + return document.div { + findAll { + span { + findAll { + first { it.className == classNameForPrevOrNext }.a { + findAll { eachHref.firstOrNull() ?: "" } + } } } } } + } catch (e: Exception) { + Timber.e(e, "Failed to get $prevOrNext url -> ${e.message}.") + return "" } } @@ -155,50 +169,102 @@ class ScrapingService { * `li` elements within the `ul` element and then map the `li` elements to a `Question` object */ private fun Result.getRelevantQuestionsFromQuestionDetails(): List { - return document.div { - findAll { - first { it.className == "crp_related_widget" }.ul { - li { - findAll { - map { - Question( - id = Random.nextInt(50), - question = it.text, - url = it.eachHref.firstOrNull() ?: "" - ) + return try { + document.div { + findAll { + first { it.className == "crp_related_widget" }.ul { + li { + findAll { + map { + Question( + id = Random.nextInt(50), + question = it.text, + url = it.eachHref.firstOrNull() ?: "" + ) + } } } } } } + } catch (e: Exception) { + Timber.e(e, "Failed to get relevant questions from $this -> ${e.message}") + emptyList() } } - private val faker: Faker by lazy { - faker {} - } + /** + * Makes a network call to the IslamQa.org, gets the html response, parses it + * and converts it into a [FiqhBasedQuestionListDto] + * + * @param fiqh Fiqh - The Fiqh for which the questions are to be fetched. + * @param pageNumber The page number of the questions list. + * @return A list of questions. + */ + suspend fun parseFiqhBasedQuestionsList(fiqh: Fiqh, pageNumber: Int): FiqhBasedQuestionListDto { + + return withContext(Dispatchers.IO) { + + val fiqhParamName = if (fiqh == Fiqh.UNKNOWN) Fiqh.HANAFI.paramName else fiqh.paramName - fun parseFiqhBasedQuestionsList(fiqh: Fiqh, pageNumber: Int): FiqhBasedQuestionListDto { + Timber.d("Getting question for $fiqhParamName of page $pageNumber.") - val listOfQuestions = mutableListOf() - val listOfQuestionLinks = mutableListOf() + val fiqhBasedQuestionUrl = "https://islamqa.org/category/${fiqhParamName}/" - Timber.d("Getting list of $fiqh based questions with page $pageNumber") + Timber.d("URL is $fiqhBasedQuestionUrl") - for (index in 1..18) { - val question = "Ulema of Deoband $index" - val questionLink = "https://islamqa.org/hanafi/muftionline/95119/ulema-of-deoband/" - listOfQuestions.add(question) - listOfQuestionLinks.add(questionLink) + val fiqhBasedQuestionListDto = skrape(HttpFetcher) { + request { url = fiqhBasedQuestionUrl } + response { getFiqhBasedQuestionListDtoOutOfResponse(fiqh) } + } + + Timber.d(fiqhBasedQuestionListDto.toString()) + + fiqhBasedQuestionListDto } + } - return FiqhBasedQuestionListDto( - 200, - "No problem", - listOfQuestions, - listOfQuestionLinks, + /** + * Parses the HTML response and returns [FiqhBasedQuestionListDto] class. + */ + private fun Result.getFiqhBasedQuestionListDtoOutOfResponse(fiqh: Fiqh): FiqhBasedQuestionListDto { + val dto = FiqhBasedQuestionListDto( + httpStatusCode = status { code }, + httpStatusMessage = status { message }, + questions = getFiqhBasedQuestionsFromResult(), + questionLinks = getQuestionLinksForFiqhBasedQuestions(), + fiqh = fiqh ) + + Timber.d("FiqhBasedQuestionListDto -> $dto") + return dto + } + + private fun Result.getFiqhBasedQuestionsFromResult() = try { + document.h1 { + findAll { + filter { it.className == "entry-title" }.eachText + .filterIndexed { index, _ -> index != 0 } + } + } + } catch (e: Exception) { + Timber.e(e, "Failed to get questions -> ${e.message}.") + emptyList() + } + + private fun Result.getQuestionLinksForFiqhBasedQuestions() = try { + document.h1 { + findAll { + filter { it.className == "entry-title" }.map { + it.eachHref.joinToString(",") + }.filterIndexed { index, _ -> index != 0 } + + } + } + } catch (e: Exception) { + Timber.e(e, "Failed to get question links -> ${e.message}.") + emptyList() } } \ No newline at end of file diff --git a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dto/islamQa/FiqhBasedQuestionListDto.kt b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dto/islamQa/FiqhBasedQuestionListDto.kt index f6b2cea..36c7ede 100644 --- a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dto/islamQa/FiqhBasedQuestionListDto.kt +++ b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/dto/islamQa/FiqhBasedQuestionListDto.kt @@ -1,9 +1,13 @@ package io.github.kabirnayeem99.islamqaorg.data.dto.islamQa +import io.github.kabirnayeem99.islamqaorg.domain.entity.Fiqh + data class FiqhBasedQuestionListDto( val httpStatusCode: Int, val httpStatusMessage: String, - val questions: List, - val questionLinks: List + val questions + : List, + val questionLinks: List, + val fiqh: Fiqh = Fiqh.HANAFI, ) diff --git a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/repository/QuestionAnswerRepositoryImpl.kt b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/repository/QuestionAnswerRepositoryImpl.kt index 2d4f282..a7b40f1 100644 --- a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/repository/QuestionAnswerRepositoryImpl.kt +++ b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/data/repository/QuestionAnswerRepositoryImpl.kt @@ -91,7 +91,6 @@ class QuestionAnswerRepositoryImpl } } - private var inMemoryQuestionDetail = QuestionDetail() /** * Fetches the question details based on the URL @@ -107,37 +106,46 @@ class QuestionAnswerRepositoryImpl * @return A flow of resources. */ override suspend fun getQuestionDetails(url: String): Flow> { - val questionDetail = inMemoryMutex.withLock { inMemoryQuestionDetail } return flow { try { + emit(Resource.Loading()) val questionDetailLocal = localDataSource.getDetailedQuestionAndAnswer(url) questionDetailLocal?.let { - inMemoryMutex.withLock { inMemoryQuestionDetail = it } + kotlinx.coroutines.delay(1600) emit(Resource.Success(it)) } if (isNetworkAvailable) { val questionDetailed = remoteDataSource.getDetailedQuestionAndAnswer(url) - inMemoryMutex.withLock { inMemoryQuestionDetail = questionDetailed } - localDataSource.cacheQuestionDetail(questionDetail) + localDataSource.cacheQuestionDetail(questionDetailed) emit(Resource.Success(questionDetailed)) } } catch (e: Exception) { + Timber.e(e, "Failed to get the detailed question -> ${e.message}.") emit(Resource.Error(e.localizedMessage ?: "Failed to get the detailed question.")) } - }.onStart { - if (questionDetail.originalLink == url) emit(Resource.Success(questionDetail)) - else emit(Resource.Loading()) }.flowOn(Dispatchers.IO) } private suspend fun getCurrentlySelectedFiqh(): Fiqh { - return preferenceDataSource.getPreferredFiqh() + val preferredFiqh = preferenceDataSource.getPreferredFiqh() + if (preferredFiqh == Fiqh.UNKNOWN) { + preferenceDataSource.savePreferredFiqh(Fiqh.HANAFI) + return Fiqh.HANAFI + } + return preferredFiqh } private var inMemoryFiqhBasedQuestionList = emptyList() + /** + * Gets questions list based on the preferred [Fiqh] of the user + * + * @param pageNumber Int - the page number from which the questions will be loaded. + * @param shouldRefresh Boolean - whether the data should be fetched from website or from local cache + * @return a flow of the [Question] list wrapped in a [Resource] class. + */ override suspend fun getFiqhBasedQuestionList( pageNumber: Int, shouldRefresh: Boolean, diff --git a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/domain/entity/Fiqh.kt b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/domain/entity/Fiqh.kt index 5fc4a1f..39be47c 100644 --- a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/domain/entity/Fiqh.kt +++ b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/domain/entity/Fiqh.kt @@ -1,10 +1,16 @@ package io.github.kabirnayeem99.islamqaorg.domain.entity -enum class Fiqh(val paramName: String) { - HANAFI("hanafi"), - MALIKI("maliki"), - SHAFII("shafii"), - HANBALI("hanbali"), - UNKNOWN(""), - +/** + * Fiqh is Islamic jurisprudence. Fiqh is often described as the human understanding and practices + * of the sharia, that is human understanding of the divine Islamic law as revealed in the Quran + * and the Sunnah. + * + * @property paramName String - the name of the Fiqh to pass to IslamQA + */ +enum class Fiqh(val paramName: String, val displayName: String) { + HANAFI("hanafi", "Hanafi"), + MALIKI("maliki", "Maliki"), + SHAFII("shafii", "Shafii"), + HANBALI("hanbali", "Hanbali"), + UNKNOWN("", ""), } \ No newline at end of file diff --git a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/domain/entity/Question.kt b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/domain/entity/Question.kt index 7917bbf..16b4a6c 100644 --- a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/domain/entity/Question.kt +++ b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/domain/entity/Question.kt @@ -12,4 +12,5 @@ data class Question( val id: Int = 0, val question: String = "", val url: String = "", + val fiqh: String = "", ) diff --git a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/home/HomeFragment.kt b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/home/HomeFragment.kt index ed04f1a..a86c6bf 100644 --- a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/home/HomeFragment.kt +++ b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/home/HomeFragment.kt @@ -7,18 +7,20 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import androidx.recyclerview.widget.LinearLayoutManager +import com.bumptech.glide.request.transition.DrawableCrossFadeFactory import dagger.hilt.android.AndroidEntryPoint import io.github.kabirnayeem99.islamqaorg.R import io.github.kabirnayeem99.islamqaorg.common.base.BaseFragment +import io.github.kabirnayeem99.islamqaorg.common.utility.ktx.rotateViewOneEighty import io.github.kabirnayeem99.islamqaorg.common.utility.ktx.showUserMessage import io.github.kabirnayeem99.islamqaorg.common.utility.ktx.viewVisibility import io.github.kabirnayeem99.islamqaorg.databinding.FragmentHomeBinding import io.github.kabirnayeem99.islamqaorg.domain.entity.Question import io.github.kabirnayeem99.islamqaorg.ui.MainActivity -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch +import kotlinx.coroutines.* import javax.inject.Inject + @AndroidEntryPoint class HomeFragment : BaseFragment() { @@ -51,20 +53,51 @@ class HomeFragment : BaseFragment() { @Inject lateinit var questionSliderAdapter: QuestionSliderAdapter + private fun handleUiState(uiState: HomeScreenUiState) { uiState.apply { + questionAdapter.submitQuestionList(fiqhBasedQuestions) questionSliderAdapter.submitQuestionList(randomQuestions) + + if (!isRandomQuestionLoading && !isFiqhBasedQuestionsLoading) { + showRotatingGeometryForever() + } + messages.firstOrNull()?.let { userMessage -> binding.root.showUserMessage(userMessage.message) homeViewModel.userMessageShown(userMessage.id) } binding.apply { - sflRandomQuestionLoading.viewVisibility(if (isRandomQuestionLoading) View.VISIBLE else View.GONE) - rvQuestions.viewVisibility(if (isRandomQuestionLoading) View.GONE else View.VISIBLE) - sflFiqhBasedQuestionLoading.viewVisibility(if (isFiqhBasedQuestionsLoading) View.VISIBLE else View.GONE) - rvLatestQuestions.viewVisibility(if (isFiqhBasedQuestionsLoading) View.GONE else View.VISIBLE) + sflRandomQuestionLoading.viewVisibility(if (isRandomQuestionLoading) View.VISIBLE else View.INVISIBLE) + rvQuestions.viewVisibility(if (isRandomQuestionLoading) View.INVISIBLE else View.VISIBLE) + sflFiqhBasedQuestionLoading.viewVisibility(if (isFiqhBasedQuestionsLoading) View.VISIBLE else View.INVISIBLE) + rvLatestQuestions.viewVisibility(if (isFiqhBasedQuestionsLoading) View.INVISIBLE else View.VISIBLE) + } + + slideShowRandomQuestionList(randomQuestions) + } + } + + + private val factory by lazy { + DrawableCrossFadeFactory.Builder().setCrossFadeEnabled(true).build() + } + + private var adapterScrollingJob: Job? = null + + /** + * Smooth scrolls through recyclerview items, to give a feeling of slide show + * + * @param randomQuestions List + */ + private fun slideShowRandomQuestionList(randomQuestions: List) { + adapterScrollingJob?.cancel() + adapterScrollingJob = viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) { + randomQuestions.forEachIndexed { index, _ -> + binding.rvQuestions.smoothScrollToPosition(index) + delay(5000) } } } @@ -92,20 +125,22 @@ class HomeFragment : BaseFragment() { questionSliderAdapter.setOnClickListener { navigateToQuestionDetailsScreen(it) } (activity as MainActivity).setOnSyncButtonClickListener { - showLoadingForAShortTimePeriod() + showRotatingGeometryForever() homeViewModel.getRandomQuestions(true) } (activity as MainActivity).setOnSettingButtonClickListener { navController.navigate(R.id.action_HomeFragment_to_settingsFragment) } + } - private fun showLoadingForAShortTimePeriod() { - viewLifecycleOwner.lifecycleScope.launch { - loading.show() - delay(2000) - loading.dismiss() + private fun showRotatingGeometryForever() { + viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) { + while (viewLifecycleOwner.lifecycleScope.isActive) { + binding.ivDesignGeometry.rotateViewOneEighty(4000) + delay(4000) + } } } diff --git a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/home/QuestionAdapter.kt b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/home/QuestionAdapter.kt index 38354ae..9e7b1da 100644 --- a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/home/QuestionAdapter.kt +++ b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/home/QuestionAdapter.kt @@ -3,11 +3,10 @@ package io.github.kabirnayeem99.islamqaorg.ui.home import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.view.animation.Animation -import android.view.animation.ScaleAnimation import androidx.recyclerview.widget.AsyncListDiffer import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView +import io.github.kabirnayeem99.islamqaorg.common.utility.ktx.viewVisibility import io.github.kabirnayeem99.islamqaorg.databinding.ListQuestionBinding import io.github.kabirnayeem99.islamqaorg.domain.entity.Question @@ -50,38 +49,25 @@ class QuestionAdapter : RecyclerView.Adapter override fun getItemCount(): Int = differ.currentList.size override fun onBindViewHolder(holder: QuestionViewHolder, position: Int) { + val currentQuestion = getQuestionAtIndex(position) + holder.binding.apply { + question = currentQuestion executePendingBindings() - if (onClick != null) root.setOnClickListener { - animate(holder.binding.root, position) - onClick!!(currentQuestion) - } - animate(holder.binding.root, position) - } - } - private fun getQuestionAtIndex(index: Int): Question = differ.currentList[index] ?: Question() + if (onClick != null) root.setOnClickListener { onClick!!(currentQuestion) } + + + val fiqhVisibilityBasedOnFiqhAvailability = + if (currentQuestion.fiqh.isBlank()) View.GONE + else View.VISIBLE - private var lastPosition = -1 - - private fun animate(view: View, position: Int) { - if (position > lastPosition) { - val animation = ScaleAnimation( - 0.0f, - 1.0f, - 0.0f, - 1.0f, - Animation.RELATIVE_TO_SELF, - 0.5f, - Animation.RELATIVE_TO_SELF, - 0.5f - ) - animation.duration = if (lastPosition != -1) (100L * (lastPosition / 2)) else 90 - view.startAnimation(animation) - lastPosition = position + tvSelectedFiqh.viewVisibility(fiqhVisibilityBasedOnFiqhAvailability) } } + private fun getQuestionAtIndex(index: Int): Question = differ.currentList[index] ?: Question() + } \ No newline at end of file diff --git a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/home/QuestionSliderAdapter.kt b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/home/QuestionSliderAdapter.kt index f529eca..0b75207 100644 --- a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/home/QuestionSliderAdapter.kt +++ b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/home/QuestionSliderAdapter.kt @@ -5,6 +5,8 @@ import android.view.ViewGroup import androidx.recyclerview.widget.AsyncListDiffer import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView +import com.bumptech.glide.Glide +import io.github.kabirnayeem99.islamqaorg.R import io.github.kabirnayeem99.islamqaorg.databinding.SlideQuestionBinding import io.github.kabirnayeem99.islamqaorg.domain.entity.Question @@ -51,6 +53,7 @@ class QuestionSliderAdapter : RecyclerView.Adapter() { private fun handleUiState(uiState: QuestionDetailsUiState) { uiState.apply { - if (isLoading) loading.show() - else { - loading.dismiss() - binding.nsvRoot.smoothScrollTo(0, 0) - } + + binding.sflLoading.viewVisibility(if (isLoading) View.VISIBLE else View.GONE) + binding.llContent.viewVisibility(if (isLoading) View.GONE else View.VISIBLE) binding.questionDetail = uiState.questionDetails diff --git a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/settings/SettingsFragment.kt b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/settings/SettingsFragment.kt index ce7753d..6b2ff53 100644 --- a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/settings/SettingsFragment.kt @@ -3,6 +3,7 @@ package io.github.kabirnayeem99.islamqaorg.ui.settings import android.os.Bundle import android.view.View import android.widget.ArrayAdapter +import androidx.core.content.ContextCompat import androidx.fragment.app.viewModels import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope @@ -30,6 +31,12 @@ class SettingsFragment : BaseFragment() { navController.navigate(R.id.action_settingsFragment_to_aboutFragment) } spinFiqh.prompt = getString(R.string.hint_fiqh) + spinFiqh.setPopupBackgroundDrawable( + ContextCompat.getDrawable( + requireContext(), + R.drawable.bg_tappable_rounded + ) + ) val fiqhAdapter = ArrayAdapter.createFromResource( requireContext(), R.array.fiqh_array, diff --git a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/start/StartActivity.kt b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/start/StartActivity.kt index 48c4693..3dec239 100644 --- a/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/start/StartActivity.kt +++ b/app/src/main/java/io/github/kabirnayeem99/islamqaorg/ui/start/StartActivity.kt @@ -6,11 +6,14 @@ import io.github.kabirnayeem99.islamqaorg.BuildConfig import io.github.kabirnayeem99.islamqaorg.R import io.github.kabirnayeem99.islamqaorg.common.base.BaseActivity import io.github.kabirnayeem99.islamqaorg.common.utility.ktx.gotoActivity +import io.github.kabirnayeem99.islamqaorg.common.utility.ktx.rotateViewOneEighty import io.github.kabirnayeem99.islamqaorg.databinding.ActivityStartBinding import io.github.kabirnayeem99.islamqaorg.ui.MainActivity import kotlinx.coroutines.delay import kotlinx.coroutines.launch +const val SPLASH_SCREEN_DURATION: Long = 3000L + class StartActivity : BaseActivity() { override val layout: Int get() = R.layout.activity_start @@ -21,13 +24,17 @@ class StartActivity : BaseActivity() { } private fun initViews() { - binding.tvAppVersionName.text = BuildConfig.VERSION_NAME + binding.apply { + tvAppVersionName.text = BuildConfig.VERSION_NAME + ivBackgroundGeometry.rotateViewOneEighty(SPLASH_SCREEN_DURATION) + } navigateToOtherScreen() } + private fun navigateToOtherScreen() { lifecycleScope.launch { - delay(3000) + delay(SPLASH_SCREEN_DURATION) gotoActivity(MainActivity::class.java, true) } } diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index 1a76d15..0000000 --- a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/app/src/main/res/drawable/bg_banner.jpg b/app/src/main/res/drawable/bg_banner.jpg new file mode 100644 index 0000000..5b4142b Binary files /dev/null and b/app/src/main/res/drawable/bg_banner.jpg differ diff --git a/app/src/main/res/drawable/bg_home.xml b/app/src/main/res/drawable/bg_home.xml new file mode 100644 index 0000000..a8b409b --- /dev/null +++ b/app/src/main/res/drawable/bg_home.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_shimmer_placeholder.xml b/app/src/main/res/drawable/bg_shimmer_placeholder.xml new file mode 100644 index 0000000..c962cb9 --- /dev/null +++ b/app/src/main/res/drawable/bg_shimmer_placeholder.xml @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_tappable_rounded.xml b/app/src/main/res/drawable/bg_tappable_rounded.xml index edf79ad..62e31ba 100644 --- a/app/src/main/res/drawable/bg_tappable_rounded.xml +++ b/app/src/main/res/drawable/bg_tappable_rounded.xml @@ -2,13 +2,13 @@ - + + android:bottom="0.5dp" + android:left="8dp" + android:right="8dp" + android:top="0.5dp" /> diff --git a/app/src/main/res/drawable/ic_islamic_geometric.xml b/app/src/main/res/drawable/ic_islamic_geometric.xml new file mode 100644 index 0000000..f58a664 --- /dev/null +++ b/app/src/main/res/drawable/ic_islamic_geometric.xml @@ -0,0 +1,7030 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml index 5b67963..6a617a7 100644 --- a/app/src/main/res/drawable/ic_launcher_background.xml +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -1,10 +1,10 @@ + android:width="200dp" + android:height="200dp" + android:viewportWidth="200" + android:viewportHeight="200"> diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 867f858..de2483c 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -21,7 +21,8 @@ android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_gravity="center"> + android:layout_gravity="center" + android:background="@color/transparent"> + android:background="@color/md_theme_light_primary"> + + + app:layout_constraintTop_toTopOf="parent"> + app:tint="@color/md_theme_light_onSurface" /> + app:cardCornerRadius="40dp" + app:cardElevation="4dp" + app:layout_constraintEnd_toEndOf="@id/cv_logo" + app:layout_constraintTop_toBottomOf="@id/cv_logo" + app:layout_constraintTop_toTopOf="@id/cv_logo"> diff --git a/app/src/main/res/layout/fragment_about.xml b/app/src/main/res/layout/fragment_about.xml index 9462289..674c631 100644 --- a/app/src/main/res/layout/fragment_about.xml +++ b/app/src/main/res/layout/fragment_about.xml @@ -27,8 +27,8 @@ - + android:orientation="vertical"> + + + android:textSize="46sp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + android:textStyle="bold" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/tv_title" /> @@ -60,13 +77,14 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" + android:layout_marginTop="14dp" android:orientation="vertical" android:visibility="visible" - app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/tv_title" - app:shimmer_base_alpha="0.3"> + app:layout_constraintTop_toBottomOf="@id/tv_relevant_q_n_a_label" + app:shimmer_base_alpha="0.6" + app:shimmer_base_color="@color/md_theme_light_surface"> + android:textStyle="bold" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/sfl_random_question_loading" /> @@ -112,10 +133,10 @@ android:id="@+id/sfl_fiqh_based_question_loading" android:layout_width="match_parent" android:layout_height="wrap_content" - app:layout_constraintBottom_toBottomOf="parent" + android:visibility="visible" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/tv_title"> + app:layout_constraintTop_toBottomOf="@id/tv_fiqh_label"> - + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_question_details.xml b/app/src/main/res/layout/fragment_question_details.xml index 82c9b8d..0f02df1 100644 --- a/app/src/main/res/layout/fragment_question_details.xml +++ b/app/src/main/res/layout/fragment_question_details.xml @@ -1,5 +1,6 @@ @@ -14,73 +15,139 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - - - - - - + android:layout_height="wrap_content"> + - - - - - + + + + + + + + + + + + + + + + + android:layout_margin="12dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toTopOf="parent"> + + + + + + + + + + + + + + + + + + - + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml index 432b752..ef73ea2 100644 --- a/app/src/main/res/layout/fragment_settings.xml +++ b/app/src/main/res/layout/fragment_settings.xml @@ -59,7 +59,7 @@ app:layout_constraintBottom_toBottomOf="@id/tv_about_label" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@id/tv_about_label" - app:tint="?android:textColorPrimary" /> + app:tint="?android:colorPrimary" /> + app:tint="?android:colorPrimary" /> + + @@ -41,14 +40,30 @@ android:layout_height="22dp" android:layout_marginEnd="6dp" android:background="@drawable/bg_icon_rounded" - android:backgroundTint="#11aaaaaa" + android:backgroundTint="@color/trans_primary" android:contentDescription="@string/content_desc_go_to_details" android:padding="5dp" android:src="@drawable/ic_arrow_forward" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" - app:tint="#aaaaaaaa" /> + app:tint="@color/md_theme_light_primary" /> + + + diff --git a/app/src/main/res/layout/slide_question.xml b/app/src/main/res/layout/slide_question.xml index 98b1d6d..0c5838b 100644 --- a/app/src/main/res/layout/slide_question.xml +++ b/app/src/main/res/layout/slide_question.xml @@ -12,29 +12,38 @@ + app:cardElevation="0.8dp" + app:strokeColor="#e7b386"> + android:layout_gravity="center"> + + + app:tint="@color/md_theme_light_onSurface" /> diff --git a/app/src/main/res/layout/slide_question_placeholder.xml b/app/src/main/res/layout/slide_question_placeholder.xml index cb8817a..ffa0e9e 100644 --- a/app/src/main/res/layout/slide_question_placeholder.xml +++ b/app/src/main/res/layout/slide_question_placeholder.xml @@ -12,25 +12,33 @@ + android:layout_gravity="center"> + + + app:tint="#e7b386" /> diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index eca70cf..90f9580 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,5 +1,5 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index eca70cf..0000000 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..b0cb592 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp deleted file mode 100644 index c209e78..0000000 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_back.png b/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_back.png new file mode 100644 index 0000000..80fd7c9 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_back.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_fore.png b/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000..21525bd Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_adaptive_fore.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp deleted file mode 100644 index b2dfe3d..0000000 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..f4c6bed Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp deleted file mode 100644 index 4f0f1d6..0000000 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_back.png b/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_back.png new file mode 100644 index 0000000..b51a72e Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_back.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_fore.png b/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000..4cb70a9 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_adaptive_fore.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp deleted file mode 100644 index 62b611d..0000000 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..6c9e4cf Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp deleted file mode 100644 index 948a307..0000000 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_back.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_back.png new file mode 100644 index 0000000..90118c3 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_back.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000..931ce23 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp deleted file mode 100644 index 1b9a695..0000000 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..5a8e8fa Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp deleted file mode 100644 index 28d4b77..0000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png new file mode 100644 index 0000000..31a7fe4 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000..328157c Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp deleted file mode 100644 index 9287f50..0000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..7298760 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp deleted file mode 100644 index aa7d642..0000000 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png new file mode 100644 index 0000000..871cf92 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png new file mode 100644 index 0000000..11a7ffe Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp deleted file mode 100644 index 9126ae3..0000000 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/app/src/main/res/values-land/dimens.xml b/app/src/main/res/values-land/dimens.xml deleted file mode 100644 index 22d7f00..0000000 --- a/app/src/main/res/values-land/dimens.xml +++ /dev/null @@ -1,3 +0,0 @@ - - 48dp - \ No newline at end of file diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml index 7613b84..1a8d332 100644 --- a/app/src/main/res/values-night/themes.xml +++ b/app/src/main/res/values-night/themes.xml @@ -3,6 +3,7 @@ + + + + + + diff --git a/app/src/main/res/values-v31/themes.xml b/app/src/main/res/values-v31/themes.xml new file mode 100644 index 0000000..70bfcaf --- /dev/null +++ b/app/src/main/res/values-v31/themes.xml @@ -0,0 +1,38 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-w1240dp/dimens.xml b/app/src/main/res/values-w1240dp/dimens.xml deleted file mode 100644 index d73f4a3..0000000 --- a/app/src/main/res/values-w1240dp/dimens.xml +++ /dev/null @@ -1,3 +0,0 @@ - - 200dp - \ No newline at end of file diff --git a/app/src/main/res/values-w600dp/dimens.xml b/app/src/main/res/values-w600dp/dimens.xml deleted file mode 100644 index 22d7f00..0000000 --- a/app/src/main/res/values-w600dp/dimens.xml +++ /dev/null @@ -1,3 +0,0 @@ - - 48dp - \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 662f281..8868b80 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,5 +1,6 @@ #933C87 + #66933C87 #FFFFFF #FFD7F2 #390034 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3548982..4995f48 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -21,10 +21,11 @@ Go to GitHub App Source Code - + Fiqh - Select your preferred Fiqh + Select your preferred madhab. Learn more about this application Info Preferences + Madhab \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 9ee98e3..2cede77 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -2,6 +2,8 @@ + + + + diff --git a/doc/images/demo_details_page.png b/doc/images/demo_details_page.png index a509380..034d07d 100644 Binary files a/doc/images/demo_details_page.png and b/doc/images/demo_details_page.png differ diff --git a/doc/images/demo_home_screen.png b/doc/images/demo_home_screen.png index 3d44140..0518e32 100644 Binary files a/doc/images/demo_home_screen.png and b/doc/images/demo_home_screen.png differ