Better client/login/authState handling
This commit is contained in:
@@ -1,15 +1,13 @@
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:simplecloudnotifier/api/api_client.dart';
|
||||
import 'package:simplecloudnotifier/models/key_token_auth.dart';
|
||||
import 'package:simplecloudnotifier/models/user.dart';
|
||||
import 'package:simplecloudnotifier/pages/account/login.dart';
|
||||
import 'package:simplecloudnotifier/state/application_log.dart';
|
||||
import 'package:simplecloudnotifier/state/globals.dart';
|
||||
import 'package:simplecloudnotifier/state/user_account.dart';
|
||||
import 'package:simplecloudnotifier/state/app_auth.dart';
|
||||
import 'package:simplecloudnotifier/utils/toaster.dart';
|
||||
|
||||
class AccountRootPage extends StatefulWidget {
|
||||
@@ -26,7 +24,7 @@ class _AccountRootPageState extends State<AccountRootPage> {
|
||||
late Future<int>? futureChannelAllCount;
|
||||
late Future<int>? futureChannelSubscribedCount;
|
||||
|
||||
late UserAccount userAcc;
|
||||
late AppAuth userAcc;
|
||||
|
||||
bool loading = false;
|
||||
|
||||
@@ -34,7 +32,7 @@ class _AccountRootPageState extends State<AccountRootPage> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
userAcc = Provider.of<UserAccount>(context, listen: false);
|
||||
userAcc = Provider.of<AppAuth>(context, listen: false);
|
||||
userAcc.addListener(_onAuthStateChanged);
|
||||
_onAuthStateChanged();
|
||||
}
|
||||
@@ -52,34 +50,34 @@ class _AccountRootPageState extends State<AccountRootPage> {
|
||||
futureChannelAllCount = null;
|
||||
futureChannelSubscribedCount = null;
|
||||
|
||||
if (userAcc.auth != null) {
|
||||
if (userAcc.isAuth()) {
|
||||
futureChannelAllCount = () async {
|
||||
if (userAcc.auth == null) throw new Exception('not logged in');
|
||||
final channels = await APIClient.getChannelList(userAcc.auth!, ChannelSelector.all);
|
||||
if (!userAcc.isAuth()) throw new Exception('not logged in');
|
||||
final channels = await APIClient.getChannelList(userAcc, ChannelSelector.all);
|
||||
return channels.length;
|
||||
}();
|
||||
|
||||
futureChannelSubscribedCount = () async {
|
||||
if (userAcc.auth == null) throw new Exception('not logged in');
|
||||
final channels = await APIClient.getChannelList(userAcc.auth!, ChannelSelector.subscribed);
|
||||
if (!userAcc.isAuth()) throw new Exception('not logged in');
|
||||
final channels = await APIClient.getChannelList(userAcc, ChannelSelector.subscribed);
|
||||
return channels.length;
|
||||
}();
|
||||
|
||||
futureSubscriptionCount = () async {
|
||||
if (userAcc.auth == null) throw new Exception('not logged in');
|
||||
final subs = await APIClient.getSubscriptionList(userAcc.auth!);
|
||||
if (!userAcc.isAuth()) throw new Exception('not logged in');
|
||||
final subs = await APIClient.getSubscriptionList(userAcc);
|
||||
return subs.length;
|
||||
}();
|
||||
|
||||
futureClientCount = () async {
|
||||
if (userAcc.auth == null) throw new Exception('not logged in');
|
||||
final clients = await APIClient.getClientList(userAcc.auth!);
|
||||
if (!userAcc.isAuth()) throw new Exception('not logged in');
|
||||
final clients = await APIClient.getClientList(userAcc);
|
||||
return clients.length;
|
||||
}();
|
||||
|
||||
futureKeyCount = () async {
|
||||
if (userAcc.auth == null) throw new Exception('not logged in');
|
||||
final keys = await APIClient.getKeyTokenList(userAcc.auth!);
|
||||
if (!userAcc.isAuth()) throw new Exception('not logged in');
|
||||
final keys = await APIClient.getKeyTokenList(userAcc);
|
||||
return keys.length;
|
||||
}();
|
||||
}
|
||||
@@ -87,13 +85,13 @@ class _AccountRootPageState extends State<AccountRootPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<UserAccount>(
|
||||
return Consumer<AppAuth>(
|
||||
builder: (context, acc, child) {
|
||||
if (acc.auth == null) {
|
||||
if (!userAcc.isAuth()) {
|
||||
return _buildNoAuth(context);
|
||||
} else {
|
||||
return FutureBuilder(
|
||||
future: acc.loadUser(false),
|
||||
future: acc.loadUser(force: false),
|
||||
builder: ((context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done) {
|
||||
if (snapshot.hasError) {
|
||||
@@ -165,7 +163,7 @@ class _AccountRootPageState extends State<AccountRootPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildShowAccount(BuildContext context, UserAccount acc, User user) {
|
||||
Widget _buildShowAccount(BuildContext context, AppAuth acc, User user) {
|
||||
//TODO better layout
|
||||
return Column(
|
||||
children: [
|
||||
@@ -446,7 +444,7 @@ class _AccountRootPageState extends State<AccountRootPage> {
|
||||
void _createNewAccount() async {
|
||||
setState(() => loading = true);
|
||||
|
||||
final acc = Provider.of<UserAccount>(context, listen: false);
|
||||
final acc = Provider.of<AppAuth>(context, listen: false);
|
||||
|
||||
try {
|
||||
final notificationSettings = await FirebaseMessaging.instance.requestPermission(provisional: true);
|
||||
@@ -467,7 +465,7 @@ class _AccountRootPageState extends State<AccountRootPage> {
|
||||
|
||||
final user = await APIClient.createUserWithClient(null, fcmToken, Globals().platform, Globals().version, Globals().hostname, Globals().clientType);
|
||||
|
||||
acc.set(user.user, user.clients[0], KeyTokenAuth(userId: user.user.userID, tokenAdmin: user.adminKey, tokenSend: user.sendKey));
|
||||
acc.set(user.user, user.clients[0], user.adminKey, user.sendKey);
|
||||
|
||||
await acc.save();
|
||||
Toaster.success("Success", 'Successfully Created a new account');
|
||||
@@ -480,7 +478,7 @@ class _AccountRootPageState extends State<AccountRootPage> {
|
||||
}
|
||||
|
||||
void _logout() async {
|
||||
final acc = Provider.of<UserAccount>(context, listen: false);
|
||||
final acc = Provider.of<AppAuth>(context, listen: false);
|
||||
|
||||
//TODO clear messages/channels/etc in open views
|
||||
acc.clear();
|
||||
|
||||
@@ -4,10 +4,10 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:simplecloudnotifier/api/api_client.dart';
|
||||
import 'package:simplecloudnotifier/components/layout/scaffold.dart';
|
||||
import 'package:simplecloudnotifier/models/key_token_auth.dart';
|
||||
import 'package:simplecloudnotifier/state/application_log.dart';
|
||||
import 'package:simplecloudnotifier/state/globals.dart';
|
||||
import 'package:simplecloudnotifier/state/user_account.dart';
|
||||
import 'package:simplecloudnotifier/state/app_auth.dart';
|
||||
import 'package:simplecloudnotifier/state/token_source.dart';
|
||||
import 'package:simplecloudnotifier/utils/toaster.dart';
|
||||
|
||||
class AccountLoginPage extends StatefulWidget {
|
||||
@@ -115,7 +115,7 @@ class _AccountLoginPageState extends State<AccountLoginPage> {
|
||||
}
|
||||
|
||||
void _login() async {
|
||||
final acc = Provider.of<UserAccount>(context, listen: false);
|
||||
final acc = Provider.of<AppAuth>(context, listen: false);
|
||||
|
||||
try {
|
||||
setState(() => loading = true);
|
||||
@@ -145,13 +145,11 @@ class _AccountLoginPageState extends State<AccountLoginPage> {
|
||||
return;
|
||||
}
|
||||
|
||||
final kta = KeyTokenAuth(userId: uid, tokenAdmin: atokv, tokenSend: stokv);
|
||||
final user = await APIClient.getUser(DirectTokenSource(uid, atokv), uid);
|
||||
|
||||
final user = await APIClient.getUser(kta, uid);
|
||||
final client = await APIClient.addClient(DirectTokenSource(uid, atokv), fcmToken, Globals().deviceModel, Globals().version, Globals().hostname, Globals().clientType);
|
||||
|
||||
final client = await APIClient.addClient(kta, fcmToken, Globals().deviceModel, Globals().version, Globals().hostname, Globals().clientType);
|
||||
|
||||
acc.set(user, client, kta);
|
||||
acc.set(user, client, atokv, stokv);
|
||||
await acc.save();
|
||||
|
||||
Toaster.success("Login", "Successfully logged in");
|
||||
|
||||
@@ -4,7 +4,7 @@ import 'package:provider/provider.dart';
|
||||
import 'package:simplecloudnotifier/api/api_client.dart';
|
||||
import 'package:simplecloudnotifier/models/channel.dart';
|
||||
import 'package:simplecloudnotifier/state/application_log.dart';
|
||||
import 'package:simplecloudnotifier/state/user_account.dart';
|
||||
import 'package:simplecloudnotifier/state/app_auth.dart';
|
||||
import 'package:simplecloudnotifier/pages/channel_list/channel_list_item.dart';
|
||||
|
||||
class ChannelRootPage extends StatefulWidget {
|
||||
@@ -17,8 +17,6 @@ class ChannelRootPage extends StatefulWidget {
|
||||
class _ChannelRootPageState extends State<ChannelRootPage> {
|
||||
final PagingController<int, Channel> _pagingController = PagingController(firstPageKey: 0);
|
||||
|
||||
late UserAccount userAcc;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_pagingController.addPageRequestListener((pageKey) {
|
||||
@@ -34,15 +32,15 @@ class _ChannelRootPageState extends State<ChannelRootPage> {
|
||||
}
|
||||
|
||||
Future<void> _fetchPage(int pageKey) async {
|
||||
final acc = Provider.of<UserAccount>(context, listen: false);
|
||||
final acc = Provider.of<AppAuth>(context, listen: false);
|
||||
|
||||
if (acc.auth == null) {
|
||||
if (!acc.isAuth()) {
|
||||
_pagingController.error = 'Not logged in';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final items = (await APIClient.getChannelList(acc.auth!, ChannelSelector.all)).map((p) => p.channel).toList();
|
||||
final items = (await APIClient.getChannelList(acc, ChannelSelector.all)).map((p) => p.channel).toList();
|
||||
|
||||
items.sort((a, b) => -1 * (a.timestampLastSent ?? '').compareTo(b.timestampLastSent ?? ''));
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import 'package:provider/provider.dart';
|
||||
import 'package:simplecloudnotifier/api/api_client.dart';
|
||||
import 'package:simplecloudnotifier/models/channel.dart';
|
||||
import 'package:simplecloudnotifier/models/message.dart';
|
||||
import 'package:simplecloudnotifier/state/user_account.dart';
|
||||
import 'package:simplecloudnotifier/state/app_auth.dart';
|
||||
|
||||
class ChannelListItem extends StatefulWidget {
|
||||
static final _dateFormat = DateFormat('yyyy-MM-dd kk:mm');
|
||||
@@ -29,11 +29,11 @@ class _ChannelListItemState extends State<ChannelListItem> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
final acc = Provider.of<UserAccount>(context, listen: false);
|
||||
final acc = Provider.of<AppAuth>(context, listen: false);
|
||||
|
||||
if (acc.auth != null) {
|
||||
if (acc.isAuth()) {
|
||||
() async {
|
||||
final (_, channelMessages) = await APIClient.getMessageList(acc.auth!, '@start', pageSize: 1, channelIDs: [widget.channel.channelID]);
|
||||
final (_, channelMessages) = await APIClient.getMessageList(acc, '@start', pageSize: 1, channelIDs: [widget.channel.channelID]);
|
||||
setState(() {
|
||||
lastMessage = channelMessages.firstOrNull;
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ import 'package:simplecloudnotifier/models/channel.dart';
|
||||
import 'package:simplecloudnotifier/models/message.dart';
|
||||
import 'package:simplecloudnotifier/pages/message_view/message_view.dart';
|
||||
import 'package:simplecloudnotifier/state/application_log.dart';
|
||||
import 'package:simplecloudnotifier/state/user_account.dart';
|
||||
import 'package:simplecloudnotifier/state/app_auth.dart';
|
||||
import 'package:simplecloudnotifier/pages/message_list/message_list_item.dart';
|
||||
|
||||
class MessageListPage extends StatefulWidget {
|
||||
@@ -38,20 +38,20 @@ class _MessageListPageState extends State<MessageListPage> {
|
||||
}
|
||||
|
||||
Future<void> _fetchPage(String thisPageToken) async {
|
||||
final acc = Provider.of<UserAccount>(context, listen: false);
|
||||
final acc = Provider.of<AppAuth>(context, listen: false);
|
||||
|
||||
if (acc.auth == null) {
|
||||
if (!acc.isAuth()) {
|
||||
_pagingController.error = 'Not logged in';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (_channels == null) {
|
||||
final channels = await APIClient.getChannelList(acc.auth!, ChannelSelector.allAny);
|
||||
final channels = await APIClient.getChannelList(acc, ChannelSelector.allAny);
|
||||
_channels = <String, Channel>{for (var v in channels) v.channel.channelID: v.channel};
|
||||
}
|
||||
|
||||
final (npt, newItems) = await APIClient.getMessageList(acc.auth!, thisPageToken, pageSize: _pageSize);
|
||||
final (npt, newItems) = await APIClient.getMessageList(acc, thisPageToken, pageSize: _pageSize);
|
||||
|
||||
if (npt == '@end') {
|
||||
_pagingController.appendLastPage(newItems);
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'package:provider/provider.dart';
|
||||
import 'package:simplecloudnotifier/api/api_client.dart';
|
||||
import 'package:simplecloudnotifier/components/layout/scaffold.dart';
|
||||
import 'package:simplecloudnotifier/models/message.dart';
|
||||
import 'package:simplecloudnotifier/state/user_account.dart';
|
||||
import 'package:simplecloudnotifier/state/app_auth.dart';
|
||||
|
||||
class MessageViewPage extends StatefulWidget {
|
||||
const MessageViewPage({super.key, required this.message});
|
||||
@@ -24,9 +24,9 @@ class _MessageViewPageState extends State<MessageViewPage> {
|
||||
}
|
||||
|
||||
Future<Message> fetchMessage() async {
|
||||
final acc = Provider.of<UserAccount>(context, listen: false);
|
||||
final acc = Provider.of<AppAuth>(context, listen: false);
|
||||
|
||||
return await APIClient.getMessage(acc.auth!, widget.message.messageID);
|
||||
return await APIClient.getMessage(acc, widget.message.messageID);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1,159 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
import 'package:simplecloudnotifier/state/application_log.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:simplecloudnotifier/state/user_account.dart';
|
||||
|
||||
class SendRootPage extends StatefulWidget {
|
||||
const SendRootPage({super.key});
|
||||
|
||||
@override
|
||||
State<SendRootPage> createState() => _SendRootPageState();
|
||||
}
|
||||
|
||||
class _SendRootPageState extends State<SendRootPage> {
|
||||
late TextEditingController _msgTitle;
|
||||
late TextEditingController _msgContent;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_msgTitle = TextEditingController();
|
||||
_msgContent = TextEditingController();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_msgTitle.dispose();
|
||||
_msgContent.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<UserAccount>(
|
||||
builder: (context, acc, child) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
_buildQRCode(context, acc),
|
||||
const SizedBox(height: 16),
|
||||
FractionallySizedBox(
|
||||
widthFactor: 1.0,
|
||||
child: TextField(
|
||||
controller: _msgTitle,
|
||||
decoration: const InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: 'Title',
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FractionallySizedBox(
|
||||
widthFactor: 1.0,
|
||||
child: TextField(
|
||||
controller: _msgContent,
|
||||
decoration: const InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: 'Text',
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FilledButton(
|
||||
style: FilledButton.styleFrom(textStyle: const TextStyle(fontSize: 20)),
|
||||
onPressed: _send,
|
||||
child: const Text('Send'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _send() {
|
||||
//...
|
||||
}
|
||||
|
||||
Widget _buildQRCode(BuildContext context, UserAccount acc) {
|
||||
if (acc.auth == null) {
|
||||
return const Placeholder();
|
||||
}
|
||||
|
||||
if (acc.user == null) {
|
||||
return FutureBuilder(
|
||||
future: acc.loadUser(false),
|
||||
builder: ((context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done) {
|
||||
if (snapshot.hasError) {
|
||||
return Text('Error: ${snapshot.error}'); //TODO better error display
|
||||
}
|
||||
var url = 'https://simplecloudnotifier.de?preset_user_id=${acc.user!.userID}&preset_user_key=${acc.auth!.tokenSend}';
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
_openWeb(url);
|
||||
},
|
||||
child: QrImageView(
|
||||
data: url,
|
||||
version: QrVersions.auto,
|
||||
size: 400.0,
|
||||
eyeStyle: QrEyeStyle(
|
||||
eyeShape: QrEyeShape.square,
|
||||
color: Theme.of(context).textTheme.bodyLarge?.color,
|
||||
),
|
||||
dataModuleStyle: QrDataModuleStyle(
|
||||
dataModuleShape: QrDataModuleShape.square,
|
||||
color: Theme.of(context).textTheme.bodyLarge?.color,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return const SizedBox(
|
||||
width: 400.0,
|
||||
height: 400.0,
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
var url = 'https://simplecloudnotifier.de?preset_user_id=${acc.user!.userID}&preset_user_key=${acc.auth!.tokenSend}';
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
_openWeb(url);
|
||||
},
|
||||
child: QrImageView(
|
||||
data: url,
|
||||
version: QrVersions.auto,
|
||||
size: 400.0,
|
||||
eyeStyle: QrEyeStyle(
|
||||
eyeShape: QrEyeShape.square,
|
||||
color: Theme.of(context).textTheme.bodyLarge?.color,
|
||||
),
|
||||
dataModuleStyle: QrDataModuleStyle(
|
||||
dataModuleShape: QrDataModuleShape.square,
|
||||
color: Theme.of(context).textTheme.bodyLarge?.color,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _openWeb(String url) async {
|
||||
try {
|
||||
final Uri uri = Uri.parse(url);
|
||||
|
||||
if (await canLaunchUrl(uri)) {
|
||||
await launchUrl(uri);
|
||||
} else {
|
||||
// TODO ("Cannot open URL");
|
||||
}
|
||||
} catch (exc, trace) {
|
||||
ApplicationLog.error('Failed to open URL: ' + exc.toString(), additional: 'URL: ${url}', trace: trace);
|
||||
}
|
||||
}
|
||||
}
|
||||
142
flutter/lib/pages/send/send.dart
Normal file
142
flutter/lib/pages/send/send.dart
Normal file
@@ -0,0 +1,142 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
import 'package:simplecloudnotifier/state/application_log.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:simplecloudnotifier/state/app_auth.dart';
|
||||
|
||||
class SendRootPage extends StatefulWidget {
|
||||
const SendRootPage({super.key});
|
||||
|
||||
@override
|
||||
State<SendRootPage> createState() => _SendRootPageState();
|
||||
}
|
||||
|
||||
class _SendRootPageState extends State<SendRootPage> {
|
||||
late TextEditingController _msgTitle;
|
||||
late TextEditingController _msgContent;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_msgTitle = TextEditingController();
|
||||
_msgContent = TextEditingController();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_msgTitle.dispose();
|
||||
_msgContent.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<AppAuth>(
|
||||
builder: (context, acc, child) {
|
||||
return SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
_buildQRCode(context, acc),
|
||||
const SizedBox(height: 16),
|
||||
FractionallySizedBox(
|
||||
widthFactor: 1.0,
|
||||
child: TextField(
|
||||
controller: _msgTitle,
|
||||
decoration: const InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: 'Title',
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FractionallySizedBox(
|
||||
widthFactor: 1.0,
|
||||
child: TextField(
|
||||
controller: _msgContent,
|
||||
decoration: const InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: 'Text',
|
||||
),
|
||||
minLines: 2,
|
||||
maxLines: null,
|
||||
keyboardType: TextInputType.multiline,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FilledButton(
|
||||
style: FilledButton.styleFrom(textStyle: const TextStyle(fontSize: 20)),
|
||||
onPressed: _send,
|
||||
child: const Text('Send'),
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _send() {
|
||||
//...
|
||||
}
|
||||
|
||||
Widget _buildQRCode(BuildContext context, AppAuth acc) {
|
||||
if (!acc.isAuth()) {
|
||||
return const Placeholder();
|
||||
}
|
||||
|
||||
return FutureBuilder(
|
||||
future: acc.loadUser(force: false),
|
||||
builder: ((context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done) {
|
||||
if (snapshot.hasError) {
|
||||
return Text('Error: ${snapshot.error}'); //TODO better error display
|
||||
}
|
||||
var url = (acc.tokenSend == null) ? 'https://simplecloudnotifier.de?preset_user_id=${acc.userID}' : 'https://simplecloudnotifier.de?preset_user_id=${acc.userID}&preset_user_key=${acc.tokenSend}';
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
_openWeb(url);
|
||||
},
|
||||
child: QrImageView(
|
||||
data: url,
|
||||
version: QrVersions.auto,
|
||||
size: 300.0,
|
||||
eyeStyle: QrEyeStyle(
|
||||
eyeShape: QrEyeShape.square,
|
||||
color: Theme.of(context).textTheme.bodyLarge?.color,
|
||||
),
|
||||
dataModuleStyle: QrDataModuleStyle(
|
||||
dataModuleShape: QrDataModuleShape.square,
|
||||
color: Theme.of(context).textTheme.bodyLarge?.color,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return const SizedBox(
|
||||
width: 300.0,
|
||||
height: 300.0,
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
void _openWeb(String url) async {
|
||||
try {
|
||||
final Uri uri = Uri.parse(url);
|
||||
|
||||
if (await canLaunchUrl(uri)) {
|
||||
await launchUrl(uri);
|
||||
} else {
|
||||
// TODO ("Cannot open URL");
|
||||
}
|
||||
} catch (exc, trace) {
|
||||
ApplicationLog.error('Failed to open URL: ' + exc.toString(), additional: 'URL: ${url}', trace: trace);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user