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