Initial commit

This commit is contained in:
2026-03-21 01:34:22 +01:00
parent 8ec17d5ed4
commit 6805f4a3f4
144 changed files with 7312 additions and 13 deletions

View File

@@ -0,0 +1,25 @@
import 'dart:io';
import 'package:flutter/services.dart';
class AutostartService {
static const _channel = MethodChannel('com.igox.busylight_buddy/autostart');
/// Returns true only on supported platforms (macOS, Windows)
static bool get isSupported => Platform.isMacOS || Platform.isWindows;
static Future<bool> isEnabled() async {
if (!isSupported) return false;
try {
return await _channel.invokeMethod<bool>('isEnabled') ?? false;
} catch (_) {
return false;
}
}
static Future<void> setEnabled(bool enabled) async {
if (!isSupported) return;
try {
await _channel.invokeMethod('setEnabled', {'enabled': enabled});
} catch (_) {}
}
}

View File

@@ -0,0 +1,99 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import '../models/busylight_color.dart';
import '../models/busylight_status.dart';
class BusylightException implements Exception {
final String message;
const BusylightException(this.message);
@override
String toString() => 'BusylightException: $message';
}
class BusylightService {
final String baseUrl;
final Duration timeout;
BusylightService({
required this.baseUrl,
this.timeout = const Duration(seconds: 5),
});
Uri _uri(String path) => Uri.parse('$baseUrl$path');
Future<Map<String, dynamic>> _get(String path) async {
try {
final res = await http.get(_uri(path)).timeout(timeout);
_checkStatus(res);
return jsonDecode(res.body) as Map<String, dynamic>;
} on BusylightException {
rethrow;
} catch (e) {
throw BusylightException('Network error: $e');
}
}
Future<Map<String, dynamic>> _post(String path, [Map<String, dynamic>? body]) async {
try {
final res = await http
.post(
_uri(path),
headers: {'Content-Type': 'application/json'},
body: body != null ? jsonEncode(body) : null,
)
.timeout(timeout);
_checkStatus(res);
return jsonDecode(res.body) as Map<String, dynamic>;
} on BusylightException {
rethrow;
} catch (e) {
throw BusylightException('Network error: $e');
}
}
void _checkStatus(http.Response res) {
if (res.statusCode < 200 || res.statusCode >= 300) {
throw BusylightException('HTTP ${res.statusCode}: ${res.body}');
}
}
// ── Status ──────────────────────────────────────────────────────────────────
Future<BusylightStatus> getStatus() async {
final json = await _get('/api/status');
return BusylightStatus.fromString(json['status'] as String);
}
Future<BusylightStatus> setStatus(BusylightStatus status) async {
final json = await _post(status.apiPath);
return BusylightStatus.fromString(json['status'] as String);
}
Future<BusylightStatus> turnOn() => setStatus(BusylightStatus.on);
Future<BusylightStatus> turnOff() => setStatus(BusylightStatus.off);
Future<BusylightStatus> setAvailable() => setStatus(BusylightStatus.available);
Future<BusylightStatus> setAway() => setStatus(BusylightStatus.away);
Future<BusylightStatus> setBusy() => setStatus(BusylightStatus.busy);
// ── Color ───────────────────────────────────────────────────────────────────
Future<BusylightColor> getColor() async {
final json = await _get('/api/color');
return BusylightColor.fromJson(json);
}
Future<void> setColor(BusylightColor color) async {
await _post('/api/color', color.toJson());
}
// ── Brightness ──────────────────────────────────────────────────────────────
// Note: brightness is read from GET /api/color response, no separate endpoint needed.
Future<void> setBrightness(double brightness) async {
await _post('/api/brightness', {'brightness': brightness.clamp(0.0, 1.0)});
}
// ── Debug ───────────────────────────────────────────────────────────────────
Future<Map<String, dynamic>> getDebug() => _get('/api/debug');
}