feat(demo): allow hiding Scrcpy full screen hint

fixes #514
This commit is contained in:
Simon Chan 2023-04-02 20:50:46 +08:00
parent 4524f90aab
commit 59c470a76c
No known key found for this signature in database
GPG key ID: A8B69F750B9BCEDD
6 changed files with 146 additions and 9 deletions

View file

@ -0,0 +1,40 @@
import { useEffect } from "react";
type CommonEventMaps<T> = T extends typeof globalThis
? WindowEventMap
: T extends Window
? WindowEventMap
: T extends Document
? DocumentEventMap
: T extends HTMLElement
? HTMLElementEventMap
: T extends SVGElement
? SVGElementEventMap
: { [type: string]: unknown };
const useClientAddEventListener = <
T extends EventTarget,
U extends keyof CommonEventMaps<T>
>(
target: T | (() => T),
type: U,
listener: (this: T, ev: CommonEventMaps<T>[U]) => any,
options?: AddEventListenerOptions,
deps?: readonly unknown[]
) => {
useEffect(() => {
const targetValue = typeof target === "function" ? target() : target;
targetValue.addEventListener(type as any, listener as any, options);
return () =>
targetValue.removeEventListener(
type as any,
listener as any,
options
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, deps);
};
export const useAddEventListener =
typeof window !== "undefined" ? useClientAddEventListener : () => {};

View file

@ -0,0 +1,4 @@
export * from "./add-event-listener";
export * from "./layout-effect";
export * from "./local-storage";
export * from "./stable-callback";

View file

@ -0,0 +1,4 @@
import { useLayoutEffect as useReactLayoutEffect } from "react";
export const useLayoutEffect =
typeof window !== "undefined" ? useReactLayoutEffect : () => {};

View file

@ -0,0 +1,34 @@
import { useState } from "react";
import { useAddEventListener } from "./add-event-listener";
import { useStableCallback } from "./stable-callback";
function useClientLocalStorage<T extends string = string>(
key: string,
fallbackValue: T
) {
const [value, setValue] = useState<T>(
() => (localStorage.getItem(key) as T) || fallbackValue
);
useAddEventListener(
globalThis,
"storage",
() =>
setValue((localStorage.getItem(key) as T | null) ?? fallbackValue),
{ passive: true },
[key, fallbackValue]
);
const handleChange = useStableCallback((value: T) => {
setValue(value);
localStorage.setItem(key, value);
});
return [value, handleChange] as const;
}
export const useLocalStorage: typeof useClientLocalStorage =
typeof localStorage !== "undefined"
? useClientLocalStorage
: (key, fallbackValue) => [fallbackValue, () => {}];

View file

@ -0,0 +1,35 @@
import { MutableRefObject, useRef } from "react";
import { useLayoutEffect } from "./layout-effect";
const UNINITIALIZED = Symbol("UNINITIALIZED");
export function useConstLazy<T>(initializer: () => T): T {
const ref = useRef<T | typeof UNINITIALIZED>(UNINITIALIZED);
if (ref.current === UNINITIALIZED) {
ref.current = initializer();
}
return ref.current;
}
export function useConst<T>(value: T): T {
const ref = useRef(value);
return ref.current;
}
export function useLatestRef<T>(value: T): MutableRefObject<T> {
const ref = useRef(value);
useLayoutEffect(() => {
ref.current = value;
}, [value]);
return ref;
}
export function useStableCallback<T extends (...args: any[]) => void>(
callback: T
): T {
const callbackRef = useLatestRef(callback);
return useConst(function (...args) {
return callbackRef.current(...args);
} as T);
}

View file

@ -1,4 +1,10 @@
import { Dialog, LayerHost, ProgressIndicator, Stack } from "@fluentui/react";
import {
Dialog,
LayerHost,
Link,
ProgressIndicator,
Stack,
} from "@fluentui/react";
import { useId } from "@fluentui/react-hooks";
import { makeStyles, shorthands } from "@griffel/react";
import { WebCodecsDecoder } from "@yume-chan/scrcpy-decoder-webcodecs";
@ -17,6 +23,7 @@ import {
SettingItem,
VideoContainer,
} from "../components/scrcpy";
import { useLocalStorage } from "../hooks";
import { GLOBAL_STATE } from "../state";
import { CommonStackTokens, RouteStackProps, formatSpeed } from "../utils";
@ -176,6 +183,11 @@ const Scrcpy: NextPage = () => {
};
}, []);
const [hintHidden, setHintHidden] = useLocalStorage<`${boolean}`>(
"scrcpy-hint-hidden",
"false"
);
useEffect(() => {
window.addEventListener("blur", handleBlur);
@ -200,14 +212,22 @@ const Scrcpy: NextPage = () => {
onKeyDown={handleKeyEvent}
onKeyUp={handleKeyEvent}
>
{keyboardLockEnabled && STATE.isFullScreen && (
{keyboardLockEnabled &&
hintHidden !== "true" &&
STATE.isFullScreen && (
<div className={classes.fullScreenStatusBar}>
<div>{GLOBAL_STATE.backend?.serial}</div>
<div>FPS: {STATE.fps}</div>
<div className={classes.spacer} />
<div>Press and hold ESC to exit full screen</div>
<div>
Press and hold ESC to exit full screen
</div>
<Link onClick={() => setHintHidden("true")}>
{`Don't show again`}
</Link>
</div>
)}
<DeviceView