Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 0 additions & 2 deletions app/guilds.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ export default function Guilds() {
const { walletAddress } = useWallet();
const { getMembership } = useMembership(walletAddress);

// In a real app, you would fetch all guilds.
// For MVP, we'll show a few example guilds that the user can explore.
const exampleGuilds = [
{ id: "guild_abc", name: "Alpha Guild", isActive: true, roleCount: 3 },
{ id: "guild_xyz", name: "Beta Community", isActive: true, roleCount: 5 },
Expand Down
92 changes: 47 additions & 45 deletions app/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,52 +25,54 @@ export default function Settings() {
const chainId = appConfig.chainId;

return (
<View className="flex-1 bg-background" testID="settings-screen">
<AppHeader title="Settings" showBack />
<ScrollView className="flex-1 px-4 py-6">
<Text className="text-lg font-bold text-text mb-3">Protocol Configuration</Text>
<Card className="mb-6">
<View className="flex-row justify-between py-2 border-b border-border">
<Text className="text-text-muted">API URL</Text>
<Text className="text-text font-medium" testID="settings-api-url">
{apiUrl}
</Text>
</View>
<View className="flex-row justify-between py-2 border-b border-border">
<Text className="text-text-muted">Default Chain ID</Text>
<Text className="text-text font-medium" testID="settings-chain-id">
{chainId}
</Text>
</View>
<View className="flex-row justify-between py-2">
<Text className="text-text-muted">SDK Version</Text>
<Text className="text-text font-medium" testID="settings-sdk-version">
0.1.0-mvp
</Text>
</View>
</Card>
<WalletRequired>
<View className="flex-1 bg-background" testID="settings-screen">
<AppHeader title="Settings" showBack />
<ScrollView className="flex-1 px-4 py-6">
<Text className="text-lg font-bold text-text mb-3">Protocol Configuration</Text>
<Card className="mb-6">
<View className="flex-row justify-between py-2 border-b border-border">
<Text className="text-text-muted">API URL</Text>
<Text className="text-text font-medium" testID="settings-api-url">
{apiUrl}
</Text>
</View>
<View className="flex-row justify-between py-2 border-b border-border">
<Text className="text-text-muted">Default Chain ID</Text>
<Text className="text-text font-medium" testID="settings-chain-id">
{chainId}
</Text>
</View>
<View className="flex-row justify-between py-2">
<Text className="text-text-muted">SDK Version</Text>
<Text className="text-text font-medium" testID="settings-sdk-version">
0.1.0-mvp
</Text>
</View>
</Card>

<Text className="text-lg font-bold text-text mb-3">Account</Text>
<Card className="mb-8">
<WalletRequired redirect={false}>
<Text className="text-text-muted mb-4">
will disconnect your current wallet address and clear any local cache.
</Text>
<Button
title="Reset App State"
onPress={handleReset}
variant="danger"
loading={isResetting}
disabled={isResetting}
/>
</WalletRequired>
</Card>
<Text className="text-lg font-bold text-text mb-3">Account</Text>
<Card className="mb-8">
<WalletRequired redirect={false}>
<Text className="text-text-muted mb-4">
will disconnect your current wallet address and clear any local cache.
</Text>
<Button
title="Reset App State"
onPress={handleReset}
variant="danger"
loading={isResetting}
disabled={isResetting}
/>
</WalletRequired>
</Card>

<View className="items-center mt-12">
<Text className="text-text-muted text-sm italic">GuildPass Mobile MVP v1.0.0</Text>
<Text className="text-text-muted text-xs mt-1">Built with Expo & NativeWind</Text>
</View>
</ScrollView>
</View>
<View className="items-center mt-12">
<Text className="text-text-muted text-sm italic">GuildPass Mobile MVP v1.0.0</Text>
<Text className="text-text-muted text-xs mt-1">Built with Expo and NativeWind</Text>
</View>
</ScrollView>
</View>
</WalletRequired>
);
}
9 changes: 0 additions & 9 deletions src/components/WalletRequired.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,9 @@ import { Button } from "./Button";

interface WalletRequiredProps {
children: React.ReactNode;
/**
* When true (default), redirects to /profile if wallet is not connected.
* When false, renders an inline connect-wallet prompt instead.
*/
redirect?: boolean;
}

/**
* Route guard that ensures a wallet is connected before rendering
* wallet-scoped content. Redirects to /profile or shows a connect prompt.
*/
export function WalletRequired({
children,
redirect = true,
Expand All @@ -30,7 +22,6 @@ export function WalletRequired({
}
}, [isHydrated, isConnected, redirect, router]);

// Wait for store hydration to avoid flash of wrong state
if (!isHydrated) {
return null;
}
Expand Down
7 changes: 0 additions & 7 deletions tests/walletRequired.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,12 @@ describe("WalletRequired", () => {
</WalletRequired>
);
});

expect(JSON.stringify(tree.toJSON())).toContain("Protected content");
});

it("returns null when store is not yet hydrated", () => {
mockIsConnected.mockReturnValue(false);
mockIsHydrated.mockReturnValue(false);

let tree: any;
act(() => {
tree = TestRenderer.create(
Expand All @@ -59,29 +57,25 @@ describe("WalletRequired", () => {
</WalletRequired>
);
});

expect(tree.toJSON()).toBeNull();
});

it("redirects to /profile when disconnected and redirect=true", () => {
mockIsConnected.mockReturnValue(false);
mockIsHydrated.mockReturnValue(true);

act(() => {
TestRenderer.create(
<WalletRequired redirect={true}>
<Text>Protected content</Text>
</WalletRequired>
);
});

expect(mockReplace).toHaveBeenCalledWith("/profile");
});

it("shows connect-wallet prompt when disconnected and redirect=false", () => {
mockIsConnected.mockReturnValue(false);
mockIsHydrated.mockReturnValue(true);

let renderer: any;
act(() => {
renderer = TestRenderer.create(
Expand All @@ -90,7 +84,6 @@ describe("WalletRequired", () => {
</WalletRequired>
);
});

expect(renderer.root.findByProps({ testID: "wallet-required-prompt" })).toBeDefined();
expect(renderer.root.findByProps({ testID: "wallet-required-connect" })).toBeDefined();
expect(mockReplace).not.toHaveBeenCalled();
Expand Down
Loading