From df6814f292f56aa0f650af3d093ba1ca7f159726 Mon Sep 17 00:00:00 2001 From: xuatz Date: Wed, 20 Aug 2025 16:49:19 +0900 Subject: fix(mobile): remove type: module so expo works (#1846) --- apps/mobile/app.config.js | 102 ++++++++++++++++++++++++++++ apps/mobile/app.json | 100 --------------------------- apps/mobile/metro.config.cjs | 57 ---------------- apps/mobile/metro.config.js | 57 ++++++++++++++++ apps/mobile/package.json | 1 - apps/mobile/plugins/camera-not-required.cjs | 23 ------- apps/mobile/plugins/camera-not-required.js | 23 +++++++ apps/mobile/plugins/trust-local-certs.cjs | 43 ------------ apps/mobile/plugins/trust-local-certs.js | 43 ++++++++++++ 9 files changed, 225 insertions(+), 224 deletions(-) create mode 100644 apps/mobile/app.config.js delete mode 100644 apps/mobile/app.json delete mode 100644 apps/mobile/metro.config.cjs create mode 100644 apps/mobile/metro.config.js delete mode 100644 apps/mobile/plugins/camera-not-required.cjs create mode 100644 apps/mobile/plugins/camera-not-required.js delete mode 100644 apps/mobile/plugins/trust-local-certs.cjs create mode 100644 apps/mobile/plugins/trust-local-certs.js (limited to 'apps/mobile') diff --git a/apps/mobile/app.config.js b/apps/mobile/app.config.js new file mode 100644 index 00000000..7e8ab546 --- /dev/null +++ b/apps/mobile/app.config.js @@ -0,0 +1,102 @@ +export default { + expo: { + name: "Karakeep", + slug: "hoarder", + scheme: "karakeep", + version: "1.7.0", + orientation: "portrait", + icon: { + light: "./assets/icon.png", + tinted: "./assets/icon-tinted.png", + }, + userInterfaceStyle: "automatic", + assetBundlePatterns: ["**/*"], + ios: { + supportsTablet: true, + bundleIdentifier: "app.hoarder.hoardermobile", + splash: { + image: "./assets/splash.png", + resizeMode: "contain", + backgroundColor: "#ffffff", + dark: { + image: "./assets/splash-white.png", + resizeMode: "contain", + backgroundColor: "#000000", + }, + }, + config: { + usesNonExemptEncryption: false, + }, + infoPlist: { + NSAppTransportSecurity: { + NSAllowsArbitraryLoads: true, + }, + }, + buildNumber: "24", + }, + android: { + adaptiveIcon: { + foregroundImage: "./assets/adaptive-icon.png", + backgroundColor: "#000000", + monochromeImage: "./assets/adaptive-icon.png", + }, + splash: { + image: "./assets/splash.png", + resizeMode: "contain", + backgroundColor: "#ffffff", + dark: { + image: "./assets/splash-white.png", + resizeMode: "contain", + backgroundColor: "#000000", + }, + }, + package: "app.hoarder.hoardermobile", + versionCode: 24, + }, + plugins: [ + "./plugins/trust-local-certs.js", + "./plugins/camera-not-required.js", + "expo-router", + [ + "expo-share-intent", + { + iosActivationRules: { + NSExtensionActivationSupportsWebURLWithMaxCount: 1, + NSExtensionActivationSupportsWebPageWithMaxCount: 1, + NSExtensionActivationSupportsImageWithMaxCount: 1, + NSExtensionActivationSupportsMovieWithMaxCount: 0, + NSExtensionActivationSupportsText: true, + NSExtensionActivationSupportsFileWithMaxCount: 10, + NSExtensionActivationRule: + 'SUBQUERY (extensionItems, $extensionItem, SUBQUERY ($extensionItem.attachments, $attachment, SUBQUERY ($attachment.registeredTypeIdentifiers, $uti, $uti UTI-CONFORMS-TO "com.adobe.pdf" || $uti UTI-CONFORMS-TO "public.image" || $uti UTI-CONFORMS-TO "public.url" || $uti UTI-CONFORMS-TO "public.plain-text").@count >= 1).@count >= 1).@count >= 1', + }, + androidIntentFilters: ["text/*", "image/*", "application/pdf"], + }, + ], + "expo-secure-store", + [ + "expo-image-picker", + { + photosPermission: + "The app access your photo gallary on your request to hoard them.", + }, + ], + [ + "expo-build-properties", + { + android: { + usesCleartextTraffic: true, + }, + }, + ], + ], + extra: { + router: { + origin: false, + }, + eas: { + projectId: "d6d14643-ad43-4cd3-902a-92c5944d5e45", + }, + }, + }, +}; diff --git a/apps/mobile/app.json b/apps/mobile/app.json deleted file mode 100644 index 908f6d97..00000000 --- a/apps/mobile/app.json +++ /dev/null @@ -1,100 +0,0 @@ -{ - "expo": { - "name": "Karakeep", - "slug": "hoarder", - "scheme": "karakeep", - "version": "1.7.0", - "orientation": "portrait", - "icon": { - "light": "./assets/icon.png", - "tinted": "./assets/icon-tinted.png" - }, - "userInterfaceStyle": "automatic", - "assetBundlePatterns": ["**/*"], - "ios": { - "supportsTablet": true, - "bundleIdentifier": "app.hoarder.hoardermobile", - "splash": { - "image": "./assets/splash.png", - "resizeMode": "contain", - "backgroundColor": "#ffffff", - "dark": { - "image": "./assets/splash-white.png", - "resizeMode": "contain", - "backgroundColor": "#000000" - } - }, - "config": { - "usesNonExemptEncryption": false - }, - "infoPlist": { - "NSAppTransportSecurity": { - "NSAllowsArbitraryLoads": true - } - }, - "buildNumber": "24" - }, - "android": { - "adaptiveIcon": { - "foregroundImage": "./assets/adaptive-icon.png", - "backgroundColor": "#000000", - "monochromeImage": "./assets/adaptive-icon.png" - }, - "splash": { - "image": "./assets/splash.png", - "resizeMode": "contain", - "backgroundColor": "#ffffff", - "dark": { - "image": "./assets/splash-white.png", - "resizeMode": "contain", - "backgroundColor": "#000000" - } - }, - "package": "app.hoarder.hoardermobile", - "versionCode": 24 - }, - "plugins": [ - "./plugins/trust-local-certs.cjs", - "./plugins/camera-not-required.cjs", - "expo-router", - [ - "expo-share-intent", - { - "iosActivationRules": { - "NSExtensionActivationSupportsWebURLWithMaxCount": 1, - "NSExtensionActivationSupportsWebPageWithMaxCount": 1, - "NSExtensionActivationSupportsImageWithMaxCount": 1, - "NSExtensionActivationSupportsMovieWithMaxCount": 0, - "NSExtensionActivationSupportsText": true, - "NSExtensionActivationSupportsFileWithMaxCount": 10, - "NSExtensionActivationRule": "SUBQUERY (extensionItems, $extensionItem, SUBQUERY ($extensionItem.attachments, $attachment, SUBQUERY ($attachment.registeredTypeIdentifiers, $uti, $uti UTI-CONFORMS-TO \"com.adobe.pdf\" || $uti UTI-CONFORMS-TO \"public.image\" || $uti UTI-CONFORMS-TO \"public.url\" || $uti UTI-CONFORMS-TO \"public.plain-text\").@count >= 1).@count >= 1).@count >= 1" - }, - "androidIntentFilters": ["text/*", "image/*", "application/pdf"] - } - ], - "expo-secure-store", - [ - "expo-image-picker", - { - "photosPermission": "The app access your photo gallary on your request to hoard them." - } - ], - [ - "expo-build-properties", - { - "android": { - "usesCleartextTraffic": true - } - } - ] - ], - "extra": { - "router": { - "origin": false - }, - "eas": { - "projectId": "d6d14643-ad43-4cd3-902a-92c5944d5e45" - } - } - } -} diff --git a/apps/mobile/metro.config.cjs b/apps/mobile/metro.config.cjs deleted file mode 100644 index f9679cb2..00000000 --- a/apps/mobile/metro.config.cjs +++ /dev/null @@ -1,57 +0,0 @@ -// Learn more: https://docs.expo.dev/guides/monorepos/ -const { getDefaultConfig } = require("expo/metro-config"); -const { FileStore } = require("metro-cache"); -const { withNativeWind } = require("nativewind/metro"); -const path = require("path"); - -module.exports = withTurborepoManagedCache( - withMonorepoPaths( - // eslint-disable-next-line no-undef - withNativeWind(getDefaultConfig(__dirname), { - input: "./globals.css", - configPath: "./tailwind.config.ts", - }), - ), -); - -/** - * Add the monorepo paths to the Metro config. - * This allows Metro to resolve modules from the monorepo. - * - * @see https://docs.expo.dev/guides/monorepos/#modify-the-metro-config - * @param {import('expo/metro-config').MetroConfig} config - * @returns {import('expo/metro-config').MetroConfig} - */ -function withMonorepoPaths(config) { - // eslint-disable-next-line no-undef - const projectRoot = __dirname; - const workspaceRoot = path.resolve(projectRoot, "../.."); - - // #1 - Watch all files in the monorepo - config.watchFolders = [workspaceRoot]; - - // #2 - Resolve modules within the project's `node_modules` first, then all monorepo modules - config.resolver.nodeModulesPaths = [ - path.resolve(projectRoot, "node_modules"), - path.resolve(workspaceRoot, "node_modules"), - ]; - - return config; -} - -/** - * Move the Metro cache to the `node_modules/.cache/metro` folder. - * This repository configured Turborepo to use this cache location as well. - * If you have any environment variables, you can configure Turborepo to invalidate it when needed. - * - * @see https://turbo.build/repo/docs/reference/configuration#env - * @param {import('expo/metro-config').MetroConfig} config - * @returns {import('expo/metro-config').MetroConfig} - */ -function withTurborepoManagedCache(config) { - config.cacheStores = [ - // eslint-disable-next-line no-undef - new FileStore({ root: path.join(__dirname, "node_modules/.cache/metro") }), - ]; - return config; -} diff --git a/apps/mobile/metro.config.js b/apps/mobile/metro.config.js new file mode 100644 index 00000000..f9679cb2 --- /dev/null +++ b/apps/mobile/metro.config.js @@ -0,0 +1,57 @@ +// Learn more: https://docs.expo.dev/guides/monorepos/ +const { getDefaultConfig } = require("expo/metro-config"); +const { FileStore } = require("metro-cache"); +const { withNativeWind } = require("nativewind/metro"); +const path = require("path"); + +module.exports = withTurborepoManagedCache( + withMonorepoPaths( + // eslint-disable-next-line no-undef + withNativeWind(getDefaultConfig(__dirname), { + input: "./globals.css", + configPath: "./tailwind.config.ts", + }), + ), +); + +/** + * Add the monorepo paths to the Metro config. + * This allows Metro to resolve modules from the monorepo. + * + * @see https://docs.expo.dev/guides/monorepos/#modify-the-metro-config + * @param {import('expo/metro-config').MetroConfig} config + * @returns {import('expo/metro-config').MetroConfig} + */ +function withMonorepoPaths(config) { + // eslint-disable-next-line no-undef + const projectRoot = __dirname; + const workspaceRoot = path.resolve(projectRoot, "../.."); + + // #1 - Watch all files in the monorepo + config.watchFolders = [workspaceRoot]; + + // #2 - Resolve modules within the project's `node_modules` first, then all monorepo modules + config.resolver.nodeModulesPaths = [ + path.resolve(projectRoot, "node_modules"), + path.resolve(workspaceRoot, "node_modules"), + ]; + + return config; +} + +/** + * Move the Metro cache to the `node_modules/.cache/metro` folder. + * This repository configured Turborepo to use this cache location as well. + * If you have any environment variables, you can configure Turborepo to invalidate it when needed. + * + * @see https://turbo.build/repo/docs/reference/configuration#env + * @param {import('expo/metro-config').MetroConfig} config + * @returns {import('expo/metro-config').MetroConfig} + */ +function withTurborepoManagedCache(config) { + config.cacheStores = [ + // eslint-disable-next-line no-undef + new FileStore({ root: path.join(__dirname, "node_modules/.cache/metro") }), + ]; + return config; +} diff --git a/apps/mobile/package.json b/apps/mobile/package.json index f66a64c4..80e4ffcb 100644 --- a/apps/mobile/package.json +++ b/apps/mobile/package.json @@ -2,7 +2,6 @@ "name": "@karakeep/mobile", "version": "1.0.0", "main": "index.ts", - "type": "module", "scripts": { "clean": "git clean -xdf .expo .turbo node_modules", "start": "expo start", diff --git a/apps/mobile/plugins/camera-not-required.cjs b/apps/mobile/plugins/camera-not-required.cjs deleted file mode 100644 index 75116604..00000000 --- a/apps/mobile/plugins/camera-not-required.cjs +++ /dev/null @@ -1,23 +0,0 @@ -const { withAndroidManifest } = require("@expo/config-plugins"); - -const withCameraNotRequired = (config) => { - return withAndroidManifest(config, async (config) => { - config.modResults = await setCustomConfigAsync(config, config.modResults); - return config; - }); -}; - -async function setCustomConfigAsync(_config, androidManifest) { - const usesFeature = androidManifest.manifest["uses-feature"] ?? []; - usesFeature.push({ - $: { - "android:name": "android.hardware.camera", - "android:required": "false", - }, - }); - androidManifest.manifest["uses-feature"] = usesFeature; - - return androidManifest; -} - -module.exports = withCameraNotRequired; diff --git a/apps/mobile/plugins/camera-not-required.js b/apps/mobile/plugins/camera-not-required.js new file mode 100644 index 00000000..75116604 --- /dev/null +++ b/apps/mobile/plugins/camera-not-required.js @@ -0,0 +1,23 @@ +const { withAndroidManifest } = require("@expo/config-plugins"); + +const withCameraNotRequired = (config) => { + return withAndroidManifest(config, async (config) => { + config.modResults = await setCustomConfigAsync(config, config.modResults); + return config; + }); +}; + +async function setCustomConfigAsync(_config, androidManifest) { + const usesFeature = androidManifest.manifest["uses-feature"] ?? []; + usesFeature.push({ + $: { + "android:name": "android.hardware.camera", + "android:required": "false", + }, + }); + androidManifest.manifest["uses-feature"] = usesFeature; + + return androidManifest; +} + +module.exports = withCameraNotRequired; diff --git a/apps/mobile/plugins/trust-local-certs.cjs b/apps/mobile/plugins/trust-local-certs.cjs deleted file mode 100644 index 40275034..00000000 --- a/apps/mobile/plugins/trust-local-certs.cjs +++ /dev/null @@ -1,43 +0,0 @@ -const { AndroidConfig, withAndroidManifest } = require("@expo/config-plugins"); -const { Paths } = require("@expo/config-plugins/build/android"); -const path = require("path"); -const fs = require("fs"); -const fsPromises = fs.promises; - -const { getMainApplicationOrThrow } = AndroidConfig.Manifest; - -const withTrustLocalCerts = (config) => { - return withAndroidManifest(config, async (config) => { - config.modResults = await setCustomConfigAsync(config, config.modResults); - return config; - }); -}; - -async function setCustomConfigAsync(config, androidManifest) { - const src_file_pat = path.join(__dirname, "network_security_config.xml"); - const res_file_path = path.join( - await Paths.getResourceFolderAsync(config.modRequest.projectRoot), - "xml", - "network_security_config.xml", - ); - - const res_dir = path.resolve(res_file_path, ".."); - - if (!fs.existsSync(res_dir)) { - await fsPromises.mkdir(res_dir); - } - - try { - await fsPromises.copyFile(src_file_pat, res_file_path); - } catch (e) { - throw e; - } - - const mainApplication = getMainApplicationOrThrow(androidManifest); - mainApplication.$["android:networkSecurityConfig"] = - "@xml/network_security_config"; - - return androidManifest; -} - -module.exports = withTrustLocalCerts; diff --git a/apps/mobile/plugins/trust-local-certs.js b/apps/mobile/plugins/trust-local-certs.js new file mode 100644 index 00000000..40275034 --- /dev/null +++ b/apps/mobile/plugins/trust-local-certs.js @@ -0,0 +1,43 @@ +const { AndroidConfig, withAndroidManifest } = require("@expo/config-plugins"); +const { Paths } = require("@expo/config-plugins/build/android"); +const path = require("path"); +const fs = require("fs"); +const fsPromises = fs.promises; + +const { getMainApplicationOrThrow } = AndroidConfig.Manifest; + +const withTrustLocalCerts = (config) => { + return withAndroidManifest(config, async (config) => { + config.modResults = await setCustomConfigAsync(config, config.modResults); + return config; + }); +}; + +async function setCustomConfigAsync(config, androidManifest) { + const src_file_pat = path.join(__dirname, "network_security_config.xml"); + const res_file_path = path.join( + await Paths.getResourceFolderAsync(config.modRequest.projectRoot), + "xml", + "network_security_config.xml", + ); + + const res_dir = path.resolve(res_file_path, ".."); + + if (!fs.existsSync(res_dir)) { + await fsPromises.mkdir(res_dir); + } + + try { + await fsPromises.copyFile(src_file_pat, res_file_path); + } catch (e) { + throw e; + } + + const mainApplication = getMainApplicationOrThrow(androidManifest); + mainApplication.$["android:networkSecurityConfig"] = + "@xml/network_security_config"; + + return androidManifest; +} + +module.exports = withTrustLocalCerts; -- cgit v1.2.3-70-g09d2