mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-01-26 10:59:53 +00:00
Add server config modified message to prompt restart (#1668)
* Server config changed message * Write to settings on unmount * nit * Highlight modified config * Move modified logic to store * Add jest test * nit
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<!-- A generalized form item for rendering in a form. -->
|
||||
<template>
|
||||
<div class="form-label flex flex-grow items-center">
|
||||
<span class="text-[var(--p-text-muted-color)]">
|
||||
<span class="text-muted" :class="props.labelClass">
|
||||
<slot name="name-prefix"></slot>
|
||||
{{ props.item.name }}
|
||||
<i
|
||||
@@ -33,15 +33,11 @@ import CustomFormValue from '@/components/common/CustomFormValue.vue'
|
||||
import InputSlider from '@/components/common/InputSlider.vue'
|
||||
|
||||
const formValue = defineModel<any>('formValue')
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
item: FormItem
|
||||
id: string | undefined
|
||||
}>(),
|
||||
{
|
||||
id: undefined
|
||||
}
|
||||
)
|
||||
const props = defineProps<{
|
||||
item: FormItem
|
||||
id?: string
|
||||
labelClass?: string | Record<string, boolean>
|
||||
}>()
|
||||
|
||||
function getFormAttrs(item: FormItem) {
|
||||
const attrs = { ...(item.attrs || {}) }
|
||||
|
||||
@@ -1,4 +1,27 @@
|
||||
<template>
|
||||
<Message v-if="modifiedConfigs.length > 0" severity="info" pt:text="w-full">
|
||||
<p>
|
||||
{{ $t('serverConfig.modifiedConfigs') }}
|
||||
</p>
|
||||
<ul>
|
||||
<li v-for="config in modifiedConfigs" :key="config.id">
|
||||
{{ config.name }}: {{ config.initialValue }} → {{ config.value }}
|
||||
</li>
|
||||
</ul>
|
||||
<div class="flex justify-end gap-2">
|
||||
<Button
|
||||
:label="$t('serverConfig.revertChanges')"
|
||||
@click="revertChanges"
|
||||
outlined
|
||||
/>
|
||||
<Button
|
||||
:label="$t('serverConfig.restart')"
|
||||
@click="restartApp"
|
||||
outlined
|
||||
severity="danger"
|
||||
/>
|
||||
</div>
|
||||
</Message>
|
||||
<div
|
||||
v-for="([label, items], i) in Object.entries(serverConfigsByCategory)"
|
||||
:key="label"
|
||||
@@ -6,32 +29,48 @@
|
||||
<Divider v-if="i > 0" />
|
||||
<h3>{{ formatCamelCase(label) }}</h3>
|
||||
<div v-for="item in items" :key="item.name" class="flex items-center mb-4">
|
||||
<FormItem :item="item" v-model:formValue="item.value" />
|
||||
<FormItem
|
||||
:item="item"
|
||||
v-model:formValue="item.value"
|
||||
:id="item.id"
|
||||
:labelClass="{
|
||||
'text-highlight': item.initialValue !== item.value
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Button from 'primevue/button'
|
||||
import Message from 'primevue/message'
|
||||
import Divider from 'primevue/divider'
|
||||
import FormItem from '@/components/common/FormItem.vue'
|
||||
import { formatCamelCase } from '@/utils/formatUtil'
|
||||
import { useSettingStore } from '@/stores/settingStore'
|
||||
import { useServerConfigStore } from '@/stores/serverConfigStore'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { onMounted, watch } from 'vue'
|
||||
import { SERVER_CONFIG_ITEMS } from '@/constants/serverConfig'
|
||||
import { electronAPI } from '@/utils/envUtil'
|
||||
import { useSettingStore } from '@/stores/settingStore'
|
||||
import { watch } from 'vue'
|
||||
|
||||
const settingStore = useSettingStore()
|
||||
const serverConfigStore = useServerConfigStore()
|
||||
const { serverConfigsByCategory, launchArgs, serverConfigValues } =
|
||||
storeToRefs(serverConfigStore)
|
||||
const {
|
||||
serverConfigsByCategory,
|
||||
serverConfigValues,
|
||||
launchArgs,
|
||||
modifiedConfigs
|
||||
} = storeToRefs(serverConfigStore)
|
||||
|
||||
onMounted(() => {
|
||||
serverConfigStore.loadServerConfig(
|
||||
SERVER_CONFIG_ITEMS,
|
||||
settingStore.get('Comfy.Server.ServerConfigValues')
|
||||
)
|
||||
})
|
||||
const revertChanges = () => {
|
||||
for (const config of modifiedConfigs.value) {
|
||||
config.value = config.initialValue
|
||||
}
|
||||
}
|
||||
|
||||
const restartApp = () => {
|
||||
electronAPI().restartApp()
|
||||
}
|
||||
|
||||
watch(launchArgs, (newVal) => {
|
||||
settingStore.set('Comfy.Server.LaunchArgs', newVal)
|
||||
|
||||
@@ -107,6 +107,14 @@ import { electronAPI as getElectronAPI, isElectron } from '@/utils/envUtil'
|
||||
// TODO(huchenlei): Add a confirmation dialog.
|
||||
electronAPI.reinstall()
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'Comfy-Desktop.Restart',
|
||||
label: 'Restart',
|
||||
icon: 'pi pi-refresh',
|
||||
function() {
|
||||
electronAPI.restartApp()
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
@@ -65,6 +65,12 @@ const messages = {
|
||||
error: 'Unable to start ComfyUI'
|
||||
}
|
||||
},
|
||||
serverConfig: {
|
||||
modifiedConfigs:
|
||||
'You have modified the following server configurations. Restart to apply changes.',
|
||||
revertChanges: 'Revert Changes',
|
||||
restart: 'Restart'
|
||||
},
|
||||
firstTimeUIMessage:
|
||||
'This is the first time you use the new UI. Choose "Menu > Use New Menu > Disabled" to restore the old UI.',
|
||||
download: 'Download',
|
||||
|
||||
@@ -3,7 +3,14 @@ import { defineStore } from 'pinia'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
export type ServerConfigWithValue<T> = ServerConfig<T> & {
|
||||
/**
|
||||
* Current value.
|
||||
*/
|
||||
value: T
|
||||
/**
|
||||
* Initial value loaded from settings.
|
||||
*/
|
||||
initialValue: T
|
||||
}
|
||||
|
||||
export const useServerConfigStore = defineStore('serverConfig', () => {
|
||||
@@ -11,6 +18,12 @@ export const useServerConfigStore = defineStore('serverConfig', () => {
|
||||
const serverConfigs = computed(() => {
|
||||
return Object.values(serverConfigById.value)
|
||||
})
|
||||
const modifiedConfigs = computed<ServerConfigWithValue<any>[]>(() => {
|
||||
return serverConfigs.value.filter((config) => {
|
||||
return config.initialValue !== config.value
|
||||
})
|
||||
})
|
||||
|
||||
const serverConfigsByCategory = computed<
|
||||
Record<string, ServerConfigWithValue<any>[]>
|
||||
>(() => {
|
||||
@@ -55,9 +68,11 @@ export const useServerConfigStore = defineStore('serverConfig', () => {
|
||||
values: Record<string, any>
|
||||
) {
|
||||
for (const config of configs) {
|
||||
const value = values[config.id] ?? config.defaultValue
|
||||
serverConfigById.value[config.id] = {
|
||||
...config,
|
||||
value: values[config.id] ?? config.defaultValue
|
||||
value,
|
||||
initialValue: value
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,6 +80,7 @@ export const useServerConfigStore = defineStore('serverConfig', () => {
|
||||
return {
|
||||
serverConfigById,
|
||||
serverConfigs,
|
||||
modifiedConfigs,
|
||||
serverConfigsByCategory,
|
||||
serverConfigValues,
|
||||
launchArgs,
|
||||
|
||||
@@ -35,6 +35,8 @@ import { useNodeBookmarkStore } from '@/stores/nodeBookmarkStore'
|
||||
import { useNodeDefStore, useNodeFrequencyStore } from '@/stores/nodeDefStore'
|
||||
import { useBottomPanelStore } from '@/stores/workspace/bottomPanelStore'
|
||||
import { useModelStore } from '@/stores/modelStore'
|
||||
import { useServerConfigStore } from '@/stores/serverConfigStore'
|
||||
import { SERVER_CONFIG_ITEMS } from '@/constants/serverConfig'
|
||||
|
||||
setupAutoQueueHandler()
|
||||
|
||||
@@ -151,6 +153,12 @@ const onGraphReady = () => {
|
||||
// Load keybindings.
|
||||
useKeybindingStore().loadUserKeybindings()
|
||||
|
||||
// Load server config
|
||||
useServerConfigStore().loadServerConfig(
|
||||
SERVER_CONFIG_ITEMS,
|
||||
settingStore.get('Comfy.Server.ServerConfigValues')
|
||||
)
|
||||
|
||||
// Load model folders
|
||||
useModelStore().loadModelFolders()
|
||||
|
||||
|
||||
@@ -177,7 +177,8 @@ export default {
|
||||
},
|
||||
|
||||
textColor: {
|
||||
muted: 'var(--p-text-muted-color)'
|
||||
muted: 'var(--p-text-muted-color)',
|
||||
highlight: 'var(--p-primary-color)'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -186,4 +186,41 @@ describe('useServerConfigStore', () => {
|
||||
'test.config3'
|
||||
])
|
||||
})
|
||||
|
||||
it('should track modified configs', () => {
|
||||
const configs = [
|
||||
{
|
||||
...dummyFormItem,
|
||||
id: 'test.config1',
|
||||
defaultValue: 'default1'
|
||||
},
|
||||
{
|
||||
...dummyFormItem,
|
||||
id: 'test.config2',
|
||||
defaultValue: 'default2'
|
||||
}
|
||||
]
|
||||
|
||||
store.loadServerConfig(configs, {
|
||||
'test.config1': 'initial1'
|
||||
})
|
||||
|
||||
// Initially no modified configs
|
||||
expect(store.modifiedConfigs).toHaveLength(0)
|
||||
|
||||
// Modify config1's value after loading
|
||||
store.serverConfigById['test.config1'].value = 'custom1'
|
||||
|
||||
// Now config1 should be in modified configs
|
||||
expect(store.modifiedConfigs).toHaveLength(1)
|
||||
expect(store.modifiedConfigs[0].id).toBe('test.config1')
|
||||
expect(store.modifiedConfigs[0].value).toBe('custom1')
|
||||
expect(store.modifiedConfigs[0].initialValue).toBe('initial1')
|
||||
|
||||
// Change config1 back to default
|
||||
store.serverConfigById['test.config1'].value = 'initial1'
|
||||
|
||||
// Should go back to no modified configs
|
||||
expect(store.modifiedConfigs).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -10,6 +10,9 @@ const mockElectronAPI: Plugin = {
|
||||
{
|
||||
tag: 'script',
|
||||
children: `window.electronAPI = {
|
||||
restartApp: () => {
|
||||
alert('restartApp')
|
||||
},
|
||||
sendReady: () => {},
|
||||
onShowSelectDirectory: () => {},
|
||||
onFirstTimeSetupComplete: () => {},
|
||||
|
||||
Reference in New Issue
Block a user