147 lines
5.0 KiB
TypeScript
147 lines
5.0 KiB
TypeScript
import { invoke } from '@tauri-apps/api';
|
|
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
|
import tw, { styled } from 'twin.macro';
|
|
import { useAsync, useAsyncCallback } from 'react-async-hook';
|
|
import { DisplayWithLedStrips } from './components/display-with-led-strips';
|
|
import { PickerConfiguration } from './models/picker-configuration';
|
|
import { DisplayConfig } from './models/display-config';
|
|
import { ScreenshotDto } from './models/screenshot.dto';
|
|
import { Alert, Fab, Snackbar } from '@mui/material';
|
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
import { faRotateBack, faSpinner } from '@fortawesome/free-solid-svg-icons';
|
|
import { update } from 'ramda';
|
|
import { CompletedLedStrip } from './components/completed-led-strip';
|
|
import { LedCountProvider } from './contents/led-count';
|
|
import debug from 'debug';
|
|
import { useSnackbar } from 'notistack';
|
|
import { fillParentCss } from '../styles/fill-parent';
|
|
|
|
const logger = debug('app:configurator');
|
|
|
|
const getPickerConfig = () => invoke<PickerConfiguration>('get_picker_config');
|
|
const getScreenshotOfDisplays = () =>
|
|
invoke<ScreenshotDto[]>('take_snapshot').then((items) => {
|
|
return items;
|
|
});
|
|
const getScreenshotByConfig = async (config: DisplayConfig) => {
|
|
return await invoke<ScreenshotDto>('get_screenshot_by_config', {
|
|
config,
|
|
});
|
|
};
|
|
const writePickerConfig = async (config: PickerConfiguration) => {
|
|
return await invoke<void>('write_picker_config', {
|
|
config,
|
|
});
|
|
};
|
|
const StyledConfiguratorContainer = styled.section(
|
|
tw`flex flex-col items-stretch relative overflow-hidden`,
|
|
fillParentCss,
|
|
);
|
|
|
|
const StyledDisplayContainer = styled.section(tw`overflow-auto`);
|
|
|
|
const ConfiguratorInner: FC = () => {
|
|
const { enqueueSnackbar } = useSnackbar();
|
|
const { loading: pendingPickerConfig, result: savedPickerConfig } = useAsync(
|
|
getPickerConfig,
|
|
[],
|
|
);
|
|
|
|
const { loading: pendingScreenshotOfDisplays, result: defaultScreenshotOfDisplays } =
|
|
useAsync(getScreenshotOfDisplays, []);
|
|
|
|
const [screenshotOfDisplays, setScreenshotOfDisplays] = useState<ScreenshotDto[]>([]);
|
|
|
|
const { loading: pendingGetLedColorsByConfig, execute: onDisplayConfigChange } =
|
|
useAsyncCallback(async (value: DisplayConfig) => {
|
|
const screenshot = await getScreenshotByConfig(value);
|
|
setScreenshotOfDisplays((old) => {
|
|
const index = old.findIndex((it) => it.config.id === screenshot.config.id);
|
|
const newValue = update(index, screenshot, old);
|
|
savedPickerConfig &&
|
|
writePickerConfig({
|
|
...savedPickerConfig,
|
|
display_configs: newValue.map((it) => it.config),
|
|
});
|
|
return newValue;
|
|
});
|
|
});
|
|
|
|
const [displayConfigs, setDisplayConfigs] = useState<DisplayConfig[]>([]);
|
|
|
|
useEffect(() => {
|
|
const displayConfigs = savedPickerConfig?.display_configs;
|
|
if (displayConfigs && defaultScreenshotOfDisplays) {
|
|
setDisplayConfigs(displayConfigs);
|
|
setScreenshotOfDisplays(defaultScreenshotOfDisplays);
|
|
(async () => {
|
|
for (const config of displayConfigs) {
|
|
await onDisplayConfigChange(config);
|
|
}
|
|
})().then();
|
|
}
|
|
}, [savedPickerConfig, onDisplayConfigChange, defaultScreenshotOfDisplays]);
|
|
|
|
const resetBackToDefaultConfig = useCallback(() => {
|
|
if (defaultScreenshotOfDisplays) {
|
|
setScreenshotOfDisplays(defaultScreenshotOfDisplays);
|
|
} else {
|
|
enqueueSnackbar('Default Config was not found. please try again later.', {
|
|
variant: 'error',
|
|
});
|
|
}
|
|
}, [setScreenshotOfDisplays, defaultScreenshotOfDisplays]);
|
|
|
|
const displays = useMemo(() => {
|
|
if (screenshotOfDisplays) {
|
|
return screenshotOfDisplays.map((screenshot, index) => (
|
|
<DisplayWithLedStrips
|
|
key={index}
|
|
config={screenshot.config}
|
|
screenshot={screenshot}
|
|
onChange={(value) => onDisplayConfigChange(value)}
|
|
/>
|
|
));
|
|
}
|
|
}, [displayConfigs, screenshotOfDisplays]);
|
|
|
|
if (pendingPickerConfig || pendingScreenshotOfDisplays) {
|
|
return (
|
|
<section>
|
|
等待 {JSON.stringify({ pendingPickerConfig, pendingScreenshotOfDisplays })}
|
|
</section>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<StyledConfiguratorContainer>
|
|
<CompletedLedStrip
|
|
screenshots={screenshotOfDisplays}
|
|
onDisplayConfigChange={onDisplayConfigChange}
|
|
/>
|
|
<StyledDisplayContainer tw="overflow-y-auto">{displays}</StyledDisplayContainer>
|
|
<Fab
|
|
aria-label="reset"
|
|
size="small"
|
|
tw="top-2 right-2 absolute"
|
|
onClick={resetBackToDefaultConfig}
|
|
>
|
|
<FontAwesomeIcon icon={faRotateBack} />
|
|
</Fab>
|
|
<Snackbar open={pendingGetLedColorsByConfig} autoHideDuration={3000}>
|
|
<Alert icon={<FontAwesomeIcon icon={faSpinner} />} sx={{ width: '100%' }}>
|
|
This is a success message!
|
|
</Alert>
|
|
</Snackbar>
|
|
</StyledConfiguratorContainer>
|
|
);
|
|
};
|
|
|
|
export const Configurator = () => {
|
|
return (
|
|
<LedCountProvider>
|
|
<ConfiguratorInner />
|
|
</LedCountProvider>
|
|
);
|
|
};
|