Track bundled vendor runtime sources
Some checks failed
CI / main (push) Has been cancelled
CI / release-e2e (push) Has been cancelled

This commit is contained in:
2026-07-07 10:05:50 +08:00
parent fbe179ab53
commit 52636c91ae
2111 changed files with 1850012 additions and 14 deletions

View File

@@ -0,0 +1,69 @@
const common = require("./common.cjs");
console.log("BuildOptimize", {
name: common.platformName(),
arch: common.platformArch(),
});
exports.default = async function (context) {
console.log("BuildOptimize.output", {
context: context,
root: context.appOutDir,
});
// copy extra electron/resources/extra/[name]-[arch] to extra
const platformName = common.platformName();
const platformArch = common.platformArch();
const name = platformName + "-" + platformArch;
const srcDir = `electron/resources/extra/${name}`;
let destDir = null;
if (platformName === 'osx') {
destDir = common.pathResolve(
context.appOutDir,
`${context.packager.appInfo.productFilename}.app`,
"Contents",
"Resources",
"extra",
name
);
} else if (platformName === 'win') {
destDir = common.pathResolve(context.appOutDir, "resources", "extra", name);
} else if (platformName === 'linux') {
destDir = common.pathResolve(context.appOutDir, "resources", "extra", name);
}
console.log("BuildOptimize.copy", {
platformName,
platformArch,
srcDir,
destDir,
});
if (srcDir && common.exists(srcDir)) {
console.log(`Copying from ${srcDir} to ${destDir}`);
common.copy(srcDir, destDir, true);
console.log(`Copy completed`);
} else {
console.log(`No matching source directory found for platform: ${platformName}-${platformArch}`);
}
// common.listFiles(context.appOutDir, true).forEach((p) => {
// console.log('BuildOptimize.path', (p.isDir ? 'D:' : 'F:') + p.path);
// })
// const localeDir = context.appOutDir + "/AigcPanel.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/";
// console.log(`localeDir: ${localeDir}`);
// fs.readdir(localeDir, function (err, files) {
// if (!(files && files.length)) {
// return;
// }
// for (let f of files) {
// if (f.endsWith('.lproj')) {
// if (!(f.startsWith("en") || f.startsWith("zh"))) {
// const p = localeDir + f;
// console.log(`removeFile: ${p}`);
// fs.rmdirSync(p, {recursive: true});
// }
// }
// }
// });
};

137
vendor/aigcpanel/scripts/common.cjs vendored Normal file
View File

@@ -0,0 +1,137 @@
const fs = require("node:fs");
const {resolve, join} = require("node:path");
const crypto = require("node:crypto");
const dir = (p) => {
p = p || ''
return join(__dirname, "../" + p)
}
const distReleaseDir = (p) => {
if (p) {
return dir("dist-release/" + p)
} else {
return dir("dist-release")
}
}
function calcSha256File(filePath) {
return new Promise((resolve, reject) => {
const hash = crypto.createHash("sha256");
const stream = fs.createReadStream(filePath);
stream.on("data", (data) => hash.update(data));
stream.on("end", () => resolve(hash.digest("hex")));
stream.on("error", reject);
});
}
const platformName = () => {
switch (process.platform) {
case "darwin":
return "osx";
case "win32":
return "win";
case "linux":
return "linux";
}
return null;
}
const platformArch = () => {
switch (process.arch) {
case "x64":
return "x86";
case "arm64":
return "arm64";
}
return null;
}
const listFiles = (dir, recursive, regex) => {
regex = regex || null
recursive = recursive || false
const files = fs.readdirSync(dir);
const list = [];
for (let f of files) {
const p = resolve(dir, f);
if (regex) {
if (!regex.test(p)) {
continue;
}
}
const stat = fs.statSync(p);
list.push({
isDir: stat.isDirectory(),
name: f,
path: p
});
if (recursive && stat.isDirectory()) {
list.push(...listFiles(p, recursive));
}
}
return list;
}
const copy = (src, dest, print) => {
print = print || false
if (!fs.existsSync(src)) {
console.warn(`Source path does not exist: ${src}`);
return;
}
if (fs.statSync(src).isDirectory()) {
fs.mkdirSync(dest, {recursive: true});
const files = fs.readdirSync(src);
for (const file of files) {
copy(join(src, file), join(dest, file));
}
} else {
if (print) {
console.log(`Copying file from ${src} to ${dest}`);
}
fs.copyFileSync(src, dest);
}
}
const pathResolve = (...args)=>{
return resolve(...args)
}
const exists = (p) => {
try {
return fs.existsSync(p);
} catch (e) {
return false;
}
}
async function calcSha256() {
console.log('calcSha256.start')
const results = []
const files = listFiles(distReleaseDir(), false, /\.(exe|dmg|AppImage|deb)$/)
for (const p of files) {
const sha256 = await calcSha256File(p.path);
results.push({
name: p.name,
sha256: sha256
})
}
const target = distReleaseDir(`sha256-${platformName()}-${platformArch()}.yml`)
const content = results.map((r) => {
return `${r.name}: ${r.sha256}`
}).join("\n")
fs.writeFileSync(target, content);
console.log('calcSha256.end', target, results)
}
module.exports = {
dir,
distReleaseDir,
platformName,
platformArch,
listFiles,
copy,
pathResolve,
exists,
calcSha256,
}

71
vendor/aigcpanel/scripts/icon_convert.sh vendored Executable file
View File

@@ -0,0 +1,71 @@
#!/bin/bash
# prepare
# brew install --cask inkscape
echo "Convert icon"
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
PROJECT_ROOT=$(realpath "${DIR}/..")
echo "PROJECT_ROOT: ${PROJECT_ROOT}"
path_svg="${PROJECT_ROOT}/public/logo.svg"
path_white_svg="${PROJECT_ROOT}/public/logo-white.svg"
path_build="${PROJECT_ROOT}/electron/resources/build"
path_extra="${PROJECT_ROOT}/electron/resources/extra"
path_source_png="${path_build}/logo_1024x1024.png"
cp -a "${path_svg}" "${PROJECT_ROOT}/src/assets/image/logo.svg"
cp -a "${path_white_svg}" "${PROJECT_ROOT}/src/assets/image/logo-white.svg"
inkscape "${path_svg}" --export-type=png --export-filename="${path_source_png}" -w 1024 -h 1024
size=(16 32 44 48 64 128 150 256 512)
for i in "${size[@]}"; do
path_png="${path_build}/logo@${i}x$i.png"
echo "Generate: logo@${i}x$i.png"
inkscape --export-type="png" --export-filename="${path_png}" -w $i -h $i "${path_source_png}"
done
path_ico="${path_build}/logo.ico"
echo "Generate: logo.ico"
magick "${path_source_png}" -define icon:auto-resize=256,48,32,16 "${path_ico}"
echo "Generate: logo.png"
rm -rf "${path_build}/logo.png"
cp -a "${path_build}/logo@256x256.png" "${path_build}/logo.png"
echo "Generate: logo.icns"
path_iconset="${path_build}/icon.iconset"
rm -rf "${path_iconset}"
mkdir -p "${path_iconset}"
cp -a "${path_build}/logo@256x256.png" "${path_iconset}/icon_256x256.png"
cp -a "${path_build}/logo@32x32.png" "${path_iconset}/icon_32x32.png"
cp -a "${path_build}/logo@16x16.png" "${path_iconset}/icon_16x16.png"
iconutil -c icns "${path_iconset}" -o "${path_build}/logo.icns"
echo "Generate: appx/StoreLogo.png"
cp -a "${path_build}/logo@256x256.png" "${path_build}/appx/StoreLogo.png"
echo "Generate: appx/Square44x44Logo.png"
cp -a "${path_build}/logo@44x44.png" "${path_build}/appx/Square44x44Logo.png"
echo "Generate: appx/Square150x150Logo.png"
cp -a "${path_build}/logo@150x150.png" "${path_build}/appx/Square150x150Logo.png"
echo "Generate: appx/Wide310x150Logo.png"
magick "${path_build}/logo@150x150.png" -resize 310x150 -background none -gravity center -extent 310x150 "${path_build}/appx/Wide310x150Logo.png"
echo "Generate: common/tray/icon.png"
mkdir -p "${path_extra}/common/tray"
cp -a "${path_build}/logo@256x256.png" "${path_extra}/common/tray/icon.png"
echo "Generate: common/tray/icon.ico"
cp -a "${path_build}/logo.ico" "${path_extra}/common/tray/icon.ico"
echo "Generate: osx/tray/iconTemplate.png"
mkdir -p "${path_extra}/osx/tray"
magick "${path_build}/logo-gray.png" -resize 16x16 -background none -gravity center "${path_extra}/osx/tray/iconTemplate.png"
echo "Generate: osx/tray/iconTemplate@2x.png"
magick "${path_build}/logo-gray.png" -resize 32x32 -background none -gravity center "${path_extra}/osx/tray/iconTemplate@2x.png"
echo "Generate: osx/tray/iconTemplate@4x.png"
magick "${path_build}/logo-gray.png" -resize 64x64 -background none -gravity center "${path_extra}/osx/tray/iconTemplate@4x.png"
rm -rf "${path_iconset}"
rm -rf ${path_build}/logo@*

43
vendor/aigcpanel/scripts/init.sh vendored Executable file
View File

@@ -0,0 +1,43 @@
#!/usr/bin/env bash
set -euo pipefail
REPO_URL="https://github.com/modstart-lib/share-binary"
REPO_DIR="share-binary"
if [ ! -d "$REPO_DIR/.git" ]; then
echo "🔹 目录不存在,正在克隆仓库..."
git clone "$REPO_URL"
else
echo "🔹 仓库已存在,进入目录并更新..."
cd "$REPO_DIR"
git pull origin main
cd ..
fi
rm -rfv electron/resources/extra/osx-arm64
mkdir -p electron/resources/extra/osx-arm64
cp -a share-binary/osx-arm64/ffmpeg electron/resources/extra/osx-arm64/ffmpeg
cp -a share-binary/osx-arm64/ffprobe electron/resources/extra/osx-arm64/ffprobe
rm -rfv electron/resources/extra/osx-x86
mkdir -p electron/resources/extra/osx-x86
cp -a share-binary/osx-x86/ffmpeg electron/resources/extra/osx-x86/ffmpeg
cp -a share-binary/osx-x86/ffprobe electron/resources/extra/osx-x86/ffprobe
rm -rfv electron/resources/extra/linux-arm64
mkdir -p electron/resources/extra/linux-arm64
cp -a share-binary/linux-arm64/ffmpeg electron/resources/extra/linux-arm64/ffmpeg
cp -a share-binary/linux-arm64/ffprobe electron/resources/extra/linux-arm64/ffprobe
rm -rfv electron/resources/extra/linux-x86
mkdir -p electron/resources/extra/linux-x86
cp -a share-binary/linux-x86/ffmpeg electron/resources/extra/linux-x86/ffmpeg
cp -a share-binary/linux-x86/ffprobe electron/resources/extra/linux-x86/ffprobe
rm -rfv electron/resources/extra/win-x86
mkdir -p electron/resources/extra/win-x86
cp -a share-binary/win-x86/ffmpeg.exe electron/resources/extra/win-x86/ffmpeg.exe
cp -a share-binary/win-x86/ffprobe.exe electron/resources/extra/win-x86/ffprobe.exe
ls -R electron/resources/extra

52
vendor/aigcpanel/scripts/notarize.cjs vendored Normal file
View File

@@ -0,0 +1,52 @@
const {notarize} = require("@electron/notarize");
const common = require('./common.cjs')
exports.default = async function notarizing(context) {
const appName = context.packager.appInfo.productFilename;
const {electronPlatformName, appOutDir} = context;
console.log(` • Notarization Start`);
// We skip notarization if the process is not running on MacOS and
// if the enviroment variable SKIP_NOTARIZE is set to `true`
// This is useful for local testing where notarization is useless
if (
electronPlatformName !== "darwin" ||
process.env.SKIP_NOTARIZE === "true"
) {
console.log(` • Skipping notarization`);
return;
}
// THIS MUST BE THE SAME AS THE `appId` property
// in your electron builder configuration
const appId = "AigcPanel";
let appPath = `${appOutDir}/${appName}.app`;
let {APPLE_ID, APPLE_ID_PASSWORD, APPLE_TEAM_ID} = process.env;
if (!APPLE_ID) {
console.info(" • Notarization ignore: APPLE_ID is empty");
await common.calcSha256()
return;
}
const notarizeOption = {
tool: "notarytool",
appBundleId: appId,
appPath,
appleId: APPLE_ID,
appleIdPassword: APPLE_ID_PASSWORD,
teamId: APPLE_TEAM_ID,
verbose: true,
}
console.log(` • Notarizing`, `appPath:${appPath} notarizeOption:${JSON.stringify(notarizeOption)}`);
try {
const result = await notarize(notarizeOption);
console.log(" • Notarization successful!");
await common.calcSha256()
return result;
} catch (error) {
console.error(" • Notarization failed:", error.message);
console.error(" • Stack trace:", error.stack);
await common.calcSha256()
throw new Error(`Notarization failed: ${error.message}`);
}
};