From 0aba35d9bdafc7708d9b31bc479c70f8b66caa66 Mon Sep 17 00:00:00 2001 From: jngibbon Date: Sun, 6 Jun 2021 21:51:05 +0200 Subject: [PATCH] Implement Settings Accordion fixes #344 --- harbour-fernschreiber.pro | 8 + qml/components/settingsPage/Accordion.qml | 47 ++ qml/components/settingsPage/AccordionItem.qml | 115 +++ .../settingsPage/ResponsiveGrid.qml | 29 + .../settingsPage/SettingsAppearance.qml | 64 ++ .../settingsPage/SettingsBehavior.qml | 171 ++++ .../settingsPage/SettingsPrivacy.qml | 267 +++++++ .../settingsPage/SettingsStorage.qml | 51 ++ .../settingsPage/SettingsUserProfile.qml | 261 +++++++ qml/pages/SettingsPage.qml | 728 +----------------- 10 files changed, 1022 insertions(+), 719 deletions(-) create mode 100644 qml/components/settingsPage/Accordion.qml create mode 100644 qml/components/settingsPage/AccordionItem.qml create mode 100644 qml/components/settingsPage/ResponsiveGrid.qml create mode 100644 qml/components/settingsPage/SettingsAppearance.qml create mode 100644 qml/components/settingsPage/SettingsBehavior.qml create mode 100644 qml/components/settingsPage/SettingsPrivacy.qml create mode 100644 qml/components/settingsPage/SettingsStorage.qml create mode 100644 qml/components/settingsPage/SettingsUserProfile.qml diff --git a/harbour-fernschreiber.pro b/harbour-fernschreiber.pro index 46bf66b..bd59210 100644 --- a/harbour-fernschreiber.pro +++ b/harbour-fernschreiber.pro @@ -108,6 +108,14 @@ DISTFILES += qml/harbour-fernschreiber.qml \ qml/components/messageContent/MessageVideo.qml \ qml/components/messageContent/MessageVoiceNote.qml \ qml/components/messageContent/WebPagePreview.qml \ + qml/components/settingsPage/Accordion.qml \ + qml/components/settingsPage/AccordionItem.qml \ + qml/components/settingsPage/ResponsiveGrid.qml \ + qml/components/settingsPage/SettingsAppearance.qml \ + qml/components/settingsPage/SettingsBehavior.qml \ + qml/components/settingsPage/SettingsPrivacy.qml \ + qml/components/settingsPage/SettingsStorage.qml \ + qml/components/settingsPage/SettingsUserProfile.qml \ qml/js/debug.js \ qml/js/functions.js \ qml/pages/ActiveSessionsPage.qml \ diff --git a/qml/components/settingsPage/Accordion.qml b/qml/components/settingsPage/Accordion.qml new file mode 100644 index 0000000..49ab79a --- /dev/null +++ b/qml/components/settingsPage/Accordion.qml @@ -0,0 +1,47 @@ +/* + Copyright (C) 2021 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Fernschreiber is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fernschreiber. If not, see . +*/ + +import QtQuick 2.6 +import Sailfish.Silica 1.0 + + +Column { + width: parent.width + property SilicaFlickable flickable + property bool animate: false + signal setActiveArea(string activeAreaTitle) + function scrollUpFlickable(amount) { + if(flickable) { + flickableAnimation.to = Math.max(0, flickable.contentY - amount); + flickableAnimation.start() + } + } + + NumberAnimation { + id: flickableAnimation + target: flickable + property: "contentY" + duration: 200 + } + onSetActiveArea: { + if(activeAreaTitle && flickable) { +// flickable.scrollToTop(); + } + } +} diff --git a/qml/components/settingsPage/AccordionItem.qml b/qml/components/settingsPage/AccordionItem.qml new file mode 100644 index 0000000..8dbbaaa --- /dev/null +++ b/qml/components/settingsPage/AccordionItem.qml @@ -0,0 +1,115 @@ +/* + Copyright (C) 2021 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Fernschreiber is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fernschreiber. If not, see . +*/ + +import QtQuick 2.6 +import Sailfish.Silica 1.0 + +Item { + id: area + width: parent.width + height: button.height + content.height + property alias icon: image + property alias text: label.text + property alias asynchronous: content.asynchronous + property bool expanded: false + default property alias els: content.sourceComponent + states: [ + State { + when: area.expanded + PropertyChanges { target: image; rotation: 90 } + PropertyChanges { target: content; height: content.implicitHeight + Theme.paddingLarge; opacity: 1.0 } + } + ] + transitions: Transition { + to: "*" + enabled: area.parent.animate + NumberAnimation { target: content; properties: "height, opacity"; duration: 200} + } + Connections { + target: area.parent + onSetActiveArea: { + var expand = (activeAreaTitle === area.text); + if(area.expanded && !expand && area.parent.scrollUpFlickable) { + area.parent.scrollUpFlickable(content.implicitHeight + Theme.paddingLarge); + } + + area.expanded = expand; + } + } + BackgroundItem { + id: button + height: Theme.itemSizeMedium + onClicked: { + area.parent.animate = true; + area.parent.setActiveArea(area.expanded ? -1 : area.text) + } + Rectangle { + anchors.fill: parent + gradient: Gradient { + GradientStop { position: 0.0; color: Theme.rgba(Theme.highlightBackgroundColor, 0.15) } + GradientStop { position: 1.0; color: "transparent" } + } + } + Label { + id: label + anchors { + left: parent.left + right: image.left + verticalCenter: parent.verticalCenter + leftMargin: Theme.horizontalPageMargin + Theme.paddingLarge + rightMargin: Theme.paddingMedium + } + horizontalAlignment: Text.AlignRight + truncationMode: TruncationMode.Fade + font.pixelSize: Theme.fontSizeSmall + color: button.highlighted ? Theme.highlightColor : Theme.primaryColor + textFormat: Text.PlainText + } + HighlightImage { + id: image + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + rightMargin: Theme.horizontalPageMargin + } + width: visible ? Theme.iconSizeMedium : 0 + highlighted: parent.highlighted + source: "image://theme/icon-m-right" + rotation: -90 + } + } + Loader { + id: content + width: parent.width + height: 0 + opacity: 0 + anchors.top: button.bottom + asynchronous: true + clip: true + } +// Column { +// id: content +// width: parent.width +// anchors.top: button.bottom +// bottomPadding: Theme.paddingLarge +// height: 0 +// opacity: 0 +// clip: true +// } +} diff --git a/qml/components/settingsPage/ResponsiveGrid.qml b/qml/components/settingsPage/ResponsiveGrid.qml new file mode 100644 index 0000000..68a5d52 --- /dev/null +++ b/qml/components/settingsPage/ResponsiveGrid.qml @@ -0,0 +1,29 @@ +/* + Copyright (C) 2021 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Fernschreiber is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fernschreiber. If not, see . +*/ + +import QtQuick 2.6 +import Sailfish.Silica 1.0 + +Grid { + width: parent.width - ( 2 * x ) + columns: (appWindow.deviceOrientation & Orientation.LandscapeMask) || Screen.sizeCategory === Screen.Large || Screen.sizeCategory === Screen.ExtraLarge ? 2 : 1 + + readonly property real columnWidth: width/columns + +} diff --git a/qml/components/settingsPage/SettingsAppearance.qml b/qml/components/settingsPage/SettingsAppearance.qml new file mode 100644 index 0000000..f0a3d39 --- /dev/null +++ b/qml/components/settingsPage/SettingsAppearance.qml @@ -0,0 +1,64 @@ +/* + Copyright (C) 2021 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Fernschreiber is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fernschreiber. If not, see . +*/ + +import QtQuick 2.6 +import Sailfish.Silica 1.0 + +AccordionItem { + text: qsTr("Appearance") + Component { + ResponsiveGrid { + bottomPadding: Theme.paddingMedium + TextSwitch { + id: stickersAsEmojisTextSwitch + width: parent.columnWidth + checked: appSettings.showStickersAsEmojis + text: qsTr("Show stickers as emojis") + description: qsTr("Only display emojis instead of the actual stickers") + automaticCheck: false + onClicked: { + appSettings.showStickersAsEmojis = !checked + } + } + + TextSwitch { + width: parent.columnWidth + checked: appSettings.showStickersAsImages + text: qsTr("Show stickers as images") + description: qsTr("Show background for stickers and align them centrally like images") + automaticCheck: false + onClicked: { + appSettings.showStickersAsImages = !checked + } + enabled: !stickersAsEmojisTextSwitch.checked + } + + TextSwitch { + width: parent.columnWidth + checked: appSettings.animateStickers + text: qsTr("Animate stickers") + automaticCheck: false + onClicked: { + appSettings.animateStickers = !checked + } + enabled: !stickersAsEmojisTextSwitch.checked + } + } + } +} diff --git a/qml/components/settingsPage/SettingsBehavior.qml b/qml/components/settingsPage/SettingsBehavior.qml new file mode 100644 index 0000000..a3f1be1 --- /dev/null +++ b/qml/components/settingsPage/SettingsBehavior.qml @@ -0,0 +1,171 @@ +/* + Copyright (C) 2021 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Fernschreiber is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fernschreiber. If not, see . +*/ + +import QtQuick 2.6 +import Sailfish.Silica 1.0 +import WerkWolf.Fernschreiber 1.0 + +AccordionItem { + text: qsTr("Behavior") + Component { + ResponsiveGrid { + bottomPadding: Theme.paddingMedium + TextSwitch { + width: parent.columnWidth + checked: appSettings.sendByEnter + text: qsTr("Send message by enter") + description: qsTr("Send your message by pressing the enter key") + automaticCheck: false + onClicked: { + appSettings.sendByEnter = !checked + } + } + + TextSwitch { + width: parent.columnWidth + checked: appSettings.focusTextAreaOnChatOpen + text: qsTr("Focus text input on chat open") + description: qsTr("Focus the text input area when entering a chat") + automaticCheck: false + onClicked: { + appSettings.focusTextAreaOnChatOpen = !checked + } + } + + TextSwitch { + width: parent.columnWidth + checked: appSettings.focusTextAreaAfterSend + text: qsTr("Focus text input area after send") + description: qsTr("Focus the text input area after sending a message") + automaticCheck: false + onClicked: { + appSettings.focusTextAreaAfterSend = !checked + } + } + + TextSwitch { + width: parent.columnWidth + checked: appSettings.delayMessageRead + text: qsTr("Delay before marking messages as read") + description: qsTr("Fernschreiber will wait a bit before messages are marked as read") + automaticCheck: false + onClicked: { + appSettings.delayMessageRead = !checked + } + } + + TextSwitch { + width: parent.columnWidth + checked: appSettings.useOpenWith + text: qsTr("Open-with menu integration") + description: qsTr("Integrate Fernschreiber into open-with menu of Sailfish OS") + automaticCheck: false + onClicked: { + appSettings.useOpenWith = !checked + } + } + + ComboBox { + id: feedbackComboBox + width: parent.columnWidth + label: qsTr("Notification feedback") + description: qsTr("Use non-graphical feedback (sound, vibration) for notifications") + menu: ContextMenu { + id: feedbackMenu + x: 0 + width: feedbackComboBox.width + + MenuItem { + readonly property int value: AppSettings.NotificationFeedbackAll + text: qsTr("All events") + onClicked: { + appSettings.notificationFeedback = value + } + } + MenuItem { + readonly property int value: AppSettings.NotificationFeedbackNew + text: qsTr("Only new events") + onClicked: { + appSettings.notificationFeedback = value + } + } + MenuItem { + readonly property int value: AppSettings.NotificationFeedbackNone + text: qsTr("None") + onClicked: { + appSettings.notificationFeedback = value + } + } + } + + Component.onCompleted: updateFeedbackSelection() + + function updateFeedbackSelection() { + var menuItems = feedbackMenu.children + var n = menuItems.length + for (var i=0; i 0 + automaticCheck: false + onClicked: { + appSettings.notificationTurnsDisplayOn = !checked + } + Behavior on height { SmoothedAnimation { duration: 200 } } + } + + TextSwitch { + width: parent.columnWidth + checked: appSettings.notificationSoundsEnabled && enabled + text: qsTr("Enable notification sounds") + description: qsTr("When sounds are enabled, Fernschreiber will use the current Sailfish OS notification sound for chats, which can be configured in the system settings.") + enabled: appSettings.notificationFeedback !== AppSettings.NotificationFeedbackNone + height: enabled ? implicitHeight: 0 + clip: height < implicitHeight + visible: height > 0 + automaticCheck: false + onClicked: { + appSettings.notificationSoundsEnabled = !checked + } + Behavior on height { SmoothedAnimation { duration: 200 } } + } + + } + } +} diff --git a/qml/components/settingsPage/SettingsPrivacy.qml b/qml/components/settingsPage/SettingsPrivacy.qml new file mode 100644 index 0000000..40a2ca0 --- /dev/null +++ b/qml/components/settingsPage/SettingsPrivacy.qml @@ -0,0 +1,267 @@ +/* + Copyright (C) 2021 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Fernschreiber is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fernschreiber. If not, see . +*/ + +import QtQuick 2.6 +import Sailfish.Silica 1.0 +import WerkWolf.Fernschreiber 1.0 + +AccordionItem { + text: qsTr("Privacy") + Component { + Column { + bottomPadding: Theme.paddingMedium + Connections { + target: tdLibWrapper + onUserPrivacySettingUpdated: { + Debug.log("Received updated privacy setting: " + setting + ":" + rule); + switch (setting) { + case TelegramAPI.SettingAllowChatInvites: + allowChatInvitesComboBox.currentIndex = rule; + break; + case TelegramAPI.SettingAllowFindingByPhoneNumber: + allowFindingByPhoneNumberComboBox.currentIndex = rule; + break; + case TelegramAPI.SettingShowLinkInForwardedMessages: + showLinkInForwardedMessagesComboBox.currentIndex = rule; + break; + case TelegramAPI.SettingShowPhoneNumber: + showPhoneNumberComboBox.currentIndex = rule; + break; + case TelegramAPI.SettingShowProfilePhoto: + showProfilePhotoComboBox.currentIndex = rule; + break; + case TelegramAPI.SettingShowStatus: + showStatusComboBox.currentIndex = rule; + break; + } + } + } + ResponsiveGrid { + ComboBox { + id: allowChatInvitesComboBox + width: parent.columnWidth + label: qsTr("Allow chat invites") + description: qsTr("Privacy setting for managing whether you can be invited to chats.") + menu: ContextMenu { + x: 0 + width: allowChatInvitesComboBox.width + + MenuItem { + text: qsTr("Yes") + onClicked: { + tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingAllowChatInvites, TelegramAPI.RuleAllowAll); + } + } + MenuItem { + text: qsTr("Your contacts only") + onClicked: { + tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingAllowChatInvites, TelegramAPI.RuleAllowContacts); + } + } + MenuItem { + text: qsTr("No") + onClicked: { + tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingAllowChatInvites, TelegramAPI.RuleRestrictAll); + } + } + } + + Component.onCompleted: { + currentIndex = tdLibWrapper.getUserPrivacySettingRule(TelegramAPI.SettingAllowChatInvites); + } + } + + ComboBox { + id: allowFindingByPhoneNumberComboBox + width: parent.columnWidth + label: qsTr("Allow finding by phone number") + description: qsTr("Privacy setting for managing whether you can be found by your phone number.") + menu: ContextMenu { + x: 0 + width: allowFindingByPhoneNumberComboBox.width + + MenuItem { + text: qsTr("Yes") + onClicked: { + tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingAllowFindingByPhoneNumber, TelegramAPI.RuleAllowAll); + } + } + MenuItem { + text: qsTr("Your contacts only") + onClicked: { + tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingAllowFindingByPhoneNumber, TelegramAPI.RuleAllowContacts); + } + } + } + + Component.onCompleted: { + currentIndex = tdLibWrapper.getUserPrivacySettingRule(TelegramAPI.SettingAllowFindingByPhoneNumber); + } + } + + ComboBox { + id: showLinkInForwardedMessagesComboBox + width: parent.columnWidth + label: qsTr("Show link in forwarded messages") + description: qsTr("Privacy setting for managing whether a link to your account is included in forwarded messages.") + menu: ContextMenu { + x: 0 + width: showLinkInForwardedMessagesComboBox.width + + MenuItem { + text: qsTr("Yes") + onClicked: { + tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowLinkInForwardedMessages, TelegramAPI.RuleAllowAll); + } + } + MenuItem { + text: qsTr("Your contacts only") + onClicked: { + tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowLinkInForwardedMessages, TelegramAPI.RuleAllowContacts); + } + } + MenuItem { + text: qsTr("No") + onClicked: { + tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowLinkInForwardedMessages, TelegramAPI.RuleRestrictAll); + } + } + } + + Component.onCompleted: { + currentIndex = tdLibWrapper.getUserPrivacySettingRule(TelegramAPI.SettingShowLinkInForwardedMessages); + } + } + + ComboBox { + id: showPhoneNumberComboBox + width: parent.columnWidth + label: qsTr("Show phone number") + description: qsTr("Privacy setting for managing whether your phone number is visible.") + menu: ContextMenu { + x: 0 + width: showPhoneNumberComboBox.width + + MenuItem { + text: qsTr("Yes") + onClicked: { + tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowPhoneNumber, TelegramAPI.RuleAllowAll); + } + } + MenuItem { + text: qsTr("Your contacts only") + onClicked: { + tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowPhoneNumber, TelegramAPI.RuleAllowContacts); + } + } + MenuItem { + text: qsTr("No") + onClicked: { + tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowPhoneNumber, TelegramAPI.RuleRestrictAll); + } + } + } + + Component.onCompleted: { + currentIndex = tdLibWrapper.getUserPrivacySettingRule(TelegramAPI.SettingShowPhoneNumber); + } + } + + ComboBox { + id: showProfilePhotoComboBox + width: parent.columnWidth + label: qsTr("Show profile photo") + description: qsTr("Privacy setting for managing whether your profile photo is visible.") + menu: ContextMenu { + x: 0 + width: showProfilePhotoComboBox.width + + MenuItem { + text: qsTr("Yes") + onClicked: { + tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowProfilePhoto, TelegramAPI.RuleAllowAll); + } + } + MenuItem { + text: qsTr("Your contacts only") + onClicked: { + tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowProfilePhoto, TelegramAPI.RuleAllowContacts); + } + } + MenuItem { + text: qsTr("No") + onClicked: { + tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowProfilePhoto, TelegramAPI.RuleRestrictAll); + } + } + } + + Component.onCompleted: { + currentIndex = tdLibWrapper.getUserPrivacySettingRule(TelegramAPI.SettingShowProfilePhoto); + } + } + + ComboBox { + id: showStatusComboBox + width: parent.columnWidth + label: qsTr("Show status") + description: qsTr("Privacy setting for managing whether your online status is visible.") + menu: ContextMenu { + x: 0 + width: showStatusComboBox.width + + MenuItem { + text: qsTr("Yes") + onClicked: { + tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowStatus, TelegramAPI.RuleAllowAll); + } + } + MenuItem { + text: qsTr("Your contacts only") + onClicked: { + tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowStatus, TelegramAPI.RuleAllowContacts); + } + } + MenuItem { + text: qsTr("No") + onClicked: { + tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowStatus, TelegramAPI.RuleRestrictAll); + } + } + } + + Component.onCompleted: { + currentIndex = tdLibWrapper.getUserPrivacySettingRule(TelegramAPI.SettingShowStatus); + } + } + } + + TextSwitch { + checked: appSettings.allowInlineBotLocationAccess + text: qsTr("Allow sending Location to inline bots") + description: qsTr("Some inline bots request location data when using them") + automaticCheck: false + onClicked: { + appSettings.allowInlineBotLocationAccess = !checked + } + } + } + } + +} diff --git a/qml/components/settingsPage/SettingsStorage.qml b/qml/components/settingsPage/SettingsStorage.qml new file mode 100644 index 0000000..8423e0e --- /dev/null +++ b/qml/components/settingsPage/SettingsStorage.qml @@ -0,0 +1,51 @@ +/* + Copyright (C) 2021 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Fernschreiber is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fernschreiber. If not, see . +*/ + +import QtQuick 2.6 +import Sailfish.Silica 1.0 +import WerkWolf.Fernschreiber 1.0 + +AccordionItem { + text: qsTr("Storage") + Component { + ResponsiveGrid { + bottomPadding: Theme.paddingMedium + TextSwitch { + width: parent.columnWidth + checked: appSettings.onlineOnlyMode + text: qsTr("Enable online-only mode") + description: qsTr("Disables offline caching. Certain features may be limited or missing in this mode. Changes require a restart of Fernschreiber to take effect.") + automaticCheck: false + onClicked: { + appSettings.onlineOnlyMode = !checked + } + } + + TextSwitch { + width: parent.columnWidth + checked: appSettings.storageOptimizer + text: qsTr("Enable storage optimizer") + automaticCheck: false + onClicked: { + appSettings.storageOptimizer = !checked + } + } + } + } +} diff --git a/qml/components/settingsPage/SettingsUserProfile.qml b/qml/components/settingsPage/SettingsUserProfile.qml new file mode 100644 index 0000000..0b6f901 --- /dev/null +++ b/qml/components/settingsPage/SettingsUserProfile.qml @@ -0,0 +1,261 @@ +/* + Copyright (C) 2021 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Fernschreiber is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fernschreiber. If not, see . +*/ + +import QtQuick 2.6 +import Sailfish.Silica 1.0 +import Sailfish.Pickers 1.0 +import WerkWolf.Fernschreiber 1.0 +import "../" +import "../../pages/" +import "../../js/functions.js" as Functions + +AccordionItem { + text: qsTr("User Profile") + Component { + Column { + id: accordionContent + bottomPadding: Theme.paddingMedium + + readonly property var userInformation: tdLibWrapper.getUserInformation() + property bool uploadInProgress: false + + Component.onCompleted: { + tdLibWrapper.getUserProfilePhotos(userInformation.id, 100, 0); + } + + Connections { + target: tdLibWrapper + onOwnUserUpdated: { + firstNameEditArea.text = userInformation.first_name; + lastNameEditArea.text = userInformation.last_name; + userNameEditArea.text = userInformation.username; + } + onUserProfilePhotosReceived: { + if (extra === userInformation.id.toString()) { + imageContainer.thumbnailModel = photos; + } + } + onFileUpdated: { + if (uploadInProgress) { + profilePictureButtonColumn.visible = !fileInformation.remote.is_uploading_active; + uploadInProgress = fileInformation.remote.is_uploading_active; + if (!fileInformation.remote.is_uploading_active) { + uploadInProgress = false; + tdLibWrapper.getUserProfilePhotos(userInformation.id, 100, 0); + } + } + } + onOkReceived: { + if (request === "deleteProfilePhoto") { + tdLibWrapper.getUserProfilePhotos(userInformation.id, 100, 0); + } + if (request === "setProfilePhoto") { + tdLibWrapper.getUserProfilePhotos(userInformation.id, 100, 0); + profilePictureButtonColumn.visible = true; + uploadInProgress = false; + } + } + } + + ResponsiveGrid { + x: Theme.horizontalPageMargin + + InformationEditArea { + id: firstNameEditArea + visible: true + canEdit: true + headerText: qsTr("First Name", "first name of the logged-in profile - header") + text: userInformation.first_name + width: parent.columnWidth + headerLeftAligned: true + + onSaveButtonClicked: { + if(!editItem.errorHighlight) { + tdLibWrapper.setName(textValue, lastNameEditArea.text); + } else { + isEditing = true; + } + } + + onTextEdited: { + if(textValue.length > 0 && textValue.length < 65) { + editItem.errorHighlight = false; + editItem.label = ""; + editItem.placeholderText = ""; + } else { + editItem.label = qsTr("Enter 1-64 characters"); + editItem.placeholderText = editItem.label; + editItem.errorHighlight = true; + } + } + } + + InformationEditArea { + id: lastNameEditArea + visible: true + canEdit: true + headerText: qsTr("Last Name", "last name of the logged-in profile - header") + text: userInformation.last_name + width: parent.columnWidth + headerLeftAligned: true + + onSaveButtonClicked: { + if(!editItem.errorHighlight) { + tdLibWrapper.setName(firstNameEditArea.text, textValue); + } else { + isEditing = true; + } + } + + onTextEdited: { + if(textValue.length >= 0 && textValue.length < 65) { + editItem.errorHighlight = false; + editItem.label = ""; + editItem.placeholderText = ""; + } else { + editItem.label = qsTr("Enter 0-64 characters"); + editItem.placeholderText = editItem.label; + editItem.errorHighlight = true; + } + } + } + + InformationEditArea { + id: userNameEditArea + visible: true + canEdit: true + headerText: qsTr("Username", "user name of the logged-in profile - header") + text: userInformation.username + width: parent.columnWidth + headerLeftAligned: true + + onSaveButtonClicked: { + tdLibWrapper.setUsername(textValue); + } + } + + } + + SectionHeader { + horizontalAlignment: Text.AlignLeft + text: qsTr("Profile Pictures") + } + + Row { + width: parent.width - ( 2 * Theme.horizontalPageMargin ) + spacing: Theme.paddingMedium + + Item { + id: imageContainer + anchors.verticalCenter: parent.verticalCenter + width: parent.width / 2 + height: profilePictureLoader.height + property var thumbnailModel: ({}) + property bool thumbnailVisible: true + property bool thumbnailActive: thumbnailModel.length > 0 + property int thumbnailRadius: imageContainer.width / 2 + + Loader { + id: profilePictureLoader + active: imageContainer.thumbnailActive + asynchronous: true + width: Theme.itemSizeExtraLarge + height: Theme.itemSizeExtraLarge + anchors.horizontalCenter: parent.horizontalCenter + source: "../ProfilePictureList.qml" + } + + ProfileThumbnail { + id: chatPictureReplacement + visible: !profilePictureLoader.active + replacementStringHint: Functions.getUserName(accordionContent.userInformation) + radius: imageContainer.thumbnailRadius + anchors.horizontalCenter: parent.horizontalCenter + width: Theme.itemSizeExtraLarge + height: Theme.itemSizeExtraLarge + } + } + + Column { + id: profilePictureButtonColumn + spacing: Theme.paddingSmall + width: parent.width / 2 + + Button { + id: addProfilePictureButton + text: qsTr("Add Picture") + anchors { + horizontalCenter: parent.horizontalCenter + } + onClicked: { + pageStack.push(imagePickerPage); + } + } + + Button { + id: removeProfilePictureButton + text: qsTr("Delete Picture") + anchors { + horizontalCenter: parent.horizontalCenter + } + onClicked: { + var pictureIdForDeletion = imageContainer.thumbnailModel[profilePictureLoader.item.currentPictureIndex].id; + Remorse.popupAction(settingsPage, qsTr("Deleting profile picture"), function() { tdLibWrapper.deleteProfilePhoto(pictureIdForDeletion) }); + } + } + } + + Column { + id: uploadStatusColumn + visible: !profilePictureButtonColumn.visible + spacing: Theme.paddingMedium + width: parent.width / 2 + + Text { + id: uploadingText + font.pixelSize: Theme.fontSizeSmall + text: qsTr("Uploading...") + horizontalAlignment: Text.AlignHCenter + color: Theme.secondaryColor + width: parent.width + } + + BusyIndicator { + anchors.horizontalCenter: parent.horizontalCenter + running: uploadStatusColumn.visible + size: BusyIndicatorSize.Medium + } + + } + + } + + Component { + id: imagePickerPage + ImagePickerPage { + onSelectedContentPropertiesChanged: { + profilePictureButtonColumn.visible = false; + uploadInProgress = true; + tdLibWrapper.setProfilePhoto(selectedContentProperties.filePath); + } + } + } + } + } +} diff --git a/qml/pages/SettingsPage.qml b/qml/pages/SettingsPage.qml index 2796198..b1cf4f9 100644 --- a/qml/pages/SettingsPage.qml +++ b/qml/pages/SettingsPage.qml @@ -21,6 +21,7 @@ import Sailfish.Silica 1.0 import Sailfish.Pickers 1.0 import WerkWolf.Fernschreiber 1.0 import "../components" +import "../components/settingsPage" import "../js/functions.js" as Functions import "../js/debug.js" as Debug @@ -28,50 +29,6 @@ Page { id: settingsPage allowedOrientations: Orientation.All - readonly property bool landscapeLayout: settingsPage.isLandscape - readonly property var userInformation: tdLibWrapper.getUserInformation() - property bool uploadInProgress: false - - onStatusChanged: { - if (status === PageStatus.Active) { - tdLibWrapper.getUserProfilePhotos(userInformation.id, 100, 0); - } - } - - Connections { - target: tdLibWrapper - onOwnUserUpdated: { - firstNameEditArea.text = userInformation.first_name; - lastNameEditArea.text = userInformation.last_name; - userNameEditArea.text = userInformation.username; - } - onUserProfilePhotosReceived: { - if (extra === userInformation.id.toString()) { - imageContainer.thumbnailModel = photos; - } - } - onFileUpdated: { - if (uploadInProgress) { - profilePictureButtonColumn.visible = !fileInformation.remote.is_uploading_active; - uploadInProgress = fileInformation.remote.is_uploading_active; - if (!fileInformation.remote.is_uploading_active) { - uploadInProgress = false; - tdLibWrapper.getUserProfilePhotos(userInformation.id, 100, 0); - } - } - } - onOkReceived: { - if (request === "deleteProfilePhoto") { - tdLibWrapper.getUserProfilePhotos(userInformation.id, 100, 0); - } - if (request === "setProfilePhoto") { - tdLibWrapper.getUserProfilePhotos(userInformation.id, 100, 0); - profilePictureButtonColumn.visible = true; - uploadInProgress = false; - } - } - } - SilicaFlickable { id: settingsContainer contentHeight: column.height @@ -80,686 +37,19 @@ Page { Column { id: column width: settingsPage.width + bottomPadding: Theme.paddingLarge PageHeader { title: qsTr("Settings") } - SectionHeader { - text: qsTr("User Profile") - } - - Grid { - width: parent.width - ( 2 * Theme.horizontalPageMargin ) - columns: landscapeLayout ? 2 : 1 - columnSpacing: Theme.paddingLarge - anchors.horizontalCenter: parent.horizontalCenter - - readonly property real columnWidth: width/columns - - InformationEditArea { - id: firstNameEditArea - visible: true - canEdit: true - headerText: qsTr("First Name", "first name of the logged-in profile - header") - text: userInformation.first_name - width: parent.columnWidth - headerLeftAligned: true - - onSaveButtonClicked: { - if(!editItem.errorHighlight) { - tdLibWrapper.setName(textValue, lastNameEditArea.text); - } else { - isEditing = true; - } - } - - onTextEdited: { - if(textValue.length > 0 && textValue.length < 65) { - editItem.errorHighlight = false; - editItem.label = ""; - editItem.placeholderText = ""; - } else { - editItem.label = qsTr("Enter 1-64 characters"); - editItem.placeholderText = editItem.label; - editItem.errorHighlight = true; - } - } - } - - InformationEditArea { - id: lastNameEditArea - visible: true - canEdit: true - headerText: qsTr("Last Name", "last name of the logged-in profile - header") - text: userInformation.last_name - width: parent.columnWidth - headerLeftAligned: true - - onSaveButtonClicked: { - if(!editItem.errorHighlight) { - tdLibWrapper.setName(firstNameEditArea.text, textValue); - } else { - isEditing = true; - } - } - - onTextEdited: { - if(textValue.length >= 0 && textValue.length < 65) { - editItem.errorHighlight = false; - editItem.label = ""; - editItem.placeholderText = ""; - } else { - editItem.label = qsTr("Enter 0-64 characters"); - editItem.placeholderText = editItem.label; - editItem.errorHighlight = true; - } - } - } - - InformationEditArea { - id: userNameEditArea - visible: true - canEdit: true - headerText: qsTr("Username", "user name of the logged-in profile - header") - text: userInformation.username - width: parent.columnWidth - headerLeftAligned: true - - onSaveButtonClicked: { - tdLibWrapper.setUsername(textValue); - } - } - - } - - SectionHeader { - horizontalAlignment: Text.AlignLeft - text: qsTr("Profile Pictures") - } - - Row { - width: parent.width - ( 2 * Theme.horizontalPageMargin ) - spacing: Theme.paddingMedium - - Item { - id: imageContainer - anchors.verticalCenter: parent.verticalCenter - width: parent.width / 2 - height: profilePictureLoader.height - property var thumbnailModel: ({}) - property bool thumbnailVisible: true - property bool thumbnailActive: thumbnailModel.length > 0 - property int thumbnailRadius: imageContainer.width / 2 - - Loader { - id: profilePictureLoader - active: imageContainer.thumbnailActive - asynchronous: true - width: Theme.itemSizeExtraLarge - height: Theme.itemSizeExtraLarge - anchors.horizontalCenter: parent.horizontalCenter - source: "../components/ProfilePictureList.qml" - } - - ProfileThumbnail { - id: chatPictureReplacement - visible: !profilePictureLoader.active - replacementStringHint: Functions.getUserName(settingsPage.userInformation) - radius: imageContainer.thumbnailRadius - anchors.horizontalCenter: parent.horizontalCenter - width: Theme.itemSizeExtraLarge - height: Theme.itemSizeExtraLarge - } - } - - Column { - id: profilePictureButtonColumn - spacing: Theme.paddingSmall - width: parent.width / 2 - - Button { - id: addProfilePictureButton - text: qsTr("Add Picture") - anchors { - horizontalCenter: parent.horizontalCenter - } - onClicked: { - pageStack.push(imagePickerPage); - } - } - - Button { - id: removeProfilePictureButton - text: qsTr("Delete Picture") - anchors { - horizontalCenter: parent.horizontalCenter - } - onClicked: { - var pictureIdForDeletion = imageContainer.thumbnailModel[profilePictureLoader.item.currentPictureIndex].id; - Remorse.popupAction(settingsPage, qsTr("Deleting profile picture"), function() { tdLibWrapper.deleteProfilePhoto(pictureIdForDeletion) }); - } - } - } - - Column { - id: uploadStatusColumn - visible: !profilePictureButtonColumn.visible - spacing: Theme.paddingMedium - width: parent.width / 2 - - Text { - id: uploadingText - font.pixelSize: Theme.fontSizeSmall - text: qsTr("Uploading...") - horizontalAlignment: Text.AlignHCenter - color: Theme.secondaryColor - width: parent.width - } - - BusyIndicator { - anchors.horizontalCenter: parent.horizontalCenter - running: uploadStatusColumn.visible - size: BusyIndicatorSize.Medium - } - - } - - } - - Component { - id: imagePickerPage - ImagePickerPage { - onSelectedContentPropertiesChanged: { - profilePictureButtonColumn.visible = false; - uploadInProgress = true; - tdLibWrapper.setProfilePhoto(selectedContentProperties.filePath); - } - } - } - - SectionHeader { - horizontalAlignment: Text.AlignLeft - text: qsTr("Privacy") - } - - Grid { - width: parent.width - columns: landscapeLayout ? 2 : 1 - anchors.horizontalCenter: parent.horizontalCenter - - readonly property real columnWidth: width/columns - - Connections { - target: tdLibWrapper - onUserPrivacySettingUpdated: { - Debug.log("Received updated privacy setting: " + setting + ":" + rule); - switch (setting) { - case TelegramAPI.SettingAllowChatInvites: - allowChatInvitesComboBox.currentIndex = rule; - break; - case TelegramAPI.SettingAllowFindingByPhoneNumber: - allowFindingByPhoneNumberComboBox.currentIndex = rule; - break; - case TelegramAPI.SettingShowLinkInForwardedMessages: - showLinkInForwardedMessagesComboBox.currentIndex = rule; - break; - case TelegramAPI.SettingShowPhoneNumber: - showPhoneNumberComboBox.currentIndex = rule; - break; - case TelegramAPI.SettingShowProfilePhoto: - showProfilePhotoComboBox.currentIndex = rule; - break; - case TelegramAPI.SettingShowStatus: - showStatusComboBox.currentIndex = rule; - break; - } - } - } - - ComboBox { - id: allowChatInvitesComboBox - width: parent.columnWidth - label: qsTr("Allow chat invites") - description: qsTr("Privacy setting for managing whether you can be invited to chats.") - menu: ContextMenu { - x: 0 - width: allowChatInvitesComboBox.width - - MenuItem { - text: qsTr("Yes") - onClicked: { - tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingAllowChatInvites, TelegramAPI.RuleAllowAll); - } - } - MenuItem { - text: qsTr("Your contacts only") - onClicked: { - tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingAllowChatInvites, TelegramAPI.RuleAllowContacts); - } - } - MenuItem { - text: qsTr("No") - onClicked: { - tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingAllowChatInvites, TelegramAPI.RuleRestrictAll); - } - } - } - - Component.onCompleted: { - currentIndex = tdLibWrapper.getUserPrivacySettingRule(TelegramAPI.SettingAllowChatInvites); - } - } - - ComboBox { - id: allowFindingByPhoneNumberComboBox - width: parent.columnWidth - label: qsTr("Allow finding by phone number") - description: qsTr("Privacy setting for managing whether you can be found by your phone number.") - menu: ContextMenu { - x: 0 - width: allowFindingByPhoneNumberComboBox.width - - MenuItem { - text: qsTr("Yes") - onClicked: { - tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingAllowFindingByPhoneNumber, TelegramAPI.RuleAllowAll); - } - } - MenuItem { - text: qsTr("Your contacts only") - onClicked: { - tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingAllowFindingByPhoneNumber, TelegramAPI.RuleAllowContacts); - } - } - } - - Component.onCompleted: { - currentIndex = tdLibWrapper.getUserPrivacySettingRule(TelegramAPI.SettingAllowFindingByPhoneNumber); - } - } - - ComboBox { - id: showLinkInForwardedMessagesComboBox - width: parent.columnWidth - label: qsTr("Show link in forwarded messages") - description: qsTr("Privacy setting for managing whether a link to your account is included in forwarded messages.") - menu: ContextMenu { - x: 0 - width: showLinkInForwardedMessagesComboBox.width - - MenuItem { - text: qsTr("Yes") - onClicked: { - tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowLinkInForwardedMessages, TelegramAPI.RuleAllowAll); - } - } - MenuItem { - text: qsTr("Your contacts only") - onClicked: { - tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowLinkInForwardedMessages, TelegramAPI.RuleAllowContacts); - } - } - MenuItem { - text: qsTr("No") - onClicked: { - tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowLinkInForwardedMessages, TelegramAPI.RuleRestrictAll); - } - } - } - - Component.onCompleted: { - currentIndex = tdLibWrapper.getUserPrivacySettingRule(TelegramAPI.SettingShowLinkInForwardedMessages); - } - } - - ComboBox { - id: showPhoneNumberComboBox - width: parent.columnWidth - label: qsTr("Show phone number") - description: qsTr("Privacy setting for managing whether your phone number is visible.") - menu: ContextMenu { - x: 0 - width: showPhoneNumberComboBox.width - - MenuItem { - text: qsTr("Yes") - onClicked: { - tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowPhoneNumber, TelegramAPI.RuleAllowAll); - } - } - MenuItem { - text: qsTr("Your contacts only") - onClicked: { - tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowPhoneNumber, TelegramAPI.RuleAllowContacts); - } - } - MenuItem { - text: qsTr("No") - onClicked: { - tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowPhoneNumber, TelegramAPI.RuleRestrictAll); - } - } - } - - Component.onCompleted: { - currentIndex = tdLibWrapper.getUserPrivacySettingRule(TelegramAPI.SettingShowPhoneNumber); - } - } - - ComboBox { - id: showProfilePhotoComboBox - width: parent.columnWidth - label: qsTr("Show profile photo") - description: qsTr("Privacy setting for managing whether your profile photo is visible.") - menu: ContextMenu { - x: 0 - width: showProfilePhotoComboBox.width - - MenuItem { - text: qsTr("Yes") - onClicked: { - tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowProfilePhoto, TelegramAPI.RuleAllowAll); - } - } - MenuItem { - text: qsTr("Your contacts only") - onClicked: { - tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowProfilePhoto, TelegramAPI.RuleAllowContacts); - } - } - MenuItem { - text: qsTr("No") - onClicked: { - tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowProfilePhoto, TelegramAPI.RuleRestrictAll); - } - } - } - - Component.onCompleted: { - currentIndex = tdLibWrapper.getUserPrivacySettingRule(TelegramAPI.SettingShowProfilePhoto); - } - } - - ComboBox { - id: showStatusComboBox - width: parent.columnWidth - label: qsTr("Show status") - description: qsTr("Privacy setting for managing whether your online status is visible.") - menu: ContextMenu { - x: 0 - width: showStatusComboBox.width - - MenuItem { - text: qsTr("Yes") - onClicked: { - tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowStatus, TelegramAPI.RuleAllowAll); - } - } - MenuItem { - text: qsTr("Your contacts only") - onClicked: { - tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowStatus, TelegramAPI.RuleAllowContacts); - } - } - MenuItem { - text: qsTr("No") - onClicked: { - tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowStatus, TelegramAPI.RuleRestrictAll); - } - } - } - - Component.onCompleted: { - currentIndex = tdLibWrapper.getUserPrivacySettingRule(TelegramAPI.SettingShowStatus); - } - } - - } - - TextSwitch { - checked: appSettings.allowInlineBotLocationAccess - text: qsTr("Allow sending Location to inline bots") - description: qsTr("Some inline bots request location data when using them") - automaticCheck: false - onClicked: { - appSettings.allowInlineBotLocationAccess = !checked - } - } - - SectionHeader { - text: qsTr("Behavior") - } - - Grid { - width: parent.width - columns: landscapeLayout ? 2 : 1 - - readonly property real columnWidth: width/columns - - TextSwitch { - width: parent.columnWidth - checked: appSettings.sendByEnter - text: qsTr("Send message by enter") - description: qsTr("Send your message by pressing the enter key") - automaticCheck: false - onClicked: { - appSettings.sendByEnter = !checked - } - } - - TextSwitch { - width: parent.columnWidth - checked: appSettings.focusTextAreaOnChatOpen - text: qsTr("Focus text input on chat open") - description: qsTr("Focus the text input area when entering a chat") - automaticCheck: false - onClicked: { - appSettings.focusTextAreaOnChatOpen = !checked - } - } - - TextSwitch { - width: parent.columnWidth - checked: appSettings.focusTextAreaAfterSend - text: qsTr("Focus text input area after send") - description: qsTr("Focus the text input area after sending a message") - automaticCheck: false - onClicked: { - appSettings.focusTextAreaAfterSend = !checked - } - } - - TextSwitch { - width: parent.columnWidth - checked: appSettings.delayMessageRead - text: qsTr("Delay before marking messages as read") - description: qsTr("Fernschreiber will wait a bit before messages are marked as read") - automaticCheck: false - onClicked: { - appSettings.delayMessageRead = !checked - } - } - - TextSwitch { - width: parent.columnWidth - checked: appSettings.useOpenWith - text: qsTr("Open-with menu integration") - description: qsTr("Integrate Fernschreiber into open-with menu of Sailfish OS") - automaticCheck: false - onClicked: { - appSettings.useOpenWith = !checked - } - } - - ComboBox { - id: feedbackComboBox - width: parent.columnWidth - label: qsTr("Notification feedback") - description: qsTr("Use non-graphical feedback (sound, vibration) for notifications") - menu: ContextMenu { - id: feedbackMenu - x: 0 - width: feedbackComboBox.width - - MenuItem { - readonly property int value: AppSettings.NotificationFeedbackAll - text: qsTr("All events") - onClicked: { - appSettings.notificationFeedback = value - } - } - MenuItem { - readonly property int value: AppSettings.NotificationFeedbackNew - text: qsTr("Only new events") - onClicked: { - appSettings.notificationFeedback = value - } - } - MenuItem { - readonly property int value: AppSettings.NotificationFeedbackNone - text: qsTr("None") - onClicked: { - appSettings.notificationFeedback = value - } - } - } - - Component.onCompleted: updateFeedbackSelection() - - function updateFeedbackSelection() { - var menuItems = feedbackMenu.children - var n = menuItems.length - for (var i=0; i 0 - automaticCheck: false - onClicked: { - appSettings.notificationTurnsDisplayOn = !checked - } - Behavior on height { SmoothedAnimation { duration: 200 } } - } - - TextSwitch { - width: parent.columnWidth - checked: appSettings.notificationSoundsEnabled && enabled - text: qsTr("Enable notification sounds") - description: qsTr("When sounds are enabled, Fernschreiber will use the current Sailfish OS notification sound for chats, which can be configured in the system settings.") - enabled: appSettings.notificationFeedback !== AppSettings.NotificationFeedbackNone - height: enabled ? implicitHeight: 0 - clip: height < implicitHeight - visible: height > 0 - automaticCheck: false - onClicked: { - appSettings.notificationSoundsEnabled = !checked - } - Behavior on height { SmoothedAnimation { duration: 200 } } - } - - } - - SectionHeader { - text: qsTr("Appearance") - } - - Grid { - width: parent.width - columns: landscapeLayout ? 2 : 1 - - readonly property real columnWidth: width/columns - - TextSwitch { - id: stickersAsEmojisTextSwitch - width: parent.columnWidth - checked: appSettings.showStickersAsEmojis - text: qsTr("Show stickers as emojis") - description: qsTr("Only display emojis instead of the actual stickers") - automaticCheck: false - onClicked: { - appSettings.showStickersAsEmojis = !checked - } - } - - TextSwitch { - width: parent.columnWidth - checked: appSettings.showStickersAsImages - text: qsTr("Show stickers as images") - description: qsTr("Show background for stickers and align them centrally like images") - automaticCheck: false - onClicked: { - appSettings.showStickersAsImages = !checked - } - enabled: !stickersAsEmojisTextSwitch.checked - } - - TextSwitch { - width: parent.columnWidth - checked: appSettings.animateStickers - text: qsTr("Animate stickers") - automaticCheck: false - onClicked: { - appSettings.animateStickers = !checked - } - enabled: !stickersAsEmojisTextSwitch.checked - } - } - - SectionHeader { - text: qsTr("Storage") - } - - Grid { - width: parent.width - columns: landscapeLayout ? 2 : 1 - - readonly property real columnWidth: width/columns - - TextSwitch { - width: parent.columnWidth - checked: appSettings.onlineOnlyMode - text: qsTr("Enable online-only mode") - description: qsTr("Disables offline caching. Certain features may be limited or missing in this mode. Changes require a restart of Fernschreiber to take effect.") - automaticCheck: false - onClicked: { - appSettings.onlineOnlyMode = !checked - } - } - - TextSwitch { - width: parent.columnWidth - checked: appSettings.storageOptimizer - text: qsTr("Enable storage optimizer") - automaticCheck: false - onClicked: { - appSettings.storageOptimizer = !checked - } - } - } - - Item { - width: 1 - height: Theme.paddingLarge // Some space at the bottom + Accordion { + flickable: settingsContainer + SettingsUserProfile { expanded: true; asynchronous: false } + SettingsPrivacy {} + SettingsBehavior {} + SettingsAppearance {} + SettingsStorage {} } }