BlueSky & more on desktop lazurite.stormlightlabs.org/
tauri rust typescript bluesky appview atproto solid
2
fork

Configure Feed

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

refactor: reorganize hooks and components

+108 -120
+1 -1
src/components/AvatarBadge.test.tsx src/components/tests/AvatarBadge.test.tsx
··· 1 1 import { render } from "@solidjs/testing-library"; 2 2 import { describe, expect, it } from "vitest"; 3 - import { AvatarBadge } from "./AvatarBadge"; 3 + import { AvatarBadge } from "../AvatarBadge"; 4 4 5 5 describe("AvatarBadge", () => { 6 6 it("uses solid primary background (no gradient)", () => {
+1 -1
src/components/LoginPanel.test.tsx src/components/tests/LoginPanel.test.tsx
··· 1 1 import { fireEvent, render, screen } from "@solidjs/testing-library"; 2 2 import { createSignal } from "solid-js"; 3 3 import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; 4 - import { LoginPanel } from "./LoginPanel"; 4 + import { LoginPanel } from "../LoginPanel"; 5 5 6 6 const invokeMock = vi.hoisted(() => vi.fn()); 7 7
+1 -1
src/components/LoginPanel.tsx
··· 1 - import { ActorSuggestionList, useActorSuggestions } from "$/components/actors/actor-search"; 1 + import { ActorSuggestionList, useActorSuggestions } from "$/components/actors/ActorSearch"; 2 2 import type { LoginSuggestion } from "$/lib/types"; 3 3 import { createEffect, Show } from "solid-js"; 4 4 import { Motion } from "solid-motionone";
+1 -1
src/components/Session.test.tsx src/components/tests/Session.test.tsx
··· 1 1 import { AppTestProviders } from "$/test/providers"; 2 2 import { render, screen } from "@solidjs/testing-library"; 3 3 import { describe, expect, it } from "vitest"; 4 - import { SessionEmptyState, SessionSpotlight } from "./Session"; 4 + import { SessionEmptyState, SessionSpotlight } from "../Session"; 5 5 6 6 describe("SessionEmptyState", () => { 7 7 it("renders empty state copy", () => {
+1 -1
src/components/Wordmark.test.tsx src/components/tests/Wordmark.test.tsx
··· 1 1 import { render, screen } from "@solidjs/testing-library"; 2 2 import { describe, expect, it } from "vitest"; 3 - import { Wordmark } from "./Wordmark"; 3 + import { Wordmark } from "../Wordmark"; 4 4 5 5 describe("Wordmark", () => { 6 6 it("renders inline SVG logo with currentColor fill", () => {
+1 -1
src/components/account/AccountSwitcher.test.tsx src/components/account/tests/AccountSwitcher.test.tsx
··· 1 1 import { AppTestProviders } from "$/test/providers"; 2 2 import { fireEvent, render, screen } from "@solidjs/testing-library"; 3 3 import { describe, expect, it, vi } from "vitest"; 4 - import { AccountSwitcher } from "./AccountSwitcher"; 4 + import { AccountSwitcher } from "../AccountSwitcher"; 5 5 6 6 const ACCOUNT = { 7 7 active: false,
src/components/actors/actor-search.tsx src/components/actors/ActorSearch.tsx
+1 -1
src/components/deck/ColumnPicker/ProfileColumnPicker.tsx
··· 1 - import { ActorSuggestionList, useActorSuggestions } from "$/components/actors/actor-search"; 1 + import { ActorSuggestionList, useActorSuggestions } from "$/components/actors/ActorSearch"; 2 2 import { Icon } from "$/components/shared/Icon"; 3 3 import type { LoginSuggestion } from "$/lib/types"; 4 4 import * as logger from "@tauri-apps/plugin-log";
+1 -1
src/components/deck/DeckColumn.tsx
··· 1 1 import { ExplorerPanel } from "$/components/explorer/ExplorerPanel"; 2 2 import { FeedContent } from "$/components/feeds/FeedContent"; 3 3 import { MessagesPanel } from "$/components/messages/MessagesPanel"; 4 - import { usePostNavigation } from "$/components/posts/usePostNavigation"; 4 + import { usePostNavigation } from "$/components/posts/hooks/usePostNavigation"; 5 5 import { ProfilePanel } from "$/components/profile/ProfilePanel"; 6 6 import { SearchPanel } from "$/components/search/SearchPanel"; 7 7 import type { Column, ColumnWidth } from "$/lib/api/types/columns";
+1 -1
src/components/deck/DeckWorkspace.tsx
··· 1 - import { useThreadOverlayNavigation } from "$/components/posts/useThreadOverlayNavigation"; 1 + import { useThreadOverlayNavigation } from "$/components/posts/hooks/useThreadOverlayNavigation"; 2 2 import { useAppSession } from "$/contexts/app-session"; 3 3 import { addColumn, getColumns, removeColumn, reorderColumns, updateColumn } from "$/lib/api/columns"; 4 4 import { FeedController } from "$/lib/api/feeds";
+1 -1
src/components/deck/useFeedColumnState.ts
··· 1 - import { usePostInteractions } from "$/components/posts/usePostInteractions"; 1 + import { usePostInteractions } from "$/components/posts/hooks/usePostInteractions"; 2 2 import { FeedController } from "$/lib/api/feeds"; 3 3 import { patchFeedItems } from "$/lib/feeds"; 4 4 import type { FeedViewPost, SavedFeedItem } from "$/lib/types";
+1 -1
src/components/explorer/ExplorerPanel.test.tsx src/components/explorer/tests/ExplorerPanel.test.tsx
··· 1 1 import { fireEvent, render, screen, waitFor } from "@solidjs/testing-library"; 2 2 import { beforeEach, describe, expect, it, vi } from "vitest"; 3 - import { ExplorerPanel } from "./ExplorerPanel"; 3 + import { ExplorerPanel } from "../ExplorerPanel"; 4 4 5 5 const describeRepoMock = vi.hoisted(() => vi.fn()); 6 6 const describeServerMock = vi.hoisted(() => vi.fn());
+1 -1
src/components/explorer/ExplorerUrlBar.test.tsx src/components/explorer/tests/ExplorerUrlBar.test.tsx
··· 1 1 import { cleanup, fireEvent, render, screen, waitFor } from "@solidjs/testing-library"; 2 2 import { beforeEach, describe, expect, it, vi } from "vitest"; 3 - import { ExplorerUrlBar } from "./ExplorerUrlBar"; 3 + import { ExplorerUrlBar } from "../ExplorerUrlBar"; 4 4 5 5 const searchActorSuggestionsMock = vi.hoisted(() => vi.fn()); 6 6
+1 -1
src/components/explorer/ExplorerUrlBar.tsx
··· 1 - import { ActorSuggestionList, useActorSuggestions } from "$/components/actors/actor-search"; 1 + import { ActorSuggestionList, useActorSuggestions } from "$/components/actors/ActorSearch"; 2 2 import { ArrowIcon, Icon } from "$/components/shared/Icon"; 3 3 import type { LoginSuggestion } from "$/lib/types"; 4 4 import { createEffect, createSignal, Show } from "solid-js";
+1 -1
src/components/explorer/views/RecordView.test.tsx src/components/explorer/views/tests/RecordView.test.tsx
··· 1 1 import { render, screen } from "@solidjs/testing-library"; 2 2 import { describe, expect, it, vi } from "vitest"; 3 - import { RecordView } from "./RecordView"; 3 + import { RecordView } from "../RecordView"; 4 4 5 5 const getRecordBacklinksMock = vi.hoisted(() => vi.fn()); 6 6
+1 -1
src/components/feeds/FeedPane.tsx
··· 5 5 import { ComposerLauncher } from "./FeedComposer"; 6 6 import { FeedContent } from "./FeedContent"; 7 7 import { FeedTabBar } from "./FeedTabs"; 8 - import type { FeedWorkspaceController } from "./useFeedWorkspaceController"; 8 + import type { FeedWorkspaceController } from "./hooks/useFeedWorkspaceController"; 9 9 10 10 function FeedHeaderActions(props: { onCompose: () => void; onRefresh: () => void }) { 11 11 return (
+3 -3
src/components/feeds/FeedWorkspace.tsx
··· 1 - import { usePostNavigation } from "$/components/posts/usePostNavigation"; 2 - import { useThreadOverlayNavigation } from "$/components/posts/useThreadOverlayNavigation"; 1 + import { usePostNavigation } from "$/components/posts/hooks/usePostNavigation"; 2 + import { useThreadOverlayNavigation } from "$/components/posts/hooks/useThreadOverlayNavigation"; 3 3 import { Icon } from "$/components/shared/Icon"; 4 4 import { useAppSession } from "$/contexts/app-session"; 5 5 import { Show } from "solid-js"; ··· 9 9 import { SavedFeedsDrawer } from "./FeedDrawer"; 10 10 import { FeedPane } from "./FeedPane"; 11 11 import { FeedWorkspaceSidebar } from "./FeedWorkspaceSidebar"; 12 - import { useFeedWorkspaceController } from "./useFeedWorkspaceController"; 12 + import { useFeedWorkspaceController } from "./hooks/useFeedWorkspaceController"; 13 13 14 14 export function FeedWorkspace() { 15 15 const session = useAppSession();
+1 -1
src/components/feeds/PostCard.tsx
··· 1 + import { useModerationDecision } from "$/components/moderation/hooks/useModerationDecision"; 1 2 import { ModeratedAvatar } from "$/components/moderation/ModeratedAvatar"; 2 3 import { ModeratedBlurOverlay } from "$/components/moderation/ModeratedBlurOverlay"; 3 4 import { ModerationBadgeRow } from "$/components/moderation/ModerationBadgeRow"; 4 5 import { ReportDialog } from "$/components/moderation/ReportDialog"; 5 - import { useModerationDecision } from "$/components/moderation/useModerationDecision"; 6 6 import { ContextMenu, type ContextMenuAnchor, type ContextMenuItem } from "$/components/shared/ContextMenu"; 7 7 import { Icon } from "$/components/shared/Icon"; 8 8 import { PostRichText } from "$/components/shared/PostRichText";
+1 -1
src/components/feeds/tests/useFeedWorkspaceController.test.tsx
··· 1 1 import { fireEvent, render, screen, waitFor } from "@solidjs/testing-library"; 2 2 import { describe, expect, it, vi } from "vitest"; 3 - import { useFeedWorkspaceController } from "../useFeedWorkspaceController"; 3 + import { useFeedWorkspaceController } from "../hooks/useFeedWorkspaceController"; 4 4 5 5 const invokeMock = vi.hoisted(() => vi.fn()); 6 6 const listenMock = vi.hoisted(() => vi.fn());
+3 -3
src/components/feeds/useFeedWorkspaceController.ts src/components/feeds/hooks/useFeedWorkspaceController.ts
··· 1 - import { usePostInteractions } from "$/components/posts/usePostInteractions"; 1 + import { usePostInteractions } from "$/components/posts/hooks/usePostInteractions"; 2 2 import { DraftController } from "$/lib/api/drafts"; 3 3 import { FeedController } from "$/lib/api/feeds"; 4 4 import { POST_CREATED_EVENT } from "$/lib/constants/events"; ··· 32 32 import * as logger from "@tauri-apps/plugin-log"; 33 33 import { createEffect, createMemo, onCleanup, onMount, untrack } from "solid-js"; 34 34 import { createStore, reconcile } from "solid-js/store"; 35 - import type { FeedWorkspaceState } from "./types"; 35 + import type { FeedWorkspaceState } from "../types"; 36 36 import { 37 37 buildLocalPrefs, 38 38 createDefaultFeedPref, ··· 44 44 getNextFocusedScrollTop, 45 45 updateFeedScrollTop, 46 46 upsertFeedViewPrefs, 47 - } from "./workspace-state"; 47 + } from "../workspace-state"; 48 48 49 49 type FeedWorkspaceProps = { 50 50 activeSession: ActiveSession;
+1 -1
src/components/moderation/ModeratedBlurOverlay.test.tsx src/components/moderation/tests/ModeratedBlurOverlay.test.tsx
··· 1 1 import { fireEvent, render, screen } from "@solidjs/testing-library"; 2 2 import { describe, expect, it } from "vitest"; 3 - import { ModeratedBlurOverlay } from "./ModeratedBlurOverlay"; 3 + import { ModeratedBlurOverlay } from "../ModeratedBlurOverlay"; 4 4 5 5 describe("ModeratedBlurOverlay", () => { 6 6 it("shows overlay and allows reveal when decision is blur-only", () => {
+1 -1
src/components/moderation/useModerationDecision.test.tsx src/components/moderation/tests/useModerationDecision.test.tsx
··· 1 1 import type { ModerationLabel } from "$/lib/types"; 2 2 import { render, waitFor } from "@solidjs/testing-library"; 3 3 import { beforeEach, describe, expect, it, vi } from "vitest"; 4 - import { useModerationDecision } from "./useModerationDecision"; 4 + import { useModerationDecision } from "../hooks/useModerationDecision"; 5 5 6 6 const moderateContentMock = vi.hoisted(() => vi.fn()); 7 7
src/components/moderation/useModerationDecision.ts src/components/moderation/hooks/useModerationDecision.ts
+1 -1
src/components/notifications/NotificationItem.tsx
··· 1 + import { useModerationDecision } from "$/components/moderation/hooks/useModerationDecision"; 1 2 import { ModeratedAvatar } from "$/components/moderation/ModeratedAvatar"; 2 3 import { ModeratedBlurOverlay } from "$/components/moderation/ModeratedBlurOverlay"; 3 4 import { ModerationBadgeRow } from "$/components/moderation/ModerationBadgeRow"; 4 - import { useModerationDecision } from "$/components/moderation/useModerationDecision"; 5 5 import { Icon } from "$/components/shared/Icon"; 6 6 import { formatRelativeTime, getAvatarLabel, getDisplayName } from "$/lib/feeds"; 7 7 import { collectModerationLabels } from "$/lib/moderation";
+1 -1
src/components/notifications/NotificationsPanel.test.tsx src/components/notifications/tests/NotificationsPanel.test.tsx
··· 2 2 import { HashRouter, Route } from "@solidjs/router"; 3 3 import { fireEvent, render, screen, waitFor, within } from "@solidjs/testing-library"; 4 4 import { beforeEach, describe, expect, it, vi } from "vitest"; 5 - import { NotificationsPanel } from "./NotificationsPanel"; 5 + import { NotificationsPanel } from "../NotificationsPanel"; 6 6 7 7 const listNotificationsMock = vi.hoisted(() => vi.fn()); 8 8 const updateSeenMock = vi.hoisted(() => vi.fn());
+2 -2
src/components/notifications/NotificationsPanel.tsx
··· 1 + import { useModerationDecision } from "$/components/moderation/hooks/useModerationDecision"; 1 2 import { ModeratedAvatar } from "$/components/moderation/ModeratedAvatar"; 2 - import { useModerationDecision } from "$/components/moderation/useModerationDecision"; 3 - import { useThreadOverlayNavigation } from "$/components/posts/useThreadOverlayNavigation"; 3 + import { useThreadOverlayNavigation } from "$/components/posts/hooks/useThreadOverlayNavigation"; 4 4 import { useAppSession } from "$/contexts/app-session"; 5 5 import { listNotifications, updateSeen } from "$/lib/api/notifications"; 6 6 import { NOTIFICATIONS_UNREAD_COUNT_EVENT } from "$/lib/constants/events";
+1 -1
src/components/notifications/notification-copy.test.ts src/components/notifications/tests/notification-copy.test.ts
··· 4 4 notificationOriginalPostUri, 5 5 notificationReasonCopy, 6 6 notificationReasonIcon, 7 - } from "./notification-copy"; 7 + } from "../notification-copy"; 8 8 9 9 describe("notification-copy", () => { 10 10 it("returns copy for known reasons", () => {
+1 -1
src/components/notifications/notification-grouping.test.ts src/components/notifications/tests/notification-grouping.test.ts
··· 5 5 groupActivityNotifications, 6 6 splitByReadState, 7 7 toSingleFeedItems, 8 - } from "./notification-grouping"; 8 + } from "../notification-grouping"; 9 9 10 10 function createNotification(reason: string, overrides: Partial<NotificationView> = {}): NotificationView { 11 11 return {
+2 -2
src/components/posts/PostEngagementPanel.test.tsx src/components/posts/tests/PostEngagementPanel.test.tsx
··· 1 1 import { HashRouter, Route } from "@solidjs/router"; 2 2 import { fireEvent, render, screen, waitFor } from "@solidjs/testing-library"; 3 3 import { beforeEach, describe, expect, it, vi } from "vitest"; 4 - import { PostEngagementPanel } from "./PostEngagementPanel"; 4 + import { PostEngagementPanel } from "../PostEngagementPanel"; 5 5 6 6 const getRecordBacklinksMock = vi.hoisted(() => vi.fn()); 7 7 const postNavigationMock = vi.hoisted(() => ({ ··· 13 13 })); 14 14 15 15 vi.mock("$/lib/api/diagnostics", () => ({ getRecordBacklinks: getRecordBacklinksMock })); 16 - vi.mock("$/components/posts/usePostNavigation", () => ({ usePostNavigation: () => postNavigationMock })); 16 + vi.mock("$/components/posts/hooks/usePostNavigation", () => ({ usePostNavigation: () => postNavigationMock })); 17 17 18 18 const POST_URI = "at://did:plc:alice/app.bsky.feed.post/123"; 19 19
+1 -1
src/components/posts/PostEngagementPanel.tsx
··· 1 - import { usePostNavigation } from "$/components/posts/usePostNavigation"; 1 + import { usePostNavigation } from "$/components/posts/hooks/usePostNavigation"; 2 2 import { Icon } from "$/components/shared/Icon"; 3 3 import { QuotedPostPreview } from "$/components/shared/QuotedPostPreview"; 4 4 import { type DiagnosticBacklinkGroup, type DiagnosticBacklinkItem, getRecordBacklinks } from "$/lib/api/diagnostics";
+1 -1
src/components/posts/PostPanel.test.tsx src/components/posts/tests/PostPanel.test.tsx
··· 3 3 import { HashRouter, Route, useParams } from "@solidjs/router"; 4 4 import { render, screen, waitFor } from "@solidjs/testing-library"; 5 5 import { beforeEach, describe, expect, it, vi } from "vitest"; 6 - import { PostPanel } from "./PostPanel"; 6 + import { PostPanel } from "../PostPanel"; 7 7 8 8 const invokeMock = vi.hoisted(() => vi.fn()); 9 9
+2 -2
src/components/posts/PostPanel.tsx
··· 6 6 import type { PostView, ThreadNode, ThreadViewPost } from "$/lib/types"; 7 7 import { createEffect, createMemo, For, Match, Show, Switch } from "solid-js"; 8 8 import { createStore } from "solid-js/store"; 9 - import { usePostInteractions } from "./usePostInteractions"; 10 - import { usePostNavigation } from "./usePostNavigation"; 9 + import { usePostInteractions } from "./hooks/usePostInteractions"; 10 + import { usePostNavigation } from "./hooks/usePostNavigation"; 11 11 12 12 type PostPanelState = { error: string | null; loading: boolean; thread: ThreadNode | null; uri: string | null }; 13 13
+1 -1
src/components/posts/ThreadDrawer.test.tsx src/components/posts/tests/ThreadDrawer.test.tsx
··· 2 2 import { HashRouter, Route } from "@solidjs/router"; 3 3 import { fireEvent, render, screen, waitFor } from "@solidjs/testing-library"; 4 4 import { describe, expect, it, vi } from "vitest"; 5 - import { ThreadDrawer } from "./ThreadDrawer"; 5 + import { ThreadDrawer } from "../ThreadDrawer"; 6 6 7 7 const invokeMock = vi.hoisted(() => vi.fn()); 8 8
+3 -3
src/components/posts/ThreadDrawer.tsx
··· 9 9 import { Motion, Presence } from "solid-motionone"; 10 10 import { PostCard } from "../feeds/PostCard"; 11 11 import { HistoryControls } from "../shared/HistoryControls"; 12 - import { usePostInteractions } from "./usePostInteractions"; 13 - import { usePostNavigation } from "./usePostNavigation"; 14 - import { useThreadOverlayNavigation } from "./useThreadOverlayNavigation"; 12 + import { usePostInteractions } from "./hooks/usePostInteractions"; 13 + import { usePostNavigation } from "./hooks/usePostNavigation"; 14 + import { useThreadOverlayNavigation } from "./hooks/useThreadOverlayNavigation"; 15 15 16 16 type ThreadDrawerState = { error: string | null; loading: boolean; thread: ThreadNode | null; uri: string | null }; 17 17
src/components/posts/usePostInteractions.ts src/components/posts/hooks/usePostInteractions.ts
+2 -2
src/components/posts/usePostNavigation.test.ts src/components/posts/tests/usePostNavigation.test.ts
··· 1 1 import { createRoot } from "solid-js"; 2 2 import { beforeEach, describe, expect, it, vi } from "vitest"; 3 - import { usePostNavigation } from "./usePostNavigation"; 3 + import { usePostNavigation } from "../hooks/usePostNavigation"; 4 4 5 5 const navigateMock = vi.hoisted(() => vi.fn()); 6 6 const threadOverlayMock = vi.hoisted(() => ({ ··· 12 12 })); 13 13 14 14 vi.mock("@solidjs/router", () => ({ useNavigate: () => navigateMock })); 15 - vi.mock("./useThreadOverlayNavigation", () => ({ useThreadOverlayNavigation: () => threadOverlayMock })); 15 + vi.mock("../hooks/useThreadOverlayNavigation", () => ({ useThreadOverlayNavigation: () => threadOverlayMock })); 16 16 17 17 describe("usePostNavigation", () => { 18 18 beforeEach(() => {
src/components/posts/usePostNavigation.ts src/components/posts/hooks/usePostNavigation.ts
+1 -1
src/components/posts/useThreadOverlayNavigation.test.ts src/components/posts/tests/useThreadOverlayNavigation.test.ts
··· 1 1 import { createRoot } from "solid-js"; 2 2 import { beforeEach, describe, expect, it, vi } from "vitest"; 3 - import { useThreadOverlayNavigation } from "./useThreadOverlayNavigation"; 3 + import { useThreadOverlayNavigation } from "../hooks/useThreadOverlayNavigation"; 4 4 5 5 const navigateMock = vi.hoisted(() => vi.fn()); 6 6 const locationState = vi.hoisted(() => ({ pathname: "/timeline", search: "" }));
src/components/posts/useThreadOverlayNavigation.ts src/components/posts/hooks/useThreadOverlayNavigation.ts
+1 -1
src/components/profile/ProfileHero.tsx
··· 1 + import { useModerationDecision } from "$/components/moderation/hooks/useModerationDecision"; 1 2 import { ModeratedAvatar } from "$/components/moderation/ModeratedAvatar"; 2 3 import { ModerationBadgeRow } from "$/components/moderation/ModerationBadgeRow"; 3 - import { useModerationDecision } from "$/components/moderation/useModerationDecision"; 4 4 import { Icon } from "$/components/shared/Icon"; 5 5 import { getAvatarLabel, getDisplayName } from "$/lib/feeds"; 6 6 import { collectModerationLabels } from "$/lib/moderation";
+2 -2
src/components/profile/ProfilePanel.test.tsx src/components/profile/tests/ProfilePanel.test.tsx
··· 1 1 import { AppTestProviders } from "$/test/providers"; 2 2 import { fireEvent, render, screen, waitFor, within } from "@solidjs/testing-library"; 3 3 import { beforeEach, describe, expect, it, vi } from "vitest"; 4 - import { ProfilePanel } from "./ProfilePanel"; 4 + import { ProfilePanel } from "../ProfilePanel"; 5 5 6 6 const followActorMock = vi.hoisted(() => vi.fn()); 7 7 const getActorLikesMock = vi.hoisted(() => vi.fn()); ··· 49 49 ); 50 50 51 51 vi.mock("@solidjs/router", () => ({ useNavigate: () => navigateMock })); 52 - vi.mock("$/components/posts/usePostNavigation", () => ({ usePostNavigation: () => postNavigationMock })); 52 + vi.mock("$/components/posts/hooks/usePostNavigation", () => ({ usePostNavigation: () => postNavigationMock })); 53 53 54 54 function deferred<T>() { 55 55 let resolve!: (value: T) => void;
+2 -2
src/components/profile/ProfilePanel.tsx
··· 1 1 import { DiagnosticsPanel } from "$/components/deck/DiagnosticsPanel"; 2 - import { usePostInteractions } from "$/components/posts/usePostInteractions"; 3 - import { usePostNavigation } from "$/components/posts/usePostNavigation"; 2 + import { usePostInteractions } from "$/components/posts/hooks/usePostInteractions"; 3 + import { usePostNavigation } from "$/components/posts/hooks/usePostNavigation"; 4 4 import { ProfileSkeleton } from "$/components/ProfileSkeleton"; 5 5 import { useAppSession } from "$/contexts/app-session"; 6 6 import {
+1 -1
src/components/rail/AppRail.test.tsx src/components/rail/tests/AppRail.test.tsx
··· 2 2 import { HashRouter, Route } from "@solidjs/router"; 3 3 import { fireEvent, render, screen, waitFor } from "@solidjs/testing-library"; 4 4 import { beforeEach, describe, expect, it, vi } from "vitest"; 5 - import { AppRail } from "./AppRail"; 5 + import { AppRail } from "../AppRail"; 6 6 7 7 const openUrlMock = vi.hoisted(() => vi.fn()); 8 8 const updateSettingMock = vi.hoisted(() => vi.fn());
+1 -1
src/components/rail/AppRailButton.test.tsx src/components/rail/tests/AppRailButton.test.tsx
··· 1 1 import { MemoryRouter, Route } from "@solidjs/router"; 2 2 import { render, screen } from "@solidjs/testing-library"; 3 3 import { describe, expect, it } from "vitest"; 4 - import { RailButton } from "./AppRailButton"; 4 + import { RailButton } from "../AppRailButton"; 5 5 6 6 function renderInRouter(ui: () => ReturnType<typeof RailButton>) { 7 7 return render(() => (
+2 -2
src/components/saved/SavedPostsPanel.test.tsx src/components/saved/tests/SavedPostsPanel.test.tsx
··· 2 2 import { AppTestProviders } from "$/test/providers"; 3 3 import { fireEvent, render, screen, waitFor } from "@solidjs/testing-library"; 4 4 import { beforeEach, describe, expect, it, vi } from "vitest"; 5 - import { SavedPostsPanel } from "./SavedPostsPanel"; 5 + import { SavedPostsPanel } from "../SavedPostsPanel"; 6 6 7 7 const getSyncStatusMock = vi.hoisted(() => vi.fn()); 8 8 const listSavedPostsMock = vi.hoisted(() => vi.fn()); ··· 20 20 }, 21 21 }), 22 22 ); 23 - vi.mock("$/components/posts/usePostNavigation", () => ({ usePostNavigation: () => postNavigationMock })); 23 + vi.mock("$/components/posts/hooks/usePostNavigation", () => ({ usePostNavigation: () => postNavigationMock })); 24 24 vi.mock("@tauri-apps/plugin-log", () => ({ error: loggerErrorMock })); 25 25 26 26 function createStatus(source: "bookmark" | "like", count: number) {
+1 -1
src/components/saved/SavedPostsPanel.tsx
··· 1 - import { usePostNavigation } from "$/components/posts/usePostNavigation"; 1 + import { usePostNavigation } from "$/components/posts/hooks/usePostNavigation"; 2 2 import { LocalPostResultsList, LocalPostResultsSkeletons } from "$/components/search/LocalPostResultsList"; 3 3 import { SearchEmptyState } from "$/components/search/SearchEmptyState"; 4 4 import { SearchQueryInput } from "$/components/search/SearchQueryInput";
+1 -1
src/components/search/EmbeddingsSettings.test.tsx src/components/search/tests/EmbeddingsSettings.test.tsx
··· 1 1 import { AppPreferencesProvider } from "$/contexts/app-preferences"; 2 2 import { fireEvent, render, screen, waitFor } from "@solidjs/testing-library"; 3 3 import { beforeEach, describe, expect, it, vi } from "vitest"; 4 - import { EmbeddingsSettings } from "./EmbeddingsSettings"; 4 + import { EmbeddingsSettings } from "../EmbeddingsSettings"; 5 5 6 6 const getEmbeddingsConfigMock = vi.hoisted(() => vi.fn()); 7 7 const prepareEmbeddingsModelMock = vi.hoisted(() => vi.fn());
+1 -1
src/components/search/HashtagPanel.test.tsx src/components/search/tests/HashtagPanel.test.tsx
··· 3 3 import { HashRouter, Route } from "@solidjs/router"; 4 4 import { fireEvent, render, screen } from "@solidjs/testing-library"; 5 5 import { beforeEach, describe, expect, it, vi } from "vitest"; 6 - import { HashtagPanel } from "./HashtagPanel"; 6 + import { HashtagPanel } from "../HashtagPanel"; 7 7 8 8 const searchPostsNetworkMock = vi.hoisted(() => vi.fn()); 9 9 const postNavigationMock = vi.hoisted(() => ({ backFromPost: vi.fn(), buildPostHref: vi.fn(), openPost: vi.fn() }));
+1 -1
src/components/search/HashtagPanel.tsx
··· 1 1 import { PostCard } from "$/components/feeds/PostCard"; 2 - import { usePostNavigation } from "$/components/posts/usePostNavigation"; 2 + import { usePostNavigation } from "$/components/posts/hooks/usePostNavigation"; 3 3 import { Icon } from "$/components/shared/Icon"; 4 4 import { SearchController } from "$/lib/api/search"; 5 5 import type { NetworkSearchResult } from "$/lib/api/types/search";
+1 -1
src/components/search/SearchEmptyState.test.tsx src/components/search/tests/SearchEmptyState.test.tsx
··· 1 1 import { render, screen } from "@solidjs/testing-library"; 2 2 import { describe, expect, it } from "vitest"; 3 - import { SearchEmptyState } from "./SearchEmptyState"; 3 + import { SearchEmptyState } from "../SearchEmptyState"; 4 4 5 5 describe("SearchEmptyState", () => { 6 6 it("renders the composed no-sync illustration", () => {
+1 -1
src/components/search/SearchPanel.test.tsx src/components/search/tests/SearchPanel.test.tsx
··· 3 3 import { HashRouter, Route } from "@solidjs/router"; 4 4 import { fireEvent, render, screen } from "@solidjs/testing-library"; 5 5 import { beforeEach, describe, expect, it, vi } from "vitest"; 6 - import { SearchPanel } from "./SearchPanel"; 6 + import { SearchPanel } from "../SearchPanel"; 7 7 8 8 const searchActorSuggestionsMock = vi.hoisted(() => vi.fn()); 9 9 const searchActorsMock = vi.hoisted(() => vi.fn());
+2 -2
src/components/search/SearchPanel.tsx
··· 1 - import { ActorSuggestionList, getActorSuggestionHeadline } from "$/components/actors/actor-search"; 1 + import { ActorSuggestionList, getActorSuggestionHeadline } from "$/components/actors/ActorSearch"; 2 2 import { AvatarBadge } from "$/components/AvatarBadge"; 3 3 import { PostCard } from "$/components/feeds/PostCard"; 4 4 import { Icon, SearchModeIcon } from "$/components/shared/Icon"; ··· 15 15 import { Motion, Presence } from "solid-motionone"; 16 16 import { PostCount } from "../shared/PostCount"; 17 17 import { EmbeddingsSettings } from "./EmbeddingsSettings"; 18 + import { useSearchController } from "./hooks/useSearchController"; 18 19 import { LocalPostResultsList, LocalPostResultsSkeletons } from "./LocalPostResultsList"; 19 20 import { PostSearchFiltersRow } from "./PostSearchFilters"; 20 21 import { SearchEmptyState } from "./SearchEmptyState"; 21 22 import { SearchQueryInput } from "./SearchQueryInput"; 22 23 import { SyncStatusPanel } from "./SyncStatusPanel"; 23 24 import type { EmptyStateReason } from "./types"; 24 - import { useSearchController } from "./useSearchController"; 25 25 26 26 const MODES: SearchMode[] = ["network", "keyword", "semantic", "hybrid"]; 27 27
+1 -1
src/components/search/SearchResultCard.test.tsx src/components/search/tests/SearchResultCard.test.tsx
··· 1 1 import { fireEvent, render, screen } from "@solidjs/testing-library"; 2 2 import { describe, expect, it, vi } from "vitest"; 3 - import { SearchResultCard } from "./SearchResultCard"; 3 + import { SearchResultCard } from "../SearchResultCard"; 4 4 5 5 describe("SearchResultCard", () => { 6 6 it("opens the thread from the post body but keeps profile navigation explicit", () => {
+1 -1
src/components/search/SyncStatusPanel.test.tsx src/components/search/tests/SyncStatusPanel.test.tsx
··· 1 1 import { fireEvent, render, screen, waitFor } from "@solidjs/testing-library"; 2 2 import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; 3 - import { SyncStatusPanel } from "./SyncStatusPanel"; 3 + import { SyncStatusPanel } from "../SyncStatusPanel"; 4 4 5 5 const getSyncStatusMock = vi.hoisted(() => vi.fn()); 6 6 const syncPostsMock = vi.hoisted(() => vi.fn());
+2 -2
src/components/search/useSearchController.ts src/components/search/hooks/useSearchController.ts
··· 1 - import { useActorSuggestions } from "$/components/actors/actor-search"; 2 - import { usePostNavigation } from "$/components/posts/usePostNavigation"; 1 + import { useActorSuggestions } from "$/components/actors/ActorSearch"; 2 + import { usePostNavigation } from "$/components/posts/hooks/usePostNavigation"; 3 3 import { useAppPreferences } from "$/contexts/app-preferences"; 4 4 import { useAppSession } from "$/contexts/app-session"; 5 5 import { SearchController } from "$/lib/api/search";
+1 -4
src/components/settings/SettingsLogs.tsx
··· 97 97 class="ui-button-secondary px-3 py-1.5 text-xs"> 98 98 Copy all 99 99 </button> 100 - <button 101 - type="button" 102 - onClick={() => void props.loadLogs()} 103 - class="ui-button-secondary px-3 py-1.5 text-xs"> 100 + <button type="button" onClick={() => void props.loadLogs()} class="ui-button-secondary px-3 py-1.5 text-xs"> 104 101 Refresh 105 102 </button> 106 103 </div>
+1 -1
src/components/settings/SettingsModeration.test.tsx src/components/settings/tests/SettingsModeration.test.tsx
··· 1 1 import { fireEvent, render, screen, waitFor } from "@solidjs/testing-library"; 2 2 import { beforeEach, describe, expect, it, vi } from "vitest"; 3 - import { SettingsModeration } from "./SettingsModeration"; 3 + import { SettingsModeration } from "../SettingsModeration"; 4 4 5 5 const getModerationPrefsMock = vi.hoisted(() => vi.fn()); 6 6 const setAdultContentEnabledMock = vi.hoisted(() => vi.fn());
+6 -2
src/components/settings/SettingsPanel.test.tsx src/components/settings/tests/SettingsPanel.test.tsx
··· 1 1 import { AppTestProviders } from "$/test/providers"; 2 2 import { fireEvent, render, screen, waitFor } from "@solidjs/testing-library"; 3 3 import { beforeEach, describe, expect, it, vi } from "vitest"; 4 - import { SettingsPanel } from "./SettingsPanel"; 4 + import { SettingsPanel } from "../SettingsPanel"; 5 5 6 6 const getSettingsMock = vi.hoisted(() => vi.fn()); 7 7 const updateSettingMock = vi.hoisted(() => vi.fn()); ··· 111 111 } 112 112 113 113 function renderSettingsPanel( 114 - options: { preferences?: Record<string, unknown>; session?: Record<string, unknown>; shell?: Record<string, unknown> } = {}, 114 + options: { 115 + preferences?: Record<string, unknown>; 116 + session?: Record<string, unknown>; 117 + shell?: Record<string, unknown>; 118 + } = {}, 115 119 ) { 116 120 render(() => ( 117 121 <AppTestProviders
+1 -1
src/components/shared/ContextMenu.test.tsx src/components/shared/tests/ContextMenu.test.tsx
··· 1 1 import { fireEvent, render, screen, waitFor } from "@solidjs/testing-library"; 2 2 import { createSignal } from "solid-js"; 3 3 import { describe, expect, it, vi } from "vitest"; 4 - import { ContextMenu, type ContextMenuAnchor } from "./ContextMenu"; 4 + import { ContextMenu, type ContextMenuAnchor } from "../ContextMenu"; 5 5 6 6 function TestMenu(props: { anchor: ContextMenuAnchor | null; onClose?: () => void }) { 7 7 const [open, setOpen] = createSignal(true);
+1 -1
src/components/shared/PostRichText.test.tsx src/components/shared/tests/PostRichText.test.tsx
··· 1 1 import { buildHashtagRoute } from "$/lib/search-routes"; 2 2 import { render, screen } from "@solidjs/testing-library"; 3 3 import { describe, expect, it } from "vitest"; 4 - import { PostRichText } from "./PostRichText"; 4 + import { PostRichText } from "../PostRichText"; 5 5 6 6 describe("PostRichText", () => { 7 7 it("renders link, mention, and tag facets", () => {
+6 -13
src/components/theme/ThemeController.test.tsx src/components/theme/tests/ThemeController.test.tsx
··· 1 1 import { ThemeController } from "$/components/theme/ThemeController"; 2 - import { AppTestProviders } from "$/test/providers"; 3 2 import type { AppSettings } from "$/lib/types"; 3 + import { AppTestProviders } from "$/test/providers"; 4 4 import { render, waitFor } from "@solidjs/testing-library"; 5 5 import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; 6 6 ··· 10 10 const tauriThemeMock = vi.hoisted(() => vi.fn(async () => null as "light" | "dark" | null)); 11 11 const onThemeChangedMock = vi.hoisted(() => vi.fn(async (_handler: ThemeChangeHandler) => noopUnlisten)); 12 12 13 - vi.mock("@tauri-apps/api/window", () => ({ 14 - getCurrentWindow: () => ({ 15 - label: "main", 16 - onThemeChanged: onThemeChangedMock, 17 - theme: tauriThemeMock, 18 - }), 19 - })); 13 + vi.mock( 14 + "@tauri-apps/api/window", 15 + () => ({ getCurrentWindow: () => ({ label: "main", onThemeChanged: onThemeChangedMock, theme: tauriThemeMock }) }), 16 + ); 20 17 21 18 function installMatchMedia(initialDark: boolean) { 22 19 const listeners = new Set<(event: MediaQueryListEvent) => void>(); ··· 45 42 }, 46 43 }; 47 44 48 - Object.defineProperty(globalThis, "matchMedia", { 49 - configurable: true, 50 - writable: true, 51 - value: vi.fn(() => media), 52 - }); 45 + Object.defineProperty(globalThis, "matchMedia", { configurable: true, writable: true, value: vi.fn(() => media) }); 53 46 54 47 return media; 55 48 }
+20 -26
src/components/theme/ThemeController.tsx
··· 1 1 import { useAppPreferences } from "$/contexts/app-preferences"; 2 2 import { 3 3 applyThemeToDocument, 4 + type EffectiveTheme, 4 5 normalizeThemeSetting, 5 6 resolveEffectiveTheme, 6 7 toEffectiveTheme, 7 - type EffectiveTheme, 8 8 } from "$/lib/theme"; 9 9 import { getCurrentWindow } from "@tauri-apps/api/window"; 10 10 import { createEffect, createMemo, createSignal, onCleanup, onMount } from "solid-js"; ··· 38 38 39 39 try { 40 40 const currentWindow = getCurrentWindow(); 41 - void currentWindow 42 - .theme() 43 - .then((theme) => { 44 - if (cancelled) { 45 - return; 46 - } 41 + void currentWindow.theme().then((theme) => { 42 + if (cancelled) { 43 + return; 44 + } 47 45 48 - setSystemTheme((current) => toEffectiveTheme(theme, current)); 49 - }) 50 - .catch(() => { 51 - // Browser test environments may not provide native window theme APIs. 52 - }); 46 + setSystemTheme((current) => toEffectiveTheme(theme, current)); 47 + }).catch(() => { 48 + // Browser test environments may not provide native window theme APIs. 49 + }); 53 50 54 - void currentWindow 55 - .onThemeChanged(({ payload }) => { 56 - setSystemTheme((current) => toEffectiveTheme(payload, current)); 57 - }) 58 - .then((unlisten) => { 59 - if (cancelled) { 60 - unlisten(); 61 - return; 62 - } 63 - unlistenThemeChange = unlisten; 64 - }) 65 - .catch(() => { 66 - // Browser test environments may not provide native window theme APIs. 67 - }); 51 + void currentWindow.onThemeChanged(({ payload }) => { 52 + setSystemTheme((current) => toEffectiveTheme(payload, current)); 53 + }).then((unlisten) => { 54 + if (cancelled) { 55 + unlisten(); 56 + return; 57 + } 58 + unlistenThemeChange = unlisten; 59 + }).catch(() => { 60 + // Browser test environments may not provide native window theme APIs. 61 + }); 68 62 } catch { 69 63 // Browser test environments may not provide native window APIs. 70 64 }
+1 -1
src/contexts/app-session.test.tsx src/contexts/tests/app-session.test.tsx
··· 1 1 import { ACCOUNT_SWITCH_EVENT, NOTIFICATIONS_UNREAD_COUNT_EVENT } from "$/lib/constants/events"; 2 2 import { render, screen, waitFor } from "@solidjs/testing-library"; 3 3 import { beforeEach, describe, expect, it, vi } from "vitest"; 4 - import { AppSessionProvider, useAppSession } from "./app-session"; 4 + import { AppSessionProvider, useAppSession } from "../app-session"; 5 5 6 6 const getAppBootstrapMock = vi.hoisted(() => vi.fn()); 7 7 const loginMock = vi.hoisted(() => vi.fn());
+2 -2
src/lib/feeds.test.ts src/lib/tests/feeds.test.ts
··· 8 8 getThreadOverlayUri, 9 9 parseFeedResponse, 10 10 parseThreadResponse, 11 - } from "./feeds"; 12 - import type { FeedViewPost, FeedViewPrefItem, SavedFeedItem } from "./types"; 11 + } from "../feeds"; 12 + import type { FeedViewPost, FeedViewPrefItem, SavedFeedItem } from "../types"; 13 13 14 14 function createFeedItem(overrides: Partial<FeedViewPost> = {}): FeedViewPost { 15 15 return {
+1 -1
src/lib/post-engagement-routes.test.ts src/lib/tests/post-engagement-routes.test.ts
··· 3 3 buildPostEngagementRoute, 4 4 buildPostEngagementTabRoute, 5 5 parsePostEngagementTab, 6 - } from "./post-engagement-routes"; 6 + } from "../post-engagement-routes"; 7 7 8 8 describe("post-engagement-routes", () => { 9 9 it("builds a canonical engagement route with tab query", () => {
+1 -1
src/lib/post-routes.test.ts src/lib/tests/post-routes.test.ts
··· 1 1 import { describe, expect, it } from "vitest"; 2 - import { buildPostRoute, decodePostRouteUri, isThreadDrawerPath } from "./post-routes"; 2 + import { buildPostRoute, decodePostRouteUri, isThreadDrawerPath } from "../post-routes"; 3 3 4 4 describe("post-routes", () => { 5 5 it("builds a canonical encoded post route", () => {
+2 -2
src/lib/profile.test.ts src/lib/tests/profile.test.ts
··· 1 1 import { describe, expect, it } from "vitest"; 2 - import { filterProfileFeed, parseActorList, parseProfileResult } from "./profile"; 3 - import type { FeedViewPost } from "./types"; 2 + import { filterProfileFeed, parseActorList, parseProfileResult } from "../profile"; 3 + import type { FeedViewPost } from "../types"; 4 4 5 5 function createFeedItem(overrides: Partial<FeedViewPost> = {}): FeedViewPost { 6 6 return {