Use AwaitableComponent for "CreateThemeDialog"

This commit is contained in:
schroda
2026-01-02 22:19:32 +01:00
parent fd856c5cbd
commit bc06d88db0
3 changed files with 201 additions and 205 deletions

View File

@@ -10,7 +10,7 @@ import { useTranslation } from 'react-i18next';
import Stack from '@mui/material/Stack';
import Button from '@mui/material/Button';
import AddCircleIcon from '@mui/icons-material/AddCircle';
import { bindDialog, bindTrigger, usePopupState } from 'material-ui-popup-state/hooks';
import { AwaitableComponent } from 'awaitable-component';
import { CustomTooltip } from '@/base/components/CustomTooltip.tsx';
import { ThemeCreationDialog } from '@/features/theme/components/CreateThemeDialog.tsx';
import { TypographyMaxLines } from '@/base/components/texts/TypographyMaxLines.tsx';
@@ -18,10 +18,7 @@ import { TypographyMaxLines } from '@/base/components/texts/TypographyMaxLines.t
export const CreateThemeButton = () => {
const { t } = useTranslation();
const popupState = usePopupState({ variant: 'popover', popupId: 'theme-creation-dialog' });
return (
<>
<Stack sx={{ alignItems: 'center', gap: 1, minWidth: '150px', maxWidth: '150px' }}>
<Button
sx={{
@@ -30,7 +27,9 @@ export const CreateThemeButton = () => {
}}
variant="contained"
size="large"
{...bindTrigger(popupState)}
onClick={() => {
AwaitableComponent.show(ThemeCreationDialog, { mode: 'create' });
}}
>
<AddCircleIcon fontSize="large" />
</Button>
@@ -40,7 +39,5 @@ export const CreateThemeButton = () => {
</TypographyMaxLines>
</CustomTooltip>
</Stack>
{popupState.isOpen && <ThemeCreationDialog bindDialogProps={bindDialog(popupState)} mode="create" />}
</>
);
};

View File

@@ -11,7 +11,6 @@ import { useState } from 'react';
import Typography from '@mui/material/Typography';
import Stack from '@mui/material/Stack';
import Button from '@mui/material/Button';
import { bindDialog } from 'material-ui-popup-state/hooks';
import Dialog from '@mui/material/Dialog';
import DialogTitle from '@mui/material/DialogTitle';
import DialogContent from '@mui/material/DialogContent';
@@ -19,6 +18,7 @@ import DialogActions from '@mui/material/DialogActions';
import TextField from '@mui/material/TextField';
import Link from '@mui/material/Link';
import { jsonrepair } from 'jsonrepair';
import { AwaitableComponentProps } from 'awaitable-component';
import { getErrorMessage, jsonSaveParse } from '@/lib/HelperFunctions.ts';
import { AppTheme, isThemeNameUnique } from '@/features/theme/services/AppThemes.ts';
import {
@@ -91,11 +91,13 @@ const dialogModeToTranslationKey: Record<
};
export const ThemeCreationDialog = ({
bindDialogProps,
mode,
appTheme = baseCustomTheme,
}: {
bindDialogProps: ReturnType<typeof bindDialog>;
isVisible,
onExitComplete,
onSubmit,
onDismiss,
}: AwaitableComponentProps<void> & {
mode: DialogMode;
appTheme?: AppTheme;
}) => {
@@ -117,7 +119,7 @@ export const ThemeCreationDialog = ({
const [didThemeChange, setDidThemeChange] = useState(mode === 'create');
return (
<Dialog {...bindDialogProps} fullWidth maxWidth="md">
<Dialog open={isVisible} onTransitionExited={onExitComplete} fullWidth maxWidth="md">
<DialogTitle>{t(dialogModeToTranslationKey[mode].title)}</DialogTitle>
<DialogContent>
{loading && <LoadingPlaceholder />}
@@ -212,12 +214,12 @@ export const ThemeCreationDialog = ({
)}
</DialogContent>
<DialogActions>
<Button autoFocus onClick={bindDialogProps.onClose} color="primary">
<Button autoFocus onClick={() => onDismiss()} color="primary">
{t('global.button.cancel')}
</Button>
<Button
disabled={invalidTheme || invalidName || isCreating || !didThemeChange || !theme.id.length}
onClick={(e) => {
onClick={() => {
makeToast(t(dialogModeToTranslationKey[mode].action, { theme: theme.getName() }), 'info');
setIsCreating(true);
@@ -227,7 +229,7 @@ export const ThemeCreationDialog = ({
t(dialogModeToTranslationKey[mode].success, { theme: theme.getName() }),
'success',
);
bindDialogProps.onClose(e);
onSubmit();
})
.catch((updateError) =>
makeToast(

View File

@@ -17,7 +17,7 @@ import CardActionArea from '@mui/material/CardActionArea';
import DeleteIcon from '@mui/icons-material/Delete';
import IconButton from '@mui/material/IconButton';
import EditIcon from '@mui/icons-material/Edit';
import { bindDialog, usePopupState } from 'material-ui-popup-state/hooks';
import { AwaitableComponent } from 'awaitable-component';
import { CustomTooltip } from '@/base/components/CustomTooltip.tsx';
import { useAppThemeContext } from '@/features/theme/AppThemeContext.tsx';
import { AppTheme } from '@/features/theme/services/AppThemes.ts';
@@ -40,8 +40,6 @@ export const ThemePreview = ({ appTheme, onDelete }: { appTheme: AppTheme; onDel
const theme = useTheme();
const { themeMode, setAppTheme, appTheme: activeAppTheme, shouldUsePureBlackMode } = useAppThemeContext();
const popupState = usePopupState({ variant: 'popover', popupId: `theme-edit-dialog-${appTheme.id}` });
const isSelected = appTheme.id === activeAppTheme;
const muiTheme = useMemo(
@@ -50,7 +48,6 @@ export const ThemePreview = ({ appTheme, onDelete }: { appTheme: AppTheme; onDel
);
return (
<>
<Stack
sx={{
justifyContent: 'center',
@@ -81,9 +78,7 @@ export const ThemePreview = ({ appTheme, onDelete }: { appTheme: AppTheme; onDel
pointerEvents: 'none',
borderRadius: 1,
...theme.applyStyles('dark', {
borderColor: isSelected
? muiTheme.palette.primary.light
: muiTheme.palette.grey['900'],
borderColor: isSelected ? muiTheme.palette.primary.light : muiTheme.palette.grey['900'],
}),
}}
/>
@@ -165,7 +160,11 @@ export const ThemePreview = ({ appTheme, onDelete }: { appTheme: AppTheme; onDel
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
popupState.open();
AwaitableComponent.show(ThemeCreationDialog, {
mode: 'edit',
appTheme,
});
}}
component="div"
size="small"
@@ -234,7 +233,5 @@ export const ThemePreview = ({ appTheme, onDelete }: { appTheme: AppTheme; onDel
<TypographyMaxLines sx={{ maxWidth: '100%' }}>{getName()}</TypographyMaxLines>
</CustomTooltip>
</Stack>
<ThemeCreationDialog bindDialogProps={bindDialog(popupState)} mode="edit" appTheme={appTheme} />
</>
);
};