Replace three-button cluster with a single context-aware primary button
Button follows the user journey: 'Connect to YouTube' (not signed in) -> 'Go Live' (connected, idle) -> 'Stop Stream' (live).
This commit is contained in:
+3
-31
@@ -119,38 +119,10 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<!-- Stream Controls -->
|
<!-- Primary action: single button, adapts to state -->
|
||||||
<StackPanel Grid.Column="3" Orientation="Horizontal" VerticalAlignment="Center">
|
<StackPanel Grid.Column="3" Orientation="Horizontal" VerticalAlignment="Center">
|
||||||
|
<Button Content="{Binding PrimaryButtonText}" Style="{StaticResource YtButton}"
|
||||||
<!-- YouTube connection status light + button -->
|
Command="{Binding PrimaryCommand}"/>
|
||||||
<Border Background="#0f3460" CornerRadius="4" Padding="8,6" Margin="0,0,12,0"
|
|
||||||
VerticalAlignment="Center" ToolTip="YouTube connection status">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<Ellipse Width="10" Height="10" Margin="0,0,8,0" VerticalAlignment="Center">
|
|
||||||
<Ellipse.Style>
|
|
||||||
<Style TargetType="Ellipse">
|
|
||||||
<Setter Property="Fill" Value="#555"/>
|
|
||||||
<Style.Triggers>
|
|
||||||
<DataTrigger Binding="{Binding IsYouTubeConnected}" Value="True">
|
|
||||||
<Setter Property="Fill" Value="#00ff00"/>
|
|
||||||
</DataTrigger>
|
|
||||||
</Style.Triggers>
|
|
||||||
</Style>
|
|
||||||
</Ellipse.Style>
|
|
||||||
</Ellipse>
|
|
||||||
<Button Content="YouTube" Style="{StaticResource YtButtonSecondary}"
|
|
||||||
Background="Transparent" Padding="0"
|
|
||||||
Command="{Binding ConnectYouTubeCommand}"
|
|
||||||
ToolTip="Sign in to YouTube (optional)"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Border>
|
|
||||||
|
|
||||||
<Button Content="Go Live" Style="{StaticResource YtButton}"
|
|
||||||
Command="{Binding StartStreamCommand}"
|
|
||||||
Visibility="{Binding IsOffline, Converter={StaticResource BoolToVis}}"/>
|
|
||||||
<Button Content="Stop Stream" Style="{StaticResource YtButton}"
|
|
||||||
Background="#333" Command="{Binding StopStreamCommand}"
|
|
||||||
Visibility="{Binding IsLive, Converter={StaticResource BoolToVis}}"/>
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|||||||
+28
-10
@@ -38,6 +38,7 @@ public class MainViewModel : ViewModelBase
|
|||||||
OnPropertyChanged(nameof(IsOffline));
|
OnPropertyChanged(nameof(IsOffline));
|
||||||
OnPropertyChanged(nameof(IsLive));
|
OnPropertyChanged(nameof(IsLive));
|
||||||
OnPropertyChanged(nameof(StatusDisplay));
|
OnPropertyChanged(nameof(StatusDisplay));
|
||||||
|
OnPropertyChanged(nameof(PrimaryButtonText));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,7 +67,11 @@ public class MainViewModel : ViewModelBase
|
|||||||
public bool IsYouTubeConnected
|
public bool IsYouTubeConnected
|
||||||
{
|
{
|
||||||
get => _isYouTubeConnected;
|
get => _isYouTubeConnected;
|
||||||
set => SetProperty(ref _isYouTubeConnected, value);
|
set
|
||||||
|
{
|
||||||
|
if (SetProperty(ref _isYouTubeConnected, value))
|
||||||
|
OnPropertyChanged(nameof(PrimaryButtonText));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string StatusDisplay => StreamStatus switch
|
public string StatusDisplay => StreamStatus switch
|
||||||
@@ -78,12 +83,20 @@ public class MainViewModel : ViewModelBase
|
|||||||
_ => "UNKNOWN"
|
_ => "UNKNOWN"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Single, context-aware primary button. Follows the user's journey:
|
||||||
|
/// not connected → connect, connected+idle → go live, live → stop.
|
||||||
|
/// </summary>
|
||||||
|
public string PrimaryButtonText => !IsYouTubeConnected
|
||||||
|
? "Connect to YouTube"
|
||||||
|
: IsLive
|
||||||
|
? "Stop Stream"
|
||||||
|
: "Go Live";
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
public ICommand AddSceneCommand { get; }
|
public ICommand AddSceneCommand { get; }
|
||||||
public ICommand RemoveSceneCommand { get; }
|
public ICommand RemoveSceneCommand { get; }
|
||||||
public ICommand StartStreamCommand { get; }
|
public ICommand PrimaryCommand { get; }
|
||||||
public ICommand StopStreamCommand { get; }
|
|
||||||
public ICommand ConnectYouTubeCommand { get; }
|
|
||||||
|
|
||||||
public MainViewModel()
|
public MainViewModel()
|
||||||
{
|
{
|
||||||
@@ -95,9 +108,7 @@ public class MainViewModel : ViewModelBase
|
|||||||
|
|
||||||
AddSceneCommand = new RelayCommand(_ => AddScene());
|
AddSceneCommand = new RelayCommand(_ => AddScene());
|
||||||
RemoveSceneCommand = new RelayCommand(scene => RemoveScene(scene as Scene));
|
RemoveSceneCommand = new RelayCommand(scene => RemoveScene(scene as Scene));
|
||||||
StartStreamCommand = new RelayCommand(_ => StartStream(), _ => StreamStatus == StreamStatus.Offline);
|
PrimaryCommand = new RelayCommand(_ => PrimaryAction());
|
||||||
StopStreamCommand = new RelayCommand(_ => StopStream(), _ => StreamStatus == StreamStatus.Streaming);
|
|
||||||
ConnectYouTubeCommand = new RelayCommand(_ => ConnectYouTube());
|
|
||||||
|
|
||||||
// Start with a default scene
|
// Start with a default scene
|
||||||
AddScene("Scene 1");
|
AddScene("Scene 1");
|
||||||
@@ -131,19 +142,16 @@ public class MainViewModel : ViewModelBase
|
|||||||
private async void StartStream()
|
private async void StartStream()
|
||||||
{
|
{
|
||||||
StreamStatus = StreamStatus.Connecting;
|
StreamStatus = StreamStatus.Connecting;
|
||||||
OnPropertyChanged(nameof(StatusDisplay));
|
|
||||||
|
|
||||||
// TODO: Initialize capture pipeline, encode, and push to RTMP
|
// TODO: Initialize capture pipeline, encode, and push to RTMP
|
||||||
// For now, simulate connection
|
// For now, simulate connection
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
StreamStatus = StreamStatus.Streaming;
|
StreamStatus = StreamStatus.Streaming;
|
||||||
OnPropertyChanged(nameof(StatusDisplay));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StopStream()
|
private void StopStream()
|
||||||
{
|
{
|
||||||
StreamStatus = StreamStatus.Offline;
|
StreamStatus = StreamStatus.Offline;
|
||||||
OnPropertyChanged(nameof(StatusDisplay));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConnectYouTube()
|
private void ConnectYouTube()
|
||||||
@@ -152,4 +160,14 @@ public class MainViewModel : ViewModelBase
|
|||||||
// For now, this is a stub
|
// For now, this is a stub
|
||||||
IsYouTubeConnected = false;
|
IsYouTubeConnected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void PrimaryAction()
|
||||||
|
{
|
||||||
|
if (!IsYouTubeConnected)
|
||||||
|
ConnectYouTube();
|
||||||
|
else if (IsLive)
|
||||||
|
StopStream();
|
||||||
|
else
|
||||||
|
StartStream();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user