mirror of
https://github.com/NoCrypt/migu.git
synced 2026-04-19 07:32:05 +00:00
feat: dev and build configs
fix: subtitles not rendering in portrait fix: notch inset safe areas chore: better code structure for capacitor feat: capacitor AL login
This commit is contained in:
parent
94155bdd59
commit
11356d1646
18 changed files with 183 additions and 70 deletions
1
capacitor/.gitignore
vendored
1
capacitor/.gitignore
vendored
|
|
@ -6,6 +6,7 @@ android/app/*
|
|||
android/app/src/*
|
||||
!android/app/src/main
|
||||
android/app/src/main/*
|
||||
!android/app/src/main/AndroidManifest.xml
|
||||
!android/app/src/main/java
|
||||
android/app/src/main/java/*
|
||||
!android/app/src/main/java/watch
|
||||
|
|
|
|||
39
capacitor/android/app/src/main/AndroidManifest.xml
Normal file
39
capacitor/android/app/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/title_activity_main"
|
||||
android:theme="@style/AppTheme.NoActionBarLaunch"
|
||||
android:launchMode="singleTask"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<!-- added scheme rest is generated -->
|
||||
<data android:scheme="miru" />
|
||||
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
<!-- Permissions -->
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
</manifest>
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
let config = {
|
||||
const mode = process.env.NODE_ENV?.trim() || 'development'
|
||||
|
||||
const config = {
|
||||
appId: 'watch.miru',
|
||||
appName: 'Miru',
|
||||
webDir: 'build',
|
||||
|
|
@ -16,21 +18,10 @@ let config = {
|
|||
}
|
||||
}
|
||||
|
||||
switch (process.env.NODE_ENV) {
|
||||
case 'qa':
|
||||
config = {
|
||||
...config
|
||||
}
|
||||
break
|
||||
default:
|
||||
config = {
|
||||
...config
|
||||
// server: {
|
||||
// url: 'http://localhost:5001/index.html',
|
||||
// cleartext: true
|
||||
// }
|
||||
}
|
||||
break
|
||||
if (mode === 'development') {
|
||||
config.server = {
|
||||
url: 'http://localhost:5001/index.html',
|
||||
cleartext: true
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = config
|
||||
|
|
|
|||
|
|
@ -2,19 +2,19 @@
|
|||
"name": "capacitor",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build:app": "build:web && build:android",
|
||||
"build:web": "cross-env NODE_ENV=production webpack build",
|
||||
"build:app": "cross-env NODE_ENV=production run-s build:web build:assets build:android",
|
||||
"build:web": "webpack build",
|
||||
"build:android": "cap build android",
|
||||
"build:ios": "run-s build:app cap-run:ios",
|
||||
"cap:android-emulator": "cap run android --target=Pixel_XL_API_33 --external --public-host=10.5.0.2 && dev:localhost-bind",
|
||||
"cap:localhost-bind": "adb reverse tcp:5001 tcp:5001",
|
||||
"cap:android": "run-s cap:android-emulator cap:localhost-bind",
|
||||
"cap:assets": "capacitor-assets generate --iconBackgroundColor #17191c --iconBackgroundColorDark #17191c --splashBackgroundColor #17191c --splashBackgroundColorDark #17191c --android",
|
||||
"cap:ios": "cap sync ios && cap open ios",
|
||||
"build:ios": "cap build ios",
|
||||
"build:assets": "capacitor-assets generate --iconBackgroundColor #17191c --iconBackgroundColorDark #17191c --splashBackgroundColor #17191c --splashBackgroundColorDark #17191c --android",
|
||||
"dev:adb-port": "adb reverse tcp:5001 tcp:5001",
|
||||
"dev:ios": "run-p dev:start cap-run:ios",
|
||||
"dev:android": "cap run android",
|
||||
"dev:android-port": "run-s dev:android dev:adb-port",
|
||||
"dev:preview": "vite preview",
|
||||
"dev:start": "run-p dev:webpack cap:android",
|
||||
"dev:webpack": "webpack serve"
|
||||
"dev:start": "run-p dev:webpack dev:android-port",
|
||||
"dev:webpack": "webpack serve",
|
||||
"test:e2e": "cross-env NODE_ENV=production run-s build:web dev:android"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@capacitor/assets": "^3.0.1",
|
||||
|
|
@ -36,6 +36,8 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@capacitor/android": "^5.5.1",
|
||||
"@capacitor/app": "^5.0.6",
|
||||
"@capacitor/browser": "^5.1.0",
|
||||
"@capacitor/cli": "^5.5.1",
|
||||
"@capacitor/core": "^5.5.1",
|
||||
"@capacitor/ios": "^5.5.1",
|
||||
|
|
|
|||
57
capacitor/src/capacitor.js
Normal file
57
capacitor/src/capacitor.js
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/* globals navigationbar */
|
||||
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 { ipcRendererUI, main } from './ipc.js'
|
||||
|
||||
main.on('open', url => Browser.open({ url }))
|
||||
|
||||
App.addListener('appUrlOpen', ({ url }) => handleProtocol(url))
|
||||
|
||||
// schema: miru://key/value
|
||||
const protocolMap = {
|
||||
auth: token => sendToken(token),
|
||||
anime: id => ipcRendererUI.emit('open-anime', id),
|
||||
w2g: link => ipcRendererUI.emit('w2glink', link),
|
||||
schedule: () => ipcRendererUI.emit('schedule'),
|
||||
donate: () => Browser.open({ url: 'https://github.com/sponsors/ThaUnknown/' })
|
||||
}
|
||||
|
||||
const protocolRx = /miru:\/\/([a-z0-9]+)\/(.*)/i
|
||||
|
||||
function handleProtocol (text) {
|
||||
const match = text.match(protocolRx)
|
||||
if (match) protocolMap[match[1]]?.(match[2])
|
||||
}
|
||||
|
||||
function sendToken (line) {
|
||||
let token = line.split('access_token=')[1].split('&token_type')[0]
|
||||
if (token) {
|
||||
if (token.endsWith('/')) token = token.slice(0, -1)
|
||||
ipcRendererUI.emit('altoken', token)
|
||||
}
|
||||
}
|
||||
|
||||
App.getLaunchUrl().then(res => {
|
||||
if (res) handleProtocol(res.url)
|
||||
})
|
||||
|
||||
SafeArea.addListener('safeAreaChanged', updateInsets)
|
||||
screen.orientation.addEventListener('change', updateInsets)
|
||||
|
||||
async function updateInsets () {
|
||||
const { insets } = await SafeArea.getSafeAreaInsets()
|
||||
for (const [key, value] of Object.entries(insets)) {
|
||||
document.documentElement.style.setProperty(`--safe-area-${key}`, `${value}px`)
|
||||
}
|
||||
}
|
||||
updateInsets()
|
||||
|
||||
StatusBar.hide()
|
||||
StatusBar.setStyle({ style: Style.Dark })
|
||||
StatusBar.setOverlaysWebView({ overlay: true })
|
||||
|
||||
navigationbar.setUp(true)
|
||||
|
||||
// cordova screen orientation plugin is also used, and it patches global screen.orientation.lock
|
||||
|
|
@ -1,26 +1,29 @@
|
|||
import EventEmitter from 'events'
|
||||
|
||||
const ipcRendererUI = new EventEmitter()
|
||||
export const ipcRendererUI = new EventEmitter()
|
||||
|
||||
export const main = new EventEmitter()
|
||||
|
||||
export default {
|
||||
emit: (event, data) => {
|
||||
// ipcRendererUI.emit(event, data)
|
||||
if (event === 'portRequest') portRequest(data)
|
||||
main.emit(event, data)
|
||||
},
|
||||
on: (event, callback) => {
|
||||
ipcRendererUI.on(event, (event, ...args) => callback(...args))
|
||||
ipcRendererUI.on(event, (...args) => callback(...args))
|
||||
},
|
||||
once: (event, callback) => {
|
||||
ipcRendererUI.once(event, (event, ...args) => callback(...args))
|
||||
ipcRendererUI.once(event, (...args) => callback(...args))
|
||||
},
|
||||
off: event => {
|
||||
ipcRendererUI.removeAllListeners(event)
|
||||
}
|
||||
}
|
||||
|
||||
main.on('portRequest', portRequest)
|
||||
|
||||
async function portRequest (data) {
|
||||
const { port1, port2 } = new MessageChannel()
|
||||
window.port = {
|
||||
globalThis.port = {
|
||||
onmessage: cb => {
|
||||
port2.onmessage = ({ type, data }) => cb({ type, data })
|
||||
},
|
||||
|
|
@ -28,7 +31,7 @@ async function portRequest (data) {
|
|||
port2.postMessage(a, b)
|
||||
}
|
||||
}
|
||||
await window.controller
|
||||
await globalThis.controller
|
||||
ipcRendererUI.emit('port', { ports: [port2] })
|
||||
ipcRendererWebTorrent.emit('port', { ports: [port1] })
|
||||
}
|
||||
|
|
@ -37,7 +40,7 @@ export const ipcRendererWebTorrent = new EventEmitter()
|
|||
|
||||
const [_platform, arch] = navigator.platform.split(' ')
|
||||
|
||||
window.version = {
|
||||
globalThis.version = {
|
||||
platform: globalThis.cordova?.platformId,
|
||||
arch,
|
||||
version: globalThis.cordova?.version
|
||||
|
|
|
|||
2
capacitor/src/main.js
Normal file
2
capacitor/src/main.js
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
import './webtorrent.js'
|
||||
import './capacitor.js'
|
||||
5
capacitor/src/support.js
Normal file
5
capacitor/src/support.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// feature support list, overriden per environment
|
||||
|
||||
export const SUPPORTS = {
|
||||
offscreenRender: false
|
||||
}
|
||||
|
|
@ -1,24 +1,5 @@
|
|||
/* globals navigationbar */
|
||||
import TorrentClient from 'common/modules/webtorrent.js'
|
||||
import { ipcRendererWebTorrent } from './ipc.js'
|
||||
import { StatusBar, Style } from '@capacitor/status-bar'
|
||||
import { SafeArea } from 'capacitor-plugin-safe-area'
|
||||
|
||||
SafeArea.addListener('safeAreaChanged', data => {
|
||||
const { insets } = data
|
||||
for (const [key, value] of Object.entries(insets)) {
|
||||
document.documentElement.style.setProperty(
|
||||
`--safe-area-${key}`,
|
||||
`${value}px`
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
StatusBar.hide()
|
||||
StatusBar.setStyle({ style: Style.Dark })
|
||||
StatusBar.setOverlaysWebView({ overlay: true })
|
||||
|
||||
navigationbar.setUp(true)
|
||||
|
||||
globalThis.chrome.runtime = { lastError: false, id: 'something' }
|
||||
|
||||
|
|
@ -33,11 +14,8 @@ const controller = (async () => {
|
|||
resolve(reg)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
if (!checkState(worker)) {
|
||||
worker.addEventListener('statechange', ({ target }) => checkState(target))
|
||||
}
|
||||
if (!checkState(worker)) worker.addEventListener('statechange', ({ target }) => checkState(target))
|
||||
})
|
||||
})()
|
||||
globalThis.controller = controller
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ const mode = process.env.NODE_ENV?.trim() || 'development'
|
|||
|
||||
/** @type {import('webpack').Configuration} */
|
||||
const capacitorConfig = {
|
||||
entry: [join(__dirname, 'src', 'webtorrent.js')],
|
||||
entry: [join(__dirname, 'src', 'main.js')],
|
||||
mode,
|
||||
plugins: [
|
||||
new webpack.ProvidePlugin({
|
||||
|
|
@ -38,6 +38,7 @@ const alias = {
|
|||
'bittorrent-dht': false,
|
||||
'webtorrent/lib/utp.cjs': false,
|
||||
'@/modules/ipc.js': join(__dirname, 'src', 'ipc.js'),
|
||||
'@/modules/support.js': join(__dirname, 'src', 'support.js'),
|
||||
net: join(__dirname, 'src', 'chrome-net.js'),
|
||||
dgram: join(__dirname, 'src', 'chrome-dgram.js'),
|
||||
http: 'stream-http',
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@
|
|||
}
|
||||
@media (min-width: 769px) {
|
||||
.page-wrapper {
|
||||
padding-left: env(safe-area-inset-left, var(--safe-area-left)) !important;
|
||||
padding-left: max(var(--safe-area-left), env(safe-area-inset-left, 0)) !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -59,4 +59,9 @@
|
|||
.navbar {
|
||||
left: unset !important
|
||||
}
|
||||
@media (pointer: none), (pointer: coarse) {
|
||||
.navbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { toTS, subRx, videoRx } from './util.js'
|
|||
import { settings } from '@/modules/settings.js'
|
||||
import { client } from '@/modules/torrent.js'
|
||||
import clipboard from './clipboard.js'
|
||||
import { SUPPORTS } from '@/modules/support.js'
|
||||
|
||||
const defaultHeader = `[Script Info]
|
||||
Title: English (US)
|
||||
|
|
@ -158,6 +159,7 @@ export default class Subtitles {
|
|||
video: this.video,
|
||||
subContent: defaultHeader,
|
||||
fonts: this.fonts,
|
||||
offscreenRender: SUPPORTS.offscreenRender,
|
||||
fallbackFont: settings.value.font?.name || 'roboto medium',
|
||||
availableFonts: {
|
||||
'roboto medium': './Roboto.ttf'
|
||||
|
|
|
|||
5
common/modules/support.js
Normal file
5
common/modules/support.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// feature support list, overriden per environment
|
||||
|
||||
export const SUPPORTS = {
|
||||
offscreenRender: true
|
||||
}
|
||||
|
|
@ -149,14 +149,14 @@ export const defaults = {
|
|||
rssQuality: '1080',
|
||||
rssFeedsNew: [['New Releases', 'SubsPlease']],
|
||||
rssAutoplay: true,
|
||||
torrentSpeed: 10,
|
||||
torrentSpeed: 5,
|
||||
torrentPersist: false,
|
||||
torrentDHT: false,
|
||||
torrentPeX: false,
|
||||
torrentPort: 0,
|
||||
dhtPort: 0,
|
||||
missingFont: true,
|
||||
maxConns: 20,
|
||||
maxConns: 50,
|
||||
subtitleLanguage: 'eng',
|
||||
audioLanguage: 'jpn',
|
||||
enableDoH: false,
|
||||
|
|
|
|||
|
|
@ -932,7 +932,7 @@
|
|||
on:loadedmetadata={autoPlay}
|
||||
on:loadedmetadata={checkAudio}
|
||||
on:loadedmetadata={clearLoadInterval}
|
||||
on:leavepictureinpicture={() => (pip = false)} />
|
||||
on:leavepictureinpicture={() => { pip = false }} />
|
||||
{#if stats}
|
||||
<div class='position-absolute top-0 bg-tp p-10 m-15 text-monospace rounded z-50'>
|
||||
<button class='close' type='button' use:click={toggleStats}><span>×</span></button>
|
||||
|
|
@ -949,10 +949,10 @@
|
|||
{/if}
|
||||
<div class='top z-40 row'>
|
||||
<div class='stats col-4 pl-20'>
|
||||
<div class='font-weight-bold overflow-hidden text-truncate'>
|
||||
<div class='font-weight-bold overflow-hidden text-truncate d-none d-md-block'>
|
||||
{#if media.title}{media.title}{/if}
|
||||
</div>
|
||||
<div class='font-weight-normal overflow-hidden text-truncate font-size-16 text-muted'>
|
||||
<div class='font-weight-normal overflow-hidden text-truncate font-size-16 text-muted d-none d-md-block'>
|
||||
{#if media.episode}Episode {media.episode}{/if}
|
||||
{#if media.episode && media.episodeTitle}{' - '}{/if}
|
||||
{#if media.episodeTitle}{media.episodeTitle}{/if}
|
||||
|
|
@ -1375,9 +1375,10 @@
|
|||
.bottom .ctrl[data-name='toggleFullscreen'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.top {
|
||||
padding-top: env(safe-area-inset-top, var(--safe-area-top)) !important;
|
||||
@media (orientation: portrait) {
|
||||
.top {
|
||||
padding-top: max(var(--safe-area-top), env(safe-area-inset-top, 0)) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,5 +8,4 @@ async function storageQuota (directory) {
|
|||
return bsize * bavail
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
window.client = new TorrentClient(ipcRenderer, storageQuota, 'node')
|
||||
globalThis.client = new TorrentClient(ipcRenderer, storageQuota, 'node')
|
||||
|
|
|
|||
|
|
@ -59,6 +59,12 @@ importers:
|
|||
'@capacitor/android':
|
||||
specifier: ^5.5.1
|
||||
version: 5.5.1(@capacitor/core@5.5.1)
|
||||
'@capacitor/app':
|
||||
specifier: ^5.0.6
|
||||
version: 5.0.6(@capacitor/core@5.5.1)
|
||||
'@capacitor/browser':
|
||||
specifier: ^5.1.0
|
||||
version: 5.1.0(@capacitor/core@5.5.1)
|
||||
'@capacitor/cli':
|
||||
specifier: ^5.5.1
|
||||
version: 5.5.1
|
||||
|
|
@ -292,6 +298,14 @@ packages:
|
|||
'@capacitor/core': 5.5.1
|
||||
dev: false
|
||||
|
||||
/@capacitor/app@5.0.6(@capacitor/core@5.5.1):
|
||||
resolution: {integrity: sha512-6ZXVdnNmaYILasC/RjQw+yfTmq2ZO7Q3v5lFcDVfq3PFGnybyYQh+RstBrYri+376OmXOXxBD7E6UxBhrMzXGA==}
|
||||
peerDependencies:
|
||||
'@capacitor/core': ^5.0.0
|
||||
dependencies:
|
||||
'@capacitor/core': 5.5.1
|
||||
dev: false
|
||||
|
||||
/@capacitor/assets@3.0.1(@types/node@20.8.7)(typescript@4.9.5):
|
||||
resolution: {integrity: sha512-VTJ3ICFuw1IoR3w6bLjpc7VC9slkNBNO4eCVFN0BAltzH04q52J//JUJ4h0F/gEd0cAKtvIcPJXH5aW6uM9JXA==}
|
||||
engines: {node: '>=10.3.0'}
|
||||
|
|
@ -318,6 +332,14 @@ packages:
|
|||
- typescript
|
||||
dev: true
|
||||
|
||||
/@capacitor/browser@5.1.0(@capacitor/core@5.5.1):
|
||||
resolution: {integrity: sha512-7togqchk2Tvq4SmLaWhcrd4x48ES/GEZsceM+29aun7WhxQEVcDU0cJsVdSU2LNFwNhWgPV2GW90etVd1B3OdQ==}
|
||||
peerDependencies:
|
||||
'@capacitor/core': ^5.0.0
|
||||
dependencies:
|
||||
'@capacitor/core': 5.5.1
|
||||
dev: false
|
||||
|
||||
/@capacitor/cli@5.5.1:
|
||||
resolution: {integrity: sha512-/oGd2IIc+k1H/fc7tUzP7vqMtZi0gNcJ4/4wUE2kzAnETxxxHXMM/2V62KfjCby/OOAzJbtI7n5OPlnWE9un1A==}
|
||||
engines: {node: '>=16.0.0'}
|
||||
|
|
|
|||
Loading…
Reference in a new issue