Warning, /network/neochat/src/qml/main.qml is written in an unsupported language. File is not indexed.
0001 // SPDX-FileCopyrightText: 2018-2020 Black Hat <bhat@encom.eu.org> 0002 // SPDX-FileCopyrightText: 2020 Carl Schwan <carl@carlschwan.eu> 0003 // SPDX-License-Identifier: GPL-3.0-only 0004 0005 import QtQuick 0006 import QtQuick.Controls as QQC2 0007 0008 import org.kde.kirigami as Kirigami 0009 0010 import org.kde.neochat 0011 import org.kde.neochat.config 0012 import org.kde.neochat.accounts 0013 0014 Kirigami.ApplicationWindow { 0015 id: root 0016 0017 property int columnWidth: Kirigami.Units.gridUnit * 13 0018 0019 property RoomListPage roomListPage 0020 property bool roomListLoaded: false 0021 0022 property RoomPage roomPage 0023 property SpaceHomePage spaceHomePage 0024 0025 property NeoChatConnection connection: Controller.activeConnection 0026 0027 minimumWidth: Kirigami.Units.gridUnit * 20 0028 minimumHeight: Kirigami.Units.gridUnit * 15 0029 0030 visible: false // Will be overridden in Component.onCompleted 0031 wideScreen: width > columnWidth * 5 0032 0033 pageStack { 0034 initialPage: WelcomePage { 0035 showExisting: true 0036 onConnectionChosen: { 0037 pageStack.replace(roomListComponent); 0038 roomListLoaded = true; 0039 roomListPage = pageStack.currentItem; 0040 RoomManager.loadInitialRoom(); 0041 } 0042 } 0043 globalToolBar.canContainHandles: true 0044 defaultColumnWidth: roomListPage ? roomListPage.currentWidth : 0 0045 globalToolBar { 0046 style: Kirigami.ApplicationHeaderStyle.ToolBar 0047 showNavigationButtons: pageStack.currentIndex > 0 || pageStack.layers.depth > 1 ? Kirigami.ApplicationHeaderStyle.ShowBackButton : 0 0048 } 0049 } 0050 0051 onConnectionChanged: { 0052 CustomEmojiModel.connection = root.connection; 0053 MatrixImageProvider.connection = root.connection; 0054 RoomManager.connection = root.connection; 0055 SpaceHierarchyCache.connection = root.connection; 0056 } 0057 0058 Connections { 0059 target: LoginHelper 0060 function onLoaded() { 0061 pageStack.replace(roomListComponent); 0062 roomListLoaded = true; 0063 roomListPage = pageStack.currentItem; 0064 RoomManager.loadInitialRoom(); 0065 } 0066 } 0067 0068 Connections { 0069 target: root.quitAction 0070 function onTriggered() { 0071 Qt.quit(); 0072 } 0073 } 0074 0075 Loader { 0076 active: Kirigami.Settings.hasPlatformMenuBar && !Kirigami.Settings.isMobile 0077 sourceComponent: GlobalMenu { 0078 connection: root.connection 0079 } 0080 } 0081 0082 // This timer allows to batch update the window size change to reduce 0083 // the io load and also work around the fact that x/y/width/height are 0084 // changed when loading the page and overwrite the saved geometry from 0085 // the previous session. 0086 Timer { 0087 id: saveWindowGeometryTimer 0088 interval: 1000 0089 onTriggered: WindowController.saveGeometry() 0090 } 0091 0092 Connections { 0093 id: saveWindowGeometryConnections 0094 enabled: false // Disable on startup to avoid writing wrong values if the window is hidden 0095 target: root 0096 0097 function onClosing() { 0098 WindowController.saveGeometry(); 0099 } 0100 function onWidthChanged() { 0101 saveWindowGeometryTimer.restart(); 0102 } 0103 function onHeightChanged() { 0104 saveWindowGeometryTimer.restart(); 0105 } 0106 function onXChanged() { 0107 saveWindowGeometryTimer.restart(); 0108 } 0109 function onYChanged() { 0110 saveWindowGeometryTimer.restart(); 0111 } 0112 } 0113 0114 Loader { 0115 id: quickView 0116 active: !Kirigami.Settings.isMobile 0117 sourceComponent: QuickSwitcher { 0118 connection: root.connection 0119 } 0120 } 0121 0122 Connections { 0123 target: RoomManager 0124 0125 function onPushRoom(room, event) { 0126 root.roomPage = pageStack.push("qrc:/org/kde/neochat/qml/RoomPage.qml", { 0127 connection: root.connection 0128 }); 0129 root.roomPage.forceActiveFocus(); 0130 if (event.length > 0) { 0131 roomPage.goToEvent(event); 0132 } 0133 } 0134 0135 function onPushSpaceHome(room) { 0136 root.spaceHomePage = pageStack.push("qrc:/org/kde/neochat/qml/SpaceHomePage.qml"); 0137 root.spaceHomePage.forceActiveFocus(); 0138 } 0139 0140 function onReplaceRoom(room, event) { 0141 if (root.roomPage) { 0142 pageStack.currentIndex = pageStack.depth - 1; 0143 } else { 0144 pageStack.pop(); 0145 root.roomPage = pageStack.push("qrc:/org/kde/neochat/qml/RoomPage.qml", { 0146 connection: root.connection 0147 }); 0148 root.spaceHomePage = null; 0149 } 0150 root.roomPage.forceActiveFocus(); 0151 if (event.length > 0) { 0152 root.roomPage.goToEvent(event); 0153 } 0154 } 0155 0156 function onReplaceSpaceHome(room) { 0157 if (root.spaceHomePage) { 0158 pageStack.currentIndex = pageStack.depth - 1; 0159 } else { 0160 pageStack.pop(); 0161 root.spaceHomePage = pageStack.push("qrc:/org/kde/neochat/qml/SpaceHomePage.qml"); 0162 root.roomPage = null; 0163 } 0164 root.spaceHomePage.forceActiveFocus(); 0165 } 0166 0167 function goToEvent(event) { 0168 if (event.length > 0) { 0169 roomItem.goToEvent(event); 0170 } 0171 roomItem.forceActiveFocus(); 0172 } 0173 0174 function onOpenRoomInNewWindow(room) { 0175 const secondaryWindow = roomWindow.createObject(undefined, { 0176 currentRoom: room, 0177 connection: root.connection 0178 }); 0179 secondaryWindow.width = root.width - pageStack.get(0).width; 0180 secondaryWindow.show(); 0181 } 0182 0183 function onAskDirectChatConfirmation(user) { 0184 askDirectChatConfirmationComponent.createObject(QQC2.ApplicationWindow.overlay, { 0185 user: user 0186 }).open(); 0187 } 0188 } 0189 0190 function pushReplaceLayer(page, args) { 0191 if (pageStack.layers.depth === 2) { 0192 pageStack.layers.replace(page, args); 0193 } else { 0194 pageStack.layers.push(page, args); 0195 } 0196 } 0197 0198 function openRoomDrawer() { 0199 pageStack.push("qrc:/org/kde/neochat/qml/RoomDrawerPage.qml", { 0200 connection: root.connection 0201 }); 0202 } 0203 0204 contextDrawer: RoomDrawer { 0205 id: contextDrawer 0206 0207 // This is a memory for all user initiated actions on the drawer, i.e. clicking the button 0208 // It is used to ensure that user choice is remembered when changing pages and expanding and contracting the window width 0209 property bool drawerUserState: Config.autoRoomInfoDrawer 0210 0211 connection: root.connection 0212 0213 // Connect to the onClicked function of the RoomDrawer handle button 0214 Connections { 0215 target: contextDrawer.handle.children[0] 0216 function onClicked() { 0217 contextDrawer.drawerUserState = contextDrawer.drawerOpen; 0218 } 0219 } 0220 0221 modal: (!root.wideScreen || !enabled) 0222 onEnabledChanged: drawerOpen = enabled && !modal 0223 onModalChanged: { 0224 if (Config.autoRoomInfoDrawer) { 0225 drawerOpen = !modal && drawerUserState; 0226 dim = false; 0227 } 0228 } 0229 enabled: RoomManager.hasOpenRoom && pageStack.layers.depth < 2 && pageStack.depth < 3 && (pageStack.visibleItems.length > 1 || pageStack.currentIndex > 0) && !Kirigami.Settings.isMobile && root.pageStack.wideMode 0230 handleVisible: enabled 0231 } 0232 0233 Component.onCompleted: { 0234 CustomEmojiModel.connection = root.connection; 0235 MatrixImageProvider.connection = root.connection; 0236 RoomManager.connection = root.connection; 0237 SpaceHierarchyCache.connection = root.connection; 0238 WindowController.setBlur(pageStack, Config.blur && !Config.compactLayout); 0239 if (Config.minimizeToSystemTrayOnStartup && !Kirigami.Settings.isMobile && Controller.supportSystemTray && Config.systemTray) { 0240 restoreWindowGeometryConnections.enabled = true; // To restore window size and position 0241 } else { 0242 visible = true; 0243 saveWindowGeometryConnections.enabled = true; 0244 } 0245 } 0246 Connections { 0247 target: Config 0248 function onBlurChanged() { 0249 WindowController.setBlur(pageStack, Config.blur && !Config.compactLayout); 0250 } 0251 function onCompactLayoutChanged() { 0252 WindowController.setBlur(pageStack, Config.blur && !Config.compactLayout); 0253 } 0254 } 0255 0256 // blur effect 0257 color: Config.blur && !Config.compactLayout ? "transparent" : Kirigami.Theme.backgroundColor 0258 0259 // we need to apply the translucency effect separately on top of the color 0260 background: Rectangle { 0261 color: Config.blur && !Config.compactLayout ? Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 1 - Config.transparency) : "transparent" 0262 } 0263 0264 Component { 0265 id: roomListComponent 0266 RoomListPage { 0267 id: roomList 0268 0269 connection: root.connection 0270 0271 Shortcut { 0272 sequences: ["Ctrl+PgUp", "Ctrl+Backtab", "Alt+Up"] 0273 onActivated: { 0274 roomList.goToPreviousRoom(); 0275 } 0276 } 0277 0278 Shortcut { 0279 sequences: ["Ctrl+PgDown", "Ctrl+Tab", "Alt+Down"] 0280 onActivated: { 0281 roomList.goToNextRoom(); 0282 } 0283 } 0284 0285 Shortcut { 0286 sequence: "Alt+Shift+Up" 0287 onActivated: { 0288 roomList.goToPreviousUnreadRoom(); 0289 } 0290 } 0291 0292 Shortcut { 0293 sequence: "Alt+Shift+Down" 0294 onActivated: { 0295 roomList.goToNextUnreadRoom(); 0296 } 0297 } 0298 } 0299 } 0300 0301 Connections { 0302 target: AccountRegistry 0303 function onRowsRemoved() { 0304 if (AccountRegistry.rowCount() === 0) { 0305 RoomManager.reset(); 0306 pageStack.clear(); 0307 roomListLoaded = false; 0308 pageStack.push("qrc:/org/kde/neochat/qml/WelcomePage.qml"); 0309 } 0310 } 0311 } 0312 0313 Connections { 0314 target: Controller 0315 0316 function onErrorOccured(error, detail) { 0317 showPassiveNotification(detail.length > 0 ? i18n("%1: %2", error, detail) : error); 0318 } 0319 } 0320 0321 Connections { 0322 id: restoreWindowGeometryConnections 0323 enabled: false 0324 target: root 0325 0326 function onVisibleChanged() { 0327 if (!visible) { 0328 return; 0329 } 0330 Controller.restoreWindowGeometry(root); 0331 restoreWindowGeometryConnections.enabled = false; // Only restore window geometry for the first time 0332 saveWindowGeometryConnections.enabled = true; 0333 } 0334 } 0335 0336 Component { 0337 id: keyVerificationDialogComponent 0338 KeyVerificationDialog {} 0339 } 0340 0341 Connections { 0342 target: root.connection 0343 0344 function onDirectChatAvailable(directChat) { 0345 RoomManager.resolveResource(directChat.id); 0346 } 0347 function onNewKeyVerificationSession(session) { 0348 applicationWindow().pageStack.pushDialogLayer(keyVerificationDialogComponent, { 0349 session: session 0350 }, { 0351 title: i18nc("@title:window", "Session Verification") 0352 }); 0353 } 0354 function onUserConsentRequired(url) { 0355 let consent = consentSheetComponent.createObject(QQC2.ApplicationWindow.overlay); 0356 consent.url = url; 0357 consent.open(); 0358 } 0359 } 0360 0361 Component { 0362 id: consentSheetComponent 0363 Kirigami.OverlaySheet { 0364 id: consentSheet 0365 0366 property string url: "" 0367 0368 title: i18n("User consent") 0369 0370 QQC2.Label { 0371 id: label 0372 0373 text: i18n("Your homeserver requires you to agree to its terms and conditions before being able to use it. Please click the button below to read them.") 0374 wrapMode: Text.WordWrap 0375 width: parent.width 0376 } 0377 footer: QQC2.Button { 0378 text: i18n("Open") 0379 onClicked: UrlHelper.openUrl(consentSheet.url) 0380 } 0381 } 0382 } 0383 0384 Component { 0385 id: createRoomDialog 0386 0387 CreateRoomDialog { 0388 connection: root.connection 0389 } 0390 } 0391 0392 Component { 0393 id: roomWindow 0394 RoomWindow {} 0395 } 0396 0397 Component { 0398 id: askDirectChatConfirmationComponent 0399 0400 Kirigami.OverlaySheet { 0401 id: askDirectChatConfirmation 0402 required property var user 0403 0404 parent: QQC2.ApplicationWindow.overlay 0405 title: i18n("Start a chat") 0406 contentItem: QQC2.Label { 0407 text: i18n("Do you want to start a chat with %1?", user.displayName) 0408 wrapMode: Text.WordWrap 0409 } 0410 footer: QQC2.DialogButtonBox { 0411 standardButtons: QQC2.DialogButtonBox.Ok | QQC2.DialogButtonBox.Cancel 0412 onAccepted: { 0413 user.requestDirectChat(); 0414 askDirectChatConfirmation.close(); 0415 } 0416 onRejected: askDirectChatConfirmation.close() 0417 } 0418 } 0419 } 0420 0421 property Item hoverLinkIndicator: QQC2.Control { 0422 parent: overlay.parent 0423 property string text 0424 opacity: linkText.text.length > 0 ? 1 : 0 0425 0426 z: 20 0427 x: 0 0428 y: parent.height - implicitHeight 0429 contentItem: QQC2.Label { 0430 id: linkText 0431 text: parent.text.startsWith("https://matrix.to/") ? "" : parent.text 0432 } 0433 Kirigami.Theme.colorSet: Kirigami.Theme.View 0434 background: Rectangle { 0435 color: Kirigami.Theme.backgroundColor 0436 } 0437 } 0438 0439 Shortcut { 0440 sequence: "Ctrl+Shift+," 0441 onActivated: { 0442 pageStack.pushDialogLayer("qrc:/org/kde/neochat/qml/SettingsPage.qml", { 0443 connection: root.connection 0444 }, { 0445 title: i18n("Configure") 0446 }); 0447 } 0448 } 0449 }