mirror of
https://github.com/NoCrypt/migu.git
synced 2026-05-10 12:01:20 +00:00
feat: w2g rewrite
This commit is contained in:
parent
4d49cf545f
commit
bf817e2da0
5 changed files with 106 additions and 301 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "Miru",
|
"name": "Miru",
|
||||||
"version": "2.11.3",
|
"version": "2.12.0",
|
||||||
"author": "ThaUnknown_ <ThaUnknown@users.noreply.github.com>",
|
"author": "ThaUnknown_ <ThaUnknown@users.noreply.github.com>",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"homepage": "https://github.com/ThaUnknown/miru#readme",
|
"homepage": "https://github.com/ThaUnknown/miru#readme",
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
"electron-notarize": "^1.1.1",
|
"electron-notarize": "^1.1.1",
|
||||||
"svelte": "^3.47.0",
|
"svelte": "^3.47.0",
|
||||||
"vite": "^3.0.0",
|
"vite": "^3.0.0",
|
||||||
"vite-plugin-commonjs-externals": "^0.1.1"
|
"vite-plugin-commonjs": "^0.5.2"
|
||||||
},
|
},
|
||||||
"standard": {
|
"standard": {
|
||||||
"ignore": [
|
"ignore": [
|
||||||
|
|
@ -121,6 +121,7 @@
|
||||||
"jassub": "^1.1.8",
|
"jassub": "^1.1.8",
|
||||||
"matroska-subtitles": "github:ThaUnknown/matroska-subtitles#patch",
|
"matroska-subtitles": "github:ThaUnknown/matroska-subtitles#patch",
|
||||||
"mime": "^3.0.0",
|
"mime": "^3.0.0",
|
||||||
|
"p2pcf": "^1.2.1",
|
||||||
"pump": "^3.0.0",
|
"pump": "^3.0.0",
|
||||||
"quartermoon": "^1.2.1",
|
"quartermoon": "^1.2.1",
|
||||||
"range-parser": "^1.2.1",
|
"range-parser": "^1.2.1",
|
||||||
|
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
<script>
|
|
||||||
import { handleCode } from './WatchTogether.svelte'
|
|
||||||
export let state
|
|
||||||
export let peer
|
|
||||||
export let cancel
|
|
||||||
|
|
||||||
let values = []
|
|
||||||
let code = ''
|
|
||||||
|
|
||||||
peer.pc.addEventListener('signalingstatechange', () => {
|
|
||||||
console.log(peer.pc.signalingState)
|
|
||||||
if (peer.pc.signalingState === 'have-remote-offer') {
|
|
||||||
value = null
|
|
||||||
index = index + 1
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
peer.signalingPort.onmessage = ({ data }) => {
|
|
||||||
// console.log(data)
|
|
||||||
const { description, candidate } = typeof data === 'string' ? JSON.parse(data) : data
|
|
||||||
if (description) {
|
|
||||||
if (description.type === 'answer') values = []
|
|
||||||
values.push(description.sdp)
|
|
||||||
} else if (candidate) {
|
|
||||||
if (candidate.candidate.includes('srflx')) values.push(candidate.candidate)
|
|
||||||
}
|
|
||||||
if (values.length > 1) {
|
|
||||||
code = btoa(JSON.stringify(values))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$: value = (step?.mode === 'copy' && code) || null
|
|
||||||
|
|
||||||
function handleInput ({ target }) {
|
|
||||||
handleCode(target.value)
|
|
||||||
value = null
|
|
||||||
}
|
|
||||||
|
|
||||||
function copyData () {
|
|
||||||
navigator.clipboard.writeText(`<miru://w2g/${state === 'host' ? 'invite' : 'join'}/${value}>`)
|
|
||||||
index = index + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
let index = 0
|
|
||||||
|
|
||||||
const map = {
|
|
||||||
guest: [
|
|
||||||
{
|
|
||||||
title: 'Paste Invite Code',
|
|
||||||
description: 'Paste the one time invite code sent to you by the lobby host.',
|
|
||||||
mode: 'paste'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Copy Invite Confirmation',
|
|
||||||
description: 'Send the host this code, which required to request a connection.',
|
|
||||||
mode: 'copy'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
host: [
|
|
||||||
{
|
|
||||||
title: 'Copy Invite Code',
|
|
||||||
description: 'Copy the one time invite code, and send it to the person you wish to invite.',
|
|
||||||
mode: 'copy'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Paste Invite Confirmation',
|
|
||||||
description: 'Paste the code sent to you by the user which wants to join your lobby.',
|
|
||||||
mode: 'paste'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
$: step = map[state]?.[index]
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class='h-full d-flex flex-column justify-content-center mb-20 pb-20 root container'>
|
|
||||||
{#if step && (value || step.mode === 'paste')}
|
|
||||||
<h1 class='font-weight-bold'>
|
|
||||||
{step.title}
|
|
||||||
</h1>
|
|
||||||
<p class='font-size-18 mt-0'>
|
|
||||||
{step.description}
|
|
||||||
</p>
|
|
||||||
<textarea disabled={step.mode === 'copy'} on:input={handleInput} bind:value class='form-control h-300 w-full mb-15' />
|
|
||||||
{#if step.mode === 'copy' && value}
|
|
||||||
<button class='btn btn-primary mt-5' type='button' on:click={copyData} disabled={!value}>Copy</button>
|
|
||||||
{/if}
|
|
||||||
{:else}
|
|
||||||
<h1 class='font-weight-bold'>Connecting...</h1>
|
|
||||||
{/if}
|
|
||||||
<button class='btn btn-danger mt-5' type='button' on:click={cancel}>Cancel</button>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
export let peers
|
export let peers
|
||||||
export let state
|
|
||||||
export let invite
|
export let invite
|
||||||
export let cleanup
|
export let cleanup
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -8,9 +7,7 @@ export let cleanup
|
||||||
<div class='d-flex flex-column py-20 root container card'>
|
<div class='d-flex flex-column py-20 root container card'>
|
||||||
<div class='d-flex align-items-center w-full'>
|
<div class='d-flex align-items-center w-full'>
|
||||||
<h1 class='font-weight-bold mr-auto'>Lobby</h1>
|
<h1 class='font-weight-bold mr-auto'>Lobby</h1>
|
||||||
{#if state === 'host'}
|
<button class='btn btn-success btn-lg ml-20' type='button' on:click={invite}>Invite To Lobby</button>
|
||||||
<button class='btn btn-success btn-lg ml-20' type='button' on:click={invite}>Invite To Lobby</button>
|
|
||||||
{/if}
|
|
||||||
<button class='btn btn-danger ml-20 btn-lg' type='button' on:click={cleanup}>Leave lobby</button>
|
<button class='btn btn-danger ml-20 btn-lg' type='button' on:click={cleanup}>Leave lobby</button>
|
||||||
</div>
|
</div>
|
||||||
{#each Object.values(peers) as peer}
|
{#each Object.values(peers) as peer}
|
||||||
|
|
@ -24,9 +21,9 @@ export let cleanup
|
||||||
{#if peer.user?.name}
|
{#if peer.user?.name}
|
||||||
<span class='material-icons pointer text-primary' on:click={() => window.IPC.emit('open', 'https://anilist.co/user/' + peer.user?.name)}> open_in_new </span>
|
<span class='material-icons pointer text-primary' on:click={() => window.IPC.emit('open', 'https://anilist.co/user/' + peer.user?.name)}> open_in_new </span>
|
||||||
{/if}
|
{/if}
|
||||||
{#if state === 'host'}
|
<!-- {#if state === 'host'}
|
||||||
<span class='material-icons ml-15 pointer text-danger' on:click={() => peer.peer.pc.close()}> logout </span>
|
<span class='material-icons ml-15 pointer text-danger' on:click={() => peer.peer.pc.close()}> logout </span>
|
||||||
{/if}
|
{/if} -->
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,84 @@
|
||||||
<script context='module'>
|
<script context='module'>
|
||||||
import { writable, get } from 'svelte/store'
|
import { writable } from 'svelte/store'
|
||||||
import { alID } from '@/modules/anilist.js'
|
import { alID } from '@/modules/anilist.js'
|
||||||
import { add, client } from '@/modules/torrent.js'
|
import { add, client } from '@/modules/torrent.js'
|
||||||
import Peer from '@/modules/Peer.js'
|
|
||||||
import { generateRandomHexCode } from '@/modules/util.js'
|
import { generateRandomHexCode } from '@/modules/util.js'
|
||||||
import { addToast } from '@/lib/Toasts.svelte'
|
// import { addToast } from '@/lib/Toasts.svelte'
|
||||||
import { page } from '@/App.svelte'
|
import { page } from '@/App.svelte'
|
||||||
import 'browser-event-target-emitter'
|
import 'browser-event-target-emitter'
|
||||||
|
|
||||||
|
import P2PCF from 'p2pcf'
|
||||||
|
|
||||||
export const w2gEmitter = new EventTarget()
|
export const w2gEmitter = new EventTarget()
|
||||||
|
|
||||||
const state = writable(null)
|
const decode = TextDecoder.prototype.decode.bind(new TextDecoder('utf-8'))
|
||||||
|
const encode = TextEncoder.prototype.encode.bind(new TextEncoder())
|
||||||
|
|
||||||
const peers = writable({})
|
const peers = writable({})
|
||||||
|
|
||||||
let peersExternal = {}
|
const state = writable(false)
|
||||||
|
|
||||||
peers.subscribe(value => (peersExternal = value))
|
let p2pcf = null
|
||||||
|
|
||||||
const pending = writable(null)
|
function joinLobby (code = generateRandomHexCode(16)) {
|
||||||
|
p2pcf = new P2PCF(generateRandomHexCode(16), code)
|
||||||
function invite () {
|
p2pcf.on('peerconnect', async peer => {
|
||||||
pending.set(new Peer({ polite: false }))
|
const user = (await alID)?.data?.Viewer || {}
|
||||||
|
peer.send(
|
||||||
|
JSON.stringify({
|
||||||
|
type: 'init',
|
||||||
|
id: user.id || generateRandomHexCode(16),
|
||||||
|
user
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
p2pcf.on('peerclose', peer => {
|
||||||
|
peers.update(object => {
|
||||||
|
delete object[peer.id]
|
||||||
|
return object
|
||||||
|
})
|
||||||
|
})
|
||||||
|
p2pcf.on('msg', (peer, data) => {
|
||||||
|
data = typeof data === 'string' ? JSON.parse(data) : JSON.parse(decode(data))
|
||||||
|
console.log(data)
|
||||||
|
switch (data.type) {
|
||||||
|
case 'init':
|
||||||
|
peers.update(object => {
|
||||||
|
object[peer.id] = {
|
||||||
|
peer,
|
||||||
|
user: data.user
|
||||||
|
}
|
||||||
|
return object
|
||||||
|
})
|
||||||
|
break
|
||||||
|
case 'player': {
|
||||||
|
if (setPlayerState(data)) w2gEmitter.emit('playerupdate', data)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'torrent': {
|
||||||
|
if (data.hash !== playerState.hash) {
|
||||||
|
playerState.hash = data.hash
|
||||||
|
add(data.magnet)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'index': {
|
||||||
|
if (playerState.index !== data.index) {
|
||||||
|
playerState.index = data.index
|
||||||
|
w2gEmitter.emit('setindex', data.index)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
console.error('Invalid message type', data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
p2pcf.start()
|
||||||
|
state.set(true)
|
||||||
|
console.log(p2pcf)
|
||||||
}
|
}
|
||||||
|
|
||||||
pending.subscribe(peer => {
|
|
||||||
if (peer) peer.ready.then(() => handlePeer(peer))
|
|
||||||
})
|
|
||||||
|
|
||||||
function setPlayerState (detail) {
|
function setPlayerState (detail) {
|
||||||
let emit = false
|
let emit = false
|
||||||
for (const key of ['paused', 'time']) {
|
for (const key of ['paused', 'time']) {
|
||||||
|
|
@ -48,20 +99,16 @@ w2gEmitter.on('index', ({ detail }) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
queueMicrotask(() => {
|
client.on('magnet', ({ detail }) => {
|
||||||
client.on('magnet', ({ detail }) => {
|
if (detail.hash !== playerState.hash) {
|
||||||
if (detail.hash !== playerState.hash) {
|
playerState.hash = detail.hash
|
||||||
playerState.hash = detail.hash
|
playerState.index = 0
|
||||||
playerState.index = 0
|
emit('torrent', detail)
|
||||||
emit('torrent', detail)
|
}
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
function emit (type, data) {
|
function emit (type, data) {
|
||||||
for (const peer of Object.values(peersExternal)) {
|
p2pcf?.broadcast(encode(JSON.stringify({ type, ...data })))
|
||||||
peer.channel.send(JSON.stringify({ type, ...data }))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const playerState = {
|
const playerState = {
|
||||||
|
|
@ -71,166 +118,25 @@ const playerState = {
|
||||||
index: 0
|
index: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancel () {
|
const linkRx = /(.*)/i
|
||||||
pending.update(peer => {
|
|
||||||
peer.pc.close()
|
|
||||||
})
|
|
||||||
if (get(state) === 'guest') state.set(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
function cleanup () {
|
|
||||||
if (get(state)) {
|
|
||||||
addToast({
|
|
||||||
text: 'The lobby you were previously in has disbanded.',
|
|
||||||
title: 'Lobby Disbanded',
|
|
||||||
type: 'danger'
|
|
||||||
})
|
|
||||||
state.set(null)
|
|
||||||
pending.set(null)
|
|
||||||
peers.update(peers => {
|
|
||||||
for (const peer of Object.values(peers)) peer?.peer?.pc.close()
|
|
||||||
return {}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handlePeer (peer) {
|
|
||||||
pending.set(null)
|
|
||||||
if (get(state) === 'guest') peer.dc.onclose = cleanup
|
|
||||||
// add event listeners and store in peers
|
|
||||||
const protocolChannel = peer.pc.createDataChannel('w2gprotocol', { negotiated: true, id: 2 })
|
|
||||||
protocolChannel.onopen = async () => {
|
|
||||||
protocolChannel.onmessage = ({ data }) => handleMessage(JSON.parse(data), protocolChannel, peer)
|
|
||||||
const user = (await alID)?.data?.Viewer || {}
|
|
||||||
protocolChannel.send(
|
|
||||||
JSON.stringify({
|
|
||||||
type: 'init',
|
|
||||||
id: user.id || generateRandomHexCode(16),
|
|
||||||
user
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const base64Rx = /((?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?)/
|
|
||||||
export function handleCode (text) {
|
|
||||||
console.log(text)
|
|
||||||
const match = text.match(base64Rx)
|
|
||||||
if (match) {
|
|
||||||
const code = match[1]
|
|
||||||
const pend = get(pending)
|
|
||||||
let val = null
|
|
||||||
try {
|
|
||||||
val = JSON.parse(atob(code))
|
|
||||||
} catch (e) {
|
|
||||||
addToast({
|
|
||||||
text: 'The provided invite code was invalid, try copying it again?',
|
|
||||||
title: 'Invalid Invite Code',
|
|
||||||
type: 'danger'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (!val) return
|
|
||||||
const [description, ...candidates] = val
|
|
||||||
|
|
||||||
pend.signalingPort.postMessage({
|
|
||||||
description: {
|
|
||||||
type: get(state) === 'host' ? 'answer' : 'offer',
|
|
||||||
sdp: description
|
|
||||||
}
|
|
||||||
})
|
|
||||||
for (const candidate of candidates) {
|
|
||||||
pend.signalingPort.postMessage({
|
|
||||||
candidate: {
|
|
||||||
candidate,
|
|
||||||
sdpMid: '0',
|
|
||||||
sdpMLineIndex: 0
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleMessage (data, channel, peer) {
|
|
||||||
if (get(state) === 'host') emit(data.type, data)
|
|
||||||
switch (data.type) {
|
|
||||||
case 'init':
|
|
||||||
peers.update(object => {
|
|
||||||
object[data.id] = {
|
|
||||||
peer,
|
|
||||||
channel,
|
|
||||||
user: data.user
|
|
||||||
}
|
|
||||||
return object
|
|
||||||
})
|
|
||||||
|
|
||||||
channel.onclose = () => {
|
|
||||||
peers.update(object => {
|
|
||||||
delete object[data.id]
|
|
||||||
return object
|
|
||||||
})
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case 'player': {
|
|
||||||
if (setPlayerState(data)) w2gEmitter.emit('playerupdate', data)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'torrent': {
|
|
||||||
if (data.hash !== playerState.hash) {
|
|
||||||
playerState.hash = data.hash
|
|
||||||
add(data.magnet)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'index': {
|
|
||||||
if (playerState.index !== data.index) {
|
|
||||||
playerState.index = data.index
|
|
||||||
w2gEmitter.emit('setindex', data.index)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
console.error('Invalid message type', data, channel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setState (newstate) {
|
|
||||||
if (newstate === 'guest') {
|
|
||||||
const peer = new Peer({ polite: true })
|
|
||||||
pending.set(peer)
|
|
||||||
}
|
|
||||||
state.set(newstate)
|
|
||||||
}
|
|
||||||
|
|
||||||
function waitToCompleteIceGathering (pc, state = pc.iceGatheringState) {
|
|
||||||
return state !== 'complete' && new Promise(resolve => {
|
|
||||||
pc.addEventListener('icegatheringstatechange', () => (pc.iceGatheringState === 'complete') && resolve())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const linkRx = /(invite|join)\/(.*)/i
|
|
||||||
window.IPC.on('w2glink', async link => {
|
window.IPC.on('w2glink', async link => {
|
||||||
const match = link.match(linkRx)
|
const match = link.match(linkRx)
|
||||||
console.log(link, match)
|
|
||||||
if (match) {
|
if (match) {
|
||||||
page.set('watchtogether')
|
page.set('watchtogether')
|
||||||
if (match[1] === 'join') {
|
joinLobby(match[1])
|
||||||
if (get(state)) {
|
|
||||||
handleCode(match[2])
|
|
||||||
} else {
|
|
||||||
console.log('no')
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!get(state)) setState('guest')
|
|
||||||
await waitToCompleteIceGathering(get(pending).pc)
|
|
||||||
handleCode(match[2])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function cleanup () {
|
||||||
|
state.set(false)
|
||||||
|
peers.set({})
|
||||||
|
p2pcf.destroy()
|
||||||
|
p2pcf = null
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Lobby from './Lobby.svelte'
|
import Lobby from './Lobby.svelte'
|
||||||
import Connect from './Connect.svelte'
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class='d-flex h-full align-items-center flex-column content'>
|
<div class='d-flex h-full align-items-center flex-column content'>
|
||||||
|
|
@ -239,17 +145,15 @@ import Connect from './Connect.svelte'
|
||||||
<div class='d-flex flex-row flex-wrap justify-content-center align-items-center h-full mb-20 pb-20 root'>
|
<div class='d-flex flex-row flex-wrap justify-content-center align-items-center h-full mb-20 pb-20 root'>
|
||||||
<div class='card d-flex flex-column align-items-center w-300 h-300 justify-content-end'>
|
<div class='card d-flex flex-column align-items-center w-300 h-300 justify-content-end'>
|
||||||
<span class='font-size-80 material-icons d-flex align-items-center h-full'>add</span>
|
<span class='font-size-80 material-icons d-flex align-items-center h-full'>add</span>
|
||||||
<button class='btn btn-primary btn-lg mt-10 btn-block' type='button' on:click={() => setState('host')}>Create Lobby</button>
|
<button class='btn btn-primary btn-lg mt-10 btn-block' type='button' on:click={() => joinLobby()}>Create Lobby</button>
|
||||||
</div>
|
</div>
|
||||||
<div class='card d-flex flex-column align-items-center w-300 h-300 justify-content-end'>
|
<div class='card d-flex flex-column align-items-center w-300 h-300 justify-content-end'>
|
||||||
<span class='font-size-80 material-icons d-flex align-items-center h-full'>group_add</span>
|
<span class='font-size-80 material-icons d-flex align-items-center h-full'>group_add</span>
|
||||||
<button class='btn btn-primary btn-lg mt-10 btn-block' type='button' on:click={() => setState('guest')}>Join Lobby</button>
|
<button class='btn btn-primary btn-lg mt-10 btn-block' type='button' on:click={() => {}}>Join Lobby</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{:else if $pending}
|
|
||||||
<Connect bind:state={$state} peer={$pending} {cancel} />
|
|
||||||
{:else}
|
{:else}
|
||||||
<Lobby bind:state={$state} bind:peers={$peers} {invite} {cleanup} />
|
<Lobby peers={$peers} {cleanup} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,25 @@
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import process from 'process'
|
import process from 'process'
|
||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import { builtinModules } from 'module'
|
|
||||||
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
||||||
import commonjsExternals from 'vite-plugin-commonjs-externals'
|
import commonjs from 'vite-plugin-commonjs'
|
||||||
|
|
||||||
const commonjsPackages = [
|
|
||||||
'@electron/remote',
|
|
||||||
'webtorrent',
|
|
||||||
'matroska-subtitles',
|
|
||||||
...builtinModules
|
|
||||||
]
|
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig(({ mode }) => {
|
||||||
resolve: {
|
return {
|
||||||
alias: {
|
resolve: {
|
||||||
'@': path.resolve('src/renderer/src')
|
alias: {
|
||||||
}
|
'@': path.resolve('src/renderer/src')
|
||||||
},
|
}
|
||||||
plugins: [commonjsExternals({ externals: commonjsPackages }), svelte()],
|
},
|
||||||
root: path.resolve(process.cwd(), 'src/renderer'),
|
plugins: [mode !== 'development' && commonjs(), svelte()],
|
||||||
base: './',
|
root: path.resolve(process.cwd(), 'src/renderer'),
|
||||||
build: {
|
base: './',
|
||||||
rollupOptions: {
|
build: {
|
||||||
output: {
|
rollupOptions: {
|
||||||
assetFileNames: '[name].[ext]'
|
output: {
|
||||||
|
assetFileNames: '[name].[ext]'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue