Skip to content

Commit

Permalink
Fix a few bugs with share link creation and updating
Browse files Browse the repository at this point in the history
  • Loading branch information
ComputerElite committed Jan 30, 2025
1 parent 4cfc6c7 commit 0a43236
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 22 deletions.
1 change: 0 additions & 1 deletion lib/components/shocker_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,6 @@ class ShockerItemState extends State<ShockerItem>
Expanded(
child: Text(
shocker.name,
style: t.textTheme.headlineSmall,
overflow: TextOverflow.ellipsis,
),
),
Expand Down
4 changes: 3 additions & 1 deletion lib/screens/home.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ class ScreenSelectorState extends State<ScreenSelector> {
setState(() {});
}),
null,
null // ToDo: Add share link button
ShareLinksScreen.getFloatingActionButton(manager, context, () {
setState(() {});
})
];
return Scaffold(
body: Padding(
Expand Down
6 changes: 6 additions & 0 deletions lib/screens/share_link_edit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ class ShareLinkEditScreenState extends State<ShareLinkEditScreen> {
Navigator.of(context).pop();
}, child: Text("Cancel")),
TextButton(onPressed: () async {
if(selectedShocker == null) {
showDialog(context: context, builder: (context) => AlertDialog(title: Text("Error"), content: Text("Please select a shocker to add"), actions: [TextButton(onPressed: () {
Navigator.of(context).pop();
}, child: Text("Ok"))],));
return;
}
showDialog(context: context, builder: (context) => LoadingDialog(title: "Adding shocker"));

String? error = await AlarmListManager.getInstance().addShockerToShareLink(selectedShocker, shareLink!);
Expand Down
191 changes: 175 additions & 16 deletions lib/screens/share_links.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,147 @@ import 'package:flutter/widgets.dart';
import 'package:pretty_qr_code/pretty_qr_code.dart';
import 'package:share_plus/share_plus.dart';
import 'package:shock_alarm_app/components/card.dart';
import 'package:shock_alarm_app/components/delete_dialog.dart';
import 'package:shock_alarm_app/components/qr_card.dart';
import 'package:shock_alarm_app/screens/share_link_edit.dart';
import 'package:shock_alarm_app/services/alarm_list_manager.dart';
import 'package:shock_alarm_app/services/openshock.dart';

import '../components/desktop_mobile_refresh_indicator.dart';

class ShareLinkCreationDialog extends StatefulWidget {
String shareLinkName = "";
DateTime? expiresOn = DateTime.now().add(Duration(days: 1));

@override
State<StatefulWidget> createState() => ShareLinkCreationDialogState();
}

class ShareLinkCreationDialogState extends State<ShareLinkCreationDialog> {
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text("Create Share Link"),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
decoration: InputDecoration(
labelText: "Name",
),
onChanged: (value) {
widget.shareLinkName = value;
},
),
Padding(padding: EdgeInsets.all(15)),
Text("Expires: ${widget.expiresOn.toString().split(".").first}",
style: TextStyle(fontSize: 20)),
TextButton(
onPressed: () async {
widget.expiresOn = await showDatePicker(
context: context,
firstDate: DateTime.now(),
lastDate: DateTime.now().add(Duration(days: 365)),
initialDate: widget.expiresOn);
if (widget.expiresOn == null) return;
TimeOfDay? time = await showTimePicker(
context: context,
initialTime: TimeOfDay.fromDateTime(widget.expiresOn!));
setState(() {
widget.expiresOn = DateTime(
widget.expiresOn!.year,
widget.expiresOn!.month,
widget.expiresOn!.day,
time!.hour,
time.minute);
});
},
child: Text("Change expiry")),
],
),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text("Cancel")),
TextButton(
onPressed: () async {
if(widget.shareLinkName.isEmpty) {
showDialog(context: context, builder: (context) {
return AlertDialog(
title: Text("Name is empty"),
content: Text("Please enter a name for the share link"),
actions: [
TextButton(onPressed: () {
Navigator.of(context).pop();
}, child: Text("Ok"))
],
);
});
return;
}

showDialog(context: context, builder: (context) => LoadingDialog(title: "Creating Share Link"));
String? error = await AlarmListManager.getInstance().createShareLink(widget.shareLinkName, widget.expiresOn!);
if(error != null) {
Navigator.of(context).pop();
showDialog(context: context, builder: (context) {
return AlertDialog(
title: Text("Error creating share link"),
content: Text(error),
actions: [
TextButton(onPressed: () {
Navigator.of(context).pop();
}, child: Text("Ok"))
],
);
});
return;
}
Navigator.of(context).pop();
Navigator.of(context).pop();
AlarmListManager.getInstance().reloadShareLinksMethod!();
},
child: Text("Create")),
],
);
}
}

class ShareLinksScreen extends StatefulWidget {
const ShareLinksScreen({Key? key}) : super(key: key);

@override
State<StatefulWidget> createState() => ShareLinksScreenState();

static getFloatingActionButton(
AlarmListManager manager, BuildContext context, Function reloadState) {
return FloatingActionButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
if (!manager.hasValidAccount()) {
return AlertDialog(
title: Text("You're not logged in"),
content: Text(
"Login to OpenShock to create a Share Link. To do this visit the settings page."),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text("Ok"))
],
);
}
return ShareLinkCreationDialog();
},
);
},
child: Icon(Icons.add));
}
}

class ShareLinksScreenState extends State<ShareLinksScreen> {
Expand All @@ -23,39 +152,44 @@ class ShareLinksScreenState extends State<ShareLinksScreen> {

Future loadShares() async {
shareLinks = await AlarmListManager.getInstance().getShareLinks();
initialLoading = false;
setState(() {
initialLoading = false;
});
}

@override
void initState() {
// TODO: implement initState
AlarmListManager.getInstance().reloadShareLinksMethod = loadShares;
initialLoading = true;
loadShares().then((value) {
setState(() {
initialLoading = false;
});
});
loadShares();
super.initState();
}

@override
Widget build(BuildContext context) {
final shareEntries =
shareLinks.map((link) => ShareLinkItem(shareLink: link)).toList();
ThemeData t = Theme.of(context);
List<Widget> shareEntries = [];
for (OpenShockShareLink shareLink in shareLinks) {
shareEntries.add(ShareLinkItem(shareLink: shareLink, reloadMethod: loadShares));
}
if(shareEntries.isEmpty) {
shareEntries.add(Center(child: Text("No share links created yet",
style: t.textTheme.headlineSmall)));
}
return initialLoading
? Center(child: CircularProgressIndicator())
: DesktopMobileRefreshIndicator(
onRefresh: () async {
return loadShares();
},
onRefresh: loadShares,
child: ListView(children: shareEntries));
}
}

class ShareLinkItem extends StatelessWidget {
final OpenShockShareLink shareLink;
final Function reloadMethod;

const ShareLinkItem({Key? key, required this.shareLink}) : super(key: key);
const ShareLinkItem({Key? key, required this.shareLink, required this.reloadMethod}) : super(key: key);

@override
Widget build(BuildContext context) {
Expand All @@ -69,7 +203,29 @@ class ShareLinkItem extends StatelessWidget {
IconButton(
icon: Icon(Icons.delete),
onPressed: () {
AlarmListManager.getInstance().deleteShareLink(shareLink);
showDialog(context: context, builder: (context) {
return DeleteDialog(onDelete: () async {
showDialog(context: context, builder: (context) => LoadingDialog(title: "Deleting ${shareLink.name}"));
String? error = await AlarmListManager.getInstance().deleteShareLink(shareLink);
Navigator.of(context).pop();
if(error != null) {
showDialog(context: context, builder: (context) {
return AlertDialog(
title: Text("Error deleting share link"),
content: Text(error),
actions: [
TextButton(onPressed: () {
Navigator.of(context).pop();
}, child: Text("Ok"))
],
);
});
return;
}
Navigator.of(context).pop();
reloadMethod();
}, title: "Delete ${shareLink.name}", body: "Are you sure you want to delete ${shareLink.name}?");
});
}),
IconButton(
onPressed: () {
Expand All @@ -95,11 +251,14 @@ class ShareLinkItem extends StatelessWidget {
onPressed: () {
Share.share(shareLink.getLink());
}),
IconButton(onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
IconButton(
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
return ShareLinkEditScreen(shareLink: shareLink);
}));
}, icon: Icon(Icons.edit))
},
icon: Icon(Icons.edit))
],
)
],
Expand Down
15 changes: 14 additions & 1 deletion lib/services/alarm_list_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class AlarmListManager {
final List<Hub> hubs = [];
final List<String> onlineHubs = [];
final List<AlarmTone> alarmTones = [];
List<OpenShockShareLink>? shareLinks;
final Map<String, bool> enabledHubs = {};
Settings settings = Settings();
OpenShockWS? ws;
Expand Down Expand Up @@ -439,6 +440,8 @@ class AlarmListManager {
Map<String?, List<ShockerLog>> availableShockerLogs = {};
Function? reloadShockerLogs;

Function()? reloadShareLinksMethod;

Future startWS(Token t, {bool stopExisting = true}) async {
if(ws != null) {
if(!stopExisting) return;
Expand Down Expand Up @@ -545,7 +548,10 @@ class AlarmListManager {
return links;
}

void deleteShareLink(OpenShockShareLink shareLink) {}
Future<String?> deleteShareLink(OpenShockShareLink shareLink) async {
OpenShockClient client = OpenShockClient();
return client.deleteShareLink(shareLink);
}

Future<OpenShockShareLink?> getShareLink(OpenShockShareLink shareLink) async {
OpenShockClient client = OpenShockClient();
Expand All @@ -557,4 +563,11 @@ class AlarmListManager {
return client.addShockerToShareLink(selectedShocker!, openShockShareLink);
}

Future<String?> createShareLink(String shareLinkName, DateTime dateTime) async {
OpenShockClient client = OpenShockClient();
Token? token = getAnyUserToken();
if(token == null) return "No token found";
return client.createShareLink(token, shareLinkName, dateTime);
}

}
27 changes: 24 additions & 3 deletions lib/services/openshock.dart
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ class OpenShockClient {

Future<String?> setPauseStateOfShareLinkShocker(OpenShockShareLink shareLink, Shocker shocker, bool paused) async {
Token? t = shareLink.tokenReference;
if(t == null) return null;
if(t == null) return "Token not found";
var response = await PostRequest(t, "/1/shares/links/${shareLink.id}/${shocker.id}/pause", jsonEncode({
"pause": paused
}));
Expand All @@ -519,7 +519,7 @@ class OpenShockClient {

Future<String?> removeShockerFromShareLink(OpenShockShareLink shareLink, Shocker shocker) async {
Token? t = shareLink.tokenReference;
if(t == null) return null;
if(t == null) return "Token not found";
var response = await DeleteRequest(t, "/1/shares/links/${shareLink.id}/${shocker.id}", "");
if(response.statusCode == 200) {
return null;
Expand All @@ -529,13 +529,34 @@ class OpenShockClient {

Future<String?> setLimitsOfShareLinkShocker(OpenShockShareLink shareLink, Shocker shocker, OpenShockShareLimits limits) async {
Token? t = shareLink.tokenReference;
if(t == null) return null;
if(t == null) return "Token not found";
var response = await PatchRequest(t, "/1/shares/links/${shareLink.id}/${shocker.id}", jsonEncode(limits.toJson()));
if(response.statusCode == 200) {
return null;
}
return getErrorCode(response, "Failed to update shocker limits");
}

Future<String?> createShareLink(Token t, String shareLinkName, DateTime dateTime) async {
var response = await PostRequest(t, "/1/shares/links", jsonEncode({
"name": shareLinkName,
"expiresOn": dateTime.toIso8601String()
}));
if(response.statusCode == 200) {
return null;
}
return getErrorCode(response, "Failed to create share link");
}

Future<String?> deleteShareLink(OpenShockShareLink shareLink) async {
Token? t = shareLink.tokenReference;
if(t == null) return "Token not found";
var response = await DeleteRequest(t, "/1/shares/links/${shareLink.id}", "");
if(response.statusCode == 200) {
return null;
}
return getErrorCode(response, "Failed to delete share link");
}
}

class OpenShockShareLink {
Expand Down

0 comments on commit 0a43236

Please sign in to comment.