134 lines
4.3 KiB
TypeScript
134 lines
4.3 KiB
TypeScript
import debug from 'debug';
|
|
import { isNil, lensPath, set, splitEvery, update } from 'ramda';
|
|
import { FC, useEffect, useMemo, useState } from 'react';
|
|
import tw, { css, styled } from 'twin.macro';
|
|
import { Borders, borders } from '../../constants/border';
|
|
import { useLedCount } from '../contents/led-count';
|
|
import { DisplayConfig, LedStripConfigOfBorders } from '../models/display-config';
|
|
import { LedStripConfig } from '../models/led-strip-config';
|
|
import { PixelRgb } from '../models/pixel-rgb';
|
|
import { ScreenshotDto } from '../models/screenshot.dto';
|
|
import { DraggableStrip } from './draggable-strip';
|
|
import { StyledPixel } from './styled-pixel';
|
|
|
|
export const logger = debug('app:completed-led-strip');
|
|
|
|
interface CompletedLedStripProps {
|
|
screenshots: ScreenshotDto[];
|
|
onDisplayConfigChange?: (value: DisplayConfig) => void;
|
|
}
|
|
|
|
type BorderLedStrip = {
|
|
pixels: PixelRgb[];
|
|
config: LedStripConfig | null;
|
|
};
|
|
|
|
const StyledContainer = styled.section(
|
|
({ rows, columns }: { rows: number; columns: number }) => [
|
|
tw`grid m-4 pb-2 items-center justify-items-center select-none`,
|
|
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;
|
|
justify-self: stretch;
|
|
`,
|
|
);
|
|
|
|
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 PixelRgb[],
|
|
config: ss.config.led_strip_of_borders[b],
|
|
})),
|
|
);
|
|
}, [screenshots]);
|
|
const ledCount = useMemo(
|
|
() => borderLedStrips.reduce((prev, curr) => prev + curr.pixels.length, 0),
|
|
[borderLedStrips],
|
|
);
|
|
|
|
const { setLedCount } = useLedCount();
|
|
// setLedCount for context
|
|
useEffect(() => {
|
|
setLedCount(ledCount);
|
|
}, [ledCount, setLedCount]);
|
|
|
|
const [overrideBorderLedStrips, setOverrideBorderLedStrips] =
|
|
useState<BorderLedStrip[]>();
|
|
|
|
const completedPixels = useMemo(() => {
|
|
const completed: PixelRgb[] = new Array(ledCount).fill([0, 0, 0]);
|
|
(overrideBorderLedStrips ?? 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, i) => <StyledPixel rgb={color} key={i} />);
|
|
}, [ledCount, borderLedStrips, overrideBorderLedStrips]);
|
|
|
|
const strips = useMemo(() => {
|
|
return borderLedStrips.map(({ config, pixels }, index) =>
|
|
config ? (
|
|
<DraggableStrip
|
|
key={index}
|
|
{...{ config, pixels, index: index + 1 }}
|
|
onConfigChange={(c) => {
|
|
setOverrideBorderLedStrips(
|
|
update(index, { config: c, pixels }, borderLedStrips),
|
|
);
|
|
}}
|
|
onConfigFinish={(c) => {
|
|
const indexOfDisplay = Math.floor(index / borders.length);
|
|
const xLens = lensPath<LedStripConfigOfBorders, Borders>([
|
|
borders[index % borders.length],
|
|
]);
|
|
const displayConfig: DisplayConfig = {
|
|
...screenshots[indexOfDisplay].config,
|
|
led_strip_of_borders: set(
|
|
xLens,
|
|
c,
|
|
screenshots[indexOfDisplay].config.led_strip_of_borders,
|
|
),
|
|
};
|
|
onDisplayConfigChange?.(displayConfig);
|
|
}}
|
|
/>
|
|
) : (
|
|
<div key={index} />
|
|
),
|
|
);
|
|
}, [borderLedStrips, screenshots]);
|
|
|
|
useEffect(() => {
|
|
setOverrideBorderLedStrips(undefined);
|
|
}, [borderLedStrips]);
|
|
return (
|
|
<StyledContainer rows={screenshots.length * borders.length} columns={ledCount}>
|
|
<StyledCompletedContainer>{completedPixels}</StyledCompletedContainer>
|
|
{strips}
|
|
</StyledContainer>
|
|
);
|
|
};
|
|
|
|
|