2019-04-22 23:08:37 +02:00
|
|
|
|
using Bit.App.Pages;
|
|
|
|
|
using Bit.Core;
|
2019-05-29 15:55:48 +02:00
|
|
|
|
using Bit.Core.Abstractions;
|
2019-04-22 23:08:37 +02:00
|
|
|
|
using Bit.Core.Enums;
|
|
|
|
|
using Bit.Core.Models.View;
|
|
|
|
|
using Bit.Core.Utilities;
|
|
|
|
|
using System;
|
2019-03-29 21:52:57 +01:00
|
|
|
|
using Xamarin.Forms;
|
|
|
|
|
|
|
|
|
|
namespace Bit.App.Controls
|
|
|
|
|
{
|
|
|
|
|
public partial class CipherViewCell : ViewCell
|
|
|
|
|
{
|
|
|
|
|
public static readonly BindableProperty CipherProperty = BindableProperty.Create(
|
|
|
|
|
nameof(Cipher), typeof(CipherView), typeof(CipherViewCell), default(CipherView), BindingMode.OneWay);
|
|
|
|
|
|
2019-06-08 18:18:49 +02:00
|
|
|
|
public static readonly BindableProperty WebsiteIconsEnabledProperty = BindableProperty.Create(
|
|
|
|
|
nameof(WebsiteIconsEnabled), typeof(bool), typeof(CipherViewCell), true, BindingMode.OneWay);
|
|
|
|
|
|
2019-04-30 17:27:53 +02:00
|
|
|
|
public static readonly BindableProperty ButtonCommandProperty = BindableProperty.Create(
|
|
|
|
|
nameof(ButtonCommand), typeof(Command<CipherView>), typeof(CipherViewCell));
|
|
|
|
|
|
2019-05-29 15:55:48 +02:00
|
|
|
|
private readonly IEnvironmentService _environmentService;
|
|
|
|
|
|
2019-03-29 21:52:57 +01:00
|
|
|
|
private CipherViewCellViewModel _viewModel;
|
2019-06-08 17:48:45 +02:00
|
|
|
|
private bool _usingNativeCell;
|
2019-03-29 21:52:57 +01:00
|
|
|
|
|
|
|
|
|
public CipherViewCell()
|
|
|
|
|
{
|
2019-05-29 15:55:48 +02:00
|
|
|
|
_environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
|
2019-06-08 17:48:45 +02:00
|
|
|
|
if(Device.RuntimePlatform == Device.iOS)
|
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
|
|
|
|
_viewModel = _grid.BindingContext as CipherViewCellViewModel;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_usingNativeCell = true;
|
|
|
|
|
}
|
2019-03-29 21:52:57 +01:00
|
|
|
|
}
|
|
|
|
|
|
2019-06-08 18:18:49 +02:00
|
|
|
|
public bool WebsiteIconsEnabled
|
|
|
|
|
{
|
|
|
|
|
get => (bool)GetValue(WebsiteIconsEnabledProperty);
|
|
|
|
|
set => SetValue(WebsiteIconsEnabledProperty, value);
|
|
|
|
|
}
|
2019-06-08 17:48:45 +02:00
|
|
|
|
|
2019-03-29 21:52:57 +01:00
|
|
|
|
public CipherView Cipher
|
|
|
|
|
{
|
|
|
|
|
get => GetValue(CipherProperty) as CipherView;
|
|
|
|
|
set => SetValue(CipherProperty, value);
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-30 17:27:53 +02:00
|
|
|
|
public Command<CipherView> ButtonCommand
|
|
|
|
|
{
|
|
|
|
|
get => GetValue(ButtonCommandProperty) as Command<CipherView>;
|
|
|
|
|
set => SetValue(ButtonCommandProperty, value);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 21:52:57 +01:00
|
|
|
|
protected override void OnPropertyChanged(string propertyName = null)
|
|
|
|
|
{
|
|
|
|
|
base.OnPropertyChanged(propertyName);
|
2019-06-08 17:48:45 +02:00
|
|
|
|
if(_usingNativeCell)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-03-29 21:52:57 +01:00
|
|
|
|
if(propertyName == CipherProperty.PropertyName)
|
|
|
|
|
{
|
|
|
|
|
_viewModel.Cipher = Cipher;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-22 23:08:37 +02:00
|
|
|
|
|
2019-06-08 17:48:45 +02:00
|
|
|
|
protected override void OnBindingContextChanged()
|
2019-04-22 23:08:37 +02:00
|
|
|
|
{
|
2019-06-08 17:48:45 +02:00
|
|
|
|
base.OnBindingContextChanged();
|
|
|
|
|
if(_usingNativeCell)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-05-03 03:25:26 +02:00
|
|
|
|
|
2019-06-08 17:48:45 +02:00
|
|
|
|
_image.Source = null;
|
2019-05-03 03:25:26 +02:00
|
|
|
|
CipherView cipher = null;
|
|
|
|
|
if(BindingContext is GroupingsPageListItem groupingsPageListItem)
|
|
|
|
|
{
|
|
|
|
|
cipher = groupingsPageListItem.Cipher;
|
|
|
|
|
}
|
|
|
|
|
else if(BindingContext is CipherView cv)
|
|
|
|
|
{
|
|
|
|
|
cipher = cv;
|
|
|
|
|
}
|
|
|
|
|
if(cipher != null)
|
2019-04-22 23:08:37 +02:00
|
|
|
|
{
|
2019-06-08 17:48:45 +02:00
|
|
|
|
var iconImage = GetIconImage(cipher);
|
|
|
|
|
if(iconImage.Item2 != null)
|
2019-04-22 23:08:37 +02:00
|
|
|
|
{
|
|
|
|
|
_image.IsVisible = true;
|
|
|
|
|
_icon.IsVisible = false;
|
2019-06-08 17:48:45 +02:00
|
|
|
|
_image.Source = iconImage.Item2;
|
2019-04-22 23:08:37 +02:00
|
|
|
|
_image.LoadingPlaceholder = "login.png";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_image.IsVisible = false;
|
|
|
|
|
_icon.IsVisible = true;
|
2019-06-08 17:48:45 +02:00
|
|
|
|
_icon.Text = iconImage.Item1;
|
2019-04-22 23:08:37 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-08 17:48:45 +02:00
|
|
|
|
public Tuple<string, string> GetIconImage(CipherView cipher)
|
|
|
|
|
{
|
|
|
|
|
string icon = null;
|
|
|
|
|
string image = null;
|
|
|
|
|
switch(cipher.Type)
|
|
|
|
|
{
|
|
|
|
|
case CipherType.Login:
|
|
|
|
|
var loginIconImage = GetLoginIconImage(cipher);
|
|
|
|
|
icon = loginIconImage.Item1;
|
|
|
|
|
image = loginIconImage.Item2;
|
|
|
|
|
break;
|
|
|
|
|
case CipherType.SecureNote:
|
|
|
|
|
icon = "";
|
|
|
|
|
break;
|
|
|
|
|
case CipherType.Card:
|
|
|
|
|
icon = "";
|
|
|
|
|
break;
|
|
|
|
|
case CipherType.Identity:
|
|
|
|
|
icon = "";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return new Tuple<string, string>(icon, image);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Tuple<string, string> GetLoginIconImage(CipherView cipher)
|
2019-04-22 23:08:37 +02:00
|
|
|
|
{
|
2019-04-25 05:53:36 +02:00
|
|
|
|
string icon = "";
|
2019-04-22 23:08:37 +02:00
|
|
|
|
string image = null;
|
|
|
|
|
if(cipher.Login.Uri != null)
|
|
|
|
|
{
|
|
|
|
|
var hostnameUri = cipher.Login.Uri;
|
|
|
|
|
var isWebsite = false;
|
|
|
|
|
|
|
|
|
|
if(hostnameUri.StartsWith(Constants.AndroidAppProtocol))
|
|
|
|
|
{
|
2019-04-25 05:53:36 +02:00
|
|
|
|
icon = "";
|
2019-04-22 23:08:37 +02:00
|
|
|
|
}
|
|
|
|
|
else if(hostnameUri.StartsWith(Constants.iOSAppProtocol))
|
|
|
|
|
{
|
2019-04-25 05:53:36 +02:00
|
|
|
|
icon = "";
|
2019-04-22 23:08:37 +02:00
|
|
|
|
}
|
2019-06-08 17:48:45 +02:00
|
|
|
|
else if(WebsiteIconsEnabled && !hostnameUri.Contains("://") && hostnameUri.Contains("."))
|
2019-04-22 23:08:37 +02:00
|
|
|
|
{
|
|
|
|
|
hostnameUri = string.Concat("http://", hostnameUri);
|
|
|
|
|
isWebsite = true;
|
|
|
|
|
}
|
2019-06-08 17:48:45 +02:00
|
|
|
|
else if(WebsiteIconsEnabled)
|
2019-04-22 23:08:37 +02:00
|
|
|
|
{
|
|
|
|
|
isWebsite = hostnameUri.StartsWith("http") && hostnameUri.Contains(".");
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-08 17:48:45 +02:00
|
|
|
|
if(WebsiteIconsEnabled && isWebsite)
|
2019-04-22 23:08:37 +02:00
|
|
|
|
{
|
|
|
|
|
var hostname = CoreHelpers.GetHostname(hostnameUri);
|
2019-05-29 15:55:48 +02:00
|
|
|
|
var iconsUrl = _environmentService.IconsUrl;
|
|
|
|
|
if(string.IsNullOrWhiteSpace(iconsUrl))
|
|
|
|
|
{
|
|
|
|
|
if(!string.IsNullOrWhiteSpace(_environmentService.BaseUrl))
|
|
|
|
|
{
|
|
|
|
|
iconsUrl = string.Format("{0}/icons", _environmentService.BaseUrl);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
iconsUrl = "https://icons.bitwarden.net";
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-22 23:08:37 +02:00
|
|
|
|
image = string.Format("{0}/{1}/icon.png", iconsUrl, hostname);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return new Tuple<string, string>(icon, image);
|
|
|
|
|
}
|
2019-04-30 17:27:53 +02:00
|
|
|
|
|
2019-06-21 15:46:46 +02:00
|
|
|
|
private void MoreButton_Clicked(object sender, EventArgs e)
|
2019-04-30 17:27:53 +02:00
|
|
|
|
{
|
|
|
|
|
ButtonCommand?.Execute(Cipher);
|
|
|
|
|
}
|
2019-03-29 21:52:57 +01:00
|
|
|
|
}
|
|
|
|
|
}
|