Core update. Base core features are done (main app doesn't compile)
Related Work Items: #416, #422, #423, #424
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using FoxTube.Utils;
|
||||
using FoxTube.Services;
|
||||
using FoxTube.Utils;
|
||||
using Google.Apis.YouTube.v3.Data;
|
||||
using SQLitePCL;
|
||||
using System;
|
||||
@@ -131,7 +132,7 @@ namespace FoxTube
|
||||
|
||||
public static async Task<Channel> GetChannel(string channelId, string part)
|
||||
{
|
||||
var request = UserManagement.Service.Channels.List(part);
|
||||
var request = UserService.Service.Channels.List(part);
|
||||
request.Id = channelId;
|
||||
request.MaxResults = 1;
|
||||
|
||||
|
||||
@@ -130,17 +130,20 @@
|
||||
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Models\Collections\InboxCollection.cs" />
|
||||
<Compile Include="Models\Collections\ViewCollection.cs" />
|
||||
<Compile Include="Models\Subscription.cs" />
|
||||
<Compile Include="Services\DownloadsCenter.cs" />
|
||||
<Compile Include="Services\DownloadsService.cs" />
|
||||
<Compile Include="Extensions.cs" />
|
||||
<Compile Include="Utils\Feedback.cs" />
|
||||
<Compile Include="Utils\FeedbackIterop.cs" />
|
||||
<Compile Include="Services\History.cs" />
|
||||
<Compile Include="Services\Inbox.cs" />
|
||||
<Compile Include="Services\InboxService.cs" />
|
||||
<Compile Include="Utils\Metrics.cs" />
|
||||
<Compile Include="Services\Search.cs" />
|
||||
<Compile Include="Settings.cs" />
|
||||
<Compile Include="Utils\StoreInterop.cs" />
|
||||
<Compile Include="UserManagement.cs" />
|
||||
<Compile Include="Services\Storage.cs" />
|
||||
<Compile Include="Utils\AddonsInterop.cs" />
|
||||
<Compile Include="Services\UserService.cs" />
|
||||
<Compile Include="Utils\SecretConstants.cs" />
|
||||
<Compile Include="Utils\Utils.cs" />
|
||||
<Compile Include="Models\DownloadItem.cs" />
|
||||
<Compile Include="Models\InboxItem.cs" />
|
||||
@@ -168,6 +171,9 @@
|
||||
<PackageReference Include="Google.Apis.YouTube.v3">
|
||||
<Version>1.45.0.1929</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Advertising.XAML">
|
||||
<Version>10.1811.22001</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.AppCenter.Analytics">
|
||||
<Version>3.2.1</Version>
|
||||
</PackageReference>
|
||||
@@ -191,13 +197,14 @@
|
||||
<WCFMetadata Include="Connected Services\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<SDKReference Include="Microsoft.Advertising.Xaml, Version=10.0">
|
||||
<Name>Microsoft Advertising SDK for XAML</Name>
|
||||
</SDKReference>
|
||||
<SDKReference Include="Microsoft.Services.Store.Engagement, Version=10.0">
|
||||
<Name>Microsoft Engagement Framework</Name>
|
||||
</SDKReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="ValueConverters\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
||||
<VisualStudioVersion>14.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using FoxTube.Services;
|
||||
using FoxTube.Utils;
|
||||
|
||||
namespace FoxTube.Models.Collections
|
||||
{
|
||||
public class InboxCollection : ViewCollection<InboxItem>
|
||||
{
|
||||
private int _pageNumber = 0;
|
||||
private HttpClient _httpClient = new HttpClient();
|
||||
|
||||
public override async Task<LoadMoreItemsResult> LoadItems()
|
||||
{
|
||||
// TODO: Add backend
|
||||
HttpResponseMessage response = await _httpClient.GetAsync($"https://xfox111.net/API/FoxTube/Inbox?" +
|
||||
$"lang={Storage.GetValue<string>(Storage.Settings.UILanguage)}&" +
|
||||
$"currentVersion={Metrics.CurrentVersion}&" +
|
||||
$"itemsCount={ItemsPerRequest}&" +
|
||||
$"iteration={_pageNumber}");
|
||||
|
||||
if (!response.IsSuccessStatusCode || response.StatusCode == System.Net.HttpStatusCode.NoContent)
|
||||
{
|
||||
HasMoreItems = false;
|
||||
return new LoadMoreItemsResult
|
||||
{
|
||||
Count = 0
|
||||
};
|
||||
}
|
||||
|
||||
InboxItem[] newItems = JsonConvert.DeserializeObject<InboxItem[]>(await response.Content.ReadAsStringAsync());
|
||||
foreach (InboxItem item in newItems)
|
||||
Items.Add(item);
|
||||
|
||||
_pageNumber++;
|
||||
|
||||
return new LoadMoreItemsResult
|
||||
{
|
||||
Count = (uint)newItems.Length
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml.Data;
|
||||
|
||||
namespace FoxTube.Models.Collections
|
||||
{
|
||||
public abstract class ViewCollection<T> : ObservableCollection<T>, ISupportIncrementalLoading
|
||||
{
|
||||
public int ItemsPerRequest { get; set; }
|
||||
public bool HasMoreItems { get; protected set; } = true;
|
||||
|
||||
public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count) =>
|
||||
AsyncInfo.Run((c) => LoadItems());
|
||||
|
||||
public abstract Task<LoadMoreItemsResult> LoadItems();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using FoxTube.Services;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
@@ -20,7 +21,7 @@ namespace FoxTube.Models
|
||||
public async Task CommenceDownload(IStreamInfo stream, IStorageFile destination)
|
||||
{
|
||||
Path = destination.Path;
|
||||
YoutubeClient client = new YoutubeClient(UserManagement.Service.HttpClient);
|
||||
YoutubeClient client = new YoutubeClient(UserService.Service.HttpClient);
|
||||
|
||||
State = DownloadState.Downloading;
|
||||
Task task = client.Videos.Streams.DownloadAsync(stream, Path, DownloadPercentage, CTS.Token);
|
||||
|
||||
@@ -13,6 +13,7 @@ using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
using YouTube;
|
||||
using YoutubeExplode;
|
||||
using FoxTube.Services;
|
||||
|
||||
namespace FoxTube.Models
|
||||
{
|
||||
@@ -36,10 +37,10 @@ namespace FoxTube.Models
|
||||
catch (Exception e)
|
||||
{
|
||||
Metrics.SendReport(new Exception("Failed to unsubscribe", e));
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
UserManagement.SubscriptionsChangedInvoker(this, subscription);
|
||||
UserService.SubscriptionsChangedInvoker(this, subscription);
|
||||
Subscriptions.Remove(subscription);
|
||||
|
||||
SaveSubscriptions();
|
||||
@@ -77,7 +78,7 @@ namespace FoxTube.Models
|
||||
};
|
||||
Subscriptions.Add(subscription);
|
||||
|
||||
UserManagement.SubscriptionsChangedInvoker(this, subscription);
|
||||
UserService.SubscriptionsChangedInvoker(this, subscription);
|
||||
|
||||
SaveSubscriptions();
|
||||
return true;
|
||||
@@ -86,7 +87,7 @@ namespace FoxTube.Models
|
||||
|
||||
private void SaveSubscriptions()
|
||||
{
|
||||
Dictionary<string, string> subs = Subscriptions.Select(i =>
|
||||
Dictionary<string, string> subs = Subscriptions.Select(i =>
|
||||
new KeyValuePair<string, string>(i.ChannelId, i.Avatar.Default__?.Url))
|
||||
as Dictionary<string, string>;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Google.Apis.YouTube.v3.Data;
|
||||
using FoxTube.Services;
|
||||
using Google.Apis.YouTube.v3.Data;
|
||||
using System;
|
||||
using YoutubeExplode;
|
||||
|
||||
@@ -36,7 +37,7 @@ namespace FoxTube.Models
|
||||
|
||||
private async void LoadInfo()
|
||||
{
|
||||
YoutubeClient client = new YoutubeClient(UserManagement.Service.HttpClient);
|
||||
YoutubeClient client = new YoutubeClient(UserService.Service.HttpClient);
|
||||
|
||||
AdditionalMeta = await client.Videos.GetAsync(Meta.Id);
|
||||
ChannelMeta = await client.Channels.GetByVideoAsync(Meta.Id);
|
||||
|
||||
+36
-11
@@ -9,23 +9,25 @@ using YoutubeExplode.Videos;
|
||||
using YoutubeExplode.Videos.Streams;
|
||||
using FoxTube.Utils;
|
||||
using FoxTube.Models;
|
||||
using Windows.Storage.Pickers;
|
||||
|
||||
namespace FoxTube.Services
|
||||
{
|
||||
public static class DownloadsCenter
|
||||
public static class DownloadsService
|
||||
{
|
||||
public static List<SavedVideo> History { get; private set; }
|
||||
public static List<SavedVideo> History { get; } = new List<SavedVideo>();
|
||||
public static List<DownloadItem> Queue { get; } = new List<DownloadItem>();
|
||||
|
||||
static DownloadsCenter() =>
|
||||
static DownloadsService() =>
|
||||
Initialize();
|
||||
|
||||
private static async void Initialize()
|
||||
{
|
||||
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync("DownloadHistory.json", CreationCollisionOption.OpenIfExists);
|
||||
StorageFile file = await Storage.Folder.CreateFileAsync("DownloadHistory.json", CreationCollisionOption.OpenIfExists);
|
||||
try
|
||||
{
|
||||
History = JsonConvert.DeserializeObject<List<SavedVideo>>(File.ReadAllText(file.Path) ?? "") ?? new List<SavedVideo>();
|
||||
List<SavedVideo> savedVideos = JsonConvert.DeserializeObject<List<SavedVideo>>(File.ReadAllText(file.Path) ?? "") ?? new List<SavedVideo>();
|
||||
History.AddRange(savedVideos);
|
||||
|
||||
foreach (SavedVideo i in History)
|
||||
try { i.IsPathValid = await StorageApplicationPermissions.MostRecentlyUsedList.GetFileAsync(i.AccessToken) != null; }
|
||||
@@ -33,7 +35,6 @@ namespace FoxTube.Services
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
History = new List<SavedVideo>();
|
||||
await file.DeleteAsync(StorageDeleteOption.PermanentDelete);
|
||||
StorageApplicationPermissions.MostRecentlyUsedList.Clear();
|
||||
Metrics.SendReport(new Exception("Failed to load downloads history", e));
|
||||
@@ -64,12 +65,12 @@ namespace FoxTube.Services
|
||||
{
|
||||
await item.CommenceDownload(streamInfo, destination);
|
||||
|
||||
SavedVideo savedItem = item as SavedVideo;
|
||||
SavedVideo savedItem = item;
|
||||
savedItem.AccessToken = StorageApplicationPermissions.MostRecentlyUsedList.Add(destination);
|
||||
|
||||
History.Add(savedItem);
|
||||
|
||||
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync("DownloadHistory.json", CreationCollisionOption.OpenIfExists);
|
||||
StorageFile file = await Storage.Folder.CreateFileAsync("DownloadHistory.json", CreationCollisionOption.OpenIfExists);
|
||||
File.WriteAllText(file.Path, JsonConvert.SerializeObject(History));
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
@@ -111,10 +112,11 @@ namespace FoxTube.Services
|
||||
|
||||
public static async Task<StorageFolder> GetDefaultDownloadsFolder()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Settings.DefaultDownloadsFolder))
|
||||
return await KnownFolders.VideosLibrary.CreateFolderAsync("FoxTube", CreationCollisionOption.OpenIfExists);
|
||||
if (Storage.GetValue<string>(Storage.Settings.DefaultDownloadsFolder) is string token && !string.IsNullOrWhiteSpace(token))
|
||||
return await StorageApplicationPermissions.FutureAccessList.GetFolderAsync(token) ??
|
||||
await KnownFolders.VideosLibrary.CreateFolderAsync("FoxTube", CreationCollisionOption.OpenIfExists);
|
||||
else
|
||||
return await StorageApplicationPermissions.FutureAccessList.GetFolderAsync(Settings.DefaultDownloadsFolder);
|
||||
return await KnownFolders.VideosLibrary.CreateFolderAsync("FoxTube", CreationCollisionOption.OpenIfExists);
|
||||
}
|
||||
|
||||
public static async Task CancelAll()
|
||||
@@ -123,5 +125,28 @@ namespace FoxTube.Services
|
||||
while (Queue.Count > 0)
|
||||
await Task.Delay(500);
|
||||
}
|
||||
|
||||
public static async Task<StorageFolder> ChangeDefaultFolder()
|
||||
{
|
||||
FolderPicker picker = new FolderPicker
|
||||
{
|
||||
SuggestedStartLocation = PickerLocationId.Downloads
|
||||
};
|
||||
|
||||
StorageFolder folder = await picker.PickSingleFolderAsync();
|
||||
|
||||
if (folder != null)
|
||||
{
|
||||
if (Storage.GetValue<string>(Storage.Settings.DefaultDownloadsFolder) is string token && !string.IsNullOrWhiteSpace(token))
|
||||
StorageApplicationPermissions.FutureAccessList.AddOrReplace(token, folder);
|
||||
else
|
||||
{
|
||||
token = StorageApplicationPermissions.FutureAccessList.Add(folder);
|
||||
Storage.SetValue(Storage.Settings.DefaultDownloadsFolder, token);
|
||||
}
|
||||
}
|
||||
|
||||
return folder;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,36 @@
|
||||
using FoxTube.Models;
|
||||
using FoxTube.Models.Collections;
|
||||
using FoxTube.Utils;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
using Windows.UI.Notifications;
|
||||
|
||||
namespace FoxTube.Services
|
||||
{
|
||||
public static class Inbox
|
||||
public static class InboxService
|
||||
{
|
||||
private static readonly HttpClient client = new HttpClient();
|
||||
private static readonly ApplicationDataContainer storage = ApplicationData.Current.RoamingSettings;
|
||||
public const string lastChangelogVersionKey = "Inbox.lastChangelogVersion";
|
||||
public const string lastCheckKey = "Inbox.lastChangelogVersion";
|
||||
|
||||
public static async void PushNew()
|
||||
private static readonly HttpClient client = new HttpClient();
|
||||
|
||||
public static InboxCollection GetInboxCollection() =>
|
||||
new InboxCollection();
|
||||
|
||||
public static async Task PushNew()
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO: Add backend
|
||||
HttpResponseMessage response = await client.GetAsync($"https://xfox111.net/FoxTube/Inbox?toast=true&publishedAfter={storage.Values["Inbox.lastCheck"]}&lang={Settings.Language}&appVersion={Metrics.CurrentVersion}");
|
||||
storage.Values["Inbox.lastCheck"] = DateTime.UtcNow.Ticks;
|
||||
HttpResponseMessage response = await client.GetAsync($"https://xfox111.net/FoxTube/Inbox?" +
|
||||
$"toast=true&" +
|
||||
$"publishedAfter={Storage.Registry.Values[lastCheckKey]}&" +
|
||||
$"lang={Storage.GetValue<string>(Storage.Settings.UILanguage)}&" +
|
||||
$"appVersion={Metrics.CurrentVersion}");
|
||||
|
||||
Storage.Registry.Values[lastCheckKey] = DateTime.UtcNow.Ticks;
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.NoContent)
|
||||
return;
|
||||
@@ -37,26 +46,6 @@ namespace FoxTube.Services
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<InboxItem[]> GetMessages()
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO: Add backend
|
||||
HttpResponseMessage response = await client.GetAsync($"https://xfox111.net/API/FoxTube/Inbox?lang={Settings.Language}¤tVersion={Metrics.CurrentVersion}");
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.NoContent)
|
||||
return new InboxItem[0];
|
||||
|
||||
return JsonConvert.DeserializeObject<InboxItem[]>(await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Metrics.SendReport(new Exception("Unable to retrieve inbox messages", e));
|
||||
|
||||
return new InboxItem[0];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires toast notification with the last changelog content
|
||||
/// </summary>
|
||||
@@ -65,9 +54,14 @@ namespace FoxTube.Services
|
||||
try
|
||||
{
|
||||
// TODO: Add backend
|
||||
Settings.LastReviewedVersion = Metrics.CurrentVersion;
|
||||
if ((string)Storage.Registry.Values[lastChangelogVersionKey] == Metrics.CurrentVersion)
|
||||
return;
|
||||
|
||||
HttpResponseMessage response = await client.GetAsync($"https://xfox111.net/API/FoxTube/Changelog?lang={Settings.Language}&version={Metrics.CurrentVersion}");
|
||||
Storage.Registry.Values[lastChangelogVersionKey] = Metrics.CurrentVersion;
|
||||
|
||||
HttpResponseMessage response = await client.GetAsync($"https://xfox111.net/API/FoxTube/Changelog?" +
|
||||
$"lang={Storage.GetValue<string>(Storage.Settings.UILanguage)}&" +
|
||||
$"version={Metrics.CurrentVersion}");
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.NoContent)
|
||||
return;
|
||||
@@ -16,7 +16,7 @@ namespace FoxTube.Services
|
||||
try
|
||||
{
|
||||
using HttpClient client = new HttpClient();
|
||||
string results = await client.GetStringAsync($"http://suggestqueries.google.com/complete/search?ds=yt&client=toolbar&q={term}&hl={Settings.RelevanceLanguage}");
|
||||
string results = await client.GetStringAsync($"http://suggestqueries.google.com/complete/search?ds=yt&client=toolbar&q={term}&hl={Storage.GetValue<string>(Storage.Settings.RelevanceLanguage)}");
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(results);
|
||||
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
using Windows.UI.Xaml;
|
||||
|
||||
namespace FoxTube.Services
|
||||
{
|
||||
public static class Storage
|
||||
{
|
||||
public static event EventHandler<Settings> SettingsChanged;
|
||||
|
||||
public static StorageFolder Folder => ApplicationData.Current.RoamingFolder;
|
||||
public static ApplicationDataContainer Registry { get; } = ApplicationData.Current.RoamingSettings;
|
||||
|
||||
private static readonly Dictionary<Settings, object> _defaultSettings = new Dictionary<Settings, object>
|
||||
{
|
||||
{ Settings.Theme, ElementTheme.Default },
|
||||
{ Settings.UILanguage, GetDefaultLanguage() },
|
||||
{ Settings.RelevanceLanguage, GetDefaultLanguage() },
|
||||
{ Settings.PromptFeedback, true },
|
||||
{ Settings.PromptReview, true },
|
||||
{ Settings.AllowAnalytics, true }
|
||||
};
|
||||
|
||||
public enum Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// ElementTheme
|
||||
/// </summary>
|
||||
Theme,
|
||||
/// <summary>
|
||||
/// string
|
||||
/// </summary>
|
||||
UILanguage,
|
||||
/// <summary>
|
||||
/// string
|
||||
/// </summary>
|
||||
RelevanceLanguage,
|
||||
/// <summary>
|
||||
/// string
|
||||
/// </summary>
|
||||
DefaultDownloadsFolder,
|
||||
/// <summary>
|
||||
/// bool
|
||||
/// </summary>
|
||||
PromptFeedback,
|
||||
/// <summary>
|
||||
/// bool
|
||||
/// </summary>
|
||||
PromptReview,
|
||||
/// <summary>
|
||||
/// bool
|
||||
/// </summary>
|
||||
AllowAnalytics,
|
||||
/// <summary>
|
||||
/// string
|
||||
/// </summary>
|
||||
Region
|
||||
}
|
||||
|
||||
public enum Metrics
|
||||
{
|
||||
/// <summary>
|
||||
/// TimeSpan
|
||||
/// </summary>
|
||||
Uptime
|
||||
}
|
||||
|
||||
|
||||
public static void SetValue(Settings key, object value)
|
||||
{
|
||||
Registry.Values[$"{key.GetType().Name}.{key}"] = value;
|
||||
SettingsChanged?.Invoke(value, key);
|
||||
}
|
||||
public static void SetValue(Metrics key, object value) =>
|
||||
Registry.Values[$"{key.GetType().Name}.{key}"] = value;
|
||||
|
||||
public static T GetValue<T>(Settings key) =>
|
||||
(T)(Registry.Values[$"{key.GetType().Name}.{key}"] ?? (_defaultSettings.ContainsKey(key) ? _defaultSettings[key] : null));
|
||||
public static T GetValue<T>(Metrics key) =>
|
||||
(T)Registry.Values[$"{key.GetType().Name}.{key}"];
|
||||
|
||||
|
||||
private static string GetDefaultLanguage()
|
||||
{
|
||||
if (CultureInfo.InstalledUICulture.TwoLetterISOLanguageName.Belongs("ua", "ru", "by", "kz", "kg", "md", "lv", "ee")) //Languages for Russian-speaking countries
|
||||
return "ru-RU";
|
||||
else
|
||||
return "en-US";
|
||||
}
|
||||
|
||||
public static async Task ResetStorage()
|
||||
{
|
||||
Registry.Values.Clear();
|
||||
foreach (IStorageItem i in await Folder.GetItemsAsync())
|
||||
await i.DeleteAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,25 +14,24 @@ using FoxTube.Utils;
|
||||
using YoutubeExplode;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Windows.Storage;
|
||||
using Google.Apis.Oauth2.v2.Data;
|
||||
|
||||
namespace FoxTube
|
||||
namespace FoxTube.Services
|
||||
{
|
||||
public static class UserManagement
|
||||
public static class UserService
|
||||
{
|
||||
public const string UsersStorageKey = "UserService.Users";
|
||||
public const string LastUserInfoKey = "UserService.LastUser";
|
||||
|
||||
public const int MaxUsersCount = 1;
|
||||
|
||||
#region Private members
|
||||
private static readonly ApplicationDataContainer storage = ApplicationData.Current.LocalSettings;
|
||||
|
||||
private static readonly ExtendedYouTubeService _defaultService = new ExtendedYouTubeService(new Google.Apis.Services.BaseClientService.Initializer
|
||||
{
|
||||
ApplicationName = "FoxTube",
|
||||
ApiKey = "AIzaSyBgHrCnrlzlVmk0cJKL8RqP9Y8x6XSuk_0",
|
||||
//ApiKey = "AIzaSyD7tpbuvmYDv9h4udo9L_g3r0sLPFAnN00"
|
||||
ApiKey = SecretConstants.YoutubeApiKey, // TODO: Replace with an actual API key
|
||||
});
|
||||
private static readonly YoutubeClient _defaultYteClient = new YoutubeClient();
|
||||
private static readonly YoutubeClient _defaultYtClient = new YoutubeClient();
|
||||
|
||||
private static string[] Scopes { get; } = new string[]
|
||||
{
|
||||
@@ -41,14 +40,7 @@ namespace FoxTube
|
||||
YouTubeService.Scope.YoutubeForceSsl
|
||||
};
|
||||
|
||||
private static ClientSecrets[] ClientSecrets { get; } = new ClientSecrets[MaxUsersCount]
|
||||
{
|
||||
new ClientSecrets
|
||||
{
|
||||
ClientId = "349735264870-2ekqlm0a4mkg3mmrfcv90s3qp3o15dq0.apps.googleusercontent.com",
|
||||
ClientSecret = "BkVZOAaCU2Zclf0Zlicg6y2_"
|
||||
}
|
||||
};
|
||||
private static ClientSecrets[] ClientSecrets { get; } = SecretConstants.ClientSecrets;
|
||||
#endregion
|
||||
|
||||
public static Userinfoplus[] Users { get; private set; } = new Userinfoplus[MaxUsersCount];
|
||||
@@ -58,12 +50,33 @@ namespace FoxTube
|
||||
public static bool CanAddAccounts => Users.Any(i => i == null);
|
||||
public static User CurrentUser { get; set; }
|
||||
public static bool Authorized => CurrentUser != null;
|
||||
public static ExtendedYouTubeService Service => IncognitoMode ? _defaultService : (CurrentUser?.Service ?? _defaultService);
|
||||
public static YoutubeClient YoutubeClient => IncognitoMode ? _defaultYteClient : (CurrentUser?.Client ?? _defaultYteClient);
|
||||
public static ExtendedYouTubeService Service
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IncognitoMode || CurrentUser == null)
|
||||
return _defaultService;
|
||||
else
|
||||
return CurrentUser.Service;
|
||||
}
|
||||
}
|
||||
public static YoutubeClient YouTubeClient
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IncognitoMode || CurrentUser == null)
|
||||
return _defaultYtClient;
|
||||
else
|
||||
return CurrentUser.Client;
|
||||
}
|
||||
}
|
||||
|
||||
public static event EventHandler<bool> UserStateUpdated;
|
||||
public static event EventHandler<Subscription> SubscriptionsChanged;
|
||||
|
||||
static UserService() =>
|
||||
Initialize();
|
||||
|
||||
public static async Task<bool> AddUser()
|
||||
{
|
||||
int queueIndex = Users.ToList().FindIndex(i => i == null);
|
||||
@@ -100,14 +113,14 @@ namespace FoxTube
|
||||
("Error details", result.ResponseErrorDetail.ToString()));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static async Task Initialize()
|
||||
public static async void Initialize()
|
||||
{
|
||||
Users = JsonConvert.DeserializeObject<Userinfoplus[]>(storage.Values["UserManagement.Users"] as string ?? "") ?? new Userinfoplus[MaxUsersCount];
|
||||
int? lastUserIndex = storage.Values["UserManagement.LastUser"] as int?;
|
||||
Users = JsonConvert.DeserializeObject<Userinfoplus[]>(Storage.Registry.Values[UsersStorageKey] as string ?? "") ?? new Userinfoplus[MaxUsersCount];
|
||||
int? lastUserIndex = Storage.Registry.Values[LastUserInfoKey] as int?;
|
||||
|
||||
if (lastUserIndex.HasValue && Users[lastUserIndex.Value] != null ||
|
||||
(lastUserIndex = Users.ToList().FindIndex(i => i != null)) > -1)
|
||||
@@ -133,12 +146,12 @@ namespace FoxTube
|
||||
|
||||
await CurrentUser.Credential.RevokeTokenAsync(CancellationToken.None);
|
||||
|
||||
storage.Values.Remove($"Subscriptions.{CurrentUser.UserInfo.Id}");
|
||||
Storage.Registry.Values.Remove($"Subscriptions.{CurrentUser.UserInfo.Id}");
|
||||
CurrentUser = null;
|
||||
Users[Users.ToList().FindIndex(i => i.Id == userId)] = null;
|
||||
|
||||
storage.Values["UserManagement.Users"] = JsonConvert.SerializeObject(Users);
|
||||
storage.Values["UserManagement.LastUser"] = null;
|
||||
Storage.Registry.Values[UsersStorageKey] = JsonConvert.SerializeObject(Users);
|
||||
Storage.Registry.Values[LastUserInfoKey] = null;
|
||||
|
||||
if (Users.Any(i => i != null))
|
||||
await SwitchUser(Users.ToList().FindIndex(i => i != null));
|
||||
@@ -189,8 +202,8 @@ namespace FoxTube
|
||||
CurrentUser = await User.GetUser(credential);
|
||||
Users[userIndex] = CurrentUser.UserInfo;
|
||||
|
||||
storage.Values["UserManagement.Users"] = JsonConvert.SerializeObject(Users);
|
||||
storage.Values["UserManagement.LastUser"] = userIndex;
|
||||
Storage.Registry.Values[UsersStorageKey] = JsonConvert.SerializeObject(Users);
|
||||
Storage.Registry.Values[LastUserInfoKey] = userIndex;
|
||||
|
||||
credential.RefreshTokenUpdated += (s, e) => UpdateToken(CurrentUser.UserInfo.Id, credential.Token.RefreshToken);
|
||||
UpdateToken(CurrentUser.UserInfo.Id, credential.Token.RefreshToken);
|
||||
@@ -1,142 +0,0 @@
|
||||
using FoxTube.Utils;
|
||||
using System.Globalization;
|
||||
using Windows.Storage;
|
||||
|
||||
namespace FoxTube
|
||||
{
|
||||
public static class Settings
|
||||
{
|
||||
static readonly ApplicationDataContainer settings = ApplicationData.Current.RoamingSettings;
|
||||
|
||||
public static string DefaultDownloadsFolder
|
||||
{
|
||||
get => (string)settings.Values["DefaultDownloadsFolder"] ?? "";
|
||||
set => settings.Values["DefaultDownloadsFolder"] = value;
|
||||
}
|
||||
public static bool AskBeforeDownloading
|
||||
{
|
||||
get => (bool?)settings.Values["AskBeforeDownloading"] ?? true;
|
||||
set => settings.Values["AskBeforeDownloading"] = value;
|
||||
}
|
||||
public static bool AllowAnalytics
|
||||
{
|
||||
get => (bool?)settings.Values["AllowAnalytics"] ?? true;
|
||||
set => settings.Values["AllowAnalytics"] = value;
|
||||
}
|
||||
public static string DesiredVideoQuality
|
||||
{
|
||||
get => (string)settings.Values["DesiredVideoQuality"] ?? "auto";
|
||||
set => settings.Values["DesiredVideoQuality"] = value;
|
||||
}
|
||||
public static string RememberedQuality
|
||||
{
|
||||
get => (string)settings.Values["RememberedVideoQuality"] ?? "1080p";
|
||||
set => settings.Values["RememberedVideoQuality"] = value;
|
||||
}
|
||||
public static bool VideoNotifications
|
||||
{
|
||||
get => (bool?)settings.Values["NewVideosNotificationsAll"] ?? true;
|
||||
set => settings.Values["NewVideosNotificationsAll"] = value;
|
||||
}
|
||||
public static bool DevNotifications
|
||||
{
|
||||
get => (bool?)settings.Values["DevelopersNewsNotifications"] ?? true;
|
||||
set => settings.Values["DevelopersNewsNotifications"] = value;
|
||||
}
|
||||
public static bool CheckConnection
|
||||
{
|
||||
get => (bool?)settings.Values["WarnIfOnMeteredConnection"] ?? false;
|
||||
set => settings.Values["WarnIfOnMeteredConnection"] = value;
|
||||
}
|
||||
public static bool Autoplay
|
||||
{
|
||||
get => (bool?)settings.Values["VideoAutoplay"] ?? true;
|
||||
set => settings.Values["VideoAutoplay"] = value;
|
||||
}
|
||||
public static double Volume
|
||||
{
|
||||
get => (double?)settings.Values["Volume"] ?? 1;
|
||||
set => settings.Values["Volume"] = value;
|
||||
}
|
||||
public static string Language
|
||||
{
|
||||
get => (string)settings.Values["InterfaceLanguage"] ?? GetDefaultLanguage();
|
||||
set => settings.Values["InterfaceLanguage"] = value;
|
||||
}
|
||||
public static string RelevanceLanguage
|
||||
{
|
||||
get => (string)settings.Values["DesiredContentLanguage"] ?? CultureInfo.InstalledUICulture.TwoLetterISOLanguageName;
|
||||
set => settings.Values["DesiredContentLanguage"] = value;
|
||||
}
|
||||
public static string Region
|
||||
{
|
||||
get => (string)settings.Values["Region"] ?? CultureInfo.InstalledUICulture.Name.Split('-')[1];
|
||||
set => settings.Values["Region"] = value;
|
||||
}
|
||||
public static int SafeSearch
|
||||
{
|
||||
get => (int?)settings.Values["SafeSearch"] ?? 0; // Moderate
|
||||
set => settings.Values["SafeSearch"] = value;
|
||||
}
|
||||
public static int DefaultHomeTab
|
||||
{
|
||||
get => (int?)settings.Values["DefaultHomeTab"] ?? 0; // Recommendations
|
||||
set => settings.Values["DefaultHomeTab"] = value;
|
||||
}
|
||||
public static bool BlockExplicitContent
|
||||
{
|
||||
get => (bool?)settings.Values["BlockExplicitContent"] ?? true;
|
||||
set => settings.Values["BlockExplicitContent"] = value;
|
||||
}
|
||||
|
||||
public static bool HasAccount
|
||||
{
|
||||
get => (bool?)settings.Values["HasAccount"] ?? false;
|
||||
set => settings.Values["HasAccount"] = value;
|
||||
}
|
||||
public static int Theme
|
||||
{
|
||||
get => (int?)settings.Values["PreferedUITheme"] ?? 2; // System
|
||||
set => settings.Values["PreferedUITheme"] = value;
|
||||
}
|
||||
public static bool PromptReview
|
||||
{
|
||||
get => (bool?)settings.Values["PromptReview"] ?? Metrics.Uptime.TotalHours > 24;
|
||||
set => settings.Values["PromptReview"] = value;
|
||||
}
|
||||
public static bool PromptFeedback
|
||||
{
|
||||
get => (bool?)settings.Values["PromptFeedback"] ?? Metrics.Uptime.TotalHours > 12;
|
||||
set => settings.Values["PromptFeedback"] = value;
|
||||
}
|
||||
public static bool ProcessClipboard
|
||||
{
|
||||
get => (bool?)settings.Values["ProcessClipboardEntry"] ?? true;
|
||||
set => settings.Values["ProcessClipboardEntry"] = value;
|
||||
}
|
||||
public static string LastReviewedVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
if (settings.Values["LastReviewedVersion"] == null)
|
||||
settings.Values["LastReviewedVersion"] = Metrics.CurrentVersion;
|
||||
return (string)settings.Values["LastReviewedVersion"];
|
||||
}
|
||||
set => settings.Values["LastReviewedVersion"] = value;
|
||||
}
|
||||
|
||||
static string GetDefaultLanguage()
|
||||
{
|
||||
if (CultureInfo.InstalledUICulture.TwoLetterISOLanguageName.Belongs("ua", "ru", "by", "kz", "kg", "md", "lv", "ee")) //Languages for Russian-speaking countries
|
||||
return "ru-RU";
|
||||
else
|
||||
return "en-US";
|
||||
}
|
||||
|
||||
public static void ResetSettings()
|
||||
{
|
||||
settings.Values.Clear();
|
||||
ApplicationData.Current.LocalSettings.Values.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,27 @@
|
||||
using Microsoft.AppCenter.Crashes;
|
||||
using Microsoft.Advertising.WinRT.UI;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Services.Store;
|
||||
|
||||
namespace FoxTube.Utils
|
||||
{
|
||||
public static class StoreInterop
|
||||
public static class AddonsInterop
|
||||
{
|
||||
public static bool AdsDisabled { get; private set; } = true;
|
||||
public static string Price { get; private set; }
|
||||
|
||||
private const bool UseTestAds = true;
|
||||
|
||||
private static bool UseTestAds => true;
|
||||
public static string ApplicationId => UseTestAds ? "d25517cb-12d4-4699-8bdc-52040c712cab" : SecretConstants.ApplicationProductId;
|
||||
public static string AdsId => UseTestAds ? "test" : SecretConstants.AdsUnitId;
|
||||
private const string ProProductId = SecretConstants.ProAddonId;
|
||||
|
||||
public static string ApplicationId => UseTestAds ? "d25517cb-12d4-4699-8bdc-52040c712cab" : "9ncqqxjtdlfh";
|
||||
public static string AdsId => UseTestAds ? "test" : "1100044398";
|
||||
private static string ProProductId => "9NP1QK556625";
|
||||
public static NativeAdsManagerV2 AdsManager => new NativeAdsManagerV2(ApplicationId, AdsId);
|
||||
|
||||
public static async Task UpdateStoreState()
|
||||
static AddonsInterop() =>
|
||||
UpdateStoreState();
|
||||
|
||||
public static async void UpdateStoreState()
|
||||
{
|
||||
StoreProductQueryResult requset = await StoreContext.GetDefault().GetAssociatedStoreProductsAsync(new[] { "Durable" });
|
||||
|
||||
@@ -42,17 +46,5 @@ namespace FoxTube.Utils
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static async void RequestReview()
|
||||
{
|
||||
StoreRateAndReviewResult result = await StoreContext.GetDefault().RequestRateAndReviewAppAsync();
|
||||
|
||||
if (result.Status == StoreRateAndReviewStatus.Error)
|
||||
Metrics.SendReport(result.ExtendedError, new[] { ErrorAttachmentLog.AttachmentWithText(result.ExtendedJsonData, "extendedJsonData.json") },
|
||||
("Status", result.Status.ToString()),
|
||||
("WasReviewUpdated", result.WasUpdated.ToString()));
|
||||
|
||||
Metrics.AddEvent("Store review request has been recieved");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
using System;
|
||||
using FoxTube.Services;
|
||||
using Microsoft.AppCenter.Crashes;
|
||||
using Microsoft.Services.Store.Engagement;
|
||||
using Windows.System;
|
||||
using Windows.Services.Store;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace FoxTube.Utils
|
||||
{
|
||||
public static class Feedback
|
||||
public static class FeedbackInterop
|
||||
{
|
||||
public static bool HasFeedbackHub => StoreServicesFeedbackLauncher.IsSupported();
|
||||
|
||||
@@ -13,15 +15,25 @@ namespace FoxTube.Utils
|
||||
{
|
||||
if (HasFeedbackHub)
|
||||
await StoreServicesFeedbackLauncher.GetDefault().LaunchAsync();
|
||||
else
|
||||
await Launcher.LaunchUriAsync("mailto:feedback@xfox111.net".ToUri());
|
||||
}
|
||||
|
||||
public static async void RequestStoreReview()
|
||||
{
|
||||
StoreRateAndReviewResult result = await StoreContext.GetDefault().RequestRateAndReviewAppAsync();
|
||||
|
||||
if (result.Status == StoreRateAndReviewStatus.Error)
|
||||
Metrics.SendReport(result.ExtendedError, new[] { ErrorAttachmentLog.AttachmentWithText(result.ExtendedJsonData, "extendedJsonData.json") },
|
||||
("Status", result.Status.ToString()),
|
||||
("WasReviewUpdated", result.WasUpdated.ToString()));
|
||||
|
||||
Metrics.AddEvent("Store review request has been received");
|
||||
}
|
||||
|
||||
public static async void PromptFeedback()
|
||||
{
|
||||
if (!HasFeedbackHub)
|
||||
{
|
||||
Settings.PromptFeedback = false;
|
||||
Storage.SetValue(Storage.Settings.PromptFeedback, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -41,7 +53,7 @@ namespace FoxTube.Utils
|
||||
ContentDialogResult result = await dialog.ShowAsync();
|
||||
|
||||
if (result != ContentDialogResult.None)
|
||||
Settings.PromptFeedback = false;
|
||||
Storage.SetValue(Storage.Settings.PromptFeedback, false);
|
||||
|
||||
if (result == ContentDialogResult.Primary)
|
||||
OpenFeedbackHub();
|
||||
@@ -61,17 +73,17 @@ namespace FoxTube.Utils
|
||||
|
||||
Content = new TextBlock
|
||||
{
|
||||
Text = "Could you leave a feedback on Microsfot Store page? It's very important for me :)"
|
||||
Text = "Could you leave a feedback on Microsoft Store page? It's very important for me :)"
|
||||
}
|
||||
};
|
||||
|
||||
ContentDialogResult result = await dialog.ShowAsync();
|
||||
|
||||
if (result != ContentDialogResult.None)
|
||||
Settings.PromptReview = false;
|
||||
Storage.SetValue(Storage.Settings.PromptReview, false);
|
||||
|
||||
if (result == ContentDialogResult.Primary)
|
||||
StoreInterop.RequestReview();
|
||||
RequestStoreReview();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,19 +6,17 @@ using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.Storage;
|
||||
using FoxTube.Services;
|
||||
|
||||
namespace FoxTube.Utils
|
||||
{
|
||||
public static class Metrics
|
||||
{
|
||||
static readonly ApplicationDataContainer storage = ApplicationData.Current.RoamingSettings;
|
||||
|
||||
static readonly Stopwatch sw = new Stopwatch();
|
||||
public static TimeSpan Uptime
|
||||
{
|
||||
get => (TimeSpan?)storage.Values["Metrics.SpentTime"] ?? TimeSpan.FromSeconds(0);
|
||||
set => storage.Values["Metrics.SpentTime"] = value;
|
||||
get => Storage.GetValue<TimeSpan?>(Storage.Metrics.Uptime) ?? TimeSpan.FromSeconds(0);
|
||||
set => Storage.SetValue(Storage.Metrics.Uptime, value);
|
||||
}
|
||||
public static string CurrentVersion
|
||||
{
|
||||
@@ -32,11 +30,11 @@ namespace FoxTube.Utils
|
||||
static Metrics()
|
||||
{
|
||||
sw.Start();
|
||||
if (!Settings.AllowAnalytics)
|
||||
if (!Storage.GetValue<bool>(Storage.Settings.AllowAnalytics))
|
||||
return;
|
||||
|
||||
AppCenter.Start("45774462-9ea7-438a-96fc-03982666f39e", typeof(Analytics), typeof(Crashes));
|
||||
AppCenter.SetCountryCode(Settings.Region);
|
||||
AppCenter.Start(SecretConstants.MetricsId, typeof(Analytics), typeof(Crashes));
|
||||
AppCenter.SetCountryCode(Storage.GetValue<string>(Storage.Settings.Region));
|
||||
AppCenter.LogLevel = LogLevel.Verbose;
|
||||
}
|
||||
|
||||
@@ -45,23 +43,30 @@ namespace FoxTube.Utils
|
||||
sw.Stop();
|
||||
Uptime += sw.Elapsed;
|
||||
|
||||
AddEvent("Session closed",
|
||||
("Duration", sw.Elapsed.ToString()),
|
||||
("Spend time total", Uptime.ToString()));
|
||||
if (Storage.GetValue<bool>(Storage.Settings.AllowAnalytics))
|
||||
AddEvent("Session closed",
|
||||
("Duration", sw.Elapsed.ToString()),
|
||||
("Spend time total", Uptime.ToString()));
|
||||
}
|
||||
|
||||
public static void AddEvent(string eventName, params (string key, string value)[] details) =>
|
||||
Analytics.TrackEvent(eventName,
|
||||
details.Length < 1 ? null :
|
||||
details.Select(i => new KeyValuePair<string, string>(i.key, i.value)) as Dictionary<string, string>);
|
||||
public static void AddEvent(string eventName, params (string key, string value)[] details)
|
||||
{
|
||||
if (Storage.GetValue<bool>(Storage.Settings.AllowAnalytics))
|
||||
Analytics.TrackEvent(eventName,
|
||||
details.Length < 1 ? null :
|
||||
details.Select(i => new KeyValuePair<string, string>(i.key, i.value)) as Dictionary<string, string>);
|
||||
}
|
||||
|
||||
public static void SendReport(Exception exception, ErrorAttachmentLog[] logs = null, params (string key, string value)[] details)
|
||||
{
|
||||
logs ??= new ErrorAttachmentLog[0];
|
||||
Crashes.TrackError(exception,
|
||||
details.Length < 1 ? null :
|
||||
details.Select(i => new KeyValuePair<string, string>(i.key, i.value)) as Dictionary<string, string>,
|
||||
logs);
|
||||
if (Storage.GetValue<bool>(Storage.Settings.AllowAnalytics))
|
||||
{
|
||||
logs ??= new ErrorAttachmentLog[0];
|
||||
Crashes.TrackError(exception ?? new Exception("Unknown exception"),
|
||||
details.Length < 1 ? null :
|
||||
details.Select(i => new KeyValuePair<string, string>(i.key, i.value)) as Dictionary<string, string>,
|
||||
logs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using Google.Apis.Auth.OAuth2;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using FoxTube.Services;
|
||||
|
||||
namespace FoxTube.Utils
|
||||
{
|
||||
public static class SecretConstants
|
||||
{
|
||||
public const string YoutubeApiKey = "AIzaSyBgHrCnrlzlVmk0cJKL8RqP9Y8x6XSuk_0";
|
||||
public const string MetricsId = "45774462-9ea7-438a-96fc-03982666f39e";
|
||||
public const string ProAddonId = "9NP1QK556625";
|
||||
public const string AdsUnitId = "1100044398";
|
||||
public const string ApplicationProductId = "9ncqqxjtdlfh";
|
||||
|
||||
public static ClientSecrets[] ClientSecrets { get; } = new ClientSecrets[UserService.MaxUsersCount]
|
||||
{
|
||||
// TODO: Replace with actual secrets
|
||||
new ClientSecrets
|
||||
{
|
||||
ClientId = "349735264870-2ekqlm0a4mkg3mmrfcv90s3qp3o15dq0.apps.googleusercontent.com",
|
||||
ClientSecret = "BkVZOAaCU2Zclf0Zlicg6y2_"
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using FoxTube.Services;
|
||||
using System;
|
||||
using Windows.ApplicationModel.Core;
|
||||
using Windows.Security.Credentials;
|
||||
|
||||
@@ -25,10 +26,10 @@ namespace FoxTube.Utils
|
||||
public static async void RestartApp(string args) =>
|
||||
await CoreApplication.RequestRestartAsync(args ?? "");
|
||||
|
||||
public static void InitializeFailsafeProtocol()
|
||||
public static async void InitializeFailsafeProtocol()
|
||||
{
|
||||
Metrics.AddEvent("Failsafe protocol initiated");
|
||||
Settings.ResetSettings();
|
||||
await Storage.ResetStorage();
|
||||
PasswordVault passwordVault = new PasswordVault();
|
||||
foreach (PasswordCredential credential in passwordVault.RetrieveAll())
|
||||
passwordVault.Remove(credential);
|
||||
|
||||
Reference in New Issue
Block a user