cipher view cell and groupings styles

This commit is contained in:
Kyle Spearrin 2019-04-22 17:08:37 -04:00
parent 6cd1171fd5
commit 913cd23c45
18 changed files with 256 additions and 35 deletions

View file

@ -58,7 +58,7 @@
<PackageReference Include="Xamarin.Essentials">
<Version>1.1.0</Version>
</PackageReference>
<PackageReference Include="Xamarin.Forms" Version="3.6.0.293080" />
<PackageReference Include="Xamarin.Forms" Version="3.6.0.344457" />
<PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0.1" />
<PackageReference Include="Xamarin.Android.Support.v7.AppCompat" Version="28.0.0.1" />
<PackageReference Include="Xamarin.Android.Support.v4" Version="28.0.0.1" />

View file

@ -39,6 +39,8 @@ namespace Bit.Droid
private void RegisterLocalServices()
{
FFImageLoading.Forms.Platform.CachedImageRenderer.Init(true);
var preferencesStorage = new PreferencesStorageService(null);
var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
var liteDbStorage = new LiteDbStorageService(Path.Combine(documentsPath, "bitwarden.db"));

View file

@ -13,7 +13,8 @@
<ItemGroup>
<PackageReference Include="Xamarin.Essentials" Version="1.1.0" />
<PackageReference Include="Xamarin.Forms" Version="3.6.0.293080" />
<PackageReference Include="Xamarin.FFImageLoading.Forms" Version="2.4.5.909-pre" />
<PackageReference Include="Xamarin.Forms" Version="3.6.0.344457" />
</ItemGroup>
<ItemGroup>

View file

@ -2,21 +2,82 @@
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Bit.App.Controls.CipherViewCell"
xmlns:controls="clr-namespace:Bit.App.Controls">
xmlns:controls="clr-namespace:Bit.App.Controls"
xmlns:ff="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms">
<ViewCell.View>
<StackLayout x:Name="_layout"
x:DataType="controls:CipherViewCellViewModel"
StyleClass="list-row">
<StackLayout.BindingContext>
<Grid x:Name="_grid"
StyleClass="list-row, list-row-platform"
RowSpacing="0"
ColumnSpacing="0"
x:DataType="controls:CipherViewCellViewModel">
<Grid.BindingContext>
<controls:CipherViewCellViewModel />
</StackLayout.BindingContext>
</Grid.BindingContext>
<Label Text="{Binding Cipher.Name, Mode=OneWay}"
StyleClass="list-title" />
<Label Text="{Binding Cipher.SubTitle, Mode=OneWay}"
StyleClass="list-subtitle" />
</StackLayout>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="60" />
</Grid.ColumnDefinitions>
<controls:FaLabel x:Name="_icon"
HorizontalOptions="Center"
VerticalOptions="Center"
StyleClass="list-icon" />
<ff:CachedImage x:Name="_image"
Grid.Column="0"
Grid.Row="0"
Grid.RowSpan="2"
BitmapOptimizations="True"
ErrorPlaceholder="login.png"
HorizontalOptions="Center"
VerticalOptions="Center"
WidthRequest="20"
HeightRequest="20"
IsVisible="False"/>
<Label LineBreakMode="TailTruncation"
Grid.Column="1"
Grid.Row="0"
StyleClass="list-title, list-title-platform"
Text="{Binding Cipher.Name, Mode=OneWay}" />
<Label LineBreakMode="TailTruncation"
Grid.Column="1"
Grid.Row="1"
Grid.ColumnSpan="3"
StyleClass="list-subtitle, list-subtitle-platform"
Text="{Binding Cipher.SubTitle, Mode=OneWay}" />
<controls:FaLabel Grid.Column="2"
Grid.Row="0"
HorizontalOptions="Start"
VerticalOptions="Center"
StyleClass="list-title-icon"
Margin="5, 0, 0, 0"
Text="&#xf1e0;"
IsVisible="{Binding Cipher.Shared, Mode=OneWay}" />
<controls:FaLabel Grid.Column="3"
Grid.Row="0"
HorizontalOptions="Start"
VerticalOptions="Center"
StyleClass="list-title-icon"
Margin="5, 0, 0, 0"
Text="&#xf0c6;"
IsVisible="{Binding Cipher.HasAttachments, Mode=OneWay}" />
<Button WidthRequest="60"
Grid.Column="4"
Grid.Row="0"
Grid.RowSpan="2"
BackgroundColor="Transparent" />
</Grid>
</ViewCell.View>
</ViewCell>

View file

@ -1,4 +1,9 @@
using Bit.Core.Models.View;
using Bit.App.Pages;
using Bit.Core;
using Bit.Core.Enums;
using Bit.Core.Models.View;
using Bit.Core.Utilities;
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
@ -13,7 +18,7 @@ namespace Bit.App.Controls
public CipherViewCell()
{
InitializeComponent();
_viewModel = _layout.BindingContext as CipherViewCellViewModel;
_viewModel = _grid.BindingContext as CipherViewCellViewModel;
}
public CipherView Cipher
@ -30,5 +35,88 @@ namespace Bit.App.Controls
_viewModel.Cipher = Cipher;
}
}
protected override void OnBindingContextChanged()
{
string icon = null;
string image = null;
_image.Source = null;
if(BindingContext is GroupingsPageListItem groupingsPageListItem && groupingsPageListItem.Cipher != null)
{
switch(groupingsPageListItem.Cipher.Type)
{
case CipherType.Login:
var loginIconImage = GetLoginIconImage(groupingsPageListItem.Cipher);
icon = loginIconImage.Item1;
image = loginIconImage.Item2;
break;
case CipherType.SecureNote:
icon = "&#xf24a;";
break;
case CipherType.Card:
icon = "&#xf09d;";
break;
case CipherType.Identity:
icon = "&#xf2c3;";
break;
default:
break;
}
if(image != null)
{
_image.IsVisible = true;
_icon.IsVisible = false;
_image.Source = image;
_image.LoadingPlaceholder = "login.png";
}
else
{
_image.IsVisible = false;
_icon.IsVisible = true;
_icon.Text = icon;
}
}
base.OnBindingContextChanged();
}
private Tuple<string, string> GetLoginIconImage(CipherView cipher)
{
string icon = "&#xf0ac;";
string image = null;
var imageEnabled = true;
if(cipher.Login.Uri != null)
{
var hostnameUri = cipher.Login.Uri;
var isWebsite = false;
if(hostnameUri.StartsWith(Constants.AndroidAppProtocol))
{
icon = "&#xf17b;";
}
else if(hostnameUri.StartsWith(Constants.iOSAppProtocol))
{
icon = "&#xf179;";
}
else if(imageEnabled && !hostnameUri.Contains("://") && hostnameUri.Contains("."))
{
hostnameUri = string.Concat("http://", hostnameUri);
isWebsite = true;
}
else if(imageEnabled)
{
isWebsite = hostnameUri.StartsWith("http") && hostnameUri.Contains(".");
}
if(imageEnabled && isWebsite)
{
var hostname = CoreHelpers.GetHostname(hostnameUri);
var iconsUrl = "https://icons.bitwarden.net";
image = string.Format("{0}/{1}/icon.png", iconsUrl, hostname);
}
}
return new Tuple<string, string>(icon, image);
}
}
}

View file

@ -22,8 +22,8 @@
x:DataType="pages:GroupingsPageListItem">
<ViewCell>
<StackLayout Orientation="Horizontal"
StyleClass="list-row">
<controls:FaLabel Text="&#xf07c;"
StyleClass="list-row, list-row-platform">
<controls:FaLabel Text="{Binding Icon, Mode=OneWay}"
HorizontalOptions="Start"
VerticalOptions="CenterAndExpand"
StyleClass="list-icon" />
@ -40,8 +40,8 @@
x:DataType="pages:GroupingsPageListItem">
<ViewCell>
<StackLayout Orientation="Horizontal"
StyleClass="list-row">
<controls:FaLabel Text="&#xf1b2;"
StyleClass="list-row, list-row-platform">
<controls:FaLabel Text="{Binding Icon, Mode=OneWay}"
HorizontalOptions="Start"
VerticalOptions="CenterAndExpand"
StyleClass="list-icon" />
@ -72,13 +72,13 @@
CachingStrategy="RecycleElement"
ItemTemplate="{StaticResource listItemDataTemplateSelector}"
IsGroupingEnabled="True"
StyleClass="list">
StyleClass="list, list-platform">
<ListView.GroupHeaderTemplate>
<DataTemplate x:DataType="pages:GroupingsPageListGroup">
<ViewCell>
<StackLayout StyleClass="list-row-header">
<Label Text="{Binding Name}"
StyleClass="list-header, list-header-themed, list-header-platform" />
StyleClass="list-header, list-header-platform" />
</StackLayout>
</ViewCell>
</DataTemplate>

View file

@ -4,8 +4,29 @@ namespace Bit.App.Pages
{
public class GroupingsPageListItem
{
private string _icon;
public FolderView Folder { get; set; }
public CollectionView Collection { get; set; }
public CipherView Cipher { get; set; }
public string Icon
{
get
{
if(_icon != null)
{
return _icon;
}
if(Folder != null)
{
_icon = Folder.Id == null ? "" : "";
}
else if(Collection != null)
{
_icon = "";
}
return _icon;
}
}
}
}

View file

@ -78,15 +78,18 @@ namespace Bit.App.Pages
var groupedItems = new List<GroupingsPageListGroup>();
if(favListItems?.Any() ?? false)
{
groupedItems.Add(new GroupingsPageListGroup(favListItems, AppResources.Favorites));
groupedItems.Add(new GroupingsPageListGroup(favListItems, AppResources.Favorites,
Device.RuntimePlatform == Device.iOS));
}
if(folderListItems?.Any() ?? false)
{
groupedItems.Add(new GroupingsPageListGroup(folderListItems, AppResources.Folders));
groupedItems.Add(new GroupingsPageListGroup(folderListItems, AppResources.Folders,
Device.RuntimePlatform == Device.iOS));
}
if(collectionListItems?.Any() ?? false)
{
groupedItems.Add(new GroupingsPageListGroup(collectionListItems, AppResources.Collections));
groupedItems.Add(new GroupingsPageListGroup(collectionListItems, AppResources.Collections,
Device.RuntimePlatform == Device.iOS));
}
GroupedItems.ResetWithRange(groupedItems);
}

View file

@ -2,9 +2,24 @@
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Bit.App.Styles.Android">
<Style TargetType="ListView"
Class="list-platform">
<Setter Property="SeparatorColor"
Value="Transparent" />
</Style>
<Style TargetType="Label"
Class="list-header-platform">
<Setter Property="TextColor"
Value="{StaticResource ListHeaderTextColor}" />
<Setter Property="FontSize"
Value="Small" />
<Setter Property="FontAttributes"
Value="Bold" />
</Style>
<Style TargetType="StackLayout"
Class="list-row-platform">
</Style>
<Style TargetType="Grid"
Class="list-row-platform">
</Style>
</ResourceDictionary>

View file

@ -2,40 +2,64 @@
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Bit.App.Styles.Base">
<!-- General -->
<Style TargetType="Label"
ApplyToDerivedTypes="True">
<Setter Property="FontSize"
Value="Medium" />
<Setter Property="TextColor"
Value="{StaticResource TextColor}" />
</Style>
<!-- List -->
<Style TargetType="ListView"
Class="list">
<Setter Property="SeparatorColor"
Value="Transparent" />
</Style>
<Style TargetType="StackLayout"
Class="list-row-header">
<Setter Property="Padding"
Value="10" />
Value="10, 12" />
</Style>
<Style TargetType="Label"
Class="list-header">
<Setter Property="FontSize"
Value="Medium" />
</Style>
<Style TargetType="StackLayout"
Class="list-row">
<Setter Property="Padding"
Value="10" />
Value="12" />
</Style>
<Style TargetType="Grid"
Class="list-row">
<Setter Property="Padding"
Value="2, 5" />
</Style>
<Style TargetType="Label"
Class="list-title">
</Style>
<Style TargetType="Label"
ApplyToDerivedTypes="True"
Class="list-title-icon">
<Setter Property="FontSize"
Value="Medium" />
Value="Small" />
<Setter Property="TextColor"
Value="{StaticResource MutedColor}" />
</Style>
<Style TargetType="Label"
Class="list-subtitle">
<Setter Property="FontSize"
Value="Small" />
<Setter Property="TextColor"
Value="{StaticResource MutedColor}" />
</Style>
<Style TargetType="Label"
Class="list-icon"
ApplyToDerivedTypes="True">
<Setter Property="Margin"
Value="3, 3, 3, 0" />
<Setter Property="FontSize"
Value="Medium" />
<Setter Property="TextColor"
Value="{StaticResource MutedColor}" />
</Style>
</ResourceDictionary>

View file

@ -8,4 +8,5 @@
<Color x:Key="SuccessColor">#00a65a</Color>
<Color x:Key="InfoColor">#555555</Color>
<Color x:Key="WarningColor">#bf7e16</Color>
<Color x:Key="MutedColor">#777777</Color>
</ResourceDictionary>

View file

@ -8,6 +8,7 @@
<Color x:Key="SuccessColor">#00a65a</Color>
<Color x:Key="InfoColor">#555555</Color>
<Color x:Key="WarningColor">#bf7e16</Color>
<Color x:Key="MutedColor">#777777</Color>
<Color x:Key="ListHeaderTextColor">#3c8dbc</Color>
</ResourceDictionary>

View file

@ -21,7 +21,7 @@
<ItemGroup>
<PackageReference Include="LiteDB" Version="4.1.4" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="PCLCrypto" Version="2.0.147" />
</ItemGroup>

View file

@ -66,6 +66,7 @@ namespace Bit.Core.Models.View
}
}
public bool Shared => OrganizationId != null;
public bool HasPasswordHistory => PasswordHistory?.Any() ?? false;
public bool HasAttachments => Attachments?.Any() ?? false;
public bool HasOldAttachments

View file

@ -35,7 +35,7 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.12.0.1\lib\netstandard2.0\Newtonsoft.Json.dll</HintPath>
<HintPath>..\..\packages\Newtonsoft.Json.12.0.2\lib\netstandard2.0\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Xml" />

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="12.0.1" targetFramework="xamarinios10" />
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="xamarinios10" />
</packages>

View file

@ -23,6 +23,9 @@ namespace Bit.iOS
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
Xamarin.Forms.Forms.Init();
FFImageLoading.Forms.Platform.CachedImageRenderer.Init();
LoadApplication(new App.App());
return base.FinishedLaunching(app, options);

View file

@ -153,7 +153,7 @@
<PackageReference Include="Xamarin.Essentials">
<Version>1.1.0</Version>
</PackageReference>
<PackageReference Include="Xamarin.Forms" Version="3.6.0.293080" />
<PackageReference Include="Xamarin.Forms" Version="3.6.0.344457" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
<ItemGroup>