Compare commits
3 Commits
3c7b3c76b9
...
13d32fb0e0
Author | SHA1 | Date | |
---|---|---|---|
|
13d32fb0e0 | ||
|
abee609e43 | ||
|
03fe09d1ce |
|
@ -80,6 +80,29 @@
|
|||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-width: 0;
|
||||
border-top-width: 1px;
|
||||
border-color: var(--color-outline-variant);
|
||||
border-style: solid;
|
||||
width: 100%;
|
||||
align-self: stretch;
|
||||
&.dashed {
|
||||
border-style: dashed;
|
||||
}
|
||||
&.dotted {
|
||||
border-style: dotted;
|
||||
}
|
||||
&.vertical {
|
||||
border-top-width: 0;
|
||||
border-left-width: 1px;
|
||||
width: auto;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
:where(button, .button) {
|
||||
border: none;
|
||||
border-radius: calc(var(--border-radius) * 2);
|
||||
|
|
|
@ -117,7 +117,7 @@ export function totalDuration(pattern: Pattern): number {
|
|||
return reduce(
|
||||
pattern.pulses,
|
||||
(former, pulse) => former + pulse.offset,
|
||||
pattern.smoothRepeat ? 100 : 0,
|
||||
pattern.smoothRepeat && pattern.pulses.length > 1 ? 100 : 0,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,15 +3,58 @@
|
|||
flex: 2;
|
||||
border-radius: calc(var(--border-radius) * 2);
|
||||
background-color: var(--color-surface-container);
|
||||
padding: calc(var(--spacing) * 2) calc(var(--spacing) * 2);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: calc(var(--spacing) * 2);
|
||||
.control_panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: calc(var(--spacing) * 2);
|
||||
.button_row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: calc(var(--spacing) * 2);
|
||||
}
|
||||
}
|
||||
.detail_panel {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: calc(var(--spacing) * 2);
|
||||
.detail_row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: calc(var(--spacing) * 2);
|
||||
.detail_unit {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: calc(var(--spacing));
|
||||
label {
|
||||
min-width: 8em;
|
||||
flex: 0 0 8em;
|
||||
text-align: right;
|
||||
}
|
||||
.content {
|
||||
flex: 1 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.preview_panel {
|
||||
min-height: 140px;
|
||||
flex: 0 0;
|
||||
}
|
||||
}
|
||||
.empty_promption {
|
||||
flex: 2;
|
||||
border-radius: calc(var(--border-radius) * 2);
|
||||
background-color: var(--color-surface-container);
|
||||
padding: calc(var(--spacing) * 2) calc(var(--spacing) * 2);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
|
|
|
@ -1,6 +1,17 @@
|
|||
import { useAtomValue } from 'jotai';
|
||||
import { FC } from 'react';
|
||||
import { CurrentPatternAtom, Pattern } from '../../context/Patterns';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { ask } from '@tauri-apps/plugin-dialog';
|
||||
import dayjs from 'dayjs';
|
||||
import { useAtomValue, useSetAtom } from 'jotai';
|
||||
import { FC, useCallback, useMemo } from 'react';
|
||||
import { NotificationType, useNotification } from '../../components/Notifications';
|
||||
import PatternPreview from '../../components/PatternPreview';
|
||||
import {
|
||||
CurrentPatternAtom,
|
||||
Pattern,
|
||||
PatternsAtom,
|
||||
SelectedPatternIdAtom,
|
||||
totalDuration,
|
||||
} from '../../context/Patterns';
|
||||
import styles from './PatternDetail.module.css';
|
||||
|
||||
const EmptyPromption: FC = () => {
|
||||
|
@ -15,11 +26,80 @@ const EmptyPromption: FC = () => {
|
|||
};
|
||||
|
||||
const Detail: FC<{ pattern: Pattern }> = ({ pattern }) => {
|
||||
const { showToast } = useNotification();
|
||||
const refreshPatterns = useSetAtom(PatternsAtom);
|
||||
const resetSelected = useSetAtom(SelectedPatternIdAtom);
|
||||
const patternDuration = useMemo(() => totalDuration(pattern), [pattern]);
|
||||
const createTime = useMemo(
|
||||
() => dayjs(pattern.createdAt).format('YYYY-MM-DD HH:mm:ss'),
|
||||
[pattern],
|
||||
);
|
||||
|
||||
const handleDeleteAction = useCallback(async () => {
|
||||
try {
|
||||
const answer = await ask(
|
||||
`The pattern ${pattern.name} will be deleted, and cannot be revoked. Are you sure?`,
|
||||
{
|
||||
title: 'Confirm action',
|
||||
kind: 'warning',
|
||||
},
|
||||
);
|
||||
if (answer) {
|
||||
await invoke('remove_pattern', { patternId: pattern.id });
|
||||
showToast(NotificationType.SUCCESS, 'Pattern deleted.');
|
||||
refreshPatterns();
|
||||
resetSelected(null);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[delete pattern]', e);
|
||||
showToast(NotificationType.ERROR, 'Failed to delete pattern. Please try again.');
|
||||
}
|
||||
}, [pattern]);
|
||||
|
||||
return (
|
||||
<div className={styles.pattern_detail}>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div className={styles.control_panel}>
|
||||
<div className={styles.button_row}>
|
||||
<button className="tonal">Edit Pattern</button>
|
||||
<button className="tonal danger" onClick={handleDeleteAction}>
|
||||
Delete Pattern
|
||||
</button>
|
||||
</div>
|
||||
<div className={styles.button_row}>
|
||||
<button className="tonal warn">Test Run</button>
|
||||
</div>
|
||||
<div className={styles.button_row}>
|
||||
<button className="tonal secondary">Add to Channel A Playlist</button>
|
||||
<button className="tonal secondary">Add to Channel B Playlist</button>
|
||||
</div>
|
||||
</div>
|
||||
<hr className="dotted" />
|
||||
<div className={styles.detail_panel}>
|
||||
<div className={styles.detail_row}>
|
||||
<div className={styles.detail_unit}>
|
||||
<label>Created At</label>
|
||||
<div className={styles.content}>{createTime}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.detail_row}>
|
||||
<div className={styles.detail_unit}>
|
||||
<label>Duration</label>
|
||||
<div className={styles.content}>{(patternDuration / 1000).toFixed(2)} s</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.detail_row}>
|
||||
<div className={styles.detail_unit}>
|
||||
<label> </label>
|
||||
<div className={styles.content}>
|
||||
{pattern.pulses.length} key frame{pattern.pulses.length > 1 && 's'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr className="dotted" />
|
||||
<div className={styles.preview_panel}>
|
||||
<PatternPreview />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user