Enable App Store builds without EAS, iOS 18 App Intents plugins, and signing fixes for distribution export. Add mobile invoice PDF preview, compact line items, and more reliable shortcut deep-link handling. Co-authored-by: Cursor <cursoragent@cursor.com>
119 lines
3.4 KiB
JavaScript
119 lines
3.4 KiB
JavaScript
// @ts-check
|
|
const {
|
|
withDangerousMod,
|
|
withXcodeProject,
|
|
IOSConfig,
|
|
} = require("@expo/config-plugins");
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
|
|
const SWIFT_FILES = [
|
|
"BeenVoiceIntentHelpers.swift",
|
|
"ClockInIntent.swift",
|
|
"ClockOutIntent.swift",
|
|
"OpenTimerIntent.swift",
|
|
"BeenVoiceShortcuts.swift",
|
|
];
|
|
|
|
/** @type {import('@expo/config-plugins').ConfigPlugin} */
|
|
function withAppIntents(config) {
|
|
const appIntentsSource = path.join(
|
|
config._internal?.projectRoot ?? process.cwd(),
|
|
"plugins",
|
|
"app-intents",
|
|
);
|
|
|
|
config = withDangerousMod(config, [
|
|
"ios",
|
|
async (config) => {
|
|
const projectRoot = config.modRequest.projectRoot;
|
|
const platformRoot = config.modRequest.platformProjectRoot;
|
|
const projectName =
|
|
config.modRequest.projectName ??
|
|
IOSConfig.XcodeUtils.getProjectName(projectRoot);
|
|
const targetDir = path.join(platformRoot, projectName);
|
|
|
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
|
|
for (const file of SWIFT_FILES) {
|
|
fs.copyFileSync(path.join(appIntentsSource, file), path.join(targetDir, file));
|
|
}
|
|
|
|
const appDelegatePath = path.join(targetDir, "AppDelegate.swift");
|
|
if (fs.existsSync(appDelegatePath)) {
|
|
let appDelegate = fs.readFileSync(appDelegatePath, "utf8");
|
|
const marker = "BeenVoiceShortcuts.updateAppShortcutParameters";
|
|
|
|
if (!appDelegate.includes("import AppIntents")) {
|
|
appDelegate = appDelegate.replace(
|
|
"internal import Expo",
|
|
"import AppIntents\ninternal import Expo",
|
|
);
|
|
}
|
|
|
|
if (appDelegate.includes(marker)) {
|
|
appDelegate = appDelegate.replace(
|
|
/if #available\(iOS 16\.0, \*\)/g,
|
|
"if #available(iOS 18.0, *)",
|
|
);
|
|
} else {
|
|
appDelegate = appDelegate.replace(
|
|
"return super.application(application, didFinishLaunchingWithOptions: launchOptions)",
|
|
`if #available(iOS 18.0, *) {
|
|
Task {
|
|
await BeenVoiceShortcuts.updateAppShortcutParameters()
|
|
}
|
|
}
|
|
|
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)`,
|
|
);
|
|
}
|
|
|
|
fs.writeFileSync(appDelegatePath, appDelegate);
|
|
}
|
|
|
|
return config;
|
|
},
|
|
]);
|
|
|
|
return withXcodeProject(config, (config) => {
|
|
const project = config.modResults;
|
|
const projectRoot = config.modRequest.projectRoot;
|
|
const platformRoot = config.modRequest.platformProjectRoot;
|
|
const projectName =
|
|
config.modRequest.projectName ??
|
|
IOSConfig.XcodeUtils.getProjectName(projectRoot);
|
|
|
|
for (const file of SWIFT_FILES) {
|
|
const filepath = `${projectName}/${file}`;
|
|
const absolutePath = path.join(platformRoot, filepath);
|
|
|
|
if (!fs.existsSync(absolutePath)) continue;
|
|
|
|
const fileRef = project.pbxFileReferenceSection();
|
|
const alreadyLinked = Object.values(fileRef).some(
|
|
(entry) =>
|
|
entry &&
|
|
typeof entry === "object" &&
|
|
"path" in entry &&
|
|
(entry.path === file ||
|
|
entry.path === `${projectName}/${file}` ||
|
|
String(entry.path).endsWith(`/${file}`)),
|
|
);
|
|
|
|
if (!alreadyLinked) {
|
|
IOSConfig.XcodeUtils.addBuildSourceFileToGroup({
|
|
filepath,
|
|
groupName: projectName,
|
|
project,
|
|
verbose: true,
|
|
});
|
|
}
|
|
}
|
|
|
|
return config;
|
|
});
|
|
}
|
|
|
|
module.exports = withAppIntents;
|