Lots of performance optimization; Added category to RaidButton; Added AboutWindow
This commit is contained in:
parent
4311bfb43f
commit
d0662351d7
@ -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
|
||||
|
@ -57,14 +57,17 @@
|
||||
Orientation="Vertical">
|
||||
<Label HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
Content="{Binding Channel.DisplayName}" />
|
||||
Content="{Binding Channel.DisplayName, FallbackValue=...}" />
|
||||
<Label HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
Content="{Binding Channel.Category, TargetNullValue=-, FallbackValue=...}" />
|
||||
<Label HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
Foreground="{Binding ViewerCountColor}"
|
||||
Content="{Binding Channel.ViewerCount}" />
|
||||
Content="{Binding Channel.ViewerCount, TargetNullValue=(Offline), FallbackValue=...}" />
|
||||
<Label HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
Content="{Binding LastRaided, TargetNullValue=Never Raided}" />
|
||||
Content="{Binding LastRaided, TargetNullValue=Never Raided, FallbackValue=...}" />
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
|
19
Extensions/WindowExtensions.cs
Normal file
19
Extensions/WindowExtensions.cs
Normal file
@ -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)
|
||||
);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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<bool> 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
|
||||
|
57
Views/AboutWindow.axaml
Normal file
57
Views/AboutWindow.axaml
Normal file
@ -0,0 +1,57 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="BetterRaid.Views.AboutWindow"
|
||||
Title="About"
|
||||
MaxWidth="300"
|
||||
MinWidth="300"
|
||||
Height="200"
|
||||
Background="DarkSlateGray">
|
||||
|
||||
<ScrollViewer>
|
||||
<StackPanel Orientation="Vertical">
|
||||
|
||||
<Label HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
Content="About BetterRaid"
|
||||
Margin="0, 10, 0, -10"
|
||||
FontSize="28"
|
||||
FontWeight="ExtraLight" />
|
||||
|
||||
<Label HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
Content="v0.0.1"
|
||||
Margin="0"
|
||||
FontSize="12"
|
||||
FontWeight="Light" />
|
||||
|
||||
<Separator Margin="0, 5, 0, 5" />
|
||||
|
||||
<TextBlock HorizontalAlignment="Left"
|
||||
Text="Programming"
|
||||
FontSize="14"
|
||||
Margin="5, 5, 0, 5"
|
||||
TextDecorations="Underline" />
|
||||
|
||||
<TextBlock HorizontalAlignment="Left"
|
||||
Text="- Enrico Ludwig <hi@zion-networks.de>"
|
||||
FontSize="12"
|
||||
Margin="15, 0, 0, 0" />
|
||||
|
||||
<TextBlock HorizontalAlignment="Left"
|
||||
Text="Graphics"
|
||||
FontSize="14"
|
||||
Margin="5, 5, 0, 5"
|
||||
TextDecorations="Underline" />
|
||||
|
||||
<TextBlock HorizontalAlignment="Left"
|
||||
Text="- UNKNOWN ARTIST"
|
||||
FontSize="12"
|
||||
Margin="15, 0, 0, 0" />
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
</Window>
|
13
Views/AboutWindow.axaml.cs
Normal file
13
Views/AboutWindow.axaml.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace BetterRaid.Views;
|
||||
|
||||
public partial class AboutWindow : Window
|
||||
{
|
||||
public AboutWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
@ -10,8 +10,7 @@
|
||||
x:DataType="vm:MainWindowViewModel"
|
||||
Icon="/Assets/avalonia-logo.ico"
|
||||
Title="BetterRaid"
|
||||
Background="DarkSlateGray"
|
||||
WindowStartupLocation="CenterScreen">
|
||||
Background="DarkSlateGray">
|
||||
|
||||
<Design.DataContext>
|
||||
<vm:MainWindowViewModel/>
|
||||
@ -35,7 +34,12 @@
|
||||
Grid.Row="0">
|
||||
|
||||
<MenuItem Header="File">
|
||||
<MenuItem Header="Exit" Command="{Binding ExitApplication}" />
|
||||
<MenuItem Header="About"
|
||||
CommandParameter="{Binding $parent[Window]}"
|
||||
Command="{Binding ShowAboutWindow}" />
|
||||
<Separator />
|
||||
<MenuItem Header="Exit"
|
||||
Command="{Binding ExitApplication}" />
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
2
db.json
2
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}
|
||||
{"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}
|
Reference in New Issue
Block a user