forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {msg} from '@lingui/core/macro'
2import {useLingui} from '@lingui/react'
3import {Trans} from '@lingui/react/macro'
4
5import {useEnableSquareButtons} from '#/state/preferences/enable-square-buttons'
6import {atoms as a} from '#/alf'
7import {Button, ButtonText} from '#/components/Button'
8import * as Dialog from '#/components/Dialog'
9import * as Prompt from '#/components/Prompt'
10import {useAnalytics} from '#/analytics'
11import {DraftsListDialog} from './DraftsListDialog'
12import {useSaveDraftMutation} from './state/queries'
13import {type DraftSummary} from './state/schema'
14
15export function DraftsButton({
16 onSelectDraft,
17 onSaveDraft,
18 onDiscard,
19 isEmpty,
20 isDirty,
21 isEditingDraft,
22 canSaveDraft,
23 textLength,
24}: {
25 onSelectDraft: (draft: DraftSummary) => void
26 onSaveDraft: () => Promise<{success: boolean}>
27 onDiscard: () => void
28 isEmpty: boolean
29 isDirty: boolean
30 isEditingDraft: boolean
31 canSaveDraft: boolean
32 textLength: number
33}) {
34 const {_} = useLingui()
35 const enableSquareButtons = useEnableSquareButtons()
36 const ax = useAnalytics()
37 const draftsDialogControl = Dialog.useDialogControl()
38 const savePromptControl = Prompt.usePromptControl()
39 const {isPending: isSaving} = useSaveDraftMutation()
40
41 const handlePress = () => {
42 if (isEmpty || !isDirty) {
43 // Composer is empty or has no unsaved changes, go directly to drafts list
44 draftsDialogControl.open()
45 } else {
46 // Composer has unsaved changes, ask what to do
47 savePromptControl.open()
48 }
49 }
50
51 const handleSaveAndOpen = async () => {
52 const {success} = await onSaveDraft()
53 if (success) {
54 draftsDialogControl.open()
55 }
56 }
57
58 const handleDiscardAndOpen = () => {
59 // Fire draft:discard metric before discarding
60 ax.metric('draft:discard', {
61 logContext: 'BeforeDraftsList',
62 hadContent: !isEmpty,
63 textLength,
64 })
65 onDiscard()
66 draftsDialogControl.open()
67 }
68
69 return (
70 <>
71 <Button
72 label={_(msg`Drafts`)}
73 variant="ghost"
74 color="primary"
75 shape="default"
76 size="small"
77 style={[
78 enableSquareButtons ? a.rounded_sm : a.rounded_full,
79 a.py_sm,
80 a.px_md,
81 a.mx_xs,
82 ]}
83 disabled={isSaving}
84 onPress={handlePress}>
85 <ButtonText style={[a.text_md]}>
86 <Trans>Drafts</Trans>
87 </ButtonText>
88 </Button>
89
90 <DraftsListDialog
91 control={draftsDialogControl}
92 onSelectDraft={onSelectDraft}
93 />
94
95 <Prompt.Outer control={savePromptControl}>
96 <Prompt.Content>
97 <Prompt.TitleText>
98 {canSaveDraft ? (
99 isEditingDraft ? (
100 <Trans>Save changes?</Trans>
101 ) : (
102 <Trans>Save draft?</Trans>
103 )
104 ) : (
105 <Trans>Discard draft?</Trans>
106 )}
107 </Prompt.TitleText>
108 </Prompt.Content>
109 <Prompt.DescriptionText>
110 {canSaveDraft ? (
111 isEditingDraft ? (
112 <Trans>
113 You have unsaved changes. Would you like to save them before
114 viewing your drafts?
115 </Trans>
116 ) : (
117 <Trans>
118 Would you like to save this as a draft before viewing your
119 drafts?
120 </Trans>
121 )
122 ) : (
123 <Trans>
124 You can only save drafts up to 1000 characters. Would you like to
125 discard this post before viewing your drafts?
126 </Trans>
127 )}
128 </Prompt.DescriptionText>
129 <Prompt.Actions>
130 {canSaveDraft && (
131 <Prompt.Action
132 cta={isEditingDraft ? _(msg`Save changes`) : _(msg`Save draft`)}
133 onPress={handleSaveAndOpen}
134 color="primary"
135 />
136 )}
137 <Prompt.Action
138 cta={_(msg`Discard`)}
139 onPress={handleDiscardAndOpen}
140 color="negative_subtle"
141 />
142 <Prompt.Cancel cta={_(msg`Keep editing`)} />
143 </Prompt.Actions>
144 </Prompt.Outer>
145 </>
146 )
147}