Пример #1
0
        public async Task ExecuteAsync()
        {
            var latestAssetUrl = await UpdateHelper.GetLatestApkAssetUrlAsync();

            var decision = await RequestUpdateDecisionAsync(latestAssetUrl);

            if (!decision)
            {
                if (_featureContext.UserInitiated)
                {
                    ToastHelper.Display("Update aborted", ToastLength.Long);
                }

                return;
            }

            var downloadFilePath = Path.Combine(FileSystem.CacheDirectory, "latest.apk");
            var downloadSuccess  = await UpdateHelper.DownloadApkAsync(latestAssetUrl, downloadFilePath, _featureContext.DownloadProgressHandler);

            if (downloadSuccess)
            {
                var providerPath  = FileProvider.GetUriForFile(_context, "amusoft.pcr.mobile.droid.provider", new Java.IO.File(downloadFilePath));
                var upgradeIntent = new Intent(Intent.ActionView);
                upgradeIntent.SetDataAndType(providerPath, "application/vnd.android.package-archive");
                upgradeIntent.AddFlags(ActivityFlags.GrantReadUriPermission);
                _context.StartActivity(upgradeIntent);
            }
        }
Пример #2
0
        private async void InstanceOnItemClicked(object sender, HostSelectionDataSource.ServerDataItem e)
        {
            var endpointAddress = new HostEndpointAddress(e.EndPoint.Address.ToString(), e.HttpsPorts[0]);

            try
            {
                var portOpen = await SocketHelper.IsPortOpenAsync(endpointAddress.IpAddress, endpointAddress.Port, TimeSpan.FromSeconds(1));

                if (!portOpen)
                {
                    ToastHelper.Display($"Failed to connect to {endpointAddress.FullAddress}", ToastLength.Long);
                    return;
                }

                using (var agent = GrpcApplicationAgentFactory.Create(GrpcChannelHub.GetChannelFor(endpointAddress)))
                {
                    var authenticated = await CheckIsAuthenticatedAsync(agent);

                    if (!authenticated)
                    {
                        if (!await TryUpdateAuthenticationAsync(agent, endpointAddress))
                        {
                            return;
                        }
                    }

                    NavigateToHost(e);
                }
            }
            catch (Exception exception)
            {
                ToastHelper.Display($"Failed to connect to {endpointAddress.FullAddress}", ToastLength.Long);
                Log.Error(exception);
            }
        }
Пример #3
0
        private async void DataSourceOnUpdateRequired(object sender, AudioFeedResponseItem e)
        {
            try
            {
                var result = await _agent.FullDesktopClient.UpdateAudioFeedAsync(new UpdateAudioFeedRequest()
                {
                    Item = e
                });

                ToastHelper.DisplaySuccess(result.Success, ToastLength.Short);

                if (result.Success)
                {
                    var feeds = await _agent.FullDesktopClient.GetAudioFeedsAsync(new AudioFeedRequest());

                    if (_recyclerView.GetAdapter() is AudioApplicationDataSource audioDataSource)
                    {
                        var match = feeds.Items.FirstOrDefault(d => d.Id == e.Id);
                        if (match != null)
                        {
                            audioDataSource.UpdateSingle(match);
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                Log.Error(exception);
                ToastHelper.Display("Update failed", ToastLength.Short);
            }
        }
Пример #4
0
        private Task TellClipboard()
        {
            if (TryGetClipboardContent(out var content))
            {
                ToastHelper.Display(content, ToastLength.Long);
            }

            return(Task.CompletedTask);
        }
Пример #5
0
        private async Task <bool> IsAuthorizedAsync()
        {
            var result = await _agent.DesktopClient.AuthenticateAsync();

            if (!result)
            {
                ToastHelper.Display("Authentication required.", ToastLength.Long);
            }

            return(result);
        }
Пример #6
0
        private async Task ButtonAction(MacPackage package)
        {
            Log.Info("Waking up host {Name} with {Count} last known addresses", package.HostName, package.Addresses.Length);
            foreach (var address in package.Addresses)
            {
                Log.Debug("Waking up physical address {Id}", address);
                await Amusoft.Toolkit.Networking.WakeOnLan.UsingAddressAsync(address);
            }

            ToastHelper.Display($"Wake On LAN for {package.HostName} sent", ToastLength.Long);
        }
Пример #7
0
        private void HolderItemOnItemClicked(object sender, EventArgs e)
        {
            if (sender is SelectServerFragmentDataSourceItem holder)
            {
                if (holder.AbsoluteAdapterPosition < 0)
                {
                    ToastHelper.Display("Error - Restart application", ToastLength.Short);
                    Log.Debug("holder.AbsoluteAdapterPosition < 0");
                    return;
                }

                ItemClicked?.Invoke(null, _dataItems[holder.AbsoluteAdapterPosition]);
            }
        }
Пример #8
0
 private void DeleteLogsClicked()
 {
     try
     {
         var root = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
         var path = Path.Combine(root, "logs", "nlog.csv");
         if (File.Exists(path))
         {
             File.Delete(path);
         }
         ToastHelper.Display("Logs deleted", ToastLength.Short);
     }
     catch (Exception e)
     {
         ToastHelper.Display("Failed to clear logs", ToastLength.Short);
         Log.Error(e);
     }
 }
Пример #9
0
        private async Task SetHostClipboard()
        {
            if (!TryGetClipboardContent(out var content))
            {
                ToastHelper.Display($"Clipboard cannot be sent", ToastLength.Long);
                return;
            }

            try
            {
                var result = await this.GetAgent().DesktopClient.SetClipboardAsync(TimeSpan.FromMinutes(1), GetRemoteName(), content);

                ToastHelper.Display(result ? "Host clipboard updated" : "error", ToastLength.Short);
            }
            catch (RpcException e) when(e.StatusCode == StatusCode.PermissionDenied)
            {
                ToastHelper.Display(e.Message, ToastLength.Long);
            }
        }
Пример #10
0
        private void SeekBarOnProgressChanged(object sender, SeekBar.ProgressChangedEventArgs e)
        {
            const int step     = 5;
            var       progress = e.Progress;

            progress       = progress / step;
            progress       = progress * step;
            _textView.Text = $"Master volume: {progress}";
            _seekBar.SetProgress(progress, true);

            Log.Info("Setting master volume to {Value} FromUser: {FromUser}", progress, e.FromUser);
            if (e.FromUser)
            {
                Debouncer.Debounce(nameof(AudioFragment) + nameof(SeekBarOnProgressChanged), async() =>
                {
                    await _agent.DesktopClient.SetMasterVolumeAsync(TimeSpan.FromSeconds(5), progress);
                    ToastHelper.Display("Volume updated", ToastLength.Short);
                }, TimeSpan.FromSeconds(2));
            }
        }
Пример #11
0
        private async void ToggleMuteClicked(object sender, EventArgs e)
        {
            var result = await _agent.DesktopClient.ToggleMuteAsync(TimeSpan.FromSeconds(5));

            switch (result)
            {
            case null:
                ToastHelper.Display("Error", ToastLength.Short);
                break;

            case true:
                ToastHelper.Display("Muted", ToastLength.Short);
                _imageViewMasterToggle.SetImageResource(Resource.Drawable.outline_volume_off_24);
                break;

            case false:
                ToastHelper.Display("Unmuted", ToastLength.Short);
                _imageViewMasterToggle.SetImageResource(Resource.Drawable.outline_volume_up_24);
                break;
            }
        }
Пример #12
0
        private async Task GetHostClipboard()
        {
            var cm = Context.GetSystemService(Context.ClipboardService) as ClipboardManager;

            if (cm == null)
            {
                return;
            }

            try
            {
                var content = await this.GetAgent().DesktopClient.GetClipboardAsync(TimeSpan.FromMinutes(1), GetRemoteName());

                cm.PrimaryClip = ClipData.NewPlainText("Host clipboard", content);
                ToastHelper.Display("Clipboard updated", ToastLength.Short);
            }
            catch (RpcException e) when(e.StatusCode == StatusCode.PermissionDenied)
            {
                ToastHelper.Display(e.Message, ToastLength.Long);
            }
        }
Пример #13
0
        private static async Task <bool> CheckIsAuthenticatedAsync(GrpcApplicationAgent agent)
        {
            var authenticated = true;
            CheckIsAuthenticatedResponse response = null;

            try
            {
                response = await agent.FullDesktopClient.CheckIsAuthenticatedAsync(new CheckIsAuthenticatedRequest()).ResponseAsync;
            }
            catch (RpcException exception) when(exception.Status.StatusCode == StatusCode.Unauthenticated)
            {
                authenticated = false;
            }
            catch (RpcException exception)
            {
                Log.Error(exception);
                ToastHelper.Display("Failed to check authentication state", ToastLength.Long);
                authenticated = false;
            }

            return(authenticated && response.Result);
        }
Пример #14
0
        private async Task <bool> TryUpdateAuthenticationAsync(GrpcApplicationAgent agent, HostEndpointAddress endpointAddress)
        {
            var input = await LoginDialog.GetInputAsync("Authentication required");

            if (input == null)
            {
                ToastHelper.Display("Authentication required", ToastLength.Long);
                return(false);
            }

            var loginResponse = await GetLoginResponseAsync(agent, input);

            if (loginResponse.InvalidCredentials)
            {
                ToastHelper.Display("Invalid credentials", ToastLength.Long);
                return(false);
            }

            var authenticationStorage = new AuthenticationStorage(endpointAddress);
            await authenticationStorage.UpdateAsync(loginResponse.AccessToken, loginResponse.RefreshToken).ConfigureAwait(false);

            return(true);
        }
Пример #15
0
		private async Task<TResult> SecuredCallAsync<TResult>(Func<DesktopIntegrationService.DesktopIntegrationServiceClient, Task<TResult>> functionCall, TResult defaultValue, [CallerMemberName] string methodName = default)
		{
			try
			{
				GrpcRequestObserver.NotifyCallRunning();
				return await functionCall(_client);
			}
			catch (RpcException e) when (e.StatusCode == StatusCode.PermissionDenied)
			{
				ToastHelper.Display("Permission denied", ToastLength.Long);
				return defaultValue;
			}
			catch (Exception e)
			{
				Log.Error(e, methodName + " failed.");
				GrpcRequestObserver.NotifyCallFailed(e);
				return defaultValue;
			}
			finally
			{
				GrpcRequestObserver.NotifyCallFinished();
			}
		}
Пример #16
0
 private void ClearStorageClicked()
 {
     SecureStorage.RemoveAll();
     ToastHelper.Display("Secure storage cleared", ToastLength.Short);
 }
Пример #17
0
        protected override async Task <Data> DoWorkAsync(CancellationToken cancellationToken)
        {
            var notificationId = (GetStateKind() + "+" + _agentAddress).GetHashCode();

            Log.Debug("Spawned notification with Id {Id}", notificationId);
            try
            {
                var scheduled = await SystemStateManager.GetScheduledTimeAsync(_agentAddress, GetStateKind());

                if (scheduled == null || DateTime.Now > scheduled.Value)
                {
                    Log.Info("A system state event passed while the device was not working.");
                    return(Data.Empty);
                }

                var progressDataBuilder = new Data.Builder();

                UpdateProgress(progressDataBuilder, 0, false);
                if (!HostEndpointAddress.TryParse(_agentAddress, out var address))
                {
                    Log.Warn("Address {Address} could not be parsed - aborting process", _agentAddress);
                    return(Data.Empty);
                }

                using (var agent = GrpcApplicationAgentFactory.Create(GrpcChannelHub.GetChannelFor(address)))
                {
                    var hostName = await agent.DesktopClient.GetHostNameAsync(TimeSpan.FromSeconds(5));

                    var notification = NotificationHelper.DisplayNotification(notificationId, builder =>
                    {
                        builder.SetCategory(NotificationCompat.CategoryProgress);
                        builder.SetContentTitle(GetNotificationTitle(hostName));
                        builder.SetOnlyAlertOnce(true);
                        builder.SetSmallIcon(GetNotificationIcon());
                        var intent = new Intent();
                        intent.SetAction(GetAbortAction());
                        intent.PutExtra(AbortBroadcastReceiver.NotificationIdTag, notificationId);
                        intent.PutExtra(AbortBroadcastReceiver.WorkIdTag, Id.ToString());
                        intent.PutExtra(AbortBroadcastReceiver.HostAddressTag, _agentAddress);
                        var pendingIntent = PendingIntent.GetBroadcast(Application.Context, notificationId, intent, PendingIntentFlags.OneShot);
                        builder.AddAction(Android.Resource.Drawable.ButtonPlus, "Abort", pendingIntent);
                    }, GetNotificationChannel());

                    SetForegroundAsync(new ForegroundInfo(notificationId, notification.Build()));

                    var startDifference = scheduled.Value - DateTime.Now;
                    while (scheduled > DateTime.Now)
                    {
                        var currentDifference = scheduled.Value - DateTime.Now;
                        var progress          = (100f / startDifference.TotalSeconds) * currentDifference.TotalSeconds;
                        notification.SetProgress(100, (int)progress, false);
                        UpdateProgress(progressDataBuilder, progress, true);
                        notification.SetContentText(currentDifference.ToString("hh\\:mm\\:ss"));

                        NotificationHelper.UpdateNotification(ApplicationContext, notificationId, notification);

                        await Task.Delay(1000, cancellationToken);
                    }

                    UpdateProgress(progressDataBuilder, 0, false);
                    NotificationHelper.DestroyNotification(notificationId);
                    SystemStateManager.Clear(_agentAddress, GetStateKind());

                    var result = await ExecuteFinalizerAsync(agent);

                    Xamarin.Essentials.MainThread.BeginInvokeOnMainThread(() =>
                    {
                        if (result)
                        {
                            ToastHelper.Display(GetSuccessToastMessage(hostName), ToastLength.Long);
                        }
                        else
                        {
                            ToastHelper.Display("Error", ToastLength.Short);
                        }
                    });
                }
            }
            catch (RpcException e)
            {
                Log.Debug(e, "Cancelling work because of an RPC exception");
                WorkManager.GetInstance(ApplicationContext).CancelWorkById(Id);
            }

            return(Data.Empty);
        }