fix[onboarding] Broken links to "Terms" and "Privacy"
- display the locally bundled privacy/terms of use texts in a popup - add support for reading text files with both relative and absolute files or URLs, useful for having the same file path in both storybook and the app Fixes #13877
This commit is contained in:
parent
e7a1f5e831
commit
666ba77051
|
@ -0,0 +1,55 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
import QtQml 2.15
|
||||||
|
|
||||||
|
import AppLayouts.Onboarding.popups 1.0
|
||||||
|
|
||||||
|
import utils 1.0
|
||||||
|
|
||||||
|
import Storybook 1.0
|
||||||
|
|
||||||
|
SplitView {
|
||||||
|
id: root
|
||||||
|
orientation: Qt.Vertical
|
||||||
|
|
||||||
|
Logs { id: logs }
|
||||||
|
|
||||||
|
function openDialog() {
|
||||||
|
popupComponent.createObject(popupBg)
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: openDialog()
|
||||||
|
|
||||||
|
Item {
|
||||||
|
SplitView.fillWidth: true
|
||||||
|
SplitView.fillHeight: true
|
||||||
|
|
||||||
|
PopupBackground {
|
||||||
|
id: popupBg
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Button {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "Reopen"
|
||||||
|
|
||||||
|
onClicked: openDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: popupComponent
|
||||||
|
BeforeGetStartedModal {
|
||||||
|
id: popup
|
||||||
|
anchors.centerIn: parent
|
||||||
|
modal: false
|
||||||
|
visible: true
|
||||||
|
onClosed: destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// category: Popups
|
||||||
|
|
||||||
|
// https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?type=design&node-id=38555-18004&mode=design&t=WHoI8vkSC9JScbPx-0
|
|
@ -17,15 +17,15 @@ QString StringUtilsInternal::escapeHtml(const QString& unsafe) const
|
||||||
}
|
}
|
||||||
|
|
||||||
QString resolveFileUsingQmlImportPaths(QQmlEngine *engine, const QString &relativeFilePath) {
|
QString resolveFileUsingQmlImportPaths(QQmlEngine *engine, const QString &relativeFilePath) {
|
||||||
QStringList importPaths = engine->importPathList();
|
const auto importPaths = engine->importPathList();
|
||||||
for (const auto &path : importPaths) {
|
for (const auto &path : importPaths) {
|
||||||
QString fullPath = path + "/" + relativeFilePath;
|
const auto fullPath = path + QStringLiteral("/") + relativeFilePath;
|
||||||
QFile file(fullPath);
|
QFile file(fullPath);
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
return fullPath;
|
return fullPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QString StringUtilsInternal::readTextFile(const QString& filePath) const
|
QString StringUtilsInternal::readTextFile(const QString& filePath) const
|
||||||
|
@ -36,18 +36,27 @@ QString StringUtilsInternal::readTextFile(const QString& filePath) const
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto resolvedFilePath = selector->selector()->select(filePath);
|
QString selectedFilePath;
|
||||||
|
const auto maybeFileUrl = QUrl(filePath).toLocalFile(); // support local file URLs (e.g. "file:///foo/bar/baz.txt")
|
||||||
|
|
||||||
QFile file(resolvedFilePath);
|
if (QFile::exists(maybeFileUrl))
|
||||||
|
selectedFilePath = maybeFileUrl;
|
||||||
|
else
|
||||||
|
selectedFilePath = selector->selector()->select(filePath);
|
||||||
|
|
||||||
|
if (selectedFilePath.startsWith(QLatin1String("qrc:/"))) // for some reason doesn't work with the "qrc:/" prefix, drop it
|
||||||
|
selectedFilePath.remove(0, 3);
|
||||||
|
|
||||||
|
QFile file(selectedFilePath);
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
auto fileUrl = resolveFileUsingQmlImportPaths(m_engine, filePath);
|
const auto resolvedFilePath = resolveFileUsingQmlImportPaths(m_engine, filePath);
|
||||||
if (fileUrl.isEmpty()) {
|
if (resolvedFilePath.isEmpty()) {
|
||||||
qWarning() << Q_FUNC_INFO << "Can't find file in QML import paths" << filePath;
|
qWarning() << Q_FUNC_INFO << "Can't find file in QML import paths" << filePath;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
file.setFileName(fileUrl);
|
file.setFileName(resolvedFilePath);
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
qWarning() << Q_FUNC_INFO << "Error opening existing file" << fileUrl << "for reading";
|
qWarning() << Q_FUNC_INFO << "Error opening existing file" << resolvedFilePath << "for reading";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import QtQml.Models 2.14
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
|
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
|
import StatusQ.Core.Utils 0.1 as SQUtils
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
import StatusQ.Controls 0.1
|
import StatusQ.Controls 0.1
|
||||||
import StatusQ.Popups.Dialog 0.1
|
import StatusQ.Popups.Dialog 0.1
|
||||||
|
@ -13,7 +14,7 @@ import StatusQ.Popups.Dialog 0.1
|
||||||
StatusDialog {
|
StatusDialog {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
width: 480
|
width: 600
|
||||||
topPadding: Style.current.bigPadding
|
topPadding: Style.current.bigPadding
|
||||||
bottomPadding: Style.current.bigPadding
|
bottomPadding: Style.current.bigPadding
|
||||||
closePolicy: Popup.NoAutoClose
|
closePolicy: Popup.NoAutoClose
|
||||||
|
@ -28,96 +29,94 @@ StatusDialog {
|
||||||
StatusButton {
|
StatusButton {
|
||||||
objectName: "getStartedStatusButton"
|
objectName: "getStartedStatusButton"
|
||||||
enabled: acknowledge.checked && termsOfUse.checked
|
enabled: acknowledge.checked && termsOfUse.checked
|
||||||
size: StatusBaseButton.Size.Large
|
text: qsTr("Get started")
|
||||||
font.weight: Font.Medium
|
|
||||||
text: qsTr("Get Started")
|
|
||||||
onClicked: root.close()
|
onClicked: root.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contentItem: Item {
|
contentItem: ColumnLayout {
|
||||||
Column {
|
spacing: Style.current.padding
|
||||||
width: 416
|
|
||||||
spacing: Style.current.padding
|
|
||||||
anchors.centerIn: parent
|
|
||||||
|
|
||||||
StatusCheckBox {
|
StatusCheckBox {
|
||||||
id: acknowledge
|
Layout.fillWidth: true
|
||||||
objectName: "acknowledgeCheckBox"
|
id: acknowledge
|
||||||
spacing: Style.current.halfPadding
|
objectName: "acknowledgeCheckBox"
|
||||||
font.pixelSize: 15
|
spacing: Style.current.halfPadding
|
||||||
width: parent.width
|
text: qsTr("I acknowledge that Status Desktop is in Beta and by using it I take the full responsibility for all risks concerning my data and funds.")
|
||||||
text: qsTr("I acknowledge that Status Desktop is in Beta and by using it I take the full responsibility for all risks concerning my data and funds.")
|
}
|
||||||
}
|
|
||||||
|
|
||||||
StatusCheckBox {
|
StatusCheckBox {
|
||||||
id: termsOfUse
|
Layout.fillWidth: true
|
||||||
objectName: "termsOfUseCheckBox"
|
id: termsOfUse
|
||||||
width: parent.width
|
objectName: "termsOfUseCheckBox"
|
||||||
font.pixelSize: 15
|
|
||||||
|
|
||||||
contentItem: Row {
|
contentItem: Row {
|
||||||
spacing: 4
|
spacing: 4
|
||||||
leftPadding: termsOfUse.indicator.width + termsOfUse.spacing
|
leftPadding: termsOfUse.indicator.width + termsOfUse.spacing
|
||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
text: qsTr("I accept Status")
|
text: qsTr("I accept Status")
|
||||||
font.pixelSize: 15
|
}
|
||||||
|
|
||||||
|
StatusLinkText {
|
||||||
|
objectName: "termsOfUseLink"
|
||||||
|
text: qsTr("Terms of Use")
|
||||||
|
color: Theme.palette.primaryColor1
|
||||||
|
font.weight: Font.Medium
|
||||||
|
font.pixelSize: Theme.primaryTextFontSize
|
||||||
|
onClicked: {
|
||||||
|
detailsPopup.title = qsTr("Status Software Terms of Use")
|
||||||
|
detailsPopup.textFile = SQUtils.StringUtils.readTextFile(Qt.resolvedUrl("../../../../imports/assets/docs/terms-of-use.mdwn"))
|
||||||
|
detailsPopup.open()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
objectName: "termsOfUseLink"
|
text: "&"
|
||||||
text: qsTr("Terms of Use")
|
}
|
||||||
color: Theme.palette.primaryColor1
|
|
||||||
font.pixelSize: 15
|
|
||||||
font.weight: Font.Medium
|
|
||||||
|
|
||||||
MouseArea {
|
StatusLinkText {
|
||||||
anchors.fill: parent
|
objectName: "privacyPolicyLink"
|
||||||
cursorShape: Qt.PointingHandCursor
|
text: qsTr("Privacy Policy")
|
||||||
hoverEnabled: true
|
color: Theme.palette.primaryColor1
|
||||||
onEntered: {
|
font.weight: Font.Medium
|
||||||
parent.font.underline = true
|
font.pixelSize: Theme.primaryTextFontSize
|
||||||
}
|
onClicked: {
|
||||||
onExited: {
|
detailsPopup.title = qsTr("Status Software Privacy Statement")
|
||||||
parent.font.underline = false
|
detailsPopup.textFile = SQUtils.StringUtils.readTextFile(Qt.resolvedUrl("../../../../imports/assets/docs/privacy.mdwn"))
|
||||||
}
|
detailsPopup.open()
|
||||||
onClicked: {
|
|
||||||
Qt.openUrlExternally("https://status.im/terms-of-use/")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusBaseText {
|
|
||||||
text: "&"
|
|
||||||
font.pixelSize: 15
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusBaseText {
|
|
||||||
objectName: "privacyPolicyLink"
|
|
||||||
text: qsTr("Privacy Policy")
|
|
||||||
color: Theme.palette.primaryColor1
|
|
||||||
font.pixelSize: 15
|
|
||||||
font.weight: Font.Medium
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
hoverEnabled: true
|
|
||||||
onEntered: {
|
|
||||||
parent.font.underline = true
|
|
||||||
}
|
|
||||||
onExited: {
|
|
||||||
parent.font.underline = false
|
|
||||||
}
|
|
||||||
onClicked: {
|
|
||||||
Qt.openUrlExternally("https://status.im/privacy-policy/")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StatusDialog {
|
||||||
|
id: detailsPopup
|
||||||
|
|
||||||
|
property string textFile
|
||||||
|
|
||||||
|
width: 600
|
||||||
|
padding: 0
|
||||||
|
standardButtons: Dialog.Ok
|
||||||
|
anchors.centerIn: parent
|
||||||
|
visible: false
|
||||||
|
|
||||||
|
onClosed: textFile = ""
|
||||||
|
|
||||||
|
StatusScrollView {
|
||||||
|
id: scrollView
|
||||||
|
anchors.fill: parent
|
||||||
|
contentWidth: availableWidth
|
||||||
|
padding: 20
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
width: scrollView.availableWidth
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
textFormat: Text.MarkdownText
|
||||||
|
text: detailsPopup.textFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
BeforeGetStartedModal 1.0 BeforeGetStartedModal.qml
|
Loading…
Reference in New Issue