mirror of
https://github.com/bitwarden/mobile
synced 2025-12-11 05:43:30 +00:00
Forms update with CollectionView conversion (#1374)
* Forms update with CollectionView conversion * updates * removed unnecessary import
This commit is contained in:
@@ -77,19 +77,19 @@
|
|||||||
<PackageReference Include="Portable.BouncyCastle">
|
<PackageReference Include="Portable.BouncyCastle">
|
||||||
<Version>1.8.10</Version>
|
<Version>1.8.10</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Xamarin.AndroidX.AutoFill" Version="1.1.0.3-beta01" />
|
<PackageReference Include="Xamarin.AndroidX.AutoFill" Version="1.1.0.6" />
|
||||||
<PackageReference Include="Xamarin.Essentials">
|
<PackageReference Include="Xamarin.Essentials">
|
||||||
<Version>1.5.3.2</Version>
|
<Version>1.6.1</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Xamarin.Firebase.Messaging">
|
<PackageReference Include="Xamarin.Firebase.Messaging">
|
||||||
<Version>121.0.1</Version>
|
<Version>121.0.1</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.0.0" />
|
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.3.0.1" />
|
||||||
<PackageReference Include="Xamarin.AndroidX.AppCompat" Version="1.1.0" />
|
<PackageReference Include="Xamarin.AndroidX.AppCompat" Version="1.2.0.7" />
|
||||||
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0" />
|
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0.7" />
|
||||||
<PackageReference Include="Xamarin.AndroidX.CardView" Version="1.0.0" />
|
<PackageReference Include="Xamarin.AndroidX.CardView" Version="1.0.0.8" />
|
||||||
<PackageReference Include="Xamarin.AndroidX.MediaRouter" Version="1.1.0" />
|
<PackageReference Include="Xamarin.AndroidX.MediaRouter" Version="1.2.2.1" />
|
||||||
<PackageReference Include="Xamarin.AndroidX.Migration" Version="1.0.6" />
|
<PackageReference Include="Xamarin.AndroidX.Migration" Version="1.0.8" />
|
||||||
<PackageReference Include="Xamarin.Google.Dagger" Version="2.27.0" />
|
<PackageReference Include="Xamarin.Google.Dagger" Version="2.27.0" />
|
||||||
<PackageReference Include="Xamarin.GooglePlayServices.SafetyNet">
|
<PackageReference Include="Xamarin.GooglePlayServices.SafetyNet">
|
||||||
<Version>117.0.0</Version>
|
<Version>117.0.0</Version>
|
||||||
@@ -120,18 +120,17 @@
|
|||||||
<Compile Include="Receivers\EventUploadReceiver.cs" />
|
<Compile Include="Receivers\EventUploadReceiver.cs" />
|
||||||
<Compile Include="Receivers\LockAlarmReceiver.cs" />
|
<Compile Include="Receivers\LockAlarmReceiver.cs" />
|
||||||
<Compile Include="Receivers\PackageReplacedReceiver.cs" />
|
<Compile Include="Receivers\PackageReplacedReceiver.cs" />
|
||||||
<Compile Include="Renderers\CipherViewCellRenderer.cs" />
|
<Compile Include="Renderers\ExtendedGridRenderer.cs" />
|
||||||
<Compile Include="Renderers\ExtendedDatePickerRenderer.cs" />
|
<Compile Include="Renderers\ExtendedDatePickerRenderer.cs" />
|
||||||
<Compile Include="Renderers\CustomTabbedRenderer.cs" />
|
<Compile Include="Renderers\CustomTabbedRenderer.cs" />
|
||||||
|
<Compile Include="Renderers\ExtendedStackLayoutRenderer.cs" />
|
||||||
<Compile Include="Renderers\ExtendedTimePickerRenderer.cs" />
|
<Compile Include="Renderers\ExtendedTimePickerRenderer.cs" />
|
||||||
<Compile Include="Renderers\ExtendedSliderRenderer.cs" />
|
<Compile Include="Renderers\ExtendedSliderRenderer.cs" />
|
||||||
<Compile Include="Renderers\CustomEditorRenderer.cs" />
|
<Compile Include="Renderers\CustomEditorRenderer.cs" />
|
||||||
<Compile Include="Renderers\CustomPickerRenderer.cs" />
|
<Compile Include="Renderers\CustomPickerRenderer.cs" />
|
||||||
<Compile Include="Renderers\CustomEntryRenderer.cs" />
|
<Compile Include="Renderers\CustomEntryRenderer.cs" />
|
||||||
<Compile Include="Renderers\CustomSearchBarRenderer.cs" />
|
<Compile Include="Renderers\CustomSearchBarRenderer.cs" />
|
||||||
<Compile Include="Renderers\ExtendedListViewRenderer.cs" />
|
|
||||||
<Compile Include="Renderers\HybridWebViewRenderer.cs" />
|
<Compile Include="Renderers\HybridWebViewRenderer.cs" />
|
||||||
<Compile Include="Renderers\SendViewCellRenderer.cs" />
|
|
||||||
<Compile Include="Services\AndroidPushNotificationService.cs" />
|
<Compile Include="Services\AndroidPushNotificationService.cs" />
|
||||||
<Compile Include="Services\AndroidLogService.cs" />
|
<Compile Include="Services\AndroidLogService.cs" />
|
||||||
<Compile Include="MainApplication.cs" />
|
<Compile Include="MainApplication.cs" />
|
||||||
@@ -173,6 +172,9 @@
|
|||||||
<AndroidResource Include="Resources\drawable\ic_launcher_foreground.xml" />
|
<AndroidResource Include="Resources\drawable\ic_launcher_foreground.xml" />
|
||||||
<AndroidResource Include="Resources\drawable\id.xml" />
|
<AndroidResource Include="Resources\drawable\id.xml" />
|
||||||
<AndroidResource Include="Resources\drawable\info.xml" />
|
<AndroidResource Include="Resources\drawable\info.xml" />
|
||||||
|
<AndroidResource Include="Resources\drawable\list_item_bg.xml" />
|
||||||
|
<AndroidResource Include="Resources\drawable\list_item_bg_dark.xml" />
|
||||||
|
<AndroidResource Include="Resources\drawable\list_item_bg_nord.xml" />
|
||||||
<AndroidResource Include="Resources\drawable\lock.xml" />
|
<AndroidResource Include="Resources\drawable\lock.xml" />
|
||||||
<AndroidResource Include="Resources\drawable\login.xml" />
|
<AndroidResource Include="Resources\drawable\login.xml" />
|
||||||
<AndroidResource Include="Resources\drawable\logo.xml" />
|
<AndroidResource Include="Resources\drawable\logo.xml" />
|
||||||
@@ -185,7 +187,6 @@
|
|||||||
<AndroidResource Include="Resources\drawable\shield.xml" />
|
<AndroidResource Include="Resources\drawable\shield.xml" />
|
||||||
<AndroidResource Include="Resources\drawable-v23\splash_screen.xml" />
|
<AndroidResource Include="Resources\drawable-v23\splash_screen.xml" />
|
||||||
<AndroidResource Include="Resources\drawable-v23\splash_screen_dark.xml" />
|
<AndroidResource Include="Resources\drawable-v23\splash_screen_dark.xml" />
|
||||||
<AndroidResource Include="Resources\layout\SendViewCell.axml" />
|
|
||||||
<AndroidResource Include="Resources\layout\Tabbar.axml" />
|
<AndroidResource Include="Resources\layout\Tabbar.axml" />
|
||||||
<AndroidResource Include="Resources\layout\Toolbar.axml" />
|
<AndroidResource Include="Resources\layout\Toolbar.axml" />
|
||||||
<AndroidResource Include="Resources\mipmap-anydpi-v26\ic_launcher.xml" />
|
<AndroidResource Include="Resources\mipmap-anydpi-v26\ic_launcher.xml" />
|
||||||
@@ -262,12 +263,6 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</AndroidResource>
|
</AndroidResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<AndroidResource Include="Resources\layout\CipherViewCell.axml">
|
|
||||||
<Generator>MSBuild:UpdateGeneratedFiles</Generator>
|
|
||||||
<SubType>Designer</SubType>
|
|
||||||
</AndroidResource>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AndroidResource Include="Resources\xml\app_restrictions.xml">
|
<AndroidResource Include="Resources\xml\app_restrictions.xml">
|
||||||
<Generator>MSBuild:UpdateGeneratedFiles</Generator>
|
<Generator>MSBuild:UpdateGeneratedFiles</Generator>
|
||||||
|
|||||||
@@ -1,242 +0,0 @@
|
|||||||
using Android.App;
|
|
||||||
using Android.Content;
|
|
||||||
using Android.Graphics;
|
|
||||||
using Android.Runtime;
|
|
||||||
using Android.Util;
|
|
||||||
using Android.Views;
|
|
||||||
using Android.Views.InputMethods;
|
|
||||||
using Android.Widget;
|
|
||||||
using Bit.App.Controls;
|
|
||||||
using Bit.App.Utilities;
|
|
||||||
using Bit.Droid.Renderers;
|
|
||||||
using FFImageLoading;
|
|
||||||
using FFImageLoading.Views;
|
|
||||||
using FFImageLoading.Work;
|
|
||||||
using System;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using Xamarin.Forms;
|
|
||||||
using Xamarin.Forms.Platform.Android;
|
|
||||||
|
|
||||||
[assembly: ExportRenderer(typeof(CipherViewCell), typeof(CipherViewCellRenderer))]
|
|
||||||
namespace Bit.Droid.Renderers
|
|
||||||
{
|
|
||||||
public class CipherViewCellRenderer : ViewCellRenderer
|
|
||||||
{
|
|
||||||
private static Typeface _faTypeface;
|
|
||||||
private static Typeface _miTypeface;
|
|
||||||
private static Android.Graphics.Color _textColor;
|
|
||||||
private static Android.Graphics.Color _mutedColor;
|
|
||||||
private static Android.Graphics.Color _disabledIconColor;
|
|
||||||
private static bool _usingLightTheme;
|
|
||||||
|
|
||||||
private AndroidCipherCell _cell;
|
|
||||||
|
|
||||||
protected override Android.Views.View GetCellCore(Cell item, Android.Views.View convertView,
|
|
||||||
ViewGroup parent, Context context)
|
|
||||||
{
|
|
||||||
// TODO expand beyond light/dark detection once we support custom theme switching without app restart
|
|
||||||
var themeChanged = _usingLightTheme != ThemeManager.UsingLightTheme;
|
|
||||||
if (_faTypeface == null)
|
|
||||||
{
|
|
||||||
_faTypeface = Typeface.CreateFromAsset(context.Assets, "FontAwesome.ttf");
|
|
||||||
}
|
|
||||||
if (_miTypeface == null)
|
|
||||||
{
|
|
||||||
_miTypeface = Typeface.CreateFromAsset(context.Assets, "MaterialIcons_Regular.ttf");
|
|
||||||
}
|
|
||||||
if (_textColor == default(Android.Graphics.Color) || themeChanged)
|
|
||||||
{
|
|
||||||
_textColor = ThemeManager.GetResourceColor("TextColor").ToAndroid();
|
|
||||||
}
|
|
||||||
if (_mutedColor == default(Android.Graphics.Color) || themeChanged)
|
|
||||||
{
|
|
||||||
_mutedColor = ThemeManager.GetResourceColor("MutedColor").ToAndroid();
|
|
||||||
}
|
|
||||||
if (_disabledIconColor == default(Android.Graphics.Color) || themeChanged)
|
|
||||||
{
|
|
||||||
_disabledIconColor = ThemeManager.GetResourceColor("DisabledIconColor").ToAndroid();
|
|
||||||
}
|
|
||||||
_usingLightTheme = ThemeManager.UsingLightTheme;
|
|
||||||
|
|
||||||
var cipherCell = item as CipherViewCell;
|
|
||||||
_cell = convertView as AndroidCipherCell;
|
|
||||||
if (_cell == null)
|
|
||||||
{
|
|
||||||
_cell = new AndroidCipherCell(context, cipherCell, _faTypeface, _miTypeface);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_cell.CipherViewCell.PropertyChanged -= CellPropertyChanged;
|
|
||||||
}
|
|
||||||
cipherCell.PropertyChanged += CellPropertyChanged;
|
|
||||||
_cell.UpdateCell(cipherCell);
|
|
||||||
_cell.UpdateColors(_textColor, _mutedColor, _disabledIconColor);
|
|
||||||
return _cell;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CellPropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
var cipherCell = sender as CipherViewCell;
|
|
||||||
_cell.CipherViewCell = cipherCell;
|
|
||||||
if (e.PropertyName == CipherViewCell.CipherProperty.PropertyName)
|
|
||||||
{
|
|
||||||
_cell.UpdateCell(cipherCell);
|
|
||||||
}
|
|
||||||
else if (e.PropertyName == CipherViewCell.WebsiteIconsEnabledProperty.PropertyName)
|
|
||||||
{
|
|
||||||
_cell.UpdateIconImage(cipherCell);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AndroidCipherCell : LinearLayout, INativeElementView
|
|
||||||
{
|
|
||||||
private readonly Typeface _faTypeface;
|
|
||||||
private readonly Typeface _miTypeface;
|
|
||||||
|
|
||||||
private IScheduledWork _currentTask;
|
|
||||||
|
|
||||||
public AndroidCipherCell(Context context, CipherViewCell cipherView, Typeface faTypeface, Typeface miTypeface)
|
|
||||||
: base(context)
|
|
||||||
{
|
|
||||||
CipherViewCell = cipherView;
|
|
||||||
_faTypeface = faTypeface;
|
|
||||||
_miTypeface = miTypeface;
|
|
||||||
|
|
||||||
var view = (context as Activity).LayoutInflater.Inflate(Resource.Layout.CipherViewCell, null);
|
|
||||||
IconImage = view.FindViewById<IconImageView>(Resource.Id.CipherCellIconImage);
|
|
||||||
Icon = view.FindViewById<TextView>(Resource.Id.CipherCellIcon);
|
|
||||||
Name = view.FindViewById<TextView>(Resource.Id.CipherCellName);
|
|
||||||
SubTitle = view.FindViewById<TextView>(Resource.Id.CipherCellSubTitle);
|
|
||||||
SharedIcon = view.FindViewById<TextView>(Resource.Id.CipherCellSharedIcon);
|
|
||||||
AttachmentsIcon = view.FindViewById<TextView>(Resource.Id.CipherCellAttachmentsIcon);
|
|
||||||
MoreButton = view.FindViewById<Android.Widget.Button>(Resource.Id.CipherCellButton);
|
|
||||||
MoreButton.Click += MoreButton_Click;
|
|
||||||
|
|
||||||
Icon.Typeface = _faTypeface;
|
|
||||||
SharedIcon.Typeface = _faTypeface;
|
|
||||||
AttachmentsIcon.Typeface = _faTypeface;
|
|
||||||
MoreButton.Typeface = _miTypeface;
|
|
||||||
|
|
||||||
var small = (float)Device.GetNamedSize(NamedSize.Small, typeof(Label));
|
|
||||||
Icon.SetTextSize(ComplexUnitType.Pt, 10);
|
|
||||||
Name.SetTextSize(ComplexUnitType.Sp, (float)Device.GetNamedSize(NamedSize.Medium, typeof(Label)));
|
|
||||||
SubTitle.SetTextSize(ComplexUnitType.Sp, small);
|
|
||||||
SharedIcon.SetTextSize(ComplexUnitType.Sp, small);
|
|
||||||
AttachmentsIcon.SetTextSize(ComplexUnitType.Sp, small);
|
|
||||||
MoreButton.SetTextSize(ComplexUnitType.Sp, 25);
|
|
||||||
|
|
||||||
AddView(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CipherViewCell CipherViewCell { get; set; }
|
|
||||||
public Element Element => CipherViewCell;
|
|
||||||
|
|
||||||
public IconImageView IconImage { get; set; }
|
|
||||||
public TextView Icon { get; set; }
|
|
||||||
public TextView Name { get; set; }
|
|
||||||
public TextView SubTitle { get; set; }
|
|
||||||
public TextView SharedIcon { get; set; }
|
|
||||||
public TextView AttachmentsIcon { get; set; }
|
|
||||||
public Android.Widget.Button MoreButton { get; set; }
|
|
||||||
|
|
||||||
public void UpdateCell(CipherViewCell cipherCell)
|
|
||||||
{
|
|
||||||
UpdateIconImage(cipherCell);
|
|
||||||
|
|
||||||
var cipher = cipherCell.Cipher;
|
|
||||||
Name.Text = cipher.Name;
|
|
||||||
if (!string.IsNullOrWhiteSpace(cipher.SubTitle))
|
|
||||||
{
|
|
||||||
SubTitle.Text = cipher.SubTitle;
|
|
||||||
SubTitle.Visibility = ViewStates.Visible;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SubTitle.Visibility = ViewStates.Invisible;
|
|
||||||
}
|
|
||||||
SharedIcon.Visibility = cipher.Shared ? ViewStates.Visible : ViewStates.Gone;
|
|
||||||
AttachmentsIcon.Visibility = cipher.HasAttachments ? ViewStates.Visible : ViewStates.Gone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateIconImage(CipherViewCell cipherCell)
|
|
||||||
{
|
|
||||||
if (_currentTask != null && !_currentTask.IsCancelled && !_currentTask.IsCompleted)
|
|
||||||
{
|
|
||||||
_currentTask.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
var cipher = cipherCell.Cipher;
|
|
||||||
|
|
||||||
var iconImage = cipherCell.GetIconImage(cipher);
|
|
||||||
if (iconImage.Item2 != null)
|
|
||||||
{
|
|
||||||
IconImage.SetImageResource(Resource.Drawable.login);
|
|
||||||
IconImage.Visibility = ViewStates.Visible;
|
|
||||||
Icon.Visibility = ViewStates.Gone;
|
|
||||||
_currentTask = ImageService.Instance.LoadUrl(iconImage.Item2).DownSample(64).Into(IconImage);
|
|
||||||
IconImage.Key = iconImage.Item2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IconImage.Visibility = ViewStates.Gone;
|
|
||||||
Icon.Visibility = ViewStates.Visible;
|
|
||||||
Icon.Text = iconImage.Item1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateColors(Android.Graphics.Color textColor, Android.Graphics.Color mutedColor,
|
|
||||||
Android.Graphics.Color iconDisabledColor)
|
|
||||||
{
|
|
||||||
Name.SetTextColor(textColor);
|
|
||||||
SubTitle.SetTextColor(mutedColor);
|
|
||||||
Icon.SetTextColor(mutedColor);
|
|
||||||
SharedIcon.SetTextColor(mutedColor);
|
|
||||||
AttachmentsIcon.SetTextColor(mutedColor);
|
|
||||||
MoreButton.SetTextColor(iconDisabledColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void MoreButton_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (CipherViewCell.ButtonCommand?.CanExecute(CipherViewCell.Cipher) ?? false)
|
|
||||||
{
|
|
||||||
CipherViewCell.ButtonCommand.Execute(CipherViewCell.Cipher);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
MoreButton.Click -= MoreButton_Click;
|
|
||||||
}
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Android.Runtime.Preserve(AllMembers = true)]
|
|
||||||
[Register("bit.droid.renderers.IconImageView")]
|
|
||||||
public class IconImageView : ImageViewAsync
|
|
||||||
{
|
|
||||||
public IconImageView(Context context) : base(context)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public IconImageView(IntPtr javaReference, JniHandleOwnership transfer)
|
|
||||||
: base(javaReference, transfer)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public IconImageView(Context context, IAttributeSet attrs)
|
|
||||||
: base(context, attrs)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public string Key { get; set; }
|
|
||||||
|
|
||||||
protected override void JavaFinalize()
|
|
||||||
{
|
|
||||||
SetImageDrawable(null);
|
|
||||||
SetImageBitmap(null);
|
|
||||||
ImageService.Instance.InvalidateCacheEntryAsync(Key, FFImageLoading.Cache.CacheType.Memory);
|
|
||||||
base.JavaFinalize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
43
src/Android/Renderers/ExtendedGridRenderer.cs
Normal file
43
src/Android/Renderers/ExtendedGridRenderer.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
using Android.Content;
|
||||||
|
using Bit.App.Controls;
|
||||||
|
using Bit.App.Utilities;
|
||||||
|
using Bit.Droid.Renderers;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
using Xamarin.Forms.Platform.Android;
|
||||||
|
|
||||||
|
[assembly: ExportRenderer(typeof(ExtendedGrid), typeof(ExtendedGridRenderer))]
|
||||||
|
namespace Bit.Droid.Renderers
|
||||||
|
{
|
||||||
|
public class ExtendedGridRenderer : ViewRenderer
|
||||||
|
{
|
||||||
|
private static int? _bgResId;
|
||||||
|
|
||||||
|
public ExtendedGridRenderer(Context context) : base(context) { }
|
||||||
|
|
||||||
|
protected override void OnElementChanged(ElementChangedEventArgs<View> elementChangedEvent)
|
||||||
|
{
|
||||||
|
base.OnElementChanged(elementChangedEvent);
|
||||||
|
if (elementChangedEvent.NewElement != null)
|
||||||
|
{
|
||||||
|
SetBackgroundResource(GetBgResId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetBgResId()
|
||||||
|
{
|
||||||
|
if (_bgResId == null)
|
||||||
|
{
|
||||||
|
if (ThemeManager.GetTheme(true) == "nord")
|
||||||
|
{
|
||||||
|
_bgResId = Resource.Drawable.list_item_bg_nord;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_bgResId ??= ThemeManager.UsingLightTheme ? Resource.Drawable.list_item_bg :
|
||||||
|
Resource.Drawable.list_item_bg_dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _bgResId.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
using Android.Content;
|
|
||||||
using Android.Views;
|
|
||||||
using Bit.App.Controls;
|
|
||||||
using Bit.Droid.Renderers;
|
|
||||||
using Xamarin.Forms;
|
|
||||||
using Xamarin.Forms.Platform.Android;
|
|
||||||
|
|
||||||
[assembly: ExportRenderer(typeof(ExtendedListView), typeof(ExtendedListViewRenderer))]
|
|
||||||
namespace Bit.Droid.Renderers
|
|
||||||
{
|
|
||||||
public class ExtendedListViewRenderer : ListViewRenderer
|
|
||||||
{
|
|
||||||
public ExtendedListViewRenderer(Context context)
|
|
||||||
: base(context)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
|
|
||||||
{
|
|
||||||
base.OnElementChanged(e);
|
|
||||||
if (Control != null && e.NewElement != null && e.NewElement is ExtendedListView listView)
|
|
||||||
{
|
|
||||||
// Pad for FAB
|
|
||||||
Control.SetPadding(0, 0, 0, 170);
|
|
||||||
Control.SetClipToPadding(false);
|
|
||||||
Control.ScrollBarStyle = ScrollbarStyles.OutsideOverlay;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
43
src/Android/Renderers/ExtendedStackLayoutRenderer.cs
Normal file
43
src/Android/Renderers/ExtendedStackLayoutRenderer.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
using Android.Content;
|
||||||
|
using Bit.App.Controls;
|
||||||
|
using Bit.App.Utilities;
|
||||||
|
using Bit.Droid.Renderers;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
using Xamarin.Forms.Platform.Android;
|
||||||
|
|
||||||
|
[assembly: ExportRenderer(typeof(ExtendedStackLayout), typeof(ExtendedStackLayoutRenderer))]
|
||||||
|
namespace Bit.Droid.Renderers
|
||||||
|
{
|
||||||
|
public class ExtendedStackLayoutRenderer : ViewRenderer
|
||||||
|
{
|
||||||
|
private static int? _bgResId;
|
||||||
|
|
||||||
|
public ExtendedStackLayoutRenderer(Context context) : base(context) { }
|
||||||
|
|
||||||
|
protected override void OnElementChanged(ElementChangedEventArgs<View> elementChangedEvent)
|
||||||
|
{
|
||||||
|
base.OnElementChanged(elementChangedEvent);
|
||||||
|
if (elementChangedEvent.NewElement != null)
|
||||||
|
{
|
||||||
|
SetBackgroundResource(GetBgResId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetBgResId()
|
||||||
|
{
|
||||||
|
if (_bgResId == null)
|
||||||
|
{
|
||||||
|
if (ThemeManager.GetTheme(true) == "nord")
|
||||||
|
{
|
||||||
|
_bgResId = Resource.Drawable.list_item_bg_nord;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_bgResId ??= ThemeManager.UsingLightTheme ? Resource.Drawable.list_item_bg :
|
||||||
|
Resource.Drawable.list_item_bg_dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _bgResId.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,210 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using Android.App;
|
|
||||||
using Android.Content;
|
|
||||||
using Android.Graphics;
|
|
||||||
using Android.Util;
|
|
||||||
using Android.Views;
|
|
||||||
using Android.Widget;
|
|
||||||
using Bit.App.Controls;
|
|
||||||
using Bit.App.Utilities;
|
|
||||||
using Bit.Droid.Renderers;
|
|
||||||
using FFImageLoading.Work;
|
|
||||||
using Xamarin.Forms;
|
|
||||||
using Xamarin.Forms.Platform.Android;
|
|
||||||
using Button = Android.Widget.Button;
|
|
||||||
using Color = Android.Graphics.Color;
|
|
||||||
using View = Android.Views.View;
|
|
||||||
|
|
||||||
[assembly: ExportRenderer(typeof(SendViewCell), typeof(SendViewCellRenderer))]
|
|
||||||
namespace Bit.Droid.Renderers
|
|
||||||
{
|
|
||||||
public class SendViewCellRenderer : ViewCellRenderer
|
|
||||||
{
|
|
||||||
private static Typeface _faTypeface;
|
|
||||||
private static Typeface _miTypeface;
|
|
||||||
private static Color _textColor;
|
|
||||||
private static Color _mutedColor;
|
|
||||||
private static Color _disabledIconColor;
|
|
||||||
private static bool _usingLightTheme;
|
|
||||||
|
|
||||||
private AndroidSendCell _cell;
|
|
||||||
|
|
||||||
protected override View GetCellCore(Cell item, View convertView,
|
|
||||||
ViewGroup parent, Context context)
|
|
||||||
{
|
|
||||||
// TODO expand beyond light/dark detection once we support custom theme switching without app restart
|
|
||||||
var themeChanged = _usingLightTheme != ThemeManager.UsingLightTheme;
|
|
||||||
if (_faTypeface == null)
|
|
||||||
{
|
|
||||||
_faTypeface = Typeface.CreateFromAsset(context.Assets, "FontAwesome.ttf");
|
|
||||||
}
|
|
||||||
if (_miTypeface == null)
|
|
||||||
{
|
|
||||||
_miTypeface = Typeface.CreateFromAsset(context.Assets, "MaterialIcons_Regular.ttf");
|
|
||||||
}
|
|
||||||
if (_textColor == default(Color) || themeChanged)
|
|
||||||
{
|
|
||||||
_textColor = ThemeManager.GetResourceColor("TextColor").ToAndroid();
|
|
||||||
}
|
|
||||||
if (_mutedColor == default(Color) || themeChanged)
|
|
||||||
{
|
|
||||||
_mutedColor = ThemeManager.GetResourceColor("MutedColor").ToAndroid();
|
|
||||||
}
|
|
||||||
if (_disabledIconColor == default(Color) || themeChanged)
|
|
||||||
{
|
|
||||||
_disabledIconColor = ThemeManager.GetResourceColor("DisabledIconColor").ToAndroid();
|
|
||||||
}
|
|
||||||
_usingLightTheme = ThemeManager.UsingLightTheme;
|
|
||||||
|
|
||||||
var sendCell = item as SendViewCell;
|
|
||||||
_cell = convertView as AndroidSendCell;
|
|
||||||
if (_cell == null)
|
|
||||||
{
|
|
||||||
_cell = new AndroidSendCell(context, sendCell, _faTypeface, _miTypeface);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_cell.SendViewCell.PropertyChanged -= CellPropertyChanged;
|
|
||||||
}
|
|
||||||
sendCell.PropertyChanged += CellPropertyChanged;
|
|
||||||
_cell.UpdateCell(sendCell);
|
|
||||||
_cell.UpdateColors(_textColor, _mutedColor, _disabledIconColor);
|
|
||||||
return _cell;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CellPropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
var sendCell = sender as SendViewCell;
|
|
||||||
_cell.SendViewCell = sendCell;
|
|
||||||
if (e.PropertyName == SendViewCell.SendProperty.PropertyName)
|
|
||||||
{
|
|
||||||
_cell.UpdateCell(sendCell);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AndroidSendCell : LinearLayout, INativeElementView
|
|
||||||
{
|
|
||||||
private readonly Typeface _faTypeface;
|
|
||||||
private readonly Typeface _miTypeface;
|
|
||||||
|
|
||||||
private IScheduledWork _currentTask;
|
|
||||||
|
|
||||||
public AndroidSendCell(Context context, SendViewCell sendView, Typeface faTypeface, Typeface miTypeface)
|
|
||||||
: base(context)
|
|
||||||
{
|
|
||||||
SendViewCell = sendView;
|
|
||||||
_faTypeface = faTypeface;
|
|
||||||
_miTypeface = miTypeface;
|
|
||||||
|
|
||||||
var view = (context as Activity).LayoutInflater.Inflate(Resource.Layout.SendViewCell, null);
|
|
||||||
Icon = view.FindViewById<TextView>(Resource.Id.SendCellIcon);
|
|
||||||
Name = view.FindViewById<TextView>(Resource.Id.SendCellName);
|
|
||||||
SubTitle = view.FindViewById<TextView>(Resource.Id.SendCellSubTitle);
|
|
||||||
DisabledIcon = view.FindViewById<TextView>(Resource.Id.SendCellDisabledIcon);
|
|
||||||
HasPasswordIcon = view.FindViewById<TextView>(Resource.Id.SendCellHasPasswordIcon);
|
|
||||||
MaxAccessCountReachedIcon = view.FindViewById<TextView>(Resource.Id.SendCellMaxAccessCountReachedIcon);
|
|
||||||
ExpiredIcon = view.FindViewById<TextView>(Resource.Id.SendCellExpiredIcon);
|
|
||||||
PendingDeleteIcon = view.FindViewById<TextView>(Resource.Id.SendCellPendingDeleteIcon);
|
|
||||||
MoreButton = view.FindViewById<Button>(Resource.Id.SendCellButton);
|
|
||||||
MoreButton.Click += MoreButton_Click;
|
|
||||||
|
|
||||||
Icon.Typeface = _faTypeface;
|
|
||||||
DisabledIcon.Typeface = _faTypeface;
|
|
||||||
HasPasswordIcon.Typeface = _faTypeface;
|
|
||||||
MaxAccessCountReachedIcon.Typeface = _faTypeface;
|
|
||||||
ExpiredIcon.Typeface = _faTypeface;
|
|
||||||
PendingDeleteIcon.Typeface = _faTypeface;
|
|
||||||
MoreButton.Typeface = _miTypeface;
|
|
||||||
|
|
||||||
var small = (float)Device.GetNamedSize(NamedSize.Small, typeof(Label));
|
|
||||||
Icon.SetTextSize(ComplexUnitType.Pt, 10);
|
|
||||||
Name.SetTextSize(ComplexUnitType.Sp, (float)Device.GetNamedSize(NamedSize.Medium, typeof(Label)));
|
|
||||||
SubTitle.SetTextSize(ComplexUnitType.Sp, small);
|
|
||||||
DisabledIcon.SetTextSize(ComplexUnitType.Sp, small);
|
|
||||||
HasPasswordIcon.SetTextSize(ComplexUnitType.Sp, small);
|
|
||||||
MaxAccessCountReachedIcon.SetTextSize(ComplexUnitType.Sp, small);
|
|
||||||
ExpiredIcon.SetTextSize(ComplexUnitType.Sp, small);
|
|
||||||
PendingDeleteIcon.SetTextSize(ComplexUnitType.Sp, small);
|
|
||||||
MoreButton.SetTextSize(ComplexUnitType.Sp, 25);
|
|
||||||
|
|
||||||
if (!SendViewCell.ShowOptions)
|
|
||||||
{
|
|
||||||
MoreButton.Visibility = ViewStates.Gone;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddView(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SendViewCell SendViewCell { get; set; }
|
|
||||||
public Element Element => SendViewCell;
|
|
||||||
|
|
||||||
public TextView Icon { get; set; }
|
|
||||||
public TextView Name { get; set; }
|
|
||||||
public TextView SubTitle { get; set; }
|
|
||||||
public TextView DisabledIcon { get; set; }
|
|
||||||
public TextView HasPasswordIcon { get; set; }
|
|
||||||
public TextView MaxAccessCountReachedIcon { get; set; }
|
|
||||||
public TextView ExpiredIcon { get; set; }
|
|
||||||
public TextView PendingDeleteIcon { get; set; }
|
|
||||||
public Button MoreButton { get; set; }
|
|
||||||
|
|
||||||
public void UpdateCell(SendViewCell sendCell)
|
|
||||||
{
|
|
||||||
UpdateIconImage(sendCell);
|
|
||||||
|
|
||||||
var send = sendCell.Send;
|
|
||||||
Name.Text = send.Name;
|
|
||||||
SubTitle.Text = send.DisplayDate;
|
|
||||||
DisabledIcon.Visibility = send.Disabled ? ViewStates.Visible : ViewStates.Gone;
|
|
||||||
HasPasswordIcon.Visibility = send.HasPassword ? ViewStates.Visible : ViewStates.Gone;
|
|
||||||
MaxAccessCountReachedIcon.Visibility = send.MaxAccessCountReached ? ViewStates.Visible : ViewStates.Gone;
|
|
||||||
ExpiredIcon.Visibility = send.Expired ? ViewStates.Visible : ViewStates.Gone;
|
|
||||||
PendingDeleteIcon.Visibility = send.PendingDelete ? ViewStates.Visible : ViewStates.Gone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateIconImage(SendViewCell sendCell)
|
|
||||||
{
|
|
||||||
if (_currentTask != null && !_currentTask.IsCancelled && !_currentTask.IsCompleted)
|
|
||||||
{
|
|
||||||
_currentTask.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
var send = sendCell.Send;
|
|
||||||
var iconImage = sendCell.GetIconImage(send);
|
|
||||||
Icon.Text = iconImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateColors(Color textColor, Color mutedColor,
|
|
||||||
Color iconDisabledColor)
|
|
||||||
{
|
|
||||||
Name.SetTextColor(textColor);
|
|
||||||
SubTitle.SetTextColor(mutedColor);
|
|
||||||
Icon.SetTextColor(mutedColor);
|
|
||||||
DisabledIcon.SetTextColor(mutedColor);
|
|
||||||
HasPasswordIcon.SetTextColor(mutedColor);
|
|
||||||
MaxAccessCountReachedIcon.SetTextColor(mutedColor);
|
|
||||||
ExpiredIcon.SetTextColor(mutedColor);
|
|
||||||
PendingDeleteIcon.SetTextColor(mutedColor);
|
|
||||||
MoreButton.SetTextColor(iconDisabledColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void MoreButton_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (SendViewCell.ButtonCommand?.CanExecute(SendViewCell.Send) ?? false)
|
|
||||||
{
|
|
||||||
SendViewCell.ButtonCommand.Execute(SendViewCell.Send);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
MoreButton.Click -= MoreButton_Click;
|
|
||||||
}
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
7
src/Android/Resources/drawable/list_item_bg.xml
Normal file
7
src/Android/Resources/drawable/list_item_bg.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:color="@color/itemPressed">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@android:id/mask"
|
||||||
|
android:drawable="@android:color/white" />
|
||||||
|
</ripple>
|
||||||
7
src/Android/Resources/drawable/list_item_bg_dark.xml
Normal file
7
src/Android/Resources/drawable/list_item_bg_dark.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:color="@color/dark_primary">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@android:id/mask"
|
||||||
|
android:drawable="@android:color/white" />
|
||||||
|
</ripple>
|
||||||
7
src/Android/Resources/drawable/list_item_bg_nord.xml
Normal file
7
src/Android/Resources/drawable/list_item_bg_nord.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:color="@color/nord_primary">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@android:id/mask"
|
||||||
|
android:drawable="@android:color/white" />
|
||||||
|
</ripple>
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:minHeight="44dp"
|
|
||||||
android:gravity="center_vertical">
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:paddingLeft="2.2dp">
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="39.8dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:gravity="center">
|
|
||||||
<bit.droid.renderers.IconImageView
|
|
||||||
android:id="@+id/CipherCellIconImage"
|
|
||||||
android:layout_width="22dp"
|
|
||||||
android:layout_height="22dp"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:gravity="center" />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/CipherCellIcon"
|
|
||||||
android:layout_width="26dp"
|
|
||||||
android:layout_height="26dp"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="[X]" />
|
|
||||||
</LinearLayout>
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/CipherCellContent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingVertical="7.65dp">
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/CipherCellContentTop"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/CipherCellName"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:text="Name" />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/CipherCellSharedIcon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:text="" />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/CipherCellAttachmentsIcon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:text="" />
|
|
||||||
</LinearLayout>
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/CipherCellSubTitle"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:text="SubTitle" />
|
|
||||||
</LinearLayout>
|
|
||||||
<Button
|
|
||||||
android:id="@+id/CipherCellButton"
|
|
||||||
android:layout_width="37dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:text=""
|
|
||||||
android:gravity="center"
|
|
||||||
android:padding="0dp"
|
|
||||||
android:background="@android:color/transparent" />
|
|
||||||
</LinearLayout>
|
|
||||||
</RelativeLayout>
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:minHeight="44dp"
|
|
||||||
android:gravity="center_vertical">
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:paddingLeft="2.2dp">
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="39.8dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:gravity="center">
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/SendCellIcon"
|
|
||||||
android:layout_width="26dp"
|
|
||||||
android:layout_height="26dp"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="[X]" />
|
|
||||||
</LinearLayout>
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/SendCellContent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingVertical="7.65dp">
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/SendCellContentTop"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/SendCellName"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:text="Name" />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/SendCellDisabledIcon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:text="" />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/SendCellHasPasswordIcon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:text="" />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/SendCellMaxAccessCountReachedIcon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:text="" />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/SendCellExpiredIcon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:text="" />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/SendCellPendingDeleteIcon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:text="" />
|
|
||||||
</LinearLayout>
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/SendCellSubTitle"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:text="SubTitle" />
|
|
||||||
</LinearLayout>
|
|
||||||
<Button
|
|
||||||
android:id="@+id/SendCellButton"
|
|
||||||
android:layout_width="37dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:text=""
|
|
||||||
android:gravity="center"
|
|
||||||
android:padding="0dp"
|
|
||||||
android:background="@android:color/transparent" />
|
|
||||||
</LinearLayout>
|
|
||||||
</RelativeLayout>
|
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
<color name="primary">#175DDC</color>
|
<color name="primary">#175DDC</color>
|
||||||
<color name="notificationBar">#1452BC</color>
|
<color name="notificationBar">#1452BC</color>
|
||||||
<color name="border">#dddddd</color>
|
<color name="border">#dddddd</color>
|
||||||
|
<color name="itemPressed">#bbbbbb</color>
|
||||||
|
|
||||||
<!-- Dark theme -->
|
<!-- Dark theme -->
|
||||||
<color name="dark_primary">#52bdfb</color>
|
<color name="dark_primary">#52bdfb</color>
|
||||||
|
|||||||
@@ -15,9 +15,9 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="4.2.0" />
|
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="4.2.0" />
|
||||||
<PackageReference Include="Plugin.Fingerprint" Version="2.1.4" />
|
<PackageReference Include="Plugin.Fingerprint" Version="2.1.4" />
|
||||||
<PackageReference Include="Xamarin.Essentials" Version="1.5.3.2" />
|
<PackageReference Include="Xamarin.Essentials" Version="1.6.1" />
|
||||||
<PackageReference Include="Xamarin.FFImageLoading.Forms" Version="2.4.11.982" />
|
<PackageReference Include="Xamarin.FFImageLoading.Forms" Version="2.4.11.982" />
|
||||||
<PackageReference Include="Xamarin.Forms" Version="4.5.0.725" />
|
<PackageReference Include="Xamarin.Forms" Version="5.0.0.2012" />
|
||||||
<PackageReference Include="ZXing.Net.Mobile" Version="2.4.1" />
|
<PackageReference Include="ZXing.Net.Mobile" Version="2.4.1" />
|
||||||
<PackageReference Include="ZXing.Net.Mobile.Forms" Version="2.4.1" />
|
<PackageReference Include="ZXing.Net.Mobile.Forms" Version="2.4.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@@ -411,4 +411,4 @@
|
|||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,114 +1,111 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
|
<controls:ExtendedGrid xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
x:Class="Bit.App.Controls.CipherViewCell"
|
x:Class="Bit.App.Controls.CipherViewCell"
|
||||||
xmlns:controls="clr-namespace:Bit.App.Controls"
|
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||||
xmlns:u="clr-namespace:Bit.App.Utilities"
|
xmlns:u="clr-namespace:Bit.App.Utilities"
|
||||||
xmlns:ff="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms">
|
xmlns:ff="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
|
||||||
|
StyleClass="list-row, list-row-platform"
|
||||||
|
RowSpacing="0"
|
||||||
|
ColumnSpacing="0"
|
||||||
|
x:DataType="controls:CipherViewCellViewModel">
|
||||||
|
|
||||||
<Grid
|
<Grid.Resources>
|
||||||
x:Name="_grid"
|
<u:IconGlyphConverter x:Key="iconGlyphConverter"/>
|
||||||
StyleClass="list-row, list-row-platform"
|
<u:IconImageConverter x:Key="iconImageConverter"/>
|
||||||
RowSpacing="0"
|
<u:InverseBoolConverter x:Key="inverseBool" />
|
||||||
ColumnSpacing="0"
|
</Grid.Resources>
|
||||||
x:DataType="controls:CipherViewCellViewModel">
|
|
||||||
|
|
||||||
<Grid.BindingContext>
|
<Grid.RowDefinitions>
|
||||||
<controls:CipherViewCellViewModel />
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.BindingContext>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="40" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="60" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<controls:FaLabel
|
||||||
|
Grid.Column="0"
|
||||||
|
HorizontalOptions="Center"
|
||||||
|
VerticalOptions="Center"
|
||||||
|
StyleClass="list-icon, list-icon-platform"
|
||||||
|
IsVisible="{Binding ShowIconImage, Converter={StaticResource inverseBool}}"
|
||||||
|
Text="{Binding Cipher, Converter={StaticResource iconGlyphConverter}}"
|
||||||
|
AutomationProperties.IsInAccessibleTree="False" />
|
||||||
|
|
||||||
|
<ff:CachedImage
|
||||||
|
Grid.Column="0"
|
||||||
|
BitmapOptimizations="True"
|
||||||
|
ErrorPlaceholder="login.png"
|
||||||
|
LoadingPlaceholder="login.png"
|
||||||
|
HorizontalOptions="Center"
|
||||||
|
VerticalOptions="Center"
|
||||||
|
WidthRequest="22"
|
||||||
|
HeightRequest="22"
|
||||||
|
IsVisible="{Binding ShowIconImage}"
|
||||||
|
Source="{Binding Cipher, Converter={StaticResource iconImageConverter}}"
|
||||||
|
AutomationProperties.IsInAccessibleTree="False" />
|
||||||
|
|
||||||
|
<Grid RowSpacing="0" ColumnSpacing="0" Grid.Row="0" Grid.Column="1" VerticalOptions="Center" Padding="0, 7">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="40" />
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
<ColumnDefinition Width="60" />
|
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<Label
|
||||||
|
LineBreakMode="TailTruncation"
|
||||||
|
Grid.Column="0"
|
||||||
|
Grid.Row="0"
|
||||||
|
StyleClass="list-title, list-title-platform"
|
||||||
|
Text="{Binding Cipher.Name}" />
|
||||||
|
<Label
|
||||||
|
LineBreakMode="TailTruncation"
|
||||||
|
Grid.Column="0"
|
||||||
|
Grid.Row="1"
|
||||||
|
Grid.ColumnSpan="3"
|
||||||
|
StyleClass="list-subtitle, list-subtitle-platform"
|
||||||
|
Text="{Binding Cipher.SubTitle}" />
|
||||||
<controls:FaLabel
|
<controls:FaLabel
|
||||||
x:Name="_icon"
|
Grid.Column="1"
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.Column="0"
|
HorizontalOptions="Start"
|
||||||
HorizontalOptions="Center"
|
|
||||||
VerticalOptions="Center"
|
VerticalOptions="Center"
|
||||||
StyleClass="list-icon, list-icon-platform"
|
StyleClass="list-title-icon"
|
||||||
AutomationProperties.IsInAccessibleTree="False" />
|
Margin="5, 0, 0, 0"
|
||||||
|
Text=""
|
||||||
<ff:CachedImage
|
IsVisible="{Binding Cipher.Shared, Mode=OneTime}"
|
||||||
x:Name="_image"
|
|
||||||
Grid.Row="0"
|
|
||||||
Grid.Column="0"
|
|
||||||
BitmapOptimizations="True"
|
|
||||||
ErrorPlaceholder="login.png"
|
|
||||||
HorizontalOptions="Center"
|
|
||||||
VerticalOptions="Center"
|
|
||||||
WidthRequest="22"
|
|
||||||
HeightRequest="22"
|
|
||||||
IsVisible="False"
|
|
||||||
AutomationProperties.IsInAccessibleTree="False" />
|
|
||||||
|
|
||||||
<Grid RowSpacing="0" ColumnSpacing="0" Grid.Row="0" Grid.Column="1" VerticalOptions="Center">
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
|
|
||||||
<Label
|
|
||||||
LineBreakMode="TailTruncation"
|
|
||||||
Grid.Column="0"
|
|
||||||
Grid.Row="0"
|
|
||||||
StyleClass="list-title, list-title-platform"
|
|
||||||
Text="{Binding Cipher.Name, Mode=OneWay}" />
|
|
||||||
<Label
|
|
||||||
LineBreakMode="TailTruncation"
|
|
||||||
Grid.Column="0"
|
|
||||||
Grid.Row="1"
|
|
||||||
Grid.ColumnSpan="3"
|
|
||||||
StyleClass="list-subtitle, list-subtitle-platform"
|
|
||||||
Text="{Binding Cipher.SubTitle, Mode=OneWay}" />
|
|
||||||
<controls:FaLabel
|
|
||||||
Grid.Column="1"
|
|
||||||
Grid.Row="0"
|
|
||||||
HorizontalOptions="Start"
|
|
||||||
VerticalOptions="Center"
|
|
||||||
StyleClass="list-title-icon"
|
|
||||||
Margin="5, 0, 0, 0"
|
|
||||||
Text=""
|
|
||||||
IsVisible="{Binding Cipher.Shared, Mode=OneWay}"
|
|
||||||
AutomationProperties.IsInAccessibleTree="True"
|
|
||||||
AutomationProperties.Name="{u:I18n Shared}" />
|
|
||||||
<controls:FaLabel
|
|
||||||
Grid.Column="2"
|
|
||||||
Grid.Row="0"
|
|
||||||
HorizontalOptions="Start"
|
|
||||||
VerticalOptions="Center"
|
|
||||||
StyleClass="list-title-icon"
|
|
||||||
Margin="5, 0, 0, 0"
|
|
||||||
Text=""
|
|
||||||
IsVisible="{Binding Cipher.HasAttachments, Mode=OneWay}"
|
|
||||||
AutomationProperties.IsInAccessibleTree="True"
|
|
||||||
AutomationProperties.Name="{u:I18n Attachments}" />
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<controls:MiButton
|
|
||||||
Grid.Row="0"
|
|
||||||
Grid.Column="2"
|
|
||||||
Text=""
|
|
||||||
StyleClass="list-row-button, list-row-button-platform, btn-disabled"
|
|
||||||
Clicked="MoreButton_Clicked"
|
|
||||||
VerticalOptions="CenterAndExpand"
|
|
||||||
HorizontalOptions="EndAndExpand"
|
|
||||||
AutomationProperties.IsInAccessibleTree="True"
|
AutomationProperties.IsInAccessibleTree="True"
|
||||||
AutomationProperties.Name="{u:I18n Options}" />
|
AutomationProperties.Name="{u:I18n Shared}" />
|
||||||
|
<controls:FaLabel
|
||||||
|
Grid.Column="2"
|
||||||
|
Grid.Row="0"
|
||||||
|
HorizontalOptions="Start"
|
||||||
|
VerticalOptions="Center"
|
||||||
|
StyleClass="list-title-icon"
|
||||||
|
Margin="5, 0, 0, 0"
|
||||||
|
Text=""
|
||||||
|
IsVisible="{Binding Cipher.HasAttachments, Mode=OneTime}"
|
||||||
|
AutomationProperties.IsInAccessibleTree="True"
|
||||||
|
AutomationProperties.Name="{u:I18n Attachments}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
</ViewCell>
|
<controls:MiButton
|
||||||
|
Grid.Row="0"
|
||||||
|
Grid.Column="2"
|
||||||
|
Text=""
|
||||||
|
StyleClass="list-row-button, list-row-button-platform, btn-disabled"
|
||||||
|
Clicked="MoreButton_Clicked"
|
||||||
|
VerticalOptions="CenterAndExpand"
|
||||||
|
HorizontalOptions="EndAndExpand"
|
||||||
|
AutomationProperties.IsInAccessibleTree="True"
|
||||||
|
AutomationProperties.Name="{u:I18n Options}" />
|
||||||
|
|
||||||
|
</controls:ExtendedGrid>
|
||||||
|
|||||||
@@ -1,45 +1,26 @@
|
|||||||
using Bit.App.Pages;
|
using System;
|
||||||
using Bit.Core;
|
|
||||||
using Bit.Core.Abstractions;
|
|
||||||
using Bit.Core.Enums;
|
|
||||||
using Bit.Core.Models.View;
|
using Bit.Core.Models.View;
|
||||||
using Bit.Core.Utilities;
|
|
||||||
using System;
|
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace Bit.App.Controls
|
namespace Bit.App.Controls
|
||||||
{
|
{
|
||||||
public partial class CipherViewCell : ViewCell
|
public partial class CipherViewCell : ExtendedGrid
|
||||||
{
|
{
|
||||||
public static readonly BindableProperty CipherProperty = BindableProperty.Create(
|
public static readonly BindableProperty CipherProperty = BindableProperty.Create(
|
||||||
nameof(Cipher), typeof(CipherView), typeof(CipherViewCell), default(CipherView), BindingMode.OneWay);
|
nameof(Cipher), typeof(CipherView), typeof(CipherViewCell), default(CipherView), BindingMode.OneWay);
|
||||||
|
|
||||||
public static readonly BindableProperty WebsiteIconsEnabledProperty = BindableProperty.Create(
|
public static readonly BindableProperty WebsiteIconsEnabledProperty = BindableProperty.Create(
|
||||||
nameof(WebsiteIconsEnabled), typeof(bool), typeof(CipherViewCell), true, BindingMode.OneWay);
|
nameof(WebsiteIconsEnabled), typeof(bool?), typeof(CipherViewCell));
|
||||||
|
|
||||||
public static readonly BindableProperty ButtonCommandProperty = BindableProperty.Create(
|
public static readonly BindableProperty ButtonCommandProperty = BindableProperty.Create(
|
||||||
nameof(ButtonCommand), typeof(Command<CipherView>), typeof(CipherViewCell));
|
nameof(ButtonCommand), typeof(Command<CipherView>), typeof(CipherViewCell));
|
||||||
|
|
||||||
private readonly IEnvironmentService _environmentService;
|
|
||||||
|
|
||||||
private CipherViewCellViewModel _viewModel;
|
|
||||||
private bool _usingNativeCell;
|
|
||||||
|
|
||||||
public CipherViewCell()
|
public CipherViewCell()
|
||||||
{
|
{
|
||||||
_environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
|
InitializeComponent();
|
||||||
if (Device.RuntimePlatform == Device.iOS)
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
_viewModel = _grid.BindingContext as CipherViewCellViewModel;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_usingNativeCell = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool WebsiteIconsEnabled
|
public bool? WebsiteIconsEnabled
|
||||||
{
|
{
|
||||||
get => (bool)GetValue(WebsiteIconsEnabledProperty);
|
get => (bool)GetValue(WebsiteIconsEnabledProperty);
|
||||||
set => SetValue(WebsiteIconsEnabledProperty, value);
|
set => SetValue(WebsiteIconsEnabledProperty, value);
|
||||||
@@ -60,130 +41,31 @@ namespace Bit.App.Controls
|
|||||||
protected override void OnPropertyChanged(string propertyName = null)
|
protected override void OnPropertyChanged(string propertyName = null)
|
||||||
{
|
{
|
||||||
base.OnPropertyChanged(propertyName);
|
base.OnPropertyChanged(propertyName);
|
||||||
if (_usingNativeCell)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (propertyName == CipherProperty.PropertyName)
|
if (propertyName == CipherProperty.PropertyName)
|
||||||
{
|
{
|
||||||
_viewModel.Cipher = Cipher;
|
if (Cipher == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BindingContext = new CipherViewCellViewModel(Cipher, WebsiteIconsEnabled ?? false);
|
||||||
}
|
}
|
||||||
}
|
else if (propertyName == WebsiteIconsEnabledProperty.PropertyName)
|
||||||
|
|
||||||
protected override void OnBindingContextChanged()
|
|
||||||
{
|
|
||||||
base.OnBindingContextChanged();
|
|
||||||
if (_usingNativeCell)
|
|
||||||
{
|
{
|
||||||
return;
|
if (Cipher == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
((CipherViewCellViewModel)BindingContext).WebsiteIconsEnabled = WebsiteIconsEnabled ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_image.Source = null;
|
|
||||||
CipherView cipher = null;
|
|
||||||
if (BindingContext is GroupingsPageListItem groupingsPageListItem)
|
|
||||||
{
|
|
||||||
cipher = groupingsPageListItem.Cipher;
|
|
||||||
}
|
|
||||||
else if (BindingContext is CipherView cv)
|
|
||||||
{
|
|
||||||
cipher = cv;
|
|
||||||
}
|
|
||||||
if (cipher != null)
|
|
||||||
{
|
|
||||||
var iconImage = GetIconImage(cipher);
|
|
||||||
if (iconImage.Item2 != null)
|
|
||||||
{
|
|
||||||
_image.IsVisible = true;
|
|
||||||
_icon.IsVisible = false;
|
|
||||||
_image.Source = iconImage.Item2;
|
|
||||||
_image.LoadingPlaceholder = "login.png";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_image.IsVisible = false;
|
|
||||||
_icon.IsVisible = true;
|
|
||||||
_icon.Text = iconImage.Item1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
string icon = "";
|
|
||||||
string image = null;
|
|
||||||
if (cipher.Login.Uri != null)
|
|
||||||
{
|
|
||||||
var hostnameUri = cipher.Login.Uri;
|
|
||||||
var isWebsite = false;
|
|
||||||
|
|
||||||
if (hostnameUri.StartsWith(Constants.AndroidAppProtocol))
|
|
||||||
{
|
|
||||||
icon = "";
|
|
||||||
}
|
|
||||||
else if (hostnameUri.StartsWith(Constants.iOSAppProtocol))
|
|
||||||
{
|
|
||||||
icon = "";
|
|
||||||
}
|
|
||||||
else if (WebsiteIconsEnabled && !hostnameUri.Contains("://") && hostnameUri.Contains("."))
|
|
||||||
{
|
|
||||||
hostnameUri = string.Concat("http://", hostnameUri);
|
|
||||||
isWebsite = true;
|
|
||||||
}
|
|
||||||
else if (WebsiteIconsEnabled)
|
|
||||||
{
|
|
||||||
isWebsite = hostnameUri.StartsWith("http") && hostnameUri.Contains(".");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (WebsiteIconsEnabled && isWebsite)
|
|
||||||
{
|
|
||||||
var hostname = CoreHelpers.GetHostname(hostnameUri);
|
|
||||||
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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
image = string.Format("{0}/{1}/icon.png", iconsUrl, hostname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Tuple<string, string>(icon, image);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MoreButton_Clicked(object sender, EventArgs e)
|
private void MoreButton_Clicked(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
ButtonCommand?.Execute(Cipher);
|
var cipher = ((sender as MiButton)?.BindingContext as CipherViewCellViewModel)?.Cipher;
|
||||||
|
if (cipher != null)
|
||||||
|
{
|
||||||
|
ButtonCommand?.Execute(cipher);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,30 @@ namespace Bit.App.Controls
|
|||||||
public class CipherViewCellViewModel : ExtendedViewModel
|
public class CipherViewCellViewModel : ExtendedViewModel
|
||||||
{
|
{
|
||||||
private CipherView _cipher;
|
private CipherView _cipher;
|
||||||
|
private bool _websiteIconsEnabled;
|
||||||
|
|
||||||
|
public CipherViewCellViewModel(CipherView cipherView, bool websiteIconsEnabled)
|
||||||
|
{
|
||||||
|
Cipher = cipherView;
|
||||||
|
WebsiteIconsEnabled = websiteIconsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
public CipherView Cipher
|
public CipherView Cipher
|
||||||
{
|
{
|
||||||
get => _cipher;
|
get => _cipher;
|
||||||
set => SetProperty(ref _cipher, value);
|
set => SetProperty(ref _cipher, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool WebsiteIconsEnabled
|
||||||
|
{
|
||||||
|
get => _websiteIconsEnabled;
|
||||||
|
set => SetProperty(ref _websiteIconsEnabled, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ShowIconImage
|
||||||
|
{
|
||||||
|
get => WebsiteIconsEnabled && !string.IsNullOrWhiteSpace(Cipher.Login?.Uri) &&
|
||||||
|
Cipher.Login.Uri.StartsWith("http");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
src/App/Controls/ExtendedCollectionView.cs
Normal file
8
src/App/Controls/ExtendedCollectionView.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Bit.App.Controls
|
||||||
|
{
|
||||||
|
public class ExtendedCollectionView : CollectionView
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/App/Controls/ExtendedGrid.cs
Normal file
8
src/App/Controls/ExtendedGrid.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Bit.App.Controls
|
||||||
|
{
|
||||||
|
public class ExtendedGrid : Grid
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
using Xamarin.Forms;
|
|
||||||
|
|
||||||
namespace Bit.App.Controls
|
|
||||||
{
|
|
||||||
public class ExtendedListView : ListView
|
|
||||||
{
|
|
||||||
public ExtendedListView() { }
|
|
||||||
|
|
||||||
public ExtendedListView(ListViewCachingStrategy cachingStrategy)
|
|
||||||
: base(cachingStrategy) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
8
src/App/Controls/ExtendedStackLayout.cs
Normal file
8
src/App/Controls/ExtendedStackLayout.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Bit.App.Controls
|
||||||
|
{
|
||||||
|
public class ExtendedStackLayout : StackLayout
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,137 +1,132 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
|
<controls:ExtendedGrid xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
x:Class="Bit.App.Controls.SendViewCell"
|
x:Class="Bit.App.Controls.SendViewCell"
|
||||||
xmlns:controls="clr-namespace:Bit.App.Controls"
|
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||||
xmlns:u="clr-namespace:Bit.App.Utilities">
|
xmlns:u="clr-namespace:Bit.App.Utilities"
|
||||||
|
StyleClass="list-row, list-row-platform"
|
||||||
|
RowSpacing="0"
|
||||||
|
ColumnSpacing="0"
|
||||||
|
x:DataType="controls:SendViewCellViewModel">
|
||||||
|
|
||||||
<Grid
|
<Grid.Resources>
|
||||||
x:Name="_grid"
|
<u:SendIconGlyphConverter x:Key="sendIconGlyphConverter"/>
|
||||||
StyleClass="list-row, list-row-platform"
|
</Grid.Resources>
|
||||||
RowSpacing="0"
|
|
||||||
ColumnSpacing="0"
|
|
||||||
x:DataType="controls:SendViewCellViewModel">
|
|
||||||
|
|
||||||
<Grid.BindingContext>
|
<Grid.RowDefinitions>
|
||||||
<controls:SendViewCellViewModel />
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.BindingContext>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="40" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="60" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<controls:FaLabel
|
||||||
|
Grid.Row="0"
|
||||||
|
Grid.Column="0"
|
||||||
|
HorizontalOptions="Center"
|
||||||
|
VerticalOptions="Center"
|
||||||
|
StyleClass="list-icon, list-icon-platform"
|
||||||
|
Text="{Binding Send, Converter={StaticResource sendIconGlyphConverter}}"
|
||||||
|
AutomationProperties.IsInAccessibleTree="False" />
|
||||||
|
|
||||||
|
<Grid RowSpacing="0" ColumnSpacing="0" Grid.Row="0" Grid.Column="1" VerticalOptions="Center" Padding="0, 7">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="40" />
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
<ColumnDefinition Width="60" />
|
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<controls:FaLabel
|
<Label
|
||||||
x:Name="_icon"
|
LineBreakMode="TailTruncation"
|
||||||
Grid.Row="0"
|
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
HorizontalOptions="Center"
|
|
||||||
VerticalOptions="Center"
|
|
||||||
StyleClass="list-icon, list-icon-platform"
|
|
||||||
AutomationProperties.IsInAccessibleTree="False" />
|
|
||||||
|
|
||||||
<Grid RowSpacing="0" ColumnSpacing="0" Grid.Row="0" Grid.Column="1" VerticalOptions="Center">
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
|
|
||||||
<Label
|
|
||||||
LineBreakMode="TailTruncation"
|
|
||||||
Grid.Column="0"
|
|
||||||
Grid.Row="0"
|
|
||||||
StyleClass="list-title, list-title-platform"
|
|
||||||
Text="{Binding Send.Name, Mode=OneWay}" />
|
|
||||||
<Label
|
|
||||||
LineBreakMode="TailTruncation"
|
|
||||||
Grid.Column="0"
|
|
||||||
Grid.Row="1"
|
|
||||||
Grid.ColumnSpan="6"
|
|
||||||
StyleClass="list-subtitle, list-subtitle-platform"
|
|
||||||
Text="{Binding Send.DisplayDate, Mode=OneWay}" />
|
|
||||||
<controls:FaLabel
|
|
||||||
Grid.Column="1"
|
|
||||||
Grid.Row="0"
|
|
||||||
HorizontalOptions="Start"
|
|
||||||
VerticalOptions="Center"
|
|
||||||
StyleClass="list-title-icon"
|
|
||||||
Margin="5, 0, 0, 0"
|
|
||||||
Text=""
|
|
||||||
IsVisible="{Binding Send.Disabled, Mode=OneWay}"
|
|
||||||
AutomationProperties.IsInAccessibleTree="True"
|
|
||||||
AutomationProperties.Name="{u:I18n Disabled}" />
|
|
||||||
<controls:FaLabel
|
|
||||||
Grid.Column="2"
|
|
||||||
Grid.Row="0"
|
|
||||||
HorizontalOptions="Start"
|
|
||||||
VerticalOptions="Center"
|
|
||||||
StyleClass="list-title-icon"
|
|
||||||
Margin="5, 0, 0, 0"
|
|
||||||
Text=""
|
|
||||||
IsVisible="{Binding Send.HasPassword, Mode=OneWay}"
|
|
||||||
AutomationProperties.IsInAccessibleTree="True"
|
|
||||||
AutomationProperties.Name="{u:I18n Password}" />
|
|
||||||
<controls:FaLabel
|
|
||||||
Grid.Column="3"
|
|
||||||
Grid.Row="0"
|
|
||||||
HorizontalOptions="Start"
|
|
||||||
VerticalOptions="Center"
|
|
||||||
StyleClass="list-title-icon"
|
|
||||||
Margin="5, 0, 0, 0"
|
|
||||||
Text=""
|
|
||||||
IsVisible="{Binding Send.MaxAccessCountReached, Mode=OneWay}"
|
|
||||||
AutomationProperties.IsInAccessibleTree="True"
|
|
||||||
AutomationProperties.Name="{u:I18n MaxAccessCountReached}" />
|
|
||||||
<controls:FaLabel
|
|
||||||
Grid.Column="4"
|
|
||||||
Grid.Row="0"
|
|
||||||
HorizontalOptions="Start"
|
|
||||||
VerticalOptions="Center"
|
|
||||||
StyleClass="list-title-icon"
|
|
||||||
Margin="5, 0, 0, 0"
|
|
||||||
Text=""
|
|
||||||
IsVisible="{Binding Send.Expired, Mode=OneWay}"
|
|
||||||
AutomationProperties.IsInAccessibleTree="True"
|
|
||||||
AutomationProperties.Name="{u:I18n Expired}" />
|
|
||||||
<controls:FaLabel
|
|
||||||
Grid.Column="5"
|
|
||||||
Grid.Row="0"
|
|
||||||
HorizontalOptions="Start"
|
|
||||||
VerticalOptions="Center"
|
|
||||||
StyleClass="list-title-icon"
|
|
||||||
Margin="5, 0, 0, 0"
|
|
||||||
Text=""
|
|
||||||
IsVisible="{Binding Send.PendingDelete, Mode=OneWay}"
|
|
||||||
AutomationProperties.IsInAccessibleTree="True"
|
|
||||||
AutomationProperties.Name="{u:I18n PendingDelete}" />
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<controls:MiButton
|
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.Column="2"
|
StyleClass="list-title, list-title-platform"
|
||||||
Text=""
|
Text="{Binding Send.Name}" />
|
||||||
IsVisible="{Binding ShowOptions, Mode=OneWay}"
|
<Label
|
||||||
StyleClass="list-row-button, list-row-button-platform, btn-disabled"
|
LineBreakMode="TailTruncation"
|
||||||
Clicked="MoreButton_Clicked"
|
Grid.Column="0"
|
||||||
VerticalOptions="CenterAndExpand"
|
Grid.Row="1"
|
||||||
HorizontalOptions="EndAndExpand"
|
Grid.ColumnSpan="6"
|
||||||
|
StyleClass="list-subtitle, list-subtitle-platform"
|
||||||
|
Text="{Binding Send.DisplayDate}" />
|
||||||
|
<controls:FaLabel
|
||||||
|
Grid.Column="1"
|
||||||
|
Grid.Row="0"
|
||||||
|
HorizontalOptions="Start"
|
||||||
|
VerticalOptions="Center"
|
||||||
|
StyleClass="list-title-icon"
|
||||||
|
Margin="5, 0, 0, 0"
|
||||||
|
Text=""
|
||||||
|
IsVisible="{Binding Send.Disabled, Mode=OneTime}"
|
||||||
AutomationProperties.IsInAccessibleTree="True"
|
AutomationProperties.IsInAccessibleTree="True"
|
||||||
AutomationProperties.Name="{u:I18n Options}" />
|
AutomationProperties.Name="{u:I18n Disabled}" />
|
||||||
|
<controls:FaLabel
|
||||||
|
Grid.Column="2"
|
||||||
|
Grid.Row="0"
|
||||||
|
HorizontalOptions="Start"
|
||||||
|
VerticalOptions="Center"
|
||||||
|
StyleClass="list-title-icon"
|
||||||
|
Margin="5, 0, 0, 0"
|
||||||
|
Text=""
|
||||||
|
IsVisible="{Binding Send.HasPassword, Mode=OneTime}"
|
||||||
|
AutomationProperties.IsInAccessibleTree="True"
|
||||||
|
AutomationProperties.Name="{u:I18n Password}" />
|
||||||
|
<controls:FaLabel
|
||||||
|
Grid.Column="3"
|
||||||
|
Grid.Row="0"
|
||||||
|
HorizontalOptions="Start"
|
||||||
|
VerticalOptions="Center"
|
||||||
|
StyleClass="list-title-icon"
|
||||||
|
Margin="5, 0, 0, 0"
|
||||||
|
Text=""
|
||||||
|
IsVisible="{Binding Send.MaxAccessCountReached, Mode=OneTime}"
|
||||||
|
AutomationProperties.IsInAccessibleTree="True"
|
||||||
|
AutomationProperties.Name="{u:I18n MaxAccessCountReached}" />
|
||||||
|
<controls:FaLabel
|
||||||
|
Grid.Column="4"
|
||||||
|
Grid.Row="0"
|
||||||
|
HorizontalOptions="Start"
|
||||||
|
VerticalOptions="Center"
|
||||||
|
StyleClass="list-title-icon"
|
||||||
|
Margin="5, 0, 0, 0"
|
||||||
|
Text=""
|
||||||
|
IsVisible="{Binding Send.Expired, Mode=OneTime}"
|
||||||
|
AutomationProperties.IsInAccessibleTree="True"
|
||||||
|
AutomationProperties.Name="{u:I18n Expired}" />
|
||||||
|
<controls:FaLabel
|
||||||
|
Grid.Column="5"
|
||||||
|
Grid.Row="0"
|
||||||
|
HorizontalOptions="Start"
|
||||||
|
VerticalOptions="Center"
|
||||||
|
StyleClass="list-title-icon"
|
||||||
|
Margin="5, 0, 0, 0"
|
||||||
|
Text=""
|
||||||
|
IsVisible="{Binding Send.PendingDelete, Mode=OneTime}"
|
||||||
|
AutomationProperties.IsInAccessibleTree="True"
|
||||||
|
AutomationProperties.Name="{u:I18n PendingDelete}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
</ViewCell>
|
<controls:MiButton
|
||||||
|
Grid.Row="0"
|
||||||
|
Grid.Column="2"
|
||||||
|
Text=""
|
||||||
|
IsVisible="{Binding ShowOptions, Mode=OneWay}"
|
||||||
|
StyleClass="list-row-button, list-row-button-platform, btn-disabled"
|
||||||
|
Clicked="MoreButton_Clicked"
|
||||||
|
VerticalOptions="CenterAndExpand"
|
||||||
|
HorizontalOptions="EndAndExpand"
|
||||||
|
AutomationProperties.IsInAccessibleTree="True"
|
||||||
|
AutomationProperties.Name="{u:I18n Options}" />
|
||||||
|
|
||||||
|
</controls:ExtendedGrid>
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using Bit.App.Pages;
|
|
||||||
using Bit.Core.Abstractions;
|
|
||||||
using Bit.Core.Enums;
|
|
||||||
using Bit.Core.Models.View;
|
using Bit.Core.Models.View;
|
||||||
using Bit.Core.Utilities;
|
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace Bit.App.Controls
|
namespace Bit.App.Controls
|
||||||
{
|
{
|
||||||
public partial class SendViewCell : ViewCell
|
public partial class SendViewCell : ExtendedGrid
|
||||||
{
|
{
|
||||||
public static readonly BindableProperty SendProperty = BindableProperty.Create(
|
public static readonly BindableProperty SendProperty = BindableProperty.Create(
|
||||||
nameof(Send), typeof(SendView), typeof(SendViewCell), default(SendView), BindingMode.OneWay);
|
nameof(Send), typeof(SendView), typeof(SendViewCell), default(SendView), BindingMode.OneWay);
|
||||||
@@ -17,25 +13,11 @@ namespace Bit.App.Controls
|
|||||||
nameof(ButtonCommand), typeof(Command<SendView>), typeof(SendViewCell));
|
nameof(ButtonCommand), typeof(Command<SendView>), typeof(SendViewCell));
|
||||||
|
|
||||||
public static readonly BindableProperty ShowOptionsProperty = BindableProperty.Create(
|
public static readonly BindableProperty ShowOptionsProperty = BindableProperty.Create(
|
||||||
nameof(ShowOptions), typeof(bool), typeof(SendViewCell));
|
nameof(ShowOptions), typeof(bool), typeof(SendViewCell), true, BindingMode.OneWay);
|
||||||
|
|
||||||
private readonly IEnvironmentService _environmentService;
|
|
||||||
|
|
||||||
private SendViewCellViewModel _viewModel;
|
|
||||||
private bool _usingNativeCell;
|
|
||||||
|
|
||||||
public SendViewCell()
|
public SendViewCell()
|
||||||
{
|
{
|
||||||
_environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
|
InitializeComponent();
|
||||||
if (Device.RuntimePlatform == Device.iOS)
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
_viewModel = _grid.BindingContext as SendViewCellViewModel;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_usingNativeCell = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SendView Send
|
public SendView Send
|
||||||
@@ -52,72 +34,30 @@ namespace Bit.App.Controls
|
|||||||
|
|
||||||
public bool ShowOptions
|
public bool ShowOptions
|
||||||
{
|
{
|
||||||
get => GetValue(ShowOptionsProperty) is bool && (bool)GetValue(ShowOptionsProperty);
|
get => (bool)GetValue(ShowOptionsProperty);
|
||||||
set => SetValue(ShowOptionsProperty, value);
|
set => SetValue(ShowOptionsProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPropertyChanged(string propertyName = null)
|
protected override void OnPropertyChanged(string propertyName = null)
|
||||||
{
|
{
|
||||||
base.OnPropertyChanged(propertyName);
|
base.OnPropertyChanged(propertyName);
|
||||||
if (_usingNativeCell)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (propertyName == SendProperty.PropertyName)
|
if (propertyName == SendProperty.PropertyName)
|
||||||
{
|
{
|
||||||
_viewModel.Send = Send;
|
if (Send == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BindingContext = new SendViewCellViewModel(Send, ShowOptions);
|
||||||
}
|
}
|
||||||
else if (propertyName == ShowOptionsProperty.PropertyName)
|
|
||||||
{
|
|
||||||
_viewModel.ShowOptions = ShowOptions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnBindingContextChanged()
|
|
||||||
{
|
|
||||||
base.OnBindingContextChanged();
|
|
||||||
if (_usingNativeCell)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SendView send = null;
|
|
||||||
if (BindingContext is SendGroupingsPageListItem sendGroupingsPageListItem)
|
|
||||||
{
|
|
||||||
send = sendGroupingsPageListItem.Send;
|
|
||||||
}
|
|
||||||
else if (BindingContext is SendView sv)
|
|
||||||
{
|
|
||||||
send = sv;
|
|
||||||
}
|
|
||||||
if (send != null)
|
|
||||||
{
|
|
||||||
var iconImage = GetIconImage(send);
|
|
||||||
_icon.IsVisible = true;
|
|
||||||
_icon.Text = iconImage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetIconImage(SendView send)
|
|
||||||
{
|
|
||||||
string icon = null;
|
|
||||||
switch (send.Type)
|
|
||||||
{
|
|
||||||
case SendType.Text:
|
|
||||||
icon = "\uf0f6"; // fa-file-text-o
|
|
||||||
break;
|
|
||||||
case SendType.File:
|
|
||||||
icon = "\uf016"; // fa-file-o
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return icon;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MoreButton_Clicked(object sender, EventArgs e)
|
private void MoreButton_Clicked(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
ButtonCommand?.Execute(Send);
|
var send = ((sender as MiButton)?.BindingContext as SendViewCellViewModel)?.Send;
|
||||||
|
if (send != null)
|
||||||
|
{
|
||||||
|
ButtonCommand?.Execute(send);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,12 @@ namespace Bit.App.Controls
|
|||||||
private SendView _send;
|
private SendView _send;
|
||||||
private bool _showOptions;
|
private bool _showOptions;
|
||||||
|
|
||||||
|
public SendViewCellViewModel(SendView sendView, bool showOptions)
|
||||||
|
{
|
||||||
|
Send = sendView;
|
||||||
|
ShowOptions = showOptions;
|
||||||
|
}
|
||||||
|
|
||||||
public SendView Send
|
public SendView Send
|
||||||
{
|
{
|
||||||
get => _send;
|
get => _send;
|
||||||
|
|||||||
@@ -43,57 +43,53 @@
|
|||||||
VerticalOptions="CenterAndExpand"
|
VerticalOptions="CenterAndExpand"
|
||||||
HorizontalOptions="CenterAndExpand"
|
HorizontalOptions="CenterAndExpand"
|
||||||
HorizontalTextAlignment="Center"></Label>
|
HorizontalTextAlignment="Center"></Label>
|
||||||
<ListView x:Name="_listView"
|
<controls:ExtendedCollectionView
|
||||||
IsVisible="{Binding ShowNoData, Converter={StaticResource inverseBool}}"
|
IsVisible="{Binding ShowNoData, Converter={StaticResource inverseBool}}"
|
||||||
ItemsSource="{Binding History}"
|
ItemsSource="{Binding History}"
|
||||||
VerticalOptions="FillAndExpand"
|
VerticalOptions="FillAndExpand"
|
||||||
HasUnevenRows="true"
|
|
||||||
CachingStrategy="RecycleElement"
|
|
||||||
StyleClass="list, list-platform">
|
StyleClass="list, list-platform">
|
||||||
<ListView.ItemTemplate>
|
<CollectionView.ItemTemplate>
|
||||||
<DataTemplate x:DataType="domain:GeneratedPasswordHistory">
|
<DataTemplate x:DataType="domain:GeneratedPasswordHistory">
|
||||||
<ViewCell>
|
<Grid
|
||||||
<Grid
|
StyleClass="list-row, list-row-platform"
|
||||||
StyleClass="list-row, list-row-platform"
|
Padding="10"
|
||||||
Padding="10"
|
RowSpacing="0"
|
||||||
RowSpacing="0"
|
ColumnSpacing="10">
|
||||||
ColumnSpacing="10">
|
|
||||||
|
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<controls:MonoLabel LineBreakMode="CharacterWrap"
|
<controls:MonoLabel LineBreakMode="CharacterWrap"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
StyleClass="list-title, list-title-platform"
|
StyleClass="list-title, list-title-platform"
|
||||||
TextType="Html"
|
TextType="Html"
|
||||||
Text="{Binding Password, Mode=OneWay, Converter={StaticResource coloredPassword}}" />
|
Text="{Binding Password, Mode=OneWay, Converter={StaticResource coloredPassword}}" />
|
||||||
<Label LineBreakMode="TailTruncation"
|
<Label LineBreakMode="TailTruncation"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
StyleClass="list-subtitle, list-subtitle-platform"
|
StyleClass="list-subtitle, list-subtitle-platform"
|
||||||
Text="{Binding Date, Mode=OneWay, Converter={StaticResource dateTime}}" />
|
Text="{Binding Date, Mode=OneWay, Converter={StaticResource dateTime}}" />
|
||||||
<controls:FaButton
|
<controls:FaButton
|
||||||
StyleClass="list-row-button, list-row-button-platform"
|
StyleClass="list-row-button, list-row-button-platform"
|
||||||
Text=""
|
Text=""
|
||||||
Command="{Binding BindingContext.CopyCommand, Source={x:Reference _page}}"
|
Command="{Binding BindingContext.CopyCommand, Source={x:Reference _page}}"
|
||||||
CommandParameter="{Binding .}"
|
CommandParameter="{Binding .}"
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Grid.RowSpan="2"
|
Grid.RowSpan="2"
|
||||||
AutomationProperties.IsInAccessibleTree="True"
|
AutomationProperties.IsInAccessibleTree="True"
|
||||||
AutomationProperties.Name="{u:I18n CopyPassword}" />
|
AutomationProperties.Name="{u:I18n CopyPassword}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</ViewCell>
|
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListView.ItemTemplate>
|
</CollectionView.ItemTemplate>
|
||||||
</ListView>
|
</controls:ExtendedCollectionView>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
||||||
</pages:BaseContentPage>
|
</pages:BaseContentPage>
|
||||||
|
|||||||
@@ -44,34 +44,32 @@
|
|||||||
<controls:SendViewCell
|
<controls:SendViewCell
|
||||||
Send="{Binding Send}"
|
Send="{Binding Send}"
|
||||||
ButtonCommand="{Binding BindingContext.SendOptionsCommand, Source={x:Reference _page}}"
|
ButtonCommand="{Binding BindingContext.SendOptionsCommand, Source={x:Reference _page}}"
|
||||||
ShowOptions="{Binding ShowOptions}" />
|
ShowOptions="{Binding BindingContext.SendEnabled, Source={x:Reference _page}}" />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
<DataTemplate x:Key="sendGroupTemplate"
|
<DataTemplate x:Key="sendGroupTemplate"
|
||||||
x:DataType="pages:SendGroupingsPageListItem">
|
x:DataType="pages:SendGroupingsPageListItem">
|
||||||
<ViewCell>
|
<controls:ExtendedStackLayout Orientation="Horizontal"
|
||||||
<StackLayout Orientation="Horizontal"
|
StyleClass="list-row, list-row-platform">
|
||||||
StyleClass="list-row, list-row-platform">
|
<controls:FaLabel Text="{Binding Icon, Mode=OneWay}"
|
||||||
<controls:FaLabel Text="{Binding Icon, Mode=OneWay}"
|
HorizontalOptions="Start"
|
||||||
HorizontalOptions="Start"
|
VerticalOptions="Center"
|
||||||
VerticalOptions="Center"
|
StyleClass="list-icon, list-icon-platform">
|
||||||
StyleClass="list-icon, list-icon-platform">
|
<controls:FaLabel.Effects>
|
||||||
<controls:FaLabel.Effects>
|
<effects:FixedSizeEffect />
|
||||||
<effects:FixedSizeEffect />
|
</controls:FaLabel.Effects>
|
||||||
</controls:FaLabel.Effects>
|
</controls:FaLabel>
|
||||||
</controls:FaLabel>
|
<Label Text="{Binding Name, Mode=OneWay}"
|
||||||
<Label Text="{Binding Name, Mode=OneWay}"
|
LineBreakMode="TailTruncation"
|
||||||
LineBreakMode="TailTruncation"
|
HorizontalOptions="FillAndExpand"
|
||||||
HorizontalOptions="FillAndExpand"
|
VerticalOptions="CenterAndExpand"
|
||||||
VerticalOptions="CenterAndExpand"
|
StyleClass="list-title" />
|
||||||
StyleClass="list-title" />
|
<Label Text="{Binding ItemCount, Mode=OneWay}"
|
||||||
<Label Text="{Binding ItemCount, Mode=OneWay}"
|
HorizontalOptions="End"
|
||||||
HorizontalOptions="End"
|
VerticalOptions="CenterAndExpand"
|
||||||
VerticalOptions="CenterAndExpand"
|
HorizontalTextAlignment="End"
|
||||||
HorizontalTextAlignment="End"
|
StyleClass="list-sub" />
|
||||||
StyleClass="list-sub" />
|
</controls:ExtendedStackLayout>
|
||||||
</StackLayout>
|
|
||||||
</ViewCell>
|
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
<pages:SendGroupingsPageListItemSelector x:Key="sendListItemDataTemplateSelector"
|
<pages:SendGroupingsPageListItemSelector x:Key="sendListItemDataTemplateSelector"
|
||||||
@@ -103,32 +101,25 @@
|
|||||||
Text="{Binding NoDataText}"
|
Text="{Binding NoDataText}"
|
||||||
HorizontalTextAlignment="Center" />
|
HorizontalTextAlignment="Center" />
|
||||||
<Button
|
<Button
|
||||||
Text="{u:I18n AddAnItem}"
|
Text="{u:I18n AddASend}"
|
||||||
Clicked="AddButton_Clicked"
|
Clicked="AddButton_Clicked" />
|
||||||
IsVisible="{Binding ShowAddSendButton}" />
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
||||||
<controls:ExtendedListView
|
<RefreshView
|
||||||
x:Name="_listView"
|
|
||||||
IsVisible="{Binding ShowList}"
|
IsVisible="{Binding ShowList}"
|
||||||
ItemsSource="{Binding GroupedSends}"
|
|
||||||
VerticalOptions="FillAndExpand"
|
|
||||||
HasUnevenRows="True"
|
|
||||||
RowHeight="-1"
|
|
||||||
RefreshCommand="{Binding RefreshCommand}"
|
|
||||||
IsPullToRefreshEnabled="True"
|
|
||||||
IsRefreshing="{Binding Refreshing}"
|
IsRefreshing="{Binding Refreshing}"
|
||||||
ItemTemplate="{StaticResource sendListItemDataTemplateSelector}"
|
Command="{Binding RefreshCommand}">
|
||||||
IsGroupingEnabled="True"
|
<controls:ExtendedCollectionView
|
||||||
ItemSelected="RowSelected"
|
ItemsSource="{Binding GroupedSends}"
|
||||||
StyleClass="list, list-platform">
|
VerticalOptions="FillAndExpand"
|
||||||
<x:Arguments>
|
ItemTemplate="{StaticResource sendListItemDataTemplateSelector}"
|
||||||
<ListViewCachingStrategy>RecycleElement</ListViewCachingStrategy>
|
IsGrouped="True"
|
||||||
</x:Arguments>
|
SelectionMode="Single"
|
||||||
|
SelectionChanged="RowSelected"
|
||||||
|
StyleClass="list, list-platform">
|
||||||
|
|
||||||
<ListView.GroupHeaderTemplate>
|
<CollectionView.GroupHeaderTemplate>
|
||||||
<DataTemplate x:DataType="pages:SendGroupingsPageListGroup">
|
<DataTemplate x:DataType="pages:SendGroupingsPageListGroup">
|
||||||
<ViewCell>
|
|
||||||
<StackLayout
|
<StackLayout
|
||||||
Spacing="0" Padding="0" VerticalOptions="FillAndExpand"
|
Spacing="0" Padding="0" VerticalOptions="FillAndExpand"
|
||||||
StyleClass="list-row-header-container, list-row-header-container-platform">
|
StyleClass="list-row-header-container, list-row-header-container-platform">
|
||||||
@@ -146,10 +137,10 @@
|
|||||||
<BoxView
|
<BoxView
|
||||||
StyleClass="list-section-separator-bottom, list-section-separator-bottom-platform" />
|
StyleClass="list-section-separator-bottom, list-section-separator-bottom-platform" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ViewCell>
|
</DataTemplate>
|
||||||
</DataTemplate>
|
</CollectionView.GroupHeaderTemplate>
|
||||||
</ListView.GroupHeaderTemplate>
|
</controls:ExtendedCollectionView>
|
||||||
</controls:ExtendedListView>
|
</RefreshView>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</ContentPage.Resources>
|
</ContentPage.Resources>
|
||||||
|
|||||||
@@ -20,14 +20,13 @@ namespace Bit.App.Pages
|
|||||||
private readonly string _pageName;
|
private readonly string _pageName;
|
||||||
|
|
||||||
private AppOptions _appOptions;
|
private AppOptions _appOptions;
|
||||||
private PreviousPageInfo _previousPage;
|
|
||||||
|
|
||||||
public SendGroupingsPage(bool mainPage, SendType? type = null, string pageTitle = null,
|
public SendGroupingsPage(bool mainPage, SendType? type = null, string pageTitle = null,
|
||||||
AppOptions appOptions = null, PreviousPageInfo previousPage = null)
|
AppOptions appOptions = null)
|
||||||
{
|
{
|
||||||
_pageName = string.Concat(nameof(GroupingsPage), "_", DateTime.UtcNow.Ticks);
|
_pageName = string.Concat(nameof(SendGroupingsPage), "_", DateTime.UtcNow.Ticks);
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
ListView = _listView;
|
SetActivityIndicator(_mainContent);
|
||||||
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
|
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
|
||||||
_syncService = ServiceContainer.Resolve<ISyncService>("syncService");
|
_syncService = ServiceContainer.Resolve<ISyncService>("syncService");
|
||||||
_vaultTimeoutService = ServiceContainer.Resolve<IVaultTimeoutService>("vaultTimeoutService");
|
_vaultTimeoutService = ServiceContainer.Resolve<IVaultTimeoutService>("vaultTimeoutService");
|
||||||
@@ -37,7 +36,6 @@ namespace Bit.App.Pages
|
|||||||
_vm.MainPage = mainPage;
|
_vm.MainPage = mainPage;
|
||||||
_vm.Type = type;
|
_vm.Type = type;
|
||||||
_appOptions = appOptions;
|
_appOptions = appOptions;
|
||||||
_previousPage = previousPage;
|
|
||||||
if (pageTitle != null)
|
if (pageTitle != null)
|
||||||
{
|
{
|
||||||
_vm.PageTitle = pageTitle;
|
_vm.PageTitle = pageTitle;
|
||||||
@@ -46,7 +44,10 @@ namespace Bit.App.Pages
|
|||||||
if (Device.RuntimePlatform == Device.iOS)
|
if (Device.RuntimePlatform == Device.iOS)
|
||||||
{
|
{
|
||||||
_absLayout.Children.Remove(_fab);
|
_absLayout.Children.Remove(_fab);
|
||||||
ToolbarItems.Add(_aboutIconItem);
|
if (type == null)
|
||||||
|
{
|
||||||
|
ToolbarItems.Add(_aboutIconItem);
|
||||||
|
}
|
||||||
ToolbarItems.Add(_addItem);
|
ToolbarItems.Add(_addItem);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -57,8 +58,6 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExtendedListView ListView { get; set; }
|
|
||||||
|
|
||||||
protected override async void OnAppearing()
|
protected override async void OnAppearing()
|
||||||
{
|
{
|
||||||
base.OnAppearing();
|
base.OnAppearing();
|
||||||
@@ -136,14 +135,14 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void RowSelected(object sender, SelectedItemChangedEventArgs e)
|
private async void RowSelected(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
((ListView)sender).SelectedItem = null;
|
((ExtendedCollectionView)sender).SelectedItem = null;
|
||||||
if (!DoOnce())
|
if (!DoOnce())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!(e.SelectedItem is SendGroupingsPageListItem item))
|
if (!(e.CurrentSelection?.FirstOrDefault() is SendGroupingsPageListItem item))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ namespace Bit.App.Pages
|
|||||||
public SendGroupingsPageListGroup(string name, int count, bool doUpper = true, bool first = false)
|
public SendGroupingsPageListGroup(string name, int count, bool doUpper = true, bool first = false)
|
||||||
: this(new List<SendGroupingsPageListItem>(), name, count, doUpper, first) { }
|
: this(new List<SendGroupingsPageListItem>(), name, count, doUpper, first) { }
|
||||||
|
|
||||||
public SendGroupingsPageListGroup(List<SendGroupingsPageListItem> groupItems, string name, int count,
|
public SendGroupingsPageListGroup(List<SendGroupingsPageListItem> sendGroupItems, string name, int count,
|
||||||
bool doUpper = true, bool first = false)
|
bool doUpper = true, bool first = false)
|
||||||
{
|
{
|
||||||
AddRange(groupItems);
|
AddRange(sendGroupItems);
|
||||||
if (string.IsNullOrWhiteSpace(name))
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
{
|
{
|
||||||
Name = "-";
|
Name = "-";
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ namespace Bit.App.Pages
|
|||||||
private bool _doingLoad;
|
private bool _doingLoad;
|
||||||
private bool _loading;
|
private bool _loading;
|
||||||
private bool _loaded;
|
private bool _loaded;
|
||||||
private bool _showAddSendButton;
|
|
||||||
private bool _showNoData;
|
private bool _showNoData;
|
||||||
private bool _showList;
|
private bool _showList;
|
||||||
private bool _syncRefreshing;
|
private bool _syncRefreshing;
|
||||||
@@ -91,11 +90,6 @@ namespace Bit.App.Pages
|
|||||||
get => _loaded;
|
get => _loaded;
|
||||||
set => SetProperty(ref _loaded, value);
|
set => SetProperty(ref _loaded, value);
|
||||||
}
|
}
|
||||||
public bool ShowAddSendButton
|
|
||||||
{
|
|
||||||
get => _showAddSendButton;
|
|
||||||
set => SetProperty(ref _showAddSendButton, value);
|
|
||||||
}
|
|
||||||
public bool ShowNoData
|
public bool ShowNoData
|
||||||
{
|
{
|
||||||
get => _showNoData;
|
get => _showNoData;
|
||||||
|
|||||||
@@ -60,23 +60,22 @@
|
|||||||
VerticalOptions="CenterAndExpand"
|
VerticalOptions="CenterAndExpand"
|
||||||
HorizontalOptions="CenterAndExpand"
|
HorizontalOptions="CenterAndExpand"
|
||||||
HorizontalTextAlignment="Center" />
|
HorizontalTextAlignment="Center" />
|
||||||
<ListView x:Name="_listView"
|
<controls:ExtendedCollectionView
|
||||||
IsVisible="{Binding ShowList}"
|
IsVisible="{Binding ShowList}"
|
||||||
ItemsSource="{Binding Sends}"
|
ItemsSource="{Binding Sends}"
|
||||||
VerticalOptions="FillAndExpand"
|
VerticalOptions="FillAndExpand"
|
||||||
HasUnevenRows="true"
|
SelectionMode="Single"
|
||||||
CachingStrategy="RecycleElement"
|
SelectionChanged="RowSelected"
|
||||||
ItemSelected="RowSelected"
|
|
||||||
StyleClass="list, list-platform">
|
StyleClass="list, list-platform">
|
||||||
<ListView.ItemTemplate>
|
<CollectionView.ItemTemplate>
|
||||||
<DataTemplate x:DataType="views:SendView">
|
<DataTemplate x:DataType="views:SendView">
|
||||||
<controls:SendViewCell
|
<controls:SendViewCell
|
||||||
Send="{Binding .}"
|
Send="{Binding .}"
|
||||||
ButtonCommand="{Binding BindingContext.SendOptionsCommand, Source={x:Reference _page}}"
|
ButtonCommand="{Binding BindingContext.SendOptionsCommand, Source={x:Reference _page}}"
|
||||||
ShowOptions="{Binding BindingContext.SendEnabled, Source={x:Reference _page}}" />
|
ShowOptions="{Binding BindingContext.SendEnabled, Source={x:Reference _page}}" />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListView.ItemTemplate>
|
</CollectionView.ItemTemplate>
|
||||||
</ListView>
|
</controls:ExtendedCollectionView>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
||||||
</pages:BaseContentPage>
|
</pages:BaseContentPage>
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Bit.App.Controls;
|
||||||
using Bit.App.Resources;
|
using Bit.App.Resources;
|
||||||
using Bit.Core.Models.View;
|
using Bit.Core.Models.View;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
@@ -87,15 +88,15 @@ namespace Bit.App.Pages
|
|||||||
Navigation.PopModalAsync(false);
|
Navigation.PopModalAsync(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void RowSelected(object sender, SelectedItemChangedEventArgs e)
|
private async void RowSelected(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
((ListView)sender).SelectedItem = null;
|
((ExtendedCollectionView)sender).SelectedItem = null;
|
||||||
if (!DoOnce())
|
if (!DoOnce())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.SelectedItem is SendView send)
|
if (e.CurrentSelection is SendView send)
|
||||||
{
|
{
|
||||||
await _vm.SelectSendAsync(send);
|
await _vm.SelectSendAsync(send);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,27 +32,25 @@
|
|||||||
VerticalOptions="CenterAndExpand"
|
VerticalOptions="CenterAndExpand"
|
||||||
HorizontalOptions="CenterAndExpand"
|
HorizontalOptions="CenterAndExpand"
|
||||||
HorizontalTextAlignment="Center"></Label>
|
HorizontalTextAlignment="Center"></Label>
|
||||||
<ListView x:Name="_listView"
|
<controls:ExtendedCollectionView
|
||||||
IsVisible="{Binding ShowNoData, Converter={StaticResource inverseBool}}"
|
IsVisible="{Binding ShowNoData, Converter={StaticResource inverseBool}}"
|
||||||
ItemsSource="{Binding Folders}"
|
ItemsSource="{Binding Folders}"
|
||||||
VerticalOptions="FillAndExpand"
|
VerticalOptions="FillAndExpand"
|
||||||
CachingStrategy="RecycleElement"
|
SelectionMode="Single"
|
||||||
ItemSelected="RowSelected"
|
SelectionChanged="RowSelected"
|
||||||
StyleClass="list, list-platform">
|
StyleClass="list, list-platform">
|
||||||
<ListView.ItemTemplate>
|
<CollectionView.ItemTemplate>
|
||||||
<DataTemplate x:DataType="views:FolderView">
|
<DataTemplate x:DataType="views:FolderView">
|
||||||
<ViewCell>
|
<controls:ExtendedStackLayout
|
||||||
<StackLayout
|
StyleClass="list-row, list-row-platform"
|
||||||
StyleClass="list-row, list-row-platform"
|
Padding="10">
|
||||||
Padding="10">
|
<Label LineBreakMode="TailTruncation"
|
||||||
<Label LineBreakMode="TailTruncation"
|
StyleClass="list-title, list-title-platform"
|
||||||
StyleClass="list-title, list-title-platform"
|
Text="{Binding Name, Mode=OneWay}" />
|
||||||
Text="{Binding Name, Mode=OneWay}" />
|
</controls:ExtendedStackLayout>
|
||||||
</StackLayout>
|
|
||||||
</ViewCell>
|
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListView.ItemTemplate>
|
</CollectionView.ItemTemplate>
|
||||||
</ListView>
|
</controls:ExtendedCollectionView>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</ContentPage.Resources>
|
</ContentPage.Resources>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using Bit.Core.Models.View;
|
using Bit.Core.Models.View;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Bit.App.Controls;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
@@ -32,14 +34,14 @@ namespace Bit.App.Pages
|
|||||||
}, _mainContent);
|
}, _mainContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void RowSelected(object sender, SelectedItemChangedEventArgs e)
|
private async void RowSelected(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
((ListView)sender).SelectedItem = null;
|
((ExtendedCollectionView)sender).SelectedItem = null;
|
||||||
if (!DoOnce())
|
if (!DoOnce())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!(e.SelectedItem is FolderView folder))
|
if (!(e.CurrentSelection?.FirstOrDefault() is FolderView folder))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,23 +19,21 @@
|
|||||||
<DataTemplate
|
<DataTemplate
|
||||||
x:Key="regularTemplate"
|
x:Key="regularTemplate"
|
||||||
x:DataType="pages:SettingsPageListItem">
|
x:DataType="pages:SettingsPageListItem">
|
||||||
<ViewCell>
|
<controls:ExtendedStackLayout Orientation="Horizontal"
|
||||||
<StackLayout Orientation="Horizontal"
|
StyleClass="list-row, list-row-platform">
|
||||||
StyleClass="list-row, list-row-platform">
|
<Label Text="{Binding Name, Mode=OneWay}"
|
||||||
<Label Text="{Binding Name, Mode=OneWay}"
|
LineBreakMode="TailTruncation"
|
||||||
LineBreakMode="TailTruncation"
|
HorizontalOptions="StartAndExpand"
|
||||||
HorizontalOptions="StartAndExpand"
|
VerticalOptions="CenterAndExpand"
|
||||||
VerticalOptions="CenterAndExpand"
|
StyleClass="list-title"/>
|
||||||
StyleClass="list-title"/>
|
<Label Text="{Binding SubLabel, Mode=OneWay}"
|
||||||
<Label Text="{Binding SubLabel, Mode=OneWay}"
|
IsVisible="{Binding SubLabel, Converter={StaticResource stringHasValue}}"
|
||||||
IsVisible="{Binding SubLabel, Converter={StaticResource stringHasValue}}"
|
HorizontalOptions="End"
|
||||||
HorizontalOptions="End"
|
HorizontalTextAlignment="End"
|
||||||
HorizontalTextAlignment="End"
|
VerticalOptions="CenterAndExpand"
|
||||||
VerticalOptions="CenterAndExpand"
|
TextColor="{Binding SubLabelColor}"
|
||||||
TextColor="{Binding SubLabelColor}"
|
StyleClass="list-sub" />
|
||||||
StyleClass="list-sub" />
|
</controls:ExtendedStackLayout>
|
||||||
</StackLayout>
|
|
||||||
</ViewCell>
|
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
<pages:SettingsPageListItemSelector
|
<pages:SettingsPageListItemSelector
|
||||||
@@ -44,35 +42,32 @@
|
|||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</ContentPage.Resources>
|
</ContentPage.Resources>
|
||||||
|
|
||||||
<ListView
|
<controls:ExtendedCollectionView
|
||||||
ItemsSource="{Binding GroupedItems}"
|
ItemsSource="{Binding GroupedItems}"
|
||||||
VerticalOptions="FillAndExpand"
|
VerticalOptions="FillAndExpand"
|
||||||
HasUnevenRows="True"
|
|
||||||
RowHeight="-1"
|
|
||||||
ItemTemplate="{StaticResource listItemDataTemplateSelector}"
|
ItemTemplate="{StaticResource listItemDataTemplateSelector}"
|
||||||
IsGroupingEnabled="True"
|
IsGrouped="True"
|
||||||
ItemSelected="RowSelected"
|
SelectionMode="Single"
|
||||||
|
SelectionChanged="RowSelected"
|
||||||
StyleClass="list, list-platform">
|
StyleClass="list, list-platform">
|
||||||
|
|
||||||
<ListView.GroupHeaderTemplate>
|
<CollectionView.GroupHeaderTemplate>
|
||||||
<DataTemplate x:DataType="pages:SettingsPageListGroup">
|
<DataTemplate x:DataType="pages:SettingsPageListGroup">
|
||||||
<ViewCell>
|
<StackLayout
|
||||||
<StackLayout
|
Padding="0" Spacing="0" VerticalOptions="FillAndExpand"
|
||||||
Padding="0" Spacing="0" VerticalOptions="FillAndExpand"
|
StyleClass="list-row-header-container, list-row-header-container-platform">
|
||||||
StyleClass="list-row-header-container, list-row-header-container-platform">
|
<BoxView
|
||||||
<BoxView
|
StyleClass="list-section-separator-top, list-section-separator-top-platform"
|
||||||
StyleClass="list-section-separator-top, list-section-separator-top-platform"
|
IsVisible="{Binding First, Converter={StaticResource inverseBool}}" />
|
||||||
IsVisible="{Binding First, Converter={StaticResource inverseBool}}" />
|
<StackLayout StyleClass="list-row-header, list-row-header-platform">
|
||||||
<StackLayout StyleClass="list-row-header, list-row-header-platform">
|
<Label
|
||||||
<Label
|
Text="{Binding Name}"
|
||||||
Text="{Binding Name}"
|
StyleClass="list-header, list-header-platform" />
|
||||||
StyleClass="list-header, list-header-platform" />
|
|
||||||
</StackLayout>
|
|
||||||
<BoxView StyleClass="list-section-separator-bottom, list-section-separator-bottom-platform" />
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ViewCell>
|
<BoxView StyleClass="list-section-separator-bottom, list-section-separator-bottom-platform" />
|
||||||
|
</StackLayout>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListView.GroupHeaderTemplate>
|
</CollectionView.GroupHeaderTemplate>
|
||||||
</ListView>
|
</controls:ExtendedCollectionView>
|
||||||
|
|
||||||
</pages:BaseContentPage>
|
</pages:BaseContentPage>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.App.Resources;
|
using Bit.App.Resources;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Bit.App.Controls;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
@@ -41,14 +43,14 @@ namespace Bit.App.Pages
|
|||||||
return base.OnBackButtonPressed();
|
return base.OnBackButtonPressed();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void RowSelected(object sender, SelectedItemChangedEventArgs e)
|
private async void RowSelected(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
((ListView)sender).SelectedItem = null;
|
((ExtendedCollectionView)sender).SelectedItem = null;
|
||||||
if (!DoOnce())
|
if (!DoOnce())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!(e.SelectedItem is SettingsPageListItem item))
|
if (!(e.CurrentSelection?.FirstOrDefault() is SettingsPageListItem item))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,40 +47,35 @@
|
|||||||
Clicked="AddButton_Clicked"></Button>
|
Clicked="AddButton_Clicked"></Button>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
||||||
<controls:ExtendedListView
|
<controls:ExtendedCollectionView
|
||||||
IsVisible="{Binding ShowList}"
|
IsVisible="{Binding ShowList}"
|
||||||
ItemsSource="{Binding GroupedItems}"
|
ItemsSource="{Binding GroupedItems}"
|
||||||
VerticalOptions="FillAndExpand"
|
VerticalOptions="FillAndExpand"
|
||||||
HasUnevenRows="true"
|
|
||||||
ItemTemplate="{StaticResource listItemDataTemplateSelector}"
|
ItemTemplate="{StaticResource listItemDataTemplateSelector}"
|
||||||
IsGroupingEnabled="True"
|
IsGrouped="True"
|
||||||
ItemSelected="RowSelected"
|
SelectionMode="Single"
|
||||||
|
SelectionChanged="RowSelected"
|
||||||
StyleClass="list, list-platform">
|
StyleClass="list, list-platform">
|
||||||
<x:Arguments>
|
|
||||||
<ListViewCachingStrategy>RecycleElement</ListViewCachingStrategy>
|
|
||||||
</x:Arguments>
|
|
||||||
|
|
||||||
<ListView.GroupHeaderTemplate>
|
<CollectionView.GroupHeaderTemplate>
|
||||||
<DataTemplate x:DataType="pages:GroupingsPageListGroup">
|
<DataTemplate x:DataType="pages:GroupingsPageListGroup">
|
||||||
<ViewCell>
|
<StackLayout
|
||||||
<StackLayout
|
Spacing="0" Padding="0" VerticalOptions="FillAndExpand"
|
||||||
Spacing="0" Padding="0" VerticalOptions="FillAndExpand"
|
StyleClass="list-row-header-container, list-row-header-container-platform">
|
||||||
StyleClass="list-row-header-container, list-row-header-container-platform">
|
<BoxView
|
||||||
<BoxView
|
StyleClass="list-section-separator-top, list-section-separator-top-platform" />
|
||||||
StyleClass="list-section-separator-top, list-section-separator-top-platform" />
|
<StackLayout StyleClass="list-row-header, list-row-header-platform">
|
||||||
<StackLayout StyleClass="list-row-header, list-row-header-platform">
|
<Label
|
||||||
<Label
|
Text="{Binding Name}"
|
||||||
Text="{Binding Name}"
|
StyleClass="list-header, list-header-platform" />
|
||||||
StyleClass="list-header, list-header-platform" />
|
<Label
|
||||||
<Label
|
Text="{Binding ItemCount}"
|
||||||
Text="{Binding ItemCount}"
|
StyleClass="list-header-sub" />
|
||||||
StyleClass="list-header-sub" />
|
|
||||||
</StackLayout>
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ViewCell>
|
</StackLayout>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListView.GroupHeaderTemplate>
|
</CollectionView.GroupHeaderTemplate>
|
||||||
</controls:ExtendedListView>
|
</controls:ExtendedCollectionView>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</ContentPage.Resources>
|
</ContentPage.Resources>
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ using Bit.Core.Abstractions;
|
|||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Bit.App.Controls;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
@@ -44,14 +46,14 @@ namespace Bit.App.Pages
|
|||||||
}, _mainContent);
|
}, _mainContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void RowSelected(object sender, SelectedItemChangedEventArgs e)
|
private async void RowSelected(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
((ListView)sender).SelectedItem = null;
|
((ExtendedCollectionView)sender).SelectedItem = null;
|
||||||
if (!DoOnce())
|
if (!DoOnce())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (e.SelectedItem is GroupingsPageListItem item && item.Cipher != null)
|
if (e.CurrentSelection?.FirstOrDefault() is GroupingsPageListItem item && item.Cipher != null)
|
||||||
{
|
{
|
||||||
await _vm.SelectCipherAsync(item.Cipher, item.FuzzyAutofill);
|
await _vm.SelectCipherAsync(item.Cipher, item.FuzzyAutofill);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,15 +60,14 @@
|
|||||||
VerticalOptions="CenterAndExpand"
|
VerticalOptions="CenterAndExpand"
|
||||||
HorizontalOptions="CenterAndExpand"
|
HorizontalOptions="CenterAndExpand"
|
||||||
HorizontalTextAlignment="Center" />
|
HorizontalTextAlignment="Center" />
|
||||||
<ListView x:Name="_listView"
|
<controls:ExtendedCollectionView
|
||||||
IsVisible="{Binding ShowList}"
|
IsVisible="{Binding ShowList}"
|
||||||
ItemsSource="{Binding Ciphers}"
|
ItemsSource="{Binding Ciphers}"
|
||||||
VerticalOptions="FillAndExpand"
|
VerticalOptions="FillAndExpand"
|
||||||
HasUnevenRows="true"
|
SelectionMode="Single"
|
||||||
CachingStrategy="RecycleElement"
|
SelectionChanged="RowSelected"
|
||||||
ItemSelected="RowSelected"
|
|
||||||
StyleClass="list, list-platform">
|
StyleClass="list, list-platform">
|
||||||
<ListView.ItemTemplate>
|
<CollectionView.ItemTemplate>
|
||||||
<DataTemplate x:DataType="views:CipherView">
|
<DataTemplate x:DataType="views:CipherView">
|
||||||
<controls:CipherViewCell
|
<controls:CipherViewCell
|
||||||
Cipher="{Binding .}"
|
Cipher="{Binding .}"
|
||||||
@@ -76,8 +75,8 @@
|
|||||||
WebsiteIconsEnabled="{Binding BindingContext.WebsiteIconsEnabled, Source={x:Reference _page}}"
|
WebsiteIconsEnabled="{Binding BindingContext.WebsiteIconsEnabled, Source={x:Reference _page}}"
|
||||||
/>
|
/>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListView.ItemTemplate>
|
</CollectionView.ItemTemplate>
|
||||||
</ListView>
|
</controls:ExtendedCollectionView>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
||||||
</pages:BaseContentPage>
|
</pages:BaseContentPage>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Bit.App.Resources;
|
|||||||
using Bit.Core.Models.View;
|
using Bit.Core.Models.View;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using System;
|
using System;
|
||||||
|
using Bit.App.Controls;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
@@ -119,15 +120,15 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void RowSelected(object sender, SelectedItemChangedEventArgs e)
|
private async void RowSelected(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
((ListView)sender).SelectedItem = null;
|
((ExtendedCollectionView)sender).SelectedItem = null;
|
||||||
if (!DoOnce())
|
if (!DoOnce())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.SelectedItem is CipherView cipher)
|
if (e.CurrentSelection is CipherView cipher)
|
||||||
{
|
{
|
||||||
await _vm.SelectCipherAsync(cipher);
|
await _vm.SelectCipherAsync(cipher);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<pages:BaseContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
<pages:BaseContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
x:Class="Bit.App.Pages.GroupingsPage"
|
x:Class="Bit.App.Pages.GroupingsPage"
|
||||||
xmlns:pages="clr-namespace:Bit.App.Pages"
|
xmlns:pages="clr-namespace:Bit.App.Pages"
|
||||||
xmlns:u="clr-namespace:Bit.App.Utilities"
|
xmlns:u="clr-namespace:Bit.App.Utilities"
|
||||||
xmlns:effects="clr-namespace:Bit.App.Effects"
|
xmlns:effects="clr-namespace:Bit.App.Effects"
|
||||||
xmlns:controls="clr-namespace:Bit.App.Controls"
|
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||||
x:DataType="pages:GroupingsPageViewModel"
|
x:DataType="pages:GroupingsPageViewModel"
|
||||||
Title="{Binding PageTitle}"
|
Title="{Binding PageTitle}"
|
||||||
x:Name="_page">
|
x:Name="_page">
|
||||||
|
|
||||||
<ContentPage.BindingContext>
|
<ContentPage.BindingContext>
|
||||||
<pages:GroupingsPageViewModel />
|
<pages:GroupingsPageViewModel />
|
||||||
@@ -45,29 +45,27 @@
|
|||||||
|
|
||||||
<DataTemplate x:Key="groupTemplate"
|
<DataTemplate x:Key="groupTemplate"
|
||||||
x:DataType="pages:GroupingsPageListItem">
|
x:DataType="pages:GroupingsPageListItem">
|
||||||
<ViewCell>
|
<controls:ExtendedStackLayout Orientation="Horizontal"
|
||||||
<StackLayout Orientation="Horizontal"
|
StyleClass="list-row, list-row-platform">
|
||||||
StyleClass="list-row, list-row-platform">
|
<controls:FaLabel Text="{Binding Icon, Mode=OneWay}"
|
||||||
<controls:FaLabel Text="{Binding Icon, Mode=OneWay}"
|
HorizontalOptions="Start"
|
||||||
HorizontalOptions="Start"
|
VerticalOptions="Center"
|
||||||
VerticalOptions="Center"
|
StyleClass="list-icon, list-icon-platform">
|
||||||
StyleClass="list-icon, list-icon-platform">
|
<controls:FaLabel.Effects>
|
||||||
<controls:FaLabel.Effects>
|
<effects:FixedSizeEffect />
|
||||||
<effects:FixedSizeEffect />
|
</controls:FaLabel.Effects>
|
||||||
</controls:FaLabel.Effects>
|
</controls:FaLabel>
|
||||||
</controls:FaLabel>
|
<Label Text="{Binding Name, Mode=OneWay}"
|
||||||
<Label Text="{Binding Name, Mode=OneWay}"
|
LineBreakMode="TailTruncation"
|
||||||
LineBreakMode="TailTruncation"
|
HorizontalOptions="FillAndExpand"
|
||||||
HorizontalOptions="FillAndExpand"
|
VerticalOptions="CenterAndExpand"
|
||||||
VerticalOptions="CenterAndExpand"
|
StyleClass="list-title"/>
|
||||||
StyleClass="list-title"/>
|
<Label Text="{Binding ItemCount, Mode=OneWay}"
|
||||||
<Label Text="{Binding ItemCount, Mode=OneWay}"
|
HorizontalOptions="End"
|
||||||
HorizontalOptions="End"
|
VerticalOptions="CenterAndExpand"
|
||||||
VerticalOptions="CenterAndExpand"
|
HorizontalTextAlignment="End"
|
||||||
HorizontalTextAlignment="End"
|
StyleClass="list-sub"/>
|
||||||
StyleClass="list-sub"/>
|
</controls:ExtendedStackLayout>
|
||||||
</StackLayout>
|
|
||||||
</ViewCell>
|
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
<pages:GroupingsPageListItemSelector x:Key="listItemDataTemplateSelector"
|
<pages:GroupingsPageListItemSelector x:Key="listItemDataTemplateSelector"
|
||||||
@@ -89,27 +87,21 @@
|
|||||||
IsVisible="{Binding ShowAddCipherButton}"></Button>
|
IsVisible="{Binding ShowAddCipherButton}"></Button>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
||||||
<controls:ExtendedListView
|
<RefreshView
|
||||||
x:Name="_listView"
|
|
||||||
IsVisible="{Binding ShowList}"
|
IsVisible="{Binding ShowList}"
|
||||||
ItemsSource="{Binding GroupedItems}"
|
|
||||||
VerticalOptions="FillAndExpand"
|
|
||||||
HasUnevenRows="True"
|
|
||||||
RowHeight="-1"
|
|
||||||
RefreshCommand="{Binding RefreshCommand}"
|
|
||||||
IsPullToRefreshEnabled="True"
|
|
||||||
IsRefreshing="{Binding Refreshing}"
|
IsRefreshing="{Binding Refreshing}"
|
||||||
ItemTemplate="{StaticResource listItemDataTemplateSelector}"
|
Command="{Binding RefreshCommand}">
|
||||||
IsGroupingEnabled="True"
|
<controls:ExtendedCollectionView
|
||||||
ItemSelected="RowSelected"
|
ItemsSource="{Binding GroupedItems}"
|
||||||
StyleClass="list, list-platform">
|
VerticalOptions="FillAndExpand"
|
||||||
<x:Arguments>
|
ItemTemplate="{StaticResource listItemDataTemplateSelector}"
|
||||||
<ListViewCachingStrategy>RecycleElement</ListViewCachingStrategy>
|
IsGrouped="True"
|
||||||
</x:Arguments>
|
SelectionMode="Single"
|
||||||
|
SelectionChanged="RowSelected"
|
||||||
|
StyleClass="list, list-platform">
|
||||||
|
|
||||||
<ListView.GroupHeaderTemplate>
|
<CollectionView.GroupHeaderTemplate>
|
||||||
<DataTemplate x:DataType="pages:GroupingsPageListGroup">
|
<DataTemplate x:DataType="pages:GroupingsPageListGroup">
|
||||||
<ViewCell>
|
|
||||||
<StackLayout
|
<StackLayout
|
||||||
Spacing="0" Padding="0" VerticalOptions="FillAndExpand"
|
Spacing="0" Padding="0" VerticalOptions="FillAndExpand"
|
||||||
StyleClass="list-row-header-container, list-row-header-container-platform">
|
StyleClass="list-row-header-container, list-row-header-container-platform">
|
||||||
@@ -126,10 +118,10 @@
|
|||||||
</StackLayout>
|
</StackLayout>
|
||||||
<BoxView StyleClass="list-section-separator-bottom, list-section-separator-bottom-platform" />
|
<BoxView StyleClass="list-section-separator-bottom, list-section-separator-bottom-platform" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ViewCell>
|
</DataTemplate>
|
||||||
</DataTemplate>
|
</CollectionView.GroupHeaderTemplate>
|
||||||
</ListView.GroupHeaderTemplate>
|
</controls:ExtendedCollectionView>
|
||||||
</controls:ExtendedListView>
|
</RefreshView>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</ContentPage.Resources>
|
</ContentPage.Resources>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.App.Controls;
|
|
||||||
using Bit.App.Models;
|
using Bit.App.Models;
|
||||||
using Bit.App.Resources;
|
using Bit.App.Resources;
|
||||||
using Bit.Core;
|
using Bit.Core;
|
||||||
@@ -9,6 +8,7 @@ using Bit.Core.Utilities;
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Bit.App.Controls;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
@@ -33,7 +33,6 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
_pageName = string.Concat(nameof(GroupingsPage), "_", DateTime.UtcNow.Ticks);
|
_pageName = string.Concat(nameof(GroupingsPage), "_", DateTime.UtcNow.Ticks);
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
ListView = _listView;
|
|
||||||
SetActivityIndicator(_mainContent);
|
SetActivityIndicator(_mainContent);
|
||||||
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
|
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
|
||||||
_syncService = ServiceContainer.Resolve<ISyncService>("syncService");
|
_syncService = ServiceContainer.Resolve<ISyncService>("syncService");
|
||||||
@@ -73,8 +72,6 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExtendedListView ListView { get; set; }
|
|
||||||
|
|
||||||
protected async override void OnAppearing()
|
protected async override void OnAppearing()
|
||||||
{
|
{
|
||||||
base.OnAppearing();
|
base.OnAppearing();
|
||||||
@@ -197,14 +194,14 @@ namespace Bit.App.Pages
|
|||||||
_vm.DisableRefreshing();
|
_vm.DisableRefreshing();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void RowSelected(object sender, SelectedItemChangedEventArgs e)
|
private async void RowSelected(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
((ListView)sender).SelectedItem = null;
|
((ExtendedCollectionView)sender).SelectedItem = null;
|
||||||
if (!DoOnce())
|
if (!DoOnce())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!(e.SelectedItem is GroupingsPageListItem item))
|
if (!(e.CurrentSelection?.FirstOrDefault() is GroupingsPageListItem item))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,30 +75,30 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
else if (Folder != null)
|
else if (Folder != null)
|
||||||
{
|
{
|
||||||
_icon = Folder.Id == null ? "" : "";
|
_icon = Folder.Id == null ? "\uf115" : "\uf07c"; // fa-folder-open-o : fa-folder-open
|
||||||
}
|
}
|
||||||
else if (Collection != null)
|
else if (Collection != null)
|
||||||
{
|
{
|
||||||
_icon = "";
|
_icon = "\uf1b2"; // fa-cube
|
||||||
}
|
}
|
||||||
else if (Type != null)
|
else if (Type != null)
|
||||||
{
|
{
|
||||||
switch (Type.Value)
|
switch (Type.Value)
|
||||||
{
|
{
|
||||||
case CipherType.Login:
|
case CipherType.Login:
|
||||||
_icon = "";
|
_icon = "\uf0ac"; // fa-globe
|
||||||
break;
|
break;
|
||||||
case CipherType.SecureNote:
|
case CipherType.SecureNote:
|
||||||
_icon = "";
|
_icon = "\uf24a"; // fa-sticky-note-o
|
||||||
break;
|
break;
|
||||||
case CipherType.Card:
|
case CipherType.Card:
|
||||||
_icon = "";
|
_icon = "\uf09d"; // fa-credit-card
|
||||||
break;
|
break;
|
||||||
case CipherType.Identity:
|
case CipherType.Identity:
|
||||||
_icon = "";
|
_icon = "\uf2c3"; // fa-id-card-o
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
_icon = "";
|
_icon = "\uf0ac"; // fa-globe
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,57 +34,53 @@
|
|||||||
VerticalOptions="CenterAndExpand"
|
VerticalOptions="CenterAndExpand"
|
||||||
HorizontalOptions="CenterAndExpand"
|
HorizontalOptions="CenterAndExpand"
|
||||||
HorizontalTextAlignment="Center"></Label>
|
HorizontalTextAlignment="Center"></Label>
|
||||||
<ListView x:Name="_listView"
|
<controls:ExtendedCollectionView
|
||||||
IsVisible="{Binding ShowNoData, Converter={StaticResource inverseBool}}"
|
IsVisible="{Binding ShowNoData, Converter={StaticResource inverseBool}}"
|
||||||
ItemsSource="{Binding History}"
|
ItemsSource="{Binding History}"
|
||||||
VerticalOptions="FillAndExpand"
|
VerticalOptions="FillAndExpand"
|
||||||
HasUnevenRows="true"
|
|
||||||
CachingStrategy="RecycleElement"
|
|
||||||
StyleClass="list, list-platform">
|
StyleClass="list, list-platform">
|
||||||
<ListView.ItemTemplate>
|
<CollectionView.ItemTemplate>
|
||||||
<DataTemplate x:DataType="views:PasswordHistoryView">
|
<DataTemplate x:DataType="views:PasswordHistoryView">
|
||||||
<ViewCell>
|
<Grid
|
||||||
<Grid
|
StyleClass="list-row, list-row-platform"
|
||||||
StyleClass="list-row, list-row-platform"
|
Padding="10"
|
||||||
Padding="10"
|
RowSpacing="0"
|
||||||
RowSpacing="0"
|
ColumnSpacing="10">
|
||||||
ColumnSpacing="10">
|
|
||||||
|
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<controls:MonoLabel LineBreakMode="CharacterWrap"
|
<controls:MonoLabel LineBreakMode="CharacterWrap"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
StyleClass="list-title, list-title-platform"
|
StyleClass="list-title, list-title-platform"
|
||||||
TextType="Html"
|
TextType="Html"
|
||||||
Text="{Binding Password, Mode=OneWay, Converter={StaticResource coloredPassword}}" />
|
Text="{Binding Password, Mode=OneWay, Converter={StaticResource coloredPassword}}" />
|
||||||
<Label LineBreakMode="TailTruncation"
|
<Label LineBreakMode="TailTruncation"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
StyleClass="list-subtitle, list-subtitle-platform"
|
StyleClass="list-subtitle, list-subtitle-platform"
|
||||||
Text="{Binding LastUsedDate, Mode=OneWay, Converter={StaticResource dateTime}}" />
|
Text="{Binding LastUsedDate, Mode=OneWay, Converter={StaticResource dateTime}}" />
|
||||||
<controls:FaButton
|
<controls:FaButton
|
||||||
StyleClass="list-row-button, list-row-button-platform"
|
StyleClass="list-row-button, list-row-button-platform"
|
||||||
Text=""
|
Text=""
|
||||||
Command="{Binding BindingContext.CopyCommand, Source={x:Reference _page}}"
|
Command="{Binding BindingContext.CopyCommand, Source={x:Reference _page}}"
|
||||||
CommandParameter="{Binding .}"
|
CommandParameter="{Binding .}"
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Grid.RowSpan="2"
|
Grid.RowSpan="2"
|
||||||
AutomationProperties.IsInAccessibleTree="True"
|
AutomationProperties.IsInAccessibleTree="True"
|
||||||
AutomationProperties.Name="{u:I18n CopyPassword}" />
|
AutomationProperties.Name="{u:I18n CopyPassword}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</ViewCell>
|
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListView.ItemTemplate>
|
</CollectionView.ItemTemplate>
|
||||||
</ListView>
|
</controls:ExtendedCollectionView>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
||||||
</pages:BaseContentPage>
|
</pages:BaseContentPage>
|
||||||
|
|||||||
8
src/App/Resources/AppResources.Designer.cs
generated
8
src/App/Resources/AppResources.Designer.cs
generated
@@ -1,7 +1,6 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// <auto-generated>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// This code was generated by a tool.
|
||||||
// Runtime Version:4.0.30319.42000
|
|
||||||
//
|
//
|
||||||
// Changes to this file may cause incorrect behavior and will be lost if
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@@ -10,7 +9,6 @@
|
|||||||
|
|
||||||
namespace Bit.App.Resources {
|
namespace Bit.App.Resources {
|
||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
|
|
||||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||||
@@ -3371,6 +3369,12 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string AddASend {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("AddASend", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static string CopyLink {
|
public static string CopyLink {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("CopyLink", resourceCulture);
|
return ResourceManager.GetString("CopyLink", resourceCulture);
|
||||||
|
|||||||
@@ -1904,6 +1904,10 @@
|
|||||||
<value>There are no Sends in your account.</value>
|
<value>There are no Sends in your account.</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="AddASend" xml:space="preserve">
|
||||||
|
<value>Add a Send</value>
|
||||||
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
|
</data>
|
||||||
<data name="CopyLink" xml:space="preserve">
|
<data name="CopyLink" xml:space="preserve">
|
||||||
<value>Copy Link</value>
|
<value>Copy Link</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -68,10 +68,10 @@
|
|||||||
|
|
||||||
<!-- List -->
|
<!-- List -->
|
||||||
|
|
||||||
<Style TargetType="ListView"
|
<Style TargetType="BoxView"
|
||||||
Class="list-platform"
|
Class="list-item-separator-bottom-platform"
|
||||||
ApplyToDerivedTypes="True">
|
ApplyToDerivedTypes="True">
|
||||||
<Setter Property="SeparatorColor"
|
<Setter Property="BackgroundColor"
|
||||||
Value="Transparent" />
|
Value="Transparent" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style TargetType="StackLayout"
|
<Style TargetType="StackLayout"
|
||||||
@@ -105,9 +105,15 @@
|
|||||||
<Style TargetType="StackLayout"
|
<Style TargetType="StackLayout"
|
||||||
Class="list-row-platform">
|
Class="list-row-platform">
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style TargetType="controls:ExtendedStackLayout"
|
||||||
|
Class="list-row-platform">
|
||||||
|
</Style>
|
||||||
<Style TargetType="Grid"
|
<Style TargetType="Grid"
|
||||||
Class="list-row-platform">
|
Class="list-row-platform">
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style TargetType="controls:ExtendedGrid"
|
||||||
|
Class="list-row-platform">
|
||||||
|
</Style>
|
||||||
<Style TargetType="Label"
|
<Style TargetType="Label"
|
||||||
Class="list-icon-platform"
|
Class="list-icon-platform"
|
||||||
ApplyToDerivedTypes="True">
|
ApplyToDerivedTypes="True">
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
|
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:controls="clr-namespace:Bit.App.Controls;assembly=BitwardenApp"
|
||||||
x:Class="Bit.App.Styles.Base">
|
x:Class="Bit.App.Styles.Base">
|
||||||
|
|
||||||
<!-- General -->
|
<!-- General -->
|
||||||
@@ -124,7 +125,7 @@
|
|||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<!-- List -->
|
<!-- List -->
|
||||||
<Style TargetType="ListView"
|
<Style TargetType="CollectionView"
|
||||||
Class="list">
|
Class="list">
|
||||||
</Style>
|
</Style>
|
||||||
<Style TargetType="StackLayout"
|
<Style TargetType="StackLayout"
|
||||||
@@ -161,11 +162,21 @@
|
|||||||
<Setter Property="Padding"
|
<Setter Property="Padding"
|
||||||
Value="10, 12" />
|
Value="10, 12" />
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style TargetType="controls:ExtendedStackLayout"
|
||||||
|
Class="list-row">
|
||||||
|
<Setter Property="Padding"
|
||||||
|
Value="10, 12" />
|
||||||
|
</Style>
|
||||||
<Style TargetType="Grid"
|
<Style TargetType="Grid"
|
||||||
Class="list-row">
|
Class="list-row">
|
||||||
<Setter Property="Padding"
|
<Setter Property="Padding"
|
||||||
Value="2, 5, 0, 5" />
|
Value="2, 5, 0, 5" />
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style TargetType="controls:ExtendedGrid"
|
||||||
|
Class="list-row">
|
||||||
|
<Setter Property="Padding"
|
||||||
|
Value="2, 5, 0, 5" />
|
||||||
|
</Style>
|
||||||
<Style TargetType="BoxView"
|
<Style TargetType="BoxView"
|
||||||
Class="list-section-separator-top">
|
Class="list-section-separator-top">
|
||||||
<Setter Property="HeightRequest"
|
<Setter Property="HeightRequest"
|
||||||
@@ -176,6 +187,11 @@
|
|||||||
<Setter Property="HeightRequest"
|
<Setter Property="HeightRequest"
|
||||||
Value="1" />
|
Value="1" />
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style TargetType="BoxView"
|
||||||
|
Class="list-item-separator-bottom">
|
||||||
|
<Setter Property="HeightRequest"
|
||||||
|
Value="1" />
|
||||||
|
</Style>
|
||||||
<Style TargetType="Label"
|
<Style TargetType="Label"
|
||||||
Class="list-title">
|
Class="list-title">
|
||||||
</Style>
|
</Style>
|
||||||
|
|||||||
@@ -51,11 +51,14 @@
|
|||||||
<Setter Property="BackgroundColor"
|
<Setter Property="BackgroundColor"
|
||||||
Value="{StaticResource BackgroundColor}" />
|
Value="{StaticResource BackgroundColor}" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style TargetType="ListView"
|
<Style TargetType="CollectionView"
|
||||||
ApplyToDerivedTypes="True">
|
ApplyToDerivedTypes="True">
|
||||||
<Setter Property="BackgroundColor"
|
<Setter Property="BackgroundColor"
|
||||||
Value="{StaticResource BackgroundColor}" />
|
Value="{StaticResource BackgroundColor}" />
|
||||||
<Setter Property="RefreshControlColor"
|
</Style>
|
||||||
|
<Style TargetType="RefreshView"
|
||||||
|
ApplyToDerivedTypes="True">
|
||||||
|
<Setter Property="RefreshColor"
|
||||||
Value="{StaticResource PrimaryColor}" />
|
Value="{StaticResource PrimaryColor}" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style TargetType="ActivityIndicator"
|
<Style TargetType="ActivityIndicator"
|
||||||
@@ -93,10 +96,10 @@
|
|||||||
|
|
||||||
<!-- List -->
|
<!-- List -->
|
||||||
|
|
||||||
<Style TargetType="ListView"
|
<Style TargetType="BoxView"
|
||||||
Class="list-platform"
|
Class="list-item-separator-bottom-platform"
|
||||||
ApplyToDerivedTypes="True">
|
ApplyToDerivedTypes="True">
|
||||||
<Setter Property="SeparatorColor"
|
<Setter Property="BackgroundColor"
|
||||||
Value="{StaticResource ListItemBorderColor}" />
|
Value="{StaticResource ListItemBorderColor}" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style TargetType="StackLayout"
|
<Style TargetType="StackLayout"
|
||||||
@@ -107,7 +110,7 @@
|
|||||||
<Style TargetType="StackLayout"
|
<Style TargetType="StackLayout"
|
||||||
Class="list-row-header-platform">
|
Class="list-row-header-platform">
|
||||||
<Setter Property="Padding"
|
<Setter Property="Padding"
|
||||||
Value="10, 0, 10, 5" />
|
Value="10, 22, 10, 5" />
|
||||||
<Setter Property="VerticalOptions"
|
<Setter Property="VerticalOptions"
|
||||||
Value="EndAndExpand" />
|
Value="EndAndExpand" />
|
||||||
</Style>
|
</Style>
|
||||||
@@ -127,15 +130,19 @@
|
|||||||
Class="list-section-separator-bottom-platform">
|
Class="list-section-separator-bottom-platform">
|
||||||
<Setter Property="Color"
|
<Setter Property="Color"
|
||||||
Value="{StaticResource ListSectionBorderBottomColor}" />
|
Value="{StaticResource ListSectionBorderBottomColor}" />
|
||||||
<Setter Property="Margin"
|
|
||||||
Value="0, 0, 0, -1" />
|
|
||||||
</Style>
|
</Style>
|
||||||
<Style TargetType="StackLayout"
|
<Style TargetType="StackLayout"
|
||||||
Class="list-row-platform">
|
Class="list-row-platform">
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style TargetType="controls:ExtendedStackLayout"
|
||||||
|
Class="list-row-platform">
|
||||||
|
</Style>
|
||||||
<Style TargetType="Grid"
|
<Style TargetType="Grid"
|
||||||
Class="list-row-platform">
|
Class="list-row-platform">
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style TargetType="controls:ExtendedGrid"
|
||||||
|
Class="list-row-platform">
|
||||||
|
</Style>
|
||||||
<Style TargetType="Label"
|
<Style TargetType="Label"
|
||||||
Class="list-icon-platform"
|
Class="list-icon-platform"
|
||||||
ApplyToDerivedTypes="True">
|
ApplyToDerivedTypes="True">
|
||||||
|
|||||||
64
src/App/Utilities/IconGlyphConverter.cs
Normal file
64
src/App/Utilities/IconGlyphConverter.cs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using Bit.Core;
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Models.View;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Bit.App.Utilities
|
||||||
|
{
|
||||||
|
public class IconGlyphConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
var cipher = value as CipherView;
|
||||||
|
return GetIcon(cipher);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetIcon(CipherView cipher)
|
||||||
|
{
|
||||||
|
string icon = null;
|
||||||
|
switch (cipher.Type)
|
||||||
|
{
|
||||||
|
case CipherType.Login:
|
||||||
|
icon = GetLoginIconGlyph(cipher);
|
||||||
|
break;
|
||||||
|
case CipherType.SecureNote:
|
||||||
|
icon = "\uf24a"; // fa-sticky-note-o
|
||||||
|
break;
|
||||||
|
case CipherType.Card:
|
||||||
|
icon = "\uf09d"; // fa-credit-card
|
||||||
|
break;
|
||||||
|
case CipherType.Identity:
|
||||||
|
icon = "\uf2c3"; // fa-id-card-o
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetLoginIconGlyph(CipherView cipher)
|
||||||
|
{
|
||||||
|
var icon = "\uf0ac"; // fa-globe
|
||||||
|
if (cipher.Login.Uri != null)
|
||||||
|
{
|
||||||
|
var hostnameUri = cipher.Login.Uri;
|
||||||
|
if (hostnameUri.StartsWith(Constants.AndroidAppProtocol))
|
||||||
|
{
|
||||||
|
icon = "\uf17b"; // fa-android
|
||||||
|
}
|
||||||
|
else if (hostnameUri.StartsWith(Constants.iOSAppProtocol))
|
||||||
|
{
|
||||||
|
icon = "\uf179"; // fa-apple
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
79
src/App/Utilities/IconImageConverter.cs
Normal file
79
src/App/Utilities/IconImageConverter.cs
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using Bit.Core.Abstractions;
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Models.View;
|
||||||
|
using Bit.Core.Utilities;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Bit.App.Utilities
|
||||||
|
{
|
||||||
|
public class IconImageConverter : IValueConverter
|
||||||
|
{
|
||||||
|
private readonly IEnvironmentService _environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
|
||||||
|
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
var cipher = value as CipherView;
|
||||||
|
return GetIcon(cipher);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetIcon(CipherView cipher)
|
||||||
|
{
|
||||||
|
string icon = null;
|
||||||
|
switch (cipher.Type)
|
||||||
|
{
|
||||||
|
case CipherType.Login:
|
||||||
|
icon = GetLoginIconImage(cipher);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetLoginIconImage(CipherView cipher)
|
||||||
|
{
|
||||||
|
string image = null;
|
||||||
|
if (cipher.Login.Uri != null)
|
||||||
|
{
|
||||||
|
var hostnameUri = cipher.Login.Uri;
|
||||||
|
var isWebsite = false;
|
||||||
|
|
||||||
|
if (!hostnameUri.Contains("://") && hostnameUri.Contains("."))
|
||||||
|
{
|
||||||
|
hostnameUri = string.Concat("http://", hostnameUri);
|
||||||
|
isWebsite = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isWebsite = hostnameUri.StartsWith("http") && hostnameUri.Contains(".");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isWebsite)
|
||||||
|
{
|
||||||
|
var hostname = CoreHelpers.GetHostname(hostnameUri);
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
image = string.Format("{0}/{1}/icon.png", iconsUrl, hostname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
36
src/App/Utilities/SendIconGlyphConverter.cs
Normal file
36
src/App/Utilities/SendIconGlyphConverter.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Models.View;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Bit.App.Utilities
|
||||||
|
{
|
||||||
|
public class SendIconGlyphConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
var send = value as SendView;
|
||||||
|
if (send == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
string icon = null;
|
||||||
|
switch (send.Type)
|
||||||
|
{
|
||||||
|
case SendType.Text:
|
||||||
|
icon = "\uf0f6"; // fa-file-text-o
|
||||||
|
break;
|
||||||
|
case SendType.File:
|
||||||
|
icon = "\uf016"; // fa-file-o
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -66,10 +66,9 @@ namespace Bit.iOS.Core.Services
|
|||||||
{
|
{
|
||||||
Duration = TimeSpan.FromSeconds(longDuration ? 5 : 3)
|
Duration = TimeSpan.FromSeconds(longDuration ? 5 : 3)
|
||||||
};
|
};
|
||||||
if (TabBarVisible())
|
_toast.BottomMargin = 110;
|
||||||
{
|
_toast.LeftMargin = 20;
|
||||||
_toast.BottomMargin = 55;
|
_toast.RightMargin = 20;
|
||||||
}
|
|
||||||
_toast.Show();
|
_toast.Show();
|
||||||
_toast.DismissCallback = () =>
|
_toast.DismissCallback = () =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Bit.iOS.Core.Views
|
|||||||
bgColor = Color.FromHex("#4c566a").ToUIColor();
|
bgColor = Color.FromHex("#4c566a").ToUIColor();
|
||||||
}
|
}
|
||||||
BackgroundColor = bgColor.ColorWithAlpha(0.9f);
|
BackgroundColor = bgColor.ColorWithAlpha(0.9f);
|
||||||
Layer.CornerRadius = 15;
|
Layer.CornerRadius = 18;
|
||||||
Layer.MasksToBounds = true;
|
Layer.MasksToBounds = true;
|
||||||
|
|
||||||
MessageLabel = new UILabel
|
MessageLabel = new UILabel
|
||||||
|
|||||||
@@ -163,7 +163,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Xamarin.Essentials">
|
<PackageReference Include="Xamarin.Essentials">
|
||||||
<Version>1.5.3.2</Version>
|
<Version>1.6.1</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
|
||||||
|
|||||||
Reference in New Issue
Block a user