Compare commits
21 Commits
work/tfell
...
work/purpo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a27a1e70f | ||
|
|
f2cf82ee8e | ||
|
|
a146fab5a0 | ||
|
|
fb6745b49a | ||
|
|
6c3ae87340 | ||
|
|
6afeaf1619 | ||
|
|
890860df92 | ||
|
|
6b8358874a | ||
|
|
fc9f37d4a4 | ||
|
|
48e410196c | ||
|
|
65cc392805 | ||
|
|
a6dd5b9a57 | ||
|
|
1d7c20e1c7 | ||
|
|
22609b21df | ||
|
|
6c5ca0ac9d | ||
|
|
b22ebf3671 | ||
|
|
ec1cc34855 | ||
|
|
a5aafde331 | ||
|
|
d42ad85b30 | ||
|
|
8648b4a3bf | ||
|
|
bdca636fb8 |
@@ -79,6 +79,7 @@ MouseArea {
|
|||||||
id: replyText
|
id: replyText
|
||||||
textMessage: reply.display
|
textMessage: reply.display
|
||||||
textFormat: Text.RichText
|
textFormat: Text.RichText
|
||||||
|
hasContextMenu: false
|
||||||
width: Math.min(implicitWidth, bubbleMaxWidth - Kirigami.Units.largeSpacing * 3)
|
width: Math.min(implicitWidth, bubbleMaxWidth - Kirigami.Units.largeSpacing * 3)
|
||||||
x: Kirigami.Units.smallSpacing * 3 + replyAvatar.width
|
x: Kirigami.Units.smallSpacing * 3 + replyAvatar.width
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,17 @@ TextEdit {
|
|||||||
property bool isEmote: false
|
property bool isEmote: false
|
||||||
property string textMessage: model.display
|
property string textMessage: model.display
|
||||||
property bool spoilerRevealed: !hasSpoiler.test(textMessage)
|
property bool spoilerRevealed: !hasSpoiler.test(textMessage)
|
||||||
|
|
||||||
|
property bool hasContextMenu: true
|
||||||
|
|
||||||
|
signal requestOpenMessageContext()
|
||||||
|
|
||||||
ListView.onReused: Qt.binding(() => !hasSpoiler.test(textMessage))
|
ListView.onReused: Qt.binding(() => !hasSpoiler.test(textMessage))
|
||||||
|
|
||||||
|
Layout.fillWidth: Config.compactLayout
|
||||||
|
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||||
|
Layout.leftMargin: Config.showAvatarInTimeline ? Kirigami.Units.largeSpacing : 0
|
||||||
|
|
||||||
text: "<style>
|
text: "<style>
|
||||||
table {
|
table {
|
||||||
width:100%;
|
width:100%;
|
||||||
@@ -53,8 +62,6 @@ a{
|
|||||||
wrapMode: Text.Wrap
|
wrapMode: Text.Wrap
|
||||||
textFormat: Text.RichText
|
textFormat: Text.RichText
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
onLinkActivated: RoomManager.openResource(link)
|
onLinkActivated: RoomManager.openResource(link)
|
||||||
onHoveredLinkChanged: if (hoveredLink.length > 0) {
|
onHoveredLinkChanged: if (hoveredLink.length > 0) {
|
||||||
applicationWindow().hoverLinkIndicator.text = hoveredLink;
|
applicationWindow().hoverLinkIndicator.text = hoveredLink;
|
||||||
@@ -70,4 +77,16 @@ a{
|
|||||||
enabled: !parent.hoveredLink && !spoilerRevealed
|
enabled: !parent.hoveredLink && !spoilerRevealed
|
||||||
onTapped: spoilerRevealed = true
|
onTapped: spoilerRevealed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TapHandler {
|
||||||
|
acceptedButtons: Qt.RightButton
|
||||||
|
onTapped: openMessageContext(model, parent.selectedText)
|
||||||
|
enabled: hasContextMenu
|
||||||
|
}
|
||||||
|
|
||||||
|
TapHandler {
|
||||||
|
acceptedButtons: Qt.LeftButton
|
||||||
|
onLongPressed: requestOpenMessageContext()
|
||||||
|
enabled: hasContextMenu
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,7 @@ Kirigami.OverlaySheet {
|
|||||||
|
|
||||||
parent: applicationWindow().overlay
|
parent: applicationWindow().overlay
|
||||||
|
|
||||||
header: Kirigami.Heading {
|
title: i18n("Create a Room")
|
||||||
text: i18n("Create a Room")
|
|
||||||
}
|
|
||||||
|
|
||||||
contentItem: Kirigami.FormLayout {
|
contentItem: Kirigami.FormLayout {
|
||||||
TextField {
|
TextField {
|
||||||
|
|||||||
@@ -1,206 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2019-2020 Black Hat <bhat@encom.eu.org>
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
|
||||||
|
|
||||||
import QtQuick 2.15
|
|
||||||
import QtQuick.Controls 2.15
|
|
||||||
import QtQuick.Layouts 1.15
|
|
||||||
import org.kde.kirigami 2.15 as Kirigami
|
|
||||||
|
|
||||||
import org.kde.neochat 1.0
|
|
||||||
import NeoChat.Component 1.0
|
|
||||||
|
|
||||||
Kirigami.OverlaySheet {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property var room
|
|
||||||
|
|
||||||
readonly property bool canChangeAvatar: room.canSendState("m.room.avatar")
|
|
||||||
readonly property bool canChangeName: room.canSendState("m.room.name")
|
|
||||||
readonly property bool canChangeTopic: room.canSendState("m.room.topic")
|
|
||||||
readonly property bool canChangeCanonicalAlias: room.canSendState("m.room.canonical_alias")
|
|
||||||
|
|
||||||
parent: applicationWindow().overlay
|
|
||||||
|
|
||||||
|
|
||||||
header: Kirigami.Heading {
|
|
||||||
text: i18nc("%1 is the room name", "Room Settings - %1", room.displayName)
|
|
||||||
elide: Text.ElideRight
|
|
||||||
}
|
|
||||||
|
|
||||||
contentItem: ColumnLayout {
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
spacing: 16
|
|
||||||
|
|
||||||
Kirigami.Avatar {
|
|
||||||
Layout.preferredWidth: 72
|
|
||||||
Layout.preferredHeight: 72
|
|
||||||
Layout.alignment: Qt.AlignTop
|
|
||||||
|
|
||||||
name: room.name
|
|
||||||
source: room.avatarMediaId ? ("image://mxc/" + room.avatarMediaId) : ""
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
enabled: canChangeAvatar
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
var fileDialog = openFileDialog.createObject(ApplicationWindow.overlay)
|
|
||||||
|
|
||||||
fileDialog.chosen.connect(function(path) {
|
|
||||||
if (!path) return
|
|
||||||
|
|
||||||
room.changeAvatar(path)
|
|
||||||
})
|
|
||||||
|
|
||||||
fileDialog.open()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Kirigami.FormLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
TextField {
|
|
||||||
id: roomNameField
|
|
||||||
text: room.name
|
|
||||||
Kirigami.FormData.label: i18n("Room Name:")
|
|
||||||
enabled: canChangeName
|
|
||||||
}
|
|
||||||
|
|
||||||
TextArea {
|
|
||||||
id: roomTopicField
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: room.topic
|
|
||||||
Kirigami.FormData.label: i18n("Room topic:")
|
|
||||||
enabled: canChangeTopic
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
Layout.alignment: Qt.AlignRight
|
|
||||||
|
|
||||||
visible: canChangeName || canChangeTopic
|
|
||||||
|
|
||||||
text: i18n("Save")
|
|
||||||
highlighted: true
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
if (room.name != roomNameField.text) {
|
|
||||||
room.setName(roomNameField.text)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (room.topic != roomTopicField.text) {
|
|
||||||
room.setTopic(roomTopicField.text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Kirigami.Separator {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
visible: canonicalAliasComboBox.visible || altAlias.visible
|
|
||||||
}
|
|
||||||
|
|
||||||
ComboBox {
|
|
||||||
id: canonicalAliasComboBox
|
|
||||||
visible: room.aliases && room.aliases.length
|
|
||||||
Kirigami.FormData.label: i18n("Canonical Alias:")
|
|
||||||
popup.z: 999; // HACK This is an absolute hack, but combos inside OverlaySheets have their popups show up underneath, because of fun z ordering stuff
|
|
||||||
|
|
||||||
enabled: canChangeCanonicalAlias
|
|
||||||
|
|
||||||
model: room.aliases
|
|
||||||
|
|
||||||
currentIndex: room.aliases.indexOf(room.canonicalAlias)
|
|
||||||
onCurrentIndexChanged: {
|
|
||||||
if (room.canonicalAlias != room.aliases[currentIndex]) {
|
|
||||||
room.setCanonicalAlias(room.aliases[currentIndex])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
id: altAlias
|
|
||||||
Kirigami.FormData.label: i18n("Other Aliases:")
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
visible: room.altAliases && room.altAliases.length
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: room.altAliases
|
|
||||||
|
|
||||||
delegate: RowLayout {
|
|
||||||
Layout.maximumWidth: parent.width
|
|
||||||
|
|
||||||
Label {
|
|
||||||
text: modelData
|
|
||||||
}
|
|
||||||
|
|
||||||
ToolButton {
|
|
||||||
icon.name: ""
|
|
||||||
onClicked: room.removeLocalAlias(modelData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Kirigami.Separator {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
visible: next.visible || prev.visible
|
|
||||||
}
|
|
||||||
|
|
||||||
Control {
|
|
||||||
id: next
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
visible: room.predecessorId && room.connection.room(room.predecessorId)
|
|
||||||
|
|
||||||
padding: Kirigami.Units.largeSpacing
|
|
||||||
|
|
||||||
contentItem: Kirigami.InlineMessage {
|
|
||||||
text: i18n("This room continues another conversation.")
|
|
||||||
actions: Kirigami.Action {
|
|
||||||
text: i18n("See older messages...")
|
|
||||||
onTriggered: {
|
|
||||||
roomListForm.enteredRoom = Controller.activeConnection.room(room.predecessorId)
|
|
||||||
root.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Control {
|
|
||||||
id: prev
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
visible: room.successorId && room.connection.room(room.successorId)
|
|
||||||
|
|
||||||
padding: Kirigami.Units.largeSpacing
|
|
||||||
|
|
||||||
contentItem: Kirigami.InlineMessage {
|
|
||||||
text: i18n("This room has been replaced.")
|
|
||||||
actions: Kirigami.Action {
|
|
||||||
text: i18n("See new room...")
|
|
||||||
onTriggered: {
|
|
||||||
roomListForm.enteredRoom = Controller.activeConnection.room(room.successorId)
|
|
||||||
root.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Component {
|
|
||||||
id: openFileDialog
|
|
||||||
|
|
||||||
OpenFileDialog {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -27,13 +27,7 @@ Kirigami.OverlaySheet {
|
|||||||
rightPadding: 0
|
rightPadding: 0
|
||||||
topPadding: 0
|
topPadding: 0
|
||||||
|
|
||||||
header: Kirigami.Heading {
|
title: i18nc("@title:menu Account detail dialog", "Account detail")
|
||||||
id: heading
|
|
||||||
text: i18nc("@title:menu Account detail dialog", "Account detail")
|
|
||||||
elide: Text.ElideRight
|
|
||||||
QQC2.ToolTip.visible: truncated && hovered
|
|
||||||
QQC2.ToolTip.text: text
|
|
||||||
}
|
|
||||||
|
|
||||||
contentItem: ColumnLayout {
|
contentItem: ColumnLayout {
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
module NeoChat.Dialog
|
module NeoChat.Dialog
|
||||||
RoomSettingsDialog 1.0 RoomSettingsDialog.qml
|
|
||||||
UserDetailDialog 1.0 UserDetailDialog.qml
|
UserDetailDialog 1.0 UserDetailDialog.qml
|
||||||
LoginDialog 1.0 LoginDialog.qml
|
LoginDialog 1.0 LoginDialog.qml
|
||||||
CreateRoomDialog 1.0 CreateRoomDialog.qml
|
CreateRoomDialog 1.0 CreateRoomDialog.qml
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ Labs.MenuBar {
|
|||||||
text: i18nc("menu", "Preferences…")
|
text: i18nc("menu", "Preferences…")
|
||||||
|
|
||||||
shortcut: StandardKey.Preferences
|
shortcut: StandardKey.Preferences
|
||||||
onTriggered: pushReplaceLayer("qrc:/imports/NeoChat/Page/SettingsPage.qml")
|
onTriggered: pageStack.pushDialogLayer("qrc:/imports/NeoChat/Settings/SettingsPage.qml")
|
||||||
}
|
}
|
||||||
Labs.MenuItem {
|
Labs.MenuItem {
|
||||||
text: i18nc("menu", "Quit NeoChat")
|
text: i18nc("menu", "Quit NeoChat")
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
import QtQuick 2.15
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.15
|
import QtQuick.Controls 2.15
|
||||||
|
|
||||||
|
import org.kde.kirigami 2.19 as Kirigami
|
||||||
|
|
||||||
import org.kde.neochat 1.0
|
import org.kde.neochat 1.0
|
||||||
import NeoChat.Page 1.0
|
import NeoChat.Page 1.0
|
||||||
|
|
||||||
@@ -16,11 +18,15 @@ Menu {
|
|||||||
property var room
|
property var room
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
|
id: newWindow
|
||||||
text: i18n("Open in new window")
|
text: i18n("Open in new window")
|
||||||
onTriggered: RoomManager.openWindow(room);
|
onTriggered: RoomManager.openWindow(room);
|
||||||
|
visible: !Kirigami.Settings.isMobile
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuSeparator {}
|
MenuSeparator {
|
||||||
|
visible: newWindow.visible
|
||||||
|
}
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: room.isFavourite ? i18n("Remove from Favourites") : i18n("Add to Favourites")
|
text: room.isFavourite ? i18n("Remove from Favourites") : i18n("Add to Favourites")
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ Loader {
|
|||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
text: i18n("Copy")
|
text: i18n("Copy")
|
||||||
icon.name: "edit-copy"
|
icon.name: "edit-copy"
|
||||||
onTriggered: Clipboard.saveText(message)
|
onTriggered: Clipboard.saveText(loadRoot.selectedText === "" ? loadRoot.message : loadRoot.selectedText)
|
||||||
},
|
},
|
||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
text: i18n("View Source")
|
text: i18n("View Source")
|
||||||
|
|||||||
@@ -12,9 +12,7 @@ Kirigami.OverlaySheet {
|
|||||||
|
|
||||||
property string sourceText
|
property string sourceText
|
||||||
|
|
||||||
header: Kirigami.Heading {
|
title: i18n("Message Source")
|
||||||
text: i18n("Message Source")
|
|
||||||
}
|
|
||||||
|
|
||||||
TextArea {
|
TextArea {
|
||||||
id: sourceTextArea
|
id: sourceTextArea
|
||||||
|
|||||||
@@ -1,13 +1,20 @@
|
|||||||
// SPDX-FileCopyrightText: 2020 Carl Schwan <carl@carlschwan.eu>
|
// SPDX-FileCopyrightText: 2020 Carl Schwan <carl@carlschwan.eu>
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
import QtQuick.Controls 2.12 as QQC2
|
import QtQuick.Controls 2.12 as QQC2
|
||||||
import org.kde.kirigami 2.12 as Kirigami
|
import org.kde.kirigami 2.12 as Kirigami
|
||||||
|
|
||||||
Kirigami.Page {
|
Kirigami.Page {
|
||||||
title: i18n("Loading")
|
title: i18n("Loading")
|
||||||
|
|
||||||
QQC2.BusyIndicator {
|
Kirigami.PlaceholderMessage {
|
||||||
|
id: loadingIndicator
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
text: i18n("Loading")
|
||||||
|
QQC2.BusyIndicator {
|
||||||
|
running: loadingIndicator.visible
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -229,7 +229,6 @@ Kirigami.ScrollablePage {
|
|||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: messageListView
|
id: messageListView
|
||||||
pixelAligned: true
|
|
||||||
visible: !invitation.visible
|
visible: !invitation.visible
|
||||||
|
|
||||||
readonly property int largestVisibleIndex: count > 0 ? indexAt(contentX + (width / 2), contentY + height - 1) : -1
|
readonly property int largestVisibleIndex: count > 0 ? indexAt(contentX + (width / 2), contentY + height - 1) : -1
|
||||||
@@ -372,18 +371,8 @@ Kirigami.ScrollablePage {
|
|||||||
|
|
||||||
innerObject: TextDelegate {
|
innerObject: TextDelegate {
|
||||||
isEmote: true
|
isEmote: true
|
||||||
Layout.fillWidth: Config.compactLayout
|
|
||||||
Layout.maximumWidth: emoteContainer.bubbleMaxWidth
|
Layout.maximumWidth: emoteContainer.bubbleMaxWidth
|
||||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
onRequestOpenMessageContext: openMessageContext(model, parent.selectedText)
|
||||||
Layout.leftMargin: Config.showAvatarInTimeline ? Kirigami.Units.largeSpacing : 0
|
|
||||||
TapHandler {
|
|
||||||
acceptedButtons: Qt.RightButton
|
|
||||||
onTapped: openMessageContext(author, model.message, eventId, toolTip, eventType, model.formattedBody, parent.selectedText)
|
|
||||||
}
|
|
||||||
TapHandler {
|
|
||||||
acceptedButtons: Qt.LeftButton
|
|
||||||
onLongPressed: openMessageContext(author, model.message, eventId, toolTip, eventType, model.formattedBody, parent.selectedText)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -398,18 +387,8 @@ Kirigami.ScrollablePage {
|
|||||||
hoverComponent: hoverActions
|
hoverComponent: hoverActions
|
||||||
|
|
||||||
innerObject: TextDelegate {
|
innerObject: TextDelegate {
|
||||||
Layout.fillWidth: Config.compactLayout
|
|
||||||
Layout.maximumWidth: messageContainer.bubbleMaxWidth
|
Layout.maximumWidth: messageContainer.bubbleMaxWidth
|
||||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
onRequestOpenMessageContext: openMessageContext(model, parent.selectedText)
|
||||||
Layout.leftMargin: Config.showAvatarInTimeline ? Kirigami.Units.largeSpacing : 0
|
|
||||||
TapHandler {
|
|
||||||
acceptedButtons: Qt.RightButton
|
|
||||||
onTapped: openMessageContext(author, model.message, eventId, toolTip, eventType, model.formattedBody, parent.selectedText)
|
|
||||||
}
|
|
||||||
TapHandler {
|
|
||||||
acceptedButtons: Qt.LeftButton
|
|
||||||
onLongPressed: openMessageContext(author, model.message, eventId, toolTip, eventType, model.formattedBody, parent.selectedText)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -424,9 +403,8 @@ Kirigami.ScrollablePage {
|
|||||||
|
|
||||||
innerObject: TextDelegate {
|
innerObject: TextDelegate {
|
||||||
Layout.fillWidth: !Config.compactLayout
|
Layout.fillWidth: !Config.compactLayout
|
||||||
|
hasContextMenu: false
|
||||||
Layout.maximumWidth: noticeContainer.bubbleMaxWidth
|
Layout.maximumWidth: noticeContainer.bubbleMaxWidth
|
||||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
|
||||||
Layout.leftMargin: Config.showAvatarInTimeline ? Kirigami.Units.largeSpacing : 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -447,13 +425,19 @@ Kirigami.ScrollablePage {
|
|||||||
Layout.maximumHeight: Kirigami.Units.gridUnit * 20
|
Layout.maximumHeight: Kirigami.Units.gridUnit * 20
|
||||||
TapHandler {
|
TapHandler {
|
||||||
acceptedButtons: Qt.RightButton
|
acceptedButtons: Qt.RightButton
|
||||||
onTapped: openFileContext(author, model.display, eventId, toolTip, progressInfo, parent)
|
onTapped: openFileContext(model, parent)
|
||||||
}
|
}
|
||||||
TapHandler {
|
TapHandler {
|
||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
onLongPressed: openFileContext(author, model.display, eventId, toolTip, progressInfo, parent)
|
onLongPressed: openFileContext(model, parent)
|
||||||
onTapped: {
|
onTapped: {
|
||||||
fullScreenImage.createObject(parent, {"filename": eventId, "localPath": currentRoom.urlToDownload(eventId), "blurhash": model.content.info["xyz.amorgan.blurhash"], "imageWidth": content.info.w, "imageHeight": content.info.h}).showFullScreen()
|
fullScreenImage.createObject(parent, {
|
||||||
|
filename: eventId,
|
||||||
|
localPath: currentRoom.urlToDownload(eventId),
|
||||||
|
blurhash: model.content.info["xyz.amorgan.blurhash"],
|
||||||
|
imageWidth: content.info.w,
|
||||||
|
imageHeight: content.info.h
|
||||||
|
}).showFullScreen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -492,11 +476,11 @@ Kirigami.ScrollablePage {
|
|||||||
Layout.maximumWidth: audioContainer.bubbleMaxWidth
|
Layout.maximumWidth: audioContainer.bubbleMaxWidth
|
||||||
TapHandler {
|
TapHandler {
|
||||||
acceptedButtons: Qt.RightButton
|
acceptedButtons: Qt.RightButton
|
||||||
onTapped: openFileContext(author, model.display, eventId, toolTip, progressInfo, parent)
|
onTapped: openFileContext(model, parent)
|
||||||
}
|
}
|
||||||
TapHandler {
|
TapHandler {
|
||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
onLongPressed: openFileContext(author, model.display, eventId, toolTip, progressInfo, parent)
|
onLongPressed: openFileContext(model, parent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -520,11 +504,11 @@ Kirigami.ScrollablePage {
|
|||||||
|
|
||||||
TapHandler {
|
TapHandler {
|
||||||
acceptedButtons: Qt.RightButton
|
acceptedButtons: Qt.RightButton
|
||||||
onTapped: openFileContext(author, model.display, eventId, toolTip, progressInfo, parent)
|
onTapped: openFileContext(model, parent)
|
||||||
}
|
}
|
||||||
TapHandler {
|
TapHandler {
|
||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
onLongPressed: openFileContext(author, model.display, eventId, toolTip, progressInfo, parent)
|
onLongPressed: openFileContext(model, parent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -543,11 +527,11 @@ Kirigami.ScrollablePage {
|
|||||||
Layout.maximumWidth: fileContainer.bubbleMaxWidth
|
Layout.maximumWidth: fileContainer.bubbleMaxWidth
|
||||||
TapHandler {
|
TapHandler {
|
||||||
acceptedButtons: Qt.RightButton
|
acceptedButtons: Qt.RightButton
|
||||||
onTapped: openFileContext(author, model.display, eventId, toolTip, progressInfo, parent)
|
onTapped: openFileContext(model, parent)
|
||||||
}
|
}
|
||||||
TapHandler {
|
TapHandler {
|
||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
onLongPressed: openFileContext(author, model.display, eventId, toolTip, progressInfo, parent)
|
onLongPressed: openFileContext(model, parent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -887,28 +871,28 @@ Kirigami.ScrollablePage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Open message context dialog for file and videos
|
/// Open message context dialog for file and videos
|
||||||
function openFileContext(author, message, eventId, source, progressInfo, file) {
|
function openFileContext(event, file) {
|
||||||
const contextMenu = fileDelegateContextMenu.createObject(page, {
|
const contextMenu = fileDelegateContextMenu.createObject(page, {
|
||||||
author: author,
|
author: event.author,
|
||||||
message: message,
|
message: event.message,
|
||||||
eventId: eventId,
|
eventId: event.eventId,
|
||||||
source: source,
|
source: event.toolTip,
|
||||||
file: file,
|
file: file,
|
||||||
progressInfo: progressInfo,
|
progressInfo: event.progressInfo,
|
||||||
});
|
});
|
||||||
contextMenu.open();
|
contextMenu.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open context menu for normal message
|
/// Open context menu for normal message
|
||||||
function openMessageContext(author, message, eventId, source, eventType, formattedBody, selectedText) {
|
function openMessageContext(event, selectedText) {
|
||||||
const contextMenu = messageDelegateContextMenu.createObject(page, {
|
const contextMenu = messageDelegateContextMenu.createObject(page, {
|
||||||
selectedText: selectedText,
|
selectedText: selectedText,
|
||||||
author: author,
|
author: event.author,
|
||||||
message: message,
|
message: event.message,
|
||||||
eventId: eventId,
|
eventId: event.eventId,
|
||||||
formattedBody: formattedBody,
|
formattedBody: event.formattedBody,
|
||||||
source: source,
|
source: event.toolTip,
|
||||||
eventType: eventType
|
eventType: event.eventType
|
||||||
});
|
});
|
||||||
contextMenu.open();
|
contextMenu.open();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,88 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2020 Tobias Fella <fella@posteo.de>
|
|
||||||
// SPDX-FileCopyrightText: 2021 Carl Schwan <carl@carlschwan.eu>
|
|
||||||
// SPDX-License-Identifier: LGPL-2.0-or-later
|
|
||||||
|
|
||||||
import QtQuick 2.15
|
|
||||||
import QtQuick.Controls 2.15 as QQC2
|
|
||||||
import QtQuick.Layouts 1.15
|
|
||||||
|
|
||||||
import org.kde.kirigami 2.15 as Kirigami
|
|
||||||
|
|
||||||
import org.kde.neochat 1.0
|
|
||||||
import NeoChat.Settings 1.0
|
|
||||||
|
|
||||||
Kirigami.ScrollablePage {
|
|
||||||
title: i18n("Settings")
|
|
||||||
bottomPadding: 0
|
|
||||||
leftPadding: 0
|
|
||||||
rightPadding: 0
|
|
||||||
topPadding: 0
|
|
||||||
|
|
||||||
onBackRequested: {
|
|
||||||
if (pageSettingStack.depth > 1 && !pageSettingStack.wideMode && pageSettingStack.currentIndex !== 0) {
|
|
||||||
event.accepted = true;
|
|
||||||
pageSettingStack.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Kirigami.PageRow {
|
|
||||||
id: pageSettingStack
|
|
||||||
anchors.fill: parent
|
|
||||||
columnView.columnWidth: Kirigami.Units.gridUnit * 12
|
|
||||||
initialPage: Kirigami.ScrollablePage {
|
|
||||||
bottomPadding: 0
|
|
||||||
leftPadding: 0
|
|
||||||
rightPadding: 0
|
|
||||||
topPadding: 0
|
|
||||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
|
||||||
ListView {
|
|
||||||
Component.onCompleted: if (pageSettingStack.wideMode) {
|
|
||||||
actions[0].trigger();
|
|
||||||
}
|
|
||||||
property list<Kirigami.Action> actions: [
|
|
||||||
Kirigami.Action {
|
|
||||||
text: i18n("General")
|
|
||||||
icon.name: "org.kde.neochat"
|
|
||||||
onTriggered: pageSettingStack.push("qrc:/imports/NeoChat/Settings/GeneralSettingsPage.qml")
|
|
||||||
},
|
|
||||||
Kirigami.Action {
|
|
||||||
text: i18n("Appearance")
|
|
||||||
icon.name: "preferences-desktop-theme-global"
|
|
||||||
onTriggered: pageSettingStack.push("qrc:/imports/NeoChat/Settings/AppearanceSettingsPage.qml")
|
|
||||||
},
|
|
||||||
Kirigami.Action {
|
|
||||||
text: i18n("Accounts")
|
|
||||||
icon.name: "preferences-system-users"
|
|
||||||
onTriggered: pageSettingStack.push("qrc:/imports/NeoChat/Page/AccountsPage.qml")
|
|
||||||
},
|
|
||||||
Kirigami.Action {
|
|
||||||
text: i18n("Custom Emoji")
|
|
||||||
icon.name: "preferences-desktop-emoticons"
|
|
||||||
onTriggered: pageSettingStack.push("qrc:/imports/NeoChat/Settings/Emoticons.qml")
|
|
||||||
},
|
|
||||||
Kirigami.Action {
|
|
||||||
text: i18n("Devices")
|
|
||||||
iconName: "network-connect"
|
|
||||||
onTriggered: pageSettingStack.push("qrc:/imports/NeoChat/Page/DevicesPage.qml")
|
|
||||||
},
|
|
||||||
Kirigami.Action {
|
|
||||||
text: i18n("About NeoChat")
|
|
||||||
icon.name: "help-about"
|
|
||||||
onTriggered: pageSettingStack.push(aboutPage)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
model: actions
|
|
||||||
delegate: Kirigami.BasicListItem {
|
|
||||||
action: modelData
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: aboutPage
|
|
||||||
Kirigami.AboutPage {
|
|
||||||
aboutData: Controller.aboutData
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,6 +5,5 @@ RoomPage 1.0 RoomPage.qml
|
|||||||
RoomWindow 1.0 RoomWindow.qml
|
RoomWindow 1.0 RoomWindow.qml
|
||||||
JoinRoomPage 1.0 JoinRoomPage.qml
|
JoinRoomPage 1.0 JoinRoomPage.qml
|
||||||
InviteUserPage 1.0 InviteUserPage.qml
|
InviteUserPage 1.0 InviteUserPage.qml
|
||||||
SettingsPage 1.0 SettingsPage.qml
|
|
||||||
ImageEditorPage 1.0 ImageEditorPage.qml
|
ImageEditorPage 1.0 ImageEditorPage.qml
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,46 @@ Kirigami.OverlayDrawer {
|
|||||||
id: roomDrawer
|
id: roomDrawer
|
||||||
readonly property var room: RoomManager.currentRoom
|
readonly property var room: RoomManager.currentRoom
|
||||||
|
|
||||||
|
width: modal ? undefined : actualWidth
|
||||||
|
readonly property int minWidth: Kirigami.Units.gridUnit * 15
|
||||||
|
readonly property int maxWidth: Kirigami.Units.gridUnit * 25
|
||||||
|
readonly property int defaultWidth: Kirigami.Units.gridUnit * 20
|
||||||
|
property int actualWidth: {
|
||||||
|
if (Config.roomDrawerWidth === -1) {
|
||||||
|
return Kirigami.Units.gridUnit * 20;
|
||||||
|
} else {
|
||||||
|
return Config.roomDrawerWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.right: undefined
|
||||||
|
width: 2
|
||||||
|
z: 500
|
||||||
|
cursorShape: !Kirigami.Settings.isMobile ? Qt.SplitHCursor : undefined
|
||||||
|
enabled: true
|
||||||
|
visible: true
|
||||||
|
onPressed: _lastX = mapToGlobal(mouseX, mouseY).x
|
||||||
|
onReleased: {
|
||||||
|
Config.roomDrawerWidth = roomDrawer.actualWidth;
|
||||||
|
Config.save();
|
||||||
|
}
|
||||||
|
property real _lastX: -1
|
||||||
|
|
||||||
|
onPositionChanged: {
|
||||||
|
if (_lastX === -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Qt.application.layoutDirection === Qt.RightToLeft) {
|
||||||
|
roomDrawer.actualWidth = Math.min(roomDrawer.maxWidth, Math.max(roomDrawer.minWidth, Config.roomDrawerWidth - _lastX + mapToGlobal(mouseX, mouseY).x))
|
||||||
|
} else {
|
||||||
|
roomDrawer.actualWidth = Math.min(roomDrawer.maxWidth, Math.max(roomDrawer.minWidth, Config.roomDrawerWidth + _lastX - mapToGlobal(mouseX, mouseY).x))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
edge: Qt.application.layoutDirection == Qt.RightToLeft ? Qt.LeftEdge : Qt.RightEdge
|
edge: Qt.application.layoutDirection == Qt.RightToLeft ? Qt.LeftEdge : Qt.RightEdge
|
||||||
@@ -30,7 +70,6 @@ Kirigami.OverlayDrawer {
|
|||||||
active: roomDrawer.drawerOpen
|
active: roomDrawer.drawerOpen
|
||||||
sourceComponent: ColumnLayout {
|
sourceComponent: ColumnLayout {
|
||||||
id: columnLayout
|
id: columnLayout
|
||||||
anchors.fill: parent
|
|
||||||
spacing: 0
|
spacing: 0
|
||||||
Kirigami.AbstractApplicationHeader {
|
Kirigami.AbstractApplicationHeader {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@@ -47,7 +86,7 @@ Kirigami.OverlayDrawer {
|
|||||||
icon.name: "list-add-user"
|
icon.name: "list-add-user"
|
||||||
text: i18n("Invite")
|
text: i18n("Invite")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
applicationWindow().pageStack.layers.push("qrc:/imports/NeoChat/Page/InviteUserPage.qml", {"room": room})
|
applicationWindow().pageStack.layers.push("qrc:/imports/NeoChat/Page/InviteUserPage.qml", {room: room})
|
||||||
roomDrawer.close();
|
roomDrawer.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,12 +108,7 @@ Kirigami.OverlayDrawer {
|
|||||||
ToolButton {
|
ToolButton {
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
icon.name: 'settings-configure'
|
icon.name: 'settings-configure'
|
||||||
onClicked: {
|
onClicked: ApplicationWindow.window.pageStack.pushDialogLayer('qrc:/imports/NeoChat/RoomSettings/Categories.qml', {room: room})
|
||||||
roomSettingDialog.createObject(ApplicationWindow.overlay, {"room": room}).open()
|
|
||||||
if (!wideScreen) {
|
|
||||||
roomDrawer.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ToolTip {
|
ToolTip {
|
||||||
text: i18n("Room settings")
|
text: i18n("Room settings")
|
||||||
@@ -83,67 +117,61 @@ Kirigami.OverlayDrawer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Control {
|
ColumnLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
padding: Kirigami.Units.largeSpacing
|
Layout.margins: Kirigami.Units.largeSpacing
|
||||||
contentItem: ColumnLayout {
|
Kirigami.Heading {
|
||||||
id: infoLayout
|
text: i18n("Room information")
|
||||||
|
level: 3
|
||||||
|
}
|
||||||
|
RowLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Kirigami.Heading {
|
Layout.margins: Kirigami.Units.largeSpacing
|
||||||
text: i18n("Room information")
|
|
||||||
level: 3
|
spacing: Kirigami.Units.largeSpacing
|
||||||
|
|
||||||
|
Kirigami.Avatar {
|
||||||
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 3.5
|
||||||
|
Layout.preferredHeight: Kirigami.Units.gridUnit * 3.5
|
||||||
|
|
||||||
|
name: room ? room.name : i18n("No name")
|
||||||
|
source: room ? ("image://mxc/" + room.avatarMediaId) : ""
|
||||||
}
|
}
|
||||||
RowLayout {
|
|
||||||
|
ColumnLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.margins: Kirigami.Units.largeSpacing
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
spacing: Kirigami.Units.largeSpacing
|
Kirigami.Heading {
|
||||||
|
Layout.maximumWidth: Kirigami.Units.gridUnit * 9
|
||||||
Kirigami.Avatar {
|
|
||||||
Layout.preferredWidth: Kirigami.Units.gridUnit * 3.5
|
|
||||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 3.5
|
|
||||||
|
|
||||||
name: room ? room.name : i18n("No name")
|
|
||||||
source: room ? ("image://mxc/" + room.avatarMediaId) : ""
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.alignment: Qt.AlignVCenter
|
level: 1
|
||||||
spacing: 0
|
font.bold: true
|
||||||
|
wrapMode: Label.Wrap
|
||||||
Kirigami.Heading {
|
text: room ? room.displayName : i18n("No name")
|
||||||
Layout.maximumWidth: Kirigami.Units.gridUnit * 9
|
}
|
||||||
Layout.fillWidth: true
|
Label {
|
||||||
level: 1
|
Layout.fillWidth: true
|
||||||
font.bold: true
|
text: room && room.canonicalAlias ? room.canonicalAlias : i18n("No Canonical Alias")
|
||||||
wrapMode: Label.Wrap
|
|
||||||
text: room ? room.displayName : i18n("No name")
|
|
||||||
}
|
|
||||||
Label {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: room && room.canonicalAlias ? room.canonicalAlias : i18n("No Canonical Alias")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextEdit {
|
TextEdit {
|
||||||
Layout.maximumWidth: Kirigami.Units.gridUnit * 13
|
Layout.fillWidth: true
|
||||||
Layout.preferredWidth: Kirigami.Units.gridUnit * 13
|
text: room && room.topic ? room.topic.replace(replaceLinks, "<a href=\"$1\">$1</a>") : i18n("No Topic")
|
||||||
Layout.fillWidth: true
|
readonly property var replaceLinks: /\(https:\/\/[^ ]*\)/
|
||||||
text: room && room.topic ? room.topic.replace(replaceLinks, "<a href=\"$1\">$1</a>") : i18n("No Topic")
|
textFormat: TextEdit.MarkdownText
|
||||||
readonly property var replaceLinks: /\(https:\/\/[^ ]*\)/
|
wrapMode: Text.WordWrap
|
||||||
textFormat: TextEdit.MarkdownText
|
selectByMouse: true
|
||||||
wrapMode: Text.WordWrap
|
color: Kirigami.Theme.textColor
|
||||||
selectByMouse: true
|
onLinkActivated: Qt.openUrlExternally(link)
|
||||||
color: Kirigami.Theme.textColor
|
readOnly: true
|
||||||
onLinkActivated: Qt.openUrlExternally(link)
|
MouseArea {
|
||||||
readOnly: true
|
anchors.fill: parent
|
||||||
MouseArea {
|
acceptedButtons: Qt.NoButton
|
||||||
anchors.fill: parent
|
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.IBeamCursor
|
||||||
acceptedButtons: Qt.NoButton
|
|
||||||
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.IBeamCursor
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,7 +181,7 @@ Kirigami.OverlayDrawer {
|
|||||||
activeFocusOnTab: false
|
activeFocusOnTab: false
|
||||||
Label {
|
Label {
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
text: room ? i18np("%1 Member", "%1 Members", room.totalMemberCount) : i18n("No Member Count")
|
text: room ? i18np("%1 Member", "%1 Members", room.joinedCount) : i18n("No Member Count")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,6 +189,11 @@ Kirigami.OverlayDrawer {
|
|||||||
padding: Kirigami.Units.smallSpacing
|
padding: Kirigami.Units.smallSpacing
|
||||||
implicitWidth: parent.width
|
implicitWidth: parent.width
|
||||||
z: 2
|
z: 2
|
||||||
|
background: Rectangle {
|
||||||
|
color: Kirigami.Theme.backgroundColor
|
||||||
|
Kirigami.Theme.inherit: false
|
||||||
|
Kirigami.Theme.colorSet: Kirigami.Theme.Window
|
||||||
|
}
|
||||||
contentItem: Kirigami.SearchField {
|
contentItem: Kirigami.SearchField {
|
||||||
id: userListSearchField
|
id: userListSearchField
|
||||||
onAccepted: sortedMessageEventModel.filterString = text;
|
onAccepted: sortedMessageEventModel.filterString = text;
|
||||||
@@ -187,6 +220,7 @@ Kirigami.OverlayDrawer {
|
|||||||
|
|
||||||
sortRole: "perm"
|
sortRole: "perm"
|
||||||
filterRole: "name"
|
filterRole: "name"
|
||||||
|
filterCaseSensitivity: Qt.CaseInsensitive
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: Kirigami.AbstractListItem {
|
delegate: Kirigami.AbstractListItem {
|
||||||
@@ -254,12 +288,6 @@ Kirigami.OverlayDrawer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
|
||||||
id: roomSettingDialog
|
|
||||||
|
|
||||||
RoomSettingsDialog {}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: userDetailDialog
|
id: userDetailDialog
|
||||||
|
|
||||||
|
|||||||
35
imports/NeoChat/RoomSettings/Categories.qml
Normal file
35
imports/NeoChat/RoomSettings/Categories.qml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
|
||||||
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import org.kde.kirigami 2.18 as Kirigami
|
||||||
|
import QtQuick.Controls 2.15 as Controls
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
Kirigami.CategorizedSettings {
|
||||||
|
id: root
|
||||||
|
required property var room
|
||||||
|
objectName: "settingsPage"
|
||||||
|
actions: [
|
||||||
|
Kirigami.SettingAction {
|
||||||
|
text: i18n("General")
|
||||||
|
icon.name: "settings-configure"
|
||||||
|
page: Qt.resolvedUrl("General.qml")
|
||||||
|
initialProperties: {
|
||||||
|
return {
|
||||||
|
room: root.room
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Kirigami.SettingAction {
|
||||||
|
text: i18n("Security")
|
||||||
|
icon.name: "security-low"
|
||||||
|
page: Qt.resolvedUrl("Security.qml")
|
||||||
|
initialProperties: {
|
||||||
|
return {
|
||||||
|
room: root.room
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
202
imports/NeoChat/RoomSettings/General.qml
Normal file
202
imports/NeoChat/RoomSettings/General.qml
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2019-2020 Black Hat <bhat@encom.eu.org>
|
||||||
|
// SPDX-FileCopyrightText: 2021 Carl Schwan <carl@carlschwan.eu>
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
import org.kde.kirigami 2.15 as Kirigami
|
||||||
|
|
||||||
|
import org.kde.neochat 1.0
|
||||||
|
import NeoChat.Component 1.0
|
||||||
|
import NeoChat.Dialog 1.0
|
||||||
|
|
||||||
|
Kirigami.ScrollablePage {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var room
|
||||||
|
|
||||||
|
readonly property bool canChangeAvatar: room.canSendState("m.room.avatar")
|
||||||
|
readonly property bool canChangeName: room.canSendState("m.room.name")
|
||||||
|
readonly property bool canChangeTopic: room.canSendState("m.room.topic")
|
||||||
|
readonly property bool canChangeCanonicalAlias: room.canSendState("m.room.canonical_alias")
|
||||||
|
|
||||||
|
title: i18n('General')
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Kirigami.FormLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
Kirigami.Avatar {
|
||||||
|
Layout.bottomMargin: Kirigami.Units.largeSpacing
|
||||||
|
|
||||||
|
name: room.name
|
||||||
|
source: room.avatarMediaId ? ("image://mxc/" + room.avatarMediaId) : ""
|
||||||
|
|
||||||
|
RoundButton {
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
height: Kirigami.Units.gridUnits
|
||||||
|
width: Kirigami.Units.gridUnits
|
||||||
|
icon.name: 'cloud-upload'
|
||||||
|
Accessible.name: i18n("Update avatar")
|
||||||
|
enabled: canChangeAvatar
|
||||||
|
onClicked: {
|
||||||
|
const fileDialog = openFileDialog.createObject(ApplicationWindow.overlay)
|
||||||
|
|
||||||
|
fileDialog.chosen.connect(function(path) {
|
||||||
|
if (!path) return
|
||||||
|
|
||||||
|
room.changeAvatar(path)
|
||||||
|
})
|
||||||
|
|
||||||
|
fileDialog.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TextField {
|
||||||
|
id: roomNameField
|
||||||
|
text: room.name
|
||||||
|
Kirigami.FormData.label: i18n("Room Name:")
|
||||||
|
enabled: canChangeName
|
||||||
|
}
|
||||||
|
|
||||||
|
TextArea {
|
||||||
|
id: roomTopicField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: room.topic
|
||||||
|
Kirigami.FormData.label: i18n("Room topic:")
|
||||||
|
enabled: canChangeTopic
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Kirigami.Separator {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: canonicalAliasComboBox.visible || altAlias.visible
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboBox {
|
||||||
|
id: canonicalAliasComboBox
|
||||||
|
visible: room.aliases && room.aliases.length
|
||||||
|
Kirigami.FormData.label: i18n("Canonical Alias:")
|
||||||
|
popup.z: 999; // HACK This is an absolute hack, but combos inside OverlaySheets have their popups show up underneath, because of fun z ordering stuff
|
||||||
|
|
||||||
|
enabled: canChangeCanonicalAlias
|
||||||
|
|
||||||
|
model: room.aliases
|
||||||
|
|
||||||
|
currentIndex: room.aliases.indexOf(room.canonicalAlias)
|
||||||
|
onCurrentIndexChanged: {
|
||||||
|
if (room.canonicalAlias != room.aliases[currentIndex]) {
|
||||||
|
room.setCanonicalAlias(room.aliases[currentIndex])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: altAlias
|
||||||
|
Kirigami.FormData.label: i18n("Other Aliases:")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
visible: room.altAliases && room.altAliases.length
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: room.altAliases
|
||||||
|
|
||||||
|
delegate: RowLayout {
|
||||||
|
Layout.maximumWidth: parent.width
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: modelData
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolButton {
|
||||||
|
icon.name: ""
|
||||||
|
onClicked: room.removeLocalAlias(modelData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Kirigami.Separator {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: next.visible || prev.visible
|
||||||
|
}
|
||||||
|
|
||||||
|
Control {
|
||||||
|
id: next
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
visible: room.predecessorId && room.connection.room(room.predecessorId)
|
||||||
|
|
||||||
|
padding: Kirigami.Units.largeSpacing
|
||||||
|
|
||||||
|
contentItem: Kirigami.InlineMessage {
|
||||||
|
text: i18n("This room continues another conversation.")
|
||||||
|
actions: Kirigami.Action {
|
||||||
|
text: i18n("See older messages...")
|
||||||
|
onTriggered: {
|
||||||
|
roomListForm.enteredRoom = Controller.activeConnection.room(room.predecessorId)
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Control {
|
||||||
|
id: prev
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
visible: room.successorId && room.connection.room(room.successorId)
|
||||||
|
|
||||||
|
padding: Kirigami.Units.largeSpacing
|
||||||
|
|
||||||
|
contentItem: Kirigami.InlineMessage {
|
||||||
|
text: i18n("This room has been replaced.")
|
||||||
|
actions: Kirigami.Action {
|
||||||
|
text: i18n("See new room...")
|
||||||
|
onTriggered: {
|
||||||
|
roomListForm.enteredRoom = Controller.activeConnection.room(room.successorId)
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: openFileDialog
|
||||||
|
|
||||||
|
OpenFileDialog {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
footer: ToolBar {
|
||||||
|
contentItem: RowLayout {
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
enabled: room.name !== roomNameField.text || room.topic !== roomTopicField.text
|
||||||
|
text: i18n("Apply")
|
||||||
|
onClicked: {
|
||||||
|
if (room.name != roomNameField.text) {
|
||||||
|
room.setName(roomNameField.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (room.topic != roomTopicField.text) {
|
||||||
|
room.setTopic(roomTopicField.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
69
imports/NeoChat/RoomSettings/Security.qml
Normal file
69
imports/NeoChat/RoomSettings/Security.qml
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2019-2020 Black Hat <bhat@encom.eu.org>
|
||||||
|
// SPDX-FileCopyrightText: 2021 Carl Schwan <carl@carlschwan.eu>
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
import org.kde.kirigami 2.15 as Kirigami
|
||||||
|
|
||||||
|
import org.kde.neochat 1.0
|
||||||
|
import NeoChat.Component 1.0
|
||||||
|
import NeoChat.Dialog 1.0
|
||||||
|
|
||||||
|
Kirigami.ScrollablePage {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var room
|
||||||
|
|
||||||
|
title: i18n('Security')
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Kirigami.FormLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
CheckBox {
|
||||||
|
text: i18nc("@option:check", "Private (invite only)")
|
||||||
|
Kirigami.FormData.label: i18nc("@option:check", "Access:")
|
||||||
|
checked: room.joinRule === "invite"
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
text: i18n("Only invited people can join.")
|
||||||
|
font: Kirigami.Theme.smallFont
|
||||||
|
}
|
||||||
|
CheckBox {
|
||||||
|
text: i18nc("@option:check", "Space members")
|
||||||
|
checked: room.joinRule === "restricted"
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
text: i18n("Anyone in a space can find and join.")
|
||||||
|
font: Kirigami.Theme.smallFont
|
||||||
|
}
|
||||||
|
CheckBox {
|
||||||
|
text: i18nc("@option:check", "Public")
|
||||||
|
checked: room.joinRule === "public"
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
text: i18nc("@option:check", "Anyone can find and join.") + room.joinRule
|
||||||
|
font: Kirigami.Theme.smallFont
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
footer: ToolBar {
|
||||||
|
contentItem: RowLayout {
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
enabled: false
|
||||||
|
text: i18n("Apply")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
12
imports/NeoChat/Settings/About.qml
Normal file
12
imports/NeoChat/Settings/About.qml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2020 Tobias Fella <fella@posteo.de>
|
||||||
|
// SPDX-FileCopyrightText: 2021 Carl Schwan <carl@carlschwan.eu>
|
||||||
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
|
import org.kde.kirigami 2.15 as Kirigami
|
||||||
|
|
||||||
|
import org.kde.neochat 1.0
|
||||||
|
|
||||||
|
Kirigami.AboutPage {
|
||||||
|
title: i18nc('@title:window', 'About NeoChat')
|
||||||
|
aboutData: Controller.aboutData
|
||||||
|
}
|
||||||
@@ -133,9 +133,7 @@ Kirigami.Page {
|
|||||||
|
|
||||||
property var connection
|
property var connection
|
||||||
|
|
||||||
header: Kirigami.Heading {
|
title: i18n("Edit Account")
|
||||||
text: i18n("Edit Account")
|
|
||||||
}
|
|
||||||
|
|
||||||
Kirigami.FormLayout {
|
Kirigami.FormLayout {
|
||||||
RowLayout {
|
RowLayout {
|
||||||
@@ -12,6 +12,7 @@ import org.kde.neochat 1.0
|
|||||||
import NeoChat.Settings 1.0
|
import NeoChat.Settings 1.0
|
||||||
|
|
||||||
Kirigami.ScrollablePage {
|
Kirigami.ScrollablePage {
|
||||||
|
title: i18nc('@title:window', 'Appearance')
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.alignment: Qt.AlignCenter
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
|||||||
@@ -82,9 +82,7 @@ Kirigami.Page {
|
|||||||
|
|
||||||
property var index
|
property var index
|
||||||
|
|
||||||
header: Kirigami.Heading {
|
title: i18n("Remove device")
|
||||||
text: i18n("Remove device")
|
|
||||||
}
|
|
||||||
Kirigami.FormLayout {
|
Kirigami.FormLayout {
|
||||||
Controls.TextField {
|
Controls.TextField {
|
||||||
id: passwordField
|
id: passwordField
|
||||||
@@ -107,9 +105,7 @@ Kirigami.Page {
|
|||||||
property int index
|
property int index
|
||||||
property string name
|
property string name
|
||||||
|
|
||||||
header: Kirigami.Heading {
|
title: i18n("Edit device")
|
||||||
text: i18n("Edit device")
|
|
||||||
}
|
|
||||||
Kirigami.FormLayout {
|
Kirigami.FormLayout {
|
||||||
Controls.TextField {
|
Controls.TextField {
|
||||||
id: nameField
|
id: nameField
|
||||||
@@ -14,6 +14,7 @@ import NeoChat.Component 1.0 as Components
|
|||||||
import NeoChat.Dialog 1.0
|
import NeoChat.Dialog 1.0
|
||||||
|
|
||||||
Kirigami.Page {
|
Kirigami.Page {
|
||||||
|
title: i18nc('@title:window', 'Custom Emojis')
|
||||||
|
|
||||||
leftPadding: pageSettingStack.wideMode ? Kirigami.Units.smallSpacing : 0
|
leftPadding: pageSettingStack.wideMode ? Kirigami.Units.smallSpacing : 0
|
||||||
topPadding: pageSettingStack.wideMode ? Kirigami.Units.smallSpacing : 0
|
topPadding: pageSettingStack.wideMode ? Kirigami.Units.smallSpacing : 0
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import org.kde.kirigami 2.15 as Kirigami
|
|||||||
import org.kde.neochat 1.0
|
import org.kde.neochat 1.0
|
||||||
|
|
||||||
Kirigami.ScrollablePage {
|
Kirigami.ScrollablePage {
|
||||||
|
title: i18nc('@title:window', 'General')
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
Kirigami.FormLayout {
|
Kirigami.FormLayout {
|
||||||
QQC2.CheckBox {
|
QQC2.CheckBox {
|
||||||
|
|||||||
43
imports/NeoChat/Settings/SettingsPage.qml
Normal file
43
imports/NeoChat/Settings/SettingsPage.qml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
|
||||||
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import org.kde.kirigami 2.18 as Kirigami
|
||||||
|
import QtQuick.Controls 2.15 as Controls
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
|
|
||||||
|
Kirigami.CategorizedSettings {
|
||||||
|
objectName: "settingsPage"
|
||||||
|
actions: [
|
||||||
|
Kirigami.SettingAction {
|
||||||
|
text: i18n("General")
|
||||||
|
icon.name: "org.kde.neochat"
|
||||||
|
page: Qt.resolvedUrl("GeneralSettingsPage.qml")
|
||||||
|
},
|
||||||
|
Kirigami.SettingAction {
|
||||||
|
text: i18n("Appearance")
|
||||||
|
icon.name: "preferences-desktop-theme-global"
|
||||||
|
page: Qt.resolvedUrl("AppearanceSettingsPage.qml")
|
||||||
|
},
|
||||||
|
Kirigami.SettingAction {
|
||||||
|
text: i18n("Accounts")
|
||||||
|
icon.name: "preferences-system-users"
|
||||||
|
page: Qt.resolvedUrl("AccountsPage.qml")
|
||||||
|
},
|
||||||
|
Kirigami.SettingAction {
|
||||||
|
text: i18n("Custom Emoji")
|
||||||
|
icon.name: "preferences-desktop-emoticons"
|
||||||
|
page: Qt.resolvedUrl("Emoticons.qml")
|
||||||
|
},
|
||||||
|
Kirigami.SettingAction {
|
||||||
|
text: i18n("Devices")
|
||||||
|
iconName: "network-connect"
|
||||||
|
page: Qt.resolvedUrl("DevicesPage.qml")
|
||||||
|
},
|
||||||
|
Kirigami.SettingAction {
|
||||||
|
text: i18n("About NeoChat")
|
||||||
|
icon.name: "help-about"
|
||||||
|
page: Qt.resolvedUrl("About.qml")
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
module NeoChat.Settings
|
module NeoChat.Settings
|
||||||
ThemeRadioButton 1.0 ThemeRadioButton.qml
|
ThemeRadioButton 1.0 ThemeRadioButton.qml
|
||||||
|
SettingsPage 1.0 SettingsPage.qml
|
||||||
|
|||||||
@@ -117,7 +117,7 @@
|
|||||||
<p xml:lang="zh-CN">Matrix 是一个分布式通讯协议,使用户重新得到控制权。 目前,NeoChat 实现了协议的大部分,除了加密聊天和视频聊天。</p>
|
<p xml:lang="zh-CN">Matrix 是一个分布式通讯协议,使用户重新得到控制权。 目前,NeoChat 实现了协议的大部分,除了加密聊天和视频聊天。</p>
|
||||||
<p>NeoChat works both on mobile and desktop while providing a consistent user experience.</p>
|
<p>NeoChat works both on mobile and desktop while providing a consistent user experience.</p>
|
||||||
<p xml:lang="az">Vahid istifadəçi interfeysi ilə təmin olunan NeoChat, həm mobil telefonda həm də kompyuterlərdə işləyir.</p>
|
<p xml:lang="az">Vahid istifadəçi interfeysi ilə təmin olunan NeoChat, həm mobil telefonda həm də kompyuterlərdə işləyir.</p>
|
||||||
<p xml:lang="ca">El NeoChat funciona en el mòbils i a l'escriptori, proporcionant un experiència d'usuari coherent.</p>
|
<p xml:lang="ca">El NeoChat funciona en els mòbils i a l'escriptori, proporcionant una experiència d'usuari coherent.</p>
|
||||||
<p xml:lang="ca-valencia">El NeoChat funciona en el mòbils i a l'escriptori, proporcionant un experiència d'usuari coherent.</p>
|
<p xml:lang="ca-valencia">El NeoChat funciona en el mòbils i a l'escriptori, proporcionant un experiència d'usuari coherent.</p>
|
||||||
<p xml:lang="de">NeoChat funktioniert sowohl auf dem Mobiltelefon als auch auf dem Arbeitsfläche und bietet ein einheitliches Benutzererlebnis. </p>
|
<p xml:lang="de">NeoChat funktioniert sowohl auf dem Mobiltelefon als auch auf dem Arbeitsfläche und bietet ein einheitliches Benutzererlebnis. </p>
|
||||||
<p xml:lang="en-GB">NeoChat works both on mobile and desktop while providing a consistent user experience.</p>
|
<p xml:lang="en-GB">NeoChat works both on mobile and desktop while providing a consistent user experience.</p>
|
||||||
|
|||||||
11
qml/main.qml
11
qml/main.qml
@@ -151,7 +151,6 @@ Kirigami.ApplicationWindow {
|
|||||||
|
|
||||||
contextDrawer: RoomDrawer {
|
contextDrawer: RoomDrawer {
|
||||||
id: contextDrawer
|
id: contextDrawer
|
||||||
contentItem.implicitWidth: columnWidth
|
|
||||||
edge: Qt.application.layoutDirection == Qt.RightToLeft ? Qt.LeftEdge : Qt.RightEdge
|
edge: Qt.application.layoutDirection == Qt.RightToLeft ? Qt.LeftEdge : Qt.RightEdge
|
||||||
modal: !root.wideScreen || !enabled
|
modal: !root.wideScreen || !enabled
|
||||||
onEnabledChanged: drawerOpen = enabled && !modal
|
onEnabledChanged: drawerOpen = enabled && !modal
|
||||||
@@ -255,7 +254,7 @@ Kirigami.ApplicationWindow {
|
|||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
text: i18n("Settings")
|
text: i18n("Settings")
|
||||||
icon.name: "settings-configure"
|
icon.name: "settings-configure"
|
||||||
onTriggered: pushReplaceLayer("qrc:/imports/NeoChat/Page/SettingsPage.qml")
|
onTriggered: pageStack.pushDialogLayer("qrc:/imports/NeoChat/Settings/SettingsPage.qml")
|
||||||
enabled: pageStack.layers.currentItem.title !== i18n("Settings")
|
enabled: pageStack.layers.currentItem.title !== i18n("Settings")
|
||||||
shortcut: StandardKey.Preferences
|
shortcut: StandardKey.Preferences
|
||||||
},
|
},
|
||||||
@@ -361,9 +360,7 @@ Kirigami.ApplicationWindow {
|
|||||||
|
|
||||||
property string url: ""
|
property string url: ""
|
||||||
|
|
||||||
header: Kirigami.Heading {
|
title: i18n("User consent")
|
||||||
text: i18n("User consent")
|
|
||||||
}
|
|
||||||
|
|
||||||
QQC2.Label {
|
QQC2.Label {
|
||||||
id: label
|
id: label
|
||||||
@@ -402,9 +399,7 @@ Kirigami.ApplicationWindow {
|
|||||||
required property var user;
|
required property var user;
|
||||||
|
|
||||||
parent: QQC2.ApplicationWindow.overlay
|
parent: QQC2.ApplicationWindow.overlay
|
||||||
header: Kirigami.Heading {
|
title: i18n("Start a chat")
|
||||||
text: i18n("Start a chat")
|
|
||||||
}
|
|
||||||
contentItem: QQC2.Label {
|
contentItem: QQC2.Label {
|
||||||
text: i18n("Do you want to start a chat with %1?", user.displayName)
|
text: i18n("Do you want to start a chat with %1?", user.displayName)
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
|
|||||||
11
res.qrc
11
res.qrc
@@ -6,14 +6,14 @@
|
|||||||
<file>imports/NeoChat/Page/RoomListPage.qml</file>
|
<file>imports/NeoChat/Page/RoomListPage.qml</file>
|
||||||
<file>imports/NeoChat/Page/RoomPage.qml</file>
|
<file>imports/NeoChat/Page/RoomPage.qml</file>
|
||||||
<file>imports/NeoChat/Page/RoomWindow.qml</file>
|
<file>imports/NeoChat/Page/RoomWindow.qml</file>
|
||||||
<file>imports/NeoChat/Page/AccountsPage.qml</file>
|
|
||||||
<file>imports/NeoChat/Page/JoinRoomPage.qml</file>
|
<file>imports/NeoChat/Page/JoinRoomPage.qml</file>
|
||||||
<file>imports/NeoChat/Page/InviteUserPage.qml</file>
|
<file>imports/NeoChat/Page/InviteUserPage.qml</file>
|
||||||
<file>imports/NeoChat/Page/SettingsPage.qml</file>
|
|
||||||
<file>imports/NeoChat/Page/StartChatPage.qml</file>
|
<file>imports/NeoChat/Page/StartChatPage.qml</file>
|
||||||
<file>imports/NeoChat/Page/ImageEditorPage.qml</file>
|
<file>imports/NeoChat/Page/ImageEditorPage.qml</file>
|
||||||
<file>imports/NeoChat/Page/DevicesPage.qml</file>
|
|
||||||
<file>imports/NeoChat/Page/WelcomePage.qml</file>
|
<file>imports/NeoChat/Page/WelcomePage.qml</file>
|
||||||
|
<file>imports/NeoChat/RoomSettings/General.qml</file>
|
||||||
|
<file>imports/NeoChat/RoomSettings/Security.qml</file>
|
||||||
|
<file>imports/NeoChat/RoomSettings/Categories.qml</file>
|
||||||
<file>imports/NeoChat/Component/qmldir</file>
|
<file>imports/NeoChat/Component/qmldir</file>
|
||||||
<file>imports/NeoChat/Component/FullScreenImage.qml</file>
|
<file>imports/NeoChat/Component/FullScreenImage.qml</file>
|
||||||
<file>imports/NeoChat/Component/FancyEffectsContainer.qml</file>
|
<file>imports/NeoChat/Component/FancyEffectsContainer.qml</file>
|
||||||
@@ -57,7 +57,6 @@
|
|||||||
<file>imports/NeoChat/Panel/qmldir</file>
|
<file>imports/NeoChat/Panel/qmldir</file>
|
||||||
<file>imports/NeoChat/Panel/RoomDrawer.qml</file>
|
<file>imports/NeoChat/Panel/RoomDrawer.qml</file>
|
||||||
<file>imports/NeoChat/Dialog/qmldir</file>
|
<file>imports/NeoChat/Dialog/qmldir</file>
|
||||||
<file>imports/NeoChat/Dialog/RoomSettingsDialog.qml</file>
|
|
||||||
<file>imports/NeoChat/Dialog/UserDetailDialog.qml</file>
|
<file>imports/NeoChat/Dialog/UserDetailDialog.qml</file>
|
||||||
<file>imports/NeoChat/Dialog/CreateRoomDialog.qml</file>
|
<file>imports/NeoChat/Dialog/CreateRoomDialog.qml</file>
|
||||||
<file>imports/NeoChat/Dialog/EmojiDialog.qml</file>
|
<file>imports/NeoChat/Dialog/EmojiDialog.qml</file>
|
||||||
@@ -73,11 +72,15 @@
|
|||||||
<file>qtquickcontrols2.conf</file>
|
<file>qtquickcontrols2.conf</file>
|
||||||
<file>imports/NeoChat/Component/glowdot.png</file>
|
<file>imports/NeoChat/Component/glowdot.png</file>
|
||||||
<file>imports/NeoChat/Component/confetti.png</file>
|
<file>imports/NeoChat/Component/confetti.png</file>
|
||||||
|
<file>imports/NeoChat/Settings/SettingsPage.qml</file>
|
||||||
<file>imports/NeoChat/Settings/ThemeRadioButton.qml</file>
|
<file>imports/NeoChat/Settings/ThemeRadioButton.qml</file>
|
||||||
<file>imports/NeoChat/Settings/ColorScheme.qml</file>
|
<file>imports/NeoChat/Settings/ColorScheme.qml</file>
|
||||||
<file>imports/NeoChat/Settings/GeneralSettingsPage.qml</file>
|
<file>imports/NeoChat/Settings/GeneralSettingsPage.qml</file>
|
||||||
<file>imports/NeoChat/Settings/Emoticons.qml</file>
|
<file>imports/NeoChat/Settings/Emoticons.qml</file>
|
||||||
<file>imports/NeoChat/Settings/AppearanceSettingsPage.qml</file>
|
<file>imports/NeoChat/Settings/AppearanceSettingsPage.qml</file>
|
||||||
|
<file>imports/NeoChat/Settings/AccountsPage.qml</file>
|
||||||
|
<file>imports/NeoChat/Settings/DevicesPage.qml</file>
|
||||||
|
<file>imports/NeoChat/Settings/About.qml</file>
|
||||||
<file>imports/NeoChat/Settings/qmldir</file>
|
<file>imports/NeoChat/Settings/qmldir</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ add_executable(neochat
|
|||||||
spellcheckhighlighter.cpp
|
spellcheckhighlighter.cpp
|
||||||
blurhash.cpp
|
blurhash.cpp
|
||||||
blurhashimageprovider.cpp
|
blurhashimageprovider.cpp
|
||||||
|
joinrulesevent.cpp
|
||||||
../res.qrc
|
../res.qrc
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -63,6 +64,18 @@ target_include_directories(neochat PRIVATE ${CMAKE_BINARY_DIR})
|
|||||||
target_link_libraries(neochat PRIVATE Qt::Quick Qt::Qml Qt::Gui Qt::Network Qt::QuickControls2 KF5::I18n KF5::Kirigami2 KF5::Notifications KF5::ConfigCore KF5::ConfigGui KF5::CoreAddons Quotient cmark::cmark ${QTKEYCHAIN_LIBRARIES} QCoro::QCoro)
|
target_link_libraries(neochat PRIVATE Qt::Quick Qt::Qml Qt::Gui Qt::Network Qt::QuickControls2 KF5::I18n KF5::Kirigami2 KF5::Notifications KF5::ConfigCore KF5::ConfigGui KF5::CoreAddons Quotient cmark::cmark ${QTKEYCHAIN_LIBRARIES} QCoro::QCoro)
|
||||||
kconfig_add_kcfg_files(neochat GENERATE_MOC neochatconfig.kcfgc)
|
kconfig_add_kcfg_files(neochat GENERATE_MOC neochatconfig.kcfgc)
|
||||||
|
|
||||||
|
if(TARGET KF5::Purpose)
|
||||||
|
function(add_share_plugin name)
|
||||||
|
kcoreaddons_add_plugin(${name} SOURCES ${ARGN} INSTALL_NAMESPACE "kf5/purpose")
|
||||||
|
target_link_libraries(${name} Qt5::Core KF5::Purpose)
|
||||||
|
set_target_properties(${name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/kf5/purpose")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
add_share_plugin(neochatpurposeplugin neochatpurposeplugin.cpp)
|
||||||
|
target_link_libraries(neochatpurposeplugin KF5::I18n KF5::Service)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
if(NEOCHAT_FLATPAK)
|
if(NEOCHAT_FLATPAK)
|
||||||
target_compile_definitions(neochat PRIVATE NEOCHAT_FLATPAK)
|
target_compile_definitions(neochat PRIVATE NEOCHAT_FLATPAK)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -106,7 +106,20 @@ void ActionsHandler::postMessage(const QString &text,
|
|||||||
CustomEmojiModel *cem)
|
CustomEmojiModel *cem)
|
||||||
{
|
{
|
||||||
QString rawText = text;
|
QString rawText = text;
|
||||||
QString cleanedText = text;
|
auto stringList = text.split(QStringLiteral("```"));
|
||||||
|
QString cleanedText;
|
||||||
|
const auto count = stringList.count();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
if (i + 1 != count) {
|
||||||
|
cleanedText += stringList[i].toHtmlEscaped() + QStringLiteral("```");
|
||||||
|
} else {
|
||||||
|
cleanedText += stringList[i].toHtmlEscaped();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cleanedText += stringList[i] + QStringLiteral("```");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto preprocess = [cem](const QString &it) -> QString {
|
auto preprocess = [cem](const QString &it) -> QString {
|
||||||
if (cem == nullptr) {
|
if (cem == nullptr) {
|
||||||
|
|||||||
16
src/joinrulesevent.cpp
Normal file
16
src/joinrulesevent.cpp
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2019 Kitsune Ral <Kitsune-Ral@users.sf.net>
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
#include "joinrulesevent.h"
|
||||||
|
|
||||||
|
using namespace Quotient;
|
||||||
|
|
||||||
|
QString JoinRulesEvent::joinRule() const
|
||||||
|
{
|
||||||
|
return fromJson<QString>(contentJson()["join_rule"_ls]);
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray JoinRulesEvent::allow() const
|
||||||
|
{
|
||||||
|
return contentJson()["allow"_ls].toArray();
|
||||||
|
}
|
||||||
29
src/joinrulesevent.h
Normal file
29
src/joinrulesevent.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2021 Carl Schwan <carl@carlschwan.eu>
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <events/stateevent.h>
|
||||||
|
#include <quotient_common.h>
|
||||||
|
|
||||||
|
namespace Quotient
|
||||||
|
{
|
||||||
|
class JoinRulesEvent : public StateEventBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DEFINE_EVENT_TYPEID("m.room.join_rules", JoinRulesEvent)
|
||||||
|
|
||||||
|
explicit JoinRulesEvent()
|
||||||
|
: StateEventBase(typeId(), matrixTypeId())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
explicit JoinRulesEvent(const QJsonObject &obj)
|
||||||
|
: StateEventBase(typeId(), obj)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString joinRule() const;
|
||||||
|
QJsonArray allow() const;
|
||||||
|
};
|
||||||
|
REGISTER_EVENT_TYPE(JoinRulesEvent)
|
||||||
|
} // namespace Quotient
|
||||||
@@ -44,6 +44,7 @@
|
|||||||
#include "devicesmodel.h"
|
#include "devicesmodel.h"
|
||||||
#include "emojimodel.h"
|
#include "emojimodel.h"
|
||||||
#include "filetypesingleton.h"
|
#include "filetypesingleton.h"
|
||||||
|
#include "joinrulesevent.h"
|
||||||
#include "login.h"
|
#include "login.h"
|
||||||
#include "matriximageprovider.h"
|
#include "matriximageprovider.h"
|
||||||
#include "messageeventmodel.h"
|
#include "messageeventmodel.h"
|
||||||
|
|||||||
@@ -48,6 +48,9 @@
|
|||||||
<entry name="RoomListPageWidth" type="int">
|
<entry name="RoomListPageWidth" type="int">
|
||||||
<default>-1</default>
|
<default>-1</default>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry name="RoomDrawerWidth" type="int">
|
||||||
|
<default>-1</default>
|
||||||
|
</entry>
|
||||||
</group>
|
</group>
|
||||||
<group name="Timeline">
|
<group name="Timeline">
|
||||||
<entry name="ShowAvatarInTimeline" type="bool">
|
<entry name="ShowAvatarInTimeline" type="bool">
|
||||||
|
|||||||
54
src/neochatpurposeplugin.cpp
Normal file
54
src/neochatpurposeplugin.cpp
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2021 Carl Schwan <carl@carlschwan.eu>
|
||||||
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
#include <purpose/pluginbase.h>
|
||||||
|
|
||||||
|
#include <KApplicationTrader>
|
||||||
|
#include <KLocalizedString>
|
||||||
|
#include <KPluginFactory>
|
||||||
|
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QUrlQuery>
|
||||||
|
|
||||||
|
EXPORT_SHARE_VERSION
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class NeoChatShareJob : public Purpose::Job
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit NeoChatShareJob(QObject *parent = nullptr)
|
||||||
|
: Purpose::Job(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void start() override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class Q_DECL_EXPORT NeoChatPurposePlugin : public Purpose::PluginBase
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
NeoChatPurposePlugin(QObject *parent, const QVariantList &)
|
||||||
|
: Purpose::PluginBase(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Purpose::Job *createJob() const override
|
||||||
|
{
|
||||||
|
return new NeoChatShareJob(nullptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
K_PLUGIN_CLASS_WITH_JSON(NeoChatPurposePlugin, "neochatpurposeplugin.json")
|
||||||
|
|
||||||
|
#include "neochatpurposeplugin.moc"
|
||||||
|
|
||||||
22
src/neochatpurposeplugin.json
Normal file
22
src/neochatpurposeplugin.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"KPlugin": {
|
||||||
|
"Authors": [
|
||||||
|
{
|
||||||
|
"Name": "Carl Schwan"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Category": "Utilities",
|
||||||
|
|
||||||
|
"Description": "Send vith NeoChat",
|
||||||
|
"Icon": "mail-message",
|
||||||
|
"License": "GPL",
|
||||||
|
"Name": "Send with NeoChat",
|
||||||
|
"X-Purpose-ActionDisplay": "Send with NeoChat..."
|
||||||
|
},
|
||||||
|
"X-Purpose-Configuration": [],
|
||||||
|
"X-Purpose-Constraints": [],
|
||||||
|
"X-Purpose-PluginTypes": [
|
||||||
|
"Export",
|
||||||
|
"ShareUrl"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -462,6 +462,9 @@ QString NeoChatRoom::eventToString(const RoomEvent &evt, Qt::TextFormat format,
|
|||||||
return e.isUpgrade() ? i18n("upgraded the room to version %1", e.version().isEmpty() ? "1" : e.version().toHtmlEscaped())
|
return e.isUpgrade() ? i18n("upgraded the room to version %1", e.version().isEmpty() ? "1" : e.version().toHtmlEscaped())
|
||||||
: i18n("created the room, version %1", e.version().isEmpty() ? "1" : e.version().toHtmlEscaped());
|
: i18n("created the room, version %1", e.version().isEmpty() ? "1" : e.version().toHtmlEscaped());
|
||||||
},
|
},
|
||||||
|
[](const RoomPowerLevelsEvent &) {
|
||||||
|
return i18nc("'power level' means permission level", "changed the power levels for this room");
|
||||||
|
},
|
||||||
[](const StateEventBase &e) {
|
[](const StateEventBase &e) {
|
||||||
if (e.matrixType() == QLatin1String("m.room.server_acl")) {
|
if (e.matrixType() == QLatin1String("m.room.server_acl")) {
|
||||||
return i18n("changed the server access control lists for this room");
|
return i18n("changed the server access control lists for this room");
|
||||||
@@ -732,6 +735,11 @@ void NeoChatRoom::deleteMessagesByUser(const QString &user)
|
|||||||
doDeleteMessagesByUser(user);
|
doDeleteMessagesByUser(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString NeoChatRoom::joinRule() const
|
||||||
|
{
|
||||||
|
return getCurrentState<JoinRulesEvent>()->joinRule();
|
||||||
|
}
|
||||||
|
|
||||||
QCoro::Task<void> NeoChatRoom::doDeleteMessagesByUser(const QString &user)
|
QCoro::Task<void> NeoChatRoom::doDeleteMessagesByUser(const QString &user)
|
||||||
{
|
{
|
||||||
QStringList events;
|
QStringList events;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "joinrulesevent.h"
|
||||||
#include <events/encryptionevent.h>
|
#include <events/encryptionevent.h>
|
||||||
#include <events/redactionevent.h>
|
#include <events/redactionevent.h>
|
||||||
#include <events/roomavatarevent.h>
|
#include <events/roomavatarevent.h>
|
||||||
@@ -33,6 +34,7 @@ class NeoChatRoom : public Room
|
|||||||
Q_PROPERTY(bool readMarkerLoaded READ readMarkerLoaded NOTIFY readMarkerLoadedChanged)
|
Q_PROPERTY(bool readMarkerLoaded READ readMarkerLoaded NOTIFY readMarkerLoadedChanged)
|
||||||
Q_PROPERTY(QDateTime lastActiveTime READ lastActiveTime NOTIFY lastActiveTimeChanged)
|
Q_PROPERTY(QDateTime lastActiveTime READ lastActiveTime NOTIFY lastActiveTimeChanged)
|
||||||
Q_PROPERTY(bool isInvite READ isInvite NOTIFY isInviteChanged)
|
Q_PROPERTY(bool isInvite READ isInvite NOTIFY isInviteChanged)
|
||||||
|
Q_PROPERTY(QString joinRule READ joinRule CONSTANT)
|
||||||
Q_PROPERTY(QString htmlSafeDisplayName READ htmlSafeDisplayName NOTIFY displayNameChanged)
|
Q_PROPERTY(QString htmlSafeDisplayName READ htmlSafeDisplayName NOTIFY displayNameChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -66,6 +68,8 @@ public:
|
|||||||
|
|
||||||
bool isEventHighlighted(const Quotient::RoomEvent *e) const;
|
bool isEventHighlighted(const Quotient::RoomEvent *e) const;
|
||||||
|
|
||||||
|
[[nodiscard]] QString joinRule() const;
|
||||||
|
|
||||||
[[nodiscard]] bool hasFileUploading() const
|
[[nodiscard]] bool hasFileUploading() const
|
||||||
{
|
{
|
||||||
return m_hasFileUploading;
|
return m_hasFileUploading;
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ QVariant UserListModel::data(const QModelIndex &index, int role) const
|
|||||||
return UserType::Member;
|
return UserType::Member;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userPl < pl->powerLevelForState("m.room.message")) {
|
if (userPl < pl->powerLevelForEvent("m.room.message")) {
|
||||||
return UserType::Muted;
|
return UserType::Muted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user