From 30321e051c3f42b261f9bd8fc51786712a428305 Mon Sep 17 00:00:00 2001 From: Samsularifin01 <158025491+Samsularifin01@users.noreply.github.com> Date: Thu, 11 Jun 2026 23:09:39 +0700 Subject: [PATCH] add button settings, and no sleep for devices --- .../smart_vision_assist/MainActivity.kt | 26 ++++ lib/screens/camera_screen.dart | 112 +++++++++++++++++- lib/services/api_config.dart | 2 +- 3 files changed, 138 insertions(+), 2 deletions(-) diff --git a/android/app/src/main/kotlin/com/example/smart_vision_assist/MainActivity.kt b/android/app/src/main/kotlin/com/example/smart_vision_assist/MainActivity.kt index 96dafdf..c1c22a1 100644 --- a/android/app/src/main/kotlin/com/example/smart_vision_assist/MainActivity.kt +++ b/android/app/src/main/kotlin/com/example/smart_vision_assist/MainActivity.kt @@ -5,12 +5,14 @@ import android.os.Build import android.os.VibrationEffect import android.os.Vibrator import android.os.VibratorManager +import android.view.WindowManager import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel class MainActivity : FlutterActivity() { private val vibrationChannel = "smart_vision_assist/vibration" + private val screenChannel = "smart_vision_assist/screen" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) @@ -31,6 +33,30 @@ class MainActivity : FlutterActivity() { else -> result.notImplemented() } } + + MethodChannel( + flutterEngine.dartExecutor.binaryMessenger, + screenChannel + ).setMethodCallHandler { call, result -> + when (call.method) { + "setKeepScreenOn" -> { + val enabled = call.argument("enabled") ?: false + setKeepScreenOn(enabled) + result.success(null) + } + else -> result.notImplemented() + } + } + } + + private fun setKeepScreenOn(enabled: Boolean) { + runOnUiThread { + if (enabled) { + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } else { + window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } + } } private fun vibrate(milliseconds: Long): Boolean { diff --git a/lib/screens/camera_screen.dart b/lib/screens/camera_screen.dart index 3d1a6dd..f6f2216 100644 --- a/lib/screens/camera_screen.dart +++ b/lib/screens/camera_screen.dart @@ -5,6 +5,7 @@ import 'dart:ui' as ui; import 'package:camera/camera.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../services/tts_service.dart'; @@ -19,7 +20,10 @@ class CameraScreen extends StatefulWidget { State createState() => _CameraScreenState(); } -class _CameraScreenState extends State { +class _CameraScreenState extends State with WidgetsBindingObserver { + static const MethodChannel _screenChannel = + MethodChannel("smart_vision_assist/screen"); + CameraController? controller; List? cameras; @@ -36,15 +40,31 @@ class _CameraScreenState extends State { Timer? _vibrationTimer; bool _isLoggingOut = false; + bool _isStatusActive = true; String _lastSpokenMessage = ""; DateTime? _lastSpokenAt; @override void initState() { super.initState(); + WidgetsBinding.instance.addObserver(this); + unawaited(_setKeepScreenOn(true)); initCamera(); } + Future _setKeepScreenOn(bool enabled) async { + try { + await _screenChannel.invokeMethod( + "setKeepScreenOn", + {"enabled": enabled}, + ); + } on MissingPluginException { + // Platform selain Android boleh mengabaikan fitur ini. + } catch (_) { + // Jangan sampai kegagalan wakelock mengganggu kamera. + } + } + Future initCamera() async { try { cameras = await availableCameras(); @@ -281,15 +301,91 @@ class _CameraScreenState extends State { await _tts.speak(message); } + Future _confirmDeactivateAccount() async { + final bool? confirmed = await showDialog( + context: context, + builder: (BuildContext confirmationContext) { + return AlertDialog( + title: const Text("Konfirmasi"), + content: const Text("Apakah anda yakin menonaktifkan akun ini?"), + actions: [ + TextButton( + onPressed: () => Navigator.of(confirmationContext).pop(false), + child: const Text("Tidak"), + ), + TextButton( + onPressed: () => Navigator.of(confirmationContext).pop(true), + child: const Text("Ya"), + ), + ], + ); + }, + ); + + return confirmed ?? false; + } + + void _showSettings() { + showDialog( + context: context, + builder: (BuildContext dialogContext) { + return StatefulBuilder( + builder: (BuildContext context, StateSetter setDialogState) { + return AlertDialog( + title: const Text("Setting"), + content: SwitchListTile( + contentPadding: EdgeInsets.zero, + title: const Text("Status"), + subtitle: Text(_isStatusActive ? "Aktif" : "Nonaktif"), + value: _isStatusActive, + onChanged: (bool value) async { + if (!value) { + final bool isConfirmed = + await _confirmDeactivateAccount(); + if (!isConfirmed || !mounted) { + return; + } + } + + setState(() { + _isStatusActive = value; + }); + setDialogState(() {}); + }, + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(dialogContext).pop(), + child: const Text("Tutup"), + ), + ], + ); + }, + ); + }, + ); + } + @override void dispose() { _detectionTimer?.cancel(); _vibrationTimer?.cancel(); + WidgetsBinding.instance.removeObserver(this); + unawaited(_setKeepScreenOn(false)); unawaited(_vibrationService.stop()); controller?.dispose(); super.dispose(); } + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + if (state == AppLifecycleState.resumed) { + unawaited(_setKeepScreenOn(true)); + } else { + unawaited(_setKeepScreenOn(false)); + } + } + Widget buildCameraPreview() { final Size? previewSize = controller?.value.previewSize; if (previewSize == null) { @@ -421,6 +517,20 @@ class _CameraScreenState extends State { ), ), ), + Positioned( + bottom: 40, + left: MediaQuery.of(context).size.width / 2 - 130, + child: Semantics( + label: "Buka setting", + button: true, + child: FloatingActionButton( + heroTag: "camera_settings", + backgroundColor: Colors.black, + onPressed: _showSettings, + child: const Icon(Icons.settings, color: Colors.white), + ), + ), + ), ], ), ), diff --git a/lib/services/api_config.dart b/lib/services/api_config.dart index 9fa5973..6a8d33b 100644 --- a/lib/services/api_config.dart +++ b/lib/services/api_config.dart @@ -5,7 +5,7 @@ class ApiConfig { static const bool useAndroidEmulator = false; // Ganti IP ini dengan IP laptop/PC Anda saat menggunakan HP fisik (ADB). - static const String deviceHost = "192.168.110.147:8000"; + static const String deviceHost = "192.168.0.31:8000"; static String get baseUrl { if (Platform.isAndroid && useAndroidEmulator) {