Skip to content

Commit

Permalink
feat(scrcpy): support Scrcpy 1.25
Browse files Browse the repository at this point in the history
  • Loading branch information
yume-chan committed Dec 22, 2022
1 parent aa033e4 commit a066bb4
Show file tree
Hide file tree
Showing 31 changed files with 1,781 additions and 1,105 deletions.
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,13 @@
"eslint.workingDirectories": [
"libraries/*",
],
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
14 changes: 7 additions & 7 deletions apps/demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
"version": "0.1.0",
"private": true,
"scripts": {
"postinstall": "fetch-scrcpy-server 1.24",
"postinstall": "fetch-scrcpy-server 1.25",
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@fluentui/react": "^8.103.10",
"@fluentui/react": "^8.104.0",
"@fluentui/react-file-type-icons": "^8.8.4",
"@fluentui/react-hooks": "^8.6.14",
"@fluentui/react-icons": "^2.0.190",
Expand All @@ -33,20 +33,20 @@
"@yume-chan/struct": "workspace:^0.0.17",
"mobx": "^6.7.0",
"mobx-react-lite": "^3.4.0",
"next": "13.0.7",
"next": "13.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"xterm": "^5.1.0",
"xterm-addon-fit": "^0.6.0",
"xterm-addon-search": "^0.10.0",
"xterm-addon-fit": "^0.7.0",
"xterm-addon-search": "^0.11.0",
"xterm-addon-webgl": "^0.14.0"
},
"devDependencies": {
"@mdx-js/loader": "^2.2.1",
"@next/mdx": "^13.0.7",
"@next/mdx": "^13.1.0",
"@types/react": "18.0.26",
"eslint": "^8.30.0",
"eslint-config-next": "13.0.7",
"eslint-config-next": "13.1.0",
"source-map-loader": "^4.0.1",
"typescript": "^4.9.4"
}
Expand Down
243 changes: 135 additions & 108 deletions apps/demo/src/components/device-view.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
import { mergeStyleSets, StackItem } from '@fluentui/react';
import { ComponentType, CSSProperties, ReactNode, useImperativeHandle, useMemo, useRef, useState } from 'react';
import { forwardRef } from '../utils/with-display-name';
import { ResizeObserver, Size } from './resize-observer';
import { StackItem } from "@fluentui/react";
import { makeStyles } from "@griffel/react";
import {
CSSProperties,
ComponentType,
ReactNode,
useImperativeHandle,
useMemo,
useRef,
useState,
} from "react";
import { forwardRef } from "../utils/with-display-name";
import { ResizeObserver, Size } from "./resize-observer";

export interface DeviceViewProps {
width: number;

height: number;

BottomElement?: ComponentType<{ className: string, style: CSSProperties, children: ReactNode; }>;
BottomElement?: ComponentType<{
className: string;
style: CSSProperties;
children: ReactNode;
}>;

children?: ReactNode;
}
Expand All @@ -17,114 +30,128 @@ export interface DeviceViewRef {
enterFullscreen(): void;
}

export const DeviceView = forwardRef<DeviceViewRef>('DeviceView')(({
width,
height,
BottomElement,
children,
}: DeviceViewProps, ref) => {
const styles = mergeStyleSets({
outer: {
width: '100%',
height: '100%',
backgroundColor: 'black',
},
inner: {
position: 'absolute',
transformOrigin: 'top left',
},
bottom: {
position: 'absolute',
},
});

const [containerSize, setContainerSize] = useState<Size>({ width: 0, height: 0 });
const [bottomSize, setBottomSize] = useState<Size>({ width: 0, height: 0 });

// Container size minus bottom element size
const usableSize = useMemo(() => ({
width: containerSize.width,
height: containerSize.height - bottomSize.height,
}), [containerSize, bottomSize]);

// Compute sizes after scaling
const childrenStyle = useMemo(() => {
let scale: number;
let childrenWidth: number;
let childrenHeight: number;
let childrenTop: number;
let childrenLeft: number;

if (width === 0 || usableSize.width === 0) {
scale = 1;
childrenWidth = 0;
childrenHeight = 0;
childrenTop = 0;
childrenLeft = 0;
} else {
const videoRatio = width / height;
const containerRatio = usableSize.width / usableSize.height;

if (videoRatio > containerRatio) {
scale = usableSize.width / width;
childrenWidth = usableSize.width;
childrenHeight = height * scale;
childrenTop = (usableSize.height - childrenHeight) / 2;
const useClasses = makeStyles({
outer: {
width: "100%",
height: "100%",
backgroundColor: "black",
},
inner: {
position: "absolute",
transformOrigin: "top left",
},
bottom: {
position: "absolute",
},
});

export const DeviceView = forwardRef<DeviceViewRef>("DeviceView")(
({ width, height, BottomElement, children }: DeviceViewProps, ref) => {
const classes = useClasses();

const [containerSize, setContainerSize] = useState<Size>({
width: 0,
height: 0,
});
const [bottomSize, setBottomSize] = useState<Size>({
width: 0,
height: 0,
});

// Container size minus bottom element size
const usableSize = useMemo(
() => ({
width: containerSize.width,
height: containerSize.height - bottomSize.height,
}),
[containerSize, bottomSize]
);

// Compute sizes after scaling
const childrenStyle = useMemo(() => {
let scale: number;
let childrenWidth: number;
let childrenHeight: number;
let childrenTop: number;
let childrenLeft: number;

if (width === 0 || usableSize.width === 0) {
scale = 1;
childrenWidth = 0;
childrenHeight = 0;
childrenTop = 0;
childrenLeft = 0;
} else {
scale = usableSize.height / height;
childrenWidth = width * scale;
childrenHeight = usableSize.height;
childrenTop = 0;
childrenLeft = (usableSize.width - childrenWidth) / 2;
const videoRatio = width / height;
const containerRatio = usableSize.width / usableSize.height;

if (videoRatio > containerRatio) {
scale = usableSize.width / width;
childrenWidth = usableSize.width;
childrenHeight = height * scale;
childrenTop = (usableSize.height - childrenHeight) / 2;
childrenLeft = 0;
} else {
scale = usableSize.height / height;
childrenWidth = width * scale;
childrenHeight = usableSize.height;
childrenTop = 0;
childrenLeft = (usableSize.width - childrenWidth) / 2;
}
}
}

return {
scale,
width: childrenWidth,
height: childrenHeight,
top: childrenTop,
left: childrenLeft,
};
}, [width, height, usableSize]);

const containerRef = useRef<HTMLDivElement | null>(null);
useImperativeHandle(ref, () => ({
enterFullscreen() { containerRef.current!.requestFullscreen(); },
}), []);

return (
<StackItem grow styles={{ root: { position: 'relative' } }}>
<div ref={containerRef} className={styles.outer}>
<ResizeObserver onResize={setContainerSize} />

<div
className={styles.inner}
style={{
top: childrenStyle.top,
left: childrenStyle.left,
width,
height,
transform: `scale(${childrenStyle.scale})`,
}}
>
{children}
</div>

{(!!width && !!BottomElement) && (
<BottomElement
className={styles.bottom}
return {
scale,
width: childrenWidth,
height: childrenHeight,
top: childrenTop,
left: childrenLeft,
};
}, [width, height, usableSize]);

const containerRef = useRef<HTMLDivElement | null>(null);
useImperativeHandle(
ref,
() => ({
enterFullscreen() {
containerRef.current!.requestFullscreen();
},
}),
[]
);

return (
<StackItem grow styles={{ root: { position: "relative" } }}>
<div ref={containerRef} className={classes.outer}>
<ResizeObserver onResize={setContainerSize} />

<div
className={classes.inner}
style={{
top: childrenStyle.top + childrenStyle.height,
top: childrenStyle.top,
left: childrenStyle.left,
width: childrenStyle.width,
width,
height,
transform: `scale(${childrenStyle.scale})`,
}}
>
<ResizeObserver onResize={setBottomSize} />
</BottomElement>
)}
</div>
</StackItem >
);
});
{children}
</div>

{!!width && !!BottomElement && (
<BottomElement
className={classes.bottom}
style={{
top: childrenStyle.top + childrenStyle.height,
left: childrenStyle.left,
width: childrenStyle.width,
}}
>
<ResizeObserver onResize={setBottomSize} />
</BottomElement>
)}
</div>
</StackItem>
);
}
);
Loading

0 comments on commit a066bb4

Please sign in to comment.