Skip to content

Commit d1a316b

Browse files
authored
Split settings up into multiple requests to stop reset accidents (#21)
* Split settings up into multiple requests to stop mismatch clients resetting everything * updated sessions command for cleaner output (no multi day) * Fixing clippy errors
1 parent bc83298 commit d1a316b

File tree

17 files changed

+2661
-976
lines changed

17 files changed

+2661
-976
lines changed

client/lib/generated/api/settings.pb.dart

Lines changed: 857 additions & 409 deletions
Large diffs are not rendered by default.

client/lib/generated/api/settings.pbgrpc.dart

Lines changed: 220 additions & 42 deletions
Large diffs are not rendered by default.

client/lib/generated/api/settings.pbjson.dart

Lines changed: 389 additions & 153 deletions
Large diffs are not rendered by default.

client/lib/helpers/settings_helper.dart

Lines changed: 0 additions & 55 deletions
This file was deleted.

client/lib/providers/branding_provider.g.dart

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/lib/views/setup/branding_setup.dart

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import 'package:flutter_hooks/flutter_hooks.dart';
44
import 'package:hooks_riverpod/hooks_riverpod.dart';
55
import 'package:time_keeper/generated/api/settings.pbgrpc.dart';
66
import 'package:time_keeper/helpers/grpc_call_wrapper.dart';
7-
import 'package:time_keeper/helpers/settings_helper.dart' as settings_helper;
87
import 'package:time_keeper/providers/branding_provider.dart';
98
import 'package:time_keeper/providers/settings_provider.dart';
109
import 'package:time_keeper/utils/grpc_result.dart';
@@ -75,22 +74,20 @@ class BrandingSetupTab extends HookConsumerWidget {
7574
}
7675

7776
final normalizedHex = _colorToHex(color);
78-
final res = await settings_helper.updateSettings(
79-
ref.read(settingsServiceProvider),
80-
(req) {
81-
if (isPrimary) {
82-
req.primaryColor = normalizedHex;
83-
} else {
84-
req.secondaryColor = normalizedHex;
85-
}
86-
},
77+
final res = await callGrpcEndpoint(
78+
() => ref
79+
.read(settingsServiceProvider)
80+
.updateBrandingSettings(
81+
isPrimary
82+
? UpdateBrandingSettingsRequest(primaryColor: normalizedHex)
83+
: UpdateBrandingSettingsRequest(
84+
secondaryColor: normalizedHex,
85+
),
86+
),
8787
);
8888

8989
if (context.mounted) {
9090
PopupDialog.fromGrpcStatus(result: res).show(context);
91-
if (res is GrpcSuccess) {
92-
await ref.read(brandingProvider.notifier).refresh();
93-
}
9491
}
9592
}
9693

client/lib/views/setup/integrations_setup.dart

Lines changed: 84 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
66
import 'package:time_keeper/generated/api/settings.pbgrpc.dart';
77
import 'package:time_keeper/generated/db/db.pbenum.dart';
88
import 'package:time_keeper/helpers/grpc_call_wrapper.dart';
9-
import 'package:time_keeper/helpers/settings_helper.dart' as settings_helper;
109
import 'package:time_keeper/providers/settings_provider.dart';
1110
import 'package:time_keeper/utils/grpc_result.dart';
1211
import 'package:time_keeper/views/setup/common/setting_row.dart';
@@ -87,39 +86,72 @@ class IntegrationsSetupTab extends HookConsumerWidget {
8786
return null;
8887
}, const []);
8988

90-
Future<void> updateDiscordSettings() async {
91-
final res = await settings_helper.updateSettings(
92-
ref.read(settingsServiceProvider),
93-
(req) {
94-
req
95-
..discordEnabled = discordEnabled.value
96-
..discordBotToken = botTokenController.text
97-
..discordGuildId = guildIdController.text
98-
..discordAnnouncementChannelId =
99-
channelAnnouncementIdController.text
100-
..discordNotificationChannelId =
101-
channelNotificationIdController.text
102-
..discordStartReminderMins = Int64(
103-
int.tryParse(startReminderMinsController.text) ?? 1440,
104-
)
105-
..discordEndReminderMins = Int64(
106-
int.tryParse(endReminderMinsController.text) ?? 15,
107-
)
108-
..discordStartReminderMessage = startReminderMessageController.text
109-
..discordEndReminderMessage = endReminderMessageController.text
110-
..discordRsvpReactionsEnabled = rsvpReactionsEnabled.value
111-
..discordSelfLinkEnabled = selfLinkEnabled.value
112-
..discordNameSyncEnabled = nameSyncEnabled.value
113-
..discordOvertimeDmEnabled = overtimeDmEnabled.value
114-
..discordOvertimeDmMins = Int64(
115-
int.tryParse(overtimeDmMinsController.text) ?? 10,
116-
)
117-
..discordOvertimeDmMessage = overtimeDmMessageController.text
118-
..discordAutoCheckoutDmEnabled = autoCheckoutDmEnabled.value
119-
..discordAutoCheckoutDmMessage =
120-
autoCheckoutDmMessageController.text
121-
..discordCheckoutEnabled = checkoutEnabled.value;
122-
},
89+
Future<void> updateDiscordCore() async {
90+
final res = await callGrpcEndpoint(
91+
() => ref
92+
.read(settingsServiceProvider)
93+
.updateDiscordCoreSettings(
94+
UpdateDiscordCoreSettingsRequest(
95+
discordEnabled: discordEnabled.value,
96+
discordBotToken: botTokenController.text,
97+
discordGuildId: guildIdController.text,
98+
discordAnnouncementChannelId:
99+
channelAnnouncementIdController.text,
100+
discordNotificationChannelId:
101+
channelNotificationIdController.text,
102+
),
103+
),
104+
);
105+
106+
if (context.mounted) {
107+
PopupDialog.fromGrpcStatus(result: res).show(context);
108+
}
109+
}
110+
111+
Future<void> updateDiscordReminder() async {
112+
final res = await callGrpcEndpoint(
113+
() => ref
114+
.read(settingsServiceProvider)
115+
.updateDiscordReminderSettings(
116+
UpdateDiscordReminderSettingsRequest(
117+
discordStartReminderMins: Int64(
118+
int.tryParse(startReminderMinsController.text) ?? 1440,
119+
),
120+
discordEndReminderMins: Int64(
121+
int.tryParse(endReminderMinsController.text) ?? 15,
122+
),
123+
discordStartReminderMessage:
124+
startReminderMessageController.text,
125+
discordEndReminderMessage: endReminderMessageController.text,
126+
),
127+
),
128+
);
129+
130+
if (context.mounted) {
131+
PopupDialog.fromGrpcStatus(result: res).show(context);
132+
}
133+
}
134+
135+
Future<void> updateDiscordBehavior() async {
136+
final res = await callGrpcEndpoint(
137+
() => ref
138+
.read(settingsServiceProvider)
139+
.updateDiscordBehaviorSettings(
140+
UpdateDiscordBehaviorSettingsRequest(
141+
discordRsvpReactionsEnabled: rsvpReactionsEnabled.value,
142+
discordSelfLinkEnabled: selfLinkEnabled.value,
143+
discordNameSyncEnabled: nameSyncEnabled.value,
144+
discordOvertimeDmEnabled: overtimeDmEnabled.value,
145+
discordOvertimeDmMins: Int64(
146+
int.tryParse(overtimeDmMinsController.text) ?? 10,
147+
),
148+
discordOvertimeDmMessage: overtimeDmMessageController.text,
149+
discordAutoCheckoutDmEnabled: autoCheckoutDmEnabled.value,
150+
discordAutoCheckoutDmMessage:
151+
autoCheckoutDmMessageController.text,
152+
discordCheckoutEnabled: checkoutEnabled.value,
153+
),
154+
),
123155
);
124156

125157
if (context.mounted) {
@@ -197,7 +229,7 @@ class IntegrationsSetupTab extends HookConsumerWidget {
197229
value: discordEnabled.value,
198230
onChanged: (value) {
199231
discordEnabled.value = value;
200-
updateDiscordSettings();
232+
updateDiscordCore();
201233
},
202234
),
203235
const SizedBox(width: 8),
@@ -213,7 +245,7 @@ class IntegrationsSetupTab extends HookConsumerWidget {
213245
controller: botTokenController,
214246
hintText: 'Enter bot token',
215247
obscureText: true,
216-
onUpdate: updateDiscordSettings,
248+
onUpdate: updateDiscordCore,
217249
),
218250
const SizedBox(height: 24),
219251
TextFieldSetting(
@@ -222,7 +254,7 @@ class IntegrationsSetupTab extends HookConsumerWidget {
222254
'The ID of your Discord server (Enable Developer Mode, right-click server, Copy Server ID)',
223255
controller: guildIdController,
224256
hintText: 'Enter server ID',
225-
onUpdate: updateDiscordSettings,
257+
onUpdate: updateDiscordCore,
226258
),
227259
const SizedBox(height: 24),
228260
TextFieldSetting(
@@ -231,7 +263,7 @@ class IntegrationsSetupTab extends HookConsumerWidget {
231263
'The ID of the channel where the bot will post session reminders (right-click channel, Copy Channel ID)',
232264
controller: channelAnnouncementIdController,
233265
hintText: 'Enter channel ID',
234-
onUpdate: updateDiscordSettings,
266+
onUpdate: updateDiscordCore,
235267
),
236268
const SizedBox(height: 24),
237269
TextFieldSetting(
@@ -240,7 +272,7 @@ class IntegrationsSetupTab extends HookConsumerWidget {
240272
'The ID of the channel where the bot will post notifications and user directed messages (right-click channel, Copy Channel ID)',
241273
controller: channelNotificationIdController,
242274
hintText: 'Enter channel ID',
243-
onUpdate: updateDiscordSettings,
275+
onUpdate: updateDiscordCore,
244276
),
245277
const SizedBox(height: 32),
246278
const Divider(),
@@ -266,7 +298,7 @@ class IntegrationsSetupTab extends HookConsumerWidget {
266298
hintText: '1440',
267299
keyboardType: TextInputType.number,
268300
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
269-
onUpdate: updateDiscordSettings,
301+
onUpdate: updateDiscordReminder,
270302
),
271303
const SizedBox(height: 24),
272304
TextFieldSetting(
@@ -277,7 +309,7 @@ class IntegrationsSetupTab extends HookConsumerWidget {
277309
hintText:
278310
'@here Session on {date} from {start_time} to {end_time} @ {location} starting in ~{mins} minutes!',
279311
multiline: true,
280-
onUpdate: updateDiscordSettings,
312+
onUpdate: updateDiscordReminder,
281313
),
282314
const SizedBox(height: 24),
283315
TextFieldSetting(
@@ -288,7 +320,7 @@ class IntegrationsSetupTab extends HookConsumerWidget {
288320
hintText: '15',
289321
keyboardType: TextInputType.number,
290322
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
291-
onUpdate: updateDiscordSettings,
323+
onUpdate: updateDiscordReminder,
292324
),
293325
const SizedBox(height: 24),
294326
TextFieldSetting(
@@ -299,7 +331,7 @@ class IntegrationsSetupTab extends HookConsumerWidget {
299331
hintText:
300332
'@here Session at {location} is ending in ~{mins} minutes \u2014 don\'t forget to sign out!',
301333
multiline: true,
302-
onUpdate: updateDiscordSettings,
334+
onUpdate: updateDiscordReminder,
303335
),
304336
const SizedBox(height: 24),
305337
SettingRow(
@@ -313,7 +345,7 @@ class IntegrationsSetupTab extends HookConsumerWidget {
313345
value: rsvpReactionsEnabled.value,
314346
onChanged: (value) {
315347
rsvpReactionsEnabled.value = value;
316-
updateDiscordSettings();
348+
updateDiscordBehavior();
317349
},
318350
),
319351
const SizedBox(width: 8),
@@ -332,7 +364,7 @@ class IntegrationsSetupTab extends HookConsumerWidget {
332364
value: selfLinkEnabled.value,
333365
onChanged: (value) {
334366
selfLinkEnabled.value = value;
335-
updateDiscordSettings();
367+
updateDiscordBehavior();
336368
},
337369
),
338370
const SizedBox(width: 8),
@@ -351,7 +383,7 @@ class IntegrationsSetupTab extends HookConsumerWidget {
351383
value: nameSyncEnabled.value,
352384
onChanged: (value) {
353385
nameSyncEnabled.value = value;
354-
updateDiscordSettings();
386+
updateDiscordBehavior();
355387
},
356388
),
357389
const SizedBox(width: 8),
@@ -371,7 +403,7 @@ class IntegrationsSetupTab extends HookConsumerWidget {
371403
value: checkoutEnabled.value,
372404
onChanged: (value) {
373405
checkoutEnabled.value = value;
374-
updateDiscordSettings();
406+
updateDiscordBehavior();
375407
},
376408
),
377409
const SizedBox(width: 8),
@@ -406,7 +438,7 @@ class IntegrationsSetupTab extends HookConsumerWidget {
406438
value: overtimeDmEnabled.value,
407439
onChanged: (value) {
408440
overtimeDmEnabled.value = value;
409-
updateDiscordSettings();
441+
updateDiscordBehavior();
410442
},
411443
),
412444
const SizedBox(width: 8),
@@ -423,7 +455,7 @@ class IntegrationsSetupTab extends HookConsumerWidget {
423455
hintText: '10',
424456
keyboardType: TextInputType.number,
425457
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
426-
onUpdate: updateDiscordSettings,
458+
onUpdate: updateDiscordBehavior,
427459
),
428460
const SizedBox(height: 24),
429461
TextFieldSetting(
@@ -434,7 +466,7 @@ class IntegrationsSetupTab extends HookConsumerWidget {
434466
hintText:
435467
'Hey {username}, you\'re now in overtime for the session at {location}. The session ended at {end_time}. Don\'t forget to check out!',
436468
multiline: true,
437-
onUpdate: updateDiscordSettings,
469+
onUpdate: updateDiscordBehavior,
438470
),
439471
const SizedBox(height: 24),
440472
SettingRow(
@@ -447,7 +479,7 @@ class IntegrationsSetupTab extends HookConsumerWidget {
447479
value: autoCheckoutDmEnabled.value,
448480
onChanged: (value) {
449481
autoCheckoutDmEnabled.value = value;
450-
updateDiscordSettings();
482+
updateDiscordBehavior();
451483
},
452484
),
453485
const SizedBox(width: 8),
@@ -464,7 +496,7 @@ class IntegrationsSetupTab extends HookConsumerWidget {
464496
hintText:
465497
'Hey {username}, you\'ve been auto-checked-out from the session at {location} (ended at {end_time}) because a new session is starting soon.',
466498
multiline: true,
467-
onUpdate: updateDiscordSettings,
499+
onUpdate: updateDiscordBehavior,
468500
),
469501
const SizedBox(height: 32),
470502
const Divider(),

0 commit comments

Comments
 (0)