-
Notifications
You must be signed in to change notification settings - Fork 442
Fix #1493: Themes / Dark Mode Support #1324
Conversation
2f80463
to
1aa1f3e
Compare
A few smaller views had elements styled.
@@ -243,13 +243,6 @@ class TabManager: NSObject { | |||
} | |||
if let tab = selectedTab { | |||
TabEvent.post(.didGainFocus, for: tab) | |||
|
|||
switch tab.type { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved this to AppearanceExtensions.swift
let shareButton = ToolbarButton() | ||
let addTabButton = ToolbarButton() | ||
let menuButton = ToolbarButton() | ||
let tabsButton = TabsButton(top: false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit annoying, but needed some way to differentiate when TabsButton
or ToolbarButton
required certain tint elements.
This is largely caused by these buttons handling their own internal theming, which is not great.
Filed a follow up ticket for this: #1494
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At first I thought it was initial work to support fully custom toolbars, and its placement
case .add: return #imageLiteral(resourceName: "menu-add-bookmark") | ||
case .share: return #imageLiteral(resourceName: "nav-share") | ||
case .downloads: return #imageLiteral(resourceName: "menu-downloads") | ||
case .bookmarks: return #imageLiteral(resourceName: "menu_bookmarks").template |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.template
is required to properly style these buttons via tintColor
or similar.
} | ||
|
||
private var theme: Theme { | ||
Theme.of(tabManager.selectedTab) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit annoying, but necessary since theme can dynamically change while settings is up, either by theme change or by toggling Private Browsing Only.
@@ -167,6 +170,24 @@ class SettingsViewController: TableViewController { | |||
general.rows.append(row) | |||
} | |||
|
|||
let themeSubtitle = Theme.DefaultTheme(rawValue: Preferences.General.themeNormalMode.value)?.displayString |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding the theme
option to settings. Currently only manipulates the normal
theme option.
onValueChange: { | ||
Preferences.Privacy.privateBrowsingOnly.value = $0 | ||
|
||
// Need to flush the table, hacky, but works consistenly and well |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When switching into PrivateBrowsingOnly
, the settings UI needs to be updated, this is where that happens.
@@ -1,57 +0,0 @@ | |||
/* This Source Code Form is subject to the terms of the Mozilla Public |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was all moved to child folder Theme
: https://github.com/brave/brave-ios/pull/1324/files#diff-341a31b4ae4d39e8a2ab9390b46afd7e
} | ||
} | ||
|
||
fileprivate enum ThemeCodingKeys: String, CodingKey { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For JSON mappings.
@@ -0,0 +1,336 @@ | |||
/* This Source Code Form is subject to the terms of the Mozilla Public |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Big class. Takes and decodes the JSON files, and utilizes these for theming. Currently a lot of the heavy lifting is done via: DefaultTheme
, this was mostly done for time, but there are some complexities involved with fully dynamic themes (e.g. localizations), that still need to be figured out.
So should be a thorough enough solution for any "hardcoded" / hard-included themes we ship in the binary.
let theme = Theme.of(tab) | ||
applyTheme(theme) | ||
let newTheme = Theme.of(tab) | ||
if previous == nil || newTheme != Theme.of(previous) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Switched from using tab.type
to using theme change detection. Also, will "force" update the theme if the previous tab didn't exist.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks good overall, few small changes and questions.
I also have two big-picture concerns:
My first feeling was that there is not enough UX constants in the json file to support all views.
This leads to:
- Let’s say I create a new view, how do I know what value to use for my views?
Look at this picture for example
One view uses some magic value header
, the other one home
while both views have tint color taken from header
.
These values don't make much sense, we would need to use trail and error to figure out correct values, or our design team has to tell us to use header, home
instead of hard color values.
If we start supporting custom themes this can also lead to unexpected colors. If the header
color looks good in view X, it might not look good in view Y, and we won't know that unless we test for all themes including the custom ones
EDIT: This point will apply later after we start adding custom themes with the new tab experience etc.
2. I feel like we should have separate values for new tab page UI, and for general components. I supposed some people/publishers might want to have a cool new tab experience with pink colors and other bling bling, but for regular browsing you don't necessarily want to have that pink tint everywhere.
This would also help with my concern from point number 1
These 2 points are not blockers by any means, it's just what came up to my mind while reviewing the code
|
||
// MARK: - Themes | ||
|
||
public static let ThemesDisplayBrightness = NSLocalizedString("ThemesDisplayBrightness", tableName: "BraveShared", bundle: Bundle.braveShared, value: "Display & Brightness", comment: "Setting to choose the user interface theme for normal browsing mode, contains choices like 'light' or 'dark' themes") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I remember Sriram talking about changing this setting title, have we decided on it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't heard anything, we're going with this for now, can adjust in future 🤷♂
UINavigationBar.appearance().tintColor = colors.accent | ||
UINavigationBar.appearance().appearanceBarTintColor = colors.header | ||
|
||
// UISwitch.appearance().tintColor = colors.accent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove
@@ -47,12 +47,12 @@ class OnboardingNavigationController: UINavigationController { | |||
case shieldsInfo | |||
|
|||
/// Returns new ViewController associated with the screen type | |||
func viewController(with profile: Profile) -> OnboardingViewController { | |||
func viewController(with profile: Profile, theme: Theme) -> OnboardingViewController { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we passing Theme
here because selectedTab
is not available yet?
Could we use theme.of nil so it infers the theme based on preferences/privacy mode
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, mostly just no reason for on-boarding to get a tab, just giving it the minimal of what it needs. At some point it may not even need that.
We may be refactoring on-boarding to be light/dark vs being created from a theme file.
// In order to properly apply background and align this with the rest of the UI (keyboard / header) | ||
// this needs to be called. UI could be handled internally to view systems, | ||
// but then keyboard may misalign with Brave selected theme override | ||
Theme.of(nil).applyAppearanceProperties() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like we could have another Theme method for getting theme by preference/privacy mode, Theme.of(nil)
isn't readable, you need to dig into the method to see what is gonna happen
something like Theme.default
or Theme.byPrivacyMode
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main thing is ideally this is quite rare. I ma primary hesitant to use a .default
or .mode
since it should be so rarely used I don't want to make it super convenient. Otherwise, it may just be used naively.
@@ -89,7 +89,9 @@ class ReaderModeBarView: UIView { | |||
extension ReaderModeBarView: Themeable { | |||
|
|||
func applyTheme(_ theme: Theme) { | |||
backgroundColor = UIColor.Browser.Background.colorFor(theme) | |||
buttonTintColor = UIColor.Browser.Tint.colorFor(theme) | |||
styleChildren(theme: theme) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note to myself: there are no themable children in this view. I think it's still a good practice to always call styleChildren
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a comment to the protocol with this info, although not technically enforceable. Similar to calling super
on overridden methods I suppose.
tabDataSource.tabs = tabManager.tabsForCurrentMode | ||
applyTheme(privateMode ? .private : .regular) | ||
/* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Convert to ///
comment lines. Emojis can stay 🤣
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved to using //
as ///
is generally used for method / class documentation. but got rid of the /* */
thing 😄
let shareButton = ToolbarButton() | ||
let addTabButton = ToolbarButton() | ||
let menuButton = ToolbarButton() | ||
let tabsButton = TabsButton(top: false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At first I thought it was initial work to support fully custom toolbars, and its placement
@@ -144,6 +144,7 @@ class ShieldsViewController: UIViewController, PopoverContentComponent { | |||
|
|||
override func loadView() { | |||
view = View() | |||
shieldsView.set(theme: Theme.of(tab)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can't use applyTheme/styleChildren
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can, fixed.
case `private` = "C5CB0D9A-5467-432C-AB35-1A78C55CFB41" | ||
|
||
// TODO: Theme: Remove with `rawValue` | ||
var id: String { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be replaced with rawValue
as the comment says
It was a hard balance to identify some theme file that would work relatively well with fewer items. One approach that we may take in the future is defining not specific colors but genre's of colors, like Something that would require some more serious thought and be planned out in conjunction with Design. The current system basically requires us to audit themes pretty closely
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved. It must have been a lot of effort to make the app look good for all 3 themes, good job on that :)
I ran some tests on my devices and haven't noticed any bad UI, we should be good to go
Summary of Changes
This pull request fixes issue #1493
This ticket impacts a good bit, so tried to include a good bit of code comments, as well as PR comments too.
Make sure to squash this!! Lots of commits 😄
Submitter Checklist:
NSLocalizableString()
Test Plan:
Screenshots:
Reviewer Checklist:
QA/(Yes|No)
release-notes/(include|exclude)
bug
/enhancement