mirror of
https://github.com/Jellyfin2Samsung/Samsung-Jellyfin-Installer.git
synced 2026-03-01 11:21:12 +03:00
Add Dark Mode toggle with dynamic theme switching
Summary - Add dark mode toggle icon (☀️/🌙) to main window and settings header for quick theme switching - Create ThemeService for centralized theme management with save/load from settings - Replace all hardcoded colors with DynamicResource for proper theme support - Synchronize theme state between MainWindow and Settings via ThemeChanged event - Update Buttons, TextBlocks, and ComboBoxes styles to be theme-aware - Fix dark mode for all modal dialogs (BuildInfo, InstallationComplete, Installing, IpInput, TvLogs) - Update DialogService to use theme-aware colors from FluentTheme resources
This commit is contained in:
@@ -49,7 +49,10 @@ namespace Jellyfin2Samsung
|
||||
});
|
||||
}
|
||||
|
||||
RequestedThemeVariant = ThemeVariant.Light;
|
||||
// Apply saved theme on startup
|
||||
var themeService = _serviceProvider.GetRequiredService<IThemeService>();
|
||||
themeService.ApplyTheme();
|
||||
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
}
|
||||
|
||||
@@ -68,6 +71,7 @@ namespace Jellyfin2Samsung
|
||||
services.AddSingleton<INetworkService, NetworkService>();
|
||||
services.AddSingleton<ITizenCertificateService, TizenCertificateService>();
|
||||
services.AddSingleton<ITizenInstallerService, TizenInstallerService>();
|
||||
services.AddSingleton<IThemeService, ThemeService>();
|
||||
|
||||
// HttpClient (configured ONCE)
|
||||
services.AddSingleton(sp =>
|
||||
|
||||
@@ -71,6 +71,7 @@ namespace Jellyfin2Samsung.Helpers
|
||||
public bool KeepWGTFile { get; set; } = false;
|
||||
public bool PatchYoutubePlugin { get; set; } = false;
|
||||
public string CustomCss { get; set; } = "";
|
||||
public bool DarkMode { get; set; } = false;
|
||||
|
||||
// ----- Application-scoped settings (readonly at runtime) -----
|
||||
public string ReleasesUrl { get; set; } = "https://api.github.com/repos/jeppevinkel/jellyfin-tizen-builds/releases";
|
||||
|
||||
12
Jellyfin2Samsung-CrossOS/Interfaces/IThemeService.cs
Normal file
12
Jellyfin2Samsung-CrossOS/Interfaces/IThemeService.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace Jellyfin2Samsung.Interfaces
|
||||
{
|
||||
public interface IThemeService
|
||||
{
|
||||
bool IsDarkMode { get; }
|
||||
event EventHandler<bool>? ThemeChanged;
|
||||
void SetTheme(bool isDarkMode);
|
||||
void ApplyTheme();
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,31 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Styling;
|
||||
using Avalonia.Markup.Xaml.Styling;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using Jellyfin2Samsung.Interfaces;
|
||||
using Jellyfin2Samsung;
|
||||
using Jellyfin2Samsung.Helpers;
|
||||
|
||||
namespace Jellyfin2Samsung.Services
|
||||
{
|
||||
public class DialogService : IDialogService
|
||||
{
|
||||
private static IBrush GetThemeBrush(string resourceKey, bool isDarkMode)
|
||||
{
|
||||
var themeVariant = isDarkMode ? ThemeVariant.Dark : ThemeVariant.Light;
|
||||
if (Application.Current?.TryFindResource(resourceKey, themeVariant, out var resource) == true && resource is IBrush brush)
|
||||
{
|
||||
return brush;
|
||||
}
|
||||
// Ultimate fallback
|
||||
return resourceKey.Contains("Background")
|
||||
? (isDarkMode ? Brushes.Black : Brushes.White)
|
||||
: (isDarkMode ? Brushes.White : Brushes.Black);
|
||||
}
|
||||
|
||||
private Window? GetMainWindow()
|
||||
{
|
||||
if (Application.Current?.ApplicationLifetime is Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime desktop)
|
||||
@@ -27,6 +43,9 @@ namespace Jellyfin2Samsung.Services
|
||||
string yesText = "Yes",
|
||||
string noText = "No")
|
||||
{
|
||||
// Get theme from AppSettings
|
||||
var isDarkMode = AppSettings.Default.DarkMode;
|
||||
|
||||
var dialog = new Window
|
||||
{
|
||||
Title = title,
|
||||
@@ -35,11 +54,22 @@ namespace Jellyfin2Samsung.Services
|
||||
MaxWidth = 600,
|
||||
CanResize = false,
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner,
|
||||
Background = Brushes.White,
|
||||
CornerRadius = new CornerRadius(12),
|
||||
SizeToContent = SizeToContent.Height, // dynamic height
|
||||
RequestedThemeVariant = isDarkMode ? ThemeVariant.Dark : ThemeVariant.Light
|
||||
};
|
||||
|
||||
// Apply FluentTheme
|
||||
dialog.Styles.Add(new StyleInclude(new Uri("avares://Jellyfin2Samsung"))
|
||||
{
|
||||
Source = new Uri("avares://Avalonia.Themes.Fluent/FluentTheme.xaml")
|
||||
});
|
||||
|
||||
// Get colors from theme resources (same as main UI)
|
||||
var backgroundBrush = GetThemeBrush("SystemControlBackgroundAltHighBrush", isDarkMode);
|
||||
var foregroundBrush = GetThemeBrush("SystemControlForegroundBaseHighBrush", isDarkMode);
|
||||
dialog.Background = backgroundBrush;
|
||||
|
||||
var mainPanel = new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Vertical,
|
||||
@@ -52,6 +82,7 @@ namespace Jellyfin2Samsung.Services
|
||||
Text = title,
|
||||
FontSize = 18,
|
||||
FontWeight = FontWeight.Bold,
|
||||
Foreground = foregroundBrush,
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
Margin = new Thickness(0, 0, 0, 10)
|
||||
});
|
||||
@@ -117,10 +148,14 @@ namespace Jellyfin2Samsung.Services
|
||||
public async Task ShowMessageAsync(string title, string message)
|
||||
{
|
||||
var window = GetMainWindow();
|
||||
var isDarkMode = AppSettings.Default.DarkMode;
|
||||
var foregroundBrush = GetThemeBrush("SystemControlForegroundBaseHighBrush", isDarkMode);
|
||||
|
||||
var dialog = CreateStyledDialog(title, new TextBlock
|
||||
{
|
||||
Text = message,
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
Foreground = foregroundBrush,
|
||||
FontSize = 14,
|
||||
Margin = new Thickness(0, 5, 0, 0)
|
||||
});
|
||||
@@ -149,11 +184,14 @@ namespace Jellyfin2Samsung.Services
|
||||
{
|
||||
var window = owner ?? GetMainWindow();
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
var isDarkMode = AppSettings.Default.DarkMode;
|
||||
var foregroundBrush = GetThemeBrush("SystemControlForegroundBaseHighBrush", isDarkMode);
|
||||
|
||||
var dialog = CreateStyledDialog(title, new TextBlock
|
||||
{
|
||||
Text = message,
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
Foreground = foregroundBrush,
|
||||
FontSize = 14,
|
||||
Margin = new Thickness(0, 5, 0, 0)
|
||||
}, showButtons: true, tcs: tcs, yesText: yesText, noText: noText);
|
||||
|
||||
37
Jellyfin2Samsung-CrossOS/Services/ThemeService.cs
Normal file
37
Jellyfin2Samsung-CrossOS/Services/ThemeService.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Styling;
|
||||
using Jellyfin2Samsung.Helpers;
|
||||
using Jellyfin2Samsung.Interfaces;
|
||||
using System;
|
||||
|
||||
namespace Jellyfin2Samsung.Services
|
||||
{
|
||||
public class ThemeService : IThemeService
|
||||
{
|
||||
public bool IsDarkMode => AppSettings.Default.DarkMode;
|
||||
|
||||
public event EventHandler<bool>? ThemeChanged;
|
||||
|
||||
public void SetTheme(bool isDarkMode)
|
||||
{
|
||||
if (AppSettings.Default.DarkMode == isDarkMode)
|
||||
return;
|
||||
|
||||
AppSettings.Default.DarkMode = isDarkMode;
|
||||
AppSettings.Default.Save();
|
||||
|
||||
ApplyTheme();
|
||||
ThemeChanged?.Invoke(this, isDarkMode);
|
||||
}
|
||||
|
||||
public void ApplyTheme()
|
||||
{
|
||||
if (Application.Current is null)
|
||||
return;
|
||||
|
||||
Application.Current.RequestedThemeVariant = AppSettings.Default.DarkMode
|
||||
? ThemeVariant.Dark
|
||||
: ThemeVariant.Light;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,9 +34,9 @@
|
||||
<Setter Property="Width" Value="40"/>
|
||||
<Setter Property="Height" Value="40"/>
|
||||
<Setter Property="CornerRadius" Value="20"/>
|
||||
<Setter Property="Background" Value="#ffffff"/>
|
||||
<Setter Property="Foreground" Value="#2C3E50"/>
|
||||
<Setter Property="BorderBrush" Value="#d0d7de"/>
|
||||
<Setter Property="Background" Value="{DynamicResource SystemControlBackgroundAltHighBrush}"/>
|
||||
<Setter Property="Foreground" Value="{DynamicResource SystemControlForegroundBaseHighBrush}"/>
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="FontSize" Value="16"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Style Selector="ComboBox.clean">
|
||||
<Setter Property="Background" Value="White"/>
|
||||
<Setter Property="Foreground" Value="#2C3E50"/>
|
||||
<Setter Property="BorderBrush" Value="#BDC3C7"/>
|
||||
<Setter Property="Background" Value="{DynamicResource SystemControlBackgroundAltHighBrush}"/>
|
||||
<Setter Property="Foreground" Value="{DynamicResource SystemControlForegroundBaseHighBrush}"/>
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="CornerRadius" Value="4"/>
|
||||
<Setter Property="Padding" Value="12,8"/>
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
<Style Selector="TextBlock.label">
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="FontWeight" Value="Medium"/>
|
||||
<Setter Property="Foreground" Value="#2C3E50"/>
|
||||
<Setter Property="Foreground" Value="{DynamicResource SystemControlForegroundBaseHighBrush}"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="TextBlock.subtitle">
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Foreground" Value="#7F8C8D"/>
|
||||
<Setter Property="Foreground" Value="{DynamicResource SystemControlForegroundBaseMediumBrush}"/>
|
||||
</Style>
|
||||
</Styles>
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace Jellyfin2Samsung.ViewModels
|
||||
private readonly ILocalizationService _localizationService;
|
||||
private readonly CertificateHelper _certificateHelper;
|
||||
private readonly INetworkService _networkService;
|
||||
private readonly IThemeService _themeService;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? audioLanguagePreference;
|
||||
@@ -169,6 +170,9 @@ namespace Jellyfin2Samsung.ViewModels
|
||||
[ObservableProperty]
|
||||
private bool keepWGTFile;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool darkMode;
|
||||
|
||||
public ObservableCollection<LanguageOption> AvailableLanguages { get; }
|
||||
public ObservableCollection<ExistingCertificates> AvailableCertificates { get; } = new();
|
||||
public ObservableCollection<JellyfinUser> AvailableJellyfinUsers { get; } = new();
|
||||
@@ -300,13 +304,16 @@ namespace Jellyfin2Samsung.ViewModels
|
||||
JellyfinApiClient jellyfinApiClient,
|
||||
ILocalizationService localizationService,
|
||||
CertificateHelper certificateHelper,
|
||||
INetworkService networkService)
|
||||
INetworkService networkService,
|
||||
IThemeService themeService)
|
||||
{
|
||||
_jellyfinApiClient = jellyfinApiClient;
|
||||
_localizationService = localizationService;
|
||||
_certificateHelper = certificateHelper;
|
||||
_networkService = networkService;
|
||||
_themeService = themeService;
|
||||
_localizationService.LanguageChanged += OnLanguageChanged;
|
||||
_themeService.ThemeChanged += OnThemeChanged;
|
||||
|
||||
// Initialize selected users collection with change tracking
|
||||
SelectedJellyfinUsers = new ObservableCollection<JellyfinUser>();
|
||||
@@ -344,6 +351,11 @@ namespace Jellyfin2Samsung.ViewModels
|
||||
RefreshLocalizedProperties();
|
||||
}
|
||||
|
||||
private void OnThemeChanged(object? sender, bool isDarkMode)
|
||||
{
|
||||
DarkMode = isDarkMode;
|
||||
}
|
||||
|
||||
private void RefreshLocalizedProperties()
|
||||
{
|
||||
OnPropertyChanged(nameof(LblJellyfinConfig));
|
||||
@@ -927,14 +939,15 @@ namespace Jellyfin2Samsung.ViewModels
|
||||
{
|
||||
using var http = new HttpClient();
|
||||
var bytes = await http.GetByteArrayAsync(url);
|
||||
|
||||
using var ms = new System.IO.MemoryStream(bytes);
|
||||
return new Bitmap(ms);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine($"[ThemePreview] Failed to load preview: {ex.Message}");
|
||||
return null;
|
||||
using var http = new HttpClient();
|
||||
var stream = await http.GetStreamAsync(url);
|
||||
return new Bitmap(stream);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1002,7 +1015,6 @@ namespace Jellyfin2Samsung.ViewModels
|
||||
HexColor = "#6B5B95",
|
||||
CssImportUrl = "https://cdn.jsdelivr.net/gh/kingchenc/JellyThemes@master/Themes/Obsidian/Obsidian.css",
|
||||
PreviewUrl = "https://raw.githubusercontent.com/kingchenc/JellyThemes/master/Themes/Obsidian/assets/preview/Obsidian.png"
|
||||
|
||||
},
|
||||
new JellyTheme
|
||||
{
|
||||
@@ -1244,6 +1256,7 @@ namespace Jellyfin2Samsung.ViewModels
|
||||
TryOverwrite = AppSettings.Default.TryOverwrite;
|
||||
OpenAfterInstall = AppSettings.Default.OpenAfterInstall;
|
||||
KeepWGTFile = AppSettings.Default.KeepWGTFile;
|
||||
DarkMode = AppSettings.Default.DarkMode;
|
||||
}
|
||||
|
||||
private async Task LoadLocalIpAsync()
|
||||
@@ -1379,11 +1392,17 @@ namespace Jellyfin2Samsung.ViewModels
|
||||
AppSettings.Default.Save();
|
||||
}
|
||||
|
||||
partial void OnDarkModeChanged(bool value)
|
||||
{
|
||||
_themeService.SetTheme(value);
|
||||
}
|
||||
|
||||
// ========== End Main Settings Methods ==========
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_localizationService.LanguageChanged -= OnLanguageChanged;
|
||||
_themeService.ThemeChanged -= OnThemeChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using Jellyfin2Samsung.Helpers.API;
|
||||
using Jellyfin2Samsung.Helpers.Core;
|
||||
using Jellyfin2Samsung.Helpers.Tizen.Devices;
|
||||
using Jellyfin2Samsung.Interfaces;
|
||||
using Jellyfin2Samsung.Services;
|
||||
using Jellyfin2Samsung.Models;
|
||||
using Jellyfin2Samsung.Views;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@@ -29,6 +30,7 @@ namespace Jellyfin2Samsung.ViewModels
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly INetworkService _networkService;
|
||||
private readonly ILocalizationService _localizationService;
|
||||
private readonly IThemeService _themeService;
|
||||
private readonly FileHelper _fileHelper;
|
||||
private readonly DeviceHelper _deviceHelper;
|
||||
private readonly TizenApiClient _tizenApiClient;
|
||||
@@ -70,6 +72,9 @@ namespace Jellyfin2Samsung.ViewModels
|
||||
[ObservableProperty]
|
||||
private bool isSamsungLoginActive;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool darkMode;
|
||||
|
||||
private string _currentStatusKey = string.Empty;
|
||||
|
||||
private string? _downloadedPackagePath;
|
||||
@@ -91,6 +96,7 @@ namespace Jellyfin2Samsung.ViewModels
|
||||
IDialogService dialogService,
|
||||
INetworkService networkService,
|
||||
ILocalizationService localizationService,
|
||||
IThemeService themeService,
|
||||
HttpClient httpClient,
|
||||
DeviceHelper deviceHelper,
|
||||
TizenApiClient tizenApiClient,
|
||||
@@ -106,12 +112,17 @@ namespace Jellyfin2Samsung.ViewModels
|
||||
_tizenApiClient = tizenApiClient;
|
||||
_packageHelper = packageHelper;
|
||||
_localizationService = localizationService;
|
||||
_themeService = themeService;
|
||||
_fileHelper = fileHelper;
|
||||
_settingsViewModel = settingsViewModel;
|
||||
|
||||
_addLatestRelease = new AddLatestRelease(httpClient);
|
||||
|
||||
_localizationService.LanguageChanged += OnLanguageChanged;
|
||||
_themeService.ThemeChanged += OnThemeChanged;
|
||||
|
||||
// Initialize dark mode state from settings
|
||||
DarkMode = AppSettings.Default.DarkMode;
|
||||
}
|
||||
|
||||
|
||||
@@ -122,6 +133,16 @@ namespace Jellyfin2Samsung.ViewModels
|
||||
if (!string.IsNullOrEmpty(_currentStatusKey))
|
||||
StatusBar = L(_currentStatusKey);
|
||||
}
|
||||
|
||||
private void OnThemeChanged(object? sender, bool isDarkMode)
|
||||
{
|
||||
DarkMode = isDarkMode;
|
||||
}
|
||||
|
||||
partial void OnDarkModeChanged(bool value)
|
||||
{
|
||||
_themeService.SetTheme(value);
|
||||
}
|
||||
private void SetStatus(string key)
|
||||
{
|
||||
_currentStatusKey = key;
|
||||
@@ -340,6 +361,7 @@ namespace Jellyfin2Samsung.ViewModels
|
||||
await _dialogService.ShowErrorAsync($"Failed to open build info window: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task BrowseWgtAsync()
|
||||
{
|
||||
@@ -584,6 +606,7 @@ namespace Jellyfin2Samsung.ViewModels
|
||||
{
|
||||
DisposeSamsungCts();
|
||||
_localizationService.LanguageChanged -= OnLanguageChanged;
|
||||
_themeService.ThemeChanged -= OnThemeChanged;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,19 +8,18 @@
|
||||
MaxWidth="900"
|
||||
MinHeight="500"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
Title="Jellyfin Tizen Versions"
|
||||
Background="#F5F5F5">
|
||||
Title="Jellyfin Tizen Versions">
|
||||
|
||||
<Window.Styles>
|
||||
<StyleInclude Source="avares://Avalonia.Themes.Fluent/FluentTheme.xaml"/>
|
||||
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml"/>
|
||||
</Window.Styles>
|
||||
|
||||
<Border Background="White"
|
||||
<Border Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
|
||||
Padding="16"
|
||||
CornerRadius="8"
|
||||
Margin="12"
|
||||
BorderBrush="#E8E8E8"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"
|
||||
BorderThickness="1">
|
||||
|
||||
<Border.Effect>
|
||||
@@ -53,7 +52,7 @@
|
||||
FontSize="15"/>
|
||||
</Border>
|
||||
|
||||
<Border BorderBrush="#D0D0D0"
|
||||
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4"
|
||||
Height="200">
|
||||
@@ -91,7 +90,7 @@
|
||||
FontSize="15"/>
|
||||
</Border>
|
||||
|
||||
<Border BorderBrush="#D0D0D0"
|
||||
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4"
|
||||
Height="260">
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
WindowStartupLocation="CenterScreen"
|
||||
CanResize="False"
|
||||
SizeToContent="WidthAndHeight"
|
||||
Background="#F5F5F5"
|
||||
ExtendClientAreaToDecorationsHint="True"
|
||||
ExtendClientAreaChromeHints="NoChrome"
|
||||
ExtendClientAreaTitleBarHeightHint="-1">
|
||||
@@ -24,11 +23,11 @@
|
||||
<StyleInclude Source="avares://Jellyfin2Samsung/Styles/ComboBoxes.axaml"/>
|
||||
</Window.Styles>
|
||||
|
||||
<Border Background="White"
|
||||
<Border Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
|
||||
Padding="10"
|
||||
CornerRadius="8"
|
||||
Margin="20"
|
||||
BorderBrush="#E8E8E8"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"
|
||||
BorderThickness="1">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect BlurRadius="15"
|
||||
@@ -50,14 +49,14 @@
|
||||
TextWrapping="Wrap"
|
||||
FontSize="16"
|
||||
TextAlignment="Center"
|
||||
Foreground="#2C3E50"
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"
|
||||
FontWeight="Medium"/>
|
||||
|
||||
<!-- Extra Info -->
|
||||
<TextBlock Text="{Binding EasyRight}"
|
||||
TextWrapping="Wrap"
|
||||
TextAlignment="Center"
|
||||
Foreground="#7F8C8D"
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseMediumBrush}"
|
||||
FontSize="14"/>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
|
||||
@@ -12,12 +12,20 @@
|
||||
Topmost="True"
|
||||
ShowInTaskbar="False"
|
||||
Title="Installing">
|
||||
|
||||
<Window.Styles>
|
||||
<StyleInclude Source="avares://Avalonia.Themes.Fluent/FluentTheme.xaml"/>
|
||||
</Window.Styles>
|
||||
|
||||
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||
<Border Background="#FFF" CornerRadius="4" Padding="10" Margin="5"
|
||||
BorderBrush="#FF000B25" BorderThickness="1" >
|
||||
<Border Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
|
||||
CornerRadius="4" Padding="10" Margin="5"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"
|
||||
BorderThickness="1">
|
||||
<StackPanel>
|
||||
<TextBlock x:Name="StatusTextBlock"
|
||||
Text="{Binding StatusText}"
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"
|
||||
FontWeight="Bold"
|
||||
Margin="0,10"
|
||||
HorizontalAlignment="Center"/>
|
||||
|
||||
@@ -9,18 +9,21 @@
|
||||
x:Class="Jellyfin2Samsung.IpInputDialog"
|
||||
x:DataType="viewModels:IpInputDialogViewModel"
|
||||
Width="420"
|
||||
Height="220"
|
||||
Height="250"
|
||||
Title="{Binding Title}"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
CanResize="False"
|
||||
Background="White"
|
||||
CornerRadius="12">
|
||||
|
||||
<Border Background="White"
|
||||
<Window.Styles>
|
||||
<StyleInclude Source="avares://Avalonia.Themes.Fluent/FluentTheme.xaml"/>
|
||||
</Window.Styles>
|
||||
|
||||
<Border Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
|
||||
Padding="20"
|
||||
CornerRadius="12"
|
||||
Margin="10"
|
||||
BorderBrush="#E5E7EB"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"
|
||||
BorderThickness="1">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect BlurRadius="20"
|
||||
@@ -36,12 +39,13 @@
|
||||
<TextBlock Text="{Binding Title}"
|
||||
FontSize="18"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0,0,0,10"/>
|
||||
|
||||
<!-- Message -->
|
||||
<TextBlock Text="{Binding Message}"
|
||||
Foreground="#111827"
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"
|
||||
FontSize="14"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0,0,0,8"/>
|
||||
@@ -49,9 +53,8 @@
|
||||
<!-- IP Input -->
|
||||
<TextBox Text="{Binding EnteredIp}"
|
||||
Watermark="Enter IP address..."
|
||||
CaretBrush="Black"
|
||||
SelectionBrush="#2563eb"
|
||||
BorderBrush="#9CA3AF"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"
|
||||
CornerRadius="8"
|
||||
Padding="8"
|
||||
FontSize="14"
|
||||
|
||||
@@ -8,9 +8,8 @@
|
||||
x:Class="Jellyfin2Samsung.JellyfinConfigView"
|
||||
x:DataType="viewModels:JellyfinConfigViewModel"
|
||||
Title="Settings"
|
||||
Width="700"
|
||||
Height="850"
|
||||
Background="#F5F5F5">
|
||||
Width="715"
|
||||
Height="850">
|
||||
|
||||
<Window.Styles>
|
||||
<StyleInclude Source="avares://Avalonia.Themes.Fluent/FluentTheme.xaml"/>
|
||||
@@ -20,11 +19,11 @@
|
||||
<StyleInclude Source="avares://Jellyfin2Samsung/Styles/ComboBoxes.axaml"/>
|
||||
</Window.Styles>
|
||||
|
||||
<Border Background="White"
|
||||
<Border Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
|
||||
Padding="16"
|
||||
CornerRadius="8"
|
||||
Margin="6"
|
||||
BorderBrush="#E8E8E8"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"
|
||||
BorderThickness="1">
|
||||
|
||||
<Border.Effect>
|
||||
@@ -43,11 +42,33 @@
|
||||
CornerRadius="8"
|
||||
Padding="24,16"
|
||||
Margin="0,0,0,14">
|
||||
<TextBlock Text="{Binding LblSettingsHeader}"
|
||||
Foreground="White"
|
||||
FontSize="18"
|
||||
FontWeight="Medium"
|
||||
HorizontalAlignment="Center"/>
|
||||
<Grid>
|
||||
<TextBlock Text="{Binding LblSettingsHeader}"
|
||||
Foreground="White"
|
||||
FontSize="18"
|
||||
FontWeight="Medium"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"/>
|
||||
<ToggleButton IsChecked="{Binding DarkMode}"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
Padding="4">
|
||||
<ToggleButton.Styles>
|
||||
<Style Selector="ToggleButton:checked">
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
</Style>
|
||||
<Style Selector="ToggleButton:pointerover">
|
||||
<Setter Property="Background" Value="#40FFFFFF"/>
|
||||
</Style>
|
||||
</ToggleButton.Styles>
|
||||
<Panel>
|
||||
<TextBlock Text="☀" FontSize="18" Foreground="White" IsVisible="{Binding DarkMode}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
<TextBlock Text="🌙" FontSize="16" Foreground="White" IsVisible="{Binding !DarkMode}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Panel>
|
||||
</ToggleButton>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- TabControl with 5 Tabs -->
|
||||
@@ -63,7 +84,7 @@
|
||||
<TextBlock Text="{Binding LblMainSettings}"
|
||||
FontSize="15"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#2C3E50"/>
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"/>
|
||||
|
||||
<!-- Language Section -->
|
||||
<Grid ColumnDefinitions="180,*" ColumnSpacing="12">
|
||||
@@ -116,7 +137,7 @@
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
<Border Height="1" Background="#E8E8E8" Margin="0,4"/>
|
||||
<Border Height="1" Background="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" Margin="0,4"/>
|
||||
|
||||
<!-- Installation Options Section -->
|
||||
<StackPanel Spacing="12">
|
||||
@@ -200,7 +221,7 @@
|
||||
<TextBlock Text="{Binding LblServerSettings}"
|
||||
FontSize="15"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#2C3E50"/>
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"/>
|
||||
|
||||
<!-- Server Input Mode Selection -->
|
||||
<Grid ColumnDefinitions="180,*" ColumnSpacing="12">
|
||||
@@ -296,14 +317,14 @@
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<Border Height="1" Background="#E8E8E8" Margin="0,4"/>
|
||||
<Border Height="1" Background="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" Margin="0,4"/>
|
||||
|
||||
<!-- Auto-Login Settings Section -->
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock Text="{Binding LblAutoLoginSettings}"
|
||||
FontSize="15"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#2C3E50"/>
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"/>
|
||||
|
||||
<!-- Username -->
|
||||
<Grid ColumnDefinitions="180,*" ColumnSpacing="12">
|
||||
@@ -379,8 +400,8 @@
|
||||
SelectedItems="{Binding SelectedJellyfinUsers}"
|
||||
SelectionMode="Multiple"
|
||||
MaxHeight="120"
|
||||
Background="#FAFAFA"
|
||||
BorderBrush="#E0E0E0"
|
||||
Background="{DynamicResource SystemControlBackgroundChromeMediumLowBrush}"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4"
|
||||
Padding="4">
|
||||
@@ -394,20 +415,20 @@
|
||||
</Grid>
|
||||
<TextBlock Text="{Binding LblUserSelectionHint}"
|
||||
FontSize="11"
|
||||
Foreground="#7F8C8D"
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseMediumBrush}"
|
||||
FontStyle="Italic"
|
||||
Margin="180,0,0,0"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<Border Height="1" Background="#E8E8E8" Margin="0,4"/>
|
||||
<Border Height="1" Background="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" Margin="0,4"/>
|
||||
|
||||
<!-- Advanced Settings Section -->
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock Text="{Binding LblAdvancedSettings}"
|
||||
FontSize="15"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#2C3E50"/>
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"/>
|
||||
|
||||
<!-- Dev Logs -->
|
||||
<Grid ColumnDefinitions="180,*" ColumnSpacing="12">
|
||||
@@ -466,7 +487,7 @@
|
||||
<TextBlock Text="{Binding LblBrowserSettings}"
|
||||
FontSize="15"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#2C3E50"/>
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"/>
|
||||
|
||||
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="12">
|
||||
<TextBlock Grid.Column="0" Text="{Binding LblEnableBackdrops}" Classes="label" VerticalAlignment="Center"/>
|
||||
@@ -513,7 +534,7 @@
|
||||
<ToggleSwitch Grid.Column="1" IsChecked="{Binding SkipIntros}"/>
|
||||
</Grid>
|
||||
|
||||
<Border Height="1" Background="#E8E8E8" Margin="0,4"/>
|
||||
<Border Height="1" Background="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" Margin="0,4"/>
|
||||
|
||||
<Grid ColumnDefinitions="180,*" ColumnSpacing="12">
|
||||
<TextBlock Grid.Column="0" Text="{Binding LblAudioLanguagePreference}" Classes="label" VerticalAlignment="Center"/>
|
||||
@@ -551,12 +572,12 @@
|
||||
<TextBlock Text="{Binding LblCssSettings}"
|
||||
FontSize="15"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#2C3E50"/>
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"/>
|
||||
|
||||
<!-- CSS Hint -->
|
||||
<TextBlock Text="{Binding LblCssHint}"
|
||||
FontSize="12"
|
||||
Foreground="#7F8C8D"
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseMediumBrush}"
|
||||
TextWrapping="Wrap"/>
|
||||
|
||||
<!-- Custom CSS TextBox -->
|
||||
@@ -602,8 +623,7 @@
|
||||
FontWeight="SemiBold"/>
|
||||
</Grid>
|
||||
|
||||
|
||||
<Border Height="1" Background="#E8E8E8" Margin="0,16,0,8"/>
|
||||
<Border Height="1" Background="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" Margin="0,16,0,8"/>
|
||||
|
||||
<!-- JellyThemes Section -->
|
||||
<StackPanel Spacing="8">
|
||||
@@ -612,7 +632,7 @@
|
||||
Text="{Binding LblJellyThemes}"
|
||||
FontSize="15"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#2C3E50"/>
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"/>
|
||||
<Button Grid.Column="1"
|
||||
Classes="secondary"
|
||||
Command="{Binding OpenJellyThemesRepoCommand}"
|
||||
@@ -627,7 +647,7 @@
|
||||
|
||||
<TextBlock Text="{Binding LblJellyThemesHint}"
|
||||
FontSize="12"
|
||||
Foreground="#7F8C8D"
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseMediumBrush}"
|
||||
TextWrapping="Wrap"/>
|
||||
|
||||
<!-- Theme Buttons -->
|
||||
@@ -665,8 +685,8 @@
|
||||
<Border
|
||||
Margin="0,12,0,0"
|
||||
Padding="10"
|
||||
Background="#FAFAFA"
|
||||
BorderBrush="#E0E0E0"
|
||||
Background="{DynamicResource SystemControlBackgroundChromeMediumLowBrush}"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="6"
|
||||
IsVisible="{Binding HasSelectedJellyTheme}">
|
||||
@@ -676,7 +696,7 @@
|
||||
Text="{Binding SelectedJellyTheme.Name}"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#2C3E50"/>
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"/>
|
||||
|
||||
<Image
|
||||
Source="{Binding SelectedJellyThemePreview}"
|
||||
@@ -686,7 +706,7 @@
|
||||
<TextBlock
|
||||
Text="Theme preview"
|
||||
FontSize="11"
|
||||
Foreground="#7F8C8D"/>
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseMediumBrush}"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
Width="580"
|
||||
Height="410"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Title="Jellyfin2Samsung"
|
||||
Background="#F5F5F5">
|
||||
Title="Jellyfin2Samsung">
|
||||
<Window.Resources>
|
||||
<helpers:TvLogStatusToBrushConverter x:Key="TvLogStatusToBrushConverter"/>
|
||||
<helpers:StringEqualsConverter x:Key="StringEquals"/>
|
||||
@@ -24,11 +23,11 @@
|
||||
<StyleInclude Source="avares://Jellyfin2Samsung/Styles/ComboBoxes.axaml"/>
|
||||
</Window.Styles>
|
||||
|
||||
<Border Background="White"
|
||||
<Border Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
|
||||
Padding="16"
|
||||
CornerRadius="8"
|
||||
Margin="6"
|
||||
BorderBrush="#E8E8E8"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"
|
||||
BorderThickness="1">
|
||||
|
||||
<Border.Effect>
|
||||
@@ -163,6 +162,26 @@
|
||||
<Button Classes="icon" Command="{Binding OpenSettingsCommand}">
|
||||
<fa:SymbolIcon Symbol="Settings" Width="20" Height="20"/>
|
||||
</Button>
|
||||
<ToggleButton IsChecked="{Binding DarkMode}"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
Width="40"
|
||||
Height="40"
|
||||
CornerRadius="20"
|
||||
Padding="0">
|
||||
<ToggleButton.Styles>
|
||||
<Style Selector="ToggleButton:checked">
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
</Style>
|
||||
<Style Selector="ToggleButton:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource SystemControlBackgroundBaseLowBrush}"/>
|
||||
</Style>
|
||||
</ToggleButton.Styles>
|
||||
<Panel>
|
||||
<TextBlock Text="☀" FontSize="18" IsVisible="{Binding DarkMode}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
<TextBlock Text="🌙" FontSize="16" IsVisible="{Binding !DarkMode}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Panel>
|
||||
</ToggleButton>
|
||||
<Button Classes="icon"
|
||||
IsVisible="{Binding IsSamsungLoginActive}"
|
||||
Command="{Binding CancelSamsungLoginCommand}">
|
||||
@@ -175,7 +194,7 @@
|
||||
<!-- Clean footer -->
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
FontSize="11"
|
||||
Foreground="#95A5A6"
|
||||
Opacity="0.6"
|
||||
Text="{Binding FooterText}"/>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
Width="900"
|
||||
Height="650"
|
||||
Title="Samsung TV Logs"
|
||||
Background="#F5F5F5"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
|
||||
<!-- ========================= -->
|
||||
@@ -48,11 +47,11 @@
|
||||
<!-- ========================= -->
|
||||
<!-- Layout -->
|
||||
<!-- ========================= -->
|
||||
<Border Background="White"
|
||||
<Border Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
|
||||
Padding="16"
|
||||
CornerRadius="8"
|
||||
Margin="12"
|
||||
BorderBrush="#E8E8E8"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"
|
||||
BorderThickness="1">
|
||||
|
||||
<StackPanel Spacing="16">
|
||||
@@ -61,7 +60,7 @@
|
||||
<TextBlock Text="TV Log Output"
|
||||
FontSize="20"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#2C3E50"/>
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"/>
|
||||
|
||||
<!-- Status + Endpoint -->
|
||||
<StackPanel Orientation="Horizontal"
|
||||
@@ -83,11 +82,11 @@
|
||||
<!-- IP:Port -->
|
||||
<TextBlock Text="{Binding EndpointText}"
|
||||
FontSize="12"
|
||||
Foreground="#555"/>
|
||||
Foreground="{DynamicResource SystemControlForegroundBaseMediumBrush}"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Log output -->
|
||||
<Border BorderBrush="#CCCCCC"
|
||||
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"
|
||||
BorderThickness="1"
|
||||
Background="#1E1E1E"
|
||||
CornerRadius="4"
|
||||
|
||||
Reference in New Issue
Block a user