Skip to content

Commit

Permalink
Move composer state to a context
Browse files Browse the repository at this point in the history
  • Loading branch information
pfrazee committed Nov 14, 2023
1 parent 0501c2b commit a78a12c
Show file tree
Hide file tree
Showing 22 changed files with 149 additions and 152 deletions.
2 changes: 1 addition & 1 deletion src/lib/link-meta/bsky.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {LikelyType, LinkMeta} from './link-meta'
import {convertBskyAppUrlIfNeeded, makeRecordUri} from '../strings/url-helpers'
import {RootStoreModel} from 'state/index'
import {PostThreadModel} from 'state/models/content/post-thread'
import {ComposerOptsQuote} from 'state/models/ui/shell'
import {ComposerOptsQuote} from 'state/shell/composer'

// TODO
// import {Home} from 'view/screens/Home'
Expand Down
52 changes: 1 addition & 51 deletions src/state/models/ui/shell.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {AppBskyEmbedRecord, AppBskyActorDefs} from '@atproto/api'
import {AppBskyActorDefs} from '@atproto/api'
import {RootStoreModel} from '../root-store'
import {makeAutoObservable, runInAction} from 'mobx'
import {
Expand Down Expand Up @@ -37,41 +37,9 @@ export class ImagesLightbox implements LightboxModel {
}
}

export interface ComposerOptsPostRef {
uri: string
cid: string
text: string
author: {
handle: string
displayName?: string
avatar?: string
}
}
export interface ComposerOptsQuote {
uri: string
cid: string
text: string
indexedAt: string
author: {
did: string
handle: string
displayName?: string
avatar?: string
}
embeds?: AppBskyEmbedRecord.ViewRecord['embeds']
}
export interface ComposerOpts {
replyTo?: ComposerOptsPostRef
onPost?: () => void
quote?: ComposerOptsQuote
mention?: string // handle of user to mention
}

export class ShellUiModel {
isLightboxActive = false
activeLightbox: ProfileImageLightbox | ImagesLightbox | null = null
isComposerActive = false
composerOpts: ComposerOpts | undefined
tickEveryMinute = Date.now()

constructor(public rootStore: RootStoreModel) {
Expand All @@ -92,10 +60,6 @@ export class ShellUiModel {
this.closeLightbox()
return true
}
if (this.isComposerActive) {
this.closeComposer()
return true
}
return false
}

Expand All @@ -106,9 +70,6 @@ export class ShellUiModel {
if (this.isLightboxActive) {
this.closeLightbox()
}
if (this.isComposerActive) {
this.closeComposer()
}
}

openLightbox(lightbox: ProfileImageLightbox | ImagesLightbox) {
Expand All @@ -122,17 +83,6 @@ export class ShellUiModel {
this.activeLightbox = null
}

openComposer(opts: ComposerOpts) {
this.rootStore.emitNavigation()
this.isComposerActive = true
this.composerOpts = opts
}

closeComposer() {
this.isComposerActive = false
this.composerOpts = undefined
}

setupClock() {
setInterval(() => {
runInAction(() => {
Expand Down
74 changes: 74 additions & 0 deletions src/state/shell/composer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React from 'react'
import {AppBskyEmbedRecord} from '@atproto/api'

export interface ComposerOptsPostRef {
uri: string
cid: string
text: string
author: {
handle: string
displayName?: string
avatar?: string
}
}
export interface ComposerOptsQuote {
uri: string
cid: string
text: string
indexedAt: string
author: {
did: string
handle: string
displayName?: string
avatar?: string
}
embeds?: AppBskyEmbedRecord.ViewRecord['embeds']
}
export interface ComposerOpts {
replyTo?: ComposerOptsPostRef
onPost?: () => void
quote?: ComposerOptsQuote
mention?: string // handle of user to mention
}

type StateContext = ComposerOpts | undefined
type ControlsContext = {
openComposer: (opts: ComposerOpts) => void
closeComposer: () => void
}

const stateContext = React.createContext<StateContext>(undefined)
const controlsContext = React.createContext<ControlsContext>({
openComposer(_opts: ComposerOpts) {},
closeComposer() {},
})

export function Provider({children}: React.PropsWithChildren<{}>) {
const [state, setState] = React.useState<StateContext>()
const api = React.useMemo(
() => ({
openComposer(opts: ComposerOpts) {
setState(opts)
},
closeComposer() {
setState(undefined)
},
}),
[setState],
)
return (
<stateContext.Provider value={state}>
<controlsContext.Provider value={api}>
{children}
</controlsContext.Provider>
</stateContext.Provider>
)
}

export function useComposerState() {
return React.useContext(stateContext)
}

export function useComposerControls() {
return React.useContext(controlsContext)
}
5 changes: 4 additions & 1 deletion src/state/shell/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {Provider as DrawerSwipableProvider} from './drawer-swipe-disabled'
import {Provider as MinimalModeProvider} from './minimal-mode'
import {Provider as ColorModeProvider} from './color-mode'
import {Provider as OnboardingProvider} from './onboarding'
import {Provider as ComposerProvider} from './composer'

export {useIsDrawerOpen, useSetDrawerOpen} from './drawer-open'
export {
Expand All @@ -22,7 +23,9 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
<DrawerSwipableProvider>
<MinimalModeProvider>
<ColorModeProvider>
<OnboardingProvider>{children}</OnboardingProvider>
<OnboardingProvider>
<ComposerProvider>{children}</ComposerProvider>
</OnboardingProvider>
</ColorModeProvider>
</MinimalModeProvider>
</DrawerSwipableProvider>
Expand Down
3 changes: 1 addition & 2 deletions src/view/com/composer/Composer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,8 @@ import * as Toast from '../util/Toast'
import {TextInput, TextInputRef} from './text-input/TextInput'
import {CharProgress} from './char-progress/CharProgress'
import {UserAvatar} from '../util/UserAvatar'
import {useStores} from 'state/index'
import * as apilib from 'lib/api/index'
import {ComposerOpts} from 'state/models/ui/shell'
import {ComposerOpts} from 'state/shell/composer'
import {s, colors, gradients} from 'lib/styles'
import {sanitizeDisplayName} from 'lib/strings/display-names'
import {sanitizeHandle} from 'lib/strings/handles'
Expand Down
2 changes: 1 addition & 1 deletion src/view/com/composer/useExternalLinkFetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
isBskyCustomFeedUrl,
isBskyListUrl,
} from 'lib/strings/url-helpers'
import {ComposerOpts} from 'state/models/ui/shell'
import {ComposerOpts} from 'state/shell/composer'
import {POST_IMG_MAX} from 'lib/constants'
import {logger} from '#/logger'

Expand Down
6 changes: 4 additions & 2 deletions src/view/com/feeds/FeedPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {LoadLatestBtn} from '../util/load-latest/LoadLatestBtn'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useSession} from '#/state/session'
import {useComposerControls} from '#/state/shell/composer'

const POLL_FREQ = 30e3 // 30sec

Expand All @@ -46,6 +47,7 @@ export function FeedPage({
const {_} = useLingui()
const {isDesktop} = useWebMediaQueries()
const queryClient = useQueryClient()
const {openComposer} = useComposerControls()
const [onMainScroll, isScrolledDown, resetMainScroll] = useOnMainScroll()
const {screen, track} = useAnalytics()
const headerOffset = useHeaderOffset()
Expand Down Expand Up @@ -80,8 +82,8 @@ export function FeedPage({

const onPressCompose = React.useCallback(() => {
track('HomeScreen:PressCompose')
store.shell.openComposer({})
}, [store, track])
openComposer({})
}, [openComposer, track])

const onPressLoadLatest = React.useCallback(() => {
scrollToTop()
Expand Down
15 changes: 8 additions & 7 deletions src/view/com/post-thread/PostThreadItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {sanitizeHandle} from 'lib/strings/handles'
import {countLines, pluralize} from 'lib/strings/helpers'
import {isEmbedByEmbedder} from 'lib/embeds'
import {getTranslatorLink, isPostInLanguage} from '../../../locale/helpers'
import {useStores} from 'state/index'
import {PostMeta} from '../util/PostMeta'
import {PostEmbeds} from '../util/post-embeds'
import {PostCtrls} from '../util/post-ctrls/PostCtrls'
Expand All @@ -39,6 +38,8 @@ import {MAX_POST_LINES} from 'lib/constants'
import {Trans} from '@lingui/macro'
import {useLanguagePrefs} from '#/state/preferences'
import {usePostShadow, POST_TOMBSTONE} from '#/state/cache/post-shadow'
import {useComposerControls} from '#/state/shell/composer'
import {useModerationOpts} from '#/state/queries/preferences'

export function PostThreadItem({
post,
Expand All @@ -65,7 +66,7 @@ export function PostThreadItem({
hasPrecedingItem: boolean
onPostReply: () => void
}) {
const store = useStores()
const moderationOpts = useModerationOpts()
const postShadowed = usePostShadow(post, dataUpdatedAt)
const richText = useMemo(
() =>
Expand All @@ -77,8 +78,8 @@ export function PostThreadItem({
)
const moderation = useMemo(
() =>
post ? moderatePost(post, store.preferences.moderationOpts) : undefined,
[post, store],
post && moderationOpts ? moderatePost(post, moderationOpts) : undefined,
[post, moderationOpts],
)
if (postShadowed === POST_TOMBSTONE) {
return <PostThreadItemDeleted />
Expand Down Expand Up @@ -145,8 +146,8 @@ function PostThreadItemLoaded({
onPostReply: () => void
}) {
const pal = usePalette('default')
const store = useStores()
const langPrefs = useLanguagePrefs()
const {openComposer} = useComposerControls()
const [limitLines, setLimitLines] = React.useState(
countLines(richText?.text) >= MAX_POST_LINES,
)
Expand Down Expand Up @@ -187,7 +188,7 @@ function PostThreadItemLoaded({
)

const onPressReply = React.useCallback(() => {
store.shell.openComposer({
openComposer({
replyTo: {
uri: post.uri,
cid: post.cid,
Expand All @@ -200,7 +201,7 @@ function PostThreadItemLoaded({
},
onPost: onPostReply,
})
}, [store, post, record, onPostReply])
}, [openComposer, post, record, onPostReply])

const onPressShowMore = React.useCallback(() => {
setLimitLines(false)
Expand Down
8 changes: 4 additions & 4 deletions src/view/com/post/Post.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ import {PostAlerts} from '../util/moderation/PostAlerts'
import {Text} from '../util/text/Text'
import {RichText} from '../util/text/RichText'
import {PreviewableUserAvatar} from '../util/UserAvatar'
import {useStores} from 'state/index'
import {s, colors} from 'lib/styles'
import {usePalette} from 'lib/hooks/usePalette'
import {makeProfileLink} from 'lib/routes/links'
import {MAX_POST_LINES} from 'lib/constants'
import {countLines} from 'lib/strings/helpers'
import {useModerationOpts} from '#/state/queries/preferences'
import {usePostShadow, POST_TOMBSTONE} from '#/state/cache/post-shadow'
import {useComposerControls} from '#/state/shell/composer'

export function Post({
post,
Expand Down Expand Up @@ -97,7 +97,7 @@ function PostInner({
style?: StyleProp<ViewStyle>
}) {
const pal = usePalette('default')
const store = useStores()
const {openComposer} = useComposerControls()
const [limitLines, setLimitLines] = useState(
countLines(richText?.text) >= MAX_POST_LINES,
)
Expand All @@ -110,7 +110,7 @@ function PostInner({
}

const onPressReply = React.useCallback(() => {
store.shell.openComposer({
openComposer({
replyTo: {
uri: post.uri,
cid: post.cid,
Expand All @@ -122,7 +122,7 @@ function PostInner({
},
},
})
}, [store, post, record])
}, [openComposer, post, record])

const onPressShowMore = React.useCallback(() => {
setLimitLines(false)
Expand Down
8 changes: 4 additions & 4 deletions src/view/com/posts/FeedItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import {RichText} from '../util/text/RichText'
import {PostSandboxWarning} from '../util/PostSandboxWarning'
import {PreviewableUserAvatar} from '../util/UserAvatar'
import {s} from 'lib/styles'
import {useStores} from 'state/index'
import {usePalette} from 'lib/hooks/usePalette'
import {useAnalytics} from 'lib/analytics/analytics'
import {sanitizeDisplayName} from 'lib/strings/display-names'
Expand All @@ -34,6 +33,7 @@ import {isEmbedByEmbedder} from 'lib/embeds'
import {MAX_POST_LINES} from 'lib/constants'
import {countLines} from 'lib/strings/helpers'
import {usePostShadow, POST_TOMBSTONE} from '#/state/cache/post-shadow'
import {useComposerControls} from '#/state/shell/composer'

export function FeedItem({
post,
Expand Down Expand Up @@ -102,7 +102,7 @@ function FeedItemInner({
isThreadLastChild?: boolean
isThreadParent?: boolean
}) {
const store = useStores()
const {openComposer} = useComposerControls()
const pal = usePalette('default')
const {track} = useAnalytics()
const [limitLines, setLimitLines] = useState(
Expand All @@ -124,7 +124,7 @@ function FeedItemInner({

const onPressReply = React.useCallback(() => {
track('FeedItem:PostReply')
store.shell.openComposer({
openComposer({
replyTo: {
uri: post.uri,
cid: post.cid,
Expand All @@ -136,7 +136,7 @@ function FeedItemInner({
},
},
})
}, [post, record, track, store])
}, [post, record, track, openComposer])

const onPressShowMore = React.useCallback(() => {
setLimitLines(false)
Expand Down
Loading

0 comments on commit a78a12c

Please sign in to comment.