feat: Added download and loading
This commit is contained in:
parent
ed47ff673f
commit
4250284f1b
@ -285,6 +285,8 @@ dependencies {
|
||||
} else {
|
||||
implementation jscFlavor
|
||||
}
|
||||
|
||||
implementation project(':react-native-fs')
|
||||
}
|
||||
|
||||
if (isNewArchitectureEnabled()) {
|
||||
|
@ -2,6 +2,8 @@
|
||||
package="com.browses3">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:name=".MainApplication"
|
||||
@ -9,7 +11,8 @@
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:allowBackup="false"
|
||||
android:theme="@style/AppTheme">
|
||||
android:theme="@style/AppTheme"
|
||||
android:requestLegacyExternalStorage="true">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
|
@ -2,6 +2,8 @@ rootProject.name = 'BrowseS3'
|
||||
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
|
||||
include ':app'
|
||||
includeBuild('../node_modules/react-native-gradle-plugin')
|
||||
include ':react-native-fs'
|
||||
project(':react-native-fs').projectDir = new File(settingsDir, '../node_modules/react-native-fs/android')
|
||||
|
||||
if (settings.hasProperty("newArchEnabled") && settings.newArchEnabled == "true") {
|
||||
include(":ReactAndroid")
|
||||
|
90
package-lock.json
generated
90
package-lock.json
generated
@ -17,10 +17,10 @@
|
||||
"pretty-bytes": "^6.0.0",
|
||||
"react": "18.0.0",
|
||||
"react-native": "0.69.1",
|
||||
"react-native-fs": "^2.20.0",
|
||||
"react-native-keyboard-aware-scroll-view": "^0.9.5",
|
||||
"react-native-safe-area-context": "^4.3.1",
|
||||
"react-native-screens": "^3.14.0",
|
||||
"rn-fetch-blob": "^0.12.0"
|
||||
"react-native-screens": "^3.14.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.9",
|
||||
@ -12840,6 +12840,24 @@
|
||||
"nullthrows": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-fs": {
|
||||
"version": "2.20.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-fs/-/react-native-fs-2.20.0.tgz",
|
||||
"integrity": "sha512-VkTBzs7fIDUiy/XajOSNk0XazFE9l+QlMAce7lGuebZcag5CnjszB+u4BdqzwaQOdcYb5wsJIsqq4kxInIRpJQ==",
|
||||
"dependencies": {
|
||||
"base-64": "^0.1.0",
|
||||
"utf8": "^3.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react-native": "*",
|
||||
"react-native-windows": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react-native-windows": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-gradle-plugin": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/react-native-gradle-plugin/-/react-native-gradle-plugin-0.0.7.tgz",
|
||||
@ -13278,31 +13296,6 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/rn-fetch-blob": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/rn-fetch-blob/-/rn-fetch-blob-0.12.0.tgz",
|
||||
"integrity": "sha512-+QnR7AsJ14zqpVVUbzbtAjq0iI8c9tCg49tIoKO2ezjzRunN7YL6zFSFSWZm6d+mE/l9r+OeDM3jmb2tBb2WbA==",
|
||||
"dependencies": {
|
||||
"base-64": "0.1.0",
|
||||
"glob": "7.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/rn-fetch-blob/node_modules/glob": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
|
||||
"integrity": "sha512-f8c0rE8JiCxpa52kWPAOa3ZaYEnzofDzCQLCn3Vdk0Z5OVLq3BsRFJI4S4ykpeVW6QMGBUkMeUpoEgWnMTnw5Q==",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.2",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/rsvp": {
|
||||
"version": "4.8.5",
|
||||
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
|
||||
@ -15196,6 +15189,11 @@
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/utf8": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz",
|
||||
"integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ=="
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
@ -25180,6 +25178,15 @@
|
||||
"nullthrows": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"react-native-fs": {
|
||||
"version": "2.20.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-fs/-/react-native-fs-2.20.0.tgz",
|
||||
"integrity": "sha512-VkTBzs7fIDUiy/XajOSNk0XazFE9l+QlMAce7lGuebZcag5CnjszB+u4BdqzwaQOdcYb5wsJIsqq4kxInIRpJQ==",
|
||||
"requires": {
|
||||
"base-64": "^0.1.0",
|
||||
"utf8": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"react-native-gradle-plugin": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/react-native-gradle-plugin/-/react-native-gradle-plugin-0.0.7.tgz",
|
||||
@ -25503,30 +25510,6 @@
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
},
|
||||
"rn-fetch-blob": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/rn-fetch-blob/-/rn-fetch-blob-0.12.0.tgz",
|
||||
"integrity": "sha512-+QnR7AsJ14zqpVVUbzbtAjq0iI8c9tCg49tIoKO2ezjzRunN7YL6zFSFSWZm6d+mE/l9r+OeDM3jmb2tBb2WbA==",
|
||||
"requires": {
|
||||
"base-64": "0.1.0",
|
||||
"glob": "7.0.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"glob": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
|
||||
"integrity": "sha512-f8c0rE8JiCxpa52kWPAOa3ZaYEnzofDzCQLCn3Vdk0Z5OVLq3BsRFJI4S4ykpeVW6QMGBUkMeUpoEgWnMTnw5Q==",
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.2",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"rsvp": {
|
||||
"version": "4.8.5",
|
||||
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
|
||||
@ -27019,6 +27002,11 @@
|
||||
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
|
||||
"requires": {}
|
||||
},
|
||||
"utf8": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz",
|
||||
"integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ=="
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
|
@ -19,10 +19,10 @@
|
||||
"pretty-bytes": "^6.0.0",
|
||||
"react": "18.0.0",
|
||||
"react-native": "0.69.1",
|
||||
"react-native-fs": "^2.20.0",
|
||||
"react-native-keyboard-aware-scroll-view": "^0.9.5",
|
||||
"react-native-safe-area-context": "^4.3.1",
|
||||
"react-native-screens": "^3.14.0",
|
||||
"rn-fetch-blob": "^0.12.0"
|
||||
"react-native-screens": "^3.14.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.9",
|
||||
|
@ -41,7 +41,6 @@ const useSettings = () => {
|
||||
ToastAndroid.show('Successfully saved settings', ToastAndroid.SHORT);
|
||||
})
|
||||
.catch(e => {
|
||||
console.log(e);
|
||||
ToastAndroid.show('Failed to save settings', ToastAndroid.SHORT);
|
||||
throw e;
|
||||
});
|
||||
|
@ -1,11 +1,12 @@
|
||||
import React, {useState, useEffect} from 'react';
|
||||
import {ScrollView, ToastAndroid} from 'react-native';
|
||||
import {ScrollView, ToastAndroid, Text} from 'react-native';
|
||||
import useS3 from '../hooks/useS3';
|
||||
import Bucket from '../components/Bucket';
|
||||
|
||||
const Buckets = () => {
|
||||
const s3 = useS3();
|
||||
const [buckets, setBuckets] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
if (s3 && !buckets.length) {
|
||||
@ -16,10 +17,15 @@ const Buckets = () => {
|
||||
}
|
||||
|
||||
setBuckets(data.Buckets);
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
}, [s3]);
|
||||
|
||||
if (loading) {
|
||||
return <Text>Loading...</Text>;
|
||||
}
|
||||
|
||||
return (
|
||||
<ScrollView>
|
||||
{buckets.map(bucket => (
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, {useState, useEffect} from 'react';
|
||||
import {ScrollView, ToastAndroid} from 'react-native';
|
||||
import {ScrollView, ToastAndroid, Text} from 'react-native';
|
||||
import {useRoute} from '@react-navigation/native';
|
||||
import useS3 from '../hooks/useS3';
|
||||
import Directory from '../components/Directory';
|
||||
@ -9,6 +9,7 @@ const DirectoryDetails = () => {
|
||||
const route = useRoute();
|
||||
const s3 = useS3();
|
||||
const [contents, setContents] = useState({dirs: [], files: []});
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
if (s3 && !contents.length) {
|
||||
@ -29,11 +30,16 @@ const DirectoryDetails = () => {
|
||||
}
|
||||
|
||||
setContents({dirs: data.CommonPrefixes, files: data.Contents});
|
||||
setLoading(false);
|
||||
},
|
||||
);
|
||||
}
|
||||
}, [s3]);
|
||||
|
||||
if (loading) {
|
||||
return <Text>Loading...</Text>;
|
||||
}
|
||||
|
||||
return (
|
||||
<ScrollView>
|
||||
{contents.dirs.map(dir => (
|
||||
|
@ -1,14 +1,16 @@
|
||||
import React, {useState, useEffect} from 'react';
|
||||
import React, {useState, useEffect, useCallback} from 'react';
|
||||
import {
|
||||
StyleSheet,
|
||||
ScrollView,
|
||||
Text,
|
||||
View,
|
||||
Button,
|
||||
ToastAndroid,
|
||||
PermissionsAndroid,
|
||||
} from 'react-native';
|
||||
import {useRoute} from '@react-navigation/native';
|
||||
import prettyBytes from 'pretty-bytes';
|
||||
import RNFS from 'react-native-fs';
|
||||
import useS3 from '../hooks/useS3';
|
||||
|
||||
const FileDetails = () => {
|
||||
@ -18,10 +20,10 @@ const FileDetails = () => {
|
||||
|
||||
useEffect(() => {
|
||||
if (s3 && !data) {
|
||||
s3.getObject(
|
||||
s3.headObject(
|
||||
{
|
||||
Bucket: route.params.bucket,
|
||||
Key: route.params.file
|
||||
Key: route.params.file,
|
||||
},
|
||||
(err, data) => {
|
||||
if (err) {
|
||||
@ -35,6 +37,66 @@ const FileDetails = () => {
|
||||
}
|
||||
}, [s3]);
|
||||
|
||||
const download = useCallback(() => {
|
||||
PermissionsAndroid.request(
|
||||
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
|
||||
)
|
||||
.then(granted => {
|
||||
if (granted != PermissionsAndroid.RESULTS.GRANTED) {
|
||||
throw new Error('No permission');
|
||||
}
|
||||
})
|
||||
.then(() =>
|
||||
PermissionsAndroid.request(
|
||||
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
|
||||
),
|
||||
)
|
||||
.then(granted => {
|
||||
if (granted != PermissionsAndroid.RESULTS.GRANTED) {
|
||||
throw new Error('No permission');
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
ToastAndroid.show('Downloading...', ToastAndroid.LONG);
|
||||
|
||||
s3.getObject(
|
||||
{
|
||||
Bucket: route.params.bucket,
|
||||
Key: route.params.file,
|
||||
},
|
||||
(err, data) => {
|
||||
if (err) {
|
||||
ToastAndroid.show('Failed to download file', ToastAndroid.SHORT);
|
||||
return;
|
||||
}
|
||||
|
||||
const dir = `${RNFS.DownloadDirectoryPath}/BrowseS3/${route.params.bucket}`;
|
||||
const file = `${dir}/${route.params.file.replace(/\//g, '_')}`;
|
||||
const fileContents = data.Body.toString('base64');
|
||||
|
||||
RNFS.mkdir(dir)
|
||||
.then(() => RNFS.writeFile(file, fileContents, 'base64'))
|
||||
.then(() => RNFS.scanFile(file))
|
||||
.then(() => {
|
||||
ToastAndroid.show('Download completed', ToastAndroid.SHORT);
|
||||
})
|
||||
.catch(e => {
|
||||
ToastAndroid.show(
|
||||
'Failed to download file',
|
||||
ToastAndroid.SHORT,
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
})
|
||||
.catch(() => {
|
||||
ToastAndroid.show(
|
||||
'You need to grant the write permission to download files',
|
||||
ToastAndroid.SHORT,
|
||||
);
|
||||
});
|
||||
}, [s3, route]);
|
||||
|
||||
if (!data) {
|
||||
return <Text>Loading...</Text>;
|
||||
}
|
||||
@ -48,6 +110,9 @@ const FileDetails = () => {
|
||||
</Text>
|
||||
<Text style={styles.info}>Size: {prettyBytes(data.ContentLength)}</Text>
|
||||
<Text style={styles.info}>Content type: {data.ContentType}</Text>
|
||||
<View style={styles.download}>
|
||||
<Button onPress={download} title="Download" />
|
||||
</View>
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
@ -21,7 +21,6 @@ const SignUp = () => {
|
||||
|
||||
signUp(email, pass)
|
||||
.then(() => {
|
||||
console.log('asdasd');
|
||||
navigation.reset({index: 0, routes: [{name: 'Buckets'}]});
|
||||
})
|
||||
.catch(() => {});
|
||||
|
Loading…
Reference in New Issue
Block a user