tangled
alpha
login
or
join now
robinwobin.dev
/
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
Bandcamp embed (#9445)
authored by
samuel.fm
and committed by
GitHub
4 weeks ago
c83dddce
79542897
+67
-14
4 changed files
expand all
collapse all
unified
split
__tests__
lib
string.test.ts
src
components
dialogs
EmbedConsent.tsx
lib
strings
embed-player.ts
state
persisted
schema.ts
+24
__tests__/lib/string.test.ts
···
437
437
438
438
'https://www.flickr.com/groups/898944@N23/',
439
439
'https://www.flickr.com/groups',
440
440
+
441
441
+
'https://maxblansjaar.bandcamp.com/album/false-comforts',
442
442
+
'https://grmnygrmny.bandcamp.com/track/fluid',
443
443
+
'https://sufjanstevens.bandcamp.com/',
444
444
+
'https://sufjanstevens.bandcamp.com',
445
445
+
'https://bandcamp.com/',
446
446
+
'https://bandcamp.com',
440
447
]
441
448
442
449
const outputs = [
···
813
820
playerUri: 'https://embedr.flickr.com/groups/898944@N23',
814
821
},
815
822
823
823
+
undefined,
824
824
+
undefined,
825
825
+
826
826
+
{
827
827
+
type: 'bandcamp_album',
828
828
+
source: 'bandcamp',
829
829
+
playerUri:
830
830
+
'https://bandcamp.com/EmbeddedPlayer/url=https%3A%2F%2Fmaxblansjaar.bandcamp.com%2Falbum%2Ffalse-comforts/size=large/bgcol=ffffff/linkcol=0687f5/minimal=true/transparent=true/',
831
831
+
},
832
832
+
{
833
833
+
type: 'bandcamp_track',
834
834
+
source: 'bandcamp',
835
835
+
playerUri:
836
836
+
'https://bandcamp.com/EmbeddedPlayer/url=https%3A%2F%2Fgrmnygrmny.bandcamp.com%2Ftrack%2Ffluid/size=large/bgcol=ffffff/linkcol=0687f5/minimal=true/transparent=true/',
837
837
+
},
838
838
+
undefined,
839
839
+
undefined,
816
840
undefined,
817
841
undefined,
818
842
]
+9
-14
src/components/dialogs/EmbedConsent.tsx
···
9
9
externalEmbedLabels,
10
10
} from '#/lib/strings/embed-player'
11
11
import {useSetExternalEmbedPref} from '#/state/preferences'
12
12
-
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
12
12
+
import {atoms as a, web} from '#/alf'
13
13
+
import {Admonition} from '#/components/Admonition'
13
14
import {Button, ButtonText} from '#/components/Button'
14
15
import * as Dialog from '#/components/Dialog'
15
16
import {Text} from '#/components/Typography'
···
24
25
onAccept: () => void
25
26
}) {
26
27
const {_} = useLingui()
27
27
-
const t = useTheme()
28
28
const setExternalEmbedPref = useSetExternalEmbedPref()
29
29
-
const {gtMobile} = useBreakpoints()
30
29
31
30
const onShowAllPress = useCallback(() => {
32
31
for (const key of embedPlayerSources) {
···
52
51
<Dialog.Handle />
53
52
<Dialog.ScrollableInner
54
53
label={_(msg`External Media`)}
55
55
-
style={[gtMobile ? {width: 'auto', maxWidth: 400} : a.w_full]}>
54
54
+
style={web({maxWidth: 400})}>
56
55
<View style={a.gap_sm}>
57
57
-
<Text style={[a.text_2xl, a.font_semi_bold]}>
56
56
+
<Text style={[a.text_2xl, a.font_bold]}>
58
57
<Trans>External Media</Trans>
59
58
</Text>
60
59
61
60
<View style={[a.mt_sm, a.mb_2xl, a.gap_lg]}>
62
62
-
<Text>
61
61
+
<Text style={[a.text_md, a.leading_snug]}>
63
62
<Trans>
64
63
This content is hosted by {externalEmbedLabels[source]}. Do you
65
64
want to enable external media?
66
65
</Trans>
67
66
</Text>
68
67
69
69
-
<Text style={t.atoms.text_contrast_medium}>
68
68
+
<Admonition type="info">
70
69
<Trans>
71
70
External media may allow websites to collect information about
72
71
you and your device. No information is sent or requested until
73
72
you press the "play" button.
74
73
</Trans>
75
75
-
</Text>
74
74
+
</Admonition>
76
75
</View>
77
76
</View>
78
77
<View style={a.gap_md}>
79
78
<Button
80
80
-
style={gtMobile && a.flex_1}
81
79
label={_(msg`Enable external media`)}
82
80
onPress={onShowAllPress}
83
81
onAccessibilityEscape={control.close}
84
82
color="primary"
85
85
-
size="large"
86
86
-
variant="solid">
83
83
+
size="large">
87
84
<ButtonText>
88
85
<Trans>Enable external media</Trans>
89
86
</ButtonText>
90
87
</Button>
91
88
<Button
92
92
-
style={gtMobile && a.flex_1}
93
89
label={_(msg`Enable this source only`)}
94
90
onPress={onShowPress}
95
91
onAccessibilityEscape={control.close}
96
92
color="secondary"
97
97
-
size="large"
98
98
-
variant="solid">
93
93
+
size="large">
99
94
<ButtonText>
100
95
<Trans>Enable {externalEmbedLabels[source]} only</Trans>
101
96
</ButtonText>
+33
src/lib/strings/embed-player.ts
···
24
24
'giphy',
25
25
'tenor',
26
26
'flickr',
27
27
+
'bandcamp',
27
28
] as const
28
29
29
30
export type EmbedPlayerSource = (typeof embedPlayerSources)[number]
···
44
45
| 'giphy_gif'
45
46
| 'tenor_gif'
46
47
| 'flickr_album'
48
48
+
| 'bandcamp_album'
49
49
+
| 'bandcamp_track'
47
50
48
51
export const externalEmbedLabels: Record<EmbedPlayerSource, string> = {
49
52
youtube: 'YouTube',
···
56
59
appleMusic: 'Apple Music',
57
60
soundcloud: 'SoundCloud',
58
61
flickr: 'Flickr',
62
62
+
bandcamp: 'Bandcamp',
59
63
}
60
64
61
65
export interface EmbedPlayerParams {
···
459
463
return undefined
460
464
}
461
465
}
466
466
+
467
467
+
const bandcampRegex = /^[a-z\d][a-z\d-]{2,}[a-z\d]\.bandcamp\.com$/i
468
468
+
469
469
+
if (bandcampRegex.test(urlp.hostname)) {
470
470
+
const pathComponents = urlp.pathname.split('/')
471
471
+
switch (pathComponents[1]) {
472
472
+
case 'album':
473
473
+
return {
474
474
+
type: 'bandcamp_album',
475
475
+
source: 'bandcamp',
476
476
+
playerUri: `https://bandcamp.com/EmbeddedPlayer/url=${encodeURIComponent(
477
477
+
urlp.href,
478
478
+
)}/size=large/bgcol=ffffff/linkcol=0687f5/minimal=true/transparent=true/`,
479
479
+
}
480
480
+
case 'track':
481
481
+
return {
482
482
+
type: 'bandcamp_track',
483
483
+
source: 'bandcamp',
484
484
+
playerUri: `https://bandcamp.com/EmbeddedPlayer/url=${encodeURIComponent(
485
485
+
urlp.href,
486
486
+
)}/size=large/bgcol=ffffff/linkcol=0687f5/minimal=true/transparent=true/`,
487
487
+
}
488
488
+
default:
489
489
+
return undefined
490
490
+
}
491
491
+
}
462
492
}
463
493
464
494
export function getPlayerAspect({
···
498
528
return {height: 165}
499
529
case 'apple_music_song':
500
530
return {height: 150}
531
531
+
case 'bandcamp_album':
532
532
+
case 'bandcamp_track':
533
533
+
return {aspectRatio: 1}
501
534
default:
502
535
return {aspectRatio: 16 / 9}
503
536
}
+1
src/state/persisted/schema.ts
···
106
106
appleMusic: z.enum(externalEmbedOptions).optional(),
107
107
soundcloud: z.enum(externalEmbedOptions).optional(),
108
108
flickr: z.enum(externalEmbedOptions).optional(),
109
109
+
bandcamp: z.enum(externalEmbedOptions).optional(),
109
110
})
110
111
.optional(),
111
112
invites: z.object({