mirror of
https://github.com/block/buzz.git
synced 2026-11-02 23:41:08 +00:00
refactor(desktop): extract community destination restore hook
AppShell.tsx crossed the 1000-line desktop ratchet again after the forward-history wiring. Move the community destination restore effect into its own hook alongside useCommunityNavigationTransitions instead of squeezing the call site further. Signed-off-by: Matt Toohey <contact@matttoohey.com>
This commit is contained in:
@@ -15,6 +15,7 @@ import {
|
||||
import { useAppNavigation } from "@/app/navigation/useAppNavigation";
|
||||
import { describeHistoryLocation } from "@/app/navigation/navigationHistory";
|
||||
import { useBackForwardControls } from "@/app/navigation/useBackForwardControls";
|
||||
import { useCommunityDestinationRestore } from "@/app/useCommunityDestinationRestore";
|
||||
import { useCommunityNavigationTransitions } from "@/app/useCommunityNavigationTransitions";
|
||||
import { useLiveHomeFeedActions } from "@/app/useLiveHomeFeedActions";
|
||||
import { useChannelBrowserDialog } from "@/app/useChannelBrowserDialog";
|
||||
@@ -82,11 +83,6 @@ import { CommunityRail } from "@/features/sidebar/ui/CommunityRail";
|
||||
import { useChannelMutes } from "@/features/sidebar/lib/useChannelMutes";
|
||||
import { useChannelStars } from "@/features/sidebar/lib/useChannelStars";
|
||||
import { useCommunities } from "@/features/communities/useCommunities";
|
||||
import {
|
||||
consumePendingCommunityRestore,
|
||||
loadCommunityDestination,
|
||||
saveCommunityDestination,
|
||||
} from "@/features/communities/communityNavigationStorage";
|
||||
import { useAddCommunityDialogState } from "@/features/communities/addCommunityPrefill";
|
||||
import { useApplyTemplate } from "@/features/channel-templates/useApplyTemplate";
|
||||
import { relayClient } from "@/shared/api/relayClient";
|
||||
@@ -276,54 +272,15 @@ export function AppShell() {
|
||||
),
|
||||
[huddleBackingChannelIds, memberChannels, revealedHuddleChannelIds],
|
||||
);
|
||||
const hasRestoredCommunityDestinationRef = React.useRef(false);
|
||||
React.useEffect(() => {
|
||||
const activeCommunityId = communitiesHook.activeCommunity?.id;
|
||||
if (
|
||||
hasRestoredCommunityDestinationRef.current ||
|
||||
!channelsQuery.isSuccess ||
|
||||
channelsQuery.dataUpdatedAt === 0 ||
|
||||
!activeCommunityId
|
||||
) {
|
||||
return;
|
||||
}
|
||||
hasRestoredCommunityDestinationRef.current = true;
|
||||
|
||||
// Restoration belongs to an explicit community transition. Cold boot and
|
||||
// reconnect remounts must preserve the route the user explicitly opened.
|
||||
if (!consumePendingCommunityRestore(activeCommunityId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const destination = loadCommunityDestination(activeCommunityId);
|
||||
if (!destination || destination.kind === "home") {
|
||||
return;
|
||||
}
|
||||
|
||||
const channelIsAvailable = sidebarChannels.some(
|
||||
(channel) => channel.id === destination.channelId,
|
||||
);
|
||||
if (!channelIsAvailable) {
|
||||
saveCommunityDestination(activeCommunityId, { kind: "home" });
|
||||
void goHome({ replace: true });
|
||||
return;
|
||||
}
|
||||
|
||||
// The normal switch path writes the remembered channel into the hash before
|
||||
// the target community mounts, so no intermediate Inbox frame is painted.
|
||||
// Older transition callers may still arrive at neutral Home; repair those.
|
||||
if (selectedView === "home") {
|
||||
void goChannel(destination.channelId, { replace: true });
|
||||
}
|
||||
}, [
|
||||
channelsQuery.dataUpdatedAt,
|
||||
channelsQuery.isSuccess,
|
||||
communitiesHook.activeCommunity?.id,
|
||||
useCommunityDestinationRestore({
|
||||
activeCommunityId: communitiesHook.activeCommunity?.id,
|
||||
channelsDataUpdatedAt: channelsQuery.dataUpdatedAt,
|
||||
channelsLoaded: channelsQuery.isSuccess,
|
||||
goChannel,
|
||||
goHome,
|
||||
selectedView,
|
||||
sidebarChannels,
|
||||
]);
|
||||
});
|
||||
const [terminalContextOverride, setTerminalContextOverride] =
|
||||
React.useState<TerminalContextOverride | null>(null);
|
||||
const { activeChannel, terminalContext } = useTerminalContext({
|
||||
|
||||
83
desktop/src/app/useCommunityDestinationRestore.ts
Normal file
83
desktop/src/app/useCommunityDestinationRestore.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import * as React from "react";
|
||||
|
||||
import type { deriveShellRoute } from "@/app/AppShell.helpers";
|
||||
import type { useAppNavigation } from "@/app/navigation/useAppNavigation";
|
||||
import {
|
||||
consumePendingCommunityRestore,
|
||||
loadCommunityDestination,
|
||||
saveCommunityDestination,
|
||||
} from "@/features/communities/communityNavigationStorage";
|
||||
import type { Channel } from "@/shared/api/types";
|
||||
|
||||
type ShellRoute = ReturnType<typeof deriveShellRoute>;
|
||||
type AppNavigation = ReturnType<typeof useAppNavigation>;
|
||||
|
||||
/**
|
||||
* Restores the channel a community was last viewed on, once for the first
|
||||
* successful channel load after an explicit community transition.
|
||||
*/
|
||||
export function useCommunityDestinationRestore({
|
||||
activeCommunityId,
|
||||
channelsDataUpdatedAt,
|
||||
channelsLoaded,
|
||||
goChannel,
|
||||
goHome,
|
||||
selectedView,
|
||||
sidebarChannels,
|
||||
}: {
|
||||
activeCommunityId: string | undefined;
|
||||
channelsDataUpdatedAt: number;
|
||||
channelsLoaded: boolean;
|
||||
goChannel: AppNavigation["goChannel"];
|
||||
goHome: AppNavigation["goHome"];
|
||||
selectedView: ShellRoute["selectedView"];
|
||||
sidebarChannels: Channel[];
|
||||
}) {
|
||||
const hasRestoredCommunityDestinationRef = React.useRef(false);
|
||||
React.useEffect(() => {
|
||||
if (
|
||||
hasRestoredCommunityDestinationRef.current ||
|
||||
!channelsLoaded ||
|
||||
channelsDataUpdatedAt === 0 ||
|
||||
!activeCommunityId
|
||||
) {
|
||||
return;
|
||||
}
|
||||
hasRestoredCommunityDestinationRef.current = true;
|
||||
|
||||
// Restoration belongs to an explicit community transition. Cold boot and
|
||||
// reconnect remounts must preserve the route the user explicitly opened.
|
||||
if (!consumePendingCommunityRestore(activeCommunityId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const destination = loadCommunityDestination(activeCommunityId);
|
||||
if (!destination || destination.kind === "home") {
|
||||
return;
|
||||
}
|
||||
|
||||
const channelIsAvailable = sidebarChannels.some(
|
||||
(channel) => channel.id === destination.channelId,
|
||||
);
|
||||
if (!channelIsAvailable) {
|
||||
saveCommunityDestination(activeCommunityId, { kind: "home" });
|
||||
void goHome({ replace: true });
|
||||
return;
|
||||
}
|
||||
|
||||
// The normal switch path writes the remembered channel into the hash before
|
||||
// the target community mounts, so no intermediate Inbox frame is painted.
|
||||
// Older transition callers may still arrive at neutral Home; repair those.
|
||||
if (selectedView === "home") {
|
||||
void goChannel(destination.channelId, { replace: true });
|
||||
}
|
||||
}, [
|
||||
activeCommunityId,
|
||||
channelsDataUpdatedAt,
|
||||
channelsLoaded,
|
||||
goChannel,
|
||||
goHome,
|
||||
selectedView,
|
||||
sidebarChannels,
|
||||
]);
|
||||
}
|
||||
Reference in New Issue
Block a user