Page MenuHomePhorge

No OneTemporary

Size
63 KB
Referenced Files
None
Subscribers
None
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 76d4f28..4fac282 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,300 +1,301 @@
function(kazv_add_qml_files)
set(options "")
set(oneValueArgs BASE_DIRECTORY)
set(multiValueArgs SOURCES)
cmake_parse_arguments(PARSE_ARGV 0 kazv_add_qml_files "${options}" "${oneValueArgs}" "${multiValueArgs}")
set(target "${kazv_add_qml_files_UNPARSED_ARGUMENTS}")
set(allSources)
foreach(source ${kazv_add_qml_files_SOURCES})
message(STATUS "Adding source: ${kazv_add_qml_files_BASE_DIRECTORY} / ${source}")
set_source_files_properties(
"${kazv_add_qml_files_BASE_DIRECTORY}/${source}"
PROPERTIES
QT_RESOURCE_ALIAS "${source}"
)
list(APPEND allSources "${kazv_add_qml_files_BASE_DIRECTORY}/${source}")
endforeach()
qt_target_qml_sources(
"${target}"
QML_FILES ${allSources}
)
endfunction()
if(WIN32)
set(KAZV_IS_WINDOWS 1)
else()
set(KAZV_IS_WINDOWS 0)
endif()
configure_file(kazv-version.cpp.in kazv-version.cpp)
configure_file(kazv-platform.hpp.in kazv-platform.hpp)
configure_file(kazv-defs.hpp.in kazv-defs.hpp)
set(kazvqmlmodule_SRCS
qt-job-handler.cpp
qt-job.cpp
${CMAKE_CURRENT_BINARY_DIR}/kazv-version.cpp
matrix-sdk.cpp
kazv-session-lock-guard.cpp
matrix-room.cpp
matrix-room-list.cpp
matrix-room-timeline.cpp
matrix-room-pinned-events-timeline.cpp
matrix-room-member.cpp
matrix-room-member-list-model.cpp
matrix-room-state.cpp
matrix-event-reader.cpp
matrix-event-reader-list-model.cpp
matrix-event-reaction-list-model.cpp
matrix-event-reaction.cpp
matrix-event.cpp
matrix-event-list.cpp
matrix-link.cpp
meta-types.cpp
l10n-provider.cpp
qt-rand-adapter.cpp
helper.cpp
matrix-promise.cpp
kazv-util.cpp
matrix-sticker-pack.cpp
matrix-sticker.cpp
matrix-sticker-pack-list.cpp
matrix-sticker-pack-source.cpp
matrix-user-given-attrs-map.cpp
kazv-abstract-list-model.cpp
qt-promise-handler.cpp
device-mgmt/matrix-device.cpp
device-mgmt/matrix-device-list.cpp
kazv-config.cpp
kazv-path-config.cpp
kazv-io-manager.cpp
kazv-io-job.cpp
kazv-file.cpp
upload-job-model.cpp
kazv-markdown.cpp
kazv-clipboard.cpp
db-store.cpp
)
ecm_qt_declare_logging_category(kazvqmlmodule_SRCS
HEADER kazv-log.hpp
IDENTIFIER kazvLog
CATEGORY_NAME moe.kazv.mxc.kazv
)
qt_add_qml_module(kazvqmlmodule
STATIC
URI moe.kazv.mxc.kazv
VERSION 0.0
SOURCES ${kazvqmlmodule_SRCS}
)
target_link_libraries(kazvqmlmodule PUBLIC
libkazv::kazvall
Qt${QT_MAJOR_VERSION}::Core
Qt${QT_MAJOR_VERSION}::Network
Threads::Threads
Qt${QT_MAJOR_VERSION}::Gui
Qt${QT_MAJOR_VERSION}::Qml
Qt${QT_MAJOR_VERSION}::Quick
Qt${QT_MAJOR_VERSION}::QuickControls2
Qt${QT_MAJOR_VERSION}::Svg
Qt${QT_MAJOR_VERSION}::Concurrent
Qt${QT_MAJOR_VERSION}::Widgets
Qt${QT_MAJOR_VERSION}::Sql
KF${KF_MAJOR_VERSION}::ConfigCore KF${KF_MAJOR_VERSION}::KIOCore
KF${KF_MAJOR_VERSION}::Notifications
KF${KF_MAJOR_VERSION}::CoreAddons
QCoro::Core
${CMARK_TARGET_NAME}
)
target_include_directories(kazvqmlmodule PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
target_include_directories(kazvqmlmodule PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/device-mgmt)
qt_add_qml_module(kazvshortcutsqmlmodule
STATIC
URI moe.kazv.mxc.kazvshortcuts
VERSION 0.0
SOURCES
shortcuts/shortcut-util.cpp
)
target_link_libraries(kazvshortcutsqmlmodule PUBLIC
libkazv::kazvall
Qt${QT_MAJOR_VERSION}::Core
Qt${QT_MAJOR_VERSION}::Gui
Qt${QT_MAJOR_VERSION}::Qml
)
target_include_directories(kazvshortcutsqmlmodule
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/shortcuts
)
add_library(kazvprivlib INTERFACE)
target_link_libraries(kazvprivlib
INTERFACE
kazvqmlmodule
kazvqmlmoduleplugin
kazvshortcutsqmlmodule
kazvshortcutsqmlmoduleplugin
)
qt_add_qml_module(kazvqmlqmlmodule
STATIC
URI moe.kazv.mxc.kazvqml
VERSION 0.0
)
kazv_add_qml_files(kazvqmlqmlmodule
BASE_DIRECTORY contents/ui
SOURCES
Main.qml
About.qml
PageManager.qml
LoginPage.qml
MainPage.qml
TabView.qml
Tab.qml
ClosableScrollablePage.qml
+ ClosableScrollableOverlay.qml
SelfDestroyableOverlaySheet.qml
RoomListView.qml
RoomListViewItemDelegate.qml
RoomPage.qml
RoomPinnedEventsPage.qml
RoomTimelineView.qml
SendMessageBox.qml
EventView.qml
EventViewWrapper.qml
EventViewCompact.qml
EventSourceView.qml
EventHistoryView.qml
EventReactions.qml
Bubble.qml
MediaFileMenu.qml
KazvIOMenu.qml
ConfirmUploadPopup.qml
StickerPicker.qml
AddStickerPopup.qml
StickerPackNameProvider.qml
ConfirmationOverlay.qml
event-types/Simple.qml
event-types/Text.qml
event-types/Emote.qml
event-types/Notice.qml
event-types/State.qml
event-types/TextTemplate.qml
event-types/Image.qml
event-types/File.qml
event-types/Video.qml
event-types/Audio.qml
event-types/MediaBubble.qml
event-types/Redacted.qml
event-types/Reaction.qml
event-types/Fallback.qml
TypingIndicator.qml
EventReadIndicator.qml
SelectableText.qml
ReactToEventPopup.qml
FileHandler.qml
ActionSettingsPage.qml
CreateRoomPage.qml
JoinRoomPage.qml
RoomMemberListView.qml
RoomMemberListViewItemDelegate.qml
UserNameProvider.qml
RoomNameProvider.qml
Completion.qml
AsyncHandler.qml
UploadFileHelper.qml
SettingsPage.qml
settings/ProfileSettings.qml
settings/CacheSettings.qml
room-settings/RoomSettingsPage.qml
room-settings/RoomTagHandler.qml
room-settings/RoomMemberListPage.qml
room-settings/RoomInvitePage.qml
room-settings/RoomStickerPacksPage.qml
room-settings/RoomStickerPackItemDelegate.qml
room-settings/RoomStatePage.qml
device-mgmt/Device.qml
device-mgmt/DeviceList.qml
UserPage.qml
shortcuts/ActionCollection.qml
shortcuts/ActionItem.qml
shortcuts/ActionSettings.qml
shortcuts/ShortcutInput.qml
MessageNotification.qml
Notifier.qml
NotificationAction.qml
AvatarAdapter.qml
ImageAdapter.qml
FileDialogAdapter.qml
FolderDialogAdapter.qml
ScrollablePageAdapter.qml
emoji/Activities.qml
emoji/Flags.qml
emoji/Objects.qml
emoji/SmileysAndEmotion.qml
emoji/TravelAndPlaces.qml
emoji/AnimalsAndNature.qml
emoji/FoodAndDrink.qml
emoji/PeopleAndBody.qml
emoji/Symbols.qml
)
kazv_add_qml_files(kazvqmlqmlmodule
BASE_DIRECTORY js
SOURCES
l10n.js
global-this.js
matrix-helpers.js
)
kazv_add_qml_files(kazvqmlqmlmodule
BASE_DIRECTORY js/transformed-libs
SOURCES
fluent-bundle.js
fluent-sequence.js
fluent-langneg.js
bundled-deps.js
)
target_link_libraries(kazvqmlqmlmodule PUBLIC kazvprivlib)
set(kazv_SRCS
main.cpp
l10n/translations.qrc
)
add_executable(kazv ${kazv_SRCS})
target_link_libraries(kazv
PRIVATE
kazvqmlqmlmodule
kazvqmlqmlmoduleplugin
kazvprivlib
)
if(kazv_LINK_BREEZE_ICONS)
target_link_libraries(kazv PRIVATE KF${KF_MAJOR_VERSION}::BreezeIcons)
endif()
set(kazv_INSTALL_ARGS ${KF_INSTALL_TARGETS_DEFAULT_ARGS})
if(NOT kazv_INSTALL_ARGS)
set(kazv_INSTALL_ARGS ${KF${KF_MAJOR_VERSION}_INSTALL_TARGETS_DEFAULT_ARGS})
endif()
install(TARGETS kazv ${kazv_INSTALL_ARGS})
add_subdirectory(tests)
diff --git a/src/contents/ui/ActionSettingsPage.qml b/src/contents/ui/ActionSettingsPage.qml
index 01c9a21..6f5499a 100644
--- a/src/contents/ui/ActionSettingsPage.qml
+++ b/src/contents/ui/ActionSettingsPage.qml
@@ -1,21 +1,21 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2020-2022 Tusooa Zhu <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import org.kde.kirigami 2.13 as Kirigami
import '.' as Kazv
import 'shortcuts' as KazvShortcuts
-Kazv.ClosableScrollablePage {
+Kazv.ClosableScrollableOverlay {
id: page
property alias actionsToConfigure: settings.actions
title: l10n.get('action-settings-page-title')
KazvShortcuts.ActionSettings {
id: settings
shortcutsConfig: kazvConfig
}
}
diff --git a/src/contents/ui/ClosableScrollableOverlay.qml b/src/contents/ui/ClosableScrollableOverlay.qml
new file mode 100644
index 0000000..a91d2be
--- /dev/null
+++ b/src/contents/ui/ClosableScrollableOverlay.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.2
+
+import '.' as Kazv
+
+Kazv.ScrollablePageAdapter {
+ onBackRequested: (event) => {
+ event.accepted = true;
+ applicationWindow().pageStack.layers.pop();
+ }
+}
diff --git a/src/contents/ui/CreateRoomPage.qml b/src/contents/ui/CreateRoomPage.qml
index f4c264a..bb323c4 100644
--- a/src/contents/ui/CreateRoomPage.qml
+++ b/src/contents/ui/CreateRoomPage.qml
@@ -1,201 +1,201 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2022-2024 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import org.kde.kirigami 2.13 as Kirigami
import '.' as Kazv
import './matrix-helpers.js' as Helpers
import moe.kazv.mxc.kazv 0.0 as MK
-Kazv.ClosableScrollablePage {
+Kazv.ClosableScrollableOverlay {
id: createRoomPage
title: l10n.get('create-room-page-title')
property var creatingRoom: false
property var inviteUserIds: []
property var encryptedChangedOnce: false
ButtonGroup {
id: roomTypeButtons
}
Kirigami.FormLayout {
anchors.fill: parent
ColumnLayout {
Kirigami.FormData.label: l10n.get('create-room-page-type-prompt')
RadioButton {
id: typePublic
objectName: 'typePublicRadio'
checked: true
onCheckedChanged: {
if (!createRoomPage.encryptedChangedOnce) {
encrypted.checked = !checked;
}
}
text: l10n.get('create-room-page-type-public')
ButtonGroup.group: roomTypeButtons
}
RadioButton {
id: typePrivate
objectName: 'typePrivateRadio'
text: l10n.get('create-room-page-type-private')
ButtonGroup.group: roomTypeButtons
}
RadioButton {
id: typeDirect
objectName: 'typeDirectRadio'
text: l10n.get('create-room-page-type-direct')
ButtonGroup.group: roomTypeButtons
}
}
TextField {
id: roomName
objectName: 'roomNameInput'
Kirigami.FormData.label: l10n.get('create-room-page-name-prompt')
placeholderText: l10n.get('create-room-page-name-placeholder')
Layout.fillWidth: true
}
TextField {
id: roomAlias
objectName: 'roomAliasInput'
Kirigami.FormData.label: l10n.get('create-room-page-alias-prompt')
placeholderText: l10n.get('create-room-page-alias-placeholder')
Layout.fillWidth: true
}
TextField {
id: roomTopic
objectName: 'roomTopicInput'
Kirigami.FormData.label: l10n.get('create-room-page-topic-prompt')
placeholderText: l10n.get('create-room-page-topic-placeholder')
Layout.fillWidth: true
}
CheckBox {
id: allowFederate
checked: true
text: l10n.get('create-room-page-allow-federate-prompt')
Layout.fillWidth: true
}
CheckBox {
id: encrypted
objectName: 'encryptedInput'
text: l10n.get('create-room-page-encrypted-prompt')
Layout.fillWidth: true
onToggled: createRoomPage.encryptedChangedOnce = true
}
Item {
Kirigami.FormData.isSection: true
Kirigami.FormData.label: l10n.get('create-room-invite-userids-prompt')
}
ColumnLayout {
Repeater {
model: createRoomPage.inviteUserIds.length
delegate: Kirigami.SwipeListItem {
objectName: 'inviteUserItem_' + index
Layout.fillWidth: true
Layout.minimumWidth: Kirigami.Units.gridUnit * 10
contentItem: RowLayout {
Label {
Layout.fillWidth: true
objectName: 'inviteUserIdLabel'
text: createRoomPage.inviteUserIds[index]
}
}
actions: [
Kirigami.Action {
objectName: 'removeInviteAction'
icon.name: 'list-remove-symbolic'
text: l10n.get('create-room-page-action-remove-invite')
onTriggered: {
createRoomPage.inviteUserIds.splice(index, 1);
// trigger reactivity
createRoomPage.inviteUserIds = createRoomPage.inviteUserIds;
}
}
]
}
}
}
TextField {
id: newInviteUserId
Kirigami.FormData.label: l10n.get('create-room-page-add-invite-prompt')
placeholderText: l10n.get('create-room-page-add-invite-placeholder')
objectName: 'newInviteUserInput'
text: ''
Layout.fillWidth: true
}
Button {
id: addInviteUserButton
objectName: 'addInviteUserButton'
text: l10n.get('create-room-page-action-add-invite')
Layout.fillWidth: true
onClicked: {
createRoomPage.inviteUserIds.push(newInviteUserId.text);
// trigger reactivity
createRoomPage.inviteUserIds = createRoomPage.inviteUserIds;
newInviteUserId.text = '';
}
}
Button {
Layout.fillWidth: true
objectName: 'createRoomButton'
text: l10n.get('create-room-page-action-create-room')
onClicked: createRoomPage.createRoom.call()
}
}
property var createRoom: Kazv.AsyncHandler {
trigger: () => matrixSdk.createRoom(
/* isPrivate = */ typePrivate.checked || typeDirect.checked,
roomName.text,
roomAlias.text,
createRoomPage.inviteUserIds,
/* isDirect = */ typeDirect.checked && createRoomPage.inviteUserIds.length === 1,
/* allowFederate = */ allowFederate.checked,
roomTopic.text,
/* powerLevelContentOverride = */ {},
/* preset = */ typeDirect.checked
? MK.MatrixSdk.TrustedPrivateChat
: typePrivate.checked
? MK.MatrixSdk.PrivateChat
: MK.MatrixSdk.PublicChat,
/* encrypted = */ encrypted.checked,
)
onResolved: {
if (success) {
if (typeDirect.checked && createRoomPage.inviteUserIds.length === 1) {
matrixSdk.addDirectRoom(createRoomPage.inviteUserIds[0], data.roomId);
}
showPassiveNotification(l10n.get('create-room-page-success-prompt'));
pageStack.removePage(createRoomPage);
} else {
showPassiveNotification(l10n.get('create-room-page-failed-prompt', { errorCode: data.errorCode, errorMsg: data.error }));
}
}
}
function presetPage(userId) {
typeDirect.checked = true;
newInviteUserId.text = userId;
addInviteUserButton.click();
}
}
diff --git a/src/contents/ui/JoinRoomPage.qml b/src/contents/ui/JoinRoomPage.qml
index a96f1c6..69d58e0 100644
--- a/src/contents/ui/JoinRoomPage.qml
+++ b/src/contents/ui/JoinRoomPage.qml
@@ -1,80 +1,80 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2022-2024 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.1
import org.kde.kirigami 2.4 as Kirigami
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.1
import '.' as Kazv
-Kazv.ClosableScrollablePage {
+Kazv.ClosableScrollableOverlay {
id: joinRoomPage
title: l10n.get('join-room-page-title')
ButtonGroup {
id: visibilityButtons
}
ColumnLayout {
width: parent.width
spacing: Kirigami.Units.largeSpacing
GridLayout {
columns: 2
Label {
text: l10n.get('join-room-page-id-or-alias-prompt')
}
TextField {
id: idOrAlias
objectName: 'idOrAliasInput'
placeholderText: l10n.get('join-room-page-id-or-alias-placeholder')
Layout.fillWidth: true
}
Label {
text: l10n.get('join-room-page-servers-prompt')
}
TextArea {
id: servers
objectName: 'serversInput'
placeholderText: l10n.get('join-room-page-servers-placeholder')
Layout.fillWidth: true
}
}
Button {
objectName: 'joinRoomButton'
text: l10n.get('join-room-page-action-join-room')
onClicked: joinRoomPage.joinRoom()
}
}
property var joinRoomHandler: Kazv.AsyncHandler {
property var serverNames: servers.text.split('\n').map(k => k.trim()).filter(k => k)
property var room: idOrAlias.text
trigger: () => matrixSdk.joinRoom(room, serverNames)
onResolved: {
if (success) {
showPassiveNotification(l10n.get('join-room-page-success-prompt', { room }));
pageStack.removePage(joinRoomPage);
} else {
showPassiveNotification(l10n.get('join-room-page-failed-prompt', { room, errorCode: data.errorCode, errorMsg: data.error }));
}
}
}
function joinRoom()
{
joinRoomHandler.call();
}
function presetPage(roomIdOrAlias, routingServers) {
idOrAlias.text = roomIdOrAlias;
servers.text = routingServers.join('\n');
}
}
diff --git a/src/contents/ui/Main.qml b/src/contents/ui/Main.qml
index f5a5ac6..2dceb16 100644
--- a/src/contents/ui/Main.qml
+++ b/src/contents/ui/Main.qml
@@ -1,381 +1,379 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2020-2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick
import org.kde.kirigami as Kirigami
import QtQuick.Layouts
import QtQuick.Controls
import moe.kazv.mxc.kazv as MK
import '.' as Kazv
import 'shortcuts' as KazvShortcuts
import 'l10n.js' as L10n
Kirigami.ApplicationWindow {
id: root
property var kazvIOManager: MK.KazvIOManager {
cacheDirectory: kazvConfig.cacheDirectory
}
property bool loadingSession: false
property var matrixSdk: MK.MatrixSdk {
onLoginSuccessful: {
switchToMainPage();
recordLastSession();
root.purgeTimer.start();
}
onLoginFailed: {
console.log("Login Failed");
showPassiveNotification(l10n.get('login-page-request-failed-prompt', { errorCode, errorMsg }));
}
onDiscoverFailed: {
console.log("Discover Failed");
showPassiveNotification(l10n.get('login-page-discover-failed-enter-prompt', { errorCode, errorMsg }));
}
onSessionChanged: {
console.log('session changed');
reloadSdkVariables();
root.purgeTimer.start();
}
onLogoutSuccessful: {
root.loggedIn = false;
- root.mainPage = Qt.createComponent("MainPage.qml").createObject(root);
pageStack.clear();
pushLoginPage();
}
onLogoutFailed: {
console.warn('Logout failed');
showPassiveNotification(l10n.get('logout-failed-prompt', { errorCode, errorMsg }));
}
onLoadSessionFinished: (sessionName, res) => {
root.loadingSession = false;
if (res === MK.MatrixSdk.SessionLoadSuccess) {
console.log('load session successful');
switchToMainPage();
recordLastSession();
matrixSdk.getSpecVersions();
} else {
showPassiveNotification(getSessionLoadError(res, sessionName));
}
}
}
property var loggedIn: !!matrixSdk.token
property var sdkVars: QtObject {
property var roomList: matrixSdk.roomList()
property var userGivenNicknameMap: matrixSdk.userGivenNicknameMap()
property string currentRoomId: ''
}
property var purgeTimer: Timer {
interval: 1000 * 60 * 5
repeat: true
triggeredOnStart: true
onTriggered: () => {
matrixSdk.purgeEventsExceptRooms(
sdkVars.currentRoomId ? [sdkVars.currentRoomId] : []);
}
}
property var l10nProvider: MK.L10nProvider {
}
property var kazvConfig: MK.KazvConfig {
}
function initializeL10n () {
const availableLocales = l10nProvider.availableLocaleCodes();
console.log('available locales:', availableLocales);
const desiredLanguages = [Qt.uiLanguage];
console.log('ui language is: ', desiredLanguages);
const defaultLocale = 'en';
const wantedLocales = L10n.negotiateLanguages(desiredLanguages, availableLocales, defaultLocale);
console.log('wanted locales:', wantedLocales);
const bundles = L10n.generateBundles(wantedLocales, l10nProvider.getFtlData(wantedLocales));
const provider = new L10n.FluentProvider(bundles);
return provider;
}
property var l10n: initializeL10n();
property var confirmLogoutPopup: Kirigami.OverlaySheet {
id: confirmLogoutPopup
title: l10n.get('confirm-logout-popup-title')
ColumnLayout {
Label {
Layout.fillWidth: true
text: l10n.get('confirm-logout-popup-prompt')
}
RowLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignCenter
Button {
text: l10n.get('confirm-logout-popup-accept-button')
onClicked: {
hardLogout();
confirmLogoutPopup.close();
}
}
Button {
text: l10n.get('confirm-logout-popup-cancel-button')
onClicked: confirmLogoutPopup.close();
}
}
}
}
title: l10n.get('app-title')
globalDrawer: Kirigami.GlobalDrawer {
title: l10n.get('global-drawer-title')
titleIcon: "applications-graphics"
property var actionGroupName: 'global-drawer-actions'
actions: [
Kirigami.Action {
objectName: 'switch-account'
text: l10n.get('global-drawer-action-switch-account')
icon.name: 'system-switch-user'
onTriggered: switchAccount()
},
Kirigami.Action {
objectName: 'hard-logout'
text: l10n.get('global-drawer-action-hard-logout')
icon.name: 'application-exit'
onTriggered: confirmLogoutPopup.open()
},
Kirigami.Action {
objectName: 'save'
text: l10n.get('global-drawer-action-save-session')
icon.name: 'document-save'
onTriggered: {
recordLastSession()
matrixSdk.serializeToFile()
}
},
Kirigami.Action {
objectName: 'configure-shortcuts'
text: l10n.get('global-drawer-action-configure-shortcuts')
icon.name: 'configure-shortcuts'
onTriggered: {
pushActionSettingsPage();
}
},
Kirigami.Action {
objectName: 'settings'
text: l10n.get('global-drawer-action-settings')
icon.name: 'configure'
onTriggered: {
pushSettingsPage();
}
},
Kirigami.Action {
objectName: 'create-room'
enabled: root.loggedIn
icon.name: 'contact-new'
text: l10n.get('global-drawer-action-create-room')
onTriggered: {
pushCreateRoomPage();
}
},
Kirigami.Action {
objectName: 'join-room'
enabled: root.loggedIn
text: l10n.get('global-drawer-action-join-room')
icon.name: 'list-add-user'
onTriggered: {
pushJoinRoomPage();
}
},
Kirigami.Action {
objectName: 'aboutAction'
text: l10n.get('global-drawer-action-about')
icon.name: 'help-about'
onTriggered: pageStack.pushDialogLayer(Qt.resolvedUrl('About.qml'))
}
]
}
contextDrawer: Kirigami.ContextDrawer {
id: contextDrawer
}
property var actionCollection: KazvShortcuts.ActionCollection {
id: globalActionCollection
children: [
root.globalDrawer,
root.contextDrawer,
]
shortcutsConfig: kazvConfig
}
property var notifier: Kazv.Notifier {
}
pageStack.initialPage: Qt.resolvedUrl("LoginPage.qml")
- property var mainPage: Kazv.MainPage {}
-
property var emptyPage: Kirigami.Page {
title: l10n.get('empty-room-page-title')
Label {
text: l10n.get('empty-room-page-description')
}
}
signal switchToRoomRequested(string roomId)
property var pageManager: Kazv.PageManager {
pageStack: root.pageStack
sdkVars: root.sdkVars
main: root
}
function activateRoomSettingsPage(room) {
- pageStack.push(Qt.resolvedUrl("room-settings/RoomSettingsPage.qml"), {
+ pageStack.layers.push(Qt.resolvedUrl("room-settings/RoomSettingsPage.qml"), {
room
});
}
function activateRoomPinnedEventsPage(room) {
pageStack.push(Qt.resolvedUrl('RoomPinnedEventsPage.qml'), {
room
});
}
function activateRoomInvitePage(room) {
- pageStack.push(Qt.resolvedUrl("room-settings/RoomInvitePage.qml"), {
+ pageStack.layers.push(Qt.resolvedUrl("room-settings/RoomInvitePage.qml"), {
room
});
}
function activateRoomStickerPacksPage(room) {
- pageStack.push(Qt.resolvedUrl("room-settings/RoomStickerPacksPage.qml"), {
+ pageStack.layers.push(Qt.resolvedUrl("room-settings/RoomStickerPacksPage.qml"), {
room
});
}
function activateRoomStatePage(room) {
- pageStack.push(Qt.resolvedUrl("room-settings/RoomStatePage.qml"), {
+ pageStack.layers.push(Qt.resolvedUrl("room-settings/RoomStatePage.qml"), {
room
});
}
function activateUserPage(user, room, userId) {
- pageStack.push(Qt.resolvedUrl("UserPage.qml"), {
+ pageStack.layers.push(Qt.resolvedUrl("UserPage.qml"), {
userId: userId || user.userId,
user,
room
});
}
function switchToMainPage() {
- pageStack.replace([root.mainPage])
- pageStack.currentIndex = 0
+ pageStack.layers.clear();
+ pageStack.replace([Qt.resolvedUrl('MainPage.qml')]);
+ pageStack.currentIndex = 0;
}
function switchToLoginPage() {
pageStack.replace([Qt.resolvedUrl("LoginPage.qml")])
pageStack.currentIndex = 0
}
function pushLoginPage() {
- pageStack.push(Qt.resolvedUrl("LoginPage.qml"), {
+ pageStack.layers.push(Qt.resolvedUrl("LoginPage.qml"), {
isSwitchingAccount: true,
});
}
function pushActionSettingsPage() {
- pageStack.push(Qt.resolvedUrl("ActionSettingsPage.qml"), {
+ pageStack.layers.push(Qt.resolvedUrl("ActionSettingsPage.qml"), {
actionsToConfigure: globalActionCollection.allActions(),
});
}
function pushSettingsPage() {
- pageStack.push(Qt.resolvedUrl("SettingsPage.qml"));
+ pageStack.layers.push(Qt.resolvedUrl("SettingsPage.qml"));
}
function pushCreateRoomPage() {
- pageStack.push(Qt.resolvedUrl("CreateRoomPage.qml"), {});
+ pageStack.layers.push(Qt.resolvedUrl("CreateRoomPage.qml"), {});
}
function pushJoinRoomPage() {
- pageStack.push(Qt.resolvedUrl("JoinRoomPage.qml"), {});
+ pageStack.layers.push(Qt.resolvedUrl("JoinRoomPage.qml"), {});
}
function sessionNameFor(userId, deviceId) {
return userId + '/' + deviceId;
}
function getSessionLoadError(res, sessionName) {
switch (res) {
case MK.MatrixSdk.SessionNotFound:
return l10n.get('session-load-failure-not-found', { sessionName });
case MK.MatrixSdk.SessionFormatUnknown:
return l10n.get('session-load-failure-format-unknown', { sessionName });
case MK.MatrixSdk.SessionCannotBackup:
return l10n.get('session-load-failure-cannot-backup', { sessionName });
case MK.MatrixSdk.SessionLockFailed:
return l10n.get('session-load-failure-lock-failed', { sessionName });
case MK.MatrixSdk.SessionCannotOpenFile:
return l10n.get('session-load-failure-cannot-open-file', { sessionName });
case MK.MatrixSdk.SessionDeserializeFailed:
return l10n.get('session-load-failure-deserialize-failed', { sessionName });
default:
console.error('loadSession: Encountered an unknown error code');
}
}
function loadSession(sessionName) {
root.loadingSession = true;
matrixSdk.loadSession(sessionName);
}
function loadLastSession() {
console.log('last session is:', kazvConfig.lastSession);
return loadSession(kazvConfig.lastSession);
}
function recordLastSession() {
kazvConfig.lastSession = sessionNameFor(matrixSdk.userId, matrixSdk.deviceId);
}
function reloadSdkVariables() {
sdkVars.roomList = matrixSdk.roomList();
sdkVars.userGivenNicknameMap = matrixSdk.userGivenNicknameMap();
sdkVars.currentRoomId = '';
}
function switchAccount() {
pushLoginPage();
}
function hardLogout() {
matrixSdk.logout();
}
Component.onCompleted: {
actionCollection.setupShortcuts();
loadLastSession();
}
onClosing: {
kazvIOManager.clearJobs()
}
}
diff --git a/src/contents/ui/SettingsPage.qml b/src/contents/ui/SettingsPage.qml
index e2c8f92..69fb3a3 100644
--- a/src/contents/ui/SettingsPage.qml
+++ b/src/contents/ui/SettingsPage.qml
@@ -1,43 +1,43 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import org.kde.kirigami 2.13 as Kirigami
import '.' as Kazv
import 'settings' as Settings
-Kazv.ClosableScrollablePage {
+Kazv.ClosableScrollableOverlay {
id: settingsPage
title: l10n.get('settings-page-title')
contextualActions: [
Kirigami.Action {
icon.name: 'document-save'
text: l10n.get('settings-save')
onTriggered: { settingsPage.saveRecursively() }
}
]
ColumnLayout {
Settings.ProfileSettings {
id: profileSettings
Layout.fillWidth: true
}
Settings.CacheSettings {
id: cacheSettings
Layout.fillWidth: true
}
}
function saveRecursively() {
profileSettings.save();
cacheSettings.save();
}
}
diff --git a/src/contents/ui/UserPage.qml b/src/contents/ui/UserPage.qml
index 3147869..132cc48 100644
--- a/src/contents/ui/UserPage.qml
+++ b/src/contents/ui/UserPage.qml
@@ -1,394 +1,394 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2020-2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import org.kde.kirigami as Kirigami
import moe.kazv.mxc.kazv as MK
import '.' as Kazv
import 'device-mgmt' as KazvDM
import 'matrix-helpers.js' as Helpers
-Kazv.ClosableScrollablePage {
+Kazv.ClosableScrollableOverlay {
id: userPage
property string userId: ''
property var user: ({})
property var nameProvider: Kazv.UserNameProvider {
user: userPage.user
}
property var room
property var roomNameProvider: Kazv.RoomNameProvider {
room: userPage.room
}
property var roomName: roomNameProvider.name
property var editingPowerLevel: false
property var submittingPowerLevel: false
property var powerLevelsLoaded: false
property var userPowerLevel: room.userPowerLevel(userId)
property var kickingUser: false
property var canKickUser: !(user.membership === 'ban' || user.membership === 'leave')
property var banningUser: false
property var unbanningUser: false
Connections {
target: room
function onPowerLevelsChanged() {
userPage.userPowerLevel = room.userPowerLevel(userPage.userId);
}
}
title: nameProvider.name
property var ensureMemberEvent: Kazv.AsyncHandler {
trigger: () => room.ensureStateEvent('m.room.member', userId)
}
property var ensurePowerLevels: Kazv.AsyncHandler {
trigger: () => room.ensureStateEvent('m.room.power_levels', '')
onResolved: (success, data) => {
if (success) {
userPage.powerLevelsLoaded = true;
}
}
}
property var updatingNameOverride: false
property var updateNameOverride: Kazv.AsyncHandler {
trigger: () => {
userPage.updatingNameOverride = true;
return sdkVars.userGivenNicknameMap.setAndUpload(
userPage.userId, nameOverrideInput.text || null);
}
onResolved: (success, data) => {
userPage.updatingNameOverride = false;
if (!success) {
showPassiveNotification(l10n.get('user-page-update-name-override-failed-prompt', { errorCode: data.errorCode, errorMsg: data.error }));
}
}
}
property bool updatingSelfName: false
property var updateSelfName: Kazv.AsyncHandler {
trigger: () => {
userPage.updatingSelfName = true;
return userPage.room.setSelfName(selfNameInput.text);
}
onResolved: (success, data) => {
userPage.updatingSelfName = false;
if (!success) {
showPassiveNotification(l10n.get('user-page-update-self-name-failed-prompt', { errorCode: data.errorCode, errorMsg: data.error }));
}
}
}
Component.onCompleted: {
userPage.ensureMemberEvent.call();
userPage.ensurePowerLevels.call();
}
property var setPowerLevel: Kazv.AsyncHandler {
trigger: () => {
userPage.submittingPowerLevel = true;
return room.setUserPowerLevel(userPage.userId, parseInt(newPowerLevel.text));
}
onResolved: (success, data) => {
if (!success) {
showPassiveNotification(l10n.get('user-page-set-power-level-failed-prompt', { errorCode: data.errorCode, errorMsg: data.error }));
} else {
userPage.editingPowerLevel = false;
}
userPage.submittingPowerLevel = false;
}
}
property var kickUser: Kazv.AsyncHandler {
trigger: () => {
userPage.kickingUser = true;
return room.kickUser(userPage.userId, kickUserReasonInput.text);
}
onResolved: {
if (!success) {
showPassiveNotification(l10n.get('user-page-kick-user-failed-prompt', { errorCode: data.errorCode, errorMsg: data.error }));
} else {
kickUserReasonInput.text = '';
}
userPage.kickingUser = false;
}
}
property var banUser: Kazv.AsyncHandler {
trigger: () => {
userPage.banningUser = true;
return room.banUser(userPage.userId, banUserReasonInput.text);
}
onResolved: {
if (!success) {
showPassiveNotification(l10n.get('user-page-ban-user-failed-prompt', { errorCode: data.errorCode, errorMsg: data.error }));
} else {
banUserReasonInput.text = '';
}
userPage.banningUser = false;
}
}
property var unbanUser: Kazv.AsyncHandler {
trigger: () => {
userPage.unbanningUser = true;
return room.unbanUser(userPage.userId);
}
onResolved: {
if (!success) {
showPassiveNotification(l10n.get('user-page-unban-user-failed-prompt', { errorCode: data.errorCode, errorMsg: data.error }));
}
userPage.unbanningUser = false;
}
}
ColumnLayout {
Kazv.AvatarAdapter {
id: avatar
objectName: 'avatar'
Layout.alignment: Qt.AlignHCenter
Layout.preferredHeight: Kirigami.Units.iconSizes.enormous
Layout.preferredWidth: Kirigami.Units.iconSizes.enormous
mxcUri: userPage.user.avatarMxcUri
name: nameProvider.name
}
ColumnLayout {
Layout.preferredWidth: this.parent.width
Label {
objectName: 'userNameLabel'
Layout.alignment: Qt.AlignHCenter
text: !!userPage.user.name ? userPage.user.name : userPage.userId
}
Label {
objectName: 'userIdLabel'
Layout.alignment: Qt.AlignHCenter
font: Kirigami.Theme.smallFont
visible: !!userPage.user.name
text: userPage.userId
}
}
RowLayout {
visible: room.membership === MK.MatrixRoom.Join && userPage.userId === matrixSdk.userId
TextField {
id: selfNameInput
objectName: 'selfNameInput'
placeholderText: l10n.get('user-page-self-name-placeholder')
Layout.fillWidth: true
Accessible.name: l10n.get('user-page-self-name-prompt')
enabled: !userPage.updatingSelfName
text: userPage.user.name
}
Button {
objectName: 'saveSelfNameButton'
text: l10n.get('user-page-save-self-name-action')
enabled: !userPage.updatingSelfName
onClicked: userPage.updateSelfName.call()
}
}
RowLayout {
// Do not allow user to set a name override for themselves
visible: userPage.userId !== matrixSdk.userId
TextField {
id: nameOverrideInput
objectName: 'nameOverrideInput'
placeholderText: l10n.get('user-page-overrided-name-placeholder')
Layout.fillWidth: true
enabled: !userPage.updatingNameOverride
text: nameProvider.overridedName
}
Button {
objectName: 'saveNameOverrideButton'
text: l10n.get('user-page-save-name-override-action')
enabled: !userPage.updatingNameOverride
onClicked: updateNameOverride.call()
}
}
RowLayout {
visible: !userPage.editingPowerLevel
Label {
objectName: 'powerLevelLabel'
Layout.fillWidth: true
text: l10n.get('user-page-power-level', { powerLevel: userPage.userPowerLevel })
}
Button {
objectName: 'editPowerLevelButton'
text: l10n.get('user-page-edit-power-level-action')
enabled: userPage.powerLevelsLoaded
onClicked: {
userPage.editingPowerLevel = true;
}
}
}
RowLayout {
visible: userPage.editingPowerLevel
TextField {
objectName: 'newPowerLevelInput'
id: newPowerLevel
Layout.fillWidth: true
text: `${userPage.userPowerLevel}`
readOnly: userPage.submittingPowerLevel
}
Button {
objectName: 'savePowerLevelButton'
text: l10n.get('user-page-save-power-level-action')
onClicked: {
setPowerLevel.call();
}
enabled: !userPage.submittingPowerLevel
}
Button {
objectName: 'discardPowerLevelButton'
text: l10n.get('user-page-discard-power-level-action')
enabled: !userPage.submittingPowerLevel
onClicked: {
userPage.editingPowerLevel = false;
newPowerLevel.text = `${userPage.userPowerLevel}`;
}
}
}
ColumnLayout {
Kirigami.PromptDialog {
id: kickUserReasonDialog
objectName: 'kickUserReasonDialog'
title: l10n.get('user-page-kick-user-confirm-dialog-title')
standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
onAccepted: {
userPage.kickUser.call()
}
ColumnLayout {
Label {
Layout.fillWidth: true
text: l10n.get('user-page-kick-user-confirm-dialog-content', {
userId: userPage.user.userId,
name: nameProvider.name,
roomName: userPage.roomName,
})
wrapMode: Text.Wrap
}
ColumnLayout {
Label {
Layout.fillWidth: true
text: l10n.get('user-page-kick-user-confirm-dialog-content', {
userId: userPage.user.userId,
name: userPage.user.name,
roomName: userPage.roomName,
})
wrapMode: Text.Wrap
}
Kirigami.FormLayout {
Layout.fillWidth: true
TextField {
Layout.fillWidth: true
id: kickUserReasonInput
objectName: 'kickUserReasonInput'
readOnly: userPage.kickingUser
Kirigami.FormData.label: l10n.get('user-page-kick-user-reason-prompt')
}
}
}
}
}
Button {
objectName: 'kickUserButton'
icon.name: 'im-kick-user'
Layout.fillWidth: true
enabled: !userPage.kickingUser
text: l10n.get('user-page-kick-user-action')
visible: userPage.canKickUser
onClicked: {
kickUserReasonDialog.open()
}
}
}
RowLayout {
Kirigami.PromptDialog {
id: banUserReasonDialog
objectName: 'banUserReasonDialog'
title: l10n.get('user-page-ban-user-confirm-dialog-title')
standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
onAccepted: {
userPage.banUser.call()
}
ColumnLayout {
Label {
Layout.fillWidth: true
text: l10n.get('user-page-ban-user-confirm-dialog-content', {
userId: userPage.user.userId,
name: nameProvider.name,
roomName: userPage.roomName,
})
wrapMode: Text.Wrap
}
Kirigami.FormLayout {
Layout.fillWidth: true
TextField {
Layout.fillWidth: true
id: banUserReasonInput
objectName: 'banUserReasonInput'
readOnly: userPage.banningUser
Kirigami.FormData.label: l10n.get('user-page-ban-user-reason-prompt')
}
}
}
}
Button {
objectName: 'banUserButton'
Layout.fillWidth: true
icon.name: 'im-ban-kick-user'
enabled: !userPage.banningUser
text: l10n.get('user-page-ban-user-action')
visible: !unbanUserButton.visible
onClicked: {
banUserReasonDialog.open()
}
}
Button {
id: unbanUserButton
objectName: 'unbanUserButton'
Layout.fillWidth: true
icon.name: 'im-user-online'
enabled: !userPage.unbanningUser
text: l10n.get('user-page-unban-user-action')
visible: user.membership === "ban"
onClicked: {
userPage.unbanUser.call()
}
}
}
KazvDM.DeviceList {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumHeight: childrenRect.height
userId: userPage.userId
devices: matrixSdk.devicesOfUser(userId)
}
}
}
diff --git a/src/contents/ui/room-settings/RoomInvitePage.qml b/src/contents/ui/room-settings/RoomInvitePage.qml
index e01752b..fa70ca2 100644
--- a/src/contents/ui/room-settings/RoomInvitePage.qml
+++ b/src/contents/ui/room-settings/RoomInvitePage.qml
@@ -1,61 +1,61 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import org.kde.kirigami 2.20 as Kirigami
import '..' as Kazv
import '../matrix-helpers.js' as Helpers
-Kazv.ClosableScrollablePage {
+Kazv.ClosableScrollableOverlay {
id: roomInvitePage
property var room
property var roomNameProvider: Kazv.RoomNameProvider {
room: roomInvitePage.room
}
property var roomDisplayName: roomNameProvider.name
property var inviting: false
title: l10n.get('room-invite-page-title', { room: roomDisplayName })
property var inviteUser: Kazv.AsyncHandler {
trigger: () => {
roomInvitePage.inviting = true;
return room.inviteUser(inviteUserIdInput.text);
}
onResolved: {
roomInvitePage.inviting = false;
if (!success) {
showPassiveNotification(l10n.get('room-invite-page-invite-failed-prompt', { errorCode: data.errorCode, errorMsg: data.error }));
} else {
pageStack.removePage(roomInvitePage);
}
}
}
Kirigami.FormLayout {
TextField {
id: inviteUserIdInput
objectName: 'inviteUserIdInput'
placeholderText: l10n.get('room-invite-invitee-matrix-id-placeholder')
Kirigami.FormData.label: l10n.get('room-invite-invitee-matrix-id-prompt')
}
Button {
objectName: 'inviteUserButton'
text: l10n.get('room-invite-page-invite-button')
enabled: !roomInvitePage.inviting
Layout.fillWidth: true
onClicked: {
roomInvitePage.inviteUser.call();
}
}
}
}
diff --git a/src/contents/ui/room-settings/RoomMemberListPage.qml b/src/contents/ui/room-settings/RoomMemberListPage.qml
index 5e3532c..ad77622 100644
--- a/src/contents/ui/room-settings/RoomMemberListPage.qml
+++ b/src/contents/ui/room-settings/RoomMemberListPage.qml
@@ -1,34 +1,34 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import org.kde.kirigami 2.13 as Kirigami
import '../matrix-helpers.js' as Helpers
import '..' as Kazv
-Kazv.ClosableScrollablePage {
+Kazv.ClosableScrollableOverlay {
id: roomSettingsPage
property var room
required property var members
property var roomNameProvider: Kazv.RoomNameProvider {
room: roomSettingsPage.room
}
property var roomDisplayName: roomNameProvider.name
title: l10n.get('room-member-list-page-title', { room: roomDisplayName })
Kazv.RoomMemberListView {
room: roomSettingsPage.room
members: roomSettingsPage.members
}
Component.onCompleted: room.refreshState()
}
diff --git a/src/contents/ui/room-settings/RoomSettingsPage.qml b/src/contents/ui/room-settings/RoomSettingsPage.qml
index 7603b3c..9cb4080 100644
--- a/src/contents/ui/room-settings/RoomSettingsPage.qml
+++ b/src/contents/ui/room-settings/RoomSettingsPage.qml
@@ -1,433 +1,433 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import org.kde.kirigami 2.20 as Kirigami
import moe.kazv.mxc.kazv 0.0 as MK
import '../matrix-helpers.js' as Helpers
import '..' as Kazv
import '.' as RoomSettings
-Kazv.ClosableScrollablePage {
+Kazv.ClosableScrollableOverlay {
id: roomSettingsPage
property var room
property var roomNameProvider: Kazv.RoomNameProvider {
room: roomSettingsPage.room
}
property var roomDisplayName: roomNameProvider.name
property var customTagIds: room.tagIds.filter(k => k.startsWith('u.'))
property var editingName: false
property var submittingName: false
property var submitName: Kazv.AsyncHandler {
trigger: () => {
roomSettingsPage.submittingName = true;
return roomSettingsPage.room.setName(roomNameEdit.text);
}
onResolved: (success, data) => {
roomSettingsPage.submittingName = false;
if (success) {
roomSettingsPage.editingName = false;
} else {
showPassiveNotification(l10n.get('room-settings-set-name-failed-prompt', {
room: room.roomId,
errorCode: data.errorCode,
errorMsg: data.error,
}));
}
}
}
property var editingTopic: false
property var submittingTopic: false
property var submitTopic: Kazv.AsyncHandler {
trigger: () => {
roomSettingsPage.submittingTopic = true;
return roomSettingsPage.room.setTopic(roomTopicEdit.text);
}
onResolved: (success, data) => {
roomSettingsPage.submittingTopic = false;
if (success) {
roomSettingsPage.editingTopic = false;
} else {
showPassiveNotification(l10n.get('room-settings-set-topic-failed-prompt', {
room: room.roomId,
errorCode: data.errorCode,
errorMsg: data.error,
}));
}
}
}
title: l10n.get('room-settings-page-title', { room: roomDisplayName })
function tagIdToName(tagId) {
return tagId.slice(2);
}
property var encryptionPopup: Kirigami.PromptDialog {
parent: roomSettingsPage.overlay
objectName: 'encryptionPopup'
title: l10n.get('room-settings-enable-encryption-prompt-dialog-title')
standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
ColumnLayout {
Label {
Layout.fillWidth: true
text: l10n.get('room-settings-enable-encryption-prompt-dialog-prompt')
wrapMode: Text.Wrap
}
}
onAccepted: enableEncryption.call()
}
property var enablingEncryption: false
property var enableEncryption: Kazv.AsyncHandler {
trigger: () => {
roomSettingsPage.enablingEncryption = true;
return room.sendStateEvent({
type: 'm.room.encryption',
state_key: '',
content: {
algorithm: 'm.megolm.v1.aes-sha2',
},
});
}
onResolved: (success, data) => {
roomSettingsPage.enablingEncryption = false;
if (success) {
showPassiveNotification(l10n.get('room-settings-encryption-enabled-notification'));
} else {
showPassiveNotification(l10n.get('room-settings-encryption-failed-to-enable-notification', { errorCode: data.errorCode, errorMsg: data.error }));
}
}
}
property var tagHandler: RoomSettings.RoomTagHandler {
room: roomSettingsPage.room
}
property var members: room.members()
property var avatarCount: 4
ColumnLayout {
RowLayout {
Layout.alignment: Qt.AlignHCenter
Repeater {
objectName: 'roomMembersAvatarsRepeater'
model: Math.min(members.count, roomSettingsPage.avatarCount)
Kazv.AvatarAdapter {
property var member: members.at(index)
property var nameProvider: Kazv.UserNameProvider {
user: member
}
Layout.preferredHeight: Kirigami.Units.iconSizes.huge
Layout.preferredWidth: Kirigami.Units.iconSizes.huge
mxcUri: member.avatarMxcUri
name: nameProvider.name
}
}
Kirigami.Icon {
objectName: 'roomMembersAvatarsMore'
Layout.preferredHeight: Kirigami.Units.iconSizes.huge
Layout.preferredWidth: Kirigami.Units.iconSizes.huge
source: 'go-next-skip'
visible: members.count > roomSettingsPage.avatarCount
}
}
ColumnLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
Label {
objectName: 'roomIdLabel'
Layout.alignment: Qt.AlignHCenter
font: Kirigami.Theme.smallFont
text: room.roomId
}
}
RowLayout {
visible: !roomSettingsPage.editingName
Kazv.SelectableText {
objectName: 'roomNameLabel'
text: room.name || l10n.get('room-settings-name-missing')
wrapMode: Text.Wrap
Kirigami.Theme.colorGroup: !!room.name ? Kirigami.Theme.Normal : Kirigami.Theme.Inactive
Layout.fillWidth: true
}
Button {
Layout.alignment: Qt.AlignTop
objectName: 'editNameButton'
text: l10n.get('room-settings-edit-name-action')
onClicked: {
roomNameEdit.text = room.name;
roomSettingsPage.editingName = true;
}
}
}
RowLayout {
visible: roomSettingsPage.editingName
TextArea {
id: roomNameEdit
objectName: 'roomNameEdit'
Layout.fillWidth: true
wrapMode: Text.Wrap
}
Button {
Layout.alignment: Qt.AlignTop
objectName: 'saveNameButton'
enabled: !roomSettingsPage.submittingName
text: l10n.get('room-settings-save-name-action')
onClicked: roomSettingsPage.submitName.call()
}
Button {
Layout.alignment: Qt.AlignTop
objectName: 'discardNameButton'
enabled: !roomSettingsPage.submittingName
text: l10n.get('room-settings-discard-name-action')
onClicked: roomSettingsPage.editingName = false
}
}
RowLayout {
visible: !roomSettingsPage.editingTopic
Kazv.SelectableText {
objectName: 'roomTopicLabel'
text: room.topic || l10n.get('room-settings-topic-missing')
font.italic: !room.topic
wrapMode: Text.Wrap
Kirigami.Theme.colorGroup: !!room.topic ? Kirigami.Theme.Normal : Kirigami.Theme.Inactive
Layout.fillWidth: true
}
Button {
Layout.alignment: Qt.AlignTop
objectName: 'editTopicButton'
text: l10n.get('room-settings-edit-topic-action')
onClicked: {
roomTopicEdit.text = room.topic;
roomSettingsPage.editingTopic = true;
}
}
}
RowLayout {
visible: roomSettingsPage.editingTopic
TextArea {
id: roomTopicEdit
objectName: 'roomTopicEdit'
Layout.fillWidth: true
wrapMode: Text.Wrap
}
Button {
Layout.alignment: Qt.AlignTop
objectName: 'saveTopicButton'
enabled: !roomSettingsPage.submittingTopic
text: l10n.get('room-settings-save-topic-action')
onClicked: roomSettingsPage.submitTopic.call()
}
Button {
Layout.alignment: Qt.AlignTop
objectName: 'discardTopicButton'
enabled: !roomSettingsPage.submittingTopic
text: l10n.get('room-settings-discard-topic-action')
onClicked: roomSettingsPage.editingTopic = false
}
}
Button {
text: l10n.get('room-settings-members-action')
icon.name: 'im-user'
Layout.fillWidth: true
- onClicked: pageStack.push(Qt.resolvedUrl('RoomMemberListPage.qml'), { room: room, members: room.members() })
+ onClicked: pageStack.layers.push(Qt.resolvedUrl('RoomMemberListPage.qml'), { room: room, members: room.members() })
}
Button {
text: l10n.get('room-settings-banned-members-action')
icon.name: 'im-kick-user'
icon.color: Kirigami.Theme.negativeTextColor
Layout.fillWidth: true
- onClicked: pageStack.push(Qt.resolvedUrl('RoomMemberListPage.qml'), { room: room, members: room.bannedMembers() })
+ onClicked: pageStack.layers.push(Qt.resolvedUrl('RoomMemberListPage.qml'), { room: room, members: room.bannedMembers() })
}
Label {
objectName: 'encryptionIndicator'
Layout.fillWidth: true
text: !!room.encrypted ? l10n.get('room-settings-encrypted') : l10n.get('room-settings-not-encrypted')
}
Button {
objectName: 'enableEncryptionButton'
Layout.fillWidth: true
visible: !room.encrypted
enabled: !roomSettingsPage.enablingEncryption
text: l10n.get('room-settings-enable-encryption-action')
onClicked: encryptionPopup.open()
}
RowLayout {
Layout.fillWidth: true
Label {
text: l10n.get('room-settings-tags')
Layout.fillWidth: true
}
CheckBox {
Layout.alignment: Qt.AlignRight
text: l10n.get('room-settings-favourited')
checkable: true
checked: tagHandler.hasTag('m.favourite')
enabled: tagHandler.available
onToggled: tagHandler.toggleTag('m.favourite')
}
}
ListView {
model: customTagIds.length
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumHeight: childrenRect.height
delegate: Kirigami.SwipeListItem {
required property var index
contentItem: RowLayout {
Label {
Layout.fillWidth: true
text: tagIdToName(customTagIds[index])
}
}
actions: [
Kirigami.Action {
enabled: tagHandler.available
icon.name: 'list-remove-symbolic'
text: l10n.get('room-settings-remove-tag')
onTriggered: tagHandler.toggleTag(customTagIds[index])
}
]
}
}
RowLayout {
TextField {
id: newTagName
enabled: tagHandler.available
text: ''
Layout.fillWidth: true
}
Button {
enabled: tagHandler.available
text: l10n.get('room-settings-add-tag')
icon.name: 'list-add'
onClicked: {
tagHandler.toggleTag('u.' + newTagName.text)
}
}
Connections {
target: tagHandler
function onTagAdded(tagId) {
if (tagId === 'u.' + newTagName.text) {
newTagName.text = '';
}
}
}
}
Button {
objectName: 'stickerPacksButton'
text: l10n.get('room-sticker-packs-action')
icon.name: 'smiley'
Layout.fillWidth: true
onClicked: {
activateRoomStickerPacksPage(roomSettingsPage.room);
}
}
Button {
text: l10n.get('room-invite-action')
icon.name: 'list-add-user'
Layout.fillWidth: true
onClicked: {
activateRoomInvitePage(roomSettingsPage.room);
}
}
Button {
text: l10n.get('room-explore-state-action')
Layout.fillWidth: true
onClicked: {
activateRoomStatePage(roomSettingsPage.room);
}
}
Button {
objectName: 'leaveRoomButton'
text: l10n.get('room-leave-action')
icon.name: 'im-ban-kick-user'
icon.color: Kirigami.Theme.negativeTextColor
Layout.fillWidth: true
onClicked: {
confirmLeaveOverlay.open();
}
}
Button {
objectName: 'forgetRoomButton'
text: l10n.get('room-forget-action')
Layout.fillWidth: true
visible: room.membership === MK.MatrixRoom.Leave
onClicked: {
confirmForgetOverlay.open();
}
}
}
property var confirmLeaveOverlay: Kazv.ConfirmationOverlay {
objectName: 'confirmLeaveRoomPopup'
parent: roomSettingsPage.overlay
title: l10n.get('room-leave-confirm-popup-title')
message: l10n.get('room-leave-confirm-popup-message')
confirmActionText: l10n.get('room-leave-confirm-popup-confirm-action')
cancelActionText: l10n.get('room-leave-confirm-popup-cancel-action')
onAccepted: leaveRoomHandler.call()
}
property var leaveRoomHandler: Kazv.AsyncHandler {
trigger: () => room.leaveRoom()
onResolved: {
if (success) {
showPassiveNotification(l10n.get('leave-room-success-prompt', { room: room.roomId }));
inviteOverlay.close();
} else {
showPassiveNotification(l10n.get('leave-room-failed-prompt', { room: room.roomId, errorCode: data.errorCode, errorMsg: data.error }));
}
}
}
property var confirmForgetOverlay: Kazv.ConfirmationOverlay {
objectName: 'confirmForgetRoomPopup'
parent: roomSettingsPage.overlay
title: l10n.get('room-forget-confirm-popup-title')
message: l10n.get('room-forget-confirm-popup-message')
confirmActionText: l10n.get('room-forget-confirm-popup-confirm-action')
cancelActionText: l10n.get('room-forget-confirm-popup-cancel-action')
onAccepted: forgetRoomHandler.call()
}
property var forgetRoomHandler: Kazv.AsyncHandler {
trigger: () => room.forgetRoom()
onResolved: (success, data) => {
if (success) {
showPassiveNotification(l10n.get('forget-room-success-prompt', { room: room.roomId }));
} else {
showPassiveNotification(l10n.get('forget-room-failed-prompt', { room: room.roomId, errorCode: data.errorCode, errorMsg: data.error }));
}
}
}
}
diff --git a/src/contents/ui/room-settings/RoomStatePage.qml b/src/contents/ui/room-settings/RoomStatePage.qml
index 9beca93..cfba1fe 100644
--- a/src/contents/ui/room-settings/RoomStatePage.qml
+++ b/src/contents/ui/room-settings/RoomStatePage.qml
@@ -1,71 +1,71 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2025 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import org.kde.kirigami as Kirigami
import moe.kazv.mxc.kazv 0.0 as MK
import '../matrix-helpers.js' as Helpers
import '..' as Kazv
-Kazv.ClosableScrollablePage {
+Kazv.ClosableScrollableOverlay {
id: roomStatePage
property var room
property var roomNameProvider: Kazv.RoomNameProvider {
room: roomStatePage.room
}
property var roomDisplayName: roomNameProvider.name
property var allState: room.allState()
property string selectedType: ''
title: l10n.get('room-state-page-title', { room: roomDisplayName })
ColumnLayout {
Flow {
id: typeChooser
Layout.fillWidth: true
Repeater {
model: allState.types
Kirigami.Chip {
required property string modelData
objectName: `chip_${modelData}`
closable: false
text: modelData
checkable: true
checked: roomStatePage.selectedType === modelData
onClicked: {
roomStatePage.selectedType = modelData
}
}
}
}
ListView {
id: lv
objectName: 'stateEventList'
model: allState.eventsForType(roomStatePage.selectedType)
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumHeight: childrenRect.height
delegate: ColumnLayout {
id: viewItem
property var event: lv.model.at(index)
width: ListView.view.width
Label {
Layout.fillWidth: true
textFormat: Qt.RichText
text: l10n.get('room-state-page-state-key', { stateKey: MK.KazvUtil.escapeHtml(viewItem.event.stateKey) })
}
Kazv.EventViewWrapper {
event: viewItem.event
Layout.fillWidth: true
compactMode: false
displayTime: false
}
}
}
}
}
diff --git a/src/contents/ui/room-settings/RoomStickerPacksPage.qml b/src/contents/ui/room-settings/RoomStickerPacksPage.qml
index b3a4b1f..847707f 100644
--- a/src/contents/ui/room-settings/RoomStickerPacksPage.qml
+++ b/src/contents/ui/room-settings/RoomStickerPacksPage.qml
@@ -1,90 +1,90 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2024 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import org.kde.kirigami as Kirigami
import moe.kazv.mxc.kazv as MK
import '..' as Kazv
import '.' as RoomSettings
import '../matrix-helpers.js' as Helpers
-Kazv.ClosableScrollablePage {
+Kazv.ClosableScrollableOverlay {
id: roomStickerPacksPage
property var room
property var stickerPackList: room.stickerPackList()
property var roomNameProvider: Kazv.RoomNameProvider {
room: roomStickerPacksPage.room
}
title: l10n.get('room-sticker-packs-page-title', {
room: roomNameProvider.name,
})
ListView {
model: roomStickerPacksPage.stickerPackList
delegate: RoomSettings.RoomStickerPackItemDelegate {
required property int index
stickerRoomsEvent: matrixSdk.stickerRoomsEvent()
stickerPack: stickerPackList.at(index)
}
}
actions: [
Kirigami.Action {
objectName: 'addStickerPackAction'
text: l10n.get('room-sticker-packs-page-add-action')
icon.name: 'list-add'
onTriggered: addStickerPackPopup.open()
}
]
property var addStickerPack: Kazv.AsyncHandler {
id: addStickerPack
trigger: () => {
const type = Helpers.roomImagePackEventType;
const stateKey = stickerPackStateKey.text;
const state = room.state(type, stateKey);
const content = state.content;
content.pack = content.pack || {};
content.pack.display_name = stickerPackName.text;
return roomStickerPacksPage.room.sendStateEvent({
type,
state_key: stateKey,
content,
});
}
onResolved: (success, data) => {
if (success) {
showPassiveNotification(l10n.get('room-sticker-packs-page-add-success'));
} else {
showPassiveNotification(l10n.get('room-sticker-packs-page-add-failed', { errorMsg: data.error, errorCode: data.errorCode }));
}
}
}
property var addStickerPackPopup: Kirigami.PromptDialog {
id: addStickerPackPopup
title: l10n.get('room-sticker-packs-page-add-popup-title')
standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
onAccepted: addStickerPack.call()
Kirigami.FormLayout {
TextField {
id: stickerPackName
objectName: 'stickerPackName'
Kirigami.FormData.label: l10n.get('room-sticker-packs-page-add-popup-name-prompt')
}
TextField {
id: stickerPackStateKey
objectName: 'stickerPackStateKey'
Kirigami.FormData.label: l10n.get('room-sticker-packs-page-add-popup-state-key-prompt')
}
}
}
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Jul 20, 2:20 AM (1 d, 16 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1695416
Default Alt Text
(63 KB)

Event Timeline