diff --git a/VDownload.Core/VDownload.Core.Strings/Strings/en-US/SubscriptionsViewResources.resw b/VDownload.Core/VDownload.Core.Strings/Strings/en-US/SubscriptionsViewResources.resw
index 8590552..1e97e5b 100644
--- a/VDownload.Core/VDownload.Core.Strings/Strings/en-US/SubscriptionsViewResources.resw
+++ b/VDownload.Core/VDownload.Core.Strings/Strings/en-US/SubscriptionsViewResources.resw
@@ -117,7 +117,22 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ Playlist has been already added
+
+
+ Error
+
Subscriptions
+
+ Add
+
+
+ Playlist URL
+
+
+ Remove
+
\ No newline at end of file
diff --git a/VDownload.Core/VDownload.Core.ViewModels/Subscriptions/Helpers/PlaylistViewModel.cs b/VDownload.Core/VDownload.Core.ViewModels/Subscriptions/Helpers/PlaylistViewModel.cs
new file mode 100644
index 0000000..8f77732
--- /dev/null
+++ b/VDownload.Core/VDownload.Core.ViewModels/Subscriptions/Helpers/PlaylistViewModel.cs
@@ -0,0 +1,39 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using VDownload.Models;
+
+namespace VDownload.Core.ViewModels.Subscriptions.Helpers
+{
+ public partial class PlaylistViewModel : ObservableObject
+ {
+ #region PROPERTIES
+
+ [ObservableProperty]
+ protected Guid _guid;
+
+ [ObservableProperty]
+ protected string _name;
+
+ [ObservableProperty]
+ protected Source _source;
+
+ #endregion
+
+
+
+ #region CONSTRUCTORS
+
+ public PlaylistViewModel(string name, Source source, Guid guid)
+ {
+ _name = name;
+ _source = source;
+ _guid = guid;
+ }
+
+ #endregion
+ }
+}
diff --git a/VDownload.Core/VDownload.Core.ViewModels/Subscriptions/SubscriptionsViewModel.cs b/VDownload.Core/VDownload.Core.ViewModels/Subscriptions/SubscriptionsViewModel.cs
index 663b143..921b770 100644
--- a/VDownload.Core/VDownload.Core.ViewModels/Subscriptions/SubscriptionsViewModel.cs
+++ b/VDownload.Core/VDownload.Core.ViewModels/Subscriptions/SubscriptionsViewModel.cs
@@ -1,13 +1,141 @@
-using CommunityToolkit.Mvvm.ComponentModel;
+using ABI.System;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using VDownload.Core.ViewModels.Subscriptions.Helpers;
+using VDownload.Models;
+using VDownload.Services.Data.Subscriptions;
+using VDownload.Services.UI.StringResources;
+using VDownload.Sources;
+using VDownload.Sources.Common;
namespace VDownload.Core.ViewModels.Subscriptions
{
- public class SubscriptionsViewModel : ObservableObject
+ public partial class SubscriptionsViewModel : ObservableObject
{
+ #region SERVICES
+
+ protected readonly ISearchService _searchService;
+ protected readonly IStringResourcesService _stringResourcesService;
+ protected readonly ISubscriptionsDataService _subscriptionsDataService;
+
+ #endregion
+
+
+
+ #region PROPERTIES
+
+ [ObservableProperty]
+ protected ObservableCollection _playlists;
+
+ [ObservableProperty]
+ protected string _url;
+
+ [ObservableProperty]
+ protected bool _loading;
+
+ [ObservableProperty]
+ protected string _error;
+
+ [ObservableProperty]
+ protected bool _isErrorOpened;
+
+ #endregion
+
+
+
+ #region CONSTRUCTORS
+
+ public SubscriptionsViewModel(ISearchService searchService, IStringResourcesService stringResourcesService, ISubscriptionsDataService subscriptionsDataService)
+ {
+ _searchService = searchService;
+ _stringResourcesService = stringResourcesService;
+ _subscriptionsDataService = subscriptionsDataService;
+
+ _playlists = new ObservableCollection();
+ _loading = false;
+ _isErrorOpened = true;
+ _error = null;
+ }
+
+ #endregion
+
+
+
+ #region COMMANDS
+
+ [RelayCommand]
+ public void Navigation()
+ {
+ Playlists.Clear();
+ foreach (Subscription sub in _subscriptionsDataService.Data)
+ {
+ Playlists.Add(new PlaylistViewModel(sub.Name, sub.Source, sub.Guid));
+ }
+ }
+
+ [RelayCommand]
+ public async Task RemovePlaylist(PlaylistViewModel playlist)
+ {
+ Playlists.Remove(playlist);
+
+ Subscription sub = _subscriptionsDataService.Data.FirstOrDefault(x => x.Guid == playlist.Guid);
+ _subscriptionsDataService.Data.Remove(sub);
+ await _subscriptionsDataService.Save();
+ }
+
+ [RelayCommand]
+ public async Task Add()
+ {
+ Loading = true;
+
+ Playlist playlist;
+ try
+ {
+ playlist = await _searchService.SearchPlaylist(Url, 0);
+ }
+ catch (MediaSearchException ex)
+ {
+ Error = _stringResourcesService.SearchResources.Get(ex.StringCode);
+ Loading = false;
+ return;
+ }
+
+
+ if (_subscriptionsDataService.Data.Any(x => x.Source == playlist.Source && x.Name == playlist.Name))
+ {
+ Error = _stringResourcesService.SubscriptionsViewResources.Get("DuplicateError");
+ Loading = false;
+ return;
+ }
+
+ Subscription subscription = new Subscription
+ {
+ Name = playlist.Name,
+ Source = playlist.Source,
+ Url = playlist.Url,
+ };
+ playlist.ForEach(x => subscription.VideoIds.Add(x.Id));
+
+ _subscriptionsDataService.Data.Add(subscription);
+ await _subscriptionsDataService.Save();
+ Playlists.Add(new PlaylistViewModel(subscription.Name, subscription.Source, subscription.Guid));
+
+ Loading = false;
+ }
+
+ [RelayCommand]
+ public void CloseError()
+ {
+ Error = null;
+ IsErrorOpened = true;
+ }
+
+ #endregion
}
}
diff --git a/VDownload.Core/VDownload.Core.Views/Subscriptions/SubscriptionsView.xaml b/VDownload.Core/VDownload.Core.Views/Subscriptions/SubscriptionsView.xaml
index 386316e..2827059 100644
--- a/VDownload.Core/VDownload.Core.Views/Subscriptions/SubscriptionsView.xaml
+++ b/VDownload.Core/VDownload.Core.Views/Subscriptions/SubscriptionsView.xaml
@@ -6,10 +6,109 @@
xmlns:local="using:VDownload.Core.Views.Subscriptions"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:ctuc="using:CommunityToolkit.WinUI.UI.Controls"
+ xmlns:ctc="using:CommunityToolkit.WinUI.Controls"
+ xmlns:ct="using:CommunityToolkit.WinUI"
+ xmlns:i="using:Microsoft.Xaml.Interactivity"
+ xmlns:ic="using:Microsoft.Xaml.Interactions.Core"
mc:Ignorable="d"
- Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
+ Background="{ThemeResource ViewBackgroundColor}"
+ x:Name="Root">
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/VDownload.Models/Playlist.cs b/VDownload.Models/Playlist.cs
index 7e202d1..d176dd0 100644
--- a/VDownload.Models/Playlist.cs
+++ b/VDownload.Models/Playlist.cs
@@ -12,6 +12,7 @@ namespace VDownload.Models
public required string Description { get; set; }
public required Uri Url { get; set; }
+ public Source Source { get; protected set; }
#endregion
}
diff --git a/VDownload.Models/Source.cs b/VDownload.Models/Source.cs
index 8862d31..4bc4528 100644
--- a/VDownload.Models/Source.cs
+++ b/VDownload.Models/Source.cs
@@ -8,7 +8,6 @@ namespace VDownload.Models
{
public enum Source
{
- Twitch,
- Subscriptions
+ Twitch
}
}
diff --git a/VDownload.Models/SubscriptionList.cs b/VDownload.Models/SubscriptionList.cs
deleted file mode 100644
index 3d406a5..0000000
--- a/VDownload.Models/SubscriptionList.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace VDownload.Models
-{
- public class SubscriptionList : VideoCollection
- {
- #region CONSTRUCTORS
-
- public SubscriptionList()
- {
- Source = Source.Subscriptions;
- }
-
- #endregion
- }
-}
diff --git a/VDownload.Models/SubscriptionsVideoList.cs b/VDownload.Models/SubscriptionsVideoList.cs
new file mode 100644
index 0000000..4030f75
--- /dev/null
+++ b/VDownload.Models/SubscriptionsVideoList.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace VDownload.Models
+{
+ public class SubscriptionsVideoList : VideoCollection
+ {
+ }
+}
diff --git a/VDownload.Models/VideoCollection.cs b/VDownload.Models/VideoCollection.cs
index ba95a92..221314f 100644
--- a/VDownload.Models/VideoCollection.cs
+++ b/VDownload.Models/VideoCollection.cs
@@ -11,7 +11,6 @@ namespace VDownload.Models
#region PROPERTIES
public required string Name { get; init; }
- public Source Source { get; protected set; }
#endregion
}
diff --git a/VDownload.Services/VDownload.Services.Data/VDownload.Services.Data.Subscriptions/Subscription.cs b/VDownload.Services/VDownload.Services.Data/VDownload.Services.Data.Subscriptions/Subscription.cs
new file mode 100644
index 0000000..b4516a9
--- /dev/null
+++ b/VDownload.Services/VDownload.Services.Data/VDownload.Services.Data.Subscriptions/Subscription.cs
@@ -0,0 +1,32 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using VDownload.Models;
+
+namespace VDownload.Services.Data.Subscriptions
+{
+ public class Subscription
+ {
+ #region PROPERTIES
+
+ [JsonProperty("guid")]
+ public Guid Guid { get; private set; } = Guid.NewGuid();
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("source")]
+ public Source Source { get; set; }
+
+ [JsonProperty("url")]
+ public Uri Url { get; set; }
+
+ [JsonProperty("video_ids")]
+ public ICollection VideoIds { get; private set; } = new List();
+
+ #endregion
+ }
+}
diff --git a/VDownload.Services/VDownload.Services.Data/VDownload.Services.Data.Subscriptions/SubscriptionsDataService.cs b/VDownload.Services/VDownload.Services.Data/VDownload.Services.Data.Subscriptions/SubscriptionsDataService.cs
index d689c21..4caee21 100644
--- a/VDownload.Services/VDownload.Services.Data/VDownload.Services.Data.Subscriptions/SubscriptionsDataService.cs
+++ b/VDownload.Services/VDownload.Services.Data/VDownload.Services.Data.Subscriptions/SubscriptionsDataService.cs
@@ -1,12 +1,97 @@
-using System;
+using Newtonsoft.Json;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using VDownload.Services.Data.Configuration;
namespace VDownload.Services.Data.Subscriptions
{
- public class SubscriptionsDataService
+ public interface ISubscriptionsDataService
{
+ #region PROPERTIES
+
+ ICollection Data { get; }
+
+ #endregion
+
+
+
+ #region METHODS
+
+ Task Load();
+ Task Save();
+
+ #endregion
+ }
+
+
+
+ public class SubscriptionsDataService : ISubscriptionsDataService
+ {
+ #region SERVICES
+
+ protected readonly IConfigurationService _configurationService;
+
+ #endregion
+
+
+
+ #region FIELDS
+
+ protected readonly string _filePath;
+
+ #endregion
+
+
+
+ #region PROPERTIES
+
+ public ICollection Data { get; private set; }
+
+ #endregion
+
+
+
+ #region CONSTRUCTORS
+
+ public SubscriptionsDataService(IConfigurationService configurationService)
+ {
+ _configurationService = configurationService;
+
+ string appdataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
+ string appdataDirectoryName = _configurationService.Common.Path.Appdata.DirectoryName;
+ string appdataAuthenticationFilename = _configurationService.Common.Path.Appdata.SubscriptionsFile;
+ _filePath = Path.Combine(appdataPath, appdataDirectoryName, appdataAuthenticationFilename);
+ }
+
+ #endregion
+
+
+
+ #region PUBLIC METHODS
+
+ public async Task Load()
+ {
+ if (File.Exists(_filePath))
+ {
+ string content = await File.ReadAllTextAsync(_filePath);
+ Data = JsonConvert.DeserializeObject>(content);
+ }
+ else
+ {
+ Data = new List();
+ }
+ }
+
+ public async Task Save()
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(_filePath));
+ string content = JsonConvert.SerializeObject(Data);
+ await File.WriteAllTextAsync(_filePath, content);
+ }
+
+ #endregion
}
}
diff --git a/VDownload.Services/VDownload.Services.Data/VDownload.Services.Data.Subscriptions/VDownload.Services.Data.Subscriptions.csproj b/VDownload.Services/VDownload.Services.Data/VDownload.Services.Data.Subscriptions/VDownload.Services.Data.Subscriptions.csproj
index fa71b7a..d81009e 100644
--- a/VDownload.Services/VDownload.Services.Data/VDownload.Services.Data.Subscriptions/VDownload.Services.Data.Subscriptions.csproj
+++ b/VDownload.Services/VDownload.Services.Data/VDownload.Services.Data.Subscriptions/VDownload.Services.Data.Subscriptions.csproj
@@ -6,4 +6,13 @@
enable
+
+
+
+
+
+
+
+
+
diff --git a/VDownload.Sources/VDownload.Sources/VDownload.Sources.csproj b/VDownload.Sources/VDownload.Sources/VDownload.Sources.csproj
index fdec61e..c27e6e9 100644
--- a/VDownload.Sources/VDownload.Sources/VDownload.Sources.csproj
+++ b/VDownload.Sources/VDownload.Sources/VDownload.Sources.csproj
@@ -8,6 +8,7 @@
+
diff --git a/VDownload/App.xaml.cs b/VDownload/App.xaml.cs
index a91d01c..af9ab08 100644
--- a/VDownload/App.xaml.cs
+++ b/VDownload/App.xaml.cs
@@ -23,6 +23,7 @@ using VDownload.Services.Data.Authentication;
using VDownload.Services.Data.Configuration;
using VDownload.Services.Data.Configuration.Models;
using VDownload.Services.Data.Settings;
+using VDownload.Services.Data.Subscriptions;
using VDownload.Services.UI.Dialogs;
using VDownload.Services.UI.DictionaryResources;
using VDownload.Services.UI.Notifications;
@@ -110,6 +111,7 @@ namespace VDownload
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
+ services.AddSingleton();
}
protected void BuildUIServices(IServiceCollection services)
@@ -189,7 +191,8 @@ namespace VDownload
IApplicationDataService applicationDataService = _serviceProvider.GetService();
ISettingsService settingsService = _serviceProvider.GetService();
IAuthenticationDataService authenticationDataService = _serviceProvider.GetService();
- await Task.WhenAll(applicationDataService.Load(), settingsService.Load(), authenticationDataService.Load());
+ ISubscriptionsDataService subscriptionsDataService = _serviceProvider.GetService();
+ await Task.WhenAll(applicationDataService.Load(), settingsService.Load(), authenticationDataService.Load(), subscriptionsDataService.Load());
}
protected void AssignStaticProperties()
diff --git a/VDownload/Dictionaries/Colors.xaml b/VDownload/Dictionaries/Colors.xaml
index 077847a..65a6043 100644
--- a/VDownload/Dictionaries/Colors.xaml
+++ b/VDownload/Dictionaries/Colors.xaml
@@ -6,10 +6,12 @@
+
+
diff --git a/VDownload/Dictionaries/Converters.xaml b/VDownload/Dictionaries/Converters.xaml
index f9324ce..350aef3 100644
--- a/VDownload/Dictionaries/Converters.xaml
+++ b/VDownload/Dictionaries/Converters.xaml
@@ -13,4 +13,7 @@
+
diff --git a/VDownload/VDownload.csproj b/VDownload/VDownload.csproj
index d6cbda5..31c3e2f 100644
--- a/VDownload/VDownload.csproj
+++ b/VDownload/VDownload.csproj
@@ -192,6 +192,7 @@
+