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