status-desktop/ui/app/AppLayouts/Profile/views/MessagingView.qml

439 lines
16 KiB
QML

import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import QtGraphicalEffects 1.13
import utils 1.0
import shared 1.0
import shared.panels 1.0
import shared.popups 1.0
import shared.status 1.0
import shared.controls 1.0
import shared.stores 1.0
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import "../stores"
import "../controls"
import "../popups"
import "../panels"
SettingsContentBase {
id: root
property MessagingStore messagingStore
property AdvancedStore advancedStore
property ContactsStore contactsStore
ColumnLayout {
id: generalColumn
spacing: 2 * Constants.settingsSection.itemSpacing
width: root.contentWidth
ButtonGroup {
id: showProfilePictureToGroup
}
ButtonGroup {
id: seeProfilePicturesFromGroup
}
ButtonGroup {
id: browserGroup
}
StatusListItem {
id: allowNewContactRequest
Layout.fillWidth: true
implicitHeight: 64
title: qsTr("Allow new contact requests")
components: [
StatusSwitch {
id: switch3
checked: !root.messagingStore.privacyModule.messagesFromContactsOnly
onCheckedChanged: {
// messagesFromContactsOnly needs to be accessed from the module (view),
// because otherwise doing `messagesFromContactsOnly = value` only changes the bool property on QML
if (root.messagingStore.privacyModule.messagesFromContactsOnly === checked) {
root.messagingStore.privacyModule.messagesFromContactsOnly = !checked
}
}
}
]
onClicked: {
switch3.checked = !switch3.checked
}
}
// SHOW PROFILE PICTURE TO
StatusBaseText {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
text: qsTr("Show My Profile Picture To")
font.pixelSize: 15
color: Theme.palette.directColor1
}
SettingsRadioButton {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
label: qsTr("Everyone")
group: showProfilePictureToGroup
checked: root.messagingStore.profilePicturesShowTo ===
Constants.profilePicturesShowTo.everyone
onClicked: root.messagingStore.setProfilePicturesShowTo(
Constants.profilePicturesShowTo.everyone
)
}
SettingsRadioButton {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
label: qsTr("Contacts")
group: showProfilePictureToGroup
checked: root.messagingStore.profilePicturesShowTo ===
Constants.profilePicturesShowTo.contactsOnly
onClicked: root.messagingStore.setProfilePicturesShowTo(
Constants.profilePicturesShowTo.contactsOnly
)
}
SettingsRadioButton {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
label: qsTr("No One")
group: showProfilePictureToGroup
checked: root.messagingStore.profilePicturesShowTo ===
Constants.profilePicturesShowTo.noOne
onClicked: root.messagingStore.setProfilePicturesShowTo(
Constants.profilePicturesShowTo.noOne
)
}
// SEE PROFILTE PICTURES FROM
StatusBaseText {
Layout.topMargin: Constants.settingsSection.itemSpacing
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
text: qsTr("See Profile Pictures From")
font.pixelSize: 15
color: Theme.palette.directColor1
}
SettingsRadioButton {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
label: qsTr("Everyone")
group: seeProfilePicturesFromGroup
checked: root.messagingStore.profilePicturesVisibility ===
Constants.profilePicturesVisibility.everyone
onClicked: root.messagingStore.setProfilePicturesVisibility(
Constants.profilePicturesVisibility.everyone
)
}
SettingsRadioButton {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
label: qsTr("Contacts")
group: seeProfilePicturesFromGroup
checked: root.messagingStore.profilePicturesVisibility ===
Constants.profilePicturesVisibility.contactsOnly
onClicked: root.messagingStore.setProfilePicturesVisibility(
Constants.profilePicturesVisibility.contactsOnly
)
}
SettingsRadioButton {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
label: qsTr("No One")
group: seeProfilePicturesFromGroup
checked: root.messagingStore.profilePicturesVisibility ===
Constants.profilePicturesVisibility.noOne
onClicked: root.messagingStore.setProfilePicturesVisibility(
Constants.profilePicturesVisibility.noOne
)
}
// Open Message Links With
StatusBaseText {
Layout.topMargin: Constants.settingsSection.itemSpacing
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
text: qsTr("Open Message Links With")
font.pixelSize: 15
color: Theme.palette.directColor1
}
SettingsRadioButton {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
label: qsTr("Status Browser")
group: browserGroup
checked: localAccountSensitiveSettings.openLinksInStatus
onClicked: {
localAccountSensitiveSettings.openLinksInStatus = true
}
}
SettingsRadioButton {
Layout.topMargin: Constants.settingsSection.itemSpacing / 2
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
label: qsTr("System Default Browser")
group: browserGroup
checked: !localAccountSensitiveSettings.openLinksInStatus
onClicked: {
localAccountSensitiveSettings.openLinksInStatus = false
}
}
Separator {
id: separator1
Layout.topMargin: Constants.settingsSection.itemSpacing
Layout.fillWidth: true
}
// CONTACTS SECTION
StatusContactRequestsIndicatorListItem {
Layout.fillWidth: true
title: qsTr("Contacts, Requests, and Blocked Users")
requestsCount: root.contactsStore.receivedContactRequestsModel.count
onClicked: Global.changeAppSectionBySectionType(Constants.appSection.profile,
Constants.settingsSubsection.contacts)
}
Separator {
id: separator2
Layout.fillWidth: true
}
// MESSAGE LINK PREVIEWS
StatusListItem {
Layout.fillWidth: true
objectName: "displayMessageLinkPreviewsItem"
title: qsTr("Display Message Link Previews")
implicitHeight: 64
components: [
StatusSwitch {
id: showMessageLinksSwitch
checked: false
onCheckedChanged: {
if (checked === false) {
// Switch all the whitelists to false
imageSwitch.checked = false
for (let i = 0; i < sitesListView.count; i++) {
let item = sitesListView.itemAt(i)
item.whitelistSwitch.checked = false
}
}
}
}
]
onClicked: {
showMessageLinksSwitch.checked = !showMessageLinksSwitch.checked
}
}
function populatePreviewableSites() {
let whitelistAsString = root.messagingStore.getLinkPreviewWhitelist()
if(whitelistAsString == "")
return
let whitelist = JSON.parse(whitelistAsString)
if (!localAccountSensitiveSettings.whitelistedUnfurlingSites) {
localAccountSensitiveSettings.whitelistedUnfurlingSites = {}
}
previewableSites.clear()
var oneEntryIsActive = false
whitelist.forEach(entry => {
entry.isWhitelisted = !!localAccountSensitiveSettings.whitelistedUnfurlingSites[entry.address]
if (entry.isWhitelisted) {
oneEntryIsActive = true
}
previewableSites.append(entry)
})
if (oneEntryIsActive) {
showMessageLinksSwitch.checked = true
}
}
Component.onCompleted: {
populatePreviewableSites()
}
StatusSectionHeadline {
id: labelWebsites
visible: showMessageLinksSwitch.checked
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
text: qsTr("Fine tune which sites to allow link previews")
}
Column {
id: siteColumn
visible: showMessageLinksSwitch.checked
Layout.fillWidth: true
ListModel {
id: previewableSites
}
Connections {
target: Global
onSettingsLoaded: {
generalColumn.populatePreviewableSites()
}
}
Connections {
target: localAccountSensitiveSettings
onWhitelistedUnfurlingSitesChanged: generalColumn.populatePreviewableSites()
}
// Manually add switch for the image unfurling
StatusListItem {
objectName: "imageUnfurlingItem"
width: parent.width
implicitHeight: 64
title: qsTr("Image unfurling")
subTitle: qsTr("All images (links that contain an image extension) will be downloaded and displayed")
// TODO find a better icon for this
asset.name: Style.svg('globe')
asset.isImage: true
Component.onCompleted: {
if (localAccountSensitiveSettings.displayChatImages) {
showMessageLinksSwitch.checked = true
}
}
components: [
StatusSwitch {
id: imageSwitch
checked: localAccountSensitiveSettings.displayChatImages
onCheckedChanged: {
if (localAccountSensitiveSettings.displayChatImages !== checked) {
localAccountSensitiveSettings.displayChatImages = checked
}
}
}
]
onClicked: {
imageSwitch.checked = !imageSwitch.checked
}
}
Repeater {
id: sitesListView
model: previewableSites
delegate: Component {
StatusListItem {
property alias whitelistSwitch: siteSwitch
width: parent.width
implicitHeight: 64
title: model.title
subTitle: model.address
asset.name: {
let filename;
switch (model.title.toLowerCase()) {
case "youtube":
case "youtube shortener":
filename = "youtube"; break;
case "github":
filename = "github"; break;
case "medium":
filename = "medium"; break;
case "tenor gifs subdomain":
filename = "tenor"; break;
case "giphy gifs":
case "giphy gifs shortener":
case "giphy gifs subdomain":
filename = "giphy"; break;
case "github":
filename = "github"; break;
case "status":
filename = "status"; break;
// TODO get a good default icon
default: filename = "../globe"
}
return Style.svg(`linkPreviewThumbnails/${filename}`)
}
asset.isImage: true
components: [
StatusSwitch {
id: siteSwitch
checked: !!model.isWhitelisted
onCheckedChanged: RootStore.updateWhitelistedUnfurlingSites(model.address, checked)
}
]
onClicked: {
siteSwitch.checked = !siteSwitch.checked
}
}
}
}
} // Site Column
Separator {
id: separator3
visible: siteColumn.visible
Layout.fillWidth: true
}
// SYNC WAKU SECTION
StatusSectionHeadline {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
text: qsTr("Message syncing")
}
StatusListItem {
Layout.fillWidth: true
title: qsTr("Waku nodes")
label: root.messagingStore.getMailserverNameForNodeAddress(root.messagingStore.activeMailserver)
components: [
StatusIcon {
icon: "chevron-down"
rotation: 270
color: Theme.palette.baseColor1
}
]
onClicked: Global.openPopup(wakuNodeModalComponent)
}
Component {
id: wakuNodeModalComponent
WakuNodesModal {
messagingStore: root.messagingStore
advancedStore: root.advancedStore
}
}
StatusSectionHeadline {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
text: qsTr("For security reasons, private chat history won't be synced.")
}
}
}