mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): split settings modal
This commit is contained in:
parent
41e324fd51
commit
9f742a669e
@ -17,6 +17,8 @@ import { useStarterModelsToast } from 'features/modelManagerV2/hooks/useStarterM
|
|||||||
import { ClearQueueConfirmationsAlertDialog } from 'features/queue/components/ClearQueueConfirmationAlertDialog';
|
import { ClearQueueConfirmationsAlertDialog } from 'features/queue/components/ClearQueueConfirmationAlertDialog';
|
||||||
import { StylePresetModal } from 'features/stylePresets/components/StylePresetForm/StylePresetModal';
|
import { StylePresetModal } from 'features/stylePresets/components/StylePresetForm/StylePresetModal';
|
||||||
import { activeStylePresetIdChanged } from 'features/stylePresets/store/stylePresetSlice';
|
import { activeStylePresetIdChanged } from 'features/stylePresets/store/stylePresetSlice';
|
||||||
|
import RefreshAfterResetModal from 'features/system/components/SettingsModal/RefreshAfterResetModal';
|
||||||
|
import SettingsModal from 'features/system/components/SettingsModal/SettingsModal';
|
||||||
import { configChanged } from 'features/system/store/configSlice';
|
import { configChanged } from 'features/system/store/configSlice';
|
||||||
import { selectLanguage } from 'features/system/store/systemSelectors';
|
import { selectLanguage } from 'features/system/store/systemSelectors';
|
||||||
import { AppContent } from 'features/ui/components/AppContent';
|
import { AppContent } from 'features/ui/components/AppContent';
|
||||||
@ -135,6 +137,8 @@ const App = ({
|
|||||||
<StylePresetModal />
|
<StylePresetModal />
|
||||||
<ClearQueueConfirmationsAlertDialog />
|
<ClearQueueConfirmationsAlertDialog />
|
||||||
<PreselectedImage selectedImage={selectedImage} />
|
<PreselectedImage selectedImage={selectedImage} />
|
||||||
|
<SettingsModal />
|
||||||
|
<RefreshAfterResetModal />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
import {
|
||||||
|
Flex,
|
||||||
|
Modal,
|
||||||
|
ModalBody,
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
ModalOverlay,
|
||||||
|
Text,
|
||||||
|
} from '@invoke-ai/ui-library';
|
||||||
|
import { useStore } from '@nanostores/react';
|
||||||
|
import { buildUseBoolean } from 'common/hooks/useBoolean';
|
||||||
|
import { atom } from 'nanostores';
|
||||||
|
import { memo, useEffect, useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const $refreshAfterResetModalState = atom(false);
|
||||||
|
export const useRefreshAfterResetModal = buildUseBoolean($refreshAfterResetModalState);
|
||||||
|
|
||||||
|
const RefreshAfterResetModal = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [countdown, setCountdown] = useState(3);
|
||||||
|
|
||||||
|
const refreshModal = useRefreshAfterResetModal();
|
||||||
|
const isOpen = useStore(refreshModal.$boolean);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isOpen) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const i = window.setInterval(() => setCountdown((prev) => prev - 1), 1000);
|
||||||
|
return () => {
|
||||||
|
window.clearInterval(i);
|
||||||
|
};
|
||||||
|
}, [isOpen]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (countdown <= 0) {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}, [countdown]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Modal
|
||||||
|
closeOnOverlayClick={false}
|
||||||
|
isOpen={isOpen}
|
||||||
|
onClose={refreshModal.setFalse}
|
||||||
|
isCentered
|
||||||
|
closeOnEsc={false}
|
||||||
|
useInert={false}
|
||||||
|
>
|
||||||
|
<ModalOverlay backdropFilter="blur(40px)" />
|
||||||
|
<ModalContent>
|
||||||
|
<ModalHeader />
|
||||||
|
<ModalBody>
|
||||||
|
<Flex justifyContent="center">
|
||||||
|
<Text fontSize="lg">
|
||||||
|
<Text>
|
||||||
|
{t('settings.resetComplete')} {t('settings.reloadingIn')} {countdown}...
|
||||||
|
</Text>
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter />
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(RefreshAfterResetModal);
|
@ -25,12 +25,13 @@ import {
|
|||||||
} from 'react-icons/pi';
|
} from 'react-icons/pi';
|
||||||
import { RiDiscordFill, RiGithubFill, RiSettings4Line } from 'react-icons/ri';
|
import { RiDiscordFill, RiGithubFill, RiSettings4Line } from 'react-icons/ri';
|
||||||
|
|
||||||
import SettingsModal from './SettingsModal';
|
import { useSettingsModal } from './SettingsModal';
|
||||||
import { SettingsUpsellMenuItem } from './SettingsUpsellMenuItem';
|
import { SettingsUpsellMenuItem } from './SettingsUpsellMenuItem';
|
||||||
const SettingsMenu = () => {
|
const SettingsMenu = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
useGlobalMenuClose(onClose);
|
useGlobalMenuClose(onClose);
|
||||||
|
const settingsModal = useSettingsModal();
|
||||||
|
|
||||||
const isBugLinkEnabled = useFeatureStatus('bugLink');
|
const isBugLinkEnabled = useFeatureStatus('bugLink');
|
||||||
const isDiscordLinkEnabled = useFeatureStatus('discordLink');
|
const isDiscordLinkEnabled = useFeatureStatus('discordLink');
|
||||||
@ -75,11 +76,9 @@ const SettingsMenu = () => {
|
|||||||
{t('common.hotkeysLabel')}
|
{t('common.hotkeysLabel')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</HotkeysModal>
|
</HotkeysModal>
|
||||||
<SettingsModal>
|
<MenuItem onClick={settingsModal.setTrue} as="button" icon={<PiToggleRightFill />}>
|
||||||
<MenuItem as="button" icon={<PiToggleRightFill />}>
|
{t('common.settingsLabel')}
|
||||||
{t('common.settingsLabel')}
|
</MenuItem>
|
||||||
</MenuItem>
|
|
||||||
</SettingsModal>
|
|
||||||
</MenuGroup>
|
</MenuGroup>
|
||||||
<MenuGroup title={t('accessibility.about')}>
|
<MenuGroup title={t('accessibility.about')}>
|
||||||
<AboutModal>
|
<AboutModal>
|
||||||
|
@ -13,13 +13,15 @@ import {
|
|||||||
ModalOverlay,
|
ModalOverlay,
|
||||||
Switch,
|
Switch,
|
||||||
Text,
|
Text,
|
||||||
useDisclosure,
|
|
||||||
} from '@invoke-ai/ui-library';
|
} from '@invoke-ai/ui-library';
|
||||||
|
import { useStore } from '@nanostores/react';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
||||||
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
||||||
|
import { buildUseBoolean } from 'common/hooks/useBoolean';
|
||||||
import { useClearStorage } from 'common/hooks/useClearStorage';
|
import { useClearStorage } from 'common/hooks/useClearStorage';
|
||||||
import { selectShouldUseCPUNoise, shouldUseCpuNoiseChanged } from 'features/controlLayers/store/paramsSlice';
|
import { selectShouldUseCPUNoise, shouldUseCpuNoiseChanged } from 'features/controlLayers/store/paramsSlice';
|
||||||
|
import { useRefreshAfterResetModal } from 'features/system/components/SettingsModal/RefreshAfterResetModal';
|
||||||
import { SettingsDeveloperLogIsEnabled } from 'features/system/components/SettingsModal/SettingsDeveloperLogIsEnabled';
|
import { SettingsDeveloperLogIsEnabled } from 'features/system/components/SettingsModal/SettingsDeveloperLogIsEnabled';
|
||||||
import { SettingsDeveloperLogLevel } from 'features/system/components/SettingsModal/SettingsDeveloperLogLevel';
|
import { SettingsDeveloperLogLevel } from 'features/system/components/SettingsModal/SettingsDeveloperLogLevel';
|
||||||
import { SettingsDeveloperLogNamespaces } from 'features/system/components/SettingsModal/SettingsDeveloperLogNamespaces';
|
import { SettingsDeveloperLogNamespaces } from 'features/system/components/SettingsModal/SettingsDeveloperLogNamespaces';
|
||||||
@ -40,8 +42,9 @@ import {
|
|||||||
} from 'features/system/store/systemSlice';
|
} from 'features/system/store/systemSlice';
|
||||||
import { selectShouldShowProgressInViewer } from 'features/ui/store/uiSelectors';
|
import { selectShouldShowProgressInViewer } from 'features/ui/store/uiSelectors';
|
||||||
import { setShouldShowProgressInViewer } from 'features/ui/store/uiSlice';
|
import { setShouldShowProgressInViewer } from 'features/ui/store/uiSlice';
|
||||||
import type { ChangeEvent, ReactElement } from 'react';
|
import { atom } from 'nanostores';
|
||||||
import { cloneElement, memo, useCallback, useEffect, useState } from 'react';
|
import type { ChangeEvent } from 'react';
|
||||||
|
import { memo, useCallback, useEffect } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useGetAppConfigQuery } from 'services/api/endpoints/appInfo';
|
import { useGetAppConfigQuery } from 'services/api/endpoints/appInfo';
|
||||||
|
|
||||||
@ -54,27 +57,29 @@ type ConfigOptions = {
|
|||||||
shouldShowLocalizationToggle?: boolean;
|
shouldShowLocalizationToggle?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const defaultConfig: ConfigOptions = {
|
||||||
|
shouldShowDeveloperSettings: true,
|
||||||
|
shouldShowResetWebUiText: true,
|
||||||
|
shouldShowClearIntermediates: true,
|
||||||
|
shouldShowLocalizationToggle: true,
|
||||||
|
};
|
||||||
|
|
||||||
type SettingsModalProps = {
|
type SettingsModalProps = {
|
||||||
/* The button to open the Settings Modal */
|
|
||||||
children: ReactElement;
|
|
||||||
config?: ConfigOptions;
|
config?: ConfigOptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
const $settingsModal = atom(false);
|
||||||
|
export const useSettingsModal = buildUseBoolean($settingsModal);
|
||||||
|
|
||||||
|
const SettingsModal = ({ config = defaultConfig }: SettingsModalProps) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [countdown, setCountdown] = useState(3);
|
|
||||||
|
|
||||||
const shouldShowDeveloperSettings = config?.shouldShowDeveloperSettings ?? true;
|
|
||||||
const shouldShowResetWebUiText = config?.shouldShowResetWebUiText ?? true;
|
|
||||||
const shouldShowClearIntermediates = config?.shouldShowClearIntermediates ?? true;
|
|
||||||
const shouldShowLocalizationToggle = config?.shouldShowLocalizationToggle ?? true;
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!shouldShowDeveloperSettings) {
|
if (!config?.shouldShowDeveloperSettings) {
|
||||||
dispatch(logIsEnabledChanged(false));
|
dispatch(logIsEnabledChanged(false));
|
||||||
}
|
}
|
||||||
}, [shouldShowDeveloperSettings, dispatch]);
|
}, [dispatch, config?.shouldShowDeveloperSettings]);
|
||||||
|
|
||||||
const { isNSFWCheckerAvailable, isWatermarkerAvailable } = useGetAppConfigQuery(undefined, {
|
const { isNSFWCheckerAvailable, isWatermarkerAvailable } = useGetAppConfigQuery(undefined, {
|
||||||
selectFromResult: ({ data }) => ({
|
selectFromResult: ({ data }) => ({
|
||||||
@ -89,11 +94,10 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
|||||||
intermediatesCount,
|
intermediatesCount,
|
||||||
isLoading: isLoadingClearIntermediates,
|
isLoading: isLoadingClearIntermediates,
|
||||||
refetchIntermediatesCount,
|
refetchIntermediatesCount,
|
||||||
} = useClearIntermediates(shouldShowClearIntermediates);
|
} = useClearIntermediates(Boolean(config?.shouldShowClearIntermediates));
|
||||||
|
const settingsModal = useSettingsModal();
|
||||||
const { isOpen: isSettingsModalOpen, onOpen: _onSettingsModalOpen, onClose: onSettingsModalClose } = useDisclosure();
|
const settingsModalIsOpen = useStore(settingsModal.$boolean);
|
||||||
|
const refreshModal = useRefreshAfterResetModal();
|
||||||
const { isOpen: isRefreshModalOpen, onOpen: onRefreshModalOpen, onClose: onRefreshModalClose } = useDisclosure();
|
|
||||||
|
|
||||||
const shouldUseCpuNoise = useAppSelector(selectShouldUseCPUNoise);
|
const shouldUseCpuNoise = useAppSelector(selectShouldUseCPUNoise);
|
||||||
const shouldConfirmOnDelete = useAppSelector(selectSystemShouldConfirmOnDelete);
|
const shouldConfirmOnDelete = useAppSelector(selectSystemShouldConfirmOnDelete);
|
||||||
@ -105,25 +109,17 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
|||||||
|
|
||||||
const clearStorage = useClearStorage();
|
const clearStorage = useClearStorage();
|
||||||
|
|
||||||
const handleOpenSettingsModel = useCallback(() => {
|
useEffect(() => {
|
||||||
if (shouldShowClearIntermediates) {
|
if (settingsModalIsOpen && Boolean(config?.shouldShowClearIntermediates)) {
|
||||||
refetchIntermediatesCount();
|
refetchIntermediatesCount();
|
||||||
}
|
}
|
||||||
_onSettingsModalOpen();
|
}, [config?.shouldShowClearIntermediates, refetchIntermediatesCount, settingsModalIsOpen]);
|
||||||
}, [_onSettingsModalOpen, refetchIntermediatesCount, shouldShowClearIntermediates]);
|
|
||||||
|
|
||||||
const handleClickResetWebUI = useCallback(() => {
|
const handleClickResetWebUI = useCallback(() => {
|
||||||
clearStorage();
|
clearStorage();
|
||||||
onSettingsModalClose();
|
settingsModal.setFalse();
|
||||||
onRefreshModalOpen();
|
refreshModal.setTrue();
|
||||||
setInterval(() => setCountdown((prev) => prev - 1), 1000);
|
}, [clearStorage, settingsModal, refreshModal]);
|
||||||
}, [clearStorage, onSettingsModalClose, onRefreshModalOpen]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (countdown <= 0) {
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
}, [countdown]);
|
|
||||||
|
|
||||||
const handleChangeShouldConfirmOnDelete = useCallback(
|
const handleChangeShouldConfirmOnDelete = useCallback(
|
||||||
(e: ChangeEvent<HTMLInputElement>) => {
|
(e: ChangeEvent<HTMLInputElement>) => {
|
||||||
@ -169,139 +165,107 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Modal isOpen={settingsModalIsOpen} onClose={settingsModal.setFalse} size="2xl" isCentered useInert={false}>
|
||||||
{cloneElement(children, {
|
<ModalOverlay />
|
||||||
onClick: handleOpenSettingsModel,
|
<ModalContent maxH="80vh" h="68rem">
|
||||||
})}
|
<ModalHeader bg="none">{t('common.settingsLabel')}</ModalHeader>
|
||||||
|
<ModalCloseButton />
|
||||||
|
<ModalBody display="flex" flexDir="column" gap={4}>
|
||||||
|
<ScrollableContent>
|
||||||
|
<Flex flexDir="column" gap={4}>
|
||||||
|
<FormControlGroup formLabelProps={{ flexGrow: 1 }}>
|
||||||
|
<StickyScrollable title={t('settings.general')}>
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel>{t('settings.confirmOnDelete')}</FormLabel>
|
||||||
|
<Switch isChecked={shouldConfirmOnDelete} onChange={handleChangeShouldConfirmOnDelete} />
|
||||||
|
</FormControl>
|
||||||
|
</StickyScrollable>
|
||||||
|
|
||||||
<Modal isOpen={isSettingsModalOpen} onClose={onSettingsModalClose} size="2xl" isCentered>
|
<StickyScrollable title={t('settings.generation')}>
|
||||||
<ModalOverlay />
|
<FormControl isDisabled={!isNSFWCheckerAvailable}>
|
||||||
<ModalContent maxH="80vh" h="68rem">
|
<FormLabel>{t('settings.enableNSFWChecker')}</FormLabel>
|
||||||
<ModalHeader bg="none">{t('common.settingsLabel')}</ModalHeader>
|
<Switch isChecked={shouldUseNSFWChecker} onChange={handleChangeShouldUseNSFWChecker} />
|
||||||
<ModalCloseButton />
|
</FormControl>
|
||||||
<ModalBody display="flex" flexDir="column" gap={4}>
|
<FormControl isDisabled={!isWatermarkerAvailable}>
|
||||||
<ScrollableContent>
|
<FormLabel>{t('settings.enableInvisibleWatermark')}</FormLabel>
|
||||||
<Flex flexDir="column" gap={4}>
|
<Switch isChecked={shouldUseWatermarker} onChange={handleChangeShouldUseWatermarker} />
|
||||||
<FormControlGroup formLabelProps={{ flexGrow: 1 }}>
|
</FormControl>
|
||||||
<StickyScrollable title={t('settings.general')}>
|
</StickyScrollable>
|
||||||
<FormControl>
|
|
||||||
<FormLabel>{t('settings.confirmOnDelete')}</FormLabel>
|
<StickyScrollable title={t('settings.ui')}>
|
||||||
<Switch isChecked={shouldConfirmOnDelete} onChange={handleChangeShouldConfirmOnDelete} />
|
<FormControl>
|
||||||
</FormControl>
|
<FormLabel>{t('settings.showProgressInViewer')}</FormLabel>
|
||||||
|
<Switch isChecked={shouldShowProgressInViewer} onChange={handleChangeShouldShowProgressInViewer} />
|
||||||
|
</FormControl>
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel>{t('settings.antialiasProgressImages')}</FormLabel>
|
||||||
|
<Switch
|
||||||
|
isChecked={shouldAntialiasProgressImage}
|
||||||
|
onChange={handleChangeShouldAntialiasProgressImage}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormControl>
|
||||||
|
<InformationalPopover feature="noiseUseCPU" inPortal={false}>
|
||||||
|
<FormLabel>{t('parameters.useCpuNoise')}</FormLabel>
|
||||||
|
</InformationalPopover>
|
||||||
|
<Switch isChecked={shouldUseCpuNoise} onChange={handleChangeShouldUseCpuNoise} />
|
||||||
|
</FormControl>
|
||||||
|
{Boolean(config?.shouldShowLocalizationToggle) && <SettingsLanguageSelect />}
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel>{t('settings.enableInformationalPopovers')}</FormLabel>
|
||||||
|
<Switch
|
||||||
|
isChecked={shouldEnableInformationalPopovers}
|
||||||
|
onChange={handleChangeShouldEnableInformationalPopovers}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</StickyScrollable>
|
||||||
|
|
||||||
|
{Boolean(config?.shouldShowDeveloperSettings) && (
|
||||||
|
<StickyScrollable title={t('settings.developer')}>
|
||||||
|
<SettingsDeveloperLogIsEnabled />
|
||||||
|
<SettingsDeveloperLogLevel />
|
||||||
|
<SettingsDeveloperLogNamespaces />
|
||||||
</StickyScrollable>
|
</StickyScrollable>
|
||||||
|
)}
|
||||||
|
|
||||||
<StickyScrollable title={t('settings.generation')}>
|
{Boolean(config?.shouldShowClearIntermediates) && (
|
||||||
<FormControl isDisabled={!isNSFWCheckerAvailable}>
|
<StickyScrollable title={t('settings.clearIntermediates')}>
|
||||||
<FormLabel>{t('settings.enableNSFWChecker')}</FormLabel>
|
<Button
|
||||||
<Switch isChecked={shouldUseNSFWChecker} onChange={handleChangeShouldUseNSFWChecker} />
|
tooltip={hasPendingItems ? t('settings.clearIntermediatesDisabled') : undefined}
|
||||||
</FormControl>
|
colorScheme="warning"
|
||||||
<FormControl isDisabled={!isWatermarkerAvailable}>
|
onClick={clearIntermediates}
|
||||||
<FormLabel>{t('settings.enableInvisibleWatermark')}</FormLabel>
|
isLoading={isLoadingClearIntermediates}
|
||||||
<Switch isChecked={shouldUseWatermarker} onChange={handleChangeShouldUseWatermarker} />
|
isDisabled={!intermediatesCount || hasPendingItems}
|
||||||
</FormControl>
|
>
|
||||||
</StickyScrollable>
|
{t('settings.clearIntermediatesWithCount', {
|
||||||
|
count: intermediatesCount ?? 0,
|
||||||
<StickyScrollable title={t('settings.ui')}>
|
})}
|
||||||
<FormControl>
|
|
||||||
<FormLabel>{t('settings.showProgressInViewer')}</FormLabel>
|
|
||||||
<Switch
|
|
||||||
isChecked={shouldShowProgressInViewer}
|
|
||||||
onChange={handleChangeShouldShowProgressInViewer}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormControl>
|
|
||||||
<FormLabel>{t('settings.antialiasProgressImages')}</FormLabel>
|
|
||||||
<Switch
|
|
||||||
isChecked={shouldAntialiasProgressImage}
|
|
||||||
onChange={handleChangeShouldAntialiasProgressImage}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormControl>
|
|
||||||
<InformationalPopover feature="noiseUseCPU" inPortal={false}>
|
|
||||||
<FormLabel>{t('parameters.useCpuNoise')}</FormLabel>
|
|
||||||
</InformationalPopover>
|
|
||||||
<Switch isChecked={shouldUseCpuNoise} onChange={handleChangeShouldUseCpuNoise} />
|
|
||||||
</FormControl>
|
|
||||||
{shouldShowLocalizationToggle && <SettingsLanguageSelect />}
|
|
||||||
<FormControl>
|
|
||||||
<FormLabel>{t('settings.enableInformationalPopovers')}</FormLabel>
|
|
||||||
<Switch
|
|
||||||
isChecked={shouldEnableInformationalPopovers}
|
|
||||||
onChange={handleChangeShouldEnableInformationalPopovers}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
</StickyScrollable>
|
|
||||||
|
|
||||||
{shouldShowDeveloperSettings && (
|
|
||||||
<StickyScrollable title={t('settings.developer')}>
|
|
||||||
<SettingsDeveloperLogIsEnabled />
|
|
||||||
<SettingsDeveloperLogLevel />
|
|
||||||
<SettingsDeveloperLogNamespaces />
|
|
||||||
</StickyScrollable>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{shouldShowClearIntermediates && (
|
|
||||||
<StickyScrollable title={t('settings.clearIntermediates')}>
|
|
||||||
<Button
|
|
||||||
tooltip={hasPendingItems ? t('settings.clearIntermediatesDisabled') : undefined}
|
|
||||||
colorScheme="warning"
|
|
||||||
onClick={clearIntermediates}
|
|
||||||
isLoading={isLoadingClearIntermediates}
|
|
||||||
isDisabled={!intermediatesCount || hasPendingItems}
|
|
||||||
>
|
|
||||||
{t('settings.clearIntermediatesWithCount', {
|
|
||||||
count: intermediatesCount ?? 0,
|
|
||||||
})}
|
|
||||||
</Button>
|
|
||||||
<Text fontWeight="bold">{t('settings.clearIntermediatesDesc1')}</Text>
|
|
||||||
<Text variant="subtext">{t('settings.clearIntermediatesDesc2')}</Text>
|
|
||||||
<Text variant="subtext">{t('settings.clearIntermediatesDesc3')}</Text>
|
|
||||||
</StickyScrollable>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<StickyScrollable title={t('settings.resetWebUI')}>
|
|
||||||
<Button colorScheme="error" onClick={handleClickResetWebUI}>
|
|
||||||
{t('settings.resetWebUI')}
|
|
||||||
</Button>
|
</Button>
|
||||||
{shouldShowResetWebUiText && (
|
<Text fontWeight="bold">{t('settings.clearIntermediatesDesc1')}</Text>
|
||||||
<>
|
<Text variant="subtext">{t('settings.clearIntermediatesDesc2')}</Text>
|
||||||
<Text variant="subtext">{t('settings.resetWebUIDesc1')}</Text>
|
<Text variant="subtext">{t('settings.clearIntermediatesDesc3')}</Text>
|
||||||
<Text variant="subtext">{t('settings.resetWebUIDesc2')}</Text>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</StickyScrollable>
|
</StickyScrollable>
|
||||||
</FormControlGroup>
|
)}
|
||||||
</Flex>
|
|
||||||
</ScrollableContent>
|
|
||||||
</ModalBody>
|
|
||||||
|
|
||||||
<ModalFooter />
|
<StickyScrollable title={t('settings.resetWebUI')}>
|
||||||
</ModalContent>
|
<Button colorScheme="error" onClick={handleClickResetWebUI}>
|
||||||
</Modal>
|
{t('settings.resetWebUI')}
|
||||||
|
</Button>
|
||||||
<Modal
|
{Boolean(config?.shouldShowResetWebUiText) && (
|
||||||
closeOnOverlayClick={false}
|
<>
|
||||||
isOpen={isRefreshModalOpen}
|
<Text variant="subtext">{t('settings.resetWebUIDesc1')}</Text>
|
||||||
onClose={onRefreshModalClose}
|
<Text variant="subtext">{t('settings.resetWebUIDesc2')}</Text>
|
||||||
isCentered
|
</>
|
||||||
closeOnEsc={false}
|
)}
|
||||||
>
|
</StickyScrollable>
|
||||||
<ModalOverlay backdropFilter="blur(40px)" />
|
</FormControlGroup>
|
||||||
<ModalContent>
|
|
||||||
<ModalHeader />
|
|
||||||
<ModalBody>
|
|
||||||
<Flex justifyContent="center">
|
|
||||||
<Text fontSize="lg">
|
|
||||||
<Text>
|
|
||||||
{t('settings.resetComplete')} {t('settings.reloadingIn')} {countdown}...
|
|
||||||
</Text>
|
|
||||||
</Text>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</ModalBody>
|
</ScrollableContent>
|
||||||
<ModalFooter />
|
</ModalBody>
|
||||||
</ModalContent>
|
|
||||||
</Modal>
|
<ModalFooter />
|
||||||
</>
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user