Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VPN-6681: Dark mode images and animations (part 1) #10170

Merged
merged 18 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .dictionary
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Mio
MozillaVPN
Mozillians
Mullvad
NavigationBarButton
NDK
NEPacketTunnelProvider
NONINFRINGEMENT
Expand Down Expand Up @@ -250,6 +251,7 @@ sécuriser
sécurisé
taskcluster
th
theming
tmp
toggleable
tooltip
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/linters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ jobs:
run: |
scripts/ci/check_colors.py nebula/ui/themes/

- name: Check for proper image usage
run: |
scripts/ci/check_images.py

ktlint:
name: Run ktLint
runs-on: ubuntu-latest
Expand Down
21 changes: 21 additions & 0 deletions docs/Components/assets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Assets used in app

To support theming, there are two different versions of all assets (images and animations). There is one for darker themes, and another for lighter themes.

Within each theme's `theme.js` file, there is a line that controls which set of assets should be used: `color.useDarkAssets = false;` (or `= true`, depending on what is most appropriate). And in the QML code, instead of explicitly setting image assets, code is run to utilize the appropriate asset: `MZAssetLookup.getImageSource("ButtonLoader")`.

**The only assets that do not have both dark and light versions are country flags.** The flag assets referenced in `ServerLabel.qml`, `ServerCountry.qml`, and `SystemTrayNotificationHandler.cpp` are expected to explicitly use assets.

**`MozillaVPN::registerNavigationBarButtons' sets up the SVGs for the bar button items. For reasons lost to time, this is done in C++, not QML.** The C++ `NavigationBarButton` class takes assets for both light and dark modes, and chooses the proper one when the theme changes.

### Adding a new asset
1. Add the asset to the repository.
2. Add the asset in `nebula/ui/resources/CMakeLists.txt` or `src/ui/resources.qrc`, depending on which folder the asset was placed in.
3. Add the asset to the `imageLookup` dictionary within `MZAssetLookup.js`.
4. Use the asset in code (`MZAssetLookup.getImageSource("YourNewName")`).

### Checks and tests
`check_images.py` is run on each PR. It checks 3 things:
1. All image and animation names used in `MZAssetLookup` are unique (there are no duplicates).
2. No QML file uses an explicit image (instead of the proper `MZAssetLookup.getImageSource`), except the expected flags.
3. The image names called in all `MZAssetLookup.getImageSource` actually exist in the `imageLookup` within `MZAssetLookup`.
3 changes: 2 additions & 1 deletion nebula/ui/compat/qt6/MZAnimatedRingsShader.qml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import QtQuick 2.0
import "qrc:/nebula/utils/MZAssetLookup.js" as MZAssetLookup

ShaderEffect {
property string shaderSrc: "qrc:/nebula/resources/shaders/baked/animatedRings.frag.qsb"
property string shaderSrc: MZAssetLookup.getAnimationSource("RingsShader")

fragmentShader: shaderSrc
}
5 changes: 3 additions & 2 deletions nebula/ui/components/MZAlert.qml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import QtQuick.Layouts 1.14

import Mozilla.Shared 1.0
import compat 0.1
import "qrc:/nebula/utils/MZAssetLookup.js" as MZAssetLookup

Rectangle {
id: alertBox
Expand Down Expand Up @@ -51,8 +52,8 @@ Rectangle {
// Private Properties, will be changed depnding on alertType
QtObject {
id: style
readonly property string darkCloseIcon: "qrc:/nebula/resources/close-dark.svg"
readonly property string whiteCloseIcon: "qrc:/nebula/resources/close-white.svg"
readonly property string darkCloseIcon: MZAssetLookup.getImageSource("CloseDark")
readonly property string whiteCloseIcon: MZAssetLookup.getImageSource("CloseWhite")
property var alertColor: MZTheme.colors.normalLevelAccent
property var alertHoverColor: MZTheme.colors.normalButton.buttonHovered
property var alertClickColor: MZTheme.colors.normalButton.buttonPressed
Expand Down
3 changes: 2 additions & 1 deletion nebula/ui/components/MZAvatar.qml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import QtQuick 2.0

import compat 0.1
import "qrc:/nebula/utils/MZAssetLookup.js" as MZAssetLookup

Item {
id: logoRoot
Expand All @@ -31,7 +32,7 @@ Item {
anchors.fill: parent
fillMode: Image.PreserveAspectFit
smooth: true
source: "qrc:/nebula/resources/avatar-default.png"
source: MZAssetLookup.getImageSource("AvatarProfile")
sourceSize.height: avatarSourceSize
sourceSize.width: avatarSourceSize
visible: avatar.status !== Image.Ready
Expand Down
3 changes: 2 additions & 1 deletion nebula/ui/components/MZButtonLoader.qml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
import QtQuick 2.5

import Mozilla.Shared 1.0
import "qrc:/nebula/utils/MZAssetLookup.js" as MZAssetLookup

Rectangle {
property string iconUrl: "qrc:/nebula/resources/buttonLoader.svg"
property string iconUrl: MZAssetLookup.getImageSource("ButtonLoader")

id: loader
anchors.fill: parent
Expand Down
3 changes: 2 additions & 1 deletion nebula/ui/components/MZCheckBox.qml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import QtQuick.Layouts 1.14

import Mozilla.Shared 1.0
import "qrc:/nebula/utils/MZUiUtils.js" as MZUiUtils
import "qrc:/nebula/utils/MZAssetLookup.js" as MZAssetLookup

CheckBox {
property var uiState: MZTheme.theme.uiState
Expand Down Expand Up @@ -81,7 +82,7 @@ CheckBox {

MZIcon {
id: checkmarkIcon
source: "qrc:/nebula/resources/checkmark-blue50.svg"
source: MZAssetLookup.getImageSource("CheckmarkNormalColor")
sourceSize.width: MZTheme.theme.checkmarkHeightWidth
sourceSize.height: MZTheme.theme.checkmarkHeightWidth
anchors.centerIn: parent
Expand Down
3 changes: 2 additions & 1 deletion nebula/ui/components/MZChevron.qml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
import QtQuick 2.5

import Mozilla.Shared 1.0
import "qrc:/nebula/utils/MZAssetLookup.js" as MZAssetLookup

// MZChevron
Image {
source: "qrc:/nebula/resources/chevron.svg"
source: MZAssetLookup.getImageSource("Chevron")
mirror: MZLocalizer.isRightToLeft
sourceSize.height: 24
sourceSize.width: 24
Expand Down
3 changes: 2 additions & 1 deletion nebula/ui/components/MZExternalLinkListItem.qml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import QtQuick 2.5
import QtQuick.Layouts 1.14

import Mozilla.Shared 1.0
import "qrc:/nebula/utils/MZAssetLookup.js" as MZAssetLookup

// MZExternalLinkListItem
MZClickableRow {
property alias title: title.text
property string iconSource: "qrc:/nebula/resources/externalLink.svg"
property string iconSource: MZAssetLookup.getImageSource("ExternalLink")
property alias iconMirror: icon.mirror

backgroundColor: MZTheme.colors.clickableRow
Expand Down
5 changes: 3 additions & 2 deletions nebula/ui/components/MZHelpSheet.qml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import QtQuick.Layouts 1.14

import components 0.1
import Mozilla.Shared 1.0
import "qrc:/nebula/utils/MZAssetLookup.js" as MZAssetLookup

//SUMMARY: MZHelpSheet is a component derived from MZBottomSheet that opens a drawer from the bottom of the screen who's content
//is always laid out in a consistnet way by passing in a model with the correct schema, and sizes to fit the content it contains
Expand Down Expand Up @@ -85,7 +86,7 @@ MZBottomSheet {
Image {
anchors.centerIn: parent

source: "qrc:/nebula/resources/tip-filled.svg"
source: MZAssetLookup.getImageSource("LightbulbFilled")
sourceSize.width: MZTheme.theme.iconSize * 1.5

mirror: MZLocalizer.isRightToLeft
Expand Down Expand Up @@ -131,7 +132,7 @@ MZBottomSheet {
sourceSize.height: MZTheme.theme.iconSize
sourceSize.width: MZTheme.theme.iconSize

source: "qrc:/nebula/resources/close-dark.svg"
source: MZAssetLookup.getImageSource("CloseDark")
fillMode: Image.PreserveAspectFit
}
}
Expand Down
9 changes: 5 additions & 4 deletions nebula/ui/components/MZInformationCard.qml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import QtQuick.Window 2.12
import Mozilla.Shared 1.0
import compat 0.1
import components 0.1
import "qrc:/nebula/utils/MZAssetLookup.js" as MZAssetLookup

Rectangle {
property alias _infoContent: infoContent.data
Expand Down Expand Up @@ -94,13 +95,13 @@ Rectangle {
function getIconImage() {
switch (cardType) {
case MZInformationCard.CardType.Info:
return "qrc:/nebula/resources/info.svg"
return MZAssetLookup.getImageSource("InfoIconThinner")
case MZInformationCard.CardType.Success:
return "qrc:/nebula/resources/success.svg"
return MZAssetLookup.getImageSource("SuccessIcon")
case MZInformationCard.CardType.Warning:
return "qrc:/nebula/resources/warning-gray.svg"
return MZAssetLookup.getImageSource("WarningIcon")
case MZInformationCard.CardType.Error:
return "qrc:/nebula/resources/warning-gray.svg"
return MZAssetLookup.getImageSource("WarningIcon")
default:
return console.error("Unable to create view for info card of type: " + cardType)
}
Expand Down
4 changes: 2 additions & 2 deletions nebula/ui/components/MZLinkRow.qml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import QtQuick 2.5
import QtQuick.Layouts 1.14

import Mozilla.Shared 1.0
import "qrc:/nebula/utils/MZAssetLookup.js" as MZAssetLookup

RowLayout {
id: linkRow
Expand Down Expand Up @@ -67,7 +67,7 @@ RowLayout {
buttonColorScheme: MZTheme.colors.clickableRow
accessibleName: title
MZIcon {
source: "qrc:/nebula/resources/externalLink.svg"
source: MZAssetLookup.getImageSource("ExternalLink")
anchors.centerIn: parent
}
onClicked: linkRow.clicked()
Expand Down
3 changes: 2 additions & 1 deletion nebula/ui/components/MZLoader.qml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import QtQuick 2.5
import Mozilla.Shared 1.0
import Mozilla.VPN 1.0
import components 0.1
import "qrc:/nebula/utils/MZAssetLookup.js" as MZAssetLookup

Item {
id: root
Expand Down Expand Up @@ -36,7 +37,7 @@ Item {
anchors.verticalCenter: root.verticalCenter
sourceSize.height: 80
fillMode: Image.PreserveAspectFit
source: "qrc:/nebula/resources/spinner.svg"
source: MZAssetLookup.getImageSource("Spinner")

ParallelAnimation {
id: startSpinning
Expand Down
3 changes: 2 additions & 1 deletion nebula/ui/components/MZMenu.qml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import QtQuick 2.5

import Mozilla.Shared 1.0
import "qrc:/nebula/utils/MZAssetLookup.js" as MZAssetLookup

Item {
id: menuBar
Expand All @@ -14,7 +15,7 @@ Item {
property bool accessibleIgnored: false
property bool btnDisabled: false
property alias forceFocus: iconButton.focus
property string _menuIconButtonSource: "qrc:/nebula/resources/back.svg"
property string _menuIconButtonSource: MZAssetLookup.getImageSource("ArrowBack")
property alias _menuIconButtonMirror: menuIcon.mirror
property alias _iconButtonAccessibleName: iconButton.accessibleName
property var _menuOnBackClicked: () => {}
Expand Down
3 changes: 2 additions & 1 deletion nebula/ui/components/MZPasteButton.qml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
import QtQuick 2.5

import Mozilla.Shared 1.0
import "qrc:/nebula/utils/MZAssetLookup.js" as MZAssetLookup

MZIconButton {
accessibleName: MZI18n.GlobalPaste

Image {
anchors.centerIn: parent
fillMode: Image.PreserveAspectFit
source: "qrc:/nebula/resources/paste.svg"
source: MZAssetLookup.getImageSource("Paste")
sourceSize.height: MZTheme.theme.iconSize * 1.5
sourceSize.width: MZTheme.theme.iconSize * 1.5
}
Expand Down
23 changes: 12 additions & 11 deletions nebula/ui/components/MZPaymentMethod.qml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import QtQuick 2.5
import QtQuick.Layouts 1.14

import Mozilla.Shared 1.0
import "qrc:/nebula/utils/MZAssetLookup.js" as MZAssetLookup

RowLayout {
id: root
Expand Down Expand Up @@ -39,57 +40,57 @@ RowLayout {
switch(paymentMethod) {
case "amex":
return {
icon: "qrc:/ui/resources/payment/amex.svg",
icon: MZAssetLookup.getImageSource("PaymentAmex"),
name: MZI18n.PaymentMethodsAmex
};
case "diners":
return {
icon: "qrc:/ui/resources/payment/diners.svg",
icon: MZAssetLookup.getImageSource("PaymentDiners"),
name: MZI18n.PaymentMethodsDiners
};
case "discover":
return {
icon: "qrc:/ui/resources/payment/discover.svg",
icon: MZAssetLookup.getImageSource("PaymentDiscover"),
name: MZI18n.PaymentMethodsDiscover
};
case "jcb":
return {
icon: "qrc:/ui/resources/payment/jcb.svg",
icon: MZAssetLookup.getImageSource("PaymentJcb"),
name: MZI18n.PaymentMethodsJcb
};
case "iap_apple":
return {
icon: "qrc:/ui/resources/payment/apple.svg",
icon: MZAssetLookup.getImageSource("PaymentApple"),
name: MZI18n.PaymentMethodsIapApple
};
case "iap_google":
return {
icon: "qrc:/ui/resources/payment/android.svg",
icon: MZAssetLookup.getImageSource("PaymentGoogle"),
name: MZI18n.PaymentMethodsIapGoogle
};
case "mastercard":
return {
icon: "qrc:/ui/resources/payment/mastercard.svg",
icon: MZAssetLookup.getImageSource("PaymentMastercard"),
name: MZI18n.PaymentMethodsMastercard
};
case "paypal":
return {
icon: "qrc:/ui/resources/payment/paypal.svg",
icon: MZAssetLookup.getImageSource("PaymentPayPal"),
name: MZI18n.PaymentMethodsPaypal
};
case "unionpay":
return {
icon: "qrc:/ui/resources/payment/unionpay.svg",
icon: MZAssetLookup.getImageSource("PaymentUnionPay"),
name: MZI18n.PaymentMethodsUnionpay
};
case "visa":
return {
icon: "qrc:/ui/resources/payment/visa.svg",
icon: MZAssetLookup.getImageSource("PaymentVisa"),
name: MZI18n.PaymentMethodsVisa
};
default:
return {
icon: "qrc:/ui/resources/payment/unbranded.svg",
icon: MZAssetLookup.getImageSource("PaymentUnbranded"),
name: ""
};
}
Expand Down
3 changes: 2 additions & 1 deletion nebula/ui/components/MZPopup.qml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import QtQuick.Controls 2.14

import Mozilla.Shared 1.0
import compat 0.1
import "qrc:/nebula/utils/MZAssetLookup.js" as MZAssetLookup

Popup {
id: popup
Expand Down Expand Up @@ -57,7 +58,7 @@ Popup {
anchors.centerIn: closeButton

fillMode: Image.PreserveAspectFit
source: "qrc:/nebula/resources/close-darker.svg"
source: MZAssetLookup.getImageSource("CloseDarker")
sourceSize.height: MZTheme.theme.iconSize
sourceSize.width: MZTheme.theme.iconSize
}
Expand Down
3 changes: 2 additions & 1 deletion nebula/ui/components/MZScreenBase.qml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import QtQuick.Layouts 1.15

import Mozilla.Shared 1.0
import components 0.1
import "qrc:/nebula/utils/MZAssetLookup.js" as MZAssetLookup

Item {
id: root
Expand All @@ -32,7 +33,7 @@ Item {
Layout.preferredWidth: parent.width
Layout.preferredHeight: MZTheme.theme.menuHeight

_menuIconButtonSource: stackview.depth === 1 ? "qrc:/nebula/resources/close-dark.svg" : "qrc:/nebula/resources/back.svg"
_menuIconButtonSource: stackview.depth === 1 ? MZAssetLookup.getImageSource("CloseDark") : MZAssetLookup.getImageSource("ArrowBack")
_menuIconButtonMirror: stackview.depth !== 1 && MZLocalizer.isRightToLeft
_iconButtonAccessibleName: stackview.depth === 1 ? MZI18n.GlobalClose : MZI18n.GlobalGoBack
_menuOnBackClicked: () => maybeRequestPreviousScreen()
Expand Down
Loading
Loading