Skip to content

Commit 6a5fcfd

Browse files
committed
save changes
1 parent cd20588 commit 6a5fcfd

File tree

9 files changed

+636
-109
lines changed

9 files changed

+636
-109
lines changed

Monica for Android/app/src/main/java/takagi/ru/monica/ui/screens/DeveloperSettingsScreen.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ private data class ClearLogsResult(
559559

560560
private object DeveloperLogDebugHelper {
561561
private const val LOG_LINE_LIMIT = 1200
562-
private const val SHARE_DIR = "temp_photos"
562+
private const val SHARE_DIR = "temp_share"
563563
private const val SHARE_PREFIX = "monica_logs_"
564564
private val AUTOFILL_LOG_TAGS = arrayOf(
565565
"MonicaAutofill:V",

Monica for Android/app/src/main/java/takagi/ru/monica/ui/screens/KeePassWebDavViewModel.kt

Lines changed: 164 additions & 81 deletions
Large diffs are not rendered by default.

Monica for Android/app/src/main/java/takagi/ru/monica/util/ImageManager.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class ImageManager(private val context: Context) {
3333

3434
companion object {
3535
private const val IMAGE_DIR = "secure_images"
36-
private const val TEMP_IMAGE_DIR = "temp_photos"
36+
private const val TEMP_IMAGE_DIR = "temp_share"
3737
private const val ALGORITHM = "AES/CBC/PKCS5Padding"
3838
private const val KEY_ALGORITHM = "AES"
3939

Monica for Android/app/src/main/java/takagi/ru/monica/util/PhotoPickerHelper.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ object PhotoPickerHelper {
221221
val timeStamp = java.text.SimpleDateFormat("yyyyMMdd_HHmmss", java.util.Locale.getDefault()).format(java.util.Date())
222222
val imageFileName = "JPEG_${timeStamp}_"
223223
// 确保使用正确的目录,与file_paths.xml中的配置匹配
224-
val storageDir = File(context.cacheDir, "temp_photos")
224+
val storageDir = File(context.cacheDir, "temp_share")
225225
if (!storageDir.exists()) {
226226
storageDir.mkdirs()
227227
}
@@ -358,4 +358,4 @@ object PhotoPickerHelper {
358358

359359
// 临时照片文件
360360
private var tempPhotoFile: File? = null
361-
}
361+
}

Monica for Android/app/src/main/java/takagi/ru/monica/utils/KeePassKdbxService.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ class KeePassKdbxService(
110110
// Global single-writer queue, shared across all service instances.
111111
private val persistScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
112112
private val persistQueue = Channel<suspend () -> Unit>(Channel.UNLIMITED)
113+
// 跨实例缓存失效信号:某实例更新数据库绑定后,其他实例的本地缓存应立即失效。
114+
private val externallyInvalidatedDatabaseIds = mutableSetOf<Long>()
113115
@Volatile
114116
private var persistWorkerStarted = false
115117

@@ -132,6 +134,16 @@ class KeePassKdbxService(
132134
suspend fun <T> withGlobalDecodeLock(block: () -> T): T {
133135
return globalDecodeMutex.withLock { block() }
134136
}
137+
138+
@Synchronized
139+
fun invalidateProcessCache(databaseId: Long) {
140+
externallyInvalidatedDatabaseIds += databaseId
141+
}
142+
143+
@Synchronized
144+
private fun consumeProcessCacheInvalidation(databaseId: Long): Boolean {
145+
return externallyInvalidatedDatabaseIds.remove(databaseId)
146+
}
135147
}
136148

137149
init {
@@ -1540,6 +1552,11 @@ class KeePassKdbxService(
15401552
}
15411553

15421554
private suspend fun getCachedLoadedDatabase(databaseId: Long): LoadedDatabase? {
1555+
if (consumeProcessCacheInvalidation(databaseId)) {
1556+
invalidateLoadedDatabaseCache(databaseId)
1557+
return null
1558+
}
1559+
15431560
val now = System.currentTimeMillis()
15441561
val cached = synchronized(loadedDatabaseCache) { loadedDatabaseCache[databaseId] } ?: return null
15451562

Monica for Android/app/src/main/java/takagi/ru/monica/utils/WebDavHelper.kt

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ class WebDavHelper(
324324
private const val KEY_KEEPASS_CONFLICT_PROTECTION_MODE = "conflict_protection_mode"
325325
private const val KEEPASS_CONFLICT_MODE_AUTO = "auto"
326326
private const val KEEPASS_CONFLICT_MODE_STRICT = "strict"
327+
private const val BACKUP_FOLDER_NAME = "Monica_Backups"
327328
}
328329

329330
// 加密相关
@@ -339,7 +340,7 @@ class WebDavHelper(
339340
* 配置 WebDAV 连接
340341
*/
341342
fun configure(url: String, user: String, pass: String) {
342-
serverUrl = url.trimEnd('/')
343+
serverUrl = normalizeServerUrl(url)
343344
username = user
344345
password = pass
345346
// 创建新的 Sardine 实例并立即设置凭证
@@ -370,7 +371,8 @@ class WebDavHelper(
370371
*/
371372
private fun loadConfig() {
372373
val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
373-
val url = prefs.getString(KEY_SERVER_URL, "") ?: ""
374+
val storedUrl = prefs.getString(KEY_SERVER_URL, "") ?: ""
375+
val url = normalizeServerUrl(storedUrl)
374376
val user = prefs.getString(KEY_USERNAME, "") ?: ""
375377
val pass = prefs.getString(KEY_PASSWORD, "") ?: ""
376378
enableEncryption = prefs.getBoolean(KEY_ENABLE_ENCRYPTION, false)
@@ -384,6 +386,9 @@ class WebDavHelper(
384386
sardine = OkHttpSardine()
385387
sardine?.setCredentials(username, password)
386388
android.util.Log.d("WebDavHelper", "Loaded WebDAV config: url=$serverUrl, user=$username, encryption=$enableEncryption")
389+
if (url != storedUrl) {
390+
saveConfig()
391+
}
387392
}
388393
}
389394

@@ -3179,6 +3184,23 @@ class WebDavHelper(
31793184
}
31803185
}.trim('_').ifEmpty { "_root" }
31813186
}
3187+
3188+
private fun normalizeServerUrl(url: String): String {
3189+
return url.trim().trimEnd('/')
3190+
}
3191+
3192+
private fun getBackupDirectoryPath(): String {
3193+
val normalizedBase = normalizeServerUrl(serverUrl)
3194+
return if (normalizedBase.endsWith("/$BACKUP_FOLDER_NAME", ignoreCase = true)) {
3195+
normalizedBase
3196+
} else {
3197+
"$normalizedBase/$BACKUP_FOLDER_NAME"
3198+
}
3199+
}
3200+
3201+
private fun getBackupFilePath(fileName: String): String {
3202+
return "${getBackupDirectoryPath()}/$fileName"
3203+
}
31823204

31833205
/**
31843206
* 上传备份文件
@@ -3197,7 +3219,7 @@ class WebDavHelper(
31973219
}
31983220

31993221
// 创建 Monica 备份目录
3200-
val backupDir = "$serverUrl/Monica_Backups"
3222+
val backupDir = getBackupDirectoryPath()
32013223
if (!sardine!!.exists(backupDir)) {
32023224
sardine!!.createDirectory(backupDir)
32033225
}
@@ -3249,7 +3271,7 @@ class WebDavHelper(
32493271
return@withContext Result.failure(Exception("WebDAV not configured"))
32503272
}
32513273

3252-
val backupDir = "$serverUrl/Monica_Backups"
3274+
val backupDir = getBackupDirectoryPath()
32533275

32543276
// 检查目录是否存在
32553277
if (!sardine!!.exists(backupDir)) {
@@ -3286,7 +3308,7 @@ class WebDavHelper(
32863308
return@withContext Result.failure(Exception("WebDAV not configured"))
32873309
}
32883310

3289-
val remotePath = "$serverUrl/Monica_Backups/${backupFile.name}"
3311+
val remotePath = getBackupFilePath(backupFile.name)
32903312

32913313
// 下载文件
32923314
sardine!!.get(remotePath).use { inputStream ->
@@ -3351,10 +3373,10 @@ class WebDavHelper(
33513373
return@withContext Result.success(true)
33523374
}
33533375

3354-
val oldPath = "$serverUrl/Monica_Backups/${backup.name}"
3376+
val oldPath = getBackupFilePath(backup.name)
33553377
// Insert _permanent before .zip
33563378
val newName = backup.name.replace(".zip", "${PERMANENT_SUFFIX}.zip")
3357-
val newPath = "$serverUrl/Monica_Backups/$newName"
3379+
val newPath = getBackupFilePath(newName)
33583380

33593381
sardine!!.move(oldPath, newPath)
33603382
android.util.Log.d("WebDavHelper", "Marked backup as permanent: ${backup.name} -> $newName")
@@ -3378,10 +3400,10 @@ class WebDavHelper(
33783400
return@withContext Result.success(true)
33793401
}
33803402

3381-
val oldPath = "$serverUrl/Monica_Backups/${backup.name}"
3403+
val oldPath = getBackupFilePath(backup.name)
33823404
// Remove _permanent suffix
33833405
val newName = backup.name.replace(PERMANENT_SUFFIX, "")
3384-
val newPath = "$serverUrl/Monica_Backups/$newName"
3406+
val newPath = getBackupFilePath(newName)
33853407

33863408
sardine!!.move(oldPath, newPath)
33873409
android.util.Log.d("WebDavHelper", "Unmarked permanent backup: ${backup.name} -> $newName")
@@ -3403,7 +3425,7 @@ class WebDavHelper(
34033425
return@withContext Result.failure(Exception("WebDAV not configured"))
34043426
}
34053427

3406-
val remotePath = "$serverUrl/Monica_Backups/${backupFile.name}"
3428+
val remotePath = getBackupFilePath(backupFile.name)
34073429
android.util.Log.d("WebDavHelper", "Deleting backup: $remotePath")
34083430

34093431
sardine!!.delete(remotePath)

Monica for Android/app/src/main/java/takagi/ru/monica/viewmodel/LocalKeePassViewModel.kt

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -426,18 +426,35 @@ class LocalKeePassViewModel(
426426
?: throw Exception("无法访问密钥文件")
427427
}
428428

429-
val database = LocalKeePassDatabase(
430-
name = name,
431-
filePath = uri.toString(),
432-
keyFileUri = keyFileUri?.toString(),
433-
storageLocation = KeePassStorageLocation.EXTERNAL,
434-
encryptedPassword = encryptedPassword,
435-
description = description,
436-
entryCount = entryCount,
437-
isDefault = allDatabases.value.isEmpty()
438-
)
439-
440-
dao.insertDatabase(database)
429+
val uriPath = uri.toString()
430+
val existing = dao.getAllDatabasesSync().firstOrNull { it.filePath == uriPath }
431+
if (existing != null) {
432+
dao.updateDatabase(
433+
existing.copy(
434+
name = name,
435+
keyFileUri = keyFileUri?.toString() ?: existing.keyFileUri,
436+
storageLocation = KeePassStorageLocation.EXTERNAL,
437+
encryptedPassword = encryptedPassword,
438+
description = description ?: existing.description,
439+
entryCount = entryCount,
440+
lastAccessedAt = System.currentTimeMillis()
441+
)
442+
)
443+
KeePassKdbxService.invalidateProcessCache(existing.id)
444+
} else {
445+
val database = LocalKeePassDatabase(
446+
name = name,
447+
filePath = uriPath,
448+
keyFileUri = keyFileUri?.toString(),
449+
storageLocation = KeePassStorageLocation.EXTERNAL,
450+
encryptedPassword = encryptedPassword,
451+
description = description,
452+
entryCount = entryCount,
453+
isDefault = allDatabases.value.isEmpty()
454+
)
455+
val newId = dao.insertDatabase(database)
456+
KeePassKdbxService.invalidateProcessCache(newId)
457+
}
441458
}
442459

443460
_operationState.value = OperationState.Success("数据库添加成功")

Monica for Android/app/src/main/res/xml/file_paths.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<paths xmlns:android="http://schemas.android.com/apk/res/android">
3-
<!-- 缓存目录,用于临时拍照 -->
4-
<cache-path name="camera_photos" path="temp_photos/" />
3+
<!-- 缓存目录,用于临时拍照与日志分享 -->
4+
<cache-path name="shared_temp" path="temp_share/" />
55

66
<!-- 内部存储,用于加密图片 -->
77
<files-path name="secure_images" path="secure_images/" />

0 commit comments

Comments
 (0)