diff --git a/capacitor/package.json b/capacitor/package.json index 3027038..12a997f 100644 --- a/capacitor/package.json +++ b/capacitor/package.json @@ -38,6 +38,7 @@ "@capacitor/local-notifications": "^6.1.0", "@capacitor/status-bar": "^6.0.1", "capacitor-folder-picker": "^0.0.2", + "capacitor-intent-uri": "^0.0.1", "capacitor-nodejs": "https://github.com/funniray/Capacitor-NodeJS/releases/download/nodejs-18/capacitor-nodejs-1.0.0-beta.6.tgz", "capacitor-plugin-safe-area": "^3.0.3", "capacitor-volume-control": "^0.0.1", diff --git a/capacitor/src/capacitor.js b/capacitor/src/capacitor.js index 189ec1f..3cc4bb7 100644 --- a/capacitor/src/capacitor.js +++ b/capacitor/src/capacitor.js @@ -3,6 +3,7 @@ import { StatusBar, Style } from '@capacitor/status-bar' import { SafeArea } from 'capacitor-plugin-safe-area' import { App } from '@capacitor/app' import { Browser } from '@capacitor/browser' +import { IntentUri } from 'capacitor-intent-uri' import { LocalNotifications } from '@capacitor/local-notifications' import { Device } from '@capacitor/device' import { FolderPicker } from 'capacitor-folder-picker' @@ -10,6 +11,10 @@ import { toast } from 'svelte-sonner' import IPC from './ipc.js' IPC.on('open', url => Browser.open({ url })) +IPC.on('intent', async url => { + await IntentUri.openUri({ url }) + IPC.emit('intent-end') +}) App.addListener('appUrlOpen', ({ url }) => handleProtocol(url)) diff --git a/capacitor/src/main.js b/capacitor/src/main.js index 585de0d..e851b74 100644 --- a/capacitor/src/main.js +++ b/capacitor/src/main.js @@ -16,6 +16,8 @@ if (typeof localStorage === 'undefined') { } } +let client + channel.on('port-init', data => { localStorage.setItem('settings', data) const port = { @@ -30,10 +32,12 @@ channel.on('port-init', data => { storedSettings = JSON.parse(localStorage.getItem('settings')) || {} } catch (error) {} - if (!globalThis.client) globalThis.client = new TorrentClient(channel, storageQuota, 'node', storedSettings.torrentPathNew || env.TMPDIR) - channel.on('ipc', a => port.onmessage(a)) - channel.emit('port', { - ports: [port] - }) + if (!client) { + client = new TorrentClient(channel, storageQuota, 'node', storedSettings.torrentPathNew || env.TMPDIR) + + channel.emit('port', { + ports: [port] + }) + } }) diff --git a/common/modules/torrent.js b/common/modules/torrent.js index 99ba557..6d0fa58 100644 --- a/common/modules/torrent.js +++ b/common/modules/torrent.js @@ -85,3 +85,12 @@ export async function add (torrentID, hide) { client.send('torrent', torrentID) } } +// external player for android +client.on('open', ({ detail }) => { + debug(`Open: ${detail}`) + IPC.emit('intent', detail) +}) + +IPC.on('intent-end', () => { + client.dispatch('externalWatched') +}) diff --git a/common/modules/webtorrent.js b/common/modules/webtorrent.js index 8681c54..ed5ada7 100644 --- a/common/modules/webtorrent.js +++ b/common/modules/webtorrent.js @@ -69,6 +69,7 @@ export default class TorrentClient extends WebTorrent { this.torrentPath = torrentPath this._ready = new Promise(resolve => { ipc.on('port', ({ ports }) => { + if (this.message) return this.message = ports[0].postMessage.bind(ports[0]) ports[0].onmessage = ({ data }) => { debug(`Received IPC message ${data.type}: ${data.data}`) @@ -324,20 +325,26 @@ export default class TorrentClient extends WebTorrent { this.dispatchError('File Too Big! This File Exceeds The Selected Drive\'s Available Space. Change Download Location In Torrent Settings To A Drive With More Space And Restart The App!') } this.current = found - if (data.data.external && this.player) { - this.playerProcess = spawn(this.player, ['' + new URL('http://localhost:' + this.server.address().port + found.streamURL)]) - this.playerProcess.stdout.on('data', () => {}) - const startTime = Date.now() - this.playerProcess.once('close', () => { - this.playerProcess = null - const seconds = (Date.now() - startTime) / 1000 - this.dispatch('externalWatched', seconds) - }) - } else { - this.parser = new Parser(this, found) - this.findSubtitleFiles(found) - this.findFontFiles(found) + if (data.data.external) { + if (this.player) { + this.playerProcess = spawn(this.player, ['' + new URL('http://localhost:' + this.server.address().port + found.streamURL)]) + this.playerProcess.stdout.on('data', () => {}) + const startTime = Date.now() + this.playerProcess.once('close', () => { + this.playerProcess = null + const seconds = (Date.now() - startTime) / 1000 + this.dispatch('externalWatched', seconds) + }) + return + } + if (SUPPORTS.isAndroid) { + this.dispatch('open', `intent://localhost:${this.server.address().port}${found.streamURL}#Intent;type=video/any;scheme=http;end;`) + return + } } + this.parser = new Parser(this, found) + this.findSubtitleFiles(found) + this.findFontFiles(found) } break } diff --git a/common/views/Settings/PlayerSettings.svelte b/common/views/Settings/PlayerSettings.svelte index 3fc833e..d17d24d 100644 --- a/common/views/Settings/PlayerSettings.svelte +++ b/common/views/Settings/PlayerSettings.svelte @@ -163,14 +163,14 @@ +

External Player Settings

+ +
+ + +
+
{#if SUPPORTS.externalPlayer} -

External Player Settings

- -
- - -
-
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8f91e18..c2aad62 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -72,6 +72,9 @@ importers: '@capacitor/app': specifier: ^6.0.1 version: 6.0.1(@capacitor/core@6.1.2) + '@capacitor/app-launcher': + specifier: ^6.0.2 + version: 6.0.2(@capacitor/core@6.1.2) '@capacitor/browser': specifier: ^6.0.2 version: 6.0.2(@capacitor/core@6.1.2) @@ -93,6 +96,9 @@ importers: capacitor-folder-picker: specifier: ^0.0.2 version: 0.0.2(@capacitor/core@6.1.2) + capacitor-intent-uri: + specifier: ^0.0.1 + version: 0.0.1(@capacitor/core@6.1.2) capacitor-nodejs: specifier: https://github.com/funniray/Capacitor-NodeJS/releases/download/nodejs-18/capacitor-nodejs-1.0.0-beta.6.tgz version: '@github.com/funniray/Capacitor-NodeJS/releases/download/nodejs-18/capacitor-nodejs-1.0.0-beta.6.tgz(@capacitor/core@6.1.2)' @@ -5726,6 +5732,14 @@ snapshots: '@capacitor/core': 6.1.2 dev: false + /@capacitor/app-launcher@6.0.2(@capacitor/core@6.1.2): + resolution: {integrity: sha512-g1hLHTnb7240HYcM28TBN3HbCkc6HV4242sj5/xxQyQ4N4R61DfJLpZDLtp0Wq9WkLlFCJ2B2svHU7ZvA3Tvgg==} + peerDependencies: + '@capacitor/core': ^6.0.0 + dependencies: + '@capacitor/core': 6.1.2 + dev: false + /@capacitor/app@6.0.1(@capacitor/core@6.1.2): resolution: {integrity: sha512-0kXbOl7LPPMFVcAii3u/7Ps0DvXlr7dtHT97r9J1faDlgdQLQUvtGp48tjvFm48gqHI0aOPRJnTBr5JXW4ETYg==} peerDependencies: @@ -5752,7 +5766,7 @@ snapshots: '@ionic/utils-subprocess': 2.1.14 '@ionic/utils-terminal': 2.3.5 commander: 9.5.0 - debug: 4.3.4 + debug: 4.3.6 env-paths: 2.2.1 kleur: 4.1.5 native-run: 1.7.4 @@ -5762,7 +5776,7 @@ snapshots: rimraf: 4.4.1 semver: 7.6.2 tar: 6.2.1 - tslib: 2.6.2 + tslib: 2.6.3 xml2js: 0.5.0 transitivePeerDependencies: - supports-color @@ -6085,10 +6099,10 @@ snapshots: dependencies: '@ionic/utils-object': 2.1.6 '@ionic/utils-terminal': 2.3.4 - debug: 4.3.4 + debug: 4.3.6 signal-exit: 3.0.7 tree-kill: 1.2.2 - tslib: 2.6.2 + tslib: 2.6.3 transitivePeerDependencies: - supports-color @@ -6110,8 +6124,8 @@ snapshots: resolution: {integrity: sha512-4+Kitey1lTA1yGtnigeYNhV/0tggI3lWBMjC7tBs1K9GXa/q7q4CtOISppdh8QgtOhrhAXS2Igp8rbko/Cj+lA==} engines: {node: '>=16.0.0'} dependencies: - debug: 4.3.4 - tslib: 2.6.2 + debug: 4.3.6 + tslib: 2.6.3 transitivePeerDependencies: - supports-color dev: true @@ -6139,8 +6153,8 @@ snapshots: '@ionic/utils-stream': 3.1.6 '@ionic/utils-terminal': 2.3.4 cross-spawn: 7.0.3 - debug: 4.3.4 - tslib: 2.6.2 + debug: 4.3.6 + tslib: 2.6.3 transitivePeerDependencies: - supports-color @@ -6161,12 +6175,12 @@ snapshots: '@ionic/utils-terminal@2.3.4': dependencies: '@types/slice-ansi': 4.0.0 - debug: 4.3.4 + debug: 4.3.6 signal-exit: 3.0.7 slice-ansi: 4.0.0 string-width: 4.2.3 strip-ansi: 6.0.1 - tslib: 2.6.2 + tslib: 2.6.3 untildify: 4.0.0 wrap-ansi: 7.0.0 transitivePeerDependencies: @@ -6354,7 +6368,7 @@ snapshots: dependencies: chrome-dgram: 3.0.6 cross-fetch-ponyfill: 1.0.3 - debug: 4.3.5 + debug: 4.3.6 default-gateway: 6.0.3 unordered-array-remove: 1.0.2 xml2js: 0.6.2 @@ -6428,7 +6442,7 @@ snapshots: '@thaunknown/simple-peer@10.0.9': dependencies: - debug: 4.3.5 + debug: 4.3.6 err-code: 3.0.1 streamx: 2.18.0 uint8-util: 2.2.5 @@ -6449,7 +6463,7 @@ snapshots: '@thaunknown/simple-websocket@9.1.1(bufferutil@4.0.8)(utf-8-validate@5.0.10)': dependencies: - debug: 4.3.5 + debug: 4.3.6 queue-microtask: 1.2.3 streamx: 2.18.0 uint8-util: 2.2.5 @@ -6461,7 +6475,7 @@ snapshots: '@thaunknown/simple-websocket@9.1.1(bufferutil@4.0.8)(utf-8-validate@6.0.4)': dependencies: - debug: 4.3.5 + debug: 4.3.6 queue-microtask: 1.2.3 streamx: 2.18.0 uint8-util: 2.2.5 @@ -6528,7 +6542,7 @@ snapshots: '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 20.14.2 + '@types/node': 22.5.0 '@types/bonjour@3.5.13': dependencies: @@ -6538,7 +6552,7 @@ snapshots: dependencies: '@types/http-cache-semantics': 4.0.4 '@types/keyv': 3.1.4 - '@types/node': 20.14.2 + '@types/node': 22.5.0 '@types/responselike': 1.0.3 '@types/connect-history-api-fallback@1.5.4': @@ -6548,7 +6562,7 @@ snapshots: '@types/connect@3.4.38': dependencies: - '@types/node': 20.14.2 + '@types/node': 22.5.0 '@types/cookie@0.6.0': {} @@ -6570,7 +6584,7 @@ snapshots: '@types/express-serve-static-core@4.19.1': dependencies: - '@types/node': 20.14.2 + '@types/node': 22.5.0 '@types/qs': 6.9.15 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -6589,7 +6603,8 @@ snapshots: '@types/fs-extra@9.0.13': dependencies: - '@types/node': 20.14.2 + '@types/node': 22.5.0 + dev: true '@types/html-minifier-terser@6.1.0': {} @@ -6599,7 +6614,7 @@ snapshots: '@types/http-proxy@1.17.14': dependencies: - '@types/node': 20.14.2 + '@types/node': 22.5.0 '@types/json-schema@7.0.15': {} @@ -6607,7 +6622,8 @@ snapshots: '@types/keyv@3.1.4': dependencies: - '@types/node': 20.14.2 + '@types/node': 22.5.0 + dev: true '@types/mime@1.3.5': {} @@ -6617,7 +6633,7 @@ snapshots: '@types/node-forge@1.3.11': dependencies: - '@types/node': 20.14.2 + '@types/node': 22.5.0 '@types/node@20.14.2': dependencies: @@ -6633,7 +6649,6 @@ snapshots: resolution: {integrity: sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg==} dependencies: undici-types: 6.19.8 - dev: true /@types/normalize-package-data@2.4.4: resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -6655,14 +6670,15 @@ snapshots: '@types/responselike@1.0.3': dependencies: - '@types/node': 20.14.2 + '@types/node': 22.5.0 + dev: true '@types/retry@0.12.2': {} '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 20.14.2 + '@types/node': 22.5.0 '@types/serve-index@1.9.4': dependencies: @@ -6689,7 +6705,8 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 20.14.2 + '@types/node': 22.5.0 + dev: true optional: true '@typescript-eslint/parser@7.1.1(eslint@8.57.0)(typescript@5.4.5)': @@ -7210,7 +7227,7 @@ snapshots: bittorrent-dht@11.0.6: dependencies: bencode: 4.0.0 - debug: 4.3.5 + debug: 4.3.6 k-bucket: 5.1.0 k-rpc: 5.1.0 last-one-wins: 1.0.4 @@ -7223,7 +7240,7 @@ snapshots: bittorrent-lsd@2.0.0: dependencies: chrome-dgram: 3.0.6 - debug: 4.3.5 + debug: 4.3.6 transitivePeerDependencies: - supports-color @@ -7233,7 +7250,7 @@ snapshots: dependencies: bencode: 4.0.0 bitfield: 4.2.0 - debug: 4.3.5 + debug: 4.3.6 rc4: 0.1.5 streamx: 2.18.0 throughput: 1.0.1 @@ -7285,7 +7302,7 @@ snapshots: clone: 2.1.2 compact2string: 1.4.1 cross-fetch-ponyfill: 1.0.3 - debug: 4.3.5 + debug: 4.3.6 ip: 2.0.1 lru: 3.1.0 minimist: 1.2.8 @@ -7521,6 +7538,14 @@ snapshots: '@capacitor/core': 6.1.2 dev: false + /capacitor-intent-uri@0.0.1(@capacitor/core@6.1.2): + resolution: {integrity: sha512-5Yx1VOoCkHFCz7OrHgYpY5lUt6H+9sv7HU7bwQtW81c8cZJgX9kMnMsfGeTOly+RmTkv69+G5q3DZDlAgi0s0w==} + peerDependencies: + '@capacitor/core': ^6.0.0 + dependencies: + '@capacitor/core': 6.1.2 + dev: false + /capacitor-plugin-safe-area@3.0.3(@capacitor/core@6.1.2): resolution: {integrity: sha512-pDM8GQIDC9xxKLZxoO4rrshDuzZqQo6jq7Ni18cYdp2JwmLvlhTYRrvriPAicY1En59UAZ574sIvGlgUBLH3Yw==} peerDependencies: @@ -9562,7 +9587,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 20.14.2 + '@types/node': 22.5.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -9748,7 +9773,7 @@ snapshots: lt_donthave@2.0.1: dependencies: - debug: 4.3.5 + debug: 4.3.6 unordered-array-remove: 1.0.2 transitivePeerDependencies: - supports-color @@ -11484,7 +11509,7 @@ snapshots: bittorrent-dht: 11.0.6 bittorrent-lsd: 2.0.0 bittorrent-tracker: 11.1.2 - debug: 4.3.5 + debug: 4.3.6 run-parallel: 1.2.0 transitivePeerDependencies: - supports-color @@ -11649,7 +11674,6 @@ snapshots: /undici-types@6.19.8: resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} - dev: true /unicorn-magic@0.1.0: resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} @@ -11708,7 +11732,7 @@ snapshots: dependencies: bencode: 4.0.0 bitfield: 4.2.0 - debug: 4.3.5 + debug: 4.3.6 uint8-util: 2.2.5 transitivePeerDependencies: - supports-color