kasy-cli 1.25.0 → 1.26.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/commands/new.js +53 -3
- package/lib/utils/i18n/messages-en.js +3 -0
- package/lib/utils/i18n/messages-es.js +3 -0
- package/lib/utils/i18n/messages-pt.js +3 -0
- package/package.json +1 -1
- package/templates/firebase/lib/components/kasy_app_bar.dart +12 -6
- package/templates/firebase/lib/components/kasy_avatar.dart +17 -10
- package/templates/firebase/lib/components/kasy_checkbox.dart +24 -15
- package/templates/firebase/lib/components/kasy_date_picker.dart +27 -20
- package/templates/firebase/lib/components/kasy_otp_verification_bottom_sheet.dart +19 -14
- package/templates/firebase/lib/components/kasy_tabs.dart +75 -65
- package/templates/firebase/lib/core/bottom_menu/bottom_menu.dart +103 -3
- package/templates/firebase/lib/core/bottom_menu/web_content_wrapper.dart +45 -2
- package/templates/firebase/lib/features/ai_chat/ui/widgets/ai_conversation_tile.dart +9 -4
- package/templates/firebase/lib/features/feedbacks/ui/widgets/add_feature_button.dart +1 -0
- package/templates/firebase/lib/features/feedbacks/ui/widgets/feature_card.dart +2 -0
- package/templates/firebase/lib/features/home/home_feed.dart +21 -5
- package/templates/firebase/lib/features/home/home_image_grid.dart +83 -58
- package/templates/firebase/lib/features/local_reminders/ui/reminder_page.dart +124 -101
- package/templates/firebase/lib/features/notifications/ui/components/notification_tile.dart +1 -0
- package/templates/firebase/lib/features/notifications/ui/widgets/notification_tile.dart +85 -85
- package/templates/firebase/lib/features/onboarding/ui/widgets/selectable_row_tile.dart +67 -62
- package/templates/firebase/lib/features/settings/ui/components/avatar_component.dart +37 -23
- package/templates/firebase/lib/features/settings/ui/widgets/admin_card.dart +14 -6
- package/templates/firebase/lib/features/subscriptions/ui/widgets/premium_banner.dart +9 -3
- package/templates/firebase/lib/features/subscriptions/ui/widgets/premium_close_button.dart +24 -16
- package/templates/firebase/lib/features/subscriptions/ui/widgets/selectable_col.dart +29 -22
- package/templates/firebase/lib/features/subscriptions/ui/widgets/selectable_row.dart +19 -12
- package/templates/firebase/lib/i18n/en.i18n.json +2 -1
- package/templates/firebase/lib/i18n/es.i18n.json +2 -1
- package/templates/firebase/lib/i18n/pt.i18n.json +2 -1
|
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|
|
2
2
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
3
3
|
import 'package:kasy_kit/components/kasy_app_bar.dart';
|
|
4
4
|
import 'package:kasy_kit/core/theme/theme.dart';
|
|
5
|
+
import 'package:kasy_kit/core/widgets/kasy_focus_ring.dart';
|
|
5
6
|
import 'package:kasy_kit/core/widgets/kasy_scroll_behavior.dart';
|
|
6
7
|
import 'package:kasy_kit/features/local_reminders/providers/reminder_notifier.dart';
|
|
7
8
|
import 'package:kasy_kit/features/local_reminders/repositories/reminder_preferences.dart';
|
|
@@ -21,22 +22,18 @@ class ReminderPage extends ConsumerWidget {
|
|
|
21
22
|
title: tr.title,
|
|
22
23
|
onBack: () => Navigator.maybePop(context),
|
|
23
24
|
slivers: [
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
color: context.colors.primary,
|
|
25
|
+
asyncState.when(
|
|
26
|
+
loading: () => SliverFillRemaining(
|
|
27
|
+
child: Center(
|
|
28
|
+
child: CircularProgressIndicator(color: context.colors.primary),
|
|
29
29
|
),
|
|
30
30
|
),
|
|
31
|
+
error: (e, _) =>
|
|
32
|
+
SliverFillRemaining(child: Center(child: Text(e.toString()))),
|
|
33
|
+
data: (state) =>
|
|
34
|
+
SliverToBoxAdapter(child: _ReminderForm(state: state)),
|
|
31
35
|
),
|
|
32
|
-
|
|
33
|
-
child: Center(child: Text(e.toString())),
|
|
34
|
-
),
|
|
35
|
-
data: (state) => SliverToBoxAdapter(
|
|
36
|
-
child: _ReminderForm(state: state),
|
|
37
|
-
),
|
|
38
|
-
),
|
|
39
|
-
],
|
|
36
|
+
],
|
|
40
37
|
),
|
|
41
38
|
);
|
|
42
39
|
}
|
|
@@ -56,10 +53,7 @@ class _ReminderForm extends ConsumerWidget {
|
|
|
56
53
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
57
54
|
children: [
|
|
58
55
|
SwitchListTile(
|
|
59
|
-
title: Text(
|
|
60
|
-
tr.toggleLabel,
|
|
61
|
-
style: context.textTheme.bodyLarge,
|
|
62
|
-
),
|
|
56
|
+
title: Text(tr.toggleLabel, style: context.textTheme.bodyLarge),
|
|
63
57
|
value: state.enabled,
|
|
64
58
|
onChanged: notifier.setEnabled,
|
|
65
59
|
),
|
|
@@ -96,7 +90,10 @@ class _ReminderForm extends ConsumerWidget {
|
|
|
96
90
|
),
|
|
97
91
|
),
|
|
98
92
|
const SizedBox(height: KasySpacing.sm),
|
|
99
|
-
_DaySelector(
|
|
93
|
+
_DaySelector(
|
|
94
|
+
current: state.dayOfWeek,
|
|
95
|
+
onChanged: notifier.setDayOfWeek,
|
|
96
|
+
),
|
|
100
97
|
],
|
|
101
98
|
if (state.type == ReminderType.specificDate) ...[
|
|
102
99
|
const SizedBox(height: KasySpacing.lg),
|
|
@@ -107,10 +104,7 @@ class _ReminderForm extends ConsumerWidget {
|
|
|
107
104
|
),
|
|
108
105
|
),
|
|
109
106
|
const SizedBox(height: KasySpacing.sm),
|
|
110
|
-
_DateTile(
|
|
111
|
-
date: state.date,
|
|
112
|
-
onChanged: notifier.setDate,
|
|
113
|
-
),
|
|
107
|
+
_DateTile(date: state.date, onChanged: notifier.setDate),
|
|
114
108
|
],
|
|
115
109
|
],
|
|
116
110
|
],
|
|
@@ -131,7 +125,10 @@ class _TypeSelector extends StatelessWidget {
|
|
|
131
125
|
segments: [
|
|
132
126
|
ButtonSegment(value: ReminderType.daily, label: Text(tr.daily)),
|
|
133
127
|
ButtonSegment(value: ReminderType.weekly, label: Text(tr.weekly)),
|
|
134
|
-
ButtonSegment(
|
|
128
|
+
ButtonSegment(
|
|
129
|
+
value: ReminderType.specificDate,
|
|
130
|
+
label: Text(tr.specificDate),
|
|
131
|
+
),
|
|
135
132
|
],
|
|
136
133
|
selected: {current},
|
|
137
134
|
onSelectionChanged: (s) => onChanged(s.first),
|
|
@@ -147,46 +144,61 @@ class _TimeTile extends StatelessWidget {
|
|
|
147
144
|
final int minute;
|
|
148
145
|
final void Function(int hour, int minute) onChanged;
|
|
149
146
|
|
|
150
|
-
const _TimeTile({
|
|
147
|
+
const _TimeTile({
|
|
148
|
+
required this.hour,
|
|
149
|
+
required this.minute,
|
|
150
|
+
required this.onChanged,
|
|
151
|
+
});
|
|
151
152
|
|
|
152
153
|
String _pad(int v) => v.toString().padLeft(2, '0');
|
|
153
154
|
|
|
154
155
|
@override
|
|
155
156
|
Widget build(BuildContext context) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
157
|
+
Future<void> pickTime() async {
|
|
158
|
+
final picked = await showTimePicker(
|
|
159
|
+
context: context,
|
|
160
|
+
initialTime: TimeOfDay(hour: hour, minute: minute),
|
|
161
|
+
);
|
|
162
|
+
if (picked != null) {
|
|
163
|
+
onChanged(picked.hour, picked.minute);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return KasyFocusRing(
|
|
168
|
+
onActivate: pickTime,
|
|
166
169
|
borderRadius: BorderRadius.circular(KasySpacing.sm),
|
|
167
|
-
child:
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
170
|
+
child: InkWell(
|
|
171
|
+
canRequestFocus: false,
|
|
172
|
+
onTap: pickTime,
|
|
173
|
+
borderRadius: BorderRadius.circular(KasySpacing.sm),
|
|
174
|
+
child: Container(
|
|
175
|
+
padding: const EdgeInsets.symmetric(
|
|
176
|
+
horizontal: KasySpacing.md,
|
|
177
|
+
vertical: KasySpacing.smd,
|
|
178
|
+
),
|
|
179
|
+
decoration: BoxDecoration(
|
|
180
|
+
color: context.colors.surface,
|
|
181
|
+
borderRadius: BorderRadius.circular(KasySpacing.sm),
|
|
182
|
+
),
|
|
183
|
+
child: Row(
|
|
184
|
+
children: [
|
|
185
|
+
Icon(KasyIcons.time, color: context.colors.primary),
|
|
186
|
+
const SizedBox(width: KasySpacing.sm),
|
|
187
|
+
Text(
|
|
188
|
+
'${_pad(hour)}:${_pad(minute)}',
|
|
189
|
+
style: context.textTheme.headlineMedium?.copyWith(
|
|
190
|
+
color: context.colors.onSurface,
|
|
191
|
+
fontWeight: FontWeight.bold,
|
|
192
|
+
),
|
|
185
193
|
),
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
194
|
+
const Spacer(),
|
|
195
|
+
Icon(
|
|
196
|
+
KasyIcons.arrowForwardIos,
|
|
197
|
+
size: 14,
|
|
198
|
+
color: context.colors.muted,
|
|
199
|
+
),
|
|
200
|
+
],
|
|
201
|
+
),
|
|
190
202
|
),
|
|
191
203
|
),
|
|
192
204
|
);
|
|
@@ -202,9 +214,7 @@ class _DaySelector extends StatelessWidget {
|
|
|
202
214
|
@override
|
|
203
215
|
Widget build(BuildContext context) {
|
|
204
216
|
// 1=Monday ... 7=Sunday (matches DateTime.weekday)
|
|
205
|
-
final days = [
|
|
206
|
-
'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb', 'Dom',
|
|
207
|
-
];
|
|
217
|
+
final days = ['Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb', 'Dom'];
|
|
208
218
|
return Wrap(
|
|
209
219
|
spacing: KasySpacing.xs,
|
|
210
220
|
children: List.generate(7, (i) {
|
|
@@ -232,55 +242,68 @@ class _DateTile extends StatelessWidget {
|
|
|
232
242
|
? '${date!.day.toString().padLeft(2, '0')}/${date!.month.toString().padLeft(2, '0')}/${date!.year} ${date!.hour.toString().padLeft(2, '0')}:${date!.minute.toString().padLeft(2, '0')}'
|
|
233
243
|
: Translations.of(context).reminderPage.selectDate;
|
|
234
244
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
245
|
+
Future<void> pickDateTime() async {
|
|
246
|
+
final now = DateTime.now();
|
|
247
|
+
final pickedDate = await showDatePicker(
|
|
248
|
+
context: context,
|
|
249
|
+
initialDate: date ?? now,
|
|
250
|
+
firstDate: now,
|
|
251
|
+
lastDate: now.add(const Duration(days: 365)),
|
|
252
|
+
);
|
|
253
|
+
if (pickedDate == null || !context.mounted) return;
|
|
254
|
+
final pickedTime = await showTimePicker(
|
|
255
|
+
context: context,
|
|
256
|
+
initialTime: TimeOfDay(
|
|
257
|
+
hour: date?.hour ?? 9,
|
|
258
|
+
minute: date?.minute ?? 0,
|
|
259
|
+
),
|
|
260
|
+
);
|
|
261
|
+
if (pickedTime == null) return;
|
|
262
|
+
onChanged(
|
|
263
|
+
DateTime(
|
|
254
264
|
pickedDate.year,
|
|
255
265
|
pickedDate.month,
|
|
256
266
|
pickedDate.day,
|
|
257
267
|
pickedTime.hour,
|
|
258
268
|
pickedTime.minute,
|
|
259
|
-
));
|
|
260
|
-
},
|
|
261
|
-
borderRadius: BorderRadius.circular(KasySpacing.sm),
|
|
262
|
-
child: Container(
|
|
263
|
-
padding: const EdgeInsets.symmetric(
|
|
264
|
-
horizontal: KasySpacing.md,
|
|
265
|
-
vertical: KasySpacing.smd,
|
|
266
269
|
),
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return KasyFocusRing(
|
|
274
|
+
onActivate: pickDateTime,
|
|
275
|
+
borderRadius: BorderRadius.circular(KasySpacing.sm),
|
|
276
|
+
child: InkWell(
|
|
277
|
+
canRequestFocus: false,
|
|
278
|
+
onTap: pickDateTime,
|
|
279
|
+
borderRadius: BorderRadius.circular(KasySpacing.sm),
|
|
280
|
+
child: Container(
|
|
281
|
+
padding: const EdgeInsets.symmetric(
|
|
282
|
+
horizontal: KasySpacing.md,
|
|
283
|
+
vertical: KasySpacing.smd,
|
|
284
|
+
),
|
|
285
|
+
decoration: BoxDecoration(
|
|
286
|
+
color: context.colors.surface,
|
|
287
|
+
borderRadius: BorderRadius.circular(KasySpacing.sm),
|
|
288
|
+
),
|
|
289
|
+
child: Row(
|
|
290
|
+
children: [
|
|
291
|
+
Icon(KasyIcons.calendar, color: context.colors.primary),
|
|
292
|
+
const SizedBox(width: KasySpacing.sm),
|
|
293
|
+
Text(
|
|
294
|
+
label,
|
|
295
|
+
style: context.textTheme.bodyLarge?.copyWith(
|
|
296
|
+
color: context.colors.onSurface,
|
|
297
|
+
),
|
|
279
298
|
),
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
299
|
+
const Spacer(),
|
|
300
|
+
Icon(
|
|
301
|
+
KasyIcons.arrowForwardIos,
|
|
302
|
+
size: 14,
|
|
303
|
+
color: context.colors.muted,
|
|
304
|
+
),
|
|
305
|
+
],
|
|
306
|
+
),
|
|
284
307
|
),
|
|
285
308
|
),
|
|
286
309
|
);
|
|
@@ -34,6 +34,7 @@ class NotificationTileComponent extends StatelessWidget {
|
|
|
34
34
|
child: KasyHover(
|
|
35
35
|
onTap: () => onTap?.call(notification),
|
|
36
36
|
borderRadius: KasyRadius.smBorderRadius,
|
|
37
|
+
focusable: true,
|
|
37
38
|
margin: const EdgeInsets.only(top: KasySpacing.sm),
|
|
38
39
|
child: NotificationTile.from(
|
|
39
40
|
key: ValueKey('notification_${notification.id}'),
|
|
@@ -2,6 +2,7 @@ import 'package:better_skeleton/better_skeleton.dart';
|
|
|
2
2
|
import 'package:flutter/material.dart';
|
|
3
3
|
import 'package:jiffy/jiffy.dart';
|
|
4
4
|
import 'package:kasy_kit/core/theme/theme.dart';
|
|
5
|
+
import 'package:kasy_kit/core/widgets/kasy_focus_ring.dart';
|
|
5
6
|
import 'package:kasy_kit/features/notifications/providers/models/notification.dart'
|
|
6
7
|
as app;
|
|
7
8
|
|
|
@@ -44,23 +45,22 @@ class NotificationTile extends StatefulWidget {
|
|
|
44
45
|
String? imageUrl,
|
|
45
46
|
OnTapNotification? onTap,
|
|
46
47
|
Key? key,
|
|
47
|
-
}) =>
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
);
|
|
48
|
+
}) => NotificationTile(
|
|
49
|
+
key: key,
|
|
50
|
+
bgOpacity: .08,
|
|
51
|
+
titleOpacity: 1,
|
|
52
|
+
showUnreadDot: true,
|
|
53
|
+
icon: imageUrl != null
|
|
54
|
+
? TileNotificationImage(url: imageUrl)
|
|
55
|
+
: const TileNotificationIcon(active: true),
|
|
56
|
+
date: date,
|
|
57
|
+
title: title,
|
|
58
|
+
description: description,
|
|
59
|
+
titleColor: context.colors.onSurface,
|
|
60
|
+
descriptionColor: context.colors.onSurface,
|
|
61
|
+
dateColor: context.colors.muted,
|
|
62
|
+
onTap: onTap,
|
|
63
|
+
);
|
|
64
64
|
|
|
65
65
|
factory NotificationTile.old({
|
|
66
66
|
required DateTime date,
|
|
@@ -70,48 +70,46 @@ class NotificationTile extends StatefulWidget {
|
|
|
70
70
|
String? imageUrl,
|
|
71
71
|
OnTapNotification? onTap,
|
|
72
72
|
Key? key,
|
|
73
|
-
}) =>
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
);
|
|
73
|
+
}) => NotificationTile(
|
|
74
|
+
key: key,
|
|
75
|
+
bgOpacity: 0,
|
|
76
|
+
titleOpacity: .6,
|
|
77
|
+
icon: imageUrl != null
|
|
78
|
+
? TileNotificationImage(url: imageUrl)
|
|
79
|
+
: const TileNotificationIcon(active: false),
|
|
80
|
+
date: date,
|
|
81
|
+
title: title,
|
|
82
|
+
description: description,
|
|
83
|
+
titleColor: context.colors.onSurface.withValues(alpha: 0.55),
|
|
84
|
+
descriptionColor: context.colors.onSurface.withValues(alpha: 0.45),
|
|
85
|
+
dateColor: context.colors.muted,
|
|
86
|
+
onTap: onTap,
|
|
87
|
+
);
|
|
89
88
|
|
|
90
89
|
factory NotificationTile.from(
|
|
91
90
|
BuildContext context,
|
|
92
91
|
app.Notification notification, {
|
|
93
92
|
Key? key,
|
|
94
93
|
OnTapNotification? onTap,
|
|
95
|
-
}) =>
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
:
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
);
|
|
94
|
+
}) => notification.seen
|
|
95
|
+
? NotificationTile.old(
|
|
96
|
+
key: key,
|
|
97
|
+
date: notification.createdAt,
|
|
98
|
+
title: notification.title,
|
|
99
|
+
description: notification.body,
|
|
100
|
+
imageUrl: notification.imageUrl,
|
|
101
|
+
context: context,
|
|
102
|
+
onTap: onTap,
|
|
103
|
+
)
|
|
104
|
+
: NotificationTile.active(
|
|
105
|
+
key: key,
|
|
106
|
+
date: notification.createdAt,
|
|
107
|
+
title: notification.title,
|
|
108
|
+
description: notification.body,
|
|
109
|
+
imageUrl: notification.imageUrl,
|
|
110
|
+
context: context,
|
|
111
|
+
onTap: onTap,
|
|
112
|
+
);
|
|
115
113
|
|
|
116
114
|
@override
|
|
117
115
|
State<NotificationTile> createState() => _NotificationTileState();
|
|
@@ -132,9 +130,7 @@ class _NotificationTileState extends State<NotificationTile>
|
|
|
132
130
|
_opacityAnimation = Tween(
|
|
133
131
|
begin: 0.0,
|
|
134
132
|
end: widget.bgOpacity,
|
|
135
|
-
).animate(
|
|
136
|
-
CurvedAnimation(parent: _controller, curve: Curves.decelerate),
|
|
137
|
-
);
|
|
133
|
+
).animate(CurvedAnimation(parent: _controller, curve: Curves.decelerate));
|
|
138
134
|
_controller.forward();
|
|
139
135
|
}
|
|
140
136
|
|
|
@@ -145,9 +141,7 @@ class _NotificationTileState extends State<NotificationTile>
|
|
|
145
141
|
_opacityAnimation = Tween(
|
|
146
142
|
begin: oldWidget.bgOpacity,
|
|
147
143
|
end: widget.bgOpacity,
|
|
148
|
-
).animate(
|
|
149
|
-
CurvedAnimation(parent: _controller, curve: Curves.ease),
|
|
150
|
-
);
|
|
144
|
+
).animate(CurvedAnimation(parent: _controller, curve: Curves.ease));
|
|
151
145
|
_controller.forward(from: 0);
|
|
152
146
|
}
|
|
153
147
|
}
|
|
@@ -165,8 +159,9 @@ class _NotificationTileState extends State<NotificationTile>
|
|
|
165
159
|
builder: (context, child) {
|
|
166
160
|
return Container(
|
|
167
161
|
decoration: BoxDecoration(
|
|
168
|
-
color: context.colors.primary
|
|
169
|
-
|
|
162
|
+
color: context.colors.primary.withValues(
|
|
163
|
+
alpha: _opacityAnimation.value,
|
|
164
|
+
),
|
|
170
165
|
borderRadius: KasyRadius.smBorderRadius,
|
|
171
166
|
),
|
|
172
167
|
padding: const EdgeInsets.all(KasySpacing.md),
|
|
@@ -187,8 +182,8 @@ class _NotificationTileState extends State<NotificationTile>
|
|
|
187
182
|
child: Text(
|
|
188
183
|
widget.title,
|
|
189
184
|
style: context.textTheme.labelLarge?.copyWith(
|
|
190
|
-
|
|
191
|
-
|
|
185
|
+
color: widget.titleColor,
|
|
186
|
+
),
|
|
192
187
|
overflow: TextOverflow.clip,
|
|
193
188
|
maxLines: 2,
|
|
194
189
|
),
|
|
@@ -198,8 +193,9 @@ class _NotificationTileState extends State<NotificationTile>
|
|
|
198
193
|
flex: 0,
|
|
199
194
|
child: Text(
|
|
200
195
|
widget.description,
|
|
201
|
-
style: context.textTheme.bodyMedium
|
|
202
|
-
|
|
196
|
+
style: context.textTheme.bodyMedium?.copyWith(
|
|
197
|
+
color: widget.descriptionColor,
|
|
198
|
+
),
|
|
203
199
|
overflow: TextOverflow.ellipsis,
|
|
204
200
|
maxLines: 3,
|
|
205
201
|
),
|
|
@@ -210,8 +206,8 @@ class _NotificationTileState extends State<NotificationTile>
|
|
|
210
206
|
child: Text(
|
|
211
207
|
Jiffy.parseFromDateTime(widget.date).fromNow(),
|
|
212
208
|
style: context.textTheme.bodySmall?.copyWith(
|
|
213
|
-
|
|
214
|
-
|
|
209
|
+
color: widget.dateColor,
|
|
210
|
+
),
|
|
215
211
|
),
|
|
216
212
|
),
|
|
217
213
|
],
|
|
@@ -264,18 +260,24 @@ class TileNotificationImage extends StatelessWidget {
|
|
|
264
260
|
|
|
265
261
|
@override
|
|
266
262
|
Widget build(BuildContext context) {
|
|
267
|
-
return
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
263
|
+
return KasyFocusRing(
|
|
264
|
+
onActivate: () => _openFullscreen(context),
|
|
265
|
+
borderRadius: BorderRadius.circular(8),
|
|
266
|
+
child: GestureDetector(
|
|
267
|
+
onTap: () => _openFullscreen(context),
|
|
268
|
+
child: ClipRRect(
|
|
269
|
+
borderRadius: BorderRadius.circular(8),
|
|
270
|
+
child: Image.network(
|
|
271
|
+
url,
|
|
272
|
+
width: 48,
|
|
273
|
+
height: 48,
|
|
274
|
+
fit: BoxFit.cover,
|
|
275
|
+
errorBuilder: (context, error, stack) =>
|
|
276
|
+
const TileNotificationIcon(active: false),
|
|
277
|
+
loadingBuilder: (_, child, progress) => progress == null
|
|
278
|
+
? child
|
|
279
|
+
: const TileNotificationIcon(active: false),
|
|
280
|
+
),
|
|
279
281
|
),
|
|
280
282
|
),
|
|
281
283
|
);
|
|
@@ -287,10 +289,7 @@ class TileNotificationImage extends StatelessWidget {
|
|
|
287
289
|
class TileNotificationIcon extends StatelessWidget {
|
|
288
290
|
final bool active;
|
|
289
291
|
|
|
290
|
-
const TileNotificationIcon({
|
|
291
|
-
super.key,
|
|
292
|
-
required this.active,
|
|
293
|
-
});
|
|
292
|
+
const TileNotificationIcon({super.key, required this.active});
|
|
294
293
|
|
|
295
294
|
@override
|
|
296
295
|
Widget build(BuildContext context) {
|
|
@@ -332,8 +331,9 @@ class _NotificationSkeletonTileState extends State<NotificationSkeletonTile>
|
|
|
332
331
|
void initState() {
|
|
333
332
|
super.initState();
|
|
334
333
|
animationController = AnimationController(
|
|
335
|
-
|
|
336
|
-
|
|
334
|
+
vsync: this,
|
|
335
|
+
duration: const Duration(milliseconds: 1000),
|
|
336
|
+
)..repeat();
|
|
337
337
|
}
|
|
338
338
|
|
|
339
339
|
@override
|