101 lines
2.8 KiB
Dart
101 lines
2.8 KiB
Dart
import 'dart:math';
|
|
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:from_css_color/from_css_color.dart';
|
|
import 'package:git_touch/models/theme.dart';
|
|
import 'package:git_touch/utils/utils.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
const contributionEmptyColor = '#ebedf0';
|
|
const contributionColors = ['#9be9a8', '#40c463', '#30a14e', '#216e39'];
|
|
|
|
class HideScrollbar extends StatelessWidget {
|
|
const HideScrollbar({super.key, this.child});
|
|
final Widget? child;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return NotificationListener<ScrollNotification>(
|
|
onNotification: (_) => true,
|
|
child: child!,
|
|
);
|
|
}
|
|
}
|
|
|
|
class ContributionDay {
|
|
ContributionDay({this.hexColor, this.count})
|
|
: assert(hexColor != null || count != null);
|
|
String? hexColor;
|
|
int? count;
|
|
}
|
|
|
|
class ContributionWidget extends StatelessWidget {
|
|
|
|
ContributionWidget({required this.weeks}) {
|
|
int? maxCount;
|
|
for (final week in weeks!) {
|
|
for (final day in week) {
|
|
if (day.count != null) {
|
|
if (maxCount == null) {
|
|
for (final week in weeks!) {
|
|
for (final day in week) {
|
|
maxCount = max(day.count!, maxCount ?? 0);
|
|
}
|
|
}
|
|
}
|
|
if (day.count == 0) {
|
|
day.hexColor = contributionEmptyColor;
|
|
} else {
|
|
// TODO: algorithm
|
|
final level = (day.count! * 4) ~/ (maxCount! + 1);
|
|
day.hexColor = contributionColors[level];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
final Iterable<Iterable<ContributionDay>>? weeks;
|
|
|
|
static Color _revertColor(Color color) {
|
|
return Color.fromRGBO(
|
|
0xff - color.red, 0xff - color.green, 0xff - color.blue, 1);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final theme = context.watch<ThemeModel>();
|
|
return Container(
|
|
alignment: Alignment.center,
|
|
padding: CommonStyle.padding,
|
|
child: HideScrollbar(
|
|
child: SingleChildScrollView(
|
|
scrollDirection: Axis.horizontal,
|
|
reverse: true,
|
|
child: Wrap(
|
|
spacing: 3,
|
|
children: [
|
|
for (final week in weeks!)
|
|
Wrap(
|
|
direction: Axis.vertical,
|
|
spacing: 3,
|
|
children: [
|
|
for (final day in week)
|
|
Container(
|
|
width: 10,
|
|
height: 10,
|
|
decoration: BoxDecoration(
|
|
color: theme.brightness == Brightness.dark
|
|
? _revertColor(fromCssColor(day.hexColor!))
|
|
: fromCssColor(day.hexColor!),
|
|
borderRadius: BorderRadius.circular(2),
|
|
),
|
|
)
|
|
],
|
|
)
|
|
],
|
|
),
|
|
)),
|
|
);
|
|
}
|
|
}
|