Skip to content

Commit 8a9b2b8

Browse files
committed
fix: 修复review问题
1 parent 86ae9ad commit 8a9b2b8

4 files changed

Lines changed: 32 additions & 14 deletions

File tree

modules/native-util/android/src/main/java/expo/modules/nativeutil/FileOperations.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,8 @@ internal class SafTreeStrategy(
194194
val childUri = DocumentsContract.buildDocumentUriUsingTree(treeUri, childDocId)
195195
val childDoc = DocumentFile.fromSingleUri(context, childUri) ?: return null
196196
if (!childDoc.exists()) return null
197-
return SafTreeStrategy(childDoc, "$relativePath$name/", treeUri, rootDocId)
197+
val childPath = if (childDoc.isDirectory) "$relativePath$name/" else "$relativePath$name"
198+
return SafTreeStrategy(childDoc, childPath, treeUri, rootDocId)
198199
}
199200

200201
@Throws(IOException::class)
@@ -267,7 +268,8 @@ internal class FileStrategy(
267268
override fun findFile(context: Context, name: String): WriteStrategy? {
268269
val file = File(baseDir, "$relativePath$name")
269270
if (!file.exists()) return null
270-
return FileStrategy(DocumentFile.fromFile(file), "$relativePath$name/", baseDir)
271+
val childPath = if (file.isDirectory) "$relativePath$name/" else "$relativePath$name"
272+
return FileStrategy(DocumentFile.fromFile(file), childPath, baseDir)
271273
}
272274

273275
@Throws(IOException::class)

src/android/app/src/main/java/com/jericx/syncclipboardmobile/expo-native/ShareActivity.kt

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,29 @@ class ShareActivity : ReactActivity() {
127127
NativeLogger.d(TAG, "Multiple files share: ${uris.size} files")
128128

129129
// Copy all files to cache directory and collect per-file metadata
130+
// 同名文件去重:跟踪已使用的文件名,冲突时追加 " (1)", " (2)" 等后缀
130131
val copiedPaths = ArrayList<String>()
131132
val fileNames = ArrayList<String>()
133+
val usedNames = HashMap<String, Int>()
132134

133135
for (uri in uris) {
134-
val fileName = getFileName(uri, type)
136+
var fileName = getFileName(uri, type)
135137

136-
val copiedFile = copyUriToCache(uri, type)
138+
// 去重:如果文件名已被使用,追加数字后缀
139+
val count = usedNames[fileName]
140+
if (count != null) {
141+
usedNames[fileName] = count + 1
142+
val dotIndex = fileName.lastIndexOf('.')
143+
if (dotIndex > 0) {
144+
fileName = "${fileName.substring(0, dotIndex)} (${count + 1})${fileName.substring(dotIndex)}"
145+
} else {
146+
fileName = "$fileName (${count + 1})"
147+
}
148+
} else {
149+
usedNames[fileName] = 1
150+
}
151+
152+
val copiedFile = copyUriToCache(uri, type, fileName)
137153
if (copiedFile != null) {
138154
copiedPaths.add("file://${copiedFile.absolutePath}")
139155
fileNames.add(fileName)
@@ -157,7 +173,7 @@ class ShareActivity : ReactActivity() {
157173
* Copy content from URI to cache directory.
158174
* Returns the copied file, or null if failed.
159175
*/
160-
private fun copyUriToCache(uri: Uri, mimeType: String?): File? {
176+
private fun copyUriToCache(uri: Uri, mimeType: String?, desiredName: String? = null): File? {
161177
return try {
162178
// Open input stream from content provider
163179
val inputStream: InputStream? = contentResolver.openInputStream(uri)
@@ -166,8 +182,8 @@ class ShareActivity : ReactActivity() {
166182
return null
167183
}
168184

169-
// Get file name from URI or generate one
170-
val fileName = getFileName(uri, mimeType)
185+
// Get file name from URI or generate one (use desiredName if provided for dedup)
186+
val fileName = desiredName ?: getFileName(uri, mimeType)
171187

172188
// Create file in cache directory
173189
val cacheDir = cacheDir

src/components/HistoryListItem.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ export const HistoryListItem = forwardRef<object, HistoryListItemProps>(
422422
</Text>
423423
</View>
424424
)}
425-
{/* 未下载标识 - 本地文件未就绪,仅当启用同步且不在传输中时显示 */}
425+
{/* 未下载标识 - 本地文件未就绪(所有类型通用),仅当启用同步且不在传输中时显示 */}
426426
{enableHistorySync && !isTransferring && !localFileReady && (
427427
<TouchableOpacity
428428
style={styles.syncBadge}

src/utils/hash.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -294,10 +294,11 @@ export interface GroupEntry {
294294
* 与桌面端 ByteArrayComparer 行为一致,对于包含非 ASCII 字符(如中文)的文件名
295295
* 至关重要——localeCompare 会产生不同的排序结果
296296
*/
297+
const utf8Encoder = new TextEncoder();
298+
297299
function compareUtf8Bytes(a: string, b: string): number {
298-
const encoder = new TextEncoder();
299-
const bytesA = encoder.encode(a);
300-
const bytesB = encoder.encode(b);
300+
const bytesA = utf8Encoder.encode(a);
301+
const bytesB = utf8Encoder.encode(b);
301302
const minLen = Math.min(bytesA.length, bytesB.length);
302303
for (let i = 0; i < minLen; i++) {
303304
if (bytesA[i] !== bytesB[i]) {
@@ -327,14 +328,13 @@ export function calculateGroupHash(entries: GroupEntry[]): string {
327328

328329
// Step 2-4: 流式生成条目字符串并计算 SHA256
329330
const hasher = sha256.create();
330-
const encoder = new TextEncoder();
331331

332332
for (const entry of sorted) {
333333
if (entry.isDirectory) {
334-
hasher.update(encoder.encode(`D|${entry.relativePath}\0`));
334+
hasher.update(utf8Encoder.encode(`D|${entry.relativePath}\0`));
335335
} else {
336336
hasher.update(
337-
encoder.encode(`F|${entry.relativePath}|${entry.length}|${entry.contentHash}\0`)
337+
utf8Encoder.encode(`F|${entry.relativePath}|${entry.length}|${entry.contentHash}\0`)
338338
);
339339
}
340340
}

0 commit comments

Comments
 (0)