mirror of
https://github.com/NoCrypt/migu.git
synced 2026-03-11 17:45:32 +00:00
feat: WebRTC support, better rendering performace
This commit is contained in:
parent
41617bd556
commit
ae17be05a6
13 changed files with 200 additions and 129 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "Miru",
|
||||
"version": "3.2.3",
|
||||
"version": "3.3.0",
|
||||
"author": "ThaUnknown_ <ThaUnknown@users.noreply.github.com>",
|
||||
"description": "Stream anime torrents, real-time with no waiting for downloads.",
|
||||
"main": "src/index.js",
|
||||
|
|
@ -109,7 +109,7 @@
|
|||
"discord-rpc": "4.0.1",
|
||||
"electron-log": "^4.4.6",
|
||||
"electron-updater": "^4.6.5",
|
||||
"jassub": "1.2.0",
|
||||
"jassub": "1.2.1",
|
||||
"js-levenshtein": "^1.1.6",
|
||||
"matroska-subtitles": "github:ThaUnknown/matroska-subtitles#patch",
|
||||
"mime": "^3.0.0",
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ specifiers:
|
|||
browser-event-target-emitter: ^1.0.0
|
||||
concurrently: ^7.0.0
|
||||
discord-rpc: 4.0.1
|
||||
electron: 20.1.1
|
||||
electron: 21.3.1
|
||||
electron-builder: ^23.3.3
|
||||
electron-log: ^4.4.6
|
||||
electron-notarize: ^1.1.1
|
||||
electron-updater: ^4.6.5
|
||||
jassub: 1.2.0
|
||||
jassub: 1.2.1
|
||||
js-levenshtein: ^1.1.6
|
||||
matroska-subtitles: github:ThaUnknown/matroska-subtitles#patch
|
||||
mime: ^3.0.0
|
||||
|
|
@ -34,7 +34,7 @@ dependencies:
|
|||
discord-rpc: 4.0.1
|
||||
electron-log: 4.4.8
|
||||
electron-updater: 4.6.5
|
||||
jassub: 1.2.0
|
||||
jassub: 1.2.1
|
||||
js-levenshtein: 1.1.6
|
||||
matroska-subtitles: github.com/ThaUnknown/matroska-subtitles/70bee097ad540e07d9e31b8f91f1dd865f7f2b45
|
||||
mime: 3.0.0
|
||||
|
|
@ -49,7 +49,7 @@ dependencies:
|
|||
devDependencies:
|
||||
'@sveltejs/vite-plugin-svelte': 1.0.1_svelte@3.49.0+vite@3.2.4
|
||||
concurrently: 7.3.0
|
||||
electron: 20.1.1
|
||||
electron: 21.3.1
|
||||
electron-builder: 23.3.3
|
||||
electron-notarize: 1.2.1
|
||||
svelte: 3.49.0
|
||||
|
|
@ -1222,8 +1222,8 @@ packages:
|
|||
- supports-color
|
||||
dev: false
|
||||
|
||||
/electron/20.1.1:
|
||||
resolution: {integrity: sha512-cFTfP4R2O5onaXiu+S20xK7eLpyX/H7PYk7lj9mlHS0ui1+w1jDDWD3RhvjmPgeksPfMAZiRLK8lAQvzSBAKdg==}
|
||||
/electron/21.3.1:
|
||||
resolution: {integrity: sha512-Ik/I9oFHA1h32JRtRm6GMgYdUctFpF/tPnHyATg4r3LXBTUT6habGh3GxSdmmTa5JgtA7uJUEm8EjjZItk7T3g==}
|
||||
engines: {node: '>= 10.17.0'}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
|
|
@ -2032,8 +2032,8 @@ packages:
|
|||
minimatch: 3.1.2
|
||||
dev: true
|
||||
|
||||
/jassub/1.2.0:
|
||||
resolution: {integrity: sha512-ijYA+pGiIKhCPQtOpO+jisQbszeyTeDMQA9qvVJC1/4UbDl1sKsM1yCwqKjvv60XiGt/glyCdda5W6b/K4taFg==}
|
||||
/jassub/1.2.1:
|
||||
resolution: {integrity: sha512-bA8s0RAGNwjuqzrcPElXEPnAN/flPFP2sbw5/Q3C5kJX52YYqyZoFAhsCumy/FY6HUWmDz1HA/Y3ep6V26ol3A==}
|
||||
dependencies:
|
||||
rvfc-polyfill: 1.0.4
|
||||
dev: false
|
||||
|
|
|
|||
111
src/index.js
111
src/index.js
|
|
@ -1,6 +1,8 @@
|
|||
const { app, BrowserWindow, protocol, shell, ipcMain, dialog } = require('electron')
|
||||
const { app, BrowserWindow, protocol, shell, ipcMain, dialog, MessageChannelMain } = require('electron')
|
||||
const path = require('path')
|
||||
require('./main/misc.js')
|
||||
const { Client } = require('discord-rpc')
|
||||
const log = require('electron-log')
|
||||
const { autoUpdater } = require('electron-updater')
|
||||
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
|
|
@ -73,6 +75,7 @@ ipcMain.on('open', (event, url) => {
|
|||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
let webtorrentWindow
|
||||
|
||||
function UpsertKeyValue (obj, keyToChange, value) {
|
||||
const keyToChangeLower = keyToChange.toLowerCase()
|
||||
|
|
@ -88,6 +91,10 @@ function UpsertKeyValue (obj, keyToChange, value) {
|
|||
obj[keyToChange] = value
|
||||
}
|
||||
|
||||
ipcMain.on('devtools', () => {
|
||||
webtorrentWindow.webContents.openDevTools()
|
||||
})
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
|
|
@ -99,12 +106,20 @@ function createWindow () {
|
|||
webPreferences: {
|
||||
enableBlinkFeatures: 'FontAccess, AudioVideoTracks',
|
||||
backgroundThrottling: false,
|
||||
nodeIntegrationInWorker: true,
|
||||
preload: path.join(__dirname, '/preload.js')
|
||||
},
|
||||
icon: path.join(__dirname, '/renderer/public/logo.ico'),
|
||||
show: false
|
||||
})
|
||||
webtorrentWindow = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false,
|
||||
enableRemoteModule: true,
|
||||
backgroundThrottling: false
|
||||
}
|
||||
})
|
||||
mainWindow.setMenuBarVisibility(false)
|
||||
|
||||
protocol.registerHttpProtocol('miru', (req, cb) => {
|
||||
|
|
@ -130,10 +145,13 @@ function createWindow () {
|
|||
// Delete this entire block of code when you are ready to package the application.
|
||||
if (process.env.NODE_ENV !== 'development ') {
|
||||
// Load production build
|
||||
webtorrentWindow.loadFile(path.join(__dirname, '/renderer/dist/webtorrent.html'))
|
||||
mainWindow.loadFile(path.join(__dirname, '/renderer/dist/index.html'))
|
||||
} else {
|
||||
// Load vite dev server page
|
||||
console.log('Development mode')
|
||||
webtorrentWindow.loadURL('http://localhost:5173/webtorrent.html')
|
||||
webtorrentWindow.webContents.openDevTools()
|
||||
mainWindow.loadURL('http://localhost:5173/')
|
||||
mainWindow.webContents.openDevTools()
|
||||
}
|
||||
|
|
@ -166,6 +184,11 @@ function createWindow () {
|
|||
mainWindow.once('ready-to-show', () => {
|
||||
mainWindow.show()
|
||||
})
|
||||
ipcMain.on('portRequest', ({ sender }) => {
|
||||
const { port1, port2 } = new MessageChannelMain()
|
||||
webtorrentWindow.webContents.postMessage('port', null, [port1])
|
||||
sender.postMessage('port', null, [port2])
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
|
|
@ -185,3 +208,85 @@ app.on('activate', () => {
|
|||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) createWindow()
|
||||
})
|
||||
|
||||
ipcMain.on('dialog', async (event, data) => {
|
||||
const { filePaths } = await dialog.showOpenDialog({
|
||||
properties: ['openDirectory']
|
||||
})
|
||||
if (filePaths.length) {
|
||||
let path = filePaths[0]
|
||||
if (!(path.endsWith('\\') || path.endsWith('/'))) {
|
||||
if (path.indexOf('\\') !== -1) {
|
||||
path += '\\'
|
||||
} else if (path.indexOf('/') !== -1) {
|
||||
path += '/'
|
||||
}
|
||||
}
|
||||
event.sender.send('path', path)
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('minimize', (event) => {
|
||||
BrowserWindow.fromWebContents(event.sender).minimize()
|
||||
})
|
||||
ipcMain.on('maximize', (event) => {
|
||||
const window = BrowserWindow.fromWebContents(event.sender)
|
||||
if (window.isMaximized()) {
|
||||
window.unmaximize()
|
||||
} else {
|
||||
window.maximize()
|
||||
}
|
||||
})
|
||||
ipcMain.on('close', () => {
|
||||
app.quit()
|
||||
})
|
||||
|
||||
let status = null
|
||||
const discord = new Client({
|
||||
transport: 'ipc'
|
||||
})
|
||||
function setDiscordRPC (event, data) {
|
||||
status = data
|
||||
if (discord?.user && status) {
|
||||
status.pid = process.pid
|
||||
discord.request('SET_ACTIVITY', status)
|
||||
}
|
||||
}
|
||||
|
||||
ipcMain.on('discord', setDiscordRPC)
|
||||
discord.on('ready', async () => {
|
||||
setDiscordRPC(null, status)
|
||||
discord.subscribe('ACTIVITY_JOIN_REQUEST')
|
||||
discord.subscribe('ACTIVITY_JOIN')
|
||||
discord.subscribe('ACTIVITY_SPECTATE')
|
||||
})
|
||||
discord.on('ACTIVITY_JOIN_REQUEST', console.log)
|
||||
discord.on('ACTIVITY_SPECTATE', console.log)
|
||||
discord.on('ACTIVITY_JOIN', (args) => {
|
||||
console.log('ACTIVITY_JOIN')
|
||||
console.log(args)
|
||||
console.log('------')
|
||||
BrowserWindow.getAllWindows()[0]?.send('w2glink', args.secret)
|
||||
})
|
||||
|
||||
function loginRPC () {
|
||||
discord.login({ clientId: '954855428355915797' }).catch(() => {
|
||||
setTimeout(loginRPC, 5000).unref()
|
||||
})
|
||||
}
|
||||
loginRPC()
|
||||
|
||||
ipcMain.on('version', (event) => {
|
||||
event.sender.send('version', app.getVersion()) // fucking stupid
|
||||
})
|
||||
|
||||
autoUpdater.logger = log
|
||||
autoUpdater.logger.transports.file.level = 'info'
|
||||
ipcMain.on('update', () => {
|
||||
autoUpdater.checkForUpdatesAndNotify()
|
||||
})
|
||||
|
||||
autoUpdater.checkForUpdatesAndNotify()
|
||||
autoUpdater.on('update-available', () => {
|
||||
BrowserWindow.getAllWindows()[0]?.send('update', true)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,83 +0,0 @@
|
|||
const { dialog, ipcMain, BrowserWindow, app } = require('electron')
|
||||
const { Client } = require('discord-rpc')
|
||||
const log = require('electron-log')
|
||||
const { autoUpdater } = require('electron-updater')
|
||||
|
||||
ipcMain.on('dialog', async (event, data) => {
|
||||
const { filePaths } = await dialog.showOpenDialog({
|
||||
properties: ['openDirectory']
|
||||
})
|
||||
if (filePaths.length) {
|
||||
let path = filePaths[0]
|
||||
if (!(path.endsWith('\\') || path.endsWith('/'))) {
|
||||
if (path.indexOf('\\') !== -1) {
|
||||
path += '\\'
|
||||
} else if (path.indexOf('/') !== -1) {
|
||||
path += '/'
|
||||
}
|
||||
}
|
||||
event.sender.send('path', path)
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('minimize', (event) => {
|
||||
BrowserWindow.fromWebContents(event.sender).minimize()
|
||||
})
|
||||
ipcMain.on('maximize', (event) => {
|
||||
const window = BrowserWindow.fromWebContents(event.sender)
|
||||
if (window.isMaximized()) {
|
||||
window.unmaximize()
|
||||
} else {
|
||||
window.maximize()
|
||||
}
|
||||
})
|
||||
|
||||
let status = null
|
||||
const discord = new Client({
|
||||
transport: 'ipc'
|
||||
})
|
||||
function setDiscordRPC (event, data) {
|
||||
status = data
|
||||
if (discord?.user && status) {
|
||||
status.pid = process.pid
|
||||
discord.request('SET_ACTIVITY', status)
|
||||
}
|
||||
}
|
||||
|
||||
ipcMain.on('discord', setDiscordRPC)
|
||||
discord.on('ready', async () => {
|
||||
setDiscordRPC(null, status)
|
||||
discord.subscribe('ACTIVITY_JOIN_REQUEST')
|
||||
discord.subscribe('ACTIVITY_JOIN')
|
||||
discord.subscribe('ACTIVITY_SPECTATE')
|
||||
})
|
||||
discord.on('ACTIVITY_JOIN_REQUEST', console.log)
|
||||
discord.on('ACTIVITY_SPECTATE', console.log)
|
||||
discord.on('ACTIVITY_JOIN', (args) => {
|
||||
console.log('ACTIVITY_JOIN')
|
||||
console.log(args)
|
||||
console.log('------')
|
||||
BrowserWindow.getAllWindows()[0]?.send('w2glink', args.secret)
|
||||
})
|
||||
|
||||
function loginRPC () {
|
||||
discord.login({ clientId: '954855428355915797' }).catch(() => {
|
||||
setTimeout(loginRPC, 5000).unref()
|
||||
})
|
||||
}
|
||||
loginRPC()
|
||||
|
||||
ipcMain.on('version', (event) => {
|
||||
event.sender.send('version', app.getVersion()) // fucking stupid
|
||||
})
|
||||
|
||||
autoUpdater.logger = log
|
||||
autoUpdater.logger.transports.file.level = 'info'
|
||||
ipcMain.on('update', () => {
|
||||
autoUpdater.checkForUpdatesAndNotify()
|
||||
})
|
||||
|
||||
autoUpdater.checkForUpdatesAndNotify()
|
||||
autoUpdater.on('update-available', () => {
|
||||
BrowserWindow.getAllWindows()[0]?.send('update', true)
|
||||
})
|
||||
|
|
@ -8,6 +8,9 @@ contextBridge.exposeInMainWorld('IPC', {
|
|||
on: (event, callback) => {
|
||||
ipcRenderer.on(event, (event, ...args) => callback(...args))
|
||||
},
|
||||
once: (event, callback) => {
|
||||
ipcRenderer.once(event, (event, ...args) => callback(...args))
|
||||
},
|
||||
off: (event) => {
|
||||
ipcRenderer.removeAllListeners(event)
|
||||
}
|
||||
|
|
@ -16,3 +19,14 @@ contextBridge.exposeInMainWorld('version', {
|
|||
arch: process.arch,
|
||||
platform: process.platform
|
||||
})
|
||||
|
||||
ipcRenderer.once('port', ({ ports }) => {
|
||||
contextBridge.exposeInMainWorld('port', {
|
||||
onmessage: (cb) => {
|
||||
ports[0].onmessage = ({ type, data }) => cb({ type, data })
|
||||
},
|
||||
postMessage: (...args) => {
|
||||
ports[0].postMessage(...args)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
<link rel='icon' href='/logo.ico'>
|
||||
<link href="/lib/Material-Icons.css" rel="stylesheet">
|
||||
|
||||
<script defer type="module" src="/src/main.js" async></script>
|
||||
<script defer type="module" src="./src/main.js" async></script>
|
||||
</head>
|
||||
|
||||
<body class="dark-mode with-custom-webkit-scrollbars with-custom-css-scrollbars">
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ const pump = require('pump')
|
|||
const rangeParser = require('range-parser')
|
||||
const mime = require('mime')
|
||||
const { SubtitleParser, SubtitleStream } = require('matroska-subtitles')
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
class TorrentClient extends WebTorrent {
|
||||
constructor (settings) {
|
||||
|
|
@ -96,8 +97,6 @@ class TorrentClient extends WebTorrent {
|
|||
this.server.on('error', console.warn)
|
||||
|
||||
this.server.listen(0)
|
||||
|
||||
onmessage = this.handleMessage.bind(this)
|
||||
}
|
||||
|
||||
handleMessage ({ data }) {
|
||||
|
|
@ -116,7 +115,7 @@ class TorrentClient extends WebTorrent {
|
|||
this.current.on('done', this.parseSubtitles.bind(this))
|
||||
this.parseFonts(this.current)
|
||||
}
|
||||
// findSubtitleFiles(current) TODO:
|
||||
// TODO: findSubtitleFiles(current)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
|
@ -140,7 +139,7 @@ class TorrentClient extends WebTorrent {
|
|||
}
|
||||
|
||||
dispatch (type, data) {
|
||||
postMessage({ type, data })
|
||||
message({ type, data })
|
||||
}
|
||||
|
||||
parseSubtitles () {
|
||||
|
|
@ -217,8 +216,14 @@ class TorrentClient extends WebTorrent {
|
|||
}
|
||||
|
||||
let client = null
|
||||
let message = null
|
||||
|
||||
onmessage = ({ data }) => {
|
||||
if (!client && data.type === 'settings') client = new TorrentClient(data.data)
|
||||
if (data.type === 'destroy') client?.predestroy()
|
||||
}
|
||||
ipcRenderer.on('port', (e) => {
|
||||
e.ports[0].onmessage = ({ data }) => {
|
||||
if (!client && data.type === 'settings') window.client = client = new TorrentClient(data.data)
|
||||
if (data.type === 'destroy') client?.predestroy()
|
||||
|
||||
client.handleMessage({ data })
|
||||
}
|
||||
message = e.ports[0].postMessage.bind(e.ports[0])
|
||||
})
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<script context='module'>
|
||||
import { writable } from 'svelte/store'
|
||||
export const title = writable('Miru')
|
||||
import { writable } from 'svelte/store'
|
||||
export const title = writable('Miru')
|
||||
</script>
|
||||
|
||||
<div class='w-full navbar border-0 bg-dark position-relative p-0'>
|
||||
|
|
@ -21,7 +21,7 @@ export const title = writable('Miru')
|
|||
<path d='M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z' />
|
||||
</svg>
|
||||
</div>
|
||||
<div class='d-flex align-items-center close' on:click={window.close}>
|
||||
<div class='d-flex align-items-center close' on:click={() => window.IPC.emit('close')}>
|
||||
<svg viewBox='0 0 24 24'>
|
||||
<path d='M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z' />
|
||||
</svg>
|
||||
|
|
|
|||
|
|
@ -180,7 +180,11 @@
|
|||
}
|
||||
|
||||
let currentTime = 0
|
||||
$: progress = currentTime / safeduration
|
||||
let progress = 0
|
||||
// needs to be slow in order to not spam repaints
|
||||
function updateProgress () {
|
||||
progress = video.currentTime / safeduration
|
||||
}
|
||||
$: targetTime = (!paused && currentTime) || targetTime
|
||||
function handleMouseDown ({ target }) {
|
||||
wasPaused = paused
|
||||
|
|
@ -858,6 +862,7 @@
|
|||
on:seeked={updatew2g}
|
||||
on:timeupdate={() => createThumbnail()}
|
||||
on:timeupdate={checkCompletion}
|
||||
on:timeupdate={updateProgress}
|
||||
on:waiting={showBuffering}
|
||||
on:loadeddata={hideBuffering}
|
||||
on:canplay={hideBuffering}
|
||||
|
|
@ -894,16 +899,14 @@
|
|||
</div>
|
||||
<span class='material-icons ctrl' title='Keybinds [`]' on:click={() => (showKeybinds = true)}> help_outline </span>
|
||||
</div>
|
||||
<div class='middle d-flex align-items-center justify-content-center flex-grow-1 position-relative'>
|
||||
<div class='position-absolute w-full h-full' on:dblclick={toggleFullscreen} on:click|self={() => (page = 'player')}>
|
||||
<div class='play-overlay w-full h-full' on:click={playPause} />
|
||||
</div>
|
||||
<div class='middle d-flex align-items-center justify-content-center flex-grow-1'>
|
||||
<div class='w-full h-full position-absolute' on:dblclick={toggleFullscreen} on:click|self={() => { if (page === 'player') playPause(); page = 'player' }} />
|
||||
<span class='material-icons ctrl' class:text-muted={!hasLast} class:disabled={!hasLast} data-name='playLast' on:click={playLast}> skip_previous </span>
|
||||
<span class='material-icons ctrl' data-name='rewind' on:click={rewind}> fast_rewind </span>
|
||||
<span class='material-icons ctrl' data-name='playPause' on:click={playPause}> {ended ? 'replay' : paused ? 'play_arrow' : 'pause'} </span>
|
||||
<span class='material-icons ctrl' data-name='forward' on:click={forward}> fast_forward </span>
|
||||
<span class='material-icons ctrl' class:text-muted={!hasNext} class:disabled={!hasNext} data-name='playNext' on:click={playNext}> skip_next </span>
|
||||
<div data-name='bufferingDisplay' class='position-absolute' />
|
||||
<div class='position-absolute bufferingDisplay' />
|
||||
</div>
|
||||
<div class='bottom d-flex z-40 flex-column px-20'>
|
||||
<div class='w-full d-flex align-items-center h-20 mb--5'>
|
||||
|
|
@ -1036,6 +1039,7 @@
|
|||
}
|
||||
.miniplayer {
|
||||
height: auto !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
.miniplayer .top,
|
||||
.miniplayer .bottom {
|
||||
|
|
@ -1105,7 +1109,7 @@
|
|||
opacity: 0.1%;
|
||||
}
|
||||
|
||||
.middle div[data-name='bufferingDisplay'] {
|
||||
.middle .bufferingDisplay {
|
||||
border: 4px solid #ffffff00;
|
||||
border-top: 4px solid #fff;
|
||||
border-radius: 50%;
|
||||
|
|
@ -1113,6 +1117,7 @@
|
|||
height: 40px;
|
||||
animation: spin 1s linear infinite;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: 0.5s opacity ease;
|
||||
filter: drop-shadow(0 0 8px #000);
|
||||
}
|
||||
|
|
@ -1120,8 +1125,12 @@
|
|||
cursor: not-allowed !important;
|
||||
}
|
||||
|
||||
.buffering .middle div[data-name='bufferingDisplay'] {
|
||||
.buffering .middle .bufferingDisplay {
|
||||
opacity: 1 !important;
|
||||
visibility: visible !important;
|
||||
}
|
||||
.pip .bufferingDisplay {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
|
|
@ -1163,9 +1172,6 @@
|
|||
font-size: 2.8rem;
|
||||
margin: 0.6rem;
|
||||
}
|
||||
.miniplayer .middle .play-overlay {
|
||||
display: none !important;
|
||||
}
|
||||
.miniplayer .middle .ctrl[data-name='playPause'] {
|
||||
font-size: 5.625rem;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,7 +138,6 @@ export default class Subtitles {
|
|||
availableFonts: {
|
||||
'roboto medium': './Roboto.ttf'
|
||||
},
|
||||
useLocalFonts: true,
|
||||
workerUrl
|
||||
})
|
||||
this.selectCaptions(this.current)
|
||||
|
|
|
|||
|
|
@ -1,25 +1,32 @@
|
|||
// import WebTorrent from 'webtorrent'
|
||||
import { set } from '@/lib/Settings.svelte'
|
||||
import { files } from '@/lib/Player/MediaHandler.svelte'
|
||||
import { page } from '@/App.svelte'
|
||||
import 'browser-event-target-emitter'
|
||||
|
||||
class TorrentWorker extends Worker {
|
||||
constructor (opts) {
|
||||
super(opts)
|
||||
this.onmessage = this.handleMessage.bind(this)
|
||||
class TorrentWorker extends EventTarget {
|
||||
constructor () {
|
||||
super()
|
||||
this.ready = new Promise((resolve) => {
|
||||
window.IPC.once('port', () => {
|
||||
this.port = window.port
|
||||
this.port.onmessage((...args) => this.handleMessage(...args))
|
||||
resolve()
|
||||
})
|
||||
window.IPC.emit('portRequest')
|
||||
})
|
||||
}
|
||||
|
||||
handleMessage ({ data }) {
|
||||
this.emit(data.type, data.data)
|
||||
}
|
||||
|
||||
send (type, data) {
|
||||
this.postMessage({ type, data })
|
||||
async send (type, data) {
|
||||
await this.ready
|
||||
this.port.postMessage({ type, data })
|
||||
}
|
||||
}
|
||||
|
||||
export const client = new TorrentWorker(new URL('./torrentworker.js', import.meta.url))
|
||||
export const client = new TorrentWorker()
|
||||
|
||||
client.send('settings', { ...set })
|
||||
|
||||
|
|
|
|||
13
src/renderer/webtorrent.html
Normal file
13
src/renderer/webtorrent.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta name='viewport' content='width=device-width,initial-scale=1'>
|
||||
<meta name="theme-color" content="#191c20">
|
||||
<title>WebTorrent Hidden Window</title>
|
||||
|
||||
<script defer src="./lib/webtorrent.js" async></script>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
||||
|
|
@ -4,6 +4,7 @@ import { defineConfig } from 'vite'
|
|||
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
||||
import commonjs from 'vite-plugin-commonjs'
|
||||
|
||||
const root = path.resolve(process.cwd(), 'src/renderer')
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(({ mode }) => {
|
||||
return {
|
||||
|
|
@ -13,12 +14,16 @@ export default defineConfig(({ mode }) => {
|
|||
}
|
||||
},
|
||||
plugins: [mode !== 'development' && commonjs(), svelte()],
|
||||
root: path.resolve(process.cwd(), 'src/renderer'),
|
||||
root,
|
||||
base: './',
|
||||
build: {
|
||||
rollupOptions: {
|
||||
output: {
|
||||
assetFileNames: '[name].[ext]'
|
||||
},
|
||||
input: {
|
||||
index: root + '/index.html',
|
||||
torrent: root + '/webtorrent.html'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue