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