feat: Add mobile (Flutter) and desktop (Electron) applications

- Add Flutter mobile app with authentication, timer, projects, and time entries
- Add Electron desktop app with system tray integration and offline support
- Implement offline storage with sync queue for both platforms
- Add comprehensive build scripts for cross-platform builds
- Include documentation and README files for both apps
- Add test suites for mobile and desktop applications
This commit is contained in:
Dries Peeters
2026-01-11 08:37:28 +01:00
parent 4a8607f400
commit 1419712a60
44 changed files with 5112 additions and 0 deletions
+82
View File
@@ -0,0 +1,82 @@
#!/usr/bin/env node
/**
* Platform-aware build script for electron-builder
* Builds for all platforms supported on the current OS
*/
const { execSync } = require('child_process');
const os = require('os');
const platform = os.platform();
let buildCommand = 'electron-builder';
console.log(`\n🔨 Building for all supported platforms on ${platform}\n`);
// Determine which platforms can be built on the current OS
switch (platform) {
case 'win32':
// Windows can technically build Linux, but requires admin privileges for symlinks
// For better UX, only build Windows on Windows by default
// Use --linux flag explicitly if admin privileges are available
const buildLinux = process.env.BUILD_LINUX_ON_WINDOWS === 'true';
if (buildLinux) {
console.log('📦 Building for Windows and Linux...');
console.log('⚠️ Linux builds on Windows require administrator privileges for symlinks.');
console.log(' If this fails, run as administrator or use: npm run build:win\n');
buildCommand += ' --win --linux';
} else {
console.log('📦 Building for Windows only...');
console.log('️ Linux builds on Windows require admin privileges (symlinks).');
console.log(' To build Linux too, set BUILD_LINUX_ON_WINDOWS=true and run as admin.\n');
buildCommand += ' --win';
}
break;
case 'darwin':
// macOS can build: Windows, macOS, Linux
console.log('📦 Building for Windows, macOS, and Linux...');
console.log('️ All platforms supported on macOS!\n');
buildCommand += ' --win --mac --linux';
break;
case 'linux':
// Linux can build: Windows, Linux
console.log('📦 Building for Windows and Linux...');
console.log('️ macOS builds require macOS. Skipping macOS build.\n');
buildCommand += ' --win --linux';
break;
default:
console.error(`❌ Unknown platform: ${platform}`);
console.log('📦 Building for current platform only...\n');
// Just build for current platform
break;
}
// Disable code signing for Windows unless certificate is explicitly provided
if (platform === 'win32') {
if (process.env.CSC_LINK || process.env.CSC_LINK_FILE) {
console.log('️ Code signing will be enabled (certificate detected)\n');
} else {
console.log('️ Code signing disabled (no certificate configured)\n');
// Explicitly disable signing to avoid errors
buildCommand += ' --config.win.sign=null';
}
}
try {
execSync(buildCommand, { stdio: 'inherit' });
console.log('\n✅ Build completed successfully!');
} catch (error) {
if (platform === 'win32') {
console.error('\n❌ Build failed!');
console.error('\n💡 Troubleshooting tips for Windows:');
console.error(' 1. Try running as Administrator');
console.error(' 2. Clear electron-builder cache: rmdir /s /q "%LOCALAPPDATA%\\electron-builder\\Cache"');
console.error(' 3. Build Windows only: npm run build:win');
console.error(' 4. Disable OneDrive sync for the desktop folder');
} else {
console.error('\n❌ Build failed!');
}
process.exit(1);
}
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env node
/**
* Clean electron-builder cache
* Helps resolve permission/symlink issues on Windows
*/
const { execSync } = require('child_process');
const os = require('os');
const path = require('path');
const fs = require('fs');
const platform = os.platform();
const cacheDir = path.join(os.homedir(),
platform === 'win32'
? 'AppData/Local/electron-builder/Cache'
: platform === 'darwin'
? 'Library/Caches/electron-builder'
: '.cache/electron-builder'
);
console.log(`\n🧹 Cleaning electron-builder cache...\n`);
console.log(`📁 Cache directory: ${cacheDir}\n`);
try {
if (fs.existsSync(cacheDir)) {
if (platform === 'win32') {
// Windows: use rmdir command
try {
execSync(`rmdir /s /q "${cacheDir}"`, { stdio: 'inherit' });
console.log('✅ Cache cleaned successfully!');
} catch (error) {
console.error('❌ Failed to clean cache. Try running as Administrator.');
console.error(' Or manually delete:', cacheDir);
process.exit(1);
}
} else {
// Unix: use rm command
execSync(`rm -rf "${cacheDir}"`, { stdio: 'inherit' });
console.log('✅ Cache cleaned successfully!');
}
} else {
console.log('️ Cache directory does not exist (already clean)');
}
} catch (error) {
console.error('❌ Error cleaning cache:', error.message);
console.error(' Try running as Administrator (Windows) or with sudo (Unix)');
process.exit(1);
}