Skip to content

Commit

Permalink
Feature: Settings
Browse files Browse the repository at this point in the history
  • Loading branch information
Aredruss committed May 1, 2021
1 parent 29c43d5 commit 080f809
Show file tree
Hide file tree
Showing 65 changed files with 875 additions and 451 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ Grab the latest version from [here](https://github.com/Aredruss/Mangatana/releas

### Built With :toolbox:
- [Kotlin](https://kotlinlang.org/) - First class and official programming language for Android development.
- [Coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html) - For implementing asynchronous code
- [Kotlin Coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html) - Lightweight solution for implementing asynchronous code
- [Koin](https://insert-koin.io/) - A smart Kotlin dependency injection library
- [Android Architecture Components](https://developer.android.com/topic/libraries/architecture) - Collection of libraries that help you design robust, testable, and maintainable apps.
- [Flow](https://kotlinlang.org/docs/reference/coroutines/flow.html) - A flow is an asynchronous version of a Sequence, a type of collection values of which are lazily produced.
- [ViewModel](https://developer.android.com/topic/libraries/architecture/viewmodel) - Stores UI-related data that isn't destroyed on UI changes.
- [Room](https://developer.android.com/topic/libraries/architecture/room) - SQLite object mapping library.
- [Datastore](https://developer.android.com/topic/libraries/architecture/datastore) - A data storage solution that allows you to store key-value pairs or typed objects with protocol buffers
- [Material Components for Android](https://github.com/material-components/material-components-android) - Modular and customizable Material Design UI components for Android.
- [Modo](https://github.com/terrakok/Modo) - Modo is an open-source navigation library based on UDF principles for developing Single Activity applications.
- [Figma](https://figma.com/) - Figma is a vector graphics editor and prototyping tool which is primarily web-based.
Expand Down
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ android {

defaultConfig {
applicationId "com.aredruss.mangatana"
minSdkVersion 23
minSdkVersion 22
targetSdkVersion 30
versionCode 1
versionName "v0.0.1"
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
android:allowClearUserData="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
<activity
android:name=".view.MainActivity"
android:theme="@style/AppTheme.Launcher"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@ package com.aredruss.mangatana.data.datastore

data class AppState(
val isDark: Boolean,
val locale: String,
val allowNsfw: Boolean
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.createDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map

class SettingsDataStore(context: Context) {
Expand All @@ -18,26 +18,40 @@ class SettingsDataStore(context: Context) {
return dataStore.data.map { prefs ->
AppState(
isDark = prefs[THEME_KEY] ?: true,
allowNsfw = prefs[AGE_KEY] ?: true,
locale = prefs[LANG_KEY] ?: "en"
allowNsfw = prefs[AGE_KEY] ?: true
)
}
}

suspend fun updateAppState(appState: AppState) {
fun getUiMode(): Flow<Boolean> {
return dataStore.data.map { prefs ->
prefs[THEME_KEY] ?: true
}
}

suspend fun updateTheme(isDark: Boolean) {
dataStore.edit { prefs ->
prefs[THEME_KEY] = appState.isDark
prefs[AGE_KEY] = appState.allowNsfw
prefs[LANG_KEY] = appState.locale
prefs[THEME_KEY] = isDark
}
}

suspend fun updateFilter(allowSmut: Boolean) {
dataStore.edit { prefs ->
prefs[AGE_KEY] = allowSmut
}
}

// Content filter is being delayed until further notice due to the fact that
// API lacks capabilities to filter manga titles by age rating
fun allowNsfw(): Flow<Boolean> = flow {
dataStore.data.map { prefs ->
prefs[AGE_KEY] ?: true
}
}

private companion object {
private const val PREF_FILENAME = "MANGATANA_PREFS"

private val THEME_KEY = booleanPreferencesKey("is_dark")
private val LANG_KEY = stringPreferencesKey("en")
private val AGE_KEY = booleanPreferencesKey("allow_nsfw")
}
}
}
2 changes: 0 additions & 2 deletions app/src/main/java/com/aredruss/mangatana/di/AppModule.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.aredruss.mangatana.di

import settingsModule

val mangatanaModules = listOf(
networkModule,
dataModule,
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/com/aredruss/mangatana/di/DataModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import kotlinx.coroutines.Dispatchers
import org.koin.dsl.module

val dataModule = module {
single { MediaMapper(Dispatchers.Default) }
single { MediaMapper(defaultDispatcher = Dispatchers.Default) }
single { JikanRepository(jikanService = get(), mediaMapper = get()) }
single { DatabaseRepository(mediaDao = get(), mediaMapper = get()) }
}
6 changes: 4 additions & 2 deletions app/src/main/java/com/aredruss/mangatana/di/SettingsModule.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package com.aredruss.mangatana.di

import com.aredruss.mangatana.data.datastore.SettingsDataStore
import com.aredruss.mangatana.view.settings.SettingsViewModel
import org.koin.android.ext.koin.androidContext
Expand All @@ -6,5 +8,5 @@ import org.koin.dsl.module

val settingsModule = module {
single { SettingsDataStore(context = androidContext()) }
viewModel { SettingsViewModel(dataStore = get()) }
}
viewModel { SettingsViewModel(dataStore = get(), databaseRepository = get()) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,21 @@ data class MediaResponse(
@SerializedName("type")
val type: String,
@SerializedName("synopsis")
val synopsis: String,
val synopsis: String?,
@SerializedName("score")
val score: Double,
@SerializedName("genres")
val genreList: List<Genre>,
@SerializedName("title_english")
val altTitle: String?,
@SerializedName(value = "authors", alternate = ["producers"])
val authorList: List<Author>?,
@SerializedName(value = "chapters", alternate = ["episodes"])
val chapters: Int?,
@SerializedName(value = "members")
val viewerCount: Long,
@SerializedName(value = "published", alternate = ["aired"])
val releaseDate: ReleaseDate
val releaseDate: ReleaseDate,
@SerializedName("rating")
val rating: String
)
8 changes: 8 additions & 0 deletions app/src/main/java/com/aredruss/mangatana/modo/Screens.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,11 @@ object Screens {
override fun create() = SettingsFragment.create()
}
}

object ScreenCategory {
const val ON_GOING = 1
const val BACKLOG = 2
const val FINISHED = 3
const val STARRED = 4
const val EXPLORE = 5
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ class DatabaseRepository(
}.flowOn(ioDispatcher)

fun searchCategoryByName(type: String, status: Int, query: String) = flow {
emit(mediaDao.getEntriesByQuery(type, status, query))
emit(mediaDao.getEntriesByQuery(type, status, "$query%"))
}.flowOn(ioDispatcher)

fun searchFavoriteByName(type: String, query: String) = flow {
emit(mediaDao.getEntriesByQueryStatus(type, query))
emit(mediaDao.getEntriesByQueryStatus(type, "$query%"))
}.flowOn(ioDispatcher)

suspend fun upsertMediaEntry(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext

class MediaMapper(
private val defaultDispatcher: CoroutineDispatcher
private val defaultDispatcher: CoroutineDispatcher,
) {

suspend fun mapToMedia(
Expand Down
15 changes: 14 additions & 1 deletion app/src/main/java/com/aredruss/mangatana/view/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,27 @@ import androidx.core.view.forEach
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction
import androidx.lifecycle.lifecycleScope
import by.kirich1409.viewbindingdelegate.viewBinding
import com.aredruss.mangatana.App
import com.aredruss.mangatana.R
import com.aredruss.mangatana.data.datastore.SettingsDataStore
import com.aredruss.mangatana.databinding.ActivityMainBinding
import com.aredruss.mangatana.modo.Screens
import com.aredruss.mangatana.view.extensions.changeTheme
import com.github.terrakok.modo.android.AppScreen
import com.github.terrakok.modo.android.ModoRender
import com.github.terrakok.modo.android.init
import com.github.terrakok.modo.back
import com.github.terrakok.modo.forward
import kotlinx.coroutines.flow.first
import org.koin.android.ext.android.inject

class MainActivity : AppCompatActivity(R.layout.activity_main) {

private val binding: ActivityMainBinding by viewBinding(R.id.main_cl)
private val modo = App.INSTANCE.modo
private val dataStore: SettingsDataStore by inject()

var menu: Menu? = null

Expand Down Expand Up @@ -51,8 +57,9 @@ class MainActivity : AppCompatActivity(R.layout.activity_main) {
}

override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.AppTheme)
applyColorTheme()
super.onCreate(savedInstanceState)

binding.apply {
setContentView(root)
}
Expand Down Expand Up @@ -96,4 +103,10 @@ class MainActivity : AppCompatActivity(R.layout.activity_main) {
modo.back()
return true
}

private fun applyColorTheme() {
lifecycleScope.launchWhenCreated {
changeTheme(dataStore.getUiMode().first())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import android.content.Intent
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.net.Uri
import android.os.Build
import androidx.appcompat.app.AppCompatDelegate
import com.aredruss.mangatana.R

fun Activity.openLink(url: String) {
Expand All @@ -31,11 +33,17 @@ fun Activity.shareLink(url: String) {

fun Activity.isOnline(): Boolean {
val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val netInfo = cm.getNetworkCapabilities(cm.activeNetwork)
netInfo != null && netInfo.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
} else {
val netInfo = cm.activeNetworkInfo
netInfo != null && netInfo.isConnected
}
}

fun Activity.changeTheme(isDark: Boolean) {
AppCompatDelegate.setDefaultNightMode(
if (isDark) AppCompatDelegate.MODE_NIGHT_YES else AppCompatDelegate.MODE_NIGHT_NO
)
}
14 changes: 11 additions & 3 deletions app/src/main/java/com/aredruss/mangatana/view/extensions/View.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,17 @@ fun Button.setDrawableEnd(id: Int) {
)
}

fun RadioButton.setIconText(icon: Int, text: Int) {
setDrawableEnd(icon)
fun RadioButton.setIconText(icon: Int?, text: Int) {
if (icon != null) setDrawableEnd(icon)
setText(text)
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
}

fun RadioButton.setIconText(icon: Int?, text: String) {
if (icon != null) setDrawableEnd(icon)
setText(text)
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
Expand All @@ -47,4 +56,3 @@ fun SearchView.hide() {
this.gone()
onActionViewCollapsed()
}

Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,3 @@ fun ViewBinding.getColor(id: Int) = if (android.os.Build.VERSION.SDK_INT >= andr
}

fun ViewBinding.getDrawable(id: Int) = ContextCompat.getDrawable(root.context, id)

fun ViewBinding.getStringArray(id: Int) = context().resources.getStringArray(id)
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import android.widget.PopupMenu
import by.kirich1409.viewbindingdelegate.viewBinding
import com.aredruss.mangatana.R
import com.aredruss.mangatana.databinding.FragmentHomeBinding
import com.aredruss.mangatana.modo.ScreenCategory
import com.aredruss.mangatana.modo.Screens
import com.aredruss.mangatana.view.util.BaseFragment
import com.aredruss.mangatana.view.util.ScreenCategory
import com.github.terrakok.modo.forward

class HomeFragment : BaseFragment(R.layout.fragment_home) {
Expand Down
Loading

0 comments on commit 080f809

Please sign in to comment.