546 lines
12 KiB
Markdown
546 lines
12 KiB
Markdown
|
|
# 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
|
||
|
|
|
||
|
|
1. **Node.js 18+** and **npm**
|
||
|
|
```bash
|
||
|
|
node --version # Should be v18.0.0 or higher
|
||
|
|
npm --version
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **Development tools** (for native modules)
|
||
|
|
```bash
|
||
|
|
# Ubuntu/Debian
|
||
|
|
sudo apt install build-essential
|
||
|
|
|
||
|
|
# Fedora
|
||
|
|
sudo dnf groupinstall "Development Tools"
|
||
|
|
|
||
|
|
# Arch
|
||
|
|
sudo pacman -S base-devel
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **Optional: ImageMagick** (for icon generation)
|
||
|
|
```bash
|
||
|
|
sudo apt install imagemagick # Ubuntu/Debian
|
||
|
|
```
|
||
|
|
|
||
|
|
### Installation
|
||
|
|
|
||
|
|
1. **Clone the repository:**
|
||
|
|
```bash
|
||
|
|
cd /path/to/tv/desktop-app
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **Install dependencies:**
|
||
|
|
```bash
|
||
|
|
npm install
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **Create an icon** (optional):
|
||
|
|
```bash
|
||
|
|
# See build/ICON_README.md for instructions
|
||
|
|
# Or let build.sh create a placeholder
|
||
|
|
```
|
||
|
|
|
||
|
|
## Running the Application
|
||
|
|
|
||
|
|
### Development Mode
|
||
|
|
|
||
|
|
Run with developer tools enabled:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
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:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
npm start
|
||
|
|
```
|
||
|
|
|
||
|
|
## Building the AppImage
|
||
|
|
|
||
|
|
### Quick Build
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 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
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 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:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"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
|
||
|
|
|
||
|
|
1. **Context Isolation:** Renderer process is sandboxed
|
||
|
|
2. **IPC Communication:** Only whitelisted methods exposed
|
||
|
|
3. **Credential Storage:** Encrypted with electron-store
|
||
|
|
4. **CSP:** Strict Content Security Policy
|
||
|
|
5. **External Links:** Blocked by default
|
||
|
|
|
||
|
|
## Configuration
|
||
|
|
|
||
|
|
### Environment Variables
|
||
|
|
|
||
|
|
Create `.env` file (optional):
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 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:
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"serverUrl": "https://your-server.com",
|
||
|
|
"rememberCredentials": true,
|
||
|
|
"username": "user@example.com",
|
||
|
|
"password": "encrypted-password-here"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Code Style
|
||
|
|
|
||
|
|
### JavaScript Style
|
||
|
|
|
||
|
|
Follow these conventions:
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
// 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
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
// 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
|
||
|
|
|
||
|
|
1. **HTTPS Server:**
|
||
|
|
```
|
||
|
|
https://streamflow.example.com
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **HTTP Server (local):**
|
||
|
|
```
|
||
|
|
http://localhost:3000
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **LAN Server:**
|
||
|
|
```
|
||
|
|
http://192.168.1.100:3000
|
||
|
|
```
|
||
|
|
|
||
|
|
4. **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:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
npm install --save-dev spectron mocha chai
|
||
|
|
```
|
||
|
|
|
||
|
|
Example test:
|
||
|
|
```javascript
|
||
|
|
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
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 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 DevTools
|
||
|
|
- `Ctrl+R` - Reload window
|
||
|
|
- `Ctrl+Shift+R` - Hard reload
|
||
|
|
|
||
|
|
### Remote Debugging
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Enable remote debugging
|
||
|
|
npm run dev -- --remote-debugging-port=9222
|
||
|
|
|
||
|
|
# Then open in Chrome:
|
||
|
|
# chrome://inspect
|
||
|
|
```
|
||
|
|
|
||
|
|
### Check Electron Version
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
// In DevTools console
|
||
|
|
console.log(process.versions);
|
||
|
|
// Shows Node, Chromium, V8, Electron versions
|
||
|
|
```
|
||
|
|
|
||
|
|
## Common Issues
|
||
|
|
|
||
|
|
### Issue: `Cannot find module 'electron'`
|
||
|
|
|
||
|
|
**Solution:**
|
||
|
|
```bash
|
||
|
|
rm -rf node_modules package-lock.json
|
||
|
|
npm install
|
||
|
|
```
|
||
|
|
|
||
|
|
### Issue: AppImage won't build
|
||
|
|
|
||
|
|
**Solution:**
|
||
|
|
```bash
|
||
|
|
# 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:
|
||
|
|
```bash
|
||
|
|
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`:
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
"connect-src 'self' " + serverUrl + " https: http: ws: wss:; "
|
||
|
|
```
|
||
|
|
|
||
|
|
## Performance Optimization
|
||
|
|
|
||
|
|
### Reduce Bundle Size
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Analyze bundle
|
||
|
|
npm install --save-dev webpack-bundle-analyzer
|
||
|
|
|
||
|
|
# Build with analysis
|
||
|
|
npm run build -- --analyze
|
||
|
|
```
|
||
|
|
|
||
|
|
### Hardware Acceleration
|
||
|
|
|
||
|
|
Ensure GPU acceleration is enabled:
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
// 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
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 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
|
||
|
|
|
||
|
|
1. Create a feature branch
|
||
|
|
2. Implement the feature
|
||
|
|
3. Test thoroughly
|
||
|
|
4. Update documentation
|
||
|
|
5. 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
|
||
|
|
|
||
|
|
- [Official Docs](https://www.electronjs.org/docs)
|
||
|
|
- [Security Guidelines](https://www.electronjs.org/docs/tutorial/security)
|
||
|
|
- [API Reference](https://www.electronjs.org/docs/api)
|
||
|
|
|
||
|
|
### electron-builder
|
||
|
|
|
||
|
|
- [Documentation](https://www.electron.build/)
|
||
|
|
- [Linux Configuration](https://www.electron.build/configuration/linux)
|
||
|
|
- [AppImage Options](https://www.electron.build/configuration/appimage)
|
||
|
|
|
||
|
|
### Tools
|
||
|
|
|
||
|
|
- [electron-log](https://github.com/megahertz/electron-log) - Logging
|
||
|
|
- [electron-store](https://github.com/sindresorhus/electron-store) - Settings
|
||
|
|
- [electron-updater](https://github.com/electron-userland/electron-builder/tree/master/packages/electron-updater) - Auto-updates
|
||
|
|
|
||
|
|
## Support
|
||
|
|
|
||
|
|
For issues or questions:
|
||
|
|
|
||
|
|
1. Check existing documentation
|
||
|
|
2. Search GitHub issues
|
||
|
|
3. 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! 🚀**
|