1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-25 12:43:39 +00:00

Dynamic theme switching and visual tweaks (#1556)

* Dynamic theme switching and visual tweaks

* update action runner to use macos-11 for iOS 15 support

* additional tweaks

* refinements

* refinements

* formatting and tweaks
This commit is contained in:
Matt Portune
2021-10-08 08:47:40 -04:00
committed by GitHub
parent 73eb3c2c1e
commit 4aad34cd75
69 changed files with 4193 additions and 5433 deletions

View File

@@ -1,17 +1,68 @@
using Bit.iOS.Core.Renderers;
using Bit.App.Abstractions;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
using Bit.iOS.Core.Renderers;
using Bit.iOS.Core.Utilities;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(TabbedPage), typeof(CustomTabbedRenderer))]
namespace Bit.iOS.Core.Renderers
{
public class CustomTabbedRenderer : TabbedRenderer
{
private IBroadcasterService _broadcasterService;
public CustomTabbedRenderer()
{
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
_broadcasterService.Subscribe(nameof(CustomTabbedRenderer), async (message) =>
{
if (message.Command == "updatedTheme")
{
Device.BeginInvokeOnMainThread(() =>
{
iOSCoreHelpers.AppearanceAdjustments();
UpdateTabBarAppearance();
});
}
});
}
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
TabBar.Translucent = false;
TabBar.Opaque = true;
UpdateTabBarAppearance();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_broadcasterService.Unsubscribe(nameof(CustomTabbedRenderer));
}
base.Dispose(disposing);
}
private void UpdateTabBarAppearance()
{
// https://developer.apple.com/forums/thread/682420
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
if (deviceActionService.SystemMajorVersion() >= 15)
{
var appearance = new UITabBarAppearance();
appearance.ConfigureWithOpaqueBackground();
appearance.BackgroundColor = ThemeHelpers.TabBarBackgroundColor;
appearance.StackedLayoutAppearance.Normal.IconColor = ThemeHelpers.TabBarItemColor;
appearance.StackedLayoutAppearance.Normal.TitleTextAttributes =
new UIStringAttributes { ForegroundColor = ThemeHelpers.TabBarItemColor };
TabBar.StandardAppearance = appearance;
TabBar.ScrollEdgeAppearance = TabBar.StandardAppearance;
}
}
}
}

View File

@@ -0,0 +1,45 @@
using System.ComponentModel;
using Bit.App.Controls;
using Bit.iOS.Core.Renderers;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(ExtendedStepper), typeof(ExtendedStepperRenderer))]
namespace Bit.iOS.Core.Renderers
{
public class ExtendedStepperRenderer : StepperRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
{
base.OnElementChanged(e);
UpdateFgColor();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == ExtendedStepper.StepperForegroundColorProperty.PropertyName)
{
UpdateFgColor();
}
else
{
base.OnElementPropertyChanged(sender, e);
}
}
private void UpdateFgColor()
{
if (Control != null && Element is ExtendedStepper view)
{
if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
{
// https://developer.apple.com/forums/thread/121495
Control.SetIncrementImage(Control.GetIncrementImage(UIControlState.Normal), UIControlState.Normal);
Control.SetDecrementImage(Control.GetDecrementImage(UIControlState.Normal), UIControlState.Normal);
}
Control.TintColor = view.StepperForegroundColor.ToUIColor();
}
}
}
}

View File

@@ -422,19 +422,6 @@ namespace Bit.iOS.Core.Services
throw new NotImplementedException();
}
public bool UsingDarkTheme()
{
try
{
if (SystemMajorVersion() > 12)
{
return UIScreen.MainScreen.TraitCollection.UserInterfaceStyle == UIUserInterfaceStyle.Dark;
}
}
catch { }
return false;
}
public long GetActiveTime()
{
// Fall back to UnixTimeMilliseconds in case this approach stops working. We'll lose clock-change

View File

@@ -1,4 +1,5 @@
using UIKit;
using Bit.App.Utilities;
using UIKit;
using Xamarin.Forms.Platform.iOS;
namespace Bit.iOS.Core.Utilities
@@ -6,24 +7,63 @@ namespace Bit.iOS.Core.Utilities
public static class ThemeHelpers
{
public static bool LightTheme = true;
public static bool UsingOsDarkTheme = false;
public static UIColor SplashBackgroundColor = Xamarin.Forms.Color.FromHex("#efeff4").ToUIColor();
public static UIColor BackgroundColor = Xamarin.Forms.Color.FromHex("#ffffff").ToUIColor();
public static UIColor MutedColor = Xamarin.Forms.Color.FromHex("#777777").ToUIColor();
public static UIColor SuccessColor = Xamarin.Forms.Color.FromHex("#00a65a").ToUIColor();
public static UIColor DangerColor = Xamarin.Forms.Color.FromHex("dd4b39").ToUIColor();
public static UIColor PrimaryColor = Xamarin.Forms.Color.FromHex("#175DDC").ToUIColor();
public static UIColor TextColor = Xamarin.Forms.Color.FromHex("#000000").ToUIColor();
public static UIColor PlaceholderColor = Xamarin.Forms.Color.FromHex("#d0d0d0").ToUIColor();
public static UIColor SeparatorColor = Xamarin.Forms.Color.FromHex("#dddddd").ToUIColor();
public static UIColor ListHeaderBackgroundColor = Xamarin.Forms.Color.FromHex("#efeff4").ToUIColor();
public static UIColor NavBarBackgroundColor = Xamarin.Forms.Color.FromHex("#175DDC").ToUIColor();
public static UIColor NavBarTextColor = Xamarin.Forms.Color.FromHex("#ffffff").ToUIColor();
public static void SetAppearance(string theme, bool usingOsDarkTheme)
public static UIColor SplashBackgroundColor
{
UsingOsDarkTheme = usingOsDarkTheme;
SetThemeVariables(theme);
get => ThemeManager.GetResourceColor("SplashBackgroundColor").ToUIColor();
}
public static UIColor BackgroundColor
{
get => ThemeManager.GetResourceColor("BackgroundColor").ToUIColor();
}
public static UIColor MutedColor
{
get => ThemeManager.GetResourceColor("MutedColor").ToUIColor();
}
public static UIColor SuccessColor
{
get => ThemeManager.GetResourceColor("SuccessColor").ToUIColor();
}
public static UIColor DangerColor
{
get => ThemeManager.GetResourceColor("DangerColor").ToUIColor();
}
public static UIColor PrimaryColor
{
get => ThemeManager.GetResourceColor("PrimaryColor").ToUIColor();
}
public static UIColor TextColor
{
get => ThemeManager.GetResourceColor("TextColor").ToUIColor();
}
public static UIColor SeparatorColor
{
get => ThemeManager.GetResourceColor("SeparatorColor").ToUIColor();
}
public static UIColor ListHeaderBackgroundColor
{
get => ThemeManager.GetResourceColor("ListHeaderBackgroundColor").ToUIColor();
}
public static UIColor NavBarBackgroundColor
{
get => ThemeManager.GetResourceColor("NavigationBarBackgroundColor").ToUIColor();
}
public static UIColor NavBarTextColor
{
get => ThemeManager.GetResourceColor("NavigationBarTextColor").ToUIColor();
}
public static UIColor TabBarBackgroundColor
{
get => ThemeManager.GetResourceColor("TabBarBackgroundColor").ToUIColor();
}
public static UIColor TabBarItemColor
{
get => ThemeManager.GetResourceColor("TabBarItemColor").ToUIColor();
}
public static void SetAppearance(string theme, bool osDarkModeEnabled)
{
SetThemeVariables(theme, osDarkModeEnabled);
UINavigationBar.Appearance.ShadowImage = new UIImage();
UINavigationBar.Appearance.SetBackgroundImage(new UIImage(), UIBarMetrics.Default);
UIStepper.Appearance.TintColor = MutedColor;
@@ -33,91 +73,22 @@ namespace Bit.iOS.Core.Utilities
}
}
public static void SetExtensionAppearance(string theme, bool usingOsDarkTheme)
{
SetAppearance(theme, usingOsDarkTheme);
UIView.Appearance.BackgroundColor = BackgroundColor;
UILabel.Appearance.TextColor = TextColor;
UITextField.Appearance.TintColor = TextColor;
UITextView.Appearance.TintColor = TextColor;
UITextField.Appearance.BackgroundColor = BackgroundColor;
UITextView.Appearance.BackgroundColor = BackgroundColor;
UITableView.Appearance.BackgroundColor = BackgroundColor;
UITableView.Appearance.SeparatorColor = SeparatorColor;
UINavigationBar.Appearance.BackgroundColor = NavBarBackgroundColor;
UINavigationBar.Appearance.BarTintColor = NavBarBackgroundColor;
UINavigationBar.Appearance.TintColor = NavBarTextColor;
UINavigationBar.Appearance.Translucent = false;
UINavigationBar.Appearance.SetTitleTextAttributes(new UITextAttributes()
{
TextColor = NavBarTextColor
});
UIBarButtonItem.Appearance.TintColor = NavBarTextColor;
UIButton.Appearance.TintColor = TextColor;
UILabel.AppearanceWhenContainedIn(typeof(UITableViewHeaderFooterView)).TextColor = MutedColor;
}
public static UIFont GetDangerFont()
{
return Xamarin.Forms.Font.SystemFontOfSize(Xamarin.Forms.NamedSize.Small,
Xamarin.Forms.FontAttributes.Bold).ToUIFont();
}
private static void SetThemeVariables(string theme)
private static void SetThemeVariables(string theme, bool osDarkModeEnabled)
{
LightTheme = false;
if (string.IsNullOrWhiteSpace(theme) && UsingOsDarkTheme)
if (string.IsNullOrWhiteSpace(theme) && osDarkModeEnabled)
{
theme = "dark";
}
if (theme == "dark")
if (theme == "dark" || theme == "black" || theme == "nord")
{
var whiteColor = Xamarin.Forms.Color.FromHex("#ffffff").ToUIColor();
MutedColor = Xamarin.Forms.Color.FromHex("#a3a3a3").ToUIColor();
SuccessColor = Xamarin.Forms.Color.FromHex("#00a65a").ToUIColor();
DangerColor = Xamarin.Forms.Color.FromHex("ff3e24").ToUIColor();
BackgroundColor = Xamarin.Forms.Color.FromHex("#303030").ToUIColor();
SplashBackgroundColor = Xamarin.Forms.Color.FromHex("#222222").ToUIColor();
PrimaryColor = Xamarin.Forms.Color.FromHex("#52bdfb").ToUIColor();
TextColor = whiteColor;
PlaceholderColor = Xamarin.Forms.Color.FromHex("#707070").ToUIColor();
SeparatorColor = Xamarin.Forms.Color.FromHex("#191919").ToUIColor();
ListHeaderBackgroundColor = Xamarin.Forms.Color.FromHex("#222222").ToUIColor();
NavBarBackgroundColor = Xamarin.Forms.Color.FromHex("#212121").ToUIColor();
NavBarTextColor = whiteColor;
}
else if (theme == "black")
{
var blackColor = Xamarin.Forms.Color.FromHex("#000000").ToUIColor();
var whiteColor = Xamarin.Forms.Color.FromHex("#ffffff").ToUIColor();
MutedColor = Xamarin.Forms.Color.FromHex("#a3a3a3").ToUIColor();
SuccessColor = Xamarin.Forms.Color.FromHex("#00a65a").ToUIColor();
DangerColor = Xamarin.Forms.Color.FromHex("ff3e24").ToUIColor();
BackgroundColor = blackColor;
SplashBackgroundColor = blackColor;
PrimaryColor = Xamarin.Forms.Color.FromHex("#52bdfb").ToUIColor();
TextColor = whiteColor;
PlaceholderColor = Xamarin.Forms.Color.FromHex("#707070").ToUIColor();
SeparatorColor = Xamarin.Forms.Color.FromHex("#282828").ToUIColor();
ListHeaderBackgroundColor = blackColor;
NavBarBackgroundColor = blackColor;
NavBarTextColor = whiteColor;
}
else if (theme == "nord")
{
MutedColor = Xamarin.Forms.Color.FromHex("#d8dee9").ToUIColor();
SuccessColor = Xamarin.Forms.Color.FromHex("#a3be8c").ToUIColor();
DangerColor = Xamarin.Forms.Color.FromHex("bf616a").ToUIColor();
BackgroundColor = Xamarin.Forms.Color.FromHex("#3b4252").ToUIColor();
SplashBackgroundColor = Xamarin.Forms.Color.FromHex("#2e3440").ToUIColor();
PrimaryColor = Xamarin.Forms.Color.FromHex("#81a1c1").ToUIColor();
TextColor = Xamarin.Forms.Color.FromHex("#e5e9f0").ToUIColor();
PlaceholderColor = Xamarin.Forms.Color.FromHex("#7b88a1").ToUIColor();
SeparatorColor = Xamarin.Forms.Color.FromHex("#2e3440").ToUIColor();
ListHeaderBackgroundColor = Xamarin.Forms.Color.FromHex("#2e3440").ToUIColor();
NavBarBackgroundColor = Xamarin.Forms.Color.FromHex("#2e3440").ToUIColor();
NavBarTextColor = Xamarin.Forms.Color.FromHex("#e5e9f0").ToUIColor();
LightTheme = false;
}
else
{

View File

@@ -84,9 +84,9 @@ namespace Bit.iOS.Core.Utilities
var bootstrapTask = BootstrapAsync(postBootstrapFunc);
}
public static void AppearanceAdjustments(IDeviceActionService deviceActionService)
public static void AppearanceAdjustments()
{
ThemeHelpers.SetAppearance(ThemeManager.GetTheme(false), deviceActionService.UsingDarkTheme());
ThemeHelpers.SetAppearance(ThemeManager.GetTheme(false), ThemeManager.OsDarkModeEnabled());
UIApplication.SharedApplication.StatusBarHidden = false;
UIApplication.SharedApplication.StatusBarStyle = UIStatusBarStyle.LightContent;
}

View File

@@ -162,6 +162,7 @@
<Compile Include="Renderers\CustomPickerRenderer.cs" />
<Compile Include="Renderers\CustomSearchBarRenderer.cs" />
<Compile Include="Renderers\CustomTabbedRenderer.cs" />
<Compile Include="Renderers\ExtendedStepperRenderer.cs" />
<Compile Include="Renderers\ExtendedTimePickerRenderer.cs" />
<Compile Include="Renderers\CustomViewCellRenderer.cs" />
<Compile Include="Renderers\HybridWebViewRenderer.cs" />