Skip to content

Commit bc271e8

Browse files
committed
fix: fixed blob support
1 parent 3022fbf commit bc271e8

File tree

8 files changed

+137
-169
lines changed

8 files changed

+137
-169
lines changed

expo-example/android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,4 @@ allprojects {
3939
maven { url 'https://www.jitpack.io' }
4040
}
4141
}
42-
apply from: "../../android/build.gradle"apply from: "../../android/build.gradle"
42+
apply from: "../../android/build.gradle"apply from: "../../android/build.gradle"apply from: "../../android/build.gradle"apply from: "../../android/build.gradle"apply from: "../../android/build.gradle"apply from: "../../android/build.gradle"
Lines changed: 30 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,46 @@
11
import React, { useContext, useState } from 'react';
2-
import { SafeAreaView, ScrollView } from 'react-native';
3-
import { useNavigation } from '@react-navigation/native';
42
import { useStyleScheme } from '@/components/Themed';
5-
import ResultListView from '@/components/ResultsListView';
6-
import DatabaseContext from '@/providers/DatabaseContext';
7-
import useNavigationBarTitleResetOption from '@/hooks/useNavigationBarTitleResetOption';
8-
import DatabaseScopeCollectionForm from '@/components/DatabaseScopeCollectionForm';
9-
import HeaderView from '@/components/HeaderView';
10-
import DocumentIdActionForm from '@/components/DocumentIdActionForm';
11-
//import get from '@/service/document/get';
3+
import { Collection } from 'cbl-reactnative';
4+
import CBLDocumentIdCollectionActionContainer from '@/components/CBLDocumentIdCollectionActionContainer';
5+
import { StyledTextInput } from '@/components/StyledTextInput';
6+
import { Divider } from '@gluestack-ui/themed';
7+
import getBlob from '@/service/document/getBlob';
128

139
export default function DocumentGetBlobScreen() {
14-
//database stuff
15-
const { databases } = useContext(DatabaseContext)!;
16-
const [databaseName, setDatabaseName] = useState<string>('');
17-
const [scopeName, setScopeName] = useState<string>('');
18-
const [collectionName, setCollectionName] = useState<string>('');
19-
const [documentId, setDocumentId] = useState<string>('');
2010
const [key, setKey] = useState<string>('');
21-
//results
22-
const [resultMessage, setResultsMessage] = useState<string[]>([]);
23-
//drawing stuff
24-
const navigation = useNavigation();
2511
const styles = useStyleScheme();
26-
useNavigationBarTitleResetOption('Get Document Text Blob', navigation, reset);
2712

2813
function reset() {
29-
setDatabaseName('');
30-
setScopeName('');
31-
setCollectionName('');
32-
setDocumentId('');
3314
setKey('');
34-
setResultsMessage([]);
3515
}
3616

37-
const update = async () => {
38-
if (databaseName === '') {
39-
setResultsMessage((prev) => [
40-
...prev,
41-
'Error: Database name is required',
42-
]);
43-
} else {
44-
try {
45-
if (documentId === '') {
46-
setResultsMessage((prev) => [
47-
...prev,
48-
'Error: Document ID is required',
49-
]);
50-
return;
51-
}
52-
/*
53-
const doc = await get(
54-
databases,
55-
databaseName,
56-
scopeName,
57-
collectionName,
58-
documentId
59-
);
60-
if (doc !== undefined && doc !== null) {
61-
const json = JSON.stringify(doc.toDictionary());
62-
const resultsMessage = `Document <${documentId}> found with JSON: ${json}`;
63-
setResultsMessage((prev) => [...prev, resultsMessage]);
64-
} else {
65-
setResultsMessage((prev) => [
66-
...prev,
67-
'Error: Document could not be retrieved',
68-
]);
69-
}
70-
*/
71-
} catch (error) {
72-
// @ts-ignore
73-
setResultsMessage((prev) => [...prev, error.message]);
74-
}
17+
async function update(
18+
collection: Collection,
19+
documentId: string
20+
): Promise<string[]> {
21+
try {
22+
const result = await getBlob(collection, documentId, key);
23+
return [result];
24+
} catch (error) {
25+
// @ts-ignore
26+
return [error.message];
7527
}
76-
};
28+
}
7729

7830
return (
79-
<SafeAreaView style={styles.container}>
80-
<ScrollView style={styles.container}>
81-
<HeaderView name="Collection" iconName="bookshelf" />
82-
<DatabaseScopeCollectionForm
83-
databaseName={databaseName}
84-
setDatabaseName={setDatabaseName}
85-
scopeName={scopeName}
86-
setScopeName={setScopeName}
87-
collectionName={collectionName}
88-
setCollectionName={setCollectionName}
89-
/>
90-
<DocumentIdActionForm
91-
documentId={documentId}
92-
setDocumentId={setDocumentId}
93-
handleUpdatePressed={update}
94-
/>
95-
<ResultListView messages={resultMessage} />
96-
</ScrollView>
97-
</SafeAreaView>
31+
<CBLDocumentIdCollectionActionContainer
32+
screenTitle="Get Blob"
33+
handleUpdatePressed={update}
34+
handleResetPressed={reset}
35+
>
36+
<Divider style={{ marginTop: 5, marginBottom: 10, marginLeft: 8 }} />
37+
<StyledTextInput
38+
style={{ marginBottom: 5 }}
39+
autoCapitalize="none"
40+
placeholder="Blob Key"
41+
onChangeText={(keyText) => setKey(keyText)}
42+
defaultValue={key}
43+
/>
44+
</CBLDocumentIdCollectionActionContainer>
9845
);
9946
}
Lines changed: 55 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,73 @@
1-
import React, { useContext, useState } from 'react';
2-
import { SafeAreaView, ScrollView } from 'react-native';
3-
import { useNavigation } from '@react-navigation/native';
1+
import React, { useState } from 'react';
42
import { useStyleScheme } from '@/components/Themed';
5-
import ResultListView from '@/components/ResultsListView';
6-
import DatabaseContext from '@/providers/DatabaseContext';
7-
import useNavigationBarTitleResetOption from '@/hooks/useNavigationBarTitleResetOption';
8-
import DatabaseScopeCollectionForm from '@/components/DatabaseScopeCollectionForm';
9-
import HeaderView from '@/components/HeaderView';
10-
import DocumentIdActionForm from '@/components/DocumentIdActionForm';
11-
//import get from '@/service/document/get';
3+
import { Collection, Blob } from 'cbl-reactnative';
4+
import CBLDocumentIdCollectionActionContainer from '@/components/CBLDocumentIdCollectionActionContainer';
5+
import { StyledTextInput } from '@/components/StyledTextInput';
6+
import { Divider } from '@gluestack-ui/themed';
7+
import setBlob from '@/service/document/setBlob';
128

139
export default function DocumentSetBlobScreen() {
1410
//database stuff
15-
const { databases } = useContext(DatabaseContext)!;
16-
const [databaseName, setDatabaseName] = useState<string>('');
17-
const [scopeName, setScopeName] = useState<string>('');
18-
const [collectionName, setCollectionName] = useState<string>('');
19-
const [documentId, setDocumentId] = useState<string>('');
2011
const [key, setKey] = useState<string>('');
12+
const [blobText, setBlobText] = useState<string>('');
2113
//results
22-
const [resultMessage, setResultsMessage] = useState<string[]>([]);
23-
//drawing stuff
24-
const navigation = useNavigation();
2514
const styles = useStyleScheme();
26-
useNavigationBarTitleResetOption('Get Document Text Blob', navigation, reset);
2715

2816
function reset() {
29-
setDatabaseName('');
30-
setScopeName('');
31-
setCollectionName('');
32-
setDocumentId('');
3317
setKey('');
34-
setResultsMessage([]);
3518
}
3619

37-
const update = async () => {
38-
if (databaseName === '') {
39-
setResultsMessage((prev) => [
40-
...prev,
41-
'Error: Database name is required',
42-
]);
43-
} else {
44-
try {
45-
if (documentId === '') {
46-
setResultsMessage((prev) => [
47-
...prev,
48-
'Error: Document ID is required',
49-
]);
50-
return;
51-
}
52-
/*
53-
const doc = await get(
54-
databases,
55-
databaseName,
56-
scopeName,
57-
collectionName,
58-
documentId
59-
);
60-
if (doc !== undefined && doc !== null) {
61-
const json = JSON.stringify(doc.toDictionary());
62-
const resultsMessage = `Document <${documentId}> found with JSON: ${json}`;
63-
setResultsMessage((prev) => [...prev, resultsMessage]);
64-
} else {
65-
setResultsMessage((prev) => [
66-
...prev,
67-
'Error: Document could not be retrieved',
68-
]);
69-
}
70-
*/
71-
} catch (error) {
72-
// @ts-ignore
73-
setResultsMessage((prev) => [...prev, error.message]);
20+
async function update(
21+
collection: Collection,
22+
documentId: string
23+
): Promise<string[]> {
24+
try {
25+
const encoder = new TextEncoder();
26+
const blob = new Blob('text/plain', encoder.encode(blobText));
27+
const mutDoc = await setBlob(collection, documentId, key, blob);
28+
if (
29+
mutDoc !== undefined &&
30+
mutDoc !== null &&
31+
mutDoc.getId() === documentId
32+
) {
33+
return [
34+
`Blob with key <${key}> set on Document <${documentId}> in Collection <${collection.fullName()}> Database <${collection.database.getName()}>`,
35+
];
36+
} else {
37+
return ['Error: Blob could not be set'];
7438
}
39+
} catch (error) {
40+
// @ts-ignore
41+
return [error.message];
7542
}
76-
};
43+
}
7744

7845
return (
79-
<SafeAreaView style={styles.container}>
80-
<ScrollView style={styles.container}>
81-
<HeaderView name="Collection" iconName="bookshelf" />
82-
<DatabaseScopeCollectionForm
83-
databaseName={databaseName}
84-
setDatabaseName={setDatabaseName}
85-
scopeName={scopeName}
86-
setScopeName={setScopeName}
87-
collectionName={collectionName}
88-
setCollectionName={setCollectionName}
89-
/>
90-
<DocumentIdActionForm
91-
documentId={documentId}
92-
setDocumentId={setDocumentId}
93-
handleUpdatePressed={update}
94-
/>
95-
<ResultListView messages={resultMessage} />
96-
</ScrollView>
97-
</SafeAreaView>
46+
<CBLDocumentIdCollectionActionContainer
47+
screenTitle="Set Blob"
48+
handleUpdatePressed={update}
49+
handleResetPressed={reset}
50+
>
51+
<Divider style={{ marginTop: 5, marginBottom: 10, marginLeft: 8 }} />
52+
<StyledTextInput
53+
style={{ marginBottom: 5 }}
54+
autoCapitalize="none"
55+
placeholder="Blob Key"
56+
onChangeText={(keyText) => setKey(keyText)}
57+
defaultValue={key}
58+
/>
59+
<Divider style={{ marginTop: 5, marginBottom: 10, marginLeft: 8 }} />
60+
<StyledTextInput
61+
autoCapitalize="none"
62+
style={[
63+
styles.textInput,
64+
{ height: undefined, minHeight: 120, marginTop: 5, marginBottom: 15 },
65+
]}
66+
placeholder="Blob Text"
67+
onChangeText={(newBlobText) => setBlobText(newBlobText)}
68+
defaultValue={blobText}
69+
multiline={true}
70+
/>
71+
</CBLDocumentIdCollectionActionContainer>
9872
);
9973
}

expo-example/hooks/useDocumentNavigationSections.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ export function useDocumentNavigationSections() {
2424
},
2525
{
2626
id: 7,
27-
title: 'Set Blob in Document',
28-
path: '/document/blob/setImage',
27+
title: 'Set Blob',
28+
path: '/document/blob/setBlob',
2929
},
3030
{
3131
id: 8,
32-
title: 'Get Blob from Document',
33-
path: '/document/blob/getImage',
32+
title: 'Get Blob',
33+
path: '/document/blob/getBlob',
3434
},
3535
{
3636
id: 9,

expo-example/ios/expoexample/Info.plist

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@
5353
<array>
5454
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
5555
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
56+
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
57+
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
58+
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
59+
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
5660
</array>
5761
<key>UILaunchStoryboardName</key>
5862
<string>SplashScreen</string>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Collection } from 'cbl-reactnative';
2+
import { Buffer } from 'buffer';
3+
4+
export default async function getBlob(
5+
collection: Collection,
6+
documentId: string,
7+
key: string
8+
): Promise<string> {
9+
try {
10+
const doc = await collection.document(documentId);
11+
const blobText = await doc.getBlobContent(key, collection);
12+
if (blobText !== undefined && blobText !== null) {
13+
const text = Buffer.from(blobText).toString('utf-8');
14+
return text;
15+
}
16+
} catch (error) {
17+
// @ts-ignore
18+
return error.message;
19+
}
20+
return 'Error: Blob Content not found';
21+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Collection, MutableDocument, Document, Blob } from 'cbl-reactnative';
2+
import { Buffer } from 'buffer';
3+
4+
export default async function setBlob(
5+
collection: Collection,
6+
documentId: string,
7+
key: string,
8+
blobText: string
9+
): Promise<Document> {
10+
const bufferText = Buffer.from(blobText, 'base64');
11+
const blob = new Blob('text/plain', bufferText);
12+
const doc = await collection.document(documentId);
13+
const mutableDoc = MutableDocument.fromDocument(doc);
14+
mutableDoc.setBlob(key, blob);
15+
await collection.save(mutableDoc);
16+
return mutableDoc;
17+
}

ios/CblReactnative.mm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ @interface RCT_EXTERN_MODULE(CblReactnative, NSObject)
182182
withResolver:(RCTPromiseResolveBlock)resolve
183183
withRejecter:(RCTPromiseRejectBlock)reject)
184184

185+
// MARK: - SQL++ Query Functions
186+
187+
RCT_EXTERN_METHOD(database_GetPath:(NSString *)name
188+
withResolver:(RCTPromiseResolveBlock)resolve
189+
withRejecter:(RCTPromiseRejectBlock)reject)
185190

186191
// MARK: - Scope Functions
187192

0 commit comments

Comments
 (0)