Update: 2026-05-08 05:24:38
This commit is contained in:
106
musadaq-app/lib/core/services/home_widget_service.dart
Normal file
106
musadaq-app/lib/core/services/home_widget_service.dart
Normal file
@@ -0,0 +1,106 @@
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../network/dio_client.dart';
|
||||
|
||||
/// Home Screen Widget Service
|
||||
/// Manages data for native iOS/Android home screen widgets.
|
||||
///
|
||||
/// Widgets show:
|
||||
/// - Quick stats (invoice count, pending, quota)
|
||||
/// - Quick scan shortcut
|
||||
/// - Today's activity summary
|
||||
///
|
||||
/// Uses MethodChannel to communicate with native widget code.
|
||||
class HomeWidgetService extends GetxService {
|
||||
static const _channel = MethodChannel('com.musadaq.widget');
|
||||
|
||||
// Widget data
|
||||
final totalInvoices = 0.obs;
|
||||
final pendingInvoices = 0.obs;
|
||||
final quotaUsed = 0.obs;
|
||||
final quotaLimit = 0.obs;
|
||||
final lastUpdate = ''.obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
// Listen for widget tap events
|
||||
_channel.setMethodCallHandler(_handleWidgetAction);
|
||||
refreshWidgetData();
|
||||
}
|
||||
|
||||
/// Refresh widget data from API
|
||||
Future<void> refreshWidgetData() async {
|
||||
try {
|
||||
final res = await DioClient().client.get('/v1/dashboard/stats');
|
||||
if (res.data['success'] == true) {
|
||||
final data = res.data['data'];
|
||||
totalInvoices.value = data['invoices']?['total'] ?? 0;
|
||||
pendingInvoices.value = data['invoices']?['pending'] ?? 0;
|
||||
}
|
||||
|
||||
final subRes = await DioClient().client.get('/v1/subscriptions/current');
|
||||
if (subRes.data['success'] == true) {
|
||||
final sub = subRes.data['data'];
|
||||
quotaUsed.value = sub['invoices']?['used'] ?? 0;
|
||||
quotaLimit.value = sub['invoices']?['limit'] ?? 0;
|
||||
}
|
||||
|
||||
lastUpdate.value = DateTime.now().toString().substring(0, 16);
|
||||
|
||||
// Push data to native widget
|
||||
await _updateNativeWidget();
|
||||
} catch (e) {
|
||||
// Widget update failure is non-critical
|
||||
}
|
||||
}
|
||||
|
||||
/// Push data to native home screen widget
|
||||
Future<void> _updateNativeWidget() async {
|
||||
try {
|
||||
await _channel.invokeMethod('updateWidget', {
|
||||
'total_invoices': totalInvoices.value,
|
||||
'pending_invoices': pendingInvoices.value,
|
||||
'quota_used': quotaUsed.value,
|
||||
'quota_limit': quotaLimit.value,
|
||||
'quota_percent': quotaLimit.value > 0
|
||||
? ((quotaUsed.value / quotaLimit.value) * 100).round()
|
||||
: 0,
|
||||
'last_update': lastUpdate.value,
|
||||
});
|
||||
} on MissingPluginException {
|
||||
// Widget not supported on this platform
|
||||
} catch (e) {
|
||||
// Non-critical
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle taps from the native widget
|
||||
Future<dynamic> _handleWidgetAction(MethodCall call) async {
|
||||
switch (call.method) {
|
||||
case 'openScanner':
|
||||
Get.toNamed('/scanner');
|
||||
break;
|
||||
case 'openInvoices':
|
||||
Get.toNamed('/main');
|
||||
break;
|
||||
case 'refreshData':
|
||||
await refreshWidgetData();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// Get widget display data as a map
|
||||
Map<String, dynamic> getWidgetData() {
|
||||
return {
|
||||
'total_invoices': totalInvoices.value,
|
||||
'pending_invoices': pendingInvoices.value,
|
||||
'quota_used': quotaUsed.value,
|
||||
'quota_limit': quotaLimit.value,
|
||||
'quota_percent': quotaLimit.value > 0
|
||||
? ((quotaUsed.value / quotaLimit.value) * 100).round()
|
||||
: 0,
|
||||
'last_update': lastUpdate.value,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user