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() { WindowController.saveGeometry(); } 0098 function onWidthChanged() { saveWindowGeometryTimer.restart(); } 0099 function onHeightChanged() { saveWindowGeometryTimer.restart(); } 0100 function onXChanged() { saveWindowGeometryTimer.restart(); } 0101 function onYChanged() { saveWindowGeometryTimer.restart(); } 0102 } 0103 0104 0105 Loader { 0106 id: quickView 0107 active: !Kirigami.Settings.isMobile 0108 sourceComponent: QuickSwitcher { 0109 connection: root.connection 0110 } 0111 } 0112 0113 Connections { 0114 target: RoomManager 0115 0116 function onPushRoom(room, event) { 0117 root.roomPage = pageStack.push("qrc:/org/kde/neochat/qml/RoomPage.qml", {connection: root.connection}); 0118 root.roomPage.forceActiveFocus(); 0119 if (event.length > 0) { 0120 roomPage.goToEvent(event); 0121 } 0122 } 0123 0124 function onPushSpaceHome(room) { 0125 root.spaceHomePage = pageStack.push("qrc:/org/kde/neochat/qml/SpaceHomePage.qml"); 0126 root.spaceHomePage.forceActiveFocus(); 0127 } 0128 0129 function onReplaceRoom(room, event) { 0130 if (root.roomPage) { 0131 pageStack.currentIndex = pageStack.depth - 1; 0132 } else { 0133 pageStack.pop(); 0134 root.roomPage = pageStack.push("qrc:/org/kde/neochat/qml/RoomPage.qml", {connection: root.connection}); 0135 root.spaceHomePage = null; 0136 } 0137 root.roomPage.forceActiveFocus(); 0138 if (event.length > 0) { 0139 root.roomPage.goToEvent(event); 0140 } 0141 } 0142 0143 function onReplaceSpaceHome(room) { 0144 if (root.spaceHomePage) { 0145 pageStack.currentIndex = pageStack.depth - 1; 0146 } else { 0147 pageStack.pop(); 0148 root.spaceHomePage = pageStack.push("qrc:/org/kde/neochat/qml/SpaceHomePage.qml"); 0149 root.roomPage = null; 0150 } 0151 root.spaceHomePage.forceActiveFocus(); 0152 } 0153 0154 function goToEvent(event) { 0155 if (event.length > 0) { 0156 roomItem.goToEvent(event); 0157 } 0158 roomItem.forceActiveFocus(); 0159 } 0160 0161 function onOpenRoomInNewWindow(room) { 0162 const secondaryWindow = roomWindow.createObject(undefined, {currentRoom: room, connection: root.connection}); 0163 secondaryWindow.width = root.width - pageStack.get(0).width; 0164 secondaryWindow.show(); 0165 } 0166 0167 function onAskDirectChatConfirmation(user) { 0168 askDirectChatConfirmationComponent.createObject(QQC2.ApplicationWindow.overlay, { 0169 user: user, 0170 }).open(); 0171 } 0172 } 0173 0174 function pushReplaceLayer(page, args) { 0175 if (pageStack.layers.depth === 2) { 0176 pageStack.layers.replace(page, args); 0177 } else { 0178 pageStack.layers.push(page, args); 0179 } 0180 } 0181 0182 function openRoomDrawer() { 0183 pageStack.push("qrc:/org/kde/neochat/qml/RoomDrawerPage.qml", { 0184 connection: root.connection 0185 }) 0186 } 0187 0188 contextDrawer: RoomDrawer { 0189 id: contextDrawer 0190 0191 // This is a memory for all user initiated actions on the drawer, i.e. clicking the button 0192 // It is used to ensure that user choice is remembered when changing pages and expanding and contracting the window width 0193 property bool drawerUserState: Config.autoRoomInfoDrawer 0194 0195 connection: root.connection 0196 0197 // Connect to the onClicked function of the RoomDrawer handle button 0198 Connections { 0199 target: contextDrawer.handle.children[0] 0200 function onClicked() { 0201 contextDrawer.drawerUserState = contextDrawer.drawerOpen 0202 } 0203 } 0204 0205 modal: (!root.wideScreen || !enabled) 0206 onEnabledChanged: drawerOpen = enabled && !modal 0207 onModalChanged: { 0208 if (Config.autoRoomInfoDrawer) { 0209 drawerOpen = !modal && drawerUserState 0210 dim = false 0211 } 0212 } 0213 enabled: RoomManager.hasOpenRoom && pageStack.layers.depth < 2 && pageStack.depth < 3 && (pageStack.visibleItems.length > 1 || pageStack.currentIndex > 0) && !Kirigami.Settings.isMobile && root.pageStack.wideMode 0214 handleVisible: enabled 0215 } 0216 0217 Component.onCompleted: { 0218 CustomEmojiModel.connection = root.connection 0219 MatrixImageProvider.connection = root.connection 0220 RoomManager.connection = root.connection 0221 SpaceHierarchyCache.connection = root.connection 0222 WindowController.setBlur(pageStack, Config.blur && !Config.compactLayout); 0223 if (Config.minimizeToSystemTrayOnStartup && !Kirigami.Settings.isMobile && Controller.supportSystemTray && Config.systemTray) { 0224 restoreWindowGeometryConnections.enabled = true; // To restore window size and position 0225 } else { 0226 visible = true; 0227 saveWindowGeometryConnections.enabled = true; 0228 } 0229 } 0230 Connections { 0231 target: Config 0232 function onBlurChanged() { 0233 WindowController.setBlur(pageStack, Config.blur && !Config.compactLayout); 0234 } 0235 function onCompactLayoutChanged() { 0236 WindowController.setBlur(pageStack, Config.blur && !Config.compactLayout); 0237 } 0238 } 0239 0240 // blur effect 0241 color: Config.blur && !Config.compactLayout ? "transparent" : Kirigami.Theme.backgroundColor 0242 0243 // we need to apply the translucency effect separately on top of the color 0244 background: Rectangle { 0245 color: Config.blur && !Config.compactLayout ? Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 1 - Config.transparency) : "transparent" 0246 } 0247 0248 Component { 0249 id: roomListComponent 0250 RoomListPage { 0251 id: roomList 0252 0253 connection: root.connection 0254 0255 Shortcut { 0256 sequences: ["Ctrl+PgUp", "Ctrl+Backtab", "Alt+Up"] 0257 onActivated: { 0258 roomList.goToPreviousRoom(); 0259 } 0260 } 0261 0262 Shortcut { 0263 sequences: ["Ctrl+PgDown", "Ctrl+Tab", "Alt+Down"] 0264 onActivated: { 0265 roomList.goToNextRoom(); 0266 } 0267 } 0268 0269 Shortcut { 0270 sequence: "Alt+Shift+Up" 0271 onActivated: { 0272 roomList.goToPreviousUnreadRoom(); 0273 } 0274 } 0275 0276 Shortcut { 0277 sequence: "Alt+Shift+Down" 0278 onActivated: { 0279 roomList.goToNextUnreadRoom(); 0280 } 0281 } 0282 } 0283 } 0284 0285 Connections { 0286 target: AccountRegistry 0287 function onRowsRemoved() { 0288 if (AccountRegistry.rowCount() === 0) { 0289 RoomManager.reset(); 0290 pageStack.clear(); 0291 roomListLoaded = false; 0292 pageStack.push("qrc:/org/kde/neochat/qml/WelcomePage.qml"); 0293 } 0294 } 0295 } 0296 0297 Connections { 0298 target: Controller 0299 0300 function onErrorOccured(error, detail) { 0301 showPassiveNotification(detail.length > 0 ? i18n("%1: %2", error, detail) : error); 0302 } 0303 } 0304 0305 Connections { 0306 id: restoreWindowGeometryConnections 0307 enabled: false 0308 target: root 0309 0310 function onVisibleChanged() { 0311 if (!visible) { 0312 return; 0313 } 0314 Controller.restoreWindowGeometry(root); 0315 restoreWindowGeometryConnections.enabled = false; // Only restore window geometry for the first time 0316 saveWindowGeometryConnections.enabled = true; 0317 } 0318 } 0319 0320 Component { 0321 id: keyVerificationDialogComponent 0322 KeyVerificationDialog { } 0323 } 0324 0325 Connections { 0326 target: root.connection 0327 0328 function onDirectChatAvailable(directChat) { 0329 RoomManager.enterRoom(root.connection.room(directChat.id)); 0330 } 0331 function onNewKeyVerificationSession(session) { 0332 applicationWindow().pageStack.pushDialogLayer(keyVerificationDialogComponent, { 0333 session: session, 0334 }, { 0335 title: i18nc("@title:window", "Session Verification") 0336 }); 0337 } 0338 function onUserConsentRequired(url) { 0339 let consent = consentSheetComponent.createObject(QQC2.ApplicationWindow.overlay) 0340 consent.url = url 0341 consent.open() 0342 } 0343 } 0344 0345 Component { 0346 id: consentSheetComponent 0347 Kirigami.OverlaySheet { 0348 id: consentSheet 0349 0350 property string url: "" 0351 0352 title: i18n("User consent") 0353 0354 QQC2.Label { 0355 id: label 0356 0357 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.") 0358 wrapMode: Text.WordWrap 0359 width: parent.width 0360 } 0361 footer: QQC2.Button { 0362 text: i18n("Open") 0363 onClicked: UrlHelper.openUrl(consentSheet.url) 0364 } 0365 } 0366 } 0367 0368 Component { 0369 id: createRoomDialog 0370 0371 CreateRoomDialog { 0372 connection: root.connection 0373 } 0374 } 0375 0376 Component { 0377 id: roomWindow 0378 RoomWindow {} 0379 } 0380 0381 Component { 0382 id: askDirectChatConfirmationComponent 0383 0384 Kirigami.OverlaySheet { 0385 id: askDirectChatConfirmation 0386 required property var user; 0387 0388 parent: QQC2.ApplicationWindow.overlay 0389 title: i18n("Start a chat") 0390 contentItem: QQC2.Label { 0391 text: i18n("Do you want to start a chat with %1?", user.displayName) 0392 wrapMode: Text.WordWrap 0393 } 0394 footer: QQC2.DialogButtonBox { 0395 standardButtons: QQC2.DialogButtonBox.Ok | QQC2.DialogButtonBox.Cancel 0396 onAccepted: { 0397 user.requestDirectChat(); 0398 askDirectChatConfirmation.close(); 0399 } 0400 onRejected: askDirectChatConfirmation.close(); 0401 } 0402 } 0403 } 0404 0405 property Item hoverLinkIndicator: QQC2.Control { 0406 parent: overlay.parent 0407 property string text 0408 opacity: linkText.text.length > 0 ? 1 : 0 0409 0410 z: 20 0411 x: 0 0412 y: parent.height - implicitHeight 0413 contentItem: QQC2.Label { 0414 id: linkText 0415 text: parent.text.startsWith("https://matrix.to/") ? "" : parent.text 0416 } 0417 Kirigami.Theme.colorSet: Kirigami.Theme.View 0418 background: Rectangle { 0419 color: Kirigami.Theme.backgroundColor 0420 } 0421 } 0422 0423 Shortcut { 0424 sequence: "Ctrl+Shift+," 0425 onActivated: { 0426 pageStack.pushDialogLayer("qrc:/org/kde/neochat/qml/SettingsPage.qml", {connection: root.connection}, { title: i18n("Configure") }) 0427 } 0428 } 0429 }