Add various informative alert-boxes
This commit is contained in:
@@ -7,6 +7,7 @@ import 'package:flutter/material.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/api/api_exception.dart';
|
||||
import 'package:simplecloudnotifier/components/error_display/error_display.dart';
|
||||
import 'package:simplecloudnotifier/models/user.dart';
|
||||
import 'package:simplecloudnotifier/pages/account/login.dart';
|
||||
@@ -166,6 +167,9 @@ class _AccountRootPageState extends State<AccountRootPage> {
|
||||
_futureSenderNamesCount = ImmediateFuture.ofValue(senderNames.length);
|
||||
_futureUser = ImmediateFuture.ofValue(user);
|
||||
});
|
||||
} on APIException catch (exc, trace) {
|
||||
ApplicationLog.error('Failed to refresh account data: ' + exc.toString(), trace: trace);
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to refresh account data');
|
||||
} catch (exc, trace) {
|
||||
ApplicationLog.error('Failed to refresh account data: ' + exc.toString(), trace: trace);
|
||||
Toaster.error("Error", 'Failed to refresh account data');
|
||||
@@ -417,7 +421,13 @@ class _AccountRootPageState extends State<AccountRootPage> {
|
||||
],
|
||||
),
|
||||
onTap: () {
|
||||
Navi.push(context, () => FilteredMessageViewPage(title: "All Messages", filter: MessageFilter(senderUserID: [user.userID])));
|
||||
Navi.push(
|
||||
context,
|
||||
() => FilteredMessageViewPage(
|
||||
title: "All Messages",
|
||||
alertText: "All messages sent from your account",
|
||||
filter: MessageFilter(senderUserID: [user.userID]),
|
||||
));
|
||||
},
|
||||
),
|
||||
];
|
||||
@@ -528,9 +538,12 @@ class _AccountRootPageState extends State<AccountRootPage> {
|
||||
context: context,
|
||||
builder: (context) => ShowTokenModal(account: acc, isAfterRegister: true),
|
||||
);
|
||||
} catch (exc, trace) {
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to create user account');
|
||||
ApplicationLog.error('Failed to create user account: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to create user account');
|
||||
ApplicationLog.error('Failed to create user account: ' + exc.toString(), trace: trace);
|
||||
} finally {
|
||||
setState(() => loading = false);
|
||||
}
|
||||
@@ -574,6 +587,9 @@ class _AccountRootPageState extends State<AccountRootPage> {
|
||||
//TODO clear messages/channels/etc in open views
|
||||
acc.clear();
|
||||
await acc.save();
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to delete user');
|
||||
ApplicationLog.error('Failed to delete user: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to delete user');
|
||||
ApplicationLog.error('Failed to delete user: ' + exc.toString(), trace: trace);
|
||||
@@ -601,6 +617,9 @@ class _AccountRootPageState extends State<AccountRootPage> {
|
||||
Toaster.success("Success", 'Username changed');
|
||||
|
||||
_backgroundRefresh();
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to update username');
|
||||
ApplicationLog.error('Failed to update username: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to update username');
|
||||
ApplicationLog.error('Failed to update username: ' + exc.toString(), trace: trace);
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:flutter/material.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/api/api_exception.dart';
|
||||
import 'package:simplecloudnotifier/components/layout/scaffold.dart';
|
||||
import 'package:simplecloudnotifier/state/application_log.dart';
|
||||
import 'package:simplecloudnotifier/state/globals.dart';
|
||||
@@ -162,9 +163,12 @@ class _AccountLoginPageState extends State<AccountLoginPage> {
|
||||
|
||||
Toaster.success("Login", "Successfully logged in");
|
||||
Navi.popToRoot(context);
|
||||
} catch (exc, trace) {
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to verify token');
|
||||
ApplicationLog.error('Failed to verify token: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to verify token');
|
||||
ApplicationLog.error('Failed to verify token: ' + exc.toString(), trace: trace);
|
||||
} finally {
|
||||
setState(() => loading = false);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ class ShowTokenModal extends StatelessWidget {
|
||||
text: alertText,
|
||||
icon: null,
|
||||
mode: BadgeMode.info,
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
if (this.account.userID != null)
|
||||
|
||||
@@ -144,28 +144,7 @@ class _ChannelRootPageState extends State<ChannelRootPage> with RouteAware {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: RefreshIndicator(
|
||||
onRefresh: () => Future.sync(
|
||||
() => _pagingController.refresh(),
|
||||
),
|
||||
child: PagedListView<int, ChannelWithSubscription>(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<ChannelWithSubscription>(
|
||||
itemBuilder: (context, item, index) => ChannelListItem(
|
||||
channel: item.channel,
|
||||
subscription: item.subscription,
|
||||
mode: ChannelListItemMode.Messages,
|
||||
onChannelListReloadTrigger: _enqueueReload,
|
||||
onSubscriptionChanged: (channelID, subscription) {
|
||||
setState(() {
|
||||
final idx = _pagingController.itemList?.indexWhere((p) => p.channel.channelID == channelID);
|
||||
if (idx != null && idx >= 0) _pagingController.itemList![idx] = ChannelWithSubscription(channel: _pagingController.itemList![idx].channel, subscription: subscription);
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
body: _buildList(context),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
heroTag: 'fab_channel_list_qr',
|
||||
onPressed: () {
|
||||
@@ -176,6 +155,31 @@ class _ChannelRootPageState extends State<ChannelRootPage> with RouteAware {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildList(BuildContext context) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => Future.sync(
|
||||
() => _pagingController.refresh(),
|
||||
),
|
||||
child: PagedListView<int, ChannelWithSubscription>(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<ChannelWithSubscription>(
|
||||
itemBuilder: (context, item, index) => ChannelListItem(
|
||||
channel: item.channel,
|
||||
subscription: item.subscription,
|
||||
mode: ChannelListItemMode.Messages,
|
||||
onChannelListReloadTrigger: _enqueueReload,
|
||||
onSubscriptionChanged: (channelID, subscription) {
|
||||
setState(() {
|
||||
final idx = _pagingController.itemList?.indexWhere((p) => p.channel.channelID == channelID);
|
||||
if (idx != null && idx >= 0) _pagingController.itemList![idx] = ChannelWithSubscription(channel: _pagingController.itemList![idx].channel, subscription: subscription);
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _enqueueReload() {
|
||||
_reloadEnqueued = true;
|
||||
}
|
||||
|
||||
@@ -3,10 +3,12 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:simplecloudnotifier/api/api_client.dart';
|
||||
import 'package:simplecloudnotifier/components/badge_display/badge_display.dart';
|
||||
import 'package:simplecloudnotifier/components/layout/scaffold.dart';
|
||||
import 'package:simplecloudnotifier/models/channel.dart';
|
||||
import 'package:simplecloudnotifier/pages/channel_scanner/channel_scanner.dart';
|
||||
import 'package:simplecloudnotifier/state/app_bar_state.dart';
|
||||
import 'package:simplecloudnotifier/state/app_settings.dart';
|
||||
import 'package:simplecloudnotifier/state/application_log.dart';
|
||||
import 'package:simplecloudnotifier/state/app_auth.dart';
|
||||
import 'package:simplecloudnotifier/pages/channel_list/channel_list_item.dart';
|
||||
@@ -121,27 +123,21 @@ class _ChannelListExtendedPageState extends State<ChannelListExtendedPage> with
|
||||
showShare: false,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(8, 4, 8, 4),
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () => Future.sync(
|
||||
() => _pagingController.refresh(),
|
||||
),
|
||||
child: PagedListView<int, ChannelWithSubscription>(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<ChannelWithSubscription>(
|
||||
itemBuilder: (context, item, index) => ChannelListItem(
|
||||
channel: item.channel,
|
||||
subscription: item.subscription,
|
||||
mode: ChannelListItemMode.Extended,
|
||||
onChannelListReloadTrigger: _enqueueReload,
|
||||
onSubscriptionChanged: (channelID, subscription) {
|
||||
setState(() {
|
||||
final idx = _pagingController.itemList?.indexWhere((p) => p.channel.channelID == channelID);
|
||||
if (idx != null && idx >= 0) _pagingController.itemList![idx] = ChannelWithSubscription(channel: _pagingController.itemList![idx].channel, subscription: subscription);
|
||||
});
|
||||
},
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
BadgeDisplay(
|
||||
text: "All channels accessible from this account\n(Your own channels and subscribed channels)",
|
||||
icon: null,
|
||||
mode: BadgeMode.info,
|
||||
textAlign: TextAlign.left,
|
||||
closable: true,
|
||||
extraPadding: EdgeInsets.fromLTRB(0, 0, 0, 16),
|
||||
hidden: !AppSettings().showInfoAlerts,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: _buildList(context),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
@@ -154,6 +150,31 @@ class _ChannelListExtendedPageState extends State<ChannelListExtendedPage> with
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildList(BuildContext context) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => Future.sync(
|
||||
() => _pagingController.refresh(),
|
||||
),
|
||||
child: PagedListView<int, ChannelWithSubscription>(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<ChannelWithSubscription>(
|
||||
itemBuilder: (context, item, index) => ChannelListItem(
|
||||
channel: item.channel,
|
||||
subscription: item.subscription,
|
||||
mode: ChannelListItemMode.Extended,
|
||||
onChannelListReloadTrigger: _enqueueReload,
|
||||
onSubscriptionChanged: (channelID, subscription) {
|
||||
setState(() {
|
||||
final idx = _pagingController.itemList?.indexWhere((p) => p.channel.channelID == channelID);
|
||||
if (idx != null && idx >= 0) _pagingController.itemList![idx] = ChannelWithSubscription(channel: _pagingController.itemList![idx].channel, subscription: subscription);
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _enqueueReload() {
|
||||
_reloadEnqueued = true;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.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/api/api_exception.dart';
|
||||
import 'package:simplecloudnotifier/models/channel.dart';
|
||||
import 'package:simplecloudnotifier/models/scn_message.dart';
|
||||
import 'package:simplecloudnotifier/models/subscription.dart';
|
||||
@@ -220,6 +221,9 @@ class _ChannelListItemState extends State<ChannelListItem> {
|
||||
} else {
|
||||
Toaster.success("Success", 'Requested widget.subscription to channel');
|
||||
}
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to subscribe to channel');
|
||||
ApplicationLog.error('Failed to subscribe to channel: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to subscribe to channel');
|
||||
ApplicationLog.error('Failed to subscribe to channel: ' + exc.toString(), trace: trace);
|
||||
@@ -238,6 +242,9 @@ class _ChannelListItemState extends State<ChannelListItem> {
|
||||
widget.onSubscriptionChanged.call(sub.channelID, null);
|
||||
|
||||
Toaster.success("Success", 'Unsubscribed from channel');
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to unsubscribe from channel');
|
||||
ApplicationLog.error('Failed to unsubscribe from channel: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to unsubscribe from channel');
|
||||
ApplicationLog.error('Failed to unsubscribe from channel: ' + exc.toString(), trace: trace);
|
||||
@@ -256,6 +263,9 @@ class _ChannelListItemState extends State<ChannelListItem> {
|
||||
widget.onSubscriptionChanged.call(sub.channelID, newSub);
|
||||
|
||||
Toaster.success("Success", 'Unsubscribed from channel');
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to unsubscribe from channel');
|
||||
ApplicationLog.error('Failed to unsubscribe from channel: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to unsubscribe from channel');
|
||||
ApplicationLog.error('Failed to unsubscribe from channel: ' + exc.toString(), trace: trace);
|
||||
@@ -274,6 +284,9 @@ class _ChannelListItemState extends State<ChannelListItem> {
|
||||
widget.onSubscriptionChanged.call(sub.channelID, newSub);
|
||||
|
||||
Toaster.success("Success", 'Subscribed to channel');
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to subscribe to channel');
|
||||
ApplicationLog.error('Failed to subscribe to channel: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to subscribe to channel');
|
||||
ApplicationLog.error('Failed to subscribe to channel: ' + exc.toString(), trace: trace);
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
import 'package:simplecloudnotifier/api/api_client.dart';
|
||||
import 'package:simplecloudnotifier/api/api_exception.dart';
|
||||
import 'package:simplecloudnotifier/components/error_display/error_display.dart';
|
||||
import 'package:simplecloudnotifier/components/layout/scaffold.dart';
|
||||
import 'package:simplecloudnotifier/models/channel.dart';
|
||||
@@ -305,7 +306,7 @@ class _ChannelViewPageState extends State<ChannelViewPage> {
|
||||
icon: FontAwesomeIcons.solidEnvelope,
|
||||
title: 'Messages',
|
||||
values: [channel.messagesSent.toString()],
|
||||
mainAction: (subscription != null && subscription!.confirmed) ? () => Navi.push(context, () => FilteredMessageViewPage(title: channel.displayName, filter: MessageFilter(channelIDs: [channel.channelID]))) : null,
|
||||
mainAction: (subscription != null && subscription!.confirmed) ? () => Navi.push(context, () => FilteredMessageViewPage(title: channel.displayName, alertText: null, filter: MessageFilter(channelIDs: [channel.channelID]))) : null,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -537,6 +538,9 @@ class _ChannelViewPageState extends State<ChannelViewPage> {
|
||||
});
|
||||
|
||||
widget.needsReload?.call();
|
||||
} on APIException catch (exc, trace) {
|
||||
ApplicationLog.error('Failed to save DisplayName: ' + exc.toString(), trace: trace);
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to save DisplayName');
|
||||
} catch (exc, trace) {
|
||||
ApplicationLog.error('Failed to save DisplayName: ' + exc.toString(), trace: trace);
|
||||
Toaster.error("Error", 'Failed to save DisplayName');
|
||||
@@ -569,9 +573,12 @@ class _ChannelViewPageState extends State<ChannelViewPage> {
|
||||
});
|
||||
|
||||
widget.needsReload?.call();
|
||||
} on APIException catch (exc, trace) {
|
||||
ApplicationLog.error('Failed to save DescriptionName: ' + exc.toString(), trace: trace);
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to save description');
|
||||
} catch (exc, trace) {
|
||||
ApplicationLog.error('Failed to save DescriptionName: ' + exc.toString(), trace: trace);
|
||||
Toaster.error("Error", 'Failed to save DescriptionName');
|
||||
Toaster.error("Error", 'Failed to save description');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -589,6 +596,9 @@ class _ChannelViewPageState extends State<ChannelViewPage> {
|
||||
} else {
|
||||
Toaster.success("Success", 'Requested subscription to channel');
|
||||
}
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to subscribe to channel');
|
||||
ApplicationLog.error('Failed to subscribe to channel: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to subscribe to channel');
|
||||
ApplicationLog.error('Failed to subscribe to channel: ' + exc.toString(), trace: trace);
|
||||
@@ -612,6 +622,9 @@ class _ChannelViewPageState extends State<ChannelViewPage> {
|
||||
await _initStateAsync(false);
|
||||
|
||||
Toaster.success("Success", 'Unsubscribed from channel');
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to unsubscribe from channel');
|
||||
ApplicationLog.error('Failed to unsubscribe from channel: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to unsubscribe from channel');
|
||||
ApplicationLog.error('Failed to unsubscribe from channel: ' + exc.toString(), trace: trace);
|
||||
@@ -630,6 +643,9 @@ class _ChannelViewPageState extends State<ChannelViewPage> {
|
||||
await _initStateAsync(false);
|
||||
|
||||
Toaster.success("Success", 'Unsubscribed from channel');
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to unsubscribe from channel');
|
||||
ApplicationLog.error('Failed to unsubscribe from channel: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to unsubscribe from channel');
|
||||
ApplicationLog.error('Failed to unsubscribe from channel: ' + exc.toString(), trace: trace);
|
||||
@@ -648,6 +664,9 @@ class _ChannelViewPageState extends State<ChannelViewPage> {
|
||||
await _initStateAsync(false);
|
||||
|
||||
Toaster.success("Success", 'Subscribed to channel');
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to subscribe to channel');
|
||||
ApplicationLog.error('Failed to subscribe to channel: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to subscribe to channel');
|
||||
ApplicationLog.error('Failed to subscribe to channel: ' + exc.toString(), trace: trace);
|
||||
@@ -664,6 +683,9 @@ class _ChannelViewPageState extends State<ChannelViewPage> {
|
||||
await _initStateAsync(false);
|
||||
|
||||
Toaster.success("Success", 'Subscription succesfully revoked');
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to revoke subscription');
|
||||
ApplicationLog.error('Failed to revoke subscription: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to revoke subscription');
|
||||
ApplicationLog.error('Failed to revoke subscription: ' + exc.toString(), trace: trace);
|
||||
@@ -680,6 +702,9 @@ class _ChannelViewPageState extends State<ChannelViewPage> {
|
||||
await _initStateAsync(false);
|
||||
|
||||
Toaster.success("Success", 'Subscription succesfully confirmed');
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to confirm subscription');
|
||||
ApplicationLog.error('Failed to confirm subscription: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to confirm subscription');
|
||||
ApplicationLog.error('Failed to confirm subscription: ' + exc.toString(), trace: trace);
|
||||
@@ -696,6 +721,9 @@ class _ChannelViewPageState extends State<ChannelViewPage> {
|
||||
await _initStateAsync(false);
|
||||
|
||||
Toaster.success("Success", 'Subscription request succesfully denied');
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to deny subscription');
|
||||
ApplicationLog.error('Failed to deny subscription: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to deny subscription');
|
||||
ApplicationLog.error('Failed to deny subscription: ' + exc.toString(), trace: trace);
|
||||
|
||||
@@ -2,8 +2,10 @@ import 'package:flutter/material.dart';
|
||||
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:simplecloudnotifier/api/api_client.dart';
|
||||
import 'package:simplecloudnotifier/components/badge_display/badge_display.dart';
|
||||
import 'package:simplecloudnotifier/components/layout/scaffold.dart';
|
||||
import 'package:simplecloudnotifier/models/client.dart';
|
||||
import 'package:simplecloudnotifier/state/app_settings.dart';
|
||||
import 'package:simplecloudnotifier/state/application_log.dart';
|
||||
import 'package:simplecloudnotifier/state/app_auth.dart';
|
||||
import 'package:simplecloudnotifier/pages/client_list/client_list_item.dart';
|
||||
@@ -69,16 +71,35 @@ class _ClientListPageState extends State<ClientListPage> {
|
||||
showShare: false,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(8, 4, 8, 4),
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () => Future.sync(
|
||||
() => _pagingController.refresh(),
|
||||
),
|
||||
child: PagedListView<int, Client>(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<Client>(
|
||||
itemBuilder: (context, item, index) => ClientListItem(item: item),
|
||||
child: Column(
|
||||
children: [
|
||||
BadgeDisplay(
|
||||
text: "All clients connected with this account",
|
||||
icon: null,
|
||||
mode: BadgeMode.info,
|
||||
textAlign: TextAlign.left,
|
||||
closable: true,
|
||||
extraPadding: EdgeInsets.fromLTRB(0, 0, 0, 16),
|
||||
hidden: !AppSettings().showInfoAlerts,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: _buildList(context),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildList(BuildContext context) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => Future.sync(
|
||||
() => _pagingController.refresh(),
|
||||
),
|
||||
child: PagedListView<int, Client>(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<Client>(
|
||||
itemBuilder: (context, item, index) => ClientListItem(item: item),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
||||
import 'package:simplecloudnotifier/api/api_client.dart';
|
||||
import 'package:simplecloudnotifier/components/badge_display/badge_display.dart';
|
||||
import 'package:simplecloudnotifier/components/layout/scaffold.dart';
|
||||
import 'package:simplecloudnotifier/models/channel.dart';
|
||||
import 'package:simplecloudnotifier/models/scn_message.dart';
|
||||
@@ -17,11 +18,13 @@ class FilteredMessageViewPage extends StatefulWidget {
|
||||
const FilteredMessageViewPage({
|
||||
required this.title,
|
||||
required this.filter,
|
||||
required this.alertText,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final String title;
|
||||
final MessageFilter filter;
|
||||
final String? alertText;
|
||||
|
||||
@override
|
||||
State<FilteredMessageViewPage> createState() => _FilteredMessageViewPageState();
|
||||
@@ -87,31 +90,52 @@ class _FilteredMessageViewPageState extends State<FilteredMessageViewPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget child = _buildMessageList(context);
|
||||
|
||||
if (widget.alertText != null) {
|
||||
child = Column(
|
||||
children: [
|
||||
BadgeDisplay(
|
||||
text: widget.alertText!,
|
||||
icon: null,
|
||||
mode: BadgeMode.info,
|
||||
textAlign: TextAlign.left,
|
||||
closable: true,
|
||||
extraPadding: EdgeInsets.fromLTRB(0, 0, 0, 16),
|
||||
hidden: !AppSettings().showInfoAlerts,
|
||||
),
|
||||
Expanded(
|
||||
child: child,
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return SCNScaffold(
|
||||
title: this.widget.title,
|
||||
showSearch: false,
|
||||
showShare: false,
|
||||
child: _buildMessageList(context),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(8, 4, 8, 4),
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildMessageList(BuildContext context) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(8, 4, 8, 4),
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () => Future.sync(
|
||||
() => _pagingController.refresh(),
|
||||
),
|
||||
child: PagedListView<String, SCNMessage>(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<SCNMessage>(
|
||||
itemBuilder: (context, item, index) => MessageListItem(
|
||||
message: item,
|
||||
allChannels: _channels ?? {},
|
||||
onPressed: () {
|
||||
Navi.push(context, () => MessageViewPage(messageID: item.messageID, preloadedData: (item,)));
|
||||
},
|
||||
),
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => Future.sync(
|
||||
() => _pagingController.refresh(),
|
||||
),
|
||||
child: PagedListView<String, SCNMessage>(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<SCNMessage>(
|
||||
itemBuilder: (context, item, index) => MessageListItem(
|
||||
message: item,
|
||||
allChannels: _channels ?? {},
|
||||
onPressed: () {
|
||||
Navi.push(context, () => MessageViewPage(messageID: item.messageID, preloadedData: (item,)));
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -3,10 +3,12 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:simplecloudnotifier/api/api_client.dart';
|
||||
import 'package:simplecloudnotifier/components/badge_display/badge_display.dart';
|
||||
import 'package:simplecloudnotifier/components/layout/scaffold.dart';
|
||||
import 'package:simplecloudnotifier/models/keytoken.dart';
|
||||
import 'package:simplecloudnotifier/pages/keytoken_list/keytoken_create_modal.dart';
|
||||
import 'package:simplecloudnotifier/pages/keytoken_list/keytoken_created_modal.dart';
|
||||
import 'package:simplecloudnotifier/state/app_settings.dart';
|
||||
import 'package:simplecloudnotifier/state/application_log.dart';
|
||||
import 'package:simplecloudnotifier/state/app_auth.dart';
|
||||
import 'package:simplecloudnotifier/pages/keytoken_list/keytoken_list_item.dart';
|
||||
@@ -72,16 +74,21 @@ class _KeyTokenListPageState extends State<KeyTokenListPage> {
|
||||
showShare: false,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(8, 4, 8, 4),
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () => Future.sync(
|
||||
() => _pagingController.refresh(),
|
||||
),
|
||||
child: PagedListView<int, KeyToken>(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<KeyToken>(
|
||||
itemBuilder: (context, item, index) => KeyTokenListItem(item: item, needsReload: _fullRefresh),
|
||||
child: Column(
|
||||
children: [
|
||||
BadgeDisplay(
|
||||
text: "These are your keys.\nKeys can be used to send messages and access your account.\n\nKeys can have different sets of permissions, the Admin-Key has full-access to your account",
|
||||
icon: null,
|
||||
mode: BadgeMode.info,
|
||||
textAlign: TextAlign.left,
|
||||
closable: true,
|
||||
extraPadding: EdgeInsets.fromLTRB(0, 0, 0, 16),
|
||||
hidden: !AppSettings().showInfoAlerts,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: _buildList(context),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
@@ -97,6 +104,20 @@ class _KeyTokenListPageState extends State<KeyTokenListPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildList(BuildContext context) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => Future.sync(
|
||||
() => _pagingController.refresh(),
|
||||
),
|
||||
child: PagedListView<int, KeyToken>(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<KeyToken>(
|
||||
itemBuilder: (context, item, index) => KeyTokenListItem(item: item, needsReload: _fullRefresh),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _created(KeyToken token, String tokValue) {
|
||||
setState(() {
|
||||
_pagingController.itemList?.insert(0, token);
|
||||
|
||||
@@ -78,7 +78,7 @@ class KeyTokenListItem extends StatelessWidget {
|
||||
SizedBox(width: 4),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Navi.push(context, () => FilteredMessageViewPage(title: item.name, filter: MessageFilter(usedKeys: [item.keytokenID])));
|
||||
Navi.push(context, () => FilteredMessageViewPage(title: item.name, alertText: 'All message sent with the key \'${item.name}\'', filter: MessageFilter(usedKeys: [item.keytokenID])));
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:simplecloudnotifier/api/api_client.dart';
|
||||
import 'package:simplecloudnotifier/api/api_exception.dart';
|
||||
import 'package:simplecloudnotifier/components/error_display/error_display.dart';
|
||||
import 'package:simplecloudnotifier/components/layout/scaffold.dart';
|
||||
import 'package:simplecloudnotifier/models/channel.dart';
|
||||
@@ -230,7 +231,7 @@ class _KeyTokenViewPageState extends State<KeyTokenViewPage> {
|
||||
title: 'Messages',
|
||||
values: [keytoken.messagesSent.toString()],
|
||||
mainAction: () {
|
||||
Navi.push(context, () => FilteredMessageViewPage(title: keytoken.name, filter: MessageFilter(usedKeys: [keytoken.keytokenID])));
|
||||
Navi.push(context, () => FilteredMessageViewPage(title: keytoken.name, alertText: 'All message sent with the key \'${keytoken.name}\'', filter: MessageFilter(usedKeys: [keytoken.keytokenID])));
|
||||
},
|
||||
),
|
||||
..._buildPermissionCard(context, true, keytoken.toPreview()),
|
||||
@@ -543,6 +544,9 @@ class _KeyTokenViewPageState extends State<KeyTokenViewPage> {
|
||||
Toaster.info('Logout', 'Successfully deleted the key');
|
||||
|
||||
Navi.pop(context);
|
||||
} on APIException catch (exc, trace) {
|
||||
ApplicationLog.error('Failed to delete key: ' + exc.toString(), trace: trace);
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to delete key');
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to delete key');
|
||||
ApplicationLog.error('Failed to delete key: ' + exc.toString(), trace: trace);
|
||||
@@ -563,6 +567,9 @@ class _KeyTokenViewPageState extends State<KeyTokenViewPage> {
|
||||
Toaster.info("Success", "Key updated");
|
||||
|
||||
widget.needsReload?.call();
|
||||
} on APIException catch (exc, trace) {
|
||||
ApplicationLog.error('Failed to update key: ' + exc.toString(), trace: trace);
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to update key');
|
||||
} catch (exc, trace) {
|
||||
ApplicationLog.error('Failed to update key: ' + exc.toString(), trace: trace);
|
||||
Toaster.error("Error", 'Failed to update key');
|
||||
@@ -583,6 +590,9 @@ class _KeyTokenViewPageState extends State<KeyTokenViewPage> {
|
||||
Toaster.info("Success", "Key updated");
|
||||
|
||||
widget.needsReload?.call();
|
||||
} on APIException catch (exc, trace) {
|
||||
ApplicationLog.error('Failed to update key: ' + exc.toString(), trace: trace);
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to update key');
|
||||
} catch (exc, trace) {
|
||||
ApplicationLog.error('Failed to update key: ' + exc.toString(), trace: trace);
|
||||
Toaster.error("Error", 'Failed to update key');
|
||||
@@ -603,6 +613,9 @@ class _KeyTokenViewPageState extends State<KeyTokenViewPage> {
|
||||
Toaster.info("Success", "Key updated");
|
||||
|
||||
widget.needsReload?.call();
|
||||
} on APIException catch (exc, trace) {
|
||||
ApplicationLog.error('Failed to update key: ' + exc.toString(), trace: trace);
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to update key');
|
||||
} catch (exc, trace) {
|
||||
ApplicationLog.error('Failed to update key: ' + exc.toString(), trace: trace);
|
||||
Toaster.error("Error", 'Failed to update key');
|
||||
|
||||
@@ -157,7 +157,7 @@ class _MessageViewPageState extends State<MessageViewPage> {
|
||||
title: 'Sender',
|
||||
values: [message.senderName!],
|
||||
mainAction: () => {
|
||||
Navi.push(context, () => FilteredMessageViewPage(title: message.senderName!, filter: MessageFilter(senderNames: [message.senderName!])))
|
||||
Navi.push(context, () => FilteredMessageViewPage(title: message.senderName!, alertText: 'All message sent from \'${message.senderName!}\'', filter: MessageFilter(senderNames: [message.senderName!])))
|
||||
},
|
||||
),
|
||||
UI.metaCard(
|
||||
@@ -169,7 +169,7 @@ class _MessageViewPageState extends State<MessageViewPage> {
|
||||
if (message.senderUserID == userAccUserID) {
|
||||
Navi.push(context, () => KeyTokenViewPage(keytokenID: message.usedKeyID, preloadedData: null, needsReload: null));
|
||||
} else {
|
||||
Navi.push(context, () => FilteredMessageViewPage(title: token?.name ?? message.usedKeyID, filter: MessageFilter(usedKeys: [message.usedKeyID])));
|
||||
Navi.push(context, () => FilteredMessageViewPage(title: token?.name ?? message.usedKeyID, alertText: 'All message sent with the specified key', filter: MessageFilter(usedKeys: [message.usedKeyID])));
|
||||
}
|
||||
},
|
||||
),
|
||||
@@ -201,14 +201,14 @@ class _MessageViewPageState extends State<MessageViewPage> {
|
||||
icon: FontAwesomeIcons.solidUser,
|
||||
title: 'User',
|
||||
values: [user?.userID ?? message.senderUserID, user?.username ?? ''],
|
||||
mainAction: () => Navi.push(context, () => FilteredMessageViewPage(title: user?.username ?? message.senderUserID, filter: MessageFilter(senderUserID: [message.senderUserID]))),
|
||||
mainAction: () => Navi.push(context, () => FilteredMessageViewPage(title: user?.username ?? message.senderUserID, alertText: 'All message sent by the specified account', filter: MessageFilter(senderUserID: [message.senderUserID]))),
|
||||
),
|
||||
UI.metaCard(
|
||||
context: context,
|
||||
icon: FontAwesomeIcons.solidBolt,
|
||||
title: 'Priority',
|
||||
values: [_prettyPrintPriority(message.priority)],
|
||||
mainAction: () => Navi.push(context, () => FilteredMessageViewPage(title: "Priority ${message.priority}", filter: MessageFilter(priority: [message.priority]))),
|
||||
mainAction: () => Navi.push(context, () => FilteredMessageViewPage(title: "Priority ${message.priority}", alertText: 'All message sent with priority ${message.priority}', filter: MessageFilter(priority: [message.priority]))),
|
||||
),
|
||||
if (message.senderUserID == userAccUserID)
|
||||
UI.button(
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
import 'package:simplecloudnotifier/api/api_client.dart';
|
||||
import 'package:simplecloudnotifier/api/api_exception.dart';
|
||||
import 'package:simplecloudnotifier/components/error_display/error_display.dart';
|
||||
import 'package:simplecloudnotifier/state/application_log.dart';
|
||||
import 'package:simplecloudnotifier/state/globals.dart';
|
||||
@@ -289,6 +290,9 @@ class _SendRootPageState extends State<SendRootPage> {
|
||||
_msgTitle.clear();
|
||||
_msgContent.clear();
|
||||
});
|
||||
} on APIException catch (e, stackTrace) {
|
||||
if (!e.toastShown) Toaster.error("Error", 'Failed to send message: ${e.toString()}');
|
||||
ApplicationLog.error('Failed to send message', trace: stackTrace);
|
||||
} catch (e, stackTrace) {
|
||||
Toaster.error("Error", 'Failed to send message: ${e.toString()}');
|
||||
ApplicationLog.error('Failed to send message', trace: stackTrace);
|
||||
@@ -308,6 +312,9 @@ class _SendRootPageState extends State<SendRootPage> {
|
||||
_msgTitle.clear();
|
||||
_msgContent.clear();
|
||||
});
|
||||
} on APIException catch (e, stackTrace) {
|
||||
if (!e.toastShown) Toaster.error("Error", 'Failed to send message: ${e.toString()}');
|
||||
ApplicationLog.error('Failed to send message', trace: stackTrace);
|
||||
} catch (e, stackTrace) {
|
||||
Toaster.error("Error", 'Failed to send message: ${e.toString()}');
|
||||
ApplicationLog.error('Failed to send message', trace: stackTrace);
|
||||
|
||||
@@ -2,8 +2,10 @@ import 'package:flutter/material.dart';
|
||||
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:simplecloudnotifier/api/api_client.dart';
|
||||
import 'package:simplecloudnotifier/components/badge_display/badge_display.dart';
|
||||
import 'package:simplecloudnotifier/components/layout/scaffold.dart';
|
||||
import 'package:simplecloudnotifier/models/sender_name_statistics.dart';
|
||||
import 'package:simplecloudnotifier/state/app_settings.dart';
|
||||
import 'package:simplecloudnotifier/state/application_log.dart';
|
||||
import 'package:simplecloudnotifier/state/app_auth.dart';
|
||||
import 'package:simplecloudnotifier/pages/sender_list/sender_list_item.dart';
|
||||
@@ -69,16 +71,35 @@ class _SenderListPageState extends State<SenderListPage> {
|
||||
showShare: false,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(8, 4, 8, 4),
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () => Future.sync(
|
||||
() => _pagingController.refresh(),
|
||||
),
|
||||
child: PagedListView<int, SenderNameStatistics>(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<SenderNameStatistics>(
|
||||
itemBuilder: (context, item, index) => SenderListItem(item: item),
|
||||
child: Column(
|
||||
children: [
|
||||
BadgeDisplay(
|
||||
text: "All sender used to send messages to this account",
|
||||
icon: null,
|
||||
mode: BadgeMode.info,
|
||||
textAlign: TextAlign.left,
|
||||
closable: true,
|
||||
extraPadding: EdgeInsets.fromLTRB(0, 0, 0, 16),
|
||||
hidden: !AppSettings().showInfoAlerts,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: _buildList(context),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildList(BuildContext context) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => Future.sync(
|
||||
() => _pagingController.refresh(),
|
||||
),
|
||||
child: PagedListView<int, SenderNameStatistics>(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<SenderNameStatistics>(
|
||||
itemBuilder: (context, item, index) => SenderListItem(item: item),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -30,7 +30,7 @@ class SenderListItem extends StatelessWidget {
|
||||
color: Theme.of(context).cardTheme.color,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Navi.push(context, () => FilteredMessageViewPage(title: item.name, filter: MessageFilter(senderNames: [item.name])));
|
||||
Navi.push(context, () => FilteredMessageViewPage(title: item.name, alertText: 'All message sent from \'${item.name!}\'', filter: MessageFilter(senderNames: [item.name])));
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
@@ -71,7 +71,7 @@ class SenderListItem extends StatelessWidget {
|
||||
SizedBox(width: 4),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Navi.push(context, () => FilteredMessageViewPage(title: item.name, filter: MessageFilter(senderNames: [item.name])));
|
||||
Navi.push(context, () => FilteredMessageViewPage(title: item.name, alertText: 'All message sent from \'${item.name!}\'', filter: MessageFilter(senderNames: [item.name])));
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
|
||||
@@ -146,6 +146,12 @@ class _SettingsRootPageState extends State<SettingsRootPage> {
|
||||
title: Text('Refresh messages on app resume'),
|
||||
onToggle: (value) => AppSettings().update((p) => p.alwaysBackgroundRefreshMessageListOnLifecycleResume = !p.alwaysBackgroundRefreshMessageListOnLifecycleResume),
|
||||
),
|
||||
SettingsTile.switchTile(
|
||||
initialValue: cfg.showInfoAlerts,
|
||||
leading: Icon(FontAwesomeIcons.solidCircleInfo),
|
||||
title: Text('Show various helpful info boxes'),
|
||||
onToggle: (value) => AppSettings().update((p) => p.showInfoAlerts = !p.showInfoAlerts),
|
||||
),
|
||||
],
|
||||
),
|
||||
SettingsSection(
|
||||
|
||||
@@ -2,10 +2,12 @@ import 'package:flutter/material.dart';
|
||||
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:simplecloudnotifier/api/api_client.dart';
|
||||
import 'package:simplecloudnotifier/components/badge_display/badge_display.dart';
|
||||
import 'package:simplecloudnotifier/components/layout/scaffold.dart';
|
||||
import 'package:simplecloudnotifier/models/channel.dart';
|
||||
import 'package:simplecloudnotifier/models/subscription.dart';
|
||||
import 'package:simplecloudnotifier/models/user.dart';
|
||||
import 'package:simplecloudnotifier/state/app_settings.dart';
|
||||
import 'package:simplecloudnotifier/state/application_log.dart';
|
||||
import 'package:simplecloudnotifier/state/app_auth.dart';
|
||||
import 'package:simplecloudnotifier/pages/subscription_list/subscription_list_item.dart';
|
||||
@@ -93,16 +95,35 @@ class _SubscriptionListPageState extends State<SubscriptionListPage> {
|
||||
showShare: false,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(8, 4, 8, 4),
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () => Future.sync(
|
||||
() => _pagingController.refresh(),
|
||||
),
|
||||
child: PagedListView<int, Subscription>(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<Subscription>(
|
||||
itemBuilder: (context, item, index) => SubscriptionListItem(item: item, userCache: userCache, channelCache: channelCache, needsReload: fullRefresh),
|
||||
child: Column(
|
||||
children: [
|
||||
BadgeDisplay(
|
||||
text: "These are subscriptions to individual Channels\n\nThey contain to your own channels, subscriptions to foreign channels and subscriptions of other users to your channels (active and requested).",
|
||||
icon: null,
|
||||
mode: BadgeMode.info,
|
||||
textAlign: TextAlign.left,
|
||||
closable: true,
|
||||
extraPadding: EdgeInsets.fromLTRB(0, 0, 0, 16),
|
||||
hidden: !AppSettings().showInfoAlerts,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: _buildList(context),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildList(BuildContext context) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => Future.sync(
|
||||
() => _pagingController.refresh(),
|
||||
),
|
||||
child: PagedListView<int, Subscription>(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<Subscription>(
|
||||
itemBuilder: (context, item, index) => SubscriptionListItem(item: item, userCache: userCache, channelCache: channelCache, needsReload: fullRefresh),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:simplecloudnotifier/api/api_client.dart';
|
||||
import 'package:simplecloudnotifier/api/api_exception.dart';
|
||||
import 'package:simplecloudnotifier/components/error_display/error_display.dart';
|
||||
import 'package:simplecloudnotifier/components/layout/scaffold.dart';
|
||||
import 'package:simplecloudnotifier/models/channel.dart';
|
||||
@@ -407,6 +408,9 @@ class _SubscriptionViewPageState extends State<SubscriptionViewPage> {
|
||||
await _initStateAsync(false);
|
||||
|
||||
Toaster.success("Success", 'Subscription succesfully confirmed');
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to confirm subscription');
|
||||
ApplicationLog.error('Failed to confirm subscription: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to confirm subscription');
|
||||
ApplicationLog.error('Failed to confirm subscription: ' + exc.toString(), trace: trace);
|
||||
@@ -429,6 +433,9 @@ class _SubscriptionViewPageState extends State<SubscriptionViewPage> {
|
||||
|
||||
Toaster.success("Success", 'Unsubscribed from channel');
|
||||
Navi.pop(context);
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to unsubscribe from channel');
|
||||
ApplicationLog.error('Failed to unsubscribe from channel: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to unsubscribe from channel');
|
||||
ApplicationLog.error('Failed to unsubscribe from channel: ' + exc.toString(), trace: trace);
|
||||
@@ -447,6 +454,9 @@ class _SubscriptionViewPageState extends State<SubscriptionViewPage> {
|
||||
await _initStateAsync(false);
|
||||
|
||||
Toaster.success("Success", 'Unsubscribed from channel');
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to unsubscribe from channel');
|
||||
ApplicationLog.error('Failed to unsubscribe from channel: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to unsubscribe from channel');
|
||||
ApplicationLog.error('Failed to unsubscribe from channel: ' + exc.toString(), trace: trace);
|
||||
@@ -465,6 +475,9 @@ class _SubscriptionViewPageState extends State<SubscriptionViewPage> {
|
||||
await _initStateAsync(false);
|
||||
|
||||
Toaster.success("Success", 'Subscribed to channel');
|
||||
} on APIException catch (exc, trace) {
|
||||
if (!exc.toastShown) Toaster.error("Error", 'Failed to subscribe to channel');
|
||||
ApplicationLog.error('Failed to subscribe to channel: ' + exc.toString(), trace: trace);
|
||||
} catch (exc, trace) {
|
||||
Toaster.error("Error", 'Failed to subscribe to channel');
|
||||
ApplicationLog.error('Failed to subscribe to channel: ' + exc.toString(), trace: trace);
|
||||
|
||||
Reference in New Issue
Block a user