Skip to content

Commit 857663b

Browse files
committed
(chore): Fix up the onboarding
1 parent efd9863 commit 857663b

10 files changed

Lines changed: 189 additions & 167 deletions

File tree

apps/polycentric/app/(onboarding)/_layout.tsx

Lines changed: 0 additions & 14 deletions
This file was deleted.

apps/polycentric/app/(onboarding)/login/_layout.tsx

Lines changed: 0 additions & 5 deletions
This file was deleted.

apps/polycentric/app/(onboarding)/signup/_layout.tsx

Lines changed: 0 additions & 1 deletion
This file was deleted.

apps/polycentric/app/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export default function IndexScreen() {
1818

1919
// If no identity, then prompt signup
2020
if (!currentIdentity) {
21-
// return <Redirect href="/(onboarding)" />;
21+
return <Redirect href="/(onboarding)" />;
2222
}
2323

2424
return <Redirect href={Routes.tabs.feed.index as Href} />;

apps/polycentric/src/common/components/layout/Layout.tsx

Lines changed: 55 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { VerticalNav } from './nav/VerticalNav';
2727
import { Ionicons } from '@expo/vector-icons';
2828
import { FUTO_URL, openCompose } from '../../constants';
2929
import { Button } from '../primitives';
30+
import { useCurrentIdentity } from '../../lib/polycentric-hooks';
3031

3132
type MainProps = {
3233
children: ReactElement | ReactElement[];
@@ -84,6 +85,7 @@ function PrimaryColumn({ children }: PrimaryColumnProps) {
8485
testID="primaryColumn"
8586
style={[
8687
Atoms.flex_1,
88+
Atoms.pb_lg,
8789
{ borderLeftColor: theme.palette.neutral_25, borderLeftWidth: 1 },
8890
{ borderRightColor: theme.palette.neutral_25, borderRightWidth: 1 },
8991
{ maxWidth: 600 },
@@ -96,13 +98,18 @@ function PrimaryColumn({ children }: PrimaryColumnProps) {
9698

9799
type ScreenProps = {
98100
children: ReactElement;
101+
showLeftSidebar?: boolean;
99102
keyboardAvoiding?: boolean;
100103
};
101104

102-
function Screen({ children, keyboardAvoiding = false }: ScreenProps) {
105+
function Screen({
106+
children,
107+
showLeftSidebar = true,
108+
keyboardAvoiding = false,
109+
}: ScreenProps) {
103110
const insets = useSafeAreaInsets();
104111

105-
const showLeftSidebar = isWeb;
112+
showLeftSidebar = showLeftSidebar && isWeb;
106113

107114
const body = keyboardAvoiding ? (
108115
<KeyboardAvoidingView
@@ -135,6 +142,8 @@ export const LeftSidebar = memo(function LeftSidebar({
135142
}: LeftSidebarProps) {
136143
const { width: deviceWidth } = useWindowDimensions();
137144

145+
const { identity } = useCurrentIdentity();
146+
138147
const narrowSidebar = deviceWidth <= Breakpoints.xl;
139148

140149
return (
@@ -190,16 +199,18 @@ export const LeftSidebar = memo(function LeftSidebar({
190199
</View>
191200
{/* 2nd Section (bottom) */}
192201
<View style={[Atoms.py_md, Atoms.self_stretch]}>
193-
<Button
194-
title="New Post"
195-
variant="primary"
196-
size="md"
197-
fullWidth
198-
icon={({ size, color }) => (
199-
<Ionicons name="add-circle" size={size} color={color} />
200-
)}
201-
onPress={() => openCompose()}
202-
/>
202+
{identity && (
203+
<Button
204+
title="New Post"
205+
variant="primary"
206+
size="md"
207+
fullWidth
208+
icon={({ size, color }) => (
209+
<Ionicons name="add-circle" size={size} color={color} />
210+
)}
211+
onPress={() => openCompose()}
212+
/>
213+
)}
203214
</View>
204215
</View>
205216
</View>
@@ -239,31 +250,41 @@ export const RightSidebar = memo(function RightSidebar({
239250
<View style={{ width, marginRight }}>
240251
<View
241252
style={[
242-
Atoms.flex_row,
243-
Atoms.items_center,
244-
Atoms.w_full,
245-
Atoms.py_sm,
246-
Atoms.px_sm,
247-
Atoms.gap_sm,
248-
Atoms.flex_wrap,
253+
Atoms.justify_between,
254+
Atoms.align_center,
255+
Atoms.h_full,
256+
Atoms.pb_lg,
249257
]}
250258
>
251-
<Pressable
252-
accessibilityLabel="Toggle color theme"
253-
accessibilityRole="button"
254-
hitSlop={8}
255-
onPress={toggleTheme}
256-
style={({ pressed }) => [pressed && { opacity: 0.65 }]}
259+
<View style={[Atoms.flex_1]}></View>
260+
<View
261+
style={[
262+
Atoms.flex_row,
263+
Atoms.items_center,
264+
Atoms.w_full,
265+
Atoms.py_sm,
266+
Atoms.px_sm,
267+
Atoms.gap_sm,
268+
Atoms.flex_wrap,
269+
]}
257270
>
258-
<Ionicons
259-
name={theme.name === 'dark' ? 'moon' : 'sunny'}
260-
size={typography.fontSize.sm}
261-
color={theme.palette.neutral_500}
262-
/>
263-
</Pressable>
264-
{LINKS.map(({ text, href }) => (
265-
<RightSidebarLink key={href} href={href} text={text} />
266-
))}
271+
<Pressable
272+
accessibilityLabel="Toggle color theme"
273+
accessibilityRole="button"
274+
hitSlop={8}
275+
onPress={toggleTheme}
276+
style={({ pressed }) => [pressed && { opacity: 0.65 }]}
277+
>
278+
<Ionicons
279+
name={theme.name === 'dark' ? 'moon' : 'sunny'}
280+
size={typography.fontSize.sm}
281+
color={theme.palette.neutral_500}
282+
/>
283+
</Pressable>
284+
{LINKS.map(({ text, href }) => (
285+
<RightSidebarLink key={href} href={href} text={text} />
286+
))}
287+
</View>
267288
</View>
268289
</View>
269290
);

apps/polycentric/src/common/lib/polycentric-hooks/PolycentricProvider.tsx

Lines changed: 84 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export interface PolycentricContextValue {
3131
error: Error | null;
3232
currentIdentity: IdentityState | null;
3333
switchIdentity: (publicKey: types.PublicKey) => Promise<void>;
34+
refreshCurrentIdentity: () => Promise<void>;
3435
}
3536

3637
interface FeedHookResult {
@@ -195,6 +196,11 @@ export function PolycentricProvider({
195196
[client],
196197
);
197198

199+
const refreshCurrentIdentity = useCallback(async () => {
200+
if (!client) return;
201+
setCurrentIdentity(await resolveIdentity(client));
202+
}, [client]);
203+
198204
const value = useMemo<PolycentricContextValue | null>(() => {
199205
if (!client || !store) return null;
200206
return {
@@ -205,8 +211,17 @@ export function PolycentricProvider({
205211
error,
206212
currentIdentity,
207213
switchIdentity,
214+
refreshCurrentIdentity,
208215
};
209-
}, [client, store, isLoading, error, currentIdentity, switchIdentity]);
216+
}, [
217+
client,
218+
store,
219+
isLoading,
220+
error,
221+
currentIdentity,
222+
switchIdentity,
223+
refreshCurrentIdentity,
224+
]);
210225

211226
if (error) {
212227
return <DefaultErrorComponent error={error} />;
@@ -257,9 +272,12 @@ const EMPTY_FEED: FeedHookResult = {
257272
/** Call the gRPC-web ListEvents endpoint directly via fetch. */
258273
async function grpcListEvents(
259274
serverUrl: string,
275+
filters?: Partial<v2.ListEventsFilters>,
260276
): Promise<v2.ListEventsResponse> {
261277
const request = v2.ListEventsRequest.toBinary(
262-
v2.ListEventsRequest.create({}),
278+
v2.ListEventsRequest.create({
279+
filters: filters ? v2.ListEventsFilters.create(filters) : undefined,
280+
}),
263281
);
264282

265283
// gRPC-web frame: 1-byte flag (0 = data) + 4-byte big-endian length + body
@@ -354,11 +372,72 @@ export function useFollowingFeed(_options?: {
354372
}
355373

356374
export function useAuthorFeed(
357-
_system: types.PublicKey,
375+
identityId: string | null | undefined,
358376
_limit?: number,
359-
_options?: { getIsAborted?: () => boolean },
377+
options?: { getIsAborted?: () => boolean },
360378
): FeedHookResult {
361-
return EMPTY_FEED;
379+
const { client, store } = usePolycentricContext();
380+
const [isLoading, setIsLoading] = useState(false);
381+
const [error, setError] = useState<Error | null>(null);
382+
const getIsAborted = options?.getIsAborted;
383+
384+
const feedKey = identityId ? `author:${identityId}` : null;
385+
386+
const fetchFeed = useCallback(async () => {
387+
if (!identityId || !feedKey) return;
388+
if (client.servers.length === 0) return;
389+
setIsLoading(true);
390+
setError(null);
391+
try {
392+
const ids: string[] = [];
393+
for (const server of client.servers) {
394+
try {
395+
const response = await grpcListEvents(server, {
396+
identity: identityId,
397+
});
398+
if (getIsAborted?.()) return;
399+
for (const bundle of response.eventBundles) {
400+
const decoded = decodeV2PostBundle(bundle);
401+
if (!decoded) continue;
402+
store
403+
.getState()
404+
.ingestPost(decoded.id, decoded.signedEvent, decoded);
405+
ids.push(decoded.id);
406+
}
407+
} catch (e) {
408+
console.warn(`Failed to fetch author feed from ${server}:`, e);
409+
}
410+
}
411+
if (getIsAborted?.()) return;
412+
store.getState().setFeed(feedKey, ids, false);
413+
} catch (e) {
414+
setError(e instanceof Error ? e : new Error(String(e)));
415+
} finally {
416+
setIsLoading(false);
417+
}
418+
}, [client, store, identityId, feedKey, getIsAborted]);
419+
420+
useEffect(() => {
421+
if (identityId) fetchFeed();
422+
}, [identityId, fetchFeed]);
423+
424+
const items = useStore(
425+
store,
426+
(s) => (feedKey ? s.feeds[feedKey]?.ids : undefined) ?? EMPTY_IDS,
427+
);
428+
const hasMore = useStore(
429+
store,
430+
(s) => (feedKey ? s.feeds[feedKey]?.hasMore : false) ?? false,
431+
);
432+
433+
return {
434+
items,
435+
isLoading,
436+
error,
437+
loadMore: NOOP,
438+
hasMore,
439+
refresh: fetchFeed,
440+
};
362441
}
363442

364443
export function useLikesFeed(_options?: {

apps/polycentric/src/common/lib/polycentric-hooks/useProfileScreenData.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ export function useProfileScreenData(
6161

6262
const username = useUsername(publicKey);
6363
const profile = useProfile(publicKey, { getIsAborted });
64-
const authorFeed = useAuthorFeed(publicKey, undefined, { getIsAborted });
64+
const authorFeed = useAuthorFeed(identityIdParam, undefined, {
65+
getIsAborted,
66+
});
6567
const likesFeed = useLikesFeed({ enabled: isSelf, getIsAborted });
6668
const followStatus = useFollowStatus(publicKey);
6769

apps/polycentric/src/features/onboarding/OnboardingWelcomeScreen.tsx

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,8 @@ import { router } from 'expo-router';
44
import { View } from 'react-native';
55
import { Routes } from '@/src/common/constants/routes';
66

7-
function PlaceholderLogo() {
8-
return (
9-
<View
10-
style={[
11-
Atoms.rounded_lg,
12-
Atoms.items_center,
13-
Atoms.justify_center,
14-
Atoms.mb_lg,
15-
{
16-
width: 100,
17-
height: 100,
18-
borderWidth: 2,
19-
borderColor: 'rgba(255, 255, 255, 0.2)',
20-
borderStyle: 'dashed',
21-
backgroundColor: 'rgba(255, 255, 255, 0.05)',
22-
},
23-
]}
24-
>
25-
<Text variant="small" color="neutral_500">
26-
LOGO
27-
</Text>
28-
</View>
29-
);
30-
}
7+
import WEB_LOGO from '../../common/assets/images/WebLogo.png';
8+
import { Image } from 'expo-image';
319

3210
export default function OnboardingWelcomeScreen() {
3311
return (
@@ -42,16 +20,25 @@ export default function OnboardingWelcomeScreen() {
4220
]}
4321
>
4422
<View
45-
style={[Atoms.flex_1, Atoms.justify_center, Atoms.items_center]}
23+
style={[
24+
Atoms.flex_1,
25+
Atoms.justify_center,
26+
Atoms.items_center,
27+
Atoms.gap_2xl,
28+
]}
4629
>
47-
<PlaceholderLogo />
30+
<Image
31+
source={WEB_LOGO}
32+
contentFit="contain"
33+
style={{ width: 50, height: 50 }}
34+
/>
4835
<View style={Atoms.items_center}>
4936
<Text variant="title" color="neutral_1000">
5037
Polycentric
5138
</Text>
52-
<Text variant="body" color="neutral_500">
39+
{/* <Text variant="body" color="neutral_500">
5340
Law without governance
54-
</Text>
41+
</Text> */}
5542
</View>
5643
</View>
5744
<View style={Atoms.gap_md}>

apps/polycentric/src/features/onboarding/SignupStackLayoutScreen.tsx

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
 (0)