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:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
45
src/iOS.Core/Renderers/ExtendedStepperRenderer.cs
Normal file
45
src/iOS.Core/Renderers/ExtendedStepperRenderer.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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" />
|
||||
|
||||
Reference in New Issue
Block a user