using System; using System.Collections.Generic; using System.IO; using System.Text.Json; namespace SourceGit.Git { /// /// User's preference settings. Serialized to /// public class Preference { /// /// Group(Virtual folder) for watched repositories. /// public class Group { /// /// Unique ID of this group. /// public string Id { get; set; } /// /// Display name. /// public string Name { get; set; } /// /// Parent ID. /// public string ParentId { get; set; } /// /// Cache UI IsExpended status. /// public bool IsExpended { get; set; } } /// /// File's display mode. /// public enum FilesDisplayMode { Tree, List, Grid, } #region STATICS /// /// Storage path for Preference. /// private static readonly string SAVE_PATH = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SourceGit", "preference.json"); /// /// Runtime singleton instance. /// private static Preference instance = null; public static Preference Instance { get { if (instance == null) Load(); return instance; } set { instance = value; } } #endregion #region SETTING_GENERAL /// /// Use light color theme. /// public bool UseLightTheme { get; set; } /// /// Check for updates. /// public bool CheckUpdate { get; set; } #endregion #region SETTING_GIT /// /// Git executable file path. /// public string GitExecutable { get; set; } /// /// Default clone directory. /// public string GitDefaultCloneDir { get; set; } #endregion #region SETTING_MERGE_TOOL /// /// Selected merge tool. /// public int MergeTool { get; set; } = 0; /// /// Executable file path for merge tool. /// public string MergeExecutable { get; set; } = "--"; #endregion #region SETTING_UI /// /// Main window's width /// public double UIMainWindowWidth { get; set; } /// /// Main window's height /// public double UIMainWindowHeight { get; set; } /// /// Show/Hide tags' list view. /// public bool UIShowTags { get; set; } = true; /// /// Use horizontal layout for histories. /// public bool UIUseHorizontalLayout { get; set; } /// /// Files' display mode in unstage view. /// public FilesDisplayMode UIUnstageDisplayMode { get; set; } = FilesDisplayMode.Grid; /// /// Files' display mode in staged view. /// public FilesDisplayMode UIStagedDisplayMode { get; set; } = FilesDisplayMode.Grid; /// /// Using datagrid instead of tree in changes. /// public bool UIUseListInChanges { get; set; } /// /// Use one side diff instead of two sides. /// public bool UIUseOneSideDiff { get; set; } #endregion #region SETTING_REPOS /// /// Groups for repositories. /// public List Groups { get; set; } = new List(); /// /// Watched repositories. /// public List Repositories { get; set; } = new List(); #endregion #region METHODS_LOAD_SAVE /// /// Load preference from disk. /// /// Loaded preference instance. public static void Load() { if (!File.Exists(SAVE_PATH)) { instance = new Preference(); } else { instance = JsonSerializer.Deserialize(File.ReadAllText(SAVE_PATH)); } } /// /// Save current preference into disk. /// public static void Save() { if (instance == null) return; var dir = Path.GetDirectoryName(SAVE_PATH); if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); var data = JsonSerializer.Serialize(instance, new JsonSerializerOptions() { WriteIndented = true }); File.WriteAllText(SAVE_PATH, data); } #endregion #region METHODS_ON_GROUP /// /// Add new group(virtual folder). /// /// Display name. /// Parent group ID. /// Added group instance. public Group AddGroup(string name, string parentId) { var group = new Group() { Name = name, Id = Guid.NewGuid().ToString(), ParentId = parentId, IsExpended = false, }; Groups.Add(group); Groups.Sort((l, r) => l.Name.CompareTo(r.Name)); return group; } /// /// Find group by ID. /// /// Unique ID /// Founded group's instance. public Group FindGroup(string id) { foreach (var group in Groups) { if (group.Id == id) return group; } return null; } /// /// Rename group. /// /// Unique ID /// New name. public void RenameGroup(string id, string newName) { foreach (var group in Groups) { if (group.Id == id) { group.Name = newName; break; } } Groups.Sort((l, r) => l.Name.CompareTo(r.Name)); } /// /// Remove a group. /// /// Unique ID public void RemoveGroup(string id) { int removedIdx = -1; for (int i = 0; i < Groups.Count; i++) { if (Groups[i].Id == id) { removedIdx = i; break; } } if (removedIdx >= 0) Groups.RemoveAt(removedIdx); } #endregion #region METHODS_ON_REPOS /// /// Add repository. /// /// Local storage path. /// Group's ID /// Added repository instance. public Repository AddRepository(string path, string groupId) { var repo = FindRepository(path); if (repo != null) return repo; var dir = new DirectoryInfo(path); repo = new Repository() { Path = dir.FullName, Name = dir.Name, GroupId = groupId, LastOpenTime = 0, }; Repositories.Add(repo); Repositories.Sort((l, r) => l.Name.CompareTo(r.Name)); return repo; } /// /// Find repository by path. /// /// Local storage path. /// Founded repository instance. public Repository FindRepository(string path) { var dir = new DirectoryInfo(path); foreach (var repo in Repositories) { if (repo.Path == dir.FullName) return repo; } return null; } /// /// Change a repository's display name in RepositoryManager. /// /// Local storage path. /// New name public void RenameRepository(string path, string newName) { var repo = FindRepository(path); if (repo == null) return; repo.Name = newName; Repositories.Sort((l, r) => l.Name.CompareTo(r.Name)); } /// /// Remove a repository in RepositoryManager. /// /// Local storage path. public void RemoveRepository(string path) { var dir = new DirectoryInfo(path); var removedIdx = -1; for (int i = 0; i < Repositories.Count; i++) { if (Repositories[i].Path == dir.FullName) { removedIdx = i; break; } } if (removedIdx >= 0) Repositories.RemoveAt(removedIdx); } #endregion } }