Build Android (FCM) / build-android-fcm (push) Canceled after 0s
Build Android / build-android (push) Canceled after 0s
Build iOS / build-ios (push) Canceled after 0s
Build Linux / build-linux (push) Canceled after 0s
Build macOS / build-macos (push) Canceled after 0s
Build Windows / build-windows (push) Canceled after 0s
Release (main) / android (oneme) (push) Canceled after 0s
Release (main) / android (qlyra) (push) Canceled after 0s
Release (main) / windows (push) Canceled after 0s
Release (main) / linux (push) Canceled after 0s
Release (main) / macos (push) Canceled after 0s
Release (main) / ios (push) Canceled after 0s
Release (main) / release (push) Canceled after 0s
83 lines
2.2 KiB
Dart
83 lines
2.2 KiB
Dart
import 'dart:async';
|
|
import 'dart:io';
|
|
|
|
import 'package:flutter/services.dart';
|
|
|
|
import '../utils/parse.dart';
|
|
|
|
enum NfcEventType { received, exchanging, cancelled, error }
|
|
|
|
class NfcEvent {
|
|
final NfcEventType type;
|
|
final int? id;
|
|
final int? phone;
|
|
final String? reason;
|
|
|
|
const NfcEvent(this.type, this.id, {this.phone, this.reason});
|
|
}
|
|
|
|
class NfcStatus {
|
|
final bool supported;
|
|
final bool enabled;
|
|
|
|
const NfcStatus({required this.supported, required this.enabled});
|
|
|
|
bool get ready => supported && enabled;
|
|
}
|
|
|
|
class NfcExchangeService {
|
|
NfcExchangeService._();
|
|
static final NfcExchangeService instance = NfcExchangeService._();
|
|
|
|
static const MethodChannel _method = MethodChannel('ru.qlyra.app/nfc');
|
|
static const EventChannel _events = EventChannel('ru.qlyra.app/nfc_events');
|
|
|
|
bool get _supported => Platform.isAndroid;
|
|
|
|
Future<NfcStatus> status() async {
|
|
if (!_supported) return const NfcStatus(supported: false, enabled: false);
|
|
try {
|
|
final res = await _method.invokeMapMethod<String, dynamic>('status');
|
|
return NfcStatus(
|
|
supported: res?['supported'] == true,
|
|
enabled: res?['enabled'] == true,
|
|
);
|
|
} catch (_) {
|
|
return const NfcStatus(supported: false, enabled: false);
|
|
}
|
|
}
|
|
|
|
Stream<NfcEvent> get events =>
|
|
_events.receiveBroadcastStream().map(_decodeEvent);
|
|
|
|
Future<void> start(int selfId, int selfPhone) =>
|
|
_method.invokeMethod('start', {'selfId': selfId, 'selfPhone': selfPhone});
|
|
|
|
Future<void> stop() async {
|
|
if (!_supported) return;
|
|
try {
|
|
await _method.invokeMethod('stop');
|
|
} catch (_) {}
|
|
}
|
|
|
|
NfcEvent _decodeEvent(dynamic raw) {
|
|
final map = raw is Map ? raw : const {};
|
|
final parsedId = parseIntOrNull(map['id']);
|
|
final parsedPhone = parseIntOrNull(map['phone']);
|
|
switch (map['event']) {
|
|
case 'received':
|
|
return NfcEvent(NfcEventType.received, parsedId, phone: parsedPhone);
|
|
case 'exchanging':
|
|
return const NfcEvent(NfcEventType.exchanging, null);
|
|
case 'error':
|
|
return NfcEvent(
|
|
NfcEventType.error,
|
|
null,
|
|
reason: map['reason'] as String?,
|
|
);
|
|
default:
|
|
return const NfcEvent(NfcEventType.cancelled, null);
|
|
}
|
|
}
|
|
}
|