mirror of
https://github.com/bitwarden/mobile.git
synced 2024-11-30 12:54:24 +01:00
redraw stack layouts on ios tableviews
This commit is contained in:
parent
fa9e22730a
commit
9456f5dc31
@ -1,6 +1,4 @@
|
|||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
using XLabs.Ioc;
|
|
||||||
using Bit.App.Abstractions;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
@ -42,6 +40,7 @@ namespace Bit.App.Controls
|
|||||||
public bool NoHeader { get; set; }
|
public bool NoHeader { get; set; }
|
||||||
public bool NoFooter { get; set; }
|
public bool NoFooter { get; set; }
|
||||||
public int BottomPadding { get; set; }
|
public int BottomPadding { get; set; }
|
||||||
|
public Func<RedrawableStackLayout> WrappingStackLayout { get; set; }
|
||||||
|
|
||||||
protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
|
protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
|
||||||
{
|
{
|
||||||
|
27
src/App/Controls/RedrawableStackLayout.cs
Normal file
27
src/App/Controls/RedrawableStackLayout.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Bit.App.Controls
|
||||||
|
{
|
||||||
|
public class RedrawableStackLayout : StackLayout
|
||||||
|
{
|
||||||
|
private DateTime _lastRedraw = DateTime.MinValue;
|
||||||
|
private TimeSpan _redrawThreshold = TimeSpan.FromMilliseconds(1000);
|
||||||
|
|
||||||
|
public async Task RedrawIfNeededAsync(int delay = 0, bool force = false)
|
||||||
|
{
|
||||||
|
var now = DateTime.UtcNow;
|
||||||
|
if(Device.RuntimePlatform == Device.iOS && (force || (now - _lastRedraw) > _redrawThreshold))
|
||||||
|
{
|
||||||
|
_lastRedraw = now;
|
||||||
|
if(delay > 0)
|
||||||
|
{
|
||||||
|
await Task.Delay(delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
InvalidateLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -30,7 +30,7 @@ namespace Bit.App.Pages
|
|||||||
public FormEntryCell ApiUrlCell { get; set; }
|
public FormEntryCell ApiUrlCell { get; set; }
|
||||||
public FormEntryCell IdentityUrlCell { get; set; }
|
public FormEntryCell IdentityUrlCell { get; set; }
|
||||||
public FormEntryCell IconsUrlCell { get; set; }
|
public FormEntryCell IconsUrlCell { get; set; }
|
||||||
public StackLayout StackLayout { get; set; }
|
public RedrawableStackLayout StackLayout { get; set; }
|
||||||
public Label SelfHostLabel { get; set; }
|
public Label SelfHostLabel { get; set; }
|
||||||
public Label CustomLabel { get; set; }
|
public Label CustomLabel { get; set; }
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ namespace Bit.App.Pages
|
|||||||
entryKeyboard: Keyboard.Url);
|
entryKeyboard: Keyboard.Url);
|
||||||
BaseUrlCell.Entry.Text = _appSettings.BaseUrl;
|
BaseUrlCell.Entry.Text = _appSettings.BaseUrl;
|
||||||
|
|
||||||
var table = new FormTableView
|
var table = new FormTableView(this)
|
||||||
{
|
{
|
||||||
Root = new TableRoot
|
Root = new TableRoot
|
||||||
{
|
{
|
||||||
@ -74,10 +74,10 @@ namespace Bit.App.Pages
|
|||||||
LineBreakMode = LineBreakMode.WordWrap,
|
LineBreakMode = LineBreakMode.WordWrap,
|
||||||
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
|
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
|
||||||
Style = (Style)Application.Current.Resources["text-muted"],
|
Style = (Style)Application.Current.Resources["text-muted"],
|
||||||
Margin = new Thickness(15, (this.IsLandscape() ? 5 : 0), 15, 25)
|
Margin = new Thickness(15, (this.IsLandscape() ? 5 : 0), 15, 5)
|
||||||
};
|
};
|
||||||
|
|
||||||
var table2 = new FormTableView
|
var table2 = new FormTableView(this)
|
||||||
{
|
{
|
||||||
Root = new TableRoot
|
Root = new TableRoot
|
||||||
{
|
{
|
||||||
@ -97,10 +97,10 @@ namespace Bit.App.Pages
|
|||||||
LineBreakMode = LineBreakMode.WordWrap,
|
LineBreakMode = LineBreakMode.WordWrap,
|
||||||
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
|
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
|
||||||
Style = (Style)Application.Current.Resources["text-muted"],
|
Style = (Style)Application.Current.Resources["text-muted"],
|
||||||
Margin = new Thickness(15, (this.IsLandscape() ? 5 : 0), 15, 25)
|
Margin = new Thickness(15, (this.IsLandscape() ? 5 : 0), 15, 5)
|
||||||
};
|
};
|
||||||
|
|
||||||
StackLayout = new StackLayout
|
StackLayout = new RedrawableStackLayout
|
||||||
{
|
{
|
||||||
Children = { table, SelfHostLabel, table2, CustomLabel },
|
Children = { table, SelfHostLabel, table2, CustomLabel },
|
||||||
Spacing = 0
|
Spacing = 0
|
||||||
@ -138,7 +138,6 @@ namespace Bit.App.Pages
|
|||||||
IdentityUrlCell.InitEvents();
|
IdentityUrlCell.InitEvents();
|
||||||
ApiUrlCell.InitEvents();
|
ApiUrlCell.InitEvents();
|
||||||
WebVaultUrlCell.InitEvents();
|
WebVaultUrlCell.InitEvents();
|
||||||
StackLayout.LayoutChanged += Layout_LayoutChanged;
|
|
||||||
BaseUrlCell.Entry.FocusWithDelay();
|
BaseUrlCell.Entry.FocusWithDelay();
|
||||||
}
|
}
|
||||||
protected override void OnDisappearing()
|
protected override void OnDisappearing()
|
||||||
@ -149,13 +148,6 @@ namespace Bit.App.Pages
|
|||||||
IdentityUrlCell.Dispose();
|
IdentityUrlCell.Dispose();
|
||||||
ApiUrlCell.Dispose();
|
ApiUrlCell.Dispose();
|
||||||
WebVaultUrlCell.Dispose();
|
WebVaultUrlCell.Dispose();
|
||||||
StackLayout.LayoutChanged -= Layout_LayoutChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Layout_LayoutChanged(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
SelfHostLabel.WidthRequest = StackLayout.Bounds.Width - SelfHostLabel.Bounds.Left * 2;
|
|
||||||
CustomLabel.WidthRequest = StackLayout.Bounds.Width - CustomLabel.Bounds.Left * 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SaveAsync()
|
private async Task SaveAsync()
|
||||||
@ -259,7 +251,7 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
private class FormTableView : ExtendedTableView
|
private class FormTableView : ExtendedTableView
|
||||||
{
|
{
|
||||||
public FormTableView()
|
public FormTableView(EnvironmentPage page)
|
||||||
{
|
{
|
||||||
Intent = TableIntent.Settings;
|
Intent = TableIntent.Settings;
|
||||||
EnableScrolling = false;
|
EnableScrolling = false;
|
||||||
@ -267,6 +259,7 @@ namespace Bit.App.Pages
|
|||||||
EnableSelection = true;
|
EnableSelection = true;
|
||||||
VerticalOptions = LayoutOptions.Start;
|
VerticalOptions = LayoutOptions.Start;
|
||||||
NoFooter = true;
|
NoFooter = true;
|
||||||
|
WrappingStackLayout = () => page.StackLayout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,12 +67,14 @@ namespace Bit.App.Pages
|
|||||||
Uppercase = false
|
Uppercase = false
|
||||||
};
|
};
|
||||||
|
|
||||||
var stackLayout = new StackLayout
|
var stackLayout = new RedrawableStackLayout
|
||||||
{
|
{
|
||||||
Spacing = 10,
|
Spacing = 10,
|
||||||
Children = { table, logoutButton }
|
Children = { table, logoutButton }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
table.WrappingStackLayout = () => stackLayout;
|
||||||
|
|
||||||
var scrollView = new ScrollView { Content = stackLayout };
|
var scrollView = new ScrollView { Content = stackLayout };
|
||||||
|
|
||||||
if(Device.RuntimePlatform == Device.iOS)
|
if(Device.RuntimePlatform == Device.iOS)
|
||||||
|
@ -71,7 +71,6 @@ namespace Bit.App.Pages
|
|||||||
HasUnevenRows = true,
|
HasUnevenRows = true,
|
||||||
EnableSelection = true,
|
EnableSelection = true,
|
||||||
NoFooter = true,
|
NoFooter = true,
|
||||||
//NoHeader = true,
|
|
||||||
VerticalOptions = LayoutOptions.Start,
|
VerticalOptions = LayoutOptions.Start,
|
||||||
Root = new TableRoot
|
Root = new TableRoot
|
||||||
{
|
{
|
||||||
@ -87,18 +86,20 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
Text = AppResources.GetPasswordHint,
|
Text = AppResources.GetPasswordHint,
|
||||||
Style = (Style)Application.Current.Resources["btn-primaryAccent"],
|
Style = (Style)Application.Current.Resources["btn-primaryAccent"],
|
||||||
Margin = new Thickness(15, 0, 15, 25),
|
|
||||||
Command = new Command(async () => await ForgotPasswordAsync()),
|
Command = new Command(async () => await ForgotPasswordAsync()),
|
||||||
|
VerticalOptions = LayoutOptions.End,
|
||||||
Uppercase = false,
|
Uppercase = false,
|
||||||
BackgroundColor = Color.Transparent
|
BackgroundColor = Color.Transparent
|
||||||
};
|
};
|
||||||
|
|
||||||
var layout = new StackLayout
|
var layout = new RedrawableStackLayout
|
||||||
{
|
{
|
||||||
Children = { table, forgotPasswordButton },
|
Children = { table, forgotPasswordButton },
|
||||||
Spacing = Helpers.OnPlatform(iOS: 0, Android: 10, Windows: 0)
|
Spacing = 10
|
||||||
};
|
};
|
||||||
|
|
||||||
|
table.WrappingStackLayout = () => layout;
|
||||||
|
|
||||||
var scrollView = new ScrollView { Content = layout };
|
var scrollView = new ScrollView { Content = layout };
|
||||||
|
|
||||||
if(Device.RuntimePlatform == Device.iOS)
|
if(Device.RuntimePlatform == Device.iOS)
|
||||||
|
@ -135,12 +135,13 @@ namespace Bit.App.Pages
|
|||||||
RememberCell
|
RememberCell
|
||||||
});
|
});
|
||||||
|
|
||||||
var layout = new StackLayout
|
var layout = new RedrawableStackLayout
|
||||||
{
|
{
|
||||||
Children = { instruction, table },
|
Children = { instruction, table },
|
||||||
Spacing = 0
|
Spacing = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
table.WrappingStackLayout = () => layout;
|
||||||
scrollView.Content = layout;
|
scrollView.Content = layout;
|
||||||
|
|
||||||
switch(_providerType.Value)
|
switch(_providerType.Value)
|
||||||
@ -213,12 +214,13 @@ namespace Bit.App.Pages
|
|||||||
RememberCell
|
RememberCell
|
||||||
});
|
});
|
||||||
|
|
||||||
var layout = new StackLayout
|
var layout = new RedrawableStackLayout
|
||||||
{
|
{
|
||||||
Children = { webView, table, anotherMethodButton },
|
Children = { webView, table, anotherMethodButton },
|
||||||
Spacing = 0
|
Spacing = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
table.WrappingStackLayout = () => layout;
|
||||||
scrollView.Content = layout;
|
scrollView.Content = layout;
|
||||||
|
|
||||||
Title = "Duo";
|
Title = "Duo";
|
||||||
@ -244,12 +246,13 @@ namespace Bit.App.Pages
|
|||||||
RememberCell
|
RememberCell
|
||||||
});
|
});
|
||||||
|
|
||||||
var layout = new StackLayout
|
var layout = new RedrawableStackLayout
|
||||||
{
|
{
|
||||||
Children = { instruction, image, table, anotherMethodButton },
|
Children = { instruction, image, table, anotherMethodButton },
|
||||||
Spacing = 0
|
Spacing = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
table.WrappingStackLayout = () => layout;
|
||||||
scrollView.Content = layout;
|
scrollView.Content = layout;
|
||||||
|
|
||||||
Title = AppResources.YubiKeyTitle;
|
Title = AppResources.YubiKeyTitle;
|
||||||
@ -524,7 +527,7 @@ namespace Bit.App.Pages
|
|||||||
NoFooter = true;
|
NoFooter = true;
|
||||||
NoHeader = true;
|
NoHeader = true;
|
||||||
VerticalOptions = LayoutOptions.Start;
|
VerticalOptions = LayoutOptions.Start;
|
||||||
Root = Root = new TableRoot
|
Root = new TableRoot
|
||||||
{
|
{
|
||||||
section
|
section
|
||||||
};
|
};
|
||||||
|
@ -64,12 +64,13 @@ namespace Bit.App.Pages
|
|||||||
Margin = new Thickness(15, (this.IsLandscape() ? 5 : 0), 15, 25)
|
Margin = new Thickness(15, (this.IsLandscape() ? 5 : 0), 15, 25)
|
||||||
};
|
};
|
||||||
|
|
||||||
var layout = new StackLayout
|
var layout = new RedrawableStackLayout
|
||||||
{
|
{
|
||||||
Children = { table, hintLabel },
|
Children = { table, hintLabel },
|
||||||
Spacing = 0
|
Spacing = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
table.WrappingStackLayout = () => layout;
|
||||||
var scrollView = new ScrollView { Content = layout };
|
var scrollView = new ScrollView { Content = layout };
|
||||||
|
|
||||||
if(Device.RuntimePlatform == Device.iOS)
|
if(Device.RuntimePlatform == Device.iOS)
|
||||||
|
@ -35,7 +35,7 @@ namespace Bit.App.Pages
|
|||||||
public FormEntryCell PasswordCell { get; set; }
|
public FormEntryCell PasswordCell { get; set; }
|
||||||
public FormEntryCell ConfirmPasswordCell { get; set; }
|
public FormEntryCell ConfirmPasswordCell { get; set; }
|
||||||
public FormEntryCell PasswordHintCell { get; set; }
|
public FormEntryCell PasswordHintCell { get; set; }
|
||||||
public StackLayout StackLayout { get; set; }
|
public RedrawableStackLayout StackLayout { get; set; }
|
||||||
public Label PasswordLabel { get; set; }
|
public Label PasswordLabel { get; set; }
|
||||||
public Label HintLabel { get; set; }
|
public Label HintLabel { get; set; }
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
PasswordHintCell.Entry.ReturnType = Enums.ReturnType.Done;
|
PasswordHintCell.Entry.ReturnType = Enums.ReturnType.Done;
|
||||||
|
|
||||||
var table = new FormTableView
|
var table = new FormTableView(this)
|
||||||
{
|
{
|
||||||
Root = new TableRoot
|
Root = new TableRoot
|
||||||
{
|
{
|
||||||
@ -83,7 +83,7 @@ namespace Bit.App.Pages
|
|||||||
Margin = new Thickness(15, (this.IsLandscape() ? 5 : 0), 15, 25)
|
Margin = new Thickness(15, (this.IsLandscape() ? 5 : 0), 15, 25)
|
||||||
};
|
};
|
||||||
|
|
||||||
var table2 = new FormTableView
|
var table2 = new FormTableView(this)
|
||||||
{
|
{
|
||||||
NoHeader = true,
|
NoHeader = true,
|
||||||
Root = new TableRoot
|
Root = new TableRoot
|
||||||
@ -105,7 +105,7 @@ namespace Bit.App.Pages
|
|||||||
Margin = new Thickness(15, (this.IsLandscape() ? 5 : 0), 15, 25)
|
Margin = new Thickness(15, (this.IsLandscape() ? 5 : 0), 15, 25)
|
||||||
};
|
};
|
||||||
|
|
||||||
StackLayout = new StackLayout
|
StackLayout = new RedrawableStackLayout
|
||||||
{
|
{
|
||||||
Children = { table, PasswordLabel, table2, HintLabel },
|
Children = { table, PasswordLabel, table2, HintLabel },
|
||||||
Spacing = 0
|
Spacing = 0
|
||||||
@ -145,7 +145,6 @@ namespace Bit.App.Pages
|
|||||||
PasswordHintCell.InitEvents();
|
PasswordHintCell.InitEvents();
|
||||||
ConfirmPasswordCell.InitEvents();
|
ConfirmPasswordCell.InitEvents();
|
||||||
PasswordHintCell.Entry.Completed += Entry_Completed;
|
PasswordHintCell.Entry.Completed += Entry_Completed;
|
||||||
StackLayout.LayoutChanged += Layout_LayoutChanged;
|
|
||||||
EmailCell.Entry.FocusWithDelay();
|
EmailCell.Entry.FocusWithDelay();
|
||||||
}
|
}
|
||||||
protected override void OnDisappearing()
|
protected override void OnDisappearing()
|
||||||
@ -156,13 +155,6 @@ namespace Bit.App.Pages
|
|||||||
PasswordHintCell.Dispose();
|
PasswordHintCell.Dispose();
|
||||||
ConfirmPasswordCell.Dispose();
|
ConfirmPasswordCell.Dispose();
|
||||||
PasswordHintCell.Entry.Completed -= Entry_Completed;
|
PasswordHintCell.Entry.Completed -= Entry_Completed;
|
||||||
StackLayout.LayoutChanged -= Layout_LayoutChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Layout_LayoutChanged(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
PasswordLabel.WidthRequest = StackLayout.Bounds.Width - PasswordLabel.Bounds.Left * 2;
|
|
||||||
HintLabel.WidthRequest = StackLayout.Bounds.Width - HintLabel.Bounds.Left * 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void Entry_Completed(object sender, EventArgs e)
|
private async void Entry_Completed(object sender, EventArgs e)
|
||||||
@ -229,7 +221,7 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
private class FormTableView : ExtendedTableView
|
private class FormTableView : ExtendedTableView
|
||||||
{
|
{
|
||||||
public FormTableView()
|
public FormTableView(RegisterPage page)
|
||||||
{
|
{
|
||||||
Intent = TableIntent.Settings;
|
Intent = TableIntent.Settings;
|
||||||
EnableScrolling = false;
|
EnableScrolling = false;
|
||||||
@ -237,6 +229,7 @@ namespace Bit.App.Pages
|
|||||||
EnableSelection = true;
|
EnableSelection = true;
|
||||||
VerticalOptions = LayoutOptions.Start;
|
VerticalOptions = LayoutOptions.Start;
|
||||||
NoFooter = true;
|
NoFooter = true;
|
||||||
|
WrappingStackLayout = () => page.StackLayout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,12 +73,14 @@ namespace Bit.App.Pages
|
|||||||
table.EstimatedRowHeight = 44;
|
table.EstimatedRowHeight = 44;
|
||||||
}
|
}
|
||||||
|
|
||||||
var stackLayout = new StackLayout
|
var stackLayout = new RedrawableStackLayout
|
||||||
{
|
{
|
||||||
Children = { logoVersionStackLayout, table },
|
Children = { logoVersionStackLayout, table },
|
||||||
Spacing = 0
|
Spacing = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
table.WrappingStackLayout = () => stackLayout;
|
||||||
|
|
||||||
if(Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.UWP)
|
if(Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.UWP)
|
||||||
{
|
{
|
||||||
ToolbarItems.Add(new DismissModalToolBarItem(this, AppResources.Close));
|
ToolbarItems.Add(new DismissModalToolBarItem(this, AppResources.Close));
|
||||||
|
@ -50,9 +50,7 @@ namespace Bit.App.Pages
|
|||||||
var mainTable = new ExtendedTableView
|
var mainTable = new ExtendedTableView
|
||||||
{
|
{
|
||||||
Intent = TableIntent.Settings,
|
Intent = TableIntent.Settings,
|
||||||
EnableScrolling = false,
|
|
||||||
HasUnevenRows = true,
|
HasUnevenRows = true,
|
||||||
VerticalOptions = LayoutOptions.Start,
|
|
||||||
Root = new TableRoot
|
Root = new TableRoot
|
||||||
{
|
{
|
||||||
new TableSection(Helpers.GetEmptyTableSectionTitle())
|
new TableSection(Helpers.GetEmptyTableSectionTitle())
|
||||||
|
@ -22,7 +22,7 @@ namespace Bit.App.Pages
|
|||||||
public ExtendedTextCell EmailCell { get; set; }
|
public ExtendedTextCell EmailCell { get; set; }
|
||||||
public ExtendedTextCell WebsiteCell { get; set; }
|
public ExtendedTextCell WebsiteCell { get; set; }
|
||||||
public ExtendedTextCell BugCell { get; set; }
|
public ExtendedTextCell BugCell { get; set; }
|
||||||
public StackLayout StackLayout { get; set; }
|
public RedrawableStackLayout StackLayout { get; set; }
|
||||||
private CustomLabel EmailLabel { get; set; }
|
private CustomLabel EmailLabel { get; set; }
|
||||||
private CustomLabel WebsiteLabel { get; set; }
|
private CustomLabel WebsiteLabel { get; set; }
|
||||||
private CustomLabel BugLabel { get; set; }
|
private CustomLabel BugLabel { get; set; }
|
||||||
@ -35,7 +35,7 @@ namespace Bit.App.Pages
|
|||||||
ShowDisclousure = true
|
ShowDisclousure = true
|
||||||
};
|
};
|
||||||
|
|
||||||
var emailTable = new CustomTableView
|
var emailTable = new CustomTableView(this)
|
||||||
{
|
{
|
||||||
Root = new TableRoot
|
Root = new TableRoot
|
||||||
{
|
{
|
||||||
@ -57,7 +57,7 @@ namespace Bit.App.Pages
|
|||||||
ShowDisclousure = true
|
ShowDisclousure = true
|
||||||
};
|
};
|
||||||
|
|
||||||
var websiteTable = new CustomTableView
|
var websiteTable = new CustomTableView(this)
|
||||||
{
|
{
|
||||||
NoHeader = true,
|
NoHeader = true,
|
||||||
Root = new TableRoot
|
Root = new TableRoot
|
||||||
@ -80,7 +80,7 @@ namespace Bit.App.Pages
|
|||||||
ShowDisclousure = true
|
ShowDisclousure = true
|
||||||
};
|
};
|
||||||
|
|
||||||
var bugTable = new CustomTableView
|
var bugTable = new CustomTableView(this)
|
||||||
{
|
{
|
||||||
NoHeader = true,
|
NoHeader = true,
|
||||||
Root = new TableRoot
|
Root = new TableRoot
|
||||||
@ -97,7 +97,7 @@ namespace Bit.App.Pages
|
|||||||
Text = AppResources.FileBugReportDescription
|
Text = AppResources.FileBugReportDescription
|
||||||
};
|
};
|
||||||
|
|
||||||
StackLayout = new StackLayout
|
StackLayout = new RedrawableStackLayout
|
||||||
{
|
{
|
||||||
Children = { emailTable, EmailLabel, websiteTable, WebsiteLabel, bugTable, BugLabel },
|
Children = { emailTable, EmailLabel, websiteTable, WebsiteLabel, bugTable, BugLabel },
|
||||||
Spacing = 0
|
Spacing = 0
|
||||||
@ -118,7 +118,6 @@ namespace Bit.App.Pages
|
|||||||
EmailCell.Tapped += EmailCell_Tapped;
|
EmailCell.Tapped += EmailCell_Tapped;
|
||||||
WebsiteCell.Tapped += WebsiteCell_Tapped;
|
WebsiteCell.Tapped += WebsiteCell_Tapped;
|
||||||
BugCell.Tapped += BugCell_Tapped;
|
BugCell.Tapped += BugCell_Tapped;
|
||||||
StackLayout.LayoutChanged += StackLayout_LayoutChanged;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDisappearing()
|
protected override void OnDisappearing()
|
||||||
@ -127,14 +126,6 @@ namespace Bit.App.Pages
|
|||||||
EmailCell.Tapped -= EmailCell_Tapped;
|
EmailCell.Tapped -= EmailCell_Tapped;
|
||||||
WebsiteCell.Tapped -= WebsiteCell_Tapped;
|
WebsiteCell.Tapped -= WebsiteCell_Tapped;
|
||||||
BugCell.Tapped -= BugCell_Tapped;
|
BugCell.Tapped -= BugCell_Tapped;
|
||||||
StackLayout.LayoutChanged -= StackLayout_LayoutChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StackLayout_LayoutChanged(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
WebsiteLabel.WidthRequest = StackLayout.Bounds.Width - WebsiteLabel.Bounds.Left * 2;
|
|
||||||
EmailLabel.WidthRequest = StackLayout.Bounds.Width - EmailLabel.Bounds.Left * 2;
|
|
||||||
BugLabel.WidthRequest = StackLayout.Bounds.Width - BugLabel.Bounds.Left * 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EmailCell_Tapped(object sender, EventArgs e)
|
private void EmailCell_Tapped(object sender, EventArgs e)
|
||||||
@ -157,7 +148,7 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
private class CustomTableView : ExtendedTableView
|
private class CustomTableView : ExtendedTableView
|
||||||
{
|
{
|
||||||
public CustomTableView()
|
public CustomTableView(SettingsHelpPage page)
|
||||||
{
|
{
|
||||||
Intent = TableIntent.Settings;
|
Intent = TableIntent.Settings;
|
||||||
EnableScrolling = false;
|
EnableScrolling = false;
|
||||||
@ -165,6 +156,7 @@ namespace Bit.App.Pages
|
|||||||
EnableSelection = true;
|
EnableSelection = true;
|
||||||
VerticalOptions = LayoutOptions.Start;
|
VerticalOptions = LayoutOptions.Start;
|
||||||
NoFooter = true;
|
NoFooter = true;
|
||||||
|
WrappingStackLayout = () => page.StackLayout;
|
||||||
|
|
||||||
if(Device.RuntimePlatform == Device.iOS)
|
if(Device.RuntimePlatform == Device.iOS)
|
||||||
{
|
{
|
||||||
|
@ -24,7 +24,7 @@ namespace Bit.App.Pages
|
|||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
private StackLayout StackLayout { get; set; }
|
private RedrawableStackLayout StackLayout { get; set; }
|
||||||
private ExtendedSwitchCell CopyTotpCell { get; set; }
|
private ExtendedSwitchCell CopyTotpCell { get; set; }
|
||||||
private Label CopyTotpLabel { get; set; }
|
private Label CopyTotpLabel { get; set; }
|
||||||
private ExtendedSwitchCell AnalyticsCell { get; set; }
|
private ExtendedSwitchCell AnalyticsCell { get; set; }
|
||||||
@ -46,7 +46,7 @@ namespace Bit.App.Pages
|
|||||||
On = _appSettings.DisableWebsiteIcons
|
On = _appSettings.DisableWebsiteIcons
|
||||||
};
|
};
|
||||||
|
|
||||||
var websiteIconsTable = new FormTableView(true)
|
var websiteIconsTable = new FormTableView(this, true)
|
||||||
{
|
{
|
||||||
Root = new TableRoot
|
Root = new TableRoot
|
||||||
{
|
{
|
||||||
@ -63,7 +63,7 @@ namespace Bit.App.Pages
|
|||||||
On = _settings.GetValueOrDefault(Constants.SettingDisableTotpCopy, false)
|
On = _settings.GetValueOrDefault(Constants.SettingDisableTotpCopy, false)
|
||||||
};
|
};
|
||||||
|
|
||||||
var totpTable = new FormTableView
|
var totpTable = new FormTableView(this)
|
||||||
{
|
{
|
||||||
Root = new TableRoot
|
Root = new TableRoot
|
||||||
{
|
{
|
||||||
@ -80,7 +80,7 @@ namespace Bit.App.Pages
|
|||||||
On = _settings.GetValueOrDefault(Constants.SettingGaOptOut, false)
|
On = _settings.GetValueOrDefault(Constants.SettingGaOptOut, false)
|
||||||
};
|
};
|
||||||
|
|
||||||
var analyticsTable = new FormTableView
|
var analyticsTable = new FormTableView(this)
|
||||||
{
|
{
|
||||||
Root = new TableRoot
|
Root = new TableRoot
|
||||||
{
|
{
|
||||||
@ -106,7 +106,7 @@ namespace Bit.App.Pages
|
|||||||
Text = AppResources.DisableWebsiteIconsDescription
|
Text = AppResources.DisableWebsiteIconsDescription
|
||||||
};
|
};
|
||||||
|
|
||||||
StackLayout = new StackLayout
|
StackLayout = new RedrawableStackLayout
|
||||||
{
|
{
|
||||||
Children =
|
Children =
|
||||||
{
|
{
|
||||||
@ -125,7 +125,7 @@ namespace Bit.App.Pages
|
|||||||
On = !_appSettings.AutofillPersistNotification && !_appSettings.AutofillPasswordField
|
On = !_appSettings.AutofillPersistNotification && !_appSettings.AutofillPasswordField
|
||||||
};
|
};
|
||||||
|
|
||||||
var autofillAlwaysTable = new FormTableView(true)
|
var autofillAlwaysTable = new FormTableView(this, true)
|
||||||
{
|
{
|
||||||
Root = new TableRoot
|
Root = new TableRoot
|
||||||
{
|
{
|
||||||
@ -147,7 +147,7 @@ namespace Bit.App.Pages
|
|||||||
On = _appSettings.AutofillPersistNotification
|
On = _appSettings.AutofillPersistNotification
|
||||||
};
|
};
|
||||||
|
|
||||||
var autofillPersistNotificationTable = new FormTableView
|
var autofillPersistNotificationTable = new FormTableView(this)
|
||||||
{
|
{
|
||||||
Root = new TableRoot
|
Root = new TableRoot
|
||||||
{
|
{
|
||||||
@ -169,7 +169,7 @@ namespace Bit.App.Pages
|
|||||||
On = _appSettings.AutofillPasswordField
|
On = _appSettings.AutofillPasswordField
|
||||||
};
|
};
|
||||||
|
|
||||||
var autofillPasswordFieldTable = new FormTableView
|
var autofillPasswordFieldTable = new FormTableView(this)
|
||||||
{
|
{
|
||||||
Root = new TableRoot
|
Root = new TableRoot
|
||||||
{
|
{
|
||||||
@ -217,7 +217,6 @@ namespace Bit.App.Pages
|
|||||||
AnalyticsCell.OnChanged += AnalyticsCell_Changed;
|
AnalyticsCell.OnChanged += AnalyticsCell_Changed;
|
||||||
WebsiteIconsCell.OnChanged += WebsiteIconsCell_Changed;
|
WebsiteIconsCell.OnChanged += WebsiteIconsCell_Changed;
|
||||||
CopyTotpCell.OnChanged += CopyTotpCell_OnChanged;
|
CopyTotpCell.OnChanged += CopyTotpCell_OnChanged;
|
||||||
StackLayout.LayoutChanged += Layout_LayoutChanged;
|
|
||||||
|
|
||||||
if(Device.RuntimePlatform == Device.Android)
|
if(Device.RuntimePlatform == Device.Android)
|
||||||
{
|
{
|
||||||
@ -234,7 +233,6 @@ namespace Bit.App.Pages
|
|||||||
AnalyticsCell.OnChanged -= AnalyticsCell_Changed;
|
AnalyticsCell.OnChanged -= AnalyticsCell_Changed;
|
||||||
WebsiteIconsCell.OnChanged -= WebsiteIconsCell_Changed;
|
WebsiteIconsCell.OnChanged -= WebsiteIconsCell_Changed;
|
||||||
CopyTotpCell.OnChanged -= CopyTotpCell_OnChanged;
|
CopyTotpCell.OnChanged -= CopyTotpCell_OnChanged;
|
||||||
StackLayout.LayoutChanged -= Layout_LayoutChanged;
|
|
||||||
|
|
||||||
if(Device.RuntimePlatform == Device.Android)
|
if(Device.RuntimePlatform == Device.Android)
|
||||||
{
|
{
|
||||||
@ -244,29 +242,6 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Layout_LayoutChanged(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
AnalyticsLabel.WidthRequest = StackLayout.Bounds.Width - AnalyticsLabel.Bounds.Left * 2;
|
|
||||||
WebsiteIconsLabel.WidthRequest = StackLayout.Bounds.Width - WebsiteIconsLabel.Bounds.Left * 2;
|
|
||||||
CopyTotpLabel.WidthRequest = StackLayout.Bounds.Width - CopyTotpLabel.Bounds.Left * 2;
|
|
||||||
|
|
||||||
if(AutofillAlwaysLabel != null)
|
|
||||||
{
|
|
||||||
AutofillAlwaysLabel.WidthRequest = StackLayout.Bounds.Width - AutofillAlwaysLabel.Bounds.Left * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(AutofillPasswordFieldLabel != null)
|
|
||||||
{
|
|
||||||
AutofillPasswordFieldLabel.WidthRequest = StackLayout.Bounds.Width - AutofillPasswordFieldLabel.Bounds.Left * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(AutofillPersistNotificationLabel != null)
|
|
||||||
{
|
|
||||||
AutofillPersistNotificationLabel.WidthRequest =
|
|
||||||
StackLayout.Bounds.Width - AutofillPersistNotificationLabel.Bounds.Left * 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WebsiteIconsCell_Changed(object sender, ToggledEventArgs e)
|
private void WebsiteIconsCell_Changed(object sender, ToggledEventArgs e)
|
||||||
{
|
{
|
||||||
var cell = sender as ExtendedSwitchCell;
|
var cell = sender as ExtendedSwitchCell;
|
||||||
@ -352,7 +327,7 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
private class FormTableView : ExtendedTableView
|
private class FormTableView : ExtendedTableView
|
||||||
{
|
{
|
||||||
public FormTableView(bool header = false)
|
public FormTableView(SettingsOptionsPage page, bool header = false)
|
||||||
{
|
{
|
||||||
Intent = TableIntent.Settings;
|
Intent = TableIntent.Settings;
|
||||||
EnableScrolling = false;
|
EnableScrolling = false;
|
||||||
@ -361,6 +336,7 @@ namespace Bit.App.Pages
|
|||||||
VerticalOptions = LayoutOptions.Start;
|
VerticalOptions = LayoutOptions.Start;
|
||||||
NoFooter = true;
|
NoFooter = true;
|
||||||
NoHeader = !header;
|
NoHeader = !header;
|
||||||
|
WrappingStackLayout = () => page.StackLayout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ namespace Bit.App.Pages
|
|||||||
table.BottomPadding = 50;
|
table.BottomPadding = 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
var stackLayout = new StackLayout
|
var stackLayout = new RedrawableStackLayout
|
||||||
{
|
{
|
||||||
Orientation = StackOrientation.Vertical,
|
Orientation = StackOrientation.Vertical,
|
||||||
Children = { Password, table },
|
Children = { Password, table },
|
||||||
@ -171,6 +171,8 @@ namespace Bit.App.Pages
|
|||||||
Spacing = 0
|
Spacing = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
table.WrappingStackLayout = () => stackLayout;
|
||||||
|
|
||||||
var scrollView = new ScrollView
|
var scrollView = new ScrollView
|
||||||
{
|
{
|
||||||
Content = stackLayout,
|
Content = stackLayout,
|
||||||
|
@ -44,7 +44,7 @@ namespace Bit.App.Pages
|
|||||||
public ExtendedObservableCollection<VaultAttachmentsPageModel.Attachment> PresentationAttchments { get; private set; }
|
public ExtendedObservableCollection<VaultAttachmentsPageModel.Attachment> PresentationAttchments { get; private set; }
|
||||||
= new ExtendedObservableCollection<VaultAttachmentsPageModel.Attachment>();
|
= new ExtendedObservableCollection<VaultAttachmentsPageModel.Attachment>();
|
||||||
public ExtendedListView ListView { get; set; }
|
public ExtendedListView ListView { get; set; }
|
||||||
public StackLayout NoDataStackLayout { get; set; }
|
public RedrawableStackLayout NoDataStackLayout { get; set; }
|
||||||
public StackLayout AddNewStackLayout { get; set; }
|
public StackLayout AddNewStackLayout { get; set; }
|
||||||
public Label FileLabel { get; set; }
|
public Label FileLabel { get; set; }
|
||||||
public ExtendedTableView NewTable { get; set; }
|
public ExtendedTableView NewTable { get; set; }
|
||||||
@ -88,6 +88,7 @@ namespace Bit.App.Pages
|
|||||||
EnableSelection = false,
|
EnableSelection = false,
|
||||||
VerticalOptions = LayoutOptions.Start,
|
VerticalOptions = LayoutOptions.Start,
|
||||||
Margin = new Thickness(0, Helpers.OnPlatform(iOS: 10, Android: 30), 0, 0),
|
Margin = new Thickness(0, Helpers.OnPlatform(iOS: 10, Android: 30), 0, 0),
|
||||||
|
WrappingStackLayout = () => NoDataStackLayout,
|
||||||
Root = new TableRoot
|
Root = new TableRoot
|
||||||
{
|
{
|
||||||
new TableSection(AppResources.AddNewAttachment)
|
new TableSection(AppResources.AddNewAttachment)
|
||||||
@ -122,7 +123,7 @@ namespace Bit.App.Pages
|
|||||||
Style = (Style)Application.Current.Resources["text-muted"]
|
Style = (Style)Application.Current.Resources["text-muted"]
|
||||||
};
|
};
|
||||||
|
|
||||||
NoDataStackLayout = new StackLayout
|
NoDataStackLayout = new RedrawableStackLayout
|
||||||
{
|
{
|
||||||
VerticalOptions = LayoutOptions.Start,
|
VerticalOptions = LayoutOptions.Start,
|
||||||
Spacing = 0,
|
Spacing = 0,
|
||||||
|
@ -36,6 +36,7 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ToolbarItem SaveToolbarItem { get; set; }
|
public ToolbarItem SaveToolbarItem { get; set; }
|
||||||
|
public ToolbarItem CloseToolbarItem { get; set; }
|
||||||
public Label NoDataLabel { get; set; }
|
public Label NoDataLabel { get; set; }
|
||||||
public TableSection FieldsSection { get; set; }
|
public TableSection FieldsSection { get; set; }
|
||||||
public ExtendedTableView Table { get; set; }
|
public ExtendedTableView Table { get; set; }
|
||||||
@ -131,12 +132,16 @@ namespace Bit.App.Pages
|
|||||||
await DisplayAlert(null, AppResources.AnErrorHasOccurred, AppResources.Ok);
|
await DisplayAlert(null, AppResources.AnErrorHasOccurred, AppResources.Ok);
|
||||||
}
|
}
|
||||||
}, ToolbarItemOrder.Default, 0);
|
}, ToolbarItemOrder.Default, 0);
|
||||||
|
ToolbarItems.Add(SaveToolbarItem);
|
||||||
|
|
||||||
Title = AppResources.CustomFields;
|
Title = AppResources.CustomFields;
|
||||||
Content = Table;
|
Content = Table;
|
||||||
|
|
||||||
if(Device.RuntimePlatform == Device.iOS)
|
if(Device.RuntimePlatform == Device.iOS)
|
||||||
{
|
{
|
||||||
|
CloseToolbarItem = new DismissModalToolBarItem(this, AppResources.Close);
|
||||||
|
ToolbarItems.Add(CloseToolbarItem);
|
||||||
|
|
||||||
Table.RowHeight = -1;
|
Table.RowHeight = -1;
|
||||||
Table.EstimatedRowHeight = 44;
|
Table.EstimatedRowHeight = 44;
|
||||||
}
|
}
|
||||||
@ -157,13 +162,14 @@ namespace Bit.App.Pages
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_cipher.Fields != null && _cipher.Fields.Any())
|
var hasFields = _cipher.Fields?.Any() ?? false;
|
||||||
|
|
||||||
|
if(hasFields)
|
||||||
{
|
{
|
||||||
Content = Table;
|
Content = Table;
|
||||||
ToolbarItems.Add(SaveToolbarItem);
|
if(CloseToolbarItem != null)
|
||||||
if(Device.RuntimePlatform == Device.iOS)
|
|
||||||
{
|
{
|
||||||
ToolbarItems.Add(new DismissModalToolBarItem(this, AppResources.Cancel));
|
CloseToolbarItem.Text = AppResources.Cancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(var field in _cipher.Fields)
|
foreach(var field in _cipher.Fields)
|
||||||
@ -213,9 +219,9 @@ namespace Bit.App.Pages
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Content = NoDataLabel;
|
Content = NoDataLabel;
|
||||||
if(Device.RuntimePlatform == Device.iOS)
|
if(ToolbarItems.Count > 0)
|
||||||
{
|
{
|
||||||
ToolbarItems.Add(new DismissModalToolBarItem(this, AppResources.Close));
|
ToolbarItems.RemoveAt(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ namespace Bit.iOS.Controls
|
|||||||
private void SetSource()
|
private void SetSource()
|
||||||
{
|
{
|
||||||
var view = (ExtendedTableView)Element;
|
var view = (ExtendedTableView)Element;
|
||||||
if(view.NoFooter || view.NoHeader)
|
if(true || view.NoFooter || view.NoHeader)
|
||||||
{
|
{
|
||||||
Control.Source = new CustomTableViewModelRenderer(view);
|
Control.Source = new CustomTableViewModelRenderer(view);
|
||||||
}
|
}
|
||||||
@ -116,6 +116,7 @@ namespace Bit.iOS.Controls
|
|||||||
public class CustomTableViewModelRenderer : UnEvenTableViewModelRenderer
|
public class CustomTableViewModelRenderer : UnEvenTableViewModelRenderer
|
||||||
{
|
{
|
||||||
private readonly ExtendedTableView _view;
|
private readonly ExtendedTableView _view;
|
||||||
|
private bool _didRedraw = false;
|
||||||
|
|
||||||
public CustomTableViewModelRenderer(ExtendedTableView model)
|
public CustomTableViewModelRenderer(ExtendedTableView model)
|
||||||
: base(model)
|
: base(model)
|
||||||
@ -123,6 +124,16 @@ namespace Bit.iOS.Controls
|
|||||||
_view = model;
|
_view = model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override async void WillDisplay(UITableView tableView, UITableViewCell cell, NSIndexPath indexPath)
|
||||||
|
{
|
||||||
|
// ref https://stackoverflow.com/a/48076188/1090359
|
||||||
|
if(!_didRedraw && _view.WrappingStackLayout != null)
|
||||||
|
{
|
||||||
|
_didRedraw = true;
|
||||||
|
await _view.WrappingStackLayout()?.RedrawIfNeededAsync(10, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
|
public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
|
||||||
{
|
{
|
||||||
if(_view.HasUnevenRows)
|
if(_view.HasUnevenRows)
|
||||||
@ -143,6 +154,16 @@ namespace Bit.iOS.Controls
|
|||||||
return base.GetHeightForHeader(tableView, section);
|
return base.GetHeightForHeader(tableView, section);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override UIView GetViewForHeader(UITableView tableView, nint section)
|
||||||
|
{
|
||||||
|
if(_view.NoHeader && section == 0)
|
||||||
|
{
|
||||||
|
return new UIView(new CGRect(0, 0, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public override nfloat GetHeightForFooter(UITableView tableView, nint section)
|
public override nfloat GetHeightForFooter(UITableView tableView, nint section)
|
||||||
{
|
{
|
||||||
if(_view.NoFooter && (section + 1) == NumberOfSections(tableView))
|
if(_view.NoFooter && (section + 1) == NumberOfSections(tableView))
|
||||||
@ -152,6 +173,16 @@ namespace Bit.iOS.Controls
|
|||||||
|
|
||||||
return 10f;
|
return 10f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override UIView GetViewForFooter(UITableView tableView, nint section)
|
||||||
|
{
|
||||||
|
if(_view.NoFooter && (section + 1) == NumberOfSections(tableView))
|
||||||
|
{
|
||||||
|
return new UIView(new CGRect(0, 0, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user