Implement PrintingStatusCard in ReceiptSpeedDial and improve error handling for Bluetooth printer connection
parent
a2eedc8efc
commit
b88c301d7d
|
@ -1,5 +1,4 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'dart:typed_data';
|
|
||||||
import 'package:cashumit/models/receipt_item.dart';
|
import 'package:cashumit/models/receipt_item.dart';
|
||||||
import 'package:cashumit/screens/add_item_screen.dart';
|
import 'package:cashumit/screens/add_item_screen.dart';
|
||||||
import 'package:bluetooth_print/bluetooth_print.dart';
|
import 'package:bluetooth_print/bluetooth_print.dart';
|
||||||
|
@ -12,6 +11,7 @@ import 'package:cashumit/widgets/store_info_config_dialog.dart';
|
||||||
import 'package:cashumit/widgets/custom_text_config_dialog.dart';
|
import 'package:cashumit/widgets/custom_text_config_dialog.dart';
|
||||||
import 'package:cashumit/screens/webview_screen.dart';
|
import 'package:cashumit/screens/webview_screen.dart';
|
||||||
import 'package:cashumit/widgets/receipt_speed_dial.dart';
|
import 'package:cashumit/widgets/receipt_speed_dial.dart';
|
||||||
|
import 'package:cashumit/widgets/printing_status_card.dart';
|
||||||
|
|
||||||
// Import service baru
|
// Import service baru
|
||||||
import 'package:cashumit/services/account_dialog_service.dart';
|
import 'package:cashumit/services/account_dialog_service.dart';
|
||||||
|
@ -21,6 +21,10 @@ import 'package:cashumit/services/esc_pos_print_service.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:cashumit/providers/receipt_provider.dart';
|
import 'package:cashumit/providers/receipt_provider.dart';
|
||||||
|
|
||||||
|
// Import untuk penanganan error
|
||||||
|
import 'dart:io';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
class ReceiptScreen extends StatefulWidget {
|
class ReceiptScreen extends StatefulWidget {
|
||||||
const ReceiptScreen({super.key});
|
const ReceiptScreen({super.key});
|
||||||
|
|
||||||
|
@ -31,6 +35,9 @@ class ReceiptScreen extends StatefulWidget {
|
||||||
class _ReceiptScreenState extends State<ReceiptScreen> {
|
class _ReceiptScreenState extends State<ReceiptScreen> {
|
||||||
// Bluetooth service
|
// Bluetooth service
|
||||||
final BluetoothService _bluetoothService = BluetoothService();
|
final BluetoothService _bluetoothService = BluetoothService();
|
||||||
|
|
||||||
|
// Printing status
|
||||||
|
bool _isPrinting = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
@ -108,25 +115,25 @@ class _ReceiptScreenState extends State<ReceiptScreen> {
|
||||||
final receiptProvider = context.read<ReceiptProvider>();
|
final receiptProvider = context.read<ReceiptProvider>();
|
||||||
final state = receiptProvider.state;
|
final state = receiptProvider.state;
|
||||||
|
|
||||||
// Cek dan reconnect jika perlu
|
|
||||||
final isConnected = await _bluetoothService.reconnectIfNeeded();
|
|
||||||
if (!isConnected) {
|
|
||||||
if (!mounted) return;
|
|
||||||
if (_bluetoothService.connectedDevice != null) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(
|
|
||||||
content: Text('Gagal menyambungkan ke printer')),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(
|
|
||||||
content: Text('Harap hubungkan printer terlebih dahulu')),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Cek dan reconnect jika perlu
|
||||||
|
final isConnected = await _bluetoothService.reconnectIfNeeded();
|
||||||
|
if (!isConnected) {
|
||||||
|
if (!mounted) return;
|
||||||
|
if (_bluetoothService.connectedDevice != null) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(
|
||||||
|
content: Text('Gagal menyambungkan ke printer')),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(
|
||||||
|
content: Text('Harap hubungkan printer terlebih dahulu')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await EscPosPrintService.printToThermalPrinter(
|
await EscPosPrintService.printToThermalPrinter(
|
||||||
items: state.items,
|
items: state.items,
|
||||||
transactionDate: state.transactionDate,
|
transactionDate: state.transactionDate,
|
||||||
|
@ -138,13 +145,39 @@ class _ReceiptScreenState extends State<ReceiptScreen> {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(content: Text('Perintah cetak dikirim ke printer')),
|
const SnackBar(content: Text('Perintah cetak dikirim ke printer')),
|
||||||
);
|
);
|
||||||
|
} on SocketException catch (e) {
|
||||||
|
// Tangani error koneksi secara spesifik
|
||||||
|
if (!mounted) return;
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(content: Text('Koneksi ke printer terputus: ${e.message}')),
|
||||||
|
);
|
||||||
|
} on PlatformException catch (e) {
|
||||||
|
// Tangani error platform secara spesifik
|
||||||
|
if (!mounted) return;
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(content: Text('Error printer: ${e.message}')),
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
// Tangani error umum
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text('Gagal mencetak struk: $e')),
|
SnackBar(content: Text('Gagal mencetak struk: $e')),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Methods to control printing status
|
||||||
|
void _startPrinting() {
|
||||||
|
setState(() {
|
||||||
|
_isPrinting = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _endPrinting() {
|
||||||
|
setState(() {
|
||||||
|
_isPrinting = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void _addItem() async {
|
void _addItem() async {
|
||||||
final newItem = await showDialog<ReceiptItem>(
|
final newItem = await showDialog<ReceiptItem>(
|
||||||
|
@ -330,95 +363,109 @@ class _ReceiptScreenState extends State<ReceiptScreen> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Stack(
|
||||||
backgroundColor:
|
children: [
|
||||||
Colors.grey[300], // Latar belakang abu-abu untuk efek struk
|
Scaffold(
|
||||||
floatingActionButton: Consumer<ReceiptProvider>(
|
backgroundColor:
|
||||||
builder: (context, receiptProvider, child) {
|
Colors.grey[300], // Latar belakang abu-abu untuk efek struk
|
||||||
final state = receiptProvider.state;
|
floatingActionButton: Consumer<ReceiptProvider>(
|
||||||
return ReceiptSpeedDial(
|
builder: (context, receiptProvider, child) {
|
||||||
bluetoothService: _bluetoothService,
|
final state = receiptProvider.state;
|
||||||
onCheckConnection: _checkBluetoothConnection,
|
return ReceiptSpeedDial(
|
||||||
onPrint: _printToThermalPrinter,
|
bluetoothService: _bluetoothService,
|
||||||
onSettings: _openSettings,
|
onCheckConnection: _checkBluetoothConnection,
|
||||||
onReloadAccounts: receiptProvider.loadAccounts,
|
onPrint: _printToThermalPrinter,
|
||||||
hasItems: state.items.isNotEmpty,
|
onSettings: _openSettings,
|
||||||
hasSourceAccount: state.sourceAccountId != null,
|
onReloadAccounts: receiptProvider.loadAccounts,
|
||||||
hasDestinationAccount: state.destinationAccountId != null,
|
hasItems: state.items.isNotEmpty,
|
||||||
onSendToFirefly: _sendToFirefly,
|
hasSourceAccount: state.sourceAccountId != null,
|
||||||
);
|
hasDestinationAccount: state.destinationAccountId != null,
|
||||||
}
|
onSendToFirefly: _sendToFirefly,
|
||||||
),
|
onPrintingStart: _startPrinting,
|
||||||
body: SafeArea(
|
onPrintingEnd: _endPrinting,
|
||||||
child: Center(
|
);
|
||||||
// Membungkus dengan widget Center untuk memastikan struk berada di tengah
|
}
|
||||||
child: SingleChildScrollView(
|
),
|
||||||
child: Column(
|
body: SafeArea(
|
||||||
crossAxisAlignment: CrossAxisAlignment
|
child: Center(
|
||||||
.center, // Memusatkan konten secara horizontal
|
// Membungkus dengan widget Center untuk memastikan struk berada di tengah
|
||||||
children: [
|
child: SingleChildScrollView(
|
||||||
// Background untuk efek kertas struk tersobek di bagian atas
|
child: Column(
|
||||||
Container(
|
crossAxisAlignment: CrossAxisAlignment
|
||||||
width: 360,
|
.center, // Memusatkan konten secara horizontal
|
||||||
color: const Color(0xFFE0E0E0), // Warna latar belakang sesuai dengan latar belakang layar
|
children: [
|
||||||
child: const Column(
|
// Background untuk efek kertas struk tersobek di bagian atas
|
||||||
children: [
|
Container(
|
||||||
SizedBox(height: 15), // Jarak atas yang lebih besar
|
width: 360,
|
||||||
ReceiptTearTop(), // Efek kertas struk tersobek di bagian atas
|
color: const Color(0xFFE0E0E0), // Warna latar belakang sesuai dengan latar belakang layar
|
||||||
],
|
child: const Column(
|
||||||
),
|
children: [
|
||||||
),
|
SizedBox(height: 15), // Jarak atas yang lebih besar
|
||||||
|
ReceiptTearTop(), // Efek kertas struk tersobek di bagian atas
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
// Konten struk
|
// Konten struk
|
||||||
Consumer<ReceiptProvider>(
|
Consumer<ReceiptProvider>(
|
||||||
builder: (context, receiptProvider, child) {
|
builder: (context, receiptProvider, child) {
|
||||||
final state = receiptProvider.state;
|
final state = receiptProvider.state;
|
||||||
return ReceiptBody(
|
return ReceiptBody(
|
||||||
items: state.items,
|
items: state.items,
|
||||||
sourceAccountName: state.sourceAccountName,
|
sourceAccountName: state.sourceAccountName,
|
||||||
destinationAccountName: state.destinationAccountName,
|
destinationAccountName: state.destinationAccountName,
|
||||||
onOpenStoreInfoConfig: _openStoreInfoConfig,
|
onOpenStoreInfoConfig: _openStoreInfoConfig,
|
||||||
onSelectSourceAccount: () => _selectSourceAccount(), // Memanggil fungsi langsung
|
onSelectSourceAccount: () => _selectSourceAccount(), // Memanggil fungsi langsung
|
||||||
onSelectDestinationAccount: () => _selectDestinationAccount(), // Memanggil fungsi langsung
|
onSelectDestinationAccount: () => _selectDestinationAccount(), // Memanggil fungsi langsung
|
||||||
onOpenCustomTextConfig: _openCustomTextConfig,
|
onOpenCustomTextConfig: _openCustomTextConfig,
|
||||||
total: state.total,
|
total: state.total,
|
||||||
onEditItem: (index) => _editItem(index), // Memanggil fungsi langsung
|
onEditItem: (index) => _editItem(index), // Memanggil fungsi langsung
|
||||||
onRemoveItem: (index) {
|
onRemoveItem: (index) {
|
||||||
// Validasi index untuk mencegah error
|
// Validasi index untuk mencegah error
|
||||||
if (index >= 0 && index < state.items.length) {
|
if (index >= 0 && index < state.items.length) {
|
||||||
// Hapus item dari daftar melalui provider
|
// Hapus item dari daftar melalui provider
|
||||||
receiptProvider.removeItem(index);
|
receiptProvider.removeItem(index);
|
||||||
} else {
|
} else {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(
|
const SnackBar(
|
||||||
content: Text(
|
content: Text(
|
||||||
"Gagal menghapus item: Index tidak valid.")),
|
"Gagal menghapus item: Index tidak valid.")),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onAddItem: () => _addItem(), // Memanggil fungsi langsung
|
onAddItem: () => _addItem(), // Memanggil fungsi langsung
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
|
||||||
// Background untuk efek kertas struk tersobek di bagian bawah
|
// Background untuk efek kertas struk tersobek di bagian bawah
|
||||||
Container(
|
Container(
|
||||||
width: 360,
|
width: 360,
|
||||||
color: const Color(0xFFE0E0E0), // Warna latar belakang sesuai dengan latar belakang layar
|
color: const Color(0xFFE0E0E0), // Warna latar belakang sesuai dengan latar belakang layar
|
||||||
child: const Column(
|
child: const Column(
|
||||||
children: [
|
children: [
|
||||||
ReceiptTearBottom(), // Efek kertas struk tersobek di bagian bawah
|
ReceiptTearBottom(), // Efek kertas struk tersobek di bagian bawah
|
||||||
SizedBox(height: 15), // Jarak bawah yang lebih besar
|
SizedBox(height: 15), // Jarak bawah yang lebih besar
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
PrintingStatusCard(
|
||||||
|
isVisible: _isPrinting,
|
||||||
|
onDismiss: () {
|
||||||
|
setState(() {
|
||||||
|
_isPrinting = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
import 'package:bluetooth_print/bluetooth_print.dart';
|
import 'package:bluetooth_print/bluetooth_print.dart';
|
||||||
import 'package:bluetooth_print/bluetooth_print_model.dart';
|
import 'package:bluetooth_print/bluetooth_print_model.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'dart:typed_data';
|
import 'dart:io';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
class BluetoothService {
|
class BluetoothService {
|
||||||
late BluetoothPrint _bluetoothPrint;
|
late BluetoothPrint _bluetoothPrint;
|
||||||
|
@ -44,7 +45,13 @@ class BluetoothService {
|
||||||
final isConnected = await _bluetoothPrint.isConnected ?? false;
|
final isConnected = await _bluetoothPrint.isConnected ?? false;
|
||||||
_isConnected = isConnected;
|
_isConnected = isConnected;
|
||||||
return isConnected;
|
return isConnected;
|
||||||
|
} on SocketException {
|
||||||
|
// Tangani error koneksi secara spesifik
|
||||||
|
_isConnected = false;
|
||||||
|
return false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
// Tangani error umum
|
||||||
|
_isConnected = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +69,17 @@ class BluetoothService {
|
||||||
await prefs.setString('bluetooth_device_name', device.name ?? '');
|
await prefs.setString('bluetooth_device_name', device.name ?? '');
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
} on SocketException {
|
||||||
|
// Tangani error koneksi secara spesifik
|
||||||
|
_isConnected = false;
|
||||||
|
return false;
|
||||||
|
} on PlatformException {
|
||||||
|
// Tangani error platform secara spesifik
|
||||||
|
_isConnected = false;
|
||||||
|
return false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
// Tangani error umum
|
||||||
|
_isConnected = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,12 +97,24 @@ class BluetoothService {
|
||||||
/// Mencetak struk ke printer thermal
|
/// Mencetak struk ke printer thermal
|
||||||
Future<void> printReceipt(Uint8List data) async {
|
Future<void> printReceipt(Uint8List data) async {
|
||||||
if (!_isConnected) {
|
if (!_isConnected) {
|
||||||
throw Exception('Printer tidak terhubung');
|
throw SocketException('Printer tidak terhubung');
|
||||||
}
|
}
|
||||||
|
|
||||||
_isPrinting = true;
|
_isPrinting = true;
|
||||||
try {
|
try {
|
||||||
await _bluetoothPrint.printRawData(data);
|
await _bluetoothPrint.printRawData(data);
|
||||||
|
} on SocketException {
|
||||||
|
// Tangani error koneksi saat mencetak
|
||||||
|
_isPrinting = false;
|
||||||
|
rethrow;
|
||||||
|
} on PlatformException {
|
||||||
|
// Tangani error platform saat mencetak
|
||||||
|
_isPrinting = false;
|
||||||
|
rethrow;
|
||||||
|
} catch (e) {
|
||||||
|
// Tangani error umum saat mencetak
|
||||||
|
_isPrinting = false;
|
||||||
|
throw Exception('Gagal mencetak: $e');
|
||||||
} finally {
|
} finally {
|
||||||
_isPrinting = false;
|
_isPrinting = false;
|
||||||
}
|
}
|
||||||
|
@ -124,7 +153,14 @@ class BluetoothService {
|
||||||
isConnected = await checkConnection();
|
isConnected = await checkConnection();
|
||||||
|
|
||||||
return isConnected;
|
return isConnected;
|
||||||
|
} on SocketException {
|
||||||
|
// Tangani error koneksi secara spesifik
|
||||||
|
return false;
|
||||||
|
} on PlatformException {
|
||||||
|
// Tangani error platform secara spesifik
|
||||||
|
return false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
// Tangani error umum
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -5,8 +5,6 @@ import 'package:cashumit/models/receipt_item.dart';
|
||||||
import 'package:flutter_esc_pos_utils/flutter_esc_pos_utils.dart';
|
import 'package:flutter_esc_pos_utils/flutter_esc_pos_utils.dart';
|
||||||
import 'package:image/image.dart' as img;
|
import 'package:image/image.dart' as img;
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:ui' as ui;
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
/// Service untuk menghasilkan perintah ESC/POS menggunakan flutter_esc_pos_utils
|
/// Service untuk menghasilkan perintah ESC/POS menggunakan flutter_esc_pos_utils
|
||||||
|
@ -342,7 +340,7 @@ class EscPosPrintService {
|
||||||
final isConnectedBeforePrint = await bluetoothService.checkConnection();
|
final isConnectedBeforePrint = await bluetoothService.checkConnection();
|
||||||
if (!isConnectedBeforePrint) {
|
if (!isConnectedBeforePrint) {
|
||||||
print('Printer tidak terhubung saat akan mencetak');
|
print('Printer tidak terhubung saat akan mencetak');
|
||||||
throw Exception('Printer tidak terhubung saat akan mencetak');
|
throw SocketException('Printer tidak terhubung saat akan mencetak');
|
||||||
}
|
}
|
||||||
|
|
||||||
print('Mengirim byte array ke printer...');
|
print('Mengirim byte array ke printer...');
|
||||||
|
@ -352,10 +350,20 @@ class EscPosPrintService {
|
||||||
final Uint8List data = Uint8List.fromList(bytes);
|
final Uint8List data = Uint8List.fromList(bytes);
|
||||||
await bluetoothService.printReceipt(data);
|
await bluetoothService.printReceipt(data);
|
||||||
print('Perintah cetak berhasil dikirim');
|
print('Perintah cetak berhasil dikirim');
|
||||||
|
} on SocketException catch (e) {
|
||||||
|
print('Socket error saat mengirim perintah cetak ke printer: $e');
|
||||||
|
throw SocketException('Koneksi ke printer terputus: ${e.message}');
|
||||||
|
} on PlatformException catch (e) {
|
||||||
|
print('Platform error saat mengirim perintah cetak ke printer: $e');
|
||||||
|
throw PlatformException(code: e.code, message: 'Error printer: ${e.message}');
|
||||||
} catch (printError) {
|
} catch (printError) {
|
||||||
print('Error saat mengirim perintah cetak ke printer: $printError');
|
print('Error saat mengirim perintah cetak ke printer: $printError');
|
||||||
throw Exception('Gagal mengirim perintah cetak: $printError');
|
throw Exception('Gagal mengirim perintah cetak: $printError');
|
||||||
}
|
}
|
||||||
|
} on SocketException {
|
||||||
|
rethrow; // Lempar ulang error koneksi
|
||||||
|
} on PlatformException {
|
||||||
|
rethrow; // Lempar ulang error platform
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
print('Error saat mencetak struk: $e');
|
print('Error saat mencetak struk: $e');
|
||||||
print('Stack trace: $stackTrace');
|
print('Stack trace: $stackTrace');
|
||||||
|
|
|
@ -8,7 +8,7 @@ class PrintingStatusCard extends StatefulWidget {
|
||||||
super.key,
|
super.key,
|
||||||
required this.isVisible,
|
required this.isVisible,
|
||||||
this.onDismiss,
|
this.onDismiss,
|
||||||
}) : super();
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<PrintingStatusCard> createState() => _PrintingStatusCardState();
|
State<PrintingStatusCard> createState() => _PrintingStatusCardState();
|
||||||
|
@ -92,10 +92,10 @@ class _PrintingStatusCardState extends State<PrintingStatusCard>
|
||||||
padding: const EdgeInsets.all(20),
|
padding: const EdgeInsets.all(20),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
gradient: const LinearGradient(
|
gradient: LinearGradient(
|
||||||
begin: Alignment.topLeft,
|
begin: Alignment.topLeft,
|
||||||
end: Alignment.bottomRight,
|
end: Alignment.bottomRight,
|
||||||
colors: [
|
colors: const [
|
||||||
Color(0xFF6A11CB),
|
Color(0xFF6A11CB),
|
||||||
Color(0xFF2575FC),
|
Color(0xFF2575FC),
|
||||||
],
|
],
|
||||||
|
|
|
@ -12,9 +12,11 @@ class ReceiptSpeedDial extends StatelessWidget {
|
||||||
final bool hasSourceAccount;
|
final bool hasSourceAccount;
|
||||||
final bool hasDestinationAccount;
|
final bool hasDestinationAccount;
|
||||||
final Future<void> Function() onSendToFirefly;
|
final Future<void> Function() onSendToFirefly;
|
||||||
|
final VoidCallback onPrintingStart;
|
||||||
|
final VoidCallback onPrintingEnd;
|
||||||
|
|
||||||
const ReceiptSpeedDial({
|
const ReceiptSpeedDial({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.bluetoothService,
|
required this.bluetoothService,
|
||||||
required this.onCheckConnection,
|
required this.onCheckConnection,
|
||||||
required this.onPrint,
|
required this.onPrint,
|
||||||
|
@ -24,7 +26,9 @@ class ReceiptSpeedDial extends StatelessWidget {
|
||||||
required this.hasSourceAccount,
|
required this.hasSourceAccount,
|
||||||
required this.hasDestinationAccount,
|
required this.hasDestinationAccount,
|
||||||
required this.onSendToFirefly,
|
required this.onSendToFirefly,
|
||||||
}) : super(key: key);
|
required this.onPrintingStart,
|
||||||
|
required this.onPrintingEnd,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -74,46 +78,60 @@ class ReceiptSpeedDial extends StatelessWidget {
|
||||||
onTap: bluetoothService.isPrinting
|
onTap: bluetoothService.isPrinting
|
||||||
? null
|
? null
|
||||||
: () async {
|
: () async {
|
||||||
// Periksa koneksi secara real-time
|
// Panggil callback untuk memulai printing status
|
||||||
final isConnected = await onCheckConnection();
|
onPrintingStart();
|
||||||
if (isConnected) {
|
|
||||||
onPrint();
|
try {
|
||||||
} else {
|
// Periksa koneksi secara real-time
|
||||||
// Coba sambungkan kembali jika ada device yang tersimpan
|
final isConnected = await onCheckConnection();
|
||||||
if (bluetoothService.connectedDevice != null) {
|
if (isConnected) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
await onPrint();
|
||||||
const SnackBar(
|
} else {
|
||||||
content: Text('Mencoba menyambungkan ke printer...')),
|
// Coba sambungkan kembali jika ada device yang tersimpan
|
||||||
);
|
if (bluetoothService.connectedDevice != null) {
|
||||||
try {
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
bool connectResult = await bluetoothService.connectToDevice(bluetoothService.connectedDevice!);
|
const SnackBar(
|
||||||
if (!connectResult) {
|
content: Text('Mencoba menyambungkan ke printer...')),
|
||||||
throw Exception('Gagal menyambungkan ke printer');
|
);
|
||||||
}
|
try {
|
||||||
// Tunggu sebentar untuk memastikan koneksi stabil
|
bool connectResult = await bluetoothService.connectToDevice(bluetoothService.connectedDevice!);
|
||||||
await Future.delayed(const Duration(milliseconds: 500));
|
if (!connectResult) {
|
||||||
// Periksa koneksi lagi
|
throw Exception('Gagal menyambungkan ke printer');
|
||||||
final isConnectedAfterConnect = await onCheckConnection();
|
}
|
||||||
if (isConnectedAfterConnect) {
|
// Tunggu sebentar untuk memastikan koneksi stabil
|
||||||
onPrint();
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
} else {
|
// Periksa koneksi lagi
|
||||||
|
final isConnectedAfterConnect = await onCheckConnection();
|
||||||
|
if (isConnectedAfterConnect) {
|
||||||
|
await onPrint();
|
||||||
|
} else {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(
|
||||||
|
content: Text('Gagal menyambungkan ke printer')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(
|
SnackBar(
|
||||||
content: Text('Gagal menyambungkan ke printer')),
|
content: Text('Gagal menyambungkan ke printer: $e')),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} else {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
const SnackBar(
|
||||||
content: Text('Gagal menyambungkan ke printer: $e')),
|
content: Text('Hubungkan printer terlebih dahulu')),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(
|
|
||||||
content: Text('Hubungkan printer terlebih dahulu')),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// Tangani error secara umum
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text('Terjadi kesalahan: $e')),
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
// Pastikan printing status selalu diakhiri
|
||||||
|
onPrintingEnd();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
backgroundColor: Colors.purple,
|
backgroundColor: Colors.purple,
|
||||||
|
|
Loading…
Reference in New Issue