+49
-26
@@ -1,7 +1,10 @@
|
||||
using FoxTube.Pages;
|
||||
using System.Diagnostics;
|
||||
using FoxTube.Classes;
|
||||
using FoxTube.Controls;
|
||||
using FoxTube.Pages;
|
||||
using Microsoft.AppCenter.Analytics;
|
||||
using System.Collections.Generic;
|
||||
using Windows.ApplicationModel.Activation;
|
||||
using Windows.UI.Notifications;
|
||||
using Windows.Globalization;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
@@ -9,47 +12,67 @@ namespace FoxTube
|
||||
{
|
||||
sealed partial class App : Application
|
||||
{
|
||||
public App()
|
||||
{
|
||||
public App() =>
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
/*protected override void OnLaunched(LaunchActivatedEventArgs e)
|
||||
/*void Initialize()
|
||||
{
|
||||
if (!(Window.Current.Content is Frame))
|
||||
Window.Current.Content = new Frame();
|
||||
Settings.LoadData();
|
||||
|
||||
if (e.PrelaunchActivated == false)
|
||||
switch (Settings.Theme)
|
||||
{
|
||||
if ((Window.Current.Content as Frame).Content == null)
|
||||
(Window.Current.Content as Frame).Navigate(typeof(MainPage), e.Arguments);
|
||||
|
||||
Window.Current.Activate();
|
||||
case 0:
|
||||
RequestedTheme = ApplicationTheme.Light;
|
||||
break;
|
||||
case 1:
|
||||
RequestedTheme = ApplicationTheme.Dark;
|
||||
break;
|
||||
}
|
||||
ApplicationLanguages.PrimaryLanguageOverride = Settings.Language;
|
||||
|
||||
Processes.InitializeApp();
|
||||
|
||||
Suspending += (s, e) => Processes.SuspendApp();
|
||||
UnhandledException += (s, e) => Analytics.TrackEvent("The app crashed", new Dictionary<string, string>()
|
||||
{
|
||||
{ "Exception", e.Exception.GetType().ToString() },
|
||||
{ "Details", e.Message },
|
||||
{ "StackTrace", e.Exception.StackTrace }
|
||||
});
|
||||
}*/
|
||||
|
||||
protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
|
||||
protected override void OnLaunched(LaunchActivatedEventArgs e)
|
||||
{
|
||||
if (!e.PrelaunchActivated && Window.Current.Content == null)
|
||||
Window.Current.Content = new MainPage(e.SplashScreen, e.Arguments);
|
||||
Window.Current.Activate();
|
||||
}
|
||||
|
||||
protected override async void OnBackgroundActivated(BackgroundActivatedEventArgs args)
|
||||
{
|
||||
var deferral = args.TaskInstance.GetDeferral();
|
||||
base.OnBackgroundActivated(args);
|
||||
|
||||
await Methods.ProcessBackgroundToast((args.TaskInstance.TriggerDetails as ToastNotificationActivatedEventArgs).Argument);
|
||||
|
||||
deferral.Complete();
|
||||
}
|
||||
|
||||
protected override void OnActivated(IActivatedEventArgs e)
|
||||
{
|
||||
base.OnActivated(e);
|
||||
|
||||
//TODO: Check this shit
|
||||
if (!(Window.Current.Content is Frame rootFrame))
|
||||
{
|
||||
rootFrame = new Frame();
|
||||
Window.Current.Content = rootFrame;
|
||||
}
|
||||
|
||||
if (rootFrame.Content == null)
|
||||
rootFrame.Navigate(typeof(MainPage));
|
||||
|
||||
if (Window.Current.Content == null)
|
||||
Window.Current.Content = new MainPage(e.SplashScreen, e);
|
||||
Window.Current.Activate();
|
||||
|
||||
Debug.WriteLine("Hello, World");
|
||||
/*if(e.Kind == ActivationKind.ToastNotification)
|
||||
{
|
||||
if (UserManagement.IsAuthorized)
|
||||
Methods.ProcessToast((e as ToastNotificationActivatedEventArgs).Argument);
|
||||
else
|
||||
UserManagement.AuthorizationStateChanged += (arg) => Methods.ProcessToast((e as ToastNotificationActivatedEventArgs).Argument);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FoxTube.Classes
|
||||
{
|
||||
public static class Downloads
|
||||
{
|
||||
public static void Cancel(string id)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using Google.Apis.YouTube.v3.Data;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
|
||||
namespace FoxTube
|
||||
{
|
||||
public delegate void AuthorizationChangedEventHandler(bool isAuthorized);
|
||||
public delegate void SubscriptionChangedEventHandler(string action, Subscription subscription);
|
||||
public delegate void ProVersionStateChangedEventHandler(bool purchased, string price);
|
||||
public delegate void NavigatingOccured(Type sourcePageType, object parameter);
|
||||
public delegate void NavigationOccured(IList pivotCollection, int? selectedPivot);
|
||||
public delegate void SimpleEventHandler();
|
||||
|
||||
public enum LoadingScreenState
|
||||
{
|
||||
Loading = 0,
|
||||
Loaded = 1,
|
||||
Error = 2,
|
||||
Blocked = 3
|
||||
}
|
||||
|
||||
public interface INavigationPage
|
||||
{
|
||||
object Parameter { get; set; }
|
||||
}
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
public static Uri ToUri(this string str) =>
|
||||
string.IsNullOrWhiteSpace(str) ? null : new Uri(str);
|
||||
|
||||
public static bool Belongs<T>(this T obj, params T[] values) =>
|
||||
values.Contains(obj);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
using FoxTube.Classes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.UI;
|
||||
using Windows.UI.ViewManagement;
|
||||
using Windows.UI.Xaml;
|
||||
|
||||
namespace FoxTube
|
||||
{
|
||||
public static class Methods
|
||||
{
|
||||
public static void ProcessToast(string argument)
|
||||
{
|
||||
string[] args = argument.Split('|');
|
||||
|
||||
switch (args[0])
|
||||
{
|
||||
case "changelog":
|
||||
case "inbox":
|
||||
Navigation.GoToDeveloper(args[1]);
|
||||
break;
|
||||
|
||||
case "video":
|
||||
Navigation.GoToVideo(args[1]);
|
||||
break;
|
||||
|
||||
case "channel":
|
||||
Navigation.GoToChannel(args[1]);
|
||||
break;
|
||||
|
||||
case "download":
|
||||
Navigation.GoToDownloads();
|
||||
break;
|
||||
case "clipboard":
|
||||
switch (args[1])
|
||||
{
|
||||
case "video":
|
||||
Navigation.GoToVideo(args[2]);
|
||||
break;
|
||||
case "channel":
|
||||
Navigation.GoToChannel(args[2]);
|
||||
break;
|
||||
case "playlist":
|
||||
Navigation.GoToPlaylist(args[2]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task ProcessBackgroundToast(string argument)
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] args = argument.Split('|');
|
||||
|
||||
switch (args[0])
|
||||
{
|
||||
case "dcancel":
|
||||
Downloads.Cancel(args[1]);
|
||||
break;
|
||||
case "later":
|
||||
await UserManagement.AddItemToWL(args[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
public static void SetTitleBar()
|
||||
{
|
||||
var titleBar = ApplicationView.GetForCurrentView().TitleBar;
|
||||
|
||||
titleBar.ButtonBackgroundColor = Colors.Transparent;
|
||||
titleBar.ButtonHoverBackgroundColor = Colors.IndianRed;
|
||||
titleBar.ButtonPressedBackgroundColor = Colors.DarkRed;
|
||||
titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
|
||||
titleBar.ButtonInactiveForegroundColor = Colors.Gray;
|
||||
titleBar.ButtonForegroundColor = Colors.White;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using FoxTube.Classes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FoxTube
|
||||
{
|
||||
public static class Navigation
|
||||
{
|
||||
public static void GoToSubscriptions()
|
||||
{
|
||||
|
||||
}
|
||||
public static void GoToSearch(SearchParameters args)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void GoToChannel(string id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void GoToHome()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void GoToVideo(string id, string playlistId = null, bool incognito = false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void GoToDeveloper(string id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void GoToPlaylist(string id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void GoToHistory()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void GoToDownloads()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
using Microsoft.AppCenter;
|
||||
using Microsoft.AppCenter.Analytics;
|
||||
using Microsoft.Services.Store.Engagement;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Windows.ApplicationModel.Background;
|
||||
using Windows.ApplicationModel.DataTransfer;
|
||||
using Windows.ApplicationModel.Resources;
|
||||
using Windows.Data.Xml.Dom;
|
||||
using Windows.System;
|
||||
using Windows.System.Power;
|
||||
using Windows.UI.Core;
|
||||
using Windows.UI.Notifications;
|
||||
using Windows.UI.Popups;
|
||||
using Windows.UI.Xaml;
|
||||
|
||||
namespace FoxTube.Classes
|
||||
{
|
||||
public static class Processes
|
||||
{
|
||||
static CoreWindowActivationState windowState = CoreWindowActivationState.CodeActivated;
|
||||
static ResourceLoader resources = ResourceLoader.GetForViewIndependentUse("Inbox");
|
||||
|
||||
static Stopwatch sw = new Stopwatch();
|
||||
public static async void InitializeApp() => await CoreWindow.GetForCurrentThread().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
||||
{
|
||||
CheckVersion();
|
||||
|
||||
RegisterToastTask();
|
||||
if (Settings.DevNotifications || Settings.VideoNotifications)
|
||||
RegisterTask();
|
||||
else
|
||||
UnregisterTask();
|
||||
|
||||
AppCenter.Start("45774462-9ea7-438a-96fc-03982666f39e", typeof(Analytics));
|
||||
AppCenter.SetCountryCode(Settings.Region);
|
||||
|
||||
sw.Start();
|
||||
|
||||
Window.Current.Activated += (s, e) => windowState = e.WindowActivationState;
|
||||
|
||||
// TODO: Initialize other stuff
|
||||
|
||||
if (Settings.ProcessClipboard)
|
||||
{
|
||||
Clipboard.ContentChanged += ParseClipboard;
|
||||
ParseClipboard();
|
||||
}
|
||||
|
||||
PromptFeedback();
|
||||
});
|
||||
|
||||
public static void SuspendApp()
|
||||
{
|
||||
sw.Stop();
|
||||
|
||||
Settings.Uptime += sw.Elapsed;
|
||||
|
||||
// TODO: Save other stuff
|
||||
|
||||
Analytics.TrackEvent("Session terminated", new Dictionary<string, string>
|
||||
{
|
||||
{ "Uptime", sw.Elapsed.ToString() },
|
||||
{ "Total time", Settings.Uptime.ToString() }
|
||||
});
|
||||
}
|
||||
|
||||
static async void ParseClipboard(object sender = null, object e = null)
|
||||
{
|
||||
if (windowState != CoreWindowActivationState.Deactivated || !Settings.ProcessClipboard)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
string link = await Clipboard.GetContent().GetTextAsync();
|
||||
|
||||
if (!link.Contains("youtube") && !link.Contains("youtu.be"))
|
||||
return;
|
||||
|
||||
string type = string.Empty;
|
||||
string name = string.Empty;
|
||||
|
||||
if (YoutubeExplode.YoutubeClient.TryParseChannelId(link, out string id))
|
||||
{
|
||||
type = "channel";
|
||||
name = (await new YoutubeExplode.YoutubeClient().GetChannelAsync(id)).Title;
|
||||
}
|
||||
else if (YoutubeExplode.YoutubeClient.TryParsePlaylistId(link, out id))
|
||||
{
|
||||
type = "playlist";
|
||||
name = (await new YoutubeExplode.YoutubeClient().GetPlaylistAsync(id)).Title;
|
||||
}
|
||||
else if (YoutubeExplode.YoutubeClient.TryParseUsername(link, out id))
|
||||
{
|
||||
id = await new YoutubeExplode.YoutubeClient().GetChannelIdAsync(id);
|
||||
type = "channel";
|
||||
name = (await new YoutubeExplode.YoutubeClient().GetChannelAsync(id)).Title;
|
||||
}
|
||||
else if (YoutubeExplode.YoutubeClient.TryParseVideoId(link, out id))
|
||||
{
|
||||
type = "video";
|
||||
name = (await new YoutubeExplode.YoutubeClient().GetVideoAsync(id)).Title;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(id))
|
||||
return;
|
||||
|
||||
XmlDocument toastXml = new XmlDocument();
|
||||
toastXml.LoadXml($@"<toast launch='clipboard|{type}|{id}'>
|
||||
<visual>
|
||||
<binding template='ToastGeneric'>
|
||||
<text>{resources.GetString("/Toasts/clipboardHead")}</text>
|
||||
<text>{name}</text>
|
||||
<text>{resources.GetString($"/Generic/{type}")}</text>
|
||||
</binding>
|
||||
</visual>
|
||||
<actions>
|
||||
<action content='{resources.GetString("/Toasts/clipboardOpen")}' arguments='clipboard|{type}|{id}'/>
|
||||
</actions>
|
||||
</toast>");
|
||||
ToastNotificationManager.CreateToastNotifier().Show(new ToastNotification(toastXml));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
static void CheckVersion()
|
||||
{
|
||||
if (Settings.GetCurrentVersion() == Settings.Version)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
XmlDocument toast = new XmlDocument();
|
||||
toast.LoadXml($@"<toast activationType='foreground' launch='changelog|{Settings.GetCurrentVersion()}'>
|
||||
<visual>
|
||||
<binding template='ToastGeneric'>
|
||||
<image placement='hero' src='ms-appx:///Assets/WhatsNewThumb.png'/>
|
||||
<image placement='appLogoOverride' hint-crop='circle' src='ms-appx:///Assets/NewsAvatar.png'/>
|
||||
<text>{resources.GetString("/Inbox/changelog")}</text>
|
||||
<text>{resources.GetString("/Inbox/whatsNew")} {Settings.GetCurrentVersion()}</text>
|
||||
</binding>
|
||||
</visual>
|
||||
</toast>");
|
||||
|
||||
ToastNotificationManager.CreateToastNotifier().Show(new ToastNotification(toast));
|
||||
|
||||
Settings.Version = Settings.GetCurrentVersion();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
static async void RegisterToastTask()
|
||||
{
|
||||
if (BackgroundTaskRegistration.AllTasks.Any(i => i.Value.Name.Equals("foxtubeToast")))
|
||||
return;
|
||||
|
||||
var backgroundRequest = await BackgroundExecutionManager.RequestAccessAsync();
|
||||
if (backgroundRequest == BackgroundAccessStatus.DeniedBySystemPolicy ||
|
||||
backgroundRequest == BackgroundAccessStatus.DeniedByUser ||
|
||||
backgroundRequest == BackgroundAccessStatus.Unspecified)
|
||||
return;
|
||||
|
||||
BackgroundTaskBuilder builder = new BackgroundTaskBuilder() { Name = "foxtubeToast" };
|
||||
builder.SetTrigger(new ToastNotificationActionTrigger());
|
||||
|
||||
BackgroundTaskRegistration registration = builder.Register();
|
||||
}
|
||||
|
||||
static async void RegisterTask()
|
||||
{
|
||||
if (BackgroundTaskRegistration.AllTasks.Any(i => i.Value.Name.Equals("foxtubeBackground")))
|
||||
return;
|
||||
|
||||
var backgroundRequest = await BackgroundExecutionManager.RequestAccessAsync();
|
||||
if (backgroundRequest == BackgroundAccessStatus.DeniedBySystemPolicy ||
|
||||
backgroundRequest == BackgroundAccessStatus.DeniedByUser ||
|
||||
backgroundRequest == BackgroundAccessStatus.Unspecified ||
|
||||
PowerManager.EnergySaverStatus == EnergySaverStatus.On)
|
||||
return;
|
||||
|
||||
BackgroundTaskBuilder builder = new BackgroundTaskBuilder()
|
||||
{
|
||||
Name = "foxtubeBackgound",
|
||||
IsNetworkRequested = true,
|
||||
TaskEntryPoint = "FoxTube.Background.BackgroundProcessor"
|
||||
};
|
||||
builder.SetTrigger(new TimeTrigger(15, false));
|
||||
|
||||
BackgroundTaskRegistration registration = builder.Register();
|
||||
}
|
||||
|
||||
static void UnregisterTask()
|
||||
{
|
||||
if (!(BackgroundTaskRegistration.AllTasks.Values.ToList().Find(i => i.Name == "foxtubeBackground") is IBackgroundTaskRegistration task))
|
||||
return;
|
||||
|
||||
task.Unregister(true);
|
||||
}
|
||||
|
||||
static async void PromptFeedback()
|
||||
{
|
||||
if (Settings.Uptime.TotalHours >= 12 && Settings.PromptFeedback)
|
||||
{
|
||||
Analytics.TrackEvent("Prompting feedback", new Dictionary<string, string>
|
||||
{
|
||||
{ "Total uptime", Settings.Uptime.ToString() }
|
||||
});
|
||||
|
||||
MessageDialog dialog = new MessageDialog(resources.GetString("/Dialogs/feedbackMessage"));
|
||||
dialog.Commands.Add(new UICommand(resources.GetString("/Dialogs/dontAsk"), (command) => Settings.PromptFeedback = false));
|
||||
dialog.Commands.Add(new UICommand(resources.GetString("/Dialogs/promptLater")));
|
||||
dialog.Commands.Add(new UICommand(resources.GetString("/Dialogs/sure"), async (command) =>
|
||||
{
|
||||
Settings.PromptFeedback = false;
|
||||
if (StoreServicesFeedbackLauncher.IsSupported())
|
||||
await StoreServicesFeedbackLauncher.GetDefault().LaunchAsync();
|
||||
else
|
||||
await Launcher.LaunchUriAsync("mailto:feedback@xfox111.net".ToUri());
|
||||
}));
|
||||
dialog.DefaultCommandIndex = 2;
|
||||
dialog.CancelCommandIndex = 1;
|
||||
await dialog.ShowAsync();
|
||||
}
|
||||
|
||||
if (Settings.Uptime.TotalHours >= 24 && Settings.PromptReview)
|
||||
{
|
||||
Analytics.TrackEvent("Prompting review", new Dictionary<string, string>
|
||||
{
|
||||
{ "Total uptime", Settings.Uptime.ToString() }
|
||||
});
|
||||
|
||||
MessageDialog dialog = new MessageDialog(resources.GetString("/Dialogs/rate"));
|
||||
dialog.Commands.Add(new UICommand(resources.GetString("/Dialogs/dontAsk"), (command) => Settings.PromptReview = false));
|
||||
dialog.Commands.Add(new UICommand(resources.GetString("/Dialogs/promptLater")));
|
||||
dialog.Commands.Add(new UICommand(resources.GetString("/Dialogs/sure"), async (command) =>
|
||||
{
|
||||
Settings.PromptReview = false;
|
||||
await Launcher.LaunchUriAsync("ms-windows-store://review/?ProductId=9NCQQXJTDLFH".ToUri());
|
||||
}));
|
||||
dialog.DefaultCommandIndex = 2;
|
||||
dialog.CancelCommandIndex = 1;
|
||||
await dialog.ShowAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FoxTube.Classes
|
||||
{
|
||||
public class SearchParameters
|
||||
{
|
||||
public SearchParameters(string query)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using Windows.Services.Store;
|
||||
|
||||
namespace FoxTube
|
||||
{
|
||||
public static class Service
|
||||
{
|
||||
public static bool AdsCheckPerformed { get; private set; } = false;
|
||||
public static bool AdsDisabled { get; private set; } = true;
|
||||
public static event ProVersionStateChangedEventHandler Purchased;
|
||||
|
||||
public static NetworkCredential EmailCredential => new NetworkCredential("foxtube.bot@xfox111.net", "JkY39w$.7?bT57O,8k3a");
|
||||
|
||||
private static bool TestAds => false; //TODO: Change this bool
|
||||
public static string AppId => TestAds ? "d25517cb-12d4-4699-8bdc-52040c712cab" : "9ncqqxjtdlfh";
|
||||
public static string AdUnitId => TestAds ? "test" : "1100037769";
|
||||
|
||||
public static async void CheckAddons()
|
||||
{
|
||||
try
|
||||
{
|
||||
StoreProductQueryResult requset = await StoreContext.GetDefault().GetAssociatedStoreProductsAsync(new[] { "Durable" });
|
||||
|
||||
if (requset.Products["9NP1QK556625"].IsInUserCollection)
|
||||
return;
|
||||
|
||||
AdsDisabled = false;
|
||||
Purchased?.Invoke(false, requset.Products["9NP1QK556625"].Price.FormattedPrice);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
public static async void GetPro()
|
||||
{
|
||||
try
|
||||
{
|
||||
StorePurchaseResult request = await StoreContext.GetDefault().RequestPurchaseAsync("9NP1QK556625");
|
||||
|
||||
if (!request.Status.Belongs(StorePurchaseStatus.AlreadyPurchased, StorePurchaseStatus.Succeeded))
|
||||
return;
|
||||
|
||||
Purchased?.Invoke(true, "");
|
||||
AdsDisabled = true;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.Storage;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace FoxTube.Classes
|
||||
{
|
||||
public static class Settings
|
||||
{
|
||||
public class SettingsContainer
|
||||
{
|
||||
public string videoQuality = "remember";
|
||||
public string rememberedQuality = "1080p";
|
||||
|
||||
public bool videoNotifications = true;
|
||||
public bool devNotifications = true;
|
||||
|
||||
public bool checkConnection = true;
|
||||
public bool autoplay = true;
|
||||
public double volume = 100;
|
||||
|
||||
public string language = GetLanguage();
|
||||
public string relevanceLanguage = CultureInfo.InstalledUICulture.TwoLetterISOLanguageName;
|
||||
public string region = CultureInfo.InstalledUICulture.Name.Split('-')[1];
|
||||
public int safeSearch = 0;
|
||||
|
||||
public bool[] hasAccount = new bool[5] { false, false, false, false, false };
|
||||
public int theme = 2;
|
||||
|
||||
public string version = GetCurrentVersion();
|
||||
public bool mature = false;
|
||||
|
||||
public TimeSpan uptime = TimeSpan.FromSeconds(0);
|
||||
public bool promptReview = true;
|
||||
public bool promptFeedback = true;
|
||||
|
||||
public bool processClipboard = true;
|
||||
public bool minimizeCommandbar = false;
|
||||
|
||||
static string GetLanguage()
|
||||
{
|
||||
if ((new[] { "ua", "ru", "by", "kz", "kg", "md", "lv", "ee" }).Contains(CultureInfo.InstalledUICulture.TwoLetterISOLanguageName))
|
||||
return "ru-RU";
|
||||
else
|
||||
return "en-US";
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetCurrentVersion()
|
||||
{
|
||||
PackageVersion ver = Package.Current.Id.Version;
|
||||
return $"{ver.Major}.{ver.Minor}";
|
||||
}
|
||||
|
||||
public static string VideoQuality
|
||||
{
|
||||
get => Container.videoQuality;
|
||||
set
|
||||
{
|
||||
Container.videoQuality = value;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
public static string RememberedQuality
|
||||
{
|
||||
get => Container.rememberedQuality;
|
||||
set
|
||||
{
|
||||
Container.rememberedQuality = value;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool VideoNotifications
|
||||
{
|
||||
get => Container.videoNotifications;
|
||||
set
|
||||
{
|
||||
Container.videoNotifications = value;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
public static bool DevNotifications
|
||||
{
|
||||
get => Container.devNotifications;
|
||||
set
|
||||
{
|
||||
Container.devNotifications = value;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CheckConnection
|
||||
{
|
||||
get => Container.checkConnection;
|
||||
set
|
||||
{
|
||||
Container.checkConnection = value;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
public static bool Autoplay
|
||||
{
|
||||
get => Container.autoplay;
|
||||
set
|
||||
{
|
||||
Container.autoplay = value;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
public static double Volume
|
||||
{
|
||||
get => Container.volume;
|
||||
set
|
||||
{
|
||||
Container.volume = value;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
|
||||
public static string Language
|
||||
{
|
||||
get => Container.language;
|
||||
set
|
||||
{
|
||||
Container.language = value;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
public static string RelevanceLanguage
|
||||
{
|
||||
get => Container.relevanceLanguage;
|
||||
set
|
||||
{
|
||||
Container.relevanceLanguage = value;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
public static string Region
|
||||
{
|
||||
get => Container.region;
|
||||
set
|
||||
{
|
||||
Container.region = value;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
public static int SafeSearch
|
||||
{
|
||||
get => Container.safeSearch;
|
||||
set
|
||||
{
|
||||
Container.safeSearch = value;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
public static bool[] HasAccount => Container.hasAccount;
|
||||
public static void SetAccount(int index, bool isAuthorized)
|
||||
{
|
||||
HasAccount[index] = isAuthorized;
|
||||
SaveData();
|
||||
}
|
||||
public static int Theme
|
||||
{
|
||||
get => Container.theme;
|
||||
set
|
||||
{
|
||||
Container.theme = value;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
|
||||
public static string Version
|
||||
{
|
||||
get => Container.version;
|
||||
set
|
||||
{
|
||||
Container.version = value;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
public static bool Mature
|
||||
{
|
||||
get => Container.mature;
|
||||
set
|
||||
{
|
||||
Container.mature = value;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
|
||||
public static TimeSpan Uptime
|
||||
{
|
||||
get => Container.uptime;
|
||||
set
|
||||
{
|
||||
Container.uptime = value;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
public static bool PromptReview
|
||||
{
|
||||
get => Container.promptReview;
|
||||
set
|
||||
{
|
||||
Container.promptReview = value;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
public static bool PromptFeedback
|
||||
{
|
||||
get => Container.promptFeedback;
|
||||
set
|
||||
{
|
||||
Container.promptFeedback = value;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ProcessClipboard
|
||||
{
|
||||
get => Container.processClipboard;
|
||||
set
|
||||
{
|
||||
Container.processClipboard = value;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
|
||||
public static AppBarClosedDisplayMode AppBarClosedMode
|
||||
{
|
||||
get => Container.minimizeCommandbar ? AppBarClosedDisplayMode.Minimal : AppBarClosedDisplayMode.Compact;
|
||||
set
|
||||
{
|
||||
Container.minimizeCommandbar = value == AppBarClosedDisplayMode.Minimal;
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
|
||||
//Settings storage
|
||||
static readonly ApplicationDataContainer storage = ApplicationData.Current.RoamingSettings;
|
||||
static SettingsContainer Container = new SettingsContainer();
|
||||
|
||||
/// <summary>
|
||||
/// Loads saved settings from storage
|
||||
/// </summary>
|
||||
public static void LoadData()
|
||||
{
|
||||
try
|
||||
{
|
||||
Container = JsonConvert.DeserializeObject<SettingsContainer>(storage.Values["settings"] as string);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Container = new SettingsContainer();
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
|
||||
static void SaveData() =>
|
||||
storage.Values["settings"] = JsonConvert.SerializeObject(Container);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
using Google.Apis.YouTube.v3.Data;
|
||||
using YoutubeExplode.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Google.Apis.Oauth2.v2.Data;
|
||||
using Google.Apis.Auth.OAuth2;
|
||||
using Google.Apis.YouTube.v3;
|
||||
using Google.Apis.Services;
|
||||
using System.Threading;
|
||||
using YoutubeExplode;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace FoxTube.Classes
|
||||
{
|
||||
public class User
|
||||
{
|
||||
public List<Subscription> Subscriptions { get; }
|
||||
|
||||
public List<YoutubeExplode.Models.Video> WatchLater { get; }
|
||||
public List<YoutubeExplode.Models.Video> WebHistory { get; }
|
||||
public List<object> AppHistory { get; }
|
||||
|
||||
public Userinfoplus UserInfo { get; }
|
||||
public UserCredential Credential { get; }
|
||||
|
||||
public YouTubeService Service { get; }
|
||||
|
||||
public YoutubeClient YoutubeClient { get; }
|
||||
|
||||
public string AccountId { get; }
|
||||
public Google.Apis.YouTube.v3.Data.Channel Channel { get; }
|
||||
|
||||
public async void Deauthenticate()
|
||||
{
|
||||
await Credential.RevokeTokenAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
public User(UserCredential credential)
|
||||
{
|
||||
Credential = credential;
|
||||
Service = new YouTubeService(new BaseClientService.Initializer
|
||||
{
|
||||
HttpClientInitializer = Credential,
|
||||
ApplicationName = "FoxTube"
|
||||
});
|
||||
|
||||
HttpClient httpClient = new HttpClient();
|
||||
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", credential.Token.AccessToken);
|
||||
YoutubeClient = new YoutubeClient(httpClient);
|
||||
}
|
||||
|
||||
public async void RefreshToken() =>
|
||||
await Credential.RefreshTokenAsync(CancellationToken.None);
|
||||
|
||||
/// <summary>
|
||||
/// Subscribes or unsibscribes authorized user from the channel
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of channel which has to be added/removed</param>
|
||||
/// <returns>Returns 'true' if channel is in subscriptions now; 'false' if it's not</returns>
|
||||
public async Task<bool> ChangeSubscriptionState(string id)
|
||||
{
|
||||
if (Subscriptions.Find(i => i.Snippet.ResourceId.ChannelId == id) is Subscription subscription)
|
||||
{
|
||||
try { await Service.Subscriptions.Delete(subscription.Id).ExecuteAsync(); }
|
||||
catch { return true; }
|
||||
|
||||
//SubscriptionsChanged?.Invoke("remove", subscription);
|
||||
Subscriptions.Remove(subscription);
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
var request = Service.Subscriptions.Insert(new Subscription
|
||||
{
|
||||
Snippet = new SubscriptionSnippet
|
||||
{
|
||||
ResourceId = new ResourceId
|
||||
{
|
||||
ChannelId = id,
|
||||
Kind = "youtube#channel"
|
||||
}
|
||||
}
|
||||
}, "snippet");
|
||||
|
||||
if (!(await request.ExecuteAsync() is Subscription sub))
|
||||
return false;
|
||||
|
||||
Subscriptions.Add(sub);
|
||||
//SubscriptionsChanged?.Invoke("add", sub);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
using FoxTube.Classes;
|
||||
using Google.Apis.Auth.OAuth2;
|
||||
using Google.Apis.Oauth2.v2.Data;
|
||||
using Google.Apis.Services;
|
||||
using Google.Apis.YouTube.v3;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using YoutubeExplode;
|
||||
|
||||
namespace FoxTube
|
||||
{
|
||||
public static class UserManagement
|
||||
{
|
||||
public static event AuthorizationChangedEventHandler AuthorizationStateChanged;
|
||||
public static event SubscriptionChangedEventHandler SubscriptionChanged;
|
||||
|
||||
static ClientSecrets[] Secrets => new ClientSecrets[5]
|
||||
{
|
||||
new ClientSecrets
|
||||
{
|
||||
ClientId = "349735264870-2ekqlm0a4mkg3mmrfcv90s3qp3o15dq0.apps.googleusercontent.com",
|
||||
ClientSecret = "BkVZOAaCU2Zclf0Zlicg6y2_"
|
||||
},
|
||||
new ClientSecrets
|
||||
{
|
||||
ClientId = "1096685398208-ha281qmg52ga8g8nn4n6943oct1tq6nj.apps.googleusercontent.com",
|
||||
ClientSecret = "Cew9WbJcsoisYnR-Wuyhukov"
|
||||
},
|
||||
new ClientSecrets
|
||||
{
|
||||
ClientId = "1096685398208-59ktbv2jsvalrmli1pevur9aujnjhjeb.apps.googleusercontent.com",
|
||||
ClientSecret = "eHvXHlIJ9r64yReOmMnuben7"
|
||||
},
|
||||
new ClientSecrets
|
||||
{
|
||||
ClientId = "1096685398208-ebckt9ncp69qutsmdbbufov60nq4rvpa.apps.googleusercontent.com",
|
||||
ClientSecret = "XCaBFmjoT2ZAKsGf-y80lBvc"
|
||||
},
|
||||
new ClientSecrets
|
||||
{
|
||||
ClientId = "1096685398208-ligbo8gqkp4qar1uo0e5o5di434qklma.apps.googleusercontent.com",
|
||||
ClientSecret = "oXauUkFY9I7Q1CmNkKGmszRQ"
|
||||
},
|
||||
};
|
||||
|
||||
static YouTubeService NoAuthService { get; } = new YouTubeService(new BaseClientService.Initializer
|
||||
{
|
||||
ApiKey = "AIzaSyBgHrCnrlzlVmk0cJKL8RqP9Y8x6XSuk_0",
|
||||
ApplicationName = "FoxTube"
|
||||
});
|
||||
static YoutubeClient NoAuthClient { get; } = new YoutubeClient();
|
||||
|
||||
public static YouTubeService Service => Current == null ? NoAuthService : Current.Service;
|
||||
public static YoutubeClient YoutubeClient => Current == null ? NoAuthClient : Current.YoutubeClient;
|
||||
|
||||
public static bool IsAuthorized => Current != null;
|
||||
|
||||
public static User Current { get; set; }
|
||||
|
||||
static (Userinfoplus info, UserCredential credential)[] UserInfos = new (Userinfoplus, UserCredential)[5];
|
||||
|
||||
public static bool CheckPerformed { get; }
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static async Task AddItemToWL(string id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static async void CreateNew()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static async void Logout()
|
||||
{
|
||||
Current?.Deauthenticate();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace FoxTube
|
||||
{
|
||||
public class ViewModel : Page
|
||||
{
|
||||
public List<Microsoft.UI.Xaml.Controls.NavigationViewItem> PivotItems { get; } = new List<Microsoft.UI.Xaml.Controls.NavigationViewItem>();
|
||||
|
||||
public object Parameter { get; private set; }
|
||||
|
||||
public void PivotChanged(int index) { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<StackPanel
|
||||
x:Class="FoxTube.Controls.AccountManager"
|
||||
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"
|
||||
xmlns:ui="using:Microsoft.UI.Xaml.Controls"
|
||||
Orientation="Horizontal">
|
||||
|
||||
<ui:NavigationViewItem Width="42" Visibility="Visible" Name="manager" Padding="0" Tapped="Manager_Tapped">
|
||||
<ui:NavigationViewItem.ContextFlyout>
|
||||
<Flyout>
|
||||
<Grid Width="300" Margin="-10">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="60"/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Image Stretch="UniformToFill" MaxHeight="60" Source="https://yt3.ggpht.com/TckH7MhPH7UcxPnHeEj6R78xe1uOmrlHdUD1Usy7sr36xLDzl86NxAyfmDOIUrxl6kpiBgtKgA=w2276-fcrop64=1,00005a57ffffa5a8-nd-c0xffffffff-rj-k-no"/>
|
||||
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.Background>
|
||||
<SolidColorBrush Color="Black" Opacity=".5"/>
|
||||
</Grid.Background>
|
||||
<PersonPicture HorizontalAlignment="Left" Margin="5" Height="50"/>
|
||||
<StackPanel VerticalAlignment="Center" Grid.Column="1">
|
||||
<TextBlock Text="Michael Gordeev" FontWeight="Bold"/>
|
||||
<TextBlock Text="michael.xfox@outlook.com" Style="{StaticResource CaptionTextBlockStyle}"/>
|
||||
</StackPanel>
|
||||
<ui:NavigationViewItem Grid.Column="2" Width="42" Icon="BlockContact" Foreground="Red"/>
|
||||
</Grid>
|
||||
|
||||
<ui:NavigationViewList Grid.Row="1">
|
||||
<ui:NavigationViewItem Content="My channel" Icon="Contact"/>
|
||||
<ui:NavigationViewItem Content="Upload a video" Icon="Upload" Tapped="NavigationViewItem_Tapped"/>
|
||||
<ui:NavigationViewItemSeparator/>
|
||||
<ui:NavigationViewItem>
|
||||
<StackPanel Orientation="Horizontal" Padding="5" Margin="-5,0,0,0">
|
||||
<PersonPicture Height="20" Margin="-5,0,15,0">
|
||||
<PersonPicture.ProfilePicture>
|
||||
<BitmapImage UriSource="https://yt3.ggpht.com/a/AGF-l7_hHK5yjEPhlM72Tmk26zoOVkNx88pWoZnFVQ=s240-mo-c-c0xffffffff-rj-k-no" DecodePixelHeight="20" DecodePixelWidth="20"/>
|
||||
</PersonPicture.ProfilePicture>
|
||||
</PersonPicture>
|
||||
<StackPanel>
|
||||
<TextBlock FontSize="14" Text="BadComedian"/>
|
||||
<TextBlock Text="eugene.comedian@fondkino-sdoh.net" FontSize="11" Margin="0,-4,0,0"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ui:NavigationViewItem>
|
||||
<ui:NavigationViewItem Content="Add account" Icon="Add"/>
|
||||
<ui:NavigationViewItemSeparator/>
|
||||
<ui:NavigationViewItem Name="removeAds" Content="Remove ads (5$)" Icon="Shop" Tapped="RemoveAds_Tapped"/>
|
||||
<ui:NavigationViewItem Content="Settings" Icon="Setting" Tapped="Settings_Click"/>
|
||||
</ui:NavigationViewList>
|
||||
</Grid>
|
||||
</Flyout>
|
||||
</ui:NavigationViewItem.ContextFlyout>
|
||||
|
||||
<PersonPicture Height="25" Margin="-8,0,0,0"/>
|
||||
</ui:NavigationViewItem>
|
||||
|
||||
<ui:NavigationViewItem Width="42" Name="account" Tapped="Manager_Tapped" Icon="AddFriend">
|
||||
<ui:NavigationViewItem.ContextFlyout>
|
||||
<ui:MenuBarItemFlyout>
|
||||
<MenuFlyoutItem Icon="Add" Text="Add new account" Click="SignIn_Click"/>
|
||||
<MenuFlyoutItem Icon="Setting" Text="Settings" Click="Settings_Click"/>
|
||||
</ui:MenuBarItemFlyout>
|
||||
</ui:NavigationViewItem.ContextFlyout>
|
||||
</ui:NavigationViewItem>
|
||||
</StackPanel>
|
||||
@@ -0,0 +1,92 @@
|
||||
using Microsoft.AppCenter.Analytics;
|
||||
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.Media.Imaging;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
|
||||
|
||||
namespace FoxTube.Controls
|
||||
{
|
||||
public sealed partial class AccountManager : StackPanel
|
||||
{
|
||||
public AccountManager()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Service.Purchased += (purchased, price) =>
|
||||
{
|
||||
/*removeAds.Visibility = purchased ? Visibility.Collapsed : Visibility.Visible;
|
||||
removeAds.Content = $"{resources.GetString("/Main/adsFree/Content")} ({price})";*/
|
||||
};
|
||||
|
||||
if (Service.AdsCheckPerformed)
|
||||
Service.CheckAddons();
|
||||
}
|
||||
|
||||
void SignIn_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
UserManagement.CreateNew();
|
||||
Analytics.TrackEvent("Initialized authorization sequence");
|
||||
}
|
||||
|
||||
void Logout_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
manager.ContextFlyout.Hide();
|
||||
UserManagement.Logout();
|
||||
}
|
||||
|
||||
public async void Logged() //=> await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
|
||||
{
|
||||
account.Visibility = Visibility.Collapsed;
|
||||
|
||||
/*ToolTipService.SetToolTip(avatar, $"{UserManagement.Current.UserInfo.Name} ({UserManagement.Current.UserInfo.Email})");
|
||||
name.Text = UserManagement.Current.UserInfo.Name;
|
||||
email.Text = UserManagement.Current.UserInfo.Email;
|
||||
avatar.ProfilePicture = new BitmapImage(UserManagement.Current.UserInfo.Picture.ToUri()) { DecodePixelHeight = 65, DecodePixelWidth = 65 };
|
||||
(icon.Fill as ImageBrush).ImageSource = new BitmapImage(UserManagement.Current.UserInfo.Picture.ToUri()) { DecodePixelHeight = 25, DecodePixelWidth = 25 };*/
|
||||
|
||||
manager.Visibility = Visibility.Visible;
|
||||
}//);
|
||||
|
||||
public void Quit()
|
||||
{
|
||||
manager.Visibility = Visibility.Collapsed;
|
||||
account.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void NavigationViewItem_Tapped(object sender, TappedRoutedEventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Manager_Tapped(object sender, TappedRoutedEventArgs e) =>
|
||||
(sender as Microsoft.UI.Xaml.Controls.NavigationViewItem).ContextFlyout.ShowAt(sender as FrameworkElement);
|
||||
|
||||
private void Settings_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void Settings_Click(object sender, TappedRoutedEventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void RemoveAds_Tapped(object sender, TappedRoutedEventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
<UserControl
|
||||
x:Class="FoxTube.Controls.ContentFrame"
|
||||
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">
|
||||
|
||||
<Grid>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup>
|
||||
<VisualState x:Name="blocked">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="block" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<DoubleAnimation Storyboard.TargetName="block" Storyboard.TargetProperty="Opacity"
|
||||
From="0" To="1" Duration="0:0:1"/>
|
||||
|
||||
<DoubleAnimation Storyboard.TargetName="ring" Storyboard.TargetProperty="Width"
|
||||
EnableDependentAnimation="True"
|
||||
From="100" To="200" Duration="0:0:0.5"/>
|
||||
<DoubleAnimation Storyboard.TargetName="ring" Storyboard.TargetProperty="Height"
|
||||
EnableDependentAnimation="True"
|
||||
From="100" To="200" Duration="0:0:0.5"/>
|
||||
<DoubleAnimation Storyboard.TargetName="ring" Storyboard.TargetProperty="Opacity"
|
||||
From="1" To="0" Duration="0:0:0.5">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<ExponentialEase EasingMode="EaseIn"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ring" Storyboard.TargetProperty="IsActive">
|
||||
<DiscreteObjectKeyFrame KeyTime="0:0:0.5" Value="False"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
|
||||
<DoubleAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="Opacity"
|
||||
Duration="0" To="0"/>
|
||||
<DoubleAnimation Storyboard.TargetName="loadingScreen" Storyboard.TargetProperty="Opacity"
|
||||
To="0" Duration="0:0:0.1"/>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="wifiError">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="Opacity"
|
||||
Duration="0:0:0.1" To="0"/>
|
||||
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="block" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="generalBtns" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="networkBtns" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="icon" Storyboard.TargetProperty="Glyph">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value=""/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
|
||||
<DoubleAnimation Storyboard.TargetName="ring" Storyboard.TargetProperty="Width"
|
||||
EnableDependentAnimation="True"
|
||||
From="100" To="200" Duration="0:0:0.5"/>
|
||||
<DoubleAnimation Storyboard.TargetName="ring" Storyboard.TargetProperty="Height"
|
||||
EnableDependentAnimation="True"
|
||||
From="100" To="200" Duration="0:0:0.5"/>
|
||||
<DoubleAnimation Storyboard.TargetName="ring" Storyboard.TargetProperty="Opacity"
|
||||
From="1" To="0" Duration="0:0:0.5">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<ExponentialEase EasingMode="EaseIn"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ring" Storyboard.TargetProperty="IsActive">
|
||||
<DiscreteObjectKeyFrame KeyTime="0:0:0.5" Value="False"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
|
||||
<DoubleAnimation Storyboard.TargetName="loadingScreen" Storyboard.TargetProperty="Opacity"
|
||||
From="0" To="1" Duration="0:0:0.5" BeginTime="0:0:0.5">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<ExponentialEase EasingMode="EaseIn"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="commonError">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="Opacity"
|
||||
Duration="0:0:0.1" To="0"/>
|
||||
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="block" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="generalBtns" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="networkBtns" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="icon" Storyboard.TargetProperty="Glyph">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value=""/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
|
||||
<DoubleAnimation Storyboard.TargetName="ring" Storyboard.TargetProperty="Width"
|
||||
EnableDependentAnimation="True"
|
||||
From="100" To="200" Duration="0:0:0.5"/>
|
||||
<DoubleAnimation Storyboard.TargetName="ring" Storyboard.TargetProperty="Height"
|
||||
EnableDependentAnimation="True"
|
||||
From="100" To="200" Duration="0:0:0.5"/>
|
||||
<DoubleAnimation Storyboard.TargetName="ring" Storyboard.TargetProperty="Opacity"
|
||||
From="1" To="0" Duration="0:0:0.5">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<ExponentialEase EasingMode="EaseIn"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ring" Storyboard.TargetProperty="IsActive">
|
||||
<DiscreteObjectKeyFrame KeyTime="0:0:0.5" Value="False"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
|
||||
<DoubleAnimation Storyboard.TargetName="loadingScreen" Storyboard.TargetProperty="Opacity"
|
||||
From="0" To="1" Duration="0:0:0.5" BeginTime="0:0:0.5">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<ExponentialEase EasingMode="EaseIn"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="loading">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="block" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<DoubleAnimation Storyboard.TargetName="loadingScreen" Storyboard.TargetProperty="Opacity"
|
||||
To="0" Duration="0:0:0.1"/>
|
||||
<DoubleAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="Opacity"
|
||||
Duration="0:0:0.2" To="0"/>
|
||||
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ring" Storyboard.TargetProperty="IsActive">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="True"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<DoubleAnimation Storyboard.TargetName="ring" Storyboard.TargetProperty="Width"
|
||||
EnableDependentAnimation="True"
|
||||
From="0" To="100" Duration="0:0:0.5"/>
|
||||
<DoubleAnimation Storyboard.TargetName="ring" Storyboard.TargetProperty="Height"
|
||||
EnableDependentAnimation="True"
|
||||
From="0" To="100" Duration="0:0:0.5"/>
|
||||
<DoubleAnimation Storyboard.TargetName="ring" Storyboard.TargetProperty="Opacity"
|
||||
From="0" To="1" Duration="0:0:0.5">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<ExponentialEase EasingMode="EaseIn"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="loaded">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="block" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
|
||||
<DoubleAnimation Storyboard.TargetName="ring" Storyboard.TargetProperty="Width"
|
||||
EnableDependentAnimation="True"
|
||||
From="100" To="200" Duration="0:0:0.5"/>
|
||||
<DoubleAnimation Storyboard.TargetName="ring" Storyboard.TargetProperty="Height"
|
||||
EnableDependentAnimation="True"
|
||||
From="100" To="200" Duration="0:0:0.5"/>
|
||||
<DoubleAnimation Storyboard.TargetName="ring" Storyboard.TargetProperty="Opacity"
|
||||
From="1" To="0" Duration="0:0:0.5">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<ExponentialEase EasingMode="EaseIn"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ring" Storyboard.TargetProperty="IsActive">
|
||||
<DiscreteObjectKeyFrame KeyTime="0:0:0.5" Value="False"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
|
||||
<DoubleAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="Opacity"
|
||||
From="0" To="1" Duration="0:0:0.2" BeginTime="0:0:0.5"/>
|
||||
<DoubleAnimation Storyboard.TargetName="loadingScreen" Storyboard.TargetProperty="Opacity"
|
||||
To="0" Duration="0:0:0.1"/>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
|
||||
<Frame Name="content" Navigating="Content_Navigating" Opacity="0"/>
|
||||
|
||||
<ProgressRing Width="100" Height="100" Name="ring" IsActive="True"/>
|
||||
<FontIcon Glyph="" FontSize="100" Name="block" Visibility="Collapsed"/>
|
||||
|
||||
<StackPanel VerticalAlignment="Center" Name="loadingScreen" Opacity="0">
|
||||
<FontIcon Name="icon" Glyph="" FontSize="100" HorizontalAlignment="Center"/>
|
||||
|
||||
<TextBlock Name="title" Text="We are unable to display the page" FontSize="48" HorizontalAlignment="Center" TextWrapping="WrapWholeWords"/>
|
||||
<TextBlock Name="description" Text="It could be caused by YouTube internal server error or by application's bug. Please, try again later" HorizontalAlignment="Center" TextWrapping="WrapWholeWords"/>
|
||||
|
||||
<StackPanel Name="networkBtns">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Button Content="Open network settings" Margin="0,0,5,0" Click="Network_Click"/>
|
||||
<Button Content="Open troubleshooter" Background="Red" Foreground="White" Click="Troubleshooter_Click"/>
|
||||
</StackPanel>
|
||||
<TextBlock Text="OR" FontSize="20" HorizontalAlignment="Center" Margin="5"/>
|
||||
<Button Content="Refresh page" HorizontalAlignment="Center" Background="Red" Foreground="White" Click="Refresh_Click"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Name="generalBtns" Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Button Content="Refresh page" Margin="0,0,5,0" Click="Refresh_Click"/>
|
||||
<Button Name="feedback" Content="Leave feedback" Background="Red" Foreground="White" Click="Feedback_Click"/>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Name="error" Foreground="Gray" Text="Exception:" HorizontalAlignment="Center" IsTextSelectionEnabled="True"/>
|
||||
<TextBlock Name="message" Foreground="Gray" Text="Message:" HorizontalAlignment="Center" IsTextSelectionEnabled="True" TextWrapping="WrapWholeWords"/>
|
||||
<TextBlock Name="stackTrace" Foreground="Gray" Text="Stack trace:" HorizontalAlignment="Center" IsTextSelectionEnabled="True" TextWrapping="WrapWholeWords"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,130 @@
|
||||
using Microsoft.Services.Store.Engagement;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Windows.ApplicationModel.Resources;
|
||||
using Windows.System;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
|
||||
namespace FoxTube.Controls
|
||||
{
|
||||
public sealed partial class ContentFrame : UserControl
|
||||
{
|
||||
readonly ResourceLoader resources = ResourceLoader.GetForCurrentView("Loading");
|
||||
|
||||
public LoadingScreenState State { get; private set; } = LoadingScreenState.Loaded;
|
||||
public Type SourcePageType => content.CurrentSourcePageType;
|
||||
public bool CanGoBack => content.CanGoBack;
|
||||
public object FrameContent => content.Content;
|
||||
|
||||
public event NavigationOccured Navigated;
|
||||
|
||||
public ContentFrame()
|
||||
{
|
||||
InitializeComponent();
|
||||
if (!StoreServicesFeedbackLauncher.IsSupported())
|
||||
feedback.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public void Navigate(Type pageType, object parameter) =>
|
||||
content.Navigate(pageType, parameter);
|
||||
|
||||
/// <summary>
|
||||
/// Navigates on the same page and deletes last back stack entry
|
||||
/// </summary>
|
||||
public void Refresh()
|
||||
{
|
||||
content.Navigate(content.CurrentSourcePageType, (content.Content as ViewModel).Parameter);
|
||||
content.BackStack.RemoveAt(content.BackStack.Count - 1);
|
||||
}
|
||||
|
||||
public void GoBack() =>
|
||||
content.GoBack();
|
||||
|
||||
/// <summary>
|
||||
/// Clears frame back stack
|
||||
/// </summary>
|
||||
public void ClearHistory() =>
|
||||
content.BackStack.Clear();
|
||||
|
||||
/// <summary>
|
||||
/// Hides loading indicator and show blocked icon
|
||||
/// </summary>
|
||||
public void Block()
|
||||
{
|
||||
blocked.Storyboard.Begin();
|
||||
State = LoadingScreenState.Blocked;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows error screen with common error message
|
||||
/// </summary>
|
||||
/// <param name="error">Error name (Exception name also will do)</param>
|
||||
/// <param name="message">Error description or exception message</param>
|
||||
/// <param name="stackTrace">Exception's stack trace</param>
|
||||
public void ShowError(string error = "Unknown", string message = "N/A", string stackTrace = null)
|
||||
{
|
||||
title.Text = resources.GetString("/Loading/generalTitle");
|
||||
description.Text = resources.GetString("/Loading/general");
|
||||
|
||||
this.error.Text = $"{resources.GetString("/Loading/error")}: {error}";
|
||||
this.message.Text = $"{resources.GetString("/Loading/message")}: {message}";
|
||||
this.stackTrace.Text = $"{resources.GetString("/Loading/stackTrace")}: {stackTrace}";
|
||||
|
||||
this.stackTrace.Visibility = string.IsNullOrWhiteSpace(stackTrace) ? Visibility.Collapsed : Visibility.Visible;
|
||||
|
||||
commonError.Storyboard.Begin();
|
||||
State = LoadingScreenState.Error;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows error screen with network error message
|
||||
/// </summary>
|
||||
/// <param name="error">Error name (Exception name also will do)</param>
|
||||
/// <param name="message">Error description or exception message</param>
|
||||
/// <param name="stackTrace">Exception's stack trace</param>
|
||||
public void ShowConnectionError(string error = "Unknown", string message = "N/A", string stackTrace = null)
|
||||
{
|
||||
title.Text = resources.GetString("/Loading/generalTitle");
|
||||
description.Text = resources.GetString("/Loading/general");
|
||||
|
||||
this.error.Text = $"{resources.GetString("/Loading/error")}: {error}";
|
||||
this.message.Text = $"{resources.GetString("/Loading/message")}: {message}";
|
||||
this.stackTrace.Text = $"{resources.GetString("/Loading/stackTrace")}: {stackTrace}";
|
||||
|
||||
this.stackTrace.Visibility = string.IsNullOrWhiteSpace(stackTrace) ? Visibility.Collapsed : Visibility.Visible;
|
||||
|
||||
wifiError.Storyboard.Begin();
|
||||
State = LoadingScreenState.Error;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hides loading UI
|
||||
/// </summary>
|
||||
public void Complete(IEnumerable pivotCollection = null, int? selectedPivot = null)
|
||||
{
|
||||
Navigated?.Invoke(pivotCollection, selectedPivot);
|
||||
loaded.Storyboard.Begin();
|
||||
State = LoadingScreenState.Loaded;
|
||||
}
|
||||
|
||||
void Content_Navigating(object sender, NavigatingCancelEventArgs e)
|
||||
{
|
||||
loading.Storyboard.Begin();
|
||||
State = LoadingScreenState.Loading;
|
||||
}
|
||||
|
||||
async void Troubleshooter_Click(object sender, RoutedEventArgs e) =>
|
||||
await Launcher.LaunchUriAsync("ms-settings:troubleshoot".ToUri());
|
||||
|
||||
async void Network_Click(object sender, RoutedEventArgs e) =>
|
||||
await Launcher.LaunchUriAsync("ms-settings:network".ToUri());
|
||||
|
||||
async void Feedback_Click(object sender, RoutedEventArgs e) =>
|
||||
await StoreServicesFeedbackLauncher.GetDefault().LaunchAsync();
|
||||
|
||||
void Refresh_Click(object sender, RoutedEventArgs e) =>
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<UserControl
|
||||
x:Class="FoxTube.Controls.MainFrame"
|
||||
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">
|
||||
|
||||
<Grid>
|
||||
<controls:ContentFrame x:Name="content" Navigated="Content_Navigated"/>
|
||||
<controls:ContentFrame x:Name="video" Visibility="Collapsed"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,157 @@
|
||||
using System;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace FoxTube.Controls
|
||||
{
|
||||
public sealed partial class MainFrame : UserControl
|
||||
{
|
||||
public static MainFrame Current { get; private set; }
|
||||
|
||||
public event NavigatingOccured Navigating;
|
||||
public event NavigationOccured Navigated;
|
||||
|
||||
public bool CanGoBack => !VideoMinimized || content.CanGoBack;
|
||||
public bool IsVideoOpened { get; } = false;
|
||||
public bool VideoMinimized => video.Width != double.NaN;
|
||||
public Type SourcePageType => content.SourcePageType;
|
||||
|
||||
public MainFrame()
|
||||
{
|
||||
InitializeComponent();
|
||||
Current = this;
|
||||
}
|
||||
|
||||
public void NavigateTo(Type pageType, object parameter = null)
|
||||
{
|
||||
if (content.SourcePageType == pageType && parameter == (content.FrameContent as INavigationPage).Parameter)
|
||||
return;
|
||||
|
||||
content.Navigate(pageType, parameter);
|
||||
|
||||
if (video.FrameContent != null && !VideoMinimized)
|
||||
MinimizeVideo();
|
||||
|
||||
Navigating?.Invoke(pageType, parameter);
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
content.Refresh();
|
||||
Navigating?.Invoke(SourcePageType, (content.Content as ViewModel).Parameter);
|
||||
}
|
||||
|
||||
#region Video control methods
|
||||
public void OpenVideo(string id, string playlistId = null, bool incognito = false)
|
||||
{
|
||||
/*if (VideoMinimized)
|
||||
MaximizeVideo();
|
||||
|
||||
video.Navigate(typeof(VideoPage), (id, playlistId, incognito));
|
||||
|
||||
MainPage.Current.UpdateView();*/
|
||||
}
|
||||
|
||||
public void MinimizeVideo(bool player = false)
|
||||
{
|
||||
/*if (video.FrameContent == null)
|
||||
return;
|
||||
|
||||
video.Margin = new Thickness(0, 0, 25, 50);
|
||||
video.HorizontalAlignment = HorizontalAlignment.Right;
|
||||
video.VerticalAlignment = VerticalAlignment.Bottom;
|
||||
video.Width = 432;
|
||||
|
||||
if (!player)
|
||||
(video.FrameContent as VideoPage).Minimize();
|
||||
|
||||
MainPage.Current.UpdateView();*/
|
||||
}
|
||||
|
||||
public void MaximizeVideo(bool player = false)
|
||||
{
|
||||
/*if (video.FrameContent == null)
|
||||
return;
|
||||
|
||||
video.Margin = new Thickness(0);
|
||||
video.VerticalAlignment = VerticalAlignment.Stretch;
|
||||
video.HorizontalAlignment = HorizontalAlignment.Stretch;
|
||||
video.Width = double.NaN;
|
||||
|
||||
if (!player)
|
||||
(video.FrameContent as VideoPage).Maximize();
|
||||
|
||||
MainPage.Current.UpdateView();*/
|
||||
}
|
||||
|
||||
public void CloseVideo()
|
||||
{
|
||||
/*if (ApplicationView.GetForCurrentView().IsFullScreenMode)
|
||||
ApplicationView.GetForCurrentView().ExitFullScreenMode();
|
||||
|
||||
video.FrameContent = null;
|
||||
video.ClearHistory();
|
||||
|
||||
if (VideoMinimized)
|
||||
MaximizeVideo();
|
||||
|
||||
GC.Collect();
|
||||
|
||||
MainPage.Current.UpdateView();*/
|
||||
}
|
||||
|
||||
public void RefreshVideo()
|
||||
{
|
||||
/*if (video.FrameContent == null)
|
||||
return;
|
||||
|
||||
if (VideoMinimized)
|
||||
MaximizeVideo();
|
||||
|
||||
video.Refresh();
|
||||
|
||||
Methods.MainPage.UpdateView();*/
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void AuthorizationChanged(bool isAuthorized)
|
||||
{
|
||||
//TODO: Uncomment this
|
||||
/*switch (isAuthorized)
|
||||
{
|
||||
case true:
|
||||
if (content.FrameContent == null)
|
||||
NavigateTo(typeof(Home));
|
||||
else if (!content.SourcePageType.Name.Belongs("Downloads", "Settings"))
|
||||
content.Refresh();
|
||||
break;
|
||||
|
||||
case false:
|
||||
NavigateTo(typeof(Home));
|
||||
|
||||
content.ClearHistory();
|
||||
video.ClearHistory();
|
||||
break;
|
||||
}
|
||||
|
||||
RefreshVideo();*/
|
||||
}
|
||||
|
||||
public void BackRequested()
|
||||
{
|
||||
if (video.FrameContent != null && !VideoMinimized)
|
||||
{
|
||||
if (video.CanGoBack)
|
||||
video.GoBack();
|
||||
else if (video.State != LoadingScreenState.Loaded)
|
||||
CloseVideo();
|
||||
else
|
||||
MinimizeVideo();
|
||||
}
|
||||
else if (content.CanGoBack)
|
||||
content.GoBack();
|
||||
}
|
||||
|
||||
void Content_Navigated(System.Collections.IEnumerable pivotCollection, int? selectedPivot) =>
|
||||
Navigated?.Invoke(pivotCollection, selectedPivot);
|
||||
}
|
||||
}
|
||||
+62
-25
@@ -105,6 +105,29 @@
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Classes\Downloads.cs" />
|
||||
<Compile Include="Classes\Extensions.cs" />
|
||||
<Compile Include="Classes\Methods.cs" />
|
||||
<Compile Include="Classes\Navigation.cs" />
|
||||
<Compile Include="Classes\Processes.cs" />
|
||||
<Compile Include="Classes\SearchParameters.cs" />
|
||||
<Compile Include="Classes\Service.cs" />
|
||||
<Compile Include="Classes\Settings.cs" />
|
||||
<Compile Include="Classes\User.cs" />
|
||||
<Compile Include="Classes\UserManagement.cs" />
|
||||
<Compile Include="Classes\ViewModel.cs" />
|
||||
<Compile Include="Controls\AccountManager.xaml.cs">
|
||||
<DependentUpon>AccountManager.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\ContentFrame.xaml.cs">
|
||||
<DependentUpon>ContentFrame.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\MainFrame.xaml.cs">
|
||||
<DependentUpon>MainFrame.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\Home.xaml.cs">
|
||||
<DependentUpon>Home.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Pages\MainPage.xaml.cs">
|
||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -180,23 +203,40 @@
|
||||
<Content Include="Assets\Square44x44Logo.scale-200.png" />
|
||||
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
|
||||
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
|
||||
<PRIResource Include="Strings\en-US\Loading.resw" />
|
||||
<PRIResource Include="Strings\en-US\Generic.resw" />
|
||||
<PRIResource Include="Strings\en-US\Toasts.resw" />
|
||||
<PRIResource Include="Strings\en-US\Dialogs.resw" />
|
||||
<PRIResource Include="Strings\en-US\Inbox.resw" />
|
||||
<PRIResource Include="Strings\ru-RU\Report.resw" />
|
||||
<PRIResource Include="Strings\en-US\Report.resw" />
|
||||
<PRIResource Include="Strings\en-US.old\Report.resw" />
|
||||
<PRIResource Include="Strings\ru-RU\Translate.resw" />
|
||||
<PRIResource Include="Strings\en-US\Translate.resw" />
|
||||
<PRIResource Include="Strings\en-US.old\Translate.resw" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Page Include="Pages\MainPage.xaml">
|
||||
<Page Include="Controls\AccountManager.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\Generic.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<Page Include="Controls\ContentFrame.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Controls\MainFrame.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\Home.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Pages\MainPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\Resources.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
@@ -255,39 +295,39 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PRIResource Include="Strings\ru-RU\VideoPage.resw" />
|
||||
<PRIResource Include="Strings\en-US\VideoPage.resw" />
|
||||
<PRIResource Include="Strings\en-US.old\VideoPage.resw" />
|
||||
<PRIResource Include="Strings\ru-RU\Channel.resw" />
|
||||
<PRIResource Include="Strings\en-US\Channel.resw" />
|
||||
<PRIResource Include="Strings\en-US.old\Channel.resw" />
|
||||
<PRIResource Include="Strings\ru-RU\Chat.resw" />
|
||||
<PRIResource Include="Strings\en-US\Chat.resw" />
|
||||
<PRIResource Include="Strings\en-US.old\Chat.resw" />
|
||||
<PRIResource Include="Strings\ru-RU\Cards.resw" />
|
||||
<PRIResource Include="Strings\en-US\Cards.resw" />
|
||||
<PRIResource Include="Strings\en-US.old\Cards.resw" />
|
||||
<PRIResource Include="Strings\ru-RU\Methods.resw" />
|
||||
<PRIResource Include="Strings\en-US\Methods.resw" />
|
||||
<PRIResource Include="Strings\en-US.old\Methods.resw" />
|
||||
<PRIResource Include="Strings\ru-RU\Search.resw" />
|
||||
<PRIResource Include="Strings\en-US\Search.resw" />
|
||||
<PRIResource Include="Strings\en-US.old\Search.resw" />
|
||||
<PRIResource Include="Strings\ru-RU\Playlist.resw" />
|
||||
<PRIResource Include="Strings\en-US\Playlist.resw" />
|
||||
<PRIResource Include="Strings\en-US.old\Playlist.resw" />
|
||||
<PRIResource Include="Strings\ru-RU\Downloads.resw" />
|
||||
<PRIResource Include="Strings\ru-RU\CommentsPage.resw" />
|
||||
<PRIResource Include="Strings\en-US\Downloads.resw" />
|
||||
<PRIResource Include="Strings\en-US.old\Downloads.resw" />
|
||||
<PRIResource Include="Strings\ru-RU\Home.resw" />
|
||||
<PRIResource Include="Strings\en-US\Home.resw" />
|
||||
<PRIResource Include="Strings\en-US\CommentsPage.resw" />
|
||||
<PRIResource Include="Strings\en-US.old\Home.resw" />
|
||||
<PRIResource Include="Strings\en-US.old\CommentsPage.resw" />
|
||||
<PRIResource Include="Strings\ru-RU\LoadingPage.resw" />
|
||||
<PRIResource Include="Strings\en-US\LoadingPage.resw" />
|
||||
<PRIResource Include="Strings\en-US.old\LoadingPage.resw" />
|
||||
<PRIResource Include="Strings\ru-RU\Inbox.resw" />
|
||||
<PRIResource Include="Strings\ru-RU\General.resw" />
|
||||
<PRIResource Include="Strings\ru-RU\About.resw" />
|
||||
<PRIResource Include="Strings\ru-RU\Settings.resw" />
|
||||
<PRIResource Include="Strings\en-US\Inbox.resw" />
|
||||
<PRIResource Include="Strings\en-US\About.resw" />
|
||||
<PRIResource Include="Strings\en-US\General.resw" />
|
||||
<PRIResource Include="Strings\en-US\Settings.resw" />
|
||||
<PRIResource Include="Strings\en-US.old\Inbox.resw" />
|
||||
<PRIResource Include="Strings\en-US.old\About.resw" />
|
||||
<PRIResource Include="Strings\en-US.old\General.resw" />
|
||||
<PRIResource Include="Strings\en-US.old\Settings.resw" />
|
||||
<PRIResource Include="Strings\ru-RU\Main.resw">
|
||||
<SubType>Designer</SubType>
|
||||
</PRIResource>
|
||||
<PRIResource Include="Strings\en-US\Main.resw" />
|
||||
<PRIResource Include="Strings\en-US.old\Main.resw" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\FoxTube.Background\FoxTube.Background.csproj">
|
||||
@@ -303,10 +343,7 @@
|
||||
<Name>Microsoft Engagement Framework</Name>
|
||||
</SDKReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Classes\" />
|
||||
<Folder Include="Controls\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
||||
<VisualStudioVersion>14.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<local:ViewModel
|
||||
x:Class="FoxTube.Pages.Home"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:FoxTube"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
xmlns:ui="using:Microsoft.UI.Xaml.Controls"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<local:ViewModel.PivotItems>
|
||||
<ui:NavigationViewItem Content="Recommended"/>
|
||||
<ui:NavigationViewItem Content="Trending"/>
|
||||
<ui:NavigationViewItem Content="Subscriptions"/>
|
||||
</local:ViewModel.PivotItems>
|
||||
|
||||
<Grid>
|
||||
|
||||
</Grid>
|
||||
</local:ViewModel>
|
||||
@@ -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.Pages
|
||||
{
|
||||
/// <summary>
|
||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
public sealed partial class Home : ViewModel
|
||||
{
|
||||
public Home()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
+263
-2
@@ -2,13 +2,274 @@
|
||||
x:Class="FoxTube.Pages.MainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:FoxTube.Pages"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
xmlns:ui="using:Microsoft.UI.Xaml.Controls"
|
||||
xmlns:data="using:Google.Apis.YouTube.v3.Data"
|
||||
xmlns:controls="using:FoxTube.Controls">
|
||||
|
||||
<Page.Background>
|
||||
<AcrylicBrush BackgroundSource="HostBackdrop" TintColor="{StaticResource SystemColorBackgroundColor}" TintOpacity=".5"/>
|
||||
</Page.Background>
|
||||
<Page.Resources>
|
||||
<AcrylicBrush x:Key="NavigationViewTopPaneBackground" BackgroundSource="HostBackdrop" TintColor="Red" TintOpacity=".7" FallbackColor="Red"/>
|
||||
</Page.Resources>
|
||||
|
||||
<Grid>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="SplashScreenStates">
|
||||
<VisualState x:Name="FadeOut">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetName="splashImage" Storyboard.TargetProperty="Opacity"
|
||||
From="1" To="0" BeginTime="0:0:0.5" Duration="0:0:0.5">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<QuadraticEase EasingMode="EaseInOut"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
|
||||
<DoubleAnimation Storyboard.TargetName="splashRing" Storyboard.TargetProperty="Opacity"
|
||||
From="1" To="0" Duration="0:0:0.5">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<ExponentialEase EasingMode="EaseIn"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
<DoubleAnimation Storyboard.TargetName="splashRing" Storyboard.TargetProperty="Width"
|
||||
From="50" To="180" Duration="0:0:0.5" EnableDependentAnimation="True">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<QuadraticEase EasingMode="EaseIn"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
<DoubleAnimation Storyboard.TargetName="splashRing" Storyboard.TargetProperty="Height"
|
||||
From="50" To="100" Duration="0:0:0.5" EnableDependentAnimation="True">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<QuadraticEase EasingMode="EaseIn"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
|
||||
<DoubleAnimation Storyboard.TargetName="splashScreen" Storyboard.TargetProperty="Opacity"
|
||||
From="1" To="0" BeginTime="0:0:1" Duration="0:0:0.5">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<QuadraticEase EasingMode="EaseInOut"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="splashScreen" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0:0:1.5" Value="Collapsed"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="split" Storyboard.TargetProperty="IsPaneOpen">
|
||||
<DiscreteObjectKeyFrame KeyTime="0:0:1.5" Value="True"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
|
||||
<VisualStateGroup x:Name="PaneStates">
|
||||
<VisualState x:Name="ExpandedMode">
|
||||
<VisualState.StateTriggers>
|
||||
<AdaptiveTrigger x:Name="ExpandedThresholdWidth" MinWindowWidth="1008"/>
|
||||
</VisualState.StateTriggers>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="split.DisplayMode" Value="CompactInline"/>
|
||||
<Setter Target="split.IsPaneOpen" Value="True"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="CompactMode">
|
||||
<VisualState.StateTriggers>
|
||||
<AdaptiveTrigger x:Name="CompactThresholdWidth" MinWindowWidth="641"/>
|
||||
</VisualState.StateTriggers>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="split.DisplayMode" Value="CompactOverlay"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
|
||||
<VisualStateGroup x:Name="SearchStates">
|
||||
<VisualState x:Name="SearchExpanded">
|
||||
<VisualState.StateTriggers>
|
||||
<AdaptiveTrigger MinWindowWidth="1000"/>
|
||||
</VisualState.StateTriggers>
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="search" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="searchBtn" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<DoubleAnimation EnableDependentAnimation="True"
|
||||
Storyboard.TargetName="search" Storyboard.TargetProperty="Width"
|
||||
From="0" To="300" Duration="0:0:1">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<QuadraticEase EasingMode="EaseInOut"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="SearchCollapsed">
|
||||
<VisualState.StateTriggers>
|
||||
<AdaptiveTrigger MinWindowWidth="0"/>
|
||||
</VisualState.StateTriggers>
|
||||
<Storyboard>
|
||||
<DoubleAnimation EnableDependentAnimation="True"
|
||||
Storyboard.TargetName="search" Storyboard.TargetProperty="Width"
|
||||
From="300" To="0" Duration="0:0:1">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<QuadraticEase EasingMode="EaseInOut"/>
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="search" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0:0:1" Value="Collapsed"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="searchBtn" Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0:0:1" Value="Visible"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
|
||||
<ui:NavigationView PaneDisplayMode="Top" SelectionChanged="Nav_SelectionChanged" Name="nav" IsSettingsVisible="False"
|
||||
BackRequested="Nav_BackRequested" IsBackEnabled="{x:Bind content.CanGoBack}">
|
||||
<ui:NavigationView.AutoSuggestBox>
|
||||
<AutoSuggestBox x:Name="search" LostFocus="Search_LostFocus" QueryIcon="Find" QuerySubmitted="Search_QuerySubmitted" TextChanged="Search_TextChanged" PlaceholderText="Search" Width="300"/>
|
||||
</ui:NavigationView.AutoSuggestBox>
|
||||
|
||||
<ui:NavigationView.PaneHeader>
|
||||
<ui:NavigationViewItem Icon="GlobalNavigationButton" Width="42" Name="menu" Tapped="Menu_Tapped"/>
|
||||
</ui:NavigationView.PaneHeader>
|
||||
|
||||
<ui:NavigationView.PaneFooter>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<ui:NavigationViewItem Icon="Find" Width="42" Name="searchBtn" Tapped="SearchBtn_Tapped"/>
|
||||
<ui:NavigationViewItem Width="42" Name="feedback" Tapped="Feedback_Click">
|
||||
<ui:NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</ui:NavigationViewItem.Icon>
|
||||
</ui:NavigationViewItem>
|
||||
<controls:AccountManager x:Name="accountManager"/>
|
||||
</StackPanel>
|
||||
</ui:NavigationView.PaneFooter>
|
||||
|
||||
<SplitView OpenPaneLength="300" Name="split" DisplayMode="Overlay" CompactPaneLength="42"
|
||||
PaneClosing="Split_PaneToggled" PaneOpened="Split_PaneToggled">
|
||||
<SplitView.PaneBackground>
|
||||
<AcrylicBrush BackgroundSource="Backdrop" TintColor="{StaticResource SystemColorBackgroundColor}" TintOpacity=".5"/>
|
||||
</SplitView.PaneBackground>
|
||||
|
||||
<SplitView.Pane>
|
||||
<ScrollViewer>
|
||||
<StackPanel>
|
||||
<ui:NavigationViewList>
|
||||
<ui:NavigationViewList.ItemContainerTransitions>
|
||||
<TransitionCollection>
|
||||
<EntranceThemeTransition IsStaggeringEnabled="True"/>
|
||||
</TransitionCollection>
|
||||
</ui:NavigationViewList.ItemContainerTransitions>
|
||||
|
||||
<ui:NavigationViewItem Icon="Home" Content="Home" Tapped="Home_Tapped"/>
|
||||
<ui:NavigationViewItem Icon="People" Content="Subscriptions" Name="subscriptions" Tapped="Subscriptions_Tapped" Visibility="Collapsed"/>
|
||||
|
||||
<ui:NavigationViewItemHeader Content="My library" Name="libraryHeader" Visibility="Collapsed"/>
|
||||
<ui:NavigationViewItem Content="History" Name="history" Tapped="History_Tapped" Visibility="Collapsed">
|
||||
<ui:NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</ui:NavigationViewItem.Icon>
|
||||
</ui:NavigationViewItem>
|
||||
<ui:NavigationViewItem Icon="Like" Content="Liked videos" Name="likedVideos" Tapped="LikedVideos_Tapped" Visibility="Collapsed"/>
|
||||
<ui:NavigationViewItem Icon="Clock" Content="Watch later" Name="watchLater" Tapped="WatchLater_Tapped" Visibility="Collapsed"/>
|
||||
<ui:NavigationViewItem Icon="Download" Content="Downloads" Name="downloads" Tapped="Downloads_Tapped"/>
|
||||
</ui:NavigationViewList>
|
||||
|
||||
<ui:NavigationViewList Name="subscriptionsList">
|
||||
<ui:NavigationViewList.ItemContainerTransitions>
|
||||
<TransitionCollection>
|
||||
<EntranceThemeTransition IsStaggeringEnabled="True"/>
|
||||
</TransitionCollection>
|
||||
</ui:NavigationViewList.ItemContainerTransitions>
|
||||
<ui:NavigationViewList.ItemTemplate>
|
||||
<DataTemplate x:DataType="data:Subscription">
|
||||
<StackPanel Orientation="Horizontal" Padding="5" Margin="-5,0,0,0">
|
||||
<PersonPicture Height="20" Margin="-5,0,15,0">
|
||||
<PersonPicture.ProfilePicture>
|
||||
<BitmapImage UriSource="{Binding Snippet.Thumbnails.Medium.Url}" DecodePixelHeight="20" DecodePixelWidth="20"/>
|
||||
</PersonPicture.ProfilePicture>
|
||||
</PersonPicture>
|
||||
<TextBlock FontSize="14" Text="{Binding Snippet.Title}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ui:NavigationViewList.ItemTemplate>
|
||||
|
||||
<ui:NavigationViewItemHeader Content="Subscriptions" Name="subscriptionsHeader" Visibility="Collapsed"/>
|
||||
</ui:NavigationViewList>
|
||||
|
||||
<ui:NavigationViewList>
|
||||
<ui:NavigationViewList.ItemContainerTransitions>
|
||||
<TransitionCollection>
|
||||
<EntranceThemeTransition IsStaggeringEnabled="True"/>
|
||||
</TransitionCollection>
|
||||
</ui:NavigationViewList.ItemContainerTransitions>
|
||||
|
||||
<ui:NavigationViewItemHeader Content="Best of YouTube" Name="collectionsHeader"/>
|
||||
<ui:NavigationViewItem Content="Music" Tapped="Music_Tapped">
|
||||
<ui:NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</ui:NavigationViewItem.Icon>
|
||||
</ui:NavigationViewItem>
|
||||
<ui:NavigationViewItem Content="Sports" Tapped="Sports_Tapped">
|
||||
<ui:NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</ui:NavigationViewItem.Icon>
|
||||
</ui:NavigationViewItem>
|
||||
<ui:NavigationViewItem Content="Movies" Tapped="Movies_Tapped">
|
||||
<ui:NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</ui:NavigationViewItem.Icon>
|
||||
</ui:NavigationViewItem>
|
||||
<ui:NavigationViewItem Content="News" Tapped="News_Tapped">
|
||||
<ui:NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</ui:NavigationViewItem.Icon>
|
||||
</ui:NavigationViewItem>
|
||||
<ui:NavigationViewItem Content="Live" Tapped="Live_Tapped">
|
||||
<ui:NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</ui:NavigationViewItem.Icon>
|
||||
</ui:NavigationViewItem>
|
||||
<ui:NavigationViewItem Content="Spotlight" Tapped="Spotlight_Tapped">
|
||||
<ui:NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</ui:NavigationViewItem.Icon>
|
||||
</ui:NavigationViewItem>
|
||||
<ui:NavigationViewItem Content="360° video" Tapped="SphereVideo_Tapped">
|
||||
<ui:NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</ui:NavigationViewItem.Icon>
|
||||
</ui:NavigationViewItem>
|
||||
</ui:NavigationViewList>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</SplitView.Pane>
|
||||
|
||||
<SplitView.Content>
|
||||
<controls:MainFrame x:Name="content" Navigated="Content_Navigated" Navigating="Content_Navigating"/>
|
||||
</SplitView.Content>
|
||||
</SplitView>
|
||||
</ui:NavigationView>
|
||||
|
||||
<TextBlock x:Name="appTitle" Text="FoxTube" VerticalAlignment="Top" HorizontalAlignment="Left" Style="{StaticResource CaptionTextBlockStyle}" Margin="12,8"/>
|
||||
|
||||
<Grid Background="#282828" x:Name="splashScreen" Visibility="Visible">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition Height="180"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Canvas Grid.RowSpan="2">
|
||||
<Image Source="/Assets/SplashScreen.png" Name="splashImage"/>
|
||||
</Canvas>
|
||||
|
||||
<ProgressRing x:Name="splashRing" HorizontalAlignment="Center" Width="50" Height="50" IsActive="True" Grid.Row="1"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Page>
|
||||
|
||||
+255
-16
@@ -1,30 +1,269 @@
|
||||
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 System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using FoxTube.Classes;
|
||||
using Google.Apis.YouTube.v3.Data;
|
||||
using Microsoft.Services.Store.Engagement;
|
||||
using Windows.ApplicationModel.Activation;
|
||||
using Windows.Graphics.Display;
|
||||
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.Pages
|
||||
{
|
||||
/// <summary>
|
||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
public sealed partial class MainPage : Page
|
||||
{
|
||||
public MainPage()
|
||||
public MainPage(SplashScreen splash, object args)
|
||||
{
|
||||
this.InitializeComponent();
|
||||
InitializeComponent();
|
||||
|
||||
SetSplashScreen(splash);
|
||||
Methods.SetTitleBar();
|
||||
|
||||
UserManagement.AuthorizationStateChanged += AuthorizationStateChanged;
|
||||
UserManagement.SubscriptionChanged += SubscriptionChanged;
|
||||
|
||||
if (StoreServicesFeedbackLauncher.IsSupported())
|
||||
feedback.Visibility = Visibility.Visible;
|
||||
|
||||
//TODO: Initialize stuff
|
||||
//TODO: Remove this method
|
||||
Begin();
|
||||
}
|
||||
|
||||
async void Begin()
|
||||
{
|
||||
await Task.Delay(5000);
|
||||
FadeOut.Storyboard.Begin();
|
||||
}
|
||||
|
||||
void SetSplashScreen(SplashScreen splash)
|
||||
{
|
||||
double ScaleFactor = DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel;
|
||||
|
||||
splashImage.SetValue(Canvas.LeftProperty, splash.ImageLocation.Left);
|
||||
splashImage.SetValue(Canvas.TopProperty, splash.ImageLocation.Top);
|
||||
if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))
|
||||
{
|
||||
splashImage.Height = splash.ImageLocation.Height / ScaleFactor;
|
||||
splashImage.Width = splash.ImageLocation.Width / ScaleFactor;
|
||||
}
|
||||
else
|
||||
{
|
||||
splashImage.Height = splash.ImageLocation.Height;
|
||||
splashImage.Width = splash.ImageLocation.Width;
|
||||
}
|
||||
}
|
||||
|
||||
void SubscriptionChanged(string action, Subscription subscription)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case "add":
|
||||
subscriptionsHeader.Visibility = Visibility.Visible;
|
||||
if (subscriptionsList.Items.Count < 10)
|
||||
subscriptionsList.Items.Add(subscription);
|
||||
break;
|
||||
|
||||
case "remove":
|
||||
if (subscriptionsList.Items.Contains(subscription))
|
||||
{
|
||||
subscriptionsList.Items.Remove(subscription);
|
||||
if (UserManagement.Current.Subscriptions.Count >= 10)
|
||||
subscriptionsList.Items.Add(UserManagement.Current.Subscriptions[9]);
|
||||
else if (UserManagement.Current.Subscriptions.Count == 0)
|
||||
subscriptionsHeader.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AuthorizationStateChanged(bool isAuthorized)
|
||||
{
|
||||
if (isAuthorized)
|
||||
{
|
||||
accountManager.Logged();
|
||||
|
||||
subscriptions.Visibility =
|
||||
libraryHeader.Visibility =
|
||||
history.Visibility =
|
||||
likedVideos.Visibility =
|
||||
watchLater.Visibility = Visibility.Visible;
|
||||
|
||||
if (UserManagement.Current.Subscriptions.Count > 0)
|
||||
{
|
||||
subscriptionsHeader.Visibility = Visibility.Visible;
|
||||
for (int k = 0; k < UserManagement.Current.Subscriptions.Count && k < 10; k++)
|
||||
subscriptionsList.Items.Add(UserManagement.Current.Subscriptions[k]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
accountManager.Quit();
|
||||
|
||||
subscriptions.Visibility =
|
||||
libraryHeader.Visibility =
|
||||
history.Visibility =
|
||||
likedVideos.Visibility =
|
||||
watchLater.Visibility =
|
||||
subscriptionsHeader.Visibility = Visibility.Collapsed;
|
||||
|
||||
subscriptionsList.Items.Clear();
|
||||
}
|
||||
|
||||
content.AuthorizationChanged(isAuthorized);
|
||||
}
|
||||
|
||||
public void UpdateView()
|
||||
{
|
||||
nav.IsBackEnabled = content.CanGoBack;
|
||||
|
||||
if(content.SourcePageType.Name.Belongs("Subscriptions", "Home", "Settings"))
|
||||
{
|
||||
ExpandedThresholdWidth.MinWindowWidth = 1008;
|
||||
split.IsPaneOpen = split.DisplayMode == SplitViewDisplayMode.CompactInline ? true : false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExpandedThresholdWidth.MinWindowWidth = short.MaxValue;
|
||||
split.IsPaneOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
async void Search_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args) => await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
|
||||
{
|
||||
//TODO: Finish search bar
|
||||
if (search.Text.Length < 3 || args.Reason != AutoSuggestionBoxTextChangeReason.UserInput)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.Load($"http://suggestqueries.google.com/complete/search?ds=yt&client=toolbar&q={search.Text}&hl={Settings.RelevanceLanguage}");
|
||||
|
||||
List<string> items = new List<string>();
|
||||
|
||||
for (int i = 0; i < doc["toplevel"].ChildNodes.Count && i < 5; i++)
|
||||
items.Add(doc["toplevel"].ChildNodes[i]["suggestion"].GetAttribute("data"));
|
||||
search.ItemsSource = items;
|
||||
}
|
||||
catch
|
||||
{
|
||||
search.ItemsSource = null;
|
||||
}
|
||||
});
|
||||
|
||||
private void Split_PaneToggled(SplitView sender, object args)
|
||||
{
|
||||
subscriptionsHeader.Visibility = split.IsPaneOpen && subscriptionsList.Items.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
|
||||
|
||||
libraryHeader.Visibility =
|
||||
collectionsHeader.Visibility =
|
||||
libraryHeader.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
void Nav_SelectionChanged(Microsoft.UI.Xaml.Controls.NavigationView sender, Microsoft.UI.Xaml.Controls.NavigationViewSelectionChangedEventArgs args)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#region Simple UI interaction events
|
||||
void Nav_BackRequested(Microsoft.UI.Xaml.Controls.NavigationView sender, Microsoft.UI.Xaml.Controls.NavigationViewBackRequestedEventArgs args) =>
|
||||
content.BackRequested();
|
||||
|
||||
void Menu_Tapped(object sender, TappedRoutedEventArgs e) =>
|
||||
split.IsPaneOpen = !split.IsPaneOpen;
|
||||
|
||||
async void Feedback_Click(object sender, RoutedEventArgs e) =>
|
||||
await StoreServicesFeedbackLauncher.GetDefault().LaunchAsync();
|
||||
|
||||
void Home_Tapped(object sender, TappedRoutedEventArgs e) =>
|
||||
Navigation.GoToHome();
|
||||
|
||||
void Subscriptions_Tapped(object sender, TappedRoutedEventArgs e) =>
|
||||
Navigation.GoToSubscriptions();
|
||||
|
||||
void History_Tapped(object sender, TappedRoutedEventArgs e) =>
|
||||
Navigation.GoToHistory();
|
||||
|
||||
void LikedVideos_Tapped(object sender, TappedRoutedEventArgs e) =>
|
||||
Navigation.GoToPlaylist(UserManagement.Current.Channel.ContentDetails.RelatedPlaylists.Likes);
|
||||
|
||||
void WatchLater_Tapped(object sender, TappedRoutedEventArgs e) =>
|
||||
Navigation.GoToPlaylist("WL");
|
||||
|
||||
void Downloads_Tapped(object sender, TappedRoutedEventArgs e) =>
|
||||
Navigation.GoToDownloads();
|
||||
|
||||
void Music_Tapped(object sender, TappedRoutedEventArgs e) =>
|
||||
Navigation.GoToChannel("UC-9-kyTW8ZkZNDHQJ6FgpwQ");
|
||||
|
||||
void Sports_Tapped(object sender, TappedRoutedEventArgs e) =>
|
||||
Navigation.GoToChannel("UCEgdi0XIXXZ-qJOFPf4JSKw");
|
||||
|
||||
void Movies_Tapped(object sender, TappedRoutedEventArgs e) =>
|
||||
Navigation.GoToChannel("UClgRkhTL3_hImCAmdLfDE4g");
|
||||
|
||||
void News_Tapped(object sender, TappedRoutedEventArgs e) =>
|
||||
Navigation.GoToChannel("UCYfdidRxbB8Qhf0Nx7ioOYw");
|
||||
|
||||
void Live_Tapped(object sender, TappedRoutedEventArgs e) =>
|
||||
Navigation.GoToChannel("UC4R8DWoMoI7CAwX8_LjQHig");
|
||||
|
||||
void Spotlight_Tapped(object sender, TappedRoutedEventArgs e) =>
|
||||
Navigation.GoToChannel("UC8iNz9uwDGfomRnnKKbOhOQ");
|
||||
|
||||
private void SphereVideo_Tapped(object sender, TappedRoutedEventArgs e) =>
|
||||
Navigation.GoToChannel("UCzuqhhs6NWbgTzMuM09WKDQ");
|
||||
#endregion
|
||||
|
||||
#region Search bar methods
|
||||
async void SearchBtn_Tapped(object sender, TappedRoutedEventArgs e)
|
||||
{
|
||||
menu.Visibility =
|
||||
accountManager.Visibility =
|
||||
feedback.Visibility = Visibility.Collapsed;
|
||||
nav.IsBackButtonVisible = Microsoft.UI.Xaml.Controls.NavigationViewBackButtonVisible.Collapsed;
|
||||
|
||||
SearchExpanded.Storyboard.Begin();
|
||||
await Task.Delay(1);
|
||||
search.Focus(FocusState.Pointer);
|
||||
}
|
||||
|
||||
async void Search_LostFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (ActualWidth >= 1000)
|
||||
return;
|
||||
|
||||
SearchCollapsed.Storyboard.Begin();
|
||||
await Task.Delay(1000);
|
||||
|
||||
menu.Visibility =
|
||||
accountManager.Visibility =
|
||||
feedback.Visibility = Visibility.Visible;
|
||||
nav.IsBackButtonVisible = Microsoft.UI.Xaml.Controls.NavigationViewBackButtonVisible.Visible;
|
||||
}
|
||||
|
||||
void Search_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(search.Text))
|
||||
Navigation.GoToSearch(new SearchParameters(search.Text));
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void Content_Navigated(System.Collections.IList pivotCollection, int? selectedPivot)
|
||||
{
|
||||
nav.MenuItemsSource = pivotCollection;
|
||||
if(selectedPivot.HasValue)
|
||||
nav.SelectedItem = pivotCollection[selectedPivot.Value];
|
||||
}
|
||||
|
||||
private void Content_Navigating(Type sourcePageType, object parameter)
|
||||
{
|
||||
nav.MenuItems.Clear();
|
||||
UpdateView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="all.Content" xml:space="preserve">
|
||||
<value>All</value>
|
||||
</data>
|
||||
<data name="changelog" xml:space="preserve">
|
||||
<value>Changelog</value>
|
||||
</data>
|
||||
<data name="changelogs.Content" xml:space="preserve">
|
||||
<value>Changelogs</value>
|
||||
</data>
|
||||
<data name="dev" xml:space="preserve">
|
||||
<value>Developer's message</value>
|
||||
</data>
|
||||
<data name="filter.Header" xml:space="preserve">
|
||||
<value>Filter</value>
|
||||
</data>
|
||||
<data name="messages.Content" xml:space="preserve">
|
||||
<value>Messages</value>
|
||||
</data>
|
||||
<data name="select.Text" xml:space="preserve">
|
||||
<value>Select item from the list</value>
|
||||
</data>
|
||||
<data name="whatsnew" xml:space="preserve">
|
||||
<value>What's new in v</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,135 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="dontAsk" xml:space="preserve">
|
||||
<value>Don't ask me anymore</value>
|
||||
</data>
|
||||
<data name="feedbackMessage" xml:space="preserve">
|
||||
<value>Have some thoughts to share about the app or any suggestions? Leave feedback!</value>
|
||||
</data>
|
||||
<data name="promptLater" xml:space="preserve">
|
||||
<value>Maybe later</value>
|
||||
</data>
|
||||
<data name="rate" xml:space="preserve">
|
||||
<value>Like our app? Review it on Microsoft Store!</value>
|
||||
</data>
|
||||
<data name="sure" xml:space="preserve">
|
||||
<value>Sure!</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="channel" xml:space="preserve">
|
||||
<value>Channel</value>
|
||||
</data>
|
||||
<data name="playlist" xml:space="preserve">
|
||||
<value>Playlist</value>
|
||||
</data>
|
||||
<data name="video" xml:space="preserve">
|
||||
<value>Video</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -117,28 +117,10 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="all.Content" xml:space="preserve">
|
||||
<value>All</value>
|
||||
</data>
|
||||
<data name="changelog" xml:space="preserve">
|
||||
<value>Changelog</value>
|
||||
</data>
|
||||
<data name="changelogs.Content" xml:space="preserve">
|
||||
<value>Changelogs</value>
|
||||
</data>
|
||||
<data name="dev" xml:space="preserve">
|
||||
<value>Developer's message</value>
|
||||
</data>
|
||||
<data name="filter.Header" xml:space="preserve">
|
||||
<value>Filter</value>
|
||||
</data>
|
||||
<data name="messages.Content" xml:space="preserve">
|
||||
<value>Messages</value>
|
||||
</data>
|
||||
<data name="select.Text" xml:space="preserve">
|
||||
<value>Select item from the list</value>
|
||||
</data>
|
||||
<data name="whatsnew" xml:space="preserve">
|
||||
<value>What's new in v</value>
|
||||
<data name="whatsNew" xml:space="preserve">
|
||||
<value>What's new in version</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,150 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="error" xml:space="preserve">
|
||||
<value>Error</value>
|
||||
</data>
|
||||
<data name="feedback.Content" xml:space="preserve">
|
||||
<value>Leave feedback</value>
|
||||
</data>
|
||||
<data name="general" xml:space="preserve">
|
||||
<value>It could be caused by YouTube internal server error or by application's bug. Please, try again later</value>
|
||||
</data>
|
||||
<data name="generalTitle" xml:space="preserve">
|
||||
<value>We are unable to display the page</value>
|
||||
</data>
|
||||
<data name="message" xml:space="preserve">
|
||||
<value>Message</value>
|
||||
</data>
|
||||
<data name="network.Content" xml:space="preserve">
|
||||
<value>Open network settings</value>
|
||||
</data>
|
||||
<data name="or.Text" xml:space="preserve">
|
||||
<value>OR</value>
|
||||
</data>
|
||||
<data name="refresh.Content" xml:space="preserve">
|
||||
<value>Refresh page</value>
|
||||
</data>
|
||||
<data name="stackTrace" xml:space="preserve">
|
||||
<value>Stack trace</value>
|
||||
</data>
|
||||
<data name="troubleshooter.Content" xml:space="preserve">
|
||||
<value>Open troubleshooter</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,126 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="clipboardHead" xml:space="preserve">
|
||||
<value>We've found this on your clipboard</value>
|
||||
</data>
|
||||
<data name="clipboardOpen" xml:space="preserve">
|
||||
<value>Open in FoxTube</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,375 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:FoxTube.Controls.Player"
|
||||
xmlns:controls="using:FoxTube.Controls"
|
||||
xmlns:adverts="using:FoxTube.Controls.Adverts">
|
||||
|
||||
<Style TargetType="local:PlayerControls">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="UseSystemFocusVisuals" Value="True" />
|
||||
<Setter Property="IsTextScaleFactorEnabled" Value="False" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:PlayerControls">
|
||||
<Grid Background="Transparent" Name="root">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.Resources>
|
||||
<Style x:Key="PlayerSeek" TargetType="Slider">
|
||||
<Setter Property="Margin" Value="0"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Slider">
|
||||
<Grid>
|
||||
<Grid.Resources>
|
||||
<Style TargetType="Thumb">
|
||||
<Setter Property="Background" Value="Red" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Thumb">
|
||||
<Ellipse Fill="{TemplateBinding Background}"/>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Grid.Resources>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal"/>
|
||||
<VisualState x:Name="Pressed">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalTrackRect" Storyboard.TargetProperty="Fill">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTrackFillPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalThumb" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderThumbBackgroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SliderContainer" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderContainerBackgroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Disabled">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalDecreaseRect" Storyboard.TargetProperty="Fill">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTrackValueFillDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalTrackRect" Storyboard.TargetProperty="Fill">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTrackFillDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalThumb" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderThumbBackgroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SliderContainer" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderContainerBackgroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="PointerOver">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalTrackRect" Storyboard.TargetProperty="Fill">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTrackFillPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalThumb" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderThumbBackgroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SliderContainer" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderContainerBackgroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="FocusEngagementStates">
|
||||
<VisualState x:Name="FocusDisengaged"/>
|
||||
<VisualState x:Name="FocusEngagedHorizontal">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SliderContainer" Storyboard.TargetProperty="(Control.IsTemplateFocusTarget)">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="False" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalThumb" Storyboard.TargetProperty="(Control.IsTemplateFocusTarget)">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="True" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
|
||||
<Grid x:Name="SliderContainer" Control.IsTemplateFocusTarget="True" Background="{ThemeResource SliderContainerBackground}">
|
||||
<Grid x:Name="HorizontalTemplate">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Rectangle x:Name="HorizontalTrackRect" Height="{StaticResource SliderTrackThemeHeight}" Fill="{TemplateBinding Background}" Grid.ColumnSpan="3"/>
|
||||
|
||||
<ProgressBar x:Name="DownloadProgressIndicator" Grid.ColumnSpan="3"
|
||||
Height="{ThemeResource SliderTrackThemeHeight}"
|
||||
Foreground="{ThemeResource SystemControlHighlightChromeAltLowBrush}"
|
||||
Background="Transparent"
|
||||
BorderBrush="Transparent"
|
||||
BorderThickness="1"/>
|
||||
|
||||
<Rectangle Height="4" x:Name="HorizontalDecreaseRect" Fill="{StaticResource SystemAccentColor}"/>
|
||||
|
||||
<Thumb x:Name="HorizontalThumb"
|
||||
Height="15" Width="15" Grid.Column="1"
|
||||
AutomationProperties.AccessibilityView="Raw">
|
||||
<Thumb.DataContext>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="112"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Image x:Name="ThumbnailImage" Width="192"/>
|
||||
<TextBlock Grid.Row="1" x:Name="TimeElapsedPreview"/>
|
||||
</Grid>
|
||||
</Thumb.DataContext>
|
||||
</Thumb>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Grid.Resources>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="ControlPanelVisibilityStates">
|
||||
<VisualState x:Name="ControlPanelFadeIn">
|
||||
<Storyboard>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Border">
|
||||
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
|
||||
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="1" />
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="ControlPanelFadeOut">
|
||||
<Storyboard>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Border">
|
||||
<EasingDoubleKeyFrame KeyTime="0" Value="1" />
|
||||
<EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0" />
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsHitTestVisible" Storyboard.TargetName="Border">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="False" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
|
||||
<VisualStateGroup x:Name="MediaStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Buffering">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="BufferingProgressBar">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Loading">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="BufferingProgressBar">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<DoubleAnimation Storyboard.TargetName="ProgressSlider"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="0"
|
||||
Duration="0" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<!--<VisualState x:Name="Error">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ErrorBorder">
|
||||
<DiscreteObjectKeyFrame KeyTime="0">
|
||||
<DiscreteObjectKeyFrame.Value>
|
||||
<Visibility>Visible</Visibility>
|
||||
</DiscreteObjectKeyFrame.Value>
|
||||
</DiscreteObjectKeyFrame>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>-->
|
||||
<VisualState x:Name="Disabled">
|
||||
<Storyboard/>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
|
||||
<VisualStateGroup x:Name="PlayPauseStates">
|
||||
<VisualState x:Name="PlayState" />
|
||||
<VisualState x:Name="PauseState">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlayPauseSymbol" Storyboard.TargetProperty="Symbol">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="Pause" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="FullWindowStates">
|
||||
<VisualState x:Name="NonFullWindowState" />
|
||||
<VisualState x:Name="FullWindowState">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="FullWindowSymbol" Storyboard.TargetProperty="Symbol">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="BackToWindow" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
|
||||
<Border x:Name="Border">
|
||||
<Border.Resources>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource ButtonRevealStyle}">
|
||||
<Setter Property="Width" Value="50"/>
|
||||
<Setter Property="Height" Value="50"/>
|
||||
<Setter Property="FontSize" Value="20"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="FontFamily" Value="Segoe UI, Segoe MDL2 Assets"/>
|
||||
</Style>
|
||||
</Border.Resources>
|
||||
<Grid x:Name="ControlPanelGrid">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid x:Name="header">
|
||||
<Grid.Background>
|
||||
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
|
||||
<GradientStop Color="Black"/>
|
||||
<GradientStop Color="#00000000" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
</Grid.Background>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button x:Name="MinimizeButton" HorizontalAlignment="Left" VerticalAlignment="Top" Content=""/>
|
||||
|
||||
<StackPanel VerticalAlignment="Top" Grid.Column="1" Margin="10,0">
|
||||
<TextBlock x:Name="title" Text="Name" TextTrimming="CharacterEllipsis" MaxLines="1" Style="{StaticResource TitleTextBlockStyle}"/>
|
||||
<TextBlock x:Name="channel" Text="Channel" TextTrimming="CharacterEllipsis" FontStyle="Italic"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel x:Name="RightHeaderControls" Orientation="Horizontal" VerticalAlignment="Top" Grid.Column="2">
|
||||
<Button x:Name="CloseButton" HorizontalAlignment="Right" VerticalAlignment="Top" Content=""/>
|
||||
<Button x:Name="CastButton" Content=""/>
|
||||
<Button x:Name="CompactOverlayButton" HorizontalAlignment="Right" VerticalAlignment="Top" Content=""/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<Grid x:Name="centerTrigger" Grid.Row="1"/>
|
||||
|
||||
<Grid x:Name="center" Grid.Row="1" Visibility="Collapsed" Background="#7F000000">
|
||||
<Button x:Name="drag" IsHitTestVisible="False" Height="32" Width="47" Margin="0,0,47,0" Content="" Visibility="Collapsed" Padding="0" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Top" HorizontalAlignment="Right"/>
|
||||
<StackPanel x:Name="centerControls" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
<ProgressBar x:Name="SeekIndicator" Background="Transparent" VerticalAlignment="Bottom"/>
|
||||
</Grid>
|
||||
|
||||
<Grid x:Name="footer" Grid.Row="2">
|
||||
<Grid.Background>
|
||||
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
|
||||
<GradientStop Color="Black" Offset="1"/>
|
||||
<GradientStop Color="#00000000" Offset="0"/>
|
||||
</LinearGradientBrush>
|
||||
</Grid.Background>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<ProgressBar x:Name="BufferingProgressBar" VerticalAlignment="Bottom" Grid.ColumnSpan="3" Background="Transparent" IsIndeterminate="True" Visibility="Collapsed"/>
|
||||
|
||||
<StackPanel x:Name="LeftFooterControls" Orientation="Horizontal" VerticalAlignment="Bottom">
|
||||
<Button x:Name="PlayPauseButton">
|
||||
<SymbolIcon x:Name="PlayPauseSymbol" Symbol="Play"/>
|
||||
<Button.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="Space"/>
|
||||
</Button.KeyboardAccelerators>
|
||||
</Button>
|
||||
<Button x:Name="PreviousButton" Content="" Visibility="Collapsed"/>
|
||||
<Button x:Name="NextButton" Content=""/>
|
||||
<Button x:Name="VolumeMenuButton" Content="">
|
||||
<Button.Flyout>
|
||||
<Flyout>
|
||||
<StackPanel Orientation="Horizontal" Margin="-10">
|
||||
<Button x:Name="AudioMuteButton" Content="" FontFamily="Segoe MDL2 Assets" Height="50" Width="50" Background="Transparent" FontSize="20"/>
|
||||
<Slider x:Name="VolumeSlider" Width="150" Margin="10,5,10,0" VerticalAlignment="Center" TickPlacement="Outside" TickFrequency="10"/>
|
||||
</StackPanel>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
<Button x:Name="PlayLiveButton" Width="NaN" Visibility="Collapsed">
|
||||
<TextBlock x:Uid="/VideoPage/live" Text="🔴 LIVE"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
||||
<Grid x:Name="CenterFooterControls" Height="50" Grid.Column="1" VerticalAlignment="Bottom">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="1" Margin="5,0" VerticalAlignment="Center" HorizontalAlignment="Left" x:Name="TimeElapsedElement" Text="00:00"/>
|
||||
<TextBlock Grid.Row="1" Margin="5,0" VerticalAlignment="Center" HorizontalAlignment="Right" x:Name="TimeRemainingElement" Text="00:00"/>
|
||||
<Slider x:Name="ProgressSlider" Style="{StaticResource PlayerSeek}" IsThumbToolTipEnabled="False" HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="5,0"/>
|
||||
</Grid>
|
||||
|
||||
<StackPanel x:Name="RightFooterControls" Grid.Column="2" VerticalAlignment="Bottom" Orientation="Horizontal">
|
||||
<Button x:Name="SkipBackwardButton" Content="">
|
||||
<Button.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="Left"/>
|
||||
</Button.KeyboardAccelerators>
|
||||
</Button>
|
||||
<Button x:Name="SkipForwardButton" Content="">
|
||||
<Button.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="Right"/>
|
||||
</Button.KeyboardAccelerators>
|
||||
</Button>
|
||||
<Line Stroke="White" StrokeThickness="2" Y1="5" Y2="45"/>
|
||||
<Button x:Name="CaptionsMenuButton" Content="">
|
||||
<Button.Flyout>
|
||||
<Flyout>
|
||||
<StackPanel Width="225">
|
||||
<ToggleSwitch x:Name="CaptionsToggleSwitch" OnContent="Subtitles" OffContent="Subtitles" x:Uid="/VideoPage/subsSwitch"/>
|
||||
<ComboBox x:Name="CaptionsSelector" Header="Language" x:Uid="/VideoPage/subsSelector" PlaceholderText="No captions are available" HorizontalAlignment="Stretch"/>
|
||||
</StackPanel>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
<Button x:Name="SettingsMenuButton" Content="">
|
||||
<Button.Flyout>
|
||||
<Flyout>
|
||||
<StackPanel>
|
||||
<Slider x:Name="PlaybackSpeedSlider" x:Uid="/VideoPage/playbackSpeed" Orientation="Horizontal" TickPlacement="Outside" StepFrequency=".1" Value="1" Maximum="3" Header="Playback speed"/>
|
||||
<ComboBox Width="225" x:Name="QualitySelector" Header="Language" x:Uid="/VideoPage/qualitySelector"/>
|
||||
</StackPanel>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
<Button x:Name="FullWindowButton">
|
||||
<SymbolIcon x:Name="FullWindowSymbol" Symbol="FullScreen"/>
|
||||
<Button.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="F11"/>
|
||||
</Button.KeyboardAccelerators>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<controls:LiveCaptions Visibility="Collapsed" x:Name="CaptionControl"/>
|
||||
|
||||
<adverts:PlayerAdvert Grid.Row="1" x:Name="AdvertControl" VerticalAlignment="Bottom"/>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -7,6 +7,15 @@
|
||||
<Style TargetType="Button" BasedOn="{StaticResource ButtonRevealStyle}">
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="NavigationViewHeaderButton" TargetType="Button" BasedOn="{StaticResource ButtonRevealStyle}">
|
||||
<Setter Property="FontFamily" Value="Segoe MDL2 Assets"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="Height" Value="41"/>
|
||||
<Setter Property="Width" Value="60"/>
|
||||
<Setter Property="FontSize" Value="15"/>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="ListViewItem" BasedOn="{StaticResource ListViewItemRevealStyle}"/>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="SelectionHighlightColor" Value="Red"/>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 102 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
+3792
File diff suppressed because one or more lines are too long
+3267
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 241 KiB |
Binary file not shown.
Reference in New Issue
Block a user