add settings screen
get playlist from settings, in first run - open Settings
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
namespace TV_Player
|
||||
{
|
||||
[Serializable]
|
||||
public class GroupInfo
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Channels;
|
||||
using System.Xml;
|
||||
|
||||
namespace TV_Player
|
||||
@@ -28,7 +27,6 @@ namespace TV_Player
|
||||
public static class M3UParser
|
||||
{
|
||||
|
||||
|
||||
public static async Task<List<ProgramGuide>> DownloadGuideFromWebAsync(string url)
|
||||
{
|
||||
List<ProgramGuide> epgChannels = new List<ProgramGuide>(); ;
|
||||
@@ -46,7 +44,6 @@ namespace TV_Player
|
||||
return epgChannels;
|
||||
}
|
||||
|
||||
|
||||
private static List<ProgramGuide> ParseEpg(string epgData)
|
||||
{
|
||||
List<ProgramGuide> epgChannels = new List<ProgramGuide>();
|
||||
@@ -75,14 +72,14 @@ namespace TV_Player
|
||||
{
|
||||
ProgramInfo program = new ProgramInfo();
|
||||
|
||||
var id=reader.GetAttribute("channel");
|
||||
var id = reader.GetAttribute("channel");
|
||||
var channel = epgChannels.FirstOrDefault(x => x.Id == id);
|
||||
program.StartTime = DateTime.ParseExact(reader.GetAttribute("start"), "yyyyMMddHHmmss zzz", null);
|
||||
program.StopTime = DateTime.ParseExact(reader.GetAttribute("stop"), "yyyyMMddHHmmss zzz", null);
|
||||
|
||||
reader.Read();
|
||||
program.Title = reader.ReadElementContentAsString();
|
||||
|
||||
|
||||
|
||||
channel.Programs.Add(program);
|
||||
}
|
||||
@@ -92,132 +89,126 @@ namespace TV_Player
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
//using (XmlReader reader = XmlReader.Create(new System.IO.StringReader(epgData)))
|
||||
//{
|
||||
// ProgramGuide currentChannel = null;
|
||||
// XmlDocument doc = new XmlDocument();
|
||||
// doc.LoadXml(epgData);
|
||||
|
||||
// XmlNodeList channelNodes = doc.SelectNodes("//channel");
|
||||
|
||||
// foreach (XmlNode channelNode in channelNodes)
|
||||
// {
|
||||
// ProgramGuide channel = new ProgramGuide();
|
||||
// channel.Id = channelNode.Attributes["id"].Value;
|
||||
// channel.DisplayName = channelNode.SelectSingleNode("display-name").InnerText;
|
||||
|
||||
// XmlNodeList programNodes = doc.SelectNodes($"//programme[@channel='{channel.Id}']");
|
||||
// foreach (XmlNode programNode in programNodes)
|
||||
// {
|
||||
// ProgramInfo program = new ProgramInfo();
|
||||
// program.Title = programNode.SelectSingleNode("title").InnerText;
|
||||
// program.StartTime = DateTime.ParseExact(programNode.Attributes["start"].Value, "yyyyMMddHHmmss zzz", null);
|
||||
// program.StopTime = DateTime.ParseExact(programNode.Attributes["stop"].Value, "yyyyMMddHHmmss zzz", null);
|
||||
|
||||
// channel.Programs.Add(program);
|
||||
// }
|
||||
|
||||
// epgChannels.Add(channel);
|
||||
// }
|
||||
//}
|
||||
|
||||
return epgChannels;
|
||||
}
|
||||
|
||||
|
||||
public static async Task<List<M3UInfo>> DownloadM3UFromWebAsync(string url)
|
||||
{
|
||||
List<M3UInfo> playlistItems = new List<M3UInfo>();
|
||||
|
||||
using (var client = new HttpClient())
|
||||
using (var request = new HttpRequestMessage())
|
||||
private static async Task<string> ReadFile(string url)
|
||||
{
|
||||
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/text"));
|
||||
request.Method = HttpMethod.Get;
|
||||
request.RequestUri = new Uri(url);
|
||||
var response = await client.GetAsync(url);
|
||||
response.EnsureSuccessStatusCode();
|
||||
string responseBody = await response.Content.ReadAsStringAsync();
|
||||
|
||||
// Parse M3U content
|
||||
playlistItems = ParseM3UFromString(responseBody);
|
||||
}
|
||||
return playlistItems;
|
||||
}
|
||||
|
||||
static string[] SplitStringBeforeSeparator(string input, string separator)
|
||||
{
|
||||
string[] parts = input.Split(separator);
|
||||
|
||||
// Reconstruct the string until the separator is reached
|
||||
int separatorIndex = input.IndexOf(separator);
|
||||
if (separatorIndex != -1)
|
||||
{
|
||||
parts[0] = input.Substring(0, separatorIndex + 1);
|
||||
for (int i = 1; i < parts.Length; i++)
|
||||
string responseBody;
|
||||
using (var client = new HttpClient())
|
||||
using (var request = new HttpRequestMessage())
|
||||
{
|
||||
parts[i] = separator + parts[i];
|
||||
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/text"));
|
||||
request.Method = HttpMethod.Get;
|
||||
request.RequestUri = new Uri(url);
|
||||
var response = await client.GetAsync(url);
|
||||
response.EnsureSuccessStatusCode();
|
||||
responseBody = await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
return responseBody;
|
||||
}
|
||||
|
||||
return parts;
|
||||
}
|
||||
|
||||
static List<M3UInfo> ParseM3UFromString(string content)
|
||||
{
|
||||
List<M3UInfo> playlistItems = new List<M3UInfo>();
|
||||
|
||||
try
|
||||
public static async Task<(List<M3UInfo> programList, string programGuide)> DownloadM3UFromWebAsync(string url)
|
||||
{
|
||||
var m3u = SplitStringBeforeSeparator(content, "#EXT");
|
||||
var fileData=await ReadFile(url);
|
||||
// Parse M3U content
|
||||
return ParseM3UFromString(fileData);
|
||||
}
|
||||
private static string[] SplitStringBeforeSeparator(string input, string separator)
|
||||
{
|
||||
string[] parts = input.Split(separator);
|
||||
|
||||
foreach (var line in m3u)
|
||||
// Reconstruct the string until the separator is reached
|
||||
int separatorIndex = input.IndexOf(separator);
|
||||
if (separatorIndex != -1)
|
||||
{
|
||||
if (line.StartsWith("#EXTINF:"))
|
||||
parts[0] = input.Substring(0, separatorIndex + 1);
|
||||
for (int i = 1; i < parts.Length; i++)
|
||||
{
|
||||
if (TryParseM3ULine(line, out var m3uInfo))
|
||||
parts[i] = separator + parts[i];
|
||||
}
|
||||
}
|
||||
|
||||
return parts;
|
||||
}
|
||||
|
||||
private static (List<M3UInfo> programList, string programGuide) ParseM3UFromString(string content)
|
||||
{
|
||||
List<M3UInfo> playlistItems = new List<M3UInfo>();
|
||||
string programGuideLink = string.Empty;
|
||||
try
|
||||
{
|
||||
var m3u = SplitStringBeforeSeparator(content, "#EXT");
|
||||
|
||||
foreach (var line in m3u)
|
||||
{
|
||||
if (line.StartsWith("#EXTINF:"))
|
||||
{
|
||||
playlistItems.Add(m3uInfo);
|
||||
if (TryParseM3ULine(line, out var m3uInfo))
|
||||
{
|
||||
playlistItems.Add(m3uInfo);
|
||||
}
|
||||
}
|
||||
if (line.StartsWith("#EXTM3U"))
|
||||
{
|
||||
programGuideLink=ExtractXtvgUrl(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error reading M3U file: " + ex.Message);
|
||||
}
|
||||
|
||||
return playlistItems;
|
||||
}
|
||||
|
||||
|
||||
static bool TryParseM3ULine(string m3uLine, out M3UInfo? info)
|
||||
{
|
||||
info = null;
|
||||
string pattern = @"#EXTINF:\d+ CUID=""(?<CUID>.*?)"" number=""(?<Number>.*?)"" tvg-id=""(?<TvgID>.*?)"" tvg-name=""(?<TvgName>.*?)"".*?tvg-logo=""(?<Logo>.*?)"" group-title=""(?<GroupTitle>.*?)""[^,]*,(?<Name>.*)[^\r](?<URL>.*)$";
|
||||
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
|
||||
|
||||
Match match = regex.Match(m3uLine);
|
||||
if (match.Success)
|
||||
{
|
||||
info = new M3UInfo
|
||||
catch (Exception ex)
|
||||
{
|
||||
CUID = match.Groups["CUID"].Value,
|
||||
Number = match.Groups["Number"].Value,
|
||||
TvgID = match.Groups["TvgID"].Value,
|
||||
TvgName = match.Groups["TvgName"].Value,
|
||||
GroupTitle = match.Groups["GroupTitle"].Value,
|
||||
Logo = match.Groups["Logo"].Value,
|
||||
Name = match.Groups["Name"].Value,
|
||||
Url = match.Groups["URL"].Value
|
||||
};
|
||||
return true;
|
||||
Console.WriteLine("Error reading M3U file: " + ex.Message);
|
||||
}
|
||||
|
||||
return (playlistItems,programGuideLink);
|
||||
}
|
||||
|
||||
return false;
|
||||
private static bool TryParseM3ULine(string m3uLine, out M3UInfo? info)
|
||||
{
|
||||
info = null;
|
||||
string pattern = @"#EXTINF:\d+ CUID=""(?<CUID>.*?)"" number=""(?<Number>.*?)"" tvg-id=""(?<TvgID>.*?)"" tvg-name=""(?<TvgName>.*?)"".*?tvg-logo=""(?<Logo>.*?)"" group-title=""(?<GroupTitle>.*?)""[^,]*,(?<Name>.*)[^\r](?<URL>.*)$";
|
||||
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
|
||||
|
||||
Match match = regex.Match(m3uLine);
|
||||
if (match.Success)
|
||||
{
|
||||
info = new M3UInfo
|
||||
{
|
||||
CUID = match.Groups["CUID"].Value,
|
||||
Number = match.Groups["Number"].Value,
|
||||
TvgID = match.Groups["TvgID"].Value,
|
||||
TvgName = match.Groups["TvgName"].Value,
|
||||
GroupTitle = match.Groups["GroupTitle"].Value,
|
||||
Logo = match.Groups["Logo"].Value,
|
||||
Name = match.Groups["Name"].Value,
|
||||
Url = match.Groups["URL"].Value
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string ExtractXtvgUrl(string m3uEntry)
|
||||
{
|
||||
// Define a regular expression pattern to match x-tvg-url attribute
|
||||
string pattern = @"x-tvg-url=""(.*?)""";
|
||||
|
||||
// Use Regex.Match to find the first match
|
||||
Match match = Regex.Match(m3uEntry, pattern);
|
||||
|
||||
// Check if a match is found and get the value from the capturing group
|
||||
if (match.Success && match.Groups.Count > 1)
|
||||
{
|
||||
return match.Groups[1].Value;
|
||||
}
|
||||
|
||||
// Return null or an empty string if no match is found
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using TV_Player.ViewModels;
|
||||
|
||||
namespace TV_Player
|
||||
{
|
||||
@@ -48,11 +49,14 @@ namespace TV_Player
|
||||
public Action ButtonBackAction { get; set; }
|
||||
public ICommand BackCommand { get; }
|
||||
|
||||
public ICommand SettingsCommand{ get; }
|
||||
|
||||
public MainViewModel()
|
||||
{
|
||||
|
||||
BackCommand = new RelayCommand(OnButtonBackClick);
|
||||
FullscreenCommand = new RelayCommand(OnFullSctreenButtonClick);
|
||||
SettingsCommand = new RelayCommand(OnSettingsButtonClick);
|
||||
|
||||
CurrentWindowStyle = WindowStyle.SingleBorderWindow;
|
||||
}
|
||||
@@ -76,5 +80,10 @@ namespace TV_Player
|
||||
|
||||
ButtonBackAction?.Invoke();
|
||||
}
|
||||
|
||||
private void OnSettingsButtonClick()
|
||||
{
|
||||
TVPlayerViewModel.Instance.ShowSettingsScreen();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,14 @@ namespace TV_Player
|
||||
public delegate void SourceUrlChanged(string videoURL);
|
||||
public event SourceUrlChanged SourceUrlChangedEvent;
|
||||
|
||||
private M3UInfo _currentProgram;
|
||||
private M3UInfo _currentProgram;
|
||||
|
||||
private bool _isProgramInfoVisible;
|
||||
public bool IsProgramInfoVisible
|
||||
{
|
||||
get => _isProgramInfoVisible;
|
||||
set => SetProperty(ref _isProgramInfoVisible, value);
|
||||
}
|
||||
|
||||
private string _topPaneTitle;
|
||||
public string TopPanelTitle
|
||||
@@ -71,7 +78,7 @@ namespace TV_Player
|
||||
PreviousCommand = new RelayCommand(PreviousProgram);
|
||||
FullscreenCommand = new RelayCommand(TVPlayerViewModel.Instance.FullScreenToggle);
|
||||
|
||||
_programSubscriber = ProgramsData.Instance.AllPrograms.Subscribe(x =>
|
||||
_programSubscriber = TVPlayerViewModel.Instance.PlaylistData.AllPrograms.Subscribe(x =>
|
||||
{
|
||||
_programs = x.Where(p => p.GroupTitle == _currentProgram.GroupTitle).ToList();
|
||||
_currentProgramIndex = _programs.Select((program, index) => new { program, index })
|
||||
@@ -79,7 +86,7 @@ namespace TV_Player
|
||||
.Select(x => x.index)
|
||||
.FirstOrDefault();
|
||||
});
|
||||
|
||||
|
||||
UpdateUI();
|
||||
}
|
||||
|
||||
@@ -89,7 +96,7 @@ namespace TV_Player
|
||||
TopPanelTitle = _currentProgram.Name;
|
||||
SourceUrlChangedEvent?.Invoke(_currentProgram.Url);
|
||||
|
||||
_programGuideDisposable = ProgramsData.Instance.ProgramGuideInfo.Subscribe(x =>
|
||||
_programGuideDisposable = TVPlayerViewModel.Instance.PlaylistData.ProgramGuideInfo.Subscribe(x =>
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -125,23 +132,33 @@ namespace TV_Player
|
||||
}
|
||||
private void UpdateScreenInfo()
|
||||
{
|
||||
_currentProgramInfo = _currentGuide.Programs.FirstOrDefault(d => d.StartTime <= DateTime.Now && d.StopTime >= DateTime.Now);
|
||||
if (_currentProgramInfo.Title != ProgramGuideText)
|
||||
try
|
||||
{
|
||||
ProgramGuideText = _currentProgramInfo.Title;
|
||||
StartProgram = _currentProgramInfo.StartTime.ToShortTimeString();
|
||||
EndProgram = _currentProgramInfo.StopTime.ToShortTimeString();
|
||||
_currentProgramInfo = _currentGuide.Programs.FirstOrDefault(d => d.StartTime <= DateTime.Now && d.StopTime >= DateTime.Now);
|
||||
if (_currentProgramInfo == null)
|
||||
{
|
||||
IsProgramInfoVisible = false;
|
||||
}
|
||||
else if (_currentProgramInfo.Title != ProgramGuideText)
|
||||
{
|
||||
IsProgramInfoVisible = true;
|
||||
ProgramGuideText = _currentProgramInfo.Title;
|
||||
StartProgram = _currentProgramInfo.StartTime.ToShortTimeString();
|
||||
EndProgram = _currentProgramInfo.StopTime.ToShortTimeString();
|
||||
|
||||
var programMinutes = (_currentProgramInfo.StopTime - _currentProgramInfo.StartTime).TotalMinutes;
|
||||
DurationValue = (int)((DateTime.Now - _currentProgramInfo.StartTime).TotalMinutes / programMinutes * 100);
|
||||
}
|
||||
|
||||
}
|
||||
var programMinutes = (_currentProgramInfo.StopTime - _currentProgramInfo.StartTime).TotalMinutes;
|
||||
DurationValue = (int)((DateTime.Now - _currentProgramInfo.StartTime).TotalMinutes / programMinutes * 100);
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
private void OnButtonBackClick()
|
||||
{
|
||||
var groupInfo = new GroupInfo() { Name = _currentProgram.GroupTitle, Count = 0 };
|
||||
|
||||
var programListViewModel = new ProgramsListViewModel(groupInfo);
|
||||
var conrtrol = new ProgramsList();
|
||||
TVPlayerViewModel.Instance.SetPageContext(conrtrol, programListViewModel);
|
||||
TVPlayerViewModel.Instance.ShowProgramsListScreen(groupInfo);
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
@@ -4,16 +4,6 @@ namespace TV_Player
|
||||
{
|
||||
public class ProgramsData
|
||||
{
|
||||
private static ProgramsData _instance;
|
||||
public static ProgramsData Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
_instance ??= new ProgramsData();
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly ReplaySubject<List<M3UInfo>> programsSubject = new ReplaySubject<List<M3UInfo>>();
|
||||
private readonly ReplaySubject<List<GroupInfo>> groupsSubject = new ReplaySubject<List<GroupInfo>>();
|
||||
private readonly ReplaySubject<List<ProgramGuide>> programGuideSubject = new ReplaySubject<List<ProgramGuide>>();
|
||||
@@ -21,29 +11,35 @@ namespace TV_Player
|
||||
public IObservable<List<GroupInfo>> GroupsInformation => groupsSubject;
|
||||
|
||||
public IObservable<List<ProgramGuide>> ProgramGuideInfo => programGuideSubject;
|
||||
private ProgramsData()
|
||||
{
|
||||
Task.Run(() => GetPrograms());
|
||||
Task.Run(() => GetProgramGuide());
|
||||
public ProgramsData()
|
||||
{
|
||||
}
|
||||
private async Task GetPrograms()
|
||||
|
||||
private async Task GetPrograms(string m3uLink)
|
||||
{
|
||||
string m3uLink = "http://pl.da-tv.vip/a71e77fa/835b3216/tv.m3u";
|
||||
var programs = await M3UParser.DownloadM3UFromWebAsync(m3uLink);
|
||||
//string m3uLink = "http://pl.da-tv.vip/a71e77fa/835b3216/tv.m3u";
|
||||
var result = await M3UParser.DownloadM3UFromWebAsync(m3uLink);
|
||||
|
||||
programsSubject.OnNext(result.programList);
|
||||
|
||||
programsSubject.OnNext(programs);
|
||||
|
||||
var groupping = programs.GroupBy(item => item.GroupTitle)
|
||||
var groupping = result.programList.GroupBy(item => item.GroupTitle)
|
||||
.Select(group => new GroupInfo() { Name = group.Key, Count = group.Count() })
|
||||
.ToList();
|
||||
groupsSubject.OnNext(groupping);
|
||||
|
||||
await Task.Run(() => GetProgramGuide(result.programGuide));
|
||||
}
|
||||
|
||||
private async Task GetProgramGuide()
|
||||
private async Task GetProgramGuide(string guideLink)
|
||||
{
|
||||
string guideLink = "http://epg.da-tv.vip/107-light.xml";
|
||||
//string guideLink = "http://epg.da-tv.vip/107-light.xml";
|
||||
var programGuide = await M3UParser.DownloadGuideFromWebAsync(guideLink);
|
||||
programGuideSubject.OnNext(programGuide);
|
||||
}
|
||||
|
||||
internal void GetData(string playlistURL)
|
||||
{
|
||||
Task.Run(() => GetPrograms(playlistURL));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,16 +20,14 @@ namespace TV_Player
|
||||
public ProgramsGroupViewModel()
|
||||
{
|
||||
ItemSelectedCommand = new RelayCommand(OnItemSelected);
|
||||
_groupInformationSubscriber = ProgramsData.Instance.GroupsInformation.Subscribe(x=>Programs = x);
|
||||
_groupInformationSubscriber = TVPlayerViewModel.Instance.PlaylistData.GroupsInformation.Subscribe(x=>Programs = x);
|
||||
|
||||
TVPlayerViewModel.Instance.TopPanelVisible(true, "Группы");
|
||||
}
|
||||
|
||||
private void OnItemSelected()
|
||||
{
|
||||
var programListViewModel = new ProgramsListViewModel(SelectedItem);
|
||||
var conrtrol = new ProgramsList();
|
||||
TVPlayerViewModel.Instance.SetPageContext(conrtrol, programListViewModel);
|
||||
TVPlayerViewModel.Instance.ShowProgramsListScreen(SelectedItem);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -16,26 +16,22 @@ namespace TV_Player
|
||||
public M3UInfo SelectedItem { get; set; }
|
||||
public ICommand ItemSelectedCommand { get; }
|
||||
private IDisposable _programSubscriber;
|
||||
|
||||
public ProgramsListViewModel(GroupInfo groupInfo)
|
||||
{
|
||||
TVPlayerViewModel.Instance.TopPanelVisible(true, groupInfo.Name);
|
||||
ItemSelectedCommand = new RelayCommand(OnItemSelected);
|
||||
_programSubscriber = ProgramsData.Instance.AllPrograms.Subscribe(x => Programs = x.Where(p => p.GroupTitle == groupInfo.Name).ToList());
|
||||
_programSubscriber = TVPlayerViewModel.Instance.PlaylistData.AllPrograms.Subscribe(x => Programs = x.Where(p => p.GroupTitle == groupInfo.Name).ToList());
|
||||
|
||||
TVPlayerViewModel.Instance.SetBackButtonAction(new Action(() =>
|
||||
{
|
||||
var programGroupViewModel = new ProgramsGroupViewModel();
|
||||
var conrtrol = new ProgramsGroupGrid();
|
||||
TVPlayerViewModel.Instance.SetPageContext(conrtrol, programGroupViewModel);
|
||||
TVPlayerViewModel.Instance.ShowProgramsGroupScreen();
|
||||
}));
|
||||
}
|
||||
|
||||
private void OnItemSelected()
|
||||
{
|
||||
var playerViewModel = new PlayerViewModel(SelectedItem);
|
||||
var conrtrol = new VideoPlayer();
|
||||
conrtrol.SourceUrl = SelectedItem.Url;
|
||||
TVPlayerViewModel.Instance.SetPageContext(conrtrol, playerViewModel);
|
||||
TVPlayerViewModel.Instance.ShowPlayerScreen(SelectedItem);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace TV_Player.ViewModels
|
||||
{
|
||||
//public class RelayCommand : ICommand
|
||||
//{
|
||||
// private readonly Action _execute;
|
||||
// private readonly Func<bool> _canExecute;
|
||||
|
||||
// public event EventHandler CanExecuteChanged;
|
||||
|
||||
// public RelayCommand(Action execute, Func<bool> canExecute = null)
|
||||
// {
|
||||
// _execute = execute ?? throw new ArgumentNullException(nameof(execute));
|
||||
// _canExecute = canExecute;
|
||||
// }
|
||||
|
||||
// public bool CanExecute(object parameter)
|
||||
// {
|
||||
// return _canExecute == null || _canExecute();
|
||||
// }
|
||||
|
||||
// public void Execute(object parameter)
|
||||
// {
|
||||
// _execute();
|
||||
// }
|
||||
|
||||
// public void RaiseCanExecuteChanged()
|
||||
// {
|
||||
// CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.IO;
|
||||
|
||||
namespace TV_Player.ViewModels
|
||||
{
|
||||
public static class SettingsModel
|
||||
{
|
||||
private const string _filePath = "settings.json";
|
||||
|
||||
public static string PlaylistURL { get; set; }
|
||||
public static bool StartFullScreen { get; set; }
|
||||
public static bool StartFromLastScreen { get; set; }
|
||||
public static string LastScreen { get; set; }
|
||||
public static GroupInfo Group { get; set; }
|
||||
public static M3UInfo Program { get; set; }
|
||||
|
||||
|
||||
public static void SaveSetttings()
|
||||
{
|
||||
// Create an anonymous object to hold the properties
|
||||
var dataToSerialize = new
|
||||
{
|
||||
PlaylistURL,
|
||||
StartFromLastScreen,
|
||||
StartFullScreen,
|
||||
LastScreen,
|
||||
Group,
|
||||
Program
|
||||
};
|
||||
|
||||
// Serialize the object to JSON
|
||||
string json = JsonConvert.SerializeObject(dataToSerialize, Formatting.Indented);
|
||||
|
||||
// Save the JSON to a file
|
||||
File.WriteAllText(_filePath, json);
|
||||
}
|
||||
|
||||
public static void LoadSettings()
|
||||
{
|
||||
var loadedData = new
|
||||
{
|
||||
PlaylistURL = default(string),
|
||||
LastScreen = default(string),
|
||||
Group = default(GroupInfo),
|
||||
Program = default(M3UInfo),
|
||||
StartFromLastScreen = default(bool),
|
||||
StartFullScreen = default(bool)
|
||||
};
|
||||
if (File.Exists(_filePath))
|
||||
{
|
||||
// Read the JSON content from the file
|
||||
string json = File.ReadAllText(_filePath);
|
||||
loadedData = JsonConvert.DeserializeAnonymousType(json, loadedData);
|
||||
}
|
||||
// Assign the values to the properties
|
||||
PlaylistURL = loadedData.PlaylistURL;
|
||||
LastScreen = loadedData.LastScreen;
|
||||
Group = loadedData.Group;
|
||||
Program = loadedData.Program;
|
||||
StartFromLastScreen = loadedData.StartFromLastScreen;
|
||||
StartFullScreen = loadedData.StartFullScreen;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace TV_Player.ViewModels
|
||||
{
|
||||
internal class SettingsViewModel : ObservableViewModelBase
|
||||
{
|
||||
private string _playlistURL;
|
||||
public string PlaylistURL
|
||||
{
|
||||
get => _playlistURL;
|
||||
set => SetProperty(ref _playlistURL, 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 BackCommand { get; }
|
||||
|
||||
public SettingsViewModel()
|
||||
{
|
||||
TVPlayerViewModel.Instance.TopPanelVisible(false, "");
|
||||
|
||||
SaveCommand = new RelayCommand(OnSaveSettings);
|
||||
BackCommand = new RelayCommand(OnBackCommand);
|
||||
|
||||
StartFullScreen = SettingsModel.StartFullScreen;
|
||||
StartLastScreen = SettingsModel.StartFromLastScreen;
|
||||
PlaylistURL = SettingsModel.PlaylistURL;
|
||||
}
|
||||
|
||||
private void OnBackCommand()
|
||||
{
|
||||
TVPlayerViewModel.Instance.SelectScreen();
|
||||
}
|
||||
|
||||
private void OnSaveSettings()
|
||||
{
|
||||
SettingsModel.StartFullScreen = StartFullScreen;
|
||||
SettingsModel.StartFromLastScreen = StartLastScreen;
|
||||
SettingsModel.PlaylistURL = PlaylistURL;
|
||||
|
||||
SettingsModel.SaveSetttings();
|
||||
TVPlayerViewModel.Instance.InitializeTVWithData();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ namespace TV_Player.ViewModels
|
||||
public class TVPlayerViewModel : IDisposable
|
||||
{
|
||||
private readonly MainViewModel _mainViewModel;
|
||||
public ProgramsData PlaylistData { get; private set; }
|
||||
|
||||
public Action ButtonBackAction { get; set; }
|
||||
|
||||
@@ -21,6 +22,8 @@ namespace TV_Player.ViewModels
|
||||
|
||||
public TVPlayerViewModel()
|
||||
{
|
||||
PlaylistData = new ProgramsData();
|
||||
|
||||
_mainViewModel = new MainViewModel();
|
||||
var mainWindow = new MainWindow();
|
||||
mainWindow.DataContext = _mainViewModel;
|
||||
@@ -28,19 +31,81 @@ namespace TV_Player.ViewModels
|
||||
mainWindow.Show();
|
||||
_instance = this;
|
||||
|
||||
ShowInitialScreen();
|
||||
SettingsModel.LoadSettings();
|
||||
InitializeTVWithData();
|
||||
}
|
||||
|
||||
private void ShowInitialScreen()
|
||||
public void InitializeTVWithData()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(SettingsModel.PlaylistURL))
|
||||
{
|
||||
if (SettingsModel.StartFullScreen)
|
||||
FullScreenToggle();
|
||||
PlaylistData.GetData(SettingsModel.PlaylistURL);
|
||||
if (SettingsModel.StartFromLastScreen)
|
||||
SelectScreen();
|
||||
else
|
||||
ShowProgramsGroupScreen();
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowSettingsScreen();
|
||||
}
|
||||
}
|
||||
|
||||
public void SelectScreen()
|
||||
{
|
||||
switch (SettingsModel.LastScreen)
|
||||
{
|
||||
case "ProgramsListViewModel":
|
||||
ShowProgramsListScreen(SettingsModel.Group);
|
||||
break;
|
||||
case "PlayerViewModel":
|
||||
ShowPlayerScreen(SettingsModel.Program);
|
||||
break;
|
||||
default:
|
||||
ShowProgramsGroupScreen();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowProgramsGroupScreen()
|
||||
{
|
||||
var vm = new ProgramsGroupViewModel();
|
||||
|
||||
var control = new ProgramsGroupGrid();
|
||||
control.DataContext = vm;
|
||||
|
||||
SettingsModel.LastScreen = nameof(ProgramsGroupViewModel);
|
||||
SetPageContext(control, vm);
|
||||
}
|
||||
|
||||
public void ShowProgramsListScreen(GroupInfo group)
|
||||
{
|
||||
SettingsModel.Group = group;
|
||||
var programListViewModel = new ProgramsListViewModel(group);
|
||||
var conrtrol = new ProgramsList();
|
||||
SettingsModel.LastScreen = nameof(ProgramsListViewModel);
|
||||
SetPageContext(conrtrol, programListViewModel);
|
||||
}
|
||||
|
||||
public void ShowPlayerScreen(M3UInfo program)
|
||||
{
|
||||
SettingsModel.Program = program;
|
||||
var playerViewModel = new PlayerViewModel(program);
|
||||
var conrtrol = new VideoPlayer();
|
||||
conrtrol.SourceUrl = program.Url;
|
||||
SettingsModel.LastScreen = nameof(PlayerViewModel);
|
||||
SetPageContext(conrtrol, playerViewModel);
|
||||
}
|
||||
|
||||
public void ShowSettingsScreen()
|
||||
{
|
||||
var playerViewModel = new SettingsViewModel();
|
||||
var conrtrol = new Settings();
|
||||
SetPageContext(conrtrol, playerViewModel);
|
||||
}
|
||||
|
||||
public void TopPanelVisible(bool value, string title)
|
||||
{
|
||||
_mainViewModel.IsTopPanelVisible = value;
|
||||
@@ -57,13 +122,15 @@ namespace TV_Player.ViewModels
|
||||
_mainViewModel.ButtonBackAction = action;
|
||||
}
|
||||
|
||||
public void SetPageContext(ContentControl control, object viewModel)
|
||||
private void SetPageContext(ContentControl control, object viewModel)
|
||||
{
|
||||
if (_mainViewModel.Control is IDisposable disposable)
|
||||
disposable.Dispose();
|
||||
control.DataContext = viewModel;
|
||||
|
||||
_mainViewModel.Control = control;
|
||||
|
||||
SettingsModel.SaveSetttings();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
Reference in New Issue
Block a user