miru/capacitor/src/capacitor.js
ThaUnknown eeed27ffcf feat: better debug tooling, debug mode
fix: make account related buttons disabled when not signed in
fix: improve DTS exclusions
fix: softlock on navigation in androidTV
2024-08-18 10:22:15 +02:00

118 lines
3.3 KiB
JavaScript

/* globals navigationbar, PictureInPicture */
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 { LocalNotifications } from '@capacitor/local-notifications'
import { Device } from '@capacitor/device'
import IPC from './ipc.js'
IPC.on('open', url => Browser.open({ url }))
App.addListener('appUrlOpen', ({ url }) => handleProtocol(url))
let canShowNotifications = false
LocalNotifications.checkPermissions().then(async value => {
if (value) {
try {
await LocalNotifications.requestPermissions()
canShowNotifications = true
} catch (e) {
console.error(e)
}
}
})
let id = 0
IPC.on('notification', noti => {
/** @type {import('@capacitor/local-notifications').LocalNotificationSchema} */
const notification = {
title: noti.title,
body: noti.body,
id: id++,
attachments: [
{
id: '' + id++,
url: noti.icon
}
]
}
if (canShowNotifications) LocalNotifications.schedule({ notifications: [notification] })
})
IPC.on('get-device-info', async () => {
const deviceInfo = {
features: {},
info: await Device.getInfo(),
cpu: {},
ram: {}
}
IPC.emit('device-info', JSON.stringify(deviceInfo))
})
// schema: miru://key/value
const protocolMap = {
auth: token => sendToken(token),
anime: id => IPC.emit('open-anime', id),
w2g: link => IPC.emit('w2glink', link),
schedule: () => IPC.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)
IPC.emit('altoken', token)
}
}
App.getLaunchUrl().then(res => {
if (location.hash !== '#skipAlLogin') {
location.hash = '#skipAlLogin'
if (res) handleProtocol(res.url)
} else {
location.hash = ''
}
})
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
// hook into pip request, and use our own pip implementation, then instantly report exit pip
// this is more like DOM PiP, rather than video PiP
HTMLVideoElement.prototype.requestPictureInPicture = function () {
PictureInPicture.enter(this.videoWidth, this.videoHeight, success => {
this.dispatchEvent(new Event('leavepictureinpicture'))
if (success) document.querySelector('.content-wrapper').requestFullscreen()
}, err => {
this.dispatchEvent(new Event('leavepictureinpicture'))
console.error(err)
})
return Promise.resolve({})
}