feat(Settings/Privacy and security): add Privacy Policy popup (#16171)

- mention the "Privacy Policy" document in the text explaining "Help us
improve Status", make a link to it and display it in a separate popup
- add a standalone header button to the settings page, doing the same
- extend storybook page with the "placement" param

Fixes #16157
This commit is contained in:
Lukáš Tinkl 2024-08-21 17:17:20 +02:00 committed by GitHub
parent 94539eb744
commit 2bfa6bbf2a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 109 additions and 40 deletions

View File

@ -1,4 +1,5 @@
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15 import QtQuick.Controls 2.15
import shared.popups 1.0 import shared.popups 1.0
@ -9,8 +10,9 @@ import Storybook 1.0
SplitView { SplitView {
orientation: Qt.Vertical orientation: Qt.Vertical
Item { Logs { id: logs }
Item {
SplitView.fillWidth: true SplitView.fillWidth: true
SplitView.fillHeight: true SplitView.fillHeight: true
@ -24,14 +26,54 @@ SplitView {
onClicked: popup.open() onClicked: popup.open()
} }
}
MetricsEnablePopup { MetricsEnablePopup {
id: popup id: popup
anchors.centerIn: parent anchors.centerIn: parent
modal: false modal: false
visible: true visible: true
placement: Constants.metricsEnablePlacement.unknown placement: ctrlPlacement.currentValue
onSetMetricsEnabledRequested: logs.logEvent("setMetricsEnabledRequested", ["enabled"], arguments)
onClosed: logs.logEvent("closed()")
}
Connections {
target: Global
function onPrivacyPolicyRequested() {
logs.logEvent("Global::privacyPolicyRequested()")
}
}
}
LogsAndControlsPanel {
id: logsAndControlsPanel
SplitView.minimumHeight: 100
SplitView.preferredHeight: 200
logsView.logText: logs.logText
ColumnLayout {
anchors.fill: parent
RowLayout {
Layout.fillWidth: true
Label {
text: "Placement:"
}
ComboBox {
Layout.preferredWidth: 200
id: ctrlPlacement
model: [
Constants.metricsEnablePlacement.unknown,
Constants.metricsEnablePlacement.welcome,
Constants.metricsEnablePlacement.privacyAndSecurity,
Constants.metricsEnablePlacement.startApp
]
}
}
Item { Layout.fillHeight: true }
}
} }
} }

View File

@ -128,7 +128,7 @@ headline_StatusTitleSubtitle = {"container": statusDesktop_mainWindow_overlay, "
keys_exist_StatusBaseText = {"container": statusDesktop_mainWindow_overlay, "type": "StatusBaseText", "unnamed": 1, "visible": True} keys_exist_StatusBaseText = {"container": statusDesktop_mainWindow_overlay, "type": "StatusBaseText", "unnamed": 1, "visible": True}
# Share Usage Data Popup # Share Usage Data Popup
not_now_StatusButton = {"checkable": False, "container": statusDesktop_mainWindow_overlay, "objectName": "notShareMetricsButton", "type": "StatusButton", "visible": True} not_now_StatusButton = {"checkable": False, "container": statusDesktop_mainWindow_overlay, "objectName": "notShareMetricsButton", "type": "StatusFlatButton", "visible": True}
share_usage_data_StatusButton = {"checkable": False, "container": statusDesktop_mainWindow_overlay, "objectName": "shareMetricsButton", "type": "StatusButton", "visible": True} share_usage_data_StatusButton = {"checkable": False, "container": statusDesktop_mainWindow_overlay, "objectName": "shareMetricsButton", "type": "StatusButton", "visible": True}
""" Communities """ """ Communities """

View File

@ -3,23 +3,10 @@ import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15 import QtQuick.Layouts 1.15
import utils 1.0 import utils 1.0
import shared.panels 1.0
import shared.popups 1.0
import shared.stores 1.0
import StatusQ 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1 as StatusQUtils
import StatusQ.Components 0.1 import StatusQ.Components 0.1
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import AppLayouts.Profile.stores 1.0
import "../popups"
import SortFilterProxyModel 0.2
SettingsContentBase { SettingsContentBase {
id: root id: root
@ -29,6 +16,11 @@ SettingsContentBase {
enableMetricsSwitch.checked = Qt.binding(function() { return root.isCentralizedMetricsEnabled }) enableMetricsSwitch.checked = Qt.binding(function() { return root.isCentralizedMetricsEnabled })
} }
titleRowComponentLoader.sourceComponent: StatusButton {
text: qsTr("Privacy policy")
onClicked: Global.privacyPolicyRequested()
}
ColumnLayout { ColumnLayout {
StatusListItem { StatusListItem {
Layout.preferredWidth: root.contentWidth Layout.preferredWidth: root.contentWidth
@ -38,13 +30,15 @@ SettingsContentBase {
StatusSwitch { StatusSwitch {
id: enableMetricsSwitch id: enableMetricsSwitch
checked: root.isCentralizedMetricsEnabled checked: root.isCentralizedMetricsEnabled
onClicked: { onToggled: {
Global.openMetricsEnablePopupRequested(Constants.metricsEnablePlacement.privacyAndSecurity, popup => popup.toggleMetrics.connect(refreshSwitch)) Global.openMetricsEnablePopupRequested(Constants.metricsEnablePlacement.privacyAndSecurity, null)
refreshSwitch()
} }
} }
] ]
onClicked: { onClicked: {
Global.openMetricsEnablePopupRequested(Constants.metricsEnablePlacement.privacyAndSecurity, popup => popup.toggleMetrics.connect(refreshSwitch)) Global.openMetricsEnablePopupRequested(Constants.metricsEnablePlacement.privacyAndSecurity, null)
refreshSwitch()
} }
} }
} }

View File

@ -8,6 +8,7 @@ import StatusQ.Core 0.1
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import StatusQ.Components 0.1 import StatusQ.Components 0.1
import StatusQ.Popups 0.1 import StatusQ.Popups 0.1
import StatusQ.Popups.Dialog 0.1
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1 as SQUtils import StatusQ.Core.Utils 0.1 as SQUtils
@ -95,6 +96,7 @@ QtObject {
Global.openCommunityMemberMessagesPopupRequested.connect(openCommunityMemberMessagesPopup) Global.openCommunityMemberMessagesPopupRequested.connect(openCommunityMemberMessagesPopup)
Global.openSwapModalRequested.connect(openSwapModal) Global.openSwapModalRequested.connect(openSwapModal)
Global.openBuyCryptoModalRequested.connect(openBuyCryptoModal) Global.openBuyCryptoModalRequested.connect(openBuyCryptoModal)
Global.privacyPolicyRequested.connect(() => openPopup(privacyPolicyPopupComponent))
} }
property var currentPopup property var currentPopup
@ -1269,6 +1271,28 @@ QtObject {
} }
onClosed: destroy() onClosed: destroy()
} }
},
Component {
id: privacyPolicyPopupComponent
StatusDialog {
width: 600
padding: 0
title: qsTr("Status Software Privacy Policy")
StatusScrollView {
id: privacyDialogScrollView
anchors.fill: parent
contentWidth: availableWidth
StatusBaseText {
width: privacyDialogScrollView.availableWidth
wrapMode: Text.Wrap
textFormat: Text.MarkdownText
text: SQUtils.StringUtils.readTextFile(":/imports/assets/docs/privacy.mdwn")
onLinkActivated: Global.openLinkWithConfirmation(link, SQUtils.StringUtils.extractDomainFromLink(link))
}
}
standardButtons: Dialog.Ok
destroyOnClose: true
}
} }
] ]
} }

View File

@ -16,7 +16,7 @@ StatusModal {
property string placement: Constants.metricsEnablePlacement.unknown property string placement: Constants.metricsEnablePlacement.unknown
signal toggleMetrics(bool enabled) signal setMetricsEnabledRequested(bool enabled)
width: 640 width: 640
title: qsTr("Help us improve Status") title: qsTr("Help us improve Status")
@ -83,31 +83,38 @@ StatusModal {
Paragraph { Paragraph {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
text: qsTr("Usage data will be shared from all profiles added to device. %1").arg(root.placement !== Constants.metricsEnablePlacement.privacyAndSecurity ? "Sharing usage data can be turned off anytime in Settings / Privacy and Security." : "") textFormat: Text.RichText
text: qsTr("Usage data will be shared from all profiles added to device. %1 %2")
.arg(root.placement !== Constants.metricsEnablePlacement.privacyAndSecurity ? qsTr("Sharing usage data can be turned off anytime in Settings / Privacy and Security.") : "")
.arg(root.placement === Constants.metricsEnablePlacement.privacyAndSecurity ? qsTr("For more details refer to our %1.").arg(Utils.getStyledLink("Privacy Policy", "#", hoveredLink)) : "")
onLinkActivated: {
root.close()
Global.privacyPolicyRequested()
}
HoverHandler {
cursorShape: !!parent.hoveredLink ? Qt.PointingHandCursor : undefined
}
} }
} }
} }
rightButtons: [ rightButtons: [
StatusFlatButton {
text: qsTr("Do not share")
onClicked: {
root.setMetricsEnabledRequested(false)
close()
}
objectName: "notShareMetricsButton"
normalColor: "transparent"
},
StatusButton { StatusButton {
text: qsTr("Share usage data") text: qsTr("Share usage data")
onClicked: { onClicked: {
root.toggleMetrics(true) root.setMetricsEnabledRequested(true)
close() close()
} }
objectName: "shareMetricsButton" objectName: "shareMetricsButton"
} }
] ]
leftButtons: [
StatusButton {
text: qsTr("Not now")
onClicked: {
root.toggleMetrics(false)
close()
}
objectName: "notShareMetricsButton"
normalColor: "transparent"
}
]
} }

View File

@ -103,6 +103,8 @@ QtObject {
signal openTestnetPopup() signal openTestnetPopup()
signal privacyPolicyRequested()
// Swap // Swap
signal openSwapModalRequested(var formDataParams) signal openSwapModalRequested(var formDataParams)

View File

@ -381,7 +381,7 @@ StatusWindow {
sourceComponent: MetricsEnablePopup { sourceComponent: MetricsEnablePopup {
visible: true visible: true
onClosed: metricsPopupLoader.active = false onClosed: metricsPopupLoader.active = false
onToggleMetrics: { onSetMetricsEnabledRequested: {
applicationWindow.metricsStore.toggleCentralizedMetrics(enabled) applicationWindow.metricsStore.toggleCentralizedMetrics(enabled)
if (enabled) { if (enabled) {
Global.addCentralizedMetricIfEnabled("usage_data_shared", {placement: metricsPopupLoader.item.placement}) Global.addCentralizedMetricIfEnabled("usage_data_shared", {placement: metricsPopupLoader.item.placement})