matrixion/resources/qml/Root.qml

508 lines
16 KiB
QML
Raw Normal View History

// SPDX-FileCopyrightText: Nheko Contributors
//
// SPDX-License-Identifier: GPL-3.0-or-later
import "./delegates"
import "./device-verification"
import "./dialogs"
import "./emoji"
2022-01-09 08:56:02 +03:00
import "./pages"
import "./voip"
2022-01-30 21:14:33 +03:00
import "./ui"
import Qt.labs.platform 1.1 as Platform
2023-06-05 02:15:07 +03:00
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import im.nheko
2022-01-12 21:09:46 +03:00
Pane {
id: timelineRoot
2023-06-02 02:45:24 +03:00
function destroyOnClose(obj) {
if (obj.closing != undefined)
obj.closing.connect(() => obj.destroy(1000));
else if (obj.aboutToHide != undefined)
obj.aboutToHide.connect(() => obj.destroy(1000));
}
2023-06-02 02:45:24 +03:00
function destroyOnClosed(obj) {
obj.aboutToHide.connect(() => obj.destroy(1000));
}
//Timer {
// onTriggered: gc()
// interval: 1000
// running: true
// repeat: true
//}
2022-07-08 18:28:28 +03:00
function showAliasEditor(settings) {
2023-06-02 02:45:24 +03:00
var component = Qt.createComponent("qrc:/qml/dialogs/AliasEditor.qml");
if (component.status == Component.Ready) {
var dialog = component.createObject(timelineRoot, {
2023-06-02 02:45:24 +03:00
"roomSettings": settings
});
dialog.show();
destroyOnClose(dialog);
} else {
console.error("Failed to create component: " + component.errorString());
}
2022-07-08 18:28:28 +03:00
}
2023-06-02 02:45:24 +03:00
function showAllowedRoomsEditor(settings) {
var component = Qt.createComponent("qrc:/qml/dialogs/AllowedRoomsSettingsDialog.qml");
if (component.status == Component.Ready) {
var dialog = component.createObject(timelineRoot, {
2023-06-02 02:45:24 +03:00
"roomSettings": settings
});
dialog.show();
destroyOnClose(dialog);
} else {
console.error("Failed to create component: " + component.errorString());
}
2022-07-08 18:28:28 +03:00
}
2023-06-02 02:45:24 +03:00
function showPLEditor(settings) {
var component = Qt.createComponent("qrc:/qml/dialogs/PowerLevelEditor.qml");
if (component.status == Component.Ready) {
var dialog = component.createObject(timelineRoot, {
2023-06-02 02:45:24 +03:00
"roomSettings": settings
});
dialog.show();
destroyOnClose(dialog);
} else {
console.error("Failed to create component: " + component.errorString());
}
}
2023-06-02 02:45:24 +03:00
function showSpacePLApplyPrompt(settings, editingModel) {
var component = Qt.createComponent("qrc:/qml/dialogs/PowerLevelSpacesApplyDialog.qml");
if (component.status == Component.Ready) {
var dialog = component.createObject(timelineRoot, {
2023-06-02 02:45:24 +03:00
"roomSettings": settings,
"editingModel": editingModel
});
dialog.show();
destroyOnClose(dialog);
} else {
console.error("Failed to create component: " + component.errorString());
}
}
2023-06-02 02:45:24 +03:00
background: null
padding: 0
FontMetrics {
id: fontMetrics
}
UserDirectoryModel {
id: userDirectory
}
2023-06-19 02:38:40 +03:00
RoomDirectoryModel {
id: publicRooms
}
Component {
id: readReceiptsDialog
ReadReceipts {
}
}
2022-01-24 02:41:55 +03:00
Shortcut {
sequence: StandardKey.Quit
2023-06-02 02:45:24 +03:00
2022-01-24 02:41:55 +03:00
onActivated: Qt.quit()
}
Shortcut {
sequence: "Ctrl+K"
2023-06-02 02:45:24 +03:00
onActivated: {
2023-06-02 02:45:24 +03:00
var component = Qt.createComponent("qrc:/qml/QuickSwitcher.qml");
if (component.status == Component.Ready) {
var quickSwitch = component.createObject(timelineRoot);
quickSwitch.open();
destroyOnClosed(quickSwitch);
} else {
console.error("Failed to create component: " + component.errorString());
}
}
}
Shortcut {
// Add alternative shortcut, because sometimes Alt+A is stolen by the TextEdit
sequences: ["Alt+A", "Ctrl+Shift+A"]
2023-06-02 02:45:24 +03:00
onActivated: Rooms.nextRoomWithActivity()
}
2021-05-29 00:25:57 +03:00
Shortcut {
sequence: "Ctrl+Down"
2023-06-02 02:45:24 +03:00
onActivated: Rooms.nextRoom()
2021-05-29 00:25:57 +03:00
}
Shortcut {
sequence: "Ctrl+Up"
2023-06-02 02:45:24 +03:00
onActivated: Rooms.previousRoom()
2021-05-29 00:25:57 +03:00
}
2021-09-30 03:15:25 +03:00
Connections {
2023-06-02 02:45:24 +03:00
function onOpenJoinRoomDialog() {
var component = Qt.createComponent("qrc:/qml/dialogs/JoinRoomDialog.qml");
if (component.status == Component.Ready) {
var dialog = component.createObject(timelineRoot);
2023-06-02 02:45:24 +03:00
dialog.show();
destroyOnClose(dialog);
} else {
console.error("Failed to create component: " + component.errorString());
}
2021-09-30 03:15:25 +03:00
}
2023-06-02 02:45:24 +03:00
function onOpenLogoutDialog() {
var component = Qt.createComponent("qrc:/qml/dialogs/LogoutDialog.qml");
if (component.status == Component.Ready) {
var dialog = component.createObject(timelineRoot);
2023-06-02 02:45:24 +03:00
dialog.open();
destroyOnClose(dialog);
} else {
console.error("Failed to create component: " + component.errorString());
}
2021-09-25 04:32:06 +03:00
}
function onShowRoomJoinPrompt(summary) {
2023-06-02 02:45:24 +03:00
var component = Qt.createComponent("qrc:/qml/dialogs/ConfirmJoinRoomDialog.qml");
if (component.status == Component.Ready) {
2023-06-02 02:45:24 +03:00
var dialog = component.createObject(timelineRoot, {
"summary": summary
});
dialog.show();
destroyOnClose(dialog);
} else {
console.error("Failed to create component: " + component.errorString());
}
}
2021-09-30 03:15:25 +03:00
target: Nheko
}
Connections {
function onNewDeviceVerificationRequest(flow) {
2023-06-02 02:45:24 +03:00
var component = Qt.createComponent("qrc:/qml/device-verification/DeviceVerification.qml");
if (component.status == Component.Ready) {
2023-06-02 02:45:24 +03:00
var dialog = component.createObject(timelineRoot, {
"flow": flow
});
dialog.show();
destroyOnClose(dialog);
} else {
console.error("Failed to create component: " + component.errorString());
}
}
target: VerificationManager
}
Connections {
2023-06-02 02:45:24 +03:00
function onOpenInviteUsersDialog(invitees) {
var component = Qt.createComponent("qrc:/qml/dialogs/InviteDialog.qml");
if (component.status == Component.Ready) {
2023-06-02 02:45:24 +03:00
var dialog = component.createObject(timelineRoot, {
"invitees": invitees
});
dialog.show();
destroyOnClose(dialog);
} else {
console.error("Failed to create component: " + component.errorString());
}
}
2023-06-02 02:45:24 +03:00
function onOpenLeaveRoomDialog(roomid, reason) {
var component = Qt.createComponent("qrc:/qml/dialogs/LeaveRoomDialog.qml");
if (component.status == Component.Ready) {
2023-06-02 02:45:24 +03:00
var dialog = component.createObject(timelineRoot, {
"roomId": roomid,
"reason": reason
});
dialog.open();
destroyOnClose(dialog);
} else {
console.error("Failed to create component: " + component.errorString());
}
}
function onOpenProfile(profile) {
var component = Qt.createComponent("qrc:/qml/dialogs/UserProfile.qml");
if (component.status == Component.Ready) {
var userProfile = component.createObject(timelineRoot, {
"profile": profile
});
userProfile.show();
destroyOnClose(userProfile);
} else {
console.error("Failed to create component: " + component.errorString());
}
}
2021-08-14 00:58:26 +03:00
function onOpenRoomMembersDialog(members, room) {
2023-06-02 02:45:24 +03:00
var component = Qt.createComponent("qrc:/qml/dialogs/RoomMembers.qml");
if (component.status == Component.Ready) {
var membersDialog = component.createObject(timelineRoot, {
2023-06-02 02:45:24 +03:00
"members": members,
"room": room
});
membersDialog.show();
destroyOnClose(membersDialog);
} else {
console.error("Failed to create component: " + component.errorString());
}
2021-06-11 03:13:12 +03:00
}
function onOpenRoomSettingsDialog(settings) {
2023-06-02 02:45:24 +03:00
var component = Qt.createComponent("qrc:/qml/dialogs/RoomSettings.qml");
if (component.status == Component.Ready) {
var roomSettings = component.createObject(timelineRoot, {
2023-06-02 02:45:24 +03:00
"roomSettings": settings
});
roomSettings.show();
destroyOnClose(roomSettings);
} else {
console.error("Failed to create component: " + component.errorString());
}
2021-06-11 03:13:12 +03:00
}
2022-05-10 04:19:53 +03:00
function onShowImageOverlay(room, eventId, url, originalWidth, proportionalHeight) {
2023-06-02 02:45:24 +03:00
var component = Qt.createComponent("qrc:/qml/dialogs/ImageOverlay.qml");
if (component.status == Component.Ready) {
var dialog = component.createObject(timelineRoot, {
"room": room,
"eventId": eventId,
"url": url,
"originalWidth": originalWidth ?? 0,
"proportionalHeight": proportionalHeight ?? 0
2023-06-02 02:45:24 +03:00
});
dialog.showFullScreen();
destroyOnClose(dialog);
} else {
console.error("Failed to create component: " + component.errorString());
}
}
2023-06-02 02:45:24 +03:00
function onShowImagePackSettings(room, packlist) {
var component = Qt.createComponent("qrc:/qml/dialogs/ImagePackSettingsDialog.qml");
if (component.status == Component.Ready) {
var packSet = component.createObject(timelineRoot, {
"room": room,
"packlist": packlist
});
packSet.show();
destroyOnClose(packSet);
} else {
console.error("Failed to create component: " + component.errorString());
}
}
target: TimelineManager
}
Connections {
function onNewInviteState() {
if (CallManager.haveCallInvite && Settings.mobileMode) {
2023-06-02 02:45:24 +03:00
var component = Qt.createComponent("qrc:/qml/voip/CallInvite.qml");
if (component.status == Component.Ready) {
var dialog = component.createObject(timelineRoot);
dialog.open();
destroyOnClose(dialog);
} else {
console.error("Failed to create component: " + component.errorString());
}
}
}
target: CallManager
2021-06-11 03:13:12 +03:00
}
SelfVerificationCheck {
}
InputDialog {
id: uiaPassPrompt
echoMode: TextInput.Password
prompt: qsTr("Please enter your login password to continue:")
2023-06-02 02:45:24 +03:00
title: UIA.title
onAccepted: t => {
return UIA.continuePassword(t);
}
}
InputDialog {
id: uiaEmailPrompt
prompt: qsTr("Please enter a valid email address to continue:")
2023-06-02 02:45:24 +03:00
title: UIA.title
onAccepted: t => {
return UIA.continueEmail(t);
}
}
PhoneNumberInputDialog {
id: uiaPhoneNumberPrompt
prompt: qsTr("Please enter a valid phone number to continue:")
2023-06-02 02:45:24 +03:00
title: UIA.title
onAccepted: (p, t) => {
return UIA.continuePhoneNumber(p, t);
}
}
InputDialog {
id: uiaTokenPrompt
prompt: qsTr("Please enter the token which has been sent to you:")
2023-06-02 02:45:24 +03:00
title: UIA.title
onAccepted: t => {
return UIA.submit3pidToken(t);
}
}
Platform.MessageDialog {
id: uiaErrorDialog
buttons: Platform.MessageDialog.Ok
}
Platform.MessageDialog {
id: uiaConfirmationLinkDialog
buttons: Platform.MessageDialog.Ok
text: qsTr("Wait for the confirmation link to arrive, then continue.")
2023-06-02 02:45:24 +03:00
onAccepted: UIA.continue3pidReceived()
}
Connections {
2023-06-02 02:45:24 +03:00
function onConfirm3pidToken() {
uiaConfirmationLinkDialog.open();
}
function onEmail() {
uiaEmailPrompt.show();
}
2023-06-02 02:45:24 +03:00
function onError(msg) {
uiaErrorDialog.text = msg;
uiaErrorDialog.open();
}
function onPassword() {
console.log("UIA: password needed");
uiaPassPrompt.show();
}
function onPhoneNumber() {
uiaPhoneNumberPrompt.show();
}
function onPrompt3pidToken() {
uiaTokenPrompt.show();
}
target: UIA
}
2022-01-09 02:28:03 +03:00
StackView {
id: mainWindow
2023-06-02 02:45:24 +03:00
property Transition popEnterOrg
property Transition popExitOrg
// for some reason direct bindings to a hidden StackView don't work, so manually store and restore here.
property Transition pushEnterOrg
property Transition pushExitOrg
property Transition replaceEnterOrg
property Transition replaceExitOrg
2023-06-02 02:45:24 +03:00
function updateTrans() {
pushEnter = Settings.reducedMotion ? reducedMotionTransitionEnter : pushEnterOrg;
pushExit = Settings.reducedMotion ? reducedMotionTransitionExit : pushExitOrg;
popEnter = Settings.reducedMotion ? reducedMotionTransitionEnter : popEnterOrg;
popExit = Settings.reducedMotion ? reducedMotionTransitionExit : popExitOrg;
replaceEnter = Settings.reducedMotion ? reducedMotionTransitionEnter : replaceEnterOrg;
replaceExit = Settings.reducedMotion ? reducedMotionTransitionExit : replaceExitOrg;
}
anchors.fill: parent
initialItem: welcomePage
Component.onCompleted: {
pushEnterOrg = pushEnter;
popEnterOrg = popEnter;
replaceEnterOrg = replaceEnter;
pushExitOrg = pushExit;
popExitOrg = popExit;
replaceExitOrg = replaceExit;
2023-06-02 02:45:24 +03:00
updateTrans();
}
2023-06-02 02:45:24 +03:00
Transition {
id: reducedMotionTransitionExit
PropertyAnimation {
duration: 200
from: 1
property: "opacity"
to: 0
}
}
2023-06-02 02:45:24 +03:00
Transition {
id: reducedMotionTransitionEnter
2023-06-02 02:45:24 +03:00
SequentialAnimation {
PropertyAction {
property: "opacity"
value: 0
}
PauseAnimation {
duration: 200
}
PropertyAnimation {
duration: 200
from: 0
property: "opacity"
to: 1
}
}
}
Connections {
function onReducedMotionChanged() {
mainWindow.updateTrans();
}
2023-06-02 02:45:24 +03:00
target: Settings
}
2022-01-24 02:41:55 +03:00
}
Component {
id: welcomePage
WelcomePage {
2022-01-09 02:28:03 +03:00
}
}
2022-01-12 21:09:46 +03:00
Component {
id: chatPage
ChatPage {
}
}
2022-01-24 02:41:55 +03:00
Component {
id: loginPage
LoginPage {
}
}
2022-01-28 17:24:56 +03:00
Component {
id: registerPage
RegisterPage {
2022-01-28 17:24:56 +03:00
}
}
2022-10-01 03:28:02 +03:00
Component {
id: userSettingsPage
UserSettingsPage {
}
}
2023-06-02 02:45:24 +03:00
Snackbar {
id: snackbar
2022-10-01 03:28:02 +03:00
2023-06-02 02:45:24 +03:00
}
2022-01-12 21:09:46 +03:00
Connections {
2023-06-02 02:45:24 +03:00
function onShowNotification(msg) {
snackbar.showNotification(msg);
console.log("New snack: " + msg);
}
2022-01-12 21:09:46 +03:00
function onSwitchToChatPage() {
2022-01-24 02:41:55 +03:00
mainWindow.replace(null, chatPage);
}
function onSwitchToLoginPage(error) {
2023-06-02 02:45:24 +03:00
mainWindow.replace(welcomePage, {}, loginPage, {
"error": error
}, StackView.PopTransition);
2022-01-30 21:14:33 +03:00
}
2023-06-02 02:45:24 +03:00
2022-01-12 21:09:46 +03:00
target: MainWindow
}
}