diff --git a/src/ST.Client.Desktop.Avalonia.App/Program.cs b/src/ST.Client.Desktop.Avalonia.App/Program.cs index 498bbddd0..ab4291caf 100644 --- a/src/ST.Client.Desktop.Avalonia.App/Program.cs +++ b/src/ST.Client.Desktop.Avalonia.App/Program.cs @@ -24,6 +24,8 @@ namespace System.Application.UI #if MAC AppDelegate.Init(/*args*/); FileSystemDesktopMac.InitFileSystem(); +#elif LINUX + FileSystemDesktopXDG.InitFileSystem(); #else FileSystemDesktop.InitFileSystem(); #endif diff --git a/src/ST.Client.Desktop.Linux/FileSystemDesktopXDG.cs b/src/ST.Client.Desktop.Linux/FileSystemDesktopXDG.cs new file mode 100644 index 000000000..f0046b9c1 --- /dev/null +++ b/src/ST.Client.Desktop.Linux/FileSystemDesktopXDG.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace System.Application +{ + /// + /// 适用于 Linux 的文件系统初始化 + /// XDG Base Directory Specification + /// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html + /// https://wiki.archlinux.org/title/XDG_Base_Directory + /// + public sealed class FileSystemDesktopXDG : IOPath.FileSystemBase + { + private FileSystemDesktopXDG() => throw new NotSupportedException(); + + /// + public static void InitFileSystem() + { + var appDataPath = AppDataDirectory; + var cachePath = CacheDirectory; + + var paths = new[] { appDataPath, cachePath, }; + var dict_paths = paths.ToDictionary(x => x, Directory.Exists); + + if (dict_paths.Values.All(x => !x)) + { + var old_paths = new[] { FileSystemDesktop.AppDataDirectory, FileSystemDesktop.CacheDirectory, }; + if (old_paths.All(Directory.Exists)) // 迁移之前根目录上的文件夹 + { + for (int i = 0; i < old_paths.Length; i++) + { + var path = paths[i]; + var old_path = old_paths[i]; + Directory.Move(old_path, path); + dict_paths[path] = true; + } + } + } + + foreach (var item in dict_paths) + { + if (!item.Value) + { + Directory.CreateDirectory(item.Key); + } + } + + InitFileSystem(GetAppDataDirectory, GetCacheDirectory); + string GetAppDataDirectory() => appDataPath; + string GetCacheDirectory() => cachePath; + } + + static string AppDataDirectory + { + get + { + var value = Environment.GetEnvironmentVariable(XDG_DATA_HOME); + if (!string.IsNullOrWhiteSpace(value)) + { + return Path.Combine(value, Constants.HARDCODED_APP_NAME); + } + value = Environment.GetEnvironmentVariable(HOME); + if (!string.IsNullOrWhiteSpace(value)) + { + return Path.Combine(value, ".local", "share", Constants.HARDCODED_APP_NAME); + } + throw new PlatformNotSupportedException(); + } + } + + static string CacheDirectory + { + get + { + var value = Environment.GetEnvironmentVariable(XDG_CACHE_HOME); + if (!string.IsNullOrWhiteSpace(value)) + { + return Path.Combine(value, Constants.HARDCODED_APP_NAME); + } + value = Environment.GetEnvironmentVariable(HOME); + if (!string.IsNullOrWhiteSpace(value)) + { + return Path.Combine(value, ".cache", Constants.HARDCODED_APP_NAME); + } + throw new PlatformNotSupportedException(); + } + } + + const string HOME = "$HOME"; + + const string XDG_DATA_HOME = "$XDG_DATA_HOME"; + + const string XDG_CACHE_HOME = "$XDG_CACHE_HOME"; + } +} diff --git a/src/ST.Client/FileSystemDesktop.cs b/src/ST.Client/FileSystemDesktop.cs index b441de920..541d50f25 100644 --- a/src/ST.Client/FileSystemDesktop.cs +++ b/src/ST.Client/FileSystemDesktop.cs @@ -13,29 +13,45 @@ namespace System.Application { private FileSystemDesktop() => throw new NotSupportedException(); - /// - /// 初始化文件系统 - /// - public static void InitFileSystem() + static string BaseDirectory { - //var appDataRootPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - //if (string.IsNullOrWhiteSpace(appDataRootPath)) - //{ - // // 需要测试 macOS 和 linux 上 Environment.SpecialFolder.ApplicationData 返回的目录值 - // // 之前在 android 上测试过 Environment.GetFolderPath 有些枚举值返回的是空字符串 比如StartMenu - // throw new ArgumentNullException(nameof(appDataRootPath)); - //} - //appDataRootPath = Path.Combine(appDataRootPath, BuildConfig.APPLICATION_ID); - - var appDataRootPath = + get + { + var appDataRootPath = #if NET35 WinFormsApplication.StartupPath; #else IOPath.BaseDirectory; #endif + return appDataRootPath; + } + } - var appDataPath = Path.Combine(appDataRootPath, IOPath.DirName_AppData); - var cachePath = Path.Combine(appDataRootPath, IOPath.DirName_Cache); + public static string AppDataDirectory + { + get + { + var appDataPath = Path.Combine(BaseDirectory, IOPath.DirName_AppData); + return appDataPath; + } + } + + public static string CacheDirectory + { + get + { + var cachePath = Path.Combine(BaseDirectory, IOPath.DirName_Cache); + return cachePath; + } + } + + /// + /// 初始化文件系统 + /// + public static void InitFileSystem() + { + var appDataPath = AppDataDirectory; + var cachePath = CacheDirectory; IOPath.DirCreateByNotExists(appDataPath); IOPath.DirCreateByNotExists(cachePath); InitFileSystem(GetAppDataDirectory, GetCacheDirectory);