12 KiB
StreamFlow Desktop App - Developer Guide
Project Structure
desktop-app/
├── src/
│ ├── main/
│ │ └── main.js # Main Electron process
│ ├── preload/
│ │ └── preload.js # Preload script (IPC bridge)
│ └── renderer/
│ ├── connection.html # Connection setup UI
│ └── connection.js # Connection logic
├── build/
│ ├── icon.png # Application icon (512x512)
│ └── streamflow.desktop # Linux desktop entry
├── resources/ # Additional resources
├── dist/ # Build output (git-ignored)
├── package.json # Dependencies and build config
├── build.sh # Build script
├── README.md # User documentation
├── INSTALLATION.md # Installation guide
├── SECURITY_AUDIT.md # Security documentation
└── LICENSE # MIT License
Development Setup
Prerequisites
-
Node.js 18+ and npm
node --version # Should be v18.0.0 or higher npm --version -
Development tools (for native modules)
# Ubuntu/Debian sudo apt install build-essential # Fedora sudo dnf groupinstall "Development Tools" # Arch sudo pacman -S base-devel -
Optional: ImageMagick (for icon generation)
sudo apt install imagemagick # Ubuntu/Debian
Installation
-
Clone the repository:
cd /path/to/tv/desktop-app -
Install dependencies:
npm install -
Create an icon (optional):
# See build/ICON_README.md for instructions # Or let build.sh create a placeholder
Running the Application
Development Mode
Run with developer tools enabled:
npm run dev
This enables:
- DevTools (Ctrl+Shift+I)
- Hot reload (when you change files, restart the app)
- Verbose logging
Production Mode
Run as end-users would:
npm start
Building the AppImage
Quick Build
# Build for current architecture
npm run build:appimage
# Or use the build script
./build.sh
The AppImage will be created in dist/:
dist/StreamFlow-1.0.0-x86_64.AppImage
Build for Specific Architecture
# x64 (64-bit Intel/AMD)
npm run build:linux -- --x64
# ARM64 (64-bit ARM, e.g., Raspberry Pi 4)
npm run build:linux -- --arm64
# Build both
npm run build:linux
Build Options
Edit package.json to customize:
{
"build": {
"appId": "com.streamflow.desktop",
"productName": "StreamFlow",
"linux": {
"target": ["AppImage"],
"category": "AudioVideo",
"icon": "build/icon.png"
}
}
}
Project Architecture
Electron Architecture
┌─────────────────────────────────────────┐
│ Main Process (Node.js) │
│ - Window management │
│ - Server configuration │
│ - Credential storage │
│ - IPC handlers │
└─────────────┬───────────────────────────┘
│ IPC (secure)
│
┌─────────────▼───────────────────────────┐
│ Preload Script (Bridge) │
│ - Exposes safe APIs via contextBridge │
│ - No direct Node.js access │
└─────────────┬───────────────────────────┘
│
┌─────────────▼───────────────────────────┐
│ Renderer Process (Chromium) │
│ - Connection window (local HTML) │
│ - Main window (loads web app) │
│ - Isolated from Node.js │
└─────────────────────────────────────────┘
Security Model
- Context Isolation: Renderer process is sandboxed
- IPC Communication: Only whitelisted methods exposed
- Credential Storage: Encrypted with electron-store
- CSP: Strict Content Security Policy
- External Links: Blocked by default
Configuration
Environment Variables
Create .env file (optional):
# Development mode
NODE_ENV=development
# Custom encryption key (production)
ENCRYPTION_KEY=your-random-32-byte-hex-string
Electron Store
Configuration stored in:
~/.config/streamflow-config/config.json
Structure:
{
"serverUrl": "https://your-server.com",
"rememberCredentials": true,
"username": "user@example.com",
"password": "encrypted-password-here"
}
Code Style
JavaScript Style
Follow these conventions:
// Use const for immutable values
const SERVER_URL = 'https://example.com';
// Use let for mutable values
let connectionStatus = 'disconnected';
// Use async/await over promises
async function fetchData() {
try {
const response = await axios.get(url);
return response.data;
} catch (error) {
logger.error('Fetch failed:', error);
throw error;
}
}
// Proper error handling
ipcMain.handle('my-handler', async (event, args) => {
try {
// Logic here
return { success: true, data };
} catch (error) {
logger.error('Handler error:', error);
return { success: false, error: error.message };
}
});
Comments
// Good: Explain WHY, not WHAT
// Check server health before storing config to prevent
// users from saving unreachable servers
const health = await testConnection(serverUrl);
// Bad: Comments that restate code
// Get the server URL
const serverUrl = config.get('serverUrl');
Testing
Manual Testing Checklist
- Connection window appears on first launch
- Server URL validation works
- Test connection succeeds for valid URLs
- Test connection fails gracefully for invalid URLs
- Credentials are saved when "Remember" is checked
- Credentials are NOT saved when unchecked
- 2FA flow works (if enabled on server)
- Main window loads web app correctly
- Video playback works
- Audio playback works
- Settings persist between sessions
- "Change Server" menu item works
- App closes cleanly
- Restart preserves configuration
Testing with Different Server Configurations
-
HTTPS Server:
https://streamflow.example.com -
HTTP Server (local):
http://localhost:3000 -
LAN Server:
http://192.168.1.100:3000 -
With 2FA Enabled:
- Test TOTP code entry
- Test backup code usage
- Test invalid code handling
Automated Testing
Currently, tests are manual. To add automated tests:
npm install --save-dev spectron mocha chai
Example test:
const { Application } = require('spectron');
const assert = require('assert');
describe('Application launch', function() {
this.timeout(10000);
beforeEach(function() {
this.app = new Application({
path: electronPath,
args: [path.join(__dirname, '..')]
});
return this.app.start();
});
afterEach(function() {
if (this.app && this.app.isRunning()) {
return this.app.stop();
}
});
it('shows connection window', async function() {
const count = await this.app.client.getWindowCount();
assert.equal(count, 1);
});
});
Debugging
Enable Logging
# Verbose logs
npm run dev -- --enable-logging --v=1
# Save logs to file
npm run dev 2>&1 | tee app.log
DevTools
In development mode, press:
Ctrl+Shift+I- Open DevToolsCtrl+R- Reload windowCtrl+Shift+R- Hard reload
Remote Debugging
# Enable remote debugging
npm run dev -- --remote-debugging-port=9222
# Then open in Chrome:
# chrome://inspect
Check Electron Version
// In DevTools console
console.log(process.versions);
// Shows Node, Chromium, V8, Electron versions
Common Issues
Issue: Cannot find module 'electron'
Solution:
rm -rf node_modules package-lock.json
npm install
Issue: AppImage won't build
Solution:
# Install dependencies
npm run postinstall
# Clean and rebuild
rm -rf dist
npm run build:appimage
Issue: Connection window doesn't show
Solution: Check if config exists:
cat ~/.config/streamflow-config/config.json
# To reset:
rm ~/.config/streamflow-config/config.json
Issue: CSP errors in console
Solution:
Verify the serverUrl in CSP matches your server. Edit src/main/main.js:
"connect-src 'self' " + serverUrl + " https: http: ws: wss:; "
Performance Optimization
Reduce Bundle Size
# Analyze bundle
npm install --save-dev webpack-bundle-analyzer
# Build with analysis
npm run build -- --analyze
Hardware Acceleration
Ensure GPU acceleration is enabled:
// In main.js
app.commandLine.appendSwitch('enable-features', 'VaapiVideoDecoder');
Check in DevTools:
chrome://gpu
Deployment
Release Checklist
- Update version in
package.json - Update
CHANGELOG.md - Test on clean system
- Build for all architectures
- Test AppImage on multiple distributions
- Generate checksums
- Create GitHub release
- Update documentation
Creating a Release
# 1. Update version
npm version patch # or minor, or major
# 2. Build
./build.sh
# 3. Generate checksums
cd dist
sha256sum StreamFlow-*.AppImage > SHA256SUMS
# 4. Create release on GitHub
# Upload AppImage files and SHA256SUMS
Versioning
Follow Semantic Versioning (SemVer):
- MAJOR: Breaking changes
- MINOR: New features, backwards compatible
- PATCH: Bug fixes, backwards compatible
Example: 1.2.3
- 1 = Major version
- 2 = Minor version
- 3 = Patch version
Contributing
Adding a New Feature
- Create a feature branch
- Implement the feature
- Test thoroughly
- Update documentation
- Submit pull request
Code Review Checklist
- Code follows style guidelines
- All functions have error handling
- Security implications considered
- Performance impact assessed
- Documentation updated
- Manual testing completed
- No sensitive data in logs
Resources
Electron Documentation
electron-builder
Tools
- electron-log - Logging
- electron-store - Settings
- electron-updater - Auto-updates
Support
For issues or questions:
- Check existing documentation
- Search GitHub issues
- Create a new issue with:
- OS and version
- Electron version
- Steps to reproduce
- Error messages
- Logs
License
MIT License - See LICENSE file for details.
Happy coding! 🚀