gallery and ui flow for publishing
This commit is contained in:
parent
b58f2db030
commit
380e11218c
11 changed files with 417 additions and 40 deletions
54
app/package-lock.json
generated
54
app/package-lock.json
generated
|
@ -4404,13 +4404,11 @@
|
|||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
@ -4423,18 +4421,15 @@
|
|||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
@ -4537,8 +4532,7 @@
|
|||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
@ -4548,7 +4542,6 @@
|
|||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
@ -4561,20 +4554,17 @@
|
|||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
|
@ -4591,7 +4581,6 @@
|
|||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
|
@ -4664,8 +4653,7 @@
|
|||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
@ -4675,7 +4663,6 @@
|
|||
"once": {
|
||||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
@ -4781,7 +4768,6 @@
|
|||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
@ -5567,8 +5553,8 @@
|
|||
}
|
||||
},
|
||||
"lbry-redux": {
|
||||
"version": "github:lbryio/lbry-redux#a01b919c72139d82fa981df6be4e0fe902ff8f70",
|
||||
"from": "github:lbryio/lbry-redux",
|
||||
"version": "github:lbryio/lbry-redux#03998a2acf1a9e6c1b0818821612d137b31ebea3",
|
||||
"from": "github:lbryio/lbry-redux#03998a2acf1a9e6c1b0818821612d137b31ebea3",
|
||||
"requires": {
|
||||
"proxy-polyfill": "0.1.6",
|
||||
"reselect": "^3.0.0",
|
||||
|
@ -7690,6 +7676,15 @@
|
|||
"resolved": "https://registry.npmjs.org/react-native-fast-image/-/react-native-fast-image-5.4.2.tgz",
|
||||
"integrity": "sha512-S4E96Lwmx6z6QD3MaAuP7cNcXRLfgEUYU2GB694TbGEoOjk/FO1OnfbxfFp0vUs/klr4HJwACcwihPPxrFTt8w=="
|
||||
},
|
||||
"react-native-fs": {
|
||||
"version": "2.13.3",
|
||||
"resolved": "https://registry.npmjs.org/react-native-fs/-/react-native-fs-2.13.3.tgz",
|
||||
"integrity": "sha512-B62LSSAEYQGItg7KVTzTVVCxezOYFBYp4DMVFbdoZUd1mZVFdqR2sy1HY1mye1VI/Lf3IbxSyZEQ0GmrrdwLjg==",
|
||||
"requires": {
|
||||
"base-64": "^0.1.0",
|
||||
"utf8": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"react-native-gesture-handler": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-1.2.1.tgz",
|
||||
|
@ -7752,6 +7747,14 @@
|
|||
"prop-types": "^15.6.2"
|
||||
}
|
||||
},
|
||||
"react-native-super-grid": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/react-native-super-grid/-/react-native-super-grid-3.0.4.tgz",
|
||||
"integrity": "sha512-aoK71FGP5sFcLujuODYkAqyFDAZZRpvTeEwwaoXsc0JENhExEG7rGg65T5ELqyykiDOLBihuCLKasK5gLb0WtQ==",
|
||||
"requires": {
|
||||
"prop-types": "^15.6.0"
|
||||
}
|
||||
},
|
||||
"react-native-tab-view": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/react-native-tab-view/-/react-native-tab-view-1.4.1.tgz",
|
||||
|
@ -9548,6 +9551,11 @@
|
|||
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
|
||||
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
|
||||
},
|
||||
"utf8": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz",
|
||||
"integrity": "sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY="
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"dependencies": {
|
||||
"base-64": "^0.1.0",
|
||||
"@expo/vector-icons": "^8.1.0",
|
||||
"lbry-redux": "lbryio/lbry-redux",
|
||||
"lbry-redux": "lbryio/lbry-redux#03998a2acf1a9e6c1b0818821612d137b31ebea3",
|
||||
"lbryinc": "lbryio/lbryinc",
|
||||
"lodash": ">=4.17.11",
|
||||
"merge": ">=1.2.1",
|
||||
|
@ -21,6 +21,7 @@
|
|||
"react-native-country-picker-modal": "^0.6.2",
|
||||
"react-native-exception-handler": "2.9.0",
|
||||
"react-native-fast-image": "^5.0.3",
|
||||
"react-native-fs": "^2.13.3",
|
||||
"react-native-gesture-handler": "^1.1.0",
|
||||
"react-native-image-zoom-viewer": "^2.2.5",
|
||||
"react-native-password-strength-meter": "^0.0.2",
|
||||
|
|
|
@ -149,6 +149,12 @@ const drawer = createDrawerNavigator(
|
|||
drawerIcon: ({ tintColor }) => <Icon name="wallet" size={20} style={{ color: tintColor }} />,
|
||||
},
|
||||
},
|
||||
Publish: {
|
||||
screen: PublishPage,
|
||||
navigationOptions: {
|
||||
drawerIcon: ({ tintColor }) => <Icon name="upload" size={20} style={{ color: tintColor }} />,
|
||||
},
|
||||
},
|
||||
Rewards: {
|
||||
screen: RewardsPage,
|
||||
navigationOptions: {
|
||||
|
|
|
@ -11,6 +11,9 @@ const Constants = {
|
|||
PHASE_COLLECTION: 'collection',
|
||||
PHASE_VERIFICATION: 'verification',
|
||||
|
||||
PHASE_SELECTOR: 'selector',
|
||||
PHASE_DETAILS: 'details',
|
||||
|
||||
CONTENT_TAB: 'content',
|
||||
ABOUT_TAB: 'about',
|
||||
|
||||
|
|
|
@ -1,9 +1,40 @@
|
|||
import React from 'react';
|
||||
import { NativeModules, Text, View } from 'react-native';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Image,
|
||||
NativeModules,
|
||||
Picker,
|
||||
ScrollView,
|
||||
Switch,
|
||||
Text,
|
||||
TextInput,
|
||||
TouchableOpacity,
|
||||
View
|
||||
} from 'react-native';
|
||||
import { FlatGrid } from 'react-native-super-grid';
|
||||
import Button from 'component/button';
|
||||
import Colors from 'styles/colors';
|
||||
import Constants from 'constants';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import FloatingWalletBalance from 'component/floatingWalletBalance';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||
import Link from 'component/link';
|
||||
import UriBar from 'component/uriBar';
|
||||
import publishStyle from 'styles/reward';
|
||||
import publishStyle from 'styles/publish';
|
||||
|
||||
class PublishPage extends React.PureComponent {
|
||||
state = {
|
||||
thumbnailPath: null,
|
||||
videos: null,
|
||||
currentMedia: null,
|
||||
currentPhase: Constants.PHASE_SELECTOR,
|
||||
|
||||
// publish
|
||||
anonymous: true,
|
||||
channelName: null,
|
||||
priceFree: true,
|
||||
};
|
||||
|
||||
didFocusListener;
|
||||
|
||||
componentWillMount() {
|
||||
|
@ -22,8 +53,13 @@ class PublishPage extends React.PureComponent {
|
|||
|
||||
pushDrawerStack();
|
||||
setPlayerVisible();
|
||||
NativeModules.Gallery.getThumbnailPath().then(thumbnailPath => {
|
||||
if (thumbnailPath != null) {
|
||||
this.setState({ thumbnailPath });
|
||||
}
|
||||
});
|
||||
NativeModules.Gallery.getVideos().then(videos => {
|
||||
console.log(videos);
|
||||
this.setState({ videos });
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -40,12 +76,156 @@ class PublishPage extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
setCurrentMedia(media) {
|
||||
this.setState({ currentMedia: media, currentPhase: Constants.PHASE_DETAILS });
|
||||
}
|
||||
|
||||
showSelector() {
|
||||
this.setState({
|
||||
currentMedia: null,
|
||||
currentPhase: Constants.PHASE_SELECTOR,
|
||||
// reset publish state
|
||||
anonymous: true,
|
||||
channelName: null,
|
||||
priceFree: true
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { navigation } = this.props;
|
||||
const { thumbnailPath } = this.state;
|
||||
|
||||
let content;
|
||||
if (Constants.PHASE_SELECTOR === this.state.currentPhase) {
|
||||
content = (
|
||||
<View style={publishStyle.gallerySelector}>
|
||||
<View style={publishStyle.actionsView}>
|
||||
<View style={publishStyle.record}>
|
||||
<Icon name="video" size={48} color={Colors.White} />
|
||||
<Text style={publishStyle.actionText}>Record</Text>
|
||||
</View>
|
||||
<View style={publishStyle.subActions}>
|
||||
<View style={publishStyle.photo}>
|
||||
<Icon name="camera" size={48} color={Colors.White} />
|
||||
<Text style={publishStyle.actionText}>Take a photo</Text>
|
||||
</View>
|
||||
<View style={publishStyle.upload}>
|
||||
<Icon name="file-upload" size={48} color={Colors.White} />
|
||||
<Text style={publishStyle.actionText}>Upload a file</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
{(!this.state.videos || !thumbnailPath) &&
|
||||
<View style={publishStyle.loadingView}>
|
||||
<ActivityIndicator size='large' color={Colors.LbryGreen} />
|
||||
</View>
|
||||
}
|
||||
{(this.state.videos && thumbnailPath) &&
|
||||
<FlatGrid
|
||||
style={publishStyle.galleryGrid}
|
||||
itemDimension={134}
|
||||
spacing={2}
|
||||
items={this.state.videos}
|
||||
renderItem={({ item, index }) => {
|
||||
return (
|
||||
<TouchableOpacity key={index} onPress={() => this.setCurrentMedia(item)}>
|
||||
<FastImage
|
||||
style={publishStyle.galleryGridImage}
|
||||
resizeMode={FastImage.resizeMode.cover}
|
||||
source={{ uri: `file://${thumbnailPath}/${item.id}.png` }} />
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}}
|
||||
/>}
|
||||
</View>
|
||||
);
|
||||
} else if (Constants.PHASE_DETAILS === this.state.currentPhase && this.state.currentMedia) {
|
||||
const { currentMedia } = this.state;
|
||||
content = (
|
||||
<ScrollView style={publishStyle.publishDetails}>
|
||||
<View style={publishStyle.mainThumbnailContainer}>
|
||||
<FastImage
|
||||
style={publishStyle.mainThumbnail}
|
||||
resizeMode={FastImage.resizeMode.contain}
|
||||
source={{ uri: `file://${thumbnailPath}/${currentMedia.id}.png` }}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={publishStyle.card}>
|
||||
<TextInput
|
||||
placeholder={"Title"}
|
||||
style={publishStyle.inputText}
|
||||
value={currentMedia.name}
|
||||
numberOfLines={1}
|
||||
underlineColorAndroid={Colors.NextLbryGreen} />
|
||||
<TextInput
|
||||
placeholder={"Description"}
|
||||
style={publishStyle.inputText}
|
||||
underlineColorAndroid={Colors.NextLbryGreen} />
|
||||
</View>
|
||||
|
||||
<View style={publishStyle.card}>
|
||||
<Text style={publishStyle.cardTitle}>Price</Text>
|
||||
|
||||
<View style={publishStyle.cardRow}>
|
||||
<View style={publishStyle.switchRow}>
|
||||
<Switch value={this.state.priceFree} onValueChange={value => this.setState({ priceFree: value }) } />
|
||||
<Text style={publishStyle.switchText}>Free</Text>
|
||||
</View>
|
||||
|
||||
{!this.state.priceFree &&
|
||||
<View style={[publishStyle.inputRow, publishStyle.priceInputRow]}>
|
||||
<TextInput placeholder={"0.00"} style={publishStyle.priceInput} underlineColorAndroid={Colors.NextLbryGreen} numberOfLines={1} />
|
||||
<Text style={publishStyle.currency}>LBC</Text>
|
||||
</View>}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={publishStyle.card}>
|
||||
<Text style={publishStyle.cardTitle}>Publish anonymously or as a channel?</Text>
|
||||
<View style={publishStyle.cardRow}>
|
||||
<View style={publishStyle.switchRow}>
|
||||
<Switch value={this.state.anonymous} onValueChange={value => this.setState({ anonymous: value }) } />
|
||||
<Text style={publishStyle.switchText}>Anonymous</Text>
|
||||
</View>
|
||||
|
||||
{!this.state.anonymous &&
|
||||
<Picker
|
||||
selectedValue={this.state.channelName}
|
||||
style={publishStyle.channelPicker}
|
||||
onValueChange={(itemValue, itemIndex) =>
|
||||
this.setState({channelName: itemValue})
|
||||
}>
|
||||
<Picker.Item label="Select..." value={null} />
|
||||
</Picker>}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={publishStyle.card}>
|
||||
<Text style={publishStyle.cardTitle}>Where can people find this content?</Text>
|
||||
<Text style={publishStyle.helpText}>The LBRY URL is the exact address where people can find your content (ex. lbry://myvideo)</Text>
|
||||
|
||||
<TextInput placeholder={"lbry://"} style={publishStyle.inputText} underlineColorAndroid={Colors.NextLbryGreen} numberOfLines={1} />
|
||||
<View style={publishStyle.inputRow}>
|
||||
<TextInput placeholder={"0.00"} style={publishStyle.priceInput} underlineColorAndroid={Colors.NextLbryGreen} numberOfLines={1} />
|
||||
<Text style={publishStyle.currency}>LBC</Text>
|
||||
</View>
|
||||
<Text style={publishStyle.helpText}>This LBC remains yours and the deposit can be undone at any time.</Text>
|
||||
</View>
|
||||
|
||||
<View style={publishStyle.actionButtons}>
|
||||
<Link style={publishStyle.cancelLink} text="Cancel" onPress={() => this.setState({ currentPhase: Constants.PHASE_SELECTOR })} />
|
||||
<Button style={publishStyle.publishButton} text="Publish" />
|
||||
</View>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={publishStyle.container}>
|
||||
<UriBar navigation={navigation} />
|
||||
{content}
|
||||
{(false && Constants.PHASE_SELECTOR !== this.state.currentPhase) && <FloatingWalletBalance navigation={navigation} />}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ const Colors = {
|
|||
|
||||
Black: '#000000',
|
||||
ChannelGrey: '#9b9b9b',
|
||||
DarkerGrey: '#222222',
|
||||
DarkGrey: '#555555',
|
||||
DescriptionGrey: '#999999',
|
||||
LbryGreen: '#2f9176',
|
||||
|
|
|
@ -6,6 +6,130 @@ const publishStyle = StyleSheet.create({
|
|||
flex: 1,
|
||||
backgroundColor: Colors.PageBackground,
|
||||
},
|
||||
gallerySelector: {
|
||||
flex: 1,
|
||||
marginTop: 62,
|
||||
paddingTop: 2,
|
||||
backgroundColor: Colors.DarkGrey
|
||||
},
|
||||
galleryGrid: {
|
||||
flex: 1
|
||||
},
|
||||
galleryGridImage: {
|
||||
width: 134,
|
||||
height: 90
|
||||
},
|
||||
inputText: {
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
fontSize: 16
|
||||
},
|
||||
card: {
|
||||
backgroundColor: Colors.White,
|
||||
marginTop: 16,
|
||||
marginLeft: 16,
|
||||
marginRight: 16,
|
||||
padding: 16,
|
||||
},
|
||||
actionButtons: {
|
||||
margin: 16,
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between'
|
||||
},
|
||||
publishButton: {
|
||||
backgroundColor: Colors.LbryGreen,
|
||||
alignSelf: 'flex-end'
|
||||
},
|
||||
cardTitle: {
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
fontSize: 20,
|
||||
marginBottom: 8
|
||||
},
|
||||
actionsView: {
|
||||
flexDirection: 'row',
|
||||
width: '100%',
|
||||
height: 240,
|
||||
},
|
||||
record: {
|
||||
backgroundColor: Colors.Black,
|
||||
flex: 0.5,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
},
|
||||
subActions: {
|
||||
flex: 0.5,
|
||||
borderLeftWidth: 2,
|
||||
borderLeftColor: Colors.DarkerGrey
|
||||
},
|
||||
actionText: {
|
||||
color: Colors.White,
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
fontSize: 14,
|
||||
marginTop: 8
|
||||
},
|
||||
photo: {
|
||||
backgroundColor: Colors.Black,
|
||||
height: 120,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
},
|
||||
upload: {
|
||||
backgroundColor: Colors.Black,
|
||||
height: 120,
|
||||
borderTopWidth: 2,
|
||||
borderTopColor: Colors.DarkerGrey,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
},
|
||||
publishDetails: {
|
||||
marginTop: 60
|
||||
},
|
||||
mainThumbnailContainer: {
|
||||
backgroundColor: Colors.Black,
|
||||
width: '100%',
|
||||
height: 240
|
||||
},
|
||||
mainThumbnail: {
|
||||
height: 240
|
||||
},
|
||||
inputRow: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center'
|
||||
},
|
||||
priceInput: {
|
||||
width: 80,
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
fontSize: 16
|
||||
},
|
||||
currency: {
|
||||
fontFamily: 'Inter-UI-Regular'
|
||||
},
|
||||
cardRow: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center'
|
||||
},
|
||||
switchRow: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
height: 52
|
||||
},
|
||||
switchText: {
|
||||
marginLeft: 6,
|
||||
fontSize: 16
|
||||
},
|
||||
channelPicker: {
|
||||
height: 52,
|
||||
width: 160
|
||||
},
|
||||
loadingView: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}
|
||||
});
|
||||
|
||||
export default publishStyle;
|
||||
|
|
|
@ -102,6 +102,7 @@ dependencies {
|
|||
compile project(':@react-native-community_async-storage')
|
||||
compile project(':react-native-exception-handler')
|
||||
compile project(':react-native-fast-image')
|
||||
compile project(':react-native-fs')
|
||||
compile project(':react-native-gesture-handler')
|
||||
compile project(':react-native-video')
|
||||
compile project(':rn-fetch-blob')
|
||||
|
|
|
@ -5,6 +5,8 @@ include ':react-native-exception-handler'
|
|||
project(':react-native-exception-handler').projectDir = new File(rootProject.projectDir, './react/node_modules/react-native-exception-handler/android')
|
||||
include ':react-native-fast-image'
|
||||
project(':react-native-fast-image').projectDir = new File(rootProject.projectDir, './react/node_modules/react-native-fast-image/android')
|
||||
include ':react-native-fs'
|
||||
project(':react-native-fs').projectDir = new File(settingsDir, './react/node_modules/react-native-fs/android')
|
||||
include ':react-native-gesture-handler'
|
||||
project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, './react/node_modules/react-native-gesture-handler/android')
|
||||
include ':react-native-video'
|
||||
|
|
|
@ -34,6 +34,7 @@ import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|||
import com.facebook.react.shell.MainReactPackage;
|
||||
import com.facebook.react.ReactRootView;
|
||||
import com.reactnativecommunity.asyncstorage.AsyncStoragePackage;
|
||||
import com.rnfs.RNFSPackage;
|
||||
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
|
||||
import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
|
||||
import com.RNFetchBlob.RNFetchBlobPackage;
|
||||
|
@ -141,6 +142,7 @@ public class MainActivity extends Activity implements DefaultHardwareBackBtnHand
|
|||
.addPackage(new FastImageViewPackage())
|
||||
.addPackage(new ReactVideoPackage())
|
||||
.addPackage(new RNFetchBlobPackage())
|
||||
.addPackage(new RNFSPackage())
|
||||
.addPackage(new RNGestureHandlerPackage())
|
||||
.addPackage(new LbryReactPackage())
|
||||
.setUseDeveloperSupport(true)
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
package io.lbry.browser.reactmodules;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.ContentResolver;
|
||||
import android.database.Cursor;
|
||||
import android.provider.MediaStore;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.provider.MediaStore;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.Promise;
|
||||
|
@ -13,6 +17,9 @@ import com.facebook.react.bridge.ReactMethod;
|
|||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
@ -40,6 +47,18 @@ public class GalleryModule extends ReactContextBaseJavaModule {
|
|||
promise.resolve(items);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void getThumbnailPath(Promise promise) {
|
||||
if (context != null) {
|
||||
File cacheDir = context.getExternalCacheDir();
|
||||
String thumbnailPath = String.format("%s/thumbnails", cacheDir.getAbsolutePath());
|
||||
promise.resolve(thumbnailPath);
|
||||
return;
|
||||
}
|
||||
|
||||
promise.resolve(null);
|
||||
}
|
||||
|
||||
private List<GalleryItem> loadVideos() {
|
||||
String[] projection = {
|
||||
MediaStore.MediaColumns._ID,
|
||||
|
@ -49,6 +68,7 @@ public class GalleryModule extends ReactContextBaseJavaModule {
|
|||
MediaStore.Video.Media.DURATION
|
||||
};
|
||||
|
||||
List<String> ids = new ArrayList<String>();
|
||||
List<GalleryItem> items = new ArrayList<GalleryItem>();
|
||||
Cursor cursor = context.getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projection, null, null, null);
|
||||
while (cursor.moveToNext()) {
|
||||
|
@ -58,17 +78,57 @@ public class GalleryModule extends ReactContextBaseJavaModule {
|
|||
int pathColumn = cursor.getColumnIndex(MediaStore.MediaColumns.DATA);
|
||||
int durationColumn = cursor.getColumnIndex(MediaStore.Video.Media.DURATION);
|
||||
|
||||
String id = cursor.getString(idColumn);
|
||||
GalleryItem item = new GalleryItem();
|
||||
item.setId(cursor.getString(idColumn));
|
||||
item.setId(id);
|
||||
item.setName(cursor.getString(nameColumn));
|
||||
item.setType(cursor.getString(typeColumn));
|
||||
item.setFilePath(cursor.getString(pathColumn));
|
||||
items.add(item);
|
||||
ids.add(id);
|
||||
}
|
||||
|
||||
checkThumbnails(ids);
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
private void checkThumbnails(final List<String> ids) {
|
||||
(new AsyncTask<Void, Void, Void>() {
|
||||
protected Void doInBackground(Void... param) {
|
||||
if (context != null) {
|
||||
ContentResolver resolver = context.getContentResolver();
|
||||
for (int i = 0; i < ids.size(); i++) {
|
||||
String id = ids.get(i);
|
||||
File cacheDir = context.getExternalCacheDir();
|
||||
File thumbnailsDir = new File(String.format("%s/thumbnails", cacheDir.getAbsolutePath()));
|
||||
if (!thumbnailsDir.isDirectory()) {
|
||||
thumbnailsDir.mkdirs();
|
||||
}
|
||||
|
||||
String thumbnailPath = String.format("%s/%s.png", thumbnailsDir.getAbsolutePath(), id);
|
||||
File file = new File(thumbnailPath);
|
||||
if (!file.exists()) {
|
||||
// save the thumbnail to the path
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inSampleSize = 1;
|
||||
Bitmap thumbnail = MediaStore.Video.Thumbnails.getThumbnail(
|
||||
resolver, Long.parseLong(id), MediaStore.Video.Thumbnails.MINI_KIND, options);
|
||||
if (thumbnail != null) {
|
||||
try (FileOutputStream os = new FileOutputStream(thumbnailPath)) {
|
||||
thumbnail.compress(Bitmap.CompressFormat.PNG, 80, os);
|
||||
} catch (IOException ex) {
|
||||
// skip
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
private static class GalleryItem {
|
||||
private String id;
|
||||
|
@ -79,8 +139,6 @@ public class GalleryModule extends ReactContextBaseJavaModule {
|
|||
|
||||
private String name;
|
||||
|
||||
private String thumbnailUri;
|
||||
|
||||
private String type;
|
||||
|
||||
public String getId() {
|
||||
|
@ -115,14 +173,6 @@ public class GalleryModule extends ReactContextBaseJavaModule {
|
|||
this.name = name;
|
||||
}
|
||||
|
||||
public String getThumbnailUri() {
|
||||
return thumbnailUri;
|
||||
}
|
||||
|
||||
public void setThumnbailUri(String thumbnailUri) {
|
||||
this.thumbnailUri = thumbnailUri;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
@ -137,7 +187,6 @@ public class GalleryModule extends ReactContextBaseJavaModule {
|
|||
map.putString("name", name);
|
||||
map.putString("filePath", filePath);
|
||||
map.putString("type", type);
|
||||
map.putString("thumbnailUri", thumbnailUri);
|
||||
map.putInt("duration", duration);
|
||||
|
||||
return map;
|
||||
|
|
Loading…
Add table
Reference in a new issue