From e2c717402b9533359c936abe40f82cb2729a689f Mon Sep 17 00:00:00 2001 From: SunboX Date: Fri, 26 May 2017 22:04:45 +0200 Subject: [PATCH] finally got it working stable --- NextcloudApp.sln | 4 +- NextcloudApp/App.xaml.cs | 843 +++++++++++++------------ NextcloudApp/NextcloudApp.csproj | 7 + NextcloudApp/Package.appxmanifest | 14 +- NextcloudApp/ShareTarget.xaml | 19 + NextcloudApp/ShareTarget.xaml.cs | 30 + NextcloudApp/Strings/en/Resources.resw | 3 + 7 files changed, 491 insertions(+), 429 deletions(-) create mode 100644 NextcloudApp/ShareTarget.xaml create mode 100644 NextcloudApp/ShareTarget.xaml.cs diff --git a/NextcloudApp.sln b/NextcloudApp.sln index 2ebe1b4..97afbac 100644 --- a/NextcloudApp.sln +++ b/NextcloudApp.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.6 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NextcloudApp", "NextcloudApp\NextcloudApp.csproj", "{99EFB7EA-88A3-4FCF-9289-22734215B5CF}" EndProject diff --git a/NextcloudApp/App.xaml.cs b/NextcloudApp/App.xaml.cs index f06d47d..4e67a55 100644 --- a/NextcloudApp/App.xaml.cs +++ b/NextcloudApp/App.xaml.cs @@ -1,421 +1,424 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Windows.ApplicationModel; -using Microsoft.Practices.Unity; -using Prism.Unity.Windows; -using Prism.Windows.AppModel; -using Windows.ApplicationModel.Activation; -using Windows.ApplicationModel.Resources; -using Windows.Security.Credentials; -using Windows.Storage.AccessCache; -using Windows.UI.Xaml; -using Windows.UI.Xaml.Controls; -using Newtonsoft.Json; -using NextcloudApp.Models; -using NextcloudApp.Services; -using NextcloudApp.Utils; -using NextcloudClient.Exceptions; -using NextcloudClient.Types; -using Prism.Windows.Mvvm; -using Microsoft.QueryStringDotNET; -using Windows.UI.Notifications; -using Windows.Foundation.Collections; -using Windows.System; -using Windows.ApplicationModel.DataTransfer; -using Windows.Storage; - -namespace NextcloudApp -{ - /// - /// Provides application-specific behavior to supplement the default Application class. - /// - sealed partial class App : PrismUnityApplication - { - /// - /// Initializes the singleton application object. This is the first line of authored code - /// executed, and as such is the logical equivalent of main() or WinMain(). - /// - public App() - { - UnhandledException += OnUnhandledException; - TaskScheduler.UnobservedTaskException += TaskSchedulerOnUnobservedTaskException; - InitializeComponent(); - } - - public IActivatedEventArgs ActivatedEventArgs { get; private set; } - - private async void TaskSchedulerOnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs args) - { - var exceptionStackTrace = args.Exception.StackTrace; - var - exceptionHashCode = string.IsNullOrEmpty(exceptionStackTrace) - ? args.Exception.GetHashCode().ToString() - : exceptionStackTrace.GetHashCode().ToString(); - await - ExceptionReportService.Handle(args.Exception.GetType().ToString(), args.Exception.Message, - exceptionStackTrace, args.Exception.InnerException.GetType().ToString(), exceptionHashCode); - } - - private async void OnUnhandledException(object sender, UnhandledExceptionEventArgs args) - { - var exceptionStackTrace = string.Empty; - try - { - exceptionStackTrace = args.Exception.StackTrace + ""; - } - // ReSharper disable once EmptyGeneralCatchClause - catch { } - var exceptionMessage = args.Message; - var exceptionType = string.Empty; - var innerExceptionType = string.Empty; - var exceptionHashCode = string.Empty; - if (args.Exception != null) - { - // Tasks will throw a canceled exception if they get canceled - // We don't care, but avoid closing the app - if (args.Exception.GetType() == typeof(TaskCanceledException)) - { - args.Handled = true; - return; - } - if (args.Exception.GetType() == typeof(OperationCanceledException)) - { - args.Handled = true; - return; - } - if (args.Exception.GetType() == typeof(FileNotFoundException)) - { - args.Handled = true; - return; - } - // Temporary Workaround for WP10 - if (args.Exception.GetType() == typeof(ArgumentException)) - { - args.Handled = true; - return; - } - if (args.Exception.GetType() == typeof(ResponseError)) - { - args.Handled = true; - ResponseErrorHandlerService.HandleException((ResponseError)args.Exception); - return; - } - // 0x8000000B, E_BOUNDS, System.Exception, OutOfBoundsException - if ((uint)args.Exception.HResult == 0x80004004) - { - args.Handled = true; - return; - } - // 0x80072EE7, ERROR_WINHTTP_NAME_NOT_RESOLVED, The server name or address could not be resolved - if ((uint)args.Exception.HResult == 0x80072EE7) - { - args.Handled = true; - var resourceLoader = Container.Resolve(); - var dialogService = Container.Resolve(); - var dialog = new ContentDialog - { - Title = resourceLoader.GetString("AnErrorHasOccurred"), - Content = new TextBlock - { - Text = resourceLoader.GetString("ServerNameOrAddressCouldNotBeResolved"), - TextWrapping = TextWrapping.WrapWholeWords, - Margin = new Thickness(0, 20, 0, 0) - }, - PrimaryButtonText = resourceLoader.GetString("OK") - }; - await dialogService.ShowAsync(dialog); - return; - } - exceptionType = args.Exception.GetType().ToString(); - if (args.Exception.InnerException != null) - { - innerExceptionType = args.Exception.InnerException.GetType().ToString(); - } - exceptionHashCode = string.IsNullOrEmpty(exceptionStackTrace) - ? args.Exception.GetHashCode().ToString() - : exceptionStackTrace.GetHashCode().ToString(); - } - if (args.Handled) - { - return; - } - args.Handled = true; - await - ExceptionReportService.Handle(exceptionType, exceptionMessage, exceptionStackTrace, - innerExceptionType, exceptionHashCode); - } - - protected override UIElement CreateShell(Frame rootFrame) - { - var shell = Container.Resolve(); - shell.SetContentFrame(rootFrame); - return shell; - } - - protected override void OnShareTargetActivated(ShareTargetActivatedEventArgs args) - { - base.OnShareTargetActivated(args); - - OnShareTargetActivatedsyncAsync(args); - } - - private async Task OnShareTargetActivatedsyncAsync(ShareTargetActivatedEventArgs args) - { - var fileTokens = new List(); - var sorageItems = await args.ShareOperation.Data.GetStorageItemsAsync(); - StorageApplicationPermissions.FutureAccessList.Clear(); - foreach (var storageItem in sorageItems) - { - if (storageItem.IsOfType(StorageItemTypes.File)) - { - var token = StorageApplicationPermissions.FutureAccessList.Add(storageItem); - fileTokens.Add(token); - } - } - args.ShareOperation.ReportDataRetrieved(); - - var options = new LauncherOptions() - { - TargetApplicationPackageFamilyName = Package.Current.Id.FamilyName - }; - - ValueSet inputData = new ValueSet - { - { "FileTokens", fileTokens.ToArray() } - }; - Uri uri = new Uri("nextcloud:///share"); - await Launcher.LaunchUriAsync(uri, options, inputData); - - args.ShareOperation.ReportCompleted(); - } - - //TODO: Find out, why this is not working on WP10 - //SEE: https://github.com/nextcloud/windows-universal/issues/32 - //protected override void OnFileSavePickerActivated(FileSavePickerActivatedEventArgs args) - //{ - // base.OnFileSavePickerActivated(args); - // OnActivated(args); - //} - //protected override void OnCachedFileUpdaterActivated(CachedFileUpdaterActivatedEventArgs args) - //{ - // base.OnCachedFileUpdaterActivated(args); - // OnActivated(args); - //} - - protected override void OnFileActivated(FileActivatedEventArgs args) - { - base.OnFileActivated(args); - OnActivated(args); - } - - protected override async Task OnActivateApplicationAsync(IActivatedEventArgs args) - { - ActivatedEventArgs = args; - await base.OnActivateApplicationAsync(args); - - // Remove unnecessary notifications whenever the app is used. - ToastNotificationManager.History.RemoveGroup(ToastNotificationService.SYNCACTION); - - // Handle toast activation - if (args is ToastNotificationActivatedEventArgs) - { - var toastActivationArgs = args as ToastNotificationActivatedEventArgs; - // Parse the query string - QueryString query = QueryString.Parse(toastActivationArgs.Argument); - // See what action is being requested - switch (query["action"]) - { - // Nothing to do here - case ToastNotificationService.SYNCACTION: - NavigationService.Navigate(PageToken.DirectoryList.ToString(), null); - break; - // Open Conflict Page - case ToastNotificationService.SYNCONFLICTACTION: - ToastNotificationManager.History.RemoveGroup(ToastNotificationService.SYNCONFLICTACTION); - NavigationService.Navigate(PageToken.SyncConflict.ToString(), null); - break; - } - } - else if (args.Kind == ActivationKind.Protocol) - { - var protocolArgs = args as ProtocolActivatedEventArgs; - - if (protocolArgs.Uri.AbsolutePath == "/share") - { - var pageParameters = new ShareTargetPageParameters() - { - ActivationKind = ActivationKind.ShareTarget, - FileTokens = new List() - }; - - if (protocolArgs.Data.ContainsKey("FileTokens")) - { - foreach (var token in protocolArgs.Data["FileTokens"] as string[]) - { - pageParameters.FileTokens.Add(token); - } - } - - CheckSettingsAndContinue(PageToken.ShareTarget, pageParameters); - } - } - else if (args.Kind == ActivationKind.FileSavePicker || args.Kind == ActivationKind.CachedFileUpdater) - { - CheckSettingsAndContinue(PageToken.FileSavePicker, null); - } - else if (args.Kind == ActivationKind.File) - { - if (args is FileActivatedEventArgs activatedEventArgs) - { - var sorageItems = activatedEventArgs.Files; - var pageParameters = new ShareTargetPageParameters() - { - //ShareOperation = activatedEventArgs.ShareOperation, - ActivationKind = ActivationKind.ShareTarget, - FileTokens = new List() - }; - StorageApplicationPermissions.FutureAccessList.Clear(); - foreach (var storageItem in sorageItems) - { - var token = StorageApplicationPermissions.FutureAccessList.Add(storageItem); - pageParameters.FileTokens.Add(token); - } - CheckSettingsAndContinue(PageToken.ShareTarget, pageParameters); - } - } - } - - protected override Task OnSuspendingApplicationAsync() - { - var task = base.OnSuspendingApplicationAsync(); - // Stop Background Sync Tasks - List activeSyncs = SyncDbUtils.GetActiveSyncInfos(); - foreach (var fsi in activeSyncs) - { - ToastNotificationService.ShowSyncSuspendedNotification(fsi); - SyncDbUtils.UnlockFolderSyncInfo(fsi); - } - return task; - } - - protected override Task OnInitializeAsync(IActivatedEventArgs args) - { - Container.RegisterInstance(new DialogService()); - Container.RegisterInstance(new ResourceLoaderAdapter(new ResourceLoader())); - var task = base.OnInitializeAsync(args); - DeviceGestureService.GoBackRequested += DeviceGestureServiceOnGoBackRequested; - // Just count total app starts - SettingsService.Instance.LocalSettings.AppTotalRuns = SettingsService.Instance.LocalSettings.AppTotalRuns + 1; - // Count app starts after last update - var currentVersion = - $"{Package.Current.Id.Version.Major}.{Package.Current.Id.Version.Minor}.{Package.Current.Id.Version.Build}.{Package.Current.Id.Version.Revision}"; - if (currentVersion == SettingsService.Instance.LocalSettings.AppRunsAfterLastUpdateVersion) - { - SettingsService.Instance.LocalSettings.AppRunsAfterLastUpdate = SettingsService.Instance.LocalSettings.AppRunsAfterLastUpdate + 1; - } - else - { - SettingsService.Instance.LocalSettings.AppRunsAfterLastUpdateVersion = currentVersion; - SettingsService.Instance.LocalSettings.AppRunsAfterLastUpdate = 1; - SettingsService.Instance.LocalSettings.ShowUpdateMessage = true; - } - MigrationService.Instance.StartMigration(); - return task; - } - - protected override Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args) - { - // Ensure the current window is active - Window.Current.Activate(); - // Remove unnecessary notifications whenever the app is used. - ToastNotificationManager.History.RemoveGroup(ToastNotificationService.SYNCACTION); - PinStartPageParameters pageParameters = null; - if (!string.IsNullOrEmpty(args?.Arguments)) - { - var tmpResourceInfo = JsonConvert.DeserializeObject(args.Arguments); - if (tmpResourceInfo != null) - { - pageParameters = new PinStartPageParameters() - { - ResourceInfo = tmpResourceInfo, - PageTarget = tmpResourceInfo.IsDirectory ? PageToken.DirectoryList : PageToken.FileInfo - }; - } - } - if (SettingsService.Instance.LocalSettings.UseWindowsHello) - { - CheckSettingsAndContinue(PageToken.Verification, pageParameters); - } - else - { - CheckSettingsAndContinue(pageParameters?.PageTarget ?? PageToken.DirectoryList, pageParameters); - } - return Task.FromResult(true); - } - - private void CheckSettingsAndContinue(PageToken requestedPage, IPageParameters pageParameters) - { - if ( - string.IsNullOrEmpty(SettingsService.Instance.LocalSettings.ServerAddress) || - string.IsNullOrEmpty(SettingsService.Instance.LocalSettings.Username) - ) - { - NavigationService.Navigate(PageToken.Login.ToString(), null); - } - else - { - var vault = new PasswordVault(); - IReadOnlyList credentialList = null; - try - { - credentialList = vault.FindAllByResource(SettingsService.Instance.LocalSettings.ServerAddress); - } - catch - { - // ignored - } - var credential = credentialList?.FirstOrDefault(item => item.UserName.Equals(SettingsService.Instance.LocalSettings.Username)); - if (credential != null) - { - credential.RetrievePassword(); - if (!string.IsNullOrEmpty(credential.Password)) - { - NavigationService.Navigate(requestedPage.ToString(), pageParameters?.Serialize()); - } - else - { - NavigationService.Navigate( - PageToken.Login.ToString(), - null); - } - } - else - { - NavigationService.Navigate( - PageToken.Login.ToString(), - null); - } - } - // Ensure the current window is active - Window.Current.Activate(); - } - - private void DeviceGestureServiceOnGoBackRequested(object sender, DeviceGestureEventArgs e) - { - var appShell = (AppShell)Window.Current.Content; - var contentFrame = (Frame)appShell.GetContentFrame(); - var page = (SessionStateAwarePage)contentFrame.Content; - var revertable = page?.DataContext as IRevertState; - if (revertable == null || !revertable.CanRevertState()) - { - return; - } - e.Handled = true; - e.Cancel = true; - revertable.RevertState(); - } - } +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Windows.ApplicationModel; +using Microsoft.Practices.Unity; +using Prism.Unity.Windows; +using Prism.Windows.AppModel; +using Windows.ApplicationModel.Activation; +using Windows.ApplicationModel.Resources; +using Windows.Security.Credentials; +using Windows.Storage.AccessCache; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Newtonsoft.Json; +using NextcloudApp.Models; +using NextcloudApp.Services; +using NextcloudApp.Utils; +using NextcloudClient.Exceptions; +using NextcloudClient.Types; +using Prism.Windows.Mvvm; +using Microsoft.QueryStringDotNET; +using Windows.UI.Notifications; +using Windows.Foundation.Collections; +using Windows.System; +using Windows.Storage; + +namespace NextcloudApp +{ + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + sealed partial class App : PrismUnityApplication + { + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + public App() + { + UnhandledException += OnUnhandledException; + TaskScheduler.UnobservedTaskException += TaskSchedulerOnUnobservedTaskException; + InitializeComponent(); + } + + public IActivatedEventArgs ActivatedEventArgs { get; private set; } + + private async void TaskSchedulerOnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs args) + { + var exceptionStackTrace = args.Exception.StackTrace; + var + exceptionHashCode = string.IsNullOrEmpty(exceptionStackTrace) + ? args.Exception.GetHashCode().ToString() + : exceptionStackTrace.GetHashCode().ToString(); + await + ExceptionReportService.Handle(args.Exception.GetType().ToString(), args.Exception.Message, + exceptionStackTrace, args.Exception.InnerException.GetType().ToString(), exceptionHashCode); + } + + private async void OnUnhandledException(object sender, UnhandledExceptionEventArgs args) + { + var exceptionStackTrace = string.Empty; + try + { + exceptionStackTrace = args.Exception.StackTrace + ""; + } + // ReSharper disable once EmptyGeneralCatchClause + catch { } + var exceptionMessage = args.Message; + var exceptionType = string.Empty; + var innerExceptionType = string.Empty; + var exceptionHashCode = string.Empty; + if (args.Exception != null) + { + // Tasks will throw a canceled exception if they get canceled + // We don't care, but avoid closing the app + if (args.Exception.GetType() == typeof(TaskCanceledException)) + { + args.Handled = true; + return; + } + if (args.Exception.GetType() == typeof(OperationCanceledException)) + { + args.Handled = true; + return; + } + if (args.Exception.GetType() == typeof(FileNotFoundException)) + { + args.Handled = true; + return; + } + // Temporary Workaround for WP10 + if (args.Exception.GetType() == typeof(ArgumentException)) + { + args.Handled = true; + return; + } + if (args.Exception.GetType() == typeof(ResponseError)) + { + args.Handled = true; + ResponseErrorHandlerService.HandleException((ResponseError)args.Exception); + return; + } + // 0x8000000B, E_BOUNDS, System.Exception, OutOfBoundsException + if ((uint)args.Exception.HResult == 0x80004004) + { + args.Handled = true; + return; + } + // 0x80072EE7, ERROR_WINHTTP_NAME_NOT_RESOLVED, The server name or address could not be resolved + if ((uint)args.Exception.HResult == 0x80072EE7) + { + args.Handled = true; + var resourceLoader = Container.Resolve(); + var dialogService = Container.Resolve(); + var dialog = new ContentDialog + { + Title = resourceLoader.GetString("AnErrorHasOccurred"), + Content = new TextBlock + { + Text = resourceLoader.GetString("ServerNameOrAddressCouldNotBeResolved"), + TextWrapping = TextWrapping.WrapWholeWords, + Margin = new Thickness(0, 20, 0, 0) + }, + PrimaryButtonText = resourceLoader.GetString("OK") + }; + await dialogService.ShowAsync(dialog); + return; + } + exceptionType = args.Exception.GetType().ToString(); + if (args.Exception.InnerException != null) + { + innerExceptionType = args.Exception.InnerException.GetType().ToString(); + } + exceptionHashCode = string.IsNullOrEmpty(exceptionStackTrace) + ? args.Exception.GetHashCode().ToString() + : exceptionStackTrace.GetHashCode().ToString(); + } + if (args.Handled) + { + return; + } + args.Handled = true; + await + ExceptionReportService.Handle(exceptionType, exceptionMessage, exceptionStackTrace, + innerExceptionType, exceptionHashCode); + } + + protected override UIElement CreateShell(Frame rootFrame) + { + var shell = Container.Resolve(); + shell.SetContentFrame(rootFrame); + return shell; + } + + protected override void OnShareTargetActivated(ShareTargetActivatedEventArgs args) + { + base.OnShareTargetActivated(args); + + OnShareTargetActivatedsyncAsync(args); + } + + private async void OnShareTargetActivatedsyncAsync(ShareTargetActivatedEventArgs args) + { + var sorageItems = await args.ShareOperation.Data.GetStorageItemsAsync(); + StorageApplicationPermissions.FutureAccessList.Clear(); + args.ShareOperation.ReportDataRetrieved(); + + var frame = new Frame(); + frame.Navigate(typeof(ShareTarget), null); + Window.Current.Content = frame; + Window.Current.Activate(); + + var options = new LauncherOptions() + { + TargetApplicationPackageFamilyName = Package.Current.Id.FamilyName, + DesiredRemainingView = Windows.UI.ViewManagement.ViewSizePreference.UseNone + }; + + var inputData = new ValueSet + { + { "FileTokens", (from storageItem in sorageItems where storageItem.IsOfType(StorageItemTypes.File) select StorageApplicationPermissions.FutureAccessList.Add(storageItem)).ToArray() } + }; + var uri = new Uri("nextcloud:///share"); + + await Launcher.LaunchUriAsync(uri, options, inputData); + + args.ShareOperation.ReportCompleted(); + } + + //TODO: Find out, why this is not working on WP10 + //SEE: https://github.com/nextcloud/windows-universal/issues/32 + //protected override void OnFileSavePickerActivated(FileSavePickerActivatedEventArgs args) + //{ + // base.OnFileSavePickerActivated(args); + // OnActivated(args); + //} + //protected override void OnCachedFileUpdaterActivated(CachedFileUpdaterActivatedEventArgs args) + //{ + // base.OnCachedFileUpdaterActivated(args); + // OnActivated(args); + //} + + protected override void OnFileActivated(FileActivatedEventArgs args) + { + base.OnFileActivated(args); + OnActivated(args); + } + + protected override async Task OnActivateApplicationAsync(IActivatedEventArgs args) + { + ActivatedEventArgs = args; + await base.OnActivateApplicationAsync(args); + + // Remove unnecessary notifications whenever the app is used. + ToastNotificationManager.History.RemoveGroup(ToastNotificationService.SYNCACTION); + + // Handle toast activation + var eventArgs = args as ToastNotificationActivatedEventArgs; + if (eventArgs != null) + { + var toastActivationArgs = eventArgs; + // Parse the query string + var query = QueryString.Parse(toastActivationArgs.Argument); + // See what action is being requested + switch (query["action"]) + { + // Nothing to do here + case ToastNotificationService.SYNCACTION: + NavigationService.Navigate(PageToken.DirectoryList.ToString(), null); + break; + // Open Conflict Page + case ToastNotificationService.SYNCONFLICTACTION: + ToastNotificationManager.History.RemoveGroup(ToastNotificationService.SYNCONFLICTACTION); + NavigationService.Navigate(PageToken.SyncConflict.ToString(), null); + break; + } + } + else switch (args.Kind) + { + case ActivationKind.Protocol: + var protocolArgs = args as ProtocolActivatedEventArgs; + + if (protocolArgs != null && protocolArgs.Uri.AbsolutePath == "/share") + { + var pageParameters = new ShareTargetPageParameters() + { + ActivationKind = ActivationKind.ShareTarget, + FileTokens = new List() + }; + + if (protocolArgs.Data.ContainsKey("FileTokens")) + { + var tokens = protocolArgs.Data["FileTokens"] as string[]; + if (tokens != null) + { + foreach (var token in tokens) + { + pageParameters.FileTokens.Add(token); + } + } + } + + CheckSettingsAndContinue(PageToken.ShareTarget, pageParameters); + } + break; + case ActivationKind.FileSavePicker: + case ActivationKind.CachedFileUpdater: + CheckSettingsAndContinue(PageToken.FileSavePicker, null); + break; + case ActivationKind.File: + if (args is FileActivatedEventArgs activatedEventArgs) + { + var sorageItems = activatedEventArgs.Files; + var pageParameters = new ShareTargetPageParameters() + { + //ShareOperation = activatedEventArgs.ShareOperation, + ActivationKind = ActivationKind.ShareTarget, + FileTokens = new List() + }; + StorageApplicationPermissions.FutureAccessList.Clear(); + foreach (var storageItem in sorageItems) + { + var token = StorageApplicationPermissions.FutureAccessList.Add(storageItem); + pageParameters.FileTokens.Add(token); + } + CheckSettingsAndContinue(PageToken.ShareTarget, pageParameters); + } + break; + } + } + + protected override Task OnSuspendingApplicationAsync() + { + var task = base.OnSuspendingApplicationAsync(); + // Stop Background Sync Tasks + List activeSyncs = SyncDbUtils.GetActiveSyncInfos(); + foreach (var fsi in activeSyncs) + { + ToastNotificationService.ShowSyncSuspendedNotification(fsi); + SyncDbUtils.UnlockFolderSyncInfo(fsi); + } + return task; + } + + protected override Task OnInitializeAsync(IActivatedEventArgs args) + { + Container.RegisterInstance(new DialogService()); + Container.RegisterInstance(new ResourceLoaderAdapter(new ResourceLoader())); + var task = base.OnInitializeAsync(args); + DeviceGestureService.GoBackRequested += DeviceGestureServiceOnGoBackRequested; + // Just count total app starts + SettingsService.Instance.LocalSettings.AppTotalRuns = SettingsService.Instance.LocalSettings.AppTotalRuns + 1; + // Count app starts after last update + var currentVersion = + $"{Package.Current.Id.Version.Major}.{Package.Current.Id.Version.Minor}.{Package.Current.Id.Version.Build}.{Package.Current.Id.Version.Revision}"; + if (currentVersion == SettingsService.Instance.LocalSettings.AppRunsAfterLastUpdateVersion) + { + SettingsService.Instance.LocalSettings.AppRunsAfterLastUpdate = SettingsService.Instance.LocalSettings.AppRunsAfterLastUpdate + 1; + } + else + { + SettingsService.Instance.LocalSettings.AppRunsAfterLastUpdateVersion = currentVersion; + SettingsService.Instance.LocalSettings.AppRunsAfterLastUpdate = 1; + SettingsService.Instance.LocalSettings.ShowUpdateMessage = true; + } + MigrationService.Instance.StartMigration(); + return task; + } + + protected override Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args) + { + // Ensure the current window is active + Window.Current.Activate(); + // Remove unnecessary notifications whenever the app is used. + ToastNotificationManager.History.RemoveGroup(ToastNotificationService.SYNCACTION); + PinStartPageParameters pageParameters = null; + if (!string.IsNullOrEmpty(args?.Arguments)) + { + var tmpResourceInfo = JsonConvert.DeserializeObject(args.Arguments); + if (tmpResourceInfo != null) + { + pageParameters = new PinStartPageParameters() + { + ResourceInfo = tmpResourceInfo, + PageTarget = tmpResourceInfo.IsDirectory ? PageToken.DirectoryList : PageToken.FileInfo + }; + } + } + if (SettingsService.Instance.LocalSettings.UseWindowsHello) + { + CheckSettingsAndContinue(PageToken.Verification, pageParameters); + } + else + { + CheckSettingsAndContinue(pageParameters?.PageTarget ?? PageToken.DirectoryList, pageParameters); + } + return Task.FromResult(true); + } + + private void CheckSettingsAndContinue(PageToken requestedPage, IPageParameters pageParameters) + { + if ( + string.IsNullOrEmpty(SettingsService.Instance.LocalSettings.ServerAddress) || + string.IsNullOrEmpty(SettingsService.Instance.LocalSettings.Username) + ) + { + NavigationService.Navigate(PageToken.Login.ToString(), null); + } + else + { + var vault = new PasswordVault(); + IReadOnlyList credentialList = null; + try + { + credentialList = vault.FindAllByResource(SettingsService.Instance.LocalSettings.ServerAddress); + } + catch + { + // ignored + } + var credential = credentialList?.FirstOrDefault(item => item.UserName.Equals(SettingsService.Instance.LocalSettings.Username)); + if (credential != null) + { + credential.RetrievePassword(); + if (!string.IsNullOrEmpty(credential.Password)) + { + NavigationService.Navigate(requestedPage.ToString(), pageParameters?.Serialize()); + } + else + { + NavigationService.Navigate( + PageToken.Login.ToString(), + null); + } + } + else + { + NavigationService.Navigate( + PageToken.Login.ToString(), + null); + } + } + // Ensure the current window is active + Window.Current.Activate(); + } + + private void DeviceGestureServiceOnGoBackRequested(object sender, DeviceGestureEventArgs e) + { + var appShell = (AppShell)Window.Current.Content; + var contentFrame = (Frame)appShell.GetContentFrame(); + var page = (SessionStateAwarePage)contentFrame.Content; + var revertable = page?.DataContext as IRevertState; + if (revertable == null || !revertable.CanRevertState()) + { + return; + } + e.Handled = true; + e.Cancel = true; + revertable.RevertState(); + } + } } \ No newline at end of file diff --git a/NextcloudApp/NextcloudApp.csproj b/NextcloudApp/NextcloudApp.csproj index 38b744a..4ceca96 100644 --- a/NextcloudApp/NextcloudApp.csproj +++ b/NextcloudApp/NextcloudApp.csproj @@ -168,6 +168,9 @@ + + ShareTarget.xaml + @@ -281,6 +284,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/NextcloudApp/Package.appxmanifest b/NextcloudApp/Package.appxmanifest index 1a0698a..171390b 100644 --- a/NextcloudApp/Package.appxmanifest +++ b/NextcloudApp/Package.appxmanifest @@ -27,13 +27,7 @@ - - - Assets\StoreLogo.png - Nextcloud - - - + @@ -46,6 +40,12 @@ RTF + + + Assets\StoreLogo.png + Nextcloud + + diff --git a/NextcloudApp/ShareTarget.xaml b/NextcloudApp/ShareTarget.xaml new file mode 100644 index 0000000..2d5c31a --- /dev/null +++ b/NextcloudApp/ShareTarget.xaml @@ -0,0 +1,19 @@ + + + + + + + + + + + + diff --git a/NextcloudApp/ShareTarget.xaml.cs b/NextcloudApp/ShareTarget.xaml.cs new file mode 100644 index 0000000..2586261 --- /dev/null +++ b/NextcloudApp/ShareTarget.xaml.cs @@ -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 NextcloudApp +{ + /// + /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class ShareTarget : Page + { + public ShareTarget() + { + this.InitializeComponent(); + } + } +} diff --git a/NextcloudApp/Strings/en/Resources.resw b/NextcloudApp/Strings/en/Resources.resw index e8a650a..0008bde 100644 --- a/NextcloudApp/Strings/en/Resources.resw +++ b/NextcloudApp/Strings/en/Resources.resw @@ -551,4 +551,7 @@ Please try again later. Items: {0} (folders: {1} files: {2}) + + Prepare for sharing... + \ No newline at end of file