mirror of
https://gitlab.com/vyla-entertainment/home.git
synced 2026-11-13 21:57:21 -05:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 49b2a7622b | |||
| b8e474cb92 | |||
| 8b29c9e3c7 | |||
| 5dab61b359 | |||
| eab843aa16 | |||
| b757f741b7 | |||
| 5f4c47a07c | |||
| 32677c9fb2 | |||
| 7eab57cfd9 | |||
| c8fc7da64d | |||
| 88c1824bf7 | |||
| a50cb2b6b8 | |||
| 971eae4af1 | |||
| 1400d538f3 | |||
| b1d01d94da | |||
| 9d7e218ff6 |
@@ -18,20 +18,23 @@ const REPO_CONFIG = {
|
||||
'stream-api': { name: 'stream-api', branch: 'main' },
|
||||
};
|
||||
|
||||
const clonedRepos = new Set();
|
||||
|
||||
function clonePrivateRepo(repoConfig, targetDir) {
|
||||
if (fs.existsSync(targetDir)) {
|
||||
console.log(`[DEV] ${repoConfig.name} already exists locally. Skipping clone to use local changes.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const token = process.env.GITLAB_TOKEN || process.env.VYLA_GITLAB_TOKEN;
|
||||
const auth = token ? `oauth2:${token}@` : '';
|
||||
const repoUrl = `https://${auth}gitlab.com/${GITLAB_GROUP}/${repoConfig.name}.git`;
|
||||
|
||||
try {
|
||||
if (fs.existsSync(targetDir)) {
|
||||
fs.rmSync(targetDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
|
||||
}
|
||||
|
||||
execSync(`git clone --depth 1 --branch ${repoConfig.branch} ${repoUrl} ${targetDir}`, {
|
||||
stdio: 'inherit'
|
||||
});
|
||||
|
||||
clonedRepos.add(repoConfig.name);
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to clone ${repoConfig.name}: ${error.message}`);
|
||||
}
|
||||
@@ -332,9 +335,11 @@ async function build() {
|
||||
fs.writeFileSync(path.join(__dirname, 'manifest.json'), JSON.stringify(manifest, null, 2), 'utf8');
|
||||
|
||||
for (const repo of REPOS) {
|
||||
const repoPath = path.join(__dirname, repo);
|
||||
if (fs.existsSync(repoPath)) {
|
||||
fs.rmSync(repoPath, { recursive: true, force: true });
|
||||
if (clonedRepos.has(repo)) {
|
||||
const repoPath = path.join(__dirname, repo);
|
||||
if (fs.existsSync(repoPath)) {
|
||||
fs.rmSync(repoPath, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
32
codemagic.yaml
Normal file
32
codemagic.yaml
Normal file
@@ -0,0 +1,32 @@
|
||||
workflows:
|
||||
macos-release:
|
||||
name: Build macOS Release
|
||||
max_build_duration: 60
|
||||
instance_type: mac_mini_m2
|
||||
environment:
|
||||
groups:
|
||||
- gitlab_credentials
|
||||
node: 22.14.0
|
||||
cache:
|
||||
cache_paths:
|
||||
- $HOME/.cargo/registry
|
||||
- $HOME/.cargo/git
|
||||
- src-tauri/target
|
||||
scripts:
|
||||
- name: Setup Rust toolchain
|
||||
script: |
|
||||
if ! command -v cargo &> /dev/null; then
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
|
||||
fi
|
||||
- name: Install dependencies
|
||||
script: |
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
npm install
|
||||
- name: Build & Publish macOS Release
|
||||
script: |
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
PACKAGE_VERSION=$(node -p "require('./package.json').version")
|
||||
node release.js --installer --tag="v$PACKAGE_VERSION"
|
||||
artifacts:
|
||||
- src-tauri/target/release/bundle/dmg/*.dmg
|
||||
- src-tauri/target/release/bundle/macos/*.app
|
||||
41
main.js
41
main.js
@@ -203,10 +203,34 @@ async function start() {
|
||||
|
||||
try {
|
||||
sendToTauri('status', { message: 'Inspecting local workspace and installed files...' });
|
||||
const isFirstRun = !patcher.verifyExtraction();
|
||||
const localVersion = patcher.getCurrentVersion();
|
||||
const localSha = patcher.getCurrentSha();
|
||||
debugLog(`Is First Run: ${isFirstRun}, Local Version: ${localVersion}`);
|
||||
let isFirstRun = !patcher.verifyExtraction();
|
||||
let localVersion = patcher.getCurrentVersion();
|
||||
let localSha = patcher.getCurrentSha();
|
||||
debugLog(`Is First Run: ${isFirstRun}, Local Version: ${localVersion}, Local SHA: ${localSha}`);
|
||||
|
||||
const localZipPath = path.join(__dirname, 'update-payload.zip');
|
||||
const localManifestPath = path.join(__dirname, 'manifest.json');
|
||||
let localZipManifest = null;
|
||||
|
||||
if (fs.existsSync(localZipPath) && fs.existsSync(localManifestPath)) {
|
||||
try { localZipManifest = JSON.parse(fs.readFileSync(localManifestPath, 'utf8')); } catch (e) { }
|
||||
}
|
||||
|
||||
if (localZipManifest && (isFirstRun || localZipManifest.sha256 !== localSha)) {
|
||||
debugLog("New local payload detected! Applying local build...");
|
||||
sendToTauri('status', { message: 'Extracting local development payload...' });
|
||||
patcher.purgeOldCode();
|
||||
patcher.extractZipPayload(localZipPath);
|
||||
patcher.applyPatches(getReplacementsConfig());
|
||||
patcher.bridgeCredentials(serviceManager.credentialManager);
|
||||
patcher.saveCurrentVersion(localZipManifest.version, localZipManifest.sha256);
|
||||
serviceManager.envConfig = getEnvConfig();
|
||||
|
||||
isFirstRun = false;
|
||||
localVersion = localZipManifest.version;
|
||||
localSha = localZipManifest.sha256;
|
||||
debugLog("Local payload applied successfully.");
|
||||
}
|
||||
|
||||
sendToTauri('status', { message: 'Connecting to update servers...' });
|
||||
let release = null;
|
||||
@@ -277,7 +301,14 @@ async function start() {
|
||||
patcher.extractZipPayload(localZip);
|
||||
patcher.applyPatches(getReplacementsConfig());
|
||||
patcher.bridgeCredentials(serviceManager.credentialManager);
|
||||
patcher.saveCurrentVersion("1.0.0");
|
||||
|
||||
let ver = "1.0.0";
|
||||
try {
|
||||
const man = JSON.parse(fs.readFileSync(path.join(__dirname, 'manifest.json'), 'utf8'));
|
||||
ver = man.version || ver;
|
||||
} catch (e) { }
|
||||
|
||||
patcher.saveCurrentVersion(ver);
|
||||
serviceManager.envConfig = getEnvConfig();
|
||||
debugLog("Local payload extracted successfully.");
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vyla-home",
|
||||
"version": "1.1.11",
|
||||
"version": "1.1.13",
|
||||
"description": "Vyla Home Desktop App Launcher",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
@@ -54,4 +54,4 @@
|
||||
"installerHeaderIcon": "build/icon.ico"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
162
release.js
162
release.js
@@ -78,12 +78,12 @@ function uploadFileToGitLabPackage(filePath, packageName, version, fileName) {
|
||||
}
|
||||
|
||||
function createGitLabRelease(tag, releaseLinks) {
|
||||
const sendRequest = (method, path, data = null) => {
|
||||
const sendRequest = (method, reqPath, data = null) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const options = {
|
||||
hostname: 'gitlab.com',
|
||||
port: 443,
|
||||
path: path,
|
||||
path: reqPath,
|
||||
method: method,
|
||||
headers: {
|
||||
'PRIVATE-TOKEN': TOKEN,
|
||||
@@ -101,19 +101,9 @@ function createGitLabRelease(tag, releaseLinks) {
|
||||
res.on('data', chunk => body += chunk);
|
||||
res.on('end', () => {
|
||||
if (res.statusCode >= 200 && res.statusCode < 300) {
|
||||
try {
|
||||
resolve(body ? JSON.parse(body) : {});
|
||||
} catch (e) {
|
||||
resolve({});
|
||||
}
|
||||
} else if (res.statusCode === 409 && method === 'POST') {
|
||||
console.log(`Release ${tag} already exists, deleting and recreating...`);
|
||||
sendRequest('DELETE', `/api/v4/projects/${PROJECT_ID}/releases/${encodeURIComponent(tag)}`)
|
||||
.then(() => sendRequest('POST', `/api/v4/projects/${PROJECT_ID}/releases`, data))
|
||||
.then(resolve)
|
||||
.catch(reject);
|
||||
try { resolve(body ? JSON.parse(body) : {}); } catch (e) { resolve({}); }
|
||||
} else {
|
||||
reject(new Error(`Failed to publish release (HTTP ${res.statusCode}): ${body}`));
|
||||
reject(new Error(`HTTP ${res.statusCode}: ${body}`));
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -133,13 +123,37 @@ function createGitLabRelease(tag, releaseLinks) {
|
||||
name: `Vyla Home Release ${tag}`,
|
||||
tag_name: tag,
|
||||
ref: currentRef,
|
||||
description: `Automated local release ${tag}`,
|
||||
description: `Automated Multi-Platform Release ${tag}`,
|
||||
assets: {
|
||||
links: releaseLinks
|
||||
}
|
||||
};
|
||||
|
||||
return sendRequest('POST', `/api/v4/projects/${PROJECT_ID}/releases`, releaseData);
|
||||
return sendRequest('POST', `/api/v4/projects/${PROJECT_ID}/releases`, releaseData)
|
||||
.catch(err => {
|
||||
if (err.message.includes('HTTP 409')) {
|
||||
console.log(`[CI Sync] Release ${tag} already exists. Appending our OS-specific files to it...`);
|
||||
let promiseChain = Promise.resolve();
|
||||
|
||||
for (const link of releaseLinks) {
|
||||
promiseChain = promiseChain.then(() => {
|
||||
return sendRequest('POST', `/api/v4/projects/${PROJECT_ID}/releases/${encodeURIComponent(tag)}/assets/links`, {
|
||||
name: link.name,
|
||||
url: link.url,
|
||||
link_type: link.link_type
|
||||
}).catch(e => {
|
||||
if (e.message.includes('already been taken') || e.message.includes('HTTP 409') || e.message.includes('HTTP 400')) {
|
||||
console.log(`[CI Sync] Asset link '${link.name}' is already attached. Skipping.`);
|
||||
return Promise.resolve();
|
||||
}
|
||||
throw e;
|
||||
});
|
||||
});
|
||||
}
|
||||
return promiseChain.then(() => ({ name: `Vyla Home Release ${tag}`, tag_name: tag }));
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
@@ -166,7 +180,6 @@ async function main() {
|
||||
if (isFullBuild) {
|
||||
console.log('Ensuring bundled Node.js runtime...');
|
||||
await ensureBundledNode();
|
||||
|
||||
await ensureWebView2Loader();
|
||||
|
||||
const bundleDir = path.join(__dirname, 'src-tauri', 'target', 'release', 'bundle');
|
||||
@@ -174,20 +187,32 @@ async function main() {
|
||||
fs.rmSync(bundleDir, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
console.log('Compiling Windows Tauri installer locally...');
|
||||
execSync('npm run build', {
|
||||
stdio: 'inherit'
|
||||
});
|
||||
console.log('Compiling native Tauri application...');
|
||||
execSync('npm run build', { stdio: 'inherit' });
|
||||
|
||||
const nsisDir = path.join(__dirname, 'src-tauri/target/release/bundle/nsis');
|
||||
if (fs.existsSync(nsisDir)) {
|
||||
const targetVersion = version.startsWith('v') ? version.substring(1) : version;
|
||||
const files = fs.readdirSync(nsisDir).filter(f => f.endsWith('.exe') && f.includes(targetVersion));
|
||||
const targetVersion = version.startsWith('v') ? version.substring(1) : version;
|
||||
|
||||
if (files.length > 0) {
|
||||
const originalName = files[0];
|
||||
installerPath = path.join(nsisDir, originalName);
|
||||
installerUploadName = originalName.replace(/\s+/g, '-');
|
||||
if (process.platform === 'win32') {
|
||||
const nsisDir = path.join(__dirname, 'src-tauri', 'target', 'release', 'bundle', 'nsis');
|
||||
if (fs.existsSync(nsisDir)) {
|
||||
const files = fs.readdirSync(nsisDir).filter(f => f.endsWith('.exe') && f.includes(targetVersion));
|
||||
if (files.length > 0) {
|
||||
installerPath = path.join(nsisDir, files[0]);
|
||||
installerUploadName = files[0].replace(/\s+/g, '-');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const dmgDir = path.join(__dirname, 'src-tauri', 'target', 'release', 'bundle', 'dmg');
|
||||
console.log(`Checking for Mac installer in: ${dmgDir}`);
|
||||
if (fs.existsSync(dmgDir)) {
|
||||
const files = fs.readdirSync(dmgDir).filter(f => f.endsWith('.dmg') && f.includes(targetVersion));
|
||||
if (files.length > 0) {
|
||||
installerPath = path.join(dmgDir, files[0]);
|
||||
installerUploadName = files[0].replace(/\s+/g, '-');
|
||||
console.log(`Found Mac installer: ${installerUploadName}`);
|
||||
} else {
|
||||
console.log(`[WARNING] No .dmg found containing version ${targetVersion}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -208,19 +233,25 @@ async function main() {
|
||||
|
||||
if (installerPath && installerUploadName) {
|
||||
console.log(`Uploading installer ${installerUploadName}...`);
|
||||
const installerUnique = installerUploadName.replace('.exe', `-${timestamp}.exe`);
|
||||
const ext = path.extname(installerUploadName);
|
||||
const installerUnique = installerUploadName.replace(ext, `-${timestamp}${ext}`);
|
||||
const installerUrl = await uploadFileToGitLabPackage(installerPath, 'vyla-home', version, installerUnique);
|
||||
releaseLinks.push({ name: installerUploadName, url: installerUrl, link_type: 'package' });
|
||||
} else {
|
||||
console.log(`[WARNING] No installer was selected for upload! (isFullBuild: ${isFullBuild})`);
|
||||
}
|
||||
|
||||
console.log('[3/4] Publishing GitLab Release...');
|
||||
const release = await createGitLabRelease(version, releaseLinks);
|
||||
console.log(`[4/4] Release successfully created: ${release.name} (${release.tag_name})`);
|
||||
await createGitLabRelease(version, releaseLinks);
|
||||
console.log(`[4/4] Release process successfully completed for ${version}!`);
|
||||
}
|
||||
|
||||
function ensureBundledNode() {
|
||||
const os = require('os');
|
||||
const binDir = path.join(__dirname, 'bin');
|
||||
const nodeExePath = path.join(binDir, 'node.exe');
|
||||
const isWin = os.platform() === 'win32';
|
||||
const nodeExeName = isWin ? 'node.exe' : 'node';
|
||||
const nodeExePath = path.join(binDir, nodeExeName);
|
||||
|
||||
const nodeVersion = 'v22.14.0';
|
||||
const versionMarker = path.join(binDir, `node-${nodeVersion}.marker`);
|
||||
@@ -232,35 +263,58 @@ function ensureBundledNode() {
|
||||
fs.mkdirSync(binDir, { recursive: true });
|
||||
console.log(`Downloading standalone Node.js ${nodeVersion} runtime for bundling...`);
|
||||
|
||||
const nodeUrl = `https://nodejs.org/dist/${nodeVersion}/win-x64/node.exe`;
|
||||
return new Promise((resolve, reject) => {
|
||||
const fileStream = fs.createWriteStream(nodeExePath);
|
||||
https.get(nodeUrl, (res) => {
|
||||
if (res.statusCode === 302 || res.statusCode === 301) {
|
||||
https.get(res.headers.location, (redirectRes) => {
|
||||
redirectRes.pipe(fileStream);
|
||||
fileStream.on('finish', () => {
|
||||
fileStream.close();
|
||||
fs.writeFileSync(versionMarker, nodeVersion, 'utf8');
|
||||
resolve();
|
||||
});
|
||||
}).on('error', reject);
|
||||
return;
|
||||
}
|
||||
res.pipe(fileStream);
|
||||
fileStream.on('finish', () => {
|
||||
fileStream.close();
|
||||
const download = (url, dest, cb) => {
|
||||
https.get(url, (res) => {
|
||||
if (res.statusCode === 302 || res.statusCode === 301) {
|
||||
return download(res.headers.location, dest, cb);
|
||||
}
|
||||
const fileStream = fs.createWriteStream(dest);
|
||||
res.pipe(fileStream);
|
||||
fileStream.on('finish', () => {
|
||||
fileStream.close();
|
||||
cb();
|
||||
});
|
||||
}).on('error', reject);
|
||||
};
|
||||
|
||||
if (isWin) {
|
||||
const nodeUrl = `https://nodejs.org/dist/${nodeVersion}/win-x64/node.exe`;
|
||||
download(nodeUrl, nodeExePath, () => {
|
||||
fs.writeFileSync(versionMarker, nodeVersion, 'utf8');
|
||||
resolve();
|
||||
});
|
||||
}).on('error', (err) => {
|
||||
try { fs.unlinkSync(nodeExePath); } catch (e) { }
|
||||
reject(err);
|
||||
});
|
||||
} else {
|
||||
const arch = os.arch() === 'arm64' ? 'arm64' : 'x64';
|
||||
const platform = os.platform() === 'darwin' ? 'darwin' : 'linux';
|
||||
const tarName = `node-${nodeVersion}-${platform}-${arch}`;
|
||||
const nodeUrl = `https://nodejs.org/dist/${nodeVersion}/${tarName}.tar.gz`;
|
||||
const tarPath = path.join(binDir, 'node.tar.gz');
|
||||
|
||||
download(nodeUrl, tarPath, () => {
|
||||
try {
|
||||
execSync(`tar -xzf node.tar.gz ${tarName}/bin/node`, { cwd: binDir });
|
||||
|
||||
fs.renameSync(path.join(binDir, tarName, 'bin', 'node'), path.join(binDir, 'node'));
|
||||
fs.rmSync(path.join(binDir, tarName), { recursive: true, force: true });
|
||||
fs.unlinkSync(tarPath);
|
||||
|
||||
execSync(`chmod +x node`, { cwd: binDir });
|
||||
|
||||
fs.writeFileSync(versionMarker, nodeVersion, 'utf8');
|
||||
resolve();
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function ensureWebView2Loader() {
|
||||
const os = require('os');
|
||||
if (os.platform() !== 'win32') return Promise.resolve();
|
||||
|
||||
const releaseDir = path.join(__dirname, 'src-tauri', 'target', 'release');
|
||||
const rootDllPath = path.join(__dirname, 'src-tauri', 'WebView2Loader.dll');
|
||||
fs.mkdirSync(releaseDir, { recursive: true });
|
||||
|
||||
2
src-tauri/Cargo.lock
generated
2
src-tauri/Cargo.lock
generated
@@ -4222,7 +4222,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "vyla-home"
|
||||
version = "1.1.11"
|
||||
version = "1.1.13"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"serde",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "vyla-home"
|
||||
version = "1.1.11"
|
||||
version = "1.1.13"
|
||||
description = "Vyla Home Desktop App Launcher"
|
||||
edition = "2021"
|
||||
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=src/main.rs");
|
||||
println!("cargo:rerun-if-changed=tauri.conf.json");
|
||||
|
||||
if std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default() == "windows" {
|
||||
if let (Ok(manifest_dir), Ok(out_dir)) = (std::env::var("CARGO_MANIFEST_DIR"), std::env::var("OUT_DIR")) {
|
||||
let mut target_dir = std::path::PathBuf::from(out_dir);
|
||||
target_dir.pop();
|
||||
target_dir.pop();
|
||||
target_dir.pop();
|
||||
let dll_src = std::path::Path::new(&manifest_dir).join("WebView2Loader.dll");
|
||||
let dll_dest = target_dir.join("WebView2Loader.dll");
|
||||
if dll_src.exists() {
|
||||
let _ = std::fs::copy(dll_src, dll_dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tauri_build::build();
|
||||
}
|
||||
@@ -7,26 +7,19 @@ use tauri::{Emitter, Manager, State, WebviewUrl, WebviewWindowBuilder};
|
||||
|
||||
fn debug_log(msg: &str) {
|
||||
let log_dir = if let Ok(app_data) = std::env::var("APPDATA") {
|
||||
std::path::PathBuf::from(app_data)
|
||||
.join("vyla-home")
|
||||
.join("vyla-home-files")
|
||||
.join("logs")
|
||||
std::path::PathBuf::from(app_data).join("vyla-home").join("vyla-home-files").join("logs")
|
||||
} else if let Ok(home) = std::env::var("HOME") {
|
||||
std::path::PathBuf::from(home).join("Library").join("Logs").join("VylaHome")
|
||||
} else if let Ok(user_profile) = std::env::var("USERPROFILE") {
|
||||
std::path::PathBuf::from(user_profile)
|
||||
.join(".vyla-home")
|
||||
.join("logs")
|
||||
std::path::PathBuf::from(user_profile).join(".vyla-home").join("logs")
|
||||
} else {
|
||||
std::path::PathBuf::from("logs")
|
||||
std::env::temp_dir().join("vyla-home-logs")
|
||||
};
|
||||
|
||||
let _ = std::fs::create_dir_all(&log_dir);
|
||||
let log_path = log_dir.join("rust-debug.log");
|
||||
|
||||
if let Ok(mut file) = std::fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.append(true)
|
||||
.open(&log_path)
|
||||
{
|
||||
if let Ok(mut file) = std::fs::OpenOptions::new().create(true).append(true).open(&log_path) {
|
||||
use std::io::Write;
|
||||
let _ = writeln!(file, "[RUST] {}", msg);
|
||||
}
|
||||
@@ -570,11 +563,45 @@ fn main() {
|
||||
let app_data = app.path().app_data_dir().unwrap_or_default();
|
||||
let app_data_str = clean_path(&app_data);
|
||||
|
||||
let vyla_files = if let Ok(appdata_env) = std::env::var("APPDATA") {
|
||||
std::path::PathBuf::from(appdata_env).join("vyla-home").join("vyla-home-files")
|
||||
} else {
|
||||
app_data.join("vyla-home-files")
|
||||
};
|
||||
|
||||
let version_file = vyla_files.join("version.json");
|
||||
let current_app_version = app.package_info().version.to_string();
|
||||
let mut version_mismatch = false;
|
||||
|
||||
if version_file.exists() {
|
||||
if let Ok(content) = std::fs::read_to_string(&version_file) {
|
||||
if let Ok(json) = serde_json::from_str::<serde_json::Value>(&content) {
|
||||
if let Some(version) = json.get("version").and_then(|v| v.as_str()) {
|
||||
if version != current_app_version {
|
||||
version_mismatch = true;
|
||||
}
|
||||
} else {
|
||||
version_mismatch = true;
|
||||
}
|
||||
} else {
|
||||
version_mismatch = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if version_mismatch {
|
||||
debug_log(&format!("App version updated to {}. Cleaning old files.", current_app_version));
|
||||
let dirs_to_remove = ["frontend", "player", "stream-api", "auth-proxy", "config"];
|
||||
for d in dirs_to_remove {
|
||||
let _ = std::fs::remove_dir_all(vyla_files.join(d));
|
||||
}
|
||||
let _ = std::fs::remove_file(&version_file);
|
||||
}
|
||||
|
||||
let window = WebviewWindowBuilder::new(app, "main", WebviewUrl::App("index.html".into()))
|
||||
.title("Vyla Home")
|
||||
.inner_size(1280.0, 800.0)
|
||||
.decorations(false)
|
||||
.transparent(false)
|
||||
.resizable(true)
|
||||
.devtools(cfg!(debug_assertions))
|
||||
.initialization_script("window.__VYLA_WINDOW_LABEL = 'main';")
|
||||
@@ -618,11 +645,15 @@ fn main() {
|
||||
child.id()
|
||||
));
|
||||
if let Some(stderr) = child.stderr.take() {
|
||||
let w = window.clone();
|
||||
std::thread::spawn(move || {
|
||||
use std::io::{BufRead, BufReader};
|
||||
let reader = BufReader::new(stderr);
|
||||
for line in reader.lines().flatten() {
|
||||
debug_log(&format!("[NODE STDERR] {}", line));
|
||||
if line.contains("Error") || line.contains("Exception") || line.contains("MODULE_NOT_FOUND") {
|
||||
let _ = w.emit("error", serde_json::json!({ "message": format!("Backend failed: {}", line) }));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Vyla Home",
|
||||
"version": "1.1.11",
|
||||
"version": "1.1.13",
|
||||
"identifier": "com.vyla.home",
|
||||
"build": {
|
||||
"frontendDist": "../ui"
|
||||
@@ -29,8 +29,9 @@
|
||||
},
|
||||
"resources": [
|
||||
"WebView2Loader.dll",
|
||||
"../bin/*",
|
||||
"../bin/**/*",
|
||||
"../main.js",
|
||||
"../preload.js",
|
||||
"../service-manager.js",
|
||||
"../patcher.js",
|
||||
"../crypto-utils.js",
|
||||
@@ -40,4 +41,4 @@
|
||||
"../node_modules/**/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,6 +195,9 @@
|
||||
<div class="loader-container">
|
||||
<div class="loader-card">
|
||||
<div class="status-text" id="status-message">Starting runtime engine...</div>
|
||||
<div id="debug-log-box"
|
||||
style="display: none; width: 100%; max-height: 180px; overflow-y: auto; background: rgba(255, 50, 50, 0.12); border: 1px solid rgba(255, 100, 100, 0.3); border-radius: 8px; padding: 12px; font-family: monospace; font-size: 12px; color: #fca5a5; text-align: left; white-space: pre-wrap; word-break: break-all; margin-bottom: 20px; user-select: text;">
|
||||
</div>
|
||||
<div class="progress-track" id="progress-track" style="display: none;">
|
||||
<div class="progress-fill" id="progress-fill"></div>
|
||||
</div>
|
||||
@@ -257,7 +260,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
@@ -500,6 +503,7 @@ void main() {
|
||||
|
||||
<script>
|
||||
const statusEl = document.getElementById("status-message");
|
||||
const debugBox = document.getElementById("debug-log-box");
|
||||
const progressTrack = document.getElementById("progress-track");
|
||||
const progressFill = document.getElementById("progress-fill");
|
||||
const actionsEl = document.getElementById("update-actions");
|
||||
@@ -524,6 +528,12 @@ void main() {
|
||||
});
|
||||
}
|
||||
|
||||
function showDebug(msg) {
|
||||
if (!debugBox) return;
|
||||
debugBox.style.display = "block";
|
||||
debugBox.textContent = msg;
|
||||
}
|
||||
|
||||
async function initTauriEvents() {
|
||||
const eventApi = window.__TAURI__?.event || window.__TAURI_INTERNALS__;
|
||||
if (!eventApi || typeof eventApi.listen !== 'function') {
|
||||
@@ -567,23 +577,15 @@ void main() {
|
||||
});
|
||||
|
||||
eventApi.listen("error", (e) => {
|
||||
setStatus("Cleaning up background processes...", "#fca5a5");
|
||||
try {
|
||||
const core = window.__TAURI__?.core;
|
||||
if (core) {
|
||||
core.invoke("kill_orphans").finally(() => {
|
||||
setTimeout(() => {
|
||||
core.invoke("win_close").catch(() => {});
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
} catch (err) { }
|
||||
const data = e.payload || e;
|
||||
const msg = data && data.message ? data.message : JSON.stringify(data);
|
||||
setStatus("Runtime Error", "#fca5a5");
|
||||
showDebug(msg);
|
||||
});
|
||||
}
|
||||
|
||||
btnYes.addEventListener("click", () => {
|
||||
|
||||
if (actionsEl) actionsEl.style.display = "none";
|
||||
if (actionsEl) actionsEl.style.display = "none";
|
||||
setStatus("Starting update installation...");
|
||||
fetch("http://127.0.0.1:4891/update/yes", { method: "POST" }).catch(() => { });
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user