Skip to content

Commit 5368834

Browse files
committed
feat: updates for replicator
1 parent 5afb486 commit 5368834

26 files changed

+560
-172
lines changed

expo-example/app/replication/config.tsx

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ import ReplicatorConfigCollectionForm from '@/components/ReplicationConfigCollec
88
import ResultListView from '@/components/ResultsListView/ResultsListView';
99
import ReplicatorContext from '@/providers/ReplicatorContext';
1010
import { useNavigation } from '@react-navigation/native';
11-
import useNavigationBarTitleOption from '@/hooks/useNativgationBarTitle';
1211
import createReplicatorFromConfig from '@/service/replicator/createReplicatorFromConfig';
12+
import useNavigationBarTitleResetOption from '@/hooks/useNavigationBarTitleResetOption';
1313

1414
export default function ReplicationConfigCreateScreen() {
1515
const { setReplicatorIds } = useContext(ReplicatorContext)!;
1616
const styles = useStyleScheme();
1717
const navigation = useNavigation();
18-
useNavigationBarTitleOption('Add Replicator Config', navigation);
18+
useNavigationBarTitleResetOption('Create Replicator', navigation, reset);
1919

2020
const [replicatorType, setReplicatorType] = useState<string>('');
2121
const [connectionString, setConnectionString] = useState<string>('');
@@ -56,12 +56,22 @@ export default function ReplicationConfigCreateScreen() {
5656
setResultMessages([]);
5757
}
5858

59+
function isConnectionStringValid(connStringLower: string) {
60+
return (
61+
connStringLower.startsWith('ws://') ||
62+
connStringLower.startsWith('wss://')
63+
);
64+
}
65+
5966
async function update(
6067
database: Database,
6168
scopeName: string,
6269
collections: string[]
6370
): Promise<void> {
6471
try {
72+
if (database === null || database === undefined) {
73+
setResultMessages(['Database is required, currently not set']);
74+
}
6575
const connStringLower = connectionString.toLowerCase();
6676
if (replicatorType === '') {
6777
setResultMessages(['Replicator Type is required']);
@@ -79,11 +89,7 @@ export default function ReplicationConfigCreateScreen() {
7989
setResultMessages(['At least one collection is required']);
8090
return;
8191
}
82-
if (
83-
connStringLower === '' ||
84-
!connStringLower.startsWith('ws://') ||
85-
!connStringLower.startsWith('wss://')
86-
) {
92+
if (connStringLower === '' || !isConnectionStringValid(connStringLower)) {
8793
setResultMessages(['Connection String is required']);
8894
return;
8995
}
@@ -114,7 +120,7 @@ export default function ReplicationConfigCreateScreen() {
114120
]);
115121
} catch (error) {
116122
// @ts-ignore
117-
return [error.message];
123+
setResultMessages((prev) => [...prev, error.message]);
118124
}
119125
}
120126

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from 'react';
2+
import { Replicator } from 'cbl-reactnative';
3+
import CBLReplicatorActionContainer from '@/components/CBLReplicatorActionContainer/CBLReplicatorActionContainer';
4+
5+
export default function ReplicatorPendingDocsScreen() {
6+
function reset() {}
7+
8+
async function update(replicator: Replicator): Promise<string[]> {
9+
return [''];
10+
}
11+
12+
return (
13+
<CBLReplicatorActionContainer
14+
handleUpdatePressed={update}
15+
handleResetPressed={reset}
16+
screenTitle="Pending Documents"
17+
/>
18+
);
19+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React from 'react';
2+
import { Replicator } from 'cbl-reactnative';
3+
import CBLReplicatorActionContainer from '@/components/CBLReplicatorActionContainer/CBLReplicatorActionContainer';
4+
import start from '@/service/replicator/start';
5+
6+
export default function ReplicatorStartScreen() {
7+
function reset() {}
8+
9+
async function update(replicator: Replicator): Promise<string[]> {
10+
try {
11+
await start(replicator, false);
12+
return ['Replicator started.'];
13+
} catch (e) {
14+
// @ts-ignore
15+
return [error.message];
16+
}
17+
}
18+
19+
return (
20+
<CBLReplicatorActionContainer
21+
handleUpdatePressed={update}
22+
handleResetPressed={reset}
23+
screenTitle="Start Replicator"
24+
/>
25+
);
26+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React, { useContext } from 'react';
2+
import { Replicator } from 'cbl-reactnative';
3+
import CBLReplicatorActionContainer from '@/components/CBLReplicatorActionContainer/CBLReplicatorActionContainer';
4+
import DatabaseContext from '@/providers/DatabaseContext';
5+
import ReplicatorStatusChangeContext from '@/providers/ReplicatorStatusChangeContext';
6+
7+
export default function ReplicatorStatusScreen() {
8+
const { statusChangeMessages, setStatusChangeMessages } = useContext(
9+
ReplicatorStatusChangeContext
10+
)!;
11+
function reset() {}
12+
13+
async function update(replicator: Replicator): Promise<string[]> {
14+
return [''];
15+
}
16+
17+
return (
18+
<CBLReplicatorActionContainer
19+
handleUpdatePressed={update}
20+
handleResetPressed={reset}
21+
screenTitle="Replicator Status"
22+
/>
23+
);
24+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React from 'react';
2+
import { Replicator } from 'cbl-reactnative';
3+
import CBLReplicatorActionContainer from '@/components/CBLReplicatorActionContainer/CBLReplicatorActionContainer';
4+
import stop from '@/service/replicator/stop';
5+
6+
export default function ReplicatorStopScreen() {
7+
function reset() {}
8+
9+
async function update(replicator: Replicator): Promise<string[]> {
10+
try {
11+
await stop(replicator);
12+
return ['Replicator stopped.'];
13+
} catch (e) {
14+
// @ts-ignore
15+
return [error.message];
16+
}
17+
}
18+
19+
return (
20+
<CBLReplicatorActionContainer
21+
handleUpdatePressed={update}
22+
handleResetPressed={reset}
23+
screenTitle="Stop Replicator"
24+
/>
25+
);
26+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import React, { useContext, useState } from 'react';
2+
import { SafeAreaView } from 'react-native';
3+
import ReplicatorContext from '@/providers/ReplicatorContext';
4+
import { useNavigation } from '@react-navigation/native';
5+
import { useStyleScheme } from '@/components/Themed/Themed';
6+
import ResultListView from '@/components/ResultsListView/ResultsListView';
7+
import SelectKeyValue from '@/components/SelectKeyValue/SelectKeyValue';
8+
import HeaderToolbarView from '@/components/HeaderToolbarView/HeaderToolbarView';
9+
import { CBLReplicatorActionContainerProps } from '@/components/CBLReplicatorActionContainer/CBLReplicatorActionContainerProps.type';
10+
import useNavigationBarTitleResetOption from '@/hooks/useNavigationBarTitleResetOption';
11+
import { Item } from '@/types/item.type';
12+
13+
export default function CBLReplicatorActionContainer({
14+
screenTitle,
15+
handleUpdatePressed,
16+
handleResetPressed,
17+
children,
18+
}: CBLReplicatorActionContainerProps) {
19+
const { replicatorIds } = useContext(ReplicatorContext)!;
20+
const [replicatorId, setReplicatorId] = useState<string>('');
21+
const [resultMessage, setResultsMessage] = useState<string[]>([]);
22+
const navigation = useNavigation();
23+
const styles = useStyleScheme();
24+
useNavigationBarTitleResetOption(screenTitle, navigation, reset);
25+
const items: Item[] = Object.keys(replicatorIds).map((key) => ({
26+
key: key,
27+
value: key,
28+
}));
29+
const icons = [
30+
{
31+
iconName: 'play',
32+
onPress: update,
33+
},
34+
];
35+
36+
async function update() {
37+
if (replicatorId === '') {
38+
setResultsMessage((prev) => [...prev, 'Error: replicatorId is required']);
39+
} else {
40+
try {
41+
if (replicatorId in replicatorIds) {
42+
const replicator = replicatorIds[replicatorId];
43+
const resultMessages = await handleUpdatePressed(replicator);
44+
setResultsMessage((prev) => [...prev, ...resultMessages]);
45+
} else {
46+
setResultsMessage((prev) => [
47+
...prev,
48+
`Error: Replicator <${replicatorId}> not found in context. Make sure replicator was created first prior to trying to use it.`,
49+
]);
50+
}
51+
} catch (error) {
52+
// @ts-ignore
53+
setResultsMessage((prev) => [...prev, error.message]);
54+
}
55+
}
56+
}
57+
58+
function reset() {
59+
setReplicatorId('');
60+
setResultsMessage([]);
61+
handleResetPressed();
62+
}
63+
return (
64+
<SafeAreaView style={styles.container}>
65+
<HeaderToolbarView
66+
name="Replicator"
67+
iconName="database-sync"
68+
icons={icons}
69+
/>
70+
<SelectKeyValue
71+
key="replicatorIdSelect"
72+
placeholder="Replicator ID"
73+
headerTitle="Select Replicator"
74+
items={items}
75+
onSelectChange={setReplicatorId}
76+
/>
77+
{children && children}
78+
<ResultListView messages={resultMessage} />
79+
</SafeAreaView>
80+
);
81+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import React from 'react';
2+
import { Replicator } from 'cbl-reactnative';
3+
4+
export type CBLReplicatorActionContainerProps = {
5+
screenTitle: string;
6+
handleUpdatePressed: (replicator: Replicator) => Promise<string[]>;
7+
handleResetPressed: () => void;
8+
children?: React.ReactNode;
9+
};

expo-example/components/ReplicationConfigCollectionForm/ReplicatorConfigCollectionForm.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export default function ReplicatorConfigCollectionForm({
3131
databases[databaseName] instanceof Database
3232
) {
3333
const database = databases[databaseName];
34-
const collectionsList = collections.trim().split(',');
34+
const collectionsList = collections.split(',').map((c) => c.trim());
3535
await handleUpdatePressed(database, scopeName, collectionsList);
3636
} else {
3737
updateResultMessage([

expo-example/components/ReplicatorAuthenticationForm/ReplicatorAuthenticationForm.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { ReplicatorAuthenticationFormProps } from '@/components/ReplicatorAuthen
66
import { useStyleScheme } from '@/components/Themed/Themed';
77
import HeaderView from '@/components/HeaderView/HeaderView';
88
import { Divider } from '@gluestack-ui/themed';
9-
type Item = { key: string; value: string };
9+
import { Item } from '@/types/item.type';
1010

1111
export default function ReplicatorAuthenticationForm({
1212
selectedAuthenticationType,

expo-example/hooks/useReplicationNavigationSections.tsx

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,41 @@ export function useReplicationNavigationSections() {
66
data: [
77
{
88
id: 1,
9-
title: 'Replicator Configs',
10-
path: '/replication/configListing',
9+
title: 'Create Replicator',
10+
path: '/replication/config',
1111
},
1212
{
1313
id: 2,
14-
title: 'Replicator Start/Stop',
14+
title: 'Replicator Start',
1515
path: '/replication/start',
1616
},
1717
{
1818
id: 3,
19+
title: 'Replicator Stop',
20+
path: '/replication/stop',
21+
},
22+
{
23+
id: 4,
1924
title: 'Pending Documents',
2025
path: '/replication/pendingDocs',
2126
},
2227
{
23-
id: 4,
28+
id: 5,
2429
title: 'Is Documents Pending',
2530
path: '/replication/isPending',
2631
},
2732
{
28-
id: 5,
33+
id: 6,
2934
title: 'Replicator Logs',
3035
path: '/replication/logs',
3136
},
3237
{
33-
id: 6,
38+
id: 7,
3439
title: 'Status Changes',
3540
path: '/replication/status',
3641
},
3742
{
38-
id: 7,
43+
id: 8,
3944
title: 'Document Changes',
4045
path: '/replication/documentChange',
4146
},

0 commit comments

Comments
 (0)