Fix to Android color theme
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
import { getBestThumbnail } from '$lib/images';
|
||||
import { videoLength } from '$lib/numbers';
|
||||
import { generateChapterWebVTT, type ParsedDescription } from '$lib/description';
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
import { Capacitor, SystemBars, SystemBarsStyle, SystemBarType } from '@capacitor/core';
|
||||
import { error, type Page } from '@sveltejs/kit';
|
||||
import Mousetrap from 'mousetrap';
|
||||
import { CapacitorMusicControls } from 'capacitor-music-controls-plugin';
|
||||
@@ -20,6 +20,8 @@
|
||||
invidiousInstanceStore,
|
||||
isAndroidTvStore,
|
||||
playerAlwaysLoopStore,
|
||||
playerAndroidLockOrientation,
|
||||
playerAndroidPauseOnNetworkChange,
|
||||
playerAutoPlayStore,
|
||||
playerCCByDefault,
|
||||
playerDefaultLanguage,
|
||||
@@ -59,9 +61,10 @@
|
||||
import Airplay from './settings/Airplay.svelte';
|
||||
import Pip from './settings/Pip.svelte';
|
||||
import FullscreenToggle from './settings/FullscreenToggle.svelte';
|
||||
import { AndroidPlayer } from '$lib/player/android';
|
||||
import Timeline from './Timeline.svelte';
|
||||
import TouchControls from './TouchControls.svelte';
|
||||
import { Network, type ConnectionStatus } from '@capacitor/network';
|
||||
import { ScreenOrientation, type ScreenOrientationResult } from '@capacitor/screen-orientation';
|
||||
|
||||
interface Props {
|
||||
data: { video: VideoPlay; content: ParsedDescription; playlistId: string | null };
|
||||
@@ -86,11 +89,12 @@
|
||||
let watchProgressInterval: ReturnType<typeof setInterval>;
|
||||
let showVideoRetry = $state(false);
|
||||
|
||||
let androidPlayer: AndroidPlayer;
|
||||
|
||||
let player: shaka.Player;
|
||||
let sabrAdapter: SabrStreamingAdapter | null;
|
||||
|
||||
let androidInitialNetworkStatus: ConnectionStatus | undefined;
|
||||
let androidOriginalOrigination: ScreenOrientationResult | undefined;
|
||||
|
||||
let playerContainer: HTMLElement;
|
||||
let playerCurrentPlaybackState = $state(false);
|
||||
let playerMaxKnownTime = $state(data.video.lengthSeconds);
|
||||
@@ -369,6 +373,58 @@
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
async function onAndroidFullscreenChange() {
|
||||
const videoFormats = data.video.adaptiveFormats.filter((format) =>
|
||||
format.type.startsWith('video/')
|
||||
);
|
||||
|
||||
const isFullScreen = !!document.fullscreenElement;
|
||||
|
||||
if (isFullScreen) {
|
||||
// Ensure bar color is black while in fullscreen
|
||||
await SystemBars.setStyle({ style: SystemBarsStyle.Light });
|
||||
await SystemBars.hide({
|
||||
bar: SystemBarType.NavigationBar
|
||||
});
|
||||
await SystemBars.hide({
|
||||
bar: SystemBarType.StatusBar
|
||||
});
|
||||
} else {
|
||||
await setStatusBarColor();
|
||||
}
|
||||
|
||||
if (!$playerAndroidLockOrientation) return;
|
||||
|
||||
if (isFullScreen && videoFormats[0].resolution) {
|
||||
const widthHeight = videoFormats[0].resolution.split('x');
|
||||
|
||||
if (widthHeight.length !== 2) return;
|
||||
|
||||
if (Number(widthHeight[0]) > Number(widthHeight[1])) {
|
||||
await ScreenOrientation.lock({ orientation: 'landscape' });
|
||||
} else {
|
||||
await ScreenOrientation.lock({ orientation: 'portrait' });
|
||||
}
|
||||
} else {
|
||||
await ScreenOrientation.lock({
|
||||
orientation: (androidOriginalOrigination as ScreenOrientationResult).type
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function androidHandleRotate() {
|
||||
if (
|
||||
Capacitor.getPlatform() !== 'android' ||
|
||||
data.video.adaptiveFormats.length === 0 ||
|
||||
$isAndroidTvStore
|
||||
)
|
||||
return;
|
||||
|
||||
androidOriginalOrigination = await ScreenOrientation.orientation();
|
||||
|
||||
document.addEventListener('fullscreenchange', onAndroidFullscreenChange);
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
shaka.polyfill.installAll();
|
||||
if (!shaka.Player.isBrowserSupported()) {
|
||||
@@ -417,8 +473,6 @@
|
||||
window.addEventListener('resize', updateVideoPlayerHeight);
|
||||
updateVideoPlayerHeight();
|
||||
|
||||
androidPlayer = new AndroidPlayer(data.video, playerElement);
|
||||
|
||||
await player.attach(playerElement);
|
||||
|
||||
player?.addEventListener('error', (event) => {
|
||||
@@ -454,6 +508,19 @@
|
||||
playerElement?.addEventListener('volumechange', saveVolumePreference);
|
||||
|
||||
if (Capacitor.getPlatform() === 'android') {
|
||||
await androidHandleRotate();
|
||||
|
||||
androidInitialNetworkStatus = await Network.getStatus();
|
||||
|
||||
Network.addListener('networkStatusChange', (networkStatus) => {
|
||||
if (
|
||||
androidInitialNetworkStatus?.connectionType !== networkStatus.connectionType &&
|
||||
$playerAndroidPauseOnNetworkChange
|
||||
) {
|
||||
playerElement?.pause();
|
||||
}
|
||||
});
|
||||
|
||||
await CapacitorMusicControls.create({
|
||||
track: data.video.title,
|
||||
artist: data.video.author,
|
||||
@@ -778,7 +845,16 @@
|
||||
if (Capacitor.getPlatform() === 'android') {
|
||||
await setStatusBarColor();
|
||||
await CapacitorMusicControls.destroy();
|
||||
await androidPlayer.destroy();
|
||||
|
||||
if ($isAndroidTvStore) {
|
||||
document.removeEventListener('fullscreenchange', onAndroidFullscreenChange);
|
||||
}
|
||||
|
||||
if (androidOriginalOrigination) {
|
||||
await ScreenOrientation.lock({
|
||||
orientation: androidOriginalOrigination.type
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
import type { VideoPlay } from '$lib/api/model';
|
||||
import { playerAndroidLockOrientation, playerAndroidPauseOnNetworkChange } from '$lib/store';
|
||||
import { setStatusBarColor } from '$lib/theme';
|
||||
import { get } from 'svelte/store';
|
||||
import { Capacitor, SystemBars, SystemBarsStyle, SystemBarType } from '@capacitor/core';
|
||||
import { ScreenOrientation, type ScreenOrientationResult } from '@capacitor/screen-orientation';
|
||||
import { Network, type ConnectionStatus } from '@capacitor/network';
|
||||
|
||||
export class AndroidPlayer {
|
||||
video: VideoPlay;
|
||||
originalOrigination: ScreenOrientationResult | undefined;
|
||||
initialNetworkStatus: ConnectionStatus | undefined;
|
||||
playerElement: HTMLMediaElement | undefined;
|
||||
|
||||
constructor(video: VideoPlay, playerElement: HTMLMediaElement | undefined) {
|
||||
this.video = video;
|
||||
this.playerElement = playerElement;
|
||||
|
||||
if (Capacitor.getPlatform() !== 'android') return;
|
||||
|
||||
ScreenOrientation.orientation().then((originalOrigination) => {
|
||||
this.originalOrigination = originalOrigination;
|
||||
});
|
||||
Network.getStatus().then((initialNetworkStatus) => {
|
||||
this.initialNetworkStatus = initialNetworkStatus;
|
||||
});
|
||||
|
||||
document.addEventListener('fullscreenchange', this.onFullscreenChange);
|
||||
|
||||
Network.addListener('networkStatusChange', (networkStatus) => {
|
||||
if (
|
||||
this.initialNetworkStatus?.connectionType !== networkStatus.connectionType &&
|
||||
get(playerAndroidPauseOnNetworkChange)
|
||||
) {
|
||||
this.playerElement?.pause();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async destroy() {
|
||||
if (Capacitor.getPlatform() !== 'android') return;
|
||||
|
||||
document.removeEventListener('fullscreenchange', this.onFullscreenChange);
|
||||
|
||||
if (this.originalOrigination) {
|
||||
await ScreenOrientation.lock({
|
||||
orientation: this.originalOrigination.type
|
||||
});
|
||||
}
|
||||
|
||||
await Network.removeAllListeners();
|
||||
}
|
||||
|
||||
async onFullscreenChange() {
|
||||
if (Capacitor.getPlatform() !== 'android') return;
|
||||
|
||||
const videoFormats = this.video.adaptiveFormats.filter((format) =>
|
||||
format.type.startsWith('video/')
|
||||
);
|
||||
|
||||
const isFullScreen = !!document.fullscreenElement;
|
||||
|
||||
if (isFullScreen) {
|
||||
// Ensure bar color is black while in fullscreen
|
||||
await SystemBars.setStyle({ style: SystemBarsStyle.Light });
|
||||
await SystemBars.hide({
|
||||
bar: SystemBarType.NavigationBar
|
||||
});
|
||||
await SystemBars.hide({
|
||||
bar: SystemBarType.StatusBar
|
||||
});
|
||||
} else {
|
||||
await setStatusBarColor();
|
||||
}
|
||||
|
||||
if (!get(playerAndroidLockOrientation)) return;
|
||||
|
||||
if (isFullScreen && videoFormats[0].resolution) {
|
||||
const widthHeight = videoFormats[0].resolution.split('x');
|
||||
|
||||
if (widthHeight.length !== 2) return;
|
||||
|
||||
if (Number(widthHeight[0]) > Number(widthHeight[1])) {
|
||||
await ScreenOrientation.lock({ orientation: 'landscape' });
|
||||
} else {
|
||||
await ScreenOrientation.lock({ orientation: 'portrait' });
|
||||
}
|
||||
} else {
|
||||
if (this.originalOrigination)
|
||||
await ScreenOrientation.lock({
|
||||
orientation: this.originalOrigination.type
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,20 +81,20 @@
|
||||
});
|
||||
|
||||
onMount(async () => {
|
||||
ui();
|
||||
|
||||
if (Capacitor.getPlatform() === 'android' && !$themeColorStore) {
|
||||
try {
|
||||
const colorPalette = await colorTheme.getColorPalette();
|
||||
const colorAsHex = convertToHexColorCode(colorPalette.primary);
|
||||
themeColorStore.set(colorAsHex);
|
||||
await ui('theme', colorAsHex);
|
||||
} catch {
|
||||
// Continue regardless of error
|
||||
}
|
||||
}
|
||||
await ui();
|
||||
|
||||
if (Capacitor.getPlatform() === 'android') {
|
||||
if (!$themeColorStore) {
|
||||
try {
|
||||
const colorPalette = await colorTheme.getColorPalette();
|
||||
const colorAsHex = convertToHexColorCode(colorPalette.primary);
|
||||
themeColorStore.set(colorAsHex);
|
||||
await ui('theme', colorAsHex);
|
||||
} catch {
|
||||
// Continue regardless of error
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('click', async (event: MouseEvent) => {
|
||||
// Handles opening links in browser for android.
|
||||
const link = (event.target as HTMLElement).closest('a');
|
||||
|
||||
Reference in New Issue
Block a user