webview.qml 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. import QtQuick 2.4
  2. import Konvergo 1.0
  3. import QtWebEngine 1.7
  4. import QtWebChannel 1.0
  5. import QtQuick.Window 2.2
  6. import QtQuick.Controls 1.4
  7. KonvergoWindow
  8. {
  9. id: mainWindow
  10. title: "Jellyfin Media Player"
  11. objectName: "mainWindow"
  12. minimumHeight: windowMinSize.height
  13. minimumWidth: windowMinSize.width
  14. function runWebAction(action)
  15. {
  16. if (mainWindow.webDesktopMode)
  17. web.triggerWebAction(action)
  18. }
  19. Action
  20. {
  21. enabled: mainWindow.webDesktopMode
  22. shortcut:
  23. {
  24. if (components.system.isMacos) return "Ctrl+Meta+F"
  25. return "F11"
  26. }
  27. onTriggered: mainWindow.toggleFullscreen()
  28. }
  29. Action
  30. {
  31. shortcut: "Alt+Return"
  32. enabled:
  33. {
  34. if (mainWindow.webDesktopMode && components.system.isWindows)
  35. return true;
  36. return false;
  37. }
  38. onTriggered: mainWindow.toggleFullscreen()
  39. }
  40. Action
  41. {
  42. enabled: mainWindow.webDesktopMode
  43. shortcut: StandardKey.Close
  44. onTriggered: mainWindow.close()
  45. }
  46. Action
  47. {
  48. enabled: mainWindow.webDesktopMode
  49. shortcut: {
  50. if (components.system.isMacos) return "Ctrl+M";
  51. return "Meta+Down";
  52. }
  53. onTriggered: mainWindow.minimizeWindow()
  54. }
  55. Action
  56. {
  57. enabled: mainWindow.webDesktopMode
  58. shortcut: StandardKey.Quit
  59. onTriggered: mainWindow.close()
  60. }
  61. Action
  62. {
  63. shortcut: "Ctrl+Shift+D"
  64. enabled: mainWindow.webDesktopMode
  65. onTriggered: mainWindow.toggleDebug()
  66. }
  67. Action
  68. {
  69. shortcut: StandardKey.Copy
  70. onTriggered: runWebAction(WebEngineView.Copy)
  71. id: action_copy
  72. }
  73. Action
  74. {
  75. shortcut: StandardKey.Cut
  76. onTriggered: runWebAction(WebEngineView.Cut)
  77. id: action_cut
  78. }
  79. Action
  80. {
  81. shortcut: StandardKey.Paste
  82. onTriggered: runWebAction(WebEngineView.Paste)
  83. id: action_paste
  84. }
  85. Action
  86. {
  87. shortcut: StandardKey.SelectAll
  88. onTriggered: runWebAction(WebEngineView.SelectAll)
  89. id: action_selectall
  90. }
  91. Action
  92. {
  93. shortcut: StandardKey.Undo
  94. onTriggered: runWebAction(WebEngineView.Undo)
  95. id: action_undo
  96. }
  97. Action
  98. {
  99. shortcut: StandardKey.Redo
  100. onTriggered: runWebAction(WebEngineView.Redo)
  101. id: action_redo
  102. }
  103. Action
  104. {
  105. shortcut: StandardKey.Back
  106. onTriggered: runWebAction(WebEngineView.Back)
  107. id: action_back
  108. }
  109. Action
  110. {
  111. shortcut: StandardKey.Forward
  112. onTriggered: runWebAction(WebEngineView.Forward)
  113. id: action_forward
  114. }
  115. MpvVideo
  116. {
  117. id: video
  118. objectName: "video"
  119. // It's not a real item. Its renderer draws onto the view's background.
  120. width: 0
  121. height: 0
  122. visible: false
  123. }
  124. WebEngineView
  125. {
  126. id: web
  127. objectName: "web"
  128. settings.errorPageEnabled: false
  129. settings.localContentCanAccessRemoteUrls: true
  130. settings.localContentCanAccessFileUrls: true
  131. settings.allowRunningInsecureContent: components.settings.isUsingExternalWebClient()
  132. settings.playbackRequiresUserGesture: false
  133. profile.httpUserAgent: components.system.getUserAgent()
  134. url: mainWindow.webUrl
  135. focus: true
  136. property string currentHoveredUrl: ""
  137. onLinkHovered: web.currentHoveredUrl = hoveredUrl
  138. width: mainWindow.width
  139. height: mainWindow.height
  140. userScripts: [
  141. WebEngineScript
  142. {
  143. sourceCode: components.system.getNativeShellScript()
  144. injectionPoint: WebEngineScript.DocumentCreation
  145. worldId: WebEngineScript.MainWorld
  146. }
  147. ]
  148. Component.onCompleted:
  149. {
  150. forceActiveFocus()
  151. mainWindow.reloadWebClient.connect(reload)
  152. }
  153. onLoadingChanged:
  154. {
  155. // we use a timer here to switch to the webview since
  156. // it take a few moments for the webview to render
  157. // after it has loaded.
  158. //
  159. if (loadRequest.status == WebEngineView.LoadStartedStatus)
  160. {
  161. console.log("WebEngineLoadRequest starting: " + loadRequest.url);
  162. }
  163. else if (loadRequest.status == WebEngineView.LoadSucceededStatus)
  164. {
  165. console.log("WebEngineLoadRequest success: " + loadRequest.url);
  166. }
  167. else if (loadRequest.status == WebEngineView.LoadFailedStatus)
  168. {
  169. console.log("WebEngineLoadRequest failure: " + loadRequest.url + " error code: " + loadRequest.errorCode);
  170. errorLabel.visible = true
  171. errorLabel.text = "Error loading client, this is bad and should not happen<br>" +
  172. "You can try to <a href='reload'>reload</a> or head to our <a href='http://jellyfin.org'>support page</a><br><br>Actual Error: <pre>" +
  173. loadRequest.errorString + " [" + loadRequest.errorCode + "]</pre><br><br>" +
  174. "Provide the <a target='_blank' href='file://"+ components.system.logFilePath + "'>logfile</a> as well."
  175. }
  176. }
  177. onNewViewRequested:
  178. {
  179. if (request.userInitiated)
  180. {
  181. console.log("Opening external URL: " + web.currentHoveredUrl)
  182. components.system.openExternalUrl(web.currentHoveredUrl)
  183. }
  184. }
  185. onFullScreenRequested:
  186. {
  187. console.log("Request fullscreen: " + request.toggleOn)
  188. mainWindow.setFullScreen(request.toggleOn)
  189. request.accept()
  190. }
  191. onJavaScriptConsoleMessage:
  192. {
  193. components.system.info(message)
  194. }
  195. onCertificateError:
  196. {
  197. console.log(error.url + " :" + error.description + error.error)
  198. if (components.settings.ignoreSSLErrors()) {
  199. error.ignoreCertificateError()
  200. }
  201. }
  202. }
  203. Text
  204. {
  205. id: errorLabel
  206. z: 5
  207. anchors.centerIn: parent
  208. color: "#999999"
  209. linkColor: "#a85dc3"
  210. text: "Generic error"
  211. font.pixelSize: 32
  212. font.bold: true
  213. visible: false
  214. verticalAlignment: Text.AlignVCenter
  215. textFormat: Text.StyledText
  216. onLinkActivated:
  217. {
  218. if (link == "reload")
  219. {
  220. errorLabel.visible = false
  221. web.reload()
  222. }
  223. else
  224. {
  225. Qt.openUrlExternally(link)
  226. }
  227. }
  228. }
  229. Rectangle
  230. {
  231. id: debug
  232. color: "black"
  233. z: 10
  234. anchors.centerIn: parent
  235. width: parent.width
  236. height: parent.height
  237. opacity: 0.7
  238. visible: mainWindow.showDebugLayer
  239. Text
  240. {
  241. id: debugLabel
  242. width: (parent.width - 50) / 2
  243. height: parent.height - 25
  244. anchors.left: parent.left
  245. anchors.leftMargin: 64
  246. anchors.top: parent.top
  247. anchors.topMargin: 54
  248. anchors.bottomMargin: 54
  249. color: "white"
  250. font.pixelSize: Math.round(height / 65)
  251. wrapMode: Text.WrapAnywhere
  252. function windowDebug()
  253. {
  254. var dbg = mainWindow.debugInfo + "Window and web\n";
  255. dbg += " Window size: " + parent.width + "x" + parent.height + " - " + web.width + "x" + web.height + "\n";
  256. dbg += " DevicePixel ratio: " + Screen.devicePixelRatio + "\n";
  257. return dbg;
  258. }
  259. text: windowDebug()
  260. }
  261. Text
  262. {
  263. id: videoLabel
  264. width: (parent.width - 50) / 2
  265. height: parent.height - 25
  266. anchors.right: parent.right
  267. anchors.left: debugLabel.right
  268. anchors.rightMargin: 64
  269. anchors.top: parent.top
  270. anchors.topMargin: 54
  271. anchors.bottomMargin: 54
  272. color: "white"
  273. font.pixelSize: Math.round(height / 65)
  274. wrapMode: Text.WrapAnywhere
  275. text: mainWindow.videoInfo
  276. }
  277. }
  278. property QtObject webChannel: web.webChannel
  279. }