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

Configure Feed

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

Fix double-search issue

Grace Kind (Jul 17, 2026, 5:21 PM -0500) 5dc1d74d 45c55aa2

+49 -1
+1 -1
package.json
··· 1 1 { 2 2 "name": "impro", 3 - "version": "0.17.194", 3 + "version": "0.17.195", 4 4 "type": "module", 5 5 "scripts": { 6 6 "start": "rm -rf \"${BUILD_DIR:-build}\" && NODE_ENV=development eleventy --serve",
+4
src/js/dataLayer/requests.js
··· 667 667 await this._loadPostDependencies(searchResults); 668 668 this.dataStore.setPosts([...searchResults, ...parentPosts]); 669 669 } 670 + // Re-check relevance after loading dependencies 671 + if (requestTime !== this.dataStore.$latestPostSearchRequestTime.get()) { 672 + return; 673 + } 670 674 const existingResults = this.dataStore.$postSearchResults.get(); 671 675 if (existingResults && cursor) { 672 676 this.dataStore.$postSearchResults.set({
+44
tests/unit/specs/dataLayer/requests.test.js
··· 1021 1021 assert.deepEqual(stored.cursor, "fresh"); 1022 1022 }); 1023 1023 1024 + it("should discard a stale cursored response that finishes dependency loading after a re-search", async () => { 1025 + const dataStore = new DataStore(); 1026 + const replyPost = (uri) => ({ 1027 + uri, 1028 + record: { reply: { parent: { uri: `${uri}-parent` } } }, 1029 + }); 1030 + const page1 = { posts: [replyPost("p1")], cursor: "c1" }; 1031 + const page2 = { posts: [replyPost("p2")], cursor: null }; 1032 + let getPostsGate = null; 1033 + const mockApi = { 1034 + searchPosts: async (query, { cursor }) => (cursor ? page2 : page1), 1035 + getPosts: async () => { 1036 + if (getPostsGate) { 1037 + const gate = getPostsGate; 1038 + getPostsGate = null; 1039 + await gate; 1040 + } 1041 + return []; 1042 + }, 1043 + }; 1044 + const requests = makeRequests(mockApi, dataStore); 1045 + 1046 + await requests.loadPostSearch("query"); 1047 + 1048 + // A load-more passes the requestTime guard, then stalls loading 1049 + // dependencies while a re-search and a fresh load-more complete 1050 + let releaseGate; 1051 + getPostsGate = new Promise((resolve) => { 1052 + releaseGate = resolve; 1053 + }); 1054 + const staleLoadMore = requests.loadPostSearch("query", { cursor: "c1" }); 1055 + await new Promise((resolve) => setTimeout(resolve, 5)); 1056 + await requests.loadPostSearch("query"); 1057 + await requests.loadPostSearch("query", { cursor: "c1" }); 1058 + releaseGate(); 1059 + await staleLoadMore; 1060 + 1061 + const stored = dataStore.$postSearchResults.get(); 1062 + assert.deepEqual( 1063 + stored.posts.map((post) => post.uri), 1064 + ["p1", "p2"], 1065 + ); 1066 + }); 1067 + 1024 1068 it("should append when cursor is provided and existing results present", async () => { 1025 1069 const dataStore = new DataStore(); 1026 1070 dataStore.$postSearchResults.set({