Factor lightbox out into hook/context (#1919)

This commit is contained in:
Paul Frazee 2023-11-15 18:17:03 -08:00 committed by GitHub
parent 03b20c70e4
commit e749f2f3a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 152 additions and 104 deletions

86
src/state/lightbox.tsx Normal file
View file

@ -0,0 +1,86 @@
import React from 'react'
import {AppBskyActorDefs} from '@atproto/api'
interface Lightbox {
name: string
}
export class ProfileImageLightbox implements Lightbox {
name = 'profile-image'
constructor(public profile: AppBskyActorDefs.ProfileViewDetailed) {}
}
interface ImagesLightboxItem {
uri: string
alt?: string
}
export class ImagesLightbox implements Lightbox {
name = 'images'
constructor(public images: ImagesLightboxItem[], public index: number) {}
setIndex(index: number) {
this.index = index
}
}
const LightboxContext = React.createContext<{
activeLightbox: Lightbox | null
}>({
activeLightbox: null,
})
const LightboxControlContext = React.createContext<{
openLightbox: (lightbox: Lightbox) => void
closeLightbox: () => void
}>({
openLightbox: () => {},
closeLightbox: () => {},
})
export function Provider({children}: React.PropsWithChildren<{}>) {
const [activeLightbox, setActiveLightbox] = React.useState<Lightbox | null>(
null,
)
const openLightbox = React.useCallback(
(lightbox: Lightbox) => {
setActiveLightbox(lightbox)
},
[setActiveLightbox],
)
const closeLightbox = React.useCallback(() => {
setActiveLightbox(null)
}, [setActiveLightbox])
const state = React.useMemo(
() => ({
activeLightbox,
}),
[activeLightbox],
)
const methods = React.useMemo(
() => ({
openLightbox,
closeLightbox,
}),
[openLightbox, closeLightbox],
)
return (
<LightboxContext.Provider value={state}>
<LightboxControlContext.Provider value={methods}>
{children}
</LightboxControlContext.Provider>
</LightboxContext.Provider>
)
}
export function useLightbox() {
return React.useContext(LightboxContext)
}
export function useLightboxControls() {
return React.useContext(LightboxControlContext)
}

View file

@ -1,6 +1,6 @@
import React from 'react'
import {AppBskyActorDefs, AppBskyGraphDefs, ModerationUI} from '@atproto/api'
import {StyleProp, ViewStyle, DeviceEventEmitter} from 'react-native'
import {StyleProp, ViewStyle} from 'react-native'
import {Image as RNImage} from 'react-native-image-crop-picker'
import {ImageModel} from '#/state/models/media/image'
@ -232,7 +232,6 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
const openModal = React.useCallback(
(modal: Modal) => {
DeviceEventEmitter.emit('navigation')
setActiveModals(activeModals => [...activeModals, modal])
setIsModalActive(true)
},

View file

@ -1,4 +1,3 @@
import {AppBskyActorDefs} from '@atproto/api'
import {RootStoreModel} from '../root-store'
import {makeAutoObservable} from 'mobx'
import {
@ -13,34 +12,7 @@ export function isColorMode(v: unknown): v is ColorMode {
return v === 'system' || v === 'light' || v === 'dark'
}
interface LightboxModel {}
export class ProfileImageLightbox implements LightboxModel {
name = 'profile-image'
constructor(public profile: AppBskyActorDefs.ProfileViewDetailed) {
makeAutoObservable(this)
}
}
interface ImagesLightboxItem {
uri: string
alt?: string
}
export class ImagesLightbox implements LightboxModel {
name = 'images'
constructor(public images: ImagesLightboxItem[], public index: number) {
makeAutoObservable(this)
}
setIndex(index: number) {
this.index = index
}
}
export class ShellUiModel {
isLightboxActive = false
activeLightbox: ProfileImageLightbox | ImagesLightbox | null = null
constructor(public rootStore: RootStoreModel) {
makeAutoObservable(this, {
rootStore: false,
@ -54,32 +26,13 @@ export class ShellUiModel {
* (used by the android hardware back btn)
*/
closeAnyActiveElement(): boolean {
if (this.isLightboxActive) {
this.closeLightbox()
return true
}
return false
}
/**
* used to clear out any modals, eg for a navigation
*/
closeAllActiveElements() {
if (this.isLightboxActive) {
this.closeLightbox()
}
}
openLightbox(lightbox: ProfileImageLightbox | ImagesLightbox) {
this.rootStore.emitNavigation()
this.isLightboxActive = true
this.activeLightbox = lightbox
}
closeLightbox() {
this.isLightboxActive = false
this.activeLightbox = null
}
closeAllActiveElements() {}
setupLoginModals() {
this.rootStore.onSessionReady(() => {