Warning, /network/angelfish/src/contents/ui/mobile.qml is written in an unsupported language. File is not indexed.
0001 // SPDX-FileCopyrightText: 2014-2015 Sebastian Kügler <sebas@kde.org> 0002 // 0003 // SPDX-License-Identifier: GPL-2.0-or-later 0004 0005 import QtQuick 2.1 0006 import QtWebEngine 1.6 0007 import QtQuick.Window 2.3 0008 import Qt5Compat.GraphicalEffects 0009 import QtQuick.Layouts 1.2 0010 import QtQuick.Controls 2.2 as Controls 0011 0012 import org.kde.kirigami 2.7 as Kirigami 0013 0014 import org.kde.angelfish 1.0 0015 0016 Kirigami.ApplicationWindow { 0017 id: webBrowser 0018 title: i18n("Angelfish Web Browser") 0019 0020 /** Pointer to the currently active view. 0021 * 0022 * Browser-level functionality should use this to refer to the current 0023 * view, rather than looking up views in the mode, as far as possible. 0024 */ 0025 property WebView currentWebView: tabs.currentItem 0026 0027 // Pointer to the currently active list of tabs. 0028 // 0029 // As there are private and normal tabs, switch between 0030 // them according to the current mode. 0031 property ListWebView tabs: rootPage.privateMode ? privateTabs : regularTabs 0032 0033 // Used to determine if the window is in landscape mode 0034 property bool landscape: width > height 0035 0036 onCurrentWebViewChanged: { 0037 print("Current WebView is now : " + tabs.currentIndex); 0038 } 0039 property int borderWidth: Math.round(Kirigami.Units.gridUnit / 18); 0040 property color borderColor: Kirigami.Theme.highlightColor; 0041 0042 pageStack.globalToolBar.style: Kirigami.ApplicationHeaderStyle.ToolBar 0043 pageStack.globalToolBar.showNavigationButtons: Kirigami.ApplicationHeaderStyle.ShowBackButton 0044 0045 pageStack.columnView.columnResizeMode: Kirigami.ColumnView.SingleColumn 0046 0047 x: Settings.windowX 0048 y: Settings.windowY 0049 width: Settings.windowWidth 0050 height: Settings.windowHeight 0051 0052 globalDrawer: Kirigami.GlobalDrawer { 0053 id: globalDrawer 0054 0055 handleVisible: false 0056 0057 actions: [ 0058 Kirigami.Action { 0059 icon.name: "tab-duplicate" 0060 onTriggered: { 0061 popSubPages(); 0062 tabsSheetLoader.open(); 0063 } 0064 text: i18n("Tabs") 0065 }, 0066 Kirigami.Action { 0067 icon.name: "view-private" 0068 onTriggered: { 0069 rootPage.privateMode ? rootPage.privateMode = false : rootPage.privateMode = true 0070 } 0071 text: rootPage.privateMode ? i18n("Leave private mode") : i18n("Private mode") 0072 }, 0073 Kirigami.Action { 0074 icon.name: "bookmarks" 0075 onTriggered: { 0076 popSubPages(); 0077 pageStack.push(Qt.resolvedUrl("Bookmarks.qml")) 0078 } 0079 text: i18n("Bookmarks") 0080 }, 0081 Kirigami.Action { 0082 icon.name: "shallow-history" 0083 onTriggered: { 0084 popSubPages(); 0085 pageStack.push(Qt.resolvedUrl("History.qml")) 0086 } 0087 text: i18n("History") 0088 }, 0089 Kirigami.Action { 0090 icon.name: "download" 0091 text: i18n("Downloads") 0092 onTriggered: { 0093 popSubPages(); 0094 pageStack.push(Qt.resolvedUrl("Downloads.qml")) 0095 } 0096 }, 0097 Kirigami.Action { 0098 icon.name: "configure" 0099 text: i18n("Settings") 0100 onTriggered: { 0101 popSubPages(); 0102 pageStack.push("qrc:/SettingsPage.qml"); 0103 } 0104 } 0105 ] 0106 } 0107 0108 contextDrawer: Kirigami.ContextDrawer { 0109 id: contextDrawer 0110 actions: pageStack.currentItem?.actions ?? [] 0111 enabled: true 0112 0113 handleVisible: false 0114 } 0115 0116 // Main Page 0117 pageStack.initialPage: Kirigami.Page { 0118 id: rootPage 0119 title: currentWebView.title 0120 leftPadding: 0 0121 rightPadding: 0 0122 topPadding: 0 0123 bottomPadding: 0 0124 globalToolBarStyle: Kirigami.ApplicationHeaderStyle.None 0125 Kirigami.ColumnView.fillWidth: true 0126 Kirigami.ColumnView.pinned: true 0127 Kirigami.ColumnView.preventStealing: true 0128 0129 // Required to enforce active tab reload 0130 // on start. As a result, mixed isMobile 0131 // tabs will work correctly 0132 property bool initialized: false 0133 0134 property bool privateMode: false 0135 0136 // Used for automatically show or hid navigation 0137 // bar. Set separately to combine with other options 0138 // for navigation bar management (webapp and others) 0139 property bool navigationAutoShow: true 0140 0141 property alias questionLoader: questionLoader 0142 property alias questions: questions 0143 0144 ListWebView { 0145 id: regularTabs 0146 objectName: "regularTabsObject" 0147 anchors.fill: parent 0148 activeTabs: rootPage.initialized && !rootPage.privateMode 0149 } 0150 0151 ListWebView { 0152 id: privateTabs 0153 anchors.fill: parent 0154 activeTabs: rootPage.initialized && rootPage.privateMode 0155 privateTabsMode: true 0156 } 0157 0158 Controls.ScrollBar { 0159 visible: true 0160 anchors.right: parent.right 0161 anchors.top: parent.top 0162 anchors.bottom: parent.bottom 0163 position: currentWebView.scrollPosition.y / currentWebView.contentsSize.height 0164 orientation: Qt.Vertical 0165 size: currentWebView.height / currentWebView.contentsSize.height 0166 interactive: false 0167 } 0168 0169 ErrorHandler { 0170 id: errorHandler 0171 0172 errorString: currentWebView.errorString 0173 errorCode: currentWebView.errorCode 0174 0175 anchors { 0176 top: parent.top 0177 left: parent.left 0178 right: parent.right 0179 bottom: navigation.top 0180 } 0181 visible: currentWebView.errorCode !== "" 0182 0183 onRefreshRequested: currentWebView.reload() 0184 onCertificateIgnored: { 0185 visible = Qt.binding(() => { 0186 return currentWebView.errorCode !== ""; 0187 }) 0188 } 0189 0190 function enqueue(error){ 0191 errorString = error.description; 0192 errorCode = error.error; 0193 visible = true; 0194 errorHandler.open(error); 0195 } 0196 } 0197 0198 Loader { 0199 id: questionLoader 0200 0201 Component.onCompleted: { 0202 if (AdblockUrlInterceptor.adblockSupported && AdblockUrlInterceptor.downloadNeeded) { 0203 questionLoader.setSource("AdblockFilterDownloadQuestion.qml") 0204 } 0205 } 0206 0207 anchors.bottom: navigation.top 0208 anchors.left: parent.left 0209 anchors.right: parent.right 0210 } 0211 0212 Questions { 0213 id: questions 0214 0215 anchors.bottom: navigation.top 0216 anchors.left: parent.left 0217 anchors.right: parent.right 0218 } 0219 0220 // Container for the progress bar 0221 Item { 0222 id: progressItem 0223 0224 height: Math.round(Kirigami.Units.gridUnit / 6) 0225 z: navigation.z + 1 0226 anchors { 0227 bottom: findInPage.active ? findInPage.top : navigation.top 0228 bottomMargin: -Math.round(height / 2) 0229 left: tabs.left 0230 right: tabs.right 0231 } 0232 0233 opacity: currentWebView.loading ? 1 : 0 0234 Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad; } } 0235 0236 Rectangle { 0237 color: Kirigami.Theme.highlightColor 0238 0239 width: Math.round((currentWebView.loadProgress / 100) * parent.width) 0240 anchors { 0241 top: parent.top 0242 left: parent.left 0243 bottom: parent.bottom 0244 } 0245 } 0246 } 0247 0248 Loader { 0249 id: sheetLoader 0250 } 0251 0252 // Unload the ShareSheet again after it closed 0253 Connections { 0254 target: sheetLoader.item 0255 function onVisibleChanged() { 0256 if (!sheetLoader.item.visible) { 0257 sheetLoader.source = "" 0258 } 0259 } 0260 } 0261 0262 UrlObserver { 0263 id: urlObserver 0264 url: currentWebView.url 0265 } 0266 0267 WebAppCreator { 0268 id: webAppCreator 0269 websiteName: currentWebView.title 0270 } 0271 0272 // The menu at the bottom right 0273 actions: [ 0274 Kirigami.Action { 0275 icon.name: "edit-find" 0276 shortcut: "Ctrl+F" 0277 onTriggered: findInPage.activate() 0278 text: i18n("Find in page") 0279 }, 0280 Kirigami.Action { 0281 icon.name: "document-share" 0282 text: i18n("Share page") 0283 onTriggered: { 0284 sheetLoader.setSource("ShareSheet.qml") 0285 sheetLoader.item.url = currentWebView.url 0286 sheetLoader.item.inputTitle = currentWebView.title 0287 sheetLoader.item.open() 0288 } 0289 }, 0290 Kirigami.Action { 0291 id: addHomeScreenAction 0292 icon.name: "list-add" 0293 text: i18n("Add to homescreen") 0294 enabled: !webAppCreator.exists 0295 onTriggered: { 0296 webAppCreator.createDesktopFile(currentWebView.title, 0297 currentWebView.url, 0298 currentWebView.icon) 0299 } 0300 }, 0301 Kirigami.Action { 0302 icon.name: "application-x-object" 0303 text: i18n("Open in app") 0304 onTriggered: { 0305 Qt.openUrlExternally(currentWebView.url) 0306 } 0307 }, 0308 Kirigami.Action { 0309 enabled: currentWebView.canGoBack 0310 icon.name: "go-previous" 0311 text: i18n("Go previous") 0312 onTriggered: { 0313 currentWebView.goBack() 0314 } 0315 }, 0316 Kirigami.Action { 0317 enabled: currentWebView.canGoForward 0318 icon.name: "go-next" 0319 text: i18n("Go forward") 0320 onTriggered: { 0321 currentWebView.goForward() 0322 } 0323 }, 0324 Kirigami.Action { 0325 icon.name: currentWebView.loading ? "process-stop" : "view-refresh" 0326 text: currentWebView.loading ? i18n("Stop loading") : i18n("Refresh") 0327 onTriggered: { 0328 currentWebView.loading ? currentWebView.stopLoading() : currentWebView.reload() 0329 } 0330 }, 0331 Kirigami.Action { 0332 id: bookmarkAction 0333 checkable: true 0334 checked: urlObserver.bookmarked 0335 icon.name: "bookmarks" 0336 text: checked ? i18n("Bookmarked") : i18n("Bookmark") 0337 onTriggered: { 0338 if (checked) { 0339 var request = { 0340 url: currentWebView.url, 0341 title: currentWebView.title, 0342 icon: currentWebView.icon 0343 } 0344 BrowserManager.addBookmark(request); 0345 } else { 0346 BrowserManager.removeBookmark(currentWebView.url); 0347 } 0348 } 0349 }, 0350 Kirigami.Action { 0351 icon.name: "computer" 0352 text: i18n("Show desktop site") 0353 checkable: true 0354 checked: !currentWebView.userAgent.isMobile 0355 onTriggered: { 0356 currentWebView.userAgent.isMobile = !currentWebView.userAgent.isMobile; 0357 } 0358 }, 0359 Kirigami.Action { 0360 icon.name: currentWebView.readerMode ? "view-readermode-active" : "view-readermode" 0361 text: i18n("Reader Mode") 0362 checkable: true 0363 checked: currentWebView.readerMode 0364 onTriggered: currentWebView.readerModeSwitch() 0365 0366 }, 0367 Kirigami.Action { 0368 icon.name: "edit-select-text" 0369 text: rootPage.navigationAutoShow ? i18n("Hide navigation bar") : i18n("Show navigation bar") 0370 visible: navigation.visible 0371 onTriggered: { 0372 if (!navigation.visible) return; 0373 rootPage.navigationAutoShow = !rootPage.navigationAutoShow; 0374 } 0375 }, 0376 Kirigami.Action { 0377 icon.name: "dialog-scripts" 0378 text: i18n("Show developer tools") 0379 checkable: true 0380 checked: tabs.itemAt(tabs.currentIndex).isDeveloperToolsOpen 0381 onTriggered: { 0382 tabs.tabsModel.toggleDeveloperTools(tabs.currentIndex) 0383 } 0384 } 0385 ] 0386 0387 // Tabs sheet 0388 Loader { 0389 id: tabsSheetLoader 0390 active: false 0391 function open() { 0392 active = true; 0393 item.open(); 0394 } 0395 sourceComponent: Tabs {} 0396 } 0397 0398 // Find bar 0399 FindInPageBar { 0400 id: findInPage 0401 0402 Kirigami.Theme.colorSet: rootPage.privateMode ? Kirigami.Theme.Complementary : Kirigami.Theme.Window 0403 0404 layer.enabled: active 0405 layer.effect: DropShadow { 0406 verticalOffset: - 1 0407 color: Kirigami.Theme.disabledTextColor 0408 samples: 10 0409 spread: 0.1 0410 cached: true // element is static 0411 } 0412 } 0413 0414 // Bottom navigation bar 0415 Navigation { 0416 id: navigation 0417 0418 anchors { 0419 bottom: parent.bottom 0420 left: parent.left 0421 right: parent.right 0422 } 0423 0424 navigationShown: visible && rootPage.navigationAutoShow 0425 visible: webBrowser.visibility !== Window.FullScreen && !findInPage.active 0426 0427 tabsSheet: tabsSheetLoader 0428 0429 Kirigami.Theme.colorSet: rootPage.privateMode ? Kirigami.Theme.Complementary : Kirigami.Theme.Window 0430 0431 layer.enabled: navigation.navigationShown 0432 layer.effect: DropShadow { 0433 verticalOffset: - 1 0434 color: Kirigami.Theme.disabledTextColor 0435 samples: 10 0436 spread: 0.1 0437 cached: true // element is static 0438 } 0439 0440 onActivateUrlEntry: urlEntry.open() 0441 } 0442 0443 NavigationEntrySheet { 0444 id: urlEntry 0445 } 0446 0447 HistorySheet { 0448 id: historySheet 0449 } 0450 0451 // Thin line above navigation or find 0452 Rectangle { 0453 height: webBrowser.borderWidth 0454 color: webBrowser.borderColor 0455 anchors { 0456 left: parent.left 0457 bottom: findInPage.active ? findInPage.top : navigation.top 0458 right: parent.right 0459 } 0460 visible: navigation.navigationShown || findInPage.active 0461 } 0462 0463 // dealing with hiding and showing navigation bar 0464 property point oldScrollPosition: Qt.point(0, 0) 0465 property bool pageAlmostReady: !currentWebView.loading || currentWebView.loadProgress > 90 0466 0467 onPageAlmostReadyChanged: { 0468 if (!rootPage.pageAlmostReady) 0469 rootPage.navigationAutoShow = true; 0470 else 0471 rootPage.oldScrollPosition = currentWebView.scrollPosition; 0472 } 0473 0474 Connections { 0475 target: currentWebView 0476 function onScrollPositionChanged() { 0477 var delta = 100; 0478 if (rootPage.navigationAutoShow && rootPage.pageAlmostReady) { 0479 if (rootPage.oldScrollPosition.y + delta < currentWebView.scrollPosition.y) { 0480 // hide navbar 0481 rootPage.oldScrollPosition = currentWebView.scrollPosition; 0482 rootPage.navigationAutoShow = false; 0483 } else if (rootPage.oldScrollPosition.y > currentWebView.scrollPosition.y) { 0484 // navbar open and scrolling up 0485 rootPage.oldScrollPosition = currentWebView.scrollPosition; 0486 } 0487 } else if (!rootPage.navigationAutoShow) { 0488 if (rootPage.oldScrollPosition.y - delta > currentWebView.scrollPosition.y) { 0489 // show navbar 0490 rootPage.oldScrollPosition = currentWebView.scrollPosition; 0491 rootPage.navigationAutoShow = true; 0492 } else if (rootPage.oldScrollPosition.y < currentWebView.scrollPosition.y) { 0493 // navbar closed and scrolling down 0494 rootPage.oldScrollPosition = currentWebView.scrollPosition; 0495 } 0496 } 0497 } 0498 } 0499 } 0500 0501 Connections { 0502 target: webBrowser.pageStack 0503 function onCurrentIndexChanged() { 0504 // drop all sub pages as soon as the browser window is the 0505 // focussed one 0506 if (webBrowser.pageStack.currentIndex === 0) 0507 popSubPages(); 0508 } 0509 } 0510 0511 // Store window dimensions 0512 Component.onCompleted: { 0513 rootPage.initialized = true 0514 } 0515 0516 function popSubPages() { 0517 while (webBrowser.pageStack.depth > 1) 0518 webBrowser.pageStack.pop(); 0519 } 0520 }