Implement Web versions of the bottom sheet, toast, and progress circle
This commit is contained in:
parent
af55a89758
commit
041bfa22a9
19 changed files with 295 additions and 92 deletions
113
src/view/com/modals/SharePost.native.tsx
Normal file
113
src/view/com/modals/SharePost.native.tsx
Normal file
|
@ -0,0 +1,113 @@
|
|||
import React, {
|
||||
forwardRef,
|
||||
useState,
|
||||
useMemo,
|
||||
useImperativeHandle,
|
||||
useRef,
|
||||
} from 'react'
|
||||
import {
|
||||
Button,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
TouchableWithoutFeedback,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import BottomSheet, {BottomSheetBackdropProps} from '@gorhom/bottom-sheet'
|
||||
import Animated, {
|
||||
Extrapolate,
|
||||
interpolate,
|
||||
useAnimatedStyle,
|
||||
} from 'react-native-reanimated'
|
||||
import Toast from '../util/Toast'
|
||||
import Clipboard from '@react-native-clipboard/clipboard'
|
||||
import {s} from '../../lib/styles'
|
||||
|
||||
export const ShareModal = forwardRef(function ShareModal({}: {}, ref) {
|
||||
const [isOpen, setIsOpen] = useState<boolean>(false)
|
||||
const [uri, setUri] = useState<string>('')
|
||||
const bottomSheetRef = useRef<BottomSheet>(null)
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
open(uri: string) {
|
||||
console.log('sharing', uri)
|
||||
setUri(uri)
|
||||
setIsOpen(true)
|
||||
},
|
||||
}))
|
||||
|
||||
const onPressCopy = () => {
|
||||
Clipboard.setString(uri)
|
||||
console.log('showing')
|
||||
console.log(Toast)
|
||||
console.log(Toast.show)
|
||||
Toast.show('Link copied', {
|
||||
position: Toast.positions.TOP,
|
||||
})
|
||||
}
|
||||
const onShareBottomSheetChange = (snapPoint: number) => {
|
||||
if (snapPoint === -1) {
|
||||
console.log('unsharing')
|
||||
setIsOpen(false)
|
||||
}
|
||||
}
|
||||
const onClose = () => {
|
||||
bottomSheetRef.current?.close()
|
||||
}
|
||||
|
||||
const CustomBackdrop = ({animatedIndex, style}: BottomSheetBackdropProps) => {
|
||||
// animated variables
|
||||
const opacity = useAnimatedStyle(() => ({
|
||||
opacity: interpolate(
|
||||
animatedIndex.value, // current snap index
|
||||
[-1, 0], // input range
|
||||
[0, 0.5], // output range
|
||||
Extrapolate.CLAMP,
|
||||
),
|
||||
}))
|
||||
|
||||
const containerStyle = useMemo(
|
||||
() => [style, {backgroundColor: '#000'}, opacity],
|
||||
[style, opacity],
|
||||
)
|
||||
|
||||
return (
|
||||
<TouchableWithoutFeedback onPress={onClose}>
|
||||
<Animated.View style={containerStyle} />
|
||||
</TouchableWithoutFeedback>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{isOpen && (
|
||||
<BottomSheet
|
||||
ref={bottomSheetRef}
|
||||
snapPoints={['50%']}
|
||||
enablePanDownToClose
|
||||
backdropComponent={CustomBackdrop}
|
||||
onChange={onShareBottomSheetChange}>
|
||||
<View>
|
||||
<Text style={[s.textCenter, s.bold, s.mb10]}>Share this post</Text>
|
||||
<Text style={[s.textCenter, s.mb10]}>{uri}</Text>
|
||||
<Button title="Copy to clipboard" onPress={onPressCopy} />
|
||||
<View style={s.p10}>
|
||||
<TouchableOpacity onPress={onClose} style={styles.closeBtn}>
|
||||
<Text style={s.textCenter}>Close</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</BottomSheet>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
closeBtn: {
|
||||
width: '100%',
|
||||
borderColor: '#000',
|
||||
borderWidth: 1,
|
||||
borderRadius: 4,
|
||||
padding: 10,
|
||||
},
|
||||
})
|
57
src/view/com/modals/SharePost.tsx
Normal file
57
src/view/com/modals/SharePost.tsx
Normal file
|
@ -0,0 +1,57 @@
|
|||
import React, {forwardRef, useState, useImperativeHandle} from 'react'
|
||||
import {Button, StyleSheet, Text, TouchableOpacity, View} from 'react-native'
|
||||
import {Modal} from './WebModal'
|
||||
import Toast from '../util/Toast'
|
||||
import {s} from '../../lib/styles'
|
||||
|
||||
export const ShareModal = forwardRef(function ShareModal({}: {}, ref) {
|
||||
const [isOpen, setIsOpen] = useState<boolean>(false)
|
||||
const [uri, setUri] = useState<string>('')
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
open(uri: string) {
|
||||
console.log('sharing', uri)
|
||||
setUri(uri)
|
||||
setIsOpen(true)
|
||||
},
|
||||
}))
|
||||
|
||||
const onPressCopy = () => {
|
||||
// TODO
|
||||
Toast.show('Link copied', {
|
||||
position: Toast.positions.TOP,
|
||||
})
|
||||
}
|
||||
const onClose = () => {
|
||||
setIsOpen(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isOpen && (
|
||||
<Modal onClose={onClose}>
|
||||
<View>
|
||||
<Text style={[s.textCenter, s.bold, s.mb10]}>Share this post</Text>
|
||||
<Text style={[s.textCenter, s.mb10]}>{uri}</Text>
|
||||
<Button title="Copy to clipboard" onPress={onPressCopy} />
|
||||
<View style={s.p10}>
|
||||
<TouchableOpacity onPress={onClose} style={styles.closeBtn}>
|
||||
<Text style={s.textCenter}>Close</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
closeBtn: {
|
||||
width: '100%',
|
||||
borderColor: '#000',
|
||||
borderWidth: 1,
|
||||
borderRadius: 4,
|
||||
padding: 10,
|
||||
},
|
||||
})
|
20
src/view/com/modals/WebModal.tsx
Normal file
20
src/view/com/modals/WebModal.tsx
Normal file
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* Use this for the Web build only.
|
||||
* It's intended to replace the BottomSheet.
|
||||
*
|
||||
* Note: the dataSet properties are used to leverage custom CSS in public/index.html
|
||||
*/
|
||||
import React from 'react'
|
||||
// @ts-ignore no declarations available -prf
|
||||
import {TouchableWithoutFeedback, View} from 'react-native-web'
|
||||
|
||||
type Props = {onClose: () => void}
|
||||
export const Modal: React.FC<Props> = ({onClose, children}) => {
|
||||
return (
|
||||
<TouchableWithoutFeedback onPress={onClose}>
|
||||
<View dataSet={{'modal-overlay': 1}}>
|
||||
<View dataSet={{'modal-container': 1}}>{children}</View>
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue