Show more recent chats
| @@ -6,6 +6,10 @@ | ||
| 6 | 6 | width: 100%; |
| 7 | 7 | } |
| 8 | 8 | |
| 9 | +.welcomePanel:has(.showMoreChats) { | |
| 10 | + padding-bottom: 5px; | |
| 11 | +} | |
| 12 | + | |
| 9 | 13 | body.bubblechat .welcomePanel { |
| 10 | 14 | border-radius: 10px; |
| 11 | 15 | background-color: var(--SmartThemeBotMesBlurTintColor); |
| @@ -22,7 +26,7 @@ body.bubblechat .welcomePanel { | ||
| 22 | 26 | |
| 23 | 27 | .welcomePanel .recentChatsTitle { |
| 24 | 28 | flex-grow: 1; |
| 25 | 29 | font-size: calc(var(--mainFontSize) * 1.115); |
| 26 | 30 | font-weight: 600; |
| 27 | 31 | } |
| 28 | 32 | |
| @@ -36,7 +40,7 @@ body.bubblechat .welcomePanel { | ||
| 36 | 40 | } |
| 37 | 41 | |
| 38 | 42 | .welcomePanel .welcomeHeaderVersionDisplay { |
| 39 | 43 | font-size: calc(var(--mainFontSize) * 1.23); |
| 40 | 44 | font-weight: 600; |
| 41 | 45 | } |
| 42 | 46 | |
| @@ -174,6 +178,14 @@ body.big-avatars .welcomeRecent .recentChatList .recentChat .chatMessageContaine | ||
| 174 | 178 | font-size: calc(var(--mainFontSize) * 0.95); |
| 175 | 179 | } |
| 176 | 180 | |
| 181 | +.welcomeRecent .recentChatList .recentChat.hidden { | |
| 182 | + display: none; | |
| 183 | +} | |
| 184 | + | |
| 185 | +.welcomeRecent .recentChatList .showMoreChats { | |
| 186 | + align-self: center; | |
| 187 | +} | |
| 188 | + | |
| 177 | 189 | @media screen and (max-width: 1000px) { |
| 178 | 190 | .welcomePanel .welcomeShortcuts a span { |
| 179 | 191 | display: none; |
| @@ -37,7 +37,7 @@ | ||
| 37 | 37 | {{/if}} |
| 38 | 38 | {{#each chats}} |
| 39 | 39 | {{#with this}} |
| 40 | 40 | <div class="recentChat {{#if hidden}}hidden{{/if}}" data-file="{{chat_name}}" data-avatar="{{avatar}}"> |
| 41 | 41 | <div class="avatar" title="{{char_name}}"> |
| 42 | 42 | <img src="{{char_thumbnail}}" alt="{{char_name}}"> |
| 43 | 43 | </div> |
| @@ -66,6 +66,13 @@ | ||
| 66 | 66 | </div> |
| 67 | 67 | {{/with}} |
| 68 | 68 | {{/each}} |
| 69 | + {{#if more}} | |
| 70 | + <button class="menu_button menu_button_icon showMoreChats"> | |
| 71 | + <small data-i18n="Show more"> | |
| 72 | + Show more | |
| 73 | + </small> | |
| 74 | + </button> | |
| 75 | + {{/if}} | |
| 69 | 76 | </div> |
| 70 | 77 | </div> |
| 71 | 78 | </div> |
| @@ -62,6 +62,7 @@ async function sendWelcomePanel() { | ||
| 62 | 62 | chats, |
| 63 | 63 | empty: !chats.length, |
| 64 | 64 | version: displayVersion, |
| 65 | + more: chats.some(chat => chat.hidden), | |
| 65 | 66 | }; |
| 66 | 67 | const template = await renderTemplateAsync('welcomePanel', templateData); |
| 67 | 68 | const fragment = document.createRange().createContextualFragment(template); |
| @@ -74,9 +75,20 @@ async function sendWelcomePanel() { | ||
| 74 | 75 | } |
| 75 | 76 | }); |
| 76 | 77 | }); |
| 77 | - fragment.querySelector('button.openTemporaryChat').addEventListener('click', () => { | |
| 78 | + const hiddenChats = fragment.querySelectorAll('.recentChat.hidden'); | |
| 79 | + fragment.querySelectorAll('button.showMoreChats').forEach((button) => { | |
| 80 | + button.addEventListener('click', () => { | |
| 81 | + hiddenChats.forEach((chatItem) => { | |
| 82 | + chatItem.classList.remove('hidden'); | |
| 83 | + }); | |
| 84 | + button.remove(); | |
| 85 | + }); | |
| 86 | + }); | |
| 87 | + fragment.querySelectorAll('button.openTemporaryChat').forEach((button) => { | |
| 88 | + button.addEventListener('click', () => { | |
| 78 | 89 | void newAssistantChat({ temporary: true }); |
| 79 | 90 | }); |
| 91 | + }); | |
| 80 | 92 | chatElement.append(fragment.firstChild); |
| 81 | 93 | } catch (error) { |
| 82 | 94 | console.error('Welcome screen error:', error); |
| @@ -125,6 +137,7 @@ async function openRecentChat(avatarId, fileName) { | ||
| 125 | 137 | * @property {string} char_name Character name |
| 126 | 138 | * @property {string} date_short Date in short format |
| 127 | 139 | * @property {string} date_long Date in long format |
| 140 | + * @property {boolean} hidden Chat will be hidden by default | |
| 128 | 141 | */ |
| 129 | 142 | async function getRecentChats() { |
| 130 | 143 | const response = await fetch('/api/characters/recent', { |
| @@ -141,13 +154,15 @@ async function getRecentChats() { | ||
| 141 | 154 | data.sort((a, b) => b.last_mes - a.last_mes) |
| 142 | 155 | .map(chat => ({ chat, character: characters.find(x => x.avatar === chat.avatar) })) |
| 143 | 156 | .filter(t => t.character) |
| 144 | 157 | .forEach(({ chat, character }, index) => { |
| 158 | + const DEFAULT_DISPLAYED = 5; | |
| 145 | 159 | const chatTimestamp = timestampToMoment(chat.last_mes); |
| 146 | 160 | chat.char_name = character.name; |
| 147 | 161 | chat.date_short = chatTimestamp.format('l'); |
| 148 | 162 | chat.date_long = chatTimestamp.format('LL LT'); |
| 149 | 163 | chat.chat_name = chat.file_name.replace('.jsonl', ''); |
| 150 | 164 | chat.char_thumbnail = getThumbnailUrl('avatar', character.avatar); |
| 165 | + chat.hidden = index >= DEFAULT_DISPLAYED; | |
| 151 | 166 | }); |
| 152 | 167 | |
| 153 | 168 | return data; |
| @@ -1312,7 +1312,7 @@ router.post('/recent', async function (request, response) { | ||
| 1312 | 1312 | } |
| 1313 | 1313 | } |
| 1314 | 1314 | |
| 1315 | 1315 | const recentChats = allChatFiles.sort((a, b) => b.mtime - a.mtime).slice(0, 515); |
| 1316 | 1316 | const jsonFilesPromise = recentChats.map((file) => { |
| 1317 | 1317 | return getChatInfo(file.filePath, { avatar: file.pngFile }); |
| 1318 | 1318 | }); |