Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
be33211
feat(desktop): redesign home as an inbox
thomaspblock Apr 14, 2026
d0c818d
feat(desktop): refine inbox signal and layout
thomaspblock Apr 29, 2026
e710571
Merge remote-tracking branch 'origin/main' into inbox
thomaspblock May 11, 2026
79fbade
feat(desktop): show inbox thread context
thomaspblock May 11, 2026
37625df
Merge origin/main into inbox
thomaspblock May 11, 2026
27b2be3
fix(desktop): simplify inbox header layout
thomaspblock May 11, 2026
7987a52
Merge remote-tracking branch 'origin/main' into inbox
thomaspblock May 11, 2026
fe2c930
fix(desktop): align inbox composer overlay
thomaspblock May 12, 2026
36afb5f
fix(desktop): make inbox category filters clickable
thomaspblock May 12, 2026
8a4579f
fix(desktop): soften inbox context highlight
thomaspblock May 13, 2026
4232bb2
fix(desktop): remove inbox list search field
thomaspblock May 13, 2026
b52964d
fix(desktop): target replies from inbox threads
thomaspblock May 13, 2026
50ccef6
fix(desktop): add inbox reactions and clean header
thomaspblock May 13, 2026
2a40105
fix(desktop): simplify inbox mention conversation view
thomaspblock May 13, 2026
c4d4c8f
Merge origin/main into inbox
thomaspblock May 14, 2026
2b53fb3
fix(desktop): polish Home inbox presentation
thomaspblock May 14, 2026
f6179b3
fix(desktop): strengthen Home inbox sender names
thomaspblock May 14, 2026
f765861
Merge remote-tracking branch 'origin/main' into inbox
thomaspblock May 14, 2026
14bc93c
fix(desktop): refine Home inbox filter pills
thomaspblock May 14, 2026
babfbe2
fix(desktop): make relay inbox tests seed their item
thomaspblock May 14, 2026
1e2ccec
fix(desktop): refine inbox context header
thomaspblock May 15, 2026
c2363ff
fix(desktop): experiment with overlaid inbox context header
thomaspblock May 15, 2026
83e7513
fix(desktop): make home inbox list resizable
thomaspblock May 17, 2026
b46f70d
Merge origin/main into inbox
thomaspblock May 17, 2026
2228220
fix(desktop): show emoji reactions in inbox threads
thomaspblock May 18, 2026
856d15b
Merge inbox into home header experiment
thomaspblock May 18, 2026
f071731
fix(desktop): simplify inbox experiment header actions
thomaspblock May 18, 2026
c9b7f3a
fix(desktop): loosen inbox selected message highlight
thomaspblock May 18, 2026
9936906
Merge branch 'inbox' into inbox-home-header-experiment
thomaspblock May 18, 2026
987be03
fix(desktop): align inbox focus presentation
thomaspblock May 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions desktop/src/app/routes/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createFileRoute } from "@tanstack/react-router";

import { useAppNavigation } from "@/app/navigation/useAppNavigation";
import { useChannelsQuery } from "@/features/channels/hooks";
import { useIdentityQuery } from "@/shared/api/hooks";
import { HomeScreen } from "@/features/home/ui/HomeScreen";
Expand All @@ -9,6 +10,7 @@ export const Route = createFileRoute("/")({
});

function HomeRouteComponent() {
const { goChannel } = useAppNavigation();
const channelsQuery = useChannelsQuery();
const identityQuery = useIdentityQuery();
const channels = channelsQuery.data ?? [];
Expand All @@ -18,6 +20,9 @@ function HomeRouteComponent() {
<HomeScreen
availableChannelIds={availableChannelIds}
currentPubkey={identityQuery.data?.pubkey}
onOpenContext={(channelId, messageId) => {
void goChannel(channelId, { messageId });
}}
/>
);
}
2 changes: 1 addition & 1 deletion desktop/src/features/home/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export function useHomeFeedQuery() {
queryKey: ["home-feed"],
queryFn: () =>
getHomeFeed({
limit: 12,
limit: 50,
types: "mentions,needs_action,activity,agent_activity",
}),
staleTime: 15_000,
Expand Down
3 changes: 3 additions & 0 deletions desktop/src/features/home/ui/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import { HomeView } from "@/features/home/ui/HomeView";
type HomeScreenProps = {
availableChannelIds: ReadonlySet<string>;
currentPubkey?: string;
onOpenContext: (channelId: string, messageId: string) => void;
};

export function HomeScreen({
availableChannelIds,
currentPubkey,
onOpenContext,
}: HomeScreenProps) {
const homeFeedQuery = useHomeFeedQuery();

Expand All @@ -33,6 +35,7 @@ export function HomeScreen({
}
feed={homeFeedQuery.data}
isLoading={homeFeedQuery.isLoading}
onOpenContext={onOpenContext}
onRefresh={() => {
void homeFeedQuery.refetch();
}}
Expand Down
57 changes: 47 additions & 10 deletions desktop/src/features/home/ui/HomeView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from "@/features/home/lib/inbox";
import { useFeedItemState } from "@/features/home/useFeedItemState";
import { useInboxThreadContext } from "@/features/home/useInboxThreadContext";
import { useResizableInboxListWidth } from "@/features/home/useResizableInboxListWidth";
import { InboxDetailPane } from "@/features/home/ui/InboxDetailPane";
import { InboxListPane } from "@/features/home/ui/InboxListPane";
import {
Expand Down Expand Up @@ -104,6 +105,7 @@ type HomeViewProps = {
errorMessage?: string;
currentPubkey?: string;
availableChannelIds: ReadonlySet<string>;
onOpenContext: (channelId: string, messageId: string) => void;
onRefresh: () => void;
};

Expand All @@ -113,6 +115,7 @@ export function HomeView({
errorMessage,
currentPubkey,
availableChannelIds,
onOpenContext,
onRefresh,
}: HomeViewProps) {
const [filter, setFilter] = React.useState<InboxFilter>("all");
Expand All @@ -124,6 +127,12 @@ export function HomeView({
const [localRepliesByItemId, setLocalRepliesByItemId] = React.useState<
Record<string, InboxReply[]>
>({});
const {
canResetInboxListWidth,
handleInboxListResizeStart,
handleInboxListWidthReset,
inboxListWidthPx,
} = useResizableInboxListWidth();
const { doneSet, markDone, undoDone } = useFeedItemState(currentPubkey);
const feedItems = React.useMemo(
() =>
Expand Down Expand Up @@ -303,10 +312,12 @@ export function HomeView({
);
}

const canReply =
const canReact =
selectedItem !== null &&
selectedItem.item.channelId !== null &&
availableChannelIds.has(selectedItem.item.channelId) &&
availableChannelIds.has(selectedItem.item.channelId);
const canReply =
canReact &&
selectedItem.item.kind !== 45001 &&
selectedItem.item.kind !== 45003;
const disabledReplyReason =
Expand All @@ -323,10 +334,15 @@ export function HomeView({
selectedItem.item.pubkey.trim().toLowerCase();

return (
<div className="flex-1 overflow-hidden">
<div className="flex min-h-0 flex-1 flex-col overflow-hidden">
<div
className="grid h-full min-h-0 w-full lg:grid-cols-[320px_minmax(0,1fr)]"
className="relative grid min-h-0 flex-1 w-full lg:grid-cols-[var(--home-inbox-list-width)_minmax(0,1fr)]"
data-testid="home-inbox"
style={
{
"--home-inbox-list-width": `${inboxListWidthPx}px`,
} as React.CSSProperties
}
>
<InboxListPane
doneSet={doneSet}
Expand All @@ -340,6 +356,25 @@ export function HomeView({
selectedId={selectedItemId}
/>

<button
aria-label="Resize inbox list"
className="group absolute inset-y-0 z-20 hidden w-3 -translate-x-1/2 cursor-col-resize lg:block"
data-testid="home-inbox-list-resize-handle"
onDoubleClick={
canResetInboxListWidth ? handleInboxListWidthReset : undefined
}
onPointerDown={handleInboxListResizeStart}
style={{ left: `${inboxListWidthPx}px` }}
title={
canResetInboxListWidth
? "Drag to resize. Double-click to reset width."
: "Drag to resize."
}
type="button"
>
<span className="absolute inset-y-0 left-1/2 w-px -translate-x-1/2 bg-transparent transition-colors group-hover:bg-border/80 group-focus-visible:bg-border/80" />
</button>

<InboxDetailPane
canDelete={canDelete}
canOpenChannel={Boolean(
Expand All @@ -355,6 +390,7 @@ export function HomeView({
item={selectedItem}
messages={contextMessages}
replies={selectedItemReplies}
contextChannelName={selectedChannel?.name ?? null}
onDelete={() => {
if (!selectedItem || !canDelete) {
return;
Expand All @@ -369,6 +405,7 @@ export function HomeView({
setIsDeletingMessage(false);
});
}}
onOpenContext={onOpenContext}
onSendReply={async ({
content,
mediaTags,
Expand Down Expand Up @@ -420,13 +457,8 @@ export function HomeView({
setIsSendingReply(false);
}
}}
onToggleDone={() => {
if (selectedItem) {
handleToggleDone(selectedItem.id);
}
}}
onToggleReaction={
canReply
canReact
? async (message, emoji, remove) => {
await toggleReactionMutation.mutateAsync({
emoji,
Expand All @@ -438,6 +470,11 @@ export function HomeView({
}
: undefined
}
onToggleDone={() => {
if (selectedItem) {
handleToggleDone(selectedItem.id);
}
}}
/>
</div>
</div>
Expand Down
Loading
Loading