Skip to content
Merged
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
126 changes: 77 additions & 49 deletions example/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { Pressable, StyleSheet, Text, View } from 'react-native';
import { Pressable, StatusBar, StyleSheet, Text, View } from 'react-native';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import { SalveDbProvider } from '@salve-software/react-native-salve-db';
import Salvetron from '@salve-software/salvetron-react-native';
Expand All @@ -14,34 +14,28 @@ import { InfiniteQueryScreen } from './src/screens/InfiniteQueryScreen';
import { BenchmarkScreen } from './src/screens/BenchmarkScreen';
import { SyncTestScreen } from './src/screens/SyncTestScreen';
import { LoginScreen, type LoginTokens } from './src/screens/LoginScreen';
import { ResetControls } from './src/components/ResetControls';
import { SideMenu } from './src/components/SideMenu';
import { IconButton, ToastProvider } from './src/components/ui';
import { colors, spacing } from './src/theme/tokens';
import { WalletIcon, StackIcon, LightningIcon, ArrowsClockwiseIcon, ListIcon } from './src/theme/icons';
import { SYNC_SERVER_BASE_URL } from './src/library/syncServer';

if (__DEV__) {
Salvetron.connect({ host: 'localhost', port: 8765 });
}

const ACCENT = '#5B5FEF';

const TABS = [
{ key: 'expenses', label: 'Query', icon: '💸' },
{ key: 'infinite', label: 'Infinite Query', icon: '📜' },
{ key: 'benchmark', label: 'Benchmark', icon: '⚡' },
{ key: 'sync', label: 'Sync Test', icon: '🔄' },
{ key: 'expenses', label: 'Query', Icon: WalletIcon },
{ key: 'infinite', label: 'Infinite Query', Icon: StackIcon },
{ key: 'benchmark', label: 'Benchmark', Icon: LightningIcon },
{ key: 'sync', label: 'Sync Test', Icon: ArrowsClockwiseIcon },
] as const;

type TabKey = (typeof TABS)[number]['key'];

const SCHEMAS = [
ExpenseSchema,
BudgetSchema,
BenchmarkSchema,
FeedItemSchema,
UserSchema,
ProductSchema,
];
const SCHEMAS = [ExpenseSchema, BudgetSchema, BenchmarkSchema, FeedItemSchema, UserSchema, ProductSchema];

/** Shared by the initial SalveDbProvider mount and ResetControls' "reconfigure" button — same db name both times, so the connection (and its subscriptions) survives a reset(). */
/** Shared by the initial SalveDbProvider mount and SideMenu's "reconfigure" button — same db name both times, so the connection (and its subscriptions) survives a reset(). */
function buildDbConfig(tokens: LoginTokens) {
return {
name: 'salve-db-example',
Expand All @@ -66,10 +60,14 @@ interface AppTabsProps {

function AppTabs({ tokens, onLogout }: AppTabsProps): React.JSX.Element {
const [tab, setTab] = useState<TabKey>('expenses');
const [menuOpen, setMenuOpen] = useState(false);

return (
<View style={styles.flex}>
<ResetControls schemas={SCHEMAS} buildConfig={() => buildDbConfig(tokens)} onLogout={onLogout} />
<SafeAreaView style={styles.header} edges={['top']}>
<Text style={styles.headerTitle}>Salve DB</Text>
<IconButton icon={<ListIcon size={18} color={colors.ink} />} onPress={() => setMenuOpen(true)} />
</SafeAreaView>

<View style={styles.flex}>
{tab === 'expenses' ? <ExpensesScreen /> : null}
Expand All @@ -79,33 +77,46 @@ function AppTabs({ tokens, onLogout }: AppTabsProps): React.JSX.Element {
</View>

<SafeAreaView style={styles.tabBar} edges={['bottom']}>
{TABS.map(({ key, label, icon }) => (
<Pressable key={key} onPress={() => setTab(key)} style={styles.tabItem}>
<Text style={[styles.tabIcon, tab === key && styles.tabIconActive]}>{icon}</Text>
<Text style={[styles.tabLabel, tab === key && styles.tabLabelActive]}>{label}</Text>
</Pressable>
))}
{TABS.map(({ key, label, Icon }) => {
const active = tab === key;
return (
<Pressable key={key} onPress={() => setTab(key)} style={styles.tabItem}>
{active ? <View style={styles.tabIndicator} /> : null}
<Icon size={20} weight={active ? 'fill' : 'regular'} color={active ? colors.accent : colors.muted} />
<Text style={[styles.tabLabel, active && styles.tabLabelActive]} numberOfLines={1}>
{label}
</Text>
</Pressable>
);
})}
</SafeAreaView>

<SideMenu
visible={menuOpen}
onClose={() => setMenuOpen(false)}
schemas={SCHEMAS}
buildConfig={() => buildDbConfig(tokens)}
onLogout={onLogout}
/>
</View>
);
}

function App(): React.JSX.Element {
const [tokens, setTokens] = useState<LoginTokens | null>(null);

if (tokens === null) {
return (
<SafeAreaProvider>
<LoginScreen onLoginSuccess={setTokens} />
</SafeAreaProvider>
);
}

return (
<SafeAreaProvider>
<SalveDbProvider config={buildDbConfig(tokens)} schemas={SCHEMAS}>
<AppTabs tokens={tokens} onLogout={() => setTokens(null)} />
</SalveDbProvider>
<StatusBar barStyle="light-content" backgroundColor={colors.canvas} />
<ToastProvider>
{tokens === null ? (
<LoginScreen onLoginSuccess={setTokens} />
) : (
<SalveDbProvider config={buildDbConfig(tokens)} schemas={SCHEMAS}>
<AppTabs tokens={tokens} onLogout={() => setTokens(null)} />
</SalveDbProvider>
)}
</ToastProvider>
</SafeAreaProvider>
);
}
Expand All @@ -115,33 +126,50 @@ export default App;
const styles = StyleSheet.create({
flex: {
flex: 1,
backgroundColor: colors.canvas,
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: spacing.lg,
paddingVertical: spacing.sm,
backgroundColor: colors.surface,
borderBottomWidth: StyleSheet.hairlineWidth,
borderBottomColor: colors.line,
},
headerTitle: {
fontSize: 16,
fontWeight: '700',
color: colors.ink,
},
tabBar: {
flexDirection: 'row',
backgroundColor: '#FFFFFF',
backgroundColor: colors.surface,
borderTopWidth: StyleSheet.hairlineWidth,
borderTopColor: '#E1E2F0',
borderTopColor: colors.line,
},
tabItem: {
flex: 1,
alignItems: 'center',
paddingTop: 10,
paddingBottom: 6,
gap: 2,
},
tabIcon: {
fontSize: 20,
opacity: 0.5,
paddingTop: spacing.sm,
paddingBottom: spacing.xs,
gap: spacing.xxs,
},
tabIconActive: {
opacity: 1,
tabIndicator: {
position: 'absolute',
top: 0,
width: 24,
height: 2,
borderRadius: 1,
backgroundColor: colors.accent,
},
tabLabel: {
fontSize: 11,
fontSize: 10,
fontWeight: '600',
color: '#9B9DB8',
color: colors.muted,
},
tabLabelActive: {
color: ACCENT,
color: colors.accent,
},
});
19 changes: 19 additions & 0 deletions example/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Module augmentation required by phosphor-react-native's TypeScript setup —
// see the "Typescript support" section of its README. Declares only the
// extra `className` member each interface is missing; merges into the
// existing declaration rather than re-declaring it (an `extends` here would
// make the interface reference itself).
import 'react-native-svg';
import 'phosphor-react-native';

declare module 'react-native-svg' {
interface SvgProps {
className?: string;
}
}

declare module 'phosphor-react-native' {
interface IconProps {
className?: string;
}
}
49 changes: 49 additions & 0 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1939,6 +1939,51 @@ PODS:
- React-utils (= 0.86.0)
- ReactNativeDependencies
- ReactNativeDependencies (0.86.0)
- RNSVG (15.15.5):
- hermes-engine
- RCTRequired
- RCTTypeSafety
- React-Core
- React-Core-prebuilt
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-jsi
- React-NativeModulesApple
- React-RCTFabric
- React-renderercss
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- ReactNativeDependencies
- RNSVG/common (= 15.15.5)
- Yoga
- RNSVG/common (15.15.5):
- hermes-engine
- RCTRequired
- RCTTypeSafety
- React-Core
- React-Core-prebuilt
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-jsi
- React-NativeModulesApple
- React-RCTFabric
- React-renderercss
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- ReactNativeDependencies
- Yoga
- SalveDb (0.1.1):
- hermes-engine
- NitroModules
Expand Down Expand Up @@ -2044,6 +2089,7 @@ DEPENDENCIES:
- ReactCodegen (from `build/generated/ios/ReactCodegen`)
- ReactCommon/turbomodule/core (from `../../node_modules/react-native/ReactCommon`)
- ReactNativeDependencies (from `../../node_modules/react-native/third-party-podspecs/ReactNativeDependencies.podspec`)
- RNSVG (from `../../node_modules/react-native-svg`)
- SalveDb (from `../..`)
- Yoga (from `../../node_modules/react-native/ReactCommon/yoga`)

Expand Down Expand Up @@ -2203,6 +2249,8 @@ EXTERNAL SOURCES:
:path: "../../node_modules/react-native/ReactCommon"
ReactNativeDependencies:
:podspec: "../../node_modules/react-native/third-party-podspecs/ReactNativeDependencies.podspec"
RNSVG:
:path: "../../node_modules/react-native-svg"
SalveDb:
:path: "../.."
Yoga:
Expand Down Expand Up @@ -2286,6 +2334,7 @@ SPEC CHECKSUMS:
ReactCodegen: 1973e629fe2614a7b2cf72919cb9935b6c34675f
ReactCommon: d5c1bb4427bf51c443de5926aac332c89ddd9363
ReactNativeDependencies: fa0a54b3f5319ae0e3b9aff32bfee7a424b88e66
RNSVG: 6cae8d4082913be2eb43eaec2a456222c42195ed
SalveDb: c9d225fdca0b6ee1bf26697372566eac2aa0640f
Yoga: fe50ab299e578f397fef753cf309c6703a4db29b

Expand Down
Loading
Loading