Reworked persona lock buttons + lock to character - Slight redesign of the persona panel right side, add headers - Add buttons for all three different lock states (chat, character, default) - Update lock and toggle lock functions to accept toggle type - Write persona locking to chat functionality (saves to persona description object)
| @@ -4924,8 +4924,6 @@ | |||
| 4924 | <input id="your_name" name="your_name" data-i18n="[placeholder]Enter your name" placeholder="Enter your name" class="text_pole wide100p" value="" autocomplete="off"> | 4924 | <input id="your_name" name="your_name" data-i18n="[placeholder]Enter your name" placeholder="Enter your name" class="text_pole wide100p" value="" autocomplete="off"> |
| 4925 | <div id="your_name_button" class="menu_button fa-solid fa-check" title="Click to set a new User Name" data-i18n="[title]Click to set a new User Name"> | 4925 | <div id="your_name_button" class="menu_button fa-solid fa-check" title="Click to set a new User Name" data-i18n="[title]Click to set a new User Name"> |
| 4926 | </div> | 4926 | </div> |
| 4927 | <div id="lock_user_name" class="menu_button fa-solid fa-unlock" title="Click to lock your selected persona to the current chat. Click again to remove the lock." data-i18n="[title]Click to lock your selected persona to the current chat. Click again to remove the lock."> | ||
| 4928 | </div> | ||
| 4929 | <div id="sync_name_button" class="menu_button fa-solid fa-sync" title="Click to set user name for all messages" data-i18n="[title]Click to set user name for all messages"> | 4927 | <div id="sync_name_button" class="menu_button fa-solid fa-sync" title="Click to set user name for all messages" data-i18n="[title]Click to set user name for all messages"> |
| 4930 | </div> | 4928 | </div> |
| 4931 | <div id="persona_lore_button" class="menu_button fa-solid fa-globe" title="Persona Lore Alt+Click to open the lorebook" data-i18n="[title]Persona Lore Alt+Click to open the lorebook"> | 4929 | <div id="persona_lore_button" class="menu_button fa-solid fa-globe" title="Persona Lore Alt+Click to open the lorebook" data-i18n="[title]Persona Lore Alt+Click to open the lorebook"> |
| @@ -4937,10 +4935,6 @@ | |||
| 4937 | <div class="extension_token_counter"> | 4935 | <div class="extension_token_counter"> |
| 4938 | <span data-i18n="Tokens persona description">Tokens</span>: <span id="persona_description_token_count">0</span> | 4936 | <span data-i18n="Tokens persona description">Tokens</span>: <span id="persona_description_token_count">0</span> |
| 4939 | </div> | 4937 | </div> |
| 4940 | </div> | ||
| 4941 | |||
| 4942 | <div class="persona_management_global_settings"> | ||
| 4943 | <h4 class="standoutHeader" data-i18n="Global Settings">Global Settings</h4> | ||
| 4944 | 4938 | ||
| 4945 | <div class="persona_management_description_position_container"> | 4939 | <div class="persona_management_description_position_container"> |
| 4946 | <label for="persona_description_position" data-i18n="Position:">Position:</label> | 4940 | <label for="persona_description_position" data-i18n="Position:">Position:</label> |
| @@ -4967,6 +4961,27 @@ | |||
| 4967 | </div> | 4961 | </div> |
| 4968 | </div> | 4962 | </div> |
| 4969 | 4963 | ||
| 4964 | <h4 data-i18n="Connections">Connections</h4> | ||
| 4965 | <div id="persona_connections_buttons" class="flex-container marginBot10"> | ||
| 4966 | <div id="lock_persona_default" class="menu_button menu_button_icon" title="Click to select this as default persona for the new chats. Click again to remove the lock." data-i18n="[title]Click to select this as default persona for the new chats. Click again to remove the lock."> | ||
| 4967 | <i class="icon fa-solid fa-crown fa-fw"></i> | ||
| 4968 | <div data-i18n="Default">Default</div> | ||
| 4969 | </div> | ||
| 4970 | <div id="lock_user_name" class="menu_button menu_button_icon" title="Click to lock your selected persona to the current chat. Click again to remove the lock." data-i18n="[title]Click to lock your selected persona to the current chat. Click again to remove the lock."> | ||
| 4971 | <i class="icon fa-solid fa-unlock fa-fw"></i> | ||
| 4972 | <div data-i18n="Chat">Chat</div> | ||
| 4973 | </div> | ||
| 4974 | <div id="lock_persona_to_char" class="menu_button menu_button_icon" title="Click to lock your selected persona to the current character. Click again to remove the lock." data-i18n="[title]Click to lock your selected persona to the current character. Click again to remove the lock."> | ||
| 4975 | <i class="icon fa-solid fa-unlock fa-fw"></i> | ||
| 4976 | <div data-i18n="Character">Character</div> | ||
| 4977 | </div> | ||
| 4978 | </div> | ||
| 4979 | <div id="persona_connections_list" class="text_muted m-b-1" data-i18n="persona_no_connections">[No connections]</div> | ||
| 4980 | </div> | ||
| 4981 | |||
| 4982 | <div class="persona_management_global_settings"> | ||
| 4983 | <h4 class="standoutHeader" data-i18n="Global Settings">Global Settings</h4> | ||
| 4984 | |||
| 4970 | <div class="persona_management_show_notifications range-block"> | 4985 | <div class="persona_management_show_notifications range-block"> |
| 4971 | <label for="persona_show_notifications" class="checkbox_label"> | 4986 | <label for="persona_show_notifications" class="checkbox_label"> |
| 4972 | <input id="persona_show_notifications" type="checkbox" /> | 4987 | <input id="persona_show_notifications" type="checkbox" /> |
| @@ -7,7 +7,9 @@ import { | |||
| 7 | event_types, | 7 | event_types, |
| 8 | getRequestHeaders, | 8 | getRequestHeaders, |
| 9 | getThumbnailUrl, | 9 | getThumbnailUrl, |
| 10 | menu_type, | ||
| 10 | name1, | 11 | name1, |
| 12 | name2, | ||
| 11 | reloadCurrentChat, | 13 | reloadCurrentChat, |
| 12 | saveChatConditional, | 14 | saveChatConditional, |
| 13 | saveMetadata, | 15 | saveMetadata, |
| @@ -26,6 +28,14 @@ import { t } from './i18n.js'; | |||
| 26 | import { openWorldInfoEditor, world_names } from './world-info.js'; | 28 | import { openWorldInfoEditor, world_names } from './world-info.js'; |
| 27 | import { renderTemplateAsync } from './templates.js'; | 29 | import { renderTemplateAsync } from './templates.js'; |
| 28 | 30 | ||
| 31 | /** | ||
| 32 | * @typedef {object} PersonaConnection A connection between a character and a character or group entity | ||
| 33 | * @property {'character' | 'group'} type - Type of connection | ||
| 34 | * @property {string} id - ID of the connection (character key (avatar url), group id) | ||
| 35 | */ | ||
| 36 | |||
| 37 | /** @typedef {'chat' | 'character' | 'default'} PersonaLockType Type of the persona lock */ | ||
| 38 | |||
| 29 | let savePersonasPage = 0; | 39 | let savePersonasPage = 0; |
| 30 | const GRID_STORAGE_KEY = 'Personas_GridView'; | 40 | const GRID_STORAGE_KEY = 'Personas_GridView'; |
| 31 | const DEFAULT_DEPTH = 2; | 41 | const DEFAULT_DEPTH = 2; |
| @@ -607,15 +617,35 @@ function selectCurrentPersona() { | |||
| 607 | } | 617 | } |
| 608 | 618 | ||
| 609 | /** | 619 | /** |
| 610 | * Checks if the persona is locked for the current chat. | 620 | * Checks if a connection is locked for the current character or group edit menu |
| 621 | * @param {PersonaConnection} connection - Connection to check | ||
| 622 | * @returns {boolean} Whether the connection is locked | ||
| 623 | */ | ||
| 624 | function isPersonaConnectionLocked(connection) { | ||
| 625 | return (menu_type === 'character_edit' && connection.type === 'character' && connection.id === characters[this_chid]?.avatar) | ||
| 626 | || (menu_type === 'group_edit' && connection.type === 'group' && connection.id === selected_group); | ||
| 627 | } | ||
| 628 | |||
| 629 | /** | ||
| 630 | * Checks if the persona is locked | ||
| 631 | * @param {PersonaLockType} type - Lock type | ||
| 611 | * @returns {boolean} Whether the persona is locked | 632 | * @returns {boolean} Whether the persona is locked |
| 612 | */ | 633 | */ |
| 613 | function isPersonaLocked() { | 634 | function isPersonaLocked(type = 'chat') { |
| 614 | return !!chat_metadata['persona']; | 635 | switch (type) { |
| 636 | case 'default': | ||
| 637 | return power_user.default_persona === user_avatar; | ||
| 638 | case 'chat': | ||
| 639 | return chat_metadata['persona'] == user_avatar; | ||
| 640 | case 'character': { | ||
| 641 | return !!power_user.persona_descriptions[user_avatar]?.connections?.some(isPersonaConnectionLocked); | ||
| 642 | } | ||
| 643 | default: throw new Error(`Unknown persona lock type: ${type}`); | ||
| 644 | } | ||
| 615 | } | 645 | } |
| 616 | 646 | ||
| 617 | /** | 647 | /** |
| 618 | * Locks or unlocks the persona for the current chat. | 648 | * Locks or unlocks the persona |
| 619 | * @param {boolean} state Desired lock state | 649 | * @param {boolean} state Desired lock state |
| 620 | * @returns {Promise<void>} | 650 | * @returns {Promise<void>} |
| 621 | */ | 651 | */ |
| @@ -624,34 +654,63 @@ export async function setPersonaLockState(state) { | |||
| 624 | } | 654 | } |
| 625 | 655 | ||
| 626 | /** | 656 | /** |
| 627 | * Toggle the persona lock state for the current chat. | 657 | * Toggle the persona lock state |
| 658 | * @param {PersonaLockType} type - Lock type | ||
| 628 | * @returns {Promise<void>} | 659 | * @returns {Promise<void>} |
| 629 | */ | 660 | */ |
| 630 | export async function togglePersonaLock() { | 661 | export async function togglePersonaLock(type = 'chat') { |
| 631 | return isPersonaLocked() | 662 | return isPersonaLocked(type) |
| 632 | ? await unlockPersona() | 663 | ? await unlockPersona(type) |
| 633 | : await lockPersona(); | 664 | : await lockPersona(type); |
| 634 | } | 665 | } |
| 635 | 666 | ||
| 636 | /** | 667 | /** |
| 637 | * Unlock the persona for the current chat. | 668 | * Unlock the persona |
| 669 | * @param {PersonaLockType} type - Lock type | ||
| 670 | * @returns {Promise<void>} | ||
| 638 | */ | 671 | */ |
| 639 | async function unlockPersona() { | 672 | async function unlockPersona(type = 'chat') { |
| 673 | switch (type) { | ||
| 674 | case 'default': { | ||
| 675 | // TODO: Make this toggle-able | ||
| 676 | await toggleDefaultPersona(user_avatar, { quiet: true }); | ||
| 677 | break; | ||
| 678 | } | ||
| 679 | case 'chat': { | ||
| 640 | if (chat_metadata['persona']) { | 680 | if (chat_metadata['persona']) { |
| 641 | console.log(`Unlocking persona for this chat ${chat_metadata['persona']}`); | 681 | console.log(`Unlocking persona ${user_avatar} from this chat`); |
| 642 | delete chat_metadata['persona']; | 682 | delete chat_metadata['persona']; |
| 643 | await saveMetadata(); | 683 | await saveMetadata(); |
| 644 | if (power_user.persona_show_notifications) { | 684 | if (power_user.persona_show_notifications) { |
| 645 | toastr.info(t`User persona is now unlocked for this chat. Click the "Lock" again to revert.`, t`Persona unlocked`); | 685 | toastr.info(t`User persona ${name1} is now unlocked from this chat. Click the "Lock" again to revert.`, t`Persona unlocked`); |
| 646 | } | 686 | } |
| 647 | updateUserLockIcon(); | ||
| 648 | } | 687 | } |
| 688 | break; | ||
| 689 | } | ||
| 690 | case 'character': { | ||
| 691 | /** @type {PersonaConnection[]} */ | ||
| 692 | const connections = power_user.persona_descriptions[user_avatar]?.connections; | ||
| 693 | if (connections) { | ||
| 694 | console.log(`Unlocking persona ${user_avatar} from this character ${name2}`); | ||
| 695 | power_user.persona_descriptions[user_avatar].connections = connections.filter(c => !isPersonaConnectionLocked(c)); | ||
| 696 | saveSettingsDebounced(); | ||
| 697 | if (power_user.persona_show_notifications) { | ||
| 698 | toastr.info(t`User persona ${name1} is now unlocked from character ${name2}. Click the "Lock" again to revert.`, t`Persona unlocked`); | ||
| 699 | } | ||
| 700 | } | ||
| 701 | break; | ||
| 702 | } | ||
| 703 | } | ||
| 704 | |||
| 705 | updatePersonaLockIcons(); | ||
| 649 | } | 706 | } |
| 650 | 707 | ||
| 651 | /** | 708 | /** |
| 652 | * Lock the persona for the current chat. | 709 | * Lock the persona |
| 710 | * @param {PersonaLockType} type - Lock type | ||
| 653 | */ | 711 | */ |
| 654 | async function lockPersona() { | 712 | async function lockPersona(type = 'chat') { |
| 713 | // First make sure that user_avatar is actually a persona | ||
| 655 | if (!(user_avatar in power_user.personas)) { | 714 | if (!(user_avatar in power_user.personas)) { |
| 656 | console.log(`Creating a new persona ${user_avatar}`); | 715 | console.log(`Creating a new persona ${user_avatar}`); |
| 657 | if (power_user.persona_show_notifications) { | 716 | if (power_user.persona_show_notifications) { |
| @@ -668,17 +727,44 @@ async function lockPersona() { | |||
| 668 | depth: DEFAULT_DEPTH, | 727 | depth: DEFAULT_DEPTH, |
| 669 | role: DEFAULT_ROLE, | 728 | role: DEFAULT_ROLE, |
| 670 | lorebook: '', | 729 | lorebook: '', |
| 730 | connections: [], | ||
| 671 | }; | 731 | }; |
| 672 | } | 732 | } |
| 673 | 733 | ||
| 734 | switch (type) { | ||
| 735 | case 'default': { | ||
| 736 | // TODO: Make this toggle-able | ||
| 737 | await toggleDefaultPersona(user_avatar, { quiet: true }); | ||
| 738 | break; | ||
| 739 | } | ||
| 740 | case 'chat': { | ||
| 741 | console.log(`Locking persona ${user_avatar} to this chat`); | ||
| 674 | chat_metadata['persona'] = user_avatar; | 742 | chat_metadata['persona'] = user_avatar; |
| 675 | await saveMetadata(); | 743 | await saveMetadata(); |
| 676 | saveSettingsDebounced(); | 744 | saveSettingsDebounced(); |
| 677 | console.log(`Locking persona for this chat ${user_avatar}`); | ||
| 678 | if (power_user.persona_show_notifications) { | 745 | if (power_user.persona_show_notifications) { |
| 679 | toastr.success(t`User persona is locked to ${name1} in this chat`); | 746 | toastr.success(t`User persona ${name1} is locked to ${name2} in this chat`); |
| 747 | } | ||
| 748 | break; | ||
| 749 | } | ||
| 750 | case 'character': { | ||
| 751 | const newConnection = menu_type === 'character_edit' ? { type: 'character', id: characters[this_chid]?.avatar } : | ||
| 752 | menu_type === 'group_edit' ? { type: 'group', id: selected_group } : null; | ||
| 753 | /** @type {PersonaConnection[]} */ | ||
| 754 | const connections = power_user.persona_descriptions[user_avatar].connections?.filter(c => !isPersonaConnectionLocked(c)) ?? []; | ||
| 755 | if (newConnection && newConnection.id) { | ||
| 756 | console.log(`Locking persona ${user_avatar} to this character ${name2}`); | ||
| 757 | power_user.persona_descriptions[user_avatar].connections = [...connections, newConnection]; | ||
| 758 | saveSettingsDebounced(); | ||
| 759 | if (power_user.persona_show_notifications) { | ||
| 760 | toastr.success(t`User persona ${name1} is locked to character ${name2}`); | ||
| 761 | } | ||
| 762 | } | ||
| 763 | break; | ||
| 680 | } | 764 | } |
| 681 | updateUserLockIcon(); | 765 | } |
| 766 | |||
| 767 | updatePersonaLockIcons(); | ||
| 682 | } | 768 | } |
| 683 | 769 | ||
| 684 | 770 | ||
| @@ -730,7 +816,7 @@ async function deleteUserAvatar(e) { | |||
| 730 | 816 | ||
| 731 | saveSettingsDebounced(); | 817 | saveSettingsDebounced(); |
| 732 | await getUserAvatars(); | 818 | await getUserAvatars(); |
| 733 | updateUserLockIcon(); | 819 | updatePersonaLockIcons(); |
| 734 | } | 820 | } |
| 735 | } | 821 | } |
| 736 | 822 | ||
| @@ -853,16 +939,33 @@ function getOrCreatePersonaDescriptor() { | |||
| 853 | depth: power_user.persona_description_depth, | 939 | depth: power_user.persona_description_depth, |
| 854 | role: power_user.persona_description_role, | 940 | role: power_user.persona_description_role, |
| 855 | lorebook: power_user.persona_description_lorebook, | 941 | lorebook: power_user.persona_description_lorebook, |
| 942 | connections: [], | ||
| 856 | }; | 943 | }; |
| 857 | power_user.persona_descriptions[user_avatar] = object; | 944 | power_user.persona_descriptions[user_avatar] = object; |
| 858 | } | 945 | } |
| 859 | return object; | 946 | return object; |
| 860 | } | 947 | } |
| 861 | 948 | ||
| 862 | async function setDefaultPersona(e) { | 949 | |
| 950 | |||
| 951 | async function toggleDefaultPersonaClicked(e) { | ||
| 863 | e?.stopPropagation(); | 952 | e?.stopPropagation(); |
| 864 | const avatarId = $(this).closest('.avatar-container').find('.avatar').attr('imgfile'); | 953 | const avatarId = $(e.currentTarget).closest('.avatar-container').find('.avatar').attr('imgfile'); |
| 954 | if (avatarId) { | ||
| 955 | await toggleDefaultPersona(avatarId); | ||
| 956 | } else { | ||
| 957 | console.warn('No avatar id found'); | ||
| 958 | } | ||
| 959 | } | ||
| 865 | 960 | ||
| 961 | /** | ||
| 962 | * Sets a persona as the default one to be used for all new chats and unlocked existing chats | ||
| 963 | * @param {string} avatarId The avatar id of the persona to set as the default | ||
| 964 | * @param {object} [options] Optional arguments | ||
| 965 | * @param {boolean} [options.quiet=false] If true, no confirmation popups will be shown | ||
| 966 | * @returns {Promise<void>} | ||
| 967 | */ | ||
| 968 | async function toggleDefaultPersona(avatarId, { quiet: quiet = false } = {}) { | ||
| 866 | if (!avatarId) { | 969 | if (!avatarId) { |
| 867 | console.warn('No avatar id found'); | 970 | console.warn('No avatar id found'); |
| 868 | return; | 971 | return; |
| @@ -879,12 +982,13 @@ async function setDefaultPersona(e) { | |||
| 879 | const personaName = power_user.personas[avatarId]; | 982 | const personaName = power_user.personas[avatarId]; |
| 880 | 983 | ||
| 881 | if (avatarId === currentDefault) { | 984 | if (avatarId === currentDefault) { |
| 985 | if (!quiet) { | ||
| 882 | const confirm = await Popup.show.confirm(t`Are you sure you want to remove the default persona?`, personaName); | 986 | const confirm = await Popup.show.confirm(t`Are you sure you want to remove the default persona?`, personaName); |
| 883 | |||
| 884 | if (!confirm) { | 987 | if (!confirm) { |
| 885 | console.debug('User cancelled removing default persona'); | 988 | console.debug('User cancelled removing default persona'); |
| 886 | return; | 989 | return; |
| 887 | } | 990 | } |
| 991 | } | ||
| 888 | 992 | ||
| 889 | console.log(`Removing default persona ${avatarId}`); | 993 | console.log(`Removing default persona ${avatarId}`); |
| 890 | if (power_user.persona_show_notifications) { | 994 | if (power_user.persona_show_notifications) { |
| @@ -892,12 +996,13 @@ async function setDefaultPersona(e) { | |||
| 892 | } | 996 | } |
| 893 | delete power_user.default_persona; | 997 | delete power_user.default_persona; |
| 894 | } else { | 998 | } else { |
| 999 | if (!quiet) { | ||
| 895 | const confirm = await Popup.show.confirm(t`Are you sure you want to set \"${personaName}\" as the default persona?`, t`This name and avatar will be used for all new chats, as well as existing chats where the user persona is not locked.`); | 1000 | const confirm = await Popup.show.confirm(t`Are you sure you want to set \"${personaName}\" as the default persona?`, t`This name and avatar will be used for all new chats, as well as existing chats where the user persona is not locked.`); |
| 896 | |||
| 897 | if (!confirm) { | 1001 | if (!confirm) { |
| 898 | console.debug('User cancelled setting default persona'); | 1002 | console.debug('User cancelled setting default persona'); |
| 899 | return; | 1003 | return; |
| 900 | } | 1004 | } |
| 1005 | } | ||
| 901 | 1006 | ||
| 902 | power_user.default_persona = avatarId; | 1007 | power_user.default_persona = avatarId; |
| 903 | if (power_user.persona_show_notifications) { | 1008 | if (power_user.persona_show_notifications) { |
| @@ -907,12 +1012,26 @@ async function setDefaultPersona(e) { | |||
| 907 | 1012 | ||
| 908 | saveSettingsDebounced(); | 1013 | saveSettingsDebounced(); |
| 909 | await getUserAvatars(true, avatarId); | 1014 | await getUserAvatars(true, avatarId); |
| 1015 | updatePersonaLockIcons(); | ||
| 910 | } | 1016 | } |
| 911 | 1017 | ||
| 912 | function updateUserLockIcon() { | 1018 | function updatePersonaLockIcons() { |
| 913 | const hasLock = !!chat_metadata['persona']; | 1019 | const isDefaultPersona = power_user.default_persona === user_avatar; |
| 914 | $('#lock_user_name').toggleClass('fa-unlock', !hasLock); | 1020 | $('#lock_persona_default').toggleClass('locked', isDefaultPersona); |
| 915 | $('#lock_user_name').toggleClass('fa-lock', hasLock); | 1021 | |
| 1022 | const hasChatLock = chat_metadata['persona'] == user_avatar; | ||
| 1023 | $('#lock_user_name').toggleClass('locked', hasChatLock); | ||
| 1024 | $('#lock_user_name i.icon').toggleClass('fa-lock', hasChatLock); | ||
| 1025 | $('#lock_user_name i.icon').toggleClass('fa-unlock', !hasChatLock); | ||
| 1026 | |||
| 1027 | /** @type {PersonaConnection[]} */ | ||
| 1028 | const connections = power_user.persona_descriptions[user_avatar]?.connections; | ||
| 1029 | const hasCharLock = !!connections.some(c => | ||
| 1030 | (menu_type === 'character_edit' && c.type === 'character' && c.id === characters[this_chid]?.avatar) | ||
| 1031 | || (menu_type === 'group_edit' && c.type === 'group' && c.id === selected_group)); | ||
| 1032 | $('#lock_persona_to_char').toggleClass('locked', hasCharLock); | ||
| 1033 | $('#lock_persona_to_char i.icon').toggleClass('fa-lock', hasCharLock); | ||
| 1034 | $('#lock_persona_to_char i.icon').toggleClass('fa-unlock', !hasCharLock); | ||
| 916 | } | 1035 | } |
| 917 | 1036 | ||
| 918 | async function setChatLockedPersona() { | 1037 | async function setChatLockedPersona() { |
| @@ -942,7 +1061,7 @@ async function setChatLockedPersona() { | |||
| 942 | if (chat_metadata['persona'] && !userAvatars.includes(chatPersona)) { | 1061 | if (chat_metadata['persona'] && !userAvatars.includes(chatPersona)) { |
| 943 | console.warn('Persona avatar not found, unlocking persona'); | 1062 | console.warn('Persona avatar not found, unlocking persona'); |
| 944 | delete chat_metadata['persona']; | 1063 | delete chat_metadata['persona']; |
| 945 | updateUserLockIcon(); | 1064 | updatePersonaLockIcons(); |
| 946 | return; | 1065 | return; |
| 947 | } | 1066 | } |
| 948 | 1067 | ||
| @@ -956,7 +1075,7 @@ async function setChatLockedPersona() { | |||
| 956 | 1075 | ||
| 957 | // Persona avatar found, select it | 1076 | // Persona avatar found, select it |
| 958 | setUserAvatar(chatPersona); | 1077 | setUserAvatar(chatPersona); |
| 959 | updateUserLockIcon(); | 1078 | updatePersonaLockIcons(); |
| 960 | } | 1079 | } |
| 961 | 1080 | ||
| 962 | function onBackupPersonas() { | 1081 | function onBackupPersonas() { |
| @@ -1112,9 +1231,11 @@ async function duplicatePersona(avatarId) { | |||
| 1112 | 1231 | ||
| 1113 | export function initPersonas() { | 1232 | export function initPersonas() { |
| 1114 | $(document).on('click', '.bind_user_name', bindUserNameToPersona); | 1233 | $(document).on('click', '.bind_user_name', bindUserNameToPersona); |
| 1115 | $(document).on('click', '.set_default_persona', setDefaultPersona); | 1234 | $(document).on('click', '.set_default_persona', toggleDefaultPersonaClicked); |
| 1116 | $(document).on('click', '.delete_avatar', deleteUserAvatar); | 1235 | $(document).on('click', '.delete_avatar', deleteUserAvatar); |
| 1117 | $('#lock_user_name').on('click', togglePersonaLock); | 1236 | $('#lock_persona_default').on('click', () => togglePersonaLock('default')); |
| 1237 | $('#lock_user_name').on('click', () => togglePersonaLock('chat')); | ||
| 1238 | $('#lock_persona_to_char').on('click', () => togglePersonaLock('character')); | ||
| 1118 | $('#create_dummy_persona').on('click', createDummyPersona); | 1239 | $('#create_dummy_persona').on('click', createDummyPersona); |
| 1119 | $('#persona_description').on('input', onPersonaDescriptionInput); | 1240 | $('#persona_description').on('input', onPersonaDescriptionInput); |
| 1120 | $('#persona_description_position').on('input', onPersonaDescriptionPositionInput); | 1241 | $('#persona_description_position').on('input', onPersonaDescriptionPositionInput); |
| @@ -3759,6 +3759,14 @@ input[type='checkbox'].del_checkbox { | |||
| 3759 | color: var(--golden); | 3759 | color: var(--golden); |
| 3760 | } | 3760 | } |
| 3761 | 3761 | ||
| 3762 | #lock_persona_default.locked i.icon { | ||
| 3763 | color: var(--golden); | ||
| 3764 | } | ||
| 3765 | #lock_user_name.locked i.icon, | ||
| 3766 | #lock_persona_to_char.locked i.icon { | ||
| 3767 | color: var(--active); | ||
| 3768 | } | ||
| 3769 | |||
| 3762 | #user_avatar_block .avatar_upload { | 3770 | #user_avatar_block .avatar_upload { |
| 3763 | cursor: pointer; | 3771 | cursor: pointer; |
| 3764 | width: 60px; | 3772 | width: 60px; |