chore: added publishedDate and ordered posts 1ec34a32
Steve · 2025-11-01 21:31 5 file(s) · +38 −7
TODO.md +2 −2
2 2
3 3
Endless rambling of things to fix and improve
4 4
5 -
- [ ] Add `publishedDate` to `rssPost`
6 -
- [ ] Order posts by newest first
5 +
- [x] Add `publishedDate` to `rssPost`
6 +
- [x] Order posts by newest first
7 7
- [x] Instead of "by author" if Author is unavailable, use blog/feed name
8 8
- [x] Add auto-find RSS feed when adding a feed
9 9
- [ ] When scrolling through one feed and then selecting another, make the content scroll back to the top
src/components/app-sidebar.tsx +17 −5
89 89
	const feedPostsQuery = useQuery(postsByFeedQuery(selectedFeedId || ""));
90 90
	const feedPosts = selectedFeedId ? feedPostsQuery : allPosts;
91 91
92 -
	// Filter posts by search query
92 +
	// Filter and sort posts by search query and date
93 93
	const filteredPosts = React.useMemo(() => {
94 -
		if (!searchQuery) return feedPosts;
95 -
		return feedPosts.filter((post) =>
96 -
			post.title?.toLowerCase().includes(searchQuery.toLowerCase()),
97 -
		);
94 +
		const filtered = searchQuery
95 +
			? feedPosts.filter((post) =>
96 +
					post.title?.toLowerCase().includes(searchQuery.toLowerCase()),
97 +
				)
98 +
			: feedPosts;
99 +
100 +
		// Sort by publishedDate (most recent first)
101 +
		return [...filtered].sort((a, b) => {
102 +
			// Handle null dates - put them at the end
103 +
			if (!a.publishedDate) return 1;
104 +
			if (!b.publishedDate) return -1;
105 +
			// Most recent first (descending order)
106 +
			return b.publishedDate.localeCompare(a.publishedDate);
107 +
		});
98 108
	}, [feedPosts, searchQuery]);
99 109
100 110
	async function addFeed() {
195 205
				title: feedData.title,
196 206
				description: feedData.description || feedData.subtitle || "",
197 207
				category: categoryInput || "Uncategorized",
208 +
				dateUpdated: new Date().toISOString(),
198 209
			});
199 210
200 211
			// Process posts/entries
204 215
					author: isAtom
205 216
						? post.author?.name || feedData.title
206 217
						: post.author || feedData.title,
218 +
					publishedDate: new Date(post.pubDate || post.updated).toISOString(),
207 219
					link: isAtom
208 220
						? typeof post.link === "string"
209 221
							? post.link || post.id
src/components/dashboard.tsx +12 −0
148 148
											</Button>
149 149
										)}
150 150
									</div>
151 +
									<span className="text-xs text-muted-foreground">
152 +
										{selectedPost.publishedDate
153 +
											? new Date(selectedPost.publishedDate).toLocaleDateString(
154 +
													"en-US",
155 +
													{
156 +
														year: "numeric",
157 +
														month: "long",
158 +
														day: "numeric",
159 +
													},
160 +
												)
161 +
											: ""}
162 +
									</span>
151 163
								</div>
152 164
								<Separator />
153 165
								{selectedPost.content ? (
src/components/nav-feeds.tsx +5 −0
48 48
		{} as Record<string, Feed[]>,
49 49
	);
50 50
51 +
	// Sort feeds within each category alphabetically by title
52 +
	Object.keys(feedsByCategory).forEach((category) => {
53 +
		feedsByCategory[category].sort((a, b) => a.title.localeCompare(b.title));
54 +
	});
55 +
51 56
	const categories = Object.keys(feedsByCategory).sort();
52 57
53 58
	return (
src/lib/scheme.ts +2 −0
28 28
		title: NonEmptyString200,
29 29
		description: nullOr(NonEmptyString1000),
30 30
		category: nullOr(NonEmptyString50),
31 +
		dateUpdated: nullOr(NonEmptyString),
31 32
	},
32 33
	rssPost: {
33 34
		id: RSSPostId,
36 37
		link: NonEmptyString1000,
37 38
		content: nullOr(NonEmptyString),
38 39
		author: nullOr(NonEmptyString200),
40 +
		publishedDate: nullOr(NonEmptyString),
39 41
	},
40 42
	readStatus: {
41 43
		id: id("ReadStatus"),