This commit is contained in:
pakintada@gmail.com 2024-01-23 15:04:42 +07:00
commit 9b0f111f5b
2 changed files with 151 additions and 6 deletions

View file

@ -0,0 +1,26 @@
import { create } from 'zustand'
import { createJSONStorage, persist } from 'zustand/middleware'
interface AdbStore {
deviceSerial: string
isAlreadyConnected: boolean
setDeviceSerial: (deviceSerial: string) => void
setIsAlreadyConnected: (isAlreadyConnected: boolean) => void
}
const useAdbStore = create(
persist<AdbStore>(
set => ({
deviceSerial: '',
isAlreadyConnected: false,
setDeviceSerial: deviceSerial => set({ deviceSerial }),
setIsAlreadyConnected: isAlreadyConnected => set({ isAlreadyConnected })
}),
{
name: 'adb',
storage: createJSONStorage(() => sessionStorage)
}
)
)
export default useAdbStore

View file

@ -7,11 +7,13 @@ import type { AdbScrcpyVideoStream } from '@yume-chan/adb-scrcpy'
import { AdbScrcpyClient, AdbScrcpyOptions1_22 } from '@yume-chan/adb-scrcpy'
import { WebCodecsDecoder } from '@yume-chan/scrcpy-decoder-webcodecs'
import {
AndroidMotionEventAction,
ScrcpyLogLevel1_18,
ScrcpyOptions1_25,
ScrcpyPointerId,
ScrcpyVideoCodecId
} from '@yume-chan/scrcpy'
import { useCallback, useRef, useState } from 'react'
import { useCallback, useEffect, useRef, useState } from 'react'
import {
ReadableStream,
WritableStream,
@ -19,6 +21,7 @@ import {
DecodeUtf8Stream
} from '@yume-chan/stream-extra'
import { useBeforeUnload } from 'react-router-dom'
import useAdbStore from '../hooks/adbStore'
const AndroidPage: React.FC = () => {
const { adb, manager, device, setAdb, setDevice } = useAdb(
@ -31,6 +34,60 @@ const AndroidPage: React.FC = () => {
}))
)
const {
isAlreadyConnected,
deviceSerial,
setIsAlreadyConnected,
setDeviceSerial
} = useAdbStore(
useShallow(state => ({
isAlreadyConnected: state.isAlreadyConnected,
setIsAlreadyConnected: state.setIsAlreadyConnected,
deviceSerial: state.deviceSerial,
setDeviceSerial: state.setDeviceSerial
}))
)
useEffect(() => {
if (isAlreadyConnected) {
const reconnectAdb = async () => {
const device = await manager
?.getDevices([
{
...ADB_DEFAULT_DEVICE_FILTER,
serialNumber: deviceSerial
}
])
.then(devices => devices[0])
if (!device) {
// clear state
setIsAlreadyConnected(false)
setDeviceSerial('')
return
}
const connection = await device.connect()
const credentialStore: AdbWebCredentialStore =
new AdbWebCredentialStore()
const transport = await AdbDaemonTransport.authenticate({
serial: deviceSerial,
connection: connection,
credentialStore: credentialStore
})
const adb: Adb = new Adb(transport)
setAdb(adb)
setDevice(device)
}
reconnectAdb()
}
}, [])
async function createNewConnection() {
device?.raw.forget()
setDevice(undefined)
@ -61,6 +118,9 @@ const AndroidPage: React.FC = () => {
const adb: Adb = new Adb(transport)
setAdb(adb)
setDeviceSerial(selectedDevice.serial)
setIsAlreadyConnected(true)
}
const [client, setClient] = useState<AdbScrcpyClient | undefined>()
@ -118,13 +178,69 @@ const AndroidPage: React.FC = () => {
const videoStream: AdbScrcpyVideoStream | undefined =
await _client?.videoStream
const _decoder = new WebCodecsDecoder(ScrcpyVideoCodecId.H264)
_decoder.renderer.style.maxHeight = 'inherit'
if (videoStream) {
const _decoder = new WebCodecsDecoder(ScrcpyVideoCodecId.H264)
_decoder.renderer.style.maxHeight = 'inherit'
screenRef.current?.appendChild(_decoder.renderer)
videoStream?.stream.pipeTo(_decoder.writable)
setDecoder(_decoder)
if (_client.controlMessageWriter) {
_decoder.renderer.addEventListener('mousedown', e => {
const react = _decoder.renderer.getBoundingClientRect()
const x = e.clientX - react.left
const y = e.clientY - react.top
_client.controlMessageWriter?.injectTouch({
action: AndroidMotionEventAction.Down,
pointerId: ScrcpyPointerId.Mouse,
pointerX: x,
pointerY: y,
pressure: 1,
screenWidth: _decoder.renderer.clientWidth,
screenHeight: _decoder.renderer.clientHeight,
buttons: 0,
actionButton: 0
})
})
_decoder.renderer.addEventListener('mousemove', e => {
const react = _decoder.renderer.getBoundingClientRect()
const x = e.clientX - react.left
const y = e.clientY - react.top
_client.controlMessageWriter?.injectTouch({
action: AndroidMotionEventAction.Move,
pointerId: ScrcpyPointerId.Mouse,
pointerX: x,
pointerY: y,
pressure: 1,
screenWidth: _decoder.renderer.clientWidth,
screenHeight: _decoder.renderer.clientHeight,
buttons: 0,
actionButton: 0
})
})
_decoder.renderer.addEventListener('mouseup', e => {
const react = _decoder.renderer.getBoundingClientRect()
const x = e.clientX - react.left
const y = e.clientY - react.top
_client.controlMessageWriter?.injectTouch({
action: AndroidMotionEventAction.Up,
pointerId: ScrcpyPointerId.Mouse,
pointerX: x,
pointerY: y,
pressure: 1,
screenWidth: _decoder.renderer.clientWidth,
screenHeight: _decoder.renderer.clientHeight,
buttons: 0,
actionButton: 0
})
})
}
}
screenRef.current?.appendChild(_decoder.renderer)
videoStream?.stream.pipeTo(_decoder.writable)
setDecoder(_decoder)
setClient(_client)
}
@ -133,6 +249,9 @@ const AndroidPage: React.FC = () => {
adb?.close()
setClient(undefined)
setAdb(undefined)
setIsAlreadyConnected(false)
setDeviceSerial('')
device?.raw.forget()
}
function scrcpyDisconnect() {