├── assets └── graphics │ ├── site-logo.png │ └── logo-all_layers.svg ├── package ├── contents │ ├── ui │ │ ├── assets │ │ │ ├── logo.png │ │ │ └── logo.svg │ │ ├── CompactRepresentation.qml │ │ ├── configAdvanced.qml │ │ ├── configGeneral.qml │ │ ├── js │ │ │ └── helper_functions.js │ │ └── main.qml │ └── config │ │ ├── config.qml │ │ └── main.xml ├── metadata.desktop └── metadata.json ├── README.md └── LICENSE /assets/graphics/site-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dark-eye/com.darkeye.chatGPT/HEAD/assets/graphics/site-logo.png -------------------------------------------------------------------------------- /package/contents/ui/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dark-eye/com.darkeye.chatGPT/HEAD/package/contents/ui/assets/logo.png -------------------------------------------------------------------------------- /package/contents/config/config.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.3 2 | import org.kde.plasma.configuration 2.0 3 | 4 | ConfigModel { 5 | ConfigCategory { 6 | name: i18n("General") 7 | icon: "configure" 8 | source: "configGeneral.qml" 9 | } 10 | ConfigCategory { 11 | name: i18n("Advanced") 12 | icon: "tools" 13 | source: "configAdvanced.qml" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /package/metadata.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Encoding=UTF-8 3 | Name=ChatGPT plasmoid for Plasma 4 | Keywords=ChatGPT 5 | Icon=search-symbolic 6 | X-Plasma-API=declarativeappletscript 7 | Type=Service 8 | X-Plasma-Provides=com.darkeye.chatGPT 9 | X-KDE-ServiceTypes=Plasma/Applet 10 | X-KDE-PluginInfo-Category=Windows and Tasks 11 | X-KDE-PluginInfo-Name=com.darkeye.chatGPT 12 | X-KDE-PluginInfo-EnabledByDefault=true 13 | X-KDE-PluginInfo-Version=0.9 14 | X-KDE-PluginInfo-Website=https://github.com/dark-eye/com.darkeye.chatGPT 15 | KDE-PluginInfo-License=BSD 3.0 16 | X-Plasma-MainScript=ui/main.qml 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ChatGPT 2 | 3 | ## Installtion 4 | ``` 5 | git clone git@github.com:dark-eye/com.darkeye.chatGPT.git 6 | plasmapkg2 --install ./com.darkeye.chatGPT/package 7 | ``` 8 | 9 | ## Development 10 | 11 | Just fork or clone the project : 12 | 13 | `git clone git@github.com:dark-eye/com.darkeye.chatGPT.git` 14 | 15 | Then you can apply/install you're changes by running the following from the main git directory : 16 | 17 | `plasmapkg2 --install ./package` 18 | 19 | And remove the installed plasmoid with 20 | 21 | `plasmapkg2 --remove ./package` 22 | 23 | 24 | ## General structure and notes: 25 | TODO 26 | -------------------------------------------------------------------------------- /package/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "KPlugin": { 3 | "Authors": [ 4 | { 5 | "Name": "DarkEye" 6 | } 7 | ], 8 | "Category": "Online Services", 9 | "Description": "ChatGPT plasmoid for Plasma.", 10 | "Icon": "search-symbolic", 11 | "Id": "com.darkeye.chatGPT", 12 | "License": "BSD 3.0", 13 | "Name": "ChatGPT Plasmoid", 14 | "ServiceTypes": [ 15 | "Plasma/Applet" 16 | ], 17 | "Version": "0.8", 18 | "Website": "https://github.com/dark-eye/com.darkeye.chatGPT" 19 | }, 20 | "X-Plasma-API": "declarativeappletscript", 21 | "X-Plasma-MainScript": "ui/main.qml", 22 | "X-Plasma-StandAloneApp": true 23 | } 24 | -------------------------------------------------------------------------------- /package/contents/ui/CompactRepresentation.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.3 2 | import QtQuick.Layouts 1.0 3 | import QtQuick.Controls 2.0 4 | import org.kde.plasma.core 2.0 as PlasmaCore 5 | import org.kde.plasma.plasmoid 2.0 6 | 7 | Item { 8 | anchors.fill: parent 9 | 10 | PlasmaCore.SvgItem { 11 | anchors.centerIn: parent 12 | width: parent.width < parent.height ? parent.width : parent.height 13 | height: width 14 | 15 | svg: PlasmaCore.Svg { 16 | imagePath: Qt.resolvedUrl("assets/logo.svg"); 17 | } 18 | 19 | MouseArea { 20 | anchors.fill: parent 21 | 22 | onClicked: { 23 | plasmoid.expanded = !plasmoid.expanded 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /package/contents/config/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | true 8 | 9 | 10 | true 11 | 12 | 13 | true 14 | 15 | 16 | 0 17 | 18 | 19 | 20 | assets/logo.svg 21 | 22 | 23 | false 24 | 25 | 26 | 600 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, DarkEye 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /package/contents/ui/configAdvanced.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.3 2 | import QtQuick.Layouts 1.0 3 | import QtQuick.Controls 2.5 as QQC2 4 | import org.kde.kirigami 2.4 as Kirigami 5 | 6 | Kirigami.FormLayout { 7 | id: page 8 | property alias cfg_focusInterval: focusInterval.value 9 | property alias cfg_maxReloadTime: maxReloadTime.value 10 | property alias cfg_debugConsole: debugConsole.checked 11 | 12 | Layout.fillHeight:true 13 | 14 | QQC2.Slider { 15 | Kirigami.FormData.label:i18n("Focus input after : %1ms",focusInterval.value ); 16 | id: focusInterval 17 | from:0 18 | stepSize:10 19 | value:0 20 | to:1000 21 | live:true 22 | } 23 | 24 | QQC2.Label { 25 | font.pixelSize: 8 26 | font.italic: true 27 | text:i18n("This is a workaround to allow input field to be fcoused when using the widget shortcut.") + 28 | "\n" + 29 | i18n("incrase the timeout if theres issues with focusing on the input when using the shortcut."); 30 | } 31 | 32 | QQC2.CheckBox { 33 | id: debugConsole 34 | Layout.alignment: Qt.AlignBottom 35 | Kirigami.FormData.label: i18n("Show debug console") 36 | } 37 | 38 | 39 | QQC2.Slider { 40 | Kirigami.FormData.label:i18n("Max realod is set to : %1 second ",maxReloadTime.value ); 41 | id: maxReloadTime 42 | from:0 43 | stepSize:10 44 | value:30 45 | to:3600 46 | live:true 47 | } 48 | QQC2.Label { 49 | font.pixelSize: 8 50 | font.italic: true 51 | text:i18n("This is a limit on how often the widget will try to auto reload the page (when hidden) if the page failed to load."); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /package/contents/ui/configGeneral.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.3 2 | import QtQuick.Layouts 1.0 3 | import QtQuick.Dialogs 1.3 4 | import QtQuick.Controls 2.5 as QQC2 5 | import org.kde.kirigami 2.4 as Kirigami 6 | 7 | Kirigami.FormLayout { 8 | id: page 9 | 10 | property alias cfg_downloadLocation: fileDialog.folder 11 | property alias cfg_sendOnEnter: sendOnEnter.checked 12 | property alias cfg_matchTheme: matchTheme.checked 13 | property alias cfg_allowClipboardAccess: allowClipboardAccess.checked 14 | 15 | Layout.fillHeight:true 16 | 17 | QQC2.CheckBox { 18 | id: sendOnEnter 19 | text: i18n("Send On Enter") 20 | } 21 | QQC2.Label { 22 | font.pixelSize: 12 23 | text:i18n("When checked pressing Enter will send the query to ChatGPT."); 24 | } 25 | QQC2.Label { 26 | font.pixelSize: 8 27 | font.italic: true 28 | text:i18n("For now please reload the page with the 'Reload' Button after changing this configuration."); 29 | } 30 | 31 | QQC2.CheckBox { 32 | id: matchTheme 33 | text: i18n("Match OS theme") 34 | } 35 | 36 | QQC2.CheckBox { 37 | id: allowClipboardAccess 38 | text: i18n("Allow ChatGPT system clipboard access") 39 | } 40 | QQC2.Label { 41 | font.pixelSize: 8 42 | font.italic: true 43 | text:i18n("This is enabled by default to allow for quick code/recipe/etc but can be disabled if you are worried about ChatCGPT examining your system clipboard"); 44 | } 45 | 46 | QQC2.Button { 47 | id: downloadLocation 48 | text: i18n("Select Download Path : %1 ", fileDialog.folder ) 49 | onClicked:{ 50 | fileDialog.open(); 51 | } 52 | } 53 | QQC2.Label { 54 | font.pixelSize: 8 55 | font.italic: true 56 | text:i18n("Select the directory to download files to."); 57 | } 58 | 59 | FileDialog { 60 | id:fileDialog 61 | selectFolder:true; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /package/contents/ui/js/helper_functions.js: -------------------------------------------------------------------------------- 1 | document.userScripts={saveData:{},config:{}}; 2 | 3 | document.userScripts.getMainInput = function() { 4 | return document.querySelector('textarea#prompt-textarea'); 5 | } 6 | 7 | document.userScripts.getSendButton = function() { 8 | console.log(document.querySelector('button[data-testid=send-button]')); 9 | return document.querySelector('button[data-testid=send-button]'); 10 | } 11 | 12 | document.userScripts.getStopButton = function() { 13 | return document.querySelector('button[aria-label=Stop generating]'); 14 | } 15 | 16 | 17 | document.userScripts.setInputFocus = function () { 18 | let inputElement = document.userScripts.getMainInput(); 19 | if(inputElement) { 20 | inputElement.focus(); 21 | } 22 | console.log('setInputFocus'); 23 | } 24 | 25 | 26 | document.userScripts.setSendOnEnter = function () { 27 | 28 | let inputElement = document.userScripts.getMainInput(); 29 | if(inputElement && !document.userScripts.saveData.oldOnPress) { 30 | document.userScripts.saveData.oldOnPress = inputElement.onkeypress; 31 | inputElement.onkeypress = function(e) { 32 | // console.log('keypress : ' + e.keyCode); 33 | if(document.userScripts.config.sendOnEnter) { 34 | if( !e.shiftKey && !e.ctrlKey ) 35 | switch(e.keyCode) { 36 | case 13 : { 37 | document.userScripts.getSendButton().click(); 38 | return false; 39 | } 40 | break; 41 | } 42 | } 43 | } 44 | } 45 | 46 | console.log('setSendOnEnter'); 47 | } 48 | 49 | document.userScripts.setTheme = function (theme) { 50 | if( document.userScripts.config && document.userScripts.config.matchTheme && theme ) { 51 | localStorage.setItem('theme', theme); 52 | console.log('setTheme'); 53 | } 54 | } 55 | 56 | document.userScripts.getTheme = function () { 57 | return localStorage.getItem('theme'); 58 | } 59 | 60 | document.userScripts.removeSendOnEnter = function () { 61 | let inputElement = document.userScripts.getMainInput(); 62 | if(inputElement) { 63 | inputElement.onkeypress = document.userScripts.saveData.oldOnPress; 64 | document.userScripts.saveData.oldOnPress = null; 65 | } 66 | console.log('removeSendOnEnter'); 67 | } 68 | 69 | document.userScripts.setConfig = function (configuration) { 70 | document.userScripts.config = configuration; 71 | console.log('setConfig : ' + JSON.stringify(configuration)); 72 | } 73 | 74 | console.log('Helper Functions loaded'); 75 | -------------------------------------------------------------------------------- /package/contents/ui/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 111 | -------------------------------------------------------------------------------- /package/contents/ui/main.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: %{CURRENT_YEAR} %{AUTHOR} <%{EMAIL}> 3 | * SPDX-License-Identifier: LGPL-2.1-or-later 4 | */ 5 | 6 | import QtQuick 2.3 7 | import QtQuick.Layouts 1.0 8 | import QtQuick.Controls 2.0 9 | import QtQuick.Dialogs 1.3 10 | import org.kde.plasma.core 2.0 as PlasmaCore 11 | import org.kde.plasma.components 3.0 as PlasmaComponents 12 | import org.kde.plasma.plasmoid 2.0 13 | import org.kde.plasma.extras 2.0 as PlasmaExtras 14 | import org.kde.kirigami 2.19 as Kirigami 15 | 16 | import QtWebEngine 1.9 17 | 18 | Item { 19 | id: root 20 | property bool themeMismatch: false; 21 | property int nextReloadTime: 0; 22 | property int reloadRetries: 0; 23 | property int maxReloadRetiries: 25; 24 | property bool loadedsuccessfully:false; 25 | 26 | Plasmoid.compactRepresentation: CompactRepresentation {} 27 | 28 | Plasmoid.fullRepresentation: ColumnLayout { 29 | anchors.fill: parent 30 | 31 | Layout.minimumWidth: 256 * PlasmaCore.Units.devicePixelRatio 32 | Layout.minimumHeight: 512 * PlasmaCore.Units.devicePixelRatio 33 | Layout.preferredWidth: 520 * PlasmaCore.Units.devicePixelRatio 34 | Layout.preferredHeight: 840 * PlasmaCore.Units.devicePixelRatio 35 | 36 | //----------------------------- Helpers -------------------------------------------- 37 | // Added workaround by @zontafil thank you! 38 | 39 | Timer { 40 | id: exposeTimer 41 | 42 | interval: plasmoid.configuration.focusInterval ? plasmoid.configuration.focusInterval : 0 43 | running: false 44 | onTriggered: { 45 | gptWebView.forceActiveFocus(); 46 | gptWebView.focus=true; 47 | gptWebView.runJavaScript("document.userScripts.setInputFocus();"); 48 | console.log("Plasmoid exposeTimer :"+plasmoid.expanded ) 49 | } 50 | } 51 | 52 | Timer { 53 | id: reloadTimer 54 | 55 | interval: 1000 56 | running: !plasmoid.expand 57 | onTriggered: if( !loadedsuccessfully && 58 | !plasmoid.expanded && 59 | Date.now() > root.nextReloadTime && 60 | root.reloadRetries < root.maxReloadRetiries ){ 61 | console.log("Failed to load ChatGPT page, reloading as we are hidden.."); 62 | root.reloadRetries +=1; 63 | root.nextReloadTime = Math.min(Date.now() + 1000 * (2**root.reloadRetries) , plasmoid.configuration.maxReloadTime * 1000); 64 | gptWebView.reload(); 65 | } 66 | } 67 | 68 | //-------------------------------------- Connections && handlers ------------------------------------ 69 | 70 | 71 | Keys.onPressed: { 72 | if (event.key === Qt.Key_F5 && gptWebView) { 73 | gptWebView.reload(); 74 | } 75 | // Prevent the event from propagating further 76 | event.accepted = true; 77 | } 78 | 79 | 80 | Connections { 81 | target: plasmoid 82 | function onActivated() { 83 | console.log("Plasmoid revealed to user") 84 | } 85 | function onStatusChanged() { 86 | console.log("Plasmoid status changed "+plasmoid.status) 87 | } 88 | function hideOnWindowDeactivateChanged() { 89 | console.log("Plasmoid hideOnWindowDeactivateChanged changed") 90 | } 91 | function onExpandedChanged() { 92 | if(gptWebView && plasmoid.expanded) { 93 | if(gptWebView.LoadStatus == WebEngineView.LoadFailedStatus) { 94 | gptWebView.reload(); 95 | } 96 | 97 | exposeTimer.start(); 98 | } 99 | if(!plasmoid.expanded && root.themeMismatch && plasmoid.configuration.matchTheme ) { 100 | root.themeMismatch = false; 101 | gptWebView.reloadAndBypassCache(); 102 | } 103 | console.log("Plasmoid onExpandedChanged :"+plasmoid.expanded ) 104 | } 105 | } 106 | 107 | //------------------------------------- UI ----------------------------------------- 108 | 109 | FileDialog { 110 | id:fileDialog 111 | } 112 | 113 | ColumnLayout { 114 | spacing: Kirigami.Units.mediumSpacing 115 | 116 | PlasmaExtras.PlasmoidHeading { 117 | Layout.fillWidth: true 118 | 119 | ColumnLayout { 120 | anchors.fill: parent 121 | Layout.fillWidth: true 122 | 123 | RowLayout { 124 | Layout.fillWidth: true 125 | 126 | RowLayout { 127 | Layout.fillWidth: true 128 | spacing: Kirigami.Units.mediumSpacing 129 | 130 | PlasmaComponents.ToolButton { 131 | text: i18n("Back to ChatGPT") 132 | visible: !gptWebView.url.toString().match(/chat\.openai\.com\/(|chat|auth)/); 133 | enabled: visible 134 | icon.name: "draw-arrow-back" 135 | display: PlasmaComponents.ToolButton.IconOnly 136 | PlasmaComponents.ToolTip.text: text 137 | PlasmaComponents.ToolTip.delay: Kirigami.Units.toolTipDelay 138 | PlasmaComponents.ToolTip.visible: hovered 139 | onClicked: gptWebView.url = "https://chat.openai.com/chat"; 140 | } 141 | 142 | Kirigami.Heading { 143 | id: titleText 144 | Layout.alignment: Qt.AlignCenter 145 | Layout.fillWidth: true 146 | verticalAlignment: Text.AlignVCenter 147 | text: i18n("ChatGPT") 148 | color: theme.textColor 149 | } 150 | } 151 | 152 | PlasmaComponents.ToolButton { 153 | text: i18n("Debug") 154 | checkable: true 155 | checked: gptWebViewInspector && gptWebViewInspector.enabled 156 | visible: Qt.application.arguments[0] == "plasmoidviewer" || plasmoid.configuration.debugConsole 157 | enabled: visible 158 | icon.name: "format-text-code" 159 | display: PlasmaComponents.ToolButton.IconOnly 160 | PlasmaComponents.ToolTip.text: text 161 | PlasmaComponents.ToolTip.delay: Kirigami.Units.toolTipDelay 162 | PlasmaComponents.ToolTip.visible: hovered 163 | onToggled: { 164 | gptWebViewInspector.visible = !gptWebViewInspector.visible; 165 | gptWebViewInspector.enabled = visible || gptWebViewInspector.visible 166 | } 167 | } 168 | 169 | PlasmaComponents.ToolButton { 170 | id: proButton 171 | checkable: true 172 | checked: proLinkContainer.visible 173 | text: i18n("Im a Pro") 174 | visible: gptWebView.url.toString().match(/chat\.openai\.com\/auth/); 175 | icon.name: "x-office-contact" 176 | display: PlasmaComponents.ToolButton.IconOnly 177 | PlasmaComponents.ToolTip.text: text 178 | PlasmaComponents.ToolTip.delay: Kirigami.Units.toolTipDelay 179 | PlasmaComponents.ToolTip.visible: hovered 180 | onToggled: proLinkContainer.visible = !proLinkContainer.visible; 181 | } 182 | 183 | PlasmaComponents.ToolButton { 184 | id: refreshButton 185 | text: i18n("Reload") 186 | icon.name: "view-refresh" 187 | display: PlasmaComponents.ToolButton.IconOnly 188 | PlasmaComponents.ToolTip.text: text 189 | PlasmaComponents.ToolTip.delay: Kirigami.Units.toolTipDelay 190 | PlasmaComponents.ToolTip.visible: hovered 191 | onClicked: gptWebView.reload(); 192 | } 193 | 194 | PlasmaComponents.ToolButton { 195 | id: pinButton 196 | checkable: true 197 | checked: plasmoid.configuration.pin 198 | icon.name: "window-pin" 199 | text: i18n("Keep Open") 200 | display: PlasmaComponents.ToolButton.IconOnly 201 | PlasmaComponents.ToolTip.text: text 202 | PlasmaComponents.ToolTip.delay: Kirigami.Units.toolTipDelay 203 | PlasmaComponents.ToolTip.visible: hovered 204 | onToggled: plasmoid.configuration.pin = checked 205 | } 206 | } 207 | 208 | RowLayout { 209 | id: proLinkContainer 210 | Layout.fillWidth: true 211 | visible: false; 212 | 213 | PlasmaComponents.TextField { 214 | id: proLinkField 215 | 216 | enabled: proLinkContainer.visible 217 | Layout.fillWidth: true 218 | 219 | placeholderText: i18n("Paste the accesss link that was send to your email.") 220 | text: "" 221 | } 222 | 223 | PlasmaComponents.Button { 224 | enabled: proLinkContainer.visible 225 | icon.name: "go-next" 226 | onClicked: { 227 | gptWebView.url = proLinkField.text; 228 | proLinkContainer.visible= false; 229 | } 230 | } 231 | } 232 | } 233 | } 234 | 235 | //-------------------- Connections ----------------------- 236 | 237 | Binding { 238 | target: plasmoid 239 | property: "hideOnWindowDeactivate" 240 | value: !plasmoid.configuration.pin 241 | } 242 | } 243 | 244 | //------------------------- Actual ChatGPT View -------------------------- 245 | 246 | WebEngineView { 247 | // anchors.fill: parent 248 | Layout.fillHeight: true 249 | Layout.fillWidth: true 250 | 251 | id: gptWebView 252 | focus: true 253 | url: "https://chat.openai.com/chat" 254 | 255 | profile: WebEngineProfile { 256 | id: chatGptProfile 257 | storageName: "chat-gpt" 258 | offTheRecord: false 259 | httpCacheType: WebEngineProfile.DiskHttpCache 260 | persistentCookiesPolicy: WebEngineProfile.ForcePersistentCookies 261 | downloadPath: (plasmoid.configuration.downloadLocation ? 262 | Qt.resolveUrl(plasmoid.configuration.downloadLocation) : 263 | chatGptProfile.downloadPath) + "/" 264 | userScripts: [ 265 | WebEngineScript { 266 | injectionPoint: WebEngineScript.DocumentCreation 267 | name: "helperFunctions" 268 | worldId: WebEngineScript.MainWorld 269 | sourceUrl: "./js/helper_functions.js" 270 | } 271 | ] 272 | onDownloadFinished: { 273 | console.log("onDownloadFinished : " +download.downloadDirectory + download.downloadFileName); 274 | } 275 | onDownloadRequested : { 276 | console.log("onDownloadRequested : " + download.downloadFileName); 277 | if( plasmoid.configuration.downloadLocation ) { 278 | download.downloadDirectory = chatGptProfile.downloadPath; 279 | download.accept(); 280 | console.log("onDownloadRequested : downloaded to "+download.downloadDirectory); 281 | console.log("onDownloadRequested : downloaded to "+plasmoid.configuration.downloadLocation ); 282 | } else { 283 | console.log("onDownloadRequested : please configure a download location"); 284 | } 285 | } 286 | } 287 | 288 | settings.javascriptCanAccessClipboard: plasmoid.configuration.allowClipboardAccess 289 | 290 | onLoadingChanged: { 291 | if(WebEngineView.LoadSucceededStatus === loadRequest.status) { 292 | root.reloadRetries = 0; 293 | let themeLightness = (isDark(theme.backgroundColor) ? 'dark' : 'light') ; 294 | 295 | gptWebView.runJavaScript("document.userScripts.setConfig("+JSON.stringify(plasmoid.configuration)+");"); 296 | gptWebView.runJavaScript("document.userScripts.setSendOnEnter();"); 297 | gptWebView.runJavaScript("document.userScripts.getTheme();",function(theme) { 298 | if( !plasmoid.expanded && plasmoid.configuration.matchTheme && (!theme || theme !== themeLightness)) { 299 | gptWebView.runJavaScript("document.userScripts.setTheme('"+themeLightness+"');"); 300 | gptWebView.relreloadAndBypassCacheoad(); 301 | } else if(plasmoid.configuration.matchTheme && theme !== themeLightness) { 302 | root.themeMismatch = true; 303 | } 304 | }); 305 | gptWebView.runJavaScript("document.userScripts.setTheme('"+themeLightness+"');"); 306 | } 307 | 308 | 309 | loadedsuccessfully = ( loadRequest.status == WebEngineLoadRequest.LoadSucceededStatus && (gptWebView.loadProgress == 100 || gptWebView.loadProgress == 0)) 310 | && 311 | ( !gptWebView.loading ) 312 | 313 | } 314 | 315 | onFileDialogRequested: { 316 | console.log("onFileDialogRequested"); 317 | //console.log(JSON.stringify(request)); 318 | fileDialog.title = "Choose File"; 319 | fileDialog.accept.connect(function (request){ 320 | request.dialogAccept(fileDialog.selectedFiles); 321 | }); 322 | fileDialog.reject.connect(function(request) { 323 | request.dialogReject() 324 | }); 325 | fileDialog.open(); 326 | request.accepted = true 327 | } 328 | 329 | onJavaScriptDialogRequested : { 330 | console.log("onJavaScriptDialogRequested"); 331 | } 332 | 333 | onNewViewRequested : { 334 | console.log("onNewViewRequested"); 335 | if(request.requestedUrl.toString().match(/https?\:\/\/chat\.openai\.com/)) { 336 | gptWebView.url = request.requestedUrl; 337 | console.log(request.url); 338 | } else { 339 | Qt.openUrlExternally(request.url); 340 | request.action = WebEngineNavigationRequest.IgnoreRequest; 341 | } 342 | } 343 | 344 | onJavaScriptConsoleMessage: if( Qt.application.arguments[0].match(/plasmoidviewer/) ) { 345 | console.log("Chat-GPT: " + message); 346 | } 347 | 348 | onNavigationRequested: { 349 | if(request.navigationType == WebEngineNavigationRequest.LinkClickedNavigation) { 350 | if(request.url.toString().match(/https?\:\/\/chat\.openai\.com/)) { 351 | gptWebView.url = request.url; 352 | console.log(request.url); 353 | } else { 354 | Qt.openUrlExternally(request.url); 355 | request.action = WebEngineNavigationRequest.IgnoreRequest; 356 | } 357 | } 358 | } 359 | 360 | function isDark(color) { 361 | let luminance = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b; 362 | return (luminance < 0.5); 363 | } 364 | } 365 | WebEngineView { 366 | id:gptWebViewInspector 367 | enabled: false 368 | visible: false 369 | z:100 370 | height:parent.height /2 371 | 372 | Layout.fillWidth:true 373 | Layout.alignment:Qt.AlignBottom 374 | inspectedView:enabled ? gptWebView : null 375 | } 376 | } 377 | } 378 | 379 | 380 | -------------------------------------------------------------------------------- /assets/graphics/logo-all_layers.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 125 | --------------------------------------------------------------------------------