Implemented persistent channels and settings; working on various bugs

This commit is contained in:
Enrico Ludwig 2024-08-26 19:50:24 +02:00
parent 832f1fd150
commit fdc717dd77
10 changed files with 204 additions and 44 deletions

BIN
Assets/icons8-close-32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 627 B

View File

@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.5.002.0 VisualStudioVersion = 17.5.002.0
MinimumVisualStudioVersion = 10.0.40219.1 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 EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -11,10 +11,10 @@ Global
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C36B7D6A-D155-4AED-8A75-4D947FD7E4D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5F90F02B-A28E-4B50-9821-1F0D7226936C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C36B7D6A-D155-4AED-8A75-4D947FD7E4D2}.Debug|Any CPU.Build.0 = Debug|Any CPU {5F90F02B-A28E-4B50-9821-1F0D7226936C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C36B7D6A-D155-4AED-8A75-4D947FD7E4D2}.Release|Any CPU.ActiveCfg = Release|Any CPU {5F90F02B-A28E-4B50-9821-1F0D7226936C}.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}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -35,6 +35,23 @@
Grid.Row="0" Grid.Row="0"
Source="{Binding Channel.ThumbnailUrl}" /> Source="{Binding Channel.ThumbnailUrl}" />
<Button Width="32"
Height="32"
Background="DarkRed"
CornerRadius="16"
Padding="0"
BorderThickness="0"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Margin="5"
Command="{Binding RemoveChannel}">
<Image Source="avares://BetterRaid/Assets/icons8-close-32.png"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
</Button>
<StackPanel Grid.Column="0" <StackPanel Grid.Column="0"
Grid.Row="1" Grid.Row="1"
Orientation="Vertical"> Orientation="Vertical">

View File

@ -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<string> 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<BetterRaidDatabase>(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();
}
}
}

View File

@ -2,8 +2,5 @@ namespace BetterRaid.ViewModels;
public class AddChannelWindowViewModel : ViewModelBase public class AddChannelWindowViewModel : ViewModelBase
{ {
public void AddChannel()
{
System.Console.WriteLine("BLABLABLA");
}
} }

View File

@ -1,5 +1,6 @@
using System; using System;
using Avalonia; using Avalonia;
using BetterRaid.Models;
namespace BetterRaid.ViewModels; namespace BetterRaid.ViewModels;
@ -8,6 +9,14 @@ public partial class MainWindowViewModel : ViewModelBase
private string? _filter; private string? _filter;
private bool _onlyOnline; private bool _onlyOnline;
private BetterRaidDatabase? _db;
public BetterRaidDatabase? Database
{
get => _db;
set => SetProperty(ref _db, value);
}
public string? Filter public string? Filter
{ {
get => _filter; get => _filter;
@ -17,7 +26,14 @@ public partial class MainWindowViewModel : ViewModelBase
public bool OnlyOnline public bool OnlyOnline
{ {
get => _onlyOnline; get => _onlyOnline;
set => SetProperty(ref _onlyOnline, value); set
{
if (SetProperty(ref _onlyOnline, value))
{
if (Database != null)
Database.OnlyOnline = value;
}
}
} }
public void ExitApplication() public void ExitApplication()

View File

@ -12,6 +12,7 @@ namespace BetterRaid.ViewModels;
public class RaidButtonViewModel : ViewModelBase public class RaidButtonViewModel : ViewModelBase
{ {
private MainWindowViewModel? _mainVm;
private TwitchChannel? _channel; private TwitchChannel? _channel;
private SolidColorBrush _viewerCountColor = new SolidColorBrush(Color.FromRgb(byte.MaxValue, byte.MaxValue, byte.MaxValue)); private SolidColorBrush _viewerCountColor = new SolidColorBrush(Color.FromRgb(byte.MaxValue, byte.MaxValue, byte.MaxValue));
@ -32,14 +33,13 @@ public class RaidButtonViewModel : ViewModelBase
public SolidColorBrush ViewerCountColor public SolidColorBrush ViewerCountColor
{ {
get => _viewerCountColor; get => _viewerCountColor;
set set => SetProperty(ref _viewerCountColor, value);
{
if (value == _viewerCountColor)
return;
_viewerCountColor = value;
OnPropertyChanged();
} }
public MainWindowViewModel? MainVm
{
get => _mainVm;
set => SetProperty(ref _mainVm, value);
} }
public async Task<bool> GetOrUpdateChannelAsync() public async Task<bool> 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) private void OnChannelDataChanged(object? sender, PropertyChangedEventArgs e)
{ {
OnPropertyChanged(nameof(Channel)); OnPropertyChanged(nameof(Channel));

View File

@ -10,6 +10,7 @@
x:DataType="vm:MainWindowViewModel" x:DataType="vm:MainWindowViewModel"
Icon="/Assets/avalonia-logo.ico" Icon="/Assets/avalonia-logo.ico"
Title="BetterRaid" Title="BetterRaid"
Background="DarkSlateGray"
WindowStartupLocation="CenterScreen"> WindowStartupLocation="CenterScreen">
<Design.DataContext> <Design.DataContext>

View File

@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Threading; using Avalonia.Threading;
using BetterRaid.Models;
using BetterRaid.ViewModels; using BetterRaid.ViewModels;
namespace BetterRaid.Views; namespace BetterRaid.Views;
@ -15,39 +16,38 @@ public partial class MainWindow : Window
private ObservableCollection<RaidButtonViewModel> _raidButtonVMs; private ObservableCollection<RaidButtonViewModel> _raidButtonVMs;
private BackgroundWorker _autoUpdater; private BackgroundWorker _autoUpdater;
private string[] _channelNames = [
"Cedricun", // Ehrenbruder
"ZanTal", // Ehrenschwester
"PropzMaster",
"Artimus83",
"HyperonsLive",
"theshroomlife",
"Robocraft999",
"sllikson",
"Aron_dc",
"AIEsports"
];
public MainWindow() public MainWindow()
{ {
_raidButtonVMs = []; _raidButtonVMs = [];
_autoUpdater = new(); _autoUpdater = new();
InitializeComponent();
InitializeRaidChannels();
GenerateRaidGrid();
DataContextChanged += OnDataContextChanged; DataContextChanged += OnDataContextChanged;
InitializeComponent();
_autoUpdater.DoWork += UpdateAllTiles; _autoUpdater.DoWork += UpdateAllTiles;
_autoUpdater.RunWorkerAsync(); _autoUpdater.RunWorkerAsync();
} }
private void OnDatabaseChanged(object? sender, PropertyChangedEventArgs e)
{
InitializeRaidChannels();
GenerateRaidGrid();
}
private void OnDataContextChanged(object? sender, EventArgs e) private void OnDataContextChanged(object? sender, EventArgs e)
{ {
if (DataContext is MainWindowViewModel vm) 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; vm.PropertyChanged += OnViewModelChanged;
InitializeRaidChannels();
GenerateRaidGrid();
} }
} }
@ -105,14 +105,20 @@ public partial class MainWindow : Window
{ {
_raidButtonVMs.Clear(); _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)) if (string.IsNullOrEmpty(channel))
continue; continue;
_raidButtonVMs.Add(new RaidButtonViewModel _raidButtonVMs.Add(new RaidButtonViewModel
{ {
ChannelName = channel ChannelName = channel,
MainVm = vm
}); });
} }
} }
@ -191,11 +197,20 @@ public partial class MainWindow : Window
(int)(Position.Y + Height / 2 - dialog.Height / 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 // TODO Button Command not working, Button remains disabled
// This is a dirty workaround // This is a dirty workaround
dialog.okBtn.Click += (sender, args) => { dialog.okBtn.Click += (sender, args) => {
Array.Resize(ref _channelNames, _channelNames.Length + 1); if (string.IsNullOrWhiteSpace(dialog?.channelNameTxt.Text) == false)
_channelNames[^1] = dialog?.channelNameTxt.Text ?? ""; {
vm.Database.AddChannel(dialog.channelNameTxt.Text);
vm.Database.Save();
}
dialog?.Close(); dialog?.Close();
InitializeRaidChannels(); InitializeRaidChannels();

1
db.json Normal file
View File

@ -0,0 +1 @@
{"OnlyOnline":true,"Channels":["Cedricun","ZanTal","PropzMaster","Artimus83","HyperonsLive","theshroomlife","Robocraft999","sllikson","Aron_dc","AIEsports","GronkhTv","TobinatorLP","Lordabgrund"],"AutoSave":true}