Skip to content

Commit

Permalink
added auto saving + gamma correction filter
Browse files Browse the repository at this point in the history
  • Loading branch information
klakhov committed Jan 31, 2025
1 parent 30e900b commit 190eb74
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 68 deletions.
153 changes: 85 additions & 68 deletions cvat-ui/src/components/header/settings-modal/settings-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@

import './styles.scss';
import _ from 'lodash';
import React, { useCallback, useEffect } from 'react';
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import Tabs from 'antd/lib/tabs';
import Text from 'antd/lib/typography/Text';
import Modal from 'antd/lib/modal/Modal';
import Button from 'antd/lib/button';
import notification from 'antd/lib/notification';
import Tooltip from 'antd/lib/tooltip';
import { PlayCircleOutlined, LaptopOutlined, BuildOutlined } from '@ant-design/icons';

import { setSettings } from 'actions/settings-actions';
Expand All @@ -22,51 +21,66 @@ import PlayerSettingsContainer from 'containers/header/settings-modal/player-set
import ShortcutsSettingsContainer from 'containers/header/settings-modal/shortcuts-settings';
import { CombinedState } from 'reducers';
import { conflict, conflictDetector } from 'utils/conflict-detector';
import { ImageFilter, ImageFilterAlias } from 'utils/image-processing';
import GammaCorrection, { GammaFilterOptions } from 'utils/fabric-wrapper/gamma-correciton';

interface SettingsModalProps {
visible: boolean;
onClose(): void;
}

const SAVE_SETTINGS_DELAY = 2000;

function SettingsModal(props: SettingsModalProps): JSX.Element {
const { visible, onClose } = props;

const settings = useSelector((state: CombinedState) => state.settings);
const shortcuts = useSelector((state: CombinedState) => state.shortcuts);
const dispatch = useDispatch();

const onSaveSettings = useCallback(() => {
const settingsForSaving: any = {
shortcuts: {
keyMap: {},
},
};
for (const [key, value] of Object.entries(settings)) {
if (['player', 'workspace'].includes(key)) {
settingsForSaving[key] = value;
useEffect(() => {
const handler = setTimeout(() => {
const settingsForSaving: any = {
shortcuts: {
keyMap: {},
},
imageFilters: [],
};
for (const [key, value] of Object.entries(settings)) {
if (['player', 'workspace'].includes(key)) {
settingsForSaving[key] = value;
}
if (key === 'imageFilters') {
const filters = [];
for (const filter of value) {
filters.push({
alias: filter.alias,
params: filter.modifier.serialize(),
});
}
settingsForSaving.imageFilters = filters;
}
}
}
for (const [key] of Object.entries(shortcuts.keyMap)) {
if (key in shortcuts.defaultState) {
settingsForSaving.shortcuts.keyMap[key] = {
sequences: shortcuts.keyMap[key].sequences,
};
for (const [key] of Object.entries(shortcuts.keyMap)) {
if (key in shortcuts.defaultState) {
settingsForSaving.shortcuts.keyMap[key] = {
sequences: shortcuts.keyMap[key].sequences,
};
}
}
}

localStorage.setItem('clientSettings', JSON.stringify(settingsForSaving));
notification.success({
message: 'Settings were successfully saved',
className: 'cvat-notification-notice-save-settings-success',
});
localStorage.setItem('clientSettings', JSON.stringify(settingsForSaving));
}, SAVE_SETTINGS_DELAY);

onClose();
}, [onClose, settings, shortcuts]);
return () => {
clearTimeout(handler);
};
}, [settings, shortcuts]);

useEffect(() => {
try {
dispatch(shortcutsActions.setDefaultShortcuts(structuredClone(shortcuts.keyMap)));
const newSettings = _.pick(settings, 'player', 'workspace');
const newSettings = { ..._.pick(settings, 'player', 'workspace'), imageFilters: [] as ImageFilter[] };
const settingsString = localStorage.getItem('clientSettings') as string;
if (!settingsString) return;
const loadedSettings = JSON.parse(settingsString);
Expand All @@ -79,6 +93,26 @@ function SettingsModal(props: SettingsModalProps): JSX.Element {
}
}
}

newSettings.imageFilters = [];
if ('imageFilters' in loadedSettings) {
for (const filter of loadedSettings.imageFilters) {
switch (filter.alias) {
case ImageFilterAlias.GAMMA_CORRECTION: {
const modifier = new GammaCorrection(filter.params as GammaFilterOptions);
newSettings.imageFilters.push({
modifier,
alias: ImageFilterAlias.GAMMA_CORRECTION,
});
break;
}
default: {
break;
}
}
}
}

dispatch(setSettings(newSettings));
if ('shortcuts' in loadedSettings) {
const updateKeyMap = structuredClone(shortcuts.keyMap);
Expand Down Expand Up @@ -119,6 +153,27 @@ function SettingsModal(props: SettingsModalProps): JSX.Element {
}
}, []);

const tabItems = [
{
key: 'player',
label: <Text>Player</Text>,
icon: <PlayCircleOutlined />,
children: <PlayerSettingsContainer />,
},
{
key: 'workspace',
label: <Text>Workspace</Text>,
icon: <LaptopOutlined />,
children: <WorkspaceSettingsContainer />,
},
{
key: 'shortcuts',
label: <Text>Shortcuts</Text>,
icon: <BuildOutlined />,
children: <ShortcutsSettingsContainer />,
},
];

return (
<Modal
title='Settings'
Expand All @@ -127,51 +182,13 @@ function SettingsModal(props: SettingsModalProps): JSX.Element {
width={800}
className='cvat-settings-modal'
footer={(
<>
<Tooltip title='Will save settings to restore them after the app is reopened'>
<Button className='cvat-save-settings-button' type='primary' onClick={onSaveSettings}>
Save
</Button>
</Tooltip>
<Button className='cvat-close-settings-button' type='default' onClick={onClose}>
Close
</Button>
</>
<Button className='cvat-close-settings-button' type='default' onClick={onClose}>
Close
</Button>
)}
>
<div className='cvat-settings-tabs'>
<Tabs
type='card'
tabBarStyle={{ marginBottom: '0px', marginLeft: '-1px' }}
items={[{
key: 'player',
label: (
<span>
<PlayCircleOutlined />
<Text>Player</Text>
</span>
),
children: <PlayerSettingsContainer />,
}, {
key: 'workspace',
label: (
<span>
<LaptopOutlined />
<Text>Workspace</Text>
</span>
),
children: <WorkspaceSettingsContainer />,
}, {
key: 'shortcuts',
label: (
<span>
<BuildOutlined />
<Text>Shortcuts</Text>
</span>
),
children: <ShortcutsSettingsContainer />,
}]}
/>
<Tabs defaultActiveKey='player' type='card' items={tabItems} />
</div>
</Modal>
);
Expand Down
6 changes: 6 additions & 0 deletions cvat-ui/src/utils/fabric-wrapper/gamma-correciton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ export default class GammaCorrection extends FabricFilter {
this.#gamma = newGamma;
}

public serialize(): GammaFilterOptions {
return {
gamma: this.#gamma,
};
}

get gamma(): number {
return this.#gamma[0];
}
Expand Down
5 changes: 5 additions & 0 deletions cvat-ui/src/utils/image-processing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface ImageProcessing {

processImage: (src: ImageData, frameNumber: number) => ImageData;
configure: (options: object) => void;
serialize: () => any;
}

/* eslint @typescript-eslint/no-unused-vars: ["error", { "argsIgnorePattern": "^_" }] */
Expand All @@ -23,6 +24,10 @@ export class BaseImageFilter implements ImageProcessing {
}

configure(_options: object): void {}

serialize(): any {
return {};
}
}

export interface ImageFilter {
Expand Down

0 comments on commit 190eb74

Please sign in to comment.