mobile platform utils
This commit is contained in:
parent
36780c5ef8
commit
9e51c46522
|
@ -49,6 +49,9 @@
|
|||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Plugin.CurrentActivity">
|
||||
<Version>2.1.0.4</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Portable.BouncyCastle">
|
||||
<Version>1.8.5</Version>
|
||||
</PackageReference>
|
||||
|
@ -76,6 +79,7 @@
|
|||
<Compile Include="Resources\Resource.designer.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Services\CryptoPrimitiveService.cs" />
|
||||
<Compile Include="Services\DeviceActionService.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidAsset Include="Assets\FontAwesome.ttf" />
|
||||
|
|
|
@ -15,5 +15,11 @@ namespace Bit.Droid
|
|||
public MainApplication(IntPtr handle, JniHandleOwnership transer)
|
||||
: base(handle, transer)
|
||||
{ }
|
||||
|
||||
public override void OnCreate()
|
||||
{
|
||||
base.OnCreate();
|
||||
Plugin.CurrentActivity.CrossCurrentActivity.Current.Init(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
using Bit.App.Abstractions;
|
||||
using Plugin.CurrentActivity;
|
||||
|
||||
namespace Bit.Droid.Services
|
||||
{
|
||||
public class DeviceActionService : IDeviceActionService
|
||||
{
|
||||
private Android.Widget.Toast _toast;
|
||||
|
||||
public void Toast(string text, bool longDuration = false)
|
||||
{
|
||||
if(_toast != null)
|
||||
{
|
||||
_toast.Cancel();
|
||||
_toast.Dispose();
|
||||
_toast = null;
|
||||
}
|
||||
_toast = Android.Widget.Toast.MakeText(CrossCurrentActivity.Current.Activity, text,
|
||||
longDuration ? Android.Widget.ToastLength.Long : Android.Widget.ToastLength.Short);
|
||||
_toast.Show();
|
||||
}
|
||||
|
||||
public bool LaunchApp(string appName)
|
||||
{
|
||||
var activity = CrossCurrentActivity.Current.Activity;
|
||||
appName = appName.Replace("androidapp://", string.Empty);
|
||||
var launchIntent = activity.PackageManager.GetLaunchIntentForPackage(appName);
|
||||
if(launchIntent != null)
|
||||
{
|
||||
activity.StartActivity(launchIntent);
|
||||
}
|
||||
return launchIntent != null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IDeviceActionService
|
||||
{
|
||||
void Toast(string text, bool longDuration = false);
|
||||
bool LaunchApp(string appName);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using Bit.App.Pages;
|
||||
using Bit.App.Models;
|
||||
using Bit.App.Pages;
|
||||
using Bit.App.Utilities;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
@ -17,6 +18,23 @@ namespace Bit.App
|
|||
|
||||
ThemeManager.SetTheme("light");
|
||||
MainPage = new TabsPage();
|
||||
|
||||
MessagingCenter.Subscribe<Application, DialogDetails>(Current, "ShowDialog", async (sender, details) =>
|
||||
{
|
||||
var confirmed = true;
|
||||
// TODO: ok text
|
||||
var confirmText = string.IsNullOrWhiteSpace(details.ConfirmText) ? "Ok" : details.ConfirmText;
|
||||
if(!string.IsNullOrWhiteSpace(details.CancelText))
|
||||
{
|
||||
confirmed = await MainPage.DisplayAlert(details.Title, details.Text, confirmText,
|
||||
details.CancelText);
|
||||
}
|
||||
else
|
||||
{
|
||||
await MainPage.DisplayAlert(details.Title, details.Text, details.ConfirmText);
|
||||
}
|
||||
MessagingCenter.Send(Current, "ShowDialogResolve", new Tuple<int, bool>(details.DialogId, confirmed));
|
||||
});
|
||||
}
|
||||
|
||||
protected override void OnStart()
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
namespace Bit.App.Models
|
||||
{
|
||||
public class DialogDetails
|
||||
{
|
||||
public string Text { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string ConfirmText { get; set; }
|
||||
public string CancelText { get; set; }
|
||||
public string Type { get; set; }
|
||||
public int DialogId { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
using Bit.App.Abstractions;
|
||||
using Bit.App.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Essentials;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Services
|
||||
{
|
||||
public class MobilePlatformUtilsService
|
||||
{
|
||||
private static readonly Random _random = new Random();
|
||||
|
||||
private const int DialogPromiseExpiration = 600000; // 10 minutes
|
||||
|
||||
private readonly IDeviceActionService _deviceActionService;
|
||||
private readonly Dictionary<int, Tuple<TaskCompletionSource<bool>, DateTime>> _showDialogResolves =
|
||||
new Dictionary<int, Tuple<TaskCompletionSource<bool>, DateTime>>();
|
||||
|
||||
public MobilePlatformUtilsService(IDeviceActionService deviceActionService)
|
||||
{
|
||||
_deviceActionService = deviceActionService;
|
||||
|
||||
MessagingCenter.Subscribe<Xamarin.Forms.Application, Tuple<int, bool>>(
|
||||
Xamarin.Forms.Application.Current, "ShowDialogResolve", (sender, details) =>
|
||||
{
|
||||
var dialogId = details.Item1;
|
||||
var confirmed = details.Item2;
|
||||
if(_showDialogResolves.ContainsKey(dialogId))
|
||||
{
|
||||
var resolveObj = _showDialogResolves[dialogId].Item1;
|
||||
resolveObj.TrySetResult(confirmed);
|
||||
}
|
||||
|
||||
// Clean up old tasks
|
||||
var deleteIds = new HashSet<int>();
|
||||
foreach(var item in _showDialogResolves)
|
||||
{
|
||||
var age = DateTime.UtcNow - item.Value.Item2;
|
||||
if(age.TotalMilliseconds > DialogPromiseExpiration)
|
||||
{
|
||||
deleteIds.Add(item.Key);
|
||||
}
|
||||
}
|
||||
foreach(var id in deleteIds)
|
||||
{
|
||||
_showDialogResolves.Remove(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public string IdentityClientId => "mobile";
|
||||
|
||||
public Core.Enums.DeviceType GetDevice()
|
||||
{
|
||||
return Device.RuntimePlatform == Device.iOS ? Core.Enums.DeviceType.iOS : Core.Enums.DeviceType.Android;
|
||||
}
|
||||
|
||||
public string GetDeviceString()
|
||||
{
|
||||
return DeviceInfo.Model;
|
||||
}
|
||||
|
||||
public bool IsViewOpen()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public int? LockTimeout()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void LaunchUri(string uri, Dictionary<string, object> options = null)
|
||||
{
|
||||
if(uri.StartsWith("http://") || uri.StartsWith("https://"))
|
||||
{
|
||||
Browser.OpenAsync(uri, BrowserLaunchMode.External);
|
||||
}
|
||||
else
|
||||
{
|
||||
var launched = false;
|
||||
if(Device.RuntimePlatform == Device.Android && uri.StartsWith("androidapp://"))
|
||||
{
|
||||
launched = _deviceActionService.LaunchApp(uri);
|
||||
}
|
||||
if(!launched && (options?.ContainsKey("page") ?? false))
|
||||
{
|
||||
(options["page"] as Page).DisplayAlert(null, "", ""); // TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveFile()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public string GetApplicationVersion()
|
||||
{
|
||||
return AppInfo.VersionString;
|
||||
}
|
||||
|
||||
public bool SupportsU2f()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void ShowToast(string type, string title, string text, Dictionary<string, object> options = null)
|
||||
{
|
||||
ShowToast(type, title, new string[] { text }, options);
|
||||
}
|
||||
|
||||
public void ShowToast(string type, string title, string[] text, Dictionary<string, object> options = null)
|
||||
{
|
||||
if(text.Length > 0)
|
||||
{
|
||||
var longDuration = options != null && options.ContainsKey("longDuration") ?
|
||||
(bool)options["longDuration"] : false;
|
||||
_deviceActionService.Toast(text[0], longDuration);
|
||||
}
|
||||
}
|
||||
|
||||
public Task<bool> ShowDialogAsync(string text, string title = null, string confirmText = null,
|
||||
string cancelText = null, string type = null)
|
||||
{
|
||||
var dialogId = 0;
|
||||
lock(_random)
|
||||
{
|
||||
dialogId = _random.Next(0, int.MaxValue);
|
||||
}
|
||||
MessagingCenter.Send(Xamarin.Forms.Application.Current, "ShowAlert", new DialogDetails
|
||||
{
|
||||
Text = text,
|
||||
Title = title,
|
||||
ConfirmText = confirmText,
|
||||
CancelText = cancelText,
|
||||
Type = type,
|
||||
DialogId = dialogId
|
||||
});
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
_showDialogResolves.Add(dialogId, new Tuple<TaskCompletionSource<bool>, DateTime>(tcs, DateTime.UtcNow));
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
public bool IsDev()
|
||||
{
|
||||
return Core.Utilities.CoreHelpers.InDebugMode();
|
||||
}
|
||||
|
||||
public bool IsSelfHost()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task CopyToClipboardAsync(string text, Dictionary<string, object> options = null)
|
||||
{
|
||||
var clearMs = options != null && options.ContainsKey("clearMs") ? (int?)options["clearMs"] : null;
|
||||
await Clipboard.SetTextAsync(text);
|
||||
// TODO: send message 'copiedToClipboard'
|
||||
}
|
||||
|
||||
public async Task<string> ReadFromClipboardAsync(Dictionary<string, object> options = null)
|
||||
{
|
||||
return await Clipboard.GetTextAsync();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,50 +1,27 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Core.Enums
|
||||
namespace Bit.Core.Enums
|
||||
{
|
||||
public enum DeviceType : byte
|
||||
{
|
||||
[Display(Name = "Android")]
|
||||
Android = 0,
|
||||
[Display(Name = "iOS")]
|
||||
iOS = 1,
|
||||
[Display(Name = "Chrome Extension")]
|
||||
ChromeExtension = 2,
|
||||
[Display(Name = "Firefox Extension")]
|
||||
FirefoxExtension = 3,
|
||||
[Display(Name = "Opera Extension")]
|
||||
OperaExtension = 4,
|
||||
[Display(Name = "Edge Extension")]
|
||||
EdgeExtension = 5,
|
||||
[Display(Name = "Windows")]
|
||||
WindowsDesktop = 6,
|
||||
[Display(Name = "macOS")]
|
||||
MacOsDesktop = 7,
|
||||
[Display(Name = "Linux")]
|
||||
LinuxDesktop = 8,
|
||||
[Display(Name = "Chrome")]
|
||||
ChromeBrowser = 9,
|
||||
[Display(Name = "Firefox")]
|
||||
FirefoxBrowser = 10,
|
||||
[Display(Name = "Opera")]
|
||||
OperaBrowser = 11,
|
||||
[Display(Name = "Edge")]
|
||||
EdgeBrowser = 12,
|
||||
[Display(Name = "Internet Explorer")]
|
||||
IEBrowser = 13,
|
||||
[Display(Name = "Unknown Browser")]
|
||||
UnknownBrowser = 14,
|
||||
[Display(Name = "Android")]
|
||||
AndroidAmazon = 15,
|
||||
[Display(Name = "UWP")]
|
||||
UWP = 16,
|
||||
[Display(Name = "Safari")]
|
||||
SafariBrowser = 17,
|
||||
[Display(Name = "Vivaldi")]
|
||||
VivaldiBrowser = 18,
|
||||
[Display(Name = "Vivaldi Extension")]
|
||||
VivaldiExtension = 19,
|
||||
[Display(Name = "Safari Extension")]
|
||||
SafariExtension = 20
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,12 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Core.Enums
|
||||
namespace Bit.Core.Enums
|
||||
{
|
||||
public enum PaymentMethodType : byte
|
||||
{
|
||||
[Display(Name = "Card")]
|
||||
Card = 0,
|
||||
[Display(Name = "Bank Account")]
|
||||
BankAccount = 1,
|
||||
[Display(Name = "PayPal")]
|
||||
PayPal = 2,
|
||||
[Display(Name = "BitPay")]
|
||||
BitPay = 3,
|
||||
[Display(Name = "Credit")]
|
||||
Credit = 4,
|
||||
[Display(Name = "Wire Transfer")]
|
||||
WireTransfer = 5,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,13 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Core.Enums
|
||||
namespace Bit.Core.Enums
|
||||
{
|
||||
public enum PlanType : byte
|
||||
{
|
||||
[Display(Name = "Free")]
|
||||
Free = 0,
|
||||
[Display(Name = "Families")]
|
||||
FamiliesAnnually = 1,
|
||||
[Display(Name = "Teams (Monthly)")]
|
||||
TeamsMonthly = 2,
|
||||
[Display(Name = "Teams (Annually)")]
|
||||
TeamsAnnually = 3,
|
||||
[Display(Name = "Enterprise (Monthly)")]
|
||||
EnterpriseMonthly = 4,
|
||||
[Display(Name = "Enterprise (Annually)")]
|
||||
EnterpriseAnnually = 5,
|
||||
[Display(Name = "Custom")]
|
||||
Custom = 6
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,11 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Core.Enums
|
||||
namespace Bit.Core.Enums
|
||||
{
|
||||
public enum TransactionType : byte
|
||||
{
|
||||
[Display(Name = "Charge")]
|
||||
Charge = 0,
|
||||
[Display(Name = "Credit")]
|
||||
Credit = 1,
|
||||
[Display(Name = "Promotional Credit")]
|
||||
PromotionalCredit = 2,
|
||||
[Display(Name = "Referral Credit")]
|
||||
ReferralCredit = 3,
|
||||
[Display(Name = "Refund")]
|
||||
Refund = 4,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue