Mirror of https://github.com/improsocial/impro An extensible Bluesky client for web impro.social
5

Configure Feed

Select the types of activity you want to include in your feed.

Sort community plugins alphabetically

Grace Kind (Jul 14, 2026, 2:55 PM -0500) 964eb645 13096a40

+64 -4
+1 -1
package.json
··· 1 1 { 2 2 "name": "impro", 3 - "version": "0.17.155", 3 + "version": "0.17.156", 4 4 "type": "module", 5 5 "scripts": { 6 6 "start": "rm -rf \"${BUILD_DIR:-build}\" && NODE_ENV=development eleventy --serve",
+7 -2
src/js/plugins/pluginService.js
··· 104 104 const installedIds = new Set( 105 105 this.prefManager.$installedPlugins.get().map((entry) => entry.id), 106 106 ); 107 - return rawListings.map((listing) => ({ 107 + const sortedListings = sortBy(rawListings, (listing) => 108 + listing.name.toLowerCase(), 109 + ); 110 + return sortedListings.map((listing) => ({ 108 111 ...listing, 109 112 installed: installedIds.has(listing.id), 110 113 })); ··· 114 117 const visiblePlugins = this.localPluginsEnabled 115 118 ? installedPlugins 116 119 : installedPlugins.filter((entry) => !entry.id.endsWith("__LOCAL")); 117 - const sortedVisiblePlugins = sortBy(visiblePlugins, "name"); 120 + const sortedVisiblePlugins = sortBy(visiblePlugins, (plugin) => 121 + plugin.name.toLowerCase(), 122 + ); 118 123 return sortedVisiblePlugins.map((entry) => ({ 119 124 id: entry.id, 120 125 name: entry.name,
+1 -1
src/js/utils.js
··· 52 52 throw new Error(`Invalid direction: ${direction}`); 53 53 } 54 54 const sign = direction === "desc" ? -1 : 1; 55 - const sorted = array.sort((a, b) => { 55 + const sorted = [...array].sort((a, b) => { 56 56 const aValue = fn(a); 57 57 const bValue = fn(b); 58 58 if (aValue < bValue) return -1 * sign;
+16
tests/unit/specs/plugins/pluginService.test.js
··· 850 850 assert.deepEqual(provider.$preferences.get(), before); 851 851 }); 852 852 853 + it("sorts listings alphabetically by name, ignoring case", async () => { 854 + const { service } = makeService({ 855 + remoteListings: [ 856 + { id: "gamma", repo: "ow/gamma", name: "gamma" }, 857 + { id: "alpha", repo: "ow/alpha", name: "Alpha" }, 858 + ], 859 + localListings: [{ id: "beta__LOCAL", name: "Beta" }], 860 + }); 861 + await service.loadRegistryListings(); 862 + const listings = service.$registryListings.get(); 863 + assert.deepEqual( 864 + listings.map((listing) => listing.name), 865 + ["Alpha", "Beta", "gamma"], 866 + ); 867 + }); 868 + 853 869 it("returns only remote listings when localRegistry is absent", async () => { 854 870 const { service } = makeService({ 855 871 remoteListings: [{ id: "alpha", repo: "ow/alpha", name: "Alpha" }],
+39
tests/unit/specs/utils.test.js
··· 3 3 import { 4 4 unique, 5 5 groupBy, 6 + sortBy, 6 7 noop, 7 8 sliceByByte, 8 9 formatLargeNumber, ··· 25 26 debounce, 26 27 resetScrollOnBlur, 27 28 } from "/js/utils.js"; 29 + 30 + describe("sortBy", () => { 31 + it("sorts by a key string ascending", () => { 32 + const input = [{ name: "Gamma" }, { name: "Alpha" }, { name: "Beta" }]; 33 + const result = sortBy(input, "name"); 34 + assert.deepEqual( 35 + result.map((item) => item.name), 36 + ["Alpha", "Beta", "Gamma"], 37 + ); 38 + }); 39 + 40 + it("sorts by a function descending", () => { 41 + const input = [{ value: 1 }, { value: 3 }, { value: 2 }]; 42 + const result = sortBy(input, (item) => item.value, { 43 + direction: "desc", 44 + }); 45 + assert.deepEqual( 46 + result.map((item) => item.value), 47 + [3, 2, 1], 48 + ); 49 + }); 50 + 51 + it("returns a copy without mutating the input array", () => { 52 + const input = [{ name: "Beta" }, { name: "Alpha" }]; 53 + const result = sortBy(input, "name"); 54 + assert(result !== input); 55 + assert.deepEqual( 56 + input.map((item) => item.name), 57 + ["Beta", "Alpha"], 58 + ); 59 + }); 60 + 61 + it("throws on an invalid direction", () => { 62 + assert.throws(() => sortBy([], "name", { direction: "up" }), { 63 + message: "Invalid direction: up", 64 + }); 65 + }); 66 + }); 28 67 29 68 describe("unique", () => { 30 69 it("should remove duplicates from simple array", () => {