217 lines
6.2 KiB
Dart
217 lines
6.2 KiB
Dart
import 'dart:math';
|
|
|
|
import 'package:auto_route/auto_route.dart';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import 'package:mnemo_cards/flags.dart';
|
|
import 'package:rxdart/rxdart.dart';
|
|
|
|
import '../../theme/themes.dart';
|
|
|
|
class ProgressWidget extends StatefulWidget {
|
|
final Color color;
|
|
final List<Result>? results;
|
|
final int length;
|
|
final Stream<Duration>? timer;
|
|
final bool showMic;
|
|
final bool showSound;
|
|
final String? popText;
|
|
final ValueGetter<Object?>? popValue;
|
|
|
|
@override
|
|
State<StatefulWidget> createState() => _ProgressWidgetState();
|
|
|
|
factory ProgressWidget.value(int value, int length, Color color) =>
|
|
ProgressWidget(
|
|
List.generate(
|
|
length,
|
|
(i) => i < value ? Result.correct : Result.not_visited,
|
|
),
|
|
length,
|
|
color,
|
|
);
|
|
|
|
ProgressWidget(
|
|
this.results,
|
|
this.length,
|
|
this.color, {
|
|
this.timer,
|
|
this.popValue,
|
|
this.showMic = false,
|
|
this.showSound = false,
|
|
this.popText,
|
|
super.key,
|
|
});
|
|
}
|
|
|
|
enum Result {
|
|
correct,
|
|
wrong,
|
|
skiped,
|
|
not_visited,
|
|
}
|
|
|
|
class _ProgressWidgetState extends State<ProgressWidget> {
|
|
List<Result> get results => widget.results!;
|
|
|
|
int get length => widget.length;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Row(
|
|
children: [
|
|
TapRegion(
|
|
onTapInside: AutoRouter.of(context).maybePop,
|
|
behavior: HitTestBehavior.opaque,
|
|
child: Container(
|
|
height: 30.h,
|
|
child: Row(
|
|
children: [
|
|
Image.asset(
|
|
'icons/back.png',
|
|
color: Colors.black,
|
|
width: 17,
|
|
height: 23.h,
|
|
),
|
|
if (widget.popText != null)
|
|
Padding(
|
|
padding: const EdgeInsets.only(left: 4.0),
|
|
child: Text(
|
|
widget.popText!,
|
|
style: TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w400,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
Expanded(
|
|
child: widget.results == null
|
|
? SizedBox.shrink()
|
|
: Padding(
|
|
padding: EdgeInsets.only(left: 10.0.w),
|
|
child: ClipRRect(
|
|
borderRadius: BorderRadius.circular(16.h),
|
|
child: Container(
|
|
height: 16.h,
|
|
color: white,
|
|
child: Stack(
|
|
alignment: Alignment.center,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: AnimatedFractionallySizedBox(
|
|
alignment: Alignment.centerLeft,
|
|
widthFactor: length == 0
|
|
? 0
|
|
: (results
|
|
.where((r) =>
|
|
r != Result.not_visited)
|
|
.length) /
|
|
length,
|
|
duration: Duration(milliseconds: 300),
|
|
child: Container(
|
|
color: widget.color,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
if (widget.showMic)
|
|
Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 10.0.w),
|
|
child: Image.asset(
|
|
'icons/mic_on.png',
|
|
height: 18.h,
|
|
width: 13.w,
|
|
),
|
|
),
|
|
if (widget.showSound)
|
|
Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 10.0.w),
|
|
child: Image.asset(
|
|
'icons/sound_on.png',
|
|
height: 18.h,
|
|
width: 24.w,
|
|
),
|
|
),
|
|
if (widget.timer != null)
|
|
Padding(
|
|
padding: EdgeInsets.only(left: 10.0.w),
|
|
child: _TimeWidget(widget.timer),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _text() {
|
|
return Text(
|
|
results.where((r) => r != Result.skiped).length < length
|
|
? '${results.where((r) => r != Result.skiped).length + 1} из ${length}'
|
|
: '$length',
|
|
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
|
fontWeight: FontWeight.w800,
|
|
),
|
|
);
|
|
}
|
|
|
|
_ProgressWidgetState();
|
|
}
|
|
|
|
class _TimeWidget extends StatelessWidget {
|
|
final Stream<Duration>? timer;
|
|
|
|
_TimeWidget(Stream<Duration>? timer) : this.timer = timer;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return SizedBox(
|
|
width: 68.w,
|
|
child: StreamBuilder<Duration>(
|
|
stream: timer,
|
|
builder: (context, snapshot) {
|
|
var text = '-:-';
|
|
if (snapshot.hasData) {
|
|
final minutes = snapshot.data?.inMinutes ?? 0;
|
|
final seconds = (snapshot.data?.inSeconds ?? 0) - 60 * minutes;
|
|
text =
|
|
"${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}";
|
|
}
|
|
return Row(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
mainAxisSize: MainAxisSize.max,
|
|
children: [
|
|
Image.asset(
|
|
'icons/clock.png',
|
|
width: 15.w,
|
|
height: 15.h,
|
|
),
|
|
SizedBox(
|
|
width: 4.0.w,
|
|
),
|
|
Text(
|
|
text,
|
|
style: TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w400,
|
|
),
|
|
)
|
|
],
|
|
);
|
|
}),
|
|
);
|
|
}
|
|
}
|