remelem mukszik
This commit is contained in:
102
filcnaplo_mobile_ui/lib/pages/home/live_card/heads_up_countdown.dart
Executable file
102
filcnaplo_mobile_ui/lib/pages/home/live_card/heads_up_countdown.dart
Executable file
@@ -0,0 +1,102 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:animated_flip_counter/animated_flip_counter.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
|
||||
class HeadsUpCountdown extends StatefulWidget {
|
||||
const HeadsUpCountdown({Key? key, required this.maxTime, required this.elapsedTime}) : super(key: key);
|
||||
|
||||
final double maxTime;
|
||||
final double elapsedTime;
|
||||
|
||||
@override
|
||||
State<HeadsUpCountdown> createState() => _HeadsUpCountdownState();
|
||||
}
|
||||
|
||||
class _HeadsUpCountdownState extends State<HeadsUpCountdown> {
|
||||
static const _style = TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 70.0,
|
||||
letterSpacing: -.5,
|
||||
);
|
||||
|
||||
late final Timer _timer;
|
||||
late double elapsed;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
elapsed = widget.elapsedTime;
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
if (elapsed <= widget.maxTime) elapsed += 1;
|
||||
setState(() {});
|
||||
|
||||
if (elapsed >= widget.maxTime) {
|
||||
Future.delayed(const Duration(seconds: 5), () {
|
||||
if (mounted) Navigator.of(context).pop();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_timer.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final dur = Duration(seconds: (widget.maxTime - elapsed).round());
|
||||
return Center(
|
||||
child: Material(
|
||||
type: MaterialType.transparency,
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
AnimatedOpacity(
|
||||
opacity: dur.inSeconds > 0 ? 1.0 : 0.0,
|
||||
duration: const Duration(milliseconds: 500),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if ((dur.inHours % 24) > 0) ...[
|
||||
AnimatedFlipCounter(
|
||||
value: dur.inHours % 24,
|
||||
curve: Curves.fastLinearToSlowEaseIn,
|
||||
textStyle: _style,
|
||||
),
|
||||
const Text(":", style: _style),
|
||||
],
|
||||
AnimatedFlipCounter(
|
||||
duration: const Duration(seconds: 2),
|
||||
value: dur.inMinutes % 60,
|
||||
curve: Curves.fastLinearToSlowEaseIn,
|
||||
wholeDigits: (dur.inHours % 24) > 0 ? 2 : 1,
|
||||
textStyle: _style,
|
||||
),
|
||||
const Text(":", style: _style),
|
||||
AnimatedFlipCounter(
|
||||
duration: const Duration(seconds: 1),
|
||||
value: dur.inSeconds % 60,
|
||||
curve: Curves.fastLinearToSlowEaseIn,
|
||||
wholeDigits: 2,
|
||||
textStyle: _style,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (dur.inSeconds < 0)
|
||||
AnimatedOpacity(
|
||||
opacity: dur.inSeconds > 0 ? 0.0 : 1.0,
|
||||
duration: const Duration(milliseconds: 500),
|
||||
child: Lottie.asset("assets/animations/bell-alert.json", width: 400),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
197
filcnaplo_mobile_ui/lib/pages/home/live_card/live_card.dart
Executable file
197
filcnaplo_mobile_ui/lib/pages/home/live_card/live_card.dart
Executable file
@@ -0,0 +1,197 @@
|
||||
import 'package:animations/animations.dart';
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/helpers/subject.dart';
|
||||
import 'package:filcnaplo/icons/filc_icons.dart';
|
||||
import 'package:filcnaplo_mobile_ui/pages/home/live_card/heads_up_countdown.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:filcnaplo/utils/format.dart';
|
||||
import 'package:filcnaplo/api/providers/live_card_provider.dart';
|
||||
import 'package:filcnaplo_mobile_ui/pages/home/live_card/live_card_widget.dart';
|
||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||
import 'package:i18n_extension/i18n_widget.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'live_card.i18n.dart';
|
||||
|
||||
class LiveCard extends StatefulWidget {
|
||||
const LiveCard({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_LiveCardState createState() => _LiveCardState();
|
||||
}
|
||||
|
||||
class _LiveCardState extends State<LiveCard> {
|
||||
late void Function() listener;
|
||||
late UserProvider _userProvider;
|
||||
late LiveCardProvider liveCard;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
listener = () => setState(() {});
|
||||
_userProvider = Provider.of<UserProvider>(context, listen: false);
|
||||
liveCard = Provider.of<LiveCardProvider>(context, listen: false);
|
||||
_userProvider.addListener(liveCard.update);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_userProvider.removeListener(liveCard.update);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
liveCard = Provider.of<LiveCardProvider>(context);
|
||||
|
||||
if (!liveCard.show) return Container();
|
||||
|
||||
Widget child;
|
||||
Duration bellDelay = liveCard.delay;
|
||||
|
||||
switch (liveCard.currentState) {
|
||||
case LiveCardState.morning:
|
||||
child = LiveCardWidget(
|
||||
key: const Key('livecard.morning'),
|
||||
title: DateFormat("EEEE", I18n.of(context).locale.toString()).format(DateTime.now()).capital(),
|
||||
icon: FeatherIcons.sun,
|
||||
description: liveCard.nextLesson != null
|
||||
? Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(text: "first_lesson_1".i18n),
|
||||
TextSpan(
|
||||
text: liveCard.nextLesson!.subject.renamedTo ?? liveCard.nextLesson!.subject.name.capital(),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).colorScheme.secondary.withOpacity(.85),
|
||||
fontStyle: liveCard.nextLesson!.subject.isRenamed ? FontStyle.italic : null),
|
||||
),
|
||||
TextSpan(text: "first_lesson_2".i18n),
|
||||
TextSpan(
|
||||
text: liveCard.nextLesson!.room.capital(),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).colorScheme.secondary.withOpacity(.85),
|
||||
),
|
||||
),
|
||||
TextSpan(text: "first_lesson_3".i18n),
|
||||
TextSpan(
|
||||
text: DateFormat('H:mm').format(liveCard.nextLesson!.start),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).colorScheme.secondary.withOpacity(.85),
|
||||
),
|
||||
),
|
||||
TextSpan(text: "first_lesson_4".i18n),
|
||||
],
|
||||
),
|
||||
)
|
||||
: null,
|
||||
);
|
||||
break;
|
||||
case LiveCardState.duringLesson:
|
||||
final elapsedTime = DateTime.now().difference(liveCard.currentLesson!.start).inSeconds.toDouble() + bellDelay.inSeconds;
|
||||
final maxTime = liveCard.currentLesson!.end.difference(liveCard.currentLesson!.start).inSeconds.toDouble();
|
||||
|
||||
final showMinutes = maxTime - elapsedTime > 60;
|
||||
|
||||
child = LiveCardWidget(
|
||||
key: const Key('livecard.duringLesson'),
|
||||
leading: liveCard.currentLesson!.lessonIndex + (RegExp(r'\d').hasMatch(liveCard.currentLesson!.lessonIndex) ? "." : ""),
|
||||
title: liveCard.currentLesson!.subject.renamedTo ?? liveCard.currentLesson!.subject.name.capital(),
|
||||
titleItalic: liveCard.currentLesson!.subject.isRenamed,
|
||||
subtitle: liveCard.currentLesson!.room,
|
||||
icon: SubjectIcon.resolveVariant(subject: liveCard.currentLesson!.subject, context: context),
|
||||
description: liveCard.currentLesson!.description != "" ? Text(liveCard.currentLesson!.description) : null,
|
||||
nextSubject: liveCard.nextLesson?.subject.renamedTo ?? liveCard.nextLesson?.subject.name.capital(),
|
||||
nextSubjectItalic: liveCard.nextLesson?.subject.isRenamed ?? false,
|
||||
nextRoom: liveCard.nextLesson?.room,
|
||||
progressMax: showMinutes ? maxTime / 60 : maxTime,
|
||||
progressCurrent: showMinutes ? elapsedTime / 60 : elapsedTime,
|
||||
progressAccuracy: showMinutes ? ProgressAccuracy.minutes : ProgressAccuracy.seconds,
|
||||
onProgressTap: () {
|
||||
showDialog(
|
||||
barrierColor: Colors.black,
|
||||
context: context,
|
||||
builder: (context) => HeadsUpCountdown(maxTime: maxTime, elapsedTime: elapsedTime),
|
||||
);
|
||||
},
|
||||
);
|
||||
break;
|
||||
case LiveCardState.duringBreak:
|
||||
final iconFloorMap = {
|
||||
"to room": FeatherIcons.chevronsRight,
|
||||
"up floor": FilcIcons.upstairs,
|
||||
"down floor": FilcIcons.downstairs,
|
||||
"ground floor": FilcIcons.downstairs,
|
||||
};
|
||||
|
||||
final diff = liveCard.getFloorDifference();
|
||||
|
||||
final maxTime = liveCard.nextLesson!.start.difference(liveCard.prevLesson!.end).inSeconds.toDouble();
|
||||
final elapsedTime = DateTime.now().difference(liveCard.prevLesson!.end).inSeconds.toDouble() + bellDelay.inSeconds.toDouble();
|
||||
|
||||
final showMinutes = maxTime - elapsedTime > 60;
|
||||
|
||||
child = LiveCardWidget(
|
||||
key: const Key('livecard.duringBreak'),
|
||||
title: "break".i18n,
|
||||
icon: iconFloorMap[diff],
|
||||
description: liveCard.nextLesson!.room != liveCard.prevLesson!.room
|
||||
? Text("go $diff".i18n.fill([diff != "to room" ? (liveCard.nextLesson!.getFloor() ?? 0) : liveCard.nextLesson!.room]))
|
||||
: Text("stay".i18n),
|
||||
nextSubject: liveCard.nextLesson?.subject.renamedTo ?? liveCard.nextLesson?.subject.name.capital(),
|
||||
nextSubjectItalic: liveCard.nextLesson?.subject.isRenamed ?? false,
|
||||
nextRoom: diff != "to room" ? liveCard.nextLesson?.room : null,
|
||||
progressMax: showMinutes ? maxTime / 60 : maxTime,
|
||||
progressCurrent: showMinutes ? elapsedTime / 60 : elapsedTime,
|
||||
progressAccuracy: showMinutes ? ProgressAccuracy.minutes : ProgressAccuracy.seconds,
|
||||
onProgressTap: () {
|
||||
showDialog(
|
||||
barrierColor: Colors.black,
|
||||
context: context,
|
||||
builder: (context) => HeadsUpCountdown(
|
||||
maxTime: maxTime,
|
||||
elapsedTime: elapsedTime,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
break;
|
||||
case LiveCardState.afternoon:
|
||||
child = LiveCardWidget(
|
||||
key: const Key('livecard.afternoon'),
|
||||
title: DateFormat("EEEE", I18n.of(context).locale.toString()).format(DateTime.now()).capital(),
|
||||
icon: FeatherIcons.coffee,
|
||||
);
|
||||
break;
|
||||
case LiveCardState.night:
|
||||
child = LiveCardWidget(
|
||||
key: const Key('livecard.night'),
|
||||
title: DateFormat("EEEE", I18n.of(context).locale.toString()).format(DateTime.now()).capital(),
|
||||
icon: FeatherIcons.moon,
|
||||
);
|
||||
break;
|
||||
default:
|
||||
child = Container();
|
||||
}
|
||||
|
||||
return PageTransitionSwitcher(
|
||||
transitionBuilder: (
|
||||
Widget child,
|
||||
Animation<double> primaryAnimation,
|
||||
Animation<double> secondaryAnimation,
|
||||
) {
|
||||
return SharedAxisTransition(
|
||||
animation: primaryAnimation,
|
||||
secondaryAnimation: secondaryAnimation,
|
||||
transitionType: SharedAxisTransitionType.horizontal,
|
||||
child: child,
|
||||
fillColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
);
|
||||
},
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
57
filcnaplo_mobile_ui/lib/pages/home/live_card/live_card.i18n.dart
Executable file
57
filcnaplo_mobile_ui/lib/pages/home/live_card/live_card.i18n.dart
Executable file
@@ -0,0 +1,57 @@
|
||||
import 'package:i18n_extension/i18n_extension.dart';
|
||||
|
||||
extension Localization on String {
|
||||
static final _t = Translations.byLocale("hu_hu") +
|
||||
{
|
||||
"en_en": {
|
||||
"next": "Next",
|
||||
"remaining min": "%d mins".one("%d min"),
|
||||
"remaining sec": "%d secs".one("%d sec"),
|
||||
"break": "Break",
|
||||
"go to room": "Go to room %s.",
|
||||
"go ground floor": "Go to the ground floor.",
|
||||
"go up floor": "Go upstairs, to floor %d.",
|
||||
"go down floor": "Go downstaris, to floor %d.",
|
||||
"stay": "Stay in this room.",
|
||||
"first_lesson_1": "Your first lesson will be ",
|
||||
"first_lesson_2": " in room ",
|
||||
"first_lesson_3": ", at ",
|
||||
"first_lesson_4": ".",
|
||||
},
|
||||
"hu_hu": {
|
||||
"next": "Következő",
|
||||
"remaining min": "%d perc".one("%d perc"),
|
||||
"remaining sec": "%d másodperc".one("%d másodperc"),
|
||||
"break": "Szünet",
|
||||
"go to room": "Menj a(z) %s terembe.",
|
||||
"go ground floor": "Menj a földszintre.",
|
||||
"go up floor": "Menj fel a(z) %d. emeletre.",
|
||||
"go down floor": "Menj le a(z) %d. emeletre.",
|
||||
"stay": "Maradj ebben a teremben.",
|
||||
"first_lesson_1": "Az első órád ",
|
||||
"first_lesson_2": " lesz, a ",
|
||||
"first_lesson_3": " teremben, ",
|
||||
"first_lesson_4": "-kor.",
|
||||
},
|
||||
"de_de": {
|
||||
"next": "Nächste",
|
||||
"remaining min": "%d Minuten".one("%d Minute"),
|
||||
"remaining sec": "%d Sekunden".one("%d Sekunden"),
|
||||
"break": "Pause",
|
||||
"go to room": "Geh in den Raum %s.",
|
||||
"go ground floor": "Geh dir Treppe hinunter.",
|
||||
"go up floor": "Geh in die %d. Stock hinauf.",
|
||||
"go down floor": "Geh runter in den %d. Stock.",
|
||||
"stay": "Im Zimmer bleiben.",
|
||||
"first_lesson_1": "Ihre erste Stunde ist ",
|
||||
"first_lesson_2": ", in Raum ",
|
||||
"first_lesson_3": ", um ",
|
||||
"first_lesson_4": " Uhr.",
|
||||
},
|
||||
};
|
||||
|
||||
String get i18n => localize(this, _t);
|
||||
String fill(List<Object> params) => localizeFill(this, params);
|
||||
String plural(int value) => localizePlural(value, this, _t);
|
||||
String version(Object modifier) => localizeVersion(modifier, this, _t);
|
||||
}
|
||||
247
filcnaplo_mobile_ui/lib/pages/home/live_card/live_card_widget.dart
Executable file
247
filcnaplo_mobile_ui/lib/pages/home/live_card/live_card_widget.dart
Executable file
@@ -0,0 +1,247 @@
|
||||
import 'package:filcnaplo/theme/colors/colors.dart';
|
||||
import 'package:filcnaplo_mobile_ui/common/progress_bar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||
import 'live_card.i18n.dart';
|
||||
|
||||
enum ProgressAccuracy { minutes, seconds }
|
||||
|
||||
class LiveCardWidget extends StatefulWidget {
|
||||
const LiveCardWidget({
|
||||
Key? key,
|
||||
this.leading,
|
||||
this.title,
|
||||
this.titleItalic = false,
|
||||
this.subtitle,
|
||||
this.icon,
|
||||
this.description,
|
||||
this.nextRoom,
|
||||
this.nextSubject,
|
||||
this.nextSubjectItalic = false,
|
||||
this.progressCurrent,
|
||||
this.progressMax,
|
||||
this.progressAccuracy = ProgressAccuracy.minutes,
|
||||
this.onProgressTap,
|
||||
}) : super(key: key);
|
||||
|
||||
final String? leading;
|
||||
final String? title;
|
||||
final bool titleItalic;
|
||||
final String? subtitle;
|
||||
final IconData? icon;
|
||||
final Widget? description;
|
||||
final String? nextSubject;
|
||||
final bool nextSubjectItalic;
|
||||
final String? nextRoom;
|
||||
final double? progressCurrent;
|
||||
final double? progressMax;
|
||||
final ProgressAccuracy? progressAccuracy;
|
||||
final Function()? onProgressTap;
|
||||
|
||||
@override
|
||||
State<LiveCardWidget> createState() => _LiveCardWidgetState();
|
||||
}
|
||||
|
||||
class _LiveCardWidgetState extends State<LiveCardWidget> {
|
||||
bool hold = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onLongPressDown: (_) => setState(() => hold = true),
|
||||
onLongPressEnd: (_) => setState(() => hold = false),
|
||||
onLongPressCancel: () => setState(() => hold = false),
|
||||
child: AnimatedScale(
|
||||
scale: hold ? 1.03 : 1.0,
|
||||
curve: Curves.easeInOutBack,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
borderRadius: BorderRadius.circular(16.0),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
offset: const Offset(0, 21),
|
||||
blurRadius: 23.0,
|
||||
color: Theme.of(context).shadowColor,
|
||||
)
|
||||
],
|
||||
),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6.0),
|
||||
child: OverflowBox(
|
||||
maxHeight: 96.0,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (widget.leading != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 12.0, top: 8.0),
|
||||
child: Text(
|
||||
widget.leading!,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 32.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
if (widget.title != null)
|
||||
Expanded(
|
||||
child: Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(text: widget.title!, style: TextStyle(fontStyle: widget.titleItalic ? FontStyle.italic : null)),
|
||||
if (widget.subtitle != null)
|
||||
WidgetSpan(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(left: 6.0, bottom: 3.0),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4.0, vertical: 2.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.secondary.withOpacity(.3),
|
||||
borderRadius: BorderRadius.circular(4.0),
|
||||
),
|
||||
child: Text(
|
||||
widget.subtitle!,
|
||||
style: TextStyle(
|
||||
height: 1.2,
|
||||
fontSize: 14.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 22.0),
|
||||
maxLines: 1,
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
if (widget.title != null) const SizedBox(width: 6.0),
|
||||
if (widget.icon != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||||
child: Icon(
|
||||
widget.icon,
|
||||
size: 26.0,
|
||||
color: AppColors.of(context).text.withOpacity(.75),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (widget.description != null)
|
||||
DefaultTextStyle(
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 16.0,
|
||||
height: 1.0,
|
||||
color: AppColors.of(context).text.withOpacity(.75),
|
||||
),
|
||||
maxLines: !(widget.nextSubject == null && widget.progressCurrent == null && widget.progressMax == null) ? 1 : 2,
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
child: widget.description!,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (!(widget.nextSubject == null && widget.progressCurrent == null && widget.progressMax == null))
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
if (widget.nextSubject != null) const Icon(FeatherIcons.arrowRight, size: 12.0),
|
||||
if (widget.nextSubject != null) const SizedBox(width: 4.0),
|
||||
if (widget.nextSubject != null)
|
||||
Expanded(
|
||||
child: Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: widget.nextSubject!, style: TextStyle(fontStyle: widget.nextSubjectItalic ? FontStyle.italic : null)),
|
||||
if (widget.nextRoom != null)
|
||||
WidgetSpan(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(left: 4.0),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 3.0, vertical: 1.5),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.secondary.withOpacity(.25),
|
||||
borderRadius: BorderRadius.circular(4.0),
|
||||
),
|
||||
child: Text(
|
||||
widget.nextRoom!,
|
||||
style: TextStyle(
|
||||
height: 1.1,
|
||||
fontSize: 11.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).colorScheme.secondary.withOpacity(.9),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
style: TextStyle(
|
||||
color: AppColors.of(context).text.withOpacity(.8),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: false,
|
||||
),
|
||||
),
|
||||
if (widget.nextRoom == null && widget.nextSubject == null) const Spacer(),
|
||||
if (widget.progressCurrent != null && widget.progressMax != null)
|
||||
GestureDetector(
|
||||
onTap: widget.onProgressTap,
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
child: Text(
|
||||
"remaining ${widget.progressAccuracy == ProgressAccuracy.minutes ? 'min' : 'sec'}"
|
||||
.plural((widget.progressMax! - widget.progressCurrent!).round()),
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.of(context).text.withOpacity(.75),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
if (widget.progressCurrent != null && widget.progressMax != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||||
child: ProgressBar(value: widget.progressCurrent! / widget.progressMax!),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user