From bf49323789fbeebbace908bba931e0c38f35de04 Mon Sep 17 00:00:00 2001 From: truewhile <62226914+truewhile@users.noreply.github.com> Date: Wed, 2 Sep 2026 15:51:31 +0800 Subject: [PATCH] feat(strm): auto-append remote directory tail to local output path (#16) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When adding or editing a cloud sync path, append the last segment of the remote directory to the local output directory (e.g. /home/ubuntu/strm + 电影). Remote changes replace the previous auto-appended tail; local browse and blur commit the base path with the current remote tail. Co-authored-by: Cursor Agent Co-authored-by: truewhile --- web/src/pages/StrmDialogs.tsx | 55 +++++++++++++++++++++++++++++++---- web/src/utils/strmPaths.ts | 53 +++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 web/src/utils/strmPaths.ts diff --git a/web/src/pages/StrmDialogs.tsx b/web/src/pages/StrmDialogs.tsx index 8e682dd..1f95e29 100644 --- a/web/src/pages/StrmDialogs.tsx +++ b/web/src/pages/StrmDialogs.tsx @@ -33,6 +33,7 @@ import { normalizeEmbyRemoteLines, type EmbyRemoteLine, } from '../utils/embyRemoteLines' +import { lastPathSegment, syncLocalPathWithRemote } from '../utils/strmPaths' // ─── 弹框外壳 ──────────────────────────────────────────────────────────────── @@ -913,10 +914,27 @@ export function StrmSyncPathDialog({ const [saving, setSaving] = useState(false) const [browsing, setBrowsing] = useState(false) const [browsingLocal, setBrowsingLocal] = useState(null) + const prevRemoteTailRef = useRef(existing ? lastPathSegment(existing.remote_path) : '') const set = (key: K, value: StrmSyncPathInput[K]) => setForm((f) => ({ ...f, [key]: value })) + const updateRemotePath = (remotePath: string) => { + setForm((f) => { + const synced = syncLocalPathWithRemote(f.local_path, remotePath, prevRemoteTailRef.current) + prevRemoteTailRef.current = synced.remoteTail + return { ...f, remote_path: remotePath, local_path: synced.localPath } + }) + } + + const commitLocalPath = (localPath: string) => { + setForm((f) => { + const synced = syncLocalPathWithRemote(localPath, f.remote_path, prevRemoteTailRef.current) + prevRemoteTailRef.current = synced.remoteTail + return { ...f, local_path: synced.localPath } + }) + } + const isLocal = form.provider === 'local' const availableAccounts = accounts.filter((a) => a.provider === form.provider && a.has_credential) @@ -1000,7 +1018,15 @@ export function StrmSyncPathDialog({ : '远端路径(可通过浏览选择)' } > - set('remote_path', e.target.value)} /> + set('remote_path', e.target.value)} + onBlur={(e) => { + if (!isLocal) updateRemotePath(e.target.value) + }} + /> {isLocal && ( @@ -1023,8 +1049,23 @@ export function StrmSyncPathDialog({
- - set('local_path', e.target.value)} /> + + set('local_path', e.target.value)} + onBlur={(e) => { + if (!isLocal) commitLocalPath(e.target.value) + }} + />