Implement basic web composer
parent
5961c26800
commit
99360f7bd9
|
@ -13,29 +13,10 @@
|
||||||
#app-root { display:flex; height:100%; }
|
#app-root { display:flex; height:100%; }
|
||||||
|
|
||||||
/* Remove focus state on inputs */
|
/* Remove focus state on inputs */
|
||||||
input:focus {
|
input:focus,
|
||||||
|
textarea:focus {
|
||||||
outline: 0;
|
outline: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These styles are for src/view/com/modals/WebModal */
|
|
||||||
div[data-modal-overlay] {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
background: #0004;
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
}
|
|
||||||
div[data-modal-container] {
|
|
||||||
position: fixed;
|
|
||||||
top: 20vh;
|
|
||||||
left: calc(50vw - 300px);
|
|
||||||
width: 600px;
|
|
||||||
padding: 20px;
|
|
||||||
background: #fff;
|
|
||||||
border-radius: 10px;
|
|
||||||
box-shadow: 0 5px 10px #0005;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -11,25 +11,19 @@ import {
|
||||||
TouchableWithoutFeedback,
|
TouchableWithoutFeedback,
|
||||||
View,
|
View,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import PasteInput, {
|
|
||||||
PastedFile,
|
|
||||||
PasteInputRef,
|
|
||||||
} from '@mattermost/react-native-paste-input'
|
|
||||||
import LinearGradient from 'react-native-linear-gradient'
|
import LinearGradient from 'react-native-linear-gradient'
|
||||||
import {
|
import {
|
||||||
FontAwesomeIcon,
|
FontAwesomeIcon,
|
||||||
FontAwesomeIconStyle,
|
FontAwesomeIconStyle,
|
||||||
} from '@fortawesome/react-native-fontawesome'
|
} from '@fortawesome/react-native-fontawesome'
|
||||||
import {useAnalytics} from '@segment/analytics-react-native'
|
// import {useAnalytics} from '@segment/analytics-react-native' TODO
|
||||||
import {UserAutocompleteViewModel} from '../../../state/models/user-autocomplete-view'
|
import {UserAutocompleteViewModel} from '../../../state/models/user-autocomplete-view'
|
||||||
import {Autocomplete} from './Autocomplete'
|
import {Autocomplete} from './Autocomplete'
|
||||||
import {ExternalEmbed} from './ExternalEmbed'
|
import {ExternalEmbed} from './ExternalEmbed'
|
||||||
import {Text} from '../util/text/Text'
|
import {Text} from '../util/text/Text'
|
||||||
import * as Toast from '../util/Toast'
|
import * as Toast from '../util/Toast'
|
||||||
// @ts-ignore no type definition -prf
|
import {TextInput, TextInputRef} from './text-input/TextInput'
|
||||||
import ProgressCircle from 'react-native-progress/Circle'
|
import {CharProgress} from './char-progress/CharProgress'
|
||||||
// @ts-ignore no type definition -prf
|
|
||||||
import ProgressPie from 'react-native-progress/Pie'
|
|
||||||
import {TextLink} from '../util/Link'
|
import {TextLink} from '../util/Link'
|
||||||
import {UserAvatar} from '../util/UserAvatar'
|
import {UserAvatar} from '../util/UserAvatar'
|
||||||
import {useStores} from '../../../state'
|
import {useStores} from '../../../state'
|
||||||
|
@ -49,7 +43,6 @@ import {SelectedPhoto} from './SelectedPhoto'
|
||||||
import {usePalette} from '../../lib/hooks/usePalette'
|
import {usePalette} from '../../lib/hooks/usePalette'
|
||||||
|
|
||||||
const MAX_TEXT_LENGTH = 256
|
const MAX_TEXT_LENGTH = 256
|
||||||
const DANGER_TEXT_LENGTH = MAX_TEXT_LENGTH
|
|
||||||
const HITSLOP = {left: 10, top: 10, right: 10, bottom: 10}
|
const HITSLOP = {left: 10, top: 10, right: 10, bottom: 10}
|
||||||
|
|
||||||
export const ComposePost = observer(function ComposePost({
|
export const ComposePost = observer(function ComposePost({
|
||||||
|
@ -63,10 +56,10 @@ export const ComposePost = observer(function ComposePost({
|
||||||
onPost?: ComposerOpts['onPost']
|
onPost?: ComposerOpts['onPost']
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
}) {
|
}) {
|
||||||
const {track} = useAnalytics()
|
// const {track} = useAnalytics() TODO
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const textInput = useRef<PasteInputRef>(null)
|
const textInput = useRef<TextInputRef>(null)
|
||||||
const [isProcessing, setIsProcessing] = useState(false)
|
const [isProcessing, setIsProcessing] = useState(false)
|
||||||
const [processingState, setProcessingState] = useState('')
|
const [processingState, setProcessingState] = useState('')
|
||||||
const [error, setError] = useState('')
|
const [error, setError] = useState('')
|
||||||
|
@ -80,7 +73,6 @@ export const ComposePost = observer(function ComposePost({
|
||||||
)
|
)
|
||||||
const [selectedPhotos, setSelectedPhotos] = useState<string[]>([])
|
const [selectedPhotos, setSelectedPhotos] = useState<string[]>([])
|
||||||
|
|
||||||
// Using default import (React.use...) instead of named import (use...) to be able to mock store's data in jest environment
|
|
||||||
const autocompleteView = React.useMemo<UserAutocompleteViewModel>(
|
const autocompleteView = React.useMemo<UserAutocompleteViewModel>(
|
||||||
() => new UserAutocompleteViewModel(store),
|
() => new UserAutocompleteViewModel(store),
|
||||||
[store],
|
[store],
|
||||||
|
@ -219,19 +211,18 @@ export const ComposePost = observer(function ComposePost({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const onPaste = async (err: string | undefined, files: PastedFile[]) => {
|
const onPaste = async (err: string | undefined, uris: string[]) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return setError(cleanError(err))
|
return setError(cleanError(err))
|
||||||
}
|
}
|
||||||
if (selectedPhotos.length >= 4) {
|
if (selectedPhotos.length >= 4) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const imgFile = files.find(file => /\.(jpe?g|png)$/.test(file.fileName))
|
const imgUri = uris.find(uri => /\.(jpe?g|png)$/.test(uri))
|
||||||
if (!imgFile) {
|
if (imgUri) {
|
||||||
return
|
const finalImgPath = await cropPhoto(imgUri)
|
||||||
|
onSelectPhotos([...selectedPhotos, finalImgPath])
|
||||||
}
|
}
|
||||||
const finalImgPath = await cropPhoto(imgFile.uri)
|
|
||||||
onSelectPhotos([...selectedPhotos, finalImgPath])
|
|
||||||
}
|
}
|
||||||
const onPressCancel = () => hackfixOnClose()
|
const onPressCancel = () => hackfixOnClose()
|
||||||
const onPressPublish = async () => {
|
const onPressPublish = async () => {
|
||||||
|
@ -257,9 +248,10 @@ export const ComposePost = observer(function ComposePost({
|
||||||
autocompleteView.knownHandles,
|
autocompleteView.knownHandles,
|
||||||
setProcessingState,
|
setProcessingState,
|
||||||
)
|
)
|
||||||
track('Create Post', {
|
// TODO
|
||||||
imageCount: selectedPhotos.length,
|
// track('Create Post', {
|
||||||
})
|
// imageCount: selectedPhotos.length,
|
||||||
|
// })
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
setError(cleanError(e.message))
|
setError(cleanError(e.message))
|
||||||
setIsProcessing(false)
|
setIsProcessing(false)
|
||||||
|
@ -276,7 +268,6 @@ export const ComposePost = observer(function ComposePost({
|
||||||
}
|
}
|
||||||
|
|
||||||
const canPost = text.length <= MAX_TEXT_LENGTH
|
const canPost = text.length <= MAX_TEXT_LENGTH
|
||||||
const progressColor = text.length > DANGER_TEXT_LENGTH ? '#e60000' : undefined
|
|
||||||
|
|
||||||
const selectTextInputLayout =
|
const selectTextInputLayout =
|
||||||
selectedPhotos.length !== 0
|
selectedPhotos.length !== 0
|
||||||
|
@ -311,7 +302,7 @@ export const ComposePost = observer(function ComposePost({
|
||||||
<KeyboardAvoidingView
|
<KeyboardAvoidingView
|
||||||
testID="composePostView"
|
testID="composePostView"
|
||||||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||||
style={[pal.view, styles.outer]}>
|
style={styles.outer}>
|
||||||
<TouchableWithoutFeedback onPressIn={onPressContainer}>
|
<TouchableWithoutFeedback onPressIn={onPressContainer}>
|
||||||
<SafeAreaView style={s.flex1}>
|
<SafeAreaView style={s.flex1}>
|
||||||
<View style={styles.topbar}>
|
<View style={styles.topbar}>
|
||||||
|
@ -396,22 +387,19 @@ export const ComposePost = observer(function ComposePost({
|
||||||
avatar={store.me.avatar}
|
avatar={store.me.avatar}
|
||||||
size={50}
|
size={50}
|
||||||
/>
|
/>
|
||||||
<PasteInput
|
<TextInput
|
||||||
testID="composerTextInput"
|
testID="composerTextInput"
|
||||||
ref={textInput}
|
innerRef={textInput}
|
||||||
multiline
|
|
||||||
scrollEnabled
|
|
||||||
onChangeText={(str: string) => onChangeText(str)}
|
onChangeText={(str: string) => onChangeText(str)}
|
||||||
onPaste={onPaste}
|
onPaste={onPaste}
|
||||||
placeholder={selectTextInputPlaceholder}
|
placeholder={selectTextInputPlaceholder}
|
||||||
placeholderTextColor={pal.colors.textLight}
|
|
||||||
style={[
|
style={[
|
||||||
pal.text,
|
pal.text,
|
||||||
styles.textInput,
|
styles.textInput,
|
||||||
styles.textInputFormatting,
|
styles.textInputFormatting,
|
||||||
]}>
|
]}>
|
||||||
{textDecorated}
|
{textDecorated}
|
||||||
</PasteInput>
|
</TextInput>
|
||||||
</View>
|
</View>
|
||||||
<SelectedPhoto
|
<SelectedPhoto
|
||||||
selectedPhotos={selectedPhotos}
|
selectedPhotos={selectedPhotos}
|
||||||
|
@ -450,31 +438,7 @@ export const ComposePost = observer(function ComposePost({
|
||||||
/>
|
/>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<View style={s.flex1} />
|
<View style={s.flex1} />
|
||||||
<Text style={[s.mr10, {color: progressColor}]}>
|
<CharProgress count={text.length} />
|
||||||
{MAX_TEXT_LENGTH - text.length}
|
|
||||||
</Text>
|
|
||||||
<View>
|
|
||||||
{text.length > DANGER_TEXT_LENGTH ? (
|
|
||||||
<ProgressPie
|
|
||||||
size={30}
|
|
||||||
borderWidth={4}
|
|
||||||
borderColor={progressColor}
|
|
||||||
color={progressColor}
|
|
||||||
progress={Math.min(
|
|
||||||
(text.length - MAX_TEXT_LENGTH) / MAX_TEXT_LENGTH,
|
|
||||||
1,
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<ProgressCircle
|
|
||||||
size={30}
|
|
||||||
borderWidth={1}
|
|
||||||
borderColor={colors.gray2}
|
|
||||||
color={progressColor}
|
|
||||||
progress={text.length / MAX_TEXT_LENGTH}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
active={autocompleteView.isActive}
|
active={autocompleteView.isActive}
|
||||||
|
@ -504,7 +468,6 @@ const styles = StyleSheet.create({
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
padding: 15,
|
padding: 15,
|
||||||
paddingBottom: Platform.OS === 'ios' ? 0 : 50,
|
|
||||||
height: '100%',
|
height: '100%',
|
||||||
},
|
},
|
||||||
topbar: {
|
topbar: {
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
import React from 'react'
|
||||||
|
import {View} from 'react-native'
|
||||||
|
import {Text} from '../../util/text/Text'
|
||||||
|
// @ts-ignore no type definition -prf
|
||||||
|
import ProgressCircle from 'react-native-progress/Circle'
|
||||||
|
// @ts-ignore no type definition -prf
|
||||||
|
import ProgressPie from 'react-native-progress/Pie'
|
||||||
|
import {s, colors} from '../../../lib/styles'
|
||||||
|
|
||||||
|
const MAX_TEXT_LENGTH = 256
|
||||||
|
const DANGER_TEXT_LENGTH = MAX_TEXT_LENGTH
|
||||||
|
|
||||||
|
export function CharProgress({count}: {count: number}) {
|
||||||
|
const progressColor = count > DANGER_TEXT_LENGTH ? '#e60000' : undefined
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Text style={[s.mr10, {color: progressColor}]}>
|
||||||
|
{MAX_TEXT_LENGTH - count}
|
||||||
|
</Text>
|
||||||
|
<View>
|
||||||
|
{count > DANGER_TEXT_LENGTH ? (
|
||||||
|
<ProgressPie
|
||||||
|
size={30}
|
||||||
|
borderWidth={4}
|
||||||
|
borderColor={progressColor}
|
||||||
|
color={progressColor}
|
||||||
|
progress={Math.min((count - MAX_TEXT_LENGTH) / MAX_TEXT_LENGTH, 1)}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<ProgressCircle
|
||||||
|
size={30}
|
||||||
|
borderWidth={1}
|
||||||
|
borderColor={colors.gray2}
|
||||||
|
color={progressColor}
|
||||||
|
progress={count / MAX_TEXT_LENGTH}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
import React from 'react'
|
||||||
|
import {View} from 'react-native'
|
||||||
|
import {Text} from '../util/text/Text'
|
||||||
|
import {s} from '../../lib/styles'
|
||||||
|
|
||||||
|
const MAX_TEXT_LENGTH = 256
|
||||||
|
const DANGER_TEXT_LENGTH = MAX_TEXT_LENGTH
|
||||||
|
|
||||||
|
export function CharProgress({count}: {count: number}) {
|
||||||
|
const progressColor = count > DANGER_TEXT_LENGTH ? '#e60000' : undefined
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Text style={[s.mr10, {color: progressColor}]}>
|
||||||
|
{MAX_TEXT_LENGTH - count}
|
||||||
|
</Text>
|
||||||
|
<View>
|
||||||
|
{
|
||||||
|
null /* TODO count > DANGER_TEXT_LENGTH ? (
|
||||||
|
<ProgressPie
|
||||||
|
size={30}
|
||||||
|
borderWidth={4}
|
||||||
|
borderColor={progressColor}
|
||||||
|
color={progressColor}
|
||||||
|
progress={Math.min((count - MAX_TEXT_LENGTH) / MAX_TEXT_LENGTH, 1)}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<ProgressCircle
|
||||||
|
size={30}
|
||||||
|
borderWidth={1}
|
||||||
|
borderColor={colors.gray2}
|
||||||
|
color={progressColor}
|
||||||
|
progress={count / MAX_TEXT_LENGTH}
|
||||||
|
/>
|
||||||
|
)*/
|
||||||
|
}
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
import React from 'react'
|
||||||
|
import {StyleProp, TextStyle} from 'react-native'
|
||||||
|
import PasteInput, {
|
||||||
|
PastedFile,
|
||||||
|
PasteInputRef,
|
||||||
|
} from '@mattermost/react-native-paste-input'
|
||||||
|
import {usePalette} from '../../../lib/hooks/usePalette'
|
||||||
|
|
||||||
|
export type TextInputRef = PasteInputRef
|
||||||
|
|
||||||
|
interface TextInputProps {
|
||||||
|
testID: string
|
||||||
|
innerRef: React.Ref<TextInputRef>
|
||||||
|
placeholder: string
|
||||||
|
style: StyleProp<TextStyle>
|
||||||
|
onChangeText: (str: string) => void
|
||||||
|
onPaste: (err: string | undefined, uris: string[]) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export function TextInput({
|
||||||
|
testID,
|
||||||
|
innerRef,
|
||||||
|
placeholder,
|
||||||
|
style,
|
||||||
|
onChangeText,
|
||||||
|
onPaste,
|
||||||
|
children,
|
||||||
|
}: React.PropsWithChildren<TextInputProps>) {
|
||||||
|
const pal = usePalette('default')
|
||||||
|
const onPasteInner = (err: string | undefined, files: PastedFile[]) => {
|
||||||
|
if (err) {
|
||||||
|
onPaste(err, [])
|
||||||
|
} else {
|
||||||
|
onPaste(
|
||||||
|
undefined,
|
||||||
|
files.map(f => f.uri),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<PasteInput
|
||||||
|
testID={testID}
|
||||||
|
ref={innerRef}
|
||||||
|
multiline
|
||||||
|
scrollEnabled
|
||||||
|
onChangeText={(str: string) => onChangeText(str)}
|
||||||
|
onPaste={onPasteInner}
|
||||||
|
placeholder={placeholder}
|
||||||
|
placeholderTextColor={pal.colors.textLight}
|
||||||
|
style={style}>
|
||||||
|
{children}
|
||||||
|
</PasteInput>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
import React from 'react'
|
||||||
|
import {
|
||||||
|
StyleProp,
|
||||||
|
StyleSheet,
|
||||||
|
TextInput as RNTextInput,
|
||||||
|
TextStyle,
|
||||||
|
} from 'react-native'
|
||||||
|
import {usePalette} from '../../lib/hooks/usePalette'
|
||||||
|
import {addStyle} from '../../lib/addStyle'
|
||||||
|
|
||||||
|
export type TextInputRef = RNTextInput
|
||||||
|
|
||||||
|
interface TextInputProps {
|
||||||
|
testID: string
|
||||||
|
innerRef: React.Ref<TextInputRef>
|
||||||
|
placeholder: string
|
||||||
|
style: StyleProp<TextStyle>
|
||||||
|
onChangeText: (str: string) => void
|
||||||
|
onPaste: (err: string | undefined, uris: string[]) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export function TextInput({
|
||||||
|
testID,
|
||||||
|
innerRef,
|
||||||
|
placeholder,
|
||||||
|
style,
|
||||||
|
onChangeText,
|
||||||
|
children,
|
||||||
|
}: React.PropsWithChildren<TextInputProps>) {
|
||||||
|
const pal = usePalette('default')
|
||||||
|
style = addStyle(style, styles.input)
|
||||||
|
return (
|
||||||
|
<RNTextInput
|
||||||
|
testID={testID}
|
||||||
|
ref={innerRef}
|
||||||
|
multiline
|
||||||
|
scrollEnabled
|
||||||
|
onChangeText={(str: string) => onChangeText(str)}
|
||||||
|
placeholder={placeholder}
|
||||||
|
placeholderTextColor={pal.colors.textLight}
|
||||||
|
style={style}>
|
||||||
|
{children}
|
||||||
|
</RNTextInput>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
input: {
|
||||||
|
minHeight: 140,
|
||||||
|
},
|
||||||
|
})
|
|
@ -48,9 +48,6 @@ export const Composer = observer(
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
// events
|
|
||||||
// =
|
|
||||||
|
|
||||||
// rendering
|
// rendering
|
||||||
// =
|
// =
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
import React from 'react'
|
||||||
|
import {observer} from 'mobx-react-lite'
|
||||||
|
import {StyleSheet, View} from 'react-native'
|
||||||
|
import {ComposePost} from '../../com/composer/ComposePost'
|
||||||
|
import {ComposerOpts} from '../../../state/models/shell-ui'
|
||||||
|
import {usePalette} from '../../lib/hooks/usePalette'
|
||||||
|
|
||||||
|
export const Composer = observer(
|
||||||
|
({
|
||||||
|
active,
|
||||||
|
replyTo,
|
||||||
|
imagesOpen,
|
||||||
|
onPost,
|
||||||
|
onClose,
|
||||||
|
}: {
|
||||||
|
active: boolean
|
||||||
|
winHeight: number
|
||||||
|
replyTo?: ComposerOpts['replyTo']
|
||||||
|
imagesOpen?: ComposerOpts['imagesOpen']
|
||||||
|
onPost?: ComposerOpts['onPost']
|
||||||
|
onClose: () => void
|
||||||
|
}) => {
|
||||||
|
const pal = usePalette('default')
|
||||||
|
|
||||||
|
// rendering
|
||||||
|
// =
|
||||||
|
|
||||||
|
if (!active) {
|
||||||
|
return <View />
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.mask}>
|
||||||
|
<View style={[styles.container, pal.view]}>
|
||||||
|
<ComposePost
|
||||||
|
replyTo={replyTo}
|
||||||
|
imagesOpen={imagesOpen}
|
||||||
|
onPost={onPost}
|
||||||
|
onClose={onClose}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
mask: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
backgroundColor: '#000c',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
container: {
|
||||||
|
maxWidth: 600,
|
||||||
|
width: '100%',
|
||||||
|
paddingVertical: 0,
|
||||||
|
paddingHorizontal: 2,
|
||||||
|
borderRadius: 8,
|
||||||
|
},
|
||||||
|
})
|
|
@ -3,13 +3,14 @@ import {observer} from 'mobx-react-lite'
|
||||||
import {View, StyleSheet} from 'react-native'
|
import {View, StyleSheet} from 'react-native'
|
||||||
import {useStores} from '../../../state'
|
import {useStores} from '../../../state'
|
||||||
import {match, MatchResult} from '../../routes'
|
import {match, MatchResult} from '../../routes'
|
||||||
import {DesktopLeftColumn} from './left-column'
|
import {DesktopLeftColumn} from './DesktopLeftColumn'
|
||||||
import {DesktopRightColumn} from './right-column'
|
import {DesktopRightColumn} from './DesktopRightColumn'
|
||||||
import {Onboard} from '../../screens/Onboard'
|
import {Onboard} from '../../screens/Onboard'
|
||||||
import {Login} from '../../screens/Login'
|
import {Login} from '../../screens/Login'
|
||||||
import {ErrorBoundary} from '../../com/util/ErrorBoundary'
|
import {ErrorBoundary} from '../../com/util/ErrorBoundary'
|
||||||
import {Lightbox} from '../../com/lightbox/Lightbox'
|
import {Lightbox} from '../../com/lightbox/Lightbox'
|
||||||
import {Modal} from '../../com/modals/Modal'
|
import {Modal} from '../../com/modals/Modal'
|
||||||
|
import {Composer} from './Composer'
|
||||||
import {usePalette} from '../../lib/hooks/usePalette'
|
import {usePalette} from '../../lib/hooks/usePalette'
|
||||||
import {s} from '../../lib/styles'
|
import {s} from '../../lib/styles'
|
||||||
|
|
||||||
|
@ -49,6 +50,14 @@ export const WebShell: React.FC = observer(() => {
|
||||||
))}
|
))}
|
||||||
<DesktopLeftColumn />
|
<DesktopLeftColumn />
|
||||||
<DesktopRightColumn />
|
<DesktopRightColumn />
|
||||||
|
<Composer
|
||||||
|
active={store.shell.isComposerActive}
|
||||||
|
onClose={() => store.shell.closeComposer()}
|
||||||
|
winHeight={0}
|
||||||
|
replyTo={store.shell.composerOpts?.replyTo}
|
||||||
|
imagesOpen={store.shell.composerOpts?.imagesOpen}
|
||||||
|
onPost={store.shell.composerOpts?.onPost}
|
||||||
|
/>
|
||||||
<Modal />
|
<Modal />
|
||||||
<Lightbox />
|
<Lightbox />
|
||||||
</View>
|
</View>
|
||||||
|
|
Loading…
Reference in New Issue