chore: fix level up notification to screen, show it immeadiatley then load details (#2604)
This commit is contained in:
parent
f89a346f79
commit
6fd6d19fef
4 changed files with 427 additions and 335 deletions
|
|
@ -389,9 +389,8 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
(update) {
|
||||
if (update['level_up'] != null) {
|
||||
LevelUpUtil.showLevelUpDialog(
|
||||
update['level_up'],
|
||||
update['analytics_room_id'],
|
||||
update['construct_summary'],
|
||||
update['upper_level'],
|
||||
update['lower_level'],
|
||||
context,
|
||||
);
|
||||
} else if (update['unlocked_constructs'] != null) {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ import '../../widgets/matrix.dart';
|
|||
import 'package:fluffychat/utils/tor_stub.dart'
|
||||
if (dart.library.html) 'package:tor_detector_web/tor_detector_web.dart';
|
||||
|
||||
|
||||
enum PopupMenuAction {
|
||||
settings,
|
||||
invite,
|
||||
|
|
|
|||
|
|
@ -202,15 +202,11 @@ class GetAnalyticsController extends BaseController {
|
|||
),
|
||||
);
|
||||
|
||||
Future<void> _onLevelUp(final int lowerLevel, final int upperLevel) async {
|
||||
final result = await _generateLevelUpAnalyticsAndSaveToStateEvent(
|
||||
lowerLevel,
|
||||
upperLevel,
|
||||
);
|
||||
void _onLevelUp(final int lowerLevel, final int upperLevel) {
|
||||
setState({
|
||||
'level_up': constructListModel.level,
|
||||
'analytics_room_id': _client.analyticsRoomLocal(_l2!)?.id,
|
||||
"construct_summary": result,
|
||||
'upper_level': upperLevel,
|
||||
'lower_level': lowerLevel,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -465,7 +461,7 @@ class GetAnalyticsController extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
Future<ConstructSummary?> _generateLevelUpAnalyticsAndSaveToStateEvent(
|
||||
Future<ConstructSummary?> generateLevelUpAnalytics(
|
||||
final int lowerLevel,
|
||||
final int upperLevel,
|
||||
) async {
|
||||
|
|
|
|||
|
|
@ -7,8 +7,10 @@ import 'package:cached_network_image/cached_network_image.dart';
|
|||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/analytics_constants.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/learning_skills_enum.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/overlay.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_repo.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
|
|
@ -20,8 +22,7 @@ class LevelUpConstants {
|
|||
class LevelUpUtil {
|
||||
static Future<void> showLevelUpDialog(
|
||||
int level,
|
||||
String? analyticsRoomId,
|
||||
ConstructSummary? constructSummary,
|
||||
int prevLevel,
|
||||
BuildContext context,
|
||||
) async {
|
||||
final player = AudioPlayer();
|
||||
|
|
@ -33,51 +34,42 @@ class LevelUpUtil {
|
|||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
}
|
||||
|
||||
player.play(
|
||||
UrlSource(
|
||||
"${AppConfig.assetsBaseURL}/${AnalyticsConstants.levelUpAudioFileName}",
|
||||
),
|
||||
);
|
||||
player
|
||||
.play(
|
||||
UrlSource(
|
||||
"${AppConfig.assetsBaseURL}/${AnalyticsConstants.levelUpAudioFileName}",
|
||||
),
|
||||
)
|
||||
.then(
|
||||
(_) => Future.delayed(
|
||||
const Duration(seconds: 2),
|
||||
() => player.dispose(),
|
||||
),
|
||||
);
|
||||
|
||||
final ValueNotifier<bool> showDetailsClicked = ValueNotifier(false);
|
||||
|
||||
late final OverlayEntry overlayEntry;
|
||||
overlayEntry = OverlayEntry(
|
||||
builder: (context) => LevelUpBanner(
|
||||
OverlayUtil.showOverlay(
|
||||
overlayKey: "level_up_notification",
|
||||
context: context,
|
||||
child: LevelUpBanner(
|
||||
level: level,
|
||||
constructSummary: constructSummary,
|
||||
onDetailsClicked: () {
|
||||
showDetailsClicked.value = true;
|
||||
},
|
||||
onOverlayExit: () {
|
||||
overlayEntry.remove();
|
||||
player.dispose();
|
||||
},
|
||||
prevLevel: prevLevel,
|
||||
),
|
||||
transformTargetId: '',
|
||||
position: OverlayPositionEnum.top,
|
||||
backDropToDismiss: false,
|
||||
closePrevOverlay: false,
|
||||
canPop: false,
|
||||
);
|
||||
|
||||
Overlay.of(context).insert(overlayEntry);
|
||||
|
||||
Future.delayed(const Duration(seconds: 5), () {
|
||||
if (!showDetailsClicked.value) {
|
||||
overlayEntry.remove();
|
||||
player.dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class LevelUpBanner extends StatefulWidget {
|
||||
final int level;
|
||||
final ConstructSummary? constructSummary;
|
||||
final VoidCallback onDetailsClicked;
|
||||
final VoidCallback onOverlayExit;
|
||||
final int prevLevel;
|
||||
|
||||
const LevelUpBanner({
|
||||
required this.level,
|
||||
this.constructSummary,
|
||||
required this.onDetailsClicked,
|
||||
required this.onOverlayExit,
|
||||
required this.prevLevel,
|
||||
super.key,
|
||||
});
|
||||
|
||||
|
|
@ -86,17 +78,28 @@ class LevelUpBanner extends StatefulWidget {
|
|||
}
|
||||
|
||||
class LevelUpBannerState extends State<LevelUpBanner>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late AnimationController _controller;
|
||||
with TickerProviderStateMixin {
|
||||
late AnimationController _slideController;
|
||||
late Animation<Offset> _slideAnimation;
|
||||
|
||||
late AnimationController _sizeController;
|
||||
late Animation<double> _sizeAnimation;
|
||||
|
||||
bool _showDetails = false;
|
||||
bool _showedDetails = false;
|
||||
|
||||
ConstructSummary? _constructSummary;
|
||||
bool _loading = true;
|
||||
String? _error;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = AnimationController(
|
||||
_setConstructSummary();
|
||||
|
||||
_slideController = AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 500),
|
||||
duration: FluffyThemes.animationDuration,
|
||||
);
|
||||
|
||||
_slideAnimation = Tween<Offset>(
|
||||
|
|
@ -104,322 +107,417 @@ class LevelUpBannerState extends State<LevelUpBanner>
|
|||
end: Offset.zero,
|
||||
).animate(
|
||||
CurvedAnimation(
|
||||
parent: _controller,
|
||||
parent: _slideController,
|
||||
curve: Curves.easeOut,
|
||||
),
|
||||
);
|
||||
|
||||
_controller.forward();
|
||||
_sizeController = AnimationController(
|
||||
vsync: this,
|
||||
duration: FluffyThemes.animationDuration,
|
||||
);
|
||||
|
||||
_sizeAnimation = Tween<double>(
|
||||
begin: 0,
|
||||
end: 1,
|
||||
).animate(
|
||||
CurvedAnimation(
|
||||
parent: _sizeController,
|
||||
curve: Curves.easeOut,
|
||||
),
|
||||
);
|
||||
|
||||
_slideController.forward();
|
||||
|
||||
MatrixState.pangeaController.getAnalytics
|
||||
.generateLevelUpAnalytics(
|
||||
widget.level,
|
||||
widget.prevLevel,
|
||||
)
|
||||
.then((summary) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_constructSummary = summary;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Future.delayed(const Duration(seconds: 15), () async {
|
||||
if (mounted && !_showedDetails) _close();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
_slideController.dispose();
|
||||
_sizeController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _setConstructSummary() async {
|
||||
try {
|
||||
_constructSummary = await MatrixState.pangeaController.getAnalytics
|
||||
.generateLevelUpAnalytics(
|
||||
widget.level,
|
||||
widget.prevLevel,
|
||||
);
|
||||
} catch (e) {
|
||||
_error = e.toString();
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() => _loading = false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _close() async {
|
||||
await _slideController.reverse();
|
||||
MatrixState.pAnyState.closeOverlay("level_up_notification");
|
||||
}
|
||||
|
||||
int _skillsPoints(LearningSkillsEnum skill) {
|
||||
switch (skill) {
|
||||
case LearningSkillsEnum.writing:
|
||||
return widget.constructSummary?.writingConstructScore ?? 0;
|
||||
return _constructSummary?.writingConstructScore ?? 0;
|
||||
case LearningSkillsEnum.reading:
|
||||
return widget.constructSummary?.readingConstructScore ?? 0;
|
||||
return _constructSummary?.readingConstructScore ?? 0;
|
||||
case LearningSkillsEnum.speaking:
|
||||
return widget.constructSummary?.speakingConstructScore ?? 0;
|
||||
return _constructSummary?.speakingConstructScore ?? 0;
|
||||
case LearningSkillsEnum.hearing:
|
||||
return widget.constructSummary?.hearingConstructScore ?? 0;
|
||||
return _constructSummary?.hearingConstructScore ?? 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _toggleDetails() async {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_showDetails = !_showDetails;
|
||||
if (_showDetails && !_showedDetails) {
|
||||
_showedDetails = true;
|
||||
}
|
||||
});
|
||||
|
||||
await (_showDetails
|
||||
? _sizeController.forward()
|
||||
: _sizeController.reverse());
|
||||
|
||||
if (!_showDetails) {
|
||||
await Future.delayed(
|
||||
const Duration(milliseconds: 300),
|
||||
() async {
|
||||
if (!mounted) return;
|
||||
_close();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
children: [
|
||||
if (_showDetails)
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_showDetails = false;
|
||||
});
|
||||
widget.onOverlayExit();
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.black.withAlpha(180),
|
||||
),
|
||||
),
|
||||
SlideTransition(
|
||||
position: _slideAnimation,
|
||||
child: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: MediaQuery.of(context).size.width * 0.5,
|
||||
maxHeight: MediaQuery.of(context).size.height * 0.75,
|
||||
),
|
||||
margin: const EdgeInsets.only(top: 16),
|
||||
decoration: BoxDecoration(
|
||||
color: widget.level > 10
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.secondaryContainer,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
horizontal: 24,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: L10n.of(context).congratulationsOnReaching,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 0.5,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: "${L10n.of(context).level} ",
|
||||
style: const TextStyle(
|
||||
color: AppConfig.gold,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 0.5,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: "${widget.level} ",
|
||||
style: const TextStyle(
|
||||
color: AppConfig.gold,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 0.5,
|
||||
),
|
||||
),
|
||||
WidgetSpan(
|
||||
child: CachedNetworkImage(
|
||||
imageUrl:
|
||||
"${AppConfig.assetsBaseURL}/${LevelUpConstants.starFileName}",
|
||||
height: 24,
|
||||
width: 24,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_showDetails = !_showDetails;
|
||||
});
|
||||
widget.onDetailsClicked();
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.white,
|
||||
foregroundColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.surfaceContainerHighest,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${L10n.of(context).seeDetails} ",
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: AppConfig.gold,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
padding: const EdgeInsets.all(
|
||||
4.0,
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.keyboard_arrow_down_rounded,
|
||||
size: 20,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
final style = FluffyThemes.isColumnMode(context)
|
||||
? Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 0.5,
|
||||
)
|
||||
: Theme.of(context).textTheme.bodyLarge?.copyWith(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 0.5,
|
||||
);
|
||||
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: Stack(
|
||||
children: [
|
||||
SlideTransition(
|
||||
position: _slideAnimation,
|
||||
child: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 600.0,
|
||||
),
|
||||
AnimatedSize(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOut,
|
||||
child: _showDetails
|
||||
? Container(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: MediaQuery.of(context).size.width * 0.5,
|
||||
maxHeight:
|
||||
MediaQuery.of(context).size.height * 0.75,
|
||||
),
|
||||
margin: const EdgeInsets.only(
|
||||
top: 16,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 24.0,
|
||||
children: [
|
||||
Table(
|
||||
columnWidths: const {
|
||||
0: IntrinsicColumnWidth(),
|
||||
1: FlexColumnWidth(),
|
||||
2: IntrinsicColumnWidth(),
|
||||
},
|
||||
defaultVerticalAlignment:
|
||||
TableCellVerticalAlignment.middle,
|
||||
children: [
|
||||
...LearningSkillsEnum.values
|
||||
.where(
|
||||
(v) =>
|
||||
v.isVisible && _skillsPoints(v) > -1,
|
||||
)
|
||||
.map((skill) {
|
||||
return TableRow(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 9.0,
|
||||
horizontal: 18.0,
|
||||
),
|
||||
child: Icon(
|
||||
skill.icon,
|
||||
size: 25,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 9.0,
|
||||
horizontal: 18.0,
|
||||
),
|
||||
child: Text(
|
||||
skill.tooltip(context),
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 9.0,
|
||||
horizontal: 18.0,
|
||||
),
|
||||
child: Text(
|
||||
"+ ${_skillsPoints(skill)} XP",
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
CachedNetworkImage(
|
||||
imageUrl:
|
||||
"${AppConfig.assetsBaseURL}/${LevelUpConstants.dinoLevelUPFileName}",
|
||||
width: 400,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
if (widget.constructSummary?.textSummary !=
|
||||
null)
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondaryContainer,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Text(
|
||||
widget.constructSummary!.textSummary,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
margin: const EdgeInsets.only(
|
||||
top: 16,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: widget.level > 10
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.secondaryContainer,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
horizontal: 24,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
spacing: 8.0,
|
||||
children: [
|
||||
Flexible(
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: L10n.of(context)
|
||||
.congratulationsOnReaching,
|
||||
style: style,
|
||||
),
|
||||
TextSpan(
|
||||
text: "${L10n.of(context).level} ",
|
||||
style: style,
|
||||
),
|
||||
TextSpan(
|
||||
text: "${widget.level} ",
|
||||
style: style,
|
||||
),
|
||||
WidgetSpan(
|
||||
child: CachedNetworkImage(
|
||||
imageUrl:
|
||||
"${AppConfig.assetsBaseURL}/${LevelUpConstants.starFileName}",
|
||||
height: 24,
|
||||
width: 24,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
// Share button, currently no functionality
|
||||
// ElevatedButton(
|
||||
// onPressed: () {
|
||||
// // Add share functionality
|
||||
// },
|
||||
// style: ElevatedButton.styleFrom(
|
||||
// backgroundColor: Colors.white,
|
||||
// foregroundColor: Colors.black,
|
||||
// padding: const EdgeInsets.symmetric(
|
||||
// vertical: 12,
|
||||
// horizontal: 24,
|
||||
// ),
|
||||
// shape: RoundedRectangleBorder(
|
||||
// borderRadius: BorderRadius.circular(8),
|
||||
// ),
|
||||
// ),
|
||||
// child: const Row(
|
||||
// mainAxisSize: MainAxisSize
|
||||
// .min,
|
||||
// children: [
|
||||
// Text(
|
||||
// "Share with Friends",
|
||||
// style: TextStyle(
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(
|
||||
// width: 8,
|
||||
// ),
|
||||
// Icon(
|
||||
// Icons.ios_share,
|
||||
// size: 20,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
AnimatedSize(
|
||||
duration: FluffyThemes.animationDuration,
|
||||
child: _error == null
|
||||
? ElevatedButton(
|
||||
onPressed: _error != null
|
||||
? null
|
||||
: _constructSummary != null
|
||||
? _toggleDetails
|
||||
: () {},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.white,
|
||||
foregroundColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.surfaceContainerHighest,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${L10n.of(context).seeDetails} ",
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: AppConfig.gold,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
padding: const EdgeInsets.all(
|
||||
4.0,
|
||||
),
|
||||
child: _loading
|
||||
? const CircularProgressIndicator
|
||||
.adaptive()
|
||||
: Icon(
|
||||
_showDetails
|
||||
? Icons
|
||||
.keyboard_arrow_down_rounded
|
||||
: Icons
|
||||
.keyboard_arrow_up_rounded,
|
||||
size: 20,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Row(
|
||||
children: [
|
||||
Tooltip(
|
||||
message: L10n.of(context)
|
||||
.oopsSomethingWentWrong,
|
||||
child: Icon(
|
||||
Icons.error,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.error,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: _close,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizeTransition(
|
||||
sizeFactor: _sizeAnimation,
|
||||
child: Container(
|
||||
constraints: BoxConstraints(
|
||||
maxHeight: MediaQuery.of(context).size.height * 0.75,
|
||||
),
|
||||
margin: const EdgeInsets.only(
|
||||
top: 16,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
spacing: 24.0,
|
||||
children: [
|
||||
Table(
|
||||
columnWidths: const {
|
||||
0: IntrinsicColumnWidth(),
|
||||
1: FlexColumnWidth(),
|
||||
2: IntrinsicColumnWidth(),
|
||||
},
|
||||
defaultVerticalAlignment:
|
||||
TableCellVerticalAlignment.middle,
|
||||
children: [
|
||||
...LearningSkillsEnum.values
|
||||
.where(
|
||||
(v) => v.isVisible && _skillsPoints(v) > -1,
|
||||
)
|
||||
.map((skill) {
|
||||
return TableRow(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 9.0,
|
||||
horizontal: 18.0,
|
||||
),
|
||||
child: Icon(
|
||||
skill.icon,
|
||||
size: 25,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 9.0,
|
||||
horizontal: 18.0,
|
||||
),
|
||||
child: Text(
|
||||
skill.tooltip(context),
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 9.0,
|
||||
horizontal: 18.0,
|
||||
),
|
||||
child: Text(
|
||||
"+ ${_skillsPoints(skill)} XP",
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
CachedNetworkImage(
|
||||
imageUrl:
|
||||
"${AppConfig.assetsBaseURL}/${LevelUpConstants.dinoLevelUPFileName}",
|
||||
width: 400,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
if (_constructSummary?.textSummary != null)
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondaryContainer,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Text(
|
||||
_constructSummary!.textSummary,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
// Share button, currently no functionality
|
||||
// ElevatedButton(
|
||||
// onPressed: () {
|
||||
// // Add share functionality
|
||||
// },
|
||||
// style: ElevatedButton.styleFrom(
|
||||
// backgroundColor: Colors.white,
|
||||
// foregroundColor: Colors.black,
|
||||
// padding: const EdgeInsets.symmetric(
|
||||
// vertical: 12,
|
||||
// horizontal: 24,
|
||||
// ),
|
||||
// shape: RoundedRectangleBorder(
|
||||
// borderRadius: BorderRadius.circular(8),
|
||||
// ),
|
||||
// ),
|
||||
// child: const Row(
|
||||
// mainAxisSize: MainAxisSize
|
||||
// .min,
|
||||
// children: [
|
||||
// Text(
|
||||
// "Share with Friends",
|
||||
// style: TextStyle(
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(
|
||||
// width: 8,
|
||||
// ),
|
||||
// Icon(
|
||||
// Icons.ios_share,
|
||||
// size: 20,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue