jbilcke-hf HF staff commited on
Commit
57224ff
β€’
1 Parent(s): 9a9fd5a

improving config panels + timeline + logo

Browse files
Files changed (35) hide show
  1. package-lock.json +51 -51
  2. package.json +2 -2
  3. src/app/main.tsx +2 -2
  4. src/components/settings/constants.ts +64 -1
  5. src/components/settings/index.tsx +27 -27
  6. src/components/tags/colors.ts +1 -0
  7. src/components/tags/types.ts +1 -0
  8. src/components/toolbars/top-bar/index.tsx +1 -13
  9. src/components/toolbars/top-menu/image/index.tsx +12 -4
  10. src/components/toolbars/top-menu/index.tsx +18 -1
  11. src/components/toolbars/top-menu/lists/ImageGenerationModelList.tsx +55 -0
  12. src/components/toolbars/top-menu/{ModelList.tsx β†’ lists/ImageUpscalingModelList.tsx} +10 -5
  13. src/components/toolbars/top-menu/lists/MusicGenerationModelList.tsx +55 -0
  14. src/components/toolbars/top-menu/{ProviderList.tsx β†’ lists/ProviderList.tsx} +0 -0
  15. src/components/toolbars/top-menu/{RenderingStrategyList.tsx β†’ lists/RenderingStrategyList.tsx} +1 -1
  16. src/components/toolbars/top-menu/lists/SoundGenerationModelList.tsx +55 -0
  17. src/components/toolbars/top-menu/lists/VideoGenerationModelList.tsx +55 -0
  18. src/components/toolbars/top-menu/lists/VideoUpscalingModelList.tsx +55 -0
  19. src/components/toolbars/top-menu/lists/VoiceGenerationModelList.tsx +55 -0
  20. src/components/toolbars/top-menu/music/index.tsx +4 -4
  21. src/components/toolbars/top-menu/sound/index.tsx +4 -4
  22. src/components/toolbars/top-menu/video/index.tsx +12 -4
  23. src/components/toolbars/top-menu/voice/index.tsx +8 -4
  24. src/components/ui/menubar.tsx +2 -2
  25. src/controllers/settings/getDefaultSettingsState.ts +11 -0
  26. src/controllers/settings/types.ts +21 -0
  27. src/controllers/settings/useSettings.ts +53 -1
  28. src/controllers/ui/getDefaultUIState.ts +2 -1
  29. src/controllers/ui/types.ts +4 -2
  30. src/controllers/ui/useUI.ts +2 -1
  31. src/lib/core/constants.ts +2 -2
  32. src/lib/hf/getMyGradioSpaces.ts +55 -0
  33. src/lib/hf/types.ts +5 -0
  34. src/lib/hf/useMyGradioSpaces.ts +27 -0
  35. src/types.ts +11 -0
package-lock.json CHANGED
@@ -10,9 +10,9 @@
10
  "dependencies": {
11
  "@aitube/clap": "0.0.24",
12
  "@aitube/engine": "0.0.15",
13
- "@aitube/timeline": "file:/Users/jbilcke/Projects/Typescript_Libraries/aitube-timeline",
14
  "@fal-ai/serverless-client": "^0.10.3",
15
- "@huggingface/hub": "^0.15.0",
16
  "@huggingface/inference": "^2.7.0",
17
  "@langchain/anthropic": "^0.2.0",
18
  "@langchain/core": "^0.2.6",
@@ -86,28 +86,33 @@
86
  "zustand": "^4.5.2"
87
  }
88
  },
89
- "../Typescript_Libraries/aitube-timeline": {
 
 
 
 
 
 
 
 
 
 
 
90
  "version": "0.0.15",
91
- "license": "MIT",
 
 
 
 
 
 
 
 
 
92
  "dependencies": {
93
  "date-fns": "^3.6.0",
94
  "react-virtualized-auto-sizer": "^1.0.24"
95
  },
96
- "devDependencies": {
97
- "@types/react": "*",
98
- "@types/react-dom": "*",
99
- "@typescript-eslint/eslint-plugin": "^7.2.0",
100
- "@typescript-eslint/parser": "^7.2.0",
101
- "@vitejs/plugin-react": "^4.2.1",
102
- "bun-types": "latest",
103
- "eslint": "^8.57.0",
104
- "eslint-plugin-react-hooks": "^4.6.0",
105
- "eslint-plugin-react-refresh": "^0.4.6",
106
- "prettier": "^3.3.0",
107
- "rimraf": "^5.0.7",
108
- "typescript": "^5.4.5",
109
- "vite": "^5.2.0"
110
- },
111
  "peerDependencies": {
112
  "@aitube/clap": "0.0.24",
113
  "@radix-ui/react-slider": "^1.1.2",
@@ -125,29 +130,6 @@
125
  "zustand": "4.5.2"
126
  }
127
  },
128
- "node_modules/@aitube/clap": {
129
- "version": "0.0.24",
130
- "resolved": "https://registry.npmjs.org/@aitube/clap/-/clap-0.0.24.tgz",
131
- "integrity": "sha512-iMmxyPmVh1LWNUlWKK2rRnCSZ/CLmBeb1ADNr5pj0dFI51NNezipYXjZv9dBOb5y3FKBkL+jbEcy7kQFgKHhpw==",
132
- "dependencies": {
133
- "pure-uuid": "^1.8.1"
134
- },
135
- "peerDependencies": {
136
- "yaml": "^2.4.3"
137
- }
138
- },
139
- "node_modules/@aitube/engine": {
140
- "version": "0.0.15",
141
- "resolved": "https://registry.npmjs.org/@aitube/engine/-/engine-0.0.15.tgz",
142
- "integrity": "sha512-SxlTGOLHNPh93PY/hCXuNgCUWV7Uky9Q4mBKS4uA7+gReeYBT//x/sAWqIvV8MEj2dkx1Br3iTse1/rcVay49w==",
143
- "peerDependencies": {
144
- "@aitube/clap": "0.0.24"
145
- }
146
- },
147
- "node_modules/@aitube/timeline": {
148
- "resolved": "../Typescript_Libraries/aitube-timeline",
149
- "link": true
150
- },
151
  "node_modules/@alloc/quick-lru": {
152
  "version": "5.2.0",
153
  "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
@@ -774,9 +756,9 @@
774
  }
775
  },
776
  "node_modules/@huggingface/tasks": {
777
- "version": "0.10.11",
778
- "resolved": "https://registry.npmjs.org/@huggingface/tasks/-/tasks-0.10.11.tgz",
779
- "integrity": "sha512-talNbXgxT8fsqt8DhhF7mNZxfeCc8fAJWe1yquBzd4pA4PH/J504Z41uijo36HNoI8q3KGZ89A884sIcG3ak6Q=="
780
  },
781
  "node_modules/@humanwhocodes/config-array": {
782
  "version": "0.11.14",
@@ -4533,6 +4515,15 @@
4533
  "url": "https://github.com/sponsors/ljharb"
4534
  }
4535
  },
 
 
 
 
 
 
 
 
 
4536
  "node_modules/debounce": {
4537
  "version": "1.2.1",
4538
  "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
@@ -4755,9 +4746,9 @@
4755
  "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
4756
  },
4757
  "node_modules/electron-to-chromium": {
4758
- "version": "1.4.794",
4759
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.794.tgz",
4760
- "integrity": "sha512-6FApLtsYhDCY0Vglq3AptsdxQ+PJLc6AxlAM0HjEihUAiOPPbkASEsq9gtxUeZY9o0sJIEa3WnF0vVH4VT4iug=="
4761
  },
4762
  "node_modules/emoji-regex": {
4763
  "version": "9.2.2",
@@ -7366,9 +7357,9 @@
7366
  }
7367
  },
7368
  "node_modules/openai": {
7369
- "version": "4.49.0",
7370
- "resolved": "https://registry.npmjs.org/openai/-/openai-4.49.0.tgz",
7371
- "integrity": "sha512-/UkrBSej5ejZ4vnOFoeFefX7erjp4k3+xoLKkswjLEvgBU9QtCnOUgsfpvHkzTzgDXpqPMCzyQHQXWsgiq2xPw==",
7372
  "dependencies": {
7373
  "@types/node": "^18.11.18",
7374
  "@types/node-fetch": "^2.6.4",
@@ -8180,6 +8171,15 @@
8180
  "react-dom": ">=16.13"
8181
  }
8182
  },
 
 
 
 
 
 
 
 
 
8183
  "node_modules/read-cache": {
8184
  "version": "1.0.0",
8185
  "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
 
10
  "dependencies": {
11
  "@aitube/clap": "0.0.24",
12
  "@aitube/engine": "0.0.15",
13
+ "@aitube/timeline": "0.0.16",
14
  "@fal-ai/serverless-client": "^0.10.3",
15
+ "@huggingface/hub": "^0.15.1",
16
  "@huggingface/inference": "^2.7.0",
17
  "@langchain/anthropic": "^0.2.0",
18
  "@langchain/core": "^0.2.6",
 
86
  "zustand": "^4.5.2"
87
  }
88
  },
89
+ "node_modules/@aitube/clap": {
90
+ "version": "0.0.24",
91
+ "resolved": "https://registry.npmjs.org/@aitube/clap/-/clap-0.0.24.tgz",
92
+ "integrity": "sha512-iMmxyPmVh1LWNUlWKK2rRnCSZ/CLmBeb1ADNr5pj0dFI51NNezipYXjZv9dBOb5y3FKBkL+jbEcy7kQFgKHhpw==",
93
+ "dependencies": {
94
+ "pure-uuid": "^1.8.1"
95
+ },
96
+ "peerDependencies": {
97
+ "yaml": "^2.4.3"
98
+ }
99
+ },
100
+ "node_modules/@aitube/engine": {
101
  "version": "0.0.15",
102
+ "resolved": "https://registry.npmjs.org/@aitube/engine/-/engine-0.0.15.tgz",
103
+ "integrity": "sha512-SxlTGOLHNPh93PY/hCXuNgCUWV7Uky9Q4mBKS4uA7+gReeYBT//x/sAWqIvV8MEj2dkx1Br3iTse1/rcVay49w==",
104
+ "peerDependencies": {
105
+ "@aitube/clap": "0.0.24"
106
+ }
107
+ },
108
+ "node_modules/@aitube/timeline": {
109
+ "version": "0.0.16",
110
+ "resolved": "https://registry.npmjs.org/@aitube/timeline/-/timeline-0.0.16.tgz",
111
+ "integrity": "sha512-Jva0nt7LC9XPwFR9yNfK/MnK7Qj/wWtR3nwkP1Xs5zH7U6I4Wm6D9cm4RpLs/nZ5nDZyPgJRuw0mX8Vq9CUQgQ==",
112
  "dependencies": {
113
  "date-fns": "^3.6.0",
114
  "react-virtualized-auto-sizer": "^1.0.24"
115
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  "peerDependencies": {
117
  "@aitube/clap": "0.0.24",
118
  "@radix-ui/react-slider": "^1.1.2",
 
130
  "zustand": "4.5.2"
131
  }
132
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  "node_modules/@alloc/quick-lru": {
134
  "version": "5.2.0",
135
  "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
 
756
  }
757
  },
758
  "node_modules/@huggingface/tasks": {
759
+ "version": "0.10.12",
760
+ "resolved": "https://registry.npmjs.org/@huggingface/tasks/-/tasks-0.10.12.tgz",
761
+ "integrity": "sha512-bpW2+ey2SBoEzSvn0eTmE+loLM3/B0Nw2BQQt0xWfafkNrR8xd8Hhc+aH8KdBsWko5YSSUSxb5vS1VenQ6q+/w=="
762
  },
763
  "node_modules/@humanwhocodes/config-array": {
764
  "version": "0.11.14",
 
4515
  "url": "https://github.com/sponsors/ljharb"
4516
  }
4517
  },
4518
+ "node_modules/date-fns": {
4519
+ "version": "3.6.0",
4520
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
4521
+ "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
4522
+ "funding": {
4523
+ "type": "github",
4524
+ "url": "https://github.com/sponsors/kossnocorp"
4525
+ }
4526
+ },
4527
  "node_modules/debounce": {
4528
  "version": "1.2.1",
4529
  "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
 
4746
  "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
4747
  },
4748
  "node_modules/electron-to-chromium": {
4749
+ "version": "1.4.796",
4750
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.796.tgz",
4751
+ "integrity": "sha512-NglN/xprcM+SHD2XCli4oC6bWe6kHoytcyLKCWXmRL854F0qhPhaYgUswUsglnPxYaNQIg2uMY4BvaomIf3kLA=="
4752
  },
4753
  "node_modules/emoji-regex": {
4754
  "version": "9.2.2",
 
7357
  }
7358
  },
7359
  "node_modules/openai": {
7360
+ "version": "4.49.1",
7361
+ "resolved": "https://registry.npmjs.org/openai/-/openai-4.49.1.tgz",
7362
+ "integrity": "sha512-bsFSNhhTNon+g6r4UYPKGLi+PlfP1G9TJGSkZS5nZx+PTwW2YUTlfxXxpOKrPab5auIXJdlYpC/g/wkHGR1xug==",
7363
  "dependencies": {
7364
  "@types/node": "^18.11.18",
7365
  "@types/node-fetch": "^2.6.4",
 
8171
  "react-dom": ">=16.13"
8172
  }
8173
  },
8174
+ "node_modules/react-virtualized-auto-sizer": {
8175
+ "version": "1.0.24",
8176
+ "resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.24.tgz",
8177
+ "integrity": "sha512-3kCn7N9NEb3FlvJrSHWGQ4iVl+ydQObq2fHMn12i5wbtm74zHOPhz/i64OL3c1S1vi9i2GXtZqNqUJTQ+BnNfg==",
8178
+ "peerDependencies": {
8179
+ "react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0",
8180
+ "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0"
8181
+ }
8182
+ },
8183
  "node_modules/read-cache": {
8184
  "version": "1.0.0",
8185
  "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
package.json CHANGED
@@ -12,9 +12,9 @@
12
  "dependencies": {
13
  "@aitube/clap": "0.0.24",
14
  "@aitube/engine": "0.0.15",
15
- "@aitube/timeline": "file:/Users/jbilcke/Projects/Typescript_Libraries/aitube-timeline",
16
  "@fal-ai/serverless-client": "^0.10.3",
17
- "@huggingface/hub": "^0.15.0",
18
  "@huggingface/inference": "^2.7.0",
19
  "@langchain/anthropic": "^0.2.0",
20
  "@langchain/core": "^0.2.6",
 
12
  "dependencies": {
13
  "@aitube/clap": "0.0.24",
14
  "@aitube/engine": "0.0.15",
15
+ "@aitube/timeline": "0.0.16",
16
  "@fal-ai/serverless-client": "^0.10.3",
17
+ "@huggingface/hub": "^0.15.1",
18
  "@huggingface/inference": "^2.7.0",
19
  "@langchain/anthropic": "^0.2.0",
20
  "@langchain/core": "^0.2.6",
src/app/main.tsx CHANGED
@@ -54,8 +54,8 @@ export function Main() {
54
  <ReflexSplitter />
55
  <ReflexElement
56
  size={showTimeline ? 600 : 1}
57
- minSize={showTimeline ? 150 : 1}
58
- maxSize={showTimeline ? 1200 : 1}
59
  >
60
  <Timeline />
61
  </ReflexElement>
 
54
  <ReflexSplitter />
55
  <ReflexElement
56
  size={showTimeline ? 600 : 1}
57
+ minSize={showTimeline ? 100 : 1}
58
+ maxSize={showTimeline ? 8200 : 1}
59
  >
60
  <Timeline />
61
  </ReflexElement>
src/components/settings/constants.ts CHANGED
@@ -1,6 +1,5 @@
1
  import { ComfyIcuAccelerator, ComputeProvider } from "@/types"
2
 
3
-
4
  export const computeProviderShortNames = {
5
  [ComputeProvider.NONE]: "None",
6
  [ComputeProvider.CUSTOM]: "Custom API",
@@ -77,3 +76,67 @@ export const availableComfyIcuAccelerators = {
77
  [ComfyIcuAccelerator.A100_80GB]: "A100 (80 GB)",
78
  [ComfyIcuAccelerator.H100]: "H100",
79
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import { ComfyIcuAccelerator, ComputeProvider } from "@/types"
2
 
 
3
  export const computeProviderShortNames = {
4
  [ComputeProvider.NONE]: "None",
5
  [ComputeProvider.CUSTOM]: "Custom API",
 
76
  [ComfyIcuAccelerator.A100_80GB]: "A100 (80 GB)",
77
  [ComfyIcuAccelerator.H100]: "H100",
78
  }
79
+
80
+ export const availableModelsForAssistant: Partial<Record<ComputeProvider, string[]>> = {
81
+ [ComputeProvider.OPENAI]: [
82
+ "gpt-4o",
83
+ ]
84
+ }
85
+
86
+ export const availableModelsForAssistantTurbo: Partial<Record<ComputeProvider, string[]>> = {
87
+ [ComputeProvider.OPENAI]: [
88
+ "gpt-4-turbo"
89
+ ]
90
+ }
91
+
92
+
93
+ // note: each of those models do different things, have different parameters..
94
+ // so it will have to be taken into account
95
+ export const availableModelsForImageGeneration: Partial<Record<ComputeProvider, string[]>> = {
96
+ [ComputeProvider.FALAI]: [
97
+ "fal-ai/fast-sdxl",
98
+ "fal-ai/stable-cascade",
99
+ "fal-ai/fast-lightning-sdxl",
100
+ "fal-ai/hyper-sdxl",
101
+ // "fal-ai/photomaker",
102
+ // "fal-ai/pulid",
103
+ // "fal-ai/image-to-image",
104
+ // "fal-ai/omni-zero",
105
+ ]
106
+ }
107
+
108
+ // should we call this upscaling or post-processing?
109
+ export const availableModelsForImageUpscaling: Partial<Record<ComputeProvider, string[]>> = {
110
+ [ComputeProvider.FALAI]: [
111
+ "fal-ai/ccsr",
112
+ ]
113
+ }
114
+
115
+ export const availableModelsForVideoGeneration: Partial<Record<ComputeProvider, string[]>> = {
116
+ [ComputeProvider.FALAI]: [
117
+ "fal-ai/stable-video",
118
+ ]
119
+ }
120
+
121
+ export const availableModelsForVideoUpscaling: Partial<Record<ComputeProvider, string[]>> = {
122
+ [ComputeProvider.FALAI]: [
123
+ ]
124
+ }
125
+
126
+ export const availableModelsForSoundGeneration: Partial<Record<ComputeProvider, string[]>> = {
127
+ [ComputeProvider.FALAI]: [
128
+ "fal-ai/stable-audio"
129
+ ]
130
+ }
131
+
132
+ export const availableModelsForVoiceGeneration: Partial<Record<ComputeProvider, string[]>> = {
133
+ [ComputeProvider.FALAI]: [
134
+ "fal-ai/metavoice-v1"
135
+ ]
136
+ }
137
+
138
+ export const availableModelsForMusicGeneration: Partial<Record<ComputeProvider, string[]>> = {
139
+ [ComputeProvider.FALAI]: [
140
+ "fal-ai/stable-audio"
141
+ ]
142
+ }
src/components/settings/index.tsx CHANGED
@@ -13,37 +13,37 @@ import { SettingsSectionVideo } from "./video"
13
  import { SettingsSectionSound } from "./sound"
14
  import { SettingsSectionMusic } from "./music"
15
  import { SettingsSectionVoice } from "./voice"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
  export function SettingsDialog() {
18
 
19
  const showSettings = useUI(s => s.showSettings)
20
  const setShowSettings = useUI(s => s.setShowSettings)
21
- const [_isPending, startTransition] = useTransition()
22
-
23
- const panels = {
24
- provider: <SettingsSectionProvider />,
25
- assistant: <SettingsSectionAssistant />,
26
- image: <SettingsSectionImage />,
27
- video: <SettingsSectionVideo />,
28
- voice: <SettingsSectionVoice />,
29
- music: <SettingsSectionMusic />,
30
- sound: <SettingsSectionSound />,
31
- }
32
-
33
- const panelLabels = {
34
- provider: "Providers",
35
- assistant: "Assistant",
36
- image: "Image",
37
- video: "Video",
38
- voice: "Voice",
39
- music: "Music",
40
- sound: "Sound",
41
- } as any
42
-
43
- const [configPanel, setConfigPanel] = useState<keyof typeof panels>("provider")
44
 
45
  return (
46
- <Dialog open={showSettings} onOpenChange={setShowSettings}>
47
  <DialogContent className={cn(
48
  `select-none`,
49
  // DialogContent comes with some hardcoded values so we need to override them
@@ -57,7 +57,7 @@ export function SettingsDialog() {
57
  key={key}
58
  variant="ghost"
59
  className="flex flex-col capitalize w-full items-end text-right text-lg font-thin text-stone-300"
60
- onClick={() => setConfigPanel(key as keyof typeof panels)}>{panelLabels[key]}</Button>
61
  ))}
62
  </div>
63
  </ScrollArea>
@@ -69,10 +69,10 @@ export function SettingsDialog() {
69
  pl-8
70
  ">
71
  <ScrollArea className="flex flex-row h-full">
72
- {panels[configPanel]}
73
  </ScrollArea>
74
  <DialogFooter>
75
- <Button variant="outline" className=" dark:bg-stone-800 dark:text-stone-400 dark:border-stone-700 text-sm font-light" onClick={() => { setShowSettings(false) }}>Close</Button>
76
  </DialogFooter>
77
  </div>
78
  </DialogContent>
 
13
  import { SettingsSectionSound } from "./sound"
14
  import { SettingsSectionMusic } from "./music"
15
  import { SettingsSectionVoice } from "./voice"
16
+ import { SettingsCategory } from "@/types"
17
+
18
+ const panels: Record<SettingsCategory, JSX.Element> = {
19
+ [SettingsCategory.NONE]: <></>,
20
+ [SettingsCategory.PROVIDER]: <SettingsSectionProvider />,
21
+ [SettingsCategory.ASSISTANT]: <SettingsSectionAssistant />,
22
+ [SettingsCategory.IMAGE]: <SettingsSectionImage />,
23
+ [SettingsCategory.VIDEO]: <SettingsSectionVideo />,
24
+ [SettingsCategory.VOICE]: <SettingsSectionVoice />,
25
+ [SettingsCategory.SOUND]: <SettingsSectionSound />,
26
+ [SettingsCategory.MUSIC]: <SettingsSectionMusic />,
27
+ }
28
+
29
+ const panelLabels = {
30
+ [SettingsCategory.NONE]: "",
31
+ [SettingsCategory.PROVIDER]: "Providers",
32
+ [SettingsCategory.ASSISTANT]: "Assistant",
33
+ [SettingsCategory.IMAGE]: "Image",
34
+ [SettingsCategory.VIDEO]: "Video",
35
+ [SettingsCategory.VOICE]: "Voice",
36
+ [SettingsCategory.SOUND]: "Sound",
37
+ [SettingsCategory.MUSIC]: "Music",
38
+ } as any
39
 
40
  export function SettingsDialog() {
41
 
42
  const showSettings = useUI(s => s.showSettings)
43
  const setShowSettings = useUI(s => s.setShowSettings)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
  return (
46
+ <Dialog open={showSettings !== SettingsCategory.NONE} onOpenChange={(open) => setShowSettings(open ? SettingsCategory.PROVIDER : SettingsCategory.NONE)}>
47
  <DialogContent className={cn(
48
  `select-none`,
49
  // DialogContent comes with some hardcoded values so we need to override them
 
57
  key={key}
58
  variant="ghost"
59
  className="flex flex-col capitalize w-full items-end text-right text-lg font-thin text-stone-300"
60
+ onClick={() => setShowSettings(key as SettingsCategory)}>{panelLabels[key]}</Button>
61
  ))}
62
  </div>
63
  </ScrollArea>
 
69
  pl-8
70
  ">
71
  <ScrollArea className="flex flex-row h-full">
72
+ {panels[showSettings]}
73
  </ScrollArea>
74
  <DialogFooter>
75
+ <Button variant="outline" className=" dark:bg-stone-800 dark:text-stone-400 dark:border-stone-700 text-sm font-light" onClick={() => { setShowSettings(SettingsCategory.NONE) }}>Close</Button>
76
  </DialogFooter>
77
  </div>
78
  </DialogContent>
src/components/tags/colors.ts CHANGED
@@ -30,5 +30,6 @@ export const tagColorToTailwindClass: Record<TagColor, string> = {
30
  [TagColor.VIOLET]: `bg-violet-800 border-violet-600 text-violet-300`,
31
  [TagColor.FUCHSIA]: `bg-fuchsia-800 border-fuchsia-600 text-fuchsia-300`,
32
  [TagColor.PINK]: `bg-pink-800 border-pink-600 text-pink-300`,
 
33
  [TagColor.ROSE]: `bg-rose-800 border-rose-600 text-rose-300`
34
  }
 
30
  [TagColor.VIOLET]: `bg-violet-800 border-violet-600 text-violet-300`,
31
  [TagColor.FUCHSIA]: `bg-fuchsia-800 border-fuchsia-600 text-fuchsia-300`,
32
  [TagColor.PINK]: `bg-pink-800 border-pink-600 text-pink-300`,
33
+ [TagColor.PURPLE]: `bg-purple-800 border-purple-600 text-purple-300`,
34
  [TagColor.ROSE]: `bg-rose-800 border-rose-600 text-rose-300`
35
  }
src/components/tags/types.ts CHANGED
@@ -33,5 +33,6 @@ export enum TagColor {
33
  VIOLET = "VIOLET",
34
  FUCHSIA = "FUCHSIA",
35
  PINK = "PINK",
 
36
  ROSE = "ROSE",
37
  }
 
33
  VIOLET = "VIOLET",
34
  FUCHSIA = "FUCHSIA",
35
  PINK = "PINK",
36
+ PURPLE = "PURPLE",
37
  ROSE = "ROSE",
38
  }
src/components/toolbars/top-bar/index.tsx CHANGED
@@ -4,7 +4,7 @@ import { useTimelineState } from "@aitube/timeline"
4
  import { cn } from "@/lib/utils"
5
 
6
  import { TopMenu } from "../top-menu"
7
- import { APP_NAME, APP_REVISION } from "@/lib/core/constants"
8
 
9
 
10
  export function TopBar() {
@@ -19,18 +19,6 @@ export function TopBar() {
19
  `border-b-stone-700`,
20
  )}>
21
  <TopMenu />
22
- <div className={cn(
23
- `absolute flex flex-row flex-grow w-full`,
24
- `items-center justify-center`,
25
- `pointer-events-none`,
26
- `text-xs text-stone-300`
27
- )}>
28
- {
29
- // clap?.meta?.title || "Untitled"
30
- }
31
- <span className="text-stone-300 mr-1">{APP_NAME}.app</span>
32
- <span className="text-stone-500">({APP_REVISION})</span>
33
- </div>
34
  </div>
35
  )
36
  }
 
4
  import { cn } from "@/lib/utils"
5
 
6
  import { TopMenu } from "../top-menu"
7
+ import { APP_DOMAIN, APP_NAME, APP_REVISION } from "@/lib/core/constants"
8
 
9
 
10
  export function TopBar() {
 
19
  `border-b-stone-700`,
20
  )}>
21
  <TopMenu />
 
 
 
 
 
 
 
 
 
 
 
 
22
  </div>
23
  )
24
  }
src/components/toolbars/top-menu/image/index.tsx CHANGED
@@ -14,15 +14,21 @@ import {
14
  import { useSettings } from "@/controllers/settings"
15
  import { useUI } from "@/controllers/ui"
16
 
17
- import { ProviderList } from "../ProviderList"
18
- import { RenderingStrategyList } from "../RenderingStrategyList"
19
  import { availableComputeProvidersForImages } from "@/components/settings/constants"
20
-
 
 
21
 
22
  export function TopMenuImage() {
23
  const setShowSettings = useUI(s => s.setShowSettings)
24
  const imageProvider = useSettings(s => s.imageProvider)
25
  const setImageProvider = useSettings(s => s.setImageProvider)
 
 
 
 
26
  const imageRenderingStrategy = useSettings((s) => s.imageRenderingStrategy)
27
  const setImageRenderingStrategy = useSettings((s) => s.setImageRenderingStrategy)
28
  return (
@@ -30,8 +36,10 @@ export function TopMenuImage() {
30
  <MenubarTrigger>Image</MenubarTrigger>
31
  <MenubarContent>
32
  <MenubarSub>
33
- <MenubarItem onClick={() => { setShowSettings(true) }}>Show advanced settings</MenubarItem>
34
  <MenubarSeparator />
 
 
35
  <ProviderList providers={availableComputeProvidersForImages} current={imageProvider} setter={setImageProvider} />
36
  <RenderingStrategyList current={imageRenderingStrategy} setter={setImageRenderingStrategy} />
37
  <MenubarSeparator />
 
14
  import { useSettings } from "@/controllers/settings"
15
  import { useUI } from "@/controllers/ui"
16
 
17
+ import { ProviderList } from "../lists/ProviderList"
18
+ import { RenderingStrategyList } from "../lists/RenderingStrategyList"
19
  import { availableComputeProvidersForImages } from "@/components/settings/constants"
20
+ import { ImageGenerationModelList } from "../lists/ImageGenerationModelList"
21
+ import { ImageUpscalingModelList } from "../lists/ImageUpscalingModelList"
22
+ import { SettingsCategory } from "@/types"
23
 
24
  export function TopMenuImage() {
25
  const setShowSettings = useUI(s => s.setShowSettings)
26
  const imageProvider = useSettings(s => s.imageProvider)
27
  const setImageProvider = useSettings(s => s.setImageProvider)
28
+ const imageGenerationModel = useSettings(s => s.imageGenerationModel)
29
+ const setImageGenerationModel = useSettings(s => s.setImageGenerationModel)
30
+ const imageUpscalingModel = useSettings(s => s.imageUpscalingModel)
31
+ const setImageUpscalingModel = useSettings(s => s.setImageUpscalingModel)
32
  const imageRenderingStrategy = useSettings((s) => s.imageRenderingStrategy)
33
  const setImageRenderingStrategy = useSettings((s) => s.setImageRenderingStrategy)
34
  return (
 
36
  <MenubarTrigger>Image</MenubarTrigger>
37
  <MenubarContent>
38
  <MenubarSub>
39
+ <MenubarItem onClick={() => { setShowSettings(SettingsCategory.IMAGE) }}>Show advanced settings</MenubarItem>
40
  <MenubarSeparator />
41
+ <ImageGenerationModelList provider={imageProvider} current={imageGenerationModel} setter={setImageGenerationModel} />
42
+ <ImageUpscalingModelList provider={imageProvider} current={imageUpscalingModel} setter={setImageUpscalingModel} />
43
  <ProviderList providers={availableComputeProvidersForImages} current={imageProvider} setter={setImageProvider} />
44
  <RenderingStrategyList current={imageRenderingStrategy} setter={setImageRenderingStrategy} />
45
  <MenubarSeparator />
src/components/toolbars/top-menu/index.tsx CHANGED
@@ -9,10 +9,14 @@ import { TopMenuSound } from "./sound"
9
  import { TopMenuMusic } from "./music"
10
 
11
  import { TopMenuView } from "./view"
 
 
12
 
13
  export function TopMenu() {
14
  return (
15
- <Menubar>
 
 
16
  <TopMenuFile />
17
  <TopMenuImage />
18
  <TopMenuVideo />
@@ -20,6 +24,19 @@ export function TopMenu() {
20
  <TopMenuSound />
21
  <TopMenuMusic />
22
  <TopMenuView />
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  </Menubar>
24
  )
25
  }
 
9
  import { TopMenuMusic } from "./music"
10
 
11
  import { TopMenuView } from "./view"
12
+ import { cn } from "@aitube/timeline"
13
+ import { APP_REVISION } from "@/lib/core/constants"
14
 
15
  export function TopMenu() {
16
  return (
17
+ <Menubar className="w-full">
18
+ <span className="scale-[88%] text-purple-300/80 pl-1 text-lg font-bold tracking-[-0.03em] mr-4">Clapper<span
19
+ className="absolute text-4xs text-purple-100/70 tracking-[0.05em] uppercase mt-1.5 -ml-0 -rotate-6 ">ai</span></span>
20
  <TopMenuFile />
21
  <TopMenuImage />
22
  <TopMenuVideo />
 
24
  <TopMenuSound />
25
  <TopMenuMusic />
26
  <TopMenuView />
27
+ <div className={cn(`
28
+ flex flex-row flex-grow
29
+ px-2
30
+ items-center justify-end
31
+ pointer-events-none
32
+ text-xs text-stone-300
33
+ `
34
+ )}>
35
+ {
36
+ // clap?.meta?.title || "Untitled"
37
+ }
38
+ <span className="text-stone-500">{APP_REVISION}</span>
39
+ </div>
40
  </Menubar>
41
  )
42
  }
src/components/toolbars/top-menu/lists/ImageGenerationModelList.tsx ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client"
2
+
3
+ import {
4
+ MenubarCheckboxItem,
5
+ MenubarContent,
6
+ MenubarItem,
7
+ MenubarMenu,
8
+ MenubarSeparator,
9
+ MenubarSub,
10
+ MenubarSubContent,
11
+ MenubarSubTrigger,
12
+ } from "@/components/ui/menubar"
13
+
14
+ import { TagColor } from "@/components/tags/types"
15
+ import { Tag } from "@/components/tags/Tag"
16
+ import { ComputeProvider } from "@/types"
17
+ import { availableModelsForImageGeneration } from "@/components/settings/constants"
18
+
19
+ export function ImageGenerationModelList({
20
+ provider,
21
+ current,
22
+ setter,
23
+ }: {
24
+ provider?: ComputeProvider
25
+ current?: string
26
+ setter: (model: string) => void
27
+ }) {
28
+ const models: string[] = provider ? (availableModelsForImageGeneration[provider] || []) : []
29
+
30
+ if (models.length === 0) { return null }
31
+
32
+ return (
33
+ <MenubarSub>
34
+ <MenubarSubTrigger>
35
+ <Tag size="lg" color={TagColor.SKY}>generate&nbsp;image</Tag>
36
+ {current || "None"}
37
+ </MenubarSubTrigger>
38
+ <MenubarSubContent>
39
+ {models.map(model => (
40
+ <MenubarCheckboxItem
41
+ key={model}
42
+ checked={current === model}
43
+ onClick={(e) => {
44
+ setter(model)
45
+ e.stopPropagation()
46
+ e.preventDefault()
47
+ return false
48
+ }}>
49
+ {model}
50
+ </MenubarCheckboxItem>
51
+ ))}
52
+ </MenubarSubContent>
53
+ </MenubarSub>
54
+ )
55
+ }
src/components/toolbars/top-menu/{ModelList.tsx β†’ lists/ImageUpscalingModelList.tsx} RENAMED
@@ -13,21 +13,26 @@ import {
13
 
14
  import { TagColor } from "@/components/tags/types"
15
  import { Tag } from "@/components/tags/Tag"
 
 
16
 
17
-
18
- export function ModelList({
19
- models = [],
20
  current,
21
  setter,
22
  }: {
23
- models?: string[]
24
  current?: string
25
  setter: (model: string) => void
26
  }) {
 
 
 
 
27
  return (
28
  <MenubarSub>
29
  <MenubarSubTrigger>
30
- <Tag size="lg" color={TagColor.ZINC}>ai&nbsp;model</Tag>
31
  {current || "None"}
32
  </MenubarSubTrigger>
33
  <MenubarSubContent>
 
13
 
14
  import { TagColor } from "@/components/tags/types"
15
  import { Tag } from "@/components/tags/Tag"
16
+ import { ComputeProvider } from "@/types"
17
+ import { availableModelsForImageUpscaling } from "@/components/settings/constants"
18
 
19
+ export function ImageUpscalingModelList({
20
+ provider,
 
21
  current,
22
  setter,
23
  }: {
24
+ provider?: ComputeProvider
25
  current?: string
26
  setter: (model: string) => void
27
  }) {
28
+ const models: string[] = provider ? (availableModelsForImageUpscaling[provider] || []) : []
29
+
30
+ if (models.length === 0) { return null }
31
+
32
  return (
33
  <MenubarSub>
34
  <MenubarSubTrigger>
35
+ <Tag size="lg" color={TagColor.BLUE}>upscale&nbsp;image</Tag>
36
  {current || "None"}
37
  </MenubarSubTrigger>
38
  <MenubarSubContent>
src/components/toolbars/top-menu/lists/MusicGenerationModelList.tsx ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client"
2
+
3
+ import {
4
+ MenubarCheckboxItem,
5
+ MenubarContent,
6
+ MenubarItem,
7
+ MenubarMenu,
8
+ MenubarSeparator,
9
+ MenubarSub,
10
+ MenubarSubContent,
11
+ MenubarSubTrigger,
12
+ } from "@/components/ui/menubar"
13
+
14
+ import { TagColor } from "@/components/tags/types"
15
+ import { Tag } from "@/components/tags/Tag"
16
+ import { ComputeProvider } from "@/types"
17
+ import { availableModelsForMusicGeneration } from "@/components/settings/constants"
18
+
19
+ export function MusicGenerationModelList({
20
+ provider,
21
+ current,
22
+ setter,
23
+ }: {
24
+ provider?: ComputeProvider
25
+ current?: string
26
+ setter: (model: string) => void
27
+ }) {
28
+ const models: string[] = provider ? (availableModelsForMusicGeneration[provider] || []) : []
29
+
30
+ if (models.length === 0) { return null }
31
+
32
+ return (
33
+ <MenubarSub>
34
+ <MenubarSubTrigger>
35
+ <Tag size="lg" color={TagColor.GREEN}>generate&nbsp;music</Tag>
36
+ {current || "None"}
37
+ </MenubarSubTrigger>
38
+ <MenubarSubContent>
39
+ {models.map(model => (
40
+ <MenubarCheckboxItem
41
+ key={model}
42
+ checked={current === model}
43
+ onClick={(e) => {
44
+ setter(model)
45
+ e.stopPropagation()
46
+ e.preventDefault()
47
+ return false
48
+ }}>
49
+ {model}
50
+ </MenubarCheckboxItem>
51
+ ))}
52
+ </MenubarSubContent>
53
+ </MenubarSub>
54
+ )
55
+ }
src/components/toolbars/top-menu/{ProviderList.tsx β†’ lists/ProviderList.tsx} RENAMED
File without changes
src/components/toolbars/top-menu/{RenderingStrategyList.tsx β†’ lists/RenderingStrategyList.tsx} RENAMED
@@ -12,7 +12,7 @@ import {
12
  } from "@/components/ui/menubar"
13
 
14
  import { RenderingStrategy } from "@aitube/timeline"
15
- import { strategyLabels } from "./constants"
16
  import { Tag } from "@/components/tags/Tag"
17
  import { TagColor } from "@/components/tags/types"
18
 
 
12
  } from "@/components/ui/menubar"
13
 
14
  import { RenderingStrategy } from "@aitube/timeline"
15
+ import { strategyLabels } from "../constants"
16
  import { Tag } from "@/components/tags/Tag"
17
  import { TagColor } from "@/components/tags/types"
18
 
src/components/toolbars/top-menu/lists/SoundGenerationModelList.tsx ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client"
2
+
3
+ import {
4
+ MenubarCheckboxItem,
5
+ MenubarContent,
6
+ MenubarItem,
7
+ MenubarMenu,
8
+ MenubarSeparator,
9
+ MenubarSub,
10
+ MenubarSubContent,
11
+ MenubarSubTrigger,
12
+ } from "@/components/ui/menubar"
13
+
14
+ import { TagColor } from "@/components/tags/types"
15
+ import { Tag } from "@/components/tags/Tag"
16
+ import { ComputeProvider } from "@/types"
17
+ import { availableModelsForSoundGeneration } from "@/components/settings/constants"
18
+
19
+ export function SoundGenerationModelList({
20
+ provider,
21
+ current,
22
+ setter,
23
+ }: {
24
+ provider?: ComputeProvider
25
+ current?: string
26
+ setter: (model: string) => void
27
+ }) {
28
+ const models: string[] = provider ? (availableModelsForSoundGeneration[provider] || []) : []
29
+
30
+ if (models.length === 0) { return null }
31
+
32
+ return (
33
+ <MenubarSub>
34
+ <MenubarSubTrigger>
35
+ <Tag size="lg" color={TagColor.YELLOW}>generate&nbsp;sound</Tag>
36
+ {current || "None"}
37
+ </MenubarSubTrigger>
38
+ <MenubarSubContent>
39
+ {models.map(model => (
40
+ <MenubarCheckboxItem
41
+ key={model}
42
+ checked={current === model}
43
+ onClick={(e) => {
44
+ setter(model)
45
+ e.stopPropagation()
46
+ e.preventDefault()
47
+ return false
48
+ }}>
49
+ {model}
50
+ </MenubarCheckboxItem>
51
+ ))}
52
+ </MenubarSubContent>
53
+ </MenubarSub>
54
+ )
55
+ }
src/components/toolbars/top-menu/lists/VideoGenerationModelList.tsx ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client"
2
+
3
+ import {
4
+ MenubarCheckboxItem,
5
+ MenubarContent,
6
+ MenubarItem,
7
+ MenubarMenu,
8
+ MenubarSeparator,
9
+ MenubarSub,
10
+ MenubarSubContent,
11
+ MenubarSubTrigger,
12
+ } from "@/components/ui/menubar"
13
+
14
+ import { TagColor } from "@/components/tags/types"
15
+ import { Tag } from "@/components/tags/Tag"
16
+ import { ComputeProvider } from "@/types"
17
+ import { availableModelsForVideoGeneration } from "@/components/settings/constants"
18
+
19
+ export function VideoGenerationModelList({
20
+ provider,
21
+ current,
22
+ setter,
23
+ }: {
24
+ provider?: ComputeProvider
25
+ current?: string
26
+ setter: (model: string) => void
27
+ }) {
28
+ const models: string[] = provider ? (availableModelsForVideoGeneration[provider] || []) : []
29
+
30
+ if (models.length === 0) { return null }
31
+
32
+ return (
33
+ <MenubarSub>
34
+ <MenubarSubTrigger>
35
+ <Tag size="lg" color={TagColor.VIOLET}>generate&nbsp;video</Tag>
36
+ {current || "None"}
37
+ </MenubarSubTrigger>
38
+ <MenubarSubContent>
39
+ {models.map(model => (
40
+ <MenubarCheckboxItem
41
+ key={model}
42
+ checked={current === model}
43
+ onClick={(e) => {
44
+ setter(model)
45
+ e.stopPropagation()
46
+ e.preventDefault()
47
+ return false
48
+ }}>
49
+ {model}
50
+ </MenubarCheckboxItem>
51
+ ))}
52
+ </MenubarSubContent>
53
+ </MenubarSub>
54
+ )
55
+ }
src/components/toolbars/top-menu/lists/VideoUpscalingModelList.tsx ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client"
2
+
3
+ import {
4
+ MenubarCheckboxItem,
5
+ MenubarContent,
6
+ MenubarItem,
7
+ MenubarMenu,
8
+ MenubarSeparator,
9
+ MenubarSub,
10
+ MenubarSubContent,
11
+ MenubarSubTrigger,
12
+ } from "@/components/ui/menubar"
13
+
14
+ import { TagColor } from "@/components/tags/types"
15
+ import { Tag } from "@/components/tags/Tag"
16
+ import { ComputeProvider } from "@/types"
17
+ import { availableModelsForVideoUpscaling } from "@/components/settings/constants"
18
+
19
+ export function VideoUpscalingModelList({
20
+ provider,
21
+ current,
22
+ setter,
23
+ }: {
24
+ provider?: ComputeProvider
25
+ current?: string
26
+ setter: (model: string) => void
27
+ }) {
28
+ const models: string[] = provider ? (availableModelsForVideoUpscaling[provider] || []) : []
29
+
30
+ if (models.length === 0) { return null }
31
+
32
+ return (
33
+ <MenubarSub>
34
+ <MenubarSubTrigger>
35
+ <Tag size="lg" color={TagColor.INDIGO}>upscale&nbsp;video</Tag>
36
+ {current || "None"}
37
+ </MenubarSubTrigger>
38
+ <MenubarSubContent>
39
+ {models.map(model => (
40
+ <MenubarCheckboxItem
41
+ key={model}
42
+ checked={current === model}
43
+ onClick={(e) => {
44
+ setter(model)
45
+ e.stopPropagation()
46
+ e.preventDefault()
47
+ return false
48
+ }}>
49
+ {model}
50
+ </MenubarCheckboxItem>
51
+ ))}
52
+ </MenubarSubContent>
53
+ </MenubarSub>
54
+ )
55
+ }
src/components/toolbars/top-menu/lists/VoiceGenerationModelList.tsx ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client"
2
+
3
+ import {
4
+ MenubarCheckboxItem,
5
+ MenubarContent,
6
+ MenubarItem,
7
+ MenubarMenu,
8
+ MenubarSeparator,
9
+ MenubarSub,
10
+ MenubarSubContent,
11
+ MenubarSubTrigger,
12
+ } from "@/components/ui/menubar"
13
+
14
+ import { TagColor } from "@/components/tags/types"
15
+ import { Tag } from "@/components/tags/Tag"
16
+ import { ComputeProvider } from "@/types"
17
+ import { availableModelsForVoiceGeneration } from "@/components/settings/constants"
18
+
19
+ export function VoiceGenerationModelList({
20
+ provider,
21
+ current,
22
+ setter,
23
+ }: {
24
+ provider?: ComputeProvider
25
+ current?: string
26
+ setter: (model: string) => void
27
+ }) {
28
+ const models: string[] = provider ? (availableModelsForVoiceGeneration[provider] || []) : []
29
+
30
+ if (models.length === 0) { return null }
31
+
32
+ return (
33
+ <MenubarSub>
34
+ <MenubarSubTrigger>
35
+ <Tag size="lg" color={TagColor.ORANGE}>generate&nbsp;voice</Tag>
36
+ {current || "None"}
37
+ </MenubarSubTrigger>
38
+ <MenubarSubContent>
39
+ {models.map(model => (
40
+ <MenubarCheckboxItem
41
+ key={model}
42
+ checked={current === model}
43
+ onClick={(e) => {
44
+ setter(model)
45
+ e.stopPropagation()
46
+ e.preventDefault()
47
+ return false
48
+ }}>
49
+ {model}
50
+ </MenubarCheckboxItem>
51
+ ))}
52
+ </MenubarSubContent>
53
+ </MenubarSub>
54
+ )
55
+ }
src/components/toolbars/top-menu/music/index.tsx CHANGED
@@ -14,10 +14,10 @@ import {
14
  import { useSettings } from "@/controllers/settings"
15
  import { useUI } from "@/controllers/ui"
16
 
17
- import { ProviderList } from "../ProviderList"
18
- import { RenderingStrategyList } from "../RenderingStrategyList"
19
  import { availableComputeProvidersForMusic } from "@/components/settings/constants"
20
-
21
 
22
  export function TopMenuMusic() {
23
  const setShowSettings = useUI(s => s.setShowSettings)
@@ -30,7 +30,7 @@ export function TopMenuMusic() {
30
  <MenubarTrigger>Music</MenubarTrigger>
31
  <MenubarContent>
32
  <MenubarSub>
33
- <MenubarItem onClick={() => { setShowSettings(true) }}>Show advanced settings</MenubarItem>
34
  <MenubarSeparator />
35
  <ProviderList providers={availableComputeProvidersForMusic} current={musicProvider} setter={setMusicProvider} />
36
  <RenderingStrategyList current={musicRenderingStrategy} setter={setMusicRenderingStrategy} />
 
14
  import { useSettings } from "@/controllers/settings"
15
  import { useUI } from "@/controllers/ui"
16
 
17
+ import { ProviderList } from "../lists/ProviderList"
18
+ import { RenderingStrategyList } from "../lists/RenderingStrategyList"
19
  import { availableComputeProvidersForMusic } from "@/components/settings/constants"
20
+ import { SettingsCategory } from "@/types"
21
 
22
  export function TopMenuMusic() {
23
  const setShowSettings = useUI(s => s.setShowSettings)
 
30
  <MenubarTrigger>Music</MenubarTrigger>
31
  <MenubarContent>
32
  <MenubarSub>
33
+ <MenubarItem onClick={() => { setShowSettings(SettingsCategory.MUSIC) }}>Show advanced settings</MenubarItem>
34
  <MenubarSeparator />
35
  <ProviderList providers={availableComputeProvidersForMusic} current={musicProvider} setter={setMusicProvider} />
36
  <RenderingStrategyList current={musicRenderingStrategy} setter={setMusicRenderingStrategy} />
src/components/toolbars/top-menu/sound/index.tsx CHANGED
@@ -14,10 +14,10 @@ import {
14
  import { useSettings } from "@/controllers/settings"
15
  import { useUI } from "@/controllers/ui"
16
 
17
- import { ProviderList } from "../ProviderList"
18
- import { RenderingStrategyList } from "../RenderingStrategyList"
19
  import { availableComputeProvidersForSound } from "@/components/settings/constants"
20
-
21
 
22
  export function TopMenuSound() {
23
  const setShowSettings = useUI(s => s.setShowSettings)
@@ -30,7 +30,7 @@ export function TopMenuSound() {
30
  <MenubarTrigger>Sound</MenubarTrigger>
31
  <MenubarContent>
32
  <MenubarSub>
33
- <MenubarItem onClick={() => { setShowSettings(true) }}>Show advanced settings</MenubarItem>
34
  <MenubarSeparator />
35
  <ProviderList providers={availableComputeProvidersForSound} current={soundProvider} setter={setSoundProvider} />
36
  <RenderingStrategyList current={soundRenderingStrategy} setter={setSoundRenderingStrategy} />
 
14
  import { useSettings } from "@/controllers/settings"
15
  import { useUI } from "@/controllers/ui"
16
 
17
+ import { ProviderList } from "../lists/ProviderList"
18
+ import { RenderingStrategyList } from "../lists/RenderingStrategyList"
19
  import { availableComputeProvidersForSound } from "@/components/settings/constants"
20
+ import { SettingsCategory } from "@/types"
21
 
22
  export function TopMenuSound() {
23
  const setShowSettings = useUI(s => s.setShowSettings)
 
30
  <MenubarTrigger>Sound</MenubarTrigger>
31
  <MenubarContent>
32
  <MenubarSub>
33
+ <MenubarItem onClick={() => { setShowSettings(SettingsCategory.SOUND) }}>Show advanced settings</MenubarItem>
34
  <MenubarSeparator />
35
  <ProviderList providers={availableComputeProvidersForSound} current={soundProvider} setter={setSoundProvider} />
36
  <RenderingStrategyList current={soundRenderingStrategy} setter={setSoundRenderingStrategy} />
src/components/toolbars/top-menu/video/index.tsx CHANGED
@@ -14,15 +14,21 @@ import {
14
  import { useSettings } from "@/controllers/settings"
15
  import { useUI } from "@/controllers/ui"
16
 
17
- import { ProviderList } from "../ProviderList"
18
- import { RenderingStrategyList } from "../RenderingStrategyList"
19
  import { availableComputeProvidersForVideos } from "@/components/settings/constants"
20
-
 
 
21
 
22
  export function TopMenuVideo() {
23
  const setShowSettings = useUI(s => s.setShowSettings)
24
  const videoProvider = useSettings(s => s.videoProvider)
25
  const setVideoProvider = useSettings(s => s.setVideoProvider)
 
 
 
 
26
  const videoRenderingStrategy = useSettings((s) => s.videoRenderingStrategy)
27
  const setVideoRenderingStrategy = useSettings((s) => s.setVideoRenderingStrategy)
28
  return (
@@ -30,8 +36,10 @@ export function TopMenuVideo() {
30
  <MenubarTrigger>Video</MenubarTrigger>
31
  <MenubarContent>
32
  <MenubarSub>
33
- <MenubarItem onClick={() => { setShowSettings(true) }}>Show advanced settings</MenubarItem>
34
  <MenubarSeparator />
 
 
35
  <ProviderList providers={availableComputeProvidersForVideos} current={videoProvider} setter={setVideoProvider} />
36
  <RenderingStrategyList current={videoRenderingStrategy} setter={setVideoRenderingStrategy} />
37
  <MenubarSeparator />
 
14
  import { useSettings } from "@/controllers/settings"
15
  import { useUI } from "@/controllers/ui"
16
 
17
+ import { ProviderList } from "../lists/ProviderList"
18
+ import { RenderingStrategyList } from "../lists/RenderingStrategyList"
19
  import { availableComputeProvidersForVideos } from "@/components/settings/constants"
20
+ import { VideoGenerationModelList } from "../lists/VideoGenerationModelList"
21
+ import { VideoUpscalingModelList } from "../lists/VideoUpscalingModelList"
22
+ import { SettingsCategory } from "@/types"
23
 
24
  export function TopMenuVideo() {
25
  const setShowSettings = useUI(s => s.setShowSettings)
26
  const videoProvider = useSettings(s => s.videoProvider)
27
  const setVideoProvider = useSettings(s => s.setVideoProvider)
28
+ const videoGenerationModel = useSettings(s => s.videoGenerationModel)
29
+ const setVideoGenerationModel = useSettings(s => s.setVideoGenerationModel)
30
+ const videoUpscalingModel = useSettings(s => s.videoUpscalingModel)
31
+ const setVideoUpscalingModel = useSettings(s => s.setVideoUpscalingModel)
32
  const videoRenderingStrategy = useSettings((s) => s.videoRenderingStrategy)
33
  const setVideoRenderingStrategy = useSettings((s) => s.setVideoRenderingStrategy)
34
  return (
 
36
  <MenubarTrigger>Video</MenubarTrigger>
37
  <MenubarContent>
38
  <MenubarSub>
39
+ <MenubarItem onClick={() => { setShowSettings(SettingsCategory.VIDEO) }}>Show advanced settings</MenubarItem>
40
  <MenubarSeparator />
41
+ <VideoGenerationModelList provider={videoProvider} current={videoGenerationModel} setter={setVideoGenerationModel} />
42
+ <VideoUpscalingModelList provider={videoProvider} current={videoUpscalingModel} setter={setVideoUpscalingModel} />
43
  <ProviderList providers={availableComputeProvidersForVideos} current={videoProvider} setter={setVideoProvider} />
44
  <RenderingStrategyList current={videoRenderingStrategy} setter={setVideoRenderingStrategy} />
45
  <MenubarSeparator />
src/components/toolbars/top-menu/voice/index.tsx CHANGED
@@ -14,15 +14,18 @@ import {
14
  import { useSettings } from "@/controllers/settings"
15
  import { useUI } from "@/controllers/ui"
16
 
17
- import { ProviderList } from "../ProviderList"
18
- import { RenderingStrategyList } from "../RenderingStrategyList"
19
  import { availableComputeProvidersForVoice } from "@/components/settings/constants"
20
-
 
21
 
22
  export function TopMenuVoice() {
23
  const setShowSettings = useUI(s => s.setShowSettings)
24
  const voiceProvider = useSettings(s => s.voiceProvider)
25
  const setVoiceProvider = useSettings(s => s.setVoiceProvider)
 
 
26
  const voiceRenderingStrategy = useSettings((s) => s.voiceRenderingStrategy)
27
  const setVoiceRenderingStrategy = useSettings((s) => s.setVoiceRenderingStrategy)
28
  return (
@@ -30,8 +33,9 @@ export function TopMenuVoice() {
30
  <MenubarTrigger>Voice</MenubarTrigger>
31
  <MenubarContent>
32
  <MenubarSub>
33
- <MenubarItem onClick={() => { setShowSettings(true) }}>Show advanced settings</MenubarItem>
34
  <MenubarSeparator />
 
35
  <ProviderList providers={availableComputeProvidersForVoice} current={voiceProvider} setter={setVoiceProvider} />
36
  <RenderingStrategyList current={voiceRenderingStrategy} setter={setVoiceRenderingStrategy} />
37
  <MenubarSeparator />
 
14
  import { useSettings } from "@/controllers/settings"
15
  import { useUI } from "@/controllers/ui"
16
 
17
+ import { ProviderList } from "../lists/ProviderList"
18
+ import { RenderingStrategyList } from "../lists/RenderingStrategyList"
19
  import { availableComputeProvidersForVoice } from "@/components/settings/constants"
20
+ import { VoiceGenerationModelList } from "../lists/VoiceGenerationModelList"
21
+ import { SettingsCategory } from "@/types"
22
 
23
  export function TopMenuVoice() {
24
  const setShowSettings = useUI(s => s.setShowSettings)
25
  const voiceProvider = useSettings(s => s.voiceProvider)
26
  const setVoiceProvider = useSettings(s => s.setVoiceProvider)
27
+ const voiceGenerationModel = useSettings(s => s.voiceGenerationModel)
28
+ const setVoiceGenerationModel = useSettings(s => s.setVoiceGenerationModel)
29
  const voiceRenderingStrategy = useSettings((s) => s.voiceRenderingStrategy)
30
  const setVoiceRenderingStrategy = useSettings((s) => s.setVoiceRenderingStrategy)
31
  return (
 
33
  <MenubarTrigger>Voice</MenubarTrigger>
34
  <MenubarContent>
35
  <MenubarSub>
36
+ <MenubarItem onClick={() => { setShowSettings(SettingsCategory.VOICE) }}>Show advanced settings</MenubarItem>
37
  <MenubarSeparator />
38
+ <VoiceGenerationModelList provider={voiceProvider} current={voiceGenerationModel} setter={setVoiceGenerationModel} />
39
  <ProviderList providers={availableComputeProvidersForVoice} current={voiceProvider} setter={setVoiceProvider} />
40
  <RenderingStrategyList current={voiceRenderingStrategy} setter={setVoiceRenderingStrategy} />
41
  <MenubarSeparator />
src/components/ui/menubar.tsx CHANGED
@@ -23,7 +23,7 @@ const Menubar = React.forwardRef<
23
  <MenubarPrimitive.Root
24
  ref={ref}
25
  className={cn(
26
- "flex h-[2.25rem] items-center space-x-1 rounded-md border border-stone-200 bg-white p-1 dark:border-stone-900 dark:bg-stone-900 border-none dark:border-none shadow-none",
27
  className
28
  )}
29
  {...props}
@@ -38,7 +38,7 @@ const MenubarTrigger = React.forwardRef<
38
  <MenubarPrimitive.Trigger
39
  ref={ref}
40
  className={cn(
41
- "flex cursor-default select-none items-center rounded-sm px-3 py-1.5 text-sm font-medium outline-none focus:bg-stone-100 focus:text-stone-900 data-[state=open]:bg-stone-100 data-[state=open]:text-stone-900 dark:focus:bg-stone-800 dark:focus:text-stone-200 dark:data-[state=open]:bg-stone-800 dark:data-[state=open]:text-stone-200",
42
  className
43
  )}
44
  {...props}
 
23
  <MenubarPrimitive.Root
24
  ref={ref}
25
  className={cn(
26
+ "flex h-[2.25rem] items-center space-x-0 rounded-md border border-stone-200 bg-white p-1 dark:border-stone-900 dark:bg-stone-900 border-none dark:border-none shadow-none",
27
  className
28
  )}
29
  {...props}
 
38
  <MenubarPrimitive.Trigger
39
  ref={ref}
40
  className={cn(
41
+ "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm font-normal outline-none focus:bg-stone-100 focus:text-stone-900 data-[state=open]:bg-stone-100 data-[state=open]:text-stone-900 dark:focus:bg-stone-800 dark:text-stone-400 dark:focus:text-stone-300 dark:data-[state=open]:bg-stone-800 dark:data-[state=open]:text-stone-300",
42
  className
43
  )}
44
  {...props}
src/controllers/settings/getDefaultSettingsState.ts CHANGED
@@ -37,6 +37,17 @@ export function getDefaultSettingsState(): SettingsState {
37
  videoPromptSuffix: "",
38
  videoNegativePrompt: "",
39
 
 
 
 
 
 
 
 
 
 
 
 
40
  imageRenderingStrategy: RenderingStrategy.ON_DEMAND,
41
  videoRenderingStrategy: RenderingStrategy.ON_DEMAND,
42
  voiceRenderingStrategy: RenderingStrategy.ON_DEMAND,
 
37
  videoPromptSuffix: "",
38
  videoNegativePrompt: "",
39
 
40
+ assistantModel: "",
41
+ assistantTurboModel: "",
42
+ imageGenerationModel: "",
43
+ imageGenerationTurboModel: "",
44
+ imageUpscalingModel: "",
45
+ videoGenerationModel: "",
46
+ videoUpscalingModel: "",
47
+ soundGenerationModel: "",
48
+ voiceGenerationModel: "",
49
+ musicGenerationModel: "",
50
+
51
  imageRenderingStrategy: RenderingStrategy.ON_DEMAND,
52
  videoRenderingStrategy: RenderingStrategy.ON_DEMAND,
53
  voiceRenderingStrategy: RenderingStrategy.ON_DEMAND,
src/controllers/settings/types.ts CHANGED
@@ -36,6 +36,17 @@ export type SettingsState = {
36
  videoPromptPrefix: string
37
  videoPromptSuffix: string
38
  videoNegativePrompt: string
 
 
 
 
 
 
 
 
 
 
 
39
 
40
  imageRenderingStrategy: RenderingStrategy
41
  videoRenderingStrategy: RenderingStrategy
@@ -142,6 +153,16 @@ export type SettingsControls = {
142
  setVideoPromptSuffix: (videoPromptSuffix?: string) => void
143
  setVideoNegativePrompt: (videoNegativePrompt?: string) => void
144
 
 
 
 
 
 
 
 
 
 
 
145
  setImageRenderingStrategy: (imageRenderingStrategy?: RenderingStrategy) => void
146
  setVideoRenderingStrategy: (videoRenderingStrategy?: RenderingStrategy) => void
147
  setVoiceRenderingStrategy: (voiceRenderingStrategy?: RenderingStrategy) => void
 
36
  videoPromptPrefix: string
37
  videoPromptSuffix: string
38
  videoNegativePrompt: string
39
+
40
+ assistantModel: string
41
+ assistantTurboModel: string
42
+ imageGenerationModel: string
43
+ imageGenerationTurboModel: string
44
+ imageUpscalingModel: string
45
+ videoGenerationModel: string
46
+ videoUpscalingModel: string
47
+ soundGenerationModel: string
48
+ voiceGenerationModel: string
49
+ musicGenerationModel: string
50
 
51
  imageRenderingStrategy: RenderingStrategy
52
  videoRenderingStrategy: RenderingStrategy
 
153
  setVideoPromptSuffix: (videoPromptSuffix?: string) => void
154
  setVideoNegativePrompt: (videoNegativePrompt?: string) => void
155
 
156
+ setAssistantModel: (assistantModel?: string) => void
157
+ setAssistantTurboModel: (assistantTurboModel?: string) => void
158
+ setImageGenerationModel: (imageGenerationModel?: string) => void
159
+ setImageGenerationTurboModel: (imageGenerationTurboModel?: string) => void
160
+ setImageUpscalingModel: (imageUpscalingModel?: string) => void
161
+ setVideoGenerationModel: (videoGenerationModel?: string) => void
162
+ setVideoUpscalingModel: (videoUpscalingModel?: string) => void
163
+ setSoundGenerationModel: (soundGenerationModel?: string) => void
164
+ setVoiceGenerationModel: (voiceGenerationModel?: string) => void
165
+ setMusicGenerationModel: (musicGenerationModel?: string) => void
166
  setImageRenderingStrategy: (imageRenderingStrategy?: RenderingStrategy) => void
167
  setVideoRenderingStrategy: (videoRenderingStrategy?: RenderingStrategy) => void
168
  setVoiceRenderingStrategy: (voiceRenderingStrategy?: RenderingStrategy) => void
src/controllers/settings/useSettings.ts CHANGED
@@ -105,6 +105,46 @@ export const useSettings = create<SettingsStore>()(
105
  setVideoNegativePrompt: (videoNegativePrompt?: string) => {
106
  set({ videoNegativePrompt: getValidString(videoNegativePrompt, getDefaultSettingsState().videoNegativePrompt) })
107
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  setImageRenderingStrategy: (imageRenderingStrategy?: RenderingStrategy) => {
109
  const { imageRenderingStrategy: defaulImageRenderingStrategy } = getDefaultSettingsState()
110
  set({ imageRenderingStrategy: parseRenderingStrategy(imageRenderingStrategy, defaulImageRenderingStrategy) })
@@ -328,7 +368,19 @@ export const useSettings = create<SettingsStore>()(
328
  imageNegativePrompt: state.imageNegativePrompt || defaultSettings.imageNegativePrompt,
329
  videoPromptPrefix: state.videoPromptPrefix || defaultSettings.videoPromptPrefix,
330
  videoPromptSuffix: state.videoPromptSuffix || defaultSettings.videoPromptSuffix,
331
- videoNegativePrompt: state.videoNegativePrompt || defaultSettings.videoNegativePrompt,
 
 
 
 
 
 
 
 
 
 
 
 
332
  imageRenderingStrategy: state.imageRenderingStrategy || defaultSettings.imageRenderingStrategy,
333
  videoRenderingStrategy: state.videoRenderingStrategy || defaultSettings.videoRenderingStrategy,
334
  voiceRenderingStrategy: state.voiceRenderingStrategy || defaultSettings.voiceRenderingStrategy,
 
105
  setVideoNegativePrompt: (videoNegativePrompt?: string) => {
106
  set({ videoNegativePrompt: getValidString(videoNegativePrompt, getDefaultSettingsState().videoNegativePrompt) })
107
  },
108
+ setAssistantModel: (assistantModel?: string) => {
109
+ const { assistantModel: defaultAssistantModel } = getDefaultSettingsState()
110
+ set({ assistantModel: getValidString(assistantModel, defaultAssistantModel) })
111
+ },
112
+ setAssistantTurboModel: (assistantTurboModel?: string) => {
113
+ const { assistantTurboModel: defaultAssistantTurboModel } = getDefaultSettingsState()
114
+ set({ assistantTurboModel: getValidString(assistantTurboModel, defaultAssistantTurboModel) })
115
+ },
116
+ setImageGenerationModel: (imageGenerationModel?: string) => {
117
+ const { imageGenerationModel: defaultImageGenerationModel } = getDefaultSettingsState()
118
+ set({ imageGenerationModel: getValidString(imageGenerationModel, defaultImageGenerationModel) })
119
+ },
120
+ setImageGenerationTurboModel: (imageGenerationTurboModel?: string) => {
121
+ const { imageGenerationTurboModel: defaultImageGenerationTurboModel } = getDefaultSettingsState()
122
+ set({ imageGenerationTurboModel: getValidString(imageGenerationTurboModel, defaultImageGenerationTurboModel) })
123
+ },
124
+ setImageUpscalingModel: (imageUpscalingModel?: string) => {
125
+ const { imageUpscalingModel: defaultImageUpscalingModel } = getDefaultSettingsState()
126
+ set({ imageUpscalingModel: getValidString(imageUpscalingModel, defaultImageUpscalingModel) })
127
+ },
128
+ setVideoGenerationModel: (videoGenerationModel?: string) => {
129
+ const { videoGenerationModel: defaultVideoGenerationModel } = getDefaultSettingsState()
130
+ set({ videoGenerationModel: getValidString(videoGenerationModel, defaultVideoGenerationModel) })
131
+ },
132
+ setVideoUpscalingModel: (videoUpscalingModel?: string) => {
133
+ const { videoUpscalingModel: defaultVideoUpscalingModel} = getDefaultSettingsState()
134
+ set({ videoUpscalingModel: getValidString(videoUpscalingModel, defaultVideoUpscalingModel) })
135
+ },
136
+ setSoundGenerationModel: (soundGenerationModel?: string) => {
137
+ const { soundGenerationModel: defaultSoundGenerationModel } = getDefaultSettingsState()
138
+ set({ soundGenerationModel: getValidString(soundGenerationModel, defaultSoundGenerationModel) })
139
+ },
140
+ setVoiceGenerationModel: (voiceGenerationModel?: string) => {
141
+ const { voiceGenerationModel: defaultVoiceGenerationModel } = getDefaultSettingsState()
142
+ set({ voiceGenerationModel: getValidString(voiceGenerationModel, defaultVoiceGenerationModel) })
143
+ },
144
+ setMusicGenerationModel: (musicGenerationModel?: string) => {
145
+ const { musicGenerationModel: defaultVoiceGenerationModel } = getDefaultSettingsState()
146
+ set({ musicGenerationModel: getValidString(musicGenerationModel, defaultVoiceGenerationModel) })
147
+ },
148
  setImageRenderingStrategy: (imageRenderingStrategy?: RenderingStrategy) => {
149
  const { imageRenderingStrategy: defaulImageRenderingStrategy } = getDefaultSettingsState()
150
  set({ imageRenderingStrategy: parseRenderingStrategy(imageRenderingStrategy, defaulImageRenderingStrategy) })
 
368
  imageNegativePrompt: state.imageNegativePrompt || defaultSettings.imageNegativePrompt,
369
  videoPromptPrefix: state.videoPromptPrefix || defaultSettings.videoPromptPrefix,
370
  videoPromptSuffix: state.videoPromptSuffix || defaultSettings.videoPromptSuffix,
371
+ videoNegativePrompt: state.videoNegativePrompt || defaultSettings.videoNegativePrompt,
372
+
373
+ assistantModel: state.assistantModel || defaultSettings.assistantModel,
374
+ assistantTurboModel: state.assistantTurboModel || defaultSettings.assistantTurboModel,
375
+ imageGenerationModel: state.imageGenerationModel || defaultSettings.imageGenerationModel,
376
+ imageGenerationTurboModel: state.imageGenerationTurboModel || defaultSettings.imageGenerationTurboModel,
377
+ imageUpscalingModel: state.imageUpscalingModel || defaultSettings.imageUpscalingModel,
378
+ videoGenerationModel: state.videoGenerationModel || defaultSettings.videoGenerationModel,
379
+ videoUpscalingModel: state.videoUpscalingModel || defaultSettings.videoUpscalingModel,
380
+ soundGenerationModel: state.soundGenerationModel || defaultSettings.soundGenerationModel,
381
+ voiceGenerationModel: state.voiceGenerationModel || defaultSettings.voiceGenerationModel,
382
+ musicGenerationModel: state.musicGenerationModel || defaultSettings.musicGenerationModel,
383
+
384
  imageRenderingStrategy: state.imageRenderingStrategy || defaultSettings.imageRenderingStrategy,
385
  videoRenderingStrategy: state.videoRenderingStrategy || defaultSettings.videoRenderingStrategy,
386
  voiceRenderingStrategy: state.voiceRenderingStrategy || defaultSettings.voiceRenderingStrategy,
src/controllers/ui/getDefaultUIState.ts CHANGED
@@ -1,8 +1,9 @@
 
1
  import { UIState } from "./types"
2
 
3
  export function getDefaultUIState(): UIState {
4
  const state: UIState = {
5
- showSettings: false,
6
  showImporter: false,
7
  showTimeline: true,
8
  showExplorer: true,
 
1
+ import { SettingsCategory } from "@/types"
2
  import { UIState } from "./types"
3
 
4
  export function getDefaultUIState(): UIState {
5
  const state: UIState = {
6
+ showSettings: SettingsCategory.NONE,
7
  showImporter: false,
8
  showTimeline: true,
9
  showExplorer: true,
src/controllers/ui/types.ts CHANGED
@@ -1,5 +1,7 @@
 
 
1
  export type UIState = {
2
- showSettings: boolean
3
  showImporter: boolean
4
  showTimeline: boolean
5
  showExplorer: boolean
@@ -10,7 +12,7 @@ export type UIState = {
10
  }
11
 
12
  export type UIControls = {
13
- setShowSettings: (showSettings: boolean) => void
14
  setShowImporter: (showImporter: boolean) => void
15
  setShowTimeline: (showTimeline: boolean) => void
16
  setShowExplorer: (showExplorer: boolean) => void
 
1
+ import { SettingsCategory } from "@/types"
2
+
3
  export type UIState = {
4
+ showSettings: SettingsCategory
5
  showImporter: boolean
6
  showTimeline: boolean
7
  showExplorer: boolean
 
12
  }
13
 
14
  export type UIControls = {
15
+ setShowSettings: (showSettings: SettingsCategory) => void
16
  setShowImporter: (showImporter: boolean) => void
17
  setShowTimeline: (showTimeline: boolean) => void
18
  setShowExplorer: (showExplorer: boolean) => void
src/controllers/ui/useUI.ts CHANGED
@@ -5,13 +5,14 @@ import { persist } from 'zustand/middleware'
5
 
6
  import { UIStore } from "./types"
7
  import { getDefaultUIState } from "./getDefaultUIState"
 
8
 
9
  export const useUI = create<UIStore>()(
10
  persist(
11
  (set, get) => ({
12
  ...getDefaultUIState(),
13
 
14
- setShowSettings: (showSettings: boolean) => {
15
  set({ showSettings })
16
  },
17
  setShowImporter: (showImporter: boolean) => {
 
5
 
6
  import { UIStore } from "./types"
7
  import { getDefaultUIState } from "./getDefaultUIState"
8
+ import { SettingsCategory } from "@/types"
9
 
10
  export const useUI = create<UIStore>()(
11
  persist(
12
  (set, get) => ({
13
  ...getDefaultUIState(),
14
 
15
+ setShowSettings: (showSettings: SettingsCategory) => {
16
  set({ showSettings })
17
  },
18
  setShowImporter: (showImporter: boolean) => {
src/lib/core/constants.ts CHANGED
@@ -3,8 +3,8 @@
3
  // who is seriously ready to spawn 32 GPUs in parallel for this?
4
  export const HARD_LIMIT_NB_MAX_ASSETS_TO_GENERATE_IN_PARALLEL = 32
5
 
6
- export const APP_NAME = "Clapper"
7
- export const APP_REVISION = "r20240606"
8
 
9
  export const APP_DOMAIN = "Clapper.app"
10
  export const APP_LINK = "https://clapper.app"
 
3
  // who is seriously ready to spawn 32 GPUs in parallel for this?
4
  export const HARD_LIMIT_NB_MAX_ASSETS_TO_GENERATE_IN_PARALLEL = 32
5
 
6
+ export const APP_NAME = "Clapper AI"
7
+ export const APP_REVISION = "r2024-06-08"
8
 
9
  export const APP_DOMAIN = "Clapper.app"
10
  export const APP_LINK = "https://clapper.app"
src/lib/hf/getMyGradioSpaces.ts ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { listSpaces, Credentials, whoAmI, SpaceEntry } from "@huggingface/hub"
2
+ import { GradioSpace } from "./types"
3
+
4
+ export async function getMyGradioSpaces({
5
+ huggingFaceApiKey
6
+ }: {
7
+ huggingFaceApiKey: string
8
+ }): Promise<GradioSpace[]> {
9
+
10
+ const accessToken = huggingFaceApiKey || ""
11
+
12
+ if (!accessToken) {
13
+ throw new Error(`cannot list spaces without a Hugging Face access token`)
14
+ }
15
+
16
+ const credentials: Credentials = { accessToken }
17
+
18
+ let username = ""
19
+ try {
20
+ const { name } = await whoAmI({ credentials })
21
+ username = name
22
+ if (!username) {
23
+ throw new Error(`returned username is empty`)
24
+ }
25
+ } catch (err) {
26
+ throw new Error(`cannot list spaces: ${err}`)
27
+ }
28
+
29
+
30
+ let maxNbSpaces = 10
31
+ let gradioSpaces: GradioSpace[] = []
32
+
33
+ for await (const space of listSpaces({
34
+ search: {
35
+ owner: username
36
+ },
37
+ additionalFields: [
38
+ "cardData",
39
+ "runtime",
40
+ "tags",
41
+ "models"
42
+ ],
43
+ credentials
44
+ })) {
45
+ if (
46
+ space.sdk !== "gradio"
47
+ ) { continue }
48
+
49
+ console.log("MySpace:", gradioSpaces)
50
+
51
+ gradioSpaces.push(space)
52
+ }
53
+
54
+ return gradioSpaces
55
+ }
src/lib/hf/types.ts ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ import { SpaceEntry} from "@huggingface/hub"
2
+ import { ApiSpaceInfo } from "@huggingface/hub/dist/src/types/api/api-space"
3
+
4
+ export type GradioSpace =
5
+ SpaceEntry & Pick<ApiSpaceInfo, "cardData" | "runtime" | "tags" | "models">
src/lib/hf/useMyGradioSpaces.ts ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useEffect, useState } from "react"
2
+
3
+ import { useSettings } from "@/controllers/settings"
4
+
5
+ import { GradioSpace } from "./types"
6
+ import { getMyGradioSpaces } from "./getMyGradioSpaces"
7
+
8
+ export function useMyGradioSpaces() {
9
+ const [gradioSpaces, setGradioSpaces] = useState<GradioSpace[]>([])
10
+
11
+ const huggingFaceApiKey = useSettings(s => s.huggingFaceApiKey)
12
+
13
+ useEffect(() => {
14
+ const fn = async () => {
15
+ try {
16
+ const newSpaces = await getMyGradioSpaces({ huggingFaceApiKey })
17
+ setGradioSpaces(newSpaces)
18
+ } catch (err) {
19
+ console.error(`failed to load the Gradio spaces (most likely your HF token is invalid)`, err)
20
+ }
21
+
22
+ }
23
+ fn()
24
+ }, [huggingFaceApiKey])
25
+
26
+ return gradioSpaces
27
+ }
src/types.ts CHANGED
@@ -1,6 +1,17 @@
1
  import { ClapEntity, ClapMeta, ClapSegment, ClapSegmentCategory } from "@aitube/clap"
2
  import { SettingsState } from "./controllers/settings"
3
 
 
 
 
 
 
 
 
 
 
 
 
4
  export enum ComputeProvider {
5
  NONE = "NONE",
6
  CUSTOM = "CUSTOM",
 
1
  import { ClapEntity, ClapMeta, ClapSegment, ClapSegmentCategory } from "@aitube/clap"
2
  import { SettingsState } from "./controllers/settings"
3
 
4
+ export enum SettingsCategory {
5
+ NONE = "NONE",
6
+ PROVIDER = "PROVIDER",
7
+ ASSISTANT = "ASSISTANT",
8
+ IMAGE = "IMAGE",
9
+ VIDEO = "VIDEO",
10
+ VOICE = "VOICE",
11
+ MUSIC = "MUSIC",
12
+ SOUND = "SOUND"
13
+ }
14
+
15
  export enum ComputeProvider {
16
  NONE = "NONE",
17
  CUSTOM = "CUSTOM",