Skip to content

Commit

Permalink
[feature|optimize|fix|doc]支持更换主题;引入DataStore;修复navController.popBackS…
Browse files Browse the repository at this point in the history
…tack()方法使用问题(google/accompanist#1320
  • Loading branch information
SkyD666 committed Mar 14, 2023
1 parent 90cbf01 commit da1d19a
Show file tree
Hide file tree
Showing 58 changed files with 1,790 additions and 559 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
![ic_add_screen_edit](image/ic_add_screen_edit.jpg) ![ic_search_config_screen](image/ic_search_config_screen.jpg)
![ic_process_text_menu](image/ic_process_text_menu.jpg) ![ic_auto_fill_menu](image/ic_auto_fill_menu.jpg)
![ic_import_export_screen](image/ic_import_export_screen.jpg) ![ic_easy_usage_screen](image/ic_easy_usage_screen.jpg)
![ic_appearance_screen](image/ic_appearance_screen.jpg) ![ic_webdav_screen](image/ic_webdav_screen.jpg)
![ic_more_screen](image/ic_more_screen.jpg) ![ic_about_screen](image/ic_about_screen.jpg)

## 🛠主要技术栈
Expand All @@ -61,6 +62,7 @@
- **Material You**
- **ViewModel**
- **Hilt**
- **DataStore**
- Room
- Splash Screen
- Navigation
Expand Down
13 changes: 8 additions & 5 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ android {
applicationId "com.skyd.raca"
minSdk 24
targetSdk 33
versionCode 2
versionName "1.1"
versionCode 3
versionName "1.2"
flavorDimensions "versionName"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
Expand Down Expand Up @@ -91,6 +91,8 @@ android {
excludes += 'DebugProbesKt.bin'
excludes += 'kotlin-tooling-metadata.json'
excludes += 'okhttp3/internal/publicsuffix/NOTICE'
excludes += 'XPP3_1.1.3.3_VERSION'
excludes += 'XPP3_1.1.3.2_VERSION'
}
}
}
Expand Down Expand Up @@ -134,15 +136,16 @@ dependencies {
implementation "com.google.accompanist:accompanist-pager:$accompanist_version"
implementation "com.google.accompanist:accompanist-flowlayout:$accompanist_version"
implementation "io.coil-kt:coil-compose:2.1.0"
implementation "androidx.profileinstaller:profileinstaller:1.3.0-beta01"
implementation "androidx.profileinstaller:profileinstaller:1.3.0-rc01"
implementation "androidx.core:core-splashscreen:1.0.0"
implementation "androidx.room:room-runtime:2.5.0"
implementation "androidx.room:room-ktx:2.5.0"
ksp "androidx.room:room-compiler:2.5.0"
implementation "com.google.code.gson:gson:2.10.1"
implementation "com.github.doyaaaaaken:kotlin-csv-jvm:1.8.0" // for JVM platform
implementation "com.github.doyaaaaaken:kotlin-csv-jvm:1.8.0"
implementation "com.github.thegrizzlylabs:sardine-android:0.8"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0"
implementation "com.github.Kyant0:Monet:0.1.0-alpha03"
implementation "androidx.datastore:datastore-preferences:1.0.0"

debugImplementation "androidx.compose.ui:ui-tooling:$md3_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:$md3_version"
Expand Down
10 changes: 8 additions & 2 deletions app/src/main/java/com/skyd/raca/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ package com.skyd.raca

import android.app.Application
import android.content.Context
import com.skyd.raca.config.initDarkMode
import androidx.appcompat.app.AppCompatDelegate
import com.skyd.raca.ext.dataStore
import com.skyd.raca.ext.get
import com.skyd.raca.model.preference.theme.DarkModePreference
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
Expand All @@ -12,7 +15,10 @@ class App : Application() {
super.onCreate()
appContext = this

initDarkMode()
AppCompatDelegate.setDefaultNightMode(
dataStore.get(DarkModePreference.key) ?: DarkModePreference.default
)

}
}

Expand Down
10 changes: 0 additions & 10 deletions app/src/main/java/com/skyd/raca/config/HomeConfig.kt

This file was deleted.

34 changes: 0 additions & 34 deletions app/src/main/java/com/skyd/raca/config/SearchConfig.kt
Original file line number Diff line number Diff line change
@@ -1,53 +1,19 @@
package com.skyd.raca.config

import com.skyd.raca.ext.editor
import com.skyd.raca.ext.sharedPreferences
import com.skyd.raca.model.bean.ARTICLE_TABLE_NAME
import com.skyd.raca.model.bean.ArticleBean.Companion.ARTICLE_COLUMN
import com.skyd.raca.model.bean.ArticleBean.Companion.TITLE_COLUMN
import com.skyd.raca.model.bean.ArticleBean.Companion.UUID_COLUMN
import com.skyd.raca.model.bean.TAG_TABLE_NAME
import com.skyd.raca.model.bean.TagBean.Companion.TAG_COLUMN

var useRegexSearch = sharedPreferences().getBoolean("useRegexSearch", false)
set(value) {
field = value
sharedPreferences().editor { putBoolean("useRegexSearch", value) }
}

val allSearchDomain: HashMap<Pair<String, String>, List<Pair<String, String>>> = hashMapOf(
(ARTICLE_TABLE_NAME to "段落表") to listOf(
UUID_COLUMN to "UUID",
TITLE_COLUMN to "标题",
ARTICLE_COLUMN to "段落",
),
(TAG_TABLE_NAME to "标签表") to listOf(
// ARTICLE_ID_COLUMN to "段落ID",
TAG_COLUMN to "标签",
// CREATE_TIME_COLUMN to "创建时间"
),
)

fun setSearchDomain(
tableName: String,
columnName: String,
search: Boolean
) {
sharedPreferences("SearchDomain").editor {
putBoolean("${tableName}/${columnName}", search)
}
}

fun getSearchDomain(
tableName: String,
columnName: String,
): Boolean {
return sharedPreferences("SearchDomain")
.getBoolean(
"${tableName}/${columnName}",
if (tableName == ARTICLE_TABLE_NAME && (columnName == TITLE_COLUMN || columnName == ARTICLE_COLUMN)) {
true
} else tableName == TAG_TABLE_NAME && columnName == TAG_COLUMN
)
}

50 changes: 0 additions & 50 deletions app/src/main/java/com/skyd/raca/config/ThemeConfig.kt

This file was deleted.

5 changes: 4 additions & 1 deletion app/src/main/java/com/skyd/raca/db/AppDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ import androidx.room.TypeConverters
import androidx.room.migration.Migration
import com.skyd.raca.appContext
import com.skyd.raca.db.dao.ArticleDao
import com.skyd.raca.db.dao.SearchDomainDao
import com.skyd.raca.db.dao.TagDao
import com.skyd.raca.model.bean.ArticleBean
import com.skyd.raca.model.bean.SearchDomainBean
import com.skyd.raca.model.bean.TagBean

const val APP_DATA_BASE_FILE_NAME = "app.db"

@Database(
entities = [ArticleBean::class, TagBean::class], version = 1
entities = [ArticleBean::class, TagBean::class, SearchDomainBean::class], version = 1
)
@TypeConverters(
value = []
Expand All @@ -24,6 +26,7 @@ abstract class AppDatabase : RoomDatabase() {

abstract fun articleDao(): ArticleDao
abstract fun tagDao(): TagDao
abstract fun searchDomainDao(): SearchDomainDao

companion object {
private var instance: AppDatabase? = null
Expand Down
33 changes: 33 additions & 0 deletions app/src/main/java/com/skyd/raca/db/dao/SearchDomainDao.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.skyd.raca.db.dao

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.skyd.raca.model.bean.*
import com.skyd.raca.model.bean.SearchDomainBean.Companion.COLUMN_NAME_COLUMN
import com.skyd.raca.model.bean.SearchDomainBean.Companion.SEARCH_COLUMN
import com.skyd.raca.model.bean.SearchDomainBean.Companion.TABLE_NAME_COLUMN

@Dao
interface SearchDomainDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun setSearchDomain(searchDomainBean: SearchDomainBean)

@Query(
value = "SELECT $SEARCH_COLUMN FROM $SEARCH_DOMAIN_TABLE_NAME" +
" WHERE $TABLE_NAME_COLUMN LIKE :tableName AND $COLUMN_NAME_COLUMN LIKE :columnName"
)
fun getSearchDomainOrNull(tableName: String, columnName: String): Boolean?

fun getSearchDomain(tableName: String, columnName: String): Boolean {
return getSearchDomainOrNull(tableName, columnName)
?: if (tableName == ARTICLE_TABLE_NAME &&
(columnName == ArticleBean.TITLE_COLUMN ||
columnName == ArticleBean.ARTICLE_COLUMN)
) true else tableName == TAG_TABLE_NAME && columnName == TagBean.TAG_COLUMN
}

@Query(value = "SELECT * FROM $SEARCH_DOMAIN_TABLE_NAME")
fun getAllSearchDomain(): List<SearchDomainBean>
}
72 changes: 72 additions & 0 deletions app/src/main/java/com/skyd/raca/ext/ColorExt.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.skyd.raca.ext

import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.Stable
import androidx.compose.ui.graphics.Color
import com.skyd.raca.model.preference.theme.DarkModePreference
import com.skyd.raca.ui.local.LocalDarkMode
import java.lang.Long.parseLong

fun String.toColorOrNull(): Color? = try {
Color(parseLong(this, 16))
} catch (e: Exception) {
null
}

fun String.checkColorHex(): String? {
var s = this.trim()
if (s.length > 6) {
s = s.substring(s.length - 6)
}
return "[0-9a-fA-F]{6}".toRegex().find(s)?.value
}

@Composable
infix fun Color.onLight(lightColor: Color): Color =
if (!DarkModePreference.isInDark(value = LocalDarkMode.current)) lightColor else this

@Composable
infix fun Color.onDark(darkColor: Color): Color =
if (DarkModePreference.isInDark(value = LocalDarkMode.current)) darkColor else this

@Stable
@Composable
@ReadOnlyComposable
infix fun Color.alwaysLight(isAlways: Boolean): Color {
val colorScheme = MaterialTheme.colorScheme
return if (isAlways && DarkModePreference.isInDark(value = LocalDarkMode.current)) {
when (this) {
colorScheme.primary -> colorScheme.onPrimary
colorScheme.secondary -> colorScheme.onSecondary
colorScheme.tertiary -> colorScheme.onTertiary
colorScheme.background -> colorScheme.onBackground
colorScheme.error -> colorScheme.onError
colorScheme.surface -> colorScheme.onSurface
colorScheme.surfaceVariant -> colorScheme.onSurfaceVariant
colorScheme.primaryContainer -> colorScheme.onPrimaryContainer
colorScheme.secondaryContainer -> colorScheme.onSecondaryContainer
colorScheme.tertiaryContainer -> colorScheme.onTertiaryContainer
colorScheme.errorContainer -> colorScheme.onErrorContainer
colorScheme.inverseSurface -> colorScheme.inverseOnSurface

colorScheme.onPrimary -> colorScheme.primary
colorScheme.onSecondary -> colorScheme.secondary
colorScheme.onTertiary -> colorScheme.tertiary
colorScheme.onBackground -> colorScheme.background
colorScheme.onError -> colorScheme.error
colorScheme.onSurface -> colorScheme.surface
colorScheme.onSurfaceVariant -> colorScheme.surfaceVariant
colorScheme.onPrimaryContainer -> colorScheme.primaryContainer
colorScheme.onSecondaryContainer -> colorScheme.secondaryContainer
colorScheme.onTertiaryContainer -> colorScheme.tertiaryContainer
colorScheme.onErrorContainer -> colorScheme.errorContainer
colorScheme.inverseOnSurface -> colorScheme.inverseSurface

else -> Color.Unspecified
}
} else {
this
}
}
41 changes: 41 additions & 0 deletions app/src/main/java/com/skyd/raca/ext/DataStoreExt.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.skyd.raca.ext

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.emptyPreferences
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import java.io.IOException

val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "App")

suspend fun <T> DataStore<Preferences>.put(key: Preferences.Key<T>, value: T) {
this.edit {
withContext(Dispatchers.IO) {
it[key] = value
}
}
}

@Suppress("UNCHECKED_CAST")
fun <T> DataStore<Preferences>.get(key: Preferences.Key<T>): T? {
return runBlocking {
this@get.data.catch { exception ->
if (exception is IOException) {
exception.printStackTrace()
emit(emptyPreferences())
} else {
throw exception
}
}.map {
it[key]
}.first() as T
}
}
10 changes: 10 additions & 0 deletions app/src/main/java/com/skyd/raca/ext/NavExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.skyd.raca.ext

import android.os.Bundle
import androidx.core.net.toUri
import androidx.lifecycle.Lifecycle
import androidx.navigation.*

fun NavController.navigate(
Expand All @@ -23,4 +24,13 @@ fun NavController.navigate(
} else {
navigate(route, navOptions, navigatorExtras)
}
}

fun NavBackStackEntry.lifecycleIsResumed() =
this.getLifecycle().currentState == Lifecycle.State.RESUMED

fun NavController.popBackStackWithLifecycle() {
if (currentBackStackEntry?.lifecycleIsResumed() == true) {
popBackStack()
}
}
Loading

0 comments on commit da1d19a

Please sign in to comment.