native/app.config.ts
Rama master · réplica de lectura del repositorio original.
import { existsSync } from "node:fs";
import type { ExpoConfig } from "expo/config";
// The update server's certificate, downloaded from its dashboard once the app exists there; until then updates are unsigned.
const certificate = "./certs/certificate.pem";
// Firebase's FCM credentials file, path supplied by the build environment; until the owner runs the push setup, builds go without it.
const googleServicesFile = process.env.NEXUL_GOOGLE_SERVICES_JSON;
const inter = "node_modules/@expo-google-fonts/inter";
const mono = "node_modules/@expo-google-fonts/jetbrains-mono";
// Android needs the family declared once with its weights; iOS reads the family from the files.
const fonts = [
{
fontFamily: "Inter",
fontDefinitions: [
{ path: `./${inter}/400Regular/Inter_400Regular.ttf`, weight: 400 },
{ path: `./${inter}/500Medium/Inter_500Medium.ttf`, weight: 500 },
{ path: `./${inter}/600SemiBold/Inter_600SemiBold.ttf`, weight: 600 },
],
},
{
fontFamily: "JetBrains Mono",
fontDefinitions: [
{ path: `./${mono}/400Regular/JetBrainsMono_400Regular.ttf`, weight: 400 },
{ path: `./${mono}/500Medium/JetBrainsMono_500Medium.ttf`, weight: 500 },
],
},
{
// A static cut of the web's display face (opsz 28, wght 560, SOFT 50, WONK 1): Android does not apply variable axes reliably.
fontFamily: "Fraunces Display",
fontDefinitions: [{ path: "./assets/fonts/Fraunces-Display.ttf", weight: 600 }],
},
];
const version = "0.1.8";
// Android only installs an update with a higher build number, so derive it from the version and every release climbs.
const [major = 0, minor = 0, patch = 0] = version.split(".").map(Number);
const buildNumber = major * 10000 + minor * 100 + patch;
const config: ExpoConfig = {
name: "Nexul",
slug: "nexul",
version,
scheme: "nexul",
orientation: "portrait",
userInterfaceStyle: "automatic",
icon: "./assets/icon.png",
ios: {
bundleIdentifier: "io.nexul.app",
buildNumber: String(buildNumber),
infoPlist: { ITSAppUsesNonExemptEncryption: false },
},
android: {
package: "io.nexul.app",
adaptiveIcon: {
foregroundImage: "./assets/adaptive-foreground.png",
monochromeImage: "./assets/adaptive-monochrome.png",
backgroundColor: "#060709",
},
versionCode: buildNumber,
...(googleServicesFile && existsSync(googleServicesFile) && { googleServicesFile }),
},
runtimeVersion: { policy: "appVersion" },
updates: {
url: process.env.NEXUL_UPDATES_URL ?? "",
requestHeaders: {
"expo-channel-name": "production",
"expo-app-id": process.env.NEXUL_UPDATES_APP_ID ?? "",
},
...(existsSync(certificate) && {
codeSigningCertificate: certificate,
codeSigningMetadata: { keyid: "main", alg: "rsa-v1_5-sha256" },
}),
},
extra: { eas: { projectId: process.env.NEXUL_EAS_PROJECT_ID ?? "" } },
plugins: [
"expo-router",
"./plugins/withReleaseSigning",
"expo-secure-store",
// Android tints the white silhouette with this color; the muted foreground token reads on both the light and dark shade.
["expo-notifications", { icon: "./assets/notification-icon.png", color: "#9ea1a8" }],
[
"expo-splash-screen",
{
image: "./assets/splash-icon.png",
backgroundColor: "#edeef1",
imageWidth: 200,
dark: { image: "./assets/splash-icon-dark.png", backgroundColor: "#060709" },
},
],
[
"expo-camera",
{
cameraPermission: "Nexul scans the connect code shown on your Devices page.",
microphonePermission: false,
recordAudioAndroid: false,
},
],
[
"expo-font",
{
android: { fonts },
ios: { fonts: fonts.flatMap((f) => f.fontDefinitions.map((d) => d.path)) },
},
],
],
experiments: { typedRoutes: true, reactCompiler: true },
};
export default config;