fix: correct UTF-8 encoding in base64 decode for file paths fix #20

The old decodeBase64 implementation tried atob() first which returns
garbled text for UTF-8 content (e.g., Chinese characters), and only
fell back to correct UTF-8 decoding when atob() threw an exception
(which it doesn't for valid base64).

Changes:
- Add encodeBase64/decodeBase64 utilities to web/src/lib/utils.ts
  using TextEncoder/TextDecoder for proper UTF-8 support
- Update file.tsx to use shared decodeBase64 instead of buggy local impl
- Update files.tsx to use shared encodeBase64 instead of deprecated
  escape/unescape approach
This commit is contained in:
weishu
2025-12-28 14:38:05 +08:00
parent d68b91fd07
commit 20c05a06ec
3 changed files with 27 additions and 22 deletions
+1 -12
View File
@@ -9,18 +9,7 @@ import { useAppGoBack } from '@/hooks/useAppGoBack'
import { useCopyToClipboard } from '@/hooks/useCopyToClipboard'
import { queryKeys } from '@/lib/query-keys'
import { langAlias, useShikiHighlighter } from '@/lib/shiki'
function decodeBase64(value: string): { text: string; ok: boolean } {
try {
return { text: atob(value), ok: true }
} catch {
try {
return { text: decodeURIComponent(escape(atob(value))), ok: true }
} catch {
return { text: '', ok: false }
}
}
}
import { decodeBase64 } from '@/lib/utils'
function decodePath(value: string): string {
if (!value) return ''
+3 -10
View File
@@ -7,14 +7,7 @@ import { useAppGoBack } from '@/hooks/useAppGoBack'
import { useGitStatusFiles } from '@/hooks/queries/useGitStatusFiles'
import { useSession } from '@/hooks/queries/useSession'
import { useSessionFileSearch } from '@/hooks/queries/useSessionFileSearch'
function encodePath(value: string): string {
try {
return btoa(value)
} catch {
return btoa(unescape(encodeURIComponent(value)))
}
}
import { encodeBase64 } from '@/lib/utils'
function BackIcon(props: { className?: string }) {
return (
@@ -255,8 +248,8 @@ export default function FilesPage() {
const handleOpenFile = useCallback((path: string, staged?: boolean) => {
const search = staged === undefined
? { path: encodePath(path) }
: { path: encodePath(path), staged }
? { path: encodeBase64(path) }
: { path: encodeBase64(path), staged }
navigate({
to: '/sessions/$sessionId/file',
params: { sessionId },