tangled
alpha
login
or
join now
bas.sh
/
witchsky.app
forked from
jollywhoppers.com/witchsky.app
0
fork
atom
Bluesky app fork with some witchin' additions 💫
0
fork
atom
overview
issues
pulls
pipelines
antlers PDSls & bridged share buttons
xan.lol
4 months ago
c416f4af
0cb096c0
verified
This commit was signed with the committer's
known signature
.
xan.lol
SSH Key Fingerprint:
SHA256:7Zs+dcly5YqxBg7v8XsE1uPMYCobHKBw7CDiNxpmSrY=
+201
-25
6 changed files
expand all
collapse all
unified
split
src
components
PostControls
ShareMenu
ShareMenuItems.tsx
ShareMenuItems.web.tsx
screens
Settings
DeerSettings.tsx
state
persisted
schema.ts
preferences
external-share-buttons.tsx
index.tsx
+44
src/components/PostControls/ShareMenu/ShareMenuItems.tsx
···
5
5
import {useLingui} from '@lingui/react'
6
6
import {useNavigation} from '@react-navigation/native'
7
7
8
8
+
import {useOpenLink} from '#/lib/hooks/useOpenLink'
8
9
import {makeProfileLink} from '#/lib/routes/links'
9
10
import {type NavigationProp} from '#/lib/routes/types'
10
11
import {shareText, shareUrl} from '#/lib/sharing'
···
13
14
import {isIOS} from '#/platform/detection'
14
15
import {useAgeAssurance} from '#/state/ageAssurance/useAgeAssurance'
15
16
import {useProfileShadow} from '#/state/cache/profile-shadow'
17
17
+
import {useShowExternalShareButtons} from '#/state/preferences/external-share-buttons'
16
18
import {useSession} from '#/state/session'
17
19
import * as Toast from '#/view/com/util/Toast'
18
20
import {atoms as a} from '#/alf'
···
23
25
import {ChainLink_Stroke2_Corner0_Rounded as ChainLinkIcon} from '#/components/icons/ChainLink'
24
26
import {Clipboard_Stroke2_Corner2_Rounded as ClipboardIcon} from '#/components/icons/Clipboard'
25
27
import {PaperPlane_Stroke2_Corner0_Rounded as PaperPlaneIcon} from '#/components/icons/PaperPlane'
28
28
+
import {SquareArrowTopRight_Stroke2_Corner0_Rounded as ExternalIcon} from '#/components/icons/SquareArrowTopRight'
26
29
import * as Menu from '#/components/Menu'
27
30
import {useDevMode} from '#/storage/hooks/dev-mode'
28
31
import {RecentChats} from './RecentChats'
···
38
41
const sendViaChatControl = useDialogControl()
39
42
const [devModeEnabled] = useDevMode()
40
43
const {isAgeRestricted} = useAgeAssurance()
44
44
+
const openLink = useOpenLink()
41
45
42
46
const postUri = post.uri
43
47
const postAuthor = useProfileShadow(post.author)
···
108
112
shareText(postAuthor.did)
109
113
}
110
114
115
115
+
const showExternalShareButtons = useShowExternalShareButtons()
116
116
+
const isBridgedPost =
117
117
+
!!post.record.bridgyOriginalUrl || !!post.record.fediverseId
118
118
+
const originalPostUrl = (post.record.bridgyOriginalUrl ||
119
119
+
post.record.fediverseId) as string | undefined
120
120
+
121
121
+
const onOpenOriginalPost = () => {
122
122
+
originalPostUrl && openLink(originalPostUrl, true)
123
123
+
}
124
124
+
125
125
+
const onOpenPostInPdsls = () => {
126
126
+
openLink(`https://pdsls.dev/${post.uri}`, true)
127
127
+
}
128
128
+
111
129
return (
112
130
<>
113
131
<Menu.Outer>
···
127
145
<Trans>Send via direct message</Trans>
128
146
</Menu.ItemText>
129
147
<Menu.ItemIcon icon={PaperPlaneIcon} position="right" />
148
148
+
</Menu.Item>
149
149
+
</Menu.Group>
150
150
+
)}
151
151
+
152
152
+
{showExternalShareButtons && (
153
153
+
<Menu.Group>
154
154
+
{isBridgedPost && (
155
155
+
<Menu.Item
156
156
+
testID="postDropdownOpenOriginalPost"
157
157
+
label={_(msg`Open original post`)}
158
158
+
onPress={onOpenOriginalPost}>
159
159
+
<Menu.ItemText>
160
160
+
<Trans>Open original post</Trans>
161
161
+
</Menu.ItemText>
162
162
+
<Menu.ItemIcon icon={ExternalIcon} position="right" />
163
163
+
</Menu.Item>
164
164
+
)}
165
165
+
166
166
+
<Menu.Item
167
167
+
testID="postDropdownOpenInPdsls"
168
168
+
label={_(msg`Open post in PDSls`)}
169
169
+
onPress={onOpenPostInPdsls}>
170
170
+
<Menu.ItemText>
171
171
+
<Trans>Open post in PDSls</Trans>
172
172
+
</Menu.ItemText>
173
173
+
<Menu.ItemIcon icon={ExternalIcon} position="right" />
130
174
</Menu.Item>
131
175
</Menu.Group>
132
176
)}
+42
src/components/PostControls/ShareMenu/ShareMenuItems.web.tsx
···
4
4
import {useLingui} from '@lingui/react'
5
5
import {useNavigation} from '@react-navigation/native'
6
6
7
7
+
import {useOpenLink} from '#/lib/hooks/useOpenLink'
7
8
import {makeProfileLink} from '#/lib/routes/links'
8
9
import {type NavigationProp} from '#/lib/routes/types'
9
10
import {shareText, shareUrl} from '#/lib/sharing'
···
12
13
import {isWeb} from '#/platform/detection'
13
14
import {useAgeAssurance} from '#/state/ageAssurance/useAgeAssurance'
14
15
import {useProfileShadow} from '#/state/cache/profile-shadow'
16
16
+
import {useShowExternalShareButtons} from '#/state/preferences/external-share-buttons'
15
17
import {useSession} from '#/state/session'
16
18
import {useBreakpoints} from '#/alf'
17
19
import {useDialogControl} from '#/components/Dialog'
···
21
23
import {Clipboard_Stroke2_Corner2_Rounded as ClipboardIcon} from '#/components/icons/Clipboard'
22
24
import {CodeBrackets_Stroke2_Corner0_Rounded as CodeBracketsIcon} from '#/components/icons/CodeBrackets'
23
25
import {PaperPlane_Stroke2_Corner0_Rounded as Send} from '#/components/icons/PaperPlane'
26
26
+
import {SquareArrowTopRight_Stroke2_Corner0_Rounded as ExternalIcon} from '#/components/icons/SquareArrowTopRight'
24
27
import * as Menu from '#/components/Menu'
25
28
import {useDevMode} from '#/storage/hooks/dev-mode'
26
29
import {type ShareMenuItemsProps} from './ShareMenuItems.types'
···
39
42
const sendViaChatControl = useDialogControl()
40
43
const [devModeEnabled] = useDevMode()
41
44
const {isAgeRestricted} = useAgeAssurance()
45
45
+
const openLink = useOpenLink()
42
46
43
47
const postUri = post.uri
44
48
const postCid = post.cid
···
87
91
shareText(postAuthor.did)
88
92
}
89
93
94
94
+
const showExternalShareButtons = useShowExternalShareButtons()
95
95
+
const isBridgedPost =
96
96
+
!!post.record.bridgyOriginalUrl || !!post.record.fediverseId
97
97
+
const originalPostUrl = (post.record.bridgyOriginalUrl ||
98
98
+
post.record.fediverseId) as string | undefined
99
99
+
100
100
+
const onOpenOriginalPost = () => {
101
101
+
originalPostUrl && openLink(originalPostUrl, true)
102
102
+
}
103
103
+
104
104
+
const onOpenPostInPdsls = () => {
105
105
+
openLink(`https://pdsls.dev/${post.uri}`, true)
106
106
+
}
107
107
+
90
108
const copyLinkItem = (
91
109
<Menu.Group>
92
110
<Menu.Item
···
114
132
<>
115
133
<Menu.Outer>
116
134
{copyLinkItem}
135
135
+
136
136
+
{showExternalShareButtons && isBridgedPost && (
137
137
+
<Menu.Item
138
138
+
testID="postDropdownOpenOriginalPost"
139
139
+
label={_(msg`Open original post`)}
140
140
+
onPress={onOpenOriginalPost}>
141
141
+
<Menu.ItemText>
142
142
+
<Trans>Open original post</Trans>
143
143
+
</Menu.ItemText>
144
144
+
<Menu.ItemIcon icon={ExternalIcon} position="right" />
145
145
+
</Menu.Item>
146
146
+
)}
147
147
+
148
148
+
{showExternalShareButtons && (
149
149
+
<Menu.Item
150
150
+
testID="postDropdownOpenInPdsls"
151
151
+
label={_(msg`Open post in PDSls`)}
152
152
+
onPress={onOpenPostInPdsls}>
153
153
+
<Menu.ItemText>
154
154
+
<Trans>Open post in PDSls</Trans>
155
155
+
</Menu.ItemText>
156
156
+
<Menu.ItemIcon icon={ExternalIcon} position="right" />
157
157
+
</Menu.Item>
158
158
+
)}
117
159
118
160
{hasSession && !isAgeRestricted && (
119
161
<Menu.Item
+30
src/screens/Settings/DeerSettings.tsx
···
87
87
useShowLinkInHandle,
88
88
} from '#/state/preferences/show-link-in-handle.tsx'
89
89
import {useProfilesQuery} from '#/state/queries/profile'
90
90
+
import {
91
91
+
useSetShowExternalShareButtons,
92
92
+
useShowExternalShareButtons,
93
93
+
} from '#/state/preferences/external-share-buttons'
90
94
import * as SettingsList from '#/screens/Settings/components/SettingsList'
91
95
import {atoms as a, useBreakpoints} from '#/alf'
92
96
import {Admonition} from '#/components/Admonition'
···
94
98
import * as Dialog from '#/components/Dialog'
95
99
import * as Toggle from '#/components/forms/Toggle'
96
100
import {Atom_Stroke2_Corner0_Rounded as DeerIcon} from '#/components/icons/Atom'
101
101
+
import {ChainLink_Stroke2_Corner0_Rounded as ChainLinkIcon} from '#/components/icons/ChainLink'
97
102
import {Eye_Stroke2_Corner0_Rounded as VisibilityIcon} from '#/components/icons/Eye'
98
103
import {Lab_Stroke2_Corner0_Rounded as BeakerIcon} from '#/components/icons/Lab'
99
104
import {PaintRoller_Stroke2_Corner2_Rounded as PaintRollerIcon} from '#/components/icons/PaintRoller'
···
243
248
const directFetchRecords = useDirectFetchRecords()
244
249
const setDirectFetchRecords = useSetDirectFetchRecords()
245
250
251
251
+
const showExternalShareButtons = useShowExternalShareButtons()
252
252
+
const setShowExternalShareButtons = useSetShowExternalShareButtons()
253
253
+
246
254
const noAppLabelers = useNoAppLabelers()
247
255
const setNoAppLabelers = useSetNoAppLabelers()
248
256
···
348
356
<Trans>
349
357
Fetch records directly from PDS to see contents of blocked and
350
358
detatched quotes
359
359
+
</Trans>
360
360
+
</Toggle.LabelText>
361
361
+
<Toggle.Platform />
362
362
+
</Toggle.Item>
363
363
+
</SettingsList.Group>
364
364
+
365
365
+
<SettingsList.Group contentContainerStyle={[a.gap_sm]}>
366
366
+
<SettingsList.ItemIcon icon={ChainLinkIcon} />
367
367
+
<SettingsList.ItemText>
368
368
+
<Trans>Bridging and Fediverse</Trans>
369
369
+
</SettingsList.ItemText>
370
370
+
<Toggle.Item
371
371
+
name="external_share_buttons"
372
372
+
label={_(
373
373
+
msg`Show "Open original post" and "Open post in PDSls" buttons`,
374
374
+
)}
375
375
+
value={showExternalShareButtons}
376
376
+
onChange={value => setShowExternalShareButtons(value)}
377
377
+
style={[a.w_full]}>
378
378
+
<Toggle.LabelText style={[a.flex_1]}>
379
379
+
<Trans>
380
380
+
Show "Open original post" and "Open post in PDSls" buttons
351
381
</Trans>
352
382
</Toggle.LabelText>
353
383
<Toggle.Platform />
+3
src/state/persisted/schema.ts
···
149
149
.optional(),
150
150
highQualityImages: z.boolean().optional(),
151
151
152
152
+
showExternalShareButtons: z.boolean().optional(),
153
153
+
152
154
/** @deprecated */
153
155
mutedThreads: z.array(z.string()),
154
156
trendingDisabled: z.boolean().optional(),
···
240
242
],
241
243
},
242
244
highQualityImages: false,
245
245
+
showExternalShareButtons: false,
243
246
}
244
247
245
248
export function tryParse(rawData: string): Schema | undefined {
+54
src/state/preferences/external-share-buttons.tsx
···
1
1
+
import React from 'react'
2
2
+
3
3
+
import * as persisted from '#/state/persisted'
4
4
+
5
5
+
type StateContext = persisted.Schema['showExternalShareButtons']
6
6
+
type SetContext = (v: persisted.Schema['showExternalShareButtons']) => void
7
7
+
8
8
+
const stateContext = React.createContext<StateContext>(
9
9
+
persisted.defaults.showExternalShareButtons,
10
10
+
)
11
11
+
const setContext = React.createContext<SetContext>(
12
12
+
(_: persisted.Schema['showExternalShareButtons']) => {},
13
13
+
)
14
14
+
15
15
+
export function Provider({children}: React.PropsWithChildren<{}>) {
16
16
+
const [state, setState] = React.useState(
17
17
+
persisted.get('showExternalShareButtons'),
18
18
+
)
19
19
+
20
20
+
const setStateWrapped = React.useCallback(
21
21
+
(
22
22
+
showExternalShareButtons: persisted.Schema['showExternalShareButtons'],
23
23
+
) => {
24
24
+
setState(showExternalShareButtons)
25
25
+
persisted.write('showExternalShareButtons', showExternalShareButtons)
26
26
+
},
27
27
+
[setState],
28
28
+
)
29
29
+
30
30
+
React.useEffect(() => {
31
31
+
return persisted.onUpdate(
32
32
+
'showExternalShareButtons',
33
33
+
nextShowExternalShareButtons => {
34
34
+
setState(nextShowExternalShareButtons)
35
35
+
},
36
36
+
)
37
37
+
}, [setStateWrapped])
38
38
+
39
39
+
return (
40
40
+
<stateContext.Provider value={state}>
41
41
+
<setContext.Provider value={setStateWrapped}>
42
42
+
{children}
43
43
+
</setContext.Provider>
44
44
+
</stateContext.Provider>
45
45
+
)
46
46
+
}
47
47
+
48
48
+
export function useShowExternalShareButtons() {
49
49
+
return React.useContext(stateContext)
50
50
+
}
51
51
+
52
52
+
export function useSetShowExternalShareButtons() {
53
53
+
return React.useContext(setContext)
54
54
+
}
+28
-25
src/state/preferences/index.tsx
···
14
14
import {Provider as DisableSavesMetricsProvider} from './disable-saves-metrics'
15
15
import {Provider as DisableViaRepostNotificationProvider} from './disable-via-repost-notification'
16
16
import {Provider as ExternalEmbedsProvider} from './external-embeds-prefs'
17
17
+
import {Provider as ExternalShareButtonsProvider} from './external-share-buttons'
17
18
import {Provider as GoLinksProvider} from './go-links-enabled'
18
19
import {Provider as HiddenPostsProvider} from './hidden-posts'
19
20
import {Provider as HideFeedsPromoTabProvider} from './hide-feeds-promo-tab'
···
55
56
return (
56
57
<LanguagesProvider>
57
58
<AltTextRequiredProvider>
58
58
-
<GoLinksProvider>
59
59
+
<ExternalShareButtonsProvider>
60
60
+
<GoLinksProvider>
59
61
<NoAppLabelersProvider>
60
60
-
<DirectFetchRecordsProvider>
61
61
-
<ConstellationProvider>
62
62
+
<DirectFetchRecordsProvider>
63
63
+
<ConstellationProvider>
62
64
<ConstellationInstanceProvider>
63
65
<DeerVerificationProvider>
64
66
<NoDiscoverProvider>
65
67
<ShowLinkInHandleProvider>
66
66
-
<LargeAltBadgeProvider>
67
67
-
<ExternalEmbedsProvider>
68
68
-
<HiddenPostsProvider>
68
68
+
<LargeAltBadgeProvider>
69
69
+
<ExternalEmbedsProvider>
70
70
+
<HiddenPostsProvider>
69
71
<HighQualityImagesProvider>
70
70
-
<InAppBrowserProvider>
71
71
-
<DisableHapticsProvider>
72
72
-
<AutoplayProvider>
73
73
-
<UsedStarterPacksProvider>
74
74
-
<SubtitlesProvider>
75
75
-
<TrendingSettingsProvider>
76
76
-
<RepostCarouselProvider>
72
72
+
<InAppBrowserProvider>
73
73
+
<DisableHapticsProvider>
74
74
+
<AutoplayProvider>
75
75
+
<UsedStarterPacksProvider>
76
76
+
<SubtitlesProvider>
77
77
+
<TrendingSettingsProvider>
78
78
+
<RepostCarouselProvider>
77
79
<KawaiiProvider>
78
80
<HideFeedsPromoTabProvider>
79
81
<DisableViaRepostNotificationProvider>
···
94
96
</HideFeedsPromoTabProvider>
95
97
</KawaiiProvider>
96
98
</RepostCarouselProvider>
97
97
-
</TrendingSettingsProvider>
98
98
-
</SubtitlesProvider>
99
99
-
</UsedStarterPacksProvider>
100
100
-
</AutoplayProvider>
101
101
-
</DisableHapticsProvider>
102
102
-
</InAppBrowserProvider>
99
99
+
</TrendingSettingsProvider>
100
100
+
</SubtitlesProvider>
101
101
+
</UsedStarterPacksProvider>
102
102
+
</AutoplayProvider>
103
103
+
</DisableHapticsProvider>
104
104
+
</InAppBrowserProvider>
103
105
</HighQualityImagesProvider>
104
104
-
</HiddenPostsProvider>
105
105
-
</ExternalEmbedsProvider>
106
106
-
</LargeAltBadgeProvider>
106
106
+
</HiddenPostsProvider>
107
107
+
</ExternalEmbedsProvider>
108
108
+
</LargeAltBadgeProvider>
107
109
</ShowLinkInHandleProvider>
108
110
</NoDiscoverProvider>
109
111
</DeerVerificationProvider>
110
112
</ConstellationInstanceProvider>
111
111
-
</ConstellationProvider>
112
112
-
</DirectFetchRecordsProvider>
113
113
+
</ConstellationProvider>
114
114
+
</DirectFetchRecordsProvider>
113
115
</NoAppLabelersProvider>
114
114
-
</GoLinksProvider>
116
116
+
</GoLinksProvider>
117
117
+
</ExternalShareButtonsProvider>
115
118
</AltTextRequiredProvider>
116
119
</LanguagesProvider>
117
120
)