feature/gui-configuration:支持从 GUI 配置程序。 #4
14
package.json
14
package.json
@ -16,9 +16,10 @@
|
|||||||
"@fortawesome/free-regular-svg-icons": "^6.2.1",
|
"@fortawesome/free-regular-svg-icons": "^6.2.1",
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
||||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
"@mui/material": "^5.11.2",
|
"@mui/material": "^5.11.4",
|
||||||
"@tauri-apps/api": "^1.2.0",
|
"@tauri-apps/api": "^1.2.0",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
|
"debug": "^4.3.4",
|
||||||
"ramda": "^0.28.0",
|
"ramda": "^0.28.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-async-hook": "^4.0.0",
|
"react-async-hook": "^4.0.0",
|
||||||
@ -29,6 +30,7 @@
|
|||||||
"@emotion/babel-plugin-jsx-pragmatic": "^0.2.0",
|
"@emotion/babel-plugin-jsx-pragmatic": "^0.2.0",
|
||||||
"@emotion/serialize": "^1.1.1",
|
"@emotion/serialize": "^1.1.1",
|
||||||
"@tauri-apps/cli": "^1.2.2",
|
"@tauri-apps/cli": "^1.2.2",
|
||||||
|
"@types/debug": "^4.1.7",
|
||||||
"@types/node": "^18.11.18",
|
"@types/node": "^18.11.18",
|
||||||
"@types/ramda": "^0.28.20",
|
"@types/ramda": "^0.28.20",
|
||||||
"@types/react": "^18.0.26",
|
"@types/react": "^18.0.26",
|
||||||
@ -36,13 +38,13 @@
|
|||||||
"@vitejs/plugin-react": "^2.2.0",
|
"@vitejs/plugin-react": "^2.2.0",
|
||||||
"autoprefixer": "^10.4.13",
|
"autoprefixer": "^10.4.13",
|
||||||
"babel-plugin-macros": "^3.1.0",
|
"babel-plugin-macros": "^3.1.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-import": "^2.26.0",
|
"eslint-plugin-import": "^2.27.4",
|
||||||
"eslint-plugin-jsx-a11y": "^6.6.1",
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
"eslint-plugin-simple-import-sort": "^8.0.0",
|
"eslint-plugin-simple-import-sort": "^8.0.0",
|
||||||
"postcss": "^8.4.20",
|
"postcss": "^8.4.21",
|
||||||
"prettier": "^2.8.1",
|
"prettier": "^2.8.3",
|
||||||
"tailwindcss": "^3.2.4",
|
"tailwindcss": "^3.2.4",
|
||||||
"twin.macro": "^3.1.0",
|
"twin.macro": "^3.1.0",
|
||||||
"typescript": "^4.9.4",
|
"typescript": "^4.9.4",
|
||||||
|
490
pnpm-lock.yaml
generated
490
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,13 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
|
||||||
|
pub struct LedStripConfigOfBorders {
|
||||||
|
pub top: Option<LedStripConfig>,
|
||||||
|
pub bottom: Option<LedStripConfig>,
|
||||||
|
pub left: Option<LedStripConfig>,
|
||||||
|
pub right: Option<LedStripConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
|
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
|
||||||
pub struct LedStripConfig {
|
pub struct LedStripConfig {
|
||||||
pub index: usize,
|
pub index: usize,
|
||||||
@ -13,23 +21,33 @@ pub struct DisplayConfig {
|
|||||||
pub index_of_display: usize,
|
pub index_of_display: usize,
|
||||||
pub display_width: usize,
|
pub display_width: usize,
|
||||||
pub display_height: usize,
|
pub display_height: usize,
|
||||||
pub top_led_strip: Option<LedStripConfig>,
|
pub led_strip_of_borders: LedStripConfigOfBorders,
|
||||||
pub bottom_led_strip: Option<LedStripConfig>,
|
}
|
||||||
pub left_led_strip: Option<LedStripConfig>,
|
|
||||||
pub right_led_strip: Option<LedStripConfig>,
|
impl LedStripConfigOfBorders {
|
||||||
|
pub fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
top: None,
|
||||||
|
bottom: None,
|
||||||
|
left: None,
|
||||||
|
right: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DisplayConfig {
|
impl DisplayConfig {
|
||||||
pub fn default(id: usize, index_of_display: usize, display_width: usize, display_height: usize) -> Self {
|
pub fn default(
|
||||||
|
id: usize,
|
||||||
|
index_of_display: usize,
|
||||||
|
display_width: usize,
|
||||||
|
display_height: usize,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
index_of_display,
|
index_of_display,
|
||||||
display_width,
|
display_width,
|
||||||
display_height,
|
display_height,
|
||||||
top_led_strip: None,
|
led_strip_of_borders: LedStripConfigOfBorders::default(),
|
||||||
bottom_led_strip: None,
|
|
||||||
left_led_strip: None,
|
|
||||||
right_led_strip: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ impl Screenshot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_sample_points(config: DisplayConfig) -> ScreenSamplePoints {
|
fn get_sample_points(config: DisplayConfig) -> ScreenSamplePoints {
|
||||||
let top = match config.top_led_strip {
|
let top = match config.led_strip_of_borders.top {
|
||||||
Some(led_strip_config) => Self::get_one_edge_sample_points(
|
Some(led_strip_config) => Self::get_one_edge_sample_points(
|
||||||
config.display_height / 8,
|
config.display_height / 8,
|
||||||
config.display_width,
|
config.display_width,
|
||||||
@ -48,7 +48,7 @@ impl Screenshot {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let bottom: Vec<LedSamplePoints> = match config.bottom_led_strip {
|
let bottom: Vec<LedSamplePoints> = match config.led_strip_of_borders.bottom {
|
||||||
Some(led_strip_config) => {
|
Some(led_strip_config) => {
|
||||||
let points = Self::get_one_edge_sample_points(
|
let points = Self::get_one_edge_sample_points(
|
||||||
config.display_height / 9,
|
config.display_height / 9,
|
||||||
@ -73,7 +73,7 @@ impl Screenshot {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let left: Vec<LedSamplePoints> = match config.left_led_strip {
|
let left: Vec<LedSamplePoints> = match config.led_strip_of_borders.left {
|
||||||
Some(led_strip_config) => {
|
Some(led_strip_config) => {
|
||||||
let points = Self::get_one_edge_sample_points(
|
let points = Self::get_one_edge_sample_points(
|
||||||
config.display_width / 16,
|
config.display_width / 16,
|
||||||
@ -95,7 +95,7 @@ impl Screenshot {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let right: Vec<LedSamplePoints> = match config.right_led_strip {
|
let right: Vec<LedSamplePoints> = match config.led_strip_of_borders.right {
|
||||||
Some(led_strip_config) => {
|
Some(led_strip_config) => {
|
||||||
let points = Self::get_one_edge_sample_points(
|
let points = Self::get_one_edge_sample_points(
|
||||||
config.display_width / 16,
|
config.display_width / 16,
|
||||||
@ -217,13 +217,13 @@ impl Screenshot {
|
|||||||
|
|
||||||
pub fn get_top_of_led_start_at(&self) -> usize {
|
pub fn get_top_of_led_start_at(&self) -> usize {
|
||||||
self.config
|
self.config
|
||||||
.top_led_strip
|
.led_strip_of_borders.top
|
||||||
.and_then(|c| Some(c.global_start_position))
|
.and_then(|c| Some(c.global_start_position))
|
||||||
.unwrap_or(0)
|
.unwrap_or(0)
|
||||||
}
|
}
|
||||||
pub fn get_top_of_led_end_at(&self) -> usize {
|
pub fn get_top_of_led_end_at(&self) -> usize {
|
||||||
self.config
|
self.config
|
||||||
.top_led_strip
|
.led_strip_of_borders.top
|
||||||
.and_then(|c| Some(c.global_end_position))
|
.and_then(|c| Some(c.global_end_position))
|
||||||
.unwrap_or(0)
|
.unwrap_or(0)
|
||||||
}
|
}
|
||||||
|
93
src/configurator/components/completed-led-strip.tsx
Normal file
93
src/configurator/components/completed-led-strip.tsx
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import { isNil, splitEvery } from 'ramda';
|
||||||
|
import { FC, useMemo } from 'react';
|
||||||
|
import tw, { css, styled } from 'twin.macro';
|
||||||
|
import { borders } from '../../constants/border';
|
||||||
|
import { DisplayConfig } from '../models/display-config';
|
||||||
|
import { LedStripConfig } from '../models/led-strip-config';
|
||||||
|
import { ScreenshotDto } from '../models/screenshot.dto';
|
||||||
|
import { LedStrip } from './led-strip';
|
||||||
|
import { StyledPixel } from './styled-pixel';
|
||||||
|
|
||||||
|
interface CompletedLedStripProps {
|
||||||
|
screenshots: ScreenshotDto[];
|
||||||
|
onDisplayConfigChange?: (value: DisplayConfig) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
type BorderLedStrip = {
|
||||||
|
pixels: [number, number, number][];
|
||||||
|
config: LedStripConfig | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StyledContainer = styled.section(
|
||||||
|
({ rows, columns }: { rows: number; columns: number }) => [
|
||||||
|
tw`grid m-4 pb-2`,
|
||||||
|
css`
|
||||||
|
grid-template-columns: repeat(${columns}, 1fr);
|
||||||
|
grid-template-rows: auto repeat(${rows}, 1fr);
|
||||||
|
`,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
const StyledCompletedContainer = styled.section(
|
||||||
|
tw`dark:bg-transparent shadow-xl border-gray-500 border rounded-full flex flex-wrap justify-around items-center mb-2`,
|
||||||
|
css`
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
export const CompletedLedStrip: FC<CompletedLedStripProps> = ({
|
||||||
|
screenshots,
|
||||||
|
onDisplayConfigChange,
|
||||||
|
}) => {
|
||||||
|
const borderLedStrips: BorderLedStrip[] = useMemo(() => {
|
||||||
|
return screenshots.flatMap((ss) =>
|
||||||
|
borders.map((b) => ({
|
||||||
|
pixels: splitEvery(3, Array.from(ss.colors[b])) as [number, number, number][],
|
||||||
|
config: ss.config.led_strip_of_borders[b],
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
}, [screenshots]);
|
||||||
|
const ledCount = useMemo(
|
||||||
|
() => borderLedStrips.reduce((prev, curr) => prev + curr.pixels.length, 0),
|
||||||
|
[borderLedStrips],
|
||||||
|
);
|
||||||
|
|
||||||
|
const completedPixels = useMemo(() => {
|
||||||
|
const completed: [number, number, number][] = new Array(ledCount).fill([0, 0, 0]);
|
||||||
|
borderLedStrips.forEach(({ pixels, config }) => {
|
||||||
|
if (isNil(config)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (config.global_start_position <= config.global_end_position) {
|
||||||
|
pixels.forEach((color, i) => {
|
||||||
|
completed[config.global_start_position + i] = color;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
pixels.forEach((color, i) => {
|
||||||
|
completed[config.global_start_position - i] = color;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return completed.map((color) => <StyledPixel rgb={color} />);
|
||||||
|
}, [ledCount, borderLedStrips]);
|
||||||
|
|
||||||
|
const strips = useMemo(() => {
|
||||||
|
return borderLedStrips.map(({ config, pixels }, index) => (
|
||||||
|
<LedStrip
|
||||||
|
key={index}
|
||||||
|
colors={Uint8Array.from(pixels.flat())}
|
||||||
|
config={config}
|
||||||
|
css={css`
|
||||||
|
grid-column-start: ${(config?.global_start_position ?? 0) + 1};
|
||||||
|
grid-column-end: ${(config?.global_end_position ?? 0) + 1};
|
||||||
|
`}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
}, [borderLedStrips]);
|
||||||
|
return (
|
||||||
|
<StyledContainer rows={screenshots.length * borders.length} columns={ledCount}>
|
||||||
|
<StyledCompletedContainer>{completedPixels}</StyledCompletedContainer>
|
||||||
|
{strips}
|
||||||
|
</StyledContainer>
|
||||||
|
);
|
||||||
|
};
|
@ -1,11 +1,15 @@
|
|||||||
import { HTMLAttributes, useCallback, useMemo } from 'react';
|
import { HTMLAttributes, useCallback, useMemo } from 'react';
|
||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { DisplayConfig } from '../models/display-config';
|
import { DisplayConfig, LedStripConfigOfBorders } from '../models/display-config';
|
||||||
import { LedStrip } from './led-strip';
|
import { LedStrip } from './led-strip';
|
||||||
import tw, { css, styled, theme } from 'twin.macro';
|
import tw, { css, styled, theme } from 'twin.macro';
|
||||||
import { ScreenshotDto } from '../models/screenshot.dto';
|
import { ScreenshotDto } from '../models/screenshot.dto';
|
||||||
import { LedStripEditor } from './led-strip-editor';
|
import { LedStripEditor } from './led-strip-editor';
|
||||||
import { LedStripConfig } from '../models/led-strip-config';
|
import { LedStripConfig } from '../models/led-strip-config';
|
||||||
|
import debug from 'debug';
|
||||||
|
import { lensPath, lensProp, set, view } from 'ramda';
|
||||||
|
|
||||||
|
const logger = debug('app:display-with-led-strips');
|
||||||
|
|
||||||
export interface DisplayWithLedStripsProps
|
export interface DisplayWithLedStripsProps
|
||||||
extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {
|
extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {
|
||||||
@ -36,61 +40,60 @@ export const DisplayWithLedStrips: FC<DisplayWithLedStripsProps> = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const onLedStripConfigChange = useCallback(
|
const onLedStripConfigChange = useCallback(
|
||||||
(
|
(position: keyof LedStripConfigOfBorders, value: LedStripConfig | null) => {
|
||||||
position:
|
const xLens = lensPath<
|
||||||
| 'top_led_strip'
|
DisplayConfig,
|
||||||
| 'left_led_strip'
|
'led_strip_of_borders',
|
||||||
| 'right_led_strip'
|
keyof LedStripConfigOfBorders
|
||||||
| 'bottom_led_strip',
|
>(['led_strip_of_borders', position]);
|
||||||
value: LedStripConfig | null,
|
const c = set(xLens, value, config);
|
||||||
) => {
|
logger('on change. prev: %o, curr: %o', view(xLens, config), value);
|
||||||
const c = { ...config, [position]: value };
|
|
||||||
onChange?.(c);
|
onChange?.(c);
|
||||||
},
|
},
|
||||||
[config],
|
[config],
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<StyledContainer {...htmlAttrs}>
|
<StyledContainer {...htmlAttrs}>
|
||||||
<img src={screenshotUrl} tw="row-start-3 col-start-3" />
|
<img src={screenshotUrl} tw="row-start-3 col-start-3 w-full" />
|
||||||
<LedStrip
|
<LedStrip
|
||||||
config={config.top_led_strip}
|
config={config.led_strip_of_borders.top}
|
||||||
colors={screenshot.colors.top}
|
colors={screenshot.colors.top}
|
||||||
tw="row-start-2 col-start-3"
|
tw="row-start-2 col-start-3"
|
||||||
/>
|
/>
|
||||||
<LedStrip
|
<LedStrip
|
||||||
config={config.left_led_strip}
|
config={config.led_strip_of_borders.left}
|
||||||
colors={screenshot.colors.left}
|
colors={screenshot.colors.left}
|
||||||
tw="row-start-3 col-start-2"
|
tw="row-start-3 col-start-2"
|
||||||
/>
|
/>
|
||||||
<LedStrip
|
<LedStrip
|
||||||
config={config.right_led_strip}
|
config={config.led_strip_of_borders.right}
|
||||||
colors={screenshot.colors.right}
|
colors={screenshot.colors.right}
|
||||||
tw="row-start-3 col-start-4"
|
tw="row-start-3 col-start-4"
|
||||||
/>
|
/>
|
||||||
<LedStrip
|
<LedStrip
|
||||||
config={config.bottom_led_strip}
|
config={config.led_strip_of_borders.bottom}
|
||||||
colors={screenshot.colors.bottom}
|
colors={screenshot.colors.bottom}
|
||||||
tw="row-start-4 col-start-3"
|
tw="row-start-4 col-start-3"
|
||||||
/>
|
/>
|
||||||
<LedStripEditor
|
<LedStripEditor
|
||||||
config={config.top_led_strip}
|
config={config.led_strip_of_borders.top}
|
||||||
tw="row-start-1 col-start-3"
|
tw="row-start-1 col-start-3"
|
||||||
onChange={(value) => onLedStripConfigChange('top_led_strip', value)}
|
onChange={(value) => onLedStripConfigChange('top', value)}
|
||||||
/>
|
/>
|
||||||
<LedStripEditor
|
<LedStripEditor
|
||||||
config={config.left_led_strip}
|
config={config.led_strip_of_borders.left}
|
||||||
tw="row-start-3 col-start-1"
|
tw="row-start-3 col-start-1"
|
||||||
onChange={(value) => onLedStripConfigChange('left_led_strip', value)}
|
onChange={(value) => onLedStripConfigChange('left', value)}
|
||||||
/>
|
/>
|
||||||
<LedStripEditor
|
<LedStripEditor
|
||||||
config={config.right_led_strip}
|
config={config.led_strip_of_borders.right}
|
||||||
tw="row-start-3 col-start-5"
|
tw="row-start-3 col-start-5"
|
||||||
onChange={(value) => onLedStripConfigChange('right_led_strip', value)}
|
onChange={(value) => onLedStripConfigChange('right', value)}
|
||||||
/>
|
/>
|
||||||
<LedStripEditor
|
<LedStripEditor
|
||||||
config={config.bottom_led_strip}
|
config={config.led_strip_of_borders.bottom}
|
||||||
tw="row-start-5 col-start-3"
|
tw="row-start-5 col-start-3"
|
||||||
onChange={(value) => onLedStripConfigChange('bottom_led_strip', value)}
|
onChange={(value) => onLedStripConfigChange('bottom', value)}
|
||||||
/>
|
/>
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
|
@ -3,6 +3,7 @@ import { FC } from 'react';
|
|||||||
import { LedStripConfig } from '../models/led-strip-config';
|
import { LedStripConfig } from '../models/led-strip-config';
|
||||||
import tw, { css, styled } from 'twin.macro';
|
import tw, { css, styled } from 'twin.macro';
|
||||||
import { splitEvery } from 'ramda';
|
import { splitEvery } from 'ramda';
|
||||||
|
import { StyledPixel } from './styled-pixel';
|
||||||
|
|
||||||
export interface LedStripProps extends HTMLAttributes<HTMLElement> {
|
export interface LedStripProps extends HTMLAttributes<HTMLElement> {
|
||||||
config: LedStripConfig | null;
|
config: LedStripConfig | null;
|
||||||
@ -10,19 +11,10 @@ export interface LedStripProps extends HTMLAttributes<HTMLElement> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const StyledContainer = styled.section(
|
const StyledContainer = styled.section(
|
||||||
tw`dark:bg-transparent shadow-xl border-gray-500 border rounded-full flex flex-wrap justify-around items-center`,
|
tw`dark:bg-transparent shadow-xl border-gray-500 border rounded-full flex flex-wrap justify-around items-center -mx-px -mt-px`,
|
||||||
css``,
|
css``,
|
||||||
);
|
);
|
||||||
|
|
||||||
const StyledPixel = styled.span(
|
|
||||||
({ rgb: [r, g, b] }: { rgb: [number, number, number] }) => [
|
|
||||||
tw`rounded-full h-3 w-3 bg-current block border border-gray-700`,
|
|
||||||
css`
|
|
||||||
color: rgb(${r}, ${g}, ${b});
|
|
||||||
`,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
export const LedStrip: FC<LedStripProps> = ({ config, colors, ...htmlAttrs }) => {
|
export const LedStrip: FC<LedStripProps> = ({ config, colors, ...htmlAttrs }) => {
|
||||||
const pixels = useMemo(() => {
|
const pixels = useMemo(() => {
|
||||||
const pixels = splitEvery(3, Array.from(colors)) as Array<[number, number, number]>;
|
const pixels = splitEvery(3, Array.from(colors)) as Array<[number, number, number]>;
|
||||||
|
10
src/configurator/components/styled-pixel.tsx
Normal file
10
src/configurator/components/styled-pixel.tsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import tw, { css, styled } from 'twin.macro';
|
||||||
|
|
||||||
|
export const StyledPixel = styled.span(
|
||||||
|
({ rgb: [r, g, b] }: { rgb: [number, number, number] }) => [
|
||||||
|
tw`rounded-full h-3 w-3 bg-current block border border-gray-700`,
|
||||||
|
css`
|
||||||
|
color: rgb(${r}, ${g}, ${b});
|
||||||
|
`,
|
||||||
|
],
|
||||||
|
);
|
@ -1,6 +1,6 @@
|
|||||||
import { invoke } from '@tauri-apps/api';
|
import { invoke } from '@tauri-apps/api';
|
||||||
import { FC, Fragment, useCallback, useEffect, useMemo, useState } from 'react';
|
import { FC, Fragment, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import tw from 'twin.macro';
|
import tw, { styled } from 'twin.macro';
|
||||||
import { useAsync, useAsyncCallback } from 'react-async-hook';
|
import { useAsync, useAsyncCallback } from 'react-async-hook';
|
||||||
import { DisplayWithLedStrips } from './components/display-with-led-strips';
|
import { DisplayWithLedStrips } from './components/display-with-led-strips';
|
||||||
import { PickerConfiguration } from './models/picker-configuration';
|
import { PickerConfiguration } from './models/picker-configuration';
|
||||||
@ -10,6 +10,7 @@ import { Alert, Snackbar } from '@mui/material';
|
|||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { faSpinner } from '@fortawesome/free-solid-svg-icons';
|
import { faSpinner } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { update } from 'ramda';
|
import { update } from 'ramda';
|
||||||
|
import { CompletedLedStrip } from './components/completed-led-strip';
|
||||||
|
|
||||||
const getPickerConfig = () => invoke<PickerConfiguration>('get_picker_config');
|
const getPickerConfig = () => invoke<PickerConfiguration>('get_picker_config');
|
||||||
const getScreenshotOfDisplays = () =>
|
const getScreenshotOfDisplays = () =>
|
||||||
@ -26,6 +27,9 @@ const writePickerConfig = async (config: PickerConfiguration) => {
|
|||||||
config,
|
config,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const StyledConfiguratorContainer = styled.section(tw`flex flex-col items-stretch`);
|
||||||
|
|
||||||
|
const StyledDisplayContainer = styled.section(tw`overflow-auto`);
|
||||||
|
|
||||||
export const Configurator: FC = () => {
|
export const Configurator: FC = () => {
|
||||||
const { loading: pendingPickerConfig, result: savedPickerConfig } = useAsync(
|
const { loading: pendingPickerConfig, result: savedPickerConfig } = useAsync(
|
||||||
@ -91,13 +95,14 @@ export const Configurator: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<StyledConfiguratorContainer>
|
||||||
<section>{displays}</section>;
|
<CompletedLedStrip screenshots={screenshotOfDisplays} />
|
||||||
|
<StyledDisplayContainer>{displays}</StyledDisplayContainer>;
|
||||||
<Snackbar open={pendingGetLedColorsByConfig} autoHideDuration={3000}>
|
<Snackbar open={pendingGetLedColorsByConfig} autoHideDuration={3000}>
|
||||||
<Alert icon={<FontAwesomeIcon icon={faSpinner} />} sx={{ width: '100%' }}>
|
<Alert icon={<FontAwesomeIcon icon={faSpinner} />} sx={{ width: '100%' }}>
|
||||||
This is a success message!
|
This is a success message!
|
||||||
</Alert>
|
</Alert>
|
||||||
</Snackbar>
|
</Snackbar>
|
||||||
</Fragment>
|
</StyledConfiguratorContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
import { LedStripConfig } from './led-strip-config';
|
import { Borders } from '../../constants/border';
|
||||||
|
import { LedStripConfig } from "./led-strip-config";
|
||||||
|
|
||||||
|
export class LedStripConfigOfBorders implements Record<Borders, LedStripConfig | null> {
|
||||||
|
constructor(
|
||||||
|
public top: LedStripConfig | null = null,
|
||||||
|
public bottom: LedStripConfig | null = null,
|
||||||
|
public left: LedStripConfig | null = null,
|
||||||
|
public right: LedStripConfig | null = null,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
export class DisplayConfig {
|
export class DisplayConfig {
|
||||||
top_led_strip: LedStripConfig | null = null;
|
led_strip_of_borders = new LedStripConfigOfBorders();
|
||||||
bottom_led_strip: LedStripConfig | null = null;
|
|
||||||
left_led_strip: LedStripConfig | null = null;
|
|
||||||
right_led_strip: LedStripConfig | null = null;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public id: number,
|
public id: number,
|
||||||
|
2
src/constants/border.ts
Normal file
2
src/constants/border.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export const borders = ['top', 'right', 'bottom', 'left'] as const;
|
||||||
|
export type Borders = typeof borders[number];
|
Loading…
Reference in New Issue
Block a user