Channel QR Code scanner [WIP]

This commit is contained in:
2024-10-19 22:33:08 +02:00
parent 1cf14e65a9
commit cc672d2f20
11 changed files with 228 additions and 11 deletions

View File

@@ -4,6 +4,7 @@ import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import 'package:provider/provider.dart';
import 'package:simplecloudnotifier/api/api_client.dart';
import 'package:simplecloudnotifier/models/channel.dart';
import 'package:simplecloudnotifier/pages/channel_list/channel_scanner.dart';
import 'package:simplecloudnotifier/state/app_bar_state.dart';
import 'package:simplecloudnotifier/state/application_log.dart';
import 'package:simplecloudnotifier/state/app_auth.dart';
@@ -168,7 +169,7 @@ class _ChannelRootPageState extends State<ChannelRootPage> with RouteAware {
floatingActionButton: FloatingActionButton(
heroTag: 'fab_channel_list_qr',
onPressed: () {
//TODO scan qr code to subscribe channel
Navi.push(context, () => ChannelScannerPage());
},
child: const Icon(FontAwesomeIcons.qrcode),
),

View File

@@ -199,7 +199,7 @@ class _ChannelListItemState extends State<ChannelListItem> {
await APIClient.deleteSubscription(acc, widget.channel.channelID, widget.subscription!.subscriptionID);
widget.onChannelListReloadTrigger.call();
widget.onSubscriptionChanged?.call(widget.channel.channelID, null);
widget.onSubscriptionChanged.call(widget.channel.channelID, null);
Toaster.success("Success", 'Unsubscribed from channel');
} catch (exc, trace) {

View File

@@ -0,0 +1,117 @@
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:mobile_scanner/mobile_scanner.dart';
import 'package:simplecloudnotifier/components/layout/scaffold.dart';
import 'package:simplecloudnotifier/models/scan_result.dart';
import 'package:simplecloudnotifier/utils/ui.dart';
class ChannelScannerPage extends StatefulWidget {
const ChannelScannerPage({super.key});
@override
State<ChannelScannerPage> createState() => _ChannelScannerPageState();
}
class _ChannelScannerPageState extends State<ChannelScannerPage> {
final MobileScannerController _controller = MobileScannerController(
formats: const [BarcodeFormat.qrCode],
);
ScanResult? scanResult = null;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return SCNScaffold(
title: "Scanner",
showSearch: false,
showShare: false,
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.fromLTRB(24, 16, 24, 16),
child: Column(
children: [
SizedBox(height: 16),
Center(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(UI.DefaultBorderRadius),
),
clipBehavior: Clip.hardEdge,
child: SizedBox(
height: 300,
width: 300,
child: MobileScanner(
fit: BoxFit.cover,
controller: _controller,
onDetect: _handleBarcode,
),
),
),
),
SizedBox(height: 16),
_buildScanResult(context),
],
),
),
),
);
}
void _handleBarcode(BarcodeCapture barcodes) {
setState(() {
if (barcodes.barcodes.isEmpty) {
scanResult = null;
} else {
print('parsed: ${barcodes.barcodes[0].rawValue}');
scanResult = ScanResult.parse(barcodes.barcodes[0].rawValue ?? '');
}
});
}
Widget _buildScanResult(BuildContext context) {
if (scanResult == null) {
return UI.box(
padding: EdgeInsets.fromLTRB(16, 2, 4, 2), //TODO
context: context,
child: Center(
child: Icon(FontAwesomeIcons.solidEmptySet, size: 64, color: Theme.of(context).colorScheme.onPrimaryContainer.withAlpha(128)),
),
);
}
if (scanResult! is ScanResultMessageSend) {
return UI.box(
padding: EdgeInsets.fromLTRB(16, 2, 4, 2),
context: context,
child: Text("TODO -- ScanResultMessageSend"), //TODO
);
}
if (scanResult! is ScanResultChannel) {
return UI.box(
padding: EdgeInsets.fromLTRB(16, 2, 4, 2),
context: context,
child: Text("TODO -- ScanResultChannel"), //TODO
);
}
if (scanResult! is ScanResultChannelSubscribe) {
return UI.box(
padding: EdgeInsets.fromLTRB(16, 2, 4, 2),
context: context,
child: Text("TODO -- ScanResultChannelSubscribe"), //TODO
);
}
return UI.box(
padding: EdgeInsets.fromLTRB(16, 2, 4, 2),
context: context,
child: Text("TODO -- ERROR"), //TODO
);
}
}

View File

@@ -5,6 +5,7 @@ import 'package:share_plus/share_plus.dart';
import 'package:simplecloudnotifier/api/api_client.dart';
import 'package:simplecloudnotifier/components/layout/scaffold.dart';
import 'package:simplecloudnotifier/models/channel.dart';
import 'package:simplecloudnotifier/models/scan_result.dart';
import 'package:simplecloudnotifier/models/subscription.dart';
import 'package:simplecloudnotifier/models/user.dart';
import 'package:simplecloudnotifier/pages/channel_message_view/channel_message_view.dart';
@@ -295,8 +296,8 @@ class _ChannelViewPageState extends State<ChannelViewPage> {
return FutureBuilder(
future: _futureSubscribeKey.future,
builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data != null) {
var text = '@scn.channel.subscribe' + '\n' + "v1" + '\n' + channel!.displayName + '\n' + channel!.ownerUserID + '\n' + channel!.channelID + '\n' + snapshot.data!;
if (snapshot.hasData) {
final text = (snapshot.data == null) ? ScanResult.createChannelQR(channel!) : ScanResult.createChannelSubscribeQR(channel!, snapshot.data!);
return GestureDetector(
onTap: () {
Share.share(text, subject: _displayNameOverride ?? channel!.displayName);
@@ -317,12 +318,6 @@ class _ChannelViewPageState extends State<ChannelViewPage> {
),
),
);
} else if (snapshot.hasData && snapshot.data == null) {
return const SizedBox(
width: 300.0,
height: 300.0,
child: Center(child: Icon(FontAwesomeIcons.solidSnake, size: 64)),
);
} else {
return const SizedBox(
width: 300.0,

View File

@@ -72,6 +72,9 @@ class _MessageListPageState extends State<MessageListPage> with RouteAware {
_channels = SCNDataCache().getChannelMap();
//TODO this is not 100% correct - the message-cache contains (which is right!) all messages, even from unsubscribed channels
//TODO what we should do is save another list in SCNDataCache, with the result of the last getMessageList call (page-1) and use that
//TODO this way we only get 1 page of data from cache, but its a weird behaviour anway that we loose data once _backgroundRefresh is finished
_pagingController.value = PagingState(nextPageKey: null, itemList: SCNDataCache().getMessagesSorted(), error: null);
_backgroundRefresh(true);