From fdc717dd77f6c4ddb9159f67f9e8a7499f2e6d7b Mon Sep 17 00:00:00 2001 From: Enrico Ludwig Date: Mon, 26 Aug 2024 19:50:24 +0200 Subject: [PATCH] Implemented persistent channels and settings; working on various bugs --- Assets/icons8-close-32.png | Bin 0 -> 627 bytes BetterRaid.generated.sln | 10 +-- Controls/RaidButton.axaml | 17 ++++ Models/BetterRaidDatabase.cs | 105 ++++++++++++++++++++++++ ViewModels/AddChannelWindowViewModel.cs | 5 +- ViewModels/MainWindowViewModel.cs | 18 +++- ViewModels/RaidButtonViewModel.cs | 22 +++-- Views/MainWindow.axaml | 13 +-- Views/MainWindow.axaml.cs | 57 ++++++++----- db.json | 1 + 10 files changed, 204 insertions(+), 44 deletions(-) create mode 100644 Assets/icons8-close-32.png create mode 100644 Models/BetterRaidDatabase.cs create mode 100644 db.json diff --git a/Assets/icons8-close-32.png b/Assets/icons8-close-32.png new file mode 100644 index 0000000000000000000000000000000000000000..912d32c152b5a783a081247ed4da8ced8d335067 GIT binary patch literal 627 zcmV-(0*w8MP)c8Uijs)UBk+^JPhoneZqe)VlvTMitkz1cMmw2W3X6AW35#kC3(A%h8Q?jwD z!^V!5^=%aece@13Vv&e9f;)=fxgz+a2~Acgi60fgUL4j|DkE01aZ^h?QG|bN#3>=; zZ{b)q*Kd>}|4p#22v2>9GvZe-ga^ekkKmD#I4nVa-j<<~*v>`X4eR%-AfFL&=3NQJ zJtz2C75R)WPJ6Aj>vIKYi6>Q){|kw4J+2yB-QM4Anc@CpD*>PJH?CF;sD9f~etcmi zf4F5vU%wcWBv+|3dU&4YglJNU)Nh@`d1g%F&0r~=eG}GvjC6@`O6p5~QH928hWqQ=zHXj~ zm=fnCp9HkB`rj%nz?e*9S|ft3w15!r?%K?MhZMft|)?jgh82haM^Qb{y%t);!VbNJF?ua z2|C_A_W^G*yiD+W?kM+rE%E8xt5z2AX0XKbeEfn=|C(9H>lK6>e*siK@5Z48Yxw{G N002ovPDHLkV1k4JBU%6e literal 0 HcmV?d00001 diff --git a/BetterRaid.generated.sln b/BetterRaid.generated.sln index 3c6fb95..b4591bc 100644 --- a/BetterRaid.generated.sln +++ b/BetterRaid.generated.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.5.002.0 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BetterRaid", "BetterRaid.csproj", "{C36B7D6A-D155-4AED-8A75-4D947FD7E4D2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BetterRaid", "BetterRaid.csproj", "{5F90F02B-A28E-4B50-9821-1F0D7226936C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -11,10 +11,10 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C36B7D6A-D155-4AED-8A75-4D947FD7E4D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C36B7D6A-D155-4AED-8A75-4D947FD7E4D2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C36B7D6A-D155-4AED-8A75-4D947FD7E4D2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C36B7D6A-D155-4AED-8A75-4D947FD7E4D2}.Release|Any CPU.Build.0 = Release|Any CPU + {5F90F02B-A28E-4B50-9821-1F0D7226936C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5F90F02B-A28E-4B50-9821-1F0D7226936C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5F90F02B-A28E-4B50-9821-1F0D7226936C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5F90F02B-A28E-4B50-9821-1F0D7226936C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Controls/RaidButton.axaml b/Controls/RaidButton.axaml index ed0157d..941f3bc 100644 --- a/Controls/RaidButton.axaml +++ b/Controls/RaidButton.axaml @@ -35,6 +35,23 @@ Grid.Row="0" Source="{Binding Channel.ThumbnailUrl}" /> + + diff --git a/Models/BetterRaidDatabase.cs b/Models/BetterRaidDatabase.cs new file mode 100644 index 0000000..fc855e9 --- /dev/null +++ b/Models/BetterRaidDatabase.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Runtime.CompilerServices; +using Newtonsoft.Json; + +namespace BetterRaid.Models; + +[JsonObject] +public class BetterRaidDatabase : INotifyPropertyChanged +{ + [JsonIgnore] + private string? _databaseFilePath; + private bool _onlyOnline; + + public event PropertyChangedEventHandler? PropertyChanged; + public bool OnlyOnline + { + get => _onlyOnline; + set + { + if (value == _onlyOnline) + return; + + _onlyOnline = value; + OnPropertyChanged(); + } + } + public List Channels { get; set; } = []; + public bool AutoSave { get; set; } + + public static BetterRaidDatabase LoadFromFile(string path) + { + ArgumentNullException.ThrowIfNullOrEmpty(path); + + path = Path.Combine(Environment.CurrentDirectory, path); + + if (File.Exists(path) == false) + { + throw new FileNotFoundException("Database file not found", path); + } + + var dbStr = File.ReadAllText(path); + var dbObj = JsonConvert.DeserializeObject(dbStr); + + if (dbObj == null) + { + throw new JsonException("Failed to read database file"); + } + + dbObj._databaseFilePath = path; + + Console.WriteLine("[DEBUG] Loaded database from {0}", path); + + return dbObj; + } + + public void Save(string? path = null) + { + if (string.IsNullOrEmpty(_databaseFilePath) && string.IsNullOrEmpty(path)) + { + throw new ArgumentException("No target path given to save database at"); + } + + var dbStr = JsonConvert.SerializeObject(this); + var targetPath = (path ?? _databaseFilePath)!; + + File.WriteAllText(targetPath, dbStr); + + Console.WriteLine("[DEBUG] Saved database to {0}", targetPath); + } + + public void AddChannel(string channel) + { + ArgumentNullException.ThrowIfNull(channel); + + if (Channels.Contains(channel)) + return; + + Channels.Add(channel); + OnPropertyChanged(nameof(Channels)); + } + + public void RemoveChannel(string channel) + { + ArgumentNullException.ThrowIfNull(channel); + + if (Channels.Contains(channel) == false) + return; + + Channels.Remove(channel); + OnPropertyChanged(nameof(Channels)); + } + + private void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + + if (AutoSave && _databaseFilePath != null) + { + Save(); + } + } +} \ No newline at end of file diff --git a/ViewModels/AddChannelWindowViewModel.cs b/ViewModels/AddChannelWindowViewModel.cs index 2ef962f..e2c33f4 100644 --- a/ViewModels/AddChannelWindowViewModel.cs +++ b/ViewModels/AddChannelWindowViewModel.cs @@ -2,8 +2,5 @@ namespace BetterRaid.ViewModels; public class AddChannelWindowViewModel : ViewModelBase { - public void AddChannel() - { - System.Console.WriteLine("BLABLABLA"); - } + } \ No newline at end of file diff --git a/ViewModels/MainWindowViewModel.cs b/ViewModels/MainWindowViewModel.cs index ce44536..5bfb174 100644 --- a/ViewModels/MainWindowViewModel.cs +++ b/ViewModels/MainWindowViewModel.cs @@ -1,5 +1,6 @@ using System; using Avalonia; +using BetterRaid.Models; namespace BetterRaid.ViewModels; @@ -7,6 +8,14 @@ public partial class MainWindowViewModel : ViewModelBase { private string? _filter; private bool _onlyOnline; + + private BetterRaidDatabase? _db; + + public BetterRaidDatabase? Database + { + get => _db; + set => SetProperty(ref _db, value); + } public string? Filter { @@ -17,7 +26,14 @@ public partial class MainWindowViewModel : ViewModelBase public bool OnlyOnline { get => _onlyOnline; - set => SetProperty(ref _onlyOnline, value); + set + { + if (SetProperty(ref _onlyOnline, value)) + { + if (Database != null) + Database.OnlyOnline = value; + } + } } public void ExitApplication() diff --git a/ViewModels/RaidButtonViewModel.cs b/ViewModels/RaidButtonViewModel.cs index 03e457f..523065f 100644 --- a/ViewModels/RaidButtonViewModel.cs +++ b/ViewModels/RaidButtonViewModel.cs @@ -12,6 +12,7 @@ namespace BetterRaid.ViewModels; public class RaidButtonViewModel : ViewModelBase { + private MainWindowViewModel? _mainVm; private TwitchChannel? _channel; private SolidColorBrush _viewerCountColor = new SolidColorBrush(Color.FromRgb(byte.MaxValue, byte.MaxValue, byte.MaxValue)); @@ -32,14 +33,13 @@ public class RaidButtonViewModel : ViewModelBase public SolidColorBrush ViewerCountColor { get => _viewerCountColor; - set - { - if (value == _viewerCountColor) - return; + set => SetProperty(ref _viewerCountColor, value); + } - _viewerCountColor = value; - OnPropertyChanged(); - } + public MainWindowViewModel? MainVm + { + get => _mainVm; + set => SetProperty(ref _mainVm, value); } public async Task GetOrUpdateChannelAsync() @@ -132,6 +132,14 @@ public class RaidButtonViewModel : ViewModelBase } } + public void RemoveChannel() + { + if (MainVm?.Database == null) + return; + + MainVm.Database.RemoveChannel(ChannelName); + } + private void OnChannelDataChanged(object? sender, PropertyChangedEventArgs e) { OnPropertyChanged(nameof(Channel)); diff --git a/Views/MainWindow.axaml b/Views/MainWindow.axaml index 0c01f88..e4ea100 100644 --- a/Views/MainWindow.axaml +++ b/Views/MainWindow.axaml @@ -10,6 +10,7 @@ x:DataType="vm:MainWindowViewModel" Icon="/Assets/avalonia-logo.ico" Title="BetterRaid" + Background="DarkSlateGray" WindowStartupLocation="CenterScreen"> @@ -50,12 +51,12 @@ IsChecked="{Binding OnlyOnline, Mode=TwoWay}" /> + Grid.Row="0" + Width="200" + Margin="2" + Watermark="Filter Channels" + Text="{Binding Filter, Mode=TwoWay}" + HorizontalAlignment="Right" /> diff --git a/Views/MainWindow.axaml.cs b/Views/MainWindow.axaml.cs index 24dba87..19b8347 100644 --- a/Views/MainWindow.axaml.cs +++ b/Views/MainWindow.axaml.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Threading; +using BetterRaid.Models; using BetterRaid.ViewModels; namespace BetterRaid.Views; @@ -15,39 +16,38 @@ public partial class MainWindow : Window private ObservableCollection _raidButtonVMs; private BackgroundWorker _autoUpdater; - private string[] _channelNames = [ - "Cedricun", // Ehrenbruder - "ZanTal", // Ehrenschwester - "PropzMaster", - "Artimus83", - "HyperonsLive", - "theshroomlife", - "Robocraft999", - "sllikson", - "Aron_dc", - "AIEsports" - ]; - public MainWindow() { _raidButtonVMs = []; _autoUpdater = new(); - InitializeComponent(); - InitializeRaidChannels(); - GenerateRaidGrid(); - DataContextChanged += OnDataContextChanged; + InitializeComponent(); + _autoUpdater.DoWork += UpdateAllTiles; _autoUpdater.RunWorkerAsync(); } + private void OnDatabaseChanged(object? sender, PropertyChangedEventArgs e) + { + InitializeRaidChannels(); + GenerateRaidGrid(); + } + private void OnDataContextChanged(object? sender, EventArgs e) { if (DataContext is MainWindowViewModel vm) { + vm.Database = BetterRaidDatabase.LoadFromFile("db.json"); + vm.Database.AutoSave = true; + vm.Database.PropertyChanged += OnDatabaseChanged; + vm.OnlyOnline = vm.Database.OnlyOnline; + vm.PropertyChanged += OnViewModelChanged; + + InitializeRaidChannels(); + GenerateRaidGrid(); } } @@ -105,14 +105,20 @@ public partial class MainWindow : Window { _raidButtonVMs.Clear(); - foreach (var channel in _channelNames) + var vm = DataContext as MainWindowViewModel; + + if (vm?.Database == null) + return; + + foreach (var channel in vm.Database.Channels) { if (string.IsNullOrEmpty(channel)) continue; _raidButtonVMs.Add(new RaidButtonViewModel { - ChannelName = channel + ChannelName = channel, + MainVm = vm }); } } @@ -190,12 +196,21 @@ public partial class MainWindow : Window (int)(Position.X + Width / 2 - dialog.Width / 2), (int)(Position.Y + Height / 2 - dialog.Height / 2) ); + + var vm = DataContext as MainWindowViewModel; + + if (vm?.Database == null) + return; // TODO Button Command not working, Button remains disabled // This is a dirty workaround dialog.okBtn.Click += (sender, args) => { - Array.Resize(ref _channelNames, _channelNames.Length + 1); - _channelNames[^1] = dialog?.channelNameTxt.Text ?? ""; + if (string.IsNullOrWhiteSpace(dialog?.channelNameTxt.Text) == false) + { + vm.Database.AddChannel(dialog.channelNameTxt.Text); + vm.Database.Save(); + } + dialog?.Close(); InitializeRaidChannels(); diff --git a/db.json b/db.json new file mode 100644 index 0000000..c845b43 --- /dev/null +++ b/db.json @@ -0,0 +1 @@ +{"OnlyOnline":true,"Channels":["Cedricun","ZanTal","PropzMaster","Artimus83","HyperonsLive","theshroomlife","Robocraft999","sllikson","Aron_dc","AIEsports","GronkhTv","TobinatorLP","Lordabgrund"],"AutoSave":true} \ No newline at end of file