forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1/* eslint-disable bsky-internal/avoid-unwrapped-text */
2import React from 'react'
3import {AppBskyGraphDefs, AppBskyGraphStarterpack} from '@atproto/api'
4
5import {Butterfly} from './Butterfly.js'
6import {Img} from './Img.js'
7
8export const STARTERPACK_HEIGHT = 630
9export const STARTERPACK_WIDTH = 1200
10export const TILE_SIZE = STARTERPACK_HEIGHT / 3
11
12const GRADIENT_TOP = '#0A7AFF'
13const GRADIENT_BOTTOM = '#59B9FF'
14const IMAGE_STROKE = '#359CFF'
15
16export function StarterPack(props: {
17 starterPack: AppBskyGraphDefs.StarterPackView
18 images: Map<string, Buffer>
19}) {
20 const {starterPack, images} = props
21 const record = AppBskyGraphStarterpack.isRecord(starterPack.record)
22 ? starterPack.record
23 : null
24 const imagesArray = [...images.values()]
25 const imageOfCreator = images.get(starterPack.creator.did)
26 const imagesExceptCreator = [...images.entries()]
27 .filter(([did]) => did !== starterPack.creator.did)
28 .map(([, image]) => image)
29 const imagesAcross: Buffer[] = []
30 if (imageOfCreator) {
31 if (imagesExceptCreator.length >= 6) {
32 imagesAcross.push(...imagesExceptCreator.slice(0, 3))
33 imagesAcross.push(imageOfCreator)
34 imagesAcross.push(...imagesExceptCreator.slice(3, 6))
35 } else {
36 const firstHalf = Math.floor(imagesExceptCreator.length / 2)
37 imagesAcross.push(...imagesExceptCreator.slice(0, firstHalf))
38 imagesAcross.push(imageOfCreator)
39 imagesAcross.push(
40 ...imagesExceptCreator.slice(firstHalf, imagesExceptCreator.length),
41 )
42 }
43 } else {
44 imagesAcross.push(...imagesExceptCreator.slice(0, 7))
45 }
46 const isLongTitle = record ? record.name.length > 30 : false
47 return (
48 <div
49 style={{
50 display: 'flex',
51 justifyContent: 'center',
52 width: STARTERPACK_WIDTH,
53 height: STARTERPACK_HEIGHT,
54 backgroundColor: 'black',
55 color: 'white',
56 fontFamily: 'Inter',
57 }}>
58 {/* image tiles */}
59 <div
60 style={{
61 display: 'flex',
62 flexWrap: 'wrap',
63 alignItems: 'stretch',
64 width: TILE_SIZE * 6,
65 height: TILE_SIZE * 3,
66 }}>
67 {[...Array(18)].map((_, i) => {
68 const image = imagesArray.at(i % imagesArray.length)
69 return (
70 <div
71 key={i}
72 style={{
73 display: 'flex',
74 height: TILE_SIZE,
75 width: TILE_SIZE,
76 }}>
77 {image && <Img height="100%" width="100%" src={image} />}
78 </div>
79 )
80 })}
81 {/* background overlay */}
82 <div
83 style={{
84 display: 'flex',
85 width: '100%',
86 height: '100%',
87 position: 'absolute',
88 backgroundImage: `linear-gradient(to bottom, ${GRADIENT_TOP}, ${GRADIENT_BOTTOM})`,
89 opacity: 0.9,
90 }}
91 />
92 </div>
93 {/* foreground text & images */}
94 <div
95 style={{
96 display: 'flex',
97 alignItems: 'center',
98 flexDirection: 'column',
99 width: '100%',
100 height: '100%',
101 position: 'absolute',
102 color: 'white',
103 }}>
104 <div
105 style={{
106 color: 'white',
107 padding: 60,
108 fontSize: 40,
109 }}>
110 JOIN THE CONVERSATION
111 </div>
112 <div style={{display: 'flex'}}>
113 {imagesAcross.map((image, i) => {
114 return (
115 <div
116 key={i}
117 style={{
118 display: 'flex',
119 height: 172 + 15 * 2,
120 width: 172 + 15 * 2,
121 margin: -15,
122 border: `15px solid ${IMAGE_STROKE}`,
123 borderRadius: '50%',
124 overflow: 'hidden',
125 }}>
126 <Img height="100%" width="100%" src={image} />
127 </div>
128 )
129 })}
130 </div>
131 <div
132 style={{
133 padding: '75px 30px 0px',
134 fontSize: isLongTitle ? 55 : 65,
135 display: 'flex',
136 textAlign: 'center',
137 }}>
138 {record?.name || 'Starter Pack'}
139 </div>
140 <div
141 style={{
142 display: 'flex',
143 fontSize: 40,
144 justifyContent: 'center',
145 padding: '30px 30px 10px',
146 }}>
147 on <Butterfly width="65" style={{margin: '-7px 10px 0'}} /> Bluesky
148 </div>
149 </div>
150 </div>
151 )
152}