diff --git a/public/index.html b/public/index.html
index edc9d8e1..59487592 100644
--- a/public/index.html
+++ b/public/index.html
@@ -13,29 +13,10 @@
#app-root { display:flex; height:100%; }
/* Remove focus state on inputs */
- input:focus {
+ input:focus,
+ textarea:focus {
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;
- }
diff --git a/src/view/com/composer/ComposePost.tsx b/src/view/com/composer/ComposePost.tsx
index 64e75328..2f30a1cf 100644
--- a/src/view/com/composer/ComposePost.tsx
+++ b/src/view/com/composer/ComposePost.tsx
@@ -11,25 +11,19 @@ import {
TouchableWithoutFeedback,
View,
} from 'react-native'
-import PasteInput, {
- PastedFile,
- PasteInputRef,
-} from '@mattermost/react-native-paste-input'
import LinearGradient from 'react-native-linear-gradient'
import {
FontAwesomeIcon,
FontAwesomeIconStyle,
} 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 {Autocomplete} from './Autocomplete'
import {ExternalEmbed} from './ExternalEmbed'
import {Text} from '../util/text/Text'
import * as Toast from '../util/Toast'
-// @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 {TextInput, TextInputRef} from './text-input/TextInput'
+import {CharProgress} from './char-progress/CharProgress'
import {TextLink} from '../util/Link'
import {UserAvatar} from '../util/UserAvatar'
import {useStores} from '../../../state'
@@ -49,7 +43,6 @@ import {SelectedPhoto} from './SelectedPhoto'
import {usePalette} from '../../lib/hooks/usePalette'
const MAX_TEXT_LENGTH = 256
-const DANGER_TEXT_LENGTH = MAX_TEXT_LENGTH
const HITSLOP = {left: 10, top: 10, right: 10, bottom: 10}
export const ComposePost = observer(function ComposePost({
@@ -63,10 +56,10 @@ export const ComposePost = observer(function ComposePost({
onPost?: ComposerOpts['onPost']
onClose: () => void
}) {
- const {track} = useAnalytics()
+ // const {track} = useAnalytics() TODO
const pal = usePalette('default')
const store = useStores()
- const textInput = useRef(null)
+ const textInput = useRef(null)
const [isProcessing, setIsProcessing] = useState(false)
const [processingState, setProcessingState] = useState('')
const [error, setError] = useState('')
@@ -80,7 +73,6 @@ export const ComposePost = observer(function ComposePost({
)
const [selectedPhotos, setSelectedPhotos] = useState([])
- // 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(
() => new UserAutocompleteViewModel(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) {
return setError(cleanError(err))
}
if (selectedPhotos.length >= 4) {
return
}
- const imgFile = files.find(file => /\.(jpe?g|png)$/.test(file.fileName))
- if (!imgFile) {
- return
+ const imgUri = uris.find(uri => /\.(jpe?g|png)$/.test(uri))
+ if (imgUri) {
+ const finalImgPath = await cropPhoto(imgUri)
+ onSelectPhotos([...selectedPhotos, finalImgPath])
}
- const finalImgPath = await cropPhoto(imgFile.uri)
- onSelectPhotos([...selectedPhotos, finalImgPath])
}
const onPressCancel = () => hackfixOnClose()
const onPressPublish = async () => {
@@ -257,9 +248,10 @@ export const ComposePost = observer(function ComposePost({
autocompleteView.knownHandles,
setProcessingState,
)
- track('Create Post', {
- imageCount: selectedPhotos.length,
- })
+ // TODO
+ // track('Create Post', {
+ // imageCount: selectedPhotos.length,
+ // })
} catch (e: any) {
setError(cleanError(e.message))
setIsProcessing(false)
@@ -276,7 +268,6 @@ export const ComposePost = observer(function ComposePost({
}
const canPost = text.length <= MAX_TEXT_LENGTH
- const progressColor = text.length > DANGER_TEXT_LENGTH ? '#e60000' : undefined
const selectTextInputLayout =
selectedPhotos.length !== 0
@@ -311,7 +302,7 @@ export const ComposePost = observer(function ComposePost({
+ style={styles.outer}>
@@ -396,22 +387,19 @@ export const ComposePost = observer(function ComposePost({
avatar={store.me.avatar}
size={50}
/>
- onChangeText(str)}
onPaste={onPaste}
placeholder={selectTextInputPlaceholder}
- placeholderTextColor={pal.colors.textLight}
style={[
pal.text,
styles.textInput,
styles.textInputFormatting,
]}>
{textDecorated}
-
+
-
- {MAX_TEXT_LENGTH - text.length}
-
-
- {text.length > DANGER_TEXT_LENGTH ? (
-
- ) : (
-
- )}
-
+
DANGER_TEXT_LENGTH ? '#e60000' : undefined
+ return (
+ <>
+
+ {MAX_TEXT_LENGTH - count}
+
+
+ {count > DANGER_TEXT_LENGTH ? (
+
+ ) : (
+
+ )}
+
+ >
+ )
+}
diff --git a/src/view/com/composer/char-progress/CharProgress.web.tsx b/src/view/com/composer/char-progress/CharProgress.web.tsx
new file mode 100644
index 00000000..6bdcc139
--- /dev/null
+++ b/src/view/com/composer/char-progress/CharProgress.web.tsx
@@ -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 (
+ <>
+
+ {MAX_TEXT_LENGTH - count}
+
+
+ {
+ null /* TODO count > DANGER_TEXT_LENGTH ? (
+
+ ) : (
+
+ )*/
+ }
+
+ >
+ )
+}
diff --git a/src/view/com/composer/text-input/TextInput.tsx b/src/view/com/composer/text-input/TextInput.tsx
new file mode 100644
index 00000000..3c5dacf8
--- /dev/null
+++ b/src/view/com/composer/text-input/TextInput.tsx
@@ -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
+ placeholder: string
+ style: StyleProp
+ onChangeText: (str: string) => void
+ onPaste: (err: string | undefined, uris: string[]) => void
+}
+
+export function TextInput({
+ testID,
+ innerRef,
+ placeholder,
+ style,
+ onChangeText,
+ onPaste,
+ children,
+}: React.PropsWithChildren) {
+ const pal = usePalette('default')
+ const onPasteInner = (err: string | undefined, files: PastedFile[]) => {
+ if (err) {
+ onPaste(err, [])
+ } else {
+ onPaste(
+ undefined,
+ files.map(f => f.uri),
+ )
+ }
+ }
+ return (
+ onChangeText(str)}
+ onPaste={onPasteInner}
+ placeholder={placeholder}
+ placeholderTextColor={pal.colors.textLight}
+ style={style}>
+ {children}
+
+ )
+}
diff --git a/src/view/com/composer/text-input/TextInput.web.tsx b/src/view/com/composer/text-input/TextInput.web.tsx
new file mode 100644
index 00000000..6960bf7a
--- /dev/null
+++ b/src/view/com/composer/text-input/TextInput.web.tsx
@@ -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
+ placeholder: string
+ style: StyleProp
+ onChangeText: (str: string) => void
+ onPaste: (err: string | undefined, uris: string[]) => void
+}
+
+export function TextInput({
+ testID,
+ innerRef,
+ placeholder,
+ style,
+ onChangeText,
+ children,
+}: React.PropsWithChildren) {
+ const pal = usePalette('default')
+ style = addStyle(style, styles.input)
+ return (
+ onChangeText(str)}
+ placeholder={placeholder}
+ placeholderTextColor={pal.colors.textLight}
+ style={style}>
+ {children}
+
+ )
+}
+
+const styles = StyleSheet.create({
+ input: {
+ minHeight: 140,
+ },
+})
diff --git a/src/view/shell/mobile/Composer.tsx b/src/view/shell/mobile/Composer.tsx
index a19a4704..c93931ab 100644
--- a/src/view/shell/mobile/Composer.tsx
+++ b/src/view/shell/mobile/Composer.tsx
@@ -48,9 +48,6 @@ export const Composer = observer(
],
}
- // events
- // =
-
// rendering
// =
diff --git a/src/view/shell/web/Composer.tsx b/src/view/shell/web/Composer.tsx
new file mode 100644
index 00000000..63904009
--- /dev/null
+++ b/src/view/shell/web/Composer.tsx
@@ -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
+ }
+
+ return (
+
+
+
+
+
+ )
+ },
+)
+
+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,
+ },
+})
diff --git a/src/view/shell/web/left-column.tsx b/src/view/shell/web/DesktopLeftColumn.tsx
similarity index 100%
rename from src/view/shell/web/left-column.tsx
rename to src/view/shell/web/DesktopLeftColumn.tsx
diff --git a/src/view/shell/web/right-column.tsx b/src/view/shell/web/DesktopRightColumn.tsx
similarity index 100%
rename from src/view/shell/web/right-column.tsx
rename to src/view/shell/web/DesktopRightColumn.tsx
diff --git a/src/view/shell/web/index.tsx b/src/view/shell/web/index.tsx
index a4232eab..0eb5cf75 100644
--- a/src/view/shell/web/index.tsx
+++ b/src/view/shell/web/index.tsx
@@ -3,13 +3,14 @@ import {observer} from 'mobx-react-lite'
import {View, StyleSheet} from 'react-native'
import {useStores} from '../../../state'
import {match, MatchResult} from '../../routes'
-import {DesktopLeftColumn} from './left-column'
-import {DesktopRightColumn} from './right-column'
+import {DesktopLeftColumn} from './DesktopLeftColumn'
+import {DesktopRightColumn} from './DesktopRightColumn'
import {Onboard} from '../../screens/Onboard'
import {Login} from '../../screens/Login'
import {ErrorBoundary} from '../../com/util/ErrorBoundary'
import {Lightbox} from '../../com/lightbox/Lightbox'
import {Modal} from '../../com/modals/Modal'
+import {Composer} from './Composer'
import {usePalette} from '../../lib/hooks/usePalette'
import {s} from '../../lib/styles'
@@ -49,6 +50,14 @@ export const WebShell: React.FC = observer(() => {
))}
+ store.shell.closeComposer()}
+ winHeight={0}
+ replyTo={store.shell.composerOpts?.replyTo}
+ imagesOpen={store.shell.composerOpts?.imagesOpen}
+ onPost={store.shell.composerOpts?.onPost}
+ />