forked from firka/firka
fix + ref: nav tap animation
This commit is contained in:
@@ -287,7 +287,7 @@ class _HomeTimetableScreen extends FirkaState<HomeTimetableScreen>
|
|||||||
active = -1;
|
active = -1;
|
||||||
|
|
||||||
const double cardWidth = 40.0;
|
const double cardWidth = 40.0;
|
||||||
const double spacing = 8.0;
|
const double spacing = 18.0;
|
||||||
final double totalCardWidth = cardWidth + spacing;
|
final double totalCardWidth = cardWidth + spacing;
|
||||||
|
|
||||||
// Calculate animation positions based on real display indices
|
// Calculate animation positions based on real display indices
|
||||||
@@ -365,193 +365,167 @@ class _HomeTimetableScreen extends FirkaState<HomeTimetableScreen>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildContent(BuildContext context) {
|
Widget _buildContent(BuildContext context) {
|
||||||
if (lessons != null && tests != null && events != null && dates != null) {
|
if (lessons == null || tests == null || events == null || dates == null) {
|
||||||
List<Widget> ttWidgets = [];
|
return Column(
|
||||||
List<Widget> ttDays = [];
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
final showABTimetable = widget.data.settings
|
children: [
|
||||||
.group("settings")
|
Row(
|
||||||
.subGroup("timetable_toast")
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
.boolean("ab_timetable");
|
children: [DelayedSpinnerWidget()],
|
||||||
// Build navigation icons using original dates
|
),
|
||||||
for (var i = 0; i < dates!.length; i++) {
|
],
|
||||||
final date = dates![i];
|
);
|
||||||
final realIndex = i; // Always use real index for nav icons
|
}
|
||||||
|
|
||||||
final testsOnDate = tests!
|
List<Widget> ttWidgets = [];
|
||||||
.where(
|
List<Widget> ttDays = [];
|
||||||
(test) =>
|
final showABTimetable = widget.data.settings
|
||||||
test.date.isAfter(date.subtract(Duration(seconds: 1))) &&
|
.group("settings")
|
||||||
test.date.isBefore(
|
.subGroup("timetable_toast")
|
||||||
date.add(Duration(hours: 23, minutes: 59)),
|
.boolean("ab_timetable");
|
||||||
),
|
// Build navigation icons using original dates
|
||||||
)
|
for (var i = 0; i < dates!.length; i++) {
|
||||||
.toList();
|
final date = dates![i];
|
||||||
|
final realIndex = i; // Always use real index for nav icons
|
||||||
|
|
||||||
if (testsOnDate.isNotEmpty) {
|
final testsOnDate = tests!
|
||||||
ttWidgets.add(
|
.where(
|
||||||
Stack(
|
(test) =>
|
||||||
children: [
|
test.date.isAfter(date.subtract(Duration(seconds: 1))) &&
|
||||||
BottomTimeTableNavIconWidget(
|
test.date.isBefore(date.add(Duration(hours: 23, minutes: 59))),
|
||||||
widget.data.l10n,
|
)
|
||||||
() {
|
.toList();
|
||||||
_handleNavTap(active, realIndex);
|
|
||||||
},
|
|
||||||
active == i,
|
|
||||||
date,
|
|
||||||
),
|
|
||||||
Transform.translate(
|
|
||||||
offset: Offset(38, -10),
|
|
||||||
child: BubbleTest(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
ttWidgets.add(
|
|
||||||
BottomTimeTableNavIconWidget(
|
|
||||||
widget.data.l10n,
|
|
||||||
() {
|
|
||||||
_handleNavTap(active, realIndex);
|
|
||||||
},
|
|
||||||
active == i,
|
|
||||||
date,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build carousel pages using animation dates
|
Widget ttWidget = BottomTimeTableNavIconWidget(
|
||||||
for (var i = 0; i < _animationDates!.length; i++) {
|
widget.data.l10n,
|
||||||
final date = _animationDates![i];
|
() {
|
||||||
|
_handleNavTap(active, realIndex);
|
||||||
final lessonsOnDate = lessons!
|
},
|
||||||
.where(
|
active == i,
|
||||||
(lesson) =>
|
date,
|
||||||
lesson.start.isAfter(date) &&
|
);
|
||||||
lesson.end.isBefore(date.add(Duration(hours: 24))),
|
if (testsOnDate.isNotEmpty) {
|
||||||
)
|
ttWidgets.add(
|
||||||
.toList();
|
Stack(
|
||||||
final lessonsOnDay = lessons!
|
children: [
|
||||||
.where(
|
ttWidget,
|
||||||
(lesson) =>
|
Transform.translate(offset: Offset(38, -10), child: BubbleTest()),
|
||||||
lesson.start.getMidnight().millisecondsSinceEpoch ==
|
],
|
||||||
date.getMidnight().millisecondsSinceEpoch,
|
|
||||||
)
|
|
||||||
.toList();
|
|
||||||
final eventsOnDate = events!
|
|
||||||
.where(
|
|
||||||
(lesson) =>
|
|
||||||
lesson.start.isAfter(date.subtract(Duration(seconds: 1))) &&
|
|
||||||
lesson.end.isBefore(
|
|
||||||
date.add(Duration(hours: 23, minutes: 59)),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList();
|
|
||||||
final testsOnDate = tests!
|
|
||||||
.where(
|
|
||||||
(test) =>
|
|
||||||
test.date.isAfter(date.subtract(Duration(seconds: 1))) &&
|
|
||||||
test.date.isBefore(
|
|
||||||
date.add(Duration(hours: 23, minutes: 59)),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
ttDays.add(
|
|
||||||
TimeTableDayWidget(
|
|
||||||
widget.data,
|
|
||||||
date,
|
|
||||||
lessons!,
|
|
||||||
lessonsOnDate,
|
|
||||||
eventsOnDate,
|
|
||||||
testsOnDate,
|
|
||||||
lessonsOnDay,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
ttWidgets.add(ttWidget);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<Widget> ttEmptyCards = List.empty(growable: true);
|
// Build carousel pages using animation dates
|
||||||
|
for (var i = 0; i < _animationDates!.length; i++) {
|
||||||
|
final date = _animationDates![i];
|
||||||
|
|
||||||
if (animating || _showAnimatedCard) {
|
final lessonsOnDate = lessons!
|
||||||
for (var i = 0; i < ttDays.length; i++) {
|
.where(
|
||||||
if (i == 0) {
|
(lesson) =>
|
||||||
Widget cardWidget = Card(
|
lesson.start.isAfter(date) &&
|
||||||
|
lesson.end.isBefore(date.add(Duration(hours: 24))),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
final lessonsOnDay = lessons!
|
||||||
|
.where(
|
||||||
|
(lesson) =>
|
||||||
|
lesson.start.getMidnight().millisecondsSinceEpoch ==
|
||||||
|
date.getMidnight().millisecondsSinceEpoch,
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
final eventsOnDate = events!
|
||||||
|
.where(
|
||||||
|
(lesson) =>
|
||||||
|
lesson.start.isAfter(date.subtract(Duration(seconds: 1))) &&
|
||||||
|
lesson.end.isBefore(date.add(Duration(hours: 23, minutes: 59))),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
final testsOnDate = tests!
|
||||||
|
.where(
|
||||||
|
(test) =>
|
||||||
|
test.date.isAfter(date.subtract(Duration(seconds: 1))) &&
|
||||||
|
test.date.isBefore(date.add(Duration(hours: 23, minutes: 59))),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
ttDays.add(
|
||||||
|
TimeTableDayWidget(
|
||||||
|
widget.data,
|
||||||
|
date,
|
||||||
|
lessons!,
|
||||||
|
lessonsOnDate,
|
||||||
|
eventsOnDate,
|
||||||
|
testsOnDate,
|
||||||
|
lessonsOnDay,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget ttAnimatedCard = Card(
|
||||||
|
color: Colors.transparent,
|
||||||
|
shadowColor: Colors.transparent,
|
||||||
|
child: SizedBox(width: 40, height: 54),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (_cardOffsetAnimation != null && _showAnimatedCard) {
|
||||||
|
ttAnimatedCard = AnimatedBuilder(
|
||||||
|
animation: _cardOffsetAnimation!,
|
||||||
|
builder: (context, child) {
|
||||||
|
return Transform.translate(
|
||||||
|
offset: _cardOffsetAnimation!.value,
|
||||||
|
child: Card(
|
||||||
color: appStyle.colors.buttonSecondaryFill,
|
color: appStyle.colors.buttonSecondaryFill,
|
||||||
shadowColor: Colors.transparent,
|
shadowColor: Colors.transparent,
|
||||||
child: SizedBox(width: 40, height: 54),
|
child: SizedBox(width: 40, height: 54),
|
||||||
);
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (_showAnimatedCard && _cardOffsetAnimation != null) {
|
return Stack(
|
||||||
ttEmptyCards.add(
|
children: [
|
||||||
AnimatedBuilder(
|
Column(
|
||||||
animation: _cardOffsetAnimation!,
|
children: [
|
||||||
builder: (context, child) {
|
SizedBox(
|
||||||
return Transform.translate(
|
width: MediaQuery.of(context).size.width,
|
||||||
offset: _cardOffsetAnimation!.value,
|
height: 74 + 16,
|
||||||
child: cardWidget,
|
child: Padding(
|
||||||
);
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
},
|
child: Column(
|
||||||
),
|
children: [
|
||||||
);
|
Row(
|
||||||
} else {
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
ttEmptyCards.add(
|
children: [
|
||||||
Transform.translate(offset: Offset(0, 0), child: cardWidget),
|
Text(
|
||||||
);
|
widget.data.l10n.timetable,
|
||||||
}
|
style: appStyle.fonts.H_H2.apply(
|
||||||
} else {
|
color: appStyle.colors.textPrimary,
|
||||||
ttEmptyCards.add(
|
|
||||||
Card(
|
|
||||||
color: Colors.transparent,
|
|
||||||
shadowColor: Colors.transparent,
|
|
||||||
child: SizedBox(width: 40, height: 54),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ttEmptyCards.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Stack(
|
|
||||||
children: [
|
|
||||||
Column(
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
width: MediaQuery.of(context).size.width,
|
|
||||||
height: 74 + 16,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
widget.data.l10n.timetable,
|
|
||||||
style: appStyle.fonts.H_H2.apply(
|
|
||||||
color: appStyle.colors.textPrimary,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Row(
|
),
|
||||||
children: [
|
Row(
|
||||||
GestureDetector(
|
children: [
|
||||||
child: Card(
|
GestureDetector(
|
||||||
color: appStyle.colors.buttonSecondaryFill,
|
child: Card(
|
||||||
child: Padding(
|
color: appStyle.colors.buttonSecondaryFill,
|
||||||
padding: const EdgeInsets.all(8),
|
child: Padding(
|
||||||
child: FirkaIconWidget(
|
padding: const EdgeInsets.all(8),
|
||||||
FirkaIconType.majesticons,
|
child: FirkaIconWidget(
|
||||||
Majesticon.tableSolid,
|
FirkaIconType.majesticons,
|
||||||
size: 26.0,
|
Majesticon.tableSolid,
|
||||||
color: appStyle.colors.accent,
|
size: 26.0,
|
||||||
),
|
color: appStyle.colors.accent,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onTap: () {
|
|
||||||
context.push('/timetable/monthly');
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
/* TODO: 1.1.0
|
onTap: () {
|
||||||
|
context.push('/timetable/monthly');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
/* TODO: 1.1.0
|
||||||
|
|
||||||
Card(
|
Card(
|
||||||
color: appStyle.colors.buttonSecondaryFill,
|
color: appStyle.colors.buttonSecondaryFill,
|
||||||
@@ -566,205 +540,192 @@ class _HomeTimetableScreen extends FirkaState<HomeTimetableScreen>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
*/
|
*/
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
child: Card(
|
child: Card(
|
||||||
color: appStyle.colors.buttonSecondaryFill,
|
color: appStyle.colors.buttonSecondaryFill,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
child: FirkaIconWidget(
|
child: FirkaIconWidget(
|
||||||
FirkaIconType.majesticons,
|
FirkaIconType.majesticons,
|
||||||
Majesticon.settingsCogSolid,
|
Majesticon.settingsCogSolid,
|
||||||
size: 26.0,
|
size: 26.0,
|
||||||
color: appStyle.colors.accent,
|
color: appStyle.colors.accent,
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onTap: () {
|
|
||||||
showSettingsSheet(
|
|
||||||
context,
|
|
||||||
MediaQuery.of(context).size.height * 0.4,
|
|
||||||
widget.data,
|
|
||||||
widget.data.settings
|
|
||||||
.group("settings")
|
|
||||||
.subGroup("timetable_toast"),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox(height: 16),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
GestureDetector(
|
|
||||||
behavior: HitTestBehavior.translucent,
|
|
||||||
child: SizedBox(
|
|
||||||
width: 24,
|
|
||||||
height: 24,
|
|
||||||
child: FirkaIconWidget(
|
|
||||||
FirkaIconType.icons,
|
|
||||||
"dropdownLeft",
|
|
||||||
size: 24,
|
|
||||||
color: appStyle.colors.accent,
|
|
||||||
),
|
),
|
||||||
|
onTap: () {
|
||||||
|
showSettingsSheet(
|
||||||
|
context,
|
||||||
|
MediaQuery.of(context).size.height * 0.4,
|
||||||
|
widget.data,
|
||||||
|
widget.data.settings
|
||||||
|
.group("settings")
|
||||||
|
.subGroup("timetable_toast"),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
behavior: HitTestBehavior.translucent,
|
||||||
|
child: SizedBox(
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
child: FirkaIconWidget(
|
||||||
|
FirkaIconType.icons,
|
||||||
|
"dropdownLeft",
|
||||||
|
size: 24,
|
||||||
|
color: appStyle.colors.accent,
|
||||||
),
|
),
|
||||||
onTap: () async {
|
|
||||||
var newNow = now!.subtract(Duration(days: 7));
|
|
||||||
if (!mounted) return;
|
|
||||||
setState(() {
|
|
||||||
now = newNow;
|
|
||||||
lessons = null;
|
|
||||||
dates = null;
|
|
||||||
});
|
|
||||||
await initForWeek(newNow);
|
|
||||||
setState(() {
|
|
||||||
now = newNow;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
GestureDetector(
|
onTap: () async {
|
||||||
child: Row(
|
var newNow = now!.subtract(Duration(days: 7));
|
||||||
children: [
|
if (!mounted) return;
|
||||||
|
setState(() {
|
||||||
|
now = newNow;
|
||||||
|
lessons = null;
|
||||||
|
dates = null;
|
||||||
|
});
|
||||||
|
await initForWeek(newNow);
|
||||||
|
setState(() {
|
||||||
|
now = newNow;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
now!.format(
|
||||||
|
widget.data.l10n,
|
||||||
|
FormatMode.yyyymmddwedd,
|
||||||
|
),
|
||||||
|
style: appStyle.fonts.B_16R.apply(
|
||||||
|
color: appStyle.colors.textPrimary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 4),
|
||||||
|
if (showABTimetable) ...[
|
||||||
Text(
|
Text(
|
||||||
now!.format(
|
"•",
|
||||||
widget.data.l10n,
|
style: appStyle.fonts.B_16R.apply(
|
||||||
FormatMode.yyyymmddwedd,
|
color: appStyle.colors.accent,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 4),
|
||||||
|
Text(
|
||||||
|
now!.isAWeek()
|
||||||
|
? widget.data.l10n.a_week
|
||||||
|
: widget.data.l10n.b_week,
|
||||||
style: appStyle.fonts.B_16R.apply(
|
style: appStyle.fonts.B_16R.apply(
|
||||||
color: appStyle.colors.textPrimary,
|
color: appStyle.colors.textPrimary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 4),
|
|
||||||
if (showABTimetable) ...[
|
|
||||||
Text(
|
|
||||||
"•",
|
|
||||||
style: appStyle.fonts.B_16R.apply(
|
|
||||||
color: appStyle.colors.accent,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: 4),
|
|
||||||
Text(
|
|
||||||
now!.isAWeek()
|
|
||||||
? widget.data.l10n.a_week
|
|
||||||
: widget.data.l10n.b_week,
|
|
||||||
style: appStyle.fonts.B_16R.apply(
|
|
||||||
color: appStyle.colors.textPrimary,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
],
|
||||||
),
|
],
|
||||||
onTap: () {
|
|
||||||
now = timeNow();
|
|
||||||
setActiveToToday();
|
|
||||||
_controller.jumpToPage(active);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
GestureDetector(
|
onTap: () {
|
||||||
behavior: HitTestBehavior.translucent,
|
now = timeNow();
|
||||||
child: SizedBox(
|
setActiveToToday();
|
||||||
width: 24,
|
_controller.jumpToPage(active);
|
||||||
height: 24,
|
},
|
||||||
child: FirkaIconWidget(
|
),
|
||||||
FirkaIconType.icons,
|
GestureDetector(
|
||||||
"dropdownRight",
|
behavior: HitTestBehavior.translucent,
|
||||||
size: 24,
|
child: SizedBox(
|
||||||
color: appStyle.colors.accent,
|
width: 24,
|
||||||
),
|
height: 24,
|
||||||
|
child: FirkaIconWidget(
|
||||||
|
FirkaIconType.icons,
|
||||||
|
"dropdownRight",
|
||||||
|
size: 24,
|
||||||
|
color: appStyle.colors.accent,
|
||||||
),
|
),
|
||||||
onTap: () async {
|
|
||||||
var newNow = now!.add(Duration(days: 7));
|
|
||||||
if (!mounted) return;
|
|
||||||
setState(() {
|
|
||||||
now = newNow;
|
|
||||||
lessons = null;
|
|
||||||
dates = null;
|
|
||||||
});
|
|
||||||
await initForWeek(newNow);
|
|
||||||
setState(() {
|
|
||||||
now = newNow;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
onTap: () async {
|
||||||
),
|
var newNow = now!.add(Duration(days: 7));
|
||||||
],
|
if (!mounted) return;
|
||||||
),
|
setState(() {
|
||||||
),
|
now = newNow;
|
||||||
),
|
lessons = null;
|
||||||
],
|
dates = null;
|
||||||
),
|
});
|
||||||
Column(
|
await initForWeek(newNow);
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
setState(() {
|
||||||
children: [
|
now = newNow;
|
||||||
Expanded(
|
});
|
||||||
child: TransparentPointer(
|
},
|
||||||
child: CarouselSlider(
|
),
|
||||||
items: ttDays,
|
],
|
||||||
carouselController: _controller,
|
|
||||||
options: CarouselOptions(
|
|
||||||
height: MediaQuery.of(context).size.height,
|
|
||||||
viewportFraction: 1,
|
|
||||||
enableInfiniteScroll: false,
|
|
||||||
initialPage: active,
|
|
||||||
onPageChanged: (i, _) {
|
|
||||||
if (animating || !mounted) return;
|
|
||||||
|
|
||||||
HapticFeedback.mediumImpact();
|
|
||||||
|
|
||||||
// Convert animation index to display index
|
|
||||||
final displayIndex = dates!.indexOf(
|
|
||||||
_animationDates![i],
|
|
||||||
);
|
|
||||||
maybeCacheNextWeek(displayIndex);
|
|
||||||
maybeCachePreviousWeek(displayIndex);
|
|
||||||
setState(() {
|
|
||||||
active = displayIndex;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
padding: EdgeInsets.only(bottom: 12),
|
|
||||||
decoration: ShapeDecoration(
|
|
||||||
color: Colors.transparent,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(0),
|
|
||||||
),
|
|
||||||
shadows: [
|
|
||||||
BoxShadow(
|
|
||||||
color: appStyle.colors.background,
|
|
||||||
blurRadius: 30,
|
|
||||||
spreadRadius: 20,
|
|
||||||
offset: Offset(0, -25),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
child: Stack(
|
),
|
||||||
children: [
|
),
|
||||||
Wrap(spacing: 10, children: ttEmptyCards),
|
],
|
||||||
Wrap(spacing: 10, children: ttWidgets),
|
),
|
||||||
],
|
Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TransparentPointer(
|
||||||
|
child: CarouselSlider(
|
||||||
|
items: ttDays,
|
||||||
|
carouselController: _controller,
|
||||||
|
options: CarouselOptions(
|
||||||
|
height: MediaQuery.of(context).size.height,
|
||||||
|
viewportFraction: 1,
|
||||||
|
enableInfiniteScroll: false,
|
||||||
|
initialPage: active,
|
||||||
|
onPageChanged: (i, _) {
|
||||||
|
if (animating || !mounted) return;
|
||||||
|
|
||||||
|
HapticFeedback.mediumImpact();
|
||||||
|
|
||||||
|
// Convert animation index to display index
|
||||||
|
final displayIndex = dates!.indexOf(_animationDates![i]);
|
||||||
|
maybeCacheNextWeek(displayIndex);
|
||||||
|
maybeCachePreviousWeek(displayIndex);
|
||||||
|
setState(() {
|
||||||
|
active = displayIndex;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
Container(
|
||||||
],
|
padding: EdgeInsets.only(bottom: 12),
|
||||||
);
|
decoration: ShapeDecoration(
|
||||||
} else {
|
color: Colors.transparent,
|
||||||
return Column(
|
shape: RoundedRectangleBorder(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
borderRadius: BorderRadius.circular(0),
|
||||||
children: [
|
),
|
||||||
Row(
|
shadows: [
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
BoxShadow(
|
||||||
children: [DelayedSpinnerWidget()],
|
color: appStyle.colors.background,
|
||||||
),
|
blurRadius: 30,
|
||||||
],
|
spreadRadius: 20,
|
||||||
);
|
offset: Offset(0, -25),
|
||||||
}
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
ttAnimatedCard,
|
||||||
|
Wrap(spacing: 10, children: ttWidgets),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user