正式发布2.1.2版本
修复英文情况下字符串双引号不显示的问题 优化备份与恢复数据库逻辑(使用 GitHub Copilot) 增大待办圆环 修复部分遗留的错误变量名称 优化主页性能
This commit is contained in:
parent
a305d5217f
commit
a8aa50f80b
6 changed files with 29 additions and 38 deletions
|
|
@ -34,8 +34,8 @@ android {
|
||||||
applicationId = "cn.super12138.todo"
|
applicationId = "cn.super12138.todo"
|
||||||
minSdk = 24
|
minSdk = 24
|
||||||
targetSdk = 35
|
targetSdk = 35
|
||||||
versionCode = 564
|
versionCode = 567
|
||||||
versionName = "2.0.2"
|
versionName = "2.1.2"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
|
|
@ -83,7 +83,6 @@ dependencies {
|
||||||
implementation(libs.androidx.lifecycle.runtime.ktx)
|
implementation(libs.androidx.lifecycle.runtime.ktx)
|
||||||
implementation(libs.androidx.lifecycle.viewmodel.compose)
|
implementation(libs.androidx.lifecycle.viewmodel.compose)
|
||||||
implementation(libs.androidx.compose.runtime.livedata)
|
implementation(libs.androidx.compose.runtime.livedata)
|
||||||
// implementation(libs.androidx.security)
|
|
||||||
// Compose
|
// Compose
|
||||||
implementation(libs.androidx.activity.compose)
|
implementation(libs.androidx.activity.compose)
|
||||||
implementation(platform(libs.androidx.compose.bom))
|
implementation(platform(libs.androidx.compose.bom))
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import android.content.Context
|
||||||
import cn.super12138.todo.R
|
import cn.super12138.todo.R
|
||||||
|
|
||||||
enum class SortingMethod(val id: Int) {
|
enum class SortingMethod(val id: Int) {
|
||||||
Date(1),
|
Sequential(1),
|
||||||
Subject(2),
|
Subject(2),
|
||||||
Priority(3),
|
Priority(3),
|
||||||
Completion(4),
|
Completion(4),
|
||||||
|
|
@ -13,7 +13,7 @@ enum class SortingMethod(val id: Int) {
|
||||||
|
|
||||||
fun getDisplayName(context: Context): String {
|
fun getDisplayName(context: Context): String {
|
||||||
val resId = when (this) {
|
val resId = when (this) {
|
||||||
Date -> R.string.sorting_sequential
|
Sequential -> R.string.sorting_sequential
|
||||||
Subject -> R.string.sorting_subject
|
Subject -> R.string.sorting_subject
|
||||||
Priority -> R.string.sorting_priority
|
Priority -> R.string.sorting_priority
|
||||||
Completion -> R.string.sorting_completion
|
Completion -> R.string.sorting_completion
|
||||||
|
|
@ -25,7 +25,7 @@ enum class SortingMethod(val id: Int) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun fromId(id: Int): SortingMethod {
|
fun fromId(id: Int): SortingMethod {
|
||||||
return SortingMethod.entries.find { it.id == id } ?: Date
|
return SortingMethod.entries.find { it.id == id } ?: Sequential
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -80,6 +80,9 @@ fun MainPage(
|
||||||
val filteredTodoList =
|
val filteredTodoList =
|
||||||
if (showCompleted) toDoList else toDoList.filter { item -> !item.isCompleted }
|
if (showCompleted) toDoList else toDoList.filter { item -> !item.isCompleted }
|
||||||
|
|
||||||
|
val totalTasks by remember { derivedStateOf { toDoList.size } }
|
||||||
|
val completedTasks by remember { derivedStateOf { toDoList.count { it.isCompleted } } }
|
||||||
|
|
||||||
BackHandler(enabled = !isSelectedIdsEmpty) {
|
BackHandler(enabled = !isSelectedIdsEmpty) {
|
||||||
// 当按下返回键(或进行返回操作)时清空选择
|
// 当按下返回键(或进行返回操作)时清空选择
|
||||||
viewModel.clearAllTodoSelection()
|
viewModel.clearAllTodoSelection()
|
||||||
|
|
@ -126,8 +129,8 @@ fun MainPage(
|
||||||
if (windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.COMPACT) {
|
if (windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.COMPACT) {
|
||||||
Column(modifier = Modifier.padding(innerPadding)) {
|
Column(modifier = Modifier.padding(innerPadding)) {
|
||||||
ProgressFragment(
|
ProgressFragment(
|
||||||
totalTasks = toDoList.size,
|
totalTasks = totalTasks,
|
||||||
completedTasks = toDoList.count { it.isCompleted },
|
completedTasks = completedTasks,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(2f)
|
.weight(2f)
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
|
@ -172,8 +175,8 @@ fun MainPage(
|
||||||
} else {
|
} else {
|
||||||
Row(modifier = Modifier.padding(innerPadding)) {
|
Row(modifier = Modifier.padding(innerPadding)) {
|
||||||
ProgressFragment(
|
ProgressFragment(
|
||||||
totalTasks = toDoList.size,
|
totalTasks = totalTasks,
|
||||||
completedTasks = toDoList.count { it.isCompleted },
|
completedTasks = completedTasks,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(2f)
|
.weight(2f)
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,9 @@ fun ProgressFragment(
|
||||||
progress = { animatedProgress },
|
progress = { animatedProgress },
|
||||||
strokeWidth = 10.dp,
|
strokeWidth = 10.dp,
|
||||||
gapSize = 10.dp,
|
gapSize = 10.dp,
|
||||||
modifier = Modifier.size(170.dp)
|
modifier = Modifier.size(175.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
Text(
|
Text(
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ import java.io.BufferedInputStream
|
||||||
import java.io.BufferedOutputStream
|
import java.io.BufferedOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.util.zip.ZipEntry
|
|
||||||
import java.util.zip.ZipInputStream
|
import java.util.zip.ZipInputStream
|
||||||
import java.util.zip.ZipOutputStream
|
import java.util.zip.ZipOutputStream
|
||||||
|
|
||||||
|
|
@ -40,7 +39,7 @@ class MainViewModel : ViewModel() {
|
||||||
var appSortingMethod by mutableStateOf(SortingMethod.fromId(GlobalValues.sortingMethod))
|
var appSortingMethod by mutableStateOf(SortingMethod.fromId(GlobalValues.sortingMethod))
|
||||||
val sortedTodos: Flow<List<TodoEntity>> = toDos.map { list ->
|
val sortedTodos: Flow<List<TodoEntity>> = toDos.map { list ->
|
||||||
when (appSortingMethod) {
|
when (appSortingMethod) {
|
||||||
SortingMethod.Date -> list.sortedBy { it.id }
|
SortingMethod.Sequential -> list.sortedBy { it.id }
|
||||||
SortingMethod.Subject -> list.sortedBy { it.subject }
|
SortingMethod.Subject -> list.sortedBy { it.subject }
|
||||||
SortingMethod.Priority -> list.sortedByDescending { it.priority } // 优先级高的在前
|
SortingMethod.Priority -> list.sortedByDescending { it.priority } // 优先级高的在前
|
||||||
SortingMethod.Completion -> list.sortedBy { it.isCompleted } // 未完成的在前
|
SortingMethod.Completion -> list.sortedBy { it.isCompleted } // 未完成的在前
|
||||||
|
|
@ -186,26 +185,21 @@ class MainViewModel : ViewModel() {
|
||||||
// 开启输出文件流,输出位置为用户选取的文件夹URI
|
// 开启输出文件流,输出位置为用户选取的文件夹URI
|
||||||
context.contentResolver.openOutputStream(uri)?.use { outputStream ->
|
context.contentResolver.openOutputStream(uri)?.use { outputStream ->
|
||||||
ZipOutputStream(BufferedOutputStream(outputStream)).use { zipOutStream ->
|
ZipOutputStream(BufferedOutputStream(outputStream)).use { zipOutStream ->
|
||||||
val dbFile = context.getDatabasePath(Constants.DB_NAME)
|
listOf(
|
||||||
val dbWal = File("$dbPath-wal")
|
context.getDatabasePath(Constants.DB_NAME),
|
||||||
val dbShm = File("$dbPath-shm")
|
File("$dbPath-wal"),
|
||||||
|
File("$dbPath-shm")
|
||||||
FileUtils.addFileToZip(dbFile, dbFile.name, zipOutStream)
|
).forEach { file ->
|
||||||
FileUtils.addFileToZip(dbWal, dbWal.name, zipOutStream)
|
FileUtils.addFileToZip(file, file.name, zipOutStream)
|
||||||
FileUtils.addFileToZip(dbShm, dbShm.name, zipOutStream)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行成功的回调
|
// 执行成功的回调
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) { onResult(true) }
|
||||||
onResult(true) // 成功
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
// 执行失败的回调
|
// 执行失败的回调
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) { onResult(false) }
|
||||||
onResult(false) // 失败
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -213,12 +207,11 @@ class MainViewModel : ViewModel() {
|
||||||
fun restoreDatabase(uri: Uri, context: Context, onResult: (completed: Boolean) -> Unit) {
|
fun restoreDatabase(uri: Uri, context: Context, onResult: (completed: Boolean) -> Unit) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
// 获取数据库文件路径
|
// 获取数据库文件夹
|
||||||
val outputPath = context.getDatabasePath(Constants.DB_NAME).parent
|
val outputPath = context.getDatabasePath(Constants.DB_NAME).parent
|
||||||
context.contentResolver.openInputStream(uri)?.use { inputStream ->
|
context.contentResolver.openInputStream(uri)?.use { inputStream ->
|
||||||
ZipInputStream(BufferedInputStream(inputStream)).use { zipInputStream ->
|
ZipInputStream(BufferedInputStream(inputStream)).use { zipInputStream ->
|
||||||
var zipEntry: ZipEntry? = zipInputStream.nextEntry
|
generateSequence { zipInputStream.nextEntry }.forEach { zipEntry ->
|
||||||
while (zipEntry != null) {
|
|
||||||
val outputFile = File(outputPath, zipEntry.name)
|
val outputFile = File(outputPath, zipEntry.name)
|
||||||
if (zipEntry.isDirectory) {
|
if (zipEntry.isDirectory) {
|
||||||
outputFile.mkdirs()
|
outputFile.mkdirs()
|
||||||
|
|
@ -227,18 +220,13 @@ class MainViewModel : ViewModel() {
|
||||||
FileOutputStream(outputFile).use { zipInputStream.copyTo(it) }
|
FileOutputStream(outputFile).use { zipInputStream.copyTo(it) }
|
||||||
}
|
}
|
||||||
zipInputStream.closeEntry()
|
zipInputStream.closeEntry()
|
||||||
zipEntry = zipInputStream.nextEntry
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) { onResult(true) }
|
||||||
onResult(true) // 成功
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) { onResult(false) }
|
||||||
onResult(false) // 失败
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@
|
||||||
<string name="pref_haptic_feedback">Haptic Feedback</string>
|
<string name="pref_haptic_feedback">Haptic Feedback</string>
|
||||||
<string name="pref_haptic_feedback_desc">Provide slight vibration feedback for some operations</string>
|
<string name="pref_haptic_feedback_desc">Provide slight vibration feedback for some operations</string>
|
||||||
<string name="tip_tips">Tips</string>
|
<string name="tip_tips">Tips</string>
|
||||||
<string name="pref_haptic_feedback_more_info">Before using this feature, you need to enable haptic feedback in the system settings (usually under the "Sound & Vibration" section in the "Haptic Feedback" option)</string>
|
<string name="pref_haptic_feedback_more_info">Before using this feature, you need to enable haptic feedback in the system settings (usually under the \"Sound & Vibration\" section in the \"Haptic Feedback\" option)</string>
|
||||||
<string name="pref_data">Data</string>
|
<string name="pref_data">Data</string>
|
||||||
<string name="pref_data_desc">Backup and Restore, Manage Data</string>
|
<string name="pref_data_desc">Backup and Restore, Manage Data</string>
|
||||||
<string name="pref_backup">Backup</string>
|
<string name="pref_backup">Backup</string>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue