feishin/src/renderer/features/settings/components/advanced/styles-settings.tsx

140 lines
5.2 KiB
TypeScript
Raw Normal View History

2024-08-27 08:26:34 -07:00
import { closeAllModals, openModal } from '@mantine/modals';
2025-10-29 03:54:13 +00:00
import { useEffect, useState } from 'react';
2024-08-27 08:26:34 -07:00
import { useTranslation } from 'react-i18next';
import { SettingsOptions } from '/@/renderer/features/settings/components/settings-option';
2024-08-27 08:26:34 -07:00
import { useCssSettings, useSettingsStoreActions } from '/@/renderer/store';
import { sanitizeCss } from '/@/renderer/utils/sanitize';
import { Button } from '/@/shared/components/button/button';
import { Code } from '/@/shared/components/code/code';
import { ConfirmModal } from '/@/shared/components/modal/modal';
import { Switch } from '/@/shared/components/switch/switch';
import { Text } from '/@/shared/components/text/text';
import { Textarea } from '/@/shared/components/textarea/textarea';
2024-08-27 08:26:34 -07:00
export const StylesSettings = () => {
const [open, setOpen] = useState(false);
const { t } = useTranslation();
const { content, enabled } = useCssSettings();
2024-08-27 08:26:34 -07:00
const [css, setCss] = useState(content);
const { setSettings } = useSettingsStoreActions();
const handleSave = () => {
setSettings({
css: {
content: css,
enabled,
},
});
};
const handleResetToDefault = () => {
setSettings({
css: {
content,
enabled: true,
},
});
closeAllModals();
};
2025-10-29 03:54:13 +00:00
useEffect(() => {
if (content !== css) {
setCss(content);
}
// eslint-disable-next-line react-hooks/exhaustive-deps -- Reason: This is to only fire if an external source updates the stores css.content
}, [content]);
2024-08-27 08:26:34 -07:00
const openConfirmModal = () => {
openModal({
children: (
<ConfirmModal onConfirm={handleResetToDefault}>
<Text color="red !important">
{t('setting.customCssNotice', { postProcess: 'sentenceCase' })}
</Text>
</ConfirmModal>
),
title: t('setting.customCssEnable', { postProcess: 'sentenceCase' }),
});
};
return (
<>
<SettingsOptions
control={
<Switch
checked={enabled}
onChange={(e) => {
if (!e.currentTarget.checked) {
setSettings({
css: {
content,
enabled: false,
},
});
} else {
openConfirmModal();
}
}}
/>
}
description={t('setting.customCssEnable', {
context: 'description',
postProcess: 'sentenceCase',
})}
title={t('setting.customCssEnable', { postProcess: 'sentenceCase' })}
/>
{enabled && (
<>
<SettingsOptions
control={
<>
{open && (
<Button
onClick={handleSave}
size="compact-md"
2024-08-27 08:26:34 -07:00
// disabled={isSaveButtonDisabled}
variant="filled"
>
{t('common.save', { postProcess: 'titleCase' })}
</Button>
)}
<Button
onClick={() => setOpen(!open)}
size="compact-md"
variant="filled"
2024-08-27 08:26:34 -07:00
>
{t(open ? 'common.close' : 'common.edit', {
postProcess: 'titleCase',
})}
</Button>
</>
}
description={t('setting.customCss', {
context: 'description',
postProcess: 'sentenceCase',
})}
title={t('setting.customCss', { postProcess: 'sentenceCase' })}
/>
{open && (
<>
<Textarea
autosize
defaultValue={css}
2025-06-24 14:42:16 -07:00
minRows={8}
2024-08-27 08:26:34 -07:00
onBlur={(e) =>
setCss(sanitizeCss(`<style>${e.currentTarget.value}`))
}
/>
<Text>{t('common.preview', { postProcess: 'sentenceCase' })}: </Text>
<Code block>{css}</Code>
</>
)}
</>
)}
</>
);
};