cashumit/lib/screens/settings_screen.dart.bak

520 lines
16 KiB
Dart

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:cashumit/services/firefly_api_service.dart';
import 'package:bluetooth_print/bluetooth_print.dart';
import 'package:bluetooth_print/bluetooth_print_model.dart';
import 'package:cashumit/widgets/custom_text_config_dialog.dart'; // Tambahkan import ini
class SettingsScreen extends StatefulWidget {
const SettingsScreen({super.key});
@override
State<SettingsScreen> createState() => _SettingsScreenState();
}
class _SettingsScreenState extends State<SettingsScreen> {
final _formKey = GlobalKey<FormState>();
final _urlController = TextEditingController();
final _tokenController = TextEditingController();
bool _isTestingConnection = false;
bool _isTestingAuth = false;
// Bluetooth printer variables
BluetoothPrint bluetoothPrint = BluetoothPrint.instance;
bool _isScanning = false;
List<BluetoothDevice> _devices = [];
BluetoothDevice? _selectedDevice;
bool _connected = false;
@override
void initState() {
super.initState();
_loadSettings();
_initBluetooth();
}
@override
void dispose() {
_urlController.dispose();
_tokenController.dispose();
super.dispose();
}
Future<void> _loadSettings() async {
final prefs = await SharedPreferences.getInstance();
// Tambahkan pengecekan mounted sebelum setState
if (mounted) {
setState(() {
_urlController.text = prefs.getString('firefly_url') ?? '';
_tokenController.text = prefs.getString('firefly_token') ?? '';
});
}
}
Future<void> _initBluetooth() async {
// Periksa status koneksi
final isConnected = await bluetoothPrint.isConnected ?? false;
if (mounted) {
setState(() {
_connected = isConnected;
});
}
// Listen to bluetooth state changes
bluetoothPrint.state.listen((state) {
if (mounted) {
switch (state) {
case BluetoothPrint.CONNECTED:
setState(() {
_connected = true;
});
break;
case BluetoothPrint.DISCONNECTED:
setState(() {
_connected = false;
_selectedDevice = null;
});
break;
default:
break;
}
}
});
// Load saved device
await _loadSavedBluetoothDevice();
}
/// Memuat device bluetooth yang tersimpan
Future<void> _loadSavedBluetoothDevice() async {
final prefs = await SharedPreferences.getInstance();
final deviceAddress = prefs.getString('bluetooth_device_address');
final deviceName = prefs.getString('bluetooth_device_name');
if (deviceAddress != null && deviceName != null) {
final device = BluetoothDevice();
device.name = deviceName;
device.address = deviceAddress;
if (mounted) {
setState(() {
_selectedDevice = device;
});
}
}
}
/// Menyimpan device bluetooth yang terhubung
Future<void> _saveBluetoothDevice(BluetoothDevice device) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('bluetooth_device_address', device.address ?? '');
await prefs.setString('bluetooth_device_name', device.name ?? '');
}
Future<void> _saveSettings() async {
if (_formKey.currentState!.validate()) {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('firefly_url', _urlController.text.trim());
await prefs.setString('firefly_token', _tokenController.text.trim());
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Pengaturan berhasil disimpan')),
);
}
}
}
Future<void> _testConnection() async {
// Tambahkan pengecekan mounted
if (!mounted) return;
setState(() {
_isTestingConnection = true;
});
// Simpan pengaturan terlebih dahulu
await _saveSettings();
// Uji koneksi
final success = await FireflyApiService.testConnection(baseUrl: _urlController.text.trim());
// Tambahkan pengecekan mounted sebelum setState
if (mounted) {
setState(() {
_isTestingConnection = false;
});
if (success) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Koneksi berhasil!')),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Koneksi gagal. Periksa URL dan pastikan Firefly III berjalan.')),
);
}
}
}
Future<void> _testAuthentication() async {
// Tambahkan pengecekan mounted
if (!mounted) return;
setState(() {
_isTestingAuth = true;
});
// Simpan pengaturan terlebih dahulu
await _saveSettings();
// Uji autentikasi
final success = await FireflyApiService.testAuthentication(baseUrl: _urlController.text.trim(), accessToken: _tokenController.text.trim());
// Tambahkan pengecekan mounted sebelum setState
if (mounted) {
setState(() {
_isTestingAuth = false;
});
if (success) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Autentikasi berhasil!')),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Autentikasi gagal. Periksa token yang digunakan.')),
);
}
}
}
Future<void> _scanDevices() async {
setState(() {
_isScanning = true;
_devices = [];
});
try {
// Mulai scan perangkat Bluetooth
await bluetoothPrint.startScan(timeout: const Duration(seconds: 4));
// Listen to scan results
bluetoothPrint.scanResults.listen((devices) {
if (mounted) {
setState(() {
_devices = devices;
});
}
});
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Gagal memindai perangkat: $e')),
);
}
} finally {
if (mounted) {
setState(() {
_isScanning = false;
});
}
}
}
Future<void> _connectToDevice(BluetoothDevice device) async {
try {
await bluetoothPrint.connect(device);
setState(() {
_selectedDevice = device;
});
// Simpan device yang dipilih
await _saveBluetoothDevice(device);
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Berhasil terhubung ke printer')),
);
}
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Gagal terhubung ke printer: $e')),
);
}
}
}
/// Memutuskan koneksi dari printer bluetooth
Future<void> _disconnect() async {
try {
await bluetoothPrint.disconnect();
setState(() {
_connected = false;
_selectedDevice = null;
});
// Hapus device yang tersimpan
final prefs = await SharedPreferences.getInstance();
await prefs.remove('bluetooth_device_address');
await prefs.remove('bluetooth_device_name');
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Berhasil memutus koneksi dari printer')),
);
}
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Gagal memutus koneksi dari printer: $e')),
);
}
}
}
/// Membuka dialog konfigurasi teks kustom
Future<void> _openCustomTextConfig() async {
final result = await showDialog<bool>(
context: context,
builder: (context) => const CustomTextConfigDialog(), // Tambahkan import di bagian atas
);
// Jika teks kustom berhasil disimpan, tampilkan snackbar
if (result == true && mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Teks kustom berhasil disimpan')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Pengaturan'),
centerTitle: true,
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// === Firefly III Settings ===
const Text(
'Koneksi ke Firefly III',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
const Text(
'Masukkan URL lengkap ke instance Firefly III Anda (contoh: https://firefly.example.com)',
),
const SizedBox(height: 8),
TextFormField(
controller: _urlController,
decoration: const InputDecoration(
labelText: 'Firefly III URL',
border: OutlineInputBorder(),
hintText: 'https://firefly.example.com',
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Mohon masukkan URL Firefly III';
}
return null;
},
),
const SizedBox(height: 16),
const Text(
'Masukkan Personal Access Token dari Firefly III',
),
const SizedBox(height: 8),
TextFormField(
controller: _tokenController,
decoration: const InputDecoration(
labelText: 'Access Token',
border: OutlineInputBorder(),
),
obscureText: true,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Mohon masukkan access token';
}
return null;
},
),
const SizedBox(height: 16),
Row(
children: [
Expanded(
child: ElevatedButton(
onPressed: _isTestingConnection ? null : _testConnection,
child: _isTestingConnection
? const Text('Menguji Koneksi...')
: const Text('Uji Koneksi'),
),
),
const SizedBox(width: 16),
Expanded(
child: ElevatedButton(
onPressed: _isTestingAuth ? null : _testAuthentication,
child: _isTestingAuth
? const Text('Menguji Auth...')
: const Text('Uji Auth'),
),
),
],
),
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: _saveSettings,
child: const Text('Simpan Pengaturan Firefly III'),
),
),
const SizedBox(height: 32),
// === Printer Settings ===
const Text(
'Pengaturan Printer Bluetooth',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
const Text(
'Hubungkan printer thermal Anda melalui Bluetooth untuk mencetak struk.',
),
const SizedBox(height: 16),
// Status koneksi
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(8),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('Status Printer:'),
Text(
_connected ? 'Terhubung' : 'Terputus',
style: TextStyle(
color: _connected ? Colors.green : Colors.red,
fontWeight: FontWeight.bold,
),
),
],
),
),
const SizedBox(height: 16),
// Tombol scan
ElevatedButton.icon(
onPressed: _isScanning ? null : _scanDevices,
icon: _isScanning
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Icon(Icons.bluetooth_searching),
label: Text(_isScanning ? 'Memindai...' : 'Cari Printer'),
),
const SizedBox(height: 16),
// Daftar perangkat
SizedBox(
height: 200, // Tentukan tinggi tetap untuk daftar
child: _devices.isEmpty
? const Center(
child: Text('Tidak ada perangkat ditemukan'),
)
: ListView.builder(
itemCount: _devices.length,
itemBuilder: (context, index) {
final device = _devices[index];
final isSelected = _selectedDevice?.address == device.address;
return Card(
child: ListTile(
title: Text(device.name ?? 'Unknown Device'),
subtitle: Text(device.address ?? ''),
trailing: isSelected
? const Icon(Icons.check, color: Colors.green)
: null,
onTap: () => _connectToDevice(device),
),
);
},
),
),
// Tombol disconnect
if (_connected)
Padding(
padding: const EdgeInsets.only(top: 16),
child: ElevatedButton.icon(
onPressed: _disconnect,
icon: const Icon(Icons.bluetooth_disabled),
label: const Text('Putus Koneksi'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
),
),
),
),
),
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
// Fungsi tambahan jika diperlukan
},
child: const Text('Simpan Pengaturan Printer'),
),
),
const SizedBox(height: 32),
// === Custom Text Settings ===
const Text(
'Teks Kustom Struk',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
const Text(
'Sesuaikan teks disclaimer, ucapan terima kasih, dan pantun di struk Anda.',
),
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: _openCustomTextConfig,
child: const Text('Edit Teks Kustom'),
),
),
],
),
),
),
);
}
}