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