imports, icons, fonts, styles etc

This commit is contained in:
ThaUnknown 2022-03-08 23:49:10 +01:00
parent 0e32204712
commit e889f4f414
17 changed files with 1148 additions and 115 deletions

View file

@ -10,13 +10,15 @@
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.30",
"anitomyscript": "^2.0.4",
"builtin-modules": "^3.2.0",
"concurrently": "^7.0.0",
"electron": "^16.0.10",
"electron-builder": "^22.14.13",
"svelte": "^3.46.4",
"vite": "^2.8.6",
"vite-plugin-commonjs-externals": "^0.1.1"
"vite-plugin-commonjs-externals": "^0.1.1",
"webtorrent": "^1.8.5"
},
"standard": {
"ignore": [

View file

@ -8,8 +8,8 @@ let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
width: 1600,
height: 900,
backgroundColor: '#2e2c29',
autoHideMenuBar: true,
experimentalFeatures: true,
@ -20,10 +20,10 @@ function createWindow () {
enableRemoteModule: true,
backgroundThrottling: false
},
icon: path.join(__dirname, 'public/favicon.png'),
icon: path.join(__dirname, '/renderer/public/favicon.ico'),
show: false
})
// mainWindow.removeMenu()
mainWindow.removeMenu()
// This block of code is intended for development purpose only.
// Delete this entire block of code when you are ready to package the application.
@ -40,8 +40,8 @@ function createWindow () {
// loadURL(mainWindow);
// Open the DevTools and also disable Electron Security Warning.
// process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = true;
// mainWindow.webContents.openDevTools();
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = true
mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {

View file

@ -1,13 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Miru</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<title>Miru</title>
<link rel='icon' href='/favicon.ico'>
<link href='/lib/halfmoon.css' rel='stylesheet'>
<link href="/lib/Material-Icons.css" rel="stylesheet">
<script defer src='/lib/halfmoon.js'></script>
<script defer type="module" src="/src/main.js"></script>
</head>
<body class='with-custom-webkit-scrollbars with-custom-css-scrollbars dark-mode bg-very-dark'>
</body>
</html>

Binary file not shown.

View file

@ -0,0 +1,23 @@
/* fallback */
@font-face {
font-family: 'Material Icons';
font-style: normal;
font-weight: 400;
src: url(./flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2) format('woff2');
}
.material-icons {
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
font-size: 24px;
line-height: 1;
letter-spacing: normal;
text-transform: none;
display: inline-block;
white-space: nowrap;
word-wrap: normal;
direction: ltr;
-webkit-font-feature-settings: 'liga';
-webkit-font-smoothing: antialiased;
}

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -1,66 +1,9 @@
<script>
import logo from '@/assets/svelte.png'
import Counter from '@/lib/Counter.svelte'
const process = require('process')
// import anitomyscript from 'anitomyscript'
// const WebTorrent = require('webtorrent')
// const wt = new WebTorrent()
// console.log(wt)
// anitomyscript('[GJM] Irozuku Sekai no Ashita kara - 08 [F0C587E8].mkv').then(console.log)
</script>
<main>
<img src={logo} alt="Svelte Logo" />
<h1>Hello world! {process.cwd()}</h1>
<Counter />
<p>
Visit <a href="https://svelte.dev">svelte.dev</a> to learn how to build Svelte
apps.
</p>
<p>
Check out <a href="https://github.com/sveltejs/kit#readme">SvelteKit</a> for
the officially supported framework, also powered by Vite!
</p>
</main>
<style>
:root {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}
main {
text-align: center;
padding: 1em;
margin: 0 auto;
}
img {
height: 16rem;
width: 16rem;
}
h1 {
color: #ff3e00;
text-transform: uppercase;
font-size: 4rem;
font-weight: 100;
line-height: 1.1;
margin: 2rem auto;
max-width: 14rem;
}
p {
max-width: 14rem;
margin: 1rem auto;
line-height: 1.35;
}
@media (min-width: 480px) {
h1 {
max-width: none;
}
p {
max-width: none;
}
}
</style>

View file

@ -1,34 +0,0 @@
<script>
let count = 0
const increment = () => {
count += 1
}
</script>
<button on:click={increment}>
Clicks: {count}
</button>
<style>
button {
font-family: inherit;
font-size: inherit;
padding: 1em 2em;
color: #ff3e00;
background-color: rgba(255, 62, 0, 0.1);
border-radius: 2em;
border: 2px solid rgba(255, 62, 0, 0);
outline: none;
width: 200px;
font-variant-numeric: tabular-nums;
cursor: pointer;
}
button:focus {
border: 2px solid #ff3e00;
}
button:active {
background-color: rgba(255, 62, 0, 0.2);
}
</style>

View file

@ -1,7 +1,7 @@
import App from './App.svelte'
const app = new App({
target: document.getElementById('app')
target: document.body
})
export default app

View file

@ -0,0 +1,431 @@
/* eslint-env browser */
// test ImageData constructor
; (() => {
if (typeof ImageData.prototype.constructor === 'function') {
try {
// try actually calling ImageData, as on some browsers it's reported
// as existing but calling it errors out as "TypeError: Illegal constructor"
return new ImageData(new Uint8ClampedArray([0, 0, 0, 0]), 1, 1)
} catch (e) {
console.log('detected that ImageData is not constructable despite browser saying so')
}
}
const ctx = document.createElement('canvas').getContext('2d')
window.ImageData = (data, width, height) => {
const imageData = ctx.createImageData(width, height)
if (data) imageData.data.set(data)
return imageData
}
})()
export default class SubtitlesOctopus extends EventTarget {
constructor (options = {}) {
super()
if (!window.Worker) {
this.destroy('Worker not supported')
}
// blending mode, 'js' for hardware acceleration [if browser supports it], 'wasm' for devices/browsers that don't benetit from hardware acceleration
const _blendMode = options.blendMode || 'wasm'
// drop frames when under heavy load, good for website performance
const _asyncRender = typeof createImageBitmap !== 'undefined' && (options.asyncRender ?? true)
// render in worker, rather than on main thread
const _offscreenRender = typeof OffscreenCanvas !== 'undefined' && (options.offscreenRender ?? true)
// render subs as video player renders video frames, rather than "predicting" the time with events
this._onDemandRender = 'requestVideoFrameCallback' in HTMLVideoElement.prototype && (options.onDemandRender ?? true)
this.timeOffset = options.timeOffset || 0
this._video = options.video // HTML video element (optional if canvas specified)
this._canvasParent = null // HTML canvas parent element
if (this._video) {
this._canvasParent = document.createElement('div')
this._canvasParent.className = 'subtitles-octopus'
this._canvasParent.style.position = 'relative'
if (this._video.nextSibling) {
this._video.parentNode.insertBefore(this._canvasParent, this._video.nextSibling)
} else {
this._video.parentNode.appendChild(this._canvasParent)
}
} else if (!this._canvas) {
this.destroy('Don\'t know where to render: you should give video or canvas in options.')
}
this._canvas = options.canvas || document.createElement('canvas') // HTML canvas element (optional if video specified)
this._canvas.style.display = 'block'
this._canvas.style.position = 'absolute'
this._canvas.style.pointerEvents = 'none'
this._canvasParent.appendChild(this._canvas)
this._bufferCanvas = document.createElement('canvas')
this._bufferCtx = this._bufferCanvas.getContext('2d')
this._canvasctrl = _offscreenRender ? this._canvas.transferControlToOffscreen() : this._canvas
this._ctx = !_offscreenRender && this._canvasctrl.getContext('2d')
this._lastRenderTime = 0 // Last time we got some frame from worker
this.debug = !!options.debug // When debug enabled, some performance info printed in console.
this.prescaleFactor = options.prescaleFactor || 1.0
this.prescaleHeightLimit = options.prescaleHeightLimit || 1080
this.maxRenderHeight = options.maxRenderHeight || 0 // 0 - no limit
this._worker = new Worker(options.workerUrl || 'subtitles-octopus-worker.js')
this._worker.onmessage = e => this._onmessage(e)
this._worker.onerror = e => this._error(e)
// test alpha bug
const canvas2 = document.createElement('canvas')
const ctx2 = canvas2.getContext('2d')
// test for alpha bug, where e.g. WebKit can render a transparent pixel
// (with alpha == 0) as non-black which then leads to visual artifacts
this._bufferCanvas.width = 1
this._bufferCanvas.height = 1
this._bufferCtx.clearRect(0, 0, 1, 1)
ctx2.clearRect(0, 0, 1, 1)
const prePut = ctx2.getImageData(0, 0, 1, 1).data
this._bufferCtx.putImageData(new ImageData(new Uint8ClampedArray([0, 255, 0, 0]), 1, 1), 0, 0)
ctx2.drawImage(this._bufferCanvas, 0, 0)
const postPut = ctx2.getImageData(0, 0, 1, 1).data
this.hasAlphaBug = prePut[1] !== postPut[1]
if (this.hasAlphaBug) console.log('Detected a browser having issue with transparent pixels, applying workaround')
this._worker.postMessage({
target: 'init',
asyncRender: _asyncRender,
width: this._canvas.width,
height: this._canvas.height,
URL: document.URL,
currentScript: options.workerUrl || 'subtitles-octopus-worker.js', // Link to WebAssembly worker
preMain: true,
blendMode: _blendMode,
subUrl: options.subUrl, // Link to sub file (optional if subContent specified)
subContent: options.subContent || null, // Sub content (optional if subUrl specified)
fonts: options.fonts || [], // Array with links to fonts used in sub (optional)
availableFonts: options.availableFonts || [], // Object with all available fonts (optional). Key is font name in lower case, value is link: {"arial": "/font1.ttf"}
debug: this.debug,
targetFps: options.targetFps,
libassMemoryLimit: options.libassMemoryLimit || 0, // set libass bitmap cache memory limit in MiB (approximate)
libassGlyphLimit: options.libassGlyphLimit || 0, // set libass glyph cache memory limit in MiB (approximate),
hasAlphaBug: this.hasAlphaBug
})
if (_offscreenRender === true) this.sendMessage('offscreenCanvas', null, [this._canvasctrl])
this.setVideo(options.video)
if (this._onDemandRender) this._video.requestVideoFrameCallback(this._demandRender.bind(this))
}
resize (width = 0, height = 0, top = 0, left = 0) {
let videoSize = null
if ((!width || !height) && this._video) {
videoSize = this._getVideoPosition()
const newsize = this._computeCanvasSize(videoSize.width || 0 * (window.devicePixelRatio || 1), videoSize.height || 0 * (window.devicePixelRatio || 1))
width = newsize.width
height = newsize.height
top = videoSize.y - (this._canvasParent.getBoundingClientRect().top - this._video.getBoundingClientRect().top)
left = videoSize.x
}
if (this._canvas.style.top !== top || this._canvas.style.left !== left) {
if (videoSize != null) {
this._canvas.style.top = top + 'px'
this._canvas.style.left = left + 'px'
this._canvas.style.width = videoSize.width + 'px'
this._canvas.style.height = videoSize.height + 'px'
}
if (!(this._canvasctrl.width === width && this._canvasctrl.height === height)) {
// only re-paint if dimensions actually changed
// dont spam re-paints like crazy when re-sizing with animations, but still update instantly without them
if (this._resizeTimeoutBuffer) {
clearTimeout(this._resizeTimeoutBuffer)
this._resizeTimeoutBuffer = setTimeout(() => {
this._resizeTimeoutBuffer = undefined
this._canvasctrl.width = width
this._canvasctrl.height = height
this.sendMessage('canvas', { width, height })
}, 50)
} else {
this._canvasctrl.width = width
this._canvasctrl.height = height
this.sendMessage('canvas', { width, height })
this._resizeTimeoutBuffer = setTimeout(() => {
this._resizeTimeoutBuffer = undefined
}, 50)
}
}
}
}
_getVideoPosition () {
const videoRatio = this._video.videoWidth / this._video.videoHeight
const { offsetWidth, offsetHeight } = this._video
const elementRatio = offsetWidth / offsetHeight
let width = offsetWidth
let height = offsetHeight
if (elementRatio > videoRatio) {
width = Math.floor(offsetHeight * videoRatio)
} else {
height = Math.floor(offsetWidth / videoRatio)
}
const x = (offsetWidth - width) / 2
const y = (offsetHeight - height) / 2
return { width, height, x, y }
}
_computeCanvasSize (width = 0, height = 0) {
const scalefactor = this.prescaleFactor <= 0 ? 1.0 : this.prescaleFactor
if (height <= 0 || width <= 0) {
width = 0
height = 0
} else {
const sgn = scalefactor < 1 ? -1 : 1
let newH = height
if (sgn * newH * scalefactor <= sgn * this.prescaleHeightLimit) {
newH *= scalefactor
} else if (sgn * newH < sgn * this.prescaleHeightLimit) {
newH = this.prescaleHeightLimit
}
if (this.maxRenderHeight > 0 && newH > this.maxRenderHeight) newH = this.maxRenderHeight
width *= newH / height
height = newH
}
return { width, height }
}
_timeupdate ({ type }) {
const eventmap = {
seeking: true,
waiting: true,
playing: false
}
const playing = eventmap[type]
if (playing != null) this._playstate = playing
this.setCurrentTime(this._video.paused || this._playstate, this._video.currentTime + this.timeOffset)
}
setVideo (video) {
if (video instanceof HTMLVideoElement) {
this._removeListeners()
this._video = video
if (this._onDemandRender !== true) {
this._playstate = video.paused
video.addEventListener('timeupdate', e => this._timeupdate(e), false)
video.addEventListener('progress', e => this._timeupdate(e), false)
video.addEventListener('waiting', e => this._timeupdate(e), false)
video.addEventListener('seeking', e => this._timeupdate(e), false)
video.addEventListener('playing', e => this._timeupdate(e), false)
video.addEventListener('ratechange', e => this.setRate(e), false)
}
if (video.videoWidth > 0) {
this.resize()
} else {
video.addEventListener('loadedmetadata', () => this.resize(0, 0, 0, 0), false)
}
// Support Element Resize Observer
if (typeof ResizeObserver !== 'undefined') {
if (!this._ro) this._ro = new ResizeObserver(() => this.resize(0, 0, 0, 0))
this._ro.observe(video)
}
} else {
this._error('Video element invalid!')
}
}
runBenchmark () {
this.sendMessage('runBenchmark')
}
setTrackByUrl (url) {
this.sendMessage('setTrackByUrl', { url })
}
setTrack (content) {
this.sendMessage('setTrack', { content })
}
freeTrack () {
this.sendMessage('freeTrack')
}
setIsPaused (isPaused) {
this.sendMessage('video', { isPaused })
}
setRate (rate) {
this.sendMessage('video', { rate })
}
setCurrentTime (isPaused, currentTime, rate) {
this.sendMessage('video', { isPaused, currentTime, rate })
}
createEvent (event) {
this.sendMessage('createEvent', { event })
}
setEvent (event, index) {
this.sendMessage('setEvent', { event, index })
}
removeEvent (index) {
this.sendMessage('removeEvent', { index })
}
getEvents (onError, onSuccess) {
this._fetchFromWorker({
target: 'getEvents'
}, onError, ({ events }) => {
onSuccess(events)
})
}
createStyle (style) {
this.sendMessage('createStyle', { style })
}
setStyle (event, index) {
this.sendMessage('setStyle', { event, index })
}
removeStyle (index) {
this.sendMessage('removeStyle', { index })
}
getStyles (onError, onSuccess) {
this._fetchFromWorker({
target: 'get-styles'
}, onError, ({ styles }) => {
onSuccess(styles)
})
}
_demandRender (now, metadata) {
if (this._destroyed) return null
this.sendMessage('demand', { time: metadata.mediaTime + this.timeOffset })
this._video.requestVideoFrameCallback(this._demandRender.bind(this))
}
_render (data) {
this._ctx.clearRect(0, 0, this._canvasctrl.width, this._canvasctrl.height)
for (const image of data.images) {
if (image.buffer) {
if (data.async) {
this._ctx.drawImage(image.buffer, image.x, image.y)
} else {
this._bufferCanvas.width = image.w
this._bufferCanvas.height = image.h
this._bufferCtx.putImageData(new ImageData(this._fixAlpha(new Uint8ClampedArray(image.buffer)), image.w, image.h), 0, 0)
this._ctx.drawImage(this._bufferCanvas, image.x, image.y)
}
}
}
}
_fixAlpha (uint8) {
if (this.hasAlphaBug) {
for (let j = 3; j < uint8.length; j += 4) {
uint8[j] = uint8[j] > 1 ? uint8[j] : 1
}
}
return uint8
}
_ready () {
this.dispatchEvent(new CustomEvent('ready'))
}
sendMessage (target, data = {}, transferable) {
if (transferable) {
this._worker.postMessage({
target,
transferable,
...data
}, [...transferable])
} else {
this._worker.postMessage({
target,
...data
})
}
}
_fetchFromWorker (workerOptions, onError, onSuccess) {
try {
const target = workerOptions.target
const timeout = setTimeout(() => {
reject(new Error('Error: Timeout while try to fetch ' + target))
}, 5000)
const resolve = ({ data }) => {
if (data.target === target) {
onSuccess(data)
this._worker.removeEventListener('message', resolve)
this._worker.removeEventListener('error', reject)
clearTimeout(timeout)
}
}
const reject = function (event) {
onError(event)
this._worker.removeEventListener('message', resolve)
this._worker.removeEventListener('error', reject)
clearTimeout(timeout)
}
this._worker.addEventListener('message', resolve)
this._worker.addEventListener('error', reject)
this._worker.postMessage(workerOptions)
} catch (error) {
this._error(error)
}
}
_console ({ content, command }) {
console[command].apply(console, JSON.parse(content))
}
_onmessage ({ data }) {
if (this['_' + data.target]) this['_' + data.target](data)
}
_error (err) {
this.dispatchEvent(new CustomEvent('error', { detail: err }))
throw err
}
_removeListeners () {
if (this._video) {
if (this._ro) this._ro.unobserve(this._video)
this._video.removeEventListener('timeupdate', this._timeupdate)
this._video.removeEventListener('progress', this._timeupdate)
this._video.removeEventListener('waiting', this._timeupdate)
this._video.removeEventListener('seeking', this._timeupdate)
this._video.removeEventListener('playing', this._timeupdate)
this._video.removeEventListener('ratechange', this.setRate)
}
}
destroy (err) {
if (err) this._error(err)
if (this._video) this._video.parentNode.removeChild(this._canvasParent)
this._destroyed = true
this._removeListeners()
this.sendMessage('destroy')
this._worker.terminate()
}
}
if (typeof exports !== 'undefined' && typeof module !== 'undefined' && module.exports) {
exports = module.exports = SubtitlesOctopus
}

View file

@ -11,6 +11,7 @@ const commonjsPackages = [
'electron/common',
'electron/renderer',
'original-fs',
'webtorrent',
...builtinModules
]