Skip to content

Commit

Permalink
refactor(frontend): 動画UIのフルスクリーン周りの調整 (#14877)
Browse files Browse the repository at this point in the history
* refactor(frontend): フルスクリーン周りの調整

(cherry picked from commit 783032c)

* refactor(frontend): deviceKindの循環参照を除去

(cherry picked from commit 1ca471f)

* fix

---------

Co-authored-by: taiyme <[email protected]>
  • Loading branch information
kakkokari-gtyih and taiyme authored Nov 9, 2024
1 parent a4c5ce1 commit 3a42183
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 40 deletions.
6 changes: 5 additions & 1 deletion packages/frontend/src/boot/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { updateI18n, i18n } from '@/i18n.js';
import { $i, refreshAccount, login } from '@/account.js';
import { defaultStore, ColdDeviceStorage } from '@/store.js';
import { fetchInstance, instance } from '@/instance.js';
import { deviceKind } from '@/scripts/device-kind.js';
import { deviceKind, updateDeviceKind } from '@/scripts/device-kind.js';
import { reloadChannel } from '@/scripts/unison-reload.js';
import { getUrlWithoutLoginId } from '@/scripts/login-id.js';
import { getAccountFromId } from '@/scripts/get-account-from-id.js';
Expand Down Expand Up @@ -185,6 +185,10 @@ export async function common(createVue: () => App<Element>) {
}
});

watch(defaultStore.reactiveState.overridedDeviceKind, (kind) => {
updateDeviceKind(kind);
}, { immediate: true });

watch(defaultStore.reactiveState.useBlurEffectForModal, v => {
document.documentElement.style.setProperty('--MI-modalBgFilter', v ? 'blur(4px)' : 'none');
}, { immediate: true });
Expand Down
43 changes: 20 additions & 23 deletions packages/frontend/src/components/MkMediaVideo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ import { hms } from '@/filters/hms.js';
import { defaultStore } from '@/store.js';
import { i18n } from '@/i18n.js';
import * as os from '@/os.js';
import { isFullscreenNotSupported } from '@/scripts/device-kind.js';
import { exitFullscreen, requestFullscreen } from '@/scripts/fullscreen.js';
import hasAudio from '@/scripts/media-has-audio.js';
import MkMediaRange from '@/components/MkMediaRange.vue';
import { $i, iAmModerator } from '@/account.js';
Expand Down Expand Up @@ -334,26 +334,21 @@ function togglePlayPause() {
}

function toggleFullscreen() {
if (isFullscreenNotSupported && videoEl.value) {
if (isFullscreen.value) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
videoEl.value.webkitExitFullscreen();
isFullscreen.value = false;
} else {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
videoEl.value.webkitEnterFullscreen();
isFullscreen.value = true;
}
} else if (playerEl.value) {
if (isFullscreen.value) {
document.exitFullscreen();
isFullscreen.value = false;
} else {
playerEl.value.requestFullscreen({ navigationUI: 'hide' });
isFullscreen.value = true;
}
if (playerEl.value == null || videoEl.value == null) return;
if (isFullscreen.value) {
exitFullscreen({
videoEl: videoEl.value,
});
isFullscreen.value = false;
} else {
requestFullscreen({
videoEl: videoEl.value,
playerEl: playerEl.value,
options: {
navigationUI: 'hide',
},
});
isFullscreen.value = true;
}
}

Expand Down Expand Up @@ -454,8 +449,10 @@ watch(loop, (to) => {
});

watch(hide, (to) => {
if (to && isFullscreen.value) {
document.exitFullscreen();
if (videoEl.value && to && isFullscreen.value) {
exitFullscreen({
videoEl: videoEl.value,
});
isFullscreen.value = false;
}
});
Expand Down
24 changes: 12 additions & 12 deletions packages/frontend/src/scripts/device-kind.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import { defaultStore } from '@/store.js';

await defaultStore.ready;
export type DeviceKind = 'smartphone' | 'tablet' | 'desktop';

const ua = navigator.userAgent.toLowerCase();
const isTablet = /ipad/.test(ua) || (/mobile|iphone|android/.test(ua) && window.innerWidth > 700);
const isSmartphone = !isTablet && /mobile|iphone|android/.test(ua);

const isIPhone = /iphone|ipod/gi.test(ua) && navigator.maxTouchPoints > 1;
// navigator.platform may be deprecated but this check is still required
const isIPadOS = navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1;
const isIos = /ipad|iphone|ipod/gi.test(ua) && navigator.maxTouchPoints > 1;
export const DEFAULT_DEVICE_KIND: DeviceKind = (
isSmartphone
? 'smartphone'
: isTablet
? 'tablet'
: 'desktop'
);

export const isFullscreenNotSupported = isIPhone || isIos;
export let deviceKind: DeviceKind = DEFAULT_DEVICE_KIND;

export const deviceKind: 'smartphone' | 'tablet' | 'desktop' = defaultStore.state.overridedDeviceKind ? defaultStore.state.overridedDeviceKind
: isSmartphone ? 'smartphone'
: isTablet ? 'tablet'
: 'desktop';
export function updateDeviceKind(kind: DeviceKind | null) {
deviceKind = kind ?? DEFAULT_DEVICE_KIND;
}
46 changes: 46 additions & 0 deletions packages/frontend/src/scripts/fullscreen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/

type PartiallyPartial<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

type VideoEl = PartiallyPartial<HTMLVideoElement, 'requestFullscreen'> & {
webkitEnterFullscreen?(): void;
webkitExitFullscreen?(): void;
};

type PlayerEl = PartiallyPartial<HTMLElement, 'requestFullscreen'>;

type RequestFullscreenProps = {
readonly videoEl: VideoEl;
readonly playerEl: PlayerEl;
readonly options?: FullscreenOptions | null;
};

type ExitFullscreenProps = {
readonly videoEl: VideoEl;
};

export const requestFullscreen = ({ videoEl, playerEl, options }: RequestFullscreenProps) => {
if (playerEl.requestFullscreen != null) {
playerEl.requestFullscreen(options ?? undefined);
return;
}
if (videoEl.webkitEnterFullscreen != null) {
videoEl.webkitEnterFullscreen();
return;
}
};

export const exitFullscreen = ({ videoEl }: ExitFullscreenProps) => {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (document.exitFullscreen != null) {
document.exitFullscreen();
return;
}
if (videoEl.webkitExitFullscreen != null) {
videoEl.webkitExitFullscreen();
return;
}
};
9 changes: 5 additions & 4 deletions packages/frontend/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import * as Misskey from 'misskey-js';
import { hemisphere } from '@@/js/intl-const.js';
import lightTheme from '@@/themes/l-light.json5';
import darkTheme from '@@/themes/d-green-lime.json5';
import { miLocalStorage } from './local-storage.js';
import type { SoundType } from '@/scripts/sound.js';
import { DEFAULT_DEVICE_KIND, type DeviceKind } from '@/scripts/device-kind.js';
import { miLocalStorage } from '@/local-storage.js';
import { Storage } from '@/pizzax.js';
import type { Ast } from '@syuilo/aiscript';

Expand Down Expand Up @@ -207,7 +208,7 @@ export const defaultStore = markRaw(new Storage('base', {

overridedDeviceKind: {
where: 'device',
default: null as null | 'smartphone' | 'tablet' | 'desktop',
default: null as DeviceKind | null,
},
serverDisconnectedBehavior: {
where: 'device',
Expand Down Expand Up @@ -263,11 +264,11 @@ export const defaultStore = markRaw(new Storage('base', {
},
useBlurEffectForModal: {
where: 'device',
default: !/mobile|iphone|android/.test(navigator.userAgent.toLowerCase()), // 循環参照するのでdevice-kind.tsは参照できない
default: DEFAULT_DEVICE_KIND === 'desktop',
},
useBlurEffect: {
where: 'device',
default: !/mobile|iphone|android/.test(navigator.userAgent.toLowerCase()), // 循環参照するのでdevice-kind.tsは参照できない
default: DEFAULT_DEVICE_KIND === 'desktop',
},
showFixedPostForm: {
where: 'device',
Expand Down

0 comments on commit 3a42183

Please sign in to comment.