@@ -43,6 +43,19 @@ const INPUT_METHODS: { label: string; value: InputMethod }[] = [
4343 { label : "元书输入法" , value : "hamster3" } ,
4444]
4545
46+ function isPromiseLike ( v : any ) : v is Promise < any > {
47+ return ! ! v && typeof v === "object" && typeof v . then === "function"
48+ }
49+
50+ async function callMaybeAsync ( fn : any , thisArg : any , args : any [ ] ) {
51+ try {
52+ const r = fn . apply ( thisArg , args )
53+ return isPromiseLike ( r ) ? await r : r
54+ } catch {
55+ return undefined
56+ }
57+ }
58+
4659function CenterRowButton ( props : {
4760 title : string
4861 role ?: "cancel" | "destructive"
@@ -85,6 +98,7 @@ export function SettingsView(props: {
8598 const initialSchemeEdition = initialCfg . schemeEdition
8699 const initialProSchemeKey = initialCfg . proSchemeKey
87100 const initialHamsterRootPath = initialCfg . hamsterRootPath
101+ const initialHamsterBookmarkName = initialCfg . hamsterBookmarkName
88102 const [ cfg , setCfg ] = useState < AppConfig > ( initialCfg )
89103
90104 // ✅ 用 number 承载 Picker 值(与你示例一致)
@@ -174,12 +188,33 @@ export function SettingsView(props: {
174188 . filter ( ( x : any ) => x . name && x . path )
175189 setBookmarks ( cleaned )
176190
177- const target = current ?. hamsterRootPath ?? cfg . hamsterRootPath
191+ const targetName = current ?. hamsterBookmarkName ?? cfg . hamsterBookmarkName
192+ const targetPath = current ?. hamsterRootPath ?? cfg . hamsterRootPath
178193 if ( cleaned . length ) {
179- const idx = cleaned . findIndex ( ( b ) => b . path === target )
194+ let idx = - 1
195+ if ( targetName ) idx = cleaned . findIndex ( ( b ) => b . name === targetName )
196+ if ( idx < 0 && targetPath ) idx = cleaned . findIndex ( ( b ) => b . path === targetPath )
180197 setBookmarkIdx ( idx >= 0 ? idx : 0 )
181- if ( idx < 0 && ! target ) {
182- setCfg ( ( c ) => ( { ...c , hamsterRootPath : cleaned [ 0 ] . path } ) )
198+ if ( idx >= 0 ) {
199+ const matched = cleaned [ idx ]
200+ const resolved = fm ?. bookmarkedPath
201+ ? String ( ( await callMaybeAsync ( fm . bookmarkedPath , fm , [ matched . name ] ) ) ?? matched . path )
202+ : matched . path
203+ const pathChanged = resolved !== targetPath || matched . name !== targetName
204+ if ( pathChanged ) {
205+ setCfg ( ( c ) => ( { ...c , hamsterRootPath : resolved , hamsterBookmarkName : matched . name } ) )
206+ try {
207+ const next = { ...loadConfig ( ) , hamsterRootPath : resolved , hamsterBookmarkName : matched . name }
208+ saveConfig ( next )
209+ props . onDone ?.( next )
210+ } catch { }
211+ }
212+ } else if ( ! targetPath ) {
213+ setCfg ( ( c ) => ( {
214+ ...c ,
215+ hamsterRootPath : cleaned [ 0 ] . path ,
216+ hamsterBookmarkName : cleaned [ 0 ] . name ,
217+ } ) )
183218 }
184219 } else {
185220 setBookmarkIdx ( 0 )
@@ -212,7 +247,9 @@ export function SettingsView(props: {
212247 const schemeChanged =
213248 fixed . schemeEdition !== initialSchemeEdition ||
214249 ( fixed . schemeEdition === "pro" && fixed . proSchemeKey !== initialProSchemeKey )
215- const pathChanged = fixed . hamsterRootPath !== initialHamsterRootPath
250+ const pathChanged =
251+ fixed . hamsterRootPath !== initialHamsterRootPath ||
252+ fixed . hamsterBookmarkName !== initialHamsterBookmarkName
216253 if ( schemeChanged && ! pathChanged ) {
217254 try {
218255 const { rimeDir } = await detectRimeDir ( fixed )
@@ -252,7 +289,7 @@ export function SettingsView(props: {
252289 < TextField
253290 label = { < Text > 路径</ Text > }
254291 value = { cfg . hamsterRootPath }
255- onChanged = { ( v : string ) => setCfg ( ( c ) => ( { ...c , hamsterRootPath : v } ) ) }
292+ onChanged = { ( v : string ) => setCfg ( ( c ) => ( { ...c , hamsterRootPath : v , hamsterBookmarkName : "" } ) ) }
256293 prompt = "粘贴或选择 Hamster 根目录"
257294 textFieldStyle = "roundedBorder"
258295 />
@@ -269,12 +306,22 @@ export function SettingsView(props: {
269306 setBookmarkIdx ( idx )
270307 const b = bookmarks [ idx ]
271308 if ( b ?. path ) {
272- const next : AppConfig = { ...cfg , hamsterRootPath : b . path }
273- setCfg ( next )
274- try {
275- saveConfig ( next )
276- props . onDone ?.( next )
277- } catch { }
309+ ; ( async ( ) => {
310+ const fm : any = ( globalThis as any ) . FileManager ?? Runtime . FileManager
311+ const resolved = fm ?. bookmarkedPath
312+ ? String ( ( await callMaybeAsync ( fm . bookmarkedPath , fm , [ b . name ] ) ) ?? b . path )
313+ : b . path
314+ const next : AppConfig = {
315+ ...cfg ,
316+ hamsterRootPath : resolved ,
317+ hamsterBookmarkName : b . name ,
318+ }
319+ setCfg ( next )
320+ try {
321+ saveConfig ( next )
322+ props . onDone ?.( next )
323+ } catch { }
324+ } ) ( )
278325 }
279326 } }
280327 >
0 commit comments