feat: Implement Playlists and Programs Management
- Added PlaylistsGroupViewModel to manage playlists and selection. - Introduced ProgramsGroupViewModel for handling program groups and subscriptions. - Created ProgramsListViewModel to manage individual program listings. - Developed SettingsViewModel for user settings including playlist management. - Implemented TVPlayerViewModel as the main view model coordinating screens and data. - Added PlayerView for video playback with LibVLC integration. - Created XAML views for PlaylistsGroup, ProgramsGroup, ProgramsList, and Settings. - Added sample M3U playlist for testing. - Documented WPF build instructions and project structure in WPF-BUILD.md. - Configured global.json for .NET SDK versioning.
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace TV_Player.AvaloniaApp.ViewModels;
|
||||
|
||||
public class MainWindowViewModel : TV_Player.ObservableViewModelBase
|
||||
{
|
||||
private object? _currentViewModel;
|
||||
public object? CurrentViewModel
|
||||
{
|
||||
get => _currentViewModel;
|
||||
set => SetProperty(ref _currentViewModel, value);
|
||||
}
|
||||
|
||||
private bool _isTopPanelVisible;
|
||||
public bool IsTopPanelVisible
|
||||
{
|
||||
get => _isTopPanelVisible;
|
||||
set => SetProperty(ref _isTopPanelVisible, value);
|
||||
}
|
||||
|
||||
private string _topPanelTitle = string.Empty;
|
||||
public string TopPanelTitle
|
||||
{
|
||||
get => _topPanelTitle;
|
||||
set => SetProperty(ref _topPanelTitle, value);
|
||||
}
|
||||
|
||||
private WindowState _currentWindowState = WindowState.Normal;
|
||||
public WindowState CurrentWindowState
|
||||
{
|
||||
get => _currentWindowState;
|
||||
set => SetProperty(ref _currentWindowState, value);
|
||||
}
|
||||
|
||||
public ICommand FullscreenCommand { get; }
|
||||
public ICommand CloseAppCommand { get; }
|
||||
public ICommand BackCommand { get; }
|
||||
public ICommand SettingsCommand { get; }
|
||||
|
||||
public Action? ButtonBackAction { get; set; }
|
||||
|
||||
public MainWindowViewModel()
|
||||
{
|
||||
BackCommand = new RelayCommand(TriggerBack);
|
||||
FullscreenCommand = new RelayCommand(OnFullScreenButtonClick);
|
||||
SettingsCommand = new RelayCommand(OnSettingsButtonClick);
|
||||
CloseAppCommand = new RelayCommand(OnCloseAppButtonClick);
|
||||
}
|
||||
|
||||
public void OnFullScreenButtonClick()
|
||||
{
|
||||
CurrentWindowState = CurrentWindowState == WindowState.FullScreen
|
||||
? WindowState.Normal
|
||||
: WindowState.FullScreen;
|
||||
}
|
||||
|
||||
public void OnCloseAppButtonClick()
|
||||
{
|
||||
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
desktop.Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSettingsButtonClick()
|
||||
{
|
||||
TVPlayerViewModel.Instance.ShowSettingsScreen();
|
||||
}
|
||||
|
||||
public void TriggerBack()
|
||||
{
|
||||
ButtonBackAction?.Invoke();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System.Diagnostics;
|
||||
using System.Reactive.Linq;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace TV_Player.AvaloniaApp.ViewModels;
|
||||
|
||||
public class PlayerViewModel : TV_Player.ObservableViewModelBase, IDisposable
|
||||
{
|
||||
private readonly IDisposable _programSubscription;
|
||||
private IDisposable? _programGuideDisposable;
|
||||
private IDisposable? _timer;
|
||||
private M3UInfo _currentProgram;
|
||||
private List<M3UInfo> _programs = new();
|
||||
private ProgramGuide? _currentGuide;
|
||||
private ProgramInfo? _currentProgramInfo;
|
||||
private int _currentProgramIndex;
|
||||
|
||||
public ICommand BackCommand { get; }
|
||||
public ICommand FullscreenCommand { get; }
|
||||
public ICommand NextCommand { get; }
|
||||
public ICommand PreviousCommand { get; }
|
||||
public ICommand ShowProgramListCommand { get; }
|
||||
public ICommand CloseAppCommand { get; }
|
||||
public ICommand OpenStreamCommand { get; }
|
||||
|
||||
private string _topPanelTitle = string.Empty;
|
||||
public string TopPanelTitle
|
||||
{
|
||||
get => _topPanelTitle;
|
||||
set => SetProperty(ref _topPanelTitle, value);
|
||||
}
|
||||
|
||||
private string _programGuideText = string.Empty;
|
||||
public string ProgramGuideText
|
||||
{
|
||||
get => _programGuideText;
|
||||
set => SetProperty(ref _programGuideText, value);
|
||||
}
|
||||
|
||||
private string _startProgram = string.Empty;
|
||||
public string StartProgram
|
||||
{
|
||||
get => _startProgram;
|
||||
set => SetProperty(ref _startProgram, value);
|
||||
}
|
||||
|
||||
private string _endProgram = string.Empty;
|
||||
public string EndProgram
|
||||
{
|
||||
get => _endProgram;
|
||||
set => SetProperty(ref _endProgram, value);
|
||||
}
|
||||
|
||||
private int _durationValue;
|
||||
public int DurationValue
|
||||
{
|
||||
get => _durationValue;
|
||||
set => SetProperty(ref _durationValue, value);
|
||||
}
|
||||
|
||||
private bool _isProgramInfoVisible;
|
||||
public bool IsProgramInfoVisible
|
||||
{
|
||||
get => _isProgramInfoVisible;
|
||||
set => SetProperty(ref _isProgramInfoVisible, value);
|
||||
}
|
||||
|
||||
private bool _programGuideVisible;
|
||||
public bool ProgramGuideVisible
|
||||
{
|
||||
get => _programGuideVisible;
|
||||
set => SetProperty(ref _programGuideVisible, value);
|
||||
}
|
||||
|
||||
private string _streamUrl = string.Empty;
|
||||
public string StreamUrl
|
||||
{
|
||||
get => _streamUrl;
|
||||
set => SetProperty(ref _streamUrl, value);
|
||||
}
|
||||
|
||||
private string _playbackStatus = "Buffering stream...";
|
||||
public string PlaybackStatus
|
||||
{
|
||||
get => _playbackStatus;
|
||||
set => SetProperty(ref _playbackStatus, value);
|
||||
}
|
||||
|
||||
private bool _hasPlaybackStatus = true;
|
||||
public bool HasPlaybackStatus
|
||||
{
|
||||
get => _hasPlaybackStatus;
|
||||
set => SetProperty(ref _hasPlaybackStatus, value);
|
||||
}
|
||||
|
||||
private List<ProgramInfo> _programItems = new();
|
||||
public List<ProgramInfo> Programs
|
||||
{
|
||||
get => _programItems;
|
||||
set => SetProperty(ref _programItems, value);
|
||||
}
|
||||
|
||||
public PlayerViewModel(M3UInfo selectedProgram)
|
||||
{
|
||||
_currentProgram = selectedProgram;
|
||||
BackCommand = new RelayCommand(OnButtonBackClick);
|
||||
NextCommand = new RelayCommand(NextProgram);
|
||||
PreviousCommand = new RelayCommand(PreviousProgram);
|
||||
FullscreenCommand = new RelayCommand(TVPlayerViewModel.Instance.FullScreenToggle);
|
||||
CloseAppCommand = new RelayCommand(TVPlayerViewModel.Instance.CloseAppCommand);
|
||||
ShowProgramListCommand = new RelayCommand(ShowProgramList);
|
||||
OpenStreamCommand = new RelayCommand(OpenStreamExternally);
|
||||
|
||||
_programSubscription = TVPlayerViewModel.Instance.CurrentProgramsData!
|
||||
.AllPrograms
|
||||
.Subscribe(programs =>
|
||||
{
|
||||
_programs = programs.Where(p => p.GroupTitle == _currentProgram.GroupTitle).ToList();
|
||||
_currentProgramIndex = _programs.FindIndex(p => p.Name == _currentProgram.Name);
|
||||
if (_currentProgramIndex < 0)
|
||||
_currentProgramIndex = 0;
|
||||
});
|
||||
|
||||
UpdateUi();
|
||||
}
|
||||
|
||||
public void SetPlaybackStatus(string status)
|
||||
{
|
||||
PlaybackStatus = status;
|
||||
HasPlaybackStatus = !string.IsNullOrWhiteSpace(status);
|
||||
}
|
||||
|
||||
private void UpdateUi()
|
||||
{
|
||||
TVPlayerViewModel.Instance.TopPanelVisible(false, _currentProgram.Name);
|
||||
TopPanelTitle = _currentProgram.Name;
|
||||
StreamUrl = _currentProgram.Url;
|
||||
SetPlaybackStatus(string.IsNullOrWhiteSpace(StreamUrl)
|
||||
? "No stream URL available for this channel."
|
||||
: "Buffering stream...");
|
||||
ProgramGuideVisible = false;
|
||||
|
||||
_programGuideDisposable?.Dispose();
|
||||
_timer?.Dispose();
|
||||
|
||||
_programGuideDisposable = TVPlayerViewModel.Instance.CurrentProgramsData!
|
||||
.ProgramGuideInfo
|
||||
.Subscribe(async _ =>
|
||||
{
|
||||
try
|
||||
{
|
||||
_currentGuide = await TVPlayerViewModel.Instance.CurrentProgramsData.GetGuideByProgram(_currentProgram.TvgID);
|
||||
UpdateScreenInfo();
|
||||
_timer = Observable.Interval(TimeSpan.FromMinutes(1)).Subscribe(_ => UpdateScreenInfo());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"Failed to load program guide: {ex.Message}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void PreviousProgram()
|
||||
{
|
||||
if (_programs.Count == 0)
|
||||
return;
|
||||
|
||||
_currentProgramIndex = (_currentProgramIndex - 1 + _programs.Count) % _programs.Count;
|
||||
_currentProgram = _programs[_currentProgramIndex];
|
||||
UpdateUi();
|
||||
}
|
||||
|
||||
private void NextProgram()
|
||||
{
|
||||
if (_programs.Count == 0)
|
||||
return;
|
||||
|
||||
_currentProgramIndex = (_currentProgramIndex + 1) % _programs.Count;
|
||||
_currentProgram = _programs[_currentProgramIndex];
|
||||
UpdateUi();
|
||||
}
|
||||
|
||||
private void ShowProgramList()
|
||||
{
|
||||
ProgramGuideVisible = !ProgramGuideVisible;
|
||||
}
|
||||
|
||||
private void OpenStreamExternally()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(StreamUrl))
|
||||
return;
|
||||
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = StreamUrl,
|
||||
UseShellExecute = true
|
||||
});
|
||||
}
|
||||
|
||||
private void UpdateScreenInfo()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_currentGuide?.Programs == null || _currentGuide.Programs.Count == 0)
|
||||
{
|
||||
IsProgramInfoVisible = false;
|
||||
Programs = new List<ProgramInfo>();
|
||||
return;
|
||||
}
|
||||
|
||||
_currentProgramInfo = _currentGuide.Programs
|
||||
.FirstOrDefault(item => item.StartTime <= DateTime.Now && item.EndTime >= DateTime.Now);
|
||||
|
||||
if (_currentProgramInfo == null)
|
||||
{
|
||||
IsProgramInfoVisible = false;
|
||||
Programs = _currentGuide.Programs.Take(7).ToList();
|
||||
return;
|
||||
}
|
||||
|
||||
var currentIndex = _currentGuide.Programs.FindIndex(x => x.Title == _currentProgramInfo.Title);
|
||||
Programs = _currentGuide.Programs.Skip(Math.Max(currentIndex, 0)).Take(7).ToList();
|
||||
|
||||
IsProgramInfoVisible = true;
|
||||
ProgramGuideText = _currentProgramInfo.Title;
|
||||
StartProgram = _currentProgramInfo.StartTime.ToShortTimeString();
|
||||
EndProgram = _currentProgramInfo.EndTime.ToShortTimeString();
|
||||
|
||||
var totalMinutes = (_currentProgramInfo.EndTime - _currentProgramInfo.StartTime).TotalMinutes;
|
||||
DurationValue = totalMinutes <= 0
|
||||
? 0
|
||||
: (int)((DateTime.Now - _currentProgramInfo.StartTime).TotalMinutes / totalMinutes * 100);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"Failed to update screen info: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnButtonBackClick()
|
||||
{
|
||||
TVPlayerViewModel.Instance.ShowProgramsListScreen(new GroupInfo
|
||||
{
|
||||
Name = _currentProgram.GroupTitle,
|
||||
Count = 0
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_programSubscription.Dispose();
|
||||
_programGuideDisposable?.Dispose();
|
||||
_timer?.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace TV_Player.AvaloniaApp.ViewModels;
|
||||
|
||||
public class PlaylistsGroupViewModel : TV_Player.ObservableViewModelBase
|
||||
{
|
||||
private List<GroupInfo> _programs = new();
|
||||
public List<GroupInfo> Programs
|
||||
{
|
||||
get => _programs;
|
||||
set => SetProperty(ref _programs, value);
|
||||
}
|
||||
|
||||
public ICommand SelectPlaylistCommand { get; }
|
||||
|
||||
public PlaylistsGroupViewModel()
|
||||
{
|
||||
SelectPlaylistCommand = new RelayCommand<GroupInfo>(OnItemSelected);
|
||||
Programs = TVPlayerViewModel.Instance.PlayListsData
|
||||
.Select(x => new GroupInfo { Name = x.Key, Count = 0 })
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private void OnItemSelected(GroupInfo? group)
|
||||
{
|
||||
if (group == null)
|
||||
return;
|
||||
|
||||
TVPlayerViewModel.Instance.ShowProgramsGroupScreen(group.Name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System.Windows.Input;
|
||||
using TV_Player.ViewModels;
|
||||
|
||||
namespace TV_Player.AvaloniaApp.ViewModels;
|
||||
|
||||
public class ProgramsGroupViewModel : TV_Player.ObservableViewModelBase, IDisposable
|
||||
{
|
||||
private List<GroupInfo> _programs = new();
|
||||
private readonly IDisposable _groupInformationSubscriber;
|
||||
|
||||
public List<GroupInfo> Programs
|
||||
{
|
||||
get => _programs;
|
||||
set => SetProperty(ref _programs, value);
|
||||
}
|
||||
|
||||
public ICommand SelectGroupCommand { get; }
|
||||
|
||||
public ProgramsGroupViewModel()
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("[ProgramsGroupViewModel] Initializing...");
|
||||
SelectGroupCommand = new RelayCommand<GroupInfo>(OnItemSelected);
|
||||
if (TVPlayerViewModel.Instance.CurrentProgramsData == null)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("[ProgramsGroupViewModel] ERROR: CurrentProgramsData is null!");
|
||||
Programs = new List<GroupInfo>();
|
||||
return;
|
||||
}
|
||||
|
||||
_groupInformationSubscriber = TVPlayerViewModel.Instance.CurrentProgramsData
|
||||
.GroupsInformation
|
||||
.Subscribe(groups =>
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"[ProgramsGroupViewModel.Subscribe] Received {groups.Count} groups from observable");
|
||||
// Filter hidden groups but keep all others (including "undefined")
|
||||
var filteredGroups = SettingsModel.HiddenGroups == null
|
||||
? groups
|
||||
: groups.Where(g => !SettingsModel.HiddenGroups.Contains(g.Name.ToLowerInvariant())).ToList();
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"[ProgramsGroupViewModel] Groups after filter: {string.Join(", ", filteredGroups.Select(g => $"{g.Name}({g.Count})"))}");
|
||||
Programs = filteredGroups;
|
||||
});
|
||||
}
|
||||
|
||||
private void OnItemSelected(GroupInfo? group)
|
||||
{
|
||||
if (group == null)
|
||||
return;
|
||||
|
||||
TVPlayerViewModel.Instance.ShowProgramsListScreen(group);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_groupInformationSubscriber.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows.Input;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Avalonia.Threading;
|
||||
|
||||
namespace TV_Player.AvaloniaApp.ViewModels;
|
||||
|
||||
public class ProgramsListViewModel : TV_Player.ObservableViewModelBase, IDisposable
|
||||
{
|
||||
private readonly IDisposable _programSubscription;
|
||||
private ObservableCollection<M3UInfo> _programs = new();
|
||||
|
||||
public ObservableCollection<M3UInfo> Programs
|
||||
{
|
||||
get => _programs;
|
||||
set => SetProperty(ref _programs, value);
|
||||
}
|
||||
|
||||
public ICommand SelectProgramCommand { get; }
|
||||
|
||||
public ProgramsListViewModel(GroupInfo groupInfo)
|
||||
{
|
||||
SelectProgramCommand = new RelayCommand<M3UInfo>(OnItemSelected);
|
||||
_programSubscription = TVPlayerViewModel.Instance.CurrentProgramsData!
|
||||
.AllPrograms
|
||||
.Subscribe(newPrograms =>
|
||||
{
|
||||
var filteredPrograms = newPrograms
|
||||
.Where(p => p.GroupTitle == groupInfo.Name && !string.IsNullOrWhiteSpace(p.Url))
|
||||
.ToList();
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
Programs = new ObservableCollection<M3UInfo>(filteredPrograms);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void OnItemSelected(M3UInfo? program)
|
||||
{
|
||||
if (program == null)
|
||||
return;
|
||||
|
||||
TVPlayerViewModel.Instance.ShowPlayerScreen(program);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_programSubscription.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows.Input;
|
||||
using TV_Player.ViewModels;
|
||||
|
||||
namespace TV_Player.AvaloniaApp.ViewModels;
|
||||
|
||||
public class SettingsViewModel : TV_Player.ObservableViewModelBase
|
||||
{
|
||||
private string _playlistName = string.Empty;
|
||||
public string PlaylistName
|
||||
{
|
||||
get => _playlistName;
|
||||
set => SetProperty(ref _playlistName, value);
|
||||
}
|
||||
|
||||
private string _playlistUrl = string.Empty;
|
||||
public string PlaylistURL
|
||||
{
|
||||
get => _playlistUrl;
|
||||
set => SetProperty(ref _playlistUrl, value);
|
||||
}
|
||||
|
||||
private ObservableCollection<KeyValuePair<string, string>> _playlists = new();
|
||||
public ObservableCollection<KeyValuePair<string, string>> Playlists
|
||||
{
|
||||
get => _playlists;
|
||||
set => SetProperty(ref _playlists, value);
|
||||
}
|
||||
|
||||
private bool _startFullScreen;
|
||||
public bool StartFullScreen
|
||||
{
|
||||
get => _startFullScreen;
|
||||
set => SetProperty(ref _startFullScreen, value);
|
||||
}
|
||||
|
||||
private bool _startLastScreen;
|
||||
public bool StartLastScreen
|
||||
{
|
||||
get => _startLastScreen;
|
||||
set => SetProperty(ref _startLastScreen, value);
|
||||
}
|
||||
|
||||
public ICommand SaveCommand { get; }
|
||||
public ICommand PlaylistDeleteCommand { get; }
|
||||
public ICommand BackCommand { get; }
|
||||
public ICommand AddPlaylistCommand { get; }
|
||||
|
||||
public SettingsViewModel()
|
||||
{
|
||||
SaveCommand = new RelayCommand(OnSaveSettings);
|
||||
BackCommand = new RelayCommand(OnBackCommand);
|
||||
AddPlaylistCommand = new RelayCommand(OnAddPlaylistCommand);
|
||||
PlaylistDeleteCommand = new RelayCommand<KeyValuePair<string, string>>(OnPlaylistDeleteCommand);
|
||||
|
||||
StartFullScreen = SettingsModel.StartFullScreen;
|
||||
StartLastScreen = SettingsModel.StartFromLastScreen;
|
||||
Playlists = SettingsModel.Playlists == null
|
||||
? new ObservableCollection<KeyValuePair<string, string>>()
|
||||
: new ObservableCollection<KeyValuePair<string, string>>(SettingsModel.Playlists);
|
||||
}
|
||||
|
||||
private void OnAddPlaylistCommand()
|
||||
{
|
||||
var url = PlaylistURL?.Trim();
|
||||
var name = PlaylistName?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(url))
|
||||
return;
|
||||
|
||||
if (!Uri.TryCreate(url, UriKind.Absolute, out var uriResult) ||
|
||||
(uriResult.Scheme != Uri.UriSchemeHttp && uriResult.Scheme != Uri.UriSchemeHttps))
|
||||
return;
|
||||
|
||||
if (Playlists.Any(pair => pair.Key.Equals(name, StringComparison.OrdinalIgnoreCase)))
|
||||
return;
|
||||
|
||||
Playlists.Add(new KeyValuePair<string, string>(name, url));
|
||||
PlaylistName = string.Empty;
|
||||
PlaylistURL = string.Empty;
|
||||
}
|
||||
|
||||
private void OnPlaylistDeleteCommand(KeyValuePair<string, string> pair)
|
||||
{
|
||||
Playlists.Remove(pair);
|
||||
}
|
||||
|
||||
private void OnBackCommand()
|
||||
{
|
||||
TVPlayerViewModel.Instance.SelectScreen();
|
||||
}
|
||||
|
||||
private void OnSaveSettings()
|
||||
{
|
||||
SettingsModel.StartFullScreen = StartFullScreen;
|
||||
SettingsModel.StartFromLastScreen = StartLastScreen;
|
||||
SettingsModel.Playlists = Playlists.ToDictionary(pair => pair.Key, pair => pair.Value);
|
||||
SettingsModel.SaveSetttings();
|
||||
TVPlayerViewModel.Instance.InitializeTVWithData();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
using TV_Player.ViewModels;
|
||||
|
||||
namespace TV_Player.AvaloniaApp.ViewModels;
|
||||
|
||||
public class TVPlayerViewModel : IDisposable
|
||||
{
|
||||
private static readonly Lazy<TVPlayerViewModel> LazyInstance = new(() => new TVPlayerViewModel());
|
||||
public static TVPlayerViewModel Instance => LazyInstance.Value;
|
||||
|
||||
private readonly MainWindowViewModel _mainWindowViewModel;
|
||||
|
||||
public MainWindowViewModel MainWindowViewModel => _mainWindowViewModel;
|
||||
public ProgramsData? CurrentProgramsData { get; private set; }
|
||||
public Dictionary<string, ProgramsData> PlayListsData { get; } = new();
|
||||
public string? CurrentPlaylistName { get; private set; }
|
||||
|
||||
private TVPlayerViewModel()
|
||||
{
|
||||
_mainWindowViewModel = new MainWindowViewModel();
|
||||
SettingsModel.LoadSettings();
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
InitializeTVWithData();
|
||||
}
|
||||
|
||||
public void InitializeTVWithData()
|
||||
{
|
||||
if (SettingsModel.Playlists is { Count: > 0 })
|
||||
{
|
||||
PlayListsData.Clear();
|
||||
foreach (var playlist in SettingsModel.Playlists)
|
||||
{
|
||||
PlayListsData[playlist.Key] = new ProgramsData(playlist.Key, playlist.Value);
|
||||
}
|
||||
|
||||
if (SettingsModel.StartFullScreen)
|
||||
{
|
||||
FullScreenToggle();
|
||||
}
|
||||
|
||||
if (SettingsModel.StartFromLastScreen)
|
||||
{
|
||||
SelectScreen();
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowPlaylistsGroupScreen();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowSettingsScreen();
|
||||
}
|
||||
}
|
||||
|
||||
public void SelectScreen()
|
||||
{
|
||||
switch (SettingsModel.LastScreen)
|
||||
{
|
||||
case nameof(ProgramsListViewModel):
|
||||
if (SettingsModel.Group != null)
|
||||
ShowProgramsListScreen(SettingsModel.Group);
|
||||
else
|
||||
ShowPlaylistsGroupScreen();
|
||||
break;
|
||||
case nameof(PlayerViewModel):
|
||||
if (SettingsModel.Program != null)
|
||||
ShowPlayerScreen(SettingsModel.Program);
|
||||
else
|
||||
ShowPlaylistsGroupScreen();
|
||||
break;
|
||||
default:
|
||||
ShowPlaylistsGroupScreen();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowPlaylistsGroupScreen()
|
||||
{
|
||||
SettingsModel.LastScreen = nameof(ProgramsGroupViewModel);
|
||||
TopPanelVisible(true, "Playlists");
|
||||
SetPageContext(new PlaylistsGroupViewModel());
|
||||
}
|
||||
|
||||
public void ShowProgramsGroupScreen(string playlistName)
|
||||
{
|
||||
var selectedData = PlayListsData.First(x => x.Key == playlistName);
|
||||
CurrentPlaylistName = selectedData.Key;
|
||||
CurrentProgramsData = selectedData.Value;
|
||||
|
||||
SettingsModel.LastScreen = nameof(ProgramsGroupViewModel);
|
||||
TopPanelVisible(true, "Groups");
|
||||
SetBackButtonAction(ShowPlaylistsGroupScreen);
|
||||
SetPageContext(new ProgramsGroupViewModel());
|
||||
}
|
||||
|
||||
public void ShowProgramsListScreen(GroupInfo group)
|
||||
{
|
||||
if (CurrentPlaylistName == null)
|
||||
return;
|
||||
|
||||
SettingsModel.Group = group;
|
||||
SettingsModel.LastScreen = nameof(ProgramsListViewModel);
|
||||
TopPanelVisible(true, group.Name);
|
||||
SetBackButtonAction(() => ShowProgramsGroupScreen(CurrentPlaylistName));
|
||||
SetPageContext(new ProgramsListViewModel(group));
|
||||
}
|
||||
|
||||
public void ShowPlayerScreen(M3UInfo program)
|
||||
{
|
||||
SettingsModel.Program = program;
|
||||
SettingsModel.LastScreen = nameof(PlayerViewModel);
|
||||
SetPageContext(new PlayerViewModel(program));
|
||||
}
|
||||
|
||||
public void ShowSettingsScreen()
|
||||
{
|
||||
TopPanelVisible(false, string.Empty);
|
||||
SetPageContext(new SettingsViewModel());
|
||||
}
|
||||
|
||||
public void TopPanelVisible(bool value, string title)
|
||||
{
|
||||
_mainWindowViewModel.IsTopPanelVisible = value;
|
||||
_mainWindowViewModel.TopPanelTitle = title;
|
||||
}
|
||||
|
||||
public void FullScreenToggle()
|
||||
{
|
||||
_mainWindowViewModel.OnFullScreenButtonClick();
|
||||
}
|
||||
|
||||
public void CloseAppCommand()
|
||||
{
|
||||
_mainWindowViewModel.OnCloseAppButtonClick();
|
||||
}
|
||||
|
||||
public void SetBackButtonAction(Action action)
|
||||
{
|
||||
_mainWindowViewModel.ButtonBackAction = action;
|
||||
}
|
||||
|
||||
private void SetPageContext(object viewModel)
|
||||
{
|
||||
if (_mainWindowViewModel.CurrentViewModel is IDisposable disposable)
|
||||
disposable.Dispose();
|
||||
|
||||
_mainWindowViewModel.CurrentViewModel = viewModel;
|
||||
SettingsModel.SaveSetttings();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_mainWindowViewModel.CurrentViewModel is IDisposable disposable)
|
||||
disposable.Dispose();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user