Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Trdo/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using Trdo.Controls;
using Trdo.Pages;
using Trdo.Services;
using Trdo.ViewModels;
using Windows.UI;
using Windows.UI.ViewManagement;
Expand Down Expand Up @@ -36,10 +38,21 @@ public App()
InitializeComponent();
_playerVm.PropertyChanged += PlayerVmOnPropertyChanged;

// Initialize PlaylistHistoryService early so it captures metadata from the start
PlaylistHistoryService.EnsureInitialized();

// Subscribe to theme change events
_uiSettings.ColorValuesChanged += OnColorValuesChanged;
}

public void TryShowFlyout()
{
if (_trayIcon is null)
return;

// TODO: find a way to programmatically show the flyout on the Icon
}

protected override async void OnLaunched(LaunchActivatedEventArgs args)
{
// Check for single instance using a named mutex
Expand Down Expand Up @@ -131,6 +144,13 @@ private void InitializeTrayIcon()
_trayIcon.Selected += TrayIcon_Selected;
_trayIcon.ContextMenu += TrayIcon_ContextMenu;
_trayIcon.IsVisible = true;

// Only show tutorial window on first run
if (SettingsService.IsFirstRun)
{
TutorialWindow tutorialWindow = new();
tutorialWindow.Show();
}
}

private void TrayIcon_ContextMenu(TrayIcon sender, TrayIconEventArgs args)
Expand Down
Binary file added Trdo/Assets/Tutorial.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
257 changes: 257 additions & 0 deletions Trdo/Controls/TutorialWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
<?xml version="1.0" encoding="utf-8" ?>
<ex:WindowEx
x:Class="Trdo.Controls.TutorialWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ex="using:WinUIEx"
xmlns:local="using:Trdo.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="Trdo First Run Window"
Width="400"
Height="600"
IsMaximizable="False"
IsMinimizable="False"
mc:Ignorable="d">

<ex:WindowEx.SystemBackdrop>
<MicaBackdrop />
</ex:WindowEx.SystemBackdrop>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>

<TitleBar x:Name="ModernTitlebar" Title="Trdo">
<TitleBar.IconSource>
<ImageIconSource ImageSource="/Assets/Radio.ico" />
</TitleBar.IconSource>
</TitleBar>

<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
<StackPanel
Margin="32,24,32,24"
Orientation="Vertical"
Spacing="20">

<!-- Welcome Header with Icon -->
<StackPanel
HorizontalAlignment="Center"
Orientation="Vertical"
Spacing="12">
<Image
Width="64"
Height="64"
HorizontalAlignment="Center"
Source="/Assets/Radio.ico" />
<TextBlock
HorizontalAlignment="Center"
Style="{StaticResource TitleLargeTextBlockStyle}"
Text="Welcome to Trdo!" />
<TextBlock
HorizontalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Style="{StaticResource SubheaderTextBlockStyle}"
Text="Your tiny tray radio for Windows"
TextAlignment="Center" />
</StackPanel>

<!-- Tutorial Steps -->
<StackPanel
Margin="0,8,0,0"
Orientation="Vertical"
Spacing="16">
<TextBlock
FontSize="18"
Style="{StaticResource BodyStrongTextBlockStyle}"
Text="Quick Start Guide" />

<!-- Step 1 -->
<Border
Padding="16"
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="8">
<Grid ColumnSpacing="16">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border
Grid.Column="0"
Width="32"
Height="32"
VerticalAlignment="Top"
Background="{ThemeResource AccentFillColorDefaultBrush}"
CornerRadius="20">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="16"
FontWeight="Bold"
Foreground="White"
Text="1" />
</Border>
<StackPanel
Grid.Column="1"
VerticalAlignment="Center"
Orientation="Vertical"
Spacing="4">
<TextBlock FontWeight="SemiBold" Text="Pin the Tray Icon" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Make sure the Trdo icon is always visible in your system tray"
TextWrapping="Wrap" />
</StackPanel>
</Grid>
</Border>

<!-- Step 2 -->
<Border
Padding="16"
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="8">
<Grid ColumnSpacing="16">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border
Grid.Column="0"
Width="32"
Height="32"
VerticalAlignment="Top"
Background="{ThemeResource AccentFillColorDefaultBrush}"
CornerRadius="20">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="16"
FontWeight="Bold"
Foreground="White"
Text="2" />
</Border>
<StackPanel
Grid.Column="1"
VerticalAlignment="Center"
Orientation="Vertical"
Spacing="4">
<TextBlock FontWeight="SemiBold" Text="Left Click to Play/Pause" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Quick and easy playback control at your fingertips"
TextWrapping="Wrap" />
</StackPanel>
</Grid>
</Border>

<!-- Step 3 -->
<Border
Padding="16"
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="8">
<Grid ColumnSpacing="16">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border
Grid.Column="0"
Width="32"
Height="32"
VerticalAlignment="Top"
Background="{ThemeResource AccentFillColorDefaultBrush}"
CornerRadius="20">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="16"
FontWeight="Bold"
Foreground="White"
Text="3" />
</Border>
<StackPanel
Grid.Column="1"
VerticalAlignment="Center"
Orientation="Vertical"
Spacing="4">
<TextBlock FontWeight="SemiBold" Text="Right Click for More Options" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Browse stations, adjust settings, and explore all features"
TextWrapping="Wrap" />
</StackPanel>
</Grid>
</Border>
</StackPanel>

<!-- Tutorial GIF -->
<Border
Margin="0,8,0,0"
Padding="8"
Background="{ThemeResource LayerFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="8">
<Image
HorizontalAlignment="Center"
Source="/Assets/Tutorial.gif"
Stretch="Uniform" />
</Border>

<!-- Feature Highlights -->
<StackPanel
Margin="0,8,0,0"
Orientation="Vertical"
Spacing="8">
<TextBlock Style="{StaticResource BodyStrongTextBlockStyle}" Text="✨ What makes Trdo special:" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="• Lightweight and minimalistic design"
TextWrapping="Wrap" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="• Access thousands of radio stations worldwide"
TextWrapping="Wrap" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="• Beautiful Mica backdrop and modern UI"
TextWrapping="Wrap" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="• Lives quietly in your system tray"
TextWrapping="Wrap" />
</StackPanel>
</StackPanel>
</ScrollViewer>

<!-- Bottom Action Button -->
<Border
Grid.Row="2"
Padding="32,16,32,20"
Background="{ThemeResource LayerFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="0,1,0,0">
<Button
Padding="16,8"
HorizontalAlignment="Stretch"
Click="Button_Click"
FontSize="16"
Style="{StaticResource AccentButtonStyle}">
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock FontSize="18" Text="🚀" />
<TextBlock FontWeight="SemiBold" Text="Let's Get Started!" />
</StackPanel>
</Button>
</Border>

</Grid>

</ex:WindowEx>
28 changes: 28 additions & 0 deletions Trdo/Controls/TutorialWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Trdo.Services;
using WinUIEx;

namespace Trdo.Controls;
/// <summary>
/// An empty window that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class TutorialWindow : WindowEx
{
public TutorialWindow()
{
InitializeComponent();

ExtendsContentIntoTitleBar = true;
SetTitleBar(ModernTitlebar);
}

private void Button_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
// Mark first run as complete
SettingsService.MarkFirstRunComplete();

Close();

if (App.Current is App currentApp)
currentApp.TryShowFlyout();
}
}
35 changes: 35 additions & 0 deletions Trdo/Converters/BooleanToFavoriteGlyphConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Microsoft.UI.Xaml.Data;
using System;

namespace Trdo.Converters;

/// <summary>
/// Converts a boolean favorite status to the appropriate star glyph.
/// </summary>
public class BooleanToFavoriteGlyphConverter : IValueConverter
{
/// <summary>
/// Filled star glyph (favorited).
/// </summary>
private const string FilledStar = "\uE735";

/// <summary>
/// Outline star glyph (not favorited).
/// </summary>
private const string OutlineStar = "\uE734";

public object Convert(object value, Type targetType, object parameter, string language)
{
if (value is bool isFavorited)
{
return isFavorited ? FilledStar : OutlineStar;
}

return OutlineStar;
}

public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
10 changes: 8 additions & 2 deletions Trdo/Converters/NullToVisibilityConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@
namespace Trdo.Converters;

/// <summary>
/// Converts null to Visibility. Returns Visible when value is not null, Collapsed when null.
/// Converts null or empty string to Visibility. Returns Visible when value is not null/empty, Collapsed when null/empty.
/// </summary>
public class NullToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
return value != null ? Visibility.Visible : Visibility.Collapsed;
if (value == null)
return Visibility.Collapsed;

if (value is string str)
return string.IsNullOrWhiteSpace(str) ? Visibility.Collapsed : Visibility.Visible;

return Visibility.Visible;
}

public object ConvertBack(object value, Type targetType, object parameter, string language)
Expand Down
Loading