forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1// @ts-check
2const pkg = require('./package.json')
3
4/**
5 * @param {import('@expo/config-types').ExpoConfig} _config
6 * @returns {{ expo: import('@expo/config-types').ExpoConfig }}
7 */
8module.exports = function (_config) {
9 /**
10 * App version number. Should be incremented as part of a release cycle.
11 */
12 const VERSION = pkg.version
13
14 /**
15 * Uses built-in Expo env vars
16 *
17 * @see https://docs.expo.dev/build-reference/variables/#built-in-environment-variables
18 */
19 const PLATFORM = process.env.EAS_BUILD_PLATFORM ?? 'web'
20
21 const IS_TESTFLIGHT = process.env.EXPO_PUBLIC_ENV === 'testflight'
22 const IS_PRODUCTION = process.env.EXPO_PUBLIC_ENV === 'production'
23 const IS_DEV = !IS_TESTFLIGHT && !IS_PRODUCTION
24
25 const ASSOCIATED_DOMAINS = [
26 'applinks:bsky.app',
27 'applinks:staging.bsky.app',
28 'appclips:bsky.app',
29 'appclips:go.bsky.app', // Allows App Clip to work when scanning QR codes
30 // When testing local services, enter an ngrok (et al) domain here. It must use a standard HTTP/HTTPS port.
31 ...(IS_DEV || IS_TESTFLIGHT ? [] : []),
32 ]
33
34 const UPDATES_ENABLED = IS_TESTFLIGHT || IS_PRODUCTION
35
36 const USE_SENTRY = Boolean(process.env.SENTRY_AUTH_TOKEN)
37
38 const IOS_ICON_FILE =
39 PLATFORM === 'web' // web build doesn't like .icon files
40 ? './assets/app-icons/ios_icon_default_next.png'
41 : IS_TESTFLIGHT
42 ? './assets/app-icons/ios_icon_testflight.icon'
43 : './assets/app-icons/ios_icon_default.icon'
44
45 return {
46 expo: {
47 version: VERSION,
48 name: 'Bluesky',
49 slug: 'bluesky',
50 scheme: 'bluesky',
51 owner: 'blueskysocial',
52 runtimeVersion: {
53 policy: 'appVersion',
54 },
55 icon: './assets/app-icons/ios_icon_default_next.png',
56 userInterfaceStyle: 'automatic',
57 primaryColor: '#006AFF',
58 newArchEnabled: false,
59 ios: {
60 supportsTablet: false,
61 bundleIdentifier: 'xyz.blueskyweb.app',
62 config: {
63 usesNonExemptEncryption: false,
64 },
65 icon: IOS_ICON_FILE,
66 infoPlist: {
67 CADisableMinimumFrameDurationOnPhone: true,
68 UIBackgroundModes: ['remote-notification'],
69 NSUserActivityTypes: ['INSendMessageIntent'],
70 NSCameraUsageDescription:
71 'Used for profile pictures, posts, and other kinds of content.',
72 NSMicrophoneUsageDescription:
73 'Used for posts and other kinds of content.',
74 NSPhotoLibraryAddUsageDescription:
75 'Used to save images to your library.',
76 NSPhotoLibraryUsageDescription:
77 'Used for profile pictures, posts, and other kinds of content',
78 CFBundleSpokenName: 'Blue Sky',
79 CFBundleLocalizations: [
80 'en',
81 'an',
82 'ast',
83 'ca',
84 'cy',
85 'da',
86 'de',
87 'el',
88 'eo',
89 'es',
90 'eu',
91 'fi',
92 'fr',
93 'fy',
94 'ga',
95 'gd',
96 'gl',
97 'hi',
98 'hu',
99 'ia',
100 'id',
101 'it',
102 'ja',
103 'km',
104 'ko',
105 'ne',
106 'nl',
107 'pl',
108 'pt-BR',
109 'pt-PT',
110 'ro',
111 'ru',
112 'sv',
113 'th',
114 'tr',
115 'uk',
116 'vi',
117 'yue',
118 'zh-Hans',
119 'zh-Hant',
120 ],
121 },
122 associatedDomains: ASSOCIATED_DOMAINS,
123 entitlements: {
124 'com.apple.developer.kernel.increased-memory-limit': true,
125 'com.apple.developer.kernel.extended-virtual-addressing': true,
126 'com.apple.security.application-groups': 'group.app.bsky',
127 'com.apple.developer.usernotifications.communication': true,
128 // 'com.apple.developer.device-information.user-assigned-device-name': true,
129 },
130 privacyManifests: {
131 NSPrivacyCollectedDataTypes: [
132 {
133 NSPrivacyCollectedDataType: 'NSPrivacyCollectedDataTypeCrashData',
134 NSPrivacyCollectedDataTypeLinked: false,
135 NSPrivacyCollectedDataTypeTracking: false,
136 NSPrivacyCollectedDataTypePurposes: [
137 'NSPrivacyCollectedDataTypePurposeAppFunctionality',
138 ],
139 },
140 {
141 NSPrivacyCollectedDataType:
142 'NSPrivacyCollectedDataTypePerformanceData',
143 NSPrivacyCollectedDataTypeLinked: false,
144 NSPrivacyCollectedDataTypeTracking: false,
145 NSPrivacyCollectedDataTypePurposes: [
146 'NSPrivacyCollectedDataTypePurposeAppFunctionality',
147 ],
148 },
149 {
150 NSPrivacyCollectedDataType:
151 'NSPrivacyCollectedDataTypeOtherDiagnosticData',
152 NSPrivacyCollectedDataTypeLinked: false,
153 NSPrivacyCollectedDataTypeTracking: false,
154 NSPrivacyCollectedDataTypePurposes: [
155 'NSPrivacyCollectedDataTypePurposeAppFunctionality',
156 ],
157 },
158 ],
159 NSPrivacyAccessedAPITypes: [
160 {
161 NSPrivacyAccessedAPIType:
162 'NSPrivacyAccessedAPICategoryFileTimestamp',
163 NSPrivacyAccessedAPITypeReasons: ['C617.1', '3B52.1', '0A2A.1'],
164 },
165 {
166 NSPrivacyAccessedAPIType: 'NSPrivacyAccessedAPICategoryDiskSpace',
167 NSPrivacyAccessedAPITypeReasons: ['E174.1', '85F4.1'],
168 },
169 {
170 NSPrivacyAccessedAPIType:
171 'NSPrivacyAccessedAPICategorySystemBootTime',
172 NSPrivacyAccessedAPITypeReasons: ['35F9.1'],
173 },
174 {
175 NSPrivacyAccessedAPIType:
176 'NSPrivacyAccessedAPICategoryUserDefaults',
177 NSPrivacyAccessedAPITypeReasons: ['CA92.1', '1C8F.1'],
178 },
179 ],
180 },
181 },
182 androidStatusBar: {
183 barStyle: 'light-content',
184 },
185 // Dark nav bar in light mode is better than light nav bar in dark mode
186 androidNavigationBar: {
187 barStyle: 'light-content',
188 },
189 android: {
190 icon: './assets/app-icons/android_icon_default_next.png',
191 adaptiveIcon: {
192 foregroundImage: './assets/icon-android-foreground.png',
193 monochromeImage: './assets/icon-android-monochrome.png',
194 backgroundColor: '#006AFF',
195 },
196 googleServicesFile: './google-services.json',
197 package: 'xyz.blueskyweb.app',
198 intentFilters: [
199 {
200 action: 'VIEW',
201 autoVerify: true,
202 data: [
203 {
204 scheme: 'https',
205 host: 'bsky.app',
206 },
207 ...(IS_DEV
208 ? [
209 {
210 scheme: 'http',
211 host: 'localhost:19006',
212 },
213 ]
214 : []),
215 ],
216 category: ['BROWSABLE', 'DEFAULT'],
217 },
218 ],
219 },
220 web: {
221 favicon: './assets/favicon.png',
222 },
223 updates: {
224 url: 'https://updates.bsky.app/manifest',
225 enabled: UPDATES_ENABLED,
226 fallbackToCacheTimeout: 30000,
227 codeSigningCertificate: UPDATES_ENABLED
228 ? './code-signing/certificate.pem'
229 : undefined,
230 codeSigningMetadata: UPDATES_ENABLED
231 ? {
232 keyid: 'main',
233 alg: 'rsa-v1_5-sha256',
234 }
235 : undefined,
236 checkAutomatically: 'NEVER',
237 },
238 plugins: [
239 'expo-video',
240 'expo-localization',
241 'expo-web-browser',
242 [
243 'react-native-edge-to-edge',
244 {android: {enforceNavigationBarContrast: false}},
245 ],
246 ...(USE_SENTRY
247 ? [
248 /** @type {[string, any]} */ ([
249 '@sentry/react-native/expo',
250 {
251 organization: 'blueskyweb',
252 project: 'app',
253 url: 'https://sentry.io',
254 },
255 ]),
256 ]
257 : []),
258 [
259 'expo-build-properties',
260 {
261 ios: {
262 deploymentTarget: '15.1',
263 buildReactNativeFromSource: true,
264 ccacheEnabled: IS_DEV,
265 extraPods: [
266 {
267 name: 'MCEmojiPicker',
268 git: 'https://github.com/bluesky-social/MCEmojiPicker.git',
269 branch: 'main',
270 },
271 ],
272 },
273 android: {
274 compileSdkVersion: 36,
275 targetSdkVersion: 35,
276 buildToolsVersion: '35.0.0',
277 buildReactNativeFromSource: IS_PRODUCTION,
278 },
279 },
280 ],
281 [
282 'expo-notifications',
283 {
284 icon: './assets/icon-android-notification.png',
285 color: '#1185fe',
286 sounds: PLATFORM === 'ios' ? ['assets/dm.aiff'] : ['assets/dm.mp3'],
287 },
288 ],
289 'react-native-compressor',
290 [
291 '@bitdrift/react-native',
292 {
293 networkInstrumentation: true,
294 },
295 ],
296 './plugins/starterPackAppClipExtension/withStarterPackAppClip.js',
297 './plugins/withGradleJVMHeapSizeIncrease.js',
298 './plugins/withAndroidManifestLargeHeapPlugin.js',
299 './plugins/withAndroidManifestFCMIconPlugin.js',
300 './plugins/withAndroidManifestIntentQueriesPlugin.js',
301 './plugins/withAndroidStylesAccentColorPlugin.js',
302 './plugins/withAndroidNoJitpackPlugin.js',
303 './plugins/shareExtension/withShareExtensions.js',
304 './plugins/notificationsExtension/withNotificationsExtension.js',
305 [
306 'expo-font',
307 {
308 fonts: [
309 './assets/fonts/inter/InterVariable.woff2',
310 './assets/fonts/inter/InterVariable-Italic.woff2',
311 // Android only
312 './assets/fonts/inter/Inter-Regular.otf',
313 './assets/fonts/inter/Inter-Italic.otf',
314 './assets/fonts/inter/Inter-Medium.otf',
315 './assets/fonts/inter/Inter-MediumItalic.otf',
316 './assets/fonts/inter/Inter-SemiBold.otf',
317 './assets/fonts/inter/Inter-SemiBoldItalic.otf',
318 './assets/fonts/inter/Inter-Bold.otf',
319 './assets/fonts/inter/Inter-BoldItalic.otf',
320 ],
321 },
322 ],
323 [
324 'expo-splash-screen',
325 {
326 ios: {
327 enableFullScreenImage_legacy: true, // iOS only
328 backgroundColor: '#006AFF', // primary_500
329 image: './assets/splash/splash.png',
330 resizeMode: 'cover',
331 dark: {
332 enableFullScreenImage_legacy: true, // iOS only
333 backgroundColor: '#002861', // primary_900
334 image: './assets/splash/splash-dark.png',
335 resizeMode: 'cover',
336 },
337 },
338 android: {
339 backgroundColor: '#006AFF', // primary_500
340 image: './assets/splash/android-splash-logo-white.png',
341 imageWidth: 102, // even division of 306px
342 dark: {
343 backgroundColor: '#002861', // primary_900
344 image: './assets/splash/android-splash-logo-white.png',
345 imageWidth: 102,
346 },
347 },
348 },
349 ],
350 [
351 '@mozzius/expo-dynamic-app-icon',
352 {
353 /**
354 * Default set
355 */
356 default_light: {
357 ios: './assets/app-icons/ios_icon_legacy_light.png',
358 android: './assets/app-icons/android_icon_legacy_light.png',
359 prerendered: true,
360 },
361 default_dark: {
362 ios: './assets/app-icons/ios_icon_legacy_dark.png',
363 android: './assets/app-icons/android_icon_legacy_dark.png',
364 prerendered: true,
365 },
366
367 /**
368 * Bluesky+ core set
369 */
370 core_aurora: {
371 ios: './assets/app-icons/ios_icon_core_aurora.png',
372 android: './assets/app-icons/android_icon_core_aurora.png',
373 prerendered: true,
374 },
375 core_bonfire: {
376 ios: './assets/app-icons/ios_icon_core_bonfire.png',
377 android: './assets/app-icons/android_icon_core_bonfire.png',
378 prerendered: true,
379 },
380 core_sunrise: {
381 ios: './assets/app-icons/ios_icon_core_sunrise.png',
382 android: './assets/app-icons/android_icon_core_sunrise.png',
383 prerendered: true,
384 },
385 core_sunset: {
386 ios: './assets/app-icons/ios_icon_core_sunset.png',
387 android: './assets/app-icons/android_icon_core_sunset.png',
388 prerendered: true,
389 },
390 core_midnight: {
391 ios: './assets/app-icons/ios_icon_core_midnight.png',
392 android: './assets/app-icons/android_icon_core_midnight.png',
393 prerendered: true,
394 },
395 core_flat_blue: {
396 ios: './assets/app-icons/ios_icon_core_flat_blue.png',
397 android: './assets/app-icons/android_icon_core_flat_blue.png',
398 prerendered: true,
399 },
400 core_flat_white: {
401 ios: './assets/app-icons/ios_icon_core_flat_white.png',
402 android: './assets/app-icons/android_icon_core_flat_white.png',
403 prerendered: true,
404 },
405 core_flat_black: {
406 ios: './assets/app-icons/ios_icon_core_flat_black.png',
407 android: './assets/app-icons/android_icon_core_flat_black.png',
408 prerendered: true,
409 },
410 core_classic: {
411 ios: './assets/app-icons/ios_icon_core_classic.png',
412 android: './assets/app-icons/android_icon_core_classic.png',
413 prerendered: true,
414 },
415 },
416 ],
417 ['expo-screen-orientation', {initialOrientation: 'PORTRAIT_UP'}],
418 ['expo-location'],
419 [
420 'expo-contacts',
421 {
422 contactsPermission:
423 'I agree to allow Bluesky to use my contacts for friend discovery until I opt out.',
424 },
425 ],
426 ],
427 extra: {
428 eas: {
429 build: {
430 experimental: {
431 ios: {
432 appExtensions: [
433 {
434 targetName: 'Share-with-Bluesky',
435 bundleIdentifier: 'xyz.blueskyweb.app.Share-with-Bluesky',
436 entitlements: {
437 'com.apple.security.application-groups': [
438 'group.app.bsky',
439 ],
440 },
441 },
442 {
443 targetName: 'BlueskyNSE',
444 bundleIdentifier: 'xyz.blueskyweb.app.BlueskyNSE',
445 entitlements: {
446 'com.apple.security.application-groups': [
447 'group.app.bsky',
448 ],
449 },
450 },
451 {
452 targetName: 'BlueskyClip',
453 bundleIdentifier: 'xyz.blueskyweb.app.AppClip',
454 },
455 ],
456 },
457 },
458 },
459 projectId: '55bd077a-d905-4184-9c7f-94789ba0f302',
460 },
461 },
462 },
463 }
464}