💄 Better bottom nav, snowing animation and notification tile
💫 Animated snowing animation
This commit is contained in:
@@ -212,6 +212,17 @@ class TabsScreen extends HookConsumerWidget {
|
|||||||
child: MediaQuery.removePadding(
|
child: MediaQuery.removePadding(
|
||||||
context: context,
|
context: context,
|
||||||
removeTop: true,
|
removeTop: true,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.transparent,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.1),
|
||||||
|
blurRadius: 4,
|
||||||
|
offset: const Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
child: BackdropFilter(
|
child: BackdropFilter(
|
||||||
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
|
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
|
||||||
child: BottomAppBar(
|
child: BottomAppBar(
|
||||||
@@ -227,9 +238,8 @@ class TabsScreen extends HookConsumerWidget {
|
|||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: () {
|
children: () {
|
||||||
final navItems = destinations.asMap().entries.map<Widget>((
|
final navItems = destinations.asMap().entries.map<Widget>(
|
||||||
entry,
|
(entry) {
|
||||||
) {
|
|
||||||
int index = entry.key;
|
int index = entry.key;
|
||||||
NavigationDestination dest = entry.value;
|
NavigationDestination dest = entry.value;
|
||||||
return IconButton(
|
return IconButton(
|
||||||
@@ -239,7 +249,8 @@ class TabsScreen extends HookConsumerWidget {
|
|||||||
? Theme.of(context).colorScheme.primary
|
? Theme.of(context).colorScheme.primary
|
||||||
: null,
|
: null,
|
||||||
);
|
);
|
||||||
}).toList();
|
},
|
||||||
|
).toList();
|
||||||
// Add mock item to leave space for FAB based on position
|
// Add mock item to leave space for FAB based on position
|
||||||
final gapIndex = switch (settings.fabPosition) {
|
final gapIndex = switch (settings.fabPosition) {
|
||||||
'left' => 0,
|
'left' => 0,
|
||||||
@@ -260,6 +271,7 @@ class TabsScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ class AppWrapper extends HookConsumerWidget {
|
|||||||
final networkStateShowing = useState(false);
|
final networkStateShowing = useState(false);
|
||||||
final wsNotifier = ref.watch(websocketStateProvider.notifier);
|
final wsNotifier = ref.watch(websocketStateProvider.notifier);
|
||||||
final websocketState = ref.watch(websocketStateProvider);
|
final websocketState = ref.watch(websocketStateProvider);
|
||||||
final showSnow = useState(false);
|
final isShowSnow = useState(false);
|
||||||
|
final isSnowGone = useState(false);
|
||||||
|
|
||||||
// Handle network status modal
|
// Handle network status modal
|
||||||
if (websocketState == WebSocketState.duplicateDevice() &&
|
if (websocketState == WebSocketState.duplicateDevice() &&
|
||||||
@@ -131,10 +132,18 @@ class AppWrapper extends HookConsumerWidget {
|
|||||||
settings.festivalFeatures &&
|
settings.festivalFeatures &&
|
||||||
now.month == 12 &&
|
now.month == 12 &&
|
||||||
(now.day >= 22 && now.day <= 28);
|
(now.day >= 22 && now.day <= 28);
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
final now = DateTime.now();
|
||||||
if (doesShowSnow) {
|
if (doesShowSnow) {
|
||||||
showSnow.value = true;
|
isShowSnow.value = true;
|
||||||
Future.delayed(const Duration(seconds: 10), () {
|
Future.delayed(const Duration(seconds: 60), () {
|
||||||
showSnow.value = false;
|
if (!context.mounted) return;
|
||||||
|
isShowSnow.value = false;
|
||||||
|
Future.delayed(const Duration(seconds: 3), () {
|
||||||
|
if (!context.mounted) return;
|
||||||
|
isSnowGone.value = true;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,18 +165,25 @@ class AppWrapper extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}, []);
|
||||||
|
|
||||||
return TourTriggerWidget(
|
return TourTriggerWidget(
|
||||||
key: const Key("app_tour_trigger"),
|
key: const Key("app_tour_trigger"),
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
child,
|
child,
|
||||||
if (showSnow.value)
|
if (doesShowSnow && !isSnowGone.value)
|
||||||
IgnorePointer(
|
IgnorePointer(
|
||||||
|
child: AnimatedOpacity(
|
||||||
|
opacity: isShowSnow.value ? 1 : 00,
|
||||||
|
duration: const Duration(seconds: 3),
|
||||||
child: SnowFallAnimation(
|
child: SnowFallAnimation(
|
||||||
key: const Key("app_snow_animation"),
|
key: const Key("app_snow_animation"),
|
||||||
config: SnowfallConfig(numberOfSnowflakes: 50, speed: 1.0),
|
config: SnowfallConfig(numberOfSnowflakes: 50, speed: 1.0),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -81,14 +81,14 @@ class NotificationTile extends StatelessWidget {
|
|||||||
style: compact
|
style: compact
|
||||||
? Theme.of(context).textTheme.bodySmall
|
? Theme.of(context).textTheme.bodySmall
|
||||||
: Theme.of(context).textTheme.titleMedium,
|
: Theme.of(context).textTheme.titleMedium,
|
||||||
maxLines: compact ? 2 : null,
|
maxLines: compact ? 1 : null,
|
||||||
overflow: compact ? TextOverflow.ellipsis : null,
|
overflow: compact ? TextOverflow.ellipsis : null,
|
||||||
),
|
),
|
||||||
subtitle: Column(
|
subtitle: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
if (notification.subtitle.isNotEmpty && !compact)
|
if (notification.subtitle.isNotEmpty && !compact)
|
||||||
Text(notification.subtitle).bold(),
|
Text(notification.subtitle, maxLines: compact ? 3 : null).bold(),
|
||||||
Row(
|
Row(
|
||||||
spacing: 6,
|
spacing: 6,
|
||||||
children: [
|
children: [
|
||||||
@@ -114,7 +114,9 @@ class NotificationTile extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
).opacity(0.75).padding(bottom: compact ? 2 : 4),
|
).opacity(0.75).padding(bottom: compact ? 2 : 4),
|
||||||
MarkdownTextContent(
|
MarkdownTextContent(
|
||||||
content: notification.content,
|
content: (compact && notification.content.length > 60)
|
||||||
|
? '${notification.content.substring(0, 60).replaceAll('\n', ' ')}...'
|
||||||
|
: notification.content,
|
||||||
textStyle:
|
textStyle:
|
||||||
(compact
|
(compact
|
||||||
? Theme.of(context).textTheme.bodySmall
|
? Theme.of(context).textTheme.bodySmall
|
||||||
|
|||||||
Reference in New Issue
Block a user