blob: 9ce9b66352510cfc0fc1a7bd456cbc38050277ae (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
import {AppBskyEmbedRecord, AppBskyActorDefs} from '@atproto/api'
import {RootStoreModel} from '../root-store'
import {makeAutoObservable, runInAction} from 'mobx'
import {
shouldRequestEmailConfirmation,
setEmailConfirmationRequested,
} from '#/state/shell/reminders'
import {unstable__openModal} from '#/state/modals'
export type ColorMode = 'system' | 'light' | 'dark'
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 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) {
makeAutoObservable(this, {
rootStore: false,
})
this.setupClock()
this.setupLoginModals()
}
/**
* returns true if something was closed
* (used by the android hardware back btn)
*/
closeAnyActiveElement(): boolean {
if (this.isLightboxActive) {
this.closeLightbox()
return true
}
if (this.isComposerActive) {
this.closeComposer()
return true
}
return false
}
/**
* used to clear out any modals, eg for a navigation
*/
closeAllActiveElements() {
if (this.isLightboxActive) {
this.closeLightbox()
}
if (this.isComposerActive) {
this.closeComposer()
}
}
openLightbox(lightbox: ProfileImageLightbox | ImagesLightbox) {
this.rootStore.emitNavigation()
this.isLightboxActive = true
this.activeLightbox = lightbox
}
closeLightbox() {
this.isLightboxActive = false
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(() => {
this.tickEveryMinute = Date.now()
})
}, 60_000)
}
setupLoginModals() {
this.rootStore.onSessionReady(() => {
if (shouldRequestEmailConfirmation(this.rootStore.session)) {
unstable__openModal({name: 'verify-email', showReminder: true})
setEmailConfirmationRequested()
}
})
}
}
|