#2558 Add persona duping
| @@ -6440,6 +6440,9 @@ | |||
| 6440 | <button class="menu_button set_default_persona" title="Select this as default persona for the new chats." data-i18n="[title]Select this as default persona for the new chats."> | 6440 | <button class="menu_button set_default_persona" title="Select this as default persona for the new chats." data-i18n="[title]Select this as default persona for the new chats."> |
| 6441 | <i class="fa-fw fa-solid fa-crown"></i> | 6441 | <i class="fa-fw fa-solid fa-crown"></i> |
| 6442 | </button> | 6442 | </button> |
| 6443 | <button class="menu_button duplicate_persona" title="Duplicate persona" data-i18n="[title]Duplicate persona"> | ||
| 6444 | <i class="fa-fw fa-solid fa-clone"></i> | ||
| 6445 | </button> | ||
| 6443 | <button class="menu_button delete_avatar" title="Delete persona" data-i18n="[title]Delete persona"> | 6446 | <button class="menu_button delete_avatar" title="Delete persona" data-i18n="[title]Delete persona"> |
| 6444 | <i class="fa-fw fa-solid fa-trash-alt"></i> | 6447 | <i class="fa-fw fa-solid fa-trash-alt"></i> |
| 6445 | </button> | 6448 | </button> |
| @@ -1001,6 +1001,42 @@ export function retriggerFirstMessageOnEmptyChat() { | |||
| 1001 | } | 1001 | } |
| 1002 | } | 1002 | } |
| 1003 | 1003 | ||
| 1004 | /** | ||
| 1005 | * Duplicates a persona. | ||
| 1006 | * @param {string} avatarId | ||
| 1007 | * @returns {Promise<void>} | ||
| 1008 | */ | ||
| 1009 | async function duplicatePersona(avatarId) { | ||
| 1010 | const personaName = power_user.personas[avatarId]; | ||
| 1011 | |||
| 1012 | if (!personaName) { | ||
| 1013 | toastr.warning('Current avatar is not a persona'); | ||
| 1014 | return; | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | const confirm = await Popup.show.confirm('Are you sure you want to duplicate this persona?', personaName); | ||
| 1018 | |||
| 1019 | if (!confirm) { | ||
| 1020 | console.debug('User cancelled duplicating persona'); | ||
| 1021 | return; | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | const newAvatarId = `${Date.now()}-${personaName.replace(/[^a-zA-Z0-9]/g, '')}.png`; | ||
| 1025 | const descriptor = power_user.persona_descriptions[avatarId]; | ||
| 1026 | |||
| 1027 | power_user.personas[newAvatarId] = personaName; | ||
| 1028 | power_user.persona_descriptions[newAvatarId] = { | ||
| 1029 | description: descriptor?.description || '', | ||
| 1030 | position: descriptor?.position || persona_description_positions.IN_PROMPT, | ||
| 1031 | depth: descriptor?.depth || DEFAULT_DEPTH, | ||
| 1032 | role: descriptor?.role || DEFAULT_ROLE, | ||
| 1033 | }; | ||
| 1034 | |||
| 1035 | await uploadUserAvatar(getUserAvatar(avatarId), newAvatarId); | ||
| 1036 | await getUserAvatars(true, newAvatarId); | ||
| 1037 | saveSettingsDebounced(); | ||
| 1038 | } | ||
| 1039 | |||
| 1004 | export function initPersonas() { | 1040 | export function initPersonas() { |
| 1005 | $(document).on('click', '.bind_user_name', bindUserNameToPersona); | 1041 | $(document).on('click', '.bind_user_name', bindUserNameToPersona); |
| 1006 | $(document).on('click', '.set_default_persona', setDefaultPersona); | 1042 | $(document).on('click', '.set_default_persona', setDefaultPersona); |
| @@ -1059,6 +1095,18 @@ export function initPersonas() { | |||
| 1059 | $('#avatar_upload_file').trigger('click'); | 1095 | $('#avatar_upload_file').trigger('click'); |
| 1060 | }); | 1096 | }); |
| 1061 | 1097 | ||
| 1098 | $(document).on('click', '#user_avatar_block .duplicate_persona', function (e) { | ||
| 1099 | e.stopPropagation(); | ||
| 1100 | const avatarId = $(this).closest('.avatar-container').find('.avatar').attr('imgfile'); | ||
| 1101 | |||
| 1102 | if (!avatarId) { | ||
| 1103 | console.log('no imgfile'); | ||
| 1104 | return; | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | duplicatePersona(avatarId); | ||
| 1108 | }); | ||
| 1109 | |||
| 1062 | $(document).on('click', '#user_avatar_block .set_persona_image', function (e) { | 1110 | $(document).on('click', '#user_avatar_block .set_persona_image', function (e) { |
| 1063 | e.stopPropagation(); | 1111 | e.stopPropagation(); |
| 1064 | const avatarId = $(this).closest('.avatar-container').find('.avatar').attr('imgfile'); | 1112 | const avatarId = $(this).closest('.avatar-container').find('.avatar').attr('imgfile'); |
| @@ -3032,6 +3032,10 @@ grammarly-extension { | |||
| 3032 | opacity: 1; | 3032 | opacity: 1; |
| 3033 | } | 3033 | } |
| 3034 | 3034 | ||
| 3035 | .avatar-container .avatar-buttons .menu_button { | ||
| 3036 | padding: 3px; | ||
| 3037 | } | ||
| 3038 | |||
| 3035 | /* Ross should be able to handle this later */ | 3039 | /* Ross should be able to handle this later */ |
| 3036 | /*.big-avatars .avatar-buttons{ | 3040 | /*.big-avatars .avatar-buttons{ |
| 3037 | justify-content: center; | 3041 | justify-content: center; |