|
3 | 3 | import { page } from '$app/state'; |
4 | 4 | import { getFavicon } from '$lib/api/favicon'; |
5 | 5 | import { logout } from '$lib/api/login'; |
6 | | - import type { Feed, Group } from '$lib/api/model'; |
| 6 | + import type { Feed } from '$lib/api/model'; |
7 | 7 | import { t } from '$lib/i18n'; |
| 8 | + import { globalState } from '$lib/state.svelte'; |
8 | 9 | import { |
9 | 10 | BookmarkCheck, |
10 | 11 | ChevronDown, |
|
28 | 29 | } from './ShortcutHelpModal.svelte'; |
29 | 30 | import ThemeController from './ThemeController.svelte'; |
30 | 31 |
|
31 | | - interface Props { |
32 | | - feeds: Promise<Feed[]>; |
33 | | - groups: Promise<Group[]>; |
34 | | - } |
35 | | -
|
36 | | - let { feeds, groups }: Props = $props(); |
37 | | -
|
38 | | - // State to track open groups |
39 | 32 | let openGroups = $state<Record<number, boolean>>({}); |
40 | 33 |
|
41 | | - let feedList = $derived.by(async () => { |
42 | | - const [feedsData, groupsData] = await Promise.all([feeds, groups]); |
| 34 | + let groupList = $derived.by(() => { |
43 | 35 | const groupFeeds: { id: number; name: string; feeds: (Feed & { indexInList: number })[] }[] = |
44 | 36 | []; |
45 | 37 | let curIndexInList = 0; |
46 | | - groupsData.forEach((group) => { |
| 38 | + globalState.groups.forEach((group) => { |
47 | 39 | groupFeeds.push({ |
48 | 40 | id: group.id, |
49 | 41 | name: group.name, |
50 | | - feeds: feedsData |
| 42 | + feeds: globalState.feeds |
51 | 43 | .filter((feed) => feed.group.id === group.id) |
52 | 44 | .sort((a, b) => a.name.localeCompare(b.name)) |
53 | 45 | .map((feed) => ({ |
54 | 46 | ...feed, |
55 | 47 | indexInList: curIndexInList++ |
56 | 48 | })) |
57 | 49 | }); |
58 | | - openGroups[group.id] = false; |
59 | 50 | }); |
60 | 51 | return groupFeeds; |
61 | 52 | }); |
|
115 | 106 | } |
116 | 107 |
|
117 | 108 | let selectedFeedIndex = $state(-1); |
118 | | - let selectedFeedGroupId = $state(-1); |
119 | | - $effect(() => { |
120 | | - feeds.then(() => { |
121 | | - selectedFeedIndex = -1; |
122 | | - selectedFeedGroupId = -1; |
123 | | - }); |
124 | | - }); |
125 | 109 | async function moveFeed(direction: 'prev' | 'next') { |
126 | | - const feedList = await feeds; |
| 110 | + const feedList = globalState.feeds; |
127 | 111 |
|
128 | 112 | if (feedList.length === 0) return; |
129 | 113 |
|
|
200 | 184 |
|
201 | 185 | <ul class="menu w-full"> |
202 | 186 | <li class="menu-title text-xs">{t('common.feeds')}</li> |
203 | | - {#await feedList} |
204 | | - <div class="skeleton bg-base-300 h-10"></div> |
205 | | - {:then groupData} |
206 | | - {#each groupData as group (group.id)} |
207 | | - {@const isOpen = openGroups[group.id]} |
208 | | - <li> |
209 | | - <div class="relative flex items-center pl-10"> |
210 | | - <button |
211 | | - class="btn btn-ghost btn-sm btn-square absolute top-0 left-1" |
212 | | - onclick={(event) => { |
213 | | - event.preventDefault(); |
214 | | - openGroups[group.id] = !isOpen; |
215 | | - }} |
216 | | - > |
217 | | - {#if isOpen} |
218 | | - <ChevronDown class="size-4" /> |
219 | | - {:else} |
220 | | - <ChevronRight class="size-4" /> |
221 | | - {/if} |
222 | | - </button> |
223 | | - <a href="/groups/{group.id}" class="line-clamp-1 grow text-left"> |
224 | | - {group.name} |
225 | | - </a> |
226 | | - </div> |
227 | | - <ul class:hidden={!isOpen}> |
228 | | - {#each group.feeds as feed} |
229 | | - {@const textColor = feed.suspended |
230 | | - ? 'text-neutral-content/60' |
231 | | - : feed.failure |
232 | | - ? 'text-error' |
233 | | - : ''} |
234 | | - <li> |
235 | | - <a |
236 | | - id="sidebar-feed-{feed.indexInList}" |
237 | | - data-group-id={group.id} |
238 | | - href="/feeds/{feed.id}" |
239 | | - class={`${isHighlight('/feeds/' + feed.id) ? 'menu-active' : ''} focus:ring-2`} |
240 | | - > |
241 | | - <div class="avatar"> |
242 | | - <div class="size-4 rounded-full"> |
243 | | - <img src={getFavicon(feed.link)} alt={feed.name} loading="lazy" /> |
244 | | - </div> |
| 187 | + {#each groupList as group} |
| 188 | + {@const isOpen = openGroups[group.id]} |
| 189 | + <li class="p-0"> |
| 190 | + <div class="gap-0 p-0"> |
| 191 | + <button |
| 192 | + class="btn btn-ghost btn-sm btn-square" |
| 193 | + onclick={(event) => { |
| 194 | + event.preventDefault(); |
| 195 | + openGroups[group.id] = !isOpen; |
| 196 | + }} |
| 197 | + > |
| 198 | + {#if isOpen} |
| 199 | + <ChevronDown class="size-4" /> |
| 200 | + {:else} |
| 201 | + <ChevronRight class="size-4" /> |
| 202 | + {/if} |
| 203 | + </button> |
| 204 | + <a |
| 205 | + href="/groups/{group.id}" |
| 206 | + class="line-clamp-1 block h-full grow place-content-center text-left" |
| 207 | + > |
| 208 | + {group.name} |
| 209 | + </a> |
| 210 | + </div> |
| 211 | + <ul class:hidden={!isOpen}> |
| 212 | + {#each group.feeds as feed} |
| 213 | + {@const textColor = feed.suspended |
| 214 | + ? 'text-neutral-content/60' |
| 215 | + : feed.failure |
| 216 | + ? 'text-error' |
| 217 | + : ''} |
| 218 | + <li> |
| 219 | + <a |
| 220 | + id="sidebar-feed-{feed.indexInList}" |
| 221 | + data-group-id={group.id} |
| 222 | + href="/feeds/{feed.id}" |
| 223 | + class={`${isHighlight('/feeds/' + feed.id) ? 'menu-active' : ''} focus:ring-2`} |
| 224 | + > |
| 225 | + <div class="avatar"> |
| 226 | + <div class="size-4 rounded-full"> |
| 227 | + <img src={getFavicon(feed.link)} alt={feed.name} loading="lazy" /> |
245 | 228 | </div> |
246 | | - <span class={`line-clamp-1 grow ${textColor}`}>{feed.name}</span> |
247 | | - {#if feed.unread_count > 0} |
248 | | - <span class="text-base-content/60 text-xs">{feed.unread_count}</span> |
249 | | - {/if} |
250 | | - </a> |
251 | | - </li> |
252 | | - {/each} |
253 | | - </ul> |
254 | | - </li> |
255 | | - {/each} |
256 | | - {/await} |
| 229 | + </div> |
| 230 | + <span class={`line-clamp-1 grow ${textColor}`}>{feed.name}</span> |
| 231 | + {#if feed.unread_count > 0} |
| 232 | + <span class="text-base-content/60 text-xs">{feed.unread_count}</span> |
| 233 | + {/if} |
| 234 | + </a> |
| 235 | + </li> |
| 236 | + {/each} |
| 237 | + </ul> |
| 238 | + </li> |
| 239 | + {/each} |
257 | 240 | </ul> |
258 | 241 | </div> |
259 | 242 |
|
|
0 commit comments