kasy-cli 1.38.0 → 1.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/scaffold/CHANGELOG.json +14 -0
- package/lib/scaffold/backends/api/patch/README.md +15 -0
- package/lib/scaffold/backends/api/patch/lib/features/notifications/api/device_api.dart +11 -6
- package/lib/scaffold/backends/api/patch/lib/features/settings/ui/components/admin/admin_users_api.dart +9 -1
- package/lib/scaffold/backends/api/pubspec.yaml.tpl +1 -0
- package/lib/scaffold/backends/patch-base-hashes.json +6 -6
- package/lib/scaffold/backends/supabase/edge-functions/admin-list-users/index.ts +3 -1
- package/lib/scaffold/backends/supabase/edge-functions/send-push-notification/index.ts +3 -0
- package/lib/scaffold/backends/supabase/migrations/20240101000012_welcome_decouple_from_push.sql +62 -0
- package/lib/scaffold/backends/supabase/patch/lib/features/notifications/api/device_api.dart +11 -6
- package/lib/scaffold/backends/supabase/patch/lib/features/settings/ui/components/admin/admin_users_api.dart +7 -0
- package/lib/scaffold/backends/supabase/pubspec.yaml.tpl +1 -0
- package/lib/scaffold/shared/generator-utils.js +12 -6
- package/package.json +1 -1
- package/templates/firebase/.firebase/hosting.YnVpbGQvd2Vi.cache +23 -23
- package/templates/firebase/DESIGN_SYSTEM.md +22 -8
- package/templates/firebase/assets/icons/apple_black.svg +3 -0
- package/templates/firebase/assets/icons/apple_white.svg +4 -0
- package/templates/firebase/assets/icons/facebook.svg +49 -0
- package/templates/firebase/assets/icons/google.svg +1 -0
- package/templates/firebase/functions/src/admin/functions.ts +2 -0
- package/templates/firebase/functions/src/authentication/functions.ts +13 -7
- package/templates/firebase/functions/src/notifications/triggers.ts +6 -2
- package/templates/firebase/lib/components/components.dart +1 -1
- package/templates/firebase/lib/components/kasy_app_bar.dart +314 -14
- package/templates/firebase/lib/components/kasy_card.dart +4 -0
- package/templates/firebase/lib/components/kasy_drop_down.dart +584 -0
- package/templates/firebase/lib/components/kasy_sidebar.dart +18 -6
- package/templates/firebase/lib/components/kasy_tabs.dart +31 -10
- package/templates/firebase/lib/components/kasy_text_field.dart +29 -7
- package/templates/firebase/lib/core/bottom_menu/bottom_menu.dart +27 -18
- package/templates/firebase/lib/core/bottom_menu/web_content_wrapper.dart +12 -10
- package/templates/firebase/lib/core/chrome/app_bar_config.dart +214 -0
- package/templates/firebase/lib/core/chrome/app_bar_scope.dart +102 -0
- package/templates/firebase/lib/core/data/api/user_api.dart +11 -0
- package/templates/firebase/lib/core/dev_inspector/dev_inspector_service.dart +55 -15
- package/templates/firebase/lib/core/rating/widgets/review_popup.dart +18 -35
- package/templates/firebase/lib/core/shared_preferences/shared_preferences.dart +11 -0
- package/templates/firebase/lib/core/states/logout_action.dart +11 -1
- package/templates/firebase/lib/core/states/user_state_notifier.dart +28 -1
- package/templates/firebase/lib/core/theme/texts.dart +21 -6
- package/templates/firebase/lib/core/theme/type_scale.dart +34 -15
- package/templates/firebase/lib/core/web_device_preview/web_device_preview.dart +51 -19
- package/templates/firebase/lib/core/web_viewport_scale.dart +64 -35
- package/templates/firebase/lib/core/widgets/kasy_pressable_depth.dart +14 -3
- package/templates/firebase/lib/features/ai_chat/ui/widgets/ai_chat_composer.dart +1 -1
- package/templates/firebase/lib/features/ai_chat/ui/widgets/ai_chat_conversation_view.dart +52 -35
- package/templates/firebase/lib/features/ai_chat/ui/widgets/ai_conversation_list.dart +1 -1
- package/templates/firebase/lib/features/ai_chat/ui/widgets/ai_conversation_tile.dart +18 -8
- package/templates/firebase/lib/features/authentication/ui/signin_page.dart +11 -61
- package/templates/firebase/lib/features/authentication/ui/signup_page.dart +11 -61
- package/templates/firebase/lib/features/authentication/ui/widgets/auth_card_scaffold.dart +7 -5
- package/templates/firebase/lib/features/authentication/ui/widgets/social_auth_tile.dart +83 -0
- package/templates/firebase/lib/features/feedbacks/ui/widgets/feature_card.dart +4 -4
- package/templates/firebase/lib/features/home/home_components_page.dart +253 -125
- package/templates/firebase/lib/features/home/home_components_preview_registry.dart +231 -57
- package/templates/firebase/lib/features/home/home_feed.dart +2 -2
- package/templates/firebase/lib/features/home/home_image_grid.dart +3 -3
- package/templates/firebase/lib/features/local_reminders/providers/reminder_notifier.dart +8 -1
- package/templates/firebase/lib/features/local_reminders/ui/reminder_page.dart +111 -57
- package/templates/firebase/lib/features/notifications/api/device_api.dart +11 -3
- package/templates/firebase/lib/features/notifications/ui/notifications_page.dart +16 -4
- package/templates/firebase/lib/features/notifications/ui/widgets/empty_notifications.dart +7 -56
- package/templates/firebase/lib/features/notifications/ui/widgets/notification_tile.dart +5 -5
- package/templates/firebase/lib/features/notifications/ui/widgets/push_permission_banner.dart +163 -0
- package/templates/firebase/lib/features/notifications/ui/widgets/web_notifications_bell.dart +2 -2
- package/templates/firebase/lib/features/onboarding/providers/onboarding_model.dart +9 -0
- package/templates/firebase/lib/features/onboarding/providers/onboarding_provider.dart +28 -0
- package/templates/firebase/lib/features/onboarding/ui/onboarding_page.dart +51 -12
- package/templates/firebase/lib/features/onboarding/ui/widgets/selectable_row_tile.dart +90 -32
- package/templates/firebase/lib/features/settings/settings_page.dart +53 -32
- package/templates/firebase/lib/features/settings/ui/components/admin/admin_page.dart +895 -111
- package/templates/firebase/lib/features/settings/ui/components/admin/admin_users_api.dart +7 -0
- package/templates/firebase/lib/features/settings/ui/components/admin/admin_users_tab.dart +445 -233
- package/templates/firebase/lib/features/settings/ui/components/admin/send_push_notification_page.dart +171 -41
- package/templates/firebase/lib/features/settings/ui/components/avatar_component.dart +1 -1
- package/templates/firebase/lib/features/settings/ui/components/delete_user_component.dart +9 -1
- package/templates/firebase/lib/features/settings/ui/components/language_switcher.dart +48 -47
- package/templates/firebase/lib/features/settings/ui/widgets/settings_bottom_sheet_option_tile.dart +21 -18
- package/templates/firebase/lib/features/settings/ui/widgets/settings_tile.dart +25 -10
- package/templates/firebase/lib/i18n/en.i18n.json +749 -712
- package/templates/firebase/lib/i18n/es.i18n.json +749 -712
- package/templates/firebase/lib/i18n/pt.i18n.json +749 -712
- package/templates/firebase/lib/main.dart +20 -7
- package/templates/firebase/lib/router.dart +32 -26
- package/templates/firebase/pubspec.yaml +2 -1
- package/templates/firebase/test/admin_shell_chrome_test.dart +11 -5
- package/templates/firebase/test/components/kasy_text_field_height_test.dart +77 -0
- package/templates/firebase/test/core/web_viewport_scale_test.dart +23 -16
- package/templates/firebase/tool/design_check.dart +9 -0
- package/templates/firebase/assets/icons/apple.png +0 -0
- package/templates/firebase/assets/icons/facebook.png +0 -0
- package/templates/firebase/assets/icons/google.png +0 -0
- package/templates/firebase/assets/icons/google_play_games.png +0 -0
- package/templates/firebase/lib/components/kasy_web_header.dart +0 -218
- package/templates/firebase/lib/core/chrome/web_header_scope.dart +0 -20
- package/templates/firebase/lib/features/authentication/ui/components/apple_signin.dart +0 -19
- package/templates/firebase/lib/features/authentication/ui/components/google_signin.dart +0 -32
- package/templates/firebase/lib/features/authentication/ui/widgets/round_signin.dart +0 -73
- package/templates/firebase/lib/features/feedbacks/ui/widgets/add_feature_button.dart +0 -66
- package/templates/firebase/lib/features/notifications/ui/components/notification_settings_sheet.dart +0 -179
- package/templates/firebase/lib/features/notifications/ui/components/push_notification_switcher.dart +0 -106
|
@@ -73,22 +73,10 @@ class _OnboardingSelectableRowGroupState
|
|
|
73
73
|
return Column(
|
|
74
74
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
75
75
|
children: [
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
_SelectableTileInk(
|
|
77
|
+
onTap: selectRow,
|
|
78
78
|
borderRadius: KasyRadius.lgBorderRadius,
|
|
79
|
-
child:
|
|
80
|
-
color: Colors.transparent,
|
|
81
|
-
borderRadius: KasyRadius.lgBorderRadius,
|
|
82
|
-
child: InkWell(
|
|
83
|
-
canRequestFocus: false,
|
|
84
|
-
borderRadius: KasyRadius.lgBorderRadius,
|
|
85
|
-
onTap: selectRow,
|
|
86
|
-
child: switch (hasOnSelectInfo && _selectedIndex == index) {
|
|
87
|
-
false => widget.options[index],
|
|
88
|
-
true => widget.options[index],
|
|
89
|
-
},
|
|
90
|
-
),
|
|
91
|
-
),
|
|
79
|
+
child: widget.options[index],
|
|
92
80
|
),
|
|
93
81
|
if (hasOnSelectInfo && _selectedIndex == index)
|
|
94
82
|
Padding(
|
|
@@ -150,23 +138,16 @@ class _OnboardingMultiSelectableRowGroupState
|
|
|
150
138
|
setState(() {});
|
|
151
139
|
}
|
|
152
140
|
|
|
153
|
-
return
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
child: SelectableRowTile(
|
|
164
|
-
title: option.title,
|
|
165
|
-
subtitle: option.subtitle,
|
|
166
|
-
selected: _selectedIndex.contains(index),
|
|
167
|
-
emoj: option.emoj,
|
|
168
|
-
),
|
|
169
|
-
),
|
|
141
|
+
return _SelectableTileInk(
|
|
142
|
+
onTap: toggleSelection,
|
|
143
|
+
// Match the tile's own lgBorderRadius so the hover veil and focus ring
|
|
144
|
+
// hug its shape (the old InkWell clipped at md, a mismatch).
|
|
145
|
+
borderRadius: KasyRadius.lgBorderRadius,
|
|
146
|
+
child: SelectableRowTile(
|
|
147
|
+
title: option.title,
|
|
148
|
+
subtitle: option.subtitle,
|
|
149
|
+
selected: _selectedIndex.contains(index),
|
|
150
|
+
emoj: option.emoj,
|
|
170
151
|
),
|
|
171
152
|
);
|
|
172
153
|
}).toList(),
|
|
@@ -338,6 +319,83 @@ class _SelectableRowTileState extends State<SelectableRowTile>
|
|
|
338
319
|
}
|
|
339
320
|
}
|
|
340
321
|
|
|
322
|
+
/// Adds a web hover highlight, a keyboard focus ring and a click cursor on top
|
|
323
|
+
/// of an opaque selectable tile — no Material ripple.
|
|
324
|
+
///
|
|
325
|
+
/// Because the tile paints its own background, the hover veil is layered ABOVE
|
|
326
|
+
/// the child (clipped to [borderRadius]), the same approach the tappable
|
|
327
|
+
/// [KasyCard] uses; a [KasyHover]-style overlay would sit behind the opaque
|
|
328
|
+
/// surface and never show. The child keeps its own semantics (the option title),
|
|
329
|
+
/// so screen readers still announce the option, not a generic label.
|
|
330
|
+
class _SelectableTileInk extends StatefulWidget {
|
|
331
|
+
const _SelectableTileInk({
|
|
332
|
+
required this.onTap,
|
|
333
|
+
required this.borderRadius,
|
|
334
|
+
required this.child,
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
final VoidCallback onTap;
|
|
338
|
+
final BorderRadius borderRadius;
|
|
339
|
+
final Widget child;
|
|
340
|
+
|
|
341
|
+
@override
|
|
342
|
+
State<_SelectableTileInk> createState() => _SelectableTileInkState();
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
class _SelectableTileInkState extends State<_SelectableTileInk> {
|
|
346
|
+
bool _hovered = false;
|
|
347
|
+
bool _pressed = false;
|
|
348
|
+
|
|
349
|
+
@override
|
|
350
|
+
Widget build(BuildContext context) {
|
|
351
|
+
final bool dark = context.isDark;
|
|
352
|
+
// Subtle tint that fades in on hover (web/desktop) and deepens briefly on
|
|
353
|
+
// press; invisible at rest. On touch _hovered never becomes true.
|
|
354
|
+
final double alpha = _pressed
|
|
355
|
+
? (dark ? 0.10 : 0.06)
|
|
356
|
+
: (_hovered ? (dark ? 0.06 : 0.04) : 0.0);
|
|
357
|
+
|
|
358
|
+
final Widget veiled = Stack(
|
|
359
|
+
children: <Widget>[
|
|
360
|
+
widget.child,
|
|
361
|
+
Positioned.fill(
|
|
362
|
+
child: IgnorePointer(
|
|
363
|
+
child: AnimatedContainer(
|
|
364
|
+
duration: const Duration(milliseconds: 120),
|
|
365
|
+
curve: Curves.easeOut,
|
|
366
|
+
decoration: BoxDecoration(
|
|
367
|
+
color: context.colors.onSurface.withValues(alpha: alpha),
|
|
368
|
+
borderRadius: widget.borderRadius,
|
|
369
|
+
),
|
|
370
|
+
),
|
|
371
|
+
),
|
|
372
|
+
),
|
|
373
|
+
],
|
|
374
|
+
);
|
|
375
|
+
|
|
376
|
+
return KasyFocusRing(
|
|
377
|
+
onActivate: widget.onTap,
|
|
378
|
+
borderRadius: widget.borderRadius,
|
|
379
|
+
child: MouseRegion(
|
|
380
|
+
cursor: SystemMouseCursors.click,
|
|
381
|
+
onEnter: (_) => setState(() => _hovered = true),
|
|
382
|
+
onExit: (_) => setState(() {
|
|
383
|
+
_hovered = false;
|
|
384
|
+
_pressed = false;
|
|
385
|
+
}),
|
|
386
|
+
child: GestureDetector(
|
|
387
|
+
behavior: HitTestBehavior.opaque,
|
|
388
|
+
onTap: widget.onTap,
|
|
389
|
+
onTapDown: (_) => setState(() => _pressed = true),
|
|
390
|
+
onTapUp: (_) => setState(() => _pressed = false),
|
|
391
|
+
onTapCancel: () => setState(() => _pressed = false),
|
|
392
|
+
child: veiled,
|
|
393
|
+
),
|
|
394
|
+
),
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
341
399
|
class RoundRadioBox extends StatelessWidget {
|
|
342
400
|
final Color bgColor;
|
|
343
401
|
final Color borderColor;
|
|
@@ -15,7 +15,6 @@ import 'package:kasy_kit/core/states/logout_action.dart';
|
|
|
15
15
|
import 'package:kasy_kit/core/states/user_state_notifier.dart';
|
|
16
16
|
import 'package:kasy_kit/core/theme/theme.dart';
|
|
17
17
|
import 'package:kasy_kit/core/widgets/kasy_hover.dart';
|
|
18
|
-
import 'package:kasy_kit/core/widgets/responsive_layout.dart';
|
|
19
18
|
import 'package:kasy_kit/features/authentication/repositories/authentication_repository.dart';
|
|
20
19
|
import 'package:kasy_kit/features/authentication/repositories/exceptions/authentication_exceptions.dart';
|
|
21
20
|
import 'package:kasy_kit/features/settings/ui/components/avatar_component.dart';
|
|
@@ -153,6 +152,7 @@ class SettingsPage extends ConsumerWidget {
|
|
|
153
152
|
context,
|
|
154
153
|
ref,
|
|
155
154
|
isAuthenticated: isAuthenticated,
|
|
155
|
+
hasAccount: userId != null,
|
|
156
156
|
isAdmin: user.isAdmin,
|
|
157
157
|
isPhone: isPhone,
|
|
158
158
|
),
|
|
@@ -182,6 +182,7 @@ class SettingsPage extends ConsumerWidget {
|
|
|
182
182
|
BuildContext context,
|
|
183
183
|
WidgetRef ref, {
|
|
184
184
|
required bool isAuthenticated,
|
|
185
|
+
required bool hasAccount,
|
|
185
186
|
required bool isAdmin,
|
|
186
187
|
required bool isPhone,
|
|
187
188
|
}) {
|
|
@@ -215,7 +216,7 @@ class SettingsPage extends ConsumerWidget {
|
|
|
215
216
|
padding: const EdgeInsets.only(left: KasySpacing.xs),
|
|
216
217
|
child: Text(
|
|
217
218
|
t.admin_console.settings_entry.caption,
|
|
218
|
-
style: context.textTheme.
|
|
219
|
+
style: context.textTheme.bodyMedium?.copyWith(
|
|
219
220
|
color: context.colors.muted,
|
|
220
221
|
),
|
|
221
222
|
),
|
|
@@ -226,8 +227,13 @@ class SettingsPage extends ConsumerWidget {
|
|
|
226
227
|
_settingsGroup([_LogoutRow(onTap: () => confirmLogout(context, ref))]),
|
|
227
228
|
const SizedBox(height: KasySpacing.xl),
|
|
228
229
|
],
|
|
229
|
-
|
|
230
|
-
|
|
230
|
+
// Only offer account deletion when there's a real backend account behind
|
|
231
|
+
// it. A guest with no identity has nothing to delete, so the button would
|
|
232
|
+
// just dead-end in an error and trap them on this screen.
|
|
233
|
+
if (hasAccount) ...[
|
|
234
|
+
const DeleteUserButton(),
|
|
235
|
+
const SizedBox(height: KasySpacing.xl),
|
|
236
|
+
],
|
|
231
237
|
const _VersionLabel(),
|
|
232
238
|
];
|
|
233
239
|
}
|
|
@@ -435,10 +441,9 @@ class SettingsContainer extends StatelessWidget {
|
|
|
435
441
|
Widget build(BuildContext context) {
|
|
436
442
|
return KasyCard(
|
|
437
443
|
borderRadius: BorderRadius.circular(KasyRadius.lg),
|
|
438
|
-
padding:
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
),
|
|
444
|
+
// No card padding: each row carries its own inset so the press/hover
|
|
445
|
+
// highlight spans the full card width (clipped to the rounded corners),
|
|
446
|
+
// instead of a pill floating inside a white margin.
|
|
442
447
|
child: child,
|
|
443
448
|
);
|
|
444
449
|
}
|
|
@@ -460,7 +465,7 @@ class _FieldRow extends StatelessWidget {
|
|
|
460
465
|
children: [
|
|
461
466
|
Text(
|
|
462
467
|
label,
|
|
463
|
-
style: context.
|
|
468
|
+
style: context.kasyTextTheme.listRowTitle.copyWith(
|
|
464
469
|
color: context.colors.onSurface,
|
|
465
470
|
),
|
|
466
471
|
),
|
|
@@ -471,7 +476,7 @@ class _FieldRow extends StatelessWidget {
|
|
|
471
476
|
textAlign: TextAlign.right,
|
|
472
477
|
maxLines: 1,
|
|
473
478
|
overflow: TextOverflow.ellipsis,
|
|
474
|
-
style: context.
|
|
479
|
+
style: context.kasyTextTheme.listRowValue.copyWith(
|
|
475
480
|
color: context.colors.muted,
|
|
476
481
|
),
|
|
477
482
|
),
|
|
@@ -484,18 +489,22 @@ class _FieldRow extends StatelessWidget {
|
|
|
484
489
|
);
|
|
485
490
|
if (onTap == null) {
|
|
486
491
|
return Padding(
|
|
487
|
-
padding: const EdgeInsets.symmetric(
|
|
492
|
+
padding: const EdgeInsets.symmetric(
|
|
493
|
+
horizontal: KasySpacing.md,
|
|
494
|
+
vertical: KasySpacing.smd,
|
|
495
|
+
),
|
|
488
496
|
child: row,
|
|
489
497
|
);
|
|
490
498
|
}
|
|
491
499
|
return KasyHover(
|
|
492
500
|
onTap: onTap!,
|
|
493
|
-
hoverEnabled: false,
|
|
494
|
-
pressEnabled: false,
|
|
495
501
|
focusable: true,
|
|
496
|
-
|
|
502
|
+
// Rectangular highlight (default): the card clips the rounded ends.
|
|
497
503
|
semanticLabel: label,
|
|
498
|
-
padding: const EdgeInsets.symmetric(
|
|
504
|
+
padding: const EdgeInsets.symmetric(
|
|
505
|
+
horizontal: KasySpacing.md,
|
|
506
|
+
vertical: KasySpacing.smd,
|
|
507
|
+
),
|
|
499
508
|
child: row,
|
|
500
509
|
);
|
|
501
510
|
}
|
|
@@ -512,7 +521,7 @@ class _AccountAvatarHeader extends StatelessWidget {
|
|
|
512
521
|
return const Center(
|
|
513
522
|
child: Padding(
|
|
514
523
|
padding: EdgeInsets.only(top: KasySpacing.sm),
|
|
515
|
-
child: EditableUserAvatar(diameter:
|
|
524
|
+
child: EditableUserAvatar(diameter: 80),
|
|
516
525
|
),
|
|
517
526
|
);
|
|
518
527
|
}
|
|
@@ -606,9 +615,10 @@ class _SettingsDesktopViewState extends ConsumerState<_SettingsDesktopView> {
|
|
|
606
615
|
isPhone: widget.isPhone,
|
|
607
616
|
);
|
|
608
617
|
|
|
609
|
-
const double navWidth =
|
|
610
|
-
const double gap = KasySpacing.
|
|
611
|
-
const double
|
|
618
|
+
const double navWidth = 220;
|
|
619
|
+
const double gap = KasySpacing.xl;
|
|
620
|
+
const double detailWidth = 560;
|
|
621
|
+
const double groupWidth = navWidth + gap + detailWidth;
|
|
612
622
|
|
|
613
623
|
return Center(
|
|
614
624
|
child: Padding(
|
|
@@ -641,7 +651,7 @@ class _SettingsDesktopViewState extends ConsumerState<_SettingsDesktopView> {
|
|
|
641
651
|
),
|
|
642
652
|
const SizedBox(width: gap),
|
|
643
653
|
if (fits)
|
|
644
|
-
SizedBox(width:
|
|
654
|
+
SizedBox(width: detailWidth, child: pane)
|
|
645
655
|
else
|
|
646
656
|
Expanded(child: pane),
|
|
647
657
|
],
|
|
@@ -682,7 +692,7 @@ class _DesktopNav extends StatelessWidget {
|
|
|
682
692
|
),
|
|
683
693
|
child: Row(
|
|
684
694
|
children: [
|
|
685
|
-
const EditableUserAvatar(diameter:
|
|
695
|
+
const EditableUserAvatar(diameter: 64),
|
|
686
696
|
const SizedBox(width: KasySpacing.sm),
|
|
687
697
|
Expanded(
|
|
688
698
|
child: Column(
|
|
@@ -702,7 +712,7 @@ class _DesktopNav extends StatelessWidget {
|
|
|
702
712
|
email,
|
|
703
713
|
maxLines: 1,
|
|
704
714
|
overflow: TextOverflow.ellipsis,
|
|
705
|
-
style: context.textTheme.
|
|
715
|
+
style: context.textTheme.bodyMedium?.copyWith(
|
|
706
716
|
color: context.colors.muted,
|
|
707
717
|
),
|
|
708
718
|
),
|
|
@@ -755,7 +765,7 @@ class _NavTile extends StatelessWidget {
|
|
|
755
765
|
child: Container(
|
|
756
766
|
padding: const EdgeInsets.symmetric(
|
|
757
767
|
horizontal: KasySpacing.smd,
|
|
758
|
-
vertical: KasySpacing.
|
|
768
|
+
vertical: KasySpacing.sm,
|
|
759
769
|
),
|
|
760
770
|
decoration: BoxDecoration(
|
|
761
771
|
color: selected ? c.surfaceNeutralSoft : Colors.transparent,
|
|
@@ -877,8 +887,11 @@ class _DesktopDetail extends ConsumerWidget {
|
|
|
877
887
|
const SizedBox(height: KasySpacing.xl),
|
|
878
888
|
_settingsGroup([_LogoutRow(onTap: () => confirmLogout(context, ref))]),
|
|
879
889
|
],
|
|
880
|
-
|
|
881
|
-
|
|
890
|
+
// Only when there's a real backend account to delete (see mobile layout).
|
|
891
|
+
if (userId != null) ...[
|
|
892
|
+
const SizedBox(height: KasySpacing.xl),
|
|
893
|
+
const DeleteUserButton(),
|
|
894
|
+
],
|
|
882
895
|
const SizedBox(height: KasySpacing.xl),
|
|
883
896
|
const _VersionLabel(),
|
|
884
897
|
];
|
|
@@ -894,13 +907,18 @@ class _LogoutRow extends StatelessWidget {
|
|
|
894
907
|
@override
|
|
895
908
|
Widget build(BuildContext context) {
|
|
896
909
|
return KasyHover(
|
|
897
|
-
|
|
910
|
+
// Match the card radius so the full-bleed press fill hugs the rounded
|
|
911
|
+
// corners exactly (this row is the sole child of its card).
|
|
912
|
+
borderRadius: KasyRadius.lgBorderRadius,
|
|
898
913
|
pressColor: context.colors.error,
|
|
899
914
|
focusable: true,
|
|
900
915
|
focusGapColor: context.colors.surface,
|
|
901
916
|
onTap: onTap,
|
|
902
917
|
child: Padding(
|
|
903
|
-
padding: const EdgeInsets.symmetric(
|
|
918
|
+
padding: const EdgeInsets.symmetric(
|
|
919
|
+
horizontal: KasySpacing.md,
|
|
920
|
+
vertical: KasySpacing.smd,
|
|
921
|
+
),
|
|
904
922
|
child: Row(
|
|
905
923
|
children: [
|
|
906
924
|
Icon(
|
|
@@ -911,7 +929,7 @@ class _LogoutRow extends StatelessWidget {
|
|
|
911
929
|
const SizedBox(width: KasySpacing.sm),
|
|
912
930
|
Text(
|
|
913
931
|
context.t.settings.logout,
|
|
914
|
-
style: context.
|
|
932
|
+
style: context.kasyTextTheme.listRowTitle.copyWith(
|
|
915
933
|
color: context.colors.error,
|
|
916
934
|
),
|
|
917
935
|
),
|
|
@@ -980,12 +998,12 @@ class BiometricSwitcher extends ConsumerWidget {
|
|
|
980
998
|
),
|
|
981
999
|
Padding(
|
|
982
1000
|
padding: const EdgeInsets.only(
|
|
983
|
-
left: KasyIconSize.rowLeading + KasySpacing.sm,
|
|
1001
|
+
left: KasySpacing.md + KasyIconSize.rowLeading + KasySpacing.sm,
|
|
984
1002
|
bottom: KasySpacing.xs,
|
|
985
1003
|
),
|
|
986
1004
|
child: Text(
|
|
987
1005
|
subtitle,
|
|
988
|
-
style: context.textTheme.
|
|
1006
|
+
style: context.textTheme.bodyMedium?.copyWith(
|
|
989
1007
|
color: context.colors.muted,
|
|
990
1008
|
),
|
|
991
1009
|
),
|
|
@@ -1114,7 +1132,10 @@ class ThemeSwitcher extends StatelessWidget {
|
|
|
1114
1132
|
),
|
|
1115
1133
|
];
|
|
1116
1134
|
return Padding(
|
|
1117
|
-
padding: const EdgeInsets.symmetric(
|
|
1135
|
+
padding: const EdgeInsets.symmetric(
|
|
1136
|
+
horizontal: KasySpacing.md,
|
|
1137
|
+
vertical: KasySpacing.smd,
|
|
1138
|
+
),
|
|
1118
1139
|
child: Row(
|
|
1119
1140
|
children: [
|
|
1120
1141
|
Icon(
|
|
@@ -1126,7 +1147,7 @@ class ThemeSwitcher extends StatelessWidget {
|
|
|
1126
1147
|
Expanded(
|
|
1127
1148
|
child: Text(
|
|
1128
1149
|
tr.theme_title,
|
|
1129
|
-
style: context.
|
|
1150
|
+
style: context.kasyTextTheme.listRowTitle.copyWith(
|
|
1130
1151
|
color: context.colors.onSurface,
|
|
1131
1152
|
),
|
|
1132
1153
|
),
|