Support local file paths for M3U playlists; UI tweaks
Added support for loading M3U playlists from both web URLs and local file paths, with logic to resolve relative paths. Improved exception handling in M3UParser. Enabled toggling of window border style in fullscreen mode, with data binding for WindowStyle. Removed IsValidUrl check to allow local file sources in settings. Cleaned up usings and formatting. Removed .NET SDK version from global.json.
This commit is contained in:
@@ -221,6 +221,7 @@ namespace TV_Player
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
using var client = new HttpClient();
|
using var client = new HttpClient();
|
||||||
using var request = new HttpRequestMessage();
|
using var request = new HttpRequestMessage();
|
||||||
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/text"));
|
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/text"));
|
||||||
@@ -240,6 +241,11 @@ namespace TV_Player
|
|||||||
System.Diagnostics.Debug.WriteLine($"Invalid URL: {url} - {ex.Message}");
|
System.Diagnostics.Debug.WriteLine($"Invalid URL: {url} - {ex.Message}");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"Error reading file from {url}: {ex.Message}");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<(List<M3UInfo> programList, string programGuide)> DownloadM3UFromWebAsync(string url)
|
public static async Task<(List<M3UInfo> programList, string programGuide)> DownloadM3UFromWebAsync(string url)
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
using System.Reactive;
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reactive;
|
||||||
using System.Reactive.Subjects;
|
using System.Reactive.Subjects;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace TV_Player
|
namespace TV_Player
|
||||||
{
|
{
|
||||||
@@ -25,7 +30,33 @@ namespace TV_Player
|
|||||||
//string m3uLink = "http://pl.da-tv.vip/a71e77fa/835b3216/tv.m3u";
|
//string m3uLink = "http://pl.da-tv.vip/a71e77fa/835b3216/tv.m3u";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = await M3UParser.DownloadM3UFromWebAsync(m3uLink);
|
// if link is a well-formed absolute URI load from web, otherwise treat as a local file path
|
||||||
|
// for relative paths try resolving against the application's base directory
|
||||||
|
var result = (programList: new List<M3UInfo>(), programGuide: string.Empty);
|
||||||
|
if (Uri.IsWellFormedUriString(m3uLink, UriKind.Absolute))
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine("[ProgramsData] Detected URL, downloading from web");
|
||||||
|
result = await M3UParser.DownloadM3UFromWebAsync(m3uLink);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// try as provided path first
|
||||||
|
var candidate = m3uLink;
|
||||||
|
if (!Path.IsPathRooted(candidate))
|
||||||
|
{
|
||||||
|
candidate = Path.Combine(AppContext.BaseDirectory ?? string.Empty, candidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File.Exists(candidate))
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"[ProgramsData] Detected local file, loading from disk: {candidate}");
|
||||||
|
result = await M3UParser.DownloadM3UFromWebAsync(candidate);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException($"M3U file not found: {m3uLink}");
|
||||||
|
}
|
||||||
|
}
|
||||||
System.Diagnostics.Debug.WriteLine($"[ProgramsData] Downloaded {result.programList.Count} programs");
|
System.Diagnostics.Debug.WriteLine($"[ProgramsData] Downloaded {result.programList.Count} programs");
|
||||||
|
|
||||||
programsSubject.OnNext(result.programList);
|
programsSubject.OnNext(result.programList);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:local="clr-namespace:TV_Player"
|
xmlns:local="clr-namespace:TV_Player"
|
||||||
mc:Ignorable="d" WindowStyle="None" WindowState="{Binding CurrentWindowState}"
|
mc:Ignorable="d" WindowStyle="{Binding CurrentWindowStyle}" WindowState="{Binding CurrentWindowState}"
|
||||||
Title="TV" Height="450" Width="800"
|
Title="TV" Height="450" Width="800"
|
||||||
KeyDown="UserControl_KeyDown">
|
KeyDown="UserControl_KeyDown">
|
||||||
<Window.Resources>
|
<Window.Resources>
|
||||||
|
|||||||
@@ -36,6 +36,14 @@ namespace TV_Player
|
|||||||
get => _currentWindowState;
|
get => _currentWindowState;
|
||||||
set => SetProperty(ref _currentWindowState, value);
|
set => SetProperty(ref _currentWindowState, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private WindowStyle _currentWindowStyle;
|
||||||
|
public WindowStyle CurrentWindowStyle
|
||||||
|
{
|
||||||
|
get => _currentWindowStyle;
|
||||||
|
set => SetProperty(ref _currentWindowStyle, value);
|
||||||
|
}
|
||||||
|
|
||||||
public ICommand OnKeyDownCommand { get; }
|
public ICommand OnKeyDownCommand { get; }
|
||||||
|
|
||||||
public ICommand FullscreenCommand { get; }
|
public ICommand FullscreenCommand { get; }
|
||||||
@@ -53,6 +61,7 @@ namespace TV_Player
|
|||||||
FullscreenCommand = new RelayCommand(OnFullSctreenButtonClick);
|
FullscreenCommand = new RelayCommand(OnFullSctreenButtonClick);
|
||||||
SettingsCommand = new RelayCommand(OnSettingsButtonClick);
|
SettingsCommand = new RelayCommand(OnSettingsButtonClick);
|
||||||
CloseAppCommand = new RelayCommand(OnCloseAppButtonClick);
|
CloseAppCommand = new RelayCommand(OnCloseAppButtonClick);
|
||||||
|
CurrentWindowStyle = WindowStyle.SingleBorderWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnFullSctreenButtonClick()
|
public void OnFullSctreenButtonClick()
|
||||||
@@ -60,10 +69,13 @@ namespace TV_Player
|
|||||||
if (CurrentWindowState == WindowState.Normal)
|
if (CurrentWindowState == WindowState.Normal)
|
||||||
{
|
{
|
||||||
CurrentWindowState = WindowState.Maximized;
|
CurrentWindowState = WindowState.Maximized;
|
||||||
|
CurrentWindowStyle = WindowStyle.None;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CurrentWindowState = WindowState.Normal;
|
CurrentWindowState = WindowState.Normal;
|
||||||
|
CurrentWindowStyle = WindowStyle.SingleBorderWindow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ namespace TV_Player
|
|||||||
public ProgramsGroupViewModel()
|
public ProgramsGroupViewModel()
|
||||||
{
|
{
|
||||||
ItemSelectedCommand = new RelayCommand(OnItemSelected);
|
ItemSelectedCommand = new RelayCommand(OnItemSelected);
|
||||||
_groupInformationSubscriber = TVPlayerViewModel.Instance.CurrentProgrmsData.GroupsInformation.Subscribe(x => Programs = SettingsModel.HiddenGroups == null ? x : x.Where(g => !SettingsModel.HiddenGroups.Contains(g.Name.ToLower())).ToList());
|
_groupInformationSubscriber = TVPlayerViewModel.Instance.CurrentProgrmsData.GroupsInformation.Subscribe(x =>
|
||||||
|
Programs = SettingsModel.HiddenGroups == null ? x : x.Where(g => !SettingsModel.HiddenGroups.Contains(g.Name.ToLower())).ToList());
|
||||||
|
|
||||||
TVPlayerViewModel.Instance.TopPanelVisible(true, "Groups");
|
TVPlayerViewModel.Instance.TopPanelVisible(true, "Groups");
|
||||||
|
|
||||||
|
|||||||
@@ -67,16 +67,10 @@ namespace TV_Player.ViewModels
|
|||||||
var name = PlaylistName?.Trim();
|
var name = PlaylistName?.Trim();
|
||||||
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(url))
|
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(url))
|
||||||
return;
|
return;
|
||||||
if (IsValidUrl(url))
|
Playlists.Add(new KeyValuePair<string, string>(name, url));
|
||||||
Playlists.Add(new KeyValuePair<string, string>(name, url));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsValidUrl(string url)
|
|
||||||
{
|
|
||||||
Uri uriResult;
|
|
||||||
return Uri.TryCreate(url, UriKind.Absolute, out uriResult)
|
|
||||||
&& (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPlaylistDeleteCommand(KeyValuePair<string, string> pair)
|
private void OnPlaylistDeleteCommand(KeyValuePair<string, string> pair)
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-6
@@ -1,6 +1 @@
|
|||||||
{
|
|
||||||
"sdk": {
|
|
||||||
"version": "8.0.417",
|
|
||||||
"rollForward": "latestPatch"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user