Refactored core
UI navigation framework Related Work Items: #408, #414, #416
This commit is contained in:
@@ -132,26 +132,28 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Models\Collections\InboxCollection.cs" />
|
||||
<Compile Include="Models\Collections\ViewCollection.cs" />
|
||||
<Compile Include="Models\SearchParameters.cs" />
|
||||
<Compile Include="Models\Subscription.cs" />
|
||||
<Compile Include="Services\DownloadsService.cs" />
|
||||
<Compile Include="Extensions.cs" />
|
||||
<Compile Include="Services\SettingsService.cs" />
|
||||
<Compile Include="Utils\FeedbackIterop.cs" />
|
||||
<Compile Include="Services\History.cs" />
|
||||
<Compile Include="Services\InboxService.cs" />
|
||||
<Compile Include="Utils\Metrics.cs" />
|
||||
<Compile Include="Services\Search.cs" />
|
||||
<Compile Include="Services\Storage.cs" />
|
||||
<Compile Include="Services\StorageService.cs" />
|
||||
<Compile Include="Utils\AddonsInterop.cs" />
|
||||
<Compile Include="Services\UserService.cs" />
|
||||
<Compile Include="Utils\SecretConstants.cs" />
|
||||
<Compile Include="Utils\BackgroundManager.cs" />
|
||||
<Compile Include="Utils\ToastTemplates.cs" />
|
||||
<Compile Include="Utils\Utils.cs" />
|
||||
<Compile Include="Models\DownloadItem.cs" />
|
||||
<Compile Include="Models\InboxItem.cs" />
|
||||
<Compile Include="Models\Attributes.cs" />
|
||||
<Compile Include="Models\SavedVideo.cs" />
|
||||
<Compile Include="Models\SearchSuggestion.cs" />
|
||||
<Compile Include="Models\User.cs" />
|
||||
<Compile Include="Models\VideoItem.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<EmbeddedResource Include="Properties\FoxTube.Core.rd.xml" />
|
||||
</ItemGroup>
|
||||
@@ -163,22 +165,25 @@
|
||||
<Version>1.0.3</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Google.Apis.Auth">
|
||||
<Version>1.45.0</Version>
|
||||
<Version>1.46.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Google.Apis.Blogger.v3">
|
||||
<Version>1.46.0.1986</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Google.Apis.Oauth2.v2">
|
||||
<Version>1.44.1.1869</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Google.Apis.YouTube.v3">
|
||||
<Version>1.45.0.1929</Version>
|
||||
<Version>1.46.0.1987</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Advertising.XAML">
|
||||
<Version>10.1811.22001</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.AppCenter.Analytics">
|
||||
<Version>3.2.1</Version>
|
||||
<Version>3.2.2</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.AppCenter.Crashes">
|
||||
<Version>3.2.1</Version>
|
||||
<Version>3.2.2</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
||||
<Version>6.2.10</Version>
|
||||
@@ -186,11 +191,14 @@
|
||||
<PackageReference Include="Microsoft.Services.Store.Engagement">
|
||||
<Version>10.1901.28001</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.UI.Xaml">
|
||||
<Version>2.4.0</Version>
|
||||
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications">
|
||||
<Version>6.0.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="QueryString.NET">
|
||||
<Version>1.0.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="YoutubeExplode">
|
||||
<Version>5.0.4</Version>
|
||||
<Version>5.0.5</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,45 +1,49 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using FoxTube.Services;
|
||||
using FoxTube.Utils;
|
||||
using Google.Apis.Blogger.v3;
|
||||
using Google.Apis.Blogger.v3.Data;
|
||||
|
||||
namespace FoxTube.Models.Collections
|
||||
{
|
||||
public class InboxCollection : ViewCollection<InboxItem>
|
||||
public class InboxCollection : ViewCollection<Post>
|
||||
{
|
||||
private int _pageNumber = 0;
|
||||
private HttpClient _httpClient = new HttpClient();
|
||||
private string nextPageToken;
|
||||
|
||||
public override async Task<LoadMoreItemsResult> LoadItems()
|
||||
{
|
||||
// TODO: Add backend
|
||||
HttpResponseMessage response = await _httpClient.GetAsync($"https://xfox111.net/API/FoxTube/Inbox?" +
|
||||
$"lang={Storage.GetValue<string>(Storage.Settings.UILanguage)}&" +
|
||||
$"currentVersion={Metrics.CurrentVersion}&" +
|
||||
$"itemsCount={ItemsPerRequest}&" +
|
||||
$"iteration={_pageNumber}");
|
||||
|
||||
if (!response.IsSuccessStatusCode || response.StatusCode == System.Net.HttpStatusCode.NoContent)
|
||||
try
|
||||
{
|
||||
PostsResource.ListRequest request = InboxService.Service.Posts.List(SecretConstants.BlogId);
|
||||
request.FetchImages = false;
|
||||
request.PageToken = nextPageToken;
|
||||
request.Labels = "FoxTube";
|
||||
request.MaxResults = ItemsPerRequest;
|
||||
request.OrderBy = PostsResource.ListRequest.OrderByEnum.UPDATED;
|
||||
|
||||
PostList response = await request.ExecuteAsync();
|
||||
|
||||
foreach (Post post in response.Items)
|
||||
Items.Add(post);
|
||||
|
||||
HasMoreItems = !string.IsNullOrWhiteSpace(nextPageToken = response.NextPageToken);
|
||||
|
||||
return new LoadMoreItemsResult
|
||||
{
|
||||
Count = (uint)response.Items.Count
|
||||
};
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Metrics.SendReport(new Exception("Unable to load inbox", e));
|
||||
HasMoreItems = false;
|
||||
return new LoadMoreItemsResult
|
||||
{
|
||||
Count = 0
|
||||
};
|
||||
}
|
||||
|
||||
InboxItem[] newItems = JsonConvert.DeserializeObject<InboxItem[]>(await response.Content.ReadAsStringAsync());
|
||||
foreach (InboxItem item in newItems)
|
||||
Items.Add(item);
|
||||
|
||||
_pageNumber++;
|
||||
|
||||
return new LoadMoreItemsResult
|
||||
{
|
||||
Count = (uint)newItems.Length
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace FoxTube.Models.Collections
|
||||
{
|
||||
public abstract class ViewCollection<T> : ObservableCollection<T>, ISupportIncrementalLoading
|
||||
{
|
||||
public int ItemsPerRequest { get; set; }
|
||||
public int ItemsPerRequest { get; set; } = 25;
|
||||
public bool HasMoreItems { get; protected set; } = true;
|
||||
|
||||
public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count) =>
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace FoxTube.Models
|
||||
{
|
||||
public class InboxItem
|
||||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
public string DefaultIcon { get; set; }
|
||||
public string Avatar { get; set; }
|
||||
|
||||
public string Title { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Content { get; set; }
|
||||
|
||||
public DateTime TimeStamp { get; set; }
|
||||
public string Type { get; set; }
|
||||
|
||||
public string ShortTimeStamp => $"{TimeStamp.ToShortDateString()} {TimeStamp.ToShortTimeString()}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FoxTube.Models
|
||||
{
|
||||
public class SearchParameters
|
||||
{
|
||||
public SearchParameters(string query)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,10 @@ using Google.Apis.Oauth2.v2.Data;
|
||||
using Google.Apis.Services;
|
||||
using Google.Apis.YouTube.v3;
|
||||
using Google.Apis.YouTube.v3.Data;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
using YouTube;
|
||||
using YoutubeExplode;
|
||||
using FoxTube.Services;
|
||||
@@ -42,8 +40,6 @@ namespace FoxTube.Models
|
||||
|
||||
UserService.SubscriptionsChangedInvoker(this, subscription);
|
||||
Subscriptions.Remove(subscription);
|
||||
|
||||
SaveSubscriptions();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
@@ -79,21 +75,10 @@ namespace FoxTube.Models
|
||||
Subscriptions.Add(subscription);
|
||||
|
||||
UserService.SubscriptionsChangedInvoker(this, subscription);
|
||||
|
||||
SaveSubscriptions();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveSubscriptions()
|
||||
{
|
||||
Dictionary<string, string> subs = Subscriptions.Select(i =>
|
||||
new KeyValuePair<string, string>(i.ChannelId, i.Avatar.Default__?.Url))
|
||||
as Dictionary<string, string>;
|
||||
|
||||
ApplicationData.Current.RoamingSettings.Values[$"Subscriptions.{UserInfo.Id}"] = JsonConvert.SerializeObject(subs);
|
||||
}
|
||||
|
||||
public static async Task<User> GetUser(UserCredential credential)
|
||||
{
|
||||
User user = new User
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
using FoxTube.Services;
|
||||
using Google.Apis.YouTube.v3.Data;
|
||||
using System;
|
||||
using YoutubeExplode;
|
||||
|
||||
namespace FoxTube.Models
|
||||
{
|
||||
public class VideoItem
|
||||
{
|
||||
public Video Meta { get; set; }
|
||||
public YoutubeExplode.Videos.Video AdditionalMeta { get; set; }
|
||||
public YoutubeExplode.Channels.Channel ChannelMeta { get; set; }
|
||||
|
||||
public string TimeLabel { get; set; }
|
||||
public string ViewsLabel { get; set; }
|
||||
public int LiveLabelOpacity => Meta?.LiveStreamingDetails == null ? 0 : 1;
|
||||
public string LiveLabel
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Meta?.LiveStreamingDetails == null)
|
||||
return "";
|
||||
else if (Meta.LiveStreamingDetails.ActualStartTime.HasValue)
|
||||
return "LIVE";
|
||||
else if (Meta.LiveStreamingDetails.ScheduledStartTime.HasValue)
|
||||
return $"Live in {Meta.LiveStreamingDetails.ScheduledStartTime - DateTime.Now}";
|
||||
else
|
||||
return "Upcoming";
|
||||
}
|
||||
}
|
||||
|
||||
public VideoItem(Video meta)
|
||||
{
|
||||
Meta = meta;
|
||||
LoadInfo();
|
||||
}
|
||||
|
||||
private async void LoadInfo()
|
||||
{
|
||||
YoutubeClient client = new YoutubeClient(UserService.Service.HttpClient);
|
||||
|
||||
AdditionalMeta = await client.Videos.GetAsync(Meta.Id);
|
||||
ChannelMeta = await client.Channels.GetByVideoAsync(Meta.Id);
|
||||
|
||||
TimeLabel = $"{AdditionalMeta?.Duration} • {AdditionalMeta.UploadDate.DateTime.GetFriendlyDate()}";
|
||||
ViewsLabel = $"{AdditionalMeta?.Engagement.ViewCount} views";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,12 +18,9 @@ namespace FoxTube.Services
|
||||
public static List<SavedVideo> History { get; } = new List<SavedVideo>();
|
||||
public static List<DownloadItem> Queue { get; } = new List<DownloadItem>();
|
||||
|
||||
static DownloadsService() =>
|
||||
Initialize();
|
||||
|
||||
private static async void Initialize()
|
||||
public static async Task Initialize()
|
||||
{
|
||||
StorageFile file = await Storage.Folder.CreateFileAsync("DownloadHistory.json", CreationCollisionOption.OpenIfExists);
|
||||
StorageFile file = await StorageService.Folder.CreateFileAsync("DownloadHistory.json", CreationCollisionOption.OpenIfExists);
|
||||
try
|
||||
{
|
||||
List<SavedVideo> savedVideos = JsonConvert.DeserializeObject<List<SavedVideo>>(File.ReadAllText(file.Path) ?? "") ?? new List<SavedVideo>();
|
||||
@@ -70,7 +67,7 @@ namespace FoxTube.Services
|
||||
|
||||
History.Add(savedItem);
|
||||
|
||||
StorageFile file = await Storage.Folder.CreateFileAsync("DownloadHistory.json", CreationCollisionOption.OpenIfExists);
|
||||
StorageFile file = await StorageService.Folder.CreateFileAsync("DownloadHistory.json", CreationCollisionOption.OpenIfExists);
|
||||
File.WriteAllText(file.Path, JsonConvert.SerializeObject(History));
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
@@ -112,7 +109,7 @@ namespace FoxTube.Services
|
||||
|
||||
public static async Task<StorageFolder> GetDefaultDownloadsFolder()
|
||||
{
|
||||
if (Storage.GetValue<string>(Storage.Settings.DefaultDownloadsFolder) is string token && !string.IsNullOrWhiteSpace(token))
|
||||
if (SettingsService.DefaultDownloadsFolder is string token && !string.IsNullOrWhiteSpace(token))
|
||||
return await StorageApplicationPermissions.FutureAccessList.GetFolderAsync(token) ??
|
||||
await KnownFolders.VideosLibrary.CreateFolderAsync("FoxTube", CreationCollisionOption.OpenIfExists);
|
||||
else
|
||||
@@ -137,12 +134,12 @@ namespace FoxTube.Services
|
||||
|
||||
if (folder != null)
|
||||
{
|
||||
if (Storage.GetValue<string>(Storage.Settings.DefaultDownloadsFolder) is string token && !string.IsNullOrWhiteSpace(token))
|
||||
if (SettingsService.DefaultDownloadsFolder is string token && !string.IsNullOrWhiteSpace(token))
|
||||
StorageApplicationPermissions.FutureAccessList.AddOrReplace(token, folder);
|
||||
else
|
||||
{
|
||||
token = StorageApplicationPermissions.FutureAccessList.Add(folder);
|
||||
Storage.SetValue(Storage.Settings.DefaultDownloadsFolder, token);
|
||||
SettingsService.DefaultDownloadsFolder = token;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
using FoxTube.Models.Collections;
|
||||
using FoxTube.Utils;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.UI.Notifications;
|
||||
using Google.Apis.Blogger.v3;
|
||||
using Google.Apis.Blogger.v3.Data;
|
||||
using System.Linq;
|
||||
using System.Globalization;
|
||||
using Windows.Foundation.Metadata;
|
||||
|
||||
namespace FoxTube.Services
|
||||
{
|
||||
public static class InboxService
|
||||
{
|
||||
public const string lastChangelogVersionKey = "Inbox.lastChangelogVersion";
|
||||
public const string lastCheckKey = "Inbox.lastChangelogVersion";
|
||||
public static BloggerService Service { get; } = new BloggerService(new Google.Apis.Services.BaseClientService.Initializer
|
||||
{
|
||||
ApplicationName = "FoxTube",
|
||||
ApiKey = SecretConstants.BloggerApiKey
|
||||
});
|
||||
|
||||
private static readonly HttpClient client = new HttpClient();
|
||||
|
||||
@@ -23,22 +29,19 @@ namespace FoxTube.Services
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO: Add backend
|
||||
HttpResponseMessage response = await client.GetAsync($"https://xfox111.net/FoxTube/Inbox?" +
|
||||
$"toast=true&" +
|
||||
$"publishedAfter={Storage.Registry.Values[lastCheckKey]}&" +
|
||||
$"lang={Storage.GetValue<string>(Storage.Settings.UILanguage)}&" +
|
||||
$"appVersion={Metrics.CurrentVersion}");
|
||||
PostsResource.ListRequest request = Service.Posts.List(SecretConstants.BlogId);
|
||||
request.FetchImages = false;
|
||||
request.Labels = "FoxTube";
|
||||
request.MaxResults = 500;
|
||||
request.StartDate = StorageService.LastInboxCheck.ToString("yyyy-MM-dd'T'HH:mm:ss.fffK", DateTimeFormatInfo.InvariantInfo);
|
||||
request.OrderBy = PostsResource.ListRequest.OrderByEnum.UPDATED;
|
||||
|
||||
Storage.Registry.Values[lastCheckKey] = DateTime.UtcNow.Ticks;
|
||||
PostList response = await request.ExecuteAsync();
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.NoContent)
|
||||
return;
|
||||
foreach(Post post in response.Items.Where(i => !i.Labels.Contains("Changelog")))
|
||||
ToastNotificationManager.CreateToastNotifier().Show(ToastTemplates.GetBlogpostToast(post));
|
||||
|
||||
string[] toasts = JsonConvert.DeserializeObject<string[]>(await response.Content.ReadAsStringAsync());
|
||||
|
||||
foreach (string toast in toasts)
|
||||
ToastNotificationManager.CreateToastNotifier().Show(new ToastNotification(toast.ToXml()));
|
||||
StorageService.LastInboxCheck = DateTime.UtcNow;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -46,27 +49,33 @@ namespace FoxTube.Services
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add changelog retrieval
|
||||
/// <summary>
|
||||
/// Fires toast notification with the last changelog content
|
||||
/// </summary>
|
||||
[Deprecated("In future versions it will be replaced with splash screen full size message", DeprecationType.Deprecate, 1)]
|
||||
public static async void PushChangelog()
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO: Add backend
|
||||
if ((string)Storage.Registry.Values[lastChangelogVersionKey] == Metrics.CurrentVersion)
|
||||
if (string.IsNullOrWhiteSpace(StorageService.LastOpenedVersion))
|
||||
StorageService.LastOpenedVersion = Metrics.CurrentVersion;
|
||||
|
||||
string lastVersion = StorageService.LastOpenedVersion;
|
||||
if (string.IsNullOrWhiteSpace(lastVersion) || lastVersion == Metrics.CurrentVersion)
|
||||
return;
|
||||
|
||||
Storage.Registry.Values[lastChangelogVersionKey] = Metrics.CurrentVersion;
|
||||
PostsResource.ListRequest request = Service.Posts.List(SecretConstants.BlogId);
|
||||
request.FetchImages = false;
|
||||
request.Labels = $"FoxTube,Changelog,v{Metrics.CurrentVersion}";
|
||||
request.MaxResults = 1;
|
||||
|
||||
HttpResponseMessage response = await client.GetAsync($"https://xfox111.net/API/FoxTube/Changelog?" +
|
||||
$"lang={Storage.GetValue<string>(Storage.Settings.UILanguage)}&" +
|
||||
$"version={Metrics.CurrentVersion}");
|
||||
PostList response = await request.ExecuteAsync();
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.NoContent)
|
||||
return;
|
||||
if (response.Items.Count > 0)
|
||||
ToastNotificationManager.CreateToastNotifier().Show(ToastTemplates.GetBlogpostToast(response.Items.First()));
|
||||
|
||||
ToastNotificationManager.CreateToastNotifier().Show(new ToastNotification((await response.Content.ReadAsStringAsync()).ToXml()));
|
||||
StorageService.LastOpenedVersion = Metrics.CurrentVersion;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -16,7 +16,12 @@ namespace FoxTube.Services
|
||||
try
|
||||
{
|
||||
using HttpClient client = new HttpClient();
|
||||
string results = await client.GetStringAsync($"http://suggestqueries.google.com/complete/search?ds=yt&client=toolbar&q={term}&hl={Storage.GetValue<string>(Storage.Settings.RelevanceLanguage)}");
|
||||
string results = await client.GetStringAsync($"http://suggestqueries.google.com/complete/search?" +
|
||||
$"ds=yt&" +
|
||||
$"client=toolbar&" +
|
||||
$"q={term}&" +
|
||||
$"hl={SettingsService.RelevanceLanguage}");
|
||||
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(results);
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
using Windows.Storage;
|
||||
using System.Globalization;
|
||||
using System.Diagnostics;
|
||||
using Windows.UI.Xaml;
|
||||
|
||||
namespace FoxTube.Services
|
||||
{
|
||||
public class SettingsService
|
||||
{
|
||||
private static readonly ApplicationDataContainer storage = ApplicationData.Current.RoamingSettings;
|
||||
|
||||
public static void ResetSettings() =>
|
||||
storage.Values.Clear();
|
||||
|
||||
public static ElementTheme Theme
|
||||
{
|
||||
get => (ElementTheme)GetValue(ElementTheme.Default);
|
||||
set => SetValue((int)value);
|
||||
}
|
||||
|
||||
public static string RelevanceLanguage
|
||||
{
|
||||
get => GetValue(GetDefaultLanguage());
|
||||
set => SetValue(value);
|
||||
}
|
||||
|
||||
public static bool AllowAnalytics
|
||||
{
|
||||
get => GetValue(true);
|
||||
set => SetValue(value);
|
||||
}
|
||||
|
||||
public static bool AskEveryDownload
|
||||
{
|
||||
get => GetValue(true);
|
||||
set => SetValue(value);
|
||||
}
|
||||
|
||||
public static string DefaultDownloadsFolder
|
||||
{
|
||||
get => GetValue(null);
|
||||
set => SetValue(value);
|
||||
}
|
||||
|
||||
#region Service methods
|
||||
private static string GetDefaultLanguage()
|
||||
{
|
||||
if (CultureInfo.InstalledUICulture.TwoLetterISOLanguageName.Belongs("ua", "ru", "by", "kz", "kg", "md", "lv", "ee")) // Languages for Russian-speaking countries
|
||||
return "ru-RU";
|
||||
else
|
||||
return "en-US";
|
||||
}
|
||||
|
||||
private static dynamic GetValue(object defaultValue)
|
||||
{
|
||||
string propName = (new StackTrace()).GetFrame(1).GetMethod().Name.Substring(4);
|
||||
return storage.Values[$"Settings.{propName}"] ?? defaultValue;
|
||||
}
|
||||
|
||||
private static void SetValue(object value)
|
||||
{
|
||||
string propName = (new StackTrace()).GetFrame(1).GetMethod().Name.Substring(4);
|
||||
storage.Values[$"Settings.{propName}"] = value;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
using Windows.UI.Xaml;
|
||||
|
||||
namespace FoxTube.Services
|
||||
{
|
||||
public static class Storage
|
||||
{
|
||||
public static event EventHandler<Settings> SettingsChanged;
|
||||
|
||||
public static StorageFolder Folder => ApplicationData.Current.RoamingFolder;
|
||||
public static ApplicationDataContainer Registry { get; } = ApplicationData.Current.RoamingSettings;
|
||||
|
||||
private static readonly Dictionary<Settings, object> _defaultSettings = new Dictionary<Settings, object>
|
||||
{
|
||||
{ Settings.Theme, ElementTheme.Default },
|
||||
{ Settings.UILanguage, GetDefaultLanguage() },
|
||||
{ Settings.RelevanceLanguage, GetDefaultLanguage() },
|
||||
{ Settings.PromptFeedback, true },
|
||||
{ Settings.PromptReview, true },
|
||||
{ Settings.AllowAnalytics, true }
|
||||
};
|
||||
|
||||
public enum Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// ElementTheme
|
||||
/// </summary>
|
||||
Theme,
|
||||
/// <summary>
|
||||
/// string
|
||||
/// </summary>
|
||||
UILanguage,
|
||||
/// <summary>
|
||||
/// string
|
||||
/// </summary>
|
||||
RelevanceLanguage,
|
||||
/// <summary>
|
||||
/// string
|
||||
/// </summary>
|
||||
DefaultDownloadsFolder,
|
||||
/// <summary>
|
||||
/// bool
|
||||
/// </summary>
|
||||
PromptFeedback,
|
||||
/// <summary>
|
||||
/// bool
|
||||
/// </summary>
|
||||
PromptReview,
|
||||
/// <summary>
|
||||
/// bool
|
||||
/// </summary>
|
||||
AllowAnalytics,
|
||||
/// <summary>
|
||||
/// string
|
||||
/// </summary>
|
||||
Region
|
||||
}
|
||||
|
||||
public enum Metrics
|
||||
{
|
||||
/// <summary>
|
||||
/// TimeSpan
|
||||
/// </summary>
|
||||
Uptime
|
||||
}
|
||||
|
||||
|
||||
public static void SetValue(Settings key, object value)
|
||||
{
|
||||
Registry.Values[$"{key.GetType().Name}.{key}"] = value;
|
||||
SettingsChanged?.Invoke(value, key);
|
||||
}
|
||||
public static void SetValue(Metrics key, object value) =>
|
||||
Registry.Values[$"{key.GetType().Name}.{key}"] = value;
|
||||
|
||||
public static T GetValue<T>(Settings key) =>
|
||||
(T)(Registry.Values[$"{key.GetType().Name}.{key}"] ?? (_defaultSettings.ContainsKey(key) ? _defaultSettings[key] : null));
|
||||
public static T GetValue<T>(Metrics key) =>
|
||||
(T)Registry.Values[$"{key.GetType().Name}.{key}"];
|
||||
|
||||
|
||||
private static string GetDefaultLanguage()
|
||||
{
|
||||
if (CultureInfo.InstalledUICulture.TwoLetterISOLanguageName.Belongs("ua", "ru", "by", "kz", "kg", "md", "lv", "ee")) //Languages for Russian-speaking countries
|
||||
return "ru-RU";
|
||||
else
|
||||
return "en-US";
|
||||
}
|
||||
|
||||
public static async Task ResetStorage()
|
||||
{
|
||||
Registry.Values.Clear();
|
||||
foreach (IStorageItem i in await Folder.GetItemsAsync())
|
||||
await i.DeleteAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
|
||||
namespace FoxTube.Services
|
||||
{
|
||||
public static class StorageService
|
||||
{
|
||||
private static readonly ApplicationDataContainer storage = ApplicationData.Current.RoamingSettings;
|
||||
|
||||
public static StorageFolder Folder => ApplicationData.Current.RoamingFolder;
|
||||
|
||||
public static bool PromptFeedback
|
||||
{
|
||||
get => GetValue(Uptime.TotalHours > 12);
|
||||
set => SetValue(value);
|
||||
}
|
||||
|
||||
public static bool PromptReview
|
||||
{
|
||||
get => GetValue(Uptime.TotalHours > 24);
|
||||
set => SetValue(value);
|
||||
}
|
||||
|
||||
public static TimeSpan Uptime
|
||||
{
|
||||
get => GetValue(TimeSpan.FromSeconds(0));
|
||||
set => SetValue(value);
|
||||
}
|
||||
|
||||
public static DateTime LastInboxCheck
|
||||
{
|
||||
get => GetValue(DateTime.UtcNow);
|
||||
set => SetValue(value);
|
||||
}
|
||||
|
||||
public static string LastOpenedVersion
|
||||
{
|
||||
get => GetValue(null);
|
||||
set => SetValue(value);
|
||||
}
|
||||
|
||||
public static int? LastUserIndex
|
||||
{
|
||||
get => GetValue(null);
|
||||
set => SetValue(value);
|
||||
}
|
||||
|
||||
public static string UserInfos
|
||||
{
|
||||
get => GetValue(null);
|
||||
set => SetValue(value);
|
||||
}
|
||||
|
||||
public static async Task ClearStorage()
|
||||
{
|
||||
storage.Values.Clear();
|
||||
foreach (IStorageItem i in await Folder.GetItemsAsync())
|
||||
await i.DeleteAsync();
|
||||
}
|
||||
|
||||
#region Service methods
|
||||
private static dynamic GetValue(object defaultValue)
|
||||
{
|
||||
string propName = (new StackTrace()).GetFrame(1).GetMethod().Name.Substring(4);
|
||||
return storage.Values[$"Storage.{propName}"] ?? defaultValue;
|
||||
}
|
||||
|
||||
private static void SetValue(object value)
|
||||
{
|
||||
string propName = (new StackTrace()).GetFrame(1).GetMethod().Name.Substring(4);
|
||||
storage.Values[$"Storage.{propName}"] = value;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -20,9 +20,6 @@ namespace FoxTube.Services
|
||||
{
|
||||
public static class UserService
|
||||
{
|
||||
public const string UsersStorageKey = "UserService.Users";
|
||||
public const string LastUserInfoKey = "UserService.LastUser";
|
||||
|
||||
public const int MaxUsersCount = 1;
|
||||
|
||||
#region Private members
|
||||
@@ -74,9 +71,6 @@ namespace FoxTube.Services
|
||||
public static event EventHandler<bool> UserStateUpdated;
|
||||
public static event EventHandler<Subscription> SubscriptionsChanged;
|
||||
|
||||
static UserService() =>
|
||||
Initialize();
|
||||
|
||||
public static async Task<bool> AddUser()
|
||||
{
|
||||
int queueIndex = Users.ToList().FindIndex(i => i == null);
|
||||
@@ -117,10 +111,10 @@ namespace FoxTube.Services
|
||||
return false;
|
||||
}
|
||||
|
||||
public static async void Initialize()
|
||||
public static async Task Initialize()
|
||||
{
|
||||
Users = JsonConvert.DeserializeObject<Userinfoplus[]>(Storage.Registry.Values[UsersStorageKey] as string ?? "") ?? new Userinfoplus[MaxUsersCount];
|
||||
int? lastUserIndex = Storage.Registry.Values[LastUserInfoKey] as int?;
|
||||
Users = JsonConvert.DeserializeObject<Userinfoplus[]>(StorageService.UserInfos ?? "") ?? new Userinfoplus[MaxUsersCount];
|
||||
int? lastUserIndex = StorageService.LastUserIndex;
|
||||
|
||||
if (lastUserIndex.HasValue && Users[lastUserIndex.Value] != null ||
|
||||
(lastUserIndex = Users.ToList().FindIndex(i => i != null)) > -1)
|
||||
@@ -146,12 +140,11 @@ namespace FoxTube.Services
|
||||
|
||||
await CurrentUser.Credential.RevokeTokenAsync(CancellationToken.None);
|
||||
|
||||
Storage.Registry.Values.Remove($"Subscriptions.{CurrentUser.UserInfo.Id}");
|
||||
CurrentUser = null;
|
||||
Users[Users.ToList().FindIndex(i => i.Id == userId)] = null;
|
||||
|
||||
Storage.Registry.Values[UsersStorageKey] = JsonConvert.SerializeObject(Users);
|
||||
Storage.Registry.Values[LastUserInfoKey] = null;
|
||||
StorageService.UserInfos = JsonConvert.SerializeObject(Users);
|
||||
StorageService.LastUserIndex = null;
|
||||
|
||||
if (Users.Any(i => i != null))
|
||||
await SwitchUser(Users.ToList().FindIndex(i => i != null));
|
||||
@@ -202,8 +195,8 @@ namespace FoxTube.Services
|
||||
CurrentUser = await User.GetUser(credential);
|
||||
Users[userIndex] = CurrentUser.UserInfo;
|
||||
|
||||
Storage.Registry.Values[UsersStorageKey] = JsonConvert.SerializeObject(Users);
|
||||
Storage.Registry.Values[LastUserInfoKey] = userIndex;
|
||||
StorageService.UserInfos = JsonConvert.SerializeObject(Users);
|
||||
StorageService.LastUserIndex = userIndex;
|
||||
|
||||
credential.RefreshTokenUpdated += (s, e) => UpdateToken(CurrentUser.UserInfo.Id, credential.Token.RefreshToken);
|
||||
UpdateToken(CurrentUser.UserInfo.Id, credential.Token.RefreshToken);
|
||||
|
||||
@@ -18,18 +18,15 @@ namespace FoxTube.Utils
|
||||
|
||||
public static NativeAdsManagerV2 AdsManager => new NativeAdsManagerV2(ApplicationId, AdsId);
|
||||
|
||||
static AddonsInterop() =>
|
||||
UpdateStoreState();
|
||||
|
||||
public static async void UpdateStoreState()
|
||||
public static async Task<bool> UpdateProPurchasedState()
|
||||
{
|
||||
StoreProductQueryResult requset = await StoreContext.GetDefault().GetAssociatedStoreProductsAsync(new[] { "Durable" });
|
||||
|
||||
if (requset.Products[ProProductId].IsInUserCollection)
|
||||
return;
|
||||
return AdsDisabled = true;
|
||||
|
||||
Price = requset.Products[ProProductId].Price.FormattedPrice;
|
||||
AdsDisabled = false;
|
||||
return AdsDisabled = false;
|
||||
}
|
||||
|
||||
public static async Task<bool> PurchaseApp()
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel.Activation;
|
||||
using Windows.ApplicationModel.Background;
|
||||
using Windows.System.Power;
|
||||
using Windows.UI.Notifications;
|
||||
|
||||
namespace FoxTube.Utils
|
||||
{
|
||||
// TODO: Complete class
|
||||
public static class BackgroundManager
|
||||
{
|
||||
public static async Task PerformBackgroundTask(BackgroundActivatedEventArgs args)
|
||||
{
|
||||
|
||||
if (args.TaskInstance.TriggerDetails is ToastNotificationActionTriggerDetail details)
|
||||
{
|
||||
ProcessBackgroundAction(details.Argument);
|
||||
// TODO: Process toast parameters
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Restore user
|
||||
// TODO: Update subscriptions
|
||||
// TODO: Update homepage cache
|
||||
}
|
||||
|
||||
//var saverRequest = PowerManager.EnergySaverStatus;
|
||||
}
|
||||
|
||||
public static async Task ProcessBackgroundAction(string uri)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static async void RegisterBackgroundTasks()
|
||||
{
|
||||
var backgroundRequest = await BackgroundExecutionManager.RequestAccessAsync();
|
||||
if (backgroundRequest == BackgroundAccessStatus.DeniedBySystemPolicy || backgroundRequest == BackgroundAccessStatus.DeniedByUser)
|
||||
return;
|
||||
|
||||
RegisterBackgoundTask("FoxtubeToastBackground", new ToastNotificationActionTrigger());
|
||||
RegisterBackgoundTask("FoxtubeBackground", new TimeTrigger(15, false));
|
||||
}
|
||||
|
||||
private static void RegisterBackgoundTask(string taskName, IBackgroundTrigger trigger)
|
||||
{
|
||||
if (BackgroundTaskRegistration.AllTasks.Any(i => i.Value.Name.Equals(taskName)))
|
||||
return;
|
||||
|
||||
BackgroundTaskBuilder builder = new BackgroundTaskBuilder
|
||||
{
|
||||
Name = taskName,
|
||||
IsNetworkRequested = true
|
||||
};
|
||||
builder.SetTrigger(trigger);
|
||||
|
||||
BackgroundTaskRegistration registration = builder.Register();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ namespace FoxTube.Utils
|
||||
{
|
||||
if (!HasFeedbackHub)
|
||||
{
|
||||
Storage.SetValue(Storage.Settings.PromptFeedback, false);
|
||||
StorageService.PromptFeedback = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace FoxTube.Utils
|
||||
ContentDialogResult result = await dialog.ShowAsync();
|
||||
|
||||
if (result != ContentDialogResult.None)
|
||||
Storage.SetValue(Storage.Settings.PromptFeedback, false);
|
||||
StorageService.PromptFeedback = false;
|
||||
|
||||
if (result == ContentDialogResult.Primary)
|
||||
OpenFeedbackHub();
|
||||
@@ -80,7 +80,7 @@ namespace FoxTube.Utils
|
||||
ContentDialogResult result = await dialog.ShowAsync();
|
||||
|
||||
if (result != ContentDialogResult.None)
|
||||
Storage.SetValue(Storage.Settings.PromptReview, false);
|
||||
StorageService.PromptFeedback = false;
|
||||
|
||||
if (result == ContentDialogResult.Primary)
|
||||
RequestStoreReview();
|
||||
|
||||
@@ -5,8 +5,8 @@ using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Windows.ApplicationModel;
|
||||
using FoxTube.Services;
|
||||
using System.Globalization;
|
||||
|
||||
namespace FoxTube.Utils
|
||||
{
|
||||
@@ -15,26 +15,29 @@ namespace FoxTube.Utils
|
||||
static readonly Stopwatch sw = new Stopwatch();
|
||||
public static TimeSpan Uptime
|
||||
{
|
||||
get => Storage.GetValue<TimeSpan?>(Storage.Metrics.Uptime) ?? TimeSpan.FromSeconds(0);
|
||||
set => Storage.SetValue(Storage.Metrics.Uptime, value);
|
||||
get => StorageService.Uptime;
|
||||
set => StorageService.Uptime = value;
|
||||
}
|
||||
|
||||
public static string CurrentVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
PackageVersion v = Package.Current.Id.Version;
|
||||
return $"{v.Major}.{v.Minor}.{v.Revision}.{v.Build}";
|
||||
// TODO: Remove on release
|
||||
/*PackageVersion v = Package.Current.Id.Version;
|
||||
return $"{v.Major}.{v.Minor}.{v.Revision}.{v.Build}";*/
|
||||
return "2.0 Preview 1";
|
||||
}
|
||||
}
|
||||
|
||||
static Metrics()
|
||||
{
|
||||
sw.Start();
|
||||
if (!Storage.GetValue<bool>(Storage.Settings.AllowAnalytics))
|
||||
if (!SettingsService.AllowAnalytics)
|
||||
return;
|
||||
|
||||
AppCenter.Start(SecretConstants.MetricsId, typeof(Analytics), typeof(Crashes));
|
||||
AppCenter.SetCountryCode(Storage.GetValue<string>(Storage.Settings.Region));
|
||||
AppCenter.SetCountryCode(RegionInfo.CurrentRegion.TwoLetterISORegionName);
|
||||
AppCenter.LogLevel = LogLevel.Verbose;
|
||||
}
|
||||
|
||||
@@ -43,7 +46,7 @@ namespace FoxTube.Utils
|
||||
sw.Stop();
|
||||
Uptime += sw.Elapsed;
|
||||
|
||||
if (Storage.GetValue<bool>(Storage.Settings.AllowAnalytics))
|
||||
if (SettingsService.AllowAnalytics)
|
||||
AddEvent("Session closed",
|
||||
("Duration", sw.Elapsed.ToString()),
|
||||
("Spend time total", Uptime.ToString()));
|
||||
@@ -51,7 +54,7 @@ namespace FoxTube.Utils
|
||||
|
||||
public static void AddEvent(string eventName, params (string key, string value)[] details)
|
||||
{
|
||||
if (Storage.GetValue<bool>(Storage.Settings.AllowAnalytics))
|
||||
if (SettingsService.AllowAnalytics)
|
||||
Analytics.TrackEvent(eventName,
|
||||
details.Length < 1 ? null :
|
||||
details.Select(i => new KeyValuePair<string, string>(i.key, i.value)) as Dictionary<string, string>);
|
||||
@@ -59,7 +62,7 @@ namespace FoxTube.Utils
|
||||
|
||||
public static void SendReport(Exception exception, ErrorAttachmentLog[] logs = null, params (string key, string value)[] details)
|
||||
{
|
||||
if (Storage.GetValue<bool>(Storage.Settings.AllowAnalytics))
|
||||
if (SettingsService.AllowAnalytics)
|
||||
{
|
||||
logs ??= new ErrorAttachmentLog[0];
|
||||
Crashes.TrackError(exception ?? new Exception("Unknown exception"),
|
||||
|
||||
@@ -11,6 +11,8 @@ namespace FoxTube.Utils
|
||||
public static class SecretConstants
|
||||
{
|
||||
public const string YoutubeApiKey = "AIzaSyBgHrCnrlzlVmk0cJKL8RqP9Y8x6XSuk_0";
|
||||
public const string BloggerApiKey = "AIzaSyD7tpbuvmYDv9h4udo9L_g3r0sLPFAnN00";
|
||||
public const string BlogId = "8566398713922921363";
|
||||
public const string MetricsId = "45774462-9ea7-438a-96fc-03982666f39e";
|
||||
public const string ProAddonId = "9NP1QK556625";
|
||||
public const string AdsUnitId = "1100044398";
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
using System.Linq;
|
||||
using Microsoft.Toolkit.Uwp.Notifications;
|
||||
using Google.Apis.Blogger.v3.Data;
|
||||
using Windows.UI.Notifications;
|
||||
using AngleSharp.Html.Parser;
|
||||
|
||||
namespace FoxTube.Utils
|
||||
{
|
||||
public static class ToastTemplates
|
||||
{
|
||||
public static ToastNotification GetBlogpostToast(Post post)
|
||||
{
|
||||
ToastContent toastContent = new ToastContent
|
||||
{
|
||||
Visual = new ToastVisual
|
||||
{
|
||||
BindingGeneric = new ToastBindingGeneric
|
||||
{
|
||||
Children =
|
||||
{
|
||||
new AdaptiveText
|
||||
{
|
||||
Text = new BindableString(post.Title)
|
||||
},
|
||||
new AdaptiveText()
|
||||
{
|
||||
Text = new BindableString(new HtmlParser().ParseDocument(post.Content).QuerySelector("p").TextContent),
|
||||
HintMaxLines = 2
|
||||
}
|
||||
},
|
||||
AppLogoOverride = new ToastGenericAppLogo
|
||||
{
|
||||
Source = post.Author.Image.Url,
|
||||
HintCrop = ToastGenericAppLogoCrop.Circle
|
||||
}
|
||||
}
|
||||
},
|
||||
Launch = $"Settings/Inbox/{post.Id}",
|
||||
ActivationType = ToastActivationType.Foreground
|
||||
};
|
||||
|
||||
if (post.Images.Count > 0)
|
||||
toastContent.Visual.BindingGeneric.HeroImage = new ToastGenericHeroImage
|
||||
{
|
||||
Source = post.Images.FirstOrDefault()?.Url
|
||||
};
|
||||
|
||||
return new ToastNotification(toastContent.GetXml());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
using System;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.Security.Credentials;
|
||||
using Windows.UI;
|
||||
using Windows.UI.ViewManagement;
|
||||
|
||||
namespace FoxTube.Utils
|
||||
{
|
||||
@@ -29,11 +31,36 @@ namespace FoxTube.Utils
|
||||
public static async void InitializeFailsafeProtocol()
|
||||
{
|
||||
Metrics.AddEvent("Failsafe protocol initiated");
|
||||
await Storage.ResetStorage();
|
||||
await StorageService.ClearStorage();
|
||||
PasswordVault passwordVault = new PasswordVault();
|
||||
foreach (PasswordCredential credential in passwordVault.RetrieveAll())
|
||||
passwordVault.Remove(credential);
|
||||
RestartApp();
|
||||
}
|
||||
|
||||
public static void UpdateTitleBarTheme(bool isDark)
|
||||
{
|
||||
ApplicationViewTitleBar titleBar = ApplicationView.GetForCurrentView().TitleBar;
|
||||
titleBar.ButtonBackgroundColor = Colors.Transparent;
|
||||
titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
|
||||
titleBar.ButtonInactiveForegroundColor = Colors.Gray;
|
||||
|
||||
if (isDark)
|
||||
{
|
||||
titleBar.ButtonForegroundColor =
|
||||
titleBar.ButtonHoverForegroundColor =
|
||||
titleBar.ButtonPressedForegroundColor = Colors.White;
|
||||
titleBar.ButtonHoverBackgroundColor = Color.FromArgb(50, 255, 255, 255);
|
||||
titleBar.ButtonPressedBackgroundColor = Color.FromArgb(30, 255, 255, 255);
|
||||
}
|
||||
else
|
||||
{
|
||||
titleBar.ButtonForegroundColor =
|
||||
titleBar.ButtonHoverForegroundColor =
|
||||
titleBar.ButtonPressedForegroundColor = Colors.Black;
|
||||
titleBar.ButtonHoverBackgroundColor = Color.FromArgb(50, 0, 0, 0);
|
||||
titleBar.ButtonPressedBackgroundColor = Color.FromArgb(70, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,16 @@
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
|
||||
<ResourceDictionary Source="ResourceDictionaries/NavigationViewTemplate.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<SolidColorBrush x:Key="SplashScreenBackground" Color="#404040"/>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<SolidColorBrush x:Key="SplashScreenBackground" Color="White"/>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
<Color x:Key="SystemAccentColor">Red</Color>
|
||||
|
||||
|
||||
+31
-60
@@ -1,11 +1,8 @@
|
||||
using System;
|
||||
using FoxTube.Services;
|
||||
using FoxTube.Utils;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.ApplicationModel.Activation;
|
||||
using Windows.UI;
|
||||
using Windows.UI.Popups;
|
||||
using Windows.UI.ViewManagement;
|
||||
using Windows.ApplicationModel.Background;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
@@ -21,52 +18,50 @@ namespace FoxTube
|
||||
UnhandledException += ErrorOccured;
|
||||
}
|
||||
|
||||
protected override async void OnLaunched(LaunchActivatedEventArgs args)
|
||||
protected override void OnLaunched(LaunchActivatedEventArgs args)
|
||||
{
|
||||
try
|
||||
{
|
||||
await UserManagement.Initialize();
|
||||
await StoreInterop.UpdateStoreState();
|
||||
if (Settings.LastReviewedVersion != Metrics.CurrentVersion)
|
||||
Inbox.PushChangelog();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Metrics.SendReport(new Exception("OuLaunch initialization failed", e));
|
||||
await new MessageDialog("There can be a temporary server issue or weak internet connection. Please, check your internet connection and try again later", "Something went wrong...").ShowAsync();
|
||||
Utils.Utils.CloseApp();
|
||||
base.OnLaunched(args);
|
||||
ActivateWindow(args);
|
||||
}
|
||||
|
||||
if (!args.PrelaunchActivated && Window.Current.Content == null)
|
||||
Window.Current.Content = new MainPage();
|
||||
Window.Current.Activate();
|
||||
}
|
||||
|
||||
protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
|
||||
protected override async void OnBackgroundActivated(BackgroundActivatedEventArgs args)
|
||||
{
|
||||
var deferral = args.TaskInstance.GetDeferral();
|
||||
base.OnBackgroundActivated(args);
|
||||
BackgroundTaskDeferral defferal = args.TaskInstance.GetDeferral();
|
||||
|
||||
deferral.Complete();
|
||||
await BackgroundManager.PerformBackgroundTask(args);
|
||||
|
||||
defferal.Complete();
|
||||
}
|
||||
|
||||
protected override void OnActivated(IActivatedEventArgs e)
|
||||
{
|
||||
base.OnActivated(e);
|
||||
ActivateWindow(e);
|
||||
}
|
||||
|
||||
if (Window.Current.Content == null)
|
||||
Window.Current.Content = new MainPage();
|
||||
private void ActivateWindow(IActivatedEventArgs args)
|
||||
{
|
||||
if (!(Window.Current.Content is Frame rootFrame))
|
||||
Window.Current.Content = rootFrame = new Frame();
|
||||
|
||||
if (rootFrame.Content == null && args.PreviousExecutionState != ApplicationExecutionState.Running)
|
||||
{
|
||||
if (rootFrame.Content == null)
|
||||
rootFrame.Content = new SplashScreen(args);
|
||||
Window.Current.Activate();
|
||||
}
|
||||
|
||||
void OnSuspending(object sender, SuspendingEventArgs e)
|
||||
{
|
||||
Metrics.EndSession();
|
||||
}
|
||||
|
||||
async void ErrorOccured(object sender, Windows.UI.Xaml.UnhandledExceptionEventArgs e)
|
||||
private void OnSuspending(object sender, SuspendingEventArgs e)
|
||||
{
|
||||
Metrics.AddEvent("Application chrashed",
|
||||
Metrics.EndSession();
|
||||
// TODO: Perform suspending tasks (complete downloads or cancel closing)
|
||||
}
|
||||
|
||||
private async void ErrorOccured(object sender, Windows.UI.Xaml.UnhandledExceptionEventArgs e)
|
||||
{
|
||||
Metrics.AddEvent("Application crashed",
|
||||
("Exception", e.Exception.GetType().ToString()),
|
||||
("Message", e.Message),
|
||||
("StackTrace", e.Exception.StackTrace));
|
||||
@@ -79,46 +74,22 @@ namespace FoxTube
|
||||
Content = "It may be a bug or temporary server issues. Please, try again later\n\nIf this happens again try to reset your app settings or report the problem",
|
||||
PrimaryButtonText = "Report the problem",
|
||||
SecondaryButtonText = "Reset application",
|
||||
CloseButtonText = "Close",
|
||||
CloseButtonText = "Restart the app",
|
||||
DefaultButton = ContentDialogButton.Primary
|
||||
}.ShowAsync();
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case ContentDialogResult.Primary:
|
||||
Feedback.OpenFeedbackHub();
|
||||
FeedbackInterop.OpenFeedbackHub();
|
||||
break;
|
||||
case ContentDialogResult.Secondary:
|
||||
Utils.Utils.InitializeFailsafeProtocol();
|
||||
break;
|
||||
default:
|
||||
Utils.Utils.RestartApp();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateTitleBar(bool isDark)
|
||||
{
|
||||
ApplicationViewTitleBar titleBar = ApplicationView.GetForCurrentView().TitleBar;
|
||||
titleBar.ButtonBackgroundColor = Colors.Transparent;
|
||||
titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
|
||||
titleBar.ButtonInactiveForegroundColor = Colors.Gray;
|
||||
|
||||
if (isDark)
|
||||
{
|
||||
titleBar.ButtonForegroundColor =
|
||||
titleBar.ButtonHoverForegroundColor =
|
||||
titleBar.ButtonPressedForegroundColor = Colors.White;
|
||||
titleBar.ButtonHoverBackgroundColor = Color.FromArgb(50, 255, 255, 255);
|
||||
titleBar.ButtonPressedBackgroundColor = Color.FromArgb(30, 255, 255, 255);
|
||||
}
|
||||
else
|
||||
{
|
||||
titleBar.ButtonForegroundColor =
|
||||
titleBar.ButtonHoverForegroundColor =
|
||||
titleBar.ButtonPressedForegroundColor = Colors.Black;
|
||||
titleBar.ButtonHoverBackgroundColor = Color.FromArgb(50, 0, 0, 0);
|
||||
titleBar.ButtonPressedBackgroundColor = Color.FromArgb(70, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,9 @@ using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
using FoxTube.Models;
|
||||
using FoxTube.Views.HomeSections;
|
||||
using FoxTube.Views;
|
||||
using FoxTube.Services;
|
||||
|
||||
namespace FoxTube.Utils
|
||||
{
|
||||
@@ -10,26 +13,25 @@ namespace FoxTube.Utils
|
||||
{
|
||||
public static List<Microsoft.UI.Xaml.Controls.NavigationViewItemBase> GetMenuItems(bool authorized)
|
||||
{
|
||||
List<Microsoft.UI.Xaml.Controls.NavigationViewItemBase> list = new List<Microsoft.UI.Xaml.Controls.NavigationViewItemBase>
|
||||
{
|
||||
GetItem("Home", new SymbolIcon(Symbol.Home), "home")
|
||||
};
|
||||
List<Microsoft.UI.Xaml.Controls.NavigationViewItemBase> list = new List<Microsoft.UI.Xaml.Controls.NavigationViewItemBase>();
|
||||
|
||||
if (authorized)
|
||||
list.AddRange(new Microsoft.UI.Xaml.Controls.NavigationViewItemBase[]
|
||||
{
|
||||
GetItem("Subscriptions", new SymbolIcon(Symbol.People), "subscriptions"),
|
||||
GetItem("Home", new SymbolIcon(Symbol.Home), typeof(HomeView)),
|
||||
|
||||
new Microsoft.UI.Xaml.Controls.NavigationViewItemHeader { Content = "Library" },
|
||||
GetItem("History", new FontIcon { Glyph = "\xE81C" }, "history"),
|
||||
GetItem("Liked videos", new SymbolIcon(Symbol.Like), "liked"),
|
||||
GetItem("Watch later", new SymbolIcon(Symbol.Clock), "watchLater"),
|
||||
GetItem("Downloads", new SymbolIcon(Symbol.Download), "downloads")
|
||||
GetItem("History", new FontIcon { Glyph = "\xE81C" }, typeof(HistoryView)),
|
||||
GetItem("Liked videos", new SymbolIcon(Symbol.Like), (typeof(PlaylistView), UserService.CurrentUser.Channel.ContentDetails.RelatedPlaylists.Likes)),
|
||||
GetItem("Watch later", new SymbolIcon(Symbol.Clock), (typeof(PlaylistView), "WL")),
|
||||
GetItem("Downloads", new SymbolIcon(Symbol.Download), typeof(DownloadsView)),
|
||||
GetItem("Subscriptions", new SymbolIcon(Symbol.People), typeof(SubscriptionsView))
|
||||
});
|
||||
else
|
||||
list.AddRange(new Microsoft.UI.Xaml.Controls.NavigationViewItemBase[]
|
||||
{
|
||||
GetItem("Downloads", new SymbolIcon(Symbol.Download), "downloads"),
|
||||
GetItem("Home", new SymbolIcon(Symbol.Home), typeof(TrendingView)),
|
||||
GetItem("Downloads", new SymbolIcon(Symbol.Download), typeof(DownloadsView)),
|
||||
|
||||
new Microsoft.UI.Xaml.Controls.NavigationViewItemHeader { Content = "Best of YouTube" },
|
||||
GetItem("Music", new FontIcon { Glyph = "\xE189" }, "UC-9-kyTW8ZkZNDHQJ6FgpwQ"),
|
||||
@@ -44,7 +46,7 @@ namespace FoxTube.Utils
|
||||
return list;
|
||||
}
|
||||
|
||||
private static Microsoft.UI.Xaml.Controls.NavigationViewItem GetItem(string content, IconElement icon, string tag) =>
|
||||
private static Microsoft.UI.Xaml.Controls.NavigationViewItem GetItem(string content, IconElement icon, object tag) =>
|
||||
new Microsoft.UI.Xaml.Controls.NavigationViewItem
|
||||
{
|
||||
Content = content,
|
||||
@@ -54,29 +56,29 @@ namespace FoxTube.Utils
|
||||
|
||||
public static Microsoft.UI.Xaml.Controls.NavigationViewItem GenerateItemFromSubscription(Subscription subscription)
|
||||
{
|
||||
StackPanel stack = new StackPanel
|
||||
Grid grid = new Grid
|
||||
{
|
||||
Orientation = Orientation.Horizontal,
|
||||
Padding = new Thickness(5),
|
||||
Margin = new Thickness(-5, 0, 0, 0)
|
||||
ColumnSpacing = 12
|
||||
};
|
||||
|
||||
stack.Children.Add(new Microsoft.UI.Xaml.Controls.PersonPicture
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(20) });
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition());
|
||||
|
||||
grid.Children.Add(new Microsoft.UI.Xaml.Controls.PersonPicture
|
||||
{
|
||||
Height = 20,
|
||||
Margin = new Thickness(-5, 0, 15, 0),
|
||||
Width = 20,
|
||||
ProfilePicture = new BitmapImage().LoadImage(subscription.Avatar.Default__.Url, 20, 20)
|
||||
});
|
||||
|
||||
stack.Children.Add(new TextBlock
|
||||
grid.Children.Add(new TextBlock
|
||||
{
|
||||
FontSize = 14,
|
||||
Text = subscription.Title
|
||||
});
|
||||
Grid.SetColumn(grid.Children[1] as TextBlock, 1);
|
||||
|
||||
return new Microsoft.UI.Xaml.Controls.NavigationViewItem
|
||||
{
|
||||
Content = stack,
|
||||
Content = grid,
|
||||
Tag = subscription.ChannelId
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
namespace FoxTube
|
||||
{
|
||||
public enum NavigationTarget
|
||||
{
|
||||
Home,
|
||||
Settings,
|
||||
Downloads,
|
||||
Subscriptions
|
||||
}
|
||||
|
||||
public static class Navigation
|
||||
{
|
||||
public static NavigationTarget CurrentPage { get; private set; }
|
||||
public static object CurrentParameter { get; private set; }
|
||||
|
||||
public static void NavigateTo(NavigationTarget destination) =>
|
||||
NavigateTo(destination, null);
|
||||
|
||||
public static void NavigateTo(NavigationTarget destination, object parameters)
|
||||
{
|
||||
MainPage.Current.Navigate(destination switch
|
||||
{
|
||||
NavigationTarget.Settings => typeof(Views.Settings),
|
||||
NavigationTarget.Downloads => typeof(Views.Downloads),
|
||||
NavigationTarget.Subscriptions => typeof(Views.Subscriptions),
|
||||
_ => UserManagement.Authorized ? typeof(Views.Home) : typeof(Views.HomeSections.Trending),
|
||||
},
|
||||
parameters);
|
||||
|
||||
CurrentPage = destination;
|
||||
CurrentParameter = parameters;
|
||||
}
|
||||
|
||||
public static void RefreshCurrentPage() =>
|
||||
MainPage.Current.Refresh();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace FoxTube.Pages
|
||||
{
|
||||
public class ScrollPage : Page
|
||||
{
|
||||
public ScrollViewer ScrollViewer => base.Content as ScrollViewer;
|
||||
public new UIElement Content => ScrollViewer.Content as UIElement;
|
||||
|
||||
public ScrollPage()
|
||||
{
|
||||
base.Content = new ScrollViewer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace FoxTube.Classes
|
||||
{
|
||||
public class TemplatedPage : Page
|
||||
{
|
||||
public UIElement PageDummy
|
||||
{
|
||||
get => ((base.Content as Grid).Children[0] as ContentPresenter).Content as UIElement;
|
||||
set => ((base.Content as Grid).Children[0] as ContentPresenter).Content = value;
|
||||
}
|
||||
public new UIElement Content
|
||||
{
|
||||
get => ((base.Content as Grid).Children[1] as ContentPresenter).Content as UIElement;
|
||||
set => ((base.Content as Grid).Children[1] as ContentPresenter).Content = value;
|
||||
}
|
||||
|
||||
public TemplatedPage()
|
||||
{
|
||||
Grid grid = new Grid();
|
||||
grid.Children.Add(new ContentPresenter());
|
||||
grid.Children.Add(new ContentPresenter());
|
||||
base.Content = grid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,90 +2,160 @@
|
||||
x:Class="FoxTube.Controls.AccountManager"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:data="using:Google.Apis.Oauth2.v2.Data"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
xmlns:ui="using:Microsoft.UI.Xaml.Controls"
|
||||
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls" xmlns:data="using:Google.Apis.Oauth2.v2.Data"
|
||||
Height="32"
|
||||
Padding="10,0"
|
||||
Background="Transparent"
|
||||
CornerRadius="0"
|
||||
Loaded="AppBarButton_Loaded"
|
||||
Style="{StaticResource ButtonRevealStyle}"
|
||||
CornerRadius="0"
|
||||
Padding="10,0"
|
||||
Height="32"
|
||||
Background="Transparent">
|
||||
mc:Ignorable="d">
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<FontIcon Glyph="" x:Name="icon" FontSize="15" Visibility="Visible"/>
|
||||
<PersonPicture Width="20" x:Name="profileIcon" Visibility="Collapsed"/>
|
||||
<TextBlock x:Name="buttonLabel" Text="Sign in" Margin="10,0,0,0" Style="{StaticResource CaptionTextBlockStyle}" VerticalAlignment="Center"/>
|
||||
<FontIcon
|
||||
x:Name="icon"
|
||||
FontSize="15"
|
||||
Glyph=""
|
||||
Visibility="Visible" />
|
||||
<PersonPicture
|
||||
x:Name="profileIcon"
|
||||
Width="20"
|
||||
Visibility="Collapsed" />
|
||||
<TextBlock
|
||||
x:Name="buttonLabel"
|
||||
Margin="10,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="Sign in" />
|
||||
</StackPanel>
|
||||
|
||||
<Button.Flyout>
|
||||
<Flyout Opening="Flyout_Opening">
|
||||
<StackPanel Margin="-12" Width="300">
|
||||
<StackPanel Width="300" Margin="-12">
|
||||
<Grid Height="60">
|
||||
<controls:ImageEx x:Name="bannerImage" Stretch="UniformToFill"
|
||||
<controls:ImageEx
|
||||
x:Name="bannerImage"
|
||||
PlaceholderSource="/Assets/DefaultChannelBanner.png"
|
||||
PlaceholderStretch="UniformToFill"/>
|
||||
PlaceholderStretch="UniformToFill"
|
||||
Stretch="UniformToFill" />
|
||||
|
||||
<Grid Padding="10" ColumnSpacing="20" RequestedTheme="Dark">
|
||||
<Grid
|
||||
Padding="10"
|
||||
ColumnSpacing="20"
|
||||
RequestedTheme="Dark">
|
||||
<Grid.Background>
|
||||
<AcrylicBrush FallbackColor="Transparent" TintColor="Black" TintOpacity="0" TintLuminosityOpacity=".5" Opacity=".9"/>
|
||||
<AcrylicBrush
|
||||
FallbackColor="Transparent"
|
||||
Opacity=".9"
|
||||
TintColor="Black"
|
||||
TintLuminosityOpacity=".5"
|
||||
TintOpacity="0" />
|
||||
</Grid.Background>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<PersonPicture Height="40" x:Name="avatar"/>
|
||||
<PersonPicture x:Name="avatar" Height="40" />
|
||||
<StackPanel Grid.Column="1">
|
||||
<TextBlock x:Name="name" Text="[Name]"/>
|
||||
<TextBlock x:Name="email" Text="[email]" FontStyle="Italic"/>
|
||||
<TextBlock x:Name="name" Text="[Name]" />
|
||||
<TextBlock
|
||||
x:Name="email"
|
||||
FontStyle="Italic"
|
||||
Text="[email]" />
|
||||
</StackPanel>
|
||||
<Button FontFamily="Segoe MDL2 Assets" Content="" ToolTipService.ToolTip="Account settings" Grid.Column="2" Background="Transparent"/>
|
||||
<Button
|
||||
Grid.Column="2"
|
||||
Background="Transparent"
|
||||
Content=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
ToolTipService.ToolTip="Account settings" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<NavigationViewList>
|
||||
<NavigationViewItem Tapped="NavigationViewItem_Tapped" Icon="Contact" Content="My channel" Tag="channel"/>
|
||||
<NavigationViewItem Tapped="NavigationViewItem_Tapped" Icon="Upload" Content="Upload a video" Tag="upload"/>
|
||||
<NavigationViewItem Tapped="NavigationViewItem_Tapped" Content="Start a broadcast" Tag="broadcast">
|
||||
<NavigationViewItem
|
||||
Content="My channel"
|
||||
Icon="Contact"
|
||||
Tag="channel"
|
||||
Tapped="NavigationViewItem_Tapped" />
|
||||
<NavigationViewItem
|
||||
Content="Upload a video"
|
||||
Icon="Upload"
|
||||
Tag="upload"
|
||||
Tapped="NavigationViewItem_Tapped" />
|
||||
<NavigationViewItem
|
||||
Content="Start a broadcast"
|
||||
Tag="broadcast"
|
||||
Tapped="NavigationViewItem_Tapped">
|
||||
<NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
<FontIcon Glyph="" />
|
||||
</NavigationViewItem.Icon>
|
||||
</NavigationViewItem>
|
||||
<NavigationViewItem Tapped="NavigationViewItem_Tapped" Content="Creator Stuido" Tag="creatorStudio">
|
||||
<NavigationViewItem
|
||||
Content="Creator Stuido"
|
||||
Tag="creatorStudio"
|
||||
Tapped="NavigationViewItem_Tapped">
|
||||
<NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
<FontIcon Glyph="" />
|
||||
</NavigationViewItem.Icon>
|
||||
</NavigationViewItem>
|
||||
</NavigationViewList>
|
||||
<NavigationViewList ItemClick="SwitchUser" IsItemClickEnabled="True" x:Name="usersList">
|
||||
<NavigationViewList
|
||||
x:Name="usersList"
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="SwitchUser">
|
||||
<NavigationViewList.ItemTemplate>
|
||||
<DataTemplate x:DataType="data:Userinfoplus">
|
||||
<StackPanel Orientation="Horizontal" Padding="5" Margin="-5,0,0,0">
|
||||
<StackPanel
|
||||
Margin="-5,0,0,0"
|
||||
Padding="5"
|
||||
Orientation="Horizontal">
|
||||
<ui:PersonPicture Height="20" Margin="-5,0,15,0">
|
||||
<ui:PersonPicture.ProfilePicture>
|
||||
<BitmapImage UriSource="{Binding Picture}" DecodePixelHeight="20" DecodePixelWidth="20"/>
|
||||
<BitmapImage
|
||||
DecodePixelHeight="20"
|
||||
DecodePixelWidth="20"
|
||||
UriSource="{Binding Picture}" />
|
||||
</ui:PersonPicture.ProfilePicture>
|
||||
</ui:PersonPicture>
|
||||
<StackPanel>
|
||||
<TextBlock FontSize="14" Text="{Binding Name, TargetNullValue='[name]'}"/>
|
||||
<TextBlock Style="{StaticResource CaptionTextBlockStyle}" Text="{Binding Email}" Margin="0,-6,0,0"/>
|
||||
<TextBlock FontSize="14" Text="{Binding Name, TargetNullValue='[name]'}" />
|
||||
<TextBlock
|
||||
Margin="0,-6,0,0"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{Binding Email}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</NavigationViewList.ItemTemplate>
|
||||
<NavigationViewItemHeader Content="Switch account"/>
|
||||
<NavigationViewItemHeader Content="Switch account" />
|
||||
</NavigationViewList>
|
||||
<NavigationViewList>
|
||||
<NavigationViewItemSeparator/>
|
||||
<NavigationViewItem Tapped="NavigationViewItem_Tapped" x:Name="addAccountButton" Content="Add account" Tag="addUser" Icon="Add"/>
|
||||
<NavigationViewItemSeparator />
|
||||
<NavigationViewItem
|
||||
x:Name="addAccountButton"
|
||||
Content="Add account"
|
||||
Icon="Add"
|
||||
Tag="addUser"
|
||||
Tapped="NavigationViewItem_Tapped" />
|
||||
<NavigationViewItem Tapped="Incognito_Tapped">
|
||||
<ToggleSwitch x:Name="incognito" OnContent="Incognito mode" OffContent="Incognito mode" Toggled="Icognito_Toggled"/>
|
||||
<ToggleSwitch
|
||||
x:Name="incognito"
|
||||
OffContent="Incognito mode"
|
||||
OnContent="Incognito mode"
|
||||
Toggled="Icognito_Toggled" />
|
||||
</NavigationViewItem>
|
||||
<NavigationViewItem Tapped="NavigationViewItem_Tapped" Content="Sign out" Foreground="Red" Tag="logout">
|
||||
<NavigationViewItem
|
||||
Content="Sign out"
|
||||
Foreground="Red"
|
||||
Tag="logout"
|
||||
Tapped="NavigationViewItem_Tapped">
|
||||
<NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
<FontIcon Glyph="" />
|
||||
</NavigationViewItem.Icon>
|
||||
</NavigationViewItem>
|
||||
</NavigationViewList>
|
||||
|
||||
@@ -4,6 +4,9 @@ using FoxTube.Models;
|
||||
using System.Linq;
|
||||
using Google.Apis.Oauth2.v2.Data;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
using FoxTube.Services;
|
||||
using System;
|
||||
using FoxTube.Utils;
|
||||
|
||||
namespace FoxTube.Controls
|
||||
{
|
||||
@@ -14,27 +17,40 @@ namespace FoxTube.Controls
|
||||
public AccountManager() =>
|
||||
InitializeComponent();
|
||||
|
||||
private async void Flyout_Opening(object sender, object e)
|
||||
private async void Flyout_Opening(object sender, object args)
|
||||
{
|
||||
if (UserManagement.Authorized)
|
||||
if (UserService.Authorized)
|
||||
return;
|
||||
|
||||
(sender as Flyout).Hide();
|
||||
|
||||
await UserManagement.AddUser();
|
||||
try
|
||||
{
|
||||
await UserService.AddUser();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await new ContentDialog
|
||||
{
|
||||
Title = "Failed to add account",
|
||||
Content = "Something went wrong. Please, try again later"
|
||||
}.ShowAsync();
|
||||
|
||||
Metrics.SendReport(new Exception("Failed to login", e));
|
||||
}
|
||||
}
|
||||
|
||||
private void AppBarButton_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (UserManagement.Authorized)
|
||||
if (UserService.Authorized)
|
||||
UpdateData(true);
|
||||
|
||||
UserManagement.UserStateUpdated += (s, e) => UpdateData(e);
|
||||
UserService.UserStateUpdated += (s, e) => UpdateData(e);
|
||||
}
|
||||
|
||||
private void UpdateData(bool authorized)
|
||||
{
|
||||
CurrentUser = UserManagement.CurrentUser;
|
||||
CurrentUser = UserService.CurrentUser;
|
||||
if (authorized)
|
||||
{
|
||||
buttonLabel.Text = name.Text = CurrentUser.Channel.Snippet.Title;
|
||||
@@ -49,11 +65,11 @@ namespace FoxTube.Controls
|
||||
icon.Visibility = Visibility.Collapsed;
|
||||
profileIcon.Visibility = Visibility.Visible;
|
||||
|
||||
var users = UserManagement.Users.Where(i => i.Id != CurrentUser.UserInfo.Id).ToList();
|
||||
var users = UserService.Users.Where(i => i.Id != CurrentUser.UserInfo.Id).ToList();
|
||||
usersList.ItemsSource = users;
|
||||
usersList.Visibility = users.Count > 0 ? Visibility.Visible : Visibility.Visible;
|
||||
|
||||
addAccountButton.Visibility = UserManagement.CanAddAccounts ? Visibility.Visible : Visibility.Collapsed;
|
||||
addAccountButton.Visibility = UserService.CanAddAccounts ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -68,7 +84,7 @@ namespace FoxTube.Controls
|
||||
private async void SwitchUser(object sender, ItemClickEventArgs e)
|
||||
{
|
||||
Userinfoplus user = (Userinfoplus)e.ClickedItem;
|
||||
await UserManagement.SwitchUser(UserManagement.Users.ToList().IndexOf(user));
|
||||
await UserService.SwitchUser(UserService.Users.ToList().IndexOf(user));
|
||||
}
|
||||
|
||||
private async void NavigationViewItem_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
|
||||
@@ -81,10 +97,10 @@ namespace FoxTube.Controls
|
||||
case "creatorStudio":
|
||||
break;
|
||||
case "addUser":
|
||||
await UserManagement.AddUser();
|
||||
await UserService.AddUser();
|
||||
break;
|
||||
case "logout":
|
||||
await UserManagement.Logout();
|
||||
await UserService.Logout();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -98,22 +114,17 @@ namespace FoxTube.Controls
|
||||
MainPage.Current.RequestedTheme = ElementTheme.Dark;
|
||||
else
|
||||
{
|
||||
if (Settings.Theme == 0)
|
||||
MainPage.Current.RequestedTheme = ElementTheme.Light;
|
||||
else if (Settings.Theme == 1)
|
||||
MainPage.Current.RequestedTheme = ElementTheme.Dark;
|
||||
else
|
||||
MainPage.Current.RequestedTheme = ElementTheme.Default;
|
||||
|
||||
if (RequestedTheme == ElementTheme.Default)
|
||||
App.UpdateTitleBar(Application.Current.RequestedTheme == ApplicationTheme.Dark);
|
||||
if ((Window.Current.Content as Frame).RequestedTheme == ElementTheme.Default)
|
||||
Utils.Utils.UpdateTitleBarTheme(Application.Current.RequestedTheme == ApplicationTheme.Dark);
|
||||
else
|
||||
App.UpdateTitleBar(MainPage.Current.RequestedTheme == ElementTheme.Dark);
|
||||
Utils.Utils.UpdateTitleBarTheme(MainPage.Current.RequestedTheme == ElementTheme.Dark);
|
||||
}
|
||||
|
||||
UpdateLayout();
|
||||
MainPage.Current.UpdateLayout();
|
||||
|
||||
UserManagement.IncognitoMode = incognito.IsOn;
|
||||
UserService.IncognitoMode = incognito.IsOn;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using FoxTube.Utils;
|
||||
using FoxTube.Services;
|
||||
using FoxTube.Utils;
|
||||
using Microsoft.Advertising.WinRT.UI;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
@@ -10,7 +11,7 @@ namespace FoxTube.Controls.Cards
|
||||
/// </summary>
|
||||
public sealed partial class AdvertCard : UserControl
|
||||
{
|
||||
readonly NativeAdsManagerV2 manager = new NativeAdsManagerV2(StoreInterop.ApplicationId, StoreInterop.AdsId);
|
||||
readonly NativeAdsManagerV2 manager = AddonsInterop.AdsManager;
|
||||
NativeAdV2 advert;
|
||||
|
||||
public AdvertCard()
|
||||
@@ -23,6 +24,7 @@ namespace FoxTube.Controls.Cards
|
||||
|
||||
void ErrorOccurred(object sender, NativeAdErrorEventArgs e)
|
||||
{
|
||||
UnsubscribeEvents();
|
||||
(Parent as Panel)?.Children.Remove(this);
|
||||
Metrics.AddEvent("Error has occured while loading ad",
|
||||
("Code", e.ErrorCode.ToString()),
|
||||
@@ -32,6 +34,7 @@ namespace FoxTube.Controls.Cards
|
||||
|
||||
void AdReady(object sender, NativeAdReadyEventArgs e)
|
||||
{
|
||||
UnsubscribeEvents();
|
||||
advert = e.NativeAd;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(advert.CallToActionText))
|
||||
@@ -43,9 +46,15 @@ namespace FoxTube.Controls.Cards
|
||||
|
||||
Opacity = 1;
|
||||
|
||||
Metrics.AddEvent("Advert loaded",
|
||||
("Region", Settings.Region),
|
||||
("Version", Metrics.CurrentVersion));
|
||||
/*Metrics.AddEvent("Advert loaded",
|
||||
("Region", Storage.GetValue<string>(Storage.Settings.Region)),
|
||||
("Version", Metrics.CurrentVersion));*/
|
||||
}
|
||||
|
||||
private void UnsubscribeEvents()
|
||||
{
|
||||
manager.AdReady -= AdReady;
|
||||
manager.ErrorOccurred -= ErrorOccurred;
|
||||
}
|
||||
|
||||
void UserControl_SizeChanged(object sender, SizeChangedEventArgs e) =>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using FoxTube.Services;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Pickers;
|
||||
@@ -41,7 +42,7 @@ namespace FoxTube.Controls.Dialogs
|
||||
|
||||
private async void ContentDialog_Loading(FrameworkElement sender, object args)
|
||||
{
|
||||
StorageFolder defaultFolder = await Services.DownloadsCenter.GetDefaultDownloadsFolder();
|
||||
StorageFolder defaultFolder = await DownloadsService.GetDefaultDownloadsFolder();
|
||||
location.Text = $"{defaultFolder.Name}\\{Meta.Title.ReplaceInvalidChars('_')}.mp4";
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace FoxTube.Controls.Dialogs
|
||||
public ProOfferDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
getButton.Content = $"Get for {StoreInterop.Price}!";
|
||||
getButton.Content = $"Get for {AddonsInterop.Price}!";
|
||||
}
|
||||
|
||||
private async void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) =>
|
||||
@@ -24,7 +24,7 @@ namespace FoxTube.Controls.Dialogs
|
||||
|
||||
private async Task Purchase()
|
||||
{
|
||||
if (!await StoreInterop.PurchaseApp())
|
||||
if (!await AddonsInterop.PurchaseApp())
|
||||
return;
|
||||
|
||||
ContentDialog dialog = new ContentDialog
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
</TransitionCollection>
|
||||
</controls:AdaptiveGridView.ItemContainerTransitions>
|
||||
|
||||
<controls:AdaptiveGridView.ItemTemplate>
|
||||
<!--<controls:AdaptiveGridView.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:VideoItem">
|
||||
<Grid RowSpacing="5" CornerRadius="5" Background="{ThemeResource SystemControlBackgroundChromeMediumBrush}" Padding="0,0,0,10">
|
||||
<Grid.RowDefinitions>
|
||||
@@ -85,7 +85,7 @@
|
||||
</Grid.ContextFlyout>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</controls:AdaptiveGridView.ItemTemplate>
|
||||
</controls:AdaptiveGridView.ItemTemplate>-->
|
||||
|
||||
<controls:AdaptiveGridView.Footer>
|
||||
<ProgressBar IsIndeterminate="True" x:Name="progressBar" Background="Transparent" VerticalAlignment="Bottom"/>
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace FoxTube.Controls
|
||||
|
||||
private void UserControl_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
feedbackButton.Visibility = Feedback.HasFeedbackHub ? Visibility.Visible : Visibility.Collapsed;
|
||||
feedbackButton.Visibility = FeedbackInterop.HasFeedbackHub ? Visibility.Visible : Visibility.Collapsed;
|
||||
|
||||
for (int i = 0; i < 25; i++)
|
||||
grid.Items.Add(new Image
|
||||
@@ -102,13 +102,13 @@ namespace FoxTube.Controls
|
||||
}
|
||||
|
||||
private void LeaveFeedback(object sender, RoutedEventArgs e) =>
|
||||
Feedback.OpenFeedbackHub();
|
||||
FeedbackInterop.OpenFeedbackHub();
|
||||
|
||||
private async void OpenNetworkSettings(object sender, RoutedEventArgs e) =>
|
||||
await Launcher.LaunchUriAsync("ms-settings:network".ToUri());
|
||||
|
||||
private void RefreshPage(object sender, RoutedEventArgs e) =>
|
||||
Navigation.RefreshCurrentPage();
|
||||
Navigation.Refresh();
|
||||
|
||||
private async void OpenTroubleshooter(object sender, RoutedEventArgs e) =>
|
||||
await Launcher.LaunchUriAsync("ms-settings:troubleshoot".ToUri());
|
||||
|
||||
+65
-32
@@ -106,7 +106,8 @@
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Classes\MenuItemsList.cs" />
|
||||
<Compile Include="Classes\Navigation.cs" />
|
||||
<Compile Include="Classes\ScrollPage.cs" />
|
||||
<Compile Include="Navigation.cs" />
|
||||
<Compile Include="Classes\ViewItemsCollection.cs" />
|
||||
<Compile Include="Controls\Dialogs\DownloadVideoDialog.xaml.cs">
|
||||
<DependentUpon>DownloadVideoDialog.xaml</DependentUpon>
|
||||
@@ -143,11 +144,20 @@
|
||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Views\Downloads.xaml.cs">
|
||||
<DependentUpon>Downloads.xaml</DependentUpon>
|
||||
<Compile Include="SplashScreen.xaml.cs">
|
||||
<DependentUpon>SplashScreen.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Home.xaml.cs">
|
||||
<DependentUpon>Home.xaml</DependentUpon>
|
||||
<Compile Include="Views\ChannelView.xaml.cs">
|
||||
<DependentUpon>ChannelView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\DownloadsView.xaml.cs">
|
||||
<DependentUpon>DownloadsView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\HistoryView.xaml.cs">
|
||||
<DependentUpon>HistoryView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\HomeView.xaml.cs">
|
||||
<DependentUpon>HomeView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\HomeSections\Recommended.xaml.cs">
|
||||
<DependentUpon>Recommended.xaml</DependentUpon>
|
||||
@@ -155,26 +165,29 @@
|
||||
<Compile Include="Views\HomeSections\Subscriptions.xaml.cs">
|
||||
<DependentUpon>Subscriptions.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\HomeSections\Trending.xaml.cs">
|
||||
<DependentUpon>Trending.xaml</DependentUpon>
|
||||
<Compile Include="Views\HomeSections\TrendingView.xaml.cs">
|
||||
<DependentUpon>TrendingView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Search.xaml.cs">
|
||||
<DependentUpon>Search.xaml</DependentUpon>
|
||||
<Compile Include="Views\PlaylistView.xaml.cs">
|
||||
<DependentUpon>PlaylistView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Settings.xaml.cs">
|
||||
<DependentUpon>Settings.xaml</DependentUpon>
|
||||
<Compile Include="Views\SearchView.xaml.cs">
|
||||
<DependentUpon>SearchView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsSections\About.xaml.cs">
|
||||
<DependentUpon>About.xaml</DependentUpon>
|
||||
<Compile Include="Views\SettingsSections\AboutSection.xaml.cs">
|
||||
<DependentUpon>AboutSection.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsSections\General.xaml.cs">
|
||||
<DependentUpon>General.xaml</DependentUpon>
|
||||
<Compile Include="Views\SettingsSections\PreferencesSection.xaml.cs">
|
||||
<DependentUpon>PreferencesSection.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SettingsSections\Inbox.xaml.cs">
|
||||
<DependentUpon>Inbox.xaml</DependentUpon>
|
||||
<Compile Include="Views\SettingsView.xaml.cs">
|
||||
<DependentUpon>SettingsView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Subscriptions.xaml.cs">
|
||||
<DependentUpon>Subscriptions.xaml</DependentUpon>
|
||||
<Compile Include="Views\SettingsSections\InboxSection.xaml.cs">
|
||||
<DependentUpon>InboxSection.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\SubscriptionsView.xaml.cs">
|
||||
<DependentUpon>SubscriptionsView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -296,11 +309,27 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\Downloads.xaml">
|
||||
<Page Include="ResourceDictionaries\NavigationViewTemplate.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\Home.xaml">
|
||||
<Page Include="SplashScreen.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\ChannelView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\DownloadsView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\HistoryView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\HomeView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
@@ -312,31 +341,35 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\HomeSections\Trending.xaml">
|
||||
<Page Include="Views\HomeSections\TrendingView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\Search.xaml">
|
||||
<Page Include="Views\PlaylistView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\Settings.xaml">
|
||||
<Page Include="Views\SearchView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsSections\About.xaml">
|
||||
<Page Include="Views\SettingsSections\AboutSection.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsSections\PreferencesSection.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsSections\General.xaml">
|
||||
<Page Include="Views\SettingsSections\InboxSection.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\SettingsSections\Inbox.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\Subscriptions.xaml">
|
||||
<Page Include="Views\SubscriptionsView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
@@ -352,7 +385,7 @@
|
||||
<Version>6.0.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.UI.Xaml">
|
||||
<Version>2.4.0</Version>
|
||||
<Version>2.4.2</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
+55
-33
@@ -10,29 +10,66 @@
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<Grid>
|
||||
<Border x:Name="AppTitleBar"
|
||||
VerticalAlignment="Top"
|
||||
Background="Transparent"
|
||||
Height="{Binding ElementName=NavigationViewControl, Path=CompactPaneLength}"
|
||||
Canvas.ZIndex="1">
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup>
|
||||
<VisualState>
|
||||
<VisualState.StateTriggers>
|
||||
<AdaptiveTrigger MinWindowWidth="800"/>
|
||||
</VisualState.StateTriggers>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ToolbarPanel.Margin" Value="0,0,200,0"/>
|
||||
<Setter Target="AppTitle.Opacity" Value="1"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState>
|
||||
<VisualState.StateTriggers>
|
||||
<AdaptiveTrigger MinWindowWidth="550"/>
|
||||
</VisualState.StateTriggers>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="AppTitle.Opacity" Value="1"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
|
||||
<TextBlock Text="FoxTube"
|
||||
<Grid.BackgroundTransition>
|
||||
<BrushTransition/>
|
||||
</Grid.BackgroundTransition>
|
||||
<Grid VerticalAlignment="Top" Height="40" Canvas.ZIndex="10" Margin="40,0,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="40"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button Width="40" Height="40" CornerRadius="0" Background="Transparent" Click="TogglePane">
|
||||
<FontIcon Glyph="" FontSize="16"/>
|
||||
</Button>
|
||||
|
||||
<Border Grid.Column="1" x:Name="AppTitleBar" VerticalAlignment="Stretch" Height="40" Background="Transparent">
|
||||
<TextBlock x:Name="AppTitle" Opacity="0"
|
||||
VerticalAlignment="Center" Margin="12,0"
|
||||
Style="{StaticResource CaptionTextBlockStyle}" />
|
||||
</Border>
|
||||
|
||||
<ui:NavigationView x:Name="NavigationViewControl"
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" VerticalAlignment="Top" x:Name="ToolbarPanel" Margin="0,0,140,0">
|
||||
<controls:AccountManager/>
|
||||
<Button x:Name="FeedbackButton" Click="LeaveFeedback_Click" ToolTipService.ToolTip="Leave feedback"
|
||||
Content="" Style="{StaticResource HeaderActionButton}"/>
|
||||
<Button x:Name="RefreshButton" Click="Refresh_Click" Content="" Style="{StaticResource HeaderActionButton}" ToolTipService.ToolTip="Refresh page" Opacity="0">
|
||||
<Button.OpacityTransition>
|
||||
<ScalarTransition/>
|
||||
</Button.OpacityTransition>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<ui:NavigationView Style="{StaticResource MainPageNavigationView}" x:Name="NavigationViewControl"
|
||||
IsTitleBarAutoPaddingEnabled="False"
|
||||
|
||||
DisplayModeChanged="NavigationView_DisplayModeChanged"
|
||||
|
||||
BackRequested="NavigationViewControl_BackRequested"
|
||||
ItemInvoked="NavigationViewControl_ItemInvoked"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<ui:NavigationView.PaneHeader>
|
||||
<TextBlock Style="{StaticResource TitleTextBlockStyle}" Text="Menu" VerticalAlignment="Center" Margin="10,0" Name="title"/>
|
||||
</ui:NavigationView.PaneHeader>
|
||||
IsPaneToggleButtonVisible="False"
|
||||
IsPaneOpen="True">
|
||||
|
||||
<ui:NavigationView.AutoSuggestBox>
|
||||
<AutoSuggestBox QueryIcon="Find" PlaceholderText="Search YouTube..." TextChanged="AutoSuggestBox_TextChanged" QuerySubmitted="AutoSuggestBox_QuerySubmitted" TextMemberPath="Text" >
|
||||
@@ -55,28 +92,13 @@
|
||||
<ui:NavigationView.PaneFooter>
|
||||
<NavigationViewList>
|
||||
<NavigationViewItemSeparator/>
|
||||
<NavigationViewItem Icon="Shop" Content="Get Pro" x:Name="removeAds" Tapped="RemoveAds_Tapped"/>
|
||||
<NavigationViewItem Icon="Shop" Content="Get Pro" x:Name="PurchaseButton" Tapped="RemoveAds_Tapped"/>
|
||||
</NavigationViewList>
|
||||
</ui:NavigationView.PaneFooter>
|
||||
|
||||
<Grid Margin="0,32,0,0">
|
||||
<Frame x:Name="content" Navigated="Content_Navigated"/>
|
||||
<Grid Margin="0,40,0,0">
|
||||
<Frame x:Name="ContentFrame" x:FieldModifier="public"/>
|
||||
</Grid>
|
||||
</ui:NavigationView>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Margin="0,0,0,0" HorizontalAlignment="Right" VerticalAlignment="Top" x:Name="toolbar">
|
||||
<controls:AccountManager/>
|
||||
<Button x:Name="leaveFeedback" Click="LeaveFeedback_Click" ToolTipService.ToolTip="Leave feedback"
|
||||
Content="" Style="{StaticResource HeaderActionButton}"/>
|
||||
<Button x:Name="refresh" Click="Refresh_Click" Content="" Style="{StaticResource HeaderActionButton}" ToolTipService.ToolTip="Refresh page" Opacity="0">
|
||||
<Button.OpacityTransition>
|
||||
<ScalarTransition/>
|
||||
</Button.OpacityTransition>
|
||||
</Button>
|
||||
|
||||
<Button Height="32" Width="46" Style="{StaticResource HeaderActionButton}" Margin="52,0,0,0" IsTabStop="False"/>
|
||||
<Button Height="32" Width="46" Style="{StaticResource HeaderActionButton}" IsTabStop="False"/>
|
||||
<Button Height="32" Width="46" Style="{StaticResource HeaderActionButton}" IsTabStop="False"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Page>
|
||||
+99
-131
@@ -4,12 +4,16 @@ using FoxTube.Utils;
|
||||
using FoxTube.Services;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using FoxTube.Models;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
using System.Reflection;
|
||||
using FoxTube.Views;
|
||||
using Google.Apis.YouTube.v3.Data;
|
||||
using FoxTube.Views.HomeSections;
|
||||
|
||||
// TODO: Fix header (UI)
|
||||
namespace FoxTube
|
||||
{
|
||||
public sealed partial class MainPage : Windows.UI.Xaml.Controls.Page
|
||||
@@ -21,91 +25,90 @@ namespace FoxTube
|
||||
Current = this;
|
||||
InitializeComponent();
|
||||
|
||||
#region Setup theme
|
||||
if (Settings.Theme == 0)
|
||||
RequestedTheme = ElementTheme.Light;
|
||||
else if (Settings.Theme == 1)
|
||||
RequestedTheme = ElementTheme.Dark;
|
||||
|
||||
if (RequestedTheme == ElementTheme.Default)
|
||||
App.UpdateTitleBar(Application.Current.RequestedTheme == ApplicationTheme.Dark);
|
||||
else
|
||||
App.UpdateTitleBar(RequestedTheme == ElementTheme.Dark);
|
||||
|
||||
Window.Current.SetTitleBar(AppTitleBar);
|
||||
AppTitle.Text = $"{Package.Current.DisplayName} ({Metrics.CurrentVersion})";
|
||||
|
||||
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
|
||||
#endregion
|
||||
PurchaseButton.Visibility = AddonsInterop.AdsDisabled ? Visibility.Collapsed : Visibility.Visible;
|
||||
if (!AddonsInterop.AdsDisabled)
|
||||
PurchaseButton.Content += $" ({AddonsInterop.Price})";
|
||||
|
||||
removeAds.Visibility = StoreInterop.AdsDisabled ? Visibility.Collapsed : Visibility.Visible;
|
||||
if (!StoreInterop.AdsDisabled)
|
||||
removeAds.Content += $" ({StoreInterop.Price})";
|
||||
if (!FeedbackInterop.HasFeedbackHub)
|
||||
FeedbackButton.Visibility = Visibility.Collapsed;
|
||||
|
||||
leaveFeedback.Visibility = Feedback.HasFeedbackHub ?
|
||||
Visibility.Visible : Visibility.Collapsed;
|
||||
Navigation.Navigated += Content_Navigated;
|
||||
|
||||
UserManagement.SubscriptionsChanged += UsersControl_SubscriptionsChanged;
|
||||
UserManagement.UserStateUpdated += UsersControl_UserStateUpdated;
|
||||
UsersControl_UserStateUpdated(this, UserManagement.Authorized);
|
||||
UserService.SubscriptionsChanged += UsersControl_SubscriptionsChanged;
|
||||
UserService.UserStateUpdated += UsersControl_UserStateUpdated;
|
||||
}
|
||||
|
||||
if (Settings.PromptReview)
|
||||
Feedback.PromptReview();
|
||||
if (Settings.PromptFeedback)
|
||||
Feedback.PromptFeedback();
|
||||
protected override void OnNavigatedFrom(NavigationEventArgs e)
|
||||
{
|
||||
base.OnNavigatedFrom(e);
|
||||
Current = null;
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
base.OnNavigatedTo(e);
|
||||
|
||||
Uri parameter = (e.Parameter as string)?.ToUri();
|
||||
if (parameter != null && parameter.Segments.Length > 0)
|
||||
{
|
||||
Type targetType = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(i => i.IsClass && i.Namespace.StartsWith("FoxTube.Views") && i.Name.ToLowerInvariant() == $"{parameter.Segments[0].ToLowerInvariant()}view");
|
||||
if (targetType != null)
|
||||
{
|
||||
Navigation.NavigateTo(targetType, e.Parameter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
UsersControl_UserStateUpdated(this, UserService.Authorized);
|
||||
}
|
||||
|
||||
#region Navigation
|
||||
private void Content_Navigated(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs args)
|
||||
private void Content_Navigated(object sender, NavigationEventArgs args)
|
||||
{
|
||||
NavigationViewControl.IsBackEnabled = content.CanGoBack;
|
||||
NavigationViewControl.IsBackEnabled = ContentFrame.CanGoBack;
|
||||
RefreshButton.Opacity = Convert.ToInt32(Attribute.IsDefined(args.SourcePageType, typeof(RefreshableAttribute)));
|
||||
|
||||
refresh.Opacity = Attribute.IsDefined(args.SourcePageType, typeof(RefreshableAttribute)) ? 1 : 0;
|
||||
|
||||
switch (args.SourcePageType.Name)
|
||||
NavigationViewControl.SelectedItem = args.SourcePageType.Name switch
|
||||
{
|
||||
case "Settings":
|
||||
NavigationViewControl.SelectedItem = NavigationViewControl.SettingsItem;
|
||||
break;
|
||||
case "Downloads":
|
||||
NavigationViewControl.SelectedItem = NavigationViewControl.MenuItems.FirstOrDefault(i => ((FrameworkElement)i).Tag as string == "downloads");
|
||||
break;
|
||||
case "Subscriptions":
|
||||
NavigationViewControl.SelectedItem = NavigationViewControl.MenuItems.FirstOrDefault(i => ((FrameworkElement)i).Tag as string == "subscriptions");
|
||||
break;
|
||||
case "Home":
|
||||
case "Trending":
|
||||
NavigationViewControl.SelectedItem = NavigationViewControl.MenuItems.FirstOrDefault(i => ((FrameworkElement)i).Tag as string == "home");
|
||||
break;
|
||||
case "Channel":
|
||||
NavigationViewControl.SelectedItem = NavigationViewControl.MenuItems.FirstOrDefault(i => ((FrameworkElement)i).Tag == args.Parameter);
|
||||
break;
|
||||
default:
|
||||
NavigationViewControl.SelectedItem = null;
|
||||
break;
|
||||
|
||||
// TODO: Update menu selector
|
||||
}
|
||||
nameof(SettingsView) => NavigationViewControl.SettingsItem,
|
||||
nameof(ChannelView) => NavigationViewControl.MenuItems.FirstOrDefault(i => ((FrameworkElement)i).Tag == args.Parameter),
|
||||
_ => NavigationViewControl.MenuItems.FirstOrDefault(i => ((FrameworkElement)i).Tag as Type == args.SourcePageType)
|
||||
};
|
||||
}
|
||||
|
||||
private void NavigationViewControl_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
|
||||
{
|
||||
(NavigationTarget target, object parameters) suggestedTransition;
|
||||
|
||||
Type targetType;
|
||||
string param = null;
|
||||
if (args.IsSettingsInvoked)
|
||||
suggestedTransition = (NavigationTarget.Settings, null);
|
||||
targetType = typeof(SettingsView);
|
||||
else
|
||||
suggestedTransition = args.InvokedItemContainer.Tag as string switch
|
||||
{
|
||||
"home" => (NavigationTarget.Home, null),
|
||||
"downloads" => (NavigationTarget.Downloads, null),
|
||||
"subscriptions" => (NavigationTarget.Subscriptions, null),
|
||||
_ => (NavigationTarget.Home, null) // TODO: Navigate to channel
|
||||
};
|
||||
if (args.InvokedItemContainer.Tag is Type itemType)
|
||||
targetType = itemType;
|
||||
else
|
||||
{
|
||||
targetType = typeof(ChannelView);
|
||||
param = args.InvokedItemContainer.Tag as string;
|
||||
}
|
||||
}
|
||||
|
||||
if (Navigation.CurrentPage == suggestedTransition.target && Navigation.CurrentParameter == suggestedTransition.parameters)
|
||||
if (targetType == typeof(ChannelView))
|
||||
{
|
||||
if ((Navigation.CurrentParameter is Channel channelParam && channelParam.Id == param) ||
|
||||
Navigation.CurrentParameter as string == param)
|
||||
return;
|
||||
}
|
||||
else if (Navigation.CurrentPage == targetType)
|
||||
return;
|
||||
|
||||
Navigation.NavigateTo(suggestedTransition.target, suggestedTransition.parameters);
|
||||
if (param == null)
|
||||
Navigation.NavigateTo(targetType);
|
||||
else
|
||||
Navigation.NavigateTo(targetType, param);
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -118,112 +121,77 @@ namespace FoxTube
|
||||
|
||||
private void AutoSuggestBox_QuerySubmitted(Windows.UI.Xaml.Controls.AutoSuggestBox sender, Windows.UI.Xaml.Controls.AutoSuggestBoxQuerySubmittedEventArgs args)
|
||||
{
|
||||
if (args.QueryText.Length < 3)
|
||||
return;
|
||||
|
||||
History.AddSearchHistoryEntry(args.QueryText);
|
||||
|
||||
// TODO: Go to search
|
||||
if (args.QueryText.Length >= 3)
|
||||
Navigation.NavigateTo(typeof(SearchView), new SearchParameters(args.QueryText));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Users management
|
||||
private void UsersControl_UserStateUpdated(object sender, bool authorized)
|
||||
{
|
||||
// Add general menu items
|
||||
NavigationViewControl.MenuItems.Clear();
|
||||
MenuItemsList.GetMenuItems(authorized).ForEach(i =>
|
||||
NavigationViewControl.MenuItems.Add(i));
|
||||
UpdateMenu();
|
||||
|
||||
// Add subscriptions list to the menu
|
||||
if (authorized && UserManagement.CurrentUser.Subscriptions.Count > 0)
|
||||
{
|
||||
NavigationViewControl.MenuItems.Add(new NavigationViewItemHeader { Content = "Subscriptions" });
|
||||
UserManagement.CurrentUser.Subscriptions.ToList().GetRange(0, Math.Min(UserManagement.CurrentUser.Subscriptions.Count, 10)).ForEach(i =>
|
||||
NavigationViewControl.MenuItems.Add(MenuItemsList.GenerateItemFromSubscription(i)));
|
||||
}
|
||||
|
||||
// TODO: Menu selector resets after menu update
|
||||
return;
|
||||
|
||||
// Refresh page
|
||||
if (content.CurrentSourcePageType == null || content.CurrentSourcePageType.Name.Belongs("Home", "Trending"))
|
||||
Navigation.NavigateTo(NavigationTarget.Home);
|
||||
if (ContentFrame.CurrentSourcePageType == null || ContentFrame.CurrentSourcePageType.Name.Belongs("Home", "Trending"))
|
||||
Navigation.NavigateTo(UserService.Authorized ? typeof(HomeView) : typeof(TrendingView));
|
||||
else
|
||||
Refresh();
|
||||
Navigation.RefreshForce();
|
||||
}
|
||||
|
||||
private void UsersControl_SubscriptionsChanged(object sender, Subscription subscription)
|
||||
private void UsersControl_SubscriptionsChanged(object sender, Models.Subscription subscription)
|
||||
{
|
||||
if (NavigationViewControl.MenuItems.FirstOrDefault(i => ((NavigationViewItemBase)i).Tag as string == subscription.ChannelId) is NavigationViewItem container)
|
||||
{
|
||||
NavigationViewControl.MenuItems.Remove(container);
|
||||
NavigationViewItem subscriptionsContainer = NavigationViewControl.MenuItems.Last() as NavigationViewItem;
|
||||
|
||||
if (UserManagement.CurrentUser.Subscriptions.Count < 1)
|
||||
NavigationViewControl.MenuItems.RemoveAt(NavigationViewControl.MenuItems.Count - 1);
|
||||
if (subscriptionsContainer.MenuItems.FirstOrDefault(i => ((NavigationViewItemBase)i).Tag as string == subscription.ChannelId) is NavigationViewItem container)
|
||||
{
|
||||
subscriptionsContainer.MenuItems.Remove(container);
|
||||
|
||||
if (UserService.CurrentUser.Subscriptions.Count >= 10)
|
||||
NavigationViewControl.MenuItems.Add(MenuItemsList.GenerateItemFromSubscription(UserService.CurrentUser.Subscriptions[9]));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (UserManagement.CurrentUser.Subscriptions.Count == 1)
|
||||
NavigationViewControl.MenuItems.Add(new NavigationViewItemHeader { Content = "Subscriptions" });
|
||||
|
||||
if (UserManagement.CurrentUser.Subscriptions.Count.Belongs(1, 10))
|
||||
if (UserService.CurrentUser.Subscriptions.Count.Belongs(1, 10))
|
||||
NavigationViewControl.MenuItems.Add(MenuItemsList.GenerateItemFromSubscription(subscription));
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateSubscriptions()
|
||||
public void UpdateMenu()
|
||||
{
|
||||
object itemTag = (NavigationViewControl.SelectedItem as NavigationViewItem)?.Tag;
|
||||
|
||||
// Add general menu items
|
||||
NavigationViewControl.SelectedItem = null;
|
||||
NavigationViewControl.MenuItems.Clear();
|
||||
MenuItemsList.GetMenuItems(UserManagement.Authorized).ForEach(i =>
|
||||
MenuItemsList.GetMenuItems(UserService.Authorized).ForEach(i =>
|
||||
NavigationViewControl.MenuItems.Add(i));
|
||||
|
||||
// Add subscriptions list to the menu
|
||||
if (UserManagement.Authorized && UserManagement.CurrentUser.Subscriptions.Count > 0)
|
||||
{
|
||||
NavigationViewControl.MenuItems.Add(new NavigationViewItemHeader { Content = "Subscriptions" });
|
||||
UserManagement.CurrentUser.Subscriptions.ToList().GetRange(0, Math.Min(UserManagement.CurrentUser.Subscriptions.Count, 10)).ForEach(i =>
|
||||
NavigationViewControl.MenuItems.Add(MenuItemsList.GenerateItemFromSubscription(i)));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
if (UserService.Authorized)
|
||||
UserService.CurrentUser.Subscriptions.ToList().GetRange(0, Math.Min(UserService.CurrentUser.Subscriptions.Count, 10)).ForEach(i =>
|
||||
(NavigationViewControl.MenuItems.Last() as NavigationViewItem).MenuItems.Add(MenuItemsList.GenerateItemFromSubscription(i)));
|
||||
|
||||
#region Navigation actions
|
||||
public void Refresh()
|
||||
{
|
||||
if (!Attribute.IsDefined(content.CurrentSourcePageType, typeof(RefreshableAttribute)))
|
||||
return;
|
||||
|
||||
content.Navigate(content.CurrentSourcePageType ?? typeof(Views.Home), Navigation.CurrentParameter);
|
||||
content.BackStack.RemoveAt(content.BackStack.Count - 1);
|
||||
NavigationViewControl.SelectedItem = NavigationViewControl.MenuItems.FirstOrDefault(i => (i as NavigationViewItemBase).Tag == itemTag);
|
||||
}
|
||||
|
||||
public void Navigate(Type target, object parameter) =>
|
||||
content.Navigate(target, parameter);
|
||||
#endregion
|
||||
|
||||
#region Simple button actions
|
||||
private void NavigationViewControl_BackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args)
|
||||
{
|
||||
if (content.CanGoBack)
|
||||
content.GoBack();
|
||||
}
|
||||
private void NavigationViewControl_BackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args) =>
|
||||
Navigation.GoBack();
|
||||
|
||||
private void Refresh_Click(object sender, RoutedEventArgs e) =>
|
||||
Refresh();
|
||||
Navigation.Refresh();
|
||||
|
||||
private async void RemoveAds_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e) =>
|
||||
await new ProOfferDialog().ShowAsync();
|
||||
|
||||
private void LeaveFeedback_Click(object sender, RoutedEventArgs e) =>
|
||||
Feedback.OpenFeedbackHub();
|
||||
FeedbackInterop.OpenFeedbackHub();
|
||||
|
||||
private void NavigationView_DisplayModeChanged(NavigationView sender, NavigationViewDisplayModeChangedEventArgs args) =>
|
||||
AppTitleBar.Margin = new Thickness()
|
||||
{
|
||||
Left = sender.CompactPaneLength * (sender.DisplayMode == NavigationViewDisplayMode.Minimal ? 2 : 1),
|
||||
Right = toolbar.ActualWidth + 190
|
||||
};
|
||||
private void TogglePane(object sender, RoutedEventArgs e) =>
|
||||
NavigationViewControl.IsPaneOpen = !NavigationViewControl.IsPaneOpen;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using Windows.UI.Xaml.Documents;
|
||||
using Windows.UI.Xaml.Media.Animation;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
namespace FoxTube
|
||||
{
|
||||
public static class Navigation
|
||||
{
|
||||
public static event NavigatedEventHandler Navigated;
|
||||
public static Type CurrentPage { get; private set; }
|
||||
public static object CurrentParameter { get; private set; }
|
||||
public static bool CanRefresh { get; private set; }
|
||||
public static bool CanGoBack { get; private set; }
|
||||
|
||||
public static void NavigateTo(Type view) =>
|
||||
NavigateTo(view, null, null);
|
||||
|
||||
public static void NavigateTo(Type view, object parameters) =>
|
||||
NavigateTo(view, parameters, new EntranceNavigationTransitionInfo());
|
||||
|
||||
public static void NavigateTo(Type view, object parameters, NavigationTransitionInfo transitionInfo)
|
||||
{
|
||||
MainPage.Current.ContentFrame.Navigate(view, parameters, transitionInfo);
|
||||
|
||||
CurrentPage = view;
|
||||
CurrentParameter = parameters;
|
||||
}
|
||||
|
||||
public static void Refresh()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void RefreshForce()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void GoBack()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3" IgnorableNamespaces="uap mp uap3">
|
||||
<Identity Name="53949MichaelXFoxGordeev.FoxTube" Publisher="CN=FD7A34DD-FE4D-4D7D-9D33-2DA9EBBE7725" Version="1.2.0.0" />
|
||||
<Identity Name="53949MichaelXFoxGordeev.FoxTube" Publisher="CN=FD7A34DD-FE4D-4D7D-9D33-2DA9EBBE7725" Version="2.0.1.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="04fd81c1-6473-4174-afd7-4ac71dd85721" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>FoxTube</DisplayName>
|
||||
|
||||
@@ -0,0 +1,342 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:FoxTube"
|
||||
xmlns:controls="using:Microsoft.UI.Xaml.Controls">
|
||||
|
||||
<Style x:Key="NavigationBackButtonNormalStyle" TargetType="Button">
|
||||
<Setter Property="Background" Value="{ThemeResource NavigationViewBackButtonBackground}"/>
|
||||
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
|
||||
<Setter Property="FontFamily" Value="{ThemeResource SymbolThemeFontFamily}"/>
|
||||
<Setter Property="FontSize" Value="16"/>
|
||||
<Setter Property="Height" Value="{ThemeResource NavigationBackButtonHeight}"/>
|
||||
<Setter Property="Width" Value="{ThemeResource NavigationBackButtonWidth}"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}"/>
|
||||
<Setter Property="Content" Value=""/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal"/>
|
||||
<VisualState x:Name="PointerOver">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource NavigationViewButtonBackgroundPointerOver}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource NavigationViewButtonForegroundPointerOver}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Pressed">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource NavigationViewButtonBackgroundPressed}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource NavigationViewButtonForegroundPressed}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Disabled">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource NavigationViewButtonForegroundDisabled}"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
<FontIcon x:Name="Content" AutomationProperties.AccessibilityView="Raw" FontFamily="{TemplateBinding FontFamily}" Foreground="{TemplateBinding Foreground}" FontSize="{TemplateBinding FontSize}" Glyph="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" MirroredWhenRightToLeft="True" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style x:Key="MainPageNavigationView" TargetType="controls:NavigationView">
|
||||
<Setter Property="PaneToggleButtonStyle" Value="{StaticResource PaneToggleButtonStyle}"/>
|
||||
<Setter Property="IsTabStop" Value="False"/>
|
||||
<Setter Property="CompactPaneLength" Value="{ThemeResource NavigationViewCompactPaneLength}"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="controls:NavigationView">
|
||||
<Grid x:Name="RootGrid">
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="DisplayModeGroup">
|
||||
<VisualState x:Name="Compact"/>
|
||||
<!--<VisualState x:Name="Expanded">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="RootSplitView.PaneBackground" Value="{ThemeResource NavigationViewExpandedPaneBackground}"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>-->
|
||||
<VisualState x:Name="Minimal">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="HeaderContent.Margin" Value="{ThemeResource NavigationViewMinimalHeaderMargin}"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="TopNavigationMinimal"/>
|
||||
<VisualState x:Name="MinimalWithBackButton">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="HeaderContent.Margin" Value="{ThemeResource NavigationViewMinimalHeaderMargin}"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="TogglePaneGroup">
|
||||
<VisualState x:Name="TogglePaneButtonVisible"/>
|
||||
<VisualState x:Name="TogglePaneButtonCollapsed"/>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="HeaderGroup">
|
||||
<VisualState x:Name="HeaderVisible"/>
|
||||
<VisualState x:Name="HeaderCollapsed">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="HeaderContent.Visibility" Value="Collapsed"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="SettingsGroup">
|
||||
<VisualState x:Name="SettingsVisible"/>
|
||||
<VisualState x:Name="SettingsCollapsed">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="SettingsNavPaneItem.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="SettingsTopNavPaneItem.Visibility" Value="Collapsed"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="AutoSuggestGroup">
|
||||
<VisualState x:Name="AutoSuggestBoxVisible"/>
|
||||
<VisualState x:Name="AutoSuggestBoxCollapsed">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="AutoSuggestArea.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="TopPaneAutoSuggestArea.Visibility" Value="Collapsed"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="PaneStateGroup">
|
||||
<VisualState x:Name="NotClosedCompact"/>
|
||||
<VisualState x:Name="ClosedCompact">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="PaneAutoSuggestBoxPresenter.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="PaneAutoSuggestButton.Visibility" Value="Visible"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="PaneStateListSizeGroup">
|
||||
<VisualState x:Name="ListSizeFull"/>
|
||||
<VisualState x:Name="ListSizeCompact">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="PaneContentGrid.Width" Value="{Binding CompactPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
|
||||
<Setter Target="SettingsNavPaneItem.HorizontalAlignment" Value="Left"/>
|
||||
<Setter Target="PaneTitleTextBlock.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="PaneHeaderContentBorder.Visibility" Value="Collapsed"/>
|
||||
<Setter Target="PaneCustomContentBorder.HorizontalAlignment" Value="Left"/>
|
||||
<Setter Target="FooterContentBorder.HorizontalAlignment" Value="Left"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="TitleBarVisibilityGroup">
|
||||
<VisualState x:Name="TitleBarVisible"/>
|
||||
<VisualState x:Name="TitleBarCollapsed">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="PaneContentGrid.Margin" Value="0,32,0,0"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="OverflowLabelGroup">
|
||||
<VisualState x:Name="OverflowButtonWithLabel"/>
|
||||
<VisualState x:Name="OverflowButtonNoLabel">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="TopNavOverflowButton.Style" Value="{ThemeResource NavigationViewOverflowButtonNoLabelStyleWhenPaneOnTop}"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="BackButtonGroup">
|
||||
<VisualState x:Name="BackButtonVisible"/>
|
||||
<VisualState x:Name="BackButtonCollapsed">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="BackButtonPlaceholderOnTopNav.Width" Value="0"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="PaneVisibilityGroup">
|
||||
<VisualState x:Name="PaneVisible"/>
|
||||
<VisualState x:Name="PaneCollapsed">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="RootSplitView.CompactPaneLength" Value="0"/>
|
||||
<Setter Target="PaneToggleButtonGrid.Visibility" Value="Collapsed"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
<Grid x:Name="PaneToggleButtonGrid" HorizontalAlignment="Left" Margin="0,0,0,8" VerticalAlignment="Top" Canvas.ZIndex="100">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid x:Name="TogglePaneTopPadding" Height="{Binding TemplateSettings.TopPadding, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
|
||||
<Grid x:Name="ButtonHolderGrid" Grid.Row="1">
|
||||
<Button x:Name="NavigationViewBackButton" IsEnabled="{TemplateBinding IsBackEnabled}" Style="{StaticResource NavigationBackButtonNormalStyle}" VerticalAlignment="Top" Visibility="{Binding TemplateSettings.BackButtonVisibility, RelativeSource={RelativeSource Mode=TemplatedParent}}">
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip x:Name="NavigationViewBackButtonToolTip"/>
|
||||
</ToolTipService.ToolTip>
|
||||
</Button>
|
||||
<Button x:Name="NavigationViewCloseButton" Style="{StaticResource NavigationBackButtonNormalStyle}" VerticalAlignment="Top">
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip x:Name="NavigationViewCloseButtonToolTip"/>
|
||||
</ToolTipService.ToolTip>
|
||||
</Button>
|
||||
<Button x:Name="TogglePaneButton" HorizontalAlignment="Center" AutomationProperties.LandmarkType="Navigation" Style="{TemplateBinding PaneToggleButtonStyle}" VerticalAlignment="Top" Visibility="{Binding TemplateSettings.PaneToggleButtonVisibility, RelativeSource={RelativeSource Mode=TemplatedParent}}">
|
||||
<TextBlock x:Name="PaneTitleTextBlock" Grid.Column="0" HorizontalAlignment="Left" Style="{StaticResource NavigationViewItemHeaderTextStyle}" Text="{TemplateBinding PaneTitle}" VerticalAlignment="Center"/>
|
||||
</Button>
|
||||
<Grid x:Name="PaneTitleHolder" Visibility="Collapsed">
|
||||
<ContentControl x:Name="PaneTitlePresenter" HorizontalContentAlignment="Stretch" IsTabStop="False" Margin="{ThemeResource NavigationViewPaneTitlePresenterMargin}" VerticalContentAlignment="Stretch"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel x:Name="TopNavArea" Background="{ThemeResource NavigationViewTopPaneBackground}" HorizontalAlignment="Stretch" Grid.Row="0" VerticalAlignment="Top" XYFocusKeyboardNavigation="Enabled" Canvas.ZIndex="1">
|
||||
<Grid x:Name="TopNavTopPadding" Height="{Binding TemplateSettings.TopPadding, RelativeSource={RelativeSource Mode=TemplatedParent}}" Visibility="{Binding TemplateSettings.TopPaneVisibility, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
|
||||
<Grid x:Name="TopNavGrid" Height="{ThemeResource NavigationViewTopPaneHeight}" Visibility="{Binding TemplateSettings.TopPaneVisibility, RelativeSource={RelativeSource Mode=TemplatedParent}}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition x:Name="BackButtonPlaceholderOnTopNav" Width="{ThemeResource NavigationBackButtonWidth}"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition MinWidth="48" Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid x:Name="TopNavLeftPadding" Grid.Column="1" Width="0"/>
|
||||
<ContentControl x:Name="PaneHeaderOnTopPane" Grid.Column="2" HorizontalContentAlignment="Stretch" IsTabStop="False" VerticalContentAlignment="Stretch"/>
|
||||
<ContentControl x:Name="PaneTitleOnTopPane" Grid.Column="2" HorizontalContentAlignment="Stretch" IsTabStop="False" VerticalContentAlignment="Stretch"/>
|
||||
<controls:ItemsRepeaterScrollHost Grid.Column="3">
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Hidden" HorizontalScrollMode="Disabled" VerticalScrollMode="Disabled" VerticalScrollBarVisibility="Hidden">
|
||||
<controls:ItemsRepeater x:Name="TopNavMenuItemsHost" AutomationProperties.AccessibilityView="Content" AutomationProperties.LandmarkType="Navigation" AutomationProperties.Name="{TemplateBinding AutomationProperties.Name}">
|
||||
<controls:ItemsRepeater.Layout>
|
||||
<controls:StackLayout Orientation="Horizontal"/>
|
||||
</controls:ItemsRepeater.Layout>
|
||||
</controls:ItemsRepeater>
|
||||
</ScrollViewer>
|
||||
</controls:ItemsRepeaterScrollHost>
|
||||
<Button x:Name="TopNavOverflowButton" Content="More" Grid.Column="4" Style="{StaticResource NavigationViewOverflowButtonStyleWhenPaneOnTop}" Visibility="{Binding TemplateSettings.OverflowButtonVisibility, RelativeSource={RelativeSource Mode=TemplatedParent}}">
|
||||
<Button.Flyout>
|
||||
<Flyout ElementSoundMode="{Binding ElementSoundMode, RelativeSource={RelativeSource Mode=TemplatedParent}}" Placement="Bottom">
|
||||
<Flyout.FlyoutPresenterStyle>
|
||||
<Style TargetType="FlyoutPresenter">
|
||||
<Setter Property="Padding" Value="0,8"/>
|
||||
<Setter Property="Margin" Value="0,-4,0,0"/>
|
||||
</Style>
|
||||
</Flyout.FlyoutPresenterStyle>
|
||||
<controls:ItemsRepeaterScrollHost>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<controls:ItemsRepeater x:Name="TopNavMenuItemsOverflowHost" AutomationProperties.AccessibilityView="Content">
|
||||
<controls:ItemsRepeater.Layout>
|
||||
<controls:StackLayout Orientation="Vertical"/>
|
||||
</controls:ItemsRepeater.Layout>
|
||||
</controls:ItemsRepeater>
|
||||
</ScrollViewer>
|
||||
</controls:ItemsRepeaterScrollHost>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
<ContentControl x:Name="PaneCustomContentOnTopPane" Grid.Column="5" HorizontalContentAlignment="Stretch" IsTabStop="False" VerticalContentAlignment="Stretch"/>
|
||||
<Grid x:Name="TopPaneAutoSuggestArea" Grid.Column="6" Height="{ThemeResource NavigationViewTopPaneHeight}">
|
||||
<ContentControl x:Name="TopPaneAutoSuggestBoxPresenter" HorizontalContentAlignment="Stretch" IsTabStop="False" MinWidth="48" Margin="12,0,12,0" VerticalContentAlignment="Center"/>
|
||||
</Grid>
|
||||
<ContentControl x:Name="PaneFooterOnTopPane" Grid.Column="7" HorizontalContentAlignment="Stretch" IsTabStop="False" VerticalContentAlignment="Stretch"/>
|
||||
<Grid Grid.Column="8">
|
||||
<controls:NavigationViewItem x:Name="SettingsTopNavPaneItem" Style="{ThemeResource MUX_NavigationViewSettingsItemStyleWhenOnTopPane}">
|
||||
<controls:NavigationViewItem.Icon>
|
||||
<SymbolIcon Symbol="Setting"/>
|
||||
</controls:NavigationViewItem.Icon>
|
||||
</controls:NavigationViewItem>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Border x:Name="TopNavContentOverlayAreaGrid" Child="{TemplateBinding ContentOverlay}"/>
|
||||
</StackPanel>
|
||||
<SplitView x:Name="RootSplitView" Background="{Binding Background}" CompactPaneLength="{TemplateBinding CompactPaneLength}" DisplayMode="Inline" IsTabStop="False" IsPaneOpen="{Binding IsPaneOpen, Mode=TwoWay, RelativeSource={RelativeSource Mode=TemplatedParent}}" OpenPaneLength="{TemplateBinding OpenPaneLength}" Grid.Row="1">
|
||||
<SplitView.PaneBackground>
|
||||
<AcrylicBrush BackgroundSource="HostBackdrop" TintOpacity=".8" TintColor="{ThemeResource SystemChromeHighColor}" FallbackColor="{ThemeResource SystemChromeHighColor}"/>
|
||||
</SplitView.PaneBackground>
|
||||
<SplitView.Pane>
|
||||
<Grid x:Name="PaneContentGrid" HorizontalAlignment="Left" Visibility="{Binding TemplateSettings.LeftPaneVisibility, RelativeSource={RelativeSource Mode=TemplatedParent}}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="0"/>
|
||||
<RowDefinition x:Name="PaneContentGridToggleButtonRow" Height="Auto" MinHeight="{StaticResource NavigationViewPaneHeaderRowMinHeight}"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="8"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="8"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid x:Name="ContentPaneTopPadding" Height="{Binding TemplateSettings.TopPadding, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
|
||||
<Grid Grid.Row="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition x:Name="PaneHeaderCloseButtonColumn"/>
|
||||
<ColumnDefinition x:Name="PaneHeaderToggleButtonColumn"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition x:Name="PaneHeaderContentBorderRow"/>
|
||||
</Grid.RowDefinitions>
|
||||
<ContentControl x:Name="PaneHeaderContentBorder" Grid.Column="2" HorizontalContentAlignment="Stretch" IsTabStop="False" VerticalContentAlignment="Stretch"/>
|
||||
</Grid>
|
||||
<Grid x:Name="AutoSuggestArea" Height="{ThemeResource NavigationViewTopPaneHeight}" Grid.Row="3" VerticalAlignment="Center">
|
||||
<ContentControl x:Name="PaneAutoSuggestBoxPresenter" HorizontalContentAlignment="Stretch" IsTabStop="False" Margin="{ThemeResource NavigationViewAutoSuggestBoxMargin}" VerticalContentAlignment="Center"/>
|
||||
<Button x:Name="PaneAutoSuggestButton" Style="{ThemeResource NavigationViewPaneSearchButtonStyle}" Visibility="Collapsed" Width="{TemplateBinding CompactPaneLength}"/>
|
||||
</Grid>
|
||||
<ContentControl x:Name="PaneCustomContentBorder" HorizontalContentAlignment="Stretch" IsTabStop="False" Grid.Row="4" VerticalContentAlignment="Stretch"/>
|
||||
<controls:ItemsRepeaterScrollHost HorizontalAlignment="Stretch" Margin="0,0,0,20" Grid.Row="6" VerticalAlignment="Top">
|
||||
<ScrollViewer TabNavigation="Once" VerticalScrollBarVisibility="Auto">
|
||||
<controls:ItemsRepeater x:Name="MenuItemsHost" AutomationProperties.AccessibilityView="Content" AutomationProperties.Name="{TemplateBinding AutomationProperties.Name}">
|
||||
<controls:ItemsRepeater.Layout>
|
||||
<controls:StackLayout Orientation="Vertical"/>
|
||||
</controls:ItemsRepeater.Layout>
|
||||
</controls:ItemsRepeater>
|
||||
</ScrollViewer>
|
||||
</controls:ItemsRepeaterScrollHost>
|
||||
<ContentControl x:Name="FooterContentBorder" HorizontalContentAlignment="Stretch" IsTabStop="False" Grid.Row="7" VerticalContentAlignment="Stretch"/>
|
||||
<Grid Grid.Row="8">
|
||||
<controls:NavigationViewItem x:Name="SettingsNavPaneItem">
|
||||
<controls:NavigationViewItem.Icon>
|
||||
<SymbolIcon Symbol="Setting"/>
|
||||
</controls:NavigationViewItem.Icon>
|
||||
</controls:NavigationViewItem>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</SplitView.Pane>
|
||||
<Grid x:Name="ContentGrid">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid x:Name="ContentTopPadding" Grid.ColumnSpan="2" Height="{Binding TemplateSettings.TopPadding, RelativeSource={RelativeSource Mode=TemplatedParent}}" Visibility="{Binding TemplateSettings.LeftPaneVisibility, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
|
||||
<Grid x:Name="ContentLeftPadding" Grid.Row="1"/>
|
||||
<ContentControl x:Name="HeaderContent" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" Grid.Column="1" HorizontalContentAlignment="Stretch" IsTabStop="False" MinHeight="{StaticResource PaneToggleButtonHeight}" Grid.Row="1" Style="{StaticResource NavigationViewTitleHeaderContentControlTextStyle}" VerticalContentAlignment="Stretch"/>
|
||||
<ContentPresenter Content="{TemplateBinding Content}" Grid.ColumnSpan="2" AutomationProperties.LandmarkType="Main" Grid.Row="2"/>
|
||||
</Grid>
|
||||
</SplitView>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -0,0 +1,23 @@
|
||||
<Page
|
||||
x:Class="FoxTube.SplashScreen"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Background="{ThemeResource SplashScreenBackground}"
|
||||
mc:Ignorable="d"
|
||||
Loaded="Page_Loaded">
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="3*" />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Canvas Grid.RowSpan="2">
|
||||
<Image x:Name="SplashScreenImage" Source="/Assets/SplashScreen.png" />
|
||||
</Canvas>
|
||||
|
||||
<ProgressRing x:Name="ProgressRingControl" Grid.Row="1" Width="50" Height="50" />
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -0,0 +1,91 @@
|
||||
using FoxTube.Services;
|
||||
using FoxTube.Utils;
|
||||
using System;
|
||||
using Windows.ApplicationModel.Activation;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media.Animation;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
namespace FoxTube
|
||||
{
|
||||
/// <summary>
|
||||
/// Extended splash screen. Does all initialization
|
||||
/// </summary>
|
||||
public sealed partial class SplashScreen : Page
|
||||
{
|
||||
private readonly Windows.ApplicationModel.Activation.SplashScreen splashScreen;
|
||||
private readonly string navigationParameter;
|
||||
|
||||
public SplashScreen(IActivatedEventArgs args, string parameter = null)
|
||||
{
|
||||
InitializeComponent();
|
||||
splashScreen = args.SplashScreen;
|
||||
navigationParameter = parameter;
|
||||
|
||||
Window.Current.SizeChanged += Current_SizeChanged;
|
||||
|
||||
UpdateImagePosition();
|
||||
}
|
||||
|
||||
private void Page_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ProgressRingControl.IsActive = true;
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public async void Initialize()
|
||||
{
|
||||
Frame frame = Window.Current.Content as Frame;
|
||||
|
||||
frame.RequestedTheme = SettingsService.Theme;
|
||||
if (frame.RequestedTheme == ElementTheme.Default)
|
||||
Utils.Utils.UpdateTitleBarTheme(Application.Current.RequestedTheme == ApplicationTheme.Dark);
|
||||
else
|
||||
Utils.Utils.UpdateTitleBarTheme(frame.RequestedTheme == ElementTheme.Dark);
|
||||
|
||||
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
|
||||
|
||||
if (StorageService.PromptReview)
|
||||
FeedbackInterop.PromptReview();
|
||||
if (StorageService.PromptFeedback)
|
||||
FeedbackInterop.PromptFeedback();
|
||||
|
||||
#region App init
|
||||
await UserService.Initialize();
|
||||
await DownloadsService.Initialize();
|
||||
await AddonsInterop.UpdateProPurchasedState();
|
||||
InboxService.PushChangelog();
|
||||
|
||||
BackgroundManager.RegisterBackgroundTasks();
|
||||
#endregion
|
||||
|
||||
if (navigationParameter.ToUri() is Uri uri && uri.Segments.Length > 0)
|
||||
{
|
||||
if (uri.Segments[0].ToLowerInvariant() == "action")
|
||||
await BackgroundManager.ProcessBackgroundAction(navigationParameter);
|
||||
}
|
||||
|
||||
frame.Navigate(typeof(MainPage), navigationParameter, new SlideNavigationTransitionInfo { Effect = SlideNavigationTransitionEffect.FromLeft });
|
||||
}
|
||||
|
||||
protected override void OnNavigatedFrom(NavigationEventArgs e)
|
||||
{
|
||||
base.OnNavigatedFrom(e);
|
||||
Window.Current.SizeChanged -= Current_SizeChanged;
|
||||
}
|
||||
|
||||
private void Current_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e) =>
|
||||
UpdateImagePosition();
|
||||
|
||||
private void UpdateImagePosition()
|
||||
{
|
||||
Canvas.SetLeft(SplashScreenImage, splashScreen.ImageLocation.Left);
|
||||
Canvas.SetTop(SplashScreenImage, splashScreen.ImageLocation.Top);
|
||||
SplashScreenImage.Height = splashScreen.ImageLocation.Height;
|
||||
SplashScreenImage.Width = splashScreen.ImageLocation.Width;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,14 @@
|
||||
<Page
|
||||
NavigationCacheMode="Enabled"
|
||||
x:Class="FoxTube.Views.HomeSections.Trending"
|
||||
x:Class="FoxTube.Views.ChannelView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:FoxTube.Views"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:controls="using:FoxTube.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
|
||||
Loaded="Page_Loaded">
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<Grid>
|
||||
<RefreshContainer>
|
||||
<controls:ItemsGrid x:Name="grid"/>
|
||||
</RefreshContainer>
|
||||
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls.Primitives;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
|
||||
|
||||
namespace FoxTube.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
public sealed partial class ChannelView : Page
|
||||
{
|
||||
public ChannelView()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<Page
|
||||
x:Class="FoxTube.Views.Downloads"
|
||||
x:Class="FoxTube.Views.DownloadsView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
@@ -16,13 +16,13 @@ namespace FoxTube.Views
|
||||
/// <summary>
|
||||
/// Video download page
|
||||
/// </summary>
|
||||
public sealed partial class Downloads : Page
|
||||
public sealed partial class DownloadsView : Page
|
||||
{
|
||||
public Downloads()
|
||||
public DownloadsView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
downloadHistoryList.ItemsSource = DownloadsCenter.History;
|
||||
downloadHistoryList.ItemsSource = DownloadsService.History;
|
||||
// TODO: Add downloads list
|
||||
|
||||
UpdateList();
|
||||
@@ -50,17 +50,17 @@ namespace FoxTube.Views
|
||||
}
|
||||
|
||||
private async void OpenDefaultFolder(object sender, RoutedEventArgs e) =>
|
||||
await Launcher.LaunchFolderAsync(await DownloadsCenter.GetDefaultDownloadsFolder());
|
||||
await Launcher.LaunchFolderAsync(await DownloadsService.GetDefaultDownloadsFolder());
|
||||
|
||||
private void OpenDownloadSettings(object sender, RoutedEventArgs e) =>
|
||||
Navigation.NavigateTo(NavigationTarget.Settings, "downloads");
|
||||
Navigation.NavigateTo(typeof(SettingsView), "downloads");
|
||||
|
||||
public void UpdateList() =>
|
||||
empty.Opacity = (((list.ItemsSource as List<object>)?.Count) ?? list.Items.Count) > 0 ? 0 : 1;
|
||||
|
||||
private async void AutoSuggestBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
|
||||
{
|
||||
YoutubeClient client = new YoutubeClient(UserManagement.Service.HttpClient);
|
||||
YoutubeClient client = new YoutubeClient(UserService.Service.HttpClient);
|
||||
|
||||
VideoId? id;
|
||||
Video meta;
|
||||
@@ -96,7 +96,7 @@ namespace FoxTube.Views
|
||||
private void OpenOriginal(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SavedVideo item = (sender as FrameworkElement).Parent.GetValue(TagProperty) as SavedVideo;
|
||||
Navigation.NavigateTo(NavigationTarget.Home, item.Id); // TODO: Replace with actual navigation
|
||||
Navigation.NavigateTo(typeof(SettingsView), item.Id); // TODO: Replace with actual navigation
|
||||
}
|
||||
|
||||
private async void OpenVideo(object sender, RoutedEventArgs e)
|
||||
@@ -0,0 +1,14 @@
|
||||
<Page
|
||||
x:Class="FoxTube.Views.HistoryView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:FoxTube.Views"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<Grid>
|
||||
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls.Primitives;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
|
||||
|
||||
namespace FoxTube.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
public sealed partial class HistoryView : Page
|
||||
{
|
||||
public HistoryView()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<Page
|
||||
NavigationCacheMode="Enabled"
|
||||
x:Class="FoxTube.Views.Home"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:homesections="using:FoxTube.Views.HomeSections"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Pivot x:Name="pivot">
|
||||
<PivotItem Header="Recommended">
|
||||
<homesections:Recommended/>
|
||||
</PivotItem>
|
||||
<PivotItem Header="Trending">
|
||||
<homesections:Trending/>
|
||||
</PivotItem>
|
||||
<PivotItem Header="Subscriptions">
|
||||
<homesections:Subscriptions/>
|
||||
</PivotItem>
|
||||
</Pivot>
|
||||
</Page>
|
||||
@@ -0,0 +1,17 @@
|
||||
<Page
|
||||
NavigationCacheMode="Enabled"
|
||||
x:Class="FoxTube.Views.HomeSections.TrendingView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:controls="using:FoxTube.Controls"
|
||||
mc:Ignorable="d"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
|
||||
Loaded="Page_Loaded">
|
||||
|
||||
<Grid>
|
||||
<RefreshContainer>
|
||||
<controls:ItemsGrid x:Name="grid"/>
|
||||
</RefreshContainer>
|
||||
</Grid>
|
||||
</Page>
|
||||
+8
-7
@@ -1,6 +1,7 @@
|
||||
using FoxTube.Attributes;
|
||||
using FoxTube.Controls.Cards;
|
||||
using FoxTube.Models;
|
||||
using FoxTube.Services;
|
||||
using Google.Apis.YouTube.v3;
|
||||
using Google.Apis.YouTube.v3.Data;
|
||||
using System;
|
||||
@@ -17,11 +18,11 @@ namespace FoxTube.Views.HomeSections
|
||||
/// YouTube trending videos page
|
||||
/// </summary>
|
||||
[Refreshable]
|
||||
public sealed partial class Trending : Page, IIncrementalLoadingHost
|
||||
public sealed partial class TrendingView : Page, IIncrementalLoadingHost
|
||||
{
|
||||
VideosResource.ListRequest client;
|
||||
|
||||
public Trending() =>
|
||||
public TrendingView() =>
|
||||
InitializeComponent();
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
@@ -40,11 +41,11 @@ namespace FoxTube.Views.HomeSections
|
||||
|
||||
private void LoadContent()
|
||||
{
|
||||
client = UserManagement.Service.Videos.List("snippet,liveStreamingDetails");
|
||||
client = UserService.Service.Videos.List("snippet,liveStreamingDetails");
|
||||
client.MaxResults = 25;
|
||||
|
||||
client.Chart = VideosResource.ListRequest.ChartEnum.MostPopular;
|
||||
client.RegionCode = FoxTube.Settings.Region;
|
||||
//client.RegionCode = FoxTube.Settings.Region;
|
||||
|
||||
grid.Initialize(this);
|
||||
}
|
||||
@@ -53,9 +54,9 @@ namespace FoxTube.Views.HomeSections
|
||||
{
|
||||
VideoListResponse response = await client.ExecuteAsync();
|
||||
client.PageToken = response.NextPageToken;
|
||||
|
||||
return (response.Items.Select(i => new VideoItem(i) as object).ToList(),
|
||||
!string.IsNullOrWhiteSpace(response.NextPageToken));
|
||||
return (null, false);
|
||||
/*return (response.Items.Select(i => new VideoItem(i) as object).ToList(),
|
||||
!string.IsNullOrWhiteSpace(response.NextPageToken));*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<Page
|
||||
NavigationCacheMode="Enabled"
|
||||
x:Class="FoxTube.Views.HomeView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:homesections="using:FoxTube.Views.HomeSections"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Pivot x:Name="pivot">
|
||||
<PivotItem Header="Recommended">
|
||||
<homesections:Recommended/>
|
||||
</PivotItem>
|
||||
<PivotItem Header="Trending">
|
||||
<homesections:TrendingView/>
|
||||
</PivotItem>
|
||||
<PivotItem Header="Subscriptions">
|
||||
<homesections:Subscriptions/>
|
||||
</PivotItem>
|
||||
</Pivot>
|
||||
</Page>
|
||||
@@ -8,21 +8,21 @@ namespace FoxTube.Views
|
||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
[Refreshable]
|
||||
public sealed partial class Home : Page
|
||||
public sealed partial class HomeView : Page
|
||||
{
|
||||
public Home()
|
||||
public HomeView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
pivot.SelectedIndex = FoxTube.Settings.DefaultHomeTab;
|
||||
//pivot.SelectedIndex = FoxTube.Settings.DefaultHomeTab;
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
base.OnNavigatedTo(e);
|
||||
|
||||
if (e.NavigationMode == NavigationMode.New)
|
||||
pivot.SelectedIndex = FoxTube.Settings.DefaultHomeTab;
|
||||
/*if (e.NavigationMode == NavigationMode.New)
|
||||
pivot.SelectedIndex = FoxTube.Settings.DefaultHomeTab;*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<Page
|
||||
x:Class="FoxTube.Views.PlaylistView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:FoxTube.Views"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<Grid>
|
||||
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls.Primitives;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Input;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238
|
||||
|
||||
namespace FoxTube.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
public sealed partial class PlaylistView : Page
|
||||
{
|
||||
public PlaylistView()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<Page
|
||||
xmlns:models="using:FoxTube.Core.Models"
|
||||
x:Class="FoxTube.Views.Search"
|
||||
x:Class="FoxTube.Views.SearchView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:FoxTube.Views"
|
||||
@@ -9,11 +9,11 @@ namespace FoxTube.Views
|
||||
/// Search results page
|
||||
/// </summary>
|
||||
[Refreshable]
|
||||
public sealed partial class Search : Page
|
||||
public sealed partial class SearchView : Page
|
||||
{
|
||||
bool closingByToggle = false;
|
||||
|
||||
public Search() =>
|
||||
public SearchView() =>
|
||||
InitializeComponent();
|
||||
|
||||
void ToggleFilters_Click(object sender, RoutedEventArgs e)
|
||||
@@ -1,27 +0,0 @@
|
||||
<Page
|
||||
x:Class="FoxTube.Views.Settings"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:settingssections="using:FoxTube.Views.SettingsSections"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Pivot SelectedIndex="0" Name="pivot">
|
||||
<PivotItem Name="generalTab" Header="Preferences">
|
||||
<ScrollViewer Padding="15,0">
|
||||
<settingssections:General/>
|
||||
</ScrollViewer>
|
||||
</PivotItem>
|
||||
<PivotItem Name="aboutTab" Header="About us">
|
||||
<ScrollViewer Padding="15,0">
|
||||
<settingssections:About/>
|
||||
</ScrollViewer>
|
||||
</PivotItem>
|
||||
<PivotItem Name="inboxTab" Header="Inbox">
|
||||
<ScrollViewer Padding="15,0">
|
||||
<settingssections:Inbox x:Name="inbox"/>
|
||||
</ScrollViewer>
|
||||
</PivotItem>
|
||||
</Pivot>
|
||||
</Page>
|
||||
@@ -1,68 +0,0 @@
|
||||
<Page
|
||||
x:Class="FoxTube.Views.SettingsSections.About"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<controls:DropShadowPanel Grid.Column="1" VerticalAlignment="Top">
|
||||
<Image Source="/Assets/StoreLogo.scale-400.png" Width="150"/>
|
||||
</controls:DropShadowPanel>
|
||||
|
||||
<StackPanel>
|
||||
<StackPanel.ChildrenTransitions>
|
||||
<TransitionCollection>
|
||||
<EntranceThemeTransition IsStaggeringEnabled="True" FromVerticalOffset="100"/>
|
||||
</TransitionCollection>
|
||||
</StackPanel.ChildrenTransitions>
|
||||
|
||||
<TextBlock Text="FoxTube" Style="{StaticResource SubheaderTextBlockStyle}"/>
|
||||
<TextBlock Name="version" Text="[currentVersion]" Style="{StaticResource CaptionTextBlockStyle}" FontStyle="Italic" Margin="0,-5,0,0"/>
|
||||
|
||||
<TextBlock TextWrapping="WrapWholeWords" Text="Developed by Michael "XFox" Gordeev" Margin="0,10,0,0"/>
|
||||
|
||||
<StackPanel Margin="0,10,0,0">
|
||||
<TextBlock Text="Special thanks to:" Style="{StaticResource TitleTextBlockStyle}"/>
|
||||
<TextBlock>
|
||||
<Hyperlink NavigateUri="https://github.com/Tyrrrz">@Tyrrrz</Hyperlink> for his awesome library
|
||||
<LineBreak/><Hyperlink NavigateUri="https://vk.com/msreviewnet">@msreviewnet</Hyperlink> for warm welcome and first feedback
|
||||
<LineBreak/><Underline Foreground="Red">You</Underline> for using my app :)
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,10,0,0">
|
||||
<TextBlock Text="Contacts" Style="{StaticResource TitleTextBlockStyle}"/>
|
||||
<TextBlock>
|
||||
Twitter: <Hyperlink NavigateUri="https://twitter.com/xfox111">@xfox111</Hyperlink>
|
||||
<LineBreak/>Vkontakte: <Hyperlink NavigateUri="https://vk.com/XFox.Mike">@XFox.Mike</Hyperlink>
|
||||
<!--<LineBreak/>YouTube: <Hyperlink NavigateUri="https://youtube.com/c/FoxGameStudioChannel">@xfox</Hyperlink>-->
|
||||
<LineBreak/>E-mail: <Hyperlink NavigateUri="mailto:michael@xfox111.net">michael@xfox111.net</Hyperlink>
|
||||
<LineBreak/>My website: <Hyperlink NavigateUri="https://xfox111.net">https://xfox111.net</Hyperlink>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,10,0,0">
|
||||
<TextBlock Text="Legal stuff" Style="{StaticResource TitleTextBlockStyle}"/>
|
||||
<TextBlock>
|
||||
<Hyperlink NavigateUri="https://xfox111.net/Projects/FoxTube/Privacy">Our Privacy Policy</Hyperlink>
|
||||
<LineBreak/><Hyperlink NavigateUri="https://youtube.com/t/privacy">YouTube Privacy Policy</Hyperlink>
|
||||
<LineBreak/><Hyperlink NavigateUri="https://youtube.com/t/terms">YouTube Terms of use</Hyperlink>
|
||||
<LineBreak/><Hyperlink NavigateUri="https://youtube.com/t/community_guidelines">YouTube Community Guidelines</Hyperlink>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Name="copyrights" Margin="0,10,0,0">
|
||||
©[year] Michael Gordeev
|
||||
<LineBreak/>©[year] YouTube, LLC
|
||||
</TextBlock>
|
||||
<Button Name="feedback" Content="Leave feedback" Margin="0,10" Visibility="Collapsed" Click="OpenFeedbackHub"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -1,27 +0,0 @@
|
||||
using FoxTube.Utils;
|
||||
using System;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace FoxTube.Views.SettingsSections
|
||||
{
|
||||
/// <summary>
|
||||
/// About page
|
||||
/// </summary>
|
||||
public sealed partial class About : Page
|
||||
{
|
||||
public About()
|
||||
{
|
||||
InitializeComponent();
|
||||
version.Text = Metrics.CurrentVersion;
|
||||
|
||||
copyrights.Text = copyrights.Text.Replace("[year]", DateTime.Today.Year.ToString());
|
||||
|
||||
if (Feedback.HasFeedbackHub)
|
||||
feedback.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void OpenFeedbackHub(object sender, RoutedEventArgs e) =>
|
||||
Feedback.OpenFeedbackHub();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<Page
|
||||
xmlns:system="using:System"
|
||||
xmlns:pages="using:FoxTube.Pages"
|
||||
x:Class="FoxTube.Views.SettingsSections.AboutSection"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<ScrollViewer Padding="10">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Image Grid.Column="1" VerticalAlignment="Top" Source="/Assets/StoreLogo.scale-400.png" Width="150"/>
|
||||
|
||||
<StackPanel>
|
||||
<StackPanel.ChildrenTransitions>
|
||||
<TransitionCollection>
|
||||
<EntranceThemeTransition IsStaggeringEnabled="True" FromVerticalOffset="100"/>
|
||||
</TransitionCollection>
|
||||
</StackPanel.ChildrenTransitions>
|
||||
|
||||
<TextBlock Text="FoxTube" Style="{StaticResource SubheaderTextBlockStyle}"/>
|
||||
<TextBlock x:Name="VersionLabel" Text="[currentVersion]" Style="{StaticResource CaptionTextBlockStyle}" FontStyle="Italic" Margin="0,-5,0,0"/>
|
||||
|
||||
<TextBlock TextWrapping="WrapWholeWords" Text="Developed by Michael "XFox" Gordeev" Margin="0,10,0,0"/>
|
||||
|
||||
<StackPanel Margin="0,10,0,0">
|
||||
<TextBlock Text="Special thanks to:" Style="{StaticResource TitleTextBlockStyle}"/>
|
||||
<TextBlock>
|
||||
<Hyperlink NavigateUri="https://github.com/Tyrrrz">@Tyrrrz</Hyperlink> for his awesome library
|
||||
<LineBreak/><Hyperlink NavigateUri="https://vk.com/msreviewnet">@msreviewnet</Hyperlink> for warm welcome and first feedback
|
||||
<LineBreak/><Underline Foreground="Red">You</Underline> for using my app :)
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,10,0,0">
|
||||
<TextBlock Text="Contacts" Style="{StaticResource TitleTextBlockStyle}"/>
|
||||
<TextBlock>
|
||||
Twitter: <Hyperlink NavigateUri="https://twitter.com/xfox111">@xfox111</Hyperlink>
|
||||
<LineBreak/>Vkontakte: <Hyperlink NavigateUri="https://vk.com/XFox.Mike">@XFox.Mike</Hyperlink>
|
||||
<!--<LineBreak/>YouTube: <Hyperlink NavigateUri="https://youtube.com/c/FoxGameStudioChannel">@xfox</Hyperlink>-->
|
||||
<LineBreak/>E-mail: <Hyperlink NavigateUri="mailto:michael@xfox111.net">michael@xfox111.net</Hyperlink>
|
||||
<LineBreak/>My website: <Hyperlink NavigateUri="https://xfox111.net">https://xfox111.net</Hyperlink>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,10,0,0">
|
||||
<TextBlock Text="Legal stuff" Style="{StaticResource TitleTextBlockStyle}"/>
|
||||
<TextBlock>
|
||||
<Hyperlink NavigateUri="https://xfox111.net/Projects/FoxTube/Privacy">Our Privacy Policy</Hyperlink>
|
||||
<LineBreak/><Hyperlink NavigateUri="https://youtube.com/t/privacy">YouTube Privacy Policy</Hyperlink>
|
||||
<LineBreak/><Hyperlink NavigateUri="https://youtube.com/t/terms">YouTube Terms of use</Hyperlink>
|
||||
<LineBreak/><Hyperlink NavigateUri="https://youtube.com/t/community_guidelines">YouTube Community Guidelines</Hyperlink>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Name="CopyrightsLabel" Margin="0,10,0,0">
|
||||
©[year] Michael Gordeev
|
||||
<LineBreak/>©[year] YouTube, LLC
|
||||
</TextBlock>
|
||||
<Button Name="FeedbackButton" Content="Leave feedback" Margin="0,10" Click="OpenFeedbackHub"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Page>
|
||||
@@ -0,0 +1,27 @@
|
||||
using FoxTube.Utils;
|
||||
using System;
|
||||
using Windows.UI.Xaml;
|
||||
using FoxTube.Pages;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace FoxTube.Views.SettingsSections
|
||||
{
|
||||
/// <summary>
|
||||
/// About page
|
||||
/// </summary>
|
||||
public sealed partial class AboutSection : Page
|
||||
{
|
||||
public AboutSection()
|
||||
{
|
||||
InitializeComponent();
|
||||
VersionLabel.Text = Metrics.CurrentVersion;
|
||||
|
||||
CopyrightsLabel.Text = CopyrightsLabel.Text.Replace("[year]", DateTime.Today.Year.ToString());
|
||||
|
||||
FeedbackButton.Visibility = FeedbackInterop.HasFeedbackHub ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private void OpenFeedbackHub(object sender, RoutedEventArgs e) =>
|
||||
FeedbackInterop.OpenFeedbackHub();
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
<Page
|
||||
x:Class="FoxTube.Views.SettingsSections.General"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<StackPanel>
|
||||
<StackPanel.ChildrenTransitions>
|
||||
<TransitionCollection>
|
||||
<EntranceThemeTransition IsStaggeringEnabled="True" FromVerticalOffset="100"/>
|
||||
</TransitionCollection>
|
||||
</StackPanel.ChildrenTransitions>
|
||||
|
||||
<StackPanel Margin="0,0,0,10">
|
||||
<ComboBox Header="Default homepage tab" Width="250" Name="defaultHomeTab" SelectionChanged="HomeTabChanged">
|
||||
<ComboBoxItem Content="Recommended"/>
|
||||
<ComboBoxItem Content="Trending"/>
|
||||
<ComboBoxItem Content="Subscriptions"/>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,0,0,10">
|
||||
<TextBlock Text="Region & search" Style="{StaticResource TitleTextBlockStyle}"/>
|
||||
<ComboBox Header="App interface language" Width="250" Name="language" SelectionChanged="LanguageChanged">
|
||||
<ComboBoxItem Content="English (United States)" Tag="en-US"/>
|
||||
<ComboBoxItem Content="Russian (Russia)" Tag="ru-RU"/>
|
||||
</ComboBox>
|
||||
<Button Content="Restart application" x:Name="restart" Visibility="Collapsed" Foreground="White" Background="Red" Margin="5" Click="Restart"/>
|
||||
|
||||
<ComboBox Header="Preffered content language" Width="250" Name="relevanceLanguage" SelectionChanged="RelevanceLanguageChanged" Loaded="LoadRelevaneLanguageList"/>
|
||||
<ComboBox Header="Region" Width="250" Name="region" SelectionChanged="RegionChanged" Loaded="LoadRegionList"/>
|
||||
<ComboBox Header="SafeSearch" Width="250" Name="safeSearch" SelectionChanged="SafeSearchChanged">
|
||||
<ComboBoxItem Content="Moderate"/>
|
||||
<ComboBoxItem Content="None"/>
|
||||
<ComboBoxItem Content="Strict"/>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,0,0,10">
|
||||
<TextBlock Text="Playback" Style="{StaticResource TitleTextBlockStyle}"/>
|
||||
<ComboBox Width="250" Header="Default video playback quality" Name="quality" SelectionChanged="QualityChanged" Loaded="LoadQualitiesList">
|
||||
<ComboBoxItem Tag="remember" Content="Remember my choice"/>
|
||||
<ComboBoxItem Tag="auto" Content="Auto"/>
|
||||
</ComboBox>
|
||||
<ToggleSwitch OnContent="Notify when playing on metered connection" OffContent="Notify when playing on metered connection" Name="meteredWarning" Toggled="MeteredWarningChanged"/>
|
||||
<ToggleSwitch OnContent="Play videos automatically" OffContent="Play videos automatically" Name="autoplay" Toggled="AutoplayChanged"/>
|
||||
<ToggleSwitch OnContent="Notify before playing explicit content" OffContent="Notify before playing explicit content" Name="explicitWarning" Toggled="ExplicitWarningChanged"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,0,0,10">
|
||||
<TextBlock Text="Notifications" Style="{StaticResource TitleTextBlockStyle}"/>
|
||||
<ToggleSwitch OnContent="Notify when someone of your subscriptions uploaded new video" OffContent="Notify when someone of your subscriptions uploaded new video" Name="channelNotifications" Toggled="ChannelNotificationsChanged"/>
|
||||
<ToggleSwitch OnContent="Notify if I have any YouTube link on my clipboard" OffContent="Notify if I have any YouTube link on my clipboard" x:Name="clipboardProcessing" Toggled="ClipboardProcessingChanged"/>
|
||||
<ToggleSwitch OnContent="Recieve messages from developers" OffContent="Recieve messages from developers" Name="developersNews" Toggled="DevelopersNotificationsChanged"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,0,0,10">
|
||||
<TextBlock Text="Downloads" Style="{StaticResource TitleTextBlockStyle}"/>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,5">
|
||||
<TextBox x:Name="downloadsPath" Header="Default downloads location" Width="250" IsReadOnly="True" PlaceholderText="//Videos/FoxTube"/>
|
||||
<Button x:Name="changeDownloadsPathButton" Click="ChangeDownloadsPath" VerticalAlignment="Bottom" FontFamily="Segoe MDL2 Assets" Content="" Margin="5,0"/>
|
||||
</StackPanel>
|
||||
|
||||
<ToggleSwitch x:Name="askDownloads" Toggled="AlwaysAskDownloadsChanged" OnContent="Ask where to save before downloading" OffContent="Ask where to save before downloading"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,0,0,10">
|
||||
<TextBlock Text="Theme" Style="{StaticResource TitleTextBlockStyle}"/>
|
||||
<RadioButton Content="Light" Name="light" Tag="0" GroupName="theme" Checked="ThemeChanged"/>
|
||||
<RadioButton Content="Dark" Name="dark" Tag="1" GroupName="theme" Checked="ThemeChanged"/>
|
||||
<RadioButton Content="Windows default" Tag="2" Name="system" GroupName="theme" Checked="ThemeChanged"/>
|
||||
<HyperlinkButton Content="Windows color settings" NavigateUri="ms-settings:colors"/>
|
||||
</StackPanel>
|
||||
|
||||
<Button Content="Reset application" Click="ResetApp"/>
|
||||
</StackPanel>
|
||||
</Page>
|
||||
@@ -1,166 +0,0 @@
|
||||
using FoxTube.Services;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using Windows.Globalization;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.AccessCache;
|
||||
using Windows.Storage.Pickers;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace FoxTube.Views.SettingsSections
|
||||
{
|
||||
/// <summary>
|
||||
/// Preferences page
|
||||
/// </summary>
|
||||
public sealed partial class General : Page
|
||||
{
|
||||
public General()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
defaultHomeTab.SelectedIndex = FoxTube.Settings.DefaultHomeTab;
|
||||
|
||||
language.SelectedItem = language.Items.FirstOrDefault(i => ((ComboBoxItem)i).Tag.ToString() == FoxTube.Settings.Language);
|
||||
safeSearch.SelectedIndex = FoxTube.Settings.SafeSearch;
|
||||
|
||||
meteredWarning.IsOn = FoxTube.Settings.CheckConnection;
|
||||
autoplay.IsOn = FoxTube.Settings.Autoplay;
|
||||
explicitWarning.IsOn = FoxTube.Settings.BlockExplicitContent;
|
||||
|
||||
channelNotifications.IsOn = FoxTube.Settings.VideoNotifications;
|
||||
developersNews.IsOn = FoxTube.Settings.DevNotifications;
|
||||
clipboardProcessing.IsOn = FoxTube.Settings.ProcessClipboard;
|
||||
|
||||
askDownloads.IsOn = FoxTube.Settings.AskBeforeDownloading;
|
||||
|
||||
LoadPath();
|
||||
|
||||
switch (FoxTube.Settings.Theme)
|
||||
{
|
||||
case 0:
|
||||
light.IsChecked = true;
|
||||
break;
|
||||
case 1:
|
||||
dark.IsChecked = true;
|
||||
break;
|
||||
case 2:
|
||||
system.IsChecked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private async void LoadPath() =>
|
||||
downloadsPath.Text = (await DownloadsCenter.GetDefaultDownloadsFolder()).Path;
|
||||
|
||||
private void LoadRelevaneLanguageList(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// TODO: Add list loading
|
||||
}
|
||||
|
||||
private void LoadRegionList(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// TODO: Add list loading
|
||||
}
|
||||
|
||||
private void LoadQualitiesList(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// TODO: Add qualities loading
|
||||
|
||||
quality.SelectedItem = quality.Items.FirstOrDefault(i => ((ComboBoxItem)i).Tag.ToString() == FoxTube.Settings.DesiredVideoQuality);
|
||||
}
|
||||
|
||||
private void LanguageChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if ((language.SelectedItem as ComboBoxItem).Tag.ToString() == FoxTube.Settings.Language)
|
||||
return;
|
||||
|
||||
ApplicationLanguages.PrimaryLanguageOverride = (language.SelectedItem as ComboBoxItem).Tag.ToString();
|
||||
FoxTube.Settings.Language = (language.SelectedItem as ComboBoxItem).Tag.ToString();
|
||||
restart.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void HomeTabChanged(object sender, SelectionChangedEventArgs e) =>
|
||||
FoxTube.Settings.DefaultHomeTab = defaultHomeTab.SelectedIndex;
|
||||
|
||||
private void Restart(object sender, RoutedEventArgs e) =>
|
||||
Utils.Utils.RestartApp();
|
||||
|
||||
private void RelevanceLanguageChanged(object sender, SelectionChangedEventArgs e) =>
|
||||
FoxTube.Settings.RelevanceLanguage = ((ComboBoxItem)relevanceLanguage.SelectedItem).Tag.ToString();
|
||||
|
||||
private void RegionChanged(object sender, SelectionChangedEventArgs e) =>
|
||||
FoxTube.Settings.Region = ((ComboBoxItem)region.SelectedItem).Tag.ToString();
|
||||
|
||||
private void SafeSearchChanged(object sender, SelectionChangedEventArgs e) =>
|
||||
FoxTube.Settings.SafeSearch = safeSearch.SelectedIndex;
|
||||
|
||||
private void QualityChanged(object sender, SelectionChangedEventArgs e) =>
|
||||
FoxTube.Settings.DesiredVideoQuality = (quality.SelectedItem as ComboBoxItem).Tag as string;
|
||||
|
||||
private void MeteredWarningChanged(object sender, RoutedEventArgs e) =>
|
||||
FoxTube.Settings.CheckConnection = meteredWarning.IsOn;
|
||||
|
||||
private void AutoplayChanged(object sender, RoutedEventArgs e) =>
|
||||
FoxTube.Settings.Autoplay = autoplay.IsOn;
|
||||
|
||||
private void ExplicitWarningChanged(object sender, RoutedEventArgs e) =>
|
||||
FoxTube.Settings.BlockExplicitContent = explicitWarning.IsOn;
|
||||
|
||||
private void ChannelNotificationsChanged(object sender, RoutedEventArgs e) =>
|
||||
FoxTube.Settings.VideoNotifications = channelNotifications.IsOn;
|
||||
|
||||
private void ClipboardProcessingChanged(object sender, RoutedEventArgs e) =>
|
||||
FoxTube.Settings.ProcessClipboard = clipboardProcessing.IsOn;
|
||||
|
||||
private void DevelopersNotificationsChanged(object sender, RoutedEventArgs e) =>
|
||||
FoxTube.Settings.DevNotifications = developersNews.IsOn;
|
||||
|
||||
private void ThemeChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (FoxTube.Settings.Theme.ToString() == (string)(sender as RadioButton).Tag)
|
||||
return;
|
||||
|
||||
switch ((sender as RadioButton).Name)
|
||||
{
|
||||
case "light":
|
||||
FoxTube.Settings.Theme = 0;
|
||||
MainPage.Current.RequestedTheme = ElementTheme.Light;
|
||||
App.UpdateTitleBar(false);
|
||||
break;
|
||||
case "dark":
|
||||
FoxTube.Settings.Theme = 1;
|
||||
MainPage.Current.RequestedTheme = ElementTheme.Dark;
|
||||
App.UpdateTitleBar(true);
|
||||
break;
|
||||
default:
|
||||
FoxTube.Settings.Theme = 2;
|
||||
MainPage.Current.RequestedTheme = ElementTheme.Default;
|
||||
App.UpdateTitleBar(Application.Current.RequestedTheme == ApplicationTheme.Dark);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetApp(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Utils.Utils.InitializeFailsafeProtocol();
|
||||
}
|
||||
|
||||
private async void ChangeDownloadsPath(object sender, RoutedEventArgs e)
|
||||
{
|
||||
StorageFolder destinationFolder = await new FolderPicker().PickSingleFolderAsync();
|
||||
if (destinationFolder == null)
|
||||
return;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(FoxTube.Settings.DefaultDownloadsFolder))
|
||||
StorageApplicationPermissions.FutureAccessList.Remove(FoxTube.Settings.DefaultDownloadsFolder);
|
||||
|
||||
downloadsPath.Text = destinationFolder.Path;
|
||||
FoxTube.Settings.DefaultDownloadsFolder = StorageApplicationPermissions.FutureAccessList.Add(destinationFolder);
|
||||
}
|
||||
|
||||
private void AlwaysAskDownloadsChanged(object sender, RoutedEventArgs e) =>
|
||||
FoxTube.Settings.AskBeforeDownloading = askDownloads.IsOn;
|
||||
}
|
||||
}
|
||||
+4
-5
@@ -1,11 +1,10 @@
|
||||
<Page
|
||||
x:Class="FoxTube.Views.SettingsSections.Inbox"
|
||||
x:Class="FoxTube.Views.SettingsSections.InboxSection"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
|
||||
xmlns:models="using:FoxTube.Models"
|
||||
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls" xmlns:data="using:Google.Apis.Blogger.v3.Data"
|
||||
mc:Ignorable="d"
|
||||
Loaded="Page_Loaded">
|
||||
|
||||
@@ -53,7 +52,7 @@
|
||||
</controls:MasterDetailsView.ItemContainerStyle>
|
||||
|
||||
<controls:MasterDetailsView.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:InboxItem">
|
||||
<DataTemplate x:DataType="data:Post">
|
||||
<Grid ColumnSpacing="10" Margin="10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
@@ -73,7 +72,7 @@
|
||||
</controls:MasterDetailsView.ItemTemplate>
|
||||
|
||||
<controls:MasterDetailsView.DetailsTemplate>
|
||||
<DataTemplate x:DataType="models:InboxItem">
|
||||
<DataTemplate x:DataType="data:Post">
|
||||
<ScrollViewer>
|
||||
<Grid RowSpacing="10" Margin="10">
|
||||
<Grid.RowDefinitions>
|
||||
+7
-7
@@ -1,4 +1,4 @@
|
||||
using FoxTube.Models;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Windows.UI.Xaml;
|
||||
@@ -9,17 +9,17 @@ namespace FoxTube.Views.SettingsSections
|
||||
/// <summary>
|
||||
/// Inbox view
|
||||
/// </summary>
|
||||
public sealed partial class Inbox : Page
|
||||
public sealed partial class InboxSection : Page
|
||||
{
|
||||
InboxItem[] items;
|
||||
Google.Apis.Blogger.v3.Data.Post[] items;
|
||||
string idToOpen;
|
||||
|
||||
public Inbox() =>
|
||||
public InboxSection() =>
|
||||
InitializeComponent();
|
||||
|
||||
private async void Page_Loaded(object sender, RoutedEventArgs e)
|
||||
private void Page_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
items = await Services.Inbox.GetMessages();
|
||||
items = Services.InboxService.GetInboxCollection().ToArray();
|
||||
|
||||
filter.SelectedIndex = 0;
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace FoxTube.Views.SettingsSections
|
||||
if (!IsLoaded)
|
||||
return;
|
||||
|
||||
masterDetailsView.SelectedItem = (masterDetailsView.ItemsSource as List<InboxItem>).Find(i => i.Id == id);
|
||||
masterDetailsView.SelectedItem = (masterDetailsView.ItemsSource as List<Google.Apis.Blogger.v3.Data.Post>).Find(i => i.Id == id);
|
||||
|
||||
idToOpen = null;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<Page
|
||||
x:Class="FoxTube.Views.SettingsSections.PreferencesSection"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:winui="using:Microsoft.UI.Xaml.Controls" xmlns:globalization="using:System.Globalization"
|
||||
mc:Ignorable="d"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<Page.Resources>
|
||||
<Style TargetType="ComboBox">
|
||||
<Setter Property="MinWidth" Value="250"/>
|
||||
</Style>
|
||||
</Page.Resources>
|
||||
|
||||
<ScrollViewer Padding="10">
|
||||
<StackPanel>
|
||||
<StackPanel.ChildrenTransitions>
|
||||
<TransitionCollection>
|
||||
<EntranceThemeTransition IsStaggeringEnabled="True" FromVerticalOffset="100"/>
|
||||
</TransitionCollection>
|
||||
</StackPanel.ChildrenTransitions>
|
||||
|
||||
<StackPanel Margin="0,0,0,10">
|
||||
<TextBlock Text="General" Style="{StaticResource TitleTextBlockStyle}"/>
|
||||
<CheckBox x:Name="MetricsCheckbox" Content="Allow to send anonymous statistics and data to help us improve the app" IsEnabled="False" Checked="MetricsCheckbox_Checked" Unchecked="MetricsCheckbox_Checked" ToolTipService.ToolTip="You cannot change the value since you are using preview version"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,0,0,10">
|
||||
<TextBlock Text="Region & Search" Style="{StaticResource TitleTextBlockStyle}"/>
|
||||
<ComboBox x:Name="RelevanceLanguageList" Header="Prefered content language" SelectionChanged="RelevanceLanguageList_SelectionChanged" DisplayMemberPath="DisplayName"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,0,0,10">
|
||||
<TextBlock Text="Downloads" Style="{StaticResource TitleTextBlockStyle}"/>
|
||||
<Grid Width="250" HorizontalAlignment="Left" ColumnSpacing="5">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="32"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBox x:Name="DownloadsPathTextBox" Header="Default downloads folder" IsReadOnly="True"/>
|
||||
|
||||
<Button x:Name="ChangeDownloadsPathButton" Grid.Column="1" VerticalAlignment="Bottom" FontFamily="Segoe MDL2 Assets" Content="" Padding="0" Height="32" Width="32" Click="ChangeDownloadsPathButton_Click"/>
|
||||
</Grid>
|
||||
<CheckBox x:Name="AskDownloadsCheckbox" Content="Always ask where to save a video" Checked="AskDownloadsCheckbox_Checked" Unchecked="AskDownloadsCheckbox_Checked"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,0,0,10">
|
||||
<TextBlock Text="Appearance" Style="{StaticResource TitleTextBlockStyle}"/>
|
||||
<winui:RadioButtons Header="Color mode" x:Name="ThemeRadio" SelectionChanged="ThemeRadio_SelectionChanged">
|
||||
<RadioButton Content="Windows default"/>
|
||||
<RadioButton Content="Light"/>
|
||||
<RadioButton Content="Dark"/>
|
||||
</winui:RadioButtons>
|
||||
<HyperlinkButton Content="Windows color settings" NavigateUri="ms-settings:colors"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Page>
|
||||
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using FoxTube.Services;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Windows.Storage;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using System.Linq;
|
||||
|
||||
namespace FoxTube.Views.SettingsSections
|
||||
{
|
||||
/// <summary>
|
||||
/// Preferences page
|
||||
/// </summary>
|
||||
public sealed partial class PreferencesSection : Page
|
||||
{
|
||||
public PreferencesSection()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
MetricsCheckbox.IsChecked = SettingsService.AllowAnalytics;
|
||||
|
||||
RelevanceLanguageList.ItemsSource = CultureInfo.GetCultures(CultureTypes.NeutralCultures);
|
||||
RelevanceLanguageList.SelectedIndex = CultureInfo.GetCultures(CultureTypes.NeutralCultures).ToList().FindIndex(i => i.TwoLetterISOLanguageName == SettingsService.RelevanceLanguage);
|
||||
|
||||
AskDownloadsCheckbox.IsChecked = SettingsService.AskEveryDownload;
|
||||
SetDownloadsPath();
|
||||
|
||||
ThemeRadio.SelectedIndex = (int)SettingsService.Theme;
|
||||
}
|
||||
|
||||
private async void SetDownloadsPath() =>
|
||||
DownloadsPathTextBox.Text = (await DownloadsService.GetDefaultDownloadsFolder()).Path;
|
||||
|
||||
private void ThemeRadio_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
Frame frame = Window.Current.Content as Frame;
|
||||
RadioButtons set = sender as RadioButtons;
|
||||
if ((int)SettingsService.Theme == set.SelectedIndex)
|
||||
return;
|
||||
|
||||
(Window.Current.Content as Frame).RequestedTheme = SettingsService.Theme = (ElementTheme)set.SelectedIndex;
|
||||
|
||||
if (SettingsService.Theme == ElementTheme.Default)
|
||||
Utils.Utils.UpdateTitleBarTheme(Application.Current.RequestedTheme == ApplicationTheme.Dark);
|
||||
else
|
||||
Utils.Utils.UpdateTitleBarTheme(frame.RequestedTheme == ElementTheme.Dark);
|
||||
}
|
||||
|
||||
private async void MetricsCheckbox_Checked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (MetricsCheckbox.IsChecked == SettingsService.AllowAnalytics)
|
||||
return;
|
||||
|
||||
if (!MetricsCheckbox.IsChecked.Value)
|
||||
{
|
||||
ContentDialog dialog = new ContentDialog
|
||||
{
|
||||
Title = "Are you sure?",
|
||||
Content = "This information is very important for us. It helps us to fix problems faster and implement new awesome features quickly. Be sure that none of your personal information will be involved\n" +
|
||||
"Check out our privacy policy for details\n" +
|
||||
"Are you sure you want to continue?",
|
||||
PrimaryButtonText = "No",
|
||||
CloseButtonText = "Yes",
|
||||
SecondaryButtonText = "Open privacy policy"
|
||||
};
|
||||
if (await dialog.ShowAsync() != ContentDialogResult.None)
|
||||
return;
|
||||
}
|
||||
|
||||
SettingsService.AllowAnalytics = MetricsCheckbox.IsChecked.Value;
|
||||
}
|
||||
|
||||
private void RelevanceLanguageList_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (SettingsService.RelevanceLanguage != ((CultureInfo)RelevanceLanguageList.SelectedItem).TwoLetterISOLanguageName)
|
||||
SettingsService.RelevanceLanguage = ((CultureInfo)RelevanceLanguageList.SelectedItem).TwoLetterISOLanguageName;
|
||||
}
|
||||
|
||||
private async void ChangeDownloadsPathButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
StorageFolder newFolder = await DownloadsService.ChangeDefaultFolder();
|
||||
if (newFolder != null)
|
||||
DownloadsPathTextBox.Text = newFolder.Path;
|
||||
}
|
||||
|
||||
private void AskDownloadsCheckbox_Checked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (SettingsService.AskEveryDownload != ((CheckBox)sender).IsChecked.Value)
|
||||
SettingsService.AskEveryDownload = ((CheckBox)sender).IsChecked.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<Page
|
||||
x:Class="FoxTube.Views.SettingsView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:settingssections="using:FoxTube.Views.SettingsSections"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Pivot SelectedIndex="0" Name="PivotControl">
|
||||
<PivotItem Name="PreferencesTab" Header="Preferences">
|
||||
<settingssections:PreferencesSection/>
|
||||
</PivotItem>
|
||||
<PivotItem Name="AboutTab" Header="About us">
|
||||
<settingssections:AboutSection/>
|
||||
</PivotItem>
|
||||
<PivotItem Name="InboxTab" Header="Inbox">
|
||||
<settingssections:InboxSection x:Name="InboxSection"/>
|
||||
</PivotItem>
|
||||
</Pivot>
|
||||
</Page>
|
||||
@@ -6,9 +6,9 @@ namespace FoxTube.Views
|
||||
/// <summary>
|
||||
/// Settings page
|
||||
/// </summary>
|
||||
public sealed partial class Settings : Page
|
||||
public sealed partial class SettingsView : Page
|
||||
{
|
||||
public Settings() =>
|
||||
public SettingsView() =>
|
||||
InitializeComponent();
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
@@ -24,17 +24,17 @@ namespace FoxTube.Views
|
||||
{
|
||||
case "about":
|
||||
case "info":
|
||||
pivot.SelectedItem = aboutTab;
|
||||
PivotControl.SelectedItem = AboutTab;
|
||||
break;
|
||||
case "inbox":
|
||||
case "message":
|
||||
case "changelog":
|
||||
pivot.SelectedItem = inboxTab;
|
||||
PivotControl.SelectedItem = InboxTab;
|
||||
if (param.Length > 1)
|
||||
inbox.Open(param[1]);
|
||||
InboxSection.Open(param[1]);
|
||||
break;
|
||||
default:
|
||||
pivot.SelectedItem = generalTab;
|
||||
PivotControl.SelectedItem = PreferencesTab;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<Page
|
||||
NavigationCacheMode="Enabled"
|
||||
x:Class="FoxTube.Views.Subscriptions"
|
||||
x:Class="FoxTube.Views.SubscriptionsView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
@@ -1,5 +1,6 @@
|
||||
using FoxTube.Attributes;
|
||||
using FoxTube.Models;
|
||||
using FoxTube.Services;
|
||||
using System.Linq;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
@@ -10,12 +11,12 @@ namespace FoxTube.Views
|
||||
/// User's subscriptions list
|
||||
/// </summary>
|
||||
[Refreshable]
|
||||
public sealed partial class Subscriptions : Page
|
||||
public sealed partial class SubscriptionsView : Page
|
||||
{
|
||||
public Subscriptions()
|
||||
public SubscriptionsView()
|
||||
{
|
||||
InitializeComponent();
|
||||
list.ItemsSource = UserManagement.CurrentUser.Subscriptions;
|
||||
list.ItemsSource = UserService.CurrentUser.Subscriptions;
|
||||
}
|
||||
|
||||
private void List_ItemClick(object sender, ItemClickEventArgs e)
|
||||
@@ -26,8 +27,8 @@ namespace FoxTube.Views
|
||||
private async void Unsubscribe(object sender, Windows.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
loadingScreen.IsLoading = true;
|
||||
await UserManagement.CurrentUser.UpdateSubscriptionState((sender as Button).Tag as string);
|
||||
list.ItemsSource = UserManagement.CurrentUser.Subscriptions;
|
||||
await UserService.CurrentUser.UpdateSubscriptionState((sender as Button).Tag as string);
|
||||
list.ItemsSource = UserService.CurrentUser.Subscriptions;
|
||||
loadingScreen.IsLoading = false;
|
||||
}
|
||||
|
||||
@@ -46,10 +47,10 @@ namespace FoxTube.Views
|
||||
{
|
||||
loadingScreen.IsLoading = true;
|
||||
|
||||
await UserManagement.CurrentUser.LoadSubscriptions();
|
||||
list.ItemsSource = UserManagement.CurrentUser.Subscriptions;
|
||||
await UserService.CurrentUser.LoadSubscriptions();
|
||||
list.ItemsSource = UserService.CurrentUser.Subscriptions;
|
||||
|
||||
MainPage.Current.UpdateSubscriptions();
|
||||
MainPage.Current.UpdateMenu();
|
||||
|
||||
loadingScreen.IsLoading = false;
|
||||
}
|
||||
Reference in New Issue
Block a user