diff --git a/BetterRaid.generated.sln b/BetterRaid.generated.sln
index b4591bc..9354cb2 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", "{5F90F02B-A28E-4B50-9821-1F0D7226936C}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BetterRaid", "BetterRaid.csproj", "{6BE742A5-079D-4617-BDC1-2933274CDCB7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -11,10 +11,10 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {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
+ {6BE742A5-079D-4617-BDC1-2933274CDCB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6BE742A5-079D-4617-BDC1-2933274CDCB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6BE742A5-079D-4617-BDC1-2933274CDCB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6BE742A5-079D-4617-BDC1-2933274CDCB7}.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 4eec746..06e1ba1 100644
--- a/Controls/RaidButton.axaml
+++ b/Controls/RaidButton.axaml
@@ -57,14 +57,17 @@
Orientation="Vertical">
+ Content="{Binding Channel.DisplayName, FallbackValue=...}" />
+
+ Content="{Binding Channel.ViewerCount, TargetNullValue=(Offline), FallbackValue=...}" />
+ Content="{Binding LastRaided, TargetNullValue=Never Raided, FallbackValue=...}" />
diff --git a/Extensions/WindowExtensions.cs b/Extensions/WindowExtensions.cs
new file mode 100644
index 0000000..11d681f
--- /dev/null
+++ b/Extensions/WindowExtensions.cs
@@ -0,0 +1,19 @@
+using Avalonia.Controls;
+
+namespace BetterRaid.Extensions;
+
+public static class WindowExtensions
+{
+ public static void CenterToOwner(this Window window)
+ {
+ var owner = window.Owner as Window;
+
+ if (owner == null)
+ return;
+
+ window.Position = new Avalonia.PixelPoint(
+ (int)(owner.Position.X + owner.Width / 2 - window.Width / 2),
+ (int)(owner.Position.Y + owner.Height / 2 - window.Height / 2)
+ );
+ }
+}
\ No newline at end of file
diff --git a/Models/TwitchChannel.cs b/Models/TwitchChannel.cs
index a534f26..91f10ea 100644
--- a/Models/TwitchChannel.cs
+++ b/Models/TwitchChannel.cs
@@ -6,11 +6,12 @@ namespace BetterRaid.Models;
public class TwitchChannel : INotifyPropertyChanged
{
- private string? viewerCount;
- private bool isLive;
- private string? name;
- private string? displayName;
- private string? thumbnailUrl;
+ private string? _viewerCount;
+ private bool _isLive;
+ private string? _name;
+ private string? _displayName;
+ private string? _thumbnailUrl;
+ private string? _category;
public string? BroadcasterId
{
@@ -19,63 +20,76 @@ public class TwitchChannel : INotifyPropertyChanged
}
public string? Name
{
- get => name;
+ get => _name;
set
{
- if (value == name)
+ if (value == _name)
return;
- name = value;
+ _name = value;
OnPropertyChanged();
}
}
public bool IsLive
{
- get => isLive;
+ get => _isLive;
set
{
- if (value == isLive)
+ if (value == _isLive)
return;
- isLive = value;
+ _isLive = value;
OnPropertyChanged();
}
}
public string? ViewerCount
{
- get => viewerCount;
+ get => _viewerCount;
set
{
- if (value == viewerCount)
+ if (value == _viewerCount)
return;
- viewerCount = value;
+ _viewerCount = value;
OnPropertyChanged();
}
}
public string? ThumbnailUrl
{
- get => thumbnailUrl;
+ get => _thumbnailUrl;
set
{
- if (value == thumbnailUrl)
+ if (value == _thumbnailUrl)
return;
- thumbnailUrl = value;
+ _thumbnailUrl = value;
OnPropertyChanged();
}
}
public string? DisplayName
{
- get => displayName;
+ get => _displayName;
set
{
- if (value == displayName)
+ if (value == _displayName)
return;
- displayName = value;
+ _displayName = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public string? Category
+ {
+ get => _category;
+ set
+ {
+ if (value == _category)
+ return;
+
+ _category = value;
OnPropertyChanged();
}
}
diff --git a/ViewModels/MainWindowViewModel.cs b/ViewModels/MainWindowViewModel.cs
index 3168404..051c68d 100644
--- a/ViewModels/MainWindowViewModel.cs
+++ b/ViewModels/MainWindowViewModel.cs
@@ -1,6 +1,9 @@
using System;
using Avalonia;
+using Avalonia.Controls;
+using BetterRaid.Extensions;
using BetterRaid.Models;
+using BetterRaid.Views;
namespace BetterRaid.ViewModels;
@@ -27,4 +30,11 @@ public partial class MainWindowViewModel : ViewModelBase
//TODO polish later
Environment.Exit(0);
}
+
+ public void ShowAboutWindow(Window owner)
+ {
+ var about = new AboutWindow();
+ about.ShowDialog(owner);
+ about.CenterToOwner();
+ }
}
diff --git a/ViewModels/RaidButtonViewModel.cs b/ViewModels/RaidButtonViewModel.cs
index 0c3e839..d0df1a9 100644
--- a/ViewModels/RaidButtonViewModel.cs
+++ b/ViewModels/RaidButtonViewModel.cs
@@ -3,6 +3,7 @@ using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Media;
+using Avalonia.Threading;
using BetterRaid.Models;
using TwitchLib.Api.Helix.Models.Raids.StartRaid;
using TwitchLib.Api.Helix.Models.Search;
@@ -15,13 +16,13 @@ public class RaidButtonViewModel : ViewModelBase
private TwitchChannel? _channel;
private SolidColorBrush _viewerCountColor = new SolidColorBrush(Color.FromRgb(byte.MaxValue, byte.MaxValue, byte.MaxValue));
- public required string ChannelName
+ public string ChannelName
{
get;
set;
}
- public TwitchChannel Channel => _channel ?? new TwitchChannel(ChannelName);
+ public TwitchChannel? Channel => _channel ?? new TwitchChannel(ChannelName);
public SolidColorBrush ViewerCountColor
{
@@ -33,13 +34,14 @@ public class RaidButtonViewModel : ViewModelBase
public DateTime? LastRaided => MainVm?.Database?.GetLastRaided(ChannelName);
+ public RaidButtonViewModel(string channelName)
+ {
+ ChannelName = channelName;
+ }
+
public async Task GetOrUpdateChannelAsync()
{
- if (_channel == null)
- {
- _channel = new TwitchChannel(ChannelName);
- _channel.PropertyChanged += OnChannelDataChanged;
- }
+ Console.WriteLine("[DEBUG] Updating channel '{0}' ...", ChannelName);
var currentChannelData = await GetChannelAsync(ChannelName);
@@ -48,24 +50,42 @@ public class RaidButtonViewModel : ViewModelBase
var currentStreamData = await GetStreamAsync(currentChannelData);
- _channel.BroadcasterId = currentChannelData.Id;
- _channel.Name = ChannelName;
- _channel.DisplayName = currentChannelData.DisplayName;
- _channel.IsLive = currentChannelData.IsLive;
- _channel.ThumbnailUrl = currentChannelData.ThumbnailUrl;
- _channel.ViewerCount = currentStreamData?.ViewerCount == null
+ var swapChannel = new TwitchChannel(ChannelName)
+ {
+ BroadcasterId = currentChannelData.Id,
+ Name = ChannelName,
+ DisplayName = currentChannelData.DisplayName,
+ IsLive = currentChannelData.IsLive,
+ ThumbnailUrl = currentChannelData.ThumbnailUrl,
+ ViewerCount = currentStreamData?.ViewerCount == null
? "(Offline)"
- : $"{currentStreamData?.ViewerCount} Viewers";
+ : $"{currentStreamData?.ViewerCount} Viewers",
+ Category = currentStreamData?.GameName
+ };
- if (_channel.IsLive)
+ if (_channel != null)
{
- ViewerCountColor = new SolidColorBrush(Color.FromRgb(0, byte.MaxValue, 0));
+ _channel.PropertyChanged -= OnChannelDataChanged;
}
- else
+
+ Dispatcher.UIThread.Invoke(() => {
+ ViewerCountColor = new SolidColorBrush(Color.FromRgb(
+ r: swapChannel.IsLive ? (byte) 0 : byte.MaxValue,
+ g: swapChannel.IsLive ? byte.MaxValue : (byte) 0,
+ b: 0)
+ );
+
+ _channel = swapChannel;
+ OnPropertyChanged(nameof(Channel));
+ });
+
+ if (_channel != null)
{
- ViewerCountColor = new SolidColorBrush(Color.FromRgb(byte.MaxValue, 0, 0));
+ _channel.PropertyChanged += OnChannelDataChanged;
}
+ Console.WriteLine("[DEBUG] DONE Updating channel '{0}'", ChannelName);
+
return true;
}
@@ -102,6 +122,9 @@ public class RaidButtonViewModel : ViewModelBase
if (App.TwitchAPI == null)
return;
+ if (Channel == null)
+ return;
+
StartRaidResponse? raid = null;
try
diff --git a/Views/AboutWindow.axaml b/Views/AboutWindow.axaml
new file mode 100644
index 0000000..b958636
--- /dev/null
+++ b/Views/AboutWindow.axaml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Views/AboutWindow.axaml.cs b/Views/AboutWindow.axaml.cs
new file mode 100644
index 0000000..edd21de
--- /dev/null
+++ b/Views/AboutWindow.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace BetterRaid.Views;
+
+public partial class AboutWindow : Window
+{
+ public AboutWindow()
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/Views/MainWindow.axaml b/Views/MainWindow.axaml
index 1aa6fdf..97d8b43 100644
--- a/Views/MainWindow.axaml
+++ b/Views/MainWindow.axaml
@@ -10,8 +10,7 @@
x:DataType="vm:MainWindowViewModel"
Icon="/Assets/avalonia-logo.ico"
Title="BetterRaid"
- Background="DarkSlateGray"
- WindowStartupLocation="CenterScreen">
+ Background="DarkSlateGray">
@@ -35,7 +34,12 @@
Grid.Row="0">
diff --git a/Views/MainWindow.axaml.cs b/Views/MainWindow.axaml.cs
index 908402a..07ba120 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.Extensions;
using BetterRaid.Models;
using BetterRaid.ViewModels;
@@ -25,13 +26,14 @@ public partial class MainWindow : Window
InitializeComponent();
+ _autoUpdater.WorkerSupportsCancellation = true;
_autoUpdater.DoWork += UpdateAllTiles;
- _autoUpdater.RunWorkerAsync();
}
private void OnDatabaseChanged(object? sender, PropertyChangedEventArgs e)
{
- InitializeRaidChannels();
+ // TODO: Only if new channel was added or existing were removed
+ // InitializeRaidChannels();
GenerateRaidGrid();
}
@@ -60,9 +62,14 @@ public partial class MainWindow : Window
private void InitializeRaidChannels()
{
+ if (_autoUpdater?.IsBusy == false)
+ {
+ _autoUpdater?.CancelAsync();
+ }
+
foreach (var rbvm in _raidButtonVMs)
{
- rbvm.PropertyChanged -= OnChannelDataChanged;
+ rbvm.PropertyChanged -= OnRaidButtonViewModelChanged;
}
_raidButtonVMs.Clear();
@@ -77,26 +84,25 @@ public partial class MainWindow : Window
if (string.IsNullOrEmpty(channel))
continue;
- var rbvm = new RaidButtonViewModel
+ var rbvm = new RaidButtonViewModel(channel)
{
- ChannelName = channel,
MainVm = vm
};
- rbvm.PropertyChanged += OnChannelDataChanged;
+ rbvm.PropertyChanged += OnRaidButtonViewModelChanged;
_raidButtonVMs.Add(rbvm);
}
- UpdateChannelData();
+ if (_autoUpdater?.IsBusy == false)
+ {
+ _autoUpdater?.RunWorkerAsync();
+ }
}
- private void OnChannelDataChanged(object? sender, PropertyChangedEventArgs e)
+ private void OnRaidButtonViewModelChanged(object? sender, PropertyChangedEventArgs e)
{
- if (e.PropertyName == nameof(RaidButtonViewModel.Channel))
- {
- GenerateRaidGrid();
- }
+
}
private void GenerateRaidGrid()
@@ -129,13 +135,15 @@ public partial class MainWindow : Window
}
}
- if (vm.Database.OnlyOnline && channel.Channel.IsLive == false)
+ if (vm.Database.OnlyOnline && channel.Channel?.IsLive == false)
{
visible = false;
}
return visible;
- }).ToList();
+ }).OrderByDescending(c => c.Channel?.IsLive).ToList();
+
+
var rows = (int)Math.Ceiling((visibleChannels.Count + 1) / 3.0);
for (var i = 0; i < rows; i++)
@@ -163,11 +171,6 @@ public partial class MainWindow : Window
colIndex = 0;
rowIndex++;
}
-
- if (btn.DataContext is RaidButtonViewModel rbvm)
- {
- Dispatcher.UIThread.InvokeAsync(rbvm.GetOrUpdateChannelAsync);
- }
}
var addButton = new Button
@@ -193,10 +196,7 @@ public partial class MainWindow : Window
private void OnAddChannelButtonClicked(object? sender, RoutedEventArgs e)
{
var dialog = new AddChannelWindow();
- dialog.Position = new Avalonia.PixelPoint(
- (int)(Position.X + Width / 2 - dialog.Width / 2),
- (int)(Position.Y + Height / 2 - dialog.Height / 2)
- );
+ dialog.CenterToOwner();
var vm = DataContext as MainWindowViewModel;
@@ -225,11 +225,7 @@ public partial class MainWindow : Window
{
foreach (var vm in _raidButtonVMs)
{
- Dispatcher.UIThread.InvokeAsync(async () =>
- {
- await vm.GetOrUpdateChannelAsync();
- }
- );
+ Task.Run(vm.GetOrUpdateChannelAsync);
}
}
@@ -237,8 +233,8 @@ public partial class MainWindow : Window
{
while (e.Cancel == false)
{
- Task.Delay(App.AutoUpdateDelay).Wait();
UpdateChannelData();
+ Task.Delay(App.AutoUpdateDelay).Wait();
}
}
}
\ No newline at end of file
diff --git a/db.json b/db.json
index 03da05e..a3c9c1f 100644
--- a/db.json
+++ b/db.json
@@ -1 +1 @@
-{"LastRaided":{"Cedricun":null,"ZanTal":null,"PropzMaster":null,"Artimus83":null,"HyperonsLive":null,"theshroomlife":null,"Robocraft999":null,"sllikson":null,"Aron_dc":null,"AIEsports":null,"TobinatorLP":null,"Lordabgrund":null,"GronkhTV":null},"OnlyOnline":false,"Channels":["Cedricun","ZanTal","PropzMaster","Artimus83","HyperonsLive","theshroomlife","Robocraft999","sllikson","Aron_dc","AIEsports","TobinatorLP","Lordabgrund","GronkhTV"],"AutoSave":true}
\ No newline at end of file
+{"LastRaided":{"Cedricun":null,"ZanTal":null,"PropzMaster":null,"Artimus83":null,"HyperonsLive":null,"theshroomlife":null,"Robocraft999":null,"sllikson":null,"Aron_dc":null,"AIEsports":null,"TobinatorLP":null,"Lordabgrund":null,"GronkhTV":null,"Bounty2Cooki":null,"ichdasFaultier":null,"codingPurpurTentakel":null,"DerMorzi":null},"OnlyOnline":false,"Channels":["Cedricun","ZanTal","PropzMaster","Artimus83","HyperonsLive","theshroomlife","Robocraft999","sllikson","Aron_dc","AIEsports","TobinatorLP","Lordabgrund","GronkhTV","Bounty2Cooki","ichdasFaultier","codingPurpurTentakel","DerMorzi"],"AutoSave":true}
\ No newline at end of file