|
8 | 8 | </head> |
9 | 9 |
|
10 | 10 | <body> |
11 | | - <div id="app" class="flex flex-row opacity-0"> <!-- opacity-0 will be removed on app mounted --> |
12 | | - <!-- sidebar --> |
13 | | - <div class="flex flex-col bg-black bg-opacity-5 w-64 py-8 px-4 h-screen overflow-y-auto"> |
14 | | - <h2 class="font-bold mb-4 ml-4">Conversations</h2> |
15 | | - |
16 | | - <!-- list of conversations --> |
17 | | - <div :class="{ |
18 | | - 'btn btn-ghost justify-start': true, |
19 | | - 'btn-active': messages.length === 0, |
20 | | - }" @click="newConversation"> |
21 | | - + New conversation |
22 | | - </div> |
23 | | - <div v-for="conv in conversations" :class="{ |
24 | | - 'btn btn-ghost justify-start font-normal': true, |
25 | | - 'btn-active': conv.id === viewingConvId, |
26 | | - }" @click="setViewingConv(conv.id)"> |
27 | | - <span class="truncate">{{ conv.messages[0].content }}</span> |
28 | | - </div> |
29 | | - <div class="text-center text-xs opacity-40 mt-auto mx-4"> |
30 | | - Conversations are saved to browser's localStorage |
31 | | - </div> |
32 | | - </div> |
| 11 | + <div id="app" class="opacity-0"> <!-- opacity-0 will be removed on app mounted --> |
| 12 | + <div class="flex flex-row drawer lg:drawer-open"> |
| 13 | + <input id="toggle-drawer" type="checkbox" class="drawer-toggle" checked /> |
33 | 14 |
|
34 | | - <div class="chat-screen flex flex-col w-screen h-screen px-8 mx-auto"> |
35 | | - <!-- header --> |
36 | | - <div class="flex flex-row items-center"> |
37 | | - <div class="grow text-2xl font-bold mt-8 mb-6"> |
38 | | - 🦙 llama.cpp |
39 | | - </div> |
| 15 | + <!-- sidebar --> |
| 16 | + <div class="drawer-side h-screen lg:h-screen z-50 lg:max-w-64"> |
| 17 | + <label for="toggle-drawer" aria-label="close sidebar" class="drawer-overlay"></label> |
| 18 | + <div class="flex flex-col bg-base-200 min-h-full py-4 px-4"> |
| 19 | + <div class="flex flex-row items-center justify-between mb-4 mt-4"> |
| 20 | + <h2 class="font-bold ml-4">Conversations</h2> |
40 | 21 |
|
41 | | - <!-- action buttons (top right) --> |
42 | | - <div class="flex items-center"> |
43 | | - <div v-if="messages.length > 0" class="dropdown dropdown-end"> |
44 | | - <!-- "more" button --> |
45 | | - <div tabindex="0" role="button" class="btn m-1"> |
46 | | - <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-down" viewBox="0 0 16 16"> |
47 | | - <path fill-rule="evenodd" d="M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708"/> |
| 22 | + <!-- close sidebar button --> |
| 23 | + <label for="toggle-drawer" class="btn btn-ghost lg:hidden"> |
| 24 | + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-bar-left" viewBox="0 0 16 16"> |
| 25 | + <path fill-rule="evenodd" d="M12.5 15a.5.5 0 0 1-.5-.5v-13a.5.5 0 0 1 1 0v13a.5.5 0 0 1-.5.5M10 8a.5.5 0 0 1-.5.5H3.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L3.707 7.5H9.5a.5.5 0 0 1 .5.5"/> |
48 | 26 | </svg> |
49 | | - </div> |
50 | | - <!-- "more" dropdown menu --> |
51 | | - <ul tabindex="0" class="dropdown-content menu bg-base-100 rounded-box z-[1] w-52 p-2 shadow"> |
52 | | - <li @click="downloadConv(viewingConvId)" :disabled="isGenerating"><a>Download</a></li> |
53 | | - <li class="text-error" @click="deleteConv(viewingConvId)" :disabled="isGenerating"><a>Delete</a></li> |
54 | | - </ul> |
| 27 | + </label> |
| 28 | + </div> |
| 29 | + |
| 30 | + <!-- list of conversations --> |
| 31 | + <div :class="{ |
| 32 | + 'btn btn-ghost justify-start': true, |
| 33 | + 'btn-active': messages.length === 0, |
| 34 | + }" @click="newConversation"> |
| 35 | + + New conversation |
55 | 36 | </div> |
56 | | - <button class="btn" @click="showConfigDialog = true" :disabled="isGenerating"> |
57 | | - <!-- edit config button --> |
58 | | - <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-gear" viewBox="0 0 16 16"> |
59 | | - <path d="M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492M5.754 8a2.246 2.246 0 1 1 4.492 0 2.246 2.246 0 0 1-4.492 0"/> |
60 | | - <path d="M9.796 1.343c-.527-1.79-3.065-1.79-3.592 0l-.094.319a.873.873 0 0 1-1.255.52l-.292-.16c-1.64-.892-3.433.902-2.54 2.541l.159.292a.873.873 0 0 1-.52 1.255l-.319.094c-1.79.527-1.79 3.065 0 3.592l.319.094a.873.873 0 0 1 .52 1.255l-.16.292c-.892 1.64.901 3.434 2.541 2.54l.292-.159a.873.873 0 0 1 1.255.52l.094.319c.527 1.79 3.065 1.79 3.592 0l.094-.319a.873.873 0 0 1 1.255-.52l.292.16c1.64.893 3.434-.902 2.54-2.541l-.159-.292a.873.873 0 0 1 .52-1.255l.319-.094c1.79-.527 1.79-3.065 0-3.592l-.319-.094a.873.873 0 0 1-.52-1.255l.16-.292c.893-1.64-.902-3.433-2.541-2.54l-.292.159a.873.873 0 0 1-1.255-.52zm-2.633.283c.246-.835 1.428-.835 1.674 0l.094.319a1.873 1.873 0 0 0 2.693 1.115l.291-.16c.764-.415 1.6.42 1.184 1.185l-.159.292a1.873 1.873 0 0 0 1.116 2.692l.318.094c.835.246.835 1.428 0 1.674l-.319.094a1.873 1.873 0 0 0-1.115 2.693l.16.291c.415.764-.42 1.6-1.185 1.184l-.291-.159a1.873 1.873 0 0 0-2.693 1.116l-.094.318c-.246.835-1.428.835-1.674 0l-.094-.319a1.873 1.873 0 0 0-2.692-1.115l-.292.16c-.764.415-1.6-.42-1.184-1.185l.159-.291A1.873 1.873 0 0 0 1.945 8.93l-.319-.094c-.835-.246-.835-1.428 0-1.674l.319-.094A1.873 1.873 0 0 0 3.06 4.377l-.16-.292c-.415-.764.42-1.6 1.185-1.184l.292.159a1.873 1.873 0 0 0 2.692-1.115z"/> |
| 37 | + <div v-for="conv in conversations" :class="{ |
| 38 | + 'btn btn-ghost justify-start font-normal': true, |
| 39 | + 'btn-active': conv.id === viewingConvId, |
| 40 | + }" @click="setViewingConv(conv.id)"> |
| 41 | + <span class="truncate">{{ conv.messages[0].content }}</span> |
| 42 | + </div> |
| 43 | + <div class="text-center text-xs opacity-40 mt-auto mx-4"> |
| 44 | + Conversations are saved to browser's localStorage |
| 45 | + </div> |
| 46 | + </div> |
| 47 | + </div> |
| 48 | + |
| 49 | + <!-- main view --> |
| 50 | + <div class="chat-screen drawer-content grow flex flex-col h-screen w-screen mx-auto px-4"> |
| 51 | + <!-- header --> |
| 52 | + <div class="flex flex-row items-center mt-6 mb-6"> |
| 53 | + <!-- open sidebar button --> |
| 54 | + <label for="toggle-drawer" class="btn btn-ghost lg:hidden"> |
| 55 | + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-list" viewBox="0 0 16 16"> |
| 56 | + <path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5m0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5m0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5"/> |
61 | 57 | </svg> |
62 | | - </button> |
63 | | - |
64 | | - <!-- theme controller is copied from https://daisyui.com/components/theme-controller/ --> |
65 | | - <div class="dropdown dropdown-end dropdown-bottom"> |
66 | | - <div tabindex="0" role="button" class="btn m-1"> |
67 | | - Theme |
68 | | - <svg width="12px" height="12px" class="inline-block h-2 w-2 fill-current opacity-60" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2048 2048"> |
69 | | - <path d="M1799 349l242 241-1017 1017L7 590l242-241 775 775 775-775z"></path> |
| 58 | + </label> |
| 59 | + |
| 60 | + <div class="grow text-2xl font-bold ml-2">llama.cpp</div> |
| 61 | + |
| 62 | + <!-- action buttons (top right) --> |
| 63 | + <div class="flex items-center"> |
| 64 | + <div v-if="messages.length > 0" class="dropdown dropdown-end"> |
| 65 | + <!-- "more" button --> |
| 66 | + <div tabindex="0" role="button" class="btn m-1"> |
| 67 | + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-three-dots-vertical" viewBox="0 0 16 16"> |
| 68 | + <path d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0"/> |
| 69 | + </svg> |
| 70 | + </div> |
| 71 | + <!-- "more" dropdown menu --> |
| 72 | + <ul tabindex="0" class="dropdown-content menu bg-base-100 rounded-box z-[1] w-52 p-2 shadow"> |
| 73 | + <li @click="downloadConv(viewingConvId)" :disabled="isGenerating"><a>Download</a></li> |
| 74 | + <li class="text-error" @click="deleteConv(viewingConvId)" :disabled="isGenerating"><a>Delete</a></li> |
| 75 | + </ul> |
| 76 | + </div> |
| 77 | + <button class="btn" @click="showConfigDialog = true" :disabled="isGenerating"> |
| 78 | + <!-- settings button --> |
| 79 | + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-gear" viewBox="0 0 16 16"> |
| 80 | + <path d="M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492M5.754 8a2.246 2.246 0 1 1 4.492 0 2.246 2.246 0 0 1-4.492 0"/> |
| 81 | + <path d="M9.796 1.343c-.527-1.79-3.065-1.79-3.592 0l-.094.319a.873.873 0 0 1-1.255.52l-.292-.16c-1.64-.892-3.433.902-2.54 2.541l.159.292a.873.873 0 0 1-.52 1.255l-.319.094c-1.79.527-1.79 3.065 0 3.592l.319.094a.873.873 0 0 1 .52 1.255l-.16.292c-.892 1.64.901 3.434 2.541 2.54l.292-.159a.873.873 0 0 1 1.255.52l.094.319c.527 1.79 3.065 1.79 3.592 0l.094-.319a.873.873 0 0 1 1.255-.52l.292.16c1.64.893 3.434-.902 2.54-2.541l-.159-.292a.873.873 0 0 1 .52-1.255l.319-.094c1.79-.527 1.79-3.065 0-3.592l-.319-.094a.873.873 0 0 1-.52-1.255l.16-.292c.893-1.64-.902-3.433-2.541-2.54l-.292.159a.873.873 0 0 1-1.255-.52zm-2.633.283c.246-.835 1.428-.835 1.674 0l.094.319a1.873 1.873 0 0 0 2.693 1.115l.291-.16c.764-.415 1.6.42 1.184 1.185l-.159.292a1.873 1.873 0 0 0 1.116 2.692l.318.094c.835.246.835 1.428 0 1.674l-.319.094a1.873 1.873 0 0 0-1.115 2.693l.16.291c.415.764-.42 1.6-1.185 1.184l-.291-.159a1.873 1.873 0 0 0-2.693 1.116l-.094.318c-.246.835-1.428.835-1.674 0l-.094-.319a1.873 1.873 0 0 0-2.692-1.115l-.292.16c-.764.415-1.6-.42-1.184-1.185l.159-.291A1.873 1.873 0 0 0 1.945 8.93l-.319-.094c-.835-.246-.835-1.428 0-1.674l.319-.094A1.873 1.873 0 0 0 3.06 4.377l-.16-.292c-.415-.764.42-1.6 1.185-1.184l.292.159a1.873 1.873 0 0 0 2.692-1.115z"/> |
70 | 82 | </svg> |
| 83 | + </button> |
| 84 | + |
| 85 | + <!-- theme controller is copied from https://daisyui.com/components/theme-controller/ --> |
| 86 | + <div class="dropdown dropdown-end dropdown-bottom"> |
| 87 | + <div tabindex="0" role="button" class="btn m-1"> |
| 88 | + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-palette2" viewBox="0 0 16 16"> |
| 89 | + <path d="M0 .5A.5.5 0 0 1 .5 0h5a.5.5 0 0 1 .5.5v5.277l4.147-4.131a.5.5 0 0 1 .707 0l3.535 3.536a.5.5 0 0 1 0 .708L10.261 10H15.5a.5.5 0 0 1 .5.5v5a.5.5 0 0 1-.5.5H3a3 3 0 0 1-2.121-.879A3 3 0 0 1 0 13.044m6-.21 7.328-7.3-2.829-2.828L6 7.188zM4.5 13a1.5 1.5 0 1 0-3 0 1.5 1.5 0 0 0 3 0M15 15v-4H9.258l-4.015 4zM0 .5v12.495zm0 12.495V13z"/> |
| 90 | + </svg> |
| 91 | + </div> |
| 92 | + <ul tabindex="0" class="dropdown-content bg-base-300 rounded-box z-[1] w-52 p-2 shadow-2xl h-80 overflow-y-auto"> |
| 93 | + <li> |
| 94 | + <button |
| 95 | + class="btn btn-sm btn-block btn-ghost justify-start" |
| 96 | + :class="{ 'btn-active': selectedTheme === 'auto' }" |
| 97 | + @click="setSelectedTheme('auto')"> |
| 98 | + auto |
| 99 | + </button> |
| 100 | + </li> |
| 101 | + <li v-for="theme in themes"> |
| 102 | + <input |
| 103 | + type="radio" |
| 104 | + name="theme-dropdown" |
| 105 | + class="theme-controller btn btn-sm btn-block btn-ghost justify-start" |
| 106 | + :aria-label="theme" |
| 107 | + :value="theme" |
| 108 | + :checked="selectedTheme === theme" |
| 109 | + @click="setSelectedTheme(theme)" /> |
| 110 | + </li> |
| 111 | + </ul> |
71 | 112 | </div> |
72 | | - <ul tabindex="0" class="dropdown-content bg-base-300 rounded-box z-[1] w-52 p-2 shadow-2xl h-80 overflow-y-auto"> |
73 | | - <li> |
74 | | - <button |
75 | | - class="btn btn-sm btn-block w-full btn-ghost justify-start" |
76 | | - :class="{ 'btn-active': selectedTheme === 'auto' }" |
77 | | - @click="setSelectedTheme('auto')"> |
78 | | - auto |
79 | | - </button> |
80 | | - </li> |
81 | | - <li v-for="theme in themes"> |
82 | | - <input |
83 | | - type="radio" |
84 | | - name="theme-dropdown" |
85 | | - class="theme-controller btn btn-sm btn-block w-full btn-ghost justify-start" |
86 | | - :aria-label="theme" |
87 | | - :value="theme" |
88 | | - :checked="selectedTheme === theme" |
89 | | - @click="setSelectedTheme(theme)" /> |
90 | | - </li> |
91 | | - </ul> |
92 | 113 | </div> |
93 | 114 | </div> |
94 | | - </div> |
95 | 115 |
|
96 | | - <!-- chat messages --> |
97 | | - <div id="messages-list" class="flex flex-col grow overflow-y-auto"> |
98 | | - <div class="mt-auto flex justify-center"> |
99 | | - <!-- placeholder to shift the message to the bottom --> |
100 | | - {{ messages.length === 0 ? 'Send a message to start' : '' }} |
101 | | - </div> |
102 | | - <div v-for="msg in messages" class="group"> |
103 | | - <div :class="{ |
104 | | - 'chat': true, |
105 | | - 'chat-start': msg.role !== 'user', |
106 | | - 'chat-end': msg.role === 'user', |
107 | | - }"> |
| 116 | + <!-- chat messages --> |
| 117 | + <div id="messages-list" class="flex flex-col grow overflow-y-auto"> |
| 118 | + <div class="mt-auto flex justify-center"> |
| 119 | + <!-- placeholder to shift the message to the bottom --> |
| 120 | + {{ messages.length === 0 ? 'Send a message to start' : '' }} |
| 121 | + </div> |
| 122 | + <div v-for="msg in messages" class="group"> |
108 | 123 | <div :class="{ |
109 | | - 'chat-bubble markdown': true, |
110 | | - 'chat-bubble-base-300': msg.role !== 'user', |
| 124 | + 'chat': true, |
| 125 | + 'chat-start': msg.role !== 'user', |
| 126 | + 'chat-end': msg.role === 'user', |
111 | 127 | }"> |
112 | | - <!-- textarea for editing message --> |
113 | | - <template v-if="editingMsg && editingMsg.id === msg.id"> |
114 | | - <textarea |
115 | | - class="textarea textarea-bordered bg-base-100 text-base-content w-96" |
116 | | - v-model="msg.content"></textarea> |
117 | | - <br/> |
118 | | - <button class="btn btn-ghost mt-2 mr-2" @click="editingMsg = null">Cancel</button> |
119 | | - <button class="btn mt-2" @click="editUserMsgAndRegenerate(msg)">Submit</button> |
120 | | - </template> |
121 | | - <!-- render message as markdown --> |
122 | | - <vue-markdown v-else :source="msg.content" /> |
| 128 | + <div :class="{ |
| 129 | + 'chat-bubble markdown': true, |
| 130 | + 'chat-bubble-base-300': msg.role !== 'user', |
| 131 | + }"> |
| 132 | + <!-- textarea for editing message --> |
| 133 | + <template v-if="editingMsg && editingMsg.id === msg.id"> |
| 134 | + <textarea |
| 135 | + class="textarea textarea-bordered bg-base-100 text-base-content w-96" |
| 136 | + v-model="msg.content"></textarea> |
| 137 | + <br/> |
| 138 | + <button class="btn btn-ghost mt-2 mr-2" @click="editingMsg = null">Cancel</button> |
| 139 | + <button class="btn mt-2" @click="editUserMsgAndRegenerate(msg)">Submit</button> |
| 140 | + </template> |
| 141 | + <!-- render message as markdown --> |
| 142 | + <vue-markdown v-else :source="msg.content" /> |
| 143 | + </div> |
| 144 | + </div> |
| 145 | + |
| 146 | + <!-- actions for each message --> |
| 147 | + <div :class="{'text-right': msg.role === 'user'}" class="mx-4 mt-2 mb-2"> |
| 148 | + <!-- user message --> |
| 149 | + <button v-if="msg.role === 'user'" class="badge btn-mini show-on-hover" @click="editingMsg = msg" :disabled="isGenerating"> |
| 150 | + ✍️ Edit |
| 151 | + </button> |
| 152 | + <!-- assistant message --> |
| 153 | + <button v-if="msg.role === 'assistant'" class="badge btn-mini show-on-hover mr-2" @click="regenerateMsg(msg)" :disabled="isGenerating"> |
| 154 | + 🔄 Regenerate |
| 155 | + </button> |
| 156 | + <button v-if="msg.role === 'assistant'" class="badge btn-mini show-on-hover mr-2" @click="copyMsg(msg)" :disabled="isGenerating"> |
| 157 | + 📋 Copy |
| 158 | + </button> |
123 | 159 | </div> |
124 | 160 | </div> |
125 | 161 |
|
126 | | - <!-- actions for each message --> |
127 | | - <div :class="{'text-right': msg.role === 'user'}" class="mx-4 mt-2 mb-2"> |
128 | | - <!-- user message --> |
129 | | - <button v-if="msg.role === 'user'" class="badge btn-mini show-on-hover" @click="editingMsg = msg" :disabled="isGenerating"> |
130 | | - ✍️ Edit |
131 | | - </button> |
132 | | - <!-- assistant message --> |
133 | | - <button v-if="msg.role === 'assistant'" class="badge btn-mini show-on-hover mr-2" @click="regenerateMsg(msg)" :disabled="isGenerating"> |
134 | | - 🔄 Regenerate |
135 | | - </button> |
136 | | - <button v-if="msg.role === 'assistant'" class="badge btn-mini show-on-hover mr-2" @click="copyMsg(msg)" :disabled="isGenerating"> |
137 | | - 📋 Copy |
138 | | - </button> |
| 162 | + <!-- pending (ongoing) assistant message --> |
| 163 | + <div id="pending-msg" class="chat chat-start"> |
| 164 | + <div v-if="pendingMsg" class="chat-bubble markdown chat-bubble-base-300"> |
| 165 | + <span v-if="!pendingMsg.content" class="loading loading-dots loading-md"></span> |
| 166 | + <vue-markdown v-else :source="pendingMsg.content" /> |
| 167 | + </div> |
139 | 168 | </div> |
140 | 169 | </div> |
141 | 170 |
|
142 | | - <!-- pending (ongoing) assistant message --> |
143 | | - <div id="pending-msg" class="chat chat-start"> |
144 | | - <div v-if="pendingMsg" class="chat-bubble markdown chat-bubble-base-300"> |
145 | | - <span v-if="!pendingMsg.content" class="loading loading-dots loading-md"></span> |
146 | | - <vue-markdown v-else :source="pendingMsg.content" /> |
147 | | - </div> |
| 171 | + <!-- chat input --> |
| 172 | + <div class="flex flex-row items-center mt-8 mb-6"> |
| 173 | + <textarea |
| 174 | + class="textarea textarea-bordered w-full" |
| 175 | + placeholder="Type a message (Shift+Enter to add a new line)" |
| 176 | + v-model="inputMsg" |
| 177 | + @keydown.enter.exact.prevent="sendMessage" |
| 178 | + @keydown.enter.shift.exact.prevent="inputMsg += '\n'" |
| 179 | + :disabled="isGenerating" |
| 180 | + id="msg-input" |
| 181 | + ></textarea> |
| 182 | + <button v-if="!isGenerating" class="btn btn-primary ml-2" @click="sendMessage" :disabled="inputMsg.length === 0">Send</button> |
| 183 | + <button v-else class="btn btn-neutral ml-2" @click="stopGeneration">Stop</button> |
148 | 184 | </div> |
149 | 185 | </div> |
150 | 186 |
|
151 | | - <!-- chat input --> |
152 | | - <div class="flex flex-row items-center mt-8 mb-6"> |
153 | | - <textarea |
154 | | - class="textarea textarea-bordered w-full" |
155 | | - placeholder="Type a message (Shift+Enter to add a new line)" |
156 | | - v-model="inputMsg" |
157 | | - @keydown.enter.exact.prevent="sendMessage" |
158 | | - @keydown.enter.shift.exact.prevent="inputMsg += '\n'" |
159 | | - :disabled="isGenerating" |
160 | | - id="msg-input" |
161 | | - ></textarea> |
162 | | - <button v-if="!isGenerating" class="btn btn-primary ml-2" @click="sendMessage" :disabled="inputMsg.length === 0">Send</button> |
163 | | - <button v-else class="btn btn-neutral ml-2" @click="stopGeneration">Stop</button> |
164 | | - </div> |
165 | 187 | </div> |
166 | 188 |
|
| 189 | + |
167 | 190 | <!-- modal for editing config --> |
168 | 191 | <dialog class="modal" :class="{'modal-open': showConfigDialog}"> |
169 | 192 | <div class="modal-box"> |
@@ -217,10 +240,11 @@ <h3 class="text-lg font-bold mb-6">Settings</h3> |
217 | 240 | <div class="modal-action"> |
218 | 241 | <button class="btn" @click="resetConfigDialog">Reset to default</button> |
219 | 242 | <button class="btn" @click="closeAndDiscardConfigDialog">Close</button> |
220 | | - <button class="btn btn-primary" @click="closeAndSaveConfigDialog">Save and close</button> |
| 243 | + <button class="btn btn-primary" @click="closeAndSaveConfigDialog">Save</button> |
221 | 244 | </div> |
222 | 245 | </div> |
223 | 246 | </dialog> |
| 247 | + |
224 | 248 | </div> |
225 | 249 |
|
226 | 250 | <!-- Template to be used by settings modal --> |
|
0 commit comments