Fix convert to persona with unusual names (#4319) * Fix convert to persona with unusual names * Fix picking new persona on current persona deletion * Prefer actual path on page reload

7b67769c926cf2e92cb8cbe19c22b9a678834b30

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
3 files changed, +28 -18Ignore whitespace
public/script.js+2 -6
@@ -6448,11 +6448,7 @@ async function read_avatar_load(input) {
6448 const formData = new FormData(/** @type {HTMLFormElement} */($('#form_create').get(0)));6448 const formData = new FormData(/** @type {HTMLFormElement} */($('#form_create').get(0)));
6449 await fetch(getThumbnailUrl('avatar', formData.get('avatar_url').toString()), {6449 await fetch(getThumbnailUrl('avatar', formData.get('avatar_url').toString()), {
6450 method: 'GET',6450 method: 'GET',
6451 cache: 'no-cache',6451 cache: 'reload',
6452 headers: {
6453 'pragma': 'no-cache',
6454 'cache-control': 'no-cache',
6455 },
6456 });6452 });
64576453
6458 const messages = $('.mes').toArray();6454 const messages = $('.mes').toArray();
@@ -10854,7 +10850,7 @@ jQuery(async function () {
10854 data.set(file, characters[this_chid].avatar);10850 data.set(file, characters[this_chid].avatar);
10855 await processDroppedFiles([file], data);10851 await processDroppedFiles([file], data);
10856 await openCharacterChat(chatFile);10852 await openCharacterChat(chatFile);
10857 await fetch(getThumbnailUrl('avatar', characters[this_chid].avatar), { cache: 'no-cache' });10853 await fetch(getThumbnailUrl('avatar', characters[this_chid].avatar), { cache: 'reload' });
10858 } catch {10854 } catch {
10859 toastr.error('Failed to replace the character card.', 'Something went wrong');10855 toastr.error('Failed to replace the character card.', 'Something went wrong');
10860 }10856 }
public/scripts/personas.js+25 -11
@@ -317,14 +317,20 @@ async function uploadUserAvatar(url, name) {
317 formData.append('overwrite_name', name);317 formData.append('overwrite_name', name);
318 }318 }
319319
320 await fetch('/api/avatars/upload', {320 const response = await fetch('/api/avatars/upload', {
321 method: 'POST',321 method: 'POST',
322 headers: getRequestHeaders({ omitContentType: true }),322 headers: getRequestHeaders({ omitContentType: true }),
323 cache: 'no-cache',323 cache: 'no-cache',
324 body: formData,324 body: formData,
325 });325 });
326326
327 await getUserAvatars(true, name);327 if (!response.ok) {
328 throw new Error(`Failed to upload avatar: ${response.statusText}`);
329 }
330
331 // Get the actual path from the response
332 const data = await response.json();
333 await getUserAvatars(true, data?.path || name);
328}334}
329335
330async function changeUserAvatar(e) {336async function changeUserAvatar(e) {
@@ -367,7 +373,7 @@ async function changeUserAvatar(e) {
367373
368 const response = await fetch(url, {374 const response = await fetch(url, {
369 method: 'POST',375 method: 'POST',
370 headers: getRequestHeaders({ omitContentType:true }),376 headers: getRequestHeaders({ omitContentType: true }),
371 cache: 'no-cache',377 cache: 'no-cache',
372 body: formData,378 body: formData,
373 });379 });
@@ -375,21 +381,23 @@ async function changeUserAvatar(e) {
375 if (response.ok) {381 if (response.ok) {
376 const data = await response.json();382 const data = await response.json();
377383
384 const overwriteName = formData.get('overwrite_name');
385 const dataPath = data?.path;
386
378 // If the user uploaded a new avatar, we want to make sure it's not cached387 // If the user uploaded a new avatar, we want to make sure it's not cached
379 const name = formData.get('overwrite_name');388 if (overwriteName && dataPath) {
380 if (name) {389 await fetch(getUserAvatar(String(dataPath)), { cache: 'reload' });
381 await fetch(getUserAvatar(String(name)), { cache: 'no-cache' });390 await fetch(getThumbnailUrl('persona', String(dataPath)), { cache: 'reload' });
382 await fetch(getThumbnailUrl('persona', String(name)), { cache: 'no-cache' });
383 reloadUserAvatar(true);391 reloadUserAvatar(true);
384 }392 }
385393
386 if (!name && data.path) {394 if (!overwriteName && dataPath) {
387 await getUserAvatars();395 await getUserAvatars();
388 await delay(500);396 await delay(1);
389 await createPersona(data.path);397 await createPersona(dataPath);
390 }398 }
391399
392 await getUserAvatars(true, name || data.path);400 await getUserAvatars(true, dataPath || overwriteName);
393 }401 }
394402
395 // Will allow to select the same file twice in a row403 // Will allow to select the same file twice in a row
@@ -1424,6 +1432,12 @@ async function loadPersonaForCurrentChat({ doRender = false } = {}) {
1424 // Cache persona list to check if they exist1432 // Cache persona list to check if they exist
1425 const userAvatars = await getUserAvatars(doRender);1433 const userAvatars = await getUserAvatars(doRender);
14261434
1435 // Check if the user avatar is set and exists in the list of user avatars
1436 if (userAvatars.length && !userAvatars.includes(user_avatar)) {
1437 console.log(`User avatar ${user_avatar} not found in user avatars list, pick the first available one`);
1438 setUserAvatar(userAvatars[0], { toastPersonaNameChange: false, navigateToCurrent: true });
1439 }
1440
1427 // Define a persona for this chat1441 // Define a persona for this chat
1428 let chatPersona = '';1442 let chatPersona = '';
14291443
src/endpoints/avatars.js+1 -1
@@ -53,7 +53,7 @@ router.post('/upload', getFileNameValidationFunction('overwrite_name'), async (r
53 cacheBuster.bust(request, response);53 cacheBuster.bust(request, response);
54 }54 }
5555
56 const filename = request.body.overwrite_name || `${Date.now()}.png`;56 const filename = sanitize(request.body.overwrite_name || `${Date.now()}.png`);
57 const pathToNewFile = path.join(request.user.directories.avatars, filename);57 const pathToNewFile = path.join(request.user.directories.avatars, filename);
58 writeFileAtomicSync(pathToNewFile, image);58 writeFileAtomicSync(pathToNewFile, image);
59 fs.unlinkSync(pathToUpload);59 fs.unlinkSync(pathToUpload);