Skip to content

Commit 70afcaa

Browse files
committed
merging v2.3.2
2 parents 442be2f + be8000e commit 70afcaa

19 files changed

Lines changed: 670 additions & 398 deletions

package-lock.json

Lines changed: 163 additions & 103 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/App.jsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ function App() {
2424
const [promptConfig, setPromptConfig] = useState(promptConfigDefault)
2525
const [modelConfig, setModelConfig] = useState(modelConfigDefault)
2626
const [activeDownloads, setActiveDownloads] = useState({})
27+
const [isRecommended, setIsRecommended] = useState(true)
28+
const [reloadModel, setReloadModel] = useState(1)
2729

2830
return (
2931
<div className='flex h-screen w-full'>
@@ -34,7 +36,7 @@ function App() {
3436
}
3537

3638
{/* SIDEBAR */}
37-
{isSidebarOpen &&
39+
<div className={isSidebarOpen ? '' : 'hidden'} >
3840
<Sidebar
3941
setUploadedModel={setUploadedModel}
4042
setSelectedModelUrl={setSelectedModelUrl}
@@ -43,7 +45,7 @@ function App() {
4345
setChatMessages={setChatMessages}
4446
activeDownloads={activeDownloads}
4547
/>
46-
}
48+
</div>
4749

4850
{/* MAIN CHAT */}
4951
<div className="flex-1 flex flex-col relative w-full h-full bg-gray-900 min-w-0">
@@ -73,6 +75,8 @@ function App() {
7375
promptConfig={promptConfig}
7476
modelConfig={modelConfig}
7577
setModelConfig={setModelConfig}
78+
setIsRecommended={setIsRecommended}
79+
setReloadModel={setReloadModel}
7680
/>
7781
}
7882

@@ -85,6 +89,7 @@ function App() {
8589
/>
8690

8791
<WllamaChat
92+
isRecommended={isRecommended}
8893
userPrompt={userPrompt}
8994
uploadedModel={uploadedModel}
9095
chatMessages={chatMessages}
@@ -101,6 +106,8 @@ function App() {
101106
promptConfig={promptConfig}
102107
modelConfig={modelConfig}
103108
setActiveDownloads={setActiveDownloads}
109+
setModelConfig={setModelConfig}
110+
reloadModel={reloadModel}
104111
/>
105112
</div>
106113
</div>

src/components/Buttons.jsx

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { HamburgerSvg } from "./SVGs.jsx";
22
import { PlusSvg } from "./SVGs.jsx"
3+
import { useState } from "react";
34

45
export function ClearAllHistoryButton() {
56
return (
@@ -111,4 +112,159 @@ export function TabPromptConfigButton({ setSelectedTab, className }) {
111112
Prompt Configs
112113
</button >
113114
)
115+
}
116+
117+
export function ModelConfigDoneButton({ selectedTab, setIsModelConfigOpen, setReloadModel }) {
118+
/* modelConfigTab, promptConfigTab */
119+
function handleClick () {
120+
if (selectedTab==='promptConfigTab') {setIsModelConfigOpen(false)}
121+
if (selectedTab==='modelConfigTab') {setReloadModel(prev => prev+1); setIsModelConfigOpen(false)}
122+
}
123+
return (
124+
<button
125+
onClick={handleClick}
126+
className={`w-full mt-6 text-white py-2 rounded-lg font-semibold transition-colors
127+
${selectedTab === 'promptConfigTab'
128+
? 'bg-blue-600 hover:bg-blue-500'
129+
: 'bg-red-600 hover:bg-red-400'
130+
}`}
131+
>
132+
{selectedTab === 'promptConfigTab'
133+
? "Done"
134+
: "Reload Model"
135+
}
136+
</button>
137+
)
138+
}
139+
140+
export function ModelConfigCloseButton({ setIsModelConfigOpen }) {
141+
return (
142+
<button
143+
onClick={() => setIsModelConfigOpen(false)}
144+
className="absolute top-4 right-4 text-gray-400 hover:text-white"
145+
>
146+
X
147+
</button>
148+
)
149+
}
150+
151+
export function ModelConfigMenuButton({ setIsModelConfigOpen }) {
152+
return (
153+
<button className="active:scale-95 h-full w-full" onClick={() => setIsModelConfigOpen(true)} >
154+
Configure Model
155+
</button>
156+
)
157+
}
158+
159+
export function CopyCodeBlockButton({ value }) {
160+
const [copied, setCopied] = useState(false)
161+
162+
const handleCopy = () => {
163+
navigator.clipboard.writeText(value)
164+
console.log('code block copied')
165+
setCopied(true)
166+
setTimeout(() => setCopied(false), 2000)
167+
}
168+
return (
169+
<button
170+
onClick={handleCopy}
171+
className="hover:text-white transition-colors flex items-center gap-1"
172+
>
173+
{copied ? (
174+
<span className="text-green-400">Copied!</span>
175+
) : (
176+
<span>Copy</span>
177+
)}
178+
</button>
179+
)
180+
}
181+
182+
export function ShowThinkingButton({ setIsThinkingBlockOpen, isThinkingBlockOpen }) {
183+
return (
184+
<button
185+
className="text-xs font-semibold text-gray-400 hover:text-white flex items-center gap-1 mb-1"
186+
onClick={() => setIsThinkingBlockOpen(!isThinkingBlockOpen)}
187+
>
188+
{isThinkingBlockOpen
189+
? '▼ Hide thinking'
190+
: '▶ Show thinking'
191+
}
192+
</button>
193+
)
194+
}
195+
196+
export function RenderHistoryButton({ session, setChatMessages }) {
197+
return (
198+
<button key={session.sessionId}
199+
className="w-full text-left p-2.5 rounded-lg border transition-all group relative mb-1 bg-gray-700/30 border-gray-700/50 hover:bg-gray-700"
200+
onClick={() => (setChatMessages(session.history))}
201+
>
202+
<div className="flex justify-between items-center">
203+
<span className="font-medium text-xs text-gray-300 group-hover:text-white truncate">{session.title}</span>
204+
</div>
205+
</button>
206+
)
207+
}
208+
209+
export function UploadedModelFilesButton({ index, setUploadedModel, file }) {
210+
return (
211+
<button key={index}
212+
className='w-full text-left p-2.5 rounded-lg border transition-all group relative mb-1 bg-green-900/20 border-green-800 hover:bg-green-900/40'
213+
onClick={() => (setUploadedModel(file))}
214+
>
215+
<div className="flex justify-between items-center">
216+
<div className="flex flex-col min-w-0 flex-1">
217+
<span className="font-medium text-xs text-gray-300 group-hover:text-white truncate">{file.name}</span>
218+
</div>
219+
</div>
220+
</button>
221+
)
222+
}
223+
224+
export function UploadedModelUrlsButton({ index, url, setSelectedModelUrl }) {
225+
return (
226+
<button key={index}
227+
className='w-full text-left p-2.5 rounded-lg border transition-all group relative mb-1 bg-green-900/20 border-green-800 hover:bg-green-900/40'
228+
onClick={() => (setSelectedModelUrl(url))}
229+
>
230+
<div className="flex justify-between items-center">
231+
<div className="flex flex-col min-w-0 flex-1">
232+
<span className="font-medium text-xs text-gray-300 group-hover:text-white truncate">{url.split('/').pop()}</span>
233+
</div>
234+
</div>
235+
</button>
236+
)
237+
}
238+
239+
export function RenderCsvModelsButton({ index, model, setSelectedModelUrl }) {
240+
const getModelName = (url) => {
241+
return url.split('/').pop()
242+
}
243+
const downloadedModelList = localStorage.getItem('downloadedModels') || '[]'
244+
245+
function checkIfDownloaded(url) {
246+
if (downloadedModelList.includes(url)) return true
247+
else return false
248+
}
249+
return (
250+
<button key={index}
251+
className={`w-full text-left p-2.5 rounded-lg border transition-all group relative mb-1
252+
${checkIfDownloaded(model[0])
253+
? 'bg-green-900/20 border-green-800 hover:bg-green-900/40'
254+
: 'bg-gray-700/30 border-gray-700/50 hover:bg-gray-700'}`}
255+
onClick={() => (setSelectedModelUrl(model[0]))}
256+
>
257+
<div className="flex justify-between items-center">
258+
<div className="flex flex-col min-w-0 flex-1">
259+
<span className="font-medium text-xs text-gray-300 group-hover:text-white truncate">{getModelName(model[0])}</span>
260+
{checkIfDownloaded(model[0]) &&
261+
<span className="text-[9px] text-green-400">
262+
Available offline
263+
</span>
264+
}
265+
</div>
266+
<span className="text-[10px] text-gray-500 bg-black/20 px-1.5 py-0.5 rounded whitespace-nowrap">{model[1]} MB</span>
267+
</div>
268+
</button>
269+
)
114270
}

src/components/Header.jsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@ export function Header({ isSidebarOpen, setIsSidebarOpen, modelStatus, loadedMod
55

66
return (
77
<div className="h-14 border-b border-gray-700 flex items-center px-4 justify-between bg-gray-800 z-10">
8-
<div className="flex items-center gap-3">
8+
<div className="flex items-center gap-3 min-w-0 flex-1">
99

1010
<SidebarToggleButton isSidebarOpen={isSidebarOpen} setIsSidebarOpen={setIsSidebarOpen} />
1111

12-
<div className="flex flex-col">
13-
<span id="header-status" className="font-bold text-sm text-gray-200">
12+
<div className="flex flex-col min-w-31">
13+
<span className="font-bold text-sm text-gray-200">
1414
Local AI
1515
</span>
1616

17-
<span id="active-model-name" className="text-[10px] text-gray-500 max-w-50">
17+
<span className="text-[10px] text-gray-500 truncate">
1818
{loadedModelName}
1919
</span>
2020
</div>
@@ -33,7 +33,6 @@ export function Header({ isSidebarOpen, setIsSidebarOpen, modelStatus, loadedMod
3333
>
3434
{modelStatus}
3535
</div>
36-
{/*onClick={startNewChat}*/}
3736
<NewChatButton setChatMessages={setChatMessages} chatMessages={chatMessages} />
3837
</div>
3938
</div>

src/components/InputArea.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export function InputArea({ setUserPrompt, modelStatus, isLiveTokenLive, stopMod
2525
setUserPrompt(inputValue)
2626
setInputValue('')
2727
} else {
28-
console.log('stopping model reply...')
28+
console.log('Stopping model reply...')
2929
stopModelReplyRef.current.abort()
3030
}
3131
};

0 commit comments

Comments
 (0)