Add sorting order for extensions manager

f98d27f1870a6e9c9ca257e6ad87afd7b33fcf2c

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

1 files changed, +23 -9Showing whitespace changes
public/scripts/extensions.js+23 -9
@@ -38,7 +38,8 @@ export let modules = [];
38let activeExtensions = new Set();38let activeExtensions = new Set();
3939
40const getApiUrl = () => extension_settings.apiUrl;40const getApiUrl = () => extension_settings.apiUrl;
41const sortManifests = (a, b) => parseInt(a.loading_order) - parseInt(b.loading_order) || String(a.display_name).localeCompare(String(b.display_name));41const sortManifestsByOrder = (a, b) => parseInt(a.loading_order) - parseInt(b.loading_order) || String(a.display_name).localeCompare(String(b.display_name));
42const sortManifestsByName = (a, b) => String(a.display_name).localeCompare(String(b.display_name)) || parseInt(a.loading_order) - parseInt(b.loading_order);
42let connectedToApi = false;43let connectedToApi = false;
4344
44/**45/**
@@ -355,7 +356,7 @@ async function getManifests(names) {
355 * @returns {Promise<void>}356 * @returns {Promise<void>}
356 */357 */
357async function activateExtensions() {358async function activateExtensions() {
358 const extensions = Object.entries(manifests).sort((a, b) => sortManifests(a[1], b[1]));359 const extensions = Object.entries(manifests).sort((a, b) => sortManifestsByOrder(a[1], b[1]));
359 const promises = [];360 const promises = [];
360361
361 for (let entry of extensions) {362 for (let entry of extensions) {
@@ -712,7 +713,10 @@ async function showExtensionsDetails() {
712713
713 htmlExternal.append(htmlLoading);714 htmlExternal.append(htmlLoading);
714715
715 const extensions = Object.entries(manifests).sort((a, b) => sortManifests(a[1], b[1])).map(getExtensionData);716 const sortOrderKey = 'extensions_sortByName';
717 const sortByName = localStorage.getItem(sortOrderKey) === 'true';
718 const sortFn = sortByName ? sortManifestsByName : sortManifestsByOrder;
719 const extensions = Object.entries(manifests).sort((a, b) => sortFn(a[1], b[1])).map(getExtensionData);
716720
717 extensions.forEach(value => {721 extensions.forEach(value => {
718 const { isExternal, extensionHtml } = value;722 const { isExternal, extensionHtml } = value;
@@ -729,7 +733,6 @@ async function showExtensionsDetails() {
729 /** @type {import('./popup.js').CustomPopupButton} */733 /** @type {import('./popup.js').CustomPopupButton} */
730 const updateAllButton = {734 const updateAllButton = {
731 text: t`Update all`,735 text: t`Update all`,
732 appendAtEnd: true,
733 action: async () => {736 action: async () => {
734 requiresReload = true;737 requiresReload = true;
735 await autoUpdateExtensions(true);738 await autoUpdateExtensions(true);
@@ -737,13 +740,23 @@ async function showExtensionsDetails() {
737 },740 },
738 };741 };
739742
743 /** @type {import('./popup.js').CustomPopupButton} */
744 const sortOrderButton = {
745 text: sortByName ? t`Sort: Display Name` : t`Sort: Loading Order`,
746 action: async () => {
747 abortController.abort();
748 localStorage.setItem(sortOrderKey, sortByName ? 'false' : 'true');
749 await showExtensionsDetails();
750 },
751 };
752
740 let waitingForSave = false;753 let waitingForSave = false;
741754
742 const popup = new Popup(html, POPUP_TYPE.TEXT, '', {755 const popup = new Popup(html, POPUP_TYPE.TEXT, '', {
743 okButton: t`Close`,756 okButton: t`Close`,
744 wide: true,757 wide: true,
745 large: true,758 large: true,
746 customButtons: [updateAllButton],759 customButtons: [sortOrderButton, updateAllButton],
747 allowVerticalScrolling: true,760 allowVerticalScrolling: true,
748 onClosing: async () => {761 onClosing: async () => {
749 if (waitingForSave) {762 if (waitingForSave) {
@@ -762,7 +775,7 @@ async function showExtensionsDetails() {
762 });775 });
763 popupPromise = popup.show();776 popupPromise = popup.show();
764 popup.content.scrollTop = initialScrollTop;777 popup.content.scrollTop = initialScrollTop;
765 checkForUpdatesManual(abortController.signal).finally(() => htmlLoading.remove());778 checkForUpdatesManual(sortFn, abortController.signal).finally(() => htmlLoading.remove());
766 } catch (error) {779 } catch (error) {
767 toastr.error(t`Error loading extensions. See browser console for details.`);780 toastr.error(t`Error loading extensions. See browser console for details.`);
768 console.error(error);781 console.error(error);
@@ -1073,12 +1086,13 @@ function processVersionCheckQueue() {
10731086
1074/**1087/**
1075 * Performs a manual check for updates on all 3rd-party extensions.1088 * Performs a manual check for updates on all 3rd-party extensions.
1089 * @param {function} sortFn Sort function
1076 * @param {AbortSignal} abortSignal Signal to abort the operation1090 * @param {AbortSignal} abortSignal Signal to abort the operation
1077 * @returns {Promise<any[]>}1091 * @returns {Promise<any[]>}
1078 */1092 */
1079async function checkForUpdatesManual(abortSignal) {1093async function checkForUpdatesManual(sortFn, abortSignal) {
1080 const promises = [];1094 const promises = [];
1081 for (const id of Object.keys(manifests).filter(x => x.startsWith('third-party')).sort((a, b) => sortManifests(manifests[a], manifests[b]))) {1095 for (const id of Object.keys(manifests).filter(x => x.startsWith('third-party')).sort((a, b) => sortFn(manifests[a], manifests[b]))) {
1082 const externalId = id.replace('third-party', '');1096 const externalId = id.replace('third-party', '');
1083 const promise = enqueueVersionCheck(async () => {1097 const promise = enqueueVersionCheck(async () => {
1084 try {1098 try {
@@ -1223,7 +1237,7 @@ export async function runGenerationInterceptors(chat, contextSize, type) {
1223 exitImmediately = immediately;1237 exitImmediately = immediately;
1224 };1238 };
12251239
1226 for (const manifest of Object.values(manifests).filter(x => x.generate_interceptor).sort((a, b) => sortManifests(a, b))) {1240 for (const manifest of Object.values(manifests).filter(x => x.generate_interceptor).sort((a, b) => sortManifestsByOrder(a, b))) {
1227 const interceptorKey = manifest.generate_interceptor;1241 const interceptorKey = manifest.generate_interceptor;
1228 if (typeof globalThis[interceptorKey] === 'function') {1242 if (typeof globalThis[interceptorKey] === 'function') {
1229 try {1243 try {