feat: add back log view

This commit is contained in:
Simon Chan 2021-12-09 16:01:08 +08:00
parent 4218936fa9
commit e9ef8cbbe9
5 changed files with 29 additions and 52 deletions

View file

@ -3,7 +3,7 @@ import { Adb, AdbBackend } from '@yume-chan/adb';
import AdbWebUsbBackend, { AdbWebCredentialStore, AdbWebUsbBackendWatcher } from '@yume-chan/adb-backend-webusb'; import AdbWebUsbBackend, { AdbWebCredentialStore, AdbWebUsbBackendWatcher } from '@yume-chan/adb-backend-webusb';
import AdbWsBackend from '@yume-chan/adb-backend-ws'; import AdbWsBackend from '@yume-chan/adb-backend-ws';
import { observer } from 'mobx-react-lite'; import { observer } from 'mobx-react-lite';
import { useCallback, useContext, useEffect, useMemo, useState } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react';
import { global, logger } from '../state'; import { global, logger } from '../state';
import { CommonStackTokens } from '../utils'; import { CommonStackTokens } from '../utils';
@ -92,13 +92,13 @@ function _Connect(): JSX.Element | null {
const connect = useCallback(async () => { const connect = useCallback(async () => {
try { try {
if (selectedBackend) { if (selectedBackend) {
const adb = new Adb(selectedBackend, logger.logger); const device = new Adb(selectedBackend, logger.logger);
try { try {
setConnecting(true); setConnecting(true);
await adb.connect(CredentialStore); await device.connect(CredentialStore);
global.setCurrent(adb); global.setDevice(device);
} catch (e) { } catch (e) {
adb.dispose(); device.dispose();
throw e; throw e;
} }
} }
@ -111,7 +111,7 @@ function _Connect(): JSX.Element | null {
const disconnect = useCallback(async () => { const disconnect = useCallback(async () => {
try { try {
await global.device!.dispose(); await global.device!.dispose();
global.setCurrent(undefined); global.setDevice(undefined);
} catch (e: any) { } catch (e: any) {
global.showErrorDialog(e.message); global.showErrorDialog(e.message);
} }

View file

@ -4,4 +4,4 @@ export * from './demo-mode';
export * from './device-view'; export * from './device-view';
export * from './error-dialog'; export * from './error-dialog';
export * from './external-link'; export * from './external-link';
export * from './logger'; export * from './log-view';

View file

@ -2,8 +2,9 @@ import { IconButton, IListProps, List, mergeStyles, mergeStyleSets, Stack } from
import { AdbPacketInit } from '@yume-chan/adb'; import { AdbPacketInit } from '@yume-chan/adb';
import { decodeUtf8 } from '@yume-chan/adb-backend-webusb'; import { decodeUtf8 } from '@yume-chan/adb-backend-webusb';
import { DisposableList } from '@yume-chan/event'; import { DisposableList } from '@yume-chan/event';
import { observer } from "mobx-react-lite";
import { createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'; import { createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { logger } from "../state"; import { global, logger } from "../state";
import { withDisplayName } from '../utils'; import { withDisplayName } from '../utils';
import { CommandBar } from './command-bar'; import { CommandBar } from './command-bar';
@ -44,7 +45,7 @@ function serializePacket(packet: AdbPacketInit) {
return parts.join(' '); return parts.join(' ');
} }
const LoggerLine = withDisplayName('LoggerLine')(({ packet }: { packet: [string, AdbPacketInit]; }) => { const LogLine = withDisplayName('LoggerLine')(({ packet }: { packet: [string, AdbPacketInit]; }) => {
const string = useMemo(() => serializePacket(packet[1]), [packet]); const string = useMemo(() => serializePacket(packet[1]), [packet]);
return ( return (
@ -54,43 +55,13 @@ const LoggerLine = withDisplayName('LoggerLine')(({ packet }: { packet: [string,
); );
}); });
export interface LoggerContextValue { export const ToggleLogView = observer(() => {
visible: boolean;
onVisibleChange: React.Dispatch<React.SetStateAction<boolean>>;
}
export const LoggerContext = createContext<LoggerContextValue | undefined>(undefined);
export const LoggerContextProvider = withDisplayName('LoggerContextProvider')(({ children }) => {
const [visible, setVisible] = useState(false);
const contextValue = useMemo(() => ({
visible,
onVisibleChange: setVisible,
}), [visible, setVisible]);
return (
<LoggerContext.Provider value={contextValue}>
{children}
</LoggerContext.Provider>
);
});
export const ToggleLogger = withDisplayName('ToggleLogger')(() => {
const contextValue = useContext(LoggerContext);
const handleClick = useCallback(() => {
contextValue?.onVisibleChange(value => !value);
}, [contextValue]);
if (!contextValue) {
return null;
}
return ( return (
<IconButton <IconButton
checked={contextValue.visible} checked={global.logVisible}
iconProps={{ iconName: 'ChangeEntitlements' }} iconProps={{ iconName: 'ChangeEntitlements' }}
title="Toggle Log" title="Toggle Log"
onClick={handleClick} onClick={global.toggleLog}
/> />
); );
}); });
@ -109,14 +80,13 @@ function renderCell(item?: [string, AdbPacketInit]) {
} }
return ( return (
<LoggerLine packet={item} /> <LogLine packet={item} />
); );
} }
export const Logger = withDisplayName('Logger')(({ export const LogView = observer(({
className, className,
}: LoggerProps) => { }: LoggerProps) => {
const contextValue = useContext(LoggerContext);
const [packets, setPackets] = useState<[string, AdbPacketInit][]>([]); const [packets, setPackets] = useState<[string, AdbPacketInit][]>([]);
const scrollerRef = useRef<HTMLDivElement | null>(null); const scrollerRef = useRef<HTMLDivElement | null>(null);
@ -177,7 +147,7 @@ export const Logger = withDisplayName('Logger')(({
classNames['logger-container'], classNames['logger-container'],
), [className]); ), [className]);
if (!contextValue?.visible) { if (!global.logVisible) {
return null; return null;
} }

View file

@ -3,7 +3,7 @@ import type { AppProps } from 'next/app';
import Link from 'next/link'; import Link from 'next/link';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React, { useCallback, useEffect, useState } from "react"; import React, { useCallback, useEffect, useState } from "react";
import { Connect, ErrorDialogProvider, Logger, ToggleLogger } from "../components"; import { Connect, ErrorDialogProvider, LogView, ToggleLogView } from "../components";
import '../styles/globals.css'; import '../styles/globals.css';
initializeIcons(); initializeIcons();
@ -97,7 +97,7 @@ function MyApp({ Component, pageProps }: AppProps) {
<div className={classNames.title}>WebADB Demo</div> <div className={classNames.title}>WebADB Demo</div>
</StackItem> </StackItem>
<ToggleLogger /> <ToggleLogView />
</Stack> </Stack>
<Stack grow horizontal verticalFill disableShrink styles={{ root: { minHeight: 0, overflow: 'hidden', lineHeight: '1.5' } }}> <Stack grow horizontal verticalFill disableShrink styles={{ root: { minHeight: 0, overflow: 'hidden', lineHeight: '1.5' } }}>
@ -119,9 +119,9 @@ function MyApp({ Component, pageProps }: AppProps) {
<StackItem grow styles={{ root: { width: 0 } }}> <StackItem grow styles={{ root: { width: 0 } }}>
<Component {...pageProps} /> <Component {...pageProps} />
</StackItem> </StackItem>
</Stack>
<Logger className={classNames['right-column']} /> <LogView className={classNames['right-column']} />
</Stack>
</Stack> </Stack>
</ErrorDialogProvider > </ErrorDialogProvider >
); );

View file

@ -6,16 +6,19 @@ export class GlobalState {
errorDialogVisible = false; errorDialogVisible = false;
errorDialogMessage = ''; errorDialogMessage = '';
logVisible = false;
constructor() { constructor() {
makeAutoObservable(this, { makeAutoObservable(this, {
hideErrorDialog: action.bound, hideErrorDialog: action.bound,
toggleLog: action.bound,
}); });
} }
setCurrent(device: Adb | undefined) { setDevice(device: Adb | undefined) {
this.device = device; this.device = device;
device?.onDisconnected(() => { device?.onDisconnected(() => {
this.setCurrent(undefined); this.setDevice(undefined);
}); });
} }
@ -27,6 +30,10 @@ export class GlobalState {
hideErrorDialog() { hideErrorDialog() {
this.errorDialogVisible = false; this.errorDialogVisible = false;
} }
toggleLog() {
this.logVisible = !this.logVisible;
}
} }
export const global = new GlobalState(); export const global = new GlobalState();