Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
37d639f
Initial plan
Copilot Mar 31, 2026
0e191ea
Pop out manual station into its own small window
Copilot Mar 31, 2026
fadef17
Improve window placement UX with pointer anchor service
TheJoeFin Apr 1, 2026
b6d7cc5
Merge pull request #74 from TheJoeFin/copilot/pop-out-manual-station-…
TheJoeFin Apr 1, 2026
b8c1b63
Initial plan
Copilot Apr 1, 2026
45252fe
Add Play on startup setting to auto-play last station when app opens
Copilot Apr 1, 2026
1de7e3a
Add warning InfoBar for auto-play on startup toggle
TheJoeFin Apr 1, 2026
66ea8ff
Clamp window position to non-negative work area bounds
TheJoeFin Apr 1, 2026
d947346
Merge pull request #75 from TheJoeFin/copilot/fix-auto-start-on-restart
TheJoeFin Apr 1, 2026
fafad5a
Initial plan
Copilot Apr 1, 2026
0243564
Add Apple Music and YouTube Music search options with configurable se…
Copilot Apr 1, 2026
ec82bfb
Add SVG logos for Apple Music, Discogs, and YouTube Music
TheJoeFin Apr 2, 2026
3bd4896
Redesign music search links & settings integration
TheJoeFin Apr 2, 2026
213b39e
Merge pull request #76 from TheJoeFin/copilot/add-search-options-for-…
TheJoeFin Apr 2, 2026
c1bf11a
Initial plan
Copilot Apr 2, 2026
2f928e0
Add setting to swap left/right click tray icon behavior
Copilot Apr 2, 2026
5031f27
Redesign settings UI with card layout and improved styles
TheJoeFin Apr 2, 2026
02f990f
Merge pull request #77 from TheJoeFin/copilot/add-settings-to-swap-cl…
TheJoeFin Apr 2, 2026
893a78b
Update app version and NuGet packages, reformat x:Bind
TheJoeFin Apr 2, 2026
6ae73bc
Update default music settings and InfoBar button label
TheJoeFin Apr 3, 2026
5069586
Bump app version to 1.9.1.0
TheJoeFin Apr 3, 2026
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
34 changes: 30 additions & 4 deletions Trdo/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
using Trdo.Pages;
using Trdo.Services;
using Trdo.ViewModels;
using Windows.UI;
using Windows.UI.ViewManagement;
using WinUIEx;

Expand All @@ -27,7 +26,7 @@
private readonly UISettings _uiSettings = new();
private Mutex? _singleInstanceMutex;
private EventWaitHandle? _trayIconRestoreEvent;
private DispatcherQueueTimer? _trayIconWatchdogTimer;

Check warning on line 29 in Trdo/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build

The field 'App._trayIconWatchdogTimer' is never used

Check warning on line 29 in Trdo/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build

The field 'App._trayIconWatchdogTimer' is never used
private DispatcherQueueTimer? _restoreEventMonitorTimer;

/// <summary>
Expand Down Expand Up @@ -157,16 +156,36 @@

private void TrayIcon_ContextMenu(TrayIcon sender, TrayIconEventArgs args)
{
args.Flyout = CreateFlyout();
if (SettingsService.TrayClickBehavior == 1)
{
// Swapped: right click plays/pauses (fall back to flyout if no station selected)
if (_playerVm.CanPlay)
{
_playerVm.Toggle();
_ = UpdateTrayIconAsync();
return;
}
}

// Default: right click opens flyout; also fallback when no station is available
ShowFlyout(args);
}

private void TrayIcon_Selected(TrayIcon sender, TrayIconEventArgs args)
{
if (SettingsService.TrayClickBehavior == 1)
{
// Swapped: left click opens flyout
ShowFlyout(args);
return;
}

// Default: left click plays/pauses
// Check if we can play (have stations available and one selected)
if (!_playerVm.CanPlay)
{
// No stations available, show the flyout to encourage user to add a station
args.Flyout = CreateFlyout();
ShowFlyout(args);
return;
}

Expand All @@ -175,6 +194,12 @@
_ = UpdateTrayIconAsync();
}

private void ShowFlyout(TrayIconEventArgs args)
{
WindowPlacementService.CapturePointerAnchor();
args.Flyout = CreateFlyout();
}

private Flyout CreateFlyout()
{
Flyout flyout = new()
Expand All @@ -190,6 +215,7 @@

flyout.Opened += (s, e) =>
{
WindowPlacementService.CapturePointerAnchor();
// Clear the back stack when flyout opens to prevent accumulation
Services.NavigationService.Instance.ClearBackStack();
};
Expand Down Expand Up @@ -272,7 +298,7 @@
}
else if (_playerVm.IsPlaying)
{

// Include now playing info if available
if (_playerVm.HasNowPlaying)
{
Expand Down
5 changes: 5 additions & 0 deletions Trdo/Assets/apple_music.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions Trdo/Assets/discogs.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions Trdo/Assets/ytmusic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
123 changes: 123 additions & 0 deletions Trdo/Controls/ManualStationWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8" ?>
<ex:WindowEx
x:Class="Trdo.Controls.ManualStationWindow"
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 - Add Station"
Width="400"
Height="500"
IsMaximizable="False"
IsMinimizable="False"
mc:Ignorable="d">

<ex:WindowEx.SystemBackdrop>
<MicaBackdrop />
</ex:WindowEx.SystemBackdrop>

<Grid RowDefinitions="Auto,*,Auto">

<TitleBar x:Name="ModernTitlebar" Title="{x:Bind ViewModel.PageTitle, Mode=OneWay}">
<TitleBar.IconSource>
<ImageIconSource ImageSource="/Assets/Radio.ico" />
</TitleBar.IconSource>
</TitleBar>

<!-- Content Area -->
<ScrollView Grid.Row="1" VerticalScrollBarVisibility="Auto">
<StackPanel Margin="24,16,24,16" Spacing="12">

<!-- Station Name Input -->
<StackPanel Spacing="4">
<TextBlock FontWeight="SemiBold" Text="Station Name" />
<TextBox
x:Name="StationNameTextBox"
PlaceholderText="e.g., WYMS - Hometown radio"
Text="{x:Bind ViewModel.StationName,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>

<!-- Stream URL Input -->
<StackPanel Spacing="4">
<TextBlock FontWeight="SemiBold" Text="Stream URL" />
<TextBox
x:Name="StreamUrlTextBox"
PlaceholderText="e.g., https://example.com/stream"
Text="{x:Bind ViewModel.StreamUrl,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap" />
</StackPanel>

<!-- Homepage URL Input -->
<StackPanel Spacing="4">
<TextBlock FontWeight="SemiBold" Text="Homepage (Optional)" />
<TextBox
x:Name="HomepageTextBox"
PlaceholderText="e.g., https://example.com"
Text="{x:Bind ViewModel.Homepage,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap" />
</StackPanel>

<!-- Favicon URL Input -->
<StackPanel Spacing="4">
<TextBlock FontWeight="SemiBold" Text="Station Logo/Icon URL (Optional)" />
<TextBox
x:Name="FaviconUrlTextBox"
PlaceholderText="e.g., https://example.com/logo.png"
Text="{x:Bind ViewModel.FaviconUrl,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap" />
</StackPanel>

</StackPanel>
</ScrollView>

<!-- Buttons -->
<Border
Grid.Row="2"
Padding="24,12,24,16"
Background="{ThemeResource LayerFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="0,1,0,0">
<Grid ColumnSpacing="8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

<Button
Grid.Column="0"
HorizontalAlignment="Stretch"
Click="CancelButton_Click">
<StackPanel Orientation="Horizontal" Spacing="8">
<FontIcon FontSize="16" Glyph="&#xE711;" />
<TextBlock Text="Cancel" />
</StackPanel>
</Button>

<Button
Grid.Column="1"
HorizontalAlignment="Stretch"
Click="SaveButton_Click"
IsEnabled="{x:Bind ViewModel.CanSave,
Mode=OneWay}"
Style="{StaticResource AccentButtonStyle}">
<StackPanel Orientation="Horizontal" Spacing="8">
<FontIcon FontSize="16" Glyph="&#xE74E;" />
<TextBlock Text="Save" />
</StackPanel>
</Button>
</Grid>
</Border>

</Grid>

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

namespace Trdo.Controls;

/// <summary>
/// A small standalone window for manually adding or editing a radio station.
/// Opens as a pop-out window so that closing the tray flyout does not clear the form fields.
/// </summary>
public sealed partial class ManualStationWindow : WindowEx
{
public AddStationViewModel ViewModel { get; }

public ManualStationWindow()
{
InitializeComponent();

ViewModel = new AddStationViewModel();
ViewModel.SetPlayerViewModel(PlayerViewModel.Shared);

ExtendsContentIntoTitleBar = true;
SetTitleBar(ModernTitlebar);

Activated += ManualStationWindow_Activated;
}

/// <summary>
/// Opens the window pre-filled with the given station's data for editing.
/// </summary>
public void LoadStationForEdit(RadioStation station)
{
ViewModel.LoadStationForEdit(station);
}

private void ManualStationWindow_Activated(object sender, Microsoft.UI.Xaml.WindowActivatedEventArgs args)
{
// Focus the station name field once the window is ready
if (args.WindowActivationState != Microsoft.UI.Xaml.WindowActivationState.Deactivated)
{
WindowPlacementService.PositionWindowNearAnchor(this, 400, 500);
StationNameTextBox.Focus(Microsoft.UI.Xaml.FocusState.Programmatic);
Activated -= ManualStationWindow_Activated;
}
}

private void SaveButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (ViewModel.Save())
{
Close();
}
}

private void CancelButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
Close();
}
}
10 changes: 10 additions & 0 deletions Trdo/Controls/TutorialWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ public TutorialWindow()

ExtendsContentIntoTitleBar = true;
SetTitleBar(ModernTitlebar);
Activated += TutorialWindow_Activated;
}

private void TutorialWindow_Activated(object sender, Microsoft.UI.Xaml.WindowActivatedEventArgs args)
{
if (args.WindowActivationState == Microsoft.UI.Xaml.WindowActivationState.Deactivated)
return;

WindowPlacementService.PositionWindowNearAnchor(this, 400, 600);
Activated -= TutorialWindow_Activated;
}

private void Button_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
Expand Down
2 changes: 1 addition & 1 deletion Trdo/Package.appxmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<Identity
Name="40087JoeFinApps.Trdo"
Publisher="CN=153F3B0F-BA3D-4964-8098-71AC78A1DF6A"
Version="1.8.0.0" />
Version="1.9.1.0" />

<mp:PhoneIdentity PhoneProductId="fa86867b-3ba1-44b4-b776-ea2ad8aea4c7" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>

Expand Down
Loading
Loading