From 5ea750599d08229d4b5b10d0e724ca14c73735f5 Mon Sep 17 00:00:00 2001 From: João Ferreiro Date: Mon, 28 Nov 2022 16:46:58 +0000 Subject: upload images in composer v1 --- src/state/models/user-local-photos.ts | 25 +++++ src/view/com/composer/ComposePost.tsx | 181 +++++++++++++++++++++++++++++++++- src/view/index.ts | 6 ++ 3 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 src/state/models/user-local-photos.ts (limited to 'src') diff --git a/src/state/models/user-local-photos.ts b/src/state/models/user-local-photos.ts new file mode 100644 index 000000000..4e01f1d94 --- /dev/null +++ b/src/state/models/user-local-photos.ts @@ -0,0 +1,25 @@ +import {PhotoIdentifier} from './../../../node_modules/@react-native-camera-roll/camera-roll/src/CameraRoll' +import {makeAutoObservable} from 'mobx' +import {CameraRoll} from '@react-native-camera-roll/camera-roll' +import {RootStoreModel} from './root-store' + +export class UserLocalPhotosModel { + // state + photos: PhotoIdentifier[] = [] + + constructor(public rootStore: RootStoreModel) { + makeAutoObservable(this, { + rootStore: false, + }) + } + + async setup() { + await this._getPhotos() + } + + private async _getPhotos() { + CameraRoll.getPhotos({first: 20}).then(r => { + this.photos = r.edges + }) + } +} diff --git a/src/view/com/composer/ComposePost.tsx b/src/view/com/composer/ComposePost.tsx index bb175f166..10305adb6 100644 --- a/src/view/com/composer/ComposePost.tsx +++ b/src/view/com/composer/ComposePost.tsx @@ -9,10 +9,13 @@ import { TextInput, TouchableOpacity, View, + ScrollView, + Image, } from 'react-native' import LinearGradient from 'react-native-linear-gradient' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {UserAutocompleteViewModel} from '../../../state/models/user-autocomplete-view' +import {UserLocalPhotosModel} from '../../../state/models/user-local-photos' import {Autocomplete} from './Autocomplete' import Toast from '../util/Toast' import ProgressCircle from '../util/ProgressCircle' @@ -22,6 +25,7 @@ import * as apilib from '../../../state/lib/api' import {ComposerOpts} from '../../../state/models/shell-ui' import {s, colors, gradients} from '../../lib/styles' import {detectLinkables} from '../../../lib/strings' +import {openPicker, openCamera} from 'react-native-image-crop-picker' const MAX_TEXT_LENGTH = 256 const WARNING_TEXT_LENGTH = 200 @@ -40,15 +44,24 @@ export const ComposePost = observer(function ComposePost({ const [isProcessing, setIsProcessing] = useState(false) const [error, setError] = useState('') const [text, setText] = useState('') + const [photoUris, setPhotoUris] = useState([]) const autocompleteView = useMemo( () => new UserAutocompleteViewModel(store), [], ) + const localPhotos = useMemo( + () => new UserLocalPhotosModel(store), + [], + ) useEffect(() => { autocompleteView.setup() }) + useEffect(() => { + localPhotos.setup() + }, []) + const onChangeText = (newText: string) => { setText(newText) @@ -183,12 +196,109 @@ export const ComposePost = observer(function ComposePost({ multiline scrollEnabled onChangeText={(text: string) => onChangeText(text)} - placeholder={replyTo ? 'Write your reply' : "What's up?"} + placeholder={ + replyTo + ? 'Write your reply' + : photoUris.length === 0 + ? "What's up?" + : 'Add a comment...' + } style={styles.textInput}> {textDecorated} - + {photoUris.length !== 0 && ( + + {photoUris.length !== 0 && + photoUris.map(item => ( + + { + setPhotoUris( + photoUris.filter(filterItem => filterItem !== item), + ) + }} + style={styles.removePhotoButton}> + + + + + + ))} + + )} + {localPhotos.photos != null && text === '' && photoUris.length === 0 && ( + + { + openCamera({multiple: true, maxFiles: 4}).then() + }}> + + + {localPhotos.photos.map(item => ( + { + setPhotoUris([item.node.image.uri, ...photoUris]) + }}> + + + ))} + { + openPicker({multiple: true, maxFiles: 4}).then(items => { + setPhotoUris([ + ...items.reduce( + (accum, cur) => accum.concat(cur.sourceURL!), + [] as string[], + ), + ...photoUris, + ]) + }) + }}> + + + + )} + + {MAX_TEXT_LENGTH - text.length} @@ -275,4 +385,69 @@ const styles = StyleSheet.create({ marginTop: 5, marginBottom: 10, }, + contentCenter: {alignItems: 'center'}, + selectedImageContainer: { + flex: 10, + flexDirection: 'row', + }, + selectedImage: { + borderRadius: 8, + margin: 2, + }, + selectedImage250: { + width: 250, + height: 250, + }, + selectedImage175: { + width: 175, + height: 175, + }, + selectedImage85: { + width: 85, + height: 85, + }, + photosContainer: { + width: '100%', + maxHeight: 96, + padding: 8, + overflow: 'hidden', + }, + removePhotoButton: { + position: 'absolute', + top: 8, + right: 8, + width: 24, + height: 24, + borderRadius: 12, + alignItems: 'center', + justifyContent: 'center', + backgroundColor: colors.black, + zIndex: 1, + }, + galleryButton: { + borderWidth: 1, + borderColor: colors.gray3, + alignItems: 'center', + justifyContent: 'center', + }, + photoButton: { + width: 75, + height: 75, + marginRight: 8, + borderWidth: 1, + borderRadius: 16, + borderColor: colors.gray3, + }, + photo: { + width: 75, + height: 75, + marginRight: 8, + borderRadius: 16, + }, + separator: { + borderBottomColor: 'black', + borderBottomWidth: StyleSheet.hairlineWidth, + width: '110%', + marginLeft: -16, + }, }) diff --git a/src/view/index.ts b/src/view/index.ts index e38e1debf..bd0e33cbe 100644 --- a/src/view/index.ts +++ b/src/view/index.ts @@ -56,6 +56,9 @@ import {faUserXmark} from '@fortawesome/free-solid-svg-icons/faUserXmark' import {faTicket} from '@fortawesome/free-solid-svg-icons/faTicket' import {faTrashCan} from '@fortawesome/free-regular-svg-icons/faTrashCan' import {faX} from '@fortawesome/free-solid-svg-icons/faX' +import {faCamera} from '@fortawesome/free-solid-svg-icons/faCamera' +import {faImage} from '@fortawesome/free-solid-svg-icons/faImage' +import {faXmark} from '@fortawesome/free-solid-svg-icons/faXmark' export function setup() { library.add( @@ -115,5 +118,8 @@ export function setup() { faTicket, faTrashCan, faX, + faCamera, + faImage, + faXmark, ) } -- cgit 1.4.1