Skip to content

Commit

Permalink
feat: first draft of a multiview-layout setting
Browse files Browse the repository at this point in the history
  • Loading branch information
malmen237 committed Sep 16, 2024
1 parent e4ff5a5 commit 3138488
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 72 deletions.
138 changes: 74 additions & 64 deletions src/components/modal/configureOutputModal/ConfigureOutputModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import toast from 'react-hot-toast';
import { MultiviewSettings } from '../../../interfaces/multiview';
import MultiviewSettingsConfig from './MultiviewSettings';
import PipelineSettingsConfig from './PipelineSettings';
import MultiviewLayoutSettings from './MultiviewLayoutSettings';
import { IconPlus, IconTrash } from '@tabler/icons-react';

export interface OutputStream {
Expand Down Expand Up @@ -70,6 +71,7 @@ export function ConfigureOutputModal({
const [portDuplicateIndexes, setPortDuplicateIndexes] = useState<number[]>(
[]
);
const [modalOpen, setModalOpen] = useState<string | null>(null);
const t = useTranslate();

useEffect(() => {
Expand All @@ -87,6 +89,7 @@ export function ConfigureOutputModal({
}, [preset]);

const clearInputs = () => {
setModalOpen(null);
setMultiviews(preset.pipelines[0].multiviews || []);
setOutputStreams(defaultState(preset.pipelines));
onClose();
Expand Down Expand Up @@ -264,73 +267,80 @@ export function ConfigureOutputModal({

return (
<Modal open={open} outsideClick={() => clearInputs()}>
<div className="flex gap-3">
{preset.pipelines.map((pipeline, i) => {
return (
<PipelineSettingsConfig
key={pipeline.pipeline_readable_name}
title={`${
pipeline.pipeline_name
? pipeline.pipeline_name
: pipeline.pipeline_readable_name
}`}
streams={outputstreams.filter((o) => o.pipelineIndex === i)}
addStream={addStream}
updateStream={updateStream}
updateStreams={updateStreams}
deleteStream={deleteStream}
/>
);
})}
{multiviews &&
multiviews.length > 0 &&
multiviews.map((singleItem, index) => {
{!modalOpen && (
<div className="flex gap-3">
{preset.pipelines.map((pipeline, i) => {
return (
<div className="flex" key={index}>
<div className="min-h-full border-l border-separate opacity-10 my-12"></div>
<div className="flex flex-col">
<MultiviewSettingsConfig
multiview={singleItem}
handleUpdateMultiview={(input) =>
handleUpdateMultiview(input, index)
}
portDuplicateError={
portDuplicateIndexes.length > 0
? portDuplicateIndexes.includes(index)
: false
}
/>
<div
className={`w-full flex ${
multiviews.length > 1 ? 'justify-between' : 'justify-end'
}`}
>
{multiviews.length > 1 && (
<button
type="button"
title="Add another multiview"
onClick={() => removeNewMultiview(index)}
>
<IconTrash
className={`ml-4 text-button-delete hover:text-red-400`}
/>
</button>
)}
{multiviews.length === index + 1 && (
<button
type="button"
title="Add another multiview"
onClick={() => addNewMultiview(singleItem)}
>
<IconPlus className="mr-2 text-green-400 hover:text-green-200" />
</button>
)}
</div>
</div>
</div>
<PipelineSettingsConfig
key={pipeline.pipeline_readable_name}
title={`${
pipeline.pipeline_name
? pipeline.pipeline_name
: pipeline.pipeline_readable_name
}`}
streams={outputstreams.filter((o) => o.pipelineIndex === i)}
addStream={addStream}
updateStream={updateStream}
updateStreams={updateStreams}
deleteStream={deleteStream}
/>
);
})}
</div>
{multiviews &&
multiviews.length > 0 &&
multiviews.map((singleItem, index) => {
return (
<div className="flex" key={index}>
<div className="min-h-full border-l border-separate opacity-10 my-12"></div>
<div className="flex flex-col">
<MultiviewSettingsConfig
openConfigModal={(input: string) => setModalOpen(input)}
lastItem={multiviews.length === index + 1}
multiview={singleItem}
handleUpdateMultiview={(input) =>
handleUpdateMultiview(input, index)
}
portDuplicateError={
portDuplicateIndexes.length > 0
? portDuplicateIndexes.includes(index)
: false
}
/>
<div
className={`w-full flex ${
multiviews.length > 1
? 'justify-between'
: 'justify-end'
}`}
>
{multiviews.length > 1 && (
<button
type="button"
title="Add another multiview"
onClick={() => removeNewMultiview(index)}
>
<IconTrash
className={`ml-4 text-button-delete hover:text-red-400`}
/>
</button>
)}
{multiviews.length === index + 1 && (
<button
type="button"
title="Add another multiview"
onClick={() => addNewMultiview(singleItem)}
>
<IconPlus className="mr-2 text-green-400 hover:text-green-200" />
</button>
)}
</div>
</div>
</div>
);
})}
</div>
)}
{!!modalOpen && <MultiviewLayoutSettings configMode={modalOpen} />}
<Decision onClose={() => clearInputs()} onSave={onSave} />
</Modal>
);
Expand Down
101 changes: 101 additions & 0 deletions src/components/modal/configureOutputModal/MultiviewLayoutSettings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { useEffect, useState } from 'react';
import { useMultiviewPresets } from '../../../hooks/multiviewPreset';
import Options from './Options';
import { MultiviewPreset } from '../../../interfaces/preset';
import toast from 'react-hot-toast';
import { useTranslate } from '../../../i18n/useTranslate';

export default function MultiviewLayoutSettings({
configMode
}: {
configMode: string;
}) {
const [selectedMultiviewPreset, setSelectedMultiviewPreset] = useState<
MultiviewPreset | undefined
>();
const [multiviewPresets, loading] = useMultiviewPresets();
const t = useTranslate();

const multiviewPresetNames = multiviewPresets?.map((preset) => preset.name)
? multiviewPresets?.map((preset) => preset.name)
: [];

useEffect(() => {
// if (multiview) {
// setSelectedMultiviewPreset(multiview);
// return;
// }
if (multiviewPresets && multiviewPresets[0]) {
console.log(multiviewPresets);
setSelectedMultiviewPreset(multiviewPresets[0]);
}
}, [multiviewPresets]);

const handlePresetUpdate = (name: string) => {
const selected = multiviewPresets?.find((m) => m.name === name);
if (!selected) {
toast.error(t('preset.no_multiview_found'));
return;
}
setSelectedMultiviewPreset(selected);
};

const handleChange = (key: string, value: string) => {
console.log('onChange: ', key, value);
};

const renderPresetModel = () => {
if (selectedMultiviewPreset) {
const presetHeight =
selectedMultiviewPreset.layout.output_height / 40 + 0.5;
const presetWidth =
selectedMultiviewPreset.layout.output_width / 40 + 0.5;

return (
<div
className={`border-4 border-p/50 relative p-2 m-2`}
style={{ width: `${presetWidth}rem`, height: `${presetHeight}rem` }}
>
{selectedMultiviewPreset.layout.views.map((singleView) => {
return (
<div
key={singleView.x + singleView.y}
className="flex items-center justify-center border-[1px] border-p/50 absolute w-full"
style={{
width: `${singleView.width / 40}rem`,
height: `${singleView.height / 40}rem`,
top: `${singleView.y / 40}rem`,
left: `${singleView.x / 40}rem`
}}
>
<Options
label={t('preset.video_format')}
options={selectedMultiviewPreset.layout.views.map(
(singleView) => singleView.label
)}
value={'string'}
update={(value) => handleChange('videoFormat', value)}
columnStyle
/>
</div>
);
})}
</div>
);
}
};

return (
<div className="flex flex-col w-full h-full">
{renderPresetModel()}
<div>
<Options
label={t('preset.select_multiview_layout')}
options={multiviewPresetNames}
value={selectedMultiviewPreset ? selectedMultiviewPreset.name : ''}
update={(value) => handlePresetUpdate(value)}
/>
</div>
</div>
);
}
57 changes: 49 additions & 8 deletions src/components/modal/configureOutputModal/MultiviewSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,34 @@ import { MultiviewPreset } from '../../../interfaces/preset';
import Input from './Input';
import Options from './Options';
import toast from 'react-hot-toast';
import { IconSettings } from '@tabler/icons-react';

type MultiviewSettingsProps = {
lastItem: boolean;
multiview?: MultiviewSettings;
handleUpdateMultiview: (multiview: MultiviewSettings) => void;
portDuplicateError: boolean;
openConfigModal: (input: string) => void;
};

export default function MultiviewSettingsConfig({
lastItem,
multiview,
handleUpdateMultiview,
portDuplicateError
portDuplicateError,
openConfigModal
}: MultiviewSettingsProps) {
const t = useTranslate();
const [multiviewPresets, loading] = useMultiviewPresets();
const [selectedMultiviewPreset, setSelectedMultiviewPreset] = useState<
MultiviewPreset | undefined
>(multiview);

const [modalOpen, setModalOpen] = useState(false);
const toggleConfigModal = () => {
setModalOpen((state) => !state);
};

useEffect(() => {
if (multiview) {
setSelectedMultiviewPreset(multiview);
Expand Down Expand Up @@ -142,16 +152,47 @@ export default function MultiviewSettingsConfig({
const multiviewOrPreset = multiview ? multiview : selectedMultiviewPreset;

return (
<div className="flex flex-col gap-2 rounded p-4">
<div className="flex flex-col gap-2 rounded p-4 pr-7">
<div className="flex justify-between">
<h1 className="font-bold">{t('preset.multiview_output_settings')}</h1>
</div>
<Options
label={t('preset.select_multiview_preset')}
options={multiviewPresetNames}
value={selectedMultiviewPreset ? selectedMultiviewPreset.name : ''}
update={(value) => handleSetSelectedMultiviewPreset(value)}
/>
<div className="relative">
<Options
label={t('preset.select_multiview_layout')}
options={multiviewPresetNames}
value={selectedMultiviewPreset ? selectedMultiviewPreset.name : ''}
update={(value) => handleSetSelectedMultiviewPreset(value)}
/>
{lastItem && (
<>
<button
onClick={toggleConfigModal}
title={t('preset.configure_layout')}
className={`absolute top-0 right-[-10%] min-w-fit`}
>
<IconSettings className="text-p" />
</button>
{modalOpen && (
<div className="absolute top-5 right-[-65%] flex flex-col">
<button
type="button"
className={`min-w-fit bg-zinc-700 rounded-t-sm p-1 border-b-[1px] border-b-zinc-600 hover:bg-zinc-600`}
onClick={() => openConfigModal('create')}
>
{t('preset.create_layout')}
</button>
<button
type="button"
className={`min-w-fit bg-zinc-700 rounded-b-sm p-1 hover:bg-zinc-600`}
onClick={() => openConfigModal('edit')}
>
{t('preset.update_layout')}
</button>
</div>
)}
</>
)}
</div>
<div className="flex flex-col gap-3">
<Options
label={t('preset.video_format')}
Expand Down
4 changes: 4 additions & 0 deletions src/i18n/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,10 @@ export const en = {
add_stream: 'Add stream',
stream_name: 'Stream',
multiview_output_settings: 'Multiview output',
select_multiview_layout: 'Layout',
configure_layout: 'Configure layout',
create_layout: 'Create new layout',
update_layout: 'Update layout',
select_multiview_preset: 'Preset',
no_multiview_selected: 'No multiview selected',
no_multiview_found: 'No multiview found',
Expand Down
4 changes: 4 additions & 0 deletions src/i18n/locales/sv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,10 @@ export const sv = {
multiview_output_settings: 'Multiview utgång',
no_multiview_selected: 'Ingen multiview vald',
no_multiview_found: 'Hittade ingen multiview',
select_multiview_layout: 'Komposition',
configure_layout: 'Justera komposition',
create_layout: 'Skapa komposition',
update_layout: 'Uppdatera komposition',
select_multiview_preset: 'Förinställningar',
no_port_selected: 'Unik port krävs'
},
Expand Down

0 comments on commit 3138488

Please sign in to comment.