Skip to content

Commit 21bb994

Browse files
committed
First batch of updates, rename shares tab, add ability to create user share invites by selecting multiple shockers, update login form
1 parent d3bae1b commit 21bb994

15 files changed

Lines changed: 298 additions & 103 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
**Changelog:**
2+
- Implemented V2 Shares of OpenShock api.
3+
- Reorganized shares page to accomodate new invite model
4+
- Added padding between turnstile challenge and password field
5+
- Made unlinking shockers also work when selecting multiple at once
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:share_plus/share_plus.dart';
3+
import 'package:shock_alarm_app/components/predefined_spacing.dart';
4+
import 'package:shock_alarm_app/components/qr_card.dart';
5+
import 'package:shock_alarm_app/main.dart';
6+
7+
class ShareOrQrDialog extends StatelessWidget {
8+
String title;
9+
String body;
10+
String shareString;
11+
String qrContent;
12+
String qrTitle;
13+
14+
ShareOrQrDialog(
15+
{required this.title, required this.body, required this.shareString, required this.qrContent, required this.qrTitle});
16+
17+
static void show(String title, String body, String shareString, String qrContent, String qrTitle) {
18+
showDialog(
19+
context: navigatorKey.currentContext!, builder: (context) => ShareOrQrDialog(title: title, body: body, shareString: shareString, qrContent: qrContent, qrTitle: qrTitle));
20+
}
21+
22+
@override
23+
Widget build(BuildContext context) {
24+
return AlertDialog.adaptive(
25+
title: Text(title),
26+
content: SingleChildScrollView(child: Column(
27+
children: [
28+
Text(body),
29+
Row(mainAxisAlignment: MainAxisAlignment.center, spacing: 30, children: [
30+
IconButton(onPressed: () {
31+
Share.share(shareString);
32+
}, icon: Icon(Icons.share, size: 32,)),
33+
IconButton(onPressed: () {
34+
showDialog(context: context, builder: (context) => AlertDialog.adaptive(
35+
title: Text(qrTitle),
36+
content: QrCard(data: qrContent),
37+
actions: [
38+
TextButton(
39+
onPressed: () {
40+
Navigator.of(context).pop();
41+
},
42+
child: Text('Close'))
43+
],
44+
));
45+
}, icon: Icon(Icons.qr_code, size: 32,)),
46+
],)
47+
],
48+
49+
)),
50+
actions: [
51+
TextButton(
52+
onPressed: () {
53+
Navigator.of(context).pop();
54+
},
55+
child: Text("Close"))
56+
],
57+
);
58+
}
59+
}

lib/main.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const String issues_url =
1818
"https://github.com/ComputerElite/ShockAlarmApp/issues";
1919

2020
String GetUserAgent() {
21-
return "ShockAlarm/0.3.9";
21+
return "ShockAlarm/0.4.0";
2222
}
2323

2424
bool isAndroid() {

lib/screens/screen_selector.dart

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class ScreenSelectorScreenState extends State<ScreenSelectorScreen> {
6060
navigationBarItems = [
6161
if (supportsAlarms)
6262
BottomNavigationBarItem(icon: Icon(Icons.alarm), label: 'Alarms'),
63-
BottomNavigationBarItem(icon: Icon(Icons.link), label: 'Share Links'),
63+
BottomNavigationBarItem(icon: Icon(Icons.link), label: 'Shares'),
6464
BottomNavigationBarItem(
6565
icon: OpenShockClient.getIconForControlType(ControlType.shock),
6666
label: 'Devices'),
@@ -199,7 +199,7 @@ class ScreenSelectorScreenState extends State<ScreenSelectorScreen> {
199199
String action = parts[2];
200200
String code = parts[3];
201201
if(action == "sharelink") {
202-
// openshock://sharelink/code?name=name&server=server
202+
// openshock://sharelink/<code>?name=<name>&server=<server>
203203
print("Sharelink url received");
204204
print("Url: $url");
205205

@@ -245,8 +245,9 @@ class ScreenSelectorScreenState extends State<ScreenSelectorScreen> {
245245
],
246246
);
247247
});
248-
}
248+
}
249249
else if (action == "sharecode") {
250+
// openshock://sharecode/<code>
250251
showDialog(
251252
context: context,
252253
builder: (context) {
@@ -262,7 +263,7 @@ class ScreenSelectorScreenState extends State<ScreenSelectorScreen> {
262263
child: Text("Close")),
263264
TextButton(
264265
onPressed: () async {
265-
if (await ShockerScreen.redeemShareCode(
266+
if (await ShockerScreen.redeemShareCodeOrInvite(
266267
code, context, manager)) {
267268
Navigator.of(context).pop();
268269
manager.reloadAllMethod!();

lib/screens/settings/login_popup.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'dart:io';
22

33
import 'package:cloudflare_turnstile/cloudflare_turnstile.dart';
44
import 'package:flutter/material.dart';
5+
import 'package:shock_alarm_app/components/predefined_spacing.dart';
56
import 'package:shock_alarm_app/dialogs/error_dialog.dart';
67
import 'package:shock_alarm_app/dialogs/loading_dialog.dart';
78
import 'package:shock_alarm_app/services/alarm_list_manager.dart';
@@ -73,15 +74,15 @@ class _LoginPopupState extends State<LoginPopup> {
7374
controller: widget.passwordController,
7475
autofillHints: [AutofillHints.password],
7576
),
76-
if(widget.backendInfo != null && useTurnstile) CloudFlareTurnstile(
77+
if(widget.backendInfo != null && useTurnstile) ...[Padding(padding: PredefinedSpacing.paddingMedium()) ,CloudFlareTurnstile(
7778
siteKey: widget.backendInfo!.turnstileSiteKey!, //Change with your site key
7879
baseUrl: widget.backendInfo!.frontendUrl,
7980
mode: TurnstileMode.nonInteractive,
8081
onTokenRecived: (token) {
8182
widget.turnstileToken = token;
8283
},
8384
onTokenExpired: reloadBackendData,
84-
),
85+
)],
8586
],
8687
))
8788
],

lib/screens/shares/shares.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class _SharesScreenState extends State<SharesScreen> {
7272
TextButton(
7373
onPressed: () async {
7474
LoadingDialog.show("Creating share");
75+
limits.validate();
7576

7677
String? error = await OpenShockClient()
7778
.addShare(shocker, limits, manager);

lib/screens/shockers/grouped/grouped_shocker_selector.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,18 +192,18 @@ class ShockerChipState extends State<ShockerChip> {
192192
actions.add(GestureDetector(
193193
onTap: () {
194194
Navigator.of(context).pop();
195-
a.onClick(manager, shocker, context, manager.reloadAllMethod!);
195+
a.onClick(manager, [shocker], context, manager.reloadAllMethod!);
196196
},
197197
child: Row(
198+
spacing: 5,
199+
mainAxisSize: MainAxisSize.min,
198200
children: [
199201
a.icon,
200202
Text(
201203
a.name,
202204
style: t!.textTheme.titleLarge,
203205
)
204206
],
205-
spacing: 5,
206-
mainAxisSize: MainAxisSize.min,
207207
),
208208
));
209209
}

lib/screens/shockers/grouped/grouped_shockers.dart

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -222,14 +222,13 @@ class _GroupedShockerScreenState extends State<GroupedShockerScreen> {
222222
iconColor: t.colorScheme.onSurfaceVariant,
223223
itemBuilder: (context) {
224224
return [
225-
if (AlarmListManager.getInstance().selectedShockers.length == 1)
226-
for (ShockerAction a in actions)
227-
PopupMenuItem(
228-
value: a.name,
229-
child: Row(
230-
spacing: 10,
231-
children: [a.icon, Text(a.name)],
232-
)),
225+
for (ShockerAction a in actions)
226+
if (AlarmListManager.getInstance().selectedShockers.length == 1 || a.allowMultipleShockers) PopupMenuItem(
227+
value: a.name,
228+
child: Row(
229+
spacing: 10,
230+
children: [a.icon, Text(a.name)],
231+
)),
233232
PopupMenuItem(
234233
value: "live",
235234
child: Row(
@@ -244,11 +243,14 @@ class _GroupedShockerScreenState extends State<GroupedShockerScreen> {
244243
];
245244
},
246245
onSelected: (String value) {
247-
Shocker shocker = AlarmListManager.getInstance().shockers.firstWhere(
248-
(x) => x.id == AlarmListManager.getInstance().selectedShockers[0]);
246+
List<Shocker> shockers = [];
247+
for(String id in AlarmListManager.getInstance().selectedShockers) {
248+
shockers.add(AlarmListManager.getInstance().shockers.firstWhere(
249+
(x) => x.id == id));
250+
}
249251
for (ShockerAction a in actions) {
250252
if (a.name == value) {
251-
a.onClick(AlarmListManager.getInstance(), shocker, context, onRebuild);
253+
a.onClick(AlarmListManager.getInstance(), shockers, context, onRebuild);
252254
return;
253255
}
254256
}

lib/screens/shockers/individual/shockers.dart

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ class ShockerScreen extends StatefulWidget {
3838
builder: (context) {
3939
TextEditingController codeController = TextEditingController();
4040
return AlertDialog.adaptive(
41-
title: Text("Redeem share code"),
41+
title: Text("Claim invite or share code"),
4242
content: SingleChildScrollView(
4343
child: Column(
4444
children: <Widget>[
4545
TextField(
4646
controller: codeController,
47-
decoration: InputDecoration(labelText: "Share code"),
47+
decoration: InputDecoration(labelText: "invite or share code"),
4848
)
4949
],
5050
),
@@ -63,23 +63,24 @@ class ShockerScreen extends StatefulWidget {
6363
"Invalid code", "The code cannot be empty");
6464
return;
6565
}
66-
if (await redeemShareCode(code, context, manager)) {
66+
if (await redeemShareCodeOrInvite(code, context, manager)) {
6767
Navigator.of(context).pop();
68+
InfoDialog.show("Shares active", "You can now control the shockers.");
6869

6970
await AlarmListManager.getInstance().updateShockerStore();
7071
reloadState();
7172
}
7273
},
73-
child: Text("Redeem"))
74+
child: Text("Claim"))
7475
],
7576
);
7677
});
7778
}
7879

79-
static Future<bool> redeemShareCode(
80+
static Future<bool> redeemShareCodeOrInvite(
8081
String code, BuildContext context, AlarmListManager manager) async {
81-
LoadingDialog.show("Redeeming code");
82-
String? error = await manager.redeemShareCode(code);
82+
LoadingDialog.show("Claiming code");
83+
String? error = await manager.redeemShareCodeOrInvite(code);
8384
if (error != null) {
8485
Navigator.of(context).pop();
8586
ErrorDialog.show("Error", error);
@@ -227,7 +228,7 @@ class ShockerScreen extends StatefulWidget {
227228
Navigator.of(context).pop();
228229
startRedeemShareCode(manager, context, reloadState);
229230
},
230-
child: Text("Redeem share code")),
231+
child: Text("Claim invite")),
231232
TextButton(
232233
onPressed: () async {
233234
await startPairShocker(manager, context, reloadState);

0 commit comments

Comments
 (0)