121 lines
3.4 KiB
Dart
121 lines
3.4 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
import 'package:audioplayers/audioplayers.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/rendering.dart';
|
|
import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart';
|
|
import 'package:qr_flutter/qr_flutter.dart';
|
|
import 'package:warp_api/warp_api.dart';
|
|
import 'generated/l10n.dart';
|
|
import 'main.dart';
|
|
|
|
class AnimatedQR extends StatefulWidget {
|
|
final String title;
|
|
final String caption;
|
|
final String data;
|
|
final List<String> chunks;
|
|
|
|
AnimatedQR.init(String title, String caption, String data):
|
|
this(title, caption, data, WarpApi.splitData(DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
|
base64Encode(ZLibCodec().encode(utf8.encode(data)))));
|
|
|
|
AnimatedQR(this.title, this.caption, this.data, this.chunks);
|
|
|
|
@override
|
|
AnimatedQRState createState() => AnimatedQRState();
|
|
}
|
|
|
|
class AnimatedQRState extends State<AnimatedQR> {
|
|
var index = 0;
|
|
Timer? _timer;
|
|
|
|
@override
|
|
void initState() {
|
|
_timer = new Timer.periodic(Duration(seconds: 2), (Timer timer) {
|
|
setState(() {
|
|
index += 1;
|
|
});
|
|
});
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_timer?.cancel();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final theme = Theme.of(context);
|
|
final idx = index % widget.chunks.length;
|
|
final qrSize = getScreenSize(context) / 1.2;
|
|
return Scaffold(appBar: AppBar(title: Text(widget.title)),
|
|
body: Padding(padding: EdgeInsets.all(16), child: Center(child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
QrImage(key: ValueKey(idx), data: widget.chunks[idx], size: qrSize, foregroundColor: Colors.white, backgroundColor: Colors.black),
|
|
Padding(padding: EdgeInsets.symmetric(vertical: 4)),
|
|
Text(widget.caption, style: theme.textTheme.subtitle1),
|
|
Padding(padding: EdgeInsets.symmetric(vertical: 4)),
|
|
ElevatedButton.icon(
|
|
icon: Icon(Icons.close),
|
|
label: Text(S.of(context).ok),
|
|
onPressed: () { Navigator.of(context).pop(); }
|
|
)
|
|
]
|
|
)
|
|
)));
|
|
}
|
|
}
|
|
|
|
class QrOffline extends StatelessWidget {
|
|
final String txJson;
|
|
|
|
QrOffline(this.txJson);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final s = S.of(context);
|
|
return AnimatedQR.init(s.unsignedTx, s.signOnYourOfflineDevice, txJson);
|
|
}
|
|
}
|
|
|
|
class ShowRawTx extends StatelessWidget {
|
|
final String rawTx;
|
|
|
|
ShowRawTx(this.rawTx);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final s = S.of(context);
|
|
return AnimatedQR.init(s.signedTx, s.broadcastFromYourOnlineDevice, rawTx);
|
|
}
|
|
}
|
|
|
|
Future<String?> scanMultiCode(BuildContext context) async {
|
|
if (!isMobile()) {
|
|
showSnackBar(S.of(context).barcodeScannerIsNotAvailableOnDesktop);
|
|
return null;
|
|
}
|
|
else {
|
|
final player = AudioPlayer();
|
|
final ding = AssetSource("ding.mp3");
|
|
final dropStream = FlutterBarcodeScanner.getBarcodeStreamReceiver('#FF0000', S.of(context).cancel, true, ScanMode.QR);
|
|
var f = Completer<String>();
|
|
StreamSubscription? sub;
|
|
sub = dropStream?.listen((barcode) async {
|
|
await player.play(ding);
|
|
final res = WarpApi.mergeData(barcode);
|
|
if (res.isNotEmpty) {
|
|
FlutterBarcodeScanner.dismiss();
|
|
final decoded = utf8.decode(ZLibCodec().decode(base64Decode(res)));
|
|
sub?.cancel();
|
|
f.complete(decoded);
|
|
}
|
|
});
|
|
return f.future;
|
|
}
|
|
}
|