2024-03-20 00:36:10 -07:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
|
|
|
using System.Text.Json;
|
|
|
|
using System.Text.Json.Serialization;
|
2024-09-01 21:20:11 -07:00
|
|
|
|
2024-03-20 00:36:10 -07:00
|
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
|
|
|
|
|
|
namespace SourceGit.ViewModels
|
|
|
|
{
|
|
|
|
public class Preference : ObservableObject
|
|
|
|
{
|
|
|
|
[JsonIgnore]
|
|
|
|
public static Preference Instance
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
2024-10-09 00:58:44 -07:00
|
|
|
if (_instance != null)
|
|
|
|
return _instance;
|
|
|
|
|
|
|
|
_isLoading = true;
|
|
|
|
_instance = Load();
|
|
|
|
_isLoading = false;
|
2024-03-20 00:36:10 -07:00
|
|
|
|
2024-09-18 06:35:33 -07:00
|
|
|
_instance.PrepareGit();
|
|
|
|
_instance.PrepareShellOrTerminal();
|
|
|
|
_instance.PrepareWorkspaces();
|
2024-10-23 19:20:28 -07:00
|
|
|
_instance.PrepareOpenAIPrompt();
|
2024-10-09 00:58:44 -07:00
|
|
|
|
2024-03-20 00:36:10 -07:00
|
|
|
return _instance;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public string Locale
|
|
|
|
{
|
|
|
|
get => _locale;
|
|
|
|
set
|
|
|
|
{
|
2024-08-19 02:14:41 -07:00
|
|
|
if (SetProperty(ref _locale, value) && !_isLoading)
|
2024-03-20 00:36:10 -07:00
|
|
|
App.SetLocale(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public string Theme
|
|
|
|
{
|
|
|
|
get => _theme;
|
|
|
|
set
|
|
|
|
{
|
2024-08-19 02:14:41 -07:00
|
|
|
if (SetProperty(ref _theme, value) && !_isLoading)
|
2024-07-08 01:21:57 -07:00
|
|
|
App.SetTheme(_theme, _themeOverrides);
|
2024-06-05 03:23:28 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-08 01:21:57 -07:00
|
|
|
public string ThemeOverrides
|
2024-06-05 03:23:28 -07:00
|
|
|
{
|
2024-07-08 01:21:57 -07:00
|
|
|
get => _themeOverrides;
|
2024-06-05 03:23:28 -07:00
|
|
|
set
|
|
|
|
{
|
2024-08-19 02:14:41 -07:00
|
|
|
if (SetProperty(ref _themeOverrides, value) && !_isLoading)
|
2024-06-05 03:23:28 -07:00
|
|
|
App.SetTheme(_theme, value);
|
2024-03-20 00:36:10 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-19 02:14:41 -07:00
|
|
|
public string DefaultFontFamily
|
2024-03-21 03:02:06 -07:00
|
|
|
{
|
2024-08-19 02:14:41 -07:00
|
|
|
get => _defaultFontFamily;
|
2024-08-19 20:53:37 -07:00
|
|
|
set
|
|
|
|
{
|
2024-08-19 02:14:41 -07:00
|
|
|
if (SetProperty(ref _defaultFontFamily, value) && !_isLoading)
|
|
|
|
App.SetFonts(_defaultFontFamily, _monospaceFontFamily, _onlyUseMonoFontInEditor);
|
2024-07-29 19:29:07 -07:00
|
|
|
}
|
2024-03-21 03:02:06 -07:00
|
|
|
}
|
|
|
|
|
2024-08-19 02:14:41 -07:00
|
|
|
public string MonospaceFontFamily
|
2024-03-21 03:02:06 -07:00
|
|
|
{
|
2024-08-19 02:14:41 -07:00
|
|
|
get => _monospaceFontFamily;
|
2024-07-29 19:29:07 -07:00
|
|
|
set
|
|
|
|
{
|
2024-08-19 02:14:41 -07:00
|
|
|
if (SetProperty(ref _monospaceFontFamily, value) && !_isLoading)
|
|
|
|
App.SetFonts(_defaultFontFamily, _monospaceFontFamily, _onlyUseMonoFontInEditor);
|
2024-07-29 19:29:07 -07:00
|
|
|
}
|
2024-03-21 03:02:06 -07:00
|
|
|
}
|
|
|
|
|
2024-07-29 05:20:27 -07:00
|
|
|
public bool OnlyUseMonoFontInEditor
|
|
|
|
{
|
|
|
|
get => _onlyUseMonoFontInEditor;
|
|
|
|
set
|
|
|
|
{
|
2024-08-19 02:14:41 -07:00
|
|
|
if (SetProperty(ref _onlyUseMonoFontInEditor, value) && !_isLoading)
|
|
|
|
App.SetFonts(_defaultFontFamily, _monospaceFontFamily, _onlyUseMonoFontInEditor);
|
2024-07-29 05:20:27 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-21 21:37:26 -07:00
|
|
|
public bool UseSystemWindowFrame
|
|
|
|
{
|
|
|
|
get => _useSystemWindowFrame;
|
|
|
|
set => SetProperty(ref _useSystemWindowFrame, value);
|
|
|
|
}
|
|
|
|
|
2024-03-21 21:03:04 -07:00
|
|
|
public double DefaultFontSize
|
|
|
|
{
|
|
|
|
get => _defaultFontSize;
|
|
|
|
set => SetProperty(ref _defaultFontSize, value);
|
|
|
|
}
|
|
|
|
|
2024-06-11 01:36:52 -07:00
|
|
|
public LayoutInfo Layout
|
|
|
|
{
|
|
|
|
get => _layout;
|
|
|
|
set => SetProperty(ref _layout, value);
|
|
|
|
}
|
|
|
|
|
2024-03-20 00:36:10 -07:00
|
|
|
public int MaxHistoryCommits
|
|
|
|
{
|
|
|
|
get => _maxHistoryCommits;
|
|
|
|
set => SetProperty(ref _maxHistoryCommits, value);
|
|
|
|
}
|
|
|
|
|
2024-06-23 00:45:54 -07:00
|
|
|
public int SubjectGuideLength
|
|
|
|
{
|
|
|
|
get => _subjectGuideLength;
|
|
|
|
set => SetProperty(ref _subjectGuideLength, value);
|
|
|
|
}
|
|
|
|
|
2024-03-20 00:36:10 -07:00
|
|
|
public bool UseFixedTabWidth
|
|
|
|
{
|
|
|
|
get => _useFixedTabWidth;
|
|
|
|
set => SetProperty(ref _useFixedTabWidth, value);
|
|
|
|
}
|
|
|
|
|
2024-03-26 07:11:06 -07:00
|
|
|
public bool Check4UpdatesOnStartup
|
|
|
|
{
|
|
|
|
get => _check4UpdatesOnStartup;
|
|
|
|
set => SetProperty(ref _check4UpdatesOnStartup, value);
|
|
|
|
}
|
|
|
|
|
2024-10-11 18:56:33 -07:00
|
|
|
public bool ShowAuthorTimeInGraph
|
|
|
|
{
|
|
|
|
get => _showAuthorTimeInGraph;
|
|
|
|
set => SetProperty(ref _showAuthorTimeInGraph, value);
|
|
|
|
}
|
|
|
|
|
2024-03-26 07:11:06 -07:00
|
|
|
public string IgnoreUpdateTag
|
|
|
|
{
|
2024-09-01 21:20:11 -07:00
|
|
|
get => _ignoreUpdateTag;
|
|
|
|
set => SetProperty(ref _ignoreUpdateTag, value);
|
|
|
|
}
|
2024-03-26 07:11:06 -07:00
|
|
|
|
2024-08-11 03:12:58 -07:00
|
|
|
public bool ShowTagsAsTree
|
|
|
|
{
|
|
|
|
get => _showTagsAsTree;
|
|
|
|
set => SetProperty(ref _showTagsAsTree, value);
|
|
|
|
}
|
|
|
|
|
2024-03-20 00:36:10 -07:00
|
|
|
public bool UseTwoColumnsLayoutInHistories
|
|
|
|
{
|
|
|
|
get => _useTwoColumnsLayoutInHistories;
|
|
|
|
set => SetProperty(ref _useTwoColumnsLayoutInHistories, value);
|
|
|
|
}
|
|
|
|
|
2024-07-15 20:15:41 -07:00
|
|
|
public bool DisplayTimeAsPeriodInHistories
|
|
|
|
{
|
|
|
|
get => _displayTimeAsPeriodInHistories;
|
|
|
|
set => SetProperty(ref _displayTimeAsPeriodInHistories, value);
|
|
|
|
}
|
|
|
|
|
2024-03-20 00:36:10 -07:00
|
|
|
public bool UseSideBySideDiff
|
|
|
|
{
|
|
|
|
get => _useSideBySideDiff;
|
|
|
|
set => SetProperty(ref _useSideBySideDiff, value);
|
|
|
|
}
|
|
|
|
|
2024-03-20 05:17:20 -07:00
|
|
|
public bool UseSyntaxHighlighting
|
|
|
|
{
|
|
|
|
get => _useSyntaxHighlighting;
|
|
|
|
set => SetProperty(ref _useSyntaxHighlighting, value);
|
|
|
|
}
|
|
|
|
|
2024-06-04 05:19:49 -07:00
|
|
|
public bool EnableDiffViewWordWrap
|
|
|
|
{
|
|
|
|
get => _enableDiffViewWordWrap;
|
|
|
|
set => SetProperty(ref _enableDiffViewWordWrap, value);
|
|
|
|
}
|
|
|
|
|
2024-06-19 03:15:32 -07:00
|
|
|
public bool ShowHiddenSymbolsInDiffView
|
|
|
|
{
|
|
|
|
get => _showHiddenSymbolsInDiffView;
|
|
|
|
set => SetProperty(ref _showHiddenSymbolsInDiffView, value);
|
|
|
|
}
|
|
|
|
|
2024-03-20 00:36:10 -07:00
|
|
|
public Models.ChangeViewMode UnstagedChangeViewMode
|
|
|
|
{
|
|
|
|
get => _unstagedChangeViewMode;
|
|
|
|
set => SetProperty(ref _unstagedChangeViewMode, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
public Models.ChangeViewMode StagedChangeViewMode
|
|
|
|
{
|
|
|
|
get => _stagedChangeViewMode;
|
|
|
|
set => SetProperty(ref _stagedChangeViewMode, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
public Models.ChangeViewMode CommitChangeViewMode
|
|
|
|
{
|
|
|
|
get => _commitChangeViewMode;
|
|
|
|
set => SetProperty(ref _commitChangeViewMode, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
public string GitInstallPath
|
|
|
|
{
|
2024-04-05 22:14:22 -07:00
|
|
|
get => Native.OS.GitExecutable;
|
2024-03-20 00:36:10 -07:00
|
|
|
set
|
|
|
|
{
|
2024-04-05 22:14:22 -07:00
|
|
|
if (Native.OS.GitExecutable != value)
|
2024-03-20 00:36:10 -07:00
|
|
|
{
|
2024-04-05 22:14:22 -07:00
|
|
|
Native.OS.GitExecutable = value;
|
2024-07-14 09:30:31 -07:00
|
|
|
OnPropertyChanged();
|
2024-03-20 00:36:10 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public string GitDefaultCloneDir
|
|
|
|
{
|
|
|
|
get => _gitDefaultCloneDir;
|
|
|
|
set => SetProperty(ref _gitDefaultCloneDir, value);
|
|
|
|
}
|
|
|
|
|
2024-09-13 21:09:50 -07:00
|
|
|
public int ShellOrTerminal
|
2024-09-11 03:22:05 -07:00
|
|
|
{
|
2024-09-13 21:09:50 -07:00
|
|
|
get => _shellOrTerminal;
|
2024-09-11 03:22:05 -07:00
|
|
|
set
|
|
|
|
{
|
2024-09-13 21:09:50 -07:00
|
|
|
if (SetProperty(ref _shellOrTerminal, value))
|
2024-09-11 03:22:05 -07:00
|
|
|
{
|
2024-09-13 21:09:50 -07:00
|
|
|
if (value >= 0 && value < Models.ShellOrTerminal.Supported.Count)
|
|
|
|
Native.OS.SetShellOrTerminal(Models.ShellOrTerminal.Supported[value]);
|
|
|
|
else
|
|
|
|
Native.OS.SetShellOrTerminal(null);
|
2024-09-11 03:22:05 -07:00
|
|
|
|
2024-09-13 21:09:50 -07:00
|
|
|
OnPropertyChanged(nameof(ShellOrTerminalPath));
|
2024-09-11 03:22:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-13 21:09:50 -07:00
|
|
|
public string ShellOrTerminalPath
|
2024-09-11 03:22:05 -07:00
|
|
|
{
|
2024-09-13 21:09:50 -07:00
|
|
|
get => Native.OS.ShellOrTerminal;
|
2024-09-11 03:22:05 -07:00
|
|
|
set
|
|
|
|
{
|
2024-09-13 21:09:50 -07:00
|
|
|
if (value != Native.OS.ShellOrTerminal)
|
2024-09-11 03:22:05 -07:00
|
|
|
{
|
2024-09-13 21:09:50 -07:00
|
|
|
Native.OS.ShellOrTerminal = value;
|
2024-09-11 03:22:05 -07:00
|
|
|
OnPropertyChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 00:36:10 -07:00
|
|
|
public int ExternalMergeToolType
|
|
|
|
{
|
|
|
|
get => _externalMergeToolType;
|
|
|
|
set
|
|
|
|
{
|
|
|
|
var changed = SetProperty(ref _externalMergeToolType, value);
|
2024-04-08 19:41:37 -07:00
|
|
|
if (changed && !OperatingSystem.IsWindows() && value > 0 && value < Models.ExternalMerger.Supported.Count)
|
2024-03-20 00:36:10 -07:00
|
|
|
{
|
2024-04-08 19:41:37 -07:00
|
|
|
var tool = Models.ExternalMerger.Supported[value];
|
2024-03-31 01:54:29 -07:00
|
|
|
if (File.Exists(tool.Exec))
|
|
|
|
ExternalMergeToolPath = tool.Exec;
|
|
|
|
else
|
|
|
|
ExternalMergeToolPath = string.Empty;
|
2024-03-20 00:36:10 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public string ExternalMergeToolPath
|
|
|
|
{
|
|
|
|
get => _externalMergeToolPath;
|
|
|
|
set => SetProperty(ref _externalMergeToolPath, value);
|
|
|
|
}
|
|
|
|
|
2024-09-13 21:09:50 -07:00
|
|
|
public string OpenAIServer
|
|
|
|
{
|
|
|
|
get => Models.OpenAI.Server;
|
|
|
|
set
|
|
|
|
{
|
|
|
|
if (value != Models.OpenAI.Server)
|
|
|
|
{
|
|
|
|
Models.OpenAI.Server = value;
|
|
|
|
OnPropertyChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public string OpenAIApiKey
|
|
|
|
{
|
|
|
|
get => Models.OpenAI.ApiKey;
|
|
|
|
set
|
|
|
|
{
|
|
|
|
if (value != Models.OpenAI.ApiKey)
|
|
|
|
{
|
|
|
|
Models.OpenAI.ApiKey = value;
|
|
|
|
OnPropertyChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public string OpenAIModel
|
|
|
|
{
|
|
|
|
get => Models.OpenAI.Model;
|
|
|
|
set
|
|
|
|
{
|
|
|
|
if (value != Models.OpenAI.Model)
|
|
|
|
{
|
|
|
|
Models.OpenAI.Model = value;
|
|
|
|
OnPropertyChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-23 19:20:28 -07:00
|
|
|
public string OpenAIAnalyzeDiffPrompt
|
2024-10-23 18:31:05 -07:00
|
|
|
{
|
2024-10-23 19:20:28 -07:00
|
|
|
get => Models.OpenAI.AnalyzeDiffPrompt;
|
2024-10-23 18:31:05 -07:00
|
|
|
set
|
|
|
|
{
|
2024-10-23 19:20:28 -07:00
|
|
|
if (value != Models.OpenAI.AnalyzeDiffPrompt)
|
2024-10-23 18:31:05 -07:00
|
|
|
{
|
2024-10-23 19:20:28 -07:00
|
|
|
Models.OpenAI.AnalyzeDiffPrompt = value;
|
2024-10-23 18:31:05 -07:00
|
|
|
OnPropertyChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-23 19:20:28 -07:00
|
|
|
public string OpenAIGenerateSubjectPrompt
|
2024-10-23 18:31:05 -07:00
|
|
|
{
|
2024-10-23 19:20:28 -07:00
|
|
|
get => Models.OpenAI.GenerateSubjectPrompt;
|
2024-10-23 18:31:05 -07:00
|
|
|
set
|
|
|
|
{
|
2024-10-23 19:20:28 -07:00
|
|
|
if (value != Models.OpenAI.GenerateSubjectPrompt)
|
2024-10-23 18:31:05 -07:00
|
|
|
{
|
2024-10-23 19:20:28 -07:00
|
|
|
Models.OpenAI.GenerateSubjectPrompt = value;
|
2024-10-23 18:31:05 -07:00
|
|
|
OnPropertyChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-23 21:14:51 -07:00
|
|
|
public uint StatisticsSampleColor
|
|
|
|
{
|
|
|
|
get => _statisticsSampleColor;
|
|
|
|
set => SetProperty(ref _statisticsSampleColor, value);
|
|
|
|
}
|
|
|
|
|
2024-08-22 20:24:31 -07:00
|
|
|
public List<RepositoryNode> RepositoryNodes
|
2024-03-20 00:36:10 -07:00
|
|
|
{
|
2024-08-22 20:24:31 -07:00
|
|
|
get;
|
|
|
|
set;
|
|
|
|
} = [];
|
2024-03-20 00:36:10 -07:00
|
|
|
|
2024-09-09 03:26:43 -07:00
|
|
|
public List<Workspace> Workspaces
|
2024-03-20 00:36:10 -07:00
|
|
|
{
|
|
|
|
get;
|
|
|
|
set;
|
2024-08-18 08:09:55 -07:00
|
|
|
} = [];
|
2024-03-20 00:36:10 -07:00
|
|
|
|
2024-04-06 18:51:55 -07:00
|
|
|
public double LastCheckUpdateTime
|
|
|
|
{
|
2024-09-01 21:20:11 -07:00
|
|
|
get => _lastCheckUpdateTime;
|
|
|
|
set => SetProperty(ref _lastCheckUpdateTime, value);
|
|
|
|
}
|
2024-04-06 18:51:55 -07:00
|
|
|
|
2024-07-22 00:34:31 -07:00
|
|
|
public bool IsGitConfigured()
|
2024-04-06 18:51:55 -07:00
|
|
|
{
|
2024-07-22 00:34:31 -07:00
|
|
|
var path = GitInstallPath;
|
|
|
|
return !string.IsNullOrEmpty(path) && File.Exists(path);
|
|
|
|
}
|
2024-04-06 18:51:55 -07:00
|
|
|
|
2024-07-22 00:34:31 -07:00
|
|
|
public bool ShouldCheck4UpdateOnStartup()
|
|
|
|
{
|
|
|
|
if (!_check4UpdatesOnStartup)
|
|
|
|
return false;
|
2024-04-06 18:51:55 -07:00
|
|
|
|
2024-07-22 00:34:31 -07:00
|
|
|
var lastCheck = DateTime.UnixEpoch.AddSeconds(LastCheckUpdateTime).ToLocalTime();
|
|
|
|
var now = DateTime.Now;
|
2024-04-06 18:51:55 -07:00
|
|
|
|
2024-07-22 00:34:31 -07:00
|
|
|
if (lastCheck.Year == now.Year && lastCheck.Month == now.Month && lastCheck.Day == now.Day)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
LastCheckUpdateTime = now.Subtract(DateTime.UnixEpoch.ToLocalTime()).TotalSeconds;
|
|
|
|
return true;
|
2024-04-06 18:51:55 -07:00
|
|
|
}
|
|
|
|
|
2024-09-09 03:26:43 -07:00
|
|
|
public Workspace GetActiveWorkspace()
|
|
|
|
{
|
|
|
|
foreach (var w in Workspaces)
|
|
|
|
{
|
|
|
|
if (w.IsActive)
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
var first = Workspaces[0];
|
|
|
|
first.IsActive = true;
|
|
|
|
return first;
|
|
|
|
}
|
|
|
|
|
2024-09-01 23:14:52 -07:00
|
|
|
public void AddNode(RepositoryNode node, RepositoryNode to, bool save)
|
2024-03-20 00:36:10 -07:00
|
|
|
{
|
2024-08-22 20:24:31 -07:00
|
|
|
var collection = to == null ? RepositoryNodes : to.SubNodes;
|
|
|
|
collection.Add(node);
|
|
|
|
collection.Sort((l, r) =>
|
2024-03-20 00:36:10 -07:00
|
|
|
{
|
|
|
|
if (l.IsRepository != r.IsRepository)
|
|
|
|
return l.IsRepository ? 1 : -1;
|
2024-07-14 00:55:15 -07:00
|
|
|
|
|
|
|
return string.Compare(l.Name, r.Name, StringComparison.Ordinal);
|
2024-03-20 00:36:10 -07:00
|
|
|
});
|
2024-09-01 21:20:11 -07:00
|
|
|
|
2024-09-01 23:14:52 -07:00
|
|
|
if (save)
|
|
|
|
Save();
|
2024-03-20 00:36:10 -07:00
|
|
|
}
|
|
|
|
|
2024-07-22 00:34:31 -07:00
|
|
|
public RepositoryNode FindNode(string id)
|
2024-03-20 00:36:10 -07:00
|
|
|
{
|
2024-07-22 00:34:31 -07:00
|
|
|
return FindNodeRecursive(id, RepositoryNodes);
|
2024-03-20 00:36:10 -07:00
|
|
|
}
|
|
|
|
|
2024-07-22 00:34:31 -07:00
|
|
|
public RepositoryNode FindOrAddNodeByRepositoryPath(string repo, RepositoryNode parent, bool shouldMoveNode)
|
2024-05-07 00:49:57 -07:00
|
|
|
{
|
2024-07-22 00:34:31 -07:00
|
|
|
var node = FindNodeRecursive(repo, RepositoryNodes);
|
2024-05-07 00:49:57 -07:00
|
|
|
if (node == null)
|
|
|
|
{
|
|
|
|
node = new RepositoryNode()
|
|
|
|
{
|
2024-05-07 00:52:04 -07:00
|
|
|
Id = repo,
|
2024-05-07 00:49:57 -07:00
|
|
|
Name = Path.GetFileName(repo),
|
|
|
|
Bookmark = 0,
|
|
|
|
IsRepository = true,
|
|
|
|
};
|
|
|
|
|
2024-09-01 23:14:52 -07:00
|
|
|
AddNode(node, parent, true);
|
2024-05-07 00:49:57 -07:00
|
|
|
}
|
2024-05-20 02:36:43 -07:00
|
|
|
else if (shouldMoveNode)
|
2024-05-07 00:49:57 -07:00
|
|
|
{
|
2024-09-01 23:14:52 -07:00
|
|
|
MoveNode(node, parent, true);
|
2024-05-07 00:49:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2024-09-01 23:14:52 -07:00
|
|
|
public void MoveNode(RepositoryNode node, RepositoryNode to, bool save)
|
2024-03-20 00:36:10 -07:00
|
|
|
{
|
2024-08-22 20:24:31 -07:00
|
|
|
if (to == null && RepositoryNodes.Contains(node))
|
2024-03-31 01:54:29 -07:00
|
|
|
return;
|
|
|
|
if (to != null && to.SubNodes.Contains(node))
|
|
|
|
return;
|
2024-03-20 00:36:10 -07:00
|
|
|
|
2024-09-01 23:14:52 -07:00
|
|
|
RemoveNode(node, false);
|
|
|
|
AddNode(node, to, false);
|
|
|
|
|
|
|
|
if (save)
|
|
|
|
Save();
|
2024-03-20 00:36:10 -07:00
|
|
|
}
|
|
|
|
|
2024-09-01 23:14:52 -07:00
|
|
|
public void RemoveNode(RepositoryNode node, bool save)
|
2024-03-20 00:36:10 -07:00
|
|
|
{
|
2024-08-22 20:24:31 -07:00
|
|
|
RemoveNodeRecursive(node, RepositoryNodes);
|
2024-09-01 23:14:52 -07:00
|
|
|
|
|
|
|
if (save)
|
|
|
|
Save();
|
2024-03-20 00:36:10 -07:00
|
|
|
}
|
|
|
|
|
2024-07-22 00:34:31 -07:00
|
|
|
public void SortByRenamedNode(RepositoryNode node)
|
2024-05-07 00:28:54 -07:00
|
|
|
{
|
2024-08-22 20:24:31 -07:00
|
|
|
var container = FindNodeContainer(node, RepositoryNodes);
|
|
|
|
container?.Sort((l, r) =>
|
2024-05-07 00:28:54 -07:00
|
|
|
{
|
|
|
|
if (l.IsRepository != r.IsRepository)
|
|
|
|
return l.IsRepository ? 1 : -1;
|
2024-07-14 00:55:15 -07:00
|
|
|
|
|
|
|
return string.Compare(l.Name, r.Name, StringComparison.Ordinal);
|
2024-05-07 00:28:54 -07:00
|
|
|
});
|
2024-09-01 21:20:11 -07:00
|
|
|
|
|
|
|
Save();
|
2024-05-07 00:28:54 -07:00
|
|
|
}
|
|
|
|
|
2024-10-20 05:42:14 -07:00
|
|
|
public void AutoRemoveInvalidNode()
|
|
|
|
{
|
|
|
|
var changed = RemoveInvalidRepositoriesRecursive(RepositoryNodes);
|
|
|
|
if (changed)
|
|
|
|
Save();
|
|
|
|
}
|
|
|
|
|
2024-06-30 20:57:13 -07:00
|
|
|
public void Save()
|
2024-03-20 00:36:10 -07:00
|
|
|
{
|
2024-09-10 01:37:39 -07:00
|
|
|
if (_isLoading)
|
|
|
|
return;
|
|
|
|
|
2024-09-09 03:47:53 -07:00
|
|
|
var file = Path.Combine(Native.OS.DataDir, "preference.json");
|
2024-06-30 20:57:13 -07:00
|
|
|
var data = JsonSerializer.Serialize(this, JsonCodeGen.Default.Preference);
|
2024-09-09 03:47:53 -07:00
|
|
|
File.WriteAllText(file, data);
|
2024-03-20 00:36:10 -07:00
|
|
|
}
|
|
|
|
|
2024-09-17 07:09:51 -07:00
|
|
|
private static Preference Load()
|
|
|
|
{
|
|
|
|
var path = Path.Combine(Native.OS.DataDir, "preference.json");
|
|
|
|
if (!File.Exists(path))
|
|
|
|
return new Preference();
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return JsonSerializer.Deserialize(File.ReadAllText(path), JsonCodeGen.Default.Preference);
|
|
|
|
}
|
|
|
|
catch
|
|
|
|
{
|
|
|
|
return new Preference();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-18 06:35:33 -07:00
|
|
|
private void PrepareGit()
|
|
|
|
{
|
|
|
|
var path = Native.OS.GitExecutable;
|
|
|
|
if (string.IsNullOrEmpty(path) || !File.Exists(path))
|
|
|
|
GitInstallPath = Native.OS.FindGitExecutable();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void PrepareShellOrTerminal()
|
2024-09-17 07:09:51 -07:00
|
|
|
{
|
2024-09-18 06:35:33 -07:00
|
|
|
if (_shellOrTerminal >= 0)
|
|
|
|
return;
|
|
|
|
|
2024-09-17 07:09:51 -07:00
|
|
|
for (int i = 0; i < Models.ShellOrTerminal.Supported.Count; i++)
|
|
|
|
{
|
|
|
|
var shell = Models.ShellOrTerminal.Supported[i];
|
|
|
|
if (Native.OS.TestShellOrTerminal(shell))
|
|
|
|
{
|
|
|
|
ShellOrTerminal = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-18 06:35:33 -07:00
|
|
|
private void PrepareWorkspaces()
|
|
|
|
{
|
|
|
|
if (Workspaces.Count == 0)
|
|
|
|
{
|
|
|
|
Workspaces.Add(new Workspace() { Name = "Default" });
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach (var workspace in Workspaces)
|
|
|
|
{
|
|
|
|
if (!workspace.RestoreOnStartup)
|
|
|
|
{
|
|
|
|
workspace.Repositories.Clear();
|
|
|
|
workspace.ActiveIdx = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-23 19:20:28 -07:00
|
|
|
private void PrepareOpenAIPrompt()
|
|
|
|
{
|
|
|
|
if (string.IsNullOrEmpty(Models.OpenAI.AnalyzeDiffPrompt))
|
|
|
|
{
|
|
|
|
Models.OpenAI.AnalyzeDiffPrompt = """
|
|
|
|
You are an expert developer specialist in creating commits.
|
|
|
|
Provide a super concise one sentence overall changes summary of the user `git diff` output following strictly the next rules:
|
|
|
|
- Do not use any code snippets, imports, file routes or bullets points.
|
|
|
|
- Do not mention the route of file that has been change.
|
|
|
|
- Write clear, concise, and descriptive messages that explain the MAIN GOAL made of the changes.
|
|
|
|
- Use the present tense and active voice in the message, for example, "Fix bug" instead of "Fixed bug.".
|
|
|
|
- Use the imperative mood, which gives the message a sense of command, e.g. "Add feature" instead of "Added feature".
|
|
|
|
- Avoid using general terms like "update" or "change", be specific about what was updated or changed.
|
|
|
|
- Avoid using terms like "The main goal of", just output directly the summary in plain text
|
|
|
|
""";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(Models.OpenAI.GenerateSubjectPrompt))
|
|
|
|
{
|
|
|
|
Models.OpenAI.GenerateSubjectPrompt = """
|
|
|
|
You are an expert developer specialist in creating commits messages.
|
|
|
|
Your only goal is to retrieve a single commit message.
|
|
|
|
Based on the provided user changes, combine them in ONE SINGLE commit message retrieving the global idea, following strictly the next rules:
|
|
|
|
- Assign the commit {type} according to the next conditions:
|
|
|
|
feat: Only when adding a new feature.
|
|
|
|
fix: When fixing a bug.
|
|
|
|
docs: When updating documentation.
|
|
|
|
style: When changing elements styles or design and/or making changes to the code style (formatting, missing semicolons, etc.) without changing the code logic.
|
|
|
|
test: When adding or updating tests.
|
|
|
|
chore: When making changes to the build process or auxiliary tools and libraries.
|
|
|
|
revert: When undoing a previous commit.
|
|
|
|
refactor: When restructuring code without changing its external behavior, or is any of the other refactor types.
|
|
|
|
- Do not add any issues numeration, explain your output nor introduce your answer.
|
|
|
|
- Output directly only one commit message in plain text with the next format: {type}: {commit_message}.
|
|
|
|
- Be as concise as possible, keep the message under 50 characters.
|
|
|
|
""";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-22 20:24:31 -07:00
|
|
|
private RepositoryNode FindNodeRecursive(string id, List<RepositoryNode> collection)
|
2024-03-20 00:36:10 -07:00
|
|
|
{
|
|
|
|
foreach (var node in collection)
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
if (node.Id == id)
|
|
|
|
return node;
|
2024-03-20 00:36:10 -07:00
|
|
|
|
|
|
|
var sub = FindNodeRecursive(id, node.SubNodes);
|
2024-03-31 01:54:29 -07:00
|
|
|
if (sub != null)
|
|
|
|
return sub;
|
2024-03-20 00:36:10 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2024-08-22 20:24:31 -07:00
|
|
|
private List<RepositoryNode> FindNodeContainer(RepositoryNode node, List<RepositoryNode> collection)
|
2024-05-07 00:28:54 -07:00
|
|
|
{
|
|
|
|
foreach (var sub in collection)
|
|
|
|
{
|
|
|
|
if (node == sub)
|
|
|
|
return collection;
|
|
|
|
|
|
|
|
var subCollection = FindNodeContainer(node, sub.SubNodes);
|
|
|
|
if (subCollection != null)
|
|
|
|
return subCollection;
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2024-08-22 20:24:31 -07:00
|
|
|
private bool RemoveNodeRecursive(RepositoryNode node, List<RepositoryNode> collection)
|
2024-03-20 00:36:10 -07:00
|
|
|
{
|
|
|
|
if (collection.Contains(node))
|
|
|
|
{
|
|
|
|
collection.Remove(node);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-09-17 07:09:51 -07:00
|
|
|
foreach (var one in collection)
|
2024-03-20 00:36:10 -07:00
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
if (RemoveNodeRecursive(node, one.SubNodes))
|
|
|
|
return true;
|
2024-03-20 00:36:10 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-10-20 05:42:14 -07:00
|
|
|
private bool RemoveInvalidRepositoriesRecursive(List<RepositoryNode> collection)
|
|
|
|
{
|
|
|
|
bool changed = false;
|
2024-10-23 00:28:09 -07:00
|
|
|
|
2024-10-20 05:42:14 -07:00
|
|
|
for (int i = collection.Count - 1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
var node = collection[i];
|
|
|
|
if (node.IsInvalid)
|
|
|
|
{
|
|
|
|
collection.RemoveAt(i);
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
else if (!node.IsRepository)
|
|
|
|
{
|
|
|
|
changed |= RemoveInvalidRepositoriesRecursive(node.SubNodes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
|
2024-03-20 00:36:10 -07:00
|
|
|
private static Preference _instance = null;
|
2024-08-19 02:14:41 -07:00
|
|
|
private static bool _isLoading = false;
|
2024-03-20 00:36:10 -07:00
|
|
|
|
|
|
|
private string _locale = "en_US";
|
|
|
|
private string _theme = "Default";
|
2024-07-08 01:21:57 -07:00
|
|
|
private string _themeOverrides = string.Empty;
|
2024-08-19 02:14:41 -07:00
|
|
|
private string _defaultFontFamily = string.Empty;
|
|
|
|
private string _monospaceFontFamily = string.Empty;
|
2024-07-29 05:20:27 -07:00
|
|
|
private bool _onlyUseMonoFontInEditor = false;
|
2024-08-21 21:37:26 -07:00
|
|
|
private bool _useSystemWindowFrame = false;
|
2024-03-21 21:03:04 -07:00
|
|
|
private double _defaultFontSize = 13;
|
2024-06-11 01:36:52 -07:00
|
|
|
private LayoutInfo _layout = new LayoutInfo();
|
2024-03-21 03:02:06 -07:00
|
|
|
|
2024-03-20 00:36:10 -07:00
|
|
|
private int _maxHistoryCommits = 20000;
|
2024-06-23 00:45:54 -07:00
|
|
|
private int _subjectGuideLength = 50;
|
2024-03-20 00:36:10 -07:00
|
|
|
private bool _useFixedTabWidth = true;
|
2024-10-11 18:56:33 -07:00
|
|
|
private bool _showAuthorTimeInGraph = false;
|
2024-09-01 21:20:11 -07:00
|
|
|
|
2024-03-26 07:11:06 -07:00
|
|
|
private bool _check4UpdatesOnStartup = true;
|
2024-09-01 21:20:11 -07:00
|
|
|
private double _lastCheckUpdateTime = 0;
|
|
|
|
private string _ignoreUpdateTag = string.Empty;
|
2024-07-09 21:11:51 -07:00
|
|
|
|
2024-08-11 03:12:58 -07:00
|
|
|
private bool _showTagsAsTree = false;
|
2024-03-20 00:36:10 -07:00
|
|
|
private bool _useTwoColumnsLayoutInHistories = false;
|
2024-07-15 20:15:41 -07:00
|
|
|
private bool _displayTimeAsPeriodInHistories = false;
|
2024-03-20 00:36:10 -07:00
|
|
|
private bool _useSideBySideDiff = false;
|
2024-03-20 05:17:20 -07:00
|
|
|
private bool _useSyntaxHighlighting = false;
|
2024-06-04 05:19:49 -07:00
|
|
|
private bool _enableDiffViewWordWrap = false;
|
2024-06-19 03:15:32 -07:00
|
|
|
private bool _showHiddenSymbolsInDiffView = false;
|
2024-03-20 00:36:10 -07:00
|
|
|
|
|
|
|
private Models.ChangeViewMode _unstagedChangeViewMode = Models.ChangeViewMode.List;
|
|
|
|
private Models.ChangeViewMode _stagedChangeViewMode = Models.ChangeViewMode.List;
|
|
|
|
private Models.ChangeViewMode _commitChangeViewMode = Models.ChangeViewMode.List;
|
|
|
|
|
|
|
|
private string _gitDefaultCloneDir = string.Empty;
|
|
|
|
|
2024-09-13 21:09:50 -07:00
|
|
|
private int _shellOrTerminal = -1;
|
2024-03-20 00:36:10 -07:00
|
|
|
private int _externalMergeToolType = 0;
|
|
|
|
private string _externalMergeToolPath = string.Empty;
|
2024-09-23 21:14:51 -07:00
|
|
|
|
|
|
|
private uint _statisticsSampleColor = 0xFF00FF00;
|
2024-03-20 00:36:10 -07:00
|
|
|
}
|
2024-03-31 01:54:29 -07:00
|
|
|
}
|