diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 54333f8..e520fc5 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -20,4 +20,11 @@ # hide the original source file name. #-renamesourcefileattribute SourceFile +# Gson +-keepattributes Signature +-keep class com.google.gson.reflect.TypeToken { *; } +-keep class * extends com.google.gson.reflect.TypeToken +-keepattributes AnnotationDefault,RuntimeVisibleAnnotations + +# ToDo Room -keep class cn.super12138.todo.logic.dao.ToDoRoom { *; } \ No newline at end of file diff --git a/app/src/main/kotlin/cn/super12138/todo/logic/Repository.kt b/app/src/main/kotlin/cn/super12138/todo/logic/Repository.kt index 6a46a0f..d4c469c 100644 --- a/app/src/main/kotlin/cn/super12138/todo/logic/Repository.kt +++ b/app/src/main/kotlin/cn/super12138/todo/logic/Repository.kt @@ -8,6 +8,12 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext object Repository { + /** + * 设置数据到应用设置中 + */ + fun setPreference(context: Context, key: String, value: Any) = + SPHelper.setPreference(context, key, value) + /** * 获取应用设置里的数据 */ diff --git a/app/src/main/kotlin/cn/super12138/todo/logic/database/SPHelper.kt b/app/src/main/kotlin/cn/super12138/todo/logic/database/SPHelper.kt index a1e1cf3..5c156c6 100644 --- a/app/src/main/kotlin/cn/super12138/todo/logic/database/SPHelper.kt +++ b/app/src/main/kotlin/cn/super12138/todo/logic/database/SPHelper.kt @@ -15,4 +15,20 @@ object SPHelper { PreferenceManager.getDefaultSharedPreferences(context /* Activity context */) return sharedPreferences.getBoolean(name, defaultValue) } + + fun setPreference(context: Context, name: String, value: Any) { + val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) + val editor = sharedPreferences.edit() + + when (value) { + is String -> editor.putString(name, value) + is Boolean -> editor.putBoolean(name, value) + is Int -> editor.putInt(name, value) + is Float -> editor.putFloat(name, value) + is Long -> editor.putLong(name, value) + else -> throw IllegalArgumentException("Unsupported data type") + } + + editor.apply() + } } \ No newline at end of file diff --git a/app/src/main/kotlin/cn/super12138/todo/views/BaseActivity.kt b/app/src/main/kotlin/cn/super12138/todo/views/BaseActivity.kt index 5bb8d90..250722f 100644 --- a/app/src/main/kotlin/cn/super12138/todo/views/BaseActivity.kt +++ b/app/src/main/kotlin/cn/super12138/todo/views/BaseActivity.kt @@ -4,9 +4,17 @@ import android.os.Build import android.os.Bundle import android.view.WindowManager import androidx.appcompat.app.AppCompatActivity +import cn.super12138.todo.R +import cn.super12138.todo.ToDoApplication +import cn.super12138.todo.logic.Repository open class BaseActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { + val springFestivalTheme = + Repository.getPreferenceBoolean(ToDoApplication.context, "spring_festival_theme", false) + if (springFestivalTheme) { + setTheme(R.style.Theme_SpringFestival) + } // enableEdgeToEdge() super.onCreate(savedInstanceState) // 适配刘海屏 diff --git a/app/src/main/kotlin/cn/super12138/todo/views/about/AboutActivity.kt b/app/src/main/kotlin/cn/super12138/todo/views/about/AboutActivity.kt index f09d7b8..36e8843 100644 --- a/app/src/main/kotlin/cn/super12138/todo/views/about/AboutActivity.kt +++ b/app/src/main/kotlin/cn/super12138/todo/views/about/AboutActivity.kt @@ -4,8 +4,10 @@ import android.content.Intent import android.net.Uri import android.os.Build import android.os.Bundle +import cn.super12138.todo.ToDoApplication import cn.super12138.todo.constant.Constants import cn.super12138.todo.databinding.ActivityAboutBinding +import cn.super12138.todo.logic.Repository import cn.super12138.todo.views.BaseActivity import showToast @@ -59,6 +61,24 @@ class AboutActivity : BaseActivity() { when (clickCount) { 5 -> { clickCount = 0 + val isSpringFestivalTheme = Repository.getPreferenceBoolean( + ToDoApplication.context, + "spring_festival_theme", + false + ) + if (isSpringFestivalTheme) { + Repository.setPreference( + ToDoApplication.context, + "spring_festival_theme", + false + ) + } else { + Repository.setPreference( + ToDoApplication.context, + "spring_festival_theme", + true + ) + } "🧧".showToast() } } diff --git a/app/src/main/kotlin/cn/super12138/todo/views/settings/SettingsActivity.kt b/app/src/main/kotlin/cn/super12138/todo/views/settings/SettingsActivity.kt index 2719822..f168e65 100644 --- a/app/src/main/kotlin/cn/super12138/todo/views/settings/SettingsActivity.kt +++ b/app/src/main/kotlin/cn/super12138/todo/views/settings/SettingsActivity.kt @@ -5,21 +5,19 @@ import android.os.Process import android.view.WindowManager import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatDelegate -import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import androidx.preference.ListPreference import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import androidx.preference.SwitchPreferenceCompat import cn.super12138.todo.R +import cn.super12138.todo.ToDoApplication import cn.super12138.todo.databinding.ActivitySettingsBinding import cn.super12138.todo.databinding.DialogBackupBinding import cn.super12138.todo.databinding.DialogRestoreBinding import cn.super12138.todo.logic.Repository import cn.super12138.todo.logic.dao.ToDoRoom import cn.super12138.todo.views.BaseActivity -import cn.super12138.todo.views.progress.ProgressFragmentViewModel -import cn.super12138.todo.views.todo.ToDoFragmentViewModel import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import com.google.gson.Gson @@ -56,10 +54,8 @@ class SettingsActivity : BaseActivity() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.preferences, rootKey) val gson = Gson() - val progressViewModel = - ViewModelProvider(requireActivity()).get(ProgressFragmentViewModel::class.java) - val todoViewModel = - ViewModelProvider(requireActivity()).get(ToDoFragmentViewModel::class.java) + val isDevMode = + Repository.getPreferenceBoolean(ToDoApplication.context, "dev_mode", false) findPreference("dark_mode")?.apply { setOnPreferenceChangeListener { preference, newValue -> @@ -161,8 +157,12 @@ class SettingsActivity : BaseActivity() { restoreBinding.jsonInput.error = getString(R.string.json_data_incorrect) } catch (e: Exception) { - restoreBinding.jsonInput.error = - getString(R.string.restore_failed) + if (isDevMode) { + restoreBinding.jsonInput.error = e.toString() + } else { + restoreBinding.jsonInput.error = + getString(R.string.restore_failed) + } } } } diff --git a/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoAdapter.kt b/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoAdapter.kt index c94ada8..1d13f46 100644 --- a/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoAdapter.kt +++ b/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoAdapter.kt @@ -35,7 +35,7 @@ class ToDoAdapter(val todoList: MutableList, val viewModelStoreOwner: View ViewModelProvider(viewModelStoreOwner).get(ToDoFragmentViewModel::class.java) val view = LayoutInflater.from(parent.context) - .inflate(R.layout.todo_item, parent, false) + .inflate(R.layout.item_todo, parent, false) val holder = ViewHolder(view) holder.checkToDoBtn.setOnClickListener { diff --git a/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoFragment.kt b/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoFragment.kt index 9654c97..00dac8e 100644 --- a/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoFragment.kt +++ b/app/src/main/kotlin/cn/super12138/todo/views/todo/ToDoFragment.kt @@ -21,6 +21,7 @@ import cn.super12138.todo.logic.model.ToDo import cn.super12138.todo.views.progress.ProgressFragmentViewModel import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.launch +import showToast import java.util.UUID class ToDoFragment : Fragment() { @@ -95,44 +96,58 @@ class ToDoFragment : Fragment() { ToDoDialogBinding.todoContent.error = getString(R.string.content_cannot_be_empty) } else { - val randomUUID = UUID.randomUUID().toString() - val todoSubject = when (ToDoDialogBinding.todoSubject.checkedChipId) { - R.id.subject_chinese -> getString(R.string.subject_chinese) - R.id.subject_math -> getString(R.string.subject_math) - R.id.subject_english -> getString(R.string.subject_english) - R.id.subject_biology -> getString(R.string.subject_biology) - R.id.subject_geography -> getString(R.string.subject_geography) - R.id.subject_history -> getString(R.string.subject_history) - R.id.subject_physics -> getString(R.string.subject_physics) - R.id.subject_law -> getString(R.string.subject_law) - R.id.subject_other -> getString(R.string.subject_other) - else -> getString(R.string.subject_unknown) - } - - // 显示RecyclerView - if (todoList.size + 1 > 0) { - todoViewModel.emptyTipVis.value = View.GONE - } - - // 添加到RecyclerView - todoList.add( - ToDo(randomUUID, todoContent, todoSubject) - ) - - lifecycleScope.launch { - Repository.insert( - ToDoRoom( - randomUUID, - 0, - todoSubject, - todoContent + if (todoContent == "/DEV MODE") { + if (Repository.getPreferenceBoolean( + ToDoApplication.context, + "dev_mode", + true ) + ) { + Repository.setPreference(ToDoApplication.context, "dev_mode", false) + } else { + Repository.setPreference(ToDoApplication.context, "dev_mode", true) + "Dev Mode".showToast() + } + dialog.dismiss() + } else { + val randomUUID = UUID.randomUUID().toString() + val todoSubject = when (ToDoDialogBinding.todoSubject.checkedChipId) { + R.id.subject_chinese -> getString(R.string.subject_chinese) + R.id.subject_math -> getString(R.string.subject_math) + R.id.subject_english -> getString(R.string.subject_english) + R.id.subject_biology -> getString(R.string.subject_biology) + R.id.subject_geography -> getString(R.string.subject_geography) + R.id.subject_history -> getString(R.string.subject_history) + R.id.subject_physics -> getString(R.string.subject_physics) + R.id.subject_law -> getString(R.string.subject_law) + R.id.subject_other -> getString(R.string.subject_other) + else -> getString(R.string.subject_unknown) + } + + // 显示RecyclerView + if (todoList.size + 1 > 0) { + todoViewModel.emptyTipVis.value = View.GONE + } + + // 添加到RecyclerView + todoList.add( + ToDo(randomUUID, todoContent, todoSubject) ) - progressViewModel.updateProgress() - } - binding.todoList.adapter?.notifyItemInserted(todoList.size + 1) - dialog.dismiss() + lifecycleScope.launch { + Repository.insert( + ToDoRoom( + randomUUID, + 0, + todoSubject, + todoContent + ) + ) + progressViewModel.updateProgress() + binding.todoList.adapter?.notifyItemInserted(todoList.size + 1) + dialog.dismiss() + } + } } } } diff --git a/app/src/main/res/layout/todo_item.xml b/app/src/main/res/layout/item_todo.xml similarity index 100% rename from app/src/main/res/layout/todo_item.xml rename to app/src/main/res/layout/item_todo.xml diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index ceb654e..3e2b42c 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -140,4 +140,147 @@ #1D2024 #272A2F #32353A + + + #FFB4A8 + #690100 + #940100 + #FFD8D2 + #FFB4A8 + #630F08 + #751D13 + #FFC3B9 + #F1BE6F + #442C00 + #614000 + #FFDAA6 + #FFB4AB + #690005 + #93000A + #FFDAD6 + #1E0F0D + #FADCD7 + #1E0F0D + #FADCD7 + #5C403B + #E5BEB7 + #AC8983 + #5C403B + #000000 + #FADCD7 + #3E2C29 + #BB190E + #FFDAD4 + #410000 + #FFB4A8 + #930100 + #FFDAD4 + #410000 + #FFB4A8 + #82261B + #FFDDAF + #281800 + #F1BE6F + #614000 + #1E0F0D + #483531 + #190A08 + #281715 + #2C1B19 + #372623 + #43302D + #FFBAAF + #370000 + #FF5540 + #000000 + #FFBAAF + #370000 + #E26E5D + #000000 + #F6C273 + #211400 + #B6893F + #000000 + #FFBAB1 + #370001 + #FF5449 + #000000 + #1E0F0D + #FADCD7 + #1E0F0D + #FFF9F8 + #5C403B + #E9C2BB + #BF9A95 + #9D7B76 + #000000 + #FADCD7 + #372623 + #950100 + #FFDAD4 + #2D0000 + #FFB4A8 + #740100 + #FFDAD4 + #2D0000 + #FFB4A8 + #6B150D + #FFDDAF + #1B0F00 + #F1BE6F + #4B3100 + #1E0F0D + #483531 + #190A08 + #281715 + #2C1B19 + #372623 + #43302D + #FFF9F8 + #000000 + #FFBAAF + #000000 + #FFF9F8 + #000000 + #FFBAAF + #000000 + #FFFAF7 + #000000 + #F6C273 + #000000 + #FFF9F9 + #000000 + #FFBAB1 + #000000 + #1E0F0D + #FADCD7 + #1E0F0D + #FFFFFF + #5C403B + #FFF9F8 + #E9C2BB + #E9C2BB + #000000 + #FADCD7 + #000000 + #5C0000 + #FFE0DB + #000000 + #FFBAAF + #370000 + #FFE0DB + #000000 + #FFBAAF + #370000 + #FFE3BD + #000000 + #F6C273 + #211400 + #1E0F0D + #483531 + #190A08 + #281715 + #2C1B19 + #372623 + #43302D diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml index 67efe07..fe49b5d 100644 --- a/app/src/main/res/values-night/themes.xml +++ b/app/src/main/res/values-night/themes.xml @@ -51,4 +51,56 @@ @style/AppPreferenceThemeOverlay @style/ToDo.M3AlertDialog + + \ No newline at end of file diff --git a/app/src/main/res/values-v23/themes.xml b/app/src/main/res/values-v23/themes.xml index 7be0b54..5f46963 100644 --- a/app/src/main/res/values-v23/themes.xml +++ b/app/src/main/res/values-v23/themes.xml @@ -6,4 +6,10 @@ @android:color/transparent ?attr/isLightTheme + \ 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 54fe9d3..7f9de8c 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -144,4 +144,146 @@ #ECEEF4 #E6E8EE #E1E2E8 + + #7E0100 + #FFFFFF + #BB1A0E + #FFFFFF + #A23E30 + #FFFFFF + #FF9281 + #520201 + #533700 + #FFFFFF + #7E5811 + #FFFFFF + #BA1A1A + #FFFFFF + #FFDAD6 + #410002 + #FFF8F6 + #281715 + #FFF8F6 + #281715 + #FFDAD4 + #5C403B + #906F6A + #E5BEB7 + #000000 + #3E2C29 + #FFEDEA + #FFB4A8 + #FFDAD4 + #410000 + #FFB4A8 + #930100 + #FFDAD4 + #410000 + #FFB4A8 + #82261B + #FFDDAF + #281800 + #F1BE6F + #614000 + #F1D3CE + #FFF8F6 + #FFFFFF + #FFF0EE + #FFE9E6 + #FFE2DD + #FADCD7 + #7E0100 + #FFFFFF + #BB1A0E + #FFFFFF + #7D2318 + #FFFFFF + #BF5344 + #FFFFFF + #533700 + #FFFFFF + #7E5811 + #FFFFFF + #8C0009 + #FFFFFF + #DA342E + #FFFFFF + #FFF8F6 + #281715 + #FFF8F6 + #281715 + #FFDAD4 + #573C38 + #765853 + #94736E + #000000 + #3E2C29 + #FFEDEA + #FFB4A8 + #DB3323 + #FFFFFF + #B7160B + #FFFFFF + #BF5344 + #FFFFFF + #9E3B2E + #FFFFFF + #966D26 + #FFFFFF + #7B550D + #FFFFFF + #F1D3CE + #FFF8F6 + #FFFFFF + #FFF0EE + #FFE9E6 + #FFE2DD + #FADCD7 + #4E0000 + #FFFFFF + #8C0100 + #FFFFFF + #4E0000 + #FFFFFF + #7D2318 + #FFFFFF + #311F00 + #FFFFFF + #5C3D00 + #FFFFFF + #4E0002 + #FFFFFF + #8C0009 + #FFFFFF + #FFF8F6 + #281715 + #FFF8F6 + #000000 + #FFDAD4 + #351E1A + #573C38 + #573C38 + #000000 + #3E2C29 + #FFFFFF + #FFE7E3 + #8C0100 + #FFFFFF + #620100 + #FFFFFF + #7D2318 + #FFFFFF + #5D0B05 + #FFFFFF + #5C3D00 + #FFFFFF + #3F2800 + #FFFFFF + #F1D3CE + #FFF8F6 + #FFFFFF + #FFF0EE + #FFE9E6 + #FFE2DD + #FADCD7 \ 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 aab0fe2..aab9d7d 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -68,4 +68,56 @@ ?attr/colorSurfaceContainerHigh @layout/m3_alert_dialog + + \ No newline at end of file