UI/UX improvement

This commit is contained in:
ashilkn
2025-07-26 14:21:29 +05:30
parent 10101c697b
commit 88eb935d2f
2 changed files with 107 additions and 20 deletions

View File

@@ -1,9 +1,11 @@
import "package:flutter/material.dart";
import "package:flutter_animate/flutter_animate.dart";
import 'package:photos/core/constants.dart';
import "package:photos/generated/l10n.dart";
import "package:photos/models/file/file.dart";
import "package:photos/models/selected_files.dart";
import "package:photos/theme/ente_theme.dart";
import "package:photos/ui/viewer/gallery/gallery.dart";
import "package:photos/ui/viewer/gallery/layout_settings.dart";
class GroupHeaderWidget extends StatefulWidget {
@@ -15,6 +17,8 @@ class GroupHeaderWidget extends StatefulWidget {
final bool showSelectAll;
final bool showGallerySettingCTA;
final bool showTrailingIcons;
final bool isPinnedHeader;
final bool fadeInTrailingIcons;
const GroupHeaderWidget({
super.key,
@@ -26,6 +30,8 @@ class GroupHeaderWidget extends StatefulWidget {
this.showGallerySettingCTA = false,
this.height,
this.showTrailingIcons = true,
this.isPinnedHeader = false,
this.fadeInTrailingIcons = false,
});
@override
@@ -102,20 +108,58 @@ class _GroupHeaderWidgetState extends State<GroupHeaderWidget> {
: widget.showTrailingIcons
? GestureDetector(
behavior: HitTestBehavior.translucent,
child: ValueListenableBuilder(
valueListenable: _areAllFromGroupSelectedNotifier,
builder: (context, dynamic value, _) {
return value
? const Icon(
Icons.check_circle,
size: 18,
)
: Icon(
Icons.check_circle_outlined,
color: colorScheme.strokeMuted,
size: 18,
);
},
child: Padding(
padding: const EdgeInsets.all(4),
child: ValueListenableBuilder(
valueListenable: _areAllFromGroupSelectedNotifier,
builder: (context, dynamic value, _) {
return value
? widget.fadeInTrailingIcons
? const Icon(
Icons.check_circle,
size: 22,
).animate().fadeIn(
duration: const Duration(
milliseconds: PinnedGroupHeader
.kTrailingIconsFadeInDurationMs,
),
delay: const Duration(
milliseconds: PinnedGroupHeader
.kScaleDurationInMilliseconds +
PinnedGroupHeader
.kTrailingIconsFadeInDelayMs,
),
curve: Curves.easeOut,
)
: const Icon(
Icons.check_circle,
size: 22,
)
: widget.fadeInTrailingIcons
? Icon(
Icons.check_circle_outlined,
color: colorScheme.strokeMuted,
size: 22,
).animate().fadeIn(
duration: const Duration(
milliseconds: PinnedGroupHeader
.kTrailingIconsFadeInDurationMs,
),
delay: const Duration(
milliseconds: PinnedGroupHeader
.kScaleDurationInMilliseconds +
PinnedGroupHeader
.kTrailingIconsFadeInDelayMs,
),
curve: Curves.easeOut,
)
: Icon(
Icons.check_circle_outlined,
color: colorScheme.strokeMuted,
size: 22,
);
},
),
),
onTap: () {
widget.selectedFiles?.toggleGroupSelection(
@@ -133,15 +177,32 @@ class _GroupHeaderWidgetState extends State<GroupHeaderWidget> {
onTap: () => _showLayoutSettingsOverflowMenu(context),
child: Padding(
padding: const EdgeInsets.all(4),
child: Icon(
Icons.more_vert_outlined,
color: colorScheme.strokeBase,
),
child: widget.fadeInTrailingIcons
? Icon(
Icons.more_vert_outlined,
color: colorScheme.blurStrokeBase,
).animate().fadeIn(
duration: const Duration(
milliseconds: PinnedGroupHeader
.kTrailingIconsFadeInDurationMs,
),
delay: const Duration(
milliseconds: PinnedGroupHeader
.kScaleDurationInMilliseconds +
PinnedGroupHeader
.kTrailingIconsFadeInDelayMs,
),
curve: Curves.easeOut,
)
: Icon(
Icons.more_vert_outlined,
color: colorScheme.strokeBase,
),
),
)
: const SizedBox.shrink()
: const SizedBox.shrink(),
const SizedBox(width: 12),
SizedBox(width: horizontalPadding - 4.0),
],
),
);

View File

@@ -667,6 +667,9 @@ class PinnedGroupHeader extends StatefulWidget {
final bool showSelectAll;
final ValueNotifier<bool> scrollbarInUseNotifier;
final bool showGallerySettingsCTA;
static const kScaleDurationInMilliseconds = 200;
static const kTrailingIconsFadeInDelayMs = 0;
static const kTrailingIconsFadeInDurationMs = 200;
const PinnedGroupHeader({
required this.scrollController,
@@ -689,6 +692,8 @@ class _PinnedGroupHeaderState extends State<PinnedGroupHeader> {
Timer? _enlargeHeaderTimer;
late final ValueNotifier<bool> _atZeroScrollNotifier;
Timer? _timer;
bool lastInUseState = false;
bool fadeInTrailingIcons = false;
@override
void initState() {
super.initState();
@@ -791,9 +796,26 @@ class _PinnedGroupHeaderState extends State<PinnedGroupHeader> {
_enlargeHeaderTimer?.cancel();
if (widget.scrollbarInUseNotifier.value) {
_enlargeHeader.value = true;
lastInUseState = true;
fadeInTrailingIcons = false;
} else {
_enlargeHeaderTimer = Timer(const Duration(milliseconds: 250), () {
_enlargeHeader.value = false;
if (lastInUseState) {
fadeInTrailingIcons = true;
Future.delayed(
const Duration(
milliseconds: PinnedGroupHeader.kTrailingIconsFadeInDelayMs +
PinnedGroupHeader.kTrailingIconsFadeInDurationMs +
100,
), () {
setState(() {
if (!mounted) return;
fadeInTrailingIcons = false;
});
});
}
lastInUseState = false;
});
}
}
@@ -814,7 +836,9 @@ class _PinnedGroupHeaderState extends State<PinnedGroupHeader> {
return AnimatedScale(
scale: inUse ? 1.2 : 1.0,
alignment: Alignment.topLeft,
duration: const Duration(milliseconds: 200),
duration: const Duration(
milliseconds: PinnedGroupHeader.kScaleDurationInMilliseconds,
),
curve: Curves.easeInOutSine,
child: ValueListenableBuilder<bool>(
valueListenable: _atZeroScrollNotifier,
@@ -854,6 +878,8 @@ class _PinnedGroupHeaderState extends State<PinnedGroupHeader> {
showSelectAll: widget.showSelectAll,
showGallerySettingCTA: widget.showGallerySettingsCTA,
showTrailingIcons: !inUse,
isPinnedHeader: true,
fadeInTrailingIcons: fadeInTrailingIcons,
),
),
),