diff --git a/nebula/ui/components/MZHelpSheet.qml b/nebula/ui/components/MZHelpSheet.qml
index 1b085573172..f0beb567431 100644
--- a/nebula/ui/components/MZHelpSheet.qml
+++ b/nebula/ui/components/MZHelpSheet.qml
@@ -82,7 +82,7 @@ MZBottomSheet {
id: icon
anchors.centerIn: parent
- sourceSize.width: MZTheme.theme.iconSize
+ sourceSize.width: MZTheme.theme.iconSize * 1.5
mirror: MZLocalizer.isRightToLeft
fillMode: Image.PreserveAspectFit
@@ -107,13 +107,18 @@ MZBottomSheet {
}
MZIconButton {
- id: iconButton
-
Layout.rightMargin: MZTheme.theme.windowMargin / 2
Layout.preferredHeight: MZTheme.theme.rowHeight
Layout.preferredWidth: MZTheme.theme.rowHeight
+ //Hacky workaround because for some reason, when opening a sheet via
+ //the right menu button in MZMenu, this close button is in a
+ //"Hovered" state, even though it wasn't hovered
+ //Likely something to do with both icon buttons being in the same position
+ //Relative to their parent (top right corner)
+ mouseArea.hoverEnabled: bottomSheet.opened
+
onClicked: bottomSheet.close()
accessibleName: MZI18n.GlobalClose
diff --git a/nebula/ui/components/MZIconButton.qml b/nebula/ui/components/MZIconButton.qml
index 8e602a46e8e..6ebdda9b7e6 100644
--- a/nebula/ui/components/MZIconButton.qml
+++ b/nebula/ui/components/MZIconButton.qml
@@ -12,6 +12,7 @@ MZButtonBase {
property bool skipEnsureVisible: false
property var accessibleName
property var buttonColorScheme: MZTheme.theme.iconButtonLightBackground
+ property alias mouseArea: mouseArea
property alias backgroundRadius: uiStates.radius
property alias uiStatesVisible: uiStates.visible
diff --git a/nebula/ui/resources/CMakeLists.txt b/nebula/ui/resources/CMakeLists.txt
index c780ca5f244..6243591928b 100644
--- a/nebula/ui/resources/CMakeLists.txt
+++ b/nebula/ui/resources/CMakeLists.txt
@@ -71,5 +71,7 @@ qt_add_qml_module(resources
info.svg
lock.svg
startup.svg
+ question.svg
+ tip-filled.svg
)
diff --git a/nebula/ui/resources/question.svg b/nebula/ui/resources/question.svg
new file mode 100644
index 00000000000..bc8c9e258db
--- /dev/null
+++ b/nebula/ui/resources/question.svg
@@ -0,0 +1,3 @@
+
diff --git a/nebula/ui/resources/tip-filled.svg b/nebula/ui/resources/tip-filled.svg
new file mode 100644
index 00000000000..6eede736d69
--- /dev/null
+++ b/nebula/ui/resources/tip-filled.svg
@@ -0,0 +1,11 @@
+
diff --git a/src/featurelist.h b/src/featurelist.h
index ee1cc02b05e..1704b8136b1 100644
--- a/src/featurelist.h
+++ b/src/featurelist.h
@@ -89,6 +89,13 @@ FEATURE(gleanRust, // Feature ID
QStringList(), // feature dependencies
FeatureCallback_true)
+FEATURE(helpSheets, // Feature ID
+ "Help sheets", // Feature name
+ FeatureCallback_true, // Can be flipped on
+ FeatureCallback_true, // Can be flipped off
+ QStringList(), // feature dependencies
+ FeatureCallback_false)
+
FEATURE(inAppAccountCreate, // Feature ID
"In-app Account Creation", // Feature name
FeatureCallback_true, // Can be flipped on
diff --git a/src/mozillavpn.cpp b/src/mozillavpn.cpp
index 9e46ec46ab0..707b9dacf13 100644
--- a/src/mozillavpn.cpp
+++ b/src/mozillavpn.cpp
@@ -1381,6 +1381,10 @@ void MozillaVPN::registerUrlOpenerLabels() {
uo->registerUrlLabel("upgradeToAnnualUrl", []() -> QString {
return Constants::upgradeToAnnualUrl();
});
+
+ uo->registerUrlLabel("sumoDns", []() -> QString {
+ return "https://support.mozilla.org/en-US/kb/how-do-i-change-my-dns-settings";
+ });
}
void MozillaVPN::errorHandled() {
diff --git a/src/translations/strings.yaml b/src/translations/strings.yaml
index 12666de5b15..233c9d3581e 100644
--- a/src/translations/strings.yaml
+++ b/src/translations/strings.yaml
@@ -928,6 +928,20 @@ devices:
value: My devices
comment: Title for the menu bar when viewing the devices or device limit pages
+helpSheets:
+ dnsTitle:
+ value: Custom DNS settings
+ comment: Title label for the custom dns help sheet
+ dnsHeader:
+ value: What is custom DNS?
+ comment: Header label for the custom dns help sheet
+ dnsBody1:
+ value: Whenever you connect to a website, a DNS (domain name system) first turns the domain name (e.g. www.mozilla.org) into an IP address that allows your internet traffic to reach that destination.
+ comment: Body text for the custom dns help sheet
+ dnsBody2:
+ value: Mozilla VPN allows you to choose a custom DNS server if you prefer. If you use one, you won’t be able to use other privacy features in the VPN like tracker blocking.
+ comment: Body text for the custom dns help sheet
+
global:
expand:
value: Expand
@@ -977,6 +991,12 @@ global:
getStarted:
value: Get started
comment: Label for a button used to begin something / proceed
+ help:
+ value: Help
+ comment: Action taken that will help the user
+ learnMore:
+ value: Learn more
+ comment: Label for link to allow the user to learn more about a topic
getHelp:
helpCenter: Help Center
diff --git a/src/ui/screens/settings/ViewDNSSettings.qml b/src/ui/screens/settings/ViewDNSSettings.qml
index 98e5b549326..82821363549 100644
--- a/src/ui/screens/settings/ViewDNSSettings.qml
+++ b/src/ui/screens/settings/ViewDNSSettings.qml
@@ -21,6 +21,27 @@ MZViewBase {
property bool privacyDialogNeeded: true
property bool dnsSelectionChanged: false
readonly property string telemetryScreenId : "dns_settings"
+ property Component rightMenuButton: Component {
+ Loader {
+ active: MZFeatureList.get("helpSheets").isSupported
+ sourceComponent: MZIconButton {
+ id: iconButton
+
+ onClicked: helpSheetLoader.active = true
+
+ accessibleName: MZI18n.GlobalHelp
+ Accessible.ignored: !visible
+
+ Image {
+ anchors.centerIn: parent
+
+ source: "qrc:/nebula/resources/question.svg"
+ fillMode: Image.PreserveAspectFit
+ }
+ }
+ }
+ }
+
function applyFrontendChanges(settingValue) {
if (settingValue === MZSettings.Gateway) {
@@ -73,7 +94,7 @@ MZViewBase {
function reset() {
root.customDNS = MZSettings.dnsProviderFlags === MZSettings.Custom;
root.privacyDialogNeeded = MZSettings.dnsProviderFlags !== MZSettings.Custom &&
- MZSettings.dnsProviderFlags !== MZSettings.Gateway;
+ MZSettings.dnsProviderFlags !== MZSettings.Gateway;
ipInput.text = MZSettings.userDNS;
}
@@ -224,9 +245,9 @@ MZViewBase {
}
onActiveFocusChanged: {
- if (!activeFocus && !ipInput.focusReasonA11y) {
- maybeSaveChange();
- }
+ if (!activeFocus && !ipInput.focusReasonA11y) {
+ maybeSaveChange();
+ }
}
}
@@ -258,8 +279,8 @@ MZViewBase {
Component.onCompleted: {
Glean.impression.dnsSettingsScreen.record({
- screen: telemetryScreenId,
- });
+ screen: telemetryScreenId,
+ });
reset();
}
@@ -268,11 +289,11 @@ MZViewBase {
}
onVisibleChanged: {
- if (!visible) {
- maybeSaveChange();
- } else {
- reset();
- }
+ if (!visible) {
+ maybeSaveChange();
+ } else {
+ reset();
+ }
}
Loader {
@@ -315,5 +336,27 @@ MZViewBase {
onActiveChanged: if (active) { item.open() }
}
+
+ Loader {
+ id: helpSheetLoader
+
+ active: false
+
+ onActiveChanged: if (active) item.open()
+
+ sourceComponent: MZHelpSheet {
+ title: MZI18n.HelpSheetsDnsTitle
+ iconSource: "qrc:/nebula/resources/tip-filled.svg"
+
+ model: [
+ {type: MZHelpSheet.BlockType.Title, text: MZI18n.HelpSheetsDnsHeader},
+ {type: MZHelpSheet.BlockType.Text, text: MZI18n.HelpSheetsDnsBody1, margin: 8},
+ {type: MZHelpSheet.BlockType.Text, text:MZI18n.HelpSheetsDnsBody2, margin: 16},
+ {type: MZHelpSheet.BlockType.LinkButton, text: MZI18n.GlobalLearnMore, margin: 16, action: () => { MZUrlOpener.openUrlLabel("sumoDns") } },
+ ]
+
+ onClosed: helpSheetLoader.active = false
+ }
+ }
}