Revert "Merge branch 'feature/193-statisticsview-rework' into development"
All checks were successful
Push Pipeline / update_version (push) Successful in 6s
Push Pipeline / generate_licenses (push) Successful in 38s
Push Pipeline / generate_localizations (push) Successful in 29s
Push Pipeline / test (push) Successful in 1m35s
Push Pipeline / sort_arb_files (push) Successful in 31s
Push Pipeline / format (push) Successful in 55s
Push Pipeline / build (push) Successful in 4m58s
All checks were successful
Push Pipeline / update_version (push) Successful in 6s
Push Pipeline / generate_licenses (push) Successful in 38s
Push Pipeline / generate_localizations (push) Successful in 29s
Push Pipeline / test (push) Successful in 1m35s
Push Pipeline / sort_arb_files (push) Successful in 31s
Push Pipeline / format (push) Successful in 55s
Push Pipeline / build (push) Successful in 4m58s
This reverts commit24f49e17b9, reversing changes made todba6c218d6. # Conflicts: # pubspec.yaml
This commit is contained in:
@@ -6,13 +6,11 @@ class AppSkeleton extends StatefulWidget {
|
||||
/// - [child]: The widget tree to apply the skeleton effect to.
|
||||
/// - [enabled]: A boolean to enable or disable the skeleton effect.
|
||||
/// - [fixLayoutBuilder]: A boolean to fix the layout builder for AnimatedSwitcher.
|
||||
/// - [alignment]: The alignment used for the custom layout builder and optional Align wrapper. Defaults to [Alignment.center].
|
||||
const AppSkeleton({
|
||||
super.key,
|
||||
required this.child,
|
||||
this.enabled = true,
|
||||
this.fixLayoutBuilder = false,
|
||||
this.alignment = Alignment.center,
|
||||
});
|
||||
|
||||
/// The widget tree to apply the skeleton effect to.
|
||||
@@ -24,9 +22,6 @@ class AppSkeleton extends StatefulWidget {
|
||||
/// A boolean to fix the layout builder for AnimatedSwitcher.
|
||||
final bool fixLayoutBuilder;
|
||||
|
||||
/// The alignment used for the custom layout builder and optional Align wrapper
|
||||
final Alignment alignment;
|
||||
|
||||
@override
|
||||
State<AppSkeleton> createState() => _AppSkeletonState();
|
||||
}
|
||||
@@ -50,14 +45,13 @@ class _AppSkeletonState extends State<AppSkeleton> {
|
||||
layoutBuilder: !widget.fixLayoutBuilder
|
||||
? AnimatedSwitcher.defaultLayoutBuilder
|
||||
: (Widget? currentChild, List<Widget> previousChildren) {
|
||||
final children = <Widget>[...previousChildren];
|
||||
if (currentChild != null) children.add(currentChild);
|
||||
return Stack(alignment: widget.alignment, children: children);
|
||||
return Stack(
|
||||
alignment: Alignment.topCenter,
|
||||
children: [...previousChildren, ?currentChild],
|
||||
);
|
||||
},
|
||||
),
|
||||
child: widget.fixLayoutBuilder
|
||||
? Align(alignment: widget.alignment, child: widget.child)
|
||||
: widget.child,
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ class AnimatedDialogButton extends StatefulWidget {
|
||||
const AnimatedDialogButton({
|
||||
super.key,
|
||||
required this.buttonText,
|
||||
this.onPressed,
|
||||
required this.onPressed,
|
||||
this.buttonConstraints,
|
||||
this.buttonType = ButtonType.primary,
|
||||
this.isDescructive = false,
|
||||
@@ -19,7 +19,7 @@ class AnimatedDialogButton extends StatefulWidget {
|
||||
|
||||
final String buttonText;
|
||||
|
||||
final VoidCallback? onPressed;
|
||||
final VoidCallback onPressed;
|
||||
|
||||
final BoxConstraints? buttonConstraints;
|
||||
|
||||
@@ -38,38 +38,28 @@ class _AnimatedDialogButtonState extends State<AnimatedDialogButton> {
|
||||
Widget build(BuildContext context) {
|
||||
final textStyling = _getTextStyling();
|
||||
final buttonDecoration = _getButtonDecoration();
|
||||
bool isDisabled = widget.onPressed == null;
|
||||
|
||||
return IgnorePointer(
|
||||
ignoring: isDisabled,
|
||||
child: Opacity(
|
||||
opacity: isDisabled ? 0.5 : 1.0,
|
||||
child: GestureDetector(
|
||||
onTapDown: (_) => setState(() => _isPressed = true),
|
||||
onTapUp: (_) => setState(() => _isPressed = false),
|
||||
onTapCancel: () => setState(() => _isPressed = false),
|
||||
onTap: widget.onPressed,
|
||||
child: AnimatedScale(
|
||||
scale: _isPressed ? 0.95 : 1.0,
|
||||
duration: const Duration(milliseconds: 100),
|
||||
child: AnimatedOpacity(
|
||||
opacity: _isPressed ? 0.6 : 1.0,
|
||||
duration: const Duration(milliseconds: 100),
|
||||
child: Center(
|
||||
child: Container(
|
||||
constraints: widget.buttonConstraints,
|
||||
decoration: buttonDecoration,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 12,
|
||||
),
|
||||
margin: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Text(
|
||||
widget.buttonText,
|
||||
style: textStyling,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
return GestureDetector(
|
||||
onTapDown: (_) => setState(() => _isPressed = true),
|
||||
onTapUp: (_) => setState(() => _isPressed = false),
|
||||
onTapCancel: () => setState(() => _isPressed = false),
|
||||
onTap: widget.onPressed,
|
||||
child: AnimatedScale(
|
||||
scale: _isPressed ? 0.95 : 1.0,
|
||||
duration: const Duration(milliseconds: 100),
|
||||
child: AnimatedOpacity(
|
||||
opacity: _isPressed ? 0.6 : 1.0,
|
||||
duration: const Duration(milliseconds: 100),
|
||||
child: Center(
|
||||
child: Container(
|
||||
constraints: widget.buttonConstraints,
|
||||
decoration: buttonDecoration,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
margin: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Text(
|
||||
widget.buttonText,
|
||||
style: textStyling,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -19,6 +19,7 @@ class CustomAlertDialog extends StatelessWidget {
|
||||
final String title;
|
||||
final Widget content;
|
||||
final List<CustomDialogAction> actions;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
|
||||
@@ -10,7 +10,7 @@ class CustomDialogAction extends StatelessWidget {
|
||||
/// - [onPressed]: Callback function that is triggered when the button is pressed.
|
||||
const CustomDialogAction({
|
||||
super.key,
|
||||
this.onPressed,
|
||||
required this.onPressed,
|
||||
required this.text,
|
||||
this.buttonType = ButtonType.primary,
|
||||
this.isDestructive = false,
|
||||
@@ -20,18 +20,17 @@ class CustomDialogAction extends StatelessWidget {
|
||||
|
||||
final ButtonType buttonType;
|
||||
|
||||
final VoidCallback? onPressed;
|
||||
final VoidCallback onPressed;
|
||||
|
||||
final bool isDestructive;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedDialogButton(
|
||||
onPressed: onPressed != null
|
||||
? () async {
|
||||
await HapticFeedback.selectionClick();
|
||||
onPressed?.call();
|
||||
}
|
||||
: null,
|
||||
onPressed: () async {
|
||||
await HapticFeedback.selectionClick();
|
||||
onPressed.call();
|
||||
},
|
||||
buttonText: text,
|
||||
buttonType: buttonType,
|
||||
isDescructive: isDestructive,
|
||||
|
||||
@@ -12,44 +12,41 @@ class GameLabel extends StatelessWidget {
|
||||
|
||||
final String title;
|
||||
final String description;
|
||||
final AppColor color;
|
||||
final GameColor color;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final backgroundColor = getColorFromAppColor(color);
|
||||
final backgroundColor = getColorFromGameColor(color);
|
||||
final fontColor = backgroundColor.computeLuminance() > 0.5
|
||||
? Colors.black
|
||||
: Colors.white;
|
||||
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// Title
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor.withAlpha(230),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(8),
|
||||
bottomLeft: Radius.circular(8),
|
||||
return IntrinsicHeight(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// Title
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor.withAlpha(230),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(8),
|
||||
bottomLeft: Radius.circular(8),
|
||||
),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: fontColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
|
||||
child: Text(
|
||||
title,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: false,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: fontColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Description
|
||||
Flexible(
|
||||
child: Container(
|
||||
// Description
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor.withAlpha(140),
|
||||
borderRadius: const BorderRadius.only(
|
||||
@@ -60,9 +57,6 @@ class GameLabel extends StatelessWidget {
|
||||
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
|
||||
child: Text(
|
||||
description,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: false,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: fontColor,
|
||||
@@ -70,8 +64,8 @@ class GameLabel extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ class PlayerSelection extends StatefulWidget {
|
||||
this.availablePlayers,
|
||||
this.initialSelectedPlayers,
|
||||
required this.onChanged,
|
||||
this.onPlayerCreated,
|
||||
});
|
||||
|
||||
/// An optional list of players to choose from. If null, all players from the database are used.
|
||||
@@ -38,9 +37,6 @@ class PlayerSelection extends StatefulWidget {
|
||||
/// A callback function that is invoked whenever the selection changes,
|
||||
final Function(List<Player> value) onChanged;
|
||||
|
||||
/// A callback function that is invoked when a player was created in this widget
|
||||
final VoidCallback? onPlayerCreated;
|
||||
|
||||
@override
|
||||
State<PlayerSelection> createState() => _PlayerSelectionState();
|
||||
}
|
||||
@@ -327,7 +323,6 @@ class _PlayerSelectionState extends State<PlayerSelection> {
|
||||
|
||||
/// Updates the state after successfully adding a new player.
|
||||
void _handleSuccessfulPlayerCreation(Player player) {
|
||||
widget.onPlayerCreated?.call();
|
||||
selectedPlayers.insert(0, player);
|
||||
widget.onChanged([...selectedPlayers]);
|
||||
allPlayers.add(player);
|
||||
|
||||
@@ -51,7 +51,7 @@ class GameTile extends StatelessWidget {
|
||||
? (badgeColor!.computeLuminance() > 0.5 ? Colors.black : Colors.white)
|
||||
: Colors.white;
|
||||
|
||||
final gameColor = badgeColor ?? getColorFromAppColor(AppColor.orange);
|
||||
final gameColor = badgeColor ?? getColorFromGameColor(GameColor.orange);
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:tallee/core/adaptive_page_route.dart';
|
||||
import 'package:tallee/core/common.dart';
|
||||
import 'package:tallee/core/custom_theme.dart';
|
||||
import 'package:tallee/data/models/group.dart';
|
||||
import 'package:tallee/presentation/views/main_menu/player_detail_view.dart';
|
||||
import 'package:tallee/presentation/widgets/tiles/text_icon_tile.dart';
|
||||
|
||||
class GroupTile extends StatefulWidget {
|
||||
@@ -17,7 +15,6 @@ class GroupTile extends StatefulWidget {
|
||||
required this.group,
|
||||
this.isHighlighted = false,
|
||||
this.onTap,
|
||||
this.onPlayerChanged,
|
||||
});
|
||||
|
||||
/// The group data to be displayed.
|
||||
@@ -29,9 +26,6 @@ class GroupTile extends StatefulWidget {
|
||||
/// Callback function to be executed when the tile is tapped.
|
||||
final VoidCallback? onTap;
|
||||
|
||||
/// Callback function to be executed when the players in the group are changed.
|
||||
final VoidCallback? onPlayerChanged;
|
||||
|
||||
@override
|
||||
State<GroupTile> createState() => _GroupTileState();
|
||||
}
|
||||
@@ -98,19 +92,6 @@ class _GroupTileState extends State<GroupTile> {
|
||||
text: member.name,
|
||||
suffixText: getNameCountText(member),
|
||||
iconEnabled: false,
|
||||
onTileTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
adaptivePageRoute(
|
||||
builder: (context) => PlayerDetailView(
|
||||
player: member,
|
||||
callback: () {
|
||||
widget.onPlayerChanged?.call();
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -3,13 +3,11 @@ import 'dart:core' hide Match;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:tallee/core/adaptive_page_route.dart';
|
||||
import 'package:tallee/core/common.dart';
|
||||
import 'package:tallee/core/custom_theme.dart';
|
||||
import 'package:tallee/core/enums.dart';
|
||||
import 'package:tallee/data/models/match.dart';
|
||||
import 'package:tallee/l10n/generated/app_localizations.dart';
|
||||
import 'package:tallee/presentation/views/main_menu/player_detail_view.dart';
|
||||
import 'package:tallee/presentation/widgets/game_label.dart';
|
||||
import 'package:tallee/presentation/widgets/tiles/text_icon_tile.dart';
|
||||
|
||||
@@ -26,7 +24,6 @@ class MatchTile extends StatefulWidget {
|
||||
required this.onTap,
|
||||
this.width,
|
||||
this.compact = false,
|
||||
this.onPlayerEdited,
|
||||
});
|
||||
|
||||
/// The match data to be displayed.
|
||||
@@ -35,9 +32,6 @@ class MatchTile extends StatefulWidget {
|
||||
/// The callback invoked when the tile is tapped.
|
||||
final VoidCallback onTap;
|
||||
|
||||
/// The callback invoked when the players are edited
|
||||
final VoidCallback? onPlayerEdited;
|
||||
|
||||
/// Optional width for the tile.
|
||||
final double? width;
|
||||
|
||||
@@ -230,19 +224,6 @@ class _MatchTileState extends State<MatchTile> {
|
||||
text: player.name,
|
||||
suffixText: getNameCountText(player),
|
||||
iconEnabled: false,
|
||||
onTileTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
adaptivePageRoute(
|
||||
builder: (context) => PlayerDetailView(
|
||||
player: player,
|
||||
callback: () {
|
||||
widget.onPlayerEdited?.call();
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluttericon/rpg_awesome_icons.dart';
|
||||
import 'package:tallee/core/common.dart';
|
||||
import 'package:tallee/core/custom_theme.dart';
|
||||
import 'package:tallee/core/enums.dart';
|
||||
import 'package:tallee/data/models/game.dart';
|
||||
import 'package:tallee/data/models/group.dart';
|
||||
import 'package:tallee/data/models/player.dart';
|
||||
import 'package:tallee/l10n/generated/app_localizations.dart';
|
||||
import 'package:tallee/presentation/widgets/tiles/info_tile.dart';
|
||||
@@ -25,11 +21,8 @@ class StatisticsTile extends StatelessWidget {
|
||||
required this.title,
|
||||
required this.width,
|
||||
required this.values,
|
||||
required this.itemCount,
|
||||
required this.barColor,
|
||||
required this.displayCount,
|
||||
this.selectedGroups,
|
||||
this.selectedGames,
|
||||
this.showAllValues = false,
|
||||
});
|
||||
|
||||
/// The icon displayed next to the title.
|
||||
@@ -44,16 +37,12 @@ class StatisticsTile extends StatelessWidget {
|
||||
/// A list of tuples containing labels and their corresponding numeric values.
|
||||
final List<(Player, num)> values;
|
||||
|
||||
/// The maximum number of items to display.
|
||||
final int itemCount;
|
||||
|
||||
/// The color of the bars representing the values.
|
||||
final Color barColor;
|
||||
|
||||
// statistic data
|
||||
final int displayCount;
|
||||
final List<Group>? selectedGroups;
|
||||
final List<Game>? selectedGames;
|
||||
|
||||
final bool showAllValues;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final loc = AppLocalizations.of(context);
|
||||
@@ -63,202 +52,91 @@ class StatisticsTile extends StatelessWidget {
|
||||
title: title,
|
||||
icon: icon,
|
||||
content: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20.0),
|
||||
child: Visibility(
|
||||
visible: values.isNotEmpty,
|
||||
|
||||
// No data avaiable message
|
||||
replacement: Center(
|
||||
heightFactor: 4,
|
||||
child: Text(loc.no_data_available),
|
||||
),
|
||||
|
||||
// Bar chart
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final maxBarWidth = constraints.maxWidth * 0.8;
|
||||
|
||||
// If displayCount wasnt provided, take all values
|
||||
final valuesShown = showAllValues
|
||||
? values.length
|
||||
: min(values.length, displayCount);
|
||||
final displayValues = values.take(valuesShown).toList();
|
||||
final maxVal = displayValues.isNotEmpty
|
||||
? displayValues.fold<num>(
|
||||
0,
|
||||
(currentMax, entry) =>
|
||||
entry.$2 > currentMax ? entry.$2 : currentMax,
|
||||
)
|
||||
: 0;
|
||||
|
||||
final maxBarWidth = constraints.maxWidth * 0.65;
|
||||
return Column(
|
||||
children: [
|
||||
// Bars
|
||||
...List.generate(valuesShown, (index) {
|
||||
/// Fraction of wins
|
||||
final double fraction = (maxVal > 0)
|
||||
? (displayValues[index].$2 / maxVal)
|
||||
: 0.0;
|
||||
children: List.generate(min(values.length, itemCount), (index) {
|
||||
/// The maximum wins among all players
|
||||
final maxMatches = values.isNotEmpty ? values[0].$2 : 0;
|
||||
|
||||
/// Calculated width for current the bar
|
||||
final double barWidth = (maxBarWidth * fraction).clamp(
|
||||
0.0,
|
||||
maxBarWidth,
|
||||
);
|
||||
/// Fraction of wins
|
||||
final double fraction = (maxMatches > 0)
|
||||
? (values[index].$2 / maxMatches)
|
||||
: 0.0;
|
||||
|
||||
final barClr = index >= displayCount
|
||||
? barColor.withAlpha(150)
|
||||
: barColor;
|
||||
/// Calculated width for current the bar
|
||||
final double barWidth = maxBarWidth * fraction;
|
||||
|
||||
var textClr = barColor.computeLuminance() > 0.5
|
||||
? const Color(0xFF101010)
|
||||
: CustomTheme.textColor;
|
||||
textClr = textClr.withAlpha(
|
||||
index >= displayCount ? 220 : 255,
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: maxBarWidth,
|
||||
child: Stack(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
children: [
|
||||
// Bar
|
||||
Container(
|
||||
height: 24,
|
||||
width: barWidth,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
color: barClr,
|
||||
),
|
||||
),
|
||||
|
||||
// Player
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 4.0),
|
||||
child: RichText(
|
||||
maxLines: 1,
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
text: TextSpan(
|
||||
style: DefaultTextStyle.of(context).style,
|
||||
children: [
|
||||
TextSpan(
|
||||
text: displayValues[index].$1.name,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: textClr,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: getNameCountText(
|
||||
displayValues[index].$1,
|
||||
),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color:
|
||||
(barColor ==
|
||||
getColorFromAppColor(
|
||||
AppColor.yellow,
|
||||
)
|
||||
? const Color(
|
||||
0xFF101010,
|
||||
)
|
||||
: CustomTheme.textColor)
|
||||
.withAlpha(150),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
|
||||
// Value
|
||||
Center(
|
||||
child: Text(
|
||||
displayValues[index].$2 <= 1 &&
|
||||
displayValues[index].$2 is double
|
||||
? displayValues[index].$2.toStringAsFixed(2)
|
||||
: displayValues[index].$2.toString(),
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
Container(
|
||||
height: 24,
|
||||
width: barWidth,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
color: barColor,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 4.0),
|
||||
child: RichText(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
text: TextSpan(
|
||||
style: DefaultTextStyle.of(context).style,
|
||||
children: [
|
||||
TextSpan(
|
||||
text: values[index].$1.name,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: getNameCountText(values[index].$1),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: CustomTheme.textColor.withAlpha(
|
||||
150,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
Center(
|
||||
child: Text(
|
||||
values[index].$2 <= 1 && values[index].$2 is double
|
||||
? values[index].$2.toStringAsFixed(2)
|
||||
: values[index].$2.toString(),
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
|
||||
// Group & Game info
|
||||
if (hasGame || hasGroup)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.start,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
spacing: 4,
|
||||
runSpacing: 4,
|
||||
children: [
|
||||
// Game
|
||||
if (hasGroup)
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
const Icon(
|
||||
RpgAwesome.clovers_card,
|
||||
color: CustomTheme.hintColor,
|
||||
size: 20,
|
||||
),
|
||||
Text(
|
||||
getGameText(selectedGames!),
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: CustomTheme.hintColor,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
if (hasGroup && hasGame) const SizedBox(width: 20),
|
||||
|
||||
// Group
|
||||
if (hasGroup)
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.groups,
|
||||
color: CustomTheme.hintColor,
|
||||
),
|
||||
Text(
|
||||
getGroupText(selectedGroups!),
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: CustomTheme.hintColor,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -266,24 +144,4 @@ class StatisticsTile extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String getGroupText(List<Group> groups) {
|
||||
var text = groups[0].name;
|
||||
if (groups.length > 1) {
|
||||
return '$text + ${groups.length - 1}';
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
String getGameText(List<Game> games) {
|
||||
var text = games[0].name;
|
||||
if (games.length > 1) {
|
||||
return '$text + ${games.length - 1}';
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
bool get hasGroup => selectedGroups != null && selectedGroups!.isNotEmpty;
|
||||
|
||||
bool get hasGame => selectedGames != null && selectedGames!.isNotEmpty;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ class TextIconTile extends StatelessWidget {
|
||||
this.suffixText = '',
|
||||
this.iconEnabled = true,
|
||||
this.onIconTap,
|
||||
this.onTileTap,
|
||||
});
|
||||
|
||||
/// The text to display in the tile.
|
||||
@@ -26,58 +25,52 @@ class TextIconTile extends StatelessWidget {
|
||||
/// The callback to be invoked when the icon is tapped.
|
||||
final VoidCallback? onIconTap;
|
||||
|
||||
/// The callback to be invoked when the tile is tapped.
|
||||
final VoidCallback? onTileTap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: onTileTap,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: CustomTheme.onBoxColor,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (iconEnabled) const SizedBox(width: 3),
|
||||
Flexible(
|
||||
child: RichText(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
text: TextSpan(
|
||||
style: DefaultTextStyle.of(context).style,
|
||||
children: [
|
||||
TextSpan(
|
||||
text: text,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: CustomTheme.onBoxColor,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (iconEnabled) const SizedBox(width: 3),
|
||||
Flexible(
|
||||
child: RichText(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
text: TextSpan(
|
||||
style: DefaultTextStyle.of(context).style,
|
||||
children: [
|
||||
TextSpan(
|
||||
text: text,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
TextSpan(
|
||||
text: suffixText,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: CustomTheme.textColor.withAlpha(120),
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: suffixText,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: CustomTheme.textColor.withAlpha(120),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (iconEnabled) ...<Widget>[
|
||||
const SizedBox(width: 3),
|
||||
GestureDetector(
|
||||
onTap: onIconTap,
|
||||
child: const Icon(Icons.close, size: 20),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (iconEnabled) ...<Widget>[
|
||||
const SizedBox(width: 3),
|
||||
GestureDetector(
|
||||
onTap: onIconTap,
|
||||
child: const Icon(Icons.close, size: 20),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user