Compare commits

...

31 Commits

Author SHA1 Message Date
Tobias Fella
8e906bb043 Import libQuotient QML module where necessary 2026-02-09 21:08:08 -05:00
Joshua Goins
15019d79fc Port to the new libquotient QML module
This removes our weird hacky QML thing for accessing JoinRule, and
switches to the much more elaborate QML module in libQuotient.
2026-02-09 21:08:08 -05:00
Joshua Goins
806e24c370 Bump libQuotient requirement to 0.10.0
Needed for the new QML module.
2026-02-09 21:08:08 -05:00
l10n daemon script
44f78353ab GIT_SILENT Sync po/docbooks with svn 2026-02-10 01:45:39 +00:00
l10n daemon script
3b2df95df7 GIT_SILENT Sync po/docbooks with svn 2026-02-09 01:43:37 +00:00
James Graham
8edb248647 Fix use after free in message delegate. We can't delete the incubator in the completed callback because it then returns to the incubator we just deleted. 2026-02-08 18:21:12 +00:00
l10n daemon script
07bc06f4ff GIT_SILENT Sync po/docbooks with svn 2026-02-08 01:44:05 +00:00
l10n daemon script
0d9988013b GIT_SILENT Sync po/docbooks with svn 2026-02-07 01:44:26 +00:00
Tobias Fella
c1720bbaa7 Fix various qml warnings 2026-02-06 14:45:03 +01:00
Tobias Fella
692ce82717 Fix minor warnings 2026-02-06 14:19:08 +01:00
Tobias Fella
ac04fa6a13 Fixes 2026-02-06 14:18:54 +01:00
Tobias Fella
39aaced0f9 Fix unqualified access 2026-02-06 14:17:55 +01:00
Tobias Fella
9887665560 Prevent shadowing 2026-02-06 14:17:20 +01:00
Tobias Fella
c590cb76a0 Use Application.layoutDirection 2026-02-06 14:14:31 +01:00
Tobias Fella
f9b0c56fa0 Prevent shadowing 2026-02-06 14:12:55 +01:00
Tobias Fella
aa7ab6b2ec Fix minor warnings 2026-02-06 14:12:24 +01:00
Tobias Fella
ac6a5663a1 Use required properties 2026-02-06 14:11:23 +01:00
Tobias Fella
f09dc79995 Remove unused import 2026-02-06 14:09:34 +01:00
Tobias Fella
693b2e74fe SupportDialog: Set ComponentBehavior 2026-02-06 14:07:08 +01:00
Tobias Fella
3a54d58516 Fix pageStack warnings 2026-02-06 14:05:23 +01:00
Tobias Fella
6abb117989 Set componentBehavior 2026-02-06 14:03:47 +01:00
Tobias Fella
b2dee6a96b Fix unqualified access 2026-02-06 14:02:41 +01:00
Tobias Fella
1e1ba1dca3 Cast qml object where necessary 2026-02-06 13:58:55 +01:00
Tobias Fella
55676b06c2 QrScannerPage: Prevent shadowing 2026-02-06 13:57:20 +01:00
Tobias Fella
513496cf85 Add translation context 2026-02-06 13:56:26 +01:00
Tobias Fella
69215401dd Use let instead of var 2026-02-06 13:55:45 +01:00
Tobias Fella
d5ec37e1af Fix some unqualified access warnings 2026-02-06 13:53:20 +01:00
Tobias Fella
6a45e2532c Prevent more shadowing 2026-02-06 13:50:40 +01:00
Tobias Fella
322926e31c Remove invalid anchors 2026-02-06 13:49:44 +01:00
Tobias Fella
29592a7f92 Prevent shadowing 2026-02-06 13:48:54 +01:00
Tobias Fella
8fc8baa2d2 Fix a few minor qml warnings 2026-02-06 12:53:07 +01:00
97 changed files with 8475 additions and 8388 deletions

View File

@@ -106,7 +106,7 @@ if (NOT ANDROID AND NOT WIN32 AND NOT APPLE AND NOT HAIKU)
find_package(KF6DBusAddons ${KF_MIN_VERSION} REQUIRED)
endif()
find_package(QuotientQt6 0.9.3)
find_package(QuotientQt6 0.10.0)
set_package_properties(QuotientQt6 PROPERTIES
TYPE REQUIRED
DESCRIPTION "Qt wrapper around Matrix API"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -227,7 +227,6 @@ int main(int argc, char *argv[])
Registration::instance().setAccountManager(accountManager.get());
qml_register_types_org_kde_neochat();
qmlRegisterUncreatableMetaObject(Quotient::staticMetaObject, "Quotient", 1, 0, "JoinRule", u"Access to JoinRule enum only"_s);
QQmlApplicationEngine engine;

View File

@@ -97,9 +97,9 @@ KirigamiComponents.ConvergentContextMenu {
text: i18nc("@action:inmenu Open support dialog", "Support")
icon.name: "help-contents-symbolic"
onTriggered: {
Qt.createComponent("org.kde.neochat", "SupportDialog").createObject(QQC2.Overlay.overlay, {
(Qt.createComponent("org.kde.neochat", "SupportDialog").createObject(QQC2.Overlay.overlay, {
connection: root.connection,
}).open();
}) as SupportDialog).open();
}
}

View File

@@ -4,9 +4,6 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import org.kde.kirigami as Kirigami
import org.kde.neochat

View File

@@ -79,7 +79,7 @@ Components.AbstractMaximizeComponent {
QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff
QQC2.TextArea {
id: codeText
id: codeTextEdit
topPadding: Kirigami.Units.smallSpacing
bottomPadding: Kirigami.Units.smallSpacing
leftPadding: lineNumberColumn.width + lineNumberColumn.anchors.leftMargin + Kirigami.Units.smallSpacing * 2
@@ -100,15 +100,15 @@ Components.AbstractMaximizeComponent {
SyntaxHighlighter {
property string definitionName: Repository.definitionForName(root.language).name
textEdit: definitionName == "None" ? null : codeText
textEdit: definitionName == "None" ? null : codeTextEdit
definition: definitionName
}
ColumnLayout {
id: lineNumberColumn
anchors {
top: codeText.top
topMargin: codeText.topPadding + 1
left: codeText.left
top: codeTextEdit.top
topMargin: codeTextEdit.topPadding + 1
left: codeTextEdit.left
leftMargin: Kirigami.Units.smallSpacing
}
spacing: 0
@@ -116,7 +116,7 @@ Components.AbstractMaximizeComponent {
id: repeater
model: LineModel {
id: lineModel
Component.onCompleted: setDocument(codeText.textDocument)
Component.onCompleted: setDocument(codeTextEdit.textDocument)
}
delegate: QQC2.Label {
id: label

View File

@@ -3,8 +3,6 @@
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts
import QtQml.Models
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.labs.components as KirigamiComponents

View File

@@ -41,13 +41,11 @@ ColumnLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
QQC2.Button {
anchors.bottom: parent.bottom
text: i18n("They match")
icon.name: "dialog-ok"
onClicked: root.accept()
}
QQC2.Button {
anchors.bottom: parent.bottom
text: i18n("They don't match")
icon.name: "dialog-cancel"
onClicked: root.reject()

View File

@@ -9,8 +9,6 @@ import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.delegates as Delegates
import org.kde.kirigamiaddons.labs.components as Components
import org.kde.neochat
Delegates.RoundedItemDelegate {
id: root

View File

@@ -166,7 +166,7 @@ ColumnLayout {
}
RowLayout {
visible: root.currentRoom.connection.canCheckMutualRooms
visible: (root.currentRoom.connection as NeoChatConnection).canCheckMutualRooms
spacing: 0
Layout.topMargin: Kirigami.Units.largeSpacing * 2

View File

@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts
@@ -8,8 +10,8 @@ import QtQuick.Window
import QtQml
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.delegates as Delegates
import org.kde.neochat
import io.github.quotient_im.libquotient
Kirigami.Page {
id: root

View File

@@ -2,8 +2,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtLocation
import QtPositioning

View File

@@ -100,7 +100,7 @@ Kirigami.ApplicationWindow {
function onCurrentRoomChanged() {
if (RoomManager.currentRoom && root.pageStack.depth <= 1 && root.initialized && Kirigami.Settings.isMobile) {
let roomPage = pageStack.push(Qt.createComponent('org.kde.neochat', 'RoomPage'));
let roomPage = root.pageStack.push(Qt.createComponent('org.kde.neochat', 'RoomPage'));
roomPage.forceActiveFocus();
roomPage.backRequested.connect(event => {
RoomManager.clearCurrentRoom();
@@ -151,8 +151,6 @@ Kirigami.ApplicationWindow {
}
contextDrawer: RoomDrawer {
id: contextDrawer
// This is a memory for all user initiated actions on the drawer, i.e. clicking the button
// It is used to ensure that user choice is remembered when changing pages and expanding and contracting the window width
property bool drawerUserState: NeoChatConfig.autoRoomInfoDrawer
@@ -178,9 +176,9 @@ Kirigami.ApplicationWindow {
// Connect to the onClicked function of the RoomDrawer handle button
Connections {
target: contextDrawer.handle.children[0]
target: root.contextDrawer.handle.children[0]
function onClicked() {
contextDrawer.drawerUserState = contextDrawer.drawerOpen;
root.contextDrawer.drawerUserState = root.contextDrawer.drawerOpen;
}
}

View File

@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
// SPDX-License-Identifier: GPL-3.0-only
pragma ComponentBehavior: Bound
import QtQuick
import org.kde.kirigami as Kirigami
@@ -16,7 +18,7 @@ Kirigami.PromptDialog {
customFooterActions: Kirigami.Action {
icon.name: "camera-video-symbolic"
text: hasExistingMeeting ? i18nc("@action:button Join the Jitsi meeting", "Join") : i18nc("@action:button Start a new Jitsi meeting", "Start")
text: root.hasExistingMeeting ? i18nc("@action:button Join the Jitsi meeting", "Join") : i18nc("@action:button Start a new Jitsi meeting", "Start")
onTriggered: root.accept()
}
}

View File

@@ -66,7 +66,7 @@ Kirigami.Dialog {
id: optionModel
readonly property bool allValuesSet: {
for( var i = 0; i < optionModel.rowCount(); i++ ) {
for (let i = 0; i < optionModel.rowCount(); i++) {
if (optionModel.get(i).optionText.length <= 0) {
return false;
}
@@ -83,7 +83,7 @@ Kirigami.Dialog {
function values() {
let textValues = []
for( var i = 0; i < optionModel.rowCount(); i++ ) {
for(let i = 0; i < optionModel.rowCount(); i++) {
textValues.push(optionModel.get(i).optionText);
}
return textValues;

View File

@@ -18,7 +18,7 @@ Kirigami.Page {
required property NeoChatConnection connection
padding: 0
Component.onCompleted: camera.start()
Component.onCompleted: session.camera.start()
Connections {
target: root.QQC2.ApplicationWindow.window
@@ -66,12 +66,8 @@ Kirigami.Page {
CaptureSession {
id: session
camera: Camera {
id: camera
}
imageCapture: ImageCapture {
id: imageCapture
}
camera: Camera {}
imageCapture: ImageCapture {}
videoOutput: viewFinder
}
}

View File

@@ -30,7 +30,7 @@ Kirigami.Page {
type: Kirigami.MessageType.Information
position: Kirigami.InlineMessage.Position.Header
text: xi18n("This report will <strong>only</strong> be sent to the administrators of <link>%1</link> (your server).", root.connection.domain)
text: xi18nc("@info", "This report will <strong>only</strong> be sent to the administrators of <link>%1</link> (your server).", root.connection.domain)
}
QQC2.TextArea {

View File

@@ -104,8 +104,8 @@ Kirigami.Page {
enabled: hasExistingMeeting || canStartNewMeeting
visible: root.currentRoom && !root.currentRoom.isSpace
onTriggered: {
const dialog = Qt.createComponent("org.kde.neochat", "MeetingDialog").createObject(QQC2.Overlay.overlay, { hasExistingMeeting });
dialog.onAccepted.connect(doAction);
const dialog = Qt.createComponent("org.kde.neochat", "MeetingDialog").createObject(QQC2.Overlay.overlay, { hasExistingMeeting }) as MeetingDialog;
dialog.accepted.connect(doAction);
dialog.open();
}
@@ -215,7 +215,7 @@ Kirigami.Page {
}
TapHandler {
onTapped: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'RoomPinnedMessagesPage'), {
onTapped: (root.Kirigami.PageStack.pageStack as Kirigami.PageRow).pushDialogLayer(Qt.createComponent('org.kde.neochat', 'RoomPinnedMessagesPage'), {
room: root.currentRoom
}, {
title: i18nc("@title", "Pinned Messages")

View File

@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2026 Joshua Goins <josh@redstrate.com>
// SPDX-License-Identifier: GPL-3.0-only
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts

View File

@@ -8,7 +8,6 @@ import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.components as KirigamiComponents
import org.kde.kirigamiaddons.formcard as FormCard
import org.kde.prison
import org.kde.neochat

View File

@@ -5,6 +5,7 @@ import QtQuick
import QtQml
import org.kde.neochat
import io.github.quotient_im.libquotient
VerificationMessage {
id: root

View File

@@ -40,9 +40,11 @@ ColumnLayout {
model: root.connection.getSupportedRoomVersions()
delegate: FormCard.FormTextDelegate {
id: versionDelegate
required property var modelData
text: modelData.id
contentItem.children: QQC2.Label {
text: modelData.status
text: versionDelegate.modelData.status
color: Kirigami.Theme.disabledTextColor
}
}

View File

@@ -108,7 +108,7 @@ SearchPage {
id: _private
function openManualUserDialog(): void {
let dialog = manualUserDialog.createObject(this, {
connection: root.connection
connection: root.room.connection
}) as ManualUserDialog;
dialog.parent = root.Window.window.overlay;
dialog.accepted.connect(() => {

View File

@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Qt.labs.qmlmodels

View File

@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
pragma ComponentBehavior: Bound
import QtCore
import QtQuick
import QtQuick.Controls as QQC2
@@ -34,7 +36,7 @@ QQC2.Control {
Layout.fillWidth: true
Layout.margins: Kirigami.Units.largeSpacing
Layout.preferredHeight: active ? item.implicitHeight : 0
Layout.preferredHeight: active ? (item as Item).implicitHeight : 0
active: visible
visible: root.chatBarCache.replyId.length > 0 || root.chatBarCache.attachmentPath.length > 0
@@ -71,7 +73,7 @@ QQC2.Control {
root.chatBarCache.text = text;
}
Keys.onEnterPressed: {
Keys.onEnterPressed: event => {
if (completionMenu.visible) {
completionMenu.complete();
} else if (event.modifiers & Qt.ShiftModifier) {
@@ -80,7 +82,7 @@ QQC2.Control {
_private.post();
}
}
Keys.onReturnPressed: {
Keys.onReturnPressed: event => {
if (completionMenu.visible) {
completionMenu.complete();
} else if (event.modifiers & Qt.ShiftModifier) {
@@ -108,7 +110,7 @@ QQC2.Control {
height: implicitHeight
y: -height - 5
z: 10
connection: root.Message.room.connection
connection: root.Message.room.connection as NeoChatConnection
chatDocumentHandler: documentHandler
margins: 0
Behavior on height {
@@ -165,7 +167,7 @@ QQC2.Control {
text: i18nc("@action:button", "Attach an image or file")
icon.name: "mail-attachment"
onClicked: {
let dialog = (Clipboard.hasImage ? attachDialog : openFileDialog).createObject(QQC2.Overlay.overlay);
let dialog = (Clipboard.hasImage ? attachDialog : openFileDialog).createObject(QQC2.Overlay.overlay) as QQC2.Dialog;
dialog.chosen.connect(path => root.chatBarCache.attachmentPath = path);
dialog.open();
}
@@ -225,8 +227,6 @@ QQC2.Control {
Message.maxContentWidth: paneLoader.item.width
}
QQC2.Button {
id: cancelButton
anchors.top: parent.top
anchors.right: parent.right
@@ -261,9 +261,9 @@ QQC2.Control {
function updateText() {
// This could possibly be undefined due to some esoteric QtQuick issue. Referencing it somewhere in JS is enough.
documentHandler.document;
if (chatBarCache?.isEditing && chatBarCache.relationMessage.length > 0) {
textArea.text = chatBarCache.relationMessage;
documentHandler.updateMentions(chatBarCache.editId);
if (root.chatBarCache?.isEditing && root.chatBarCache.relationMessage.length > 0) {
textArea.text = root.chatBarCache.relationMessage;
documentHandler.updateMentions(root.chatBarCache.editId);
textArea.forceActiveFocus();
textArea.cursorPosition = textArea.text.length;
}

View File

@@ -2,12 +2,13 @@
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-3.0-only
pragma ComponentBehavior: Bound
import QtCore as Core
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts
import QtQuick.Dialogs as Dialogs
import Qt.labs.qmlmodels
import org.kde.coreaddons
import org.kde.kirigami as Kirigami
@@ -51,7 +52,7 @@ ColumnLayout {
property bool autoOpenFile: false
function saveFileAs() {
const dialog = fileDialog.createObject(QQC2.Overlay.overlay);
const dialog = fileDialog.createObject(QQC2.Overlay.overlay) as Dialogs.FileDialog;
dialog.selectedFile = Message.room.fileNameToDownload(root.eventId);
dialog.open();
}
@@ -70,7 +71,7 @@ ColumnLayout {
states: [
State {
name: "downloadedInstant"
when: root.fileTransferInfo.completed && autoOpenFile
when: root.fileTransferInfo.completed && root.autoOpenFile
PropertyChanges {
openButton.icon.name: "document-open"
@@ -84,7 +85,7 @@ ColumnLayout {
},
State {
name: "downloaded"
when: root.fileTransferInfo.completed && !autoOpenFile
when: root.fileTransferInfo.completed && !root.autoOpenFile
PropertyChanges {
openButton.visible: false
@@ -138,7 +139,7 @@ ColumnLayout {
id: openButton
icon.name: "document-open"
onClicked: {
autoOpenFile = true;
root.autoOpenFile = true;
root.Message.room.downloadTempFile(root.eventId);
}
@@ -166,7 +167,7 @@ ColumnLayout {
onAccepted: {
NeoChatConfig.lastSaveDirectory = currentFolder;
NeoChatConfig.save();
if (autoOpenFile) {
if (root.autoOpenFile) {
UrlHelper.copyTo(root.fileTransferInfo.localPath, selectedFile);
} else {
root.Message.room.download(root.eventId, selectedFile);

View File

@@ -40,7 +40,7 @@ ColumnLayout {
Layout.maximumWidth: Message.maxContentWidth
LiveLocationsModel {
id: liveLocationModel
id: locationModel
eventId: root.eventId
room: Message.room
}
@@ -50,13 +50,13 @@ ColumnLayout {
Layout.preferredWidth: root.Message.maxContentWidth
Layout.preferredHeight: root.Message.maxContentWidth / 16 * 9
map.center: QtPositioning.coordinate(liveLocationModel.boundingBox.y, liveLocationModel.boundingBox.x)
map.center: QtPositioning.coordinate(locationModel.boundingBox.y, locationModel.boundingBox.x)
map.zoomLevel: 15
map.plugin: OsmLocationPlugin.plugin
MapItemView {
model: liveLocationModel
model: locationModel
delegate: LocationMapItem {}
}
@@ -64,7 +64,7 @@ ColumnLayout {
acceptedButtons: Qt.LeftButton
onTapped: {
fullScreenMap.createObject(parent, {
liveLocationModel: liveLocationModel
liveLocationModel: locationModel
})
}
}

View File

@@ -2,9 +2,10 @@
// SPDX-FileCopyrightText: 2020 Carl Schwan <carl@carlschwan.eu>
// SPDX-License-Identifier: GPL-3.0-only
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
@@ -102,7 +103,7 @@ Flow {
}
onClicked: {
var dialog = emojiDialog.createObject(reactButton);
var dialog = emojiDialog.createObject(reactButton) as EmojiDialog;
dialog.showStickers = false;
dialog.chosen.connect(emoji => {
root.Message.room.toggleReaction(root.eventId, emoji);

View File

@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Qt.labs.qmlmodels
@@ -117,6 +119,7 @@ DelegateChooser {
DelegateChoice {
roleValue: MessageComponentType.Location
delegate: MimeComponent {
required property string display
mimeIconSource: "mark-location"
label: display
}
@@ -125,6 +128,7 @@ DelegateChooser {
DelegateChoice {
roleValue: MessageComponentType.LiveLocation
delegate: MimeComponent {
required property string display
mimeIconSource: "mark-location"
label: display
}

View File

@@ -2,6 +2,8 @@
// SPDX-FileCopyrightText: 2020 Carl Schwan <carl@carlschwan.eu>
// SPDX-License-Identifier: GPL-3.0-only
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts
@@ -59,7 +61,7 @@ Kirigami.OverlayDrawer {
if (_lastX === -1) {
return;
}
if (Qt.application.layoutDirection === Qt.RightToLeft) {
if (Application.layoutDirection === Qt.RightToLeft) {
root.actualWidth = Math.min(root.maxWidth, Math.max(root.minWidth, root.roomDrawerWidth - _lastX + mapToGlobal(mouseX, mouseY).x));
} else {
root.actualWidth = Math.min(root.maxWidth, Math.max(root.minWidth, root.roomDrawerWidth + _lastX - mapToGlobal(mouseX, mouseY).x));
@@ -68,7 +70,7 @@ Kirigami.OverlayDrawer {
}
enabled: true
edge: Qt.application.layoutDirection == Qt.RightToLeft ? Qt.LeftEdge : Qt.RightEdge
edge: Application.layoutDirection == Qt.RightToLeft ? Qt.LeftEdge : Qt.RightEdge
// If modal has been changed and the drawer is closed automatically then dim on popup open will have been switched off in main.qml so switch it back on after the animation completes.
// This is to avoid dim being active for a split second when the drawer is switched to modal which looks terrible.

View File

@@ -1,8 +1,9 @@
// SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
@@ -103,7 +104,7 @@ Kirigami.Page {
Connections {
target: root.Kirigami.PageStack.pageStack
onWideModeChanged: {
function onWideModeChanged(): void {
if ((root.Kirigami.PageStack.pageStack as Kirigami.PageRow).wideMode) {
root.Kirigami.PageStack.pop();
}

View File

@@ -9,7 +9,7 @@ import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.components as KirigamiComponents
import Quotient
import io.github.quotient_im.libquotient
import org.kde.neochat
import org.kde.neochat.settings
@@ -126,7 +126,7 @@ KirigamiComponents.ConvergentContextMenu {
Kirigami.Action {
text: i18nc("@action:inmenu", "Copy Room Link")
icon.name: "edit-copy"
visible: !root.room.isDirectChat() && root.room.joinRule !== JoinRule.Invite
visible: !root.room.isDirectChat() && root.room.joinRule !== Quotient.JoinRule.Invite
onTriggered: {
// The canonical alias (if it exists) otherwise the first available alias
const firstAlias = root.room.aliases[0];

View File

@@ -46,7 +46,6 @@ QQC2.Control {
}
ColumnLayout {
id: column
width: scrollView.width
spacing: 0

View File

@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2020 Tobias Fella <tobias.fella@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts
@@ -28,7 +30,7 @@ FormCard.FormCardPage {
interval: 10
running: false
onTriggered: root.QQC2.ApplicationWindow.window.pageStack.layers.push(Qt.createComponent('org.kde.neochat.settings', 'AccountEditorPage'), {
connection: initialAccount
connection: root.initialAccount
}, {
title: i18n("Account editor")
})
@@ -44,7 +46,7 @@ FormCard.FormCardPage {
id: accountDelegate
required property NeoChatConnection connection
Layout.fillWidth: true
onClicked: root.QQC2.ApplicationWindow.window.pageStack.layers.push(Qt.createComponent('org.kde.neochat.settings', 'AccountEditorPage'), {
onClicked: (root.Kirigami.PageStack.pageStack as Kirigami.PageRow).layers.push(Qt.createComponent('org.kde.neochat.settings', 'AccountEditorPage'), {
connection: accountDelegate.connection
}, {
title: i18n("Account editor")
@@ -87,7 +89,7 @@ FormCard.FormCardPage {
QQC2.ToolButton {
text: i18n("Logout…")
icon.name: "im-kick-user"
onClicked: confirmLogoutDialogComponent.createObject(root.QQC2.Overlay.overlay).open()
onClicked: (confirmLogoutDialogComponent.createObject(root.QQC2.Overlay.overlay) as ConfirmLogoutDialog).open()
}
Component {
@@ -124,8 +126,8 @@ FormCard.FormCardPage {
property Connections connections: Connections {
target: Controller
function onConnectionAdded() {
if (pageStack.layers.depth > 2) {
pageStack.layers.pop();
if ((root.Kirigami.PageStack.pageStack as Kirigami.PageRow).layers.depth > 2) {
(root.Kirigami.PageStack.pageStack as Kirigami.PageRow).layers.pop();
}
}
}

View File

@@ -24,7 +24,6 @@ FormCard.FormCardPage {
required property NeoChatConnection connection
property DevicesModel devicesModel: DevicesModel {
id: devicesModel
connection: root.connection
}
@@ -49,7 +48,7 @@ FormCard.FormCardPage {
standardButtons: Kirigami.Dialog.Ok
})
dialog.open();
root.connection.onNewKeyVerificationSession.connect(() => {
root.connection.newKeyVerificationSession.connect(() => {
dialog.close();
});
}
@@ -76,7 +75,7 @@ FormCard.FormCardPage {
FormCard.AbstractFormDelegate {
Layout.fillWidth: true
visible: root.connection && devicesModel.count === 0 // We can assume 0 means loading since there is at least one device
visible: root.connection && root.devicesModel.count === 0 // We can assume 0 means loading since there is at least one device
contentItem: Kirigami.LoadingPlaceholder {}
}

View File

@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
pragma ComponentBehavior: Bound
import QtCore as Core
import QtQuick
import QtQuick.Controls as QQC2
@@ -27,7 +29,7 @@ FormCard.FormCardPage {
title: emoticonType === EmoticonFormCard.Stickers ? (newEmoticon ? i18nc("@title:window", "Add Sticker") : i18nc("@title:window", "Edit Sticker")) : (newEmoticon ? i18nc("@title:window", "Add Emoji") : i18nc("@title:window", "Edit Emoji"))
FormCard.FormHeader {
title: emoticonType === EmoticonFormCard.Stickers ? i18nc("@info:group", "Sticker") : i18nc("@info:group", "Emoji")
title: root.emoticonType === EmoticonFormCard.Stickers ? i18nc("@info:group", "Sticker") : i18nc("@info:group", "Emoji")
}
FormCard.FormCard {
FormCard.AbstractFormDelegate {
@@ -42,11 +44,9 @@ FormCard.FormCardPage {
source: root.url
sourceSize.width: Kirigami.Units.gridUnit * 4
sourceSize.height: Kirigami.Units.gridUnit * 4
width: Kirigami.Units.gridUnit * 4
height: Kirigami.Units.gridUnit * 4
Kirigami.Icon {
source: emoticonType === EmoticonFormCard.Stickers ? "stickers" : "preferences-desktop-emoticons"
source: root.emoticonType === EmoticonFormCard.Stickers ? "stickers" : "preferences-desktop-emoticons"
anchors.fill: parent
visible: parent.status !== Image.Ready
}
@@ -73,7 +73,7 @@ FormCard.FormCardPage {
if (fileDialog != null) {
return;
}
fileDialog = openFileDialog.createObject(QQC2.Overlay.overlay);
fileDialog = root.openFileDialog.createObject(QQC2.Overlay.overlay);
fileDialog.chosen.connect(function (receivedSource) {
mouseArea.fileDialog = null;
if (!receivedSource) {
@@ -94,12 +94,10 @@ FormCard.FormCardPage {
}
}
FormCard.FormTextFieldDelegate {
id: shortcode
label: i18n("Shortcode:")
text: root.shortcode
}
FormCard.FormTextFieldDelegate {
id: description
label: i18n("Description:")
text: root.description
}
@@ -107,19 +105,19 @@ FormCard.FormCardPage {
id: save
text: i18n("Save")
icon.name: "document-save"
enabled: !root.newEmoticon || (image.source.toString().length > 0 && shortcode.text && description.text)
enabled: !root.newEmoticon || (image.source.toString().length > 0 && root.shortcode && root.description)
onClicked: {
if (root.newEmoticon) {
model.addEmoticon(image.source, shortcode.text, description.text, emoticonType === EmoticonFormCard.Stickers ? "sticker" : "emoticon");
root.model.addEmoticon(image.source, root.shortcode, root.description, root.emoticonType === EmoticonFormCard.Stickers ? "sticker" : "emoticon");
} else {
if (description.text !== root.description) {
root.model.setEmoticonBody(proxyModel.mapToSource(proxyModel.index(model.index, 0)).row, description.text);
if (root.description !== root.description) {
root.model.setEmoticonBody(root.proxyModel.mapToSource(root.proxyModel.index(root.model.index, 0)).row, root.description);
}
if (shortcode.text !== root.shortcode) {
root.model.setEmoticonShortcode(proxyModel.mapToSource(proxyModel.index(model.index, 0)).row, shortcode.text);
if (root.shortcode !== root.shortcode) {
root.model.setEmoticonShortcode(root.proxyModel.mapToSource(root.proxyModel.index(root.model.index, 0)).row, root.shortcode);
}
if (image.source + "" !== root.url) {
root.model.setEmoticonImage(proxyModel.mapToSource(proxyModel.index(model.index, 0)).row, image.source);
root.model.setEmoticonImage(root.proxyModel.mapToSource(root.proxyModel.index(root.model.index, 0)).row, image.source);
}
}
root.closeDialog();
@@ -127,8 +125,6 @@ FormCard.FormCardPage {
}
}
property Component openFileDialog: Component {
id: openFileDialog
OpenFileDialog {
currentFolder: Core.StandardPaths.standardLocations(Core.StandardPaths.PicturesLocation)[0]
parentWindow: root.Window.window

View File

@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2022 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts
@@ -27,8 +29,8 @@ FormCard.FormCardPage {
FormCard.FormCheckDelegate {
text: i18n("Enable notifications for this account")
description: {
if (connection.pushNotificationsAvailable) {
if (connection.enablePushNotifications) {
if (root.connection.pushNotificationsAvailable) {
if (root.connection.enablePushNotifications) {
return i18n("Notifications can appear even when NeoChat isn't running.");
} else {
return i18n("Push notifications are available but could not be enabled.");
@@ -52,8 +54,6 @@ FormCard.FormCardPage {
spacing: Kirigami.Units.largeSpacing
Kirigami.Icon {
source: "data-information"
width: Kirigami.Units.iconSizes.sizeForLabels
height: Kirigami.Units.iconSizes.sizeForLabels
}
QQC2.Label {
text: i18nc("@info", "These are the default notification settings for all rooms. You can customize notifications per-room in the room list or room settings.")
@@ -78,7 +78,7 @@ FormCard.FormCardPage {
}
}
delegate: ruleDelegate
delegate: root.ruleDelegate
}
}
@@ -95,7 +95,7 @@ FormCard.FormCardPage {
}
}
delegate: ruleDelegate
delegate: root.ruleDelegate
}
}
@@ -113,7 +113,7 @@ FormCard.FormCardPage {
}
}
delegate: ruleDelegate
delegate: root.ruleDelegate
}
FormCard.AbstractFormDelegate {
Layout.fillWidth: true
@@ -176,7 +176,7 @@ FormCard.FormCardPage {
}
}
delegate: ruleDelegate
delegate: root.ruleDelegate
}
}
@@ -197,12 +197,11 @@ FormCard.FormCardPage {
}
}
delegate: ruleDelegate
delegate: root.ruleDelegate
}
}
property Component ruleDelegate: Component {
id: ruleDelegate
NotificationRuleItem {
onDeleteRule: {
root.pushRuleModel.removeKeyword(id);

View File

@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2024 Tobias Fella <tobias.fella@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts
@@ -37,6 +39,8 @@ FormCard.FormCardPage {
id: repeater
model: root.connection.ignoredUsers()
delegate: FormCard.AbstractFormDelegate {
id: ignoredUserDelegate
required property string modelData
topPadding: Kirigami.Units.smallSpacing
bottomPadding: Kirigami.Units.smallSpacing
@@ -46,7 +50,7 @@ FormCard.FormCardPage {
QQC2.Label {
Layout.fillWidth: true
text: modelData
text: ignoredUserDelegate.modelData
elide: Text.ElideRight
Accessible.ignored: true // base class sets this text on root already
}
@@ -54,7 +58,7 @@ FormCard.FormCardPage {
QQC2.ToolButton {
text: i18nc("@action:button", "Unignore this user")
icon.name: "list-remove-symbolic"
onClicked: root.connection.removeFromIgnoredUsers(modelData)
onClicked: root.connection.removeFromIgnoredUsers(ignoredUserDelegate.modelData)
display: QQC2.Button.IconOnly
QQC2.ToolTip.text: text
QQC2.ToolTip.visible: hovered

View File

@@ -2,13 +2,13 @@
// SPDX-License-Identifier: LGPL-2.0-or-later
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Dialogs
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.formcard as FormCard
import io.github.quotient_im.libquotient
import org.kde.neochat
FormCard.FormCardPage {

View File

@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts
@@ -57,9 +59,9 @@ FormCard.FormCardPage {
FormCard.FormCheckDelegate {
id: rejectInvitationsDelegate
text: i18nc("@option:check", "Reject invitations from unknown users")
description: connection.canCheckMutualRooms ? i18nc("@info", "If enabled, NeoChat will reject invitations from users you don't share a room with.") : i18nc("@info", "Your server does not support this setting.")
description: root.connection.canCheckMutualRooms ? i18nc("@info", "If enabled, NeoChat will reject invitations from users you don't share a room with.") : i18nc("@info", "Your server does not support this setting.")
checked: NeoChatConfig.rejectUnknownInvites
enabled: !NeoChatConfig.isRejectUnknownInvitesImmutable && connection.canCheckMutualRooms
enabled: !NeoChatConfig.isRejectUnknownInvitesImmutable && root.connection.canCheckMutualRooms
onToggled: {
NeoChatConfig.rejectUnknownInvites = checked;
NeoChatConfig.save();
@@ -74,7 +76,7 @@ FormCard.FormCardPage {
text: i18nc("@option:check", "Turn on encryption in new chats")
description: i18nc("@info", "If enabled, NeoChat will use encryption when starting new direct messages.")
checked: NeoChatConfig.preferUsingEncryption
enabled: !NeoChatConfig.preferUsingEncryptionImmutable
enabled: !NeoChatConfig.isPreferUsingEncryptionImmutable
onToggled: {
NeoChatConfig.preferUsingEncryption = checked;
NeoChatConfig.save();

View File

@@ -11,6 +11,8 @@ import org.kde.kirigamiaddons.formcard as FormCard
import org.kde.neochat
FormCard.FormCardPage {
id: root
title: i18nc("@title:window", "Proxy")
property int currentType
property bool proxyConfigChanged: false
@@ -21,10 +23,10 @@ FormCard.FormCardPage {
FormCard.FormRadioDelegate {
id: systemDefault
text: i18n("System Default")
checked: currentType === 0
checked: root.currentType === 0
enabled: !NeoChatConfig.isProxyTypeImmutable
onToggled: {
currentType = 0
root.currentType = 0
}
}
@@ -33,10 +35,10 @@ FormCard.FormCardPage {
FormCard.FormRadioDelegate {
id:noProxy
text: i18n("No Proxy")
checked: currentType === 3
enabled: !Config.isProxyTypeImmutable
checked: root.currentType === 3
enabled: !NeoChatConfig.isProxyTypeImmutable
onToggled: {
currentType = 3;
root.currentType = 3;
}
}
@@ -45,10 +47,10 @@ FormCard.FormCardPage {
FormCard.FormRadioDelegate {
id: http
text: i18n("HTTP")
checked: currentType === 1
checked: root.currentType === 1
enabled: !NeoChatConfig.isProxyTypeImmutable
onToggled: {
currentType = 1
root.currentType = 1
}
}
@@ -57,10 +59,10 @@ FormCard.FormCardPage {
FormCard.FormRadioDelegate {
id: socks5
text: i18n("Socks5")
checked: currentType === 2
checked: root.currentType === 2
enabled: !NeoChatConfig.isProxyTypeImmutable
onToggled: {
currentType = 2
root.currentType = 2
}
}
}
@@ -71,7 +73,7 @@ FormCard.FormCardPage {
FormCard.FormCard {
// It makes no sense to configure proxy settings for "System Default" and "No Proxy"
enabled: currentType !== 0 && currentType !== 3
enabled: root.currentType !== 0 && root.currentType !== 3
FormCard.FormTextFieldDelegate {
id: hostField
@@ -79,7 +81,7 @@ FormCard.FormCardPage {
text: NeoChatConfig.proxyHost
inputMethodHints: Qt.ImhUrlCharactersOnly
onEditingFinished: {
proxyConfigChanged = true
root.proxyConfigChanged = true
}
}
FormCard.FormDelegateSeparator { below: hostField; above: portField }
@@ -101,7 +103,7 @@ FormCard.FormCardPage {
return value // it will add a thousands separator if we don't do this, not sure why
}
onValueChanged: {
proxyConfigChanged = true
root.proxyConfigChanged = true
}
}
}
@@ -113,7 +115,7 @@ FormCard.FormCardPage {
text: NeoChatConfig.proxyUser
inputMethodHints: Qt.ImhUrlCharactersOnly
onEditingFinished: {
proxyConfigChanged = true
root.proxyConfigChanged = true
}
}
FormCard.FormDelegateSeparator { below: userField; above: passwordField }
@@ -124,7 +126,7 @@ FormCard.FormCardPage {
echoMode: TextInput.Password
inputMethodHints: Qt.ImhUrlCharactersOnly
onEditingFinished: {
proxyConfigChanged = true
root.proxyConfigChanged = true
}
}
}
@@ -139,15 +141,15 @@ FormCard.FormCardPage {
QQC2.Button {
text: i18n("Apply")
icon.name: "dialog-ok-apply-symbolic"
enabled: currentType !== NeoChatConfig.proxyType || proxyConfigChanged
enabled: root.currentType !== NeoChatConfig.proxyType || root.proxyConfigChanged
onClicked: {
NeoChatConfig.proxyType = currentType;
NeoChatConfig.proxyType = root.currentType;
NeoChatConfig.proxyHost = hostField.text;
NeoChatConfig.proxyPort = portField.value;
NeoChatConfig.proxyUser = userField.text;
NeoChatConfig.proxyPassword = passwordField.text;
NeoChatConfig.save();
proxyConfigChanged = false;
root.proxyConfigChanged = false;
ProxyController.setApplicationProxy();
}
}

View File

@@ -17,7 +17,7 @@ FormCard.FormCardPage {
property NeoChatRoom room
property PushRuleModel pushRuleModel: PushRuleModel {
connection: root.room.connection
connection: root.room.connection as NeoChatConnection
}
title: i18nc('@title:window', 'Notifications')
@@ -30,37 +30,37 @@ FormCard.FormCardPage {
FormCard.FormRadioDelegate {
icon.name: "globe"
text: i18nc("As in the default notification setting", "Default Settings")
checked: room.pushNotificationState === PushNotificationState.Default
enabled: room.pushNotificationState !== PushNotificationState.Unknown
checked: root.room.pushNotificationState === PushNotificationState.Default
enabled: root.room.pushNotificationState !== PushNotificationState.Unknown
onToggled: {
room.pushNotificationState = PushNotificationState.Default;
root.room.pushNotificationState = PushNotificationState.Default;
}
}
FormCard.FormRadioDelegate {
icon.name: "notifications"
text: i18nc("As in 'notify for all messages'", "All Messages")
checked: room.pushNotificationState === PushNotificationState.All
enabled: room.pushNotificationState !== PushNotificationState.Unknown
checked: root.room.pushNotificationState === PushNotificationState.All
enabled: root.room.pushNotificationState !== PushNotificationState.Unknown
onToggled: {
room.pushNotificationState = PushNotificationState.All;
root.room.pushNotificationState = PushNotificationState.All;
}
}
FormCard.FormRadioDelegate {
icon.name: "im-user"
text: i18nc("As in 'notify when the user is mentioned or the message contains a set keyword'", "@Mentions and Keywords")
checked: room.pushNotificationState === PushNotificationState.MentionKeyword
enabled: room.pushNotificationState !== PushNotificationState.Unknown
checked: root.room.pushNotificationState === PushNotificationState.MentionKeyword
enabled: root.room.pushNotificationState !== PushNotificationState.Unknown
onToggled: {
room.pushNotificationState = PushNotificationState.MentionKeyword;
root.room.pushNotificationState = PushNotificationState.MentionKeyword;
}
}
FormCard.FormRadioDelegate {
icon.name: "notifications-disabled"
text: i18nc("As in 'do not notify for any messages'", "None")
checked: room.pushNotificationState === PushNotificationState.Mute
enabled: room.pushNotificationState !== PushNotificationState.Unknown
checked: root.room.pushNotificationState === PushNotificationState.Mute
enabled: root.room.pushNotificationState !== PushNotificationState.Unknown
onToggled: {
room.pushNotificationState = PushNotificationState.Mute;
root.room.pushNotificationState = PushNotificationState.Mute;
}
}
}
@@ -80,16 +80,11 @@ FormCard.FormCardPage {
}
}
delegate: ruleDelegate
Component {
id: ruleDelegate
NotificationRuleItem {
onDeleteRule: {
root.pushRuleModel.removeKeyword(id);
}
onNotificatonActionChanged: action => root.pushRuleModel.setPushRuleAction(id, action)
delegate: NotificationRuleItem {
onDeleteRule: {
root.pushRuleModel.removeKeyword(id);
}
onNotificatonActionChanged: action => root.pushRuleModel.setPushRuleAction(id, action)
}
}
FormCard.AbstractFormDelegate {

View File

@@ -13,7 +13,7 @@ import org.kde.kirigamiaddons.formcard as FormCard
import org.kde.neochat
import Quotient
import io.github.quotient_im.libquotient
FormCard.FormCardPage {
id: root
@@ -65,23 +65,23 @@ FormCard.FormCardPage {
FormCard.FormRadioDelegate {
text: i18nc("@option:check", "Private (invite only)")
description: i18nc("@info", "Only invited people can join.")
checked: root.room.joinRule === JoinRule.Invite
checked: root.room.joinRule === Quotient.JoinRule.Invite
enabled: root.room.canSendState("m.room.join_rules")
onCheckedChanged: if (checked && root.room.joinRule != JoinRule.Invite) {
root.room.joinRule = JoinRule.Invite;
onCheckedChanged: if (checked && root.room.joinRule != Quotient.JoinRule.Invite) {
root.room.joinRule = Quotient.JoinRule.Invite;
}
}
FormCard.FormRadioDelegate {
text: i18nc("@option:check", "Space members")
description: i18nc("@info", "Anyone in the selected spaces can find and join.") + (!["8", "9", "10", "11", "12"].includes(root.room.version) ? `\n${root.needUpgradeRoom}` : "")
checked: root.room.joinRule === JoinRule.Restricted
checked: root.room.joinRule === Quotient.JoinRule.Restricted
enabled: root.room.canSendState("m.room.join_rules") && ["8", "9", "10", "11", "12"].includes(root.room.version)
onCheckedChanged: if (checked && root.room.joinRule != JoinRule.Restricted) {
onCheckedChanged: if (checked && root.room.joinRule != Quotient.JoinRule.Restricted) {
(selectSpacesDialog.createObject(QQC2.Overlay.overlay) as SelectSpacesDialog).open();
}
contentItem.children: QQC2.Button {
visible: root.room.joinRule === JoinRule.Restricted
visible: root.room.joinRule === Quotient.JoinRule.Restricted
text: i18nc("@action:button", "Select spaces")
icon.name: "list-add"
@@ -102,20 +102,20 @@ FormCard.FormCardPage {
FormCard.FormRadioDelegate {
text: i18nc("@option:check", "Knock")
description: i18nc("@info", "People not in the room need to request an invite to join the room.") + (!["7", "8", "9", "10", "11", "12"].includes(root.room.version) ? `\n${root.needUpgradeRoom}` : "")
checked: root.room.joinRule === JoinRule.Knock
checked: root.room.joinRule === Quotient.JoinRule.Knock
// https://spec.matrix.org/v1.4/rooms/#feature-matrix
enabled: root.room.canSendState("m.room.join_rules") && ["7", "8", "9", "10", "11", "12"].includes(root.room.version)
onCheckedChanged: if (checked && root.room.joinRule != JoinRule.Knock) {
root.room.joinRule = JoinRule.Knock;
onCheckedChanged: if (checked && root.room.joinRule != Quotient.JoinRule.Knock) {
root.room.joinRule = Quotient.JoinRule.Knock;
}
}
FormCard.FormRadioDelegate {
text: i18nc("@option:check", "Public")
description: i18nc("@option:check", "Anyone can find and join.")
checked: root.room.joinRule === JoinRule.Public
checked: root.room.joinRule === Quotient.JoinRule.Public
enabled: root.room.canSendState("m.room.join_rules")
onCheckedChanged: if (checked && root.room.joinRule != JoinRule.Public) {
root.room.joinRule = JoinRule.Public;
onCheckedChanged: if (checked && root.room.joinRule != Quotient.JoinRule.Public) {
root.room.joinRule = Quotient.JoinRule.Public;
}
}
}

View File

@@ -36,7 +36,6 @@ Kirigami.Dialog {
clip: true
ListView {
id: listView
implicitHeight: contentHeight
currentIndex: -1

View File

@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts
@@ -9,7 +11,7 @@ import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.formcard as FormCard
import org.kde.kirigamiaddons.labs.components as Components
import Quotient
import io.github.quotient_im.libquotient
import org.kde.neochat
@@ -37,12 +39,12 @@ Kirigami.Dialog {
standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
onAccepted: {
let ids = [];
for (var i in spaceGroup.buttons) {
for (let i in spaceGroup.buttons) {
if (spaceGroup.buttons[i].checked) {
ids.push(spaceGroup.buttons[i].modelData.id);
}
}
root.room.setJoinRule(JoinRule.Restricted, ids);
root.room.setJoinRule(Quotient.JoinRule.Restricted, ids);
}
QQC2.ButtonGroup {
@@ -56,6 +58,7 @@ Kirigami.Dialog {
model: root.room.parentObjects(true)
delegate: FormCard.FormCheckDelegate {
id: parentDelegate
required property var modelData
text: modelData.displayName
@@ -67,8 +70,8 @@ Kirigami.Dialog {
Layout.preferredWidth: Kirigami.Units.gridUnit * 2
Layout.preferredHeight: Kirigami.Units.gridUnit * 2
source: modelData.avatarUrl.toString().length > 0 ? connection.makeMediaUrl(modelData.avatarUrl) : ""
name: modelData.displayName
source: parentDelegate.modelData.avatarUrl.toString().length > 0 ? root.room.connection.makeMediaUrl(parentDelegate.modelData.avatarUrl) : ""
name: parentDelegate.modelData.displayName
}
}
}

View File

@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2022 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts
@@ -72,7 +74,7 @@ RowLayout {
}
}
QQC2.ToolTip.text: root.model?.readMarkersString ?? ""
QQC2.ToolTip.text: (root.model as ReadMarkerModel)?.readMarkersString ?? ""
QQC2.ToolTip.visible: hoverHandler.hovered
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay

View File

@@ -126,7 +126,7 @@ KirigamiComponents.ConvergentContextMenu {
onClicked: {
if (emojiText.text === "⋮") {
var dialog = emojiDialog.createObject(emojiDelegate) as EmojiDialog;
let dialog = emojiDialog.createObject(emojiDelegate) as EmojiDialog;
dialog.showStickers = false;
dialog.chosen.connect(emoji => {
root.room.toggleReaction(root.eventId, emoji);
@@ -214,7 +214,7 @@ KirigamiComponents.ConvergentContextMenu {
width: Kirigami.Units.gridUnit * 25
});
dialog.accepted.connect(reason => {
currentRoom.redactEvent(root.eventId, reason);
root.room.redactEvent(root.eventId, reason);
});
}
}
@@ -340,7 +340,7 @@ KirigamiComponents.ConvergentContextMenu {
width: Kirigami.Units.gridUnit * 25
});
dialog.accepted.connect(reason => {
currentRoom.reportEvent(root.eventId, reason);
root.room.reportEvent(root.eventId, reason);
});
}
}

View File

@@ -3,7 +3,6 @@
// SPDX-License-Identifier: GPL-3.0-only
import QtQuick
import QtQuick.Layouts
import Qt.labs.qmlmodels
@@ -63,12 +62,10 @@ DelegateChooser {
roleValue: DelegateType.Other
delegate: NeoChatConfig.showAllEvents ? hiddenDelegate : emptyDelegate
Component {
id: hiddenDelegate
property Component hiddenDelegate : Component {
HiddenDelegate {}
}
Component {
id: emptyDelegate
property Component emptyDelegate : Component {
Item {}
}
}

View File

@@ -1,10 +1,10 @@
// SPDX-FileCopyrightText: 2020 Black Hat <bhat@encom.eu.org>
// SPDX-License-Identifier: GPL-3.0-only
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls as QQC2
import QtQuick.Layouts
import Qt.labs.qmlmodels
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.components as KirigamiComponents
@@ -175,7 +175,7 @@ MessageDelegateBase {
const menu = Qt.createComponent("org.kde.neochat", "UserMenu").createObject(root, {
window: QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow,
author: root.author,
});
}) as UserMenu;
console.info(Qt.createComponent("org.kde.neochat", "UserMenu").errorString());
menu.popup(root.QQC2.Overlay.overlay);
}

View File

@@ -43,7 +43,7 @@ RowLayout {
display: QQC2.ToolButton.IconOnly
onClicked: {
root.reacting = true;
var dialog = emojiDialog.createObject(reactButton);
var dialog = emojiDialog.createObject(reactButton) as EmojiDialog;
dialog.chosen.connect(emoji => {
root.reacting = false;
root.room.toggleReaction(root.eventId, emoji);

View File

@@ -155,10 +155,10 @@ void MessageDelegateBase::cleanupIncubator(MessageObjectIncubator *incubator)
incubator->clear();
const auto it = std::find(m_activeIncubators.begin(), m_activeIncubators.end(), incubator);
delete incubator;
if (it != m_activeIncubators.end()) {
m_activeIncubators.erase(it);
}
delete incubator;
}
void MessageDelegateBase::cleanupItem(QQuickItem *item)
@@ -249,7 +249,12 @@ void MessageDelegateBase::updateAvatar()
markAsDirty();
}
m_avatarIncubating = false;
cleanupIncubator(incubator);
// We can't cleanup the incubator in the completedCallback otherwise
// we use after free when we return to the status changed function
// of that incubator
QTimer::singleShot(0, this, [this, incubator]() {
cleanupIncubator(incubator);
});
},
m_errorCallback);
m_activeIncubators.push_back(avatarIncubator);
@@ -313,7 +318,12 @@ void MessageDelegateBase::updateSection()
markAsDirty();
}
m_sectionIncubating = false;
cleanupIncubator(incubator);
// We can't cleanup the incubator in the completedCallback otherwise
// we use after free when we return to the status changed function
// of that incubator
QTimer::singleShot(0, this, [this, incubator]() {
cleanupIncubator(incubator);
});
},
m_errorCallback);
m_activeIncubators.push_back(sectionIncubator);
@@ -377,7 +387,12 @@ void MessageDelegateBase::updateReadMarker()
markAsDirty();
}
m_readMarkerIncubating = false;
cleanupIncubator(incubator);
// We can't cleanup the incubator in the completedCallback otherwise
// we use after free when we return to the status changed function
// of that incubator
QTimer::singleShot(0, this, [this, incubator]() {
cleanupIncubator(incubator);
});
},
m_errorCallback);
m_activeIncubators.push_back(readMarkerIncubator);
@@ -448,7 +463,12 @@ void MessageDelegateBase::updateBackground()
markAsDirty();
}
m_compactBackgroundIncubating = false;
cleanupIncubator(incubator);
// We can't cleanup the incubator in the completedCallback otherwise
// we use after free when we return to the status changed function
// of that incubator
QTimer::singleShot(0, this, [this, incubator]() {
cleanupIncubator(incubator);
});
},
m_errorCallback);
m_activeIncubators.push_back(compactBackgroundIncubator);
@@ -506,8 +526,13 @@ void MessageDelegateBase::updateQuickAction()
}
markAsDirty();
}
cleanupIncubator(incubator);
m_quickActionIncubating = false;
// We can't cleanup the incubator in the completedCallback otherwise
// we use after free when we return to the status changed function
// of that incubator
QTimer::singleShot(0, this, [this, incubator]() {
cleanupIncubator(incubator);
});
},
m_errorCallback);
m_activeIncubators.push_back(quickActionIncubator);