Compare commits
15 Commits
work/tobia
...
work/redst
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb63ac5642 | ||
|
|
bff69e21ad | ||
|
|
e117cc0cfb | ||
|
|
3af1a88e05 | ||
|
|
aa116a35f5 | ||
|
|
ac232d7f55 | ||
|
|
928911e33c | ||
|
|
e3c30f5bb3 | ||
|
|
4b51855528 | ||
|
|
79c27db0a9 | ||
|
|
78e42ab352 | ||
|
|
93909c45ee | ||
|
|
eda0bf4b23 | ||
|
|
4f4b10e0b6 | ||
|
|
2b374a8bec |
@@ -243,10 +243,7 @@ ecm_add_qml_module(neochat URI org.kde.neochat GENERATE_PLUGIN_SOURCE
|
||||
qml/MessageDelegateContextMenu.qml
|
||||
qml/FileDelegateContextMenu.qml
|
||||
qml/MessageSourceSheet.qml
|
||||
qml/ReportSheet.qml
|
||||
qml/ConfirmEncryptionDialog.qml
|
||||
qml/RemoveSheet.qml
|
||||
qml/BanSheet.qml
|
||||
qml/RoomSearchPage.qml
|
||||
qml/LocationChooser.qml
|
||||
qml/TimelineView.qml
|
||||
@@ -291,6 +288,7 @@ ecm_add_qml_module(neochat URI org.kde.neochat GENERATE_PLUGIN_SOURCE
|
||||
qml/AskDirectChatConfirmation.qml
|
||||
qml/HoverLinkIndicator.qml
|
||||
qml/AvatarNotification.qml
|
||||
qml/ReasonDialog.qml
|
||||
DEPENDENCIES
|
||||
QtCore
|
||||
QtQuick
|
||||
|
||||
@@ -211,7 +211,7 @@ QList<ActionsModel::Action> actions{
|
||||
Q_EMIT Controller::instance().showMessage(Controller::Positive, i18n("You are already in this room."));
|
||||
return QString();
|
||||
}
|
||||
if (room->members().contains(room->member(text))) {
|
||||
if (room->joinedMemberIds().contains(text)) {
|
||||
Q_EMIT Controller::instance().showMessage(Controller::Info, i18nc("<user> is already in this room.", "%1 is already in this room.", text));
|
||||
return QString();
|
||||
}
|
||||
|
||||
@@ -578,22 +578,21 @@ MessageComponent MessageContentModel::linkPreviewComponent(const QUrl &link)
|
||||
}
|
||||
if (linkPreviewer->loaded()) {
|
||||
return MessageComponent{MessageComponentType::LinkPreview, QString(), {{"link"_ls, link}}};
|
||||
} else {
|
||||
connect(linkPreviewer, &LinkPreviewer::loadedChanged, [this, link]() {
|
||||
const auto linkPreviewer = dynamic_cast<NeoChatConnection *>(m_room->connection())->previewerForLink(link);
|
||||
if (linkPreviewer != nullptr && linkPreviewer->loaded()) {
|
||||
for (auto &component : m_components) {
|
||||
if (component.attributes["link"_ls].toUrl() == link) {
|
||||
// HACK: Because DelegateChooser can't switch the delegate on dataChanged it has to think there is a new delegate.
|
||||
beginResetModel();
|
||||
component.type = MessageComponentType::LinkPreview;
|
||||
endResetModel();
|
||||
}
|
||||
}
|
||||
connect(linkPreviewer, &LinkPreviewer::loadedChanged, this, [this, link]() {
|
||||
const auto linkPreviewer = dynamic_cast<NeoChatConnection *>(m_room->connection())->previewerForLink(link);
|
||||
if (linkPreviewer != nullptr && linkPreviewer->loaded()) {
|
||||
for (auto &component : m_components) {
|
||||
if (component.attributes["link"_ls].toUrl() == link) {
|
||||
// HACK: Because DelegateChooser can't switch the delegate on dataChanged it has to think there is a new delegate.
|
||||
beginResetModel();
|
||||
component.type = MessageComponentType::LinkPreview;
|
||||
endResetModel();
|
||||
}
|
||||
}
|
||||
});
|
||||
return MessageComponent{MessageComponentType::LinkPreviewLoad, QString(), {{"link"_ls, link}}};
|
||||
}
|
||||
}
|
||||
});
|
||||
return MessageComponent{MessageComponentType::LinkPreviewLoad, QString(), {{"link"_ls, link}}};
|
||||
}
|
||||
|
||||
QList<MessageComponent> MessageContentModel::addLinkPreviews(QList<MessageComponent> inputComponents)
|
||||
|
||||
@@ -84,21 +84,19 @@ void MessageEventModel::setRoom(NeoChatRoom *room)
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_currentRoom) {
|
||||
// HACK: Reset the model to a null room first to make sure QML dismantles
|
||||
// last room's objects before the room is actually changed
|
||||
beginResetModel();
|
||||
m_currentRoom->disconnect(this);
|
||||
m_currentRoom = nullptr;
|
||||
endResetModel();
|
||||
// HACK: Reset the model to a null room first to make sure QML dismantles
|
||||
// last room's objects before the room is actually changed
|
||||
beginResetModel();
|
||||
m_currentRoom->disconnect(this);
|
||||
m_currentRoom = nullptr;
|
||||
endResetModel();
|
||||
|
||||
// Don't clear the member objects until the model has been fully reset and all
|
||||
// refs cleared.
|
||||
m_memberObjects.clear();
|
||||
m_contentModels.clear();
|
||||
m_reactionModels.clear();
|
||||
m_readMarkerModels.clear();
|
||||
}
|
||||
// Don't clear the member objects until the model has been fully reset and all
|
||||
// refs cleared.
|
||||
m_memberObjects.clear();
|
||||
m_contentModels.clear();
|
||||
m_reactionModels.clear();
|
||||
m_readMarkerModels.clear();
|
||||
|
||||
beginResetModel();
|
||||
m_currentRoom = room;
|
||||
|
||||
@@ -125,7 +125,7 @@ void WebShortcutModel::trigger(const QString &data)
|
||||
void WebShortcutModel::configureWebShortcuts()
|
||||
{
|
||||
#ifdef HAVE_KIO
|
||||
auto job = new KIO::CommandLauncherJob(QStringLiteral("kcmshell5"), QStringList() << QStringLiteral("webshortcuts"), this);
|
||||
auto job = new KIO::CommandLauncherJob(QStringLiteral("kcmshell6"), QStringList() << QStringLiteral("webshortcuts"), this);
|
||||
job->exec();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -70,6 +70,11 @@ Loader {
|
||||
*/
|
||||
property list<Kirigami.Action> actions
|
||||
|
||||
/**
|
||||
* @brief Whether the web search menu should be shown or not.
|
||||
*/
|
||||
property bool enableWebSearch: true
|
||||
|
||||
/**
|
||||
* Some common actions shared between menus
|
||||
*/
|
||||
@@ -82,16 +87,23 @@ Loader {
|
||||
|
||||
component RemoveMessageAction: Kirigami.Action {
|
||||
visible: author.isLocalMember || currentRoom.canSendState("redact")
|
||||
text: i18n("Remove")
|
||||
text: i18nc("@action:button", "Remove")
|
||||
icon.name: "edit-delete-remove"
|
||||
icon.color: "red"
|
||||
onTriggered: applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'RemoveSheet'), {
|
||||
room: currentRoom,
|
||||
eventId: eventId
|
||||
}, {
|
||||
title: i18nc("@title", "Remove Message"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
})
|
||||
onTriggered: {
|
||||
let dialog = applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReasonDialog'), {
|
||||
title: i18nc("@title:dialog", "Remove Message"),
|
||||
placeholder: i18nc("@info:placeholder", "Reason for removing this message"),
|
||||
actionText: i18nc("@action:button 'Remove' as in 'Remove this message'", "Remove"),
|
||||
icon: "delete"
|
||||
}, {
|
||||
title: i18nc("@title:dialog", "Remove Message"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
});
|
||||
dialog.accepted.connect(reason => {
|
||||
currentRoom.redactEvent(root.eventId, reason);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
component ReplyMessageAction: Kirigami.Action {
|
||||
@@ -108,13 +120,28 @@ Loader {
|
||||
text: i18nc("@action:button 'Report' as in 'Report this event to the administrators'", "Report")
|
||||
icon.name: "dialog-warning-symbolic"
|
||||
visible: !author.isLocalMember
|
||||
onTriggered: applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReportSheet'), {
|
||||
room: currentRoom,
|
||||
eventId: eventId
|
||||
}, {
|
||||
title: i18nc("@title", "Report Message"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
})
|
||||
onTriggered: {
|
||||
let dialog = applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReasonDialog'), {
|
||||
title: i18nc("@title:dialog", "Report Message"),
|
||||
placeholder: i18nc("@info:placeholder", "Reason for reporting this message"),
|
||||
icon: "dialog-warning-symbolic",
|
||||
actionText: i18nc("@action:button 'Report' as in 'Report this event to the administrators'", "Report")
|
||||
}, {
|
||||
title: i18nc("@title", "Report Message"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
});
|
||||
dialog.accepted.connect(reason => {
|
||||
currentRoom.reportEvent(root.eventId, reason);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
component ShowUserAction: Kirigami.Action {
|
||||
text: i18nc("@action:inmenu", "Show User")
|
||||
icon.name: "username-copy"
|
||||
onTriggered: {
|
||||
RoomManager.resolveResource(author.id)
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
@@ -128,6 +155,7 @@ Loader {
|
||||
id: menuItem
|
||||
visible: modelData.visible
|
||||
title: modelData.text
|
||||
icon: modelData.icon
|
||||
|
||||
Instantiator {
|
||||
model: modelData.children
|
||||
@@ -158,7 +186,8 @@ Loader {
|
||||
QQC2.Menu {
|
||||
id: webshortcutmenu
|
||||
title: i18n("Search for '%1'", webshortcutmodel.trunkatedSearchText)
|
||||
property bool isVisible: webshortcutmodel.enabled
|
||||
icon.name: "search-symbolic"
|
||||
property bool isVisible: webshortcutmodel.enabled && root.enableWebSearch
|
||||
Component.onCompleted: {
|
||||
webshortcutmenu.parent.visible = isVisible;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,9 @@ DelegateContextMenu {
|
||||
*/
|
||||
required property var progressInfo
|
||||
|
||||
// Web search isn't useful for images
|
||||
enableWebSearch: false
|
||||
|
||||
/**
|
||||
* @brief The main list of menu item actions.
|
||||
*
|
||||
@@ -67,15 +70,23 @@ DelegateContextMenu {
|
||||
text: i18n("Remove")
|
||||
icon.name: "edit-delete-remove"
|
||||
icon.color: "red"
|
||||
onTriggered: applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'RemoveSheet'), {
|
||||
room: currentRoom,
|
||||
eventId: eventId
|
||||
}, {
|
||||
title: i18nc("@title", "Remove Message"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
})
|
||||
onTriggered: {
|
||||
let dialog = applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReasonDialog'), {
|
||||
title: i18nc("@title:dialog", "Remove Message"),
|
||||
placeholder: i18nc("@info:placeholder", "Reason for removing this message"),
|
||||
actionText: i18nc("@action:button 'Remove' as in 'Remove this message'", "Remove"),
|
||||
icon: "delete"
|
||||
}, {
|
||||
title: i18nc("@title:dialog", "Remove Message"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
});
|
||||
dialog.accepted.connect(reason => {
|
||||
currentRoom.redactEvent(root.eventId, reason);
|
||||
});
|
||||
}
|
||||
},
|
||||
DelegateContextMenu.ReportMessageAction {},
|
||||
DelegateContextMenu.ShowUserAction {},
|
||||
DelegateContextMenu.ViewSourceAction {}
|
||||
]
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// SPDX-FileCopyrightText: 2019 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
|
||||
@@ -11,111 +13,77 @@ import org.kde.kirigamiaddons.labs.components as KirigamiComponents
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
Kirigami.ScrollablePage {
|
||||
SearchPage {
|
||||
id: root
|
||||
|
||||
property NeoChatRoom room
|
||||
|
||||
title: i18n("Invite a User")
|
||||
title: i18nc("@title:dialog", "Invite a User")
|
||||
|
||||
actions: [
|
||||
Kirigami.Action {
|
||||
icon.name: "dialog-close"
|
||||
text: i18nc("@action", "Cancel")
|
||||
onTriggered: root.closeDialog()
|
||||
}
|
||||
]
|
||||
header: RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: Kirigami.Units.largeSpacing
|
||||
searchFieldPlaceholder: i18nc("@info:placeholder", "Find a user…")
|
||||
noResultPlaceholderMessage: i18nc("@info:placeholder", "No users found")
|
||||
|
||||
Kirigami.SearchField {
|
||||
id: identifierField
|
||||
property bool isUserId: text.match(/@(.+):(.+)/g)
|
||||
Layout.fillWidth: true
|
||||
headerTrailing: QQC2.Button {
|
||||
icon.name: "list-add"
|
||||
display: QQC2.Button.IconOnly
|
||||
enabled: root.model.searchText.match(/@(.+):(.+)/g) && !root.room.containsUser(root.model.searchText)
|
||||
|
||||
placeholderText: i18n("Find a user...")
|
||||
onAccepted: userDictListModel.search()
|
||||
}
|
||||
text: i18nc("@action:button", "Invite this User")
|
||||
|
||||
QQC2.Button {
|
||||
visible: identifierField.isUserId
|
||||
QQC2.ToolTip.visible: hovered
|
||||
QQC2.ToolTip.text: root.room.containsUser(root.model.searchText) ? i18nc("@info:tooltip", "User is either already a member or has been invited") : text
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
|
||||
text: i18n("Add")
|
||||
highlighted: true
|
||||
|
||||
onClicked: {
|
||||
room.inviteToRoom(identifierField.text);
|
||||
}
|
||||
}
|
||||
onClicked: root.room.inviteToRoom(root.model.searchText);
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: userDictListView
|
||||
model: UserDirectoryListModel {
|
||||
id: userDictListModel
|
||||
|
||||
clip: true
|
||||
connection: root.room.connection
|
||||
}
|
||||
|
||||
model: UserDirectoryListModel {
|
||||
id: userDictListModel
|
||||
modelDelegate: Delegates.RoundedItemDelegate {
|
||||
id: delegate
|
||||
|
||||
connection: root.room.connection
|
||||
searchText: identifierField.text
|
||||
}
|
||||
required property string userId
|
||||
required property string displayName
|
||||
required property url avatarUrl
|
||||
|
||||
Kirigami.PlaceholderMessage {
|
||||
anchors.centerIn: parent
|
||||
text: displayName
|
||||
|
||||
visible: userDictListView.count < 1
|
||||
contentItem: RowLayout {
|
||||
KirigamiComponents.Avatar {
|
||||
Layout.preferredWidth: Kirigami.Units.iconSizes.medium
|
||||
Layout.preferredHeight: Kirigami.Units.iconSizes.medium
|
||||
source: delegate.avatarUrl
|
||||
name: delegate.displayName
|
||||
}
|
||||
|
||||
text: i18n("No users available")
|
||||
}
|
||||
Delegates.SubtitleContentItem {
|
||||
itemDelegate: delegate
|
||||
subtitle: delegate.userId
|
||||
labelItem.textFormat: Text.PlainText
|
||||
}
|
||||
|
||||
delegate: Delegates.RoundedItemDelegate {
|
||||
id: delegate
|
||||
QQC2.ToolButton {
|
||||
id: inviteButton
|
||||
|
||||
required property string userId
|
||||
required property string displayName
|
||||
required property url avatarUrl
|
||||
readonly property bool inRoom: root.room && root.room.containsUser(delegate.userId)
|
||||
|
||||
property bool inRoom: room && room.containsUser(userId)
|
||||
icon.name: "document-send"
|
||||
text: i18nc("@action:button", "Send invitation")
|
||||
opacity: inRoom ? 0.5 : 1
|
||||
enabled: !inRoom
|
||||
|
||||
text: displayName
|
||||
|
||||
contentItem: RowLayout {
|
||||
KirigamiComponents.Avatar {
|
||||
Layout.preferredWidth: Kirigami.Units.iconSizes.medium
|
||||
Layout.preferredHeight: Kirigami.Units.iconSizes.medium
|
||||
source: delegate.avatarUrl
|
||||
name: delegate.displayName
|
||||
onClicked: {
|
||||
inviteButton.enabled = false;
|
||||
root.room.inviteToRoom(delegate.userId);
|
||||
}
|
||||
|
||||
Delegates.SubtitleContentItem {
|
||||
itemDelegate: delegate
|
||||
subtitle: delegate.userId
|
||||
labelItem.textFormat: Text.PlainText
|
||||
}
|
||||
|
||||
QQC2.ToolButton {
|
||||
id: inviteButton
|
||||
icon.name: "document-send"
|
||||
text: i18n("Send invitation")
|
||||
checkable: true
|
||||
checked: inRoom
|
||||
opacity: inRoom ? 0.5 : 1
|
||||
|
||||
onToggled: {
|
||||
if (inRoom) {
|
||||
checked = true;
|
||||
} else {
|
||||
room.inviteToRoom(delegate.userId);
|
||||
applicationWindow().pageStack.layers.pop();
|
||||
}
|
||||
}
|
||||
|
||||
QQC2.ToolTip.text: !inRoom ? text : i18n("User is either already a member or has been invited")
|
||||
QQC2.ToolTip.visible: inviteButton.hovered
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
}
|
||||
QQC2.ToolTip.text: !inRoom ? text : i18nc("@info:tooltip", "User is either already a member or has been invited")
|
||||
QQC2.ToolTip.visible: inviteButton.hovered
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,9 +30,36 @@ Components.AbstractMaximizeComponent {
|
||||
root.close();
|
||||
}
|
||||
enabled: !!root.location
|
||||
},
|
||||
Kirigami.Action {
|
||||
text: i18nc("@action:intoolbar Re-center the map onto the set location", "Re-Center")
|
||||
icon.name: "snap-bounding-box-center-symbolic"
|
||||
onTriggered: mapView.map.fitViewportToMapItems([mapView.locationMapItem])
|
||||
enabled: root.location !== undefined
|
||||
},
|
||||
Kirigami.Action {
|
||||
text: i18nc("@action:intoolbar Determine the device's location", "Locate")
|
||||
icon.name: "mark-location-symbolic"
|
||||
enabled: positionSource.valid
|
||||
onTriggered: positionSource.update()
|
||||
}
|
||||
]
|
||||
|
||||
PositionSource {
|
||||
id: positionSource
|
||||
|
||||
active: false
|
||||
|
||||
onPositionChanged: {
|
||||
const coord = position.coordinate;
|
||||
mapView.gpsMapItem.latitude = coord.latitude;
|
||||
mapView.gpsMapItem.longitude = coord.longitude;
|
||||
|
||||
mapView.map.addMapItem(mapView.gpsMapItem);
|
||||
mapView.map.fitViewportToMapItems([mapView.gpsMapItem])
|
||||
}
|
||||
}
|
||||
|
||||
content: MapView {
|
||||
id: mapView
|
||||
map.plugin: OsmLocationPlugin.plugin
|
||||
@@ -54,6 +81,15 @@ Components.AbstractMaximizeComponent {
|
||||
author: null
|
||||
}
|
||||
|
||||
readonly property LocationMapItem gpsMapItem: LocationMapItem {
|
||||
latitude: 0.0
|
||||
longitude: 0.0
|
||||
isLive: true
|
||||
heading: NaN
|
||||
asset: ""
|
||||
author: null
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: mapView.map
|
||||
function onCopyrightLinkActivated(link: string) {
|
||||
|
||||
@@ -66,13 +66,7 @@ DelegateContextMenu {
|
||||
onTriggered: Clipboard.saveText(root.selectedText.length > 0 ? root.selectedText : root.plainText)
|
||||
},
|
||||
DelegateContextMenu.ReportMessageAction {},
|
||||
Kirigami.Action {
|
||||
text: i18nc("@action:inmenu", "Show User")
|
||||
icon.name: "username-copy"
|
||||
onTriggered: {
|
||||
RoomManager.resolveResource(author.id)
|
||||
}
|
||||
},
|
||||
DelegateContextMenu.ShowUserAction {},
|
||||
DelegateContextMenu.ViewSourceAction {},
|
||||
Kirigami.Action {
|
||||
text: i18n("Copy Link")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-FileCopyrightText: 2024 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import QtQuick
|
||||
@@ -12,10 +12,11 @@ import org.kde.neochat
|
||||
Kirigami.Page {
|
||||
id: root
|
||||
|
||||
property NeoChatRoom room
|
||||
property string userId
|
||||
required property string placeholder
|
||||
required property string actionText
|
||||
required property string icon
|
||||
|
||||
title: i18n("Ban User")
|
||||
signal accepted(reason: string)
|
||||
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
@@ -24,7 +25,7 @@ Kirigami.Page {
|
||||
|
||||
QQC2.TextArea {
|
||||
id: reason
|
||||
placeholderText: i18n("Reason for banning this user")
|
||||
placeholderText: root.placeholder
|
||||
anchors.fill: parent
|
||||
wrapMode: TextEdit.Wrap
|
||||
|
||||
@@ -40,11 +41,11 @@ Kirigami.Page {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
QQC2.Button {
|
||||
text: i18nc("@action:button 'Ban' as in 'Ban this user'", "Ban")
|
||||
icon.name: "im-ban-user"
|
||||
text: root.actionText
|
||||
icon.name: root.icon
|
||||
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.AcceptRole
|
||||
onClicked: {
|
||||
root.room.ban(root.userId, reason.text);
|
||||
root.accepted(reason.text);
|
||||
root.closeDialog();
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,7 @@ Kirigami.Dialog {
|
||||
spacing: Kirigami.Units.largeSpacing * 4
|
||||
Avatar {
|
||||
source: root.connection.makeMediaUrl(SpaceHierarchyCache.recommendedSpaceAvatar)
|
||||
name: SpaceHierarchyCache.recommendedSpaceDisplayName
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
Kirigami.Page {
|
||||
id: root
|
||||
|
||||
property NeoChatRoom room
|
||||
property string eventId
|
||||
|
||||
property string userId: ""
|
||||
|
||||
title: userId.length > 0 ? i18n("Remove Messages") : i18n("Remove Message")
|
||||
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
|
||||
QQC2.TextArea {
|
||||
id: reason
|
||||
placeholderText: userId.length > 0 ? i18n("Reason for removing this user's recent messages") : i18n("Reason for removing this message")
|
||||
anchors.fill: parent
|
||||
wrapMode: TextEdit.Wrap
|
||||
background: Rectangle {
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
}
|
||||
}
|
||||
|
||||
footer: QQC2.ToolBar {
|
||||
QQC2.DialogButtonBox {
|
||||
anchors.fill: parent
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
QQC2.Button {
|
||||
text: i18nc("@action:button 'Remove' as in 'Remove this message'", "Remove")
|
||||
icon.name: "delete"
|
||||
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.AcceptRole
|
||||
onClicked: {
|
||||
if (root.userId.length > 0) {
|
||||
root.room.deleteMessagesByUser(root.userId, reason.text);
|
||||
} else {
|
||||
root.room.redactEvent(root.eventId, reason.text);
|
||||
}
|
||||
root.closeDialog();
|
||||
}
|
||||
}
|
||||
QQC2.Button {
|
||||
text: i18nc("@action", "Cancel")
|
||||
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.RejectRole
|
||||
onClicked: root.closeDialog()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2022 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
Kirigami.Page {
|
||||
id: root
|
||||
|
||||
property NeoChatRoom room
|
||||
property string eventId
|
||||
|
||||
title: i18n("Report Message")
|
||||
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
|
||||
QQC2.TextArea {
|
||||
id: reason
|
||||
placeholderText: i18n("Reason for reporting this message")
|
||||
anchors.fill: parent
|
||||
wrapMode: TextEdit.Wrap
|
||||
|
||||
background: Rectangle {
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
}
|
||||
}
|
||||
|
||||
footer: QQC2.ToolBar {
|
||||
QQC2.DialogButtonBox {
|
||||
anchors.fill: parent
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
QQC2.Button {
|
||||
text: i18nc("@action:button 'Report' as in 'Report this event to the administrators'", "Report")
|
||||
icon.name: "dialog-warning-symbolic"
|
||||
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.AcceptRole
|
||||
onClicked: {
|
||||
root.room.reportEvent(eventId, reason.text);
|
||||
root.closeDialog();
|
||||
}
|
||||
}
|
||||
QQC2.Button {
|
||||
text: i18nc("@action", "Cancel")
|
||||
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.RejectRole
|
||||
onClicked: root.closeDialog()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,7 +145,7 @@ Delegates.RoundedItemDelegate {
|
||||
text: i18n("Configure room")
|
||||
display: QQC2.Button.IconOnly
|
||||
|
||||
icon.name: "configure"
|
||||
icon.name: "overflow-menu-symbolic"
|
||||
onClicked: createRoomListContextMenu()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ QQC2.Control {
|
||||
visible: true
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Button
|
||||
Kirigami.Theme.inherit: false
|
||||
color: root.connection.directChatsHaveHighlightNotifications ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.backgroundColor
|
||||
color: root.connection.directChatsHaveHighlightNotifications || root.connection.directChatInvites ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.backgroundColor
|
||||
radius: height / 2
|
||||
}
|
||||
|
||||
@@ -162,6 +162,13 @@ QQC2.Control {
|
||||
id: directChatNotificationCountTextMetrics
|
||||
text: directChatNotificationCountLabel.text
|
||||
}
|
||||
|
||||
Kirigami.Icon {
|
||||
anchors.fill: parent
|
||||
|
||||
source: "list-add-symbolic"
|
||||
visible: root.connection.directChatInvites && root.connection.directChatNotifications === 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -150,13 +150,18 @@ Kirigami.Dialog {
|
||||
icon.name: "im-ban-user"
|
||||
icon.color: Kirigami.Theme.negativeTextColor
|
||||
onTriggered: {
|
||||
(root.QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow).pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'BanSheet'), {
|
||||
room: root.room,
|
||||
userId: root.user.id
|
||||
let dialog = (root.QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow).pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReasonDialog'), {
|
||||
title: i18nc("@title:dialog", "Ban User"),
|
||||
placeholder: i18nc("@info:placeholder", "Reason for banning this user"),
|
||||
actionText: i18nc("@action:button 'Ban' as in 'Ban this user'", "Ban"),
|
||||
icon: "im-ban-user"
|
||||
}, {
|
||||
title: i18nc("@title", "Ban User"),
|
||||
title: i18nc("@title:dialog", "Ban User"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
});
|
||||
dialog.accepted.connect(reason => {
|
||||
root.room.ban(root.user.id, reason);
|
||||
});
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
@@ -204,17 +209,22 @@ Kirigami.Dialog {
|
||||
visible: root.room && (root.user.id === root.connection.localUserId || room.canSendState("redact"))
|
||||
|
||||
action: Kirigami.Action {
|
||||
text: i18n("Remove recent messages by this user")
|
||||
text: i18nc("@action:button", "Remove recent messages by this user")
|
||||
icon.name: "delete"
|
||||
icon.color: Kirigami.Theme.negativeTextColor
|
||||
onTriggered: {
|
||||
applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'RemoveSheet'), {
|
||||
room: root.room,
|
||||
userId: root.user.id
|
||||
let dialog = applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ReasonDialog'), {
|
||||
title: i18nc("@title:dialog", "Remove Messages"),
|
||||
placeholder: i18nc("@info:placeholder", "Reason for removing this user's recent messages"),
|
||||
actionText: i18nc("@action:button 'Remove' as in 'Remove these messages'", "Remove"),
|
||||
icon: "delete"
|
||||
}, {
|
||||
title: i18nc("@title", "Remove Messages"),
|
||||
width: Kirigami.Units.gridUnit * 25
|
||||
});
|
||||
dialog.accepted.connect(reason => {
|
||||
root.room.deleteMessagesByUser(root.user.id, reason);
|
||||
});
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ FormCard.FormCardPage {
|
||||
id: minimizeDelegate
|
||||
text: i18n("Minimize to system tray on startup")
|
||||
checked: NeoChatConfig.minimizeToSystemTrayOnStartup
|
||||
visible: Controller.supportSystemTray && !Kirigami.Settings.isMobile
|
||||
visible: Controller.supportSystemTray && !Kirigami.Settings.isMobile && NeoChatConfig.systemTray
|
||||
enabled: NeoChatConfig.systemTray && !NeoChatConfig.isMinimizeToSystemTrayOnStartupImmutable
|
||||
onToggled: {
|
||||
NeoChatConfig.minimizeToSystemTrayOnStartup = checked;
|
||||
@@ -56,6 +56,7 @@ FormCard.FormCardPage {
|
||||
FormCard.FormDelegateSeparator {
|
||||
above: minimizeDelegate
|
||||
below: automaticallyDelegate
|
||||
visible: minimizeDelegate.visible
|
||||
}
|
||||
|
||||
FormCard.FormCheckDelegate {
|
||||
@@ -193,23 +194,6 @@ FormCard.FormCardPage {
|
||||
NeoChatConfig.save();
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormDelegateSeparator {
|
||||
above: showAvatarChangeDelegate
|
||||
below: hideImagesDelegate
|
||||
}
|
||||
|
||||
FormCard.FormCheckDelegate {
|
||||
id: hideImagesDelegate
|
||||
text: i18nc("@label:checkbox", "Hide image and video events by default")
|
||||
description: i18nc("@info", "When this option is enabled, images and videos are only shown after a button is clicked.")
|
||||
checked: NeoChatConfig.hideImages
|
||||
enabled: !NeoChatConfig.isHideImagesImmutable
|
||||
onToggled: {
|
||||
NeoChatConfig.hideImages = checked;
|
||||
NeoChatConfig.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
FormCard.FormHeader {
|
||||
title: i18nc("Chat Editor", "Editor")
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.formcard as FormCard
|
||||
@@ -15,7 +16,7 @@ FormCard.FormCardPage {
|
||||
|
||||
required property NeoChatConnection connection
|
||||
|
||||
title: i18nc("@title", "Security")
|
||||
title: i18nc("@title", "Security & Safety")
|
||||
|
||||
header: KirigamiComponents.Banner {
|
||||
id: banner
|
||||
@@ -24,13 +25,39 @@ FormCard.FormCardPage {
|
||||
type: Kirigami.MessageType.Error
|
||||
}
|
||||
|
||||
FormCard.FormHeader {
|
||||
title: i18nc("@title:group", "Invitations")
|
||||
}
|
||||
FormCard.FormCard {
|
||||
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||
FormCard.FormButtonDelegate {
|
||||
id: ignoredUsersDelegate
|
||||
text: i18nc("@action:button", "Ignored Users")
|
||||
icon.name: "im-invisible-user"
|
||||
onClicked: root.QQC2.ApplicationWindow.window.pageStack.pushDialogLayer(ignoredUsersDialogComponent, {}, {
|
||||
title: i18nc("@title:window", "Ignored Users")
|
||||
});
|
||||
}
|
||||
FormCard.FormDelegateSeparator {
|
||||
above: ignoredUsersDelegate
|
||||
below: hideImagesDelegate
|
||||
}
|
||||
FormCard.FormCheckDelegate {
|
||||
id: hideImagesDelegate
|
||||
text: i18nc("@label:checkbox", "Hide images and videos by default")
|
||||
description: i18nc("@info", "When this option is enabled, images and videos are only shown after a button is clicked.")
|
||||
checked: NeoChatConfig.hideImages
|
||||
enabled: !NeoChatConfig.isHideImagesImmutable
|
||||
onToggled: {
|
||||
NeoChatConfig.hideImages = checked;
|
||||
NeoChatConfig.save();
|
||||
}
|
||||
}
|
||||
FormCard.FormDelegateSeparator {
|
||||
above: hideImagesDelegate
|
||||
below: rejectInvitationsDelegate
|
||||
}
|
||||
FormCard.FormCheckDelegate {
|
||||
id: rejectInvitationsDelegate
|
||||
text: i18nc("@option:check", "Reject invitations from unknown users")
|
||||
description: connection.canCheckMutualRooms ? i18n("If enabled, NeoChat will reject invitations from users you don't share a room with.") : i18n("Your server does not support this setting.")
|
||||
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.")
|
||||
checked: NeoChatConfig.rejectUnknownInvites
|
||||
enabled: !NeoChatConfig.isRejectUnknownInvitesImmutable && connection.canCheckMutualRooms
|
||||
onToggled: {
|
||||
@@ -40,42 +67,15 @@ FormCard.FormCardPage {
|
||||
}
|
||||
}
|
||||
FormCard.FormHeader {
|
||||
title: i18nc("@title:group", "Ignored Users")
|
||||
}
|
||||
FormCard.FormCard {
|
||||
FormCard.FormButtonDelegate {
|
||||
text: i18nc("@action:button", "Manage ignored users")
|
||||
onClicked: root.QQC2.ApplicationWindow.window.pageStack.pushDialogLayer(ignoredUsersDialogComponent, {}, {
|
||||
title: i18nc("@title:window", "Ignored Users")
|
||||
});
|
||||
}
|
||||
}
|
||||
FormCard.FormHeader {
|
||||
title: i18nc("@title", "Keys")
|
||||
}
|
||||
FormCard.FormCard {
|
||||
FormCard.FormTextDelegate {
|
||||
text: connection.deviceKey
|
||||
description: i18n("Device key")
|
||||
}
|
||||
FormCard.FormTextDelegate {
|
||||
text: connection.encryptionKey
|
||||
description: i18n("Encryption key")
|
||||
}
|
||||
FormCard.FormTextDelegate {
|
||||
text: connection.deviceId
|
||||
description: i18n("Device id")
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormHeader {
|
||||
title: i18nc("@title", "Encryption")
|
||||
visible: Controller.csSupported
|
||||
title: i18nc("@title", "Encryption Keys")
|
||||
}
|
||||
FormCard.FormCard {
|
||||
visible: Controller.csSupported
|
||||
FormCard.FormButtonDelegate {
|
||||
text: i18nc("@action:button", "Import Encryption Keys")
|
||||
id: importKeysDelegate
|
||||
text: i18nc("@action:button", "Import Keys")
|
||||
description: i18nc("@info", "Import encryption keys from a backup.")
|
||||
icon.name: "document-import"
|
||||
onClicked: {
|
||||
let dialog = root.QQC2.ApplicationWindow.window.pageStack.pushDialogLayer(Qt.createComponent("org.kde.neochat.settings", "ImportKeysDialog"), {
|
||||
@@ -91,8 +91,14 @@ FormCard.FormCardPage {
|
||||
banner.visible = false;
|
||||
}
|
||||
}
|
||||
FormCard.FormDelegateSeparator {
|
||||
above: importKeysDelegate
|
||||
below: exportKeysDelegate
|
||||
}
|
||||
FormCard.FormButtonDelegate {
|
||||
text: i18nc("@action:button", "Export Encryption Keys")
|
||||
id: exportKeysDelegate
|
||||
text: i18nc("@action:button", "Export Keys")
|
||||
description: i18nc("@info", "Export this device's encryption keys.")
|
||||
icon.name: "document-export"
|
||||
onClicked: {
|
||||
root.QQC2.ApplicationWindow.window.pageStack.pushDialogLayer(Qt.createComponent("org.kde.neochat.settings", "ExportKeysDialog"), {
|
||||
|
||||
@@ -48,7 +48,7 @@ KirigamiSettings.ConfigurationView {
|
||||
},
|
||||
KirigamiSettings.ConfigurationModule {
|
||||
moduleId: "security"
|
||||
text: i18n("Security")
|
||||
text: i18nc("@title", "Security & Safety")
|
||||
icon.name: "preferences-security"
|
||||
page: () => Qt.createComponent("org.kde.neochat.settings", "NeoChatSecurityPage")
|
||||
initialProperties: () => {
|
||||
|
||||
Reference in New Issue
Block a user