my fork of the bluesky client
1const pkg = require('./package.json')
2
3const SPLASH_CONFIG = {
4 backgroundColor: '#ffffff',
5 image: './assets/splash.png',
6 resizeMode: 'cover',
7}
8const DARK_SPLASH_CONFIG = {
9 backgroundColor: '#001429',
10 image: './assets/splash-dark.png',
11 resizeMode: 'cover',
12}
13
14const SPLASH_CONFIG_ANDROID = {
15 backgroundColor: '#0c7cff',
16 image: './assets/splash.png',
17 resizeMode: 'cover',
18}
19const DARK_SPLASH_CONFIG_ANDROID = {
20 backgroundColor: '#0f141b',
21 image: './assets/splash-dark.png',
22 resizeMode: 'cover',
23}
24
25module.exports = function (config) {
26 /**
27 * App version number. Should be incremented as part of a release cycle.
28 */
29 const VERSION = pkg.version
30
31 /**
32 * Uses built-in Expo env vars
33 *
34 * @see https://docs.expo.dev/build-reference/variables/#built-in-environment-variables
35 */
36 const PLATFORM = process.env.EAS_BUILD_PLATFORM
37
38 const IS_DEV = process.env.EXPO_PUBLIC_ENV === 'development'
39 const IS_TESTFLIGHT = process.env.EXPO_PUBLIC_ENV === 'testflight'
40 const IS_PRODUCTION = process.env.EXPO_PUBLIC_ENV === 'production'
41
42 const ASSOCIATED_DOMAINS = [
43 'applinks:bsky.app',
44 'applinks:staging.bsky.app',
45 'appclips:bsky.app',
46 'appclips:go.bsky.app', // Allows App Clip to work when scanning QR codes
47 // When testing local services, enter an ngrok (et al) domain here. It must use a standard HTTP/HTTPS port.
48 ...(IS_DEV || IS_TESTFLIGHT ? [] : []),
49 ]
50
51 const UPDATES_CHANNEL = IS_TESTFLIGHT
52 ? 'testflight'
53 : IS_PRODUCTION
54 ? 'production'
55 : undefined
56 const UPDATES_ENABLED = !!UPDATES_CHANNEL
57
58 const USE_SENTRY = Boolean(process.env.SENTRY_AUTH_TOKEN)
59 const SENTRY_DIST = `${PLATFORM}.${VERSION}.${IS_TESTFLIGHT ? 'tf' : ''}${
60 IS_DEV ? 'dev' : ''
61 }`
62
63 return {
64 expo: {
65 version: VERSION,
66 name: 'Bluesky',
67 slug: 'bluesky',
68 scheme: 'bluesky',
69 owner: 'blueskysocial',
70 runtimeVersion: {
71 policy: 'appVersion',
72 },
73 orientation: 'portrait',
74 icon: './assets/app-icons/ios_icon_default_light.png',
75 userInterfaceStyle: 'automatic',
76 splash: SPLASH_CONFIG,
77 // hsl(211, 99%, 53%), same as palette.default.brandText
78 primaryColor: '#1083fe',
79 ios: {
80 supportsTablet: false,
81 bundleIdentifier: 'xyz.blueskyweb.app',
82 config: {
83 usesNonExemptEncryption: false,
84 },
85 infoPlist: {
86 UIBackgroundModes: ['remote-notification'],
87 NSCameraUsageDescription:
88 'Used for profile pictures, posts, and other kinds of content.',
89 NSMicrophoneUsageDescription:
90 'Used for posts and other kinds of content.',
91 NSPhotoLibraryAddUsageDescription:
92 'Used to save images to your library.',
93 NSPhotoLibraryUsageDescription:
94 'Used for profile pictures, posts, and other kinds of content',
95 CFBundleSpokenName: 'Blue Sky',
96 CFBundleLocalizations: [
97 'en',
98 'ca',
99 'de',
100 'es',
101 'fi',
102 'fr',
103 'ga',
104 'hi',
105 'hu',
106 'id',
107 'it',
108 'ja',
109 'ko',
110 'pl',
111 'pt',
112 'ru',
113 'th',
114 'tr',
115 'uk',
116 'zh_CN',
117 'zh_HK',
118 'zh_TW',
119 ],
120 },
121 associatedDomains: ASSOCIATED_DOMAINS,
122 splash: {
123 ...SPLASH_CONFIG,
124 dark: DARK_SPLASH_CONFIG,
125 },
126 entitlements: {
127 'com.apple.developer.kernel.increased-memory-limit': true,
128 'com.apple.developer.kernel.extended-virtual-addressing': true,
129 'com.apple.security.application-groups': 'group.app.bsky',
130 },
131 privacyManifests: {
132 NSPrivacyAccessedAPITypes: [
133 {
134 NSPrivacyAccessedAPIType:
135 'NSPrivacyAccessedAPICategoryFileTimestamp',
136 NSPrivacyAccessedAPITypeReasons: ['C617.1', '3B52.1', '0A2A.1'],
137 },
138 {
139 NSPrivacyAccessedAPIType: 'NSPrivacyAccessedAPICategoryDiskSpace',
140 NSPrivacyAccessedAPITypeReasons: ['E174.1', '85F4.1'],
141 },
142 {
143 NSPrivacyAccessedAPIType:
144 'NSPrivacyAccessedAPICategorySystemBootTime',
145 NSPrivacyAccessedAPITypeReasons: ['35F9.1'],
146 },
147 {
148 NSPrivacyAccessedAPIType:
149 'NSPrivacyAccessedAPICategoryUserDefaults',
150 NSPrivacyAccessedAPITypeReasons: ['CA92.1', '1C8F.1'],
151 },
152 ],
153 },
154 },
155 androidStatusBar: {
156 barStyle: 'light-content',
157 backgroundColor: '#00000000',
158 },
159 // Dark nav bar in light mode is better than light nav bar in dark mode
160 androidNavigationBar: {
161 barStyle: 'light-content',
162 backgroundColor: DARK_SPLASH_CONFIG_ANDROID.backgroundColor,
163 },
164 android: {
165 icon: './assets/app-icons/android_icon_default_light.png',
166 adaptiveIcon: {
167 foregroundImage: './assets/icon-android-foreground.png',
168 monochromeImage: './assets/icon-android-foreground.png',
169 backgroundImage: './assets/icon-android-background.png',
170 backgroundColor: '#1185FE',
171 },
172 googleServicesFile: './google-services.json',
173 package: 'xyz.blueskyweb.app',
174 intentFilters: [
175 {
176 action: 'VIEW',
177 autoVerify: true,
178 data: [
179 {
180 scheme: 'https',
181 host: 'bsky.app',
182 },
183 IS_DEV && {
184 scheme: 'http',
185 host: 'localhost:19006',
186 },
187 ],
188 category: ['BROWSABLE', 'DEFAULT'],
189 },
190 ],
191 splash: {
192 ...SPLASH_CONFIG_ANDROID,
193 dark: DARK_SPLASH_CONFIG_ANDROID,
194 },
195 },
196 web: {
197 favicon: './assets/favicon.png',
198 },
199 updates: {
200 url: 'https://updates.bsky.app/manifest',
201 enabled: UPDATES_ENABLED,
202 fallbackToCacheTimeout: 30000,
203 codeSigningCertificate: UPDATES_ENABLED
204 ? './code-signing/certificate.pem'
205 : undefined,
206 codeSigningMetadata: UPDATES_ENABLED
207 ? {
208 keyid: 'main',
209 alg: 'rsa-v1_5-sha256',
210 }
211 : undefined,
212 checkAutomatically: 'NEVER',
213 channel: UPDATES_CHANNEL,
214 },
215 plugins: [
216 'expo-localization',
217 USE_SENTRY && [
218 '@sentry/react-native/expo',
219 {
220 organization: 'blueskyweb',
221 project: 'react-native',
222 release: VERSION,
223 dist: SENTRY_DIST,
224 },
225 ],
226 [
227 'expo-build-properties',
228 {
229 ios: {
230 deploymentTarget: '15.1',
231 newArchEnabled: false,
232 },
233 android: {
234 compileSdkVersion: 34,
235 targetSdkVersion: 34,
236 buildToolsVersion: '34.0.0',
237 kotlinVersion: '1.8.0',
238 newArchEnabled: false,
239 },
240 },
241 ],
242 [
243 'expo-notifications',
244 {
245 icon: './assets/icon-android-notification.png',
246 color: '#1185fe',
247 sounds: PLATFORM === 'ios' ? ['assets/dm.aiff'] : ['assets/dm.mp3'],
248 },
249 ],
250 'react-native-compressor',
251 './plugins/starterPackAppClipExtension/withStarterPackAppClip.js',
252 './plugins/withAndroidManifestPlugin.js',
253 './plugins/withAndroidManifestFCMIconPlugin.js',
254 './plugins/withAndroidStylesWindowBackgroundPlugin.js',
255 './plugins/withAndroidStylesAccentColorPlugin.js',
256 './plugins/withAndroidSplashScreenStatusBarTranslucentPlugin.js',
257 './plugins/shareExtension/withShareExtensions.js',
258 './plugins/notificationsExtension/withNotificationsExtension.js',
259 './plugins/withAppDelegateReferrer.js',
260 [
261 'expo-font',
262 {
263 fonts: [
264 './assets/fonts/inter/InterVariable.ttf',
265 './assets/fonts/inter/InterVariable-Italic.ttf',
266 // Android only
267 './assets/fonts/inter/Inter-Regular.otf',
268 './assets/fonts/inter/Inter-Italic.otf',
269 './assets/fonts/inter/Inter-SemiBold.otf',
270 './assets/fonts/inter/Inter-SemiBoldItalic.otf',
271 './assets/fonts/inter/Inter-ExtraBold.otf',
272 './assets/fonts/inter/Inter-ExtraBoldItalic.otf',
273 ],
274 },
275 ],
276 [
277 '@mozzius/expo-dynamic-app-icon',
278 {
279 /**
280 * Default set
281 */
282 default_light: {
283 ios: './assets/app-icons/ios_icon_default_light.png',
284 android: './assets/app-icons/android_icon_default_light.png',
285 prerendered: true,
286 },
287 default_dark: {
288 ios: './assets/app-icons/ios_icon_default_dark.png',
289 android: './assets/app-icons/android_icon_default_dark.png',
290 prerendered: true,
291 },
292
293 /**
294 * Bluesky+ core set
295 */
296 core_aurora: {
297 ios: './assets/app-icons/ios_icon_core_aurora.png',
298 android: './assets/app-icons/android_icon_core_aurora.png',
299 prerendered: true,
300 },
301 core_bonfire: {
302 ios: './assets/app-icons/ios_icon_core_bonfire.png',
303 android: './assets/app-icons/android_icon_core_bonfire.png',
304 prerendered: true,
305 },
306 core_sunrise: {
307 ios: './assets/app-icons/ios_icon_core_sunrise.png',
308 android: './assets/app-icons/android_icon_core_sunrise.png',
309 prerendered: true,
310 },
311 core_sunset: {
312 ios: './assets/app-icons/ios_icon_core_sunset.png',
313 android: './assets/app-icons/android_icon_core_sunset.png',
314 prerendered: true,
315 },
316 core_midnight: {
317 ios: './assets/app-icons/ios_icon_core_midnight.png',
318 android: './assets/app-icons/android_icon_core_midnight.png',
319 prerendered: true,
320 },
321 core_flat_blue: {
322 ios: './assets/app-icons/ios_icon_core_flat_blue.png',
323 android: './assets/app-icons/android_icon_core_flat_blue.png',
324 prerendered: true,
325 },
326 core_flat_white: {
327 ios: './assets/app-icons/ios_icon_core_flat_white.png',
328 android: './assets/app-icons/android_icon_core_flat_white.png',
329 prerendered: true,
330 },
331 core_flat_black: {
332 ios: './assets/app-icons/ios_icon_core_flat_black.png',
333 android: './assets/app-icons/android_icon_core_flat_black.png',
334 prerendered: true,
335 },
336 core_classic: {
337 ios: './assets/app-icons/ios_icon_core_classic.png',
338 android: './assets/app-icons/android_icon_core_classic.png',
339 prerendered: true,
340 },
341 },
342 ],
343 ].filter(Boolean),
344 extra: {
345 eas: {
346 build: {
347 experimental: {
348 ios: {
349 appExtensions: [
350 {
351 targetName: 'Share-with-Bluesky',
352 bundleIdentifier: 'xyz.blueskyweb.app.Share-with-Bluesky',
353 entitlements: {
354 'com.apple.security.application-groups': [
355 'group.app.bsky',
356 ],
357 },
358 },
359 {
360 targetName: 'BlueskyNSE',
361 bundleIdentifier: 'xyz.blueskyweb.app.BlueskyNSE',
362 entitlements: {
363 'com.apple.security.application-groups': [
364 'group.app.bsky',
365 ],
366 },
367 },
368 {
369 targetName: 'BlueskyClip',
370 bundleIdentifier: 'xyz.blueskyweb.app.AppClip',
371 },
372 ],
373 },
374 },
375 },
376 projectId: '55bd077a-d905-4184-9c7f-94789ba0f302',
377 },
378 },
379 hooks: {
380 postPublish: [
381 /*
382 * @see https://docs.expo.dev/guides/using-sentry/#app-configuration
383 */
384 {
385 file: './postHooks/uploadSentrySourcemapsPostHook',
386 config: {
387 organization: 'blueskyweb',
388 project: 'react-native',
389 release: VERSION,
390 dist: SENTRY_DIST,
391 },
392 },
393 ],
394 },
395 },
396 }
397}