44using System . IO ;
55using System . Text . Json ;
66using System . Threading . Tasks ;
7- using Avalonia ;
8- using Avalonia . Controls . ApplicationLifetimes ;
9- using Avalonia . Platform . Storage ;
107using CommunityToolkit . Mvvm . ComponentModel ;
118using CommunityToolkit . Mvvm . Input ;
12- using Microsoft . Win32 ;
139using Windows . Storage ;
1410
1511namespace ContextMenu . Avalonia . ViewModels ;
1612
1713public partial class MainWindowViewModel : ViewModelBase
1814{
15+ private const string AppName = "Kitopia" ;
1916 private const string SettingsFileName = "ContextMenuSettings.json" ;
2017 private const string ConfigFileName = "KitopiaContextMenu.json" ;
2118
@@ -38,39 +35,19 @@ private async Task LoadDataAsync()
3835 {
3936 try
4037 {
41- // 0. Check for Saved Manual Path
38+ // 0. Resolve install path
4239 var settings = LoadSettings ( ) ;
43- string ? installPath = null ;
44-
45- if ( ! string . IsNullOrEmpty ( settings . ExternalConfigPath ) )
46- {
47- // Try to infer install path from config path (..\configs\file.json)
48- var configDir = Path . GetDirectoryName ( settings . ExternalConfigPath ) ;
49- if ( configDir != null )
50- {
51- var inferredPath = Path . GetDirectoryName ( configDir ) ; // Parent of configs
52- if ( inferredPath != null && Directory . Exists ( inferredPath ) )
53- {
54- installPath = inferredPath ;
55- }
56- }
57- }
40+ KitopiaPath = GetAppRootPath ( ) ;
5841
59- // 1. If no manual path, Find Kitopia Path from Registry
60- if ( string . IsNullOrEmpty ( installPath ) )
61- {
62- installPath = FindKitopiaInstallPath ( ) ;
63- }
64-
65- if ( string . IsNullOrEmpty ( installPath ) )
42+ if ( string . IsNullOrWhiteSpace ( KitopiaPath ) )
6643 {
6744 StatusMessage = "未找到 Kitopia 安装位置,请手动设置。" ;
6845 return ;
6946 }
70- KitopiaPath = installPath ;
47+ // install path search is removed; config path is fixed under AppData
7148
7249 // 2. Locate Config
73- var configPath = Path . Combine ( installPath , "configs" , ConfigFileName ) ;
50+ var configPath = GetConfigPath ( ) ;
7451 if ( ! File . Exists ( configPath ) )
7552 {
7653 StatusMessage = $ "未找到配置文件: { configPath } ";
@@ -123,100 +100,9 @@ private async Task LoadDataAsync()
123100 }
124101
125102 [ RelayCommand ]
126- private async Task BrowsePath ( )
103+ private void BrowsePath ( )
127104 {
128- if ( Application . Current ? . ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop )
129- {
130- var folders = await desktop . MainWindow . StorageProvider . OpenFolderPickerAsync ( new FolderPickerOpenOptions
131- {
132- Title = "选择 Kitopia 安装文件夹" ,
133- AllowMultiple = false
134- } ) ;
135-
136- if ( folders . Count > 0 )
137- {
138- var path = folders [ 0 ] . Path . LocalPath ;
139-
140- // Verify it looks like Kitopia (check for executable or configs folder)
141- if ( File . Exists ( Path . Combine ( path , "Kitopia.StoreCompanion.exe" ) ) ||
142- File . Exists ( Path . Combine ( path , "KitopiaAvalonia.exe" ) ) ||
143- Directory . Exists ( Path . Combine ( path , "configs" ) ) )
144- {
145- KitopiaPath = path ;
146-
147- // Update settings with new config path
148- var settings = LoadSettings ( ) ;
149- settings . ExternalConfigPath = Path . Combine ( KitopiaPath , "configs" , ConfigFileName ) ;
150- SaveSettings ( settings ) ;
151-
152- // Reload
153- await LoadDataAsync ( ) ;
154- }
155- else
156- {
157- StatusMessage = "选择的文件夹似乎不是有效的 Kitopia 安装目录。" ;
158- }
159- }
160- }
161- }
162-
163- private string ? FindKitopiaInstallPath ( )
164- {
165- try
166- {
167- // Check HKLM and HKCU Uninstall keys
168- string [ ] roots = {
169- @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" ,
170- @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
171- } ;
172-
173- foreach ( var root in roots )
174- {
175- using var key = Registry . LocalMachine . OpenSubKey ( root ) ;
176- if ( key != null )
177- {
178- SearchRegistryKey ( key , out var path ) ;
179- if ( ! string . IsNullOrEmpty ( path ) ) return path ;
180- }
181- }
182-
183- // Try HKCU
184- using var cuKey = Registry . CurrentUser . OpenSubKey ( @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" ) ;
185- if ( cuKey != null )
186- {
187- SearchRegistryKey ( cuKey , out var path ) ;
188- if ( ! string . IsNullOrEmpty ( path ) ) return path ;
189- }
190-
191- }
192- catch { }
193- return null ;
194-
195- void SearchRegistryKey ( RegistryKey root , out string ? foundPath )
196- {
197- foundPath = null ;
198- foreach ( var subKeyName in root . GetSubKeyNames ( ) )
199- {
200- using var subKey = root . OpenSubKey ( subKeyName ) ;
201- if ( subKey == null ) continue ;
202-
203- var displayName = subKey . GetValue ( "DisplayName" ) as string ;
204- if ( displayName != null && displayName . Contains ( "Kitopia" ) && ! displayName . Contains ( "Packing" ) )
205- {
206- var installLocation = subKey . GetValue ( "InstallLocation" ) as string ;
207- if ( string . IsNullOrEmpty ( installLocation ) )
208- {
209- installLocation = subKey . GetValue ( "Path" ) as string ; // ModernInstaller uses "Path"
210- }
211-
212- if ( ! string . IsNullOrEmpty ( installLocation ) && Directory . Exists ( installLocation ) )
213- {
214- foundPath = installLocation ;
215- return ;
216- }
217- }
218- }
219- }
105+ StatusMessage = $ "配置路径已固定: { GetConfigPath ( ) } ";
220106 }
221107
222108 private ContextMenuSettings LoadSettings ( )
@@ -242,7 +128,7 @@ private void SaveSettings(ContextMenuSettings? settings = null)
242128 {
243129 settings = new ContextMenuSettings
244130 {
245- ExternalConfigPath = Path . Combine ( KitopiaPath , "configs" , ConfigFileName )
131+ ExternalConfigPath = GetConfigPath ( )
246132 } ;
247133 foreach ( var item in Items )
248134 {
@@ -263,6 +149,26 @@ private void SaveSettings(ContextMenuSettings? settings = null)
263149 }
264150 }
265151
152+ private static string GetConfigPath ( )
153+ {
154+ var configsDirectory = Path . Combine ( GetAppRootPath ( ) , "configs" ) ;
155+ Directory . CreateDirectory ( configsDirectory ) ;
156+ return Path . Combine ( configsDirectory , ConfigFileName ) ;
157+ }
158+
159+ private static string GetAppRootPath ( )
160+ {
161+ var localAppData = Environment . GetFolderPath ( Environment . SpecialFolder . LocalApplicationData ) ;
162+ if ( string . IsNullOrWhiteSpace ( localAppData ) )
163+ {
164+ localAppData = AppDomain . CurrentDomain . BaseDirectory ;
165+ }
166+
167+ var root = Path . Combine ( localAppData , AppName ) ;
168+ Directory . CreateDirectory ( root ) ;
169+ return root ;
170+ }
171+
266172 private string GetSettingsPath ( )
267173 {
268174 // Try Package LocalState first
0 commit comments