Merge branch 'gallery_rewrite' into internal_photos_july25_2

This commit is contained in:
ashilkn
2025-07-25 16:12:57 +05:30
3 changed files with 27 additions and 254 deletions

View File

@@ -1,236 +0,0 @@
// Modified CupertinoScrollbar that accepts a ValueNotifier<bool> to indicate
// if the scrollbar is in use. In flutter CupertinoScrollbar is in a different
// file where as MaterialScrollbar is in the same file as ScrollBar. So
// following the same convention by create a separate file for
// CupertinoScrollbarWithUseNotifier.
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import "package:flutter/cupertino.dart";
import 'package:flutter/services.dart';
// All values eyeballed.
const double _kScrollbarMinOverscrollLength = 8.0;
const Duration _kScrollbarTimeToFade = Duration(milliseconds: 1200);
const Duration _kScrollbarFadeDuration = Duration(milliseconds: 250);
const Duration _kScrollbarResizeDuration = Duration(milliseconds: 100);
// Extracted from iOS 13.1 beta using Debug View Hierarchy.
const Color _kScrollbarColor = CupertinoDynamicColor.withBrightness(
color: Color(0x59000000),
darkColor: Color(0x80FFFFFF),
);
// This is the amount of space from the top of a vertical scrollbar to the
// top edge of the scrollable, measured when the vertical scrollbar overscrolls
// to the top.
// TODO(LongCatIsLooong): fix https://github.com/flutter/flutter/issues/32175
const double _kScrollbarMainAxisMargin = 3.0;
const double _kScrollbarCrossAxisMargin = 3.0;
/// An iOS style scrollbar.
///
/// To add a scrollbar to a [ScrollView], wrap the scroll view widget in
/// a [CupertinoScrollbarWithUseNotifier] widget.
///
/// {@youtube 560 315 https://www.youtube.com/watch?v=DbkIQSvwnZc}
///
/// {@macro flutter.widgets.Scrollbar}
///
/// When dragging a [CupertinoScrollbarWithUseNotifier] thumb, the thickness and radius will
/// animate from [thickness] and [radius] to [thicknessWhileDragging] and
/// [radiusWhileDragging], respectively.
///
/// {@tool dartpad}
/// This sample shows a [CupertinoScrollbarWithUseNotifier] that fades in and out of view as scrolling occurs.
/// The scrollbar will fade into view as the user scrolls, and fade out when scrolling stops.
/// The `thickness` of the scrollbar will animate from 6 pixels to the `thicknessWhileDragging` of 10
/// when it is dragged by the user. The `radius` of the scrollbar thumb corners will animate from 34
/// to the `radiusWhileDragging` of 0 when the scrollbar is being dragged by the user.
///
/// ** See code in examples/api/lib/cupertino/scrollbar/cupertino_scrollbar.0.dart **
/// {@end-tool}
///
/// {@tool dartpad}
/// When [thumbVisibility] is true, the scrollbar thumb will remain visible without the
/// fade animation. This requires that a [ScrollController] is provided to controller,
/// or that the [PrimaryScrollController] is available.
///
/// ** See code in examples/api/lib/cupertino/scrollbar/cupertino_scrollbar.1.dart **
/// {@end-tool}
///
/// See also:
///
/// * [ListView], which displays a linear, scrollable list of children.
/// * [GridView], which displays a 2 dimensional, scrollable array of children.
/// * [Scrollbar], a Material Design scrollbar.
/// * [RawScrollbar], a basic scrollbar that fades in and out, extended
/// by this class to add more animations and behaviors.
class CupertinoScrollbarWithUseNotifier extends RawScrollbar {
/// Creates an iOS style scrollbar that wraps the given [child].
///
/// The [child] should be a source of [ScrollNotification] notifications,
/// typically a [Scrollable] widget.
final ValueNotifier<bool> inUseNotifier;
final double minScrollbarLength;
const CupertinoScrollbarWithUseNotifier({
super.key,
required super.child,
required this.inUseNotifier,
required this.minScrollbarLength,
super.controller,
bool? thumbVisibility,
double super.thickness = defaultThickness,
this.thicknessWhileDragging = defaultThicknessWhileDragging,
Radius super.radius = defaultRadius,
this.radiusWhileDragging = defaultRadiusWhileDragging,
ScrollNotificationPredicate? notificationPredicate,
super.scrollbarOrientation,
}) : assert(thickness < double.infinity),
assert(thicknessWhileDragging < double.infinity),
super(
thumbVisibility: thumbVisibility ?? false,
fadeDuration: _kScrollbarFadeDuration,
timeToFade: _kScrollbarTimeToFade,
pressDuration: const Duration(milliseconds: 100),
notificationPredicate:
notificationPredicate ?? defaultScrollNotificationPredicate,
);
/// Default value for [thickness] if it's not specified in [CupertinoScrollbarWithUseNotifier].
static const double defaultThickness = 3;
/// Default value for [thicknessWhileDragging] if it's not specified in
/// [CupertinoScrollbarWithUseNotifier].
static const double defaultThicknessWhileDragging = 8.0;
/// Default value for [radius] if it's not specified in [CupertinoScrollbarWithUseNotifier].
static const Radius defaultRadius = Radius.circular(1.5);
/// Default value for [radiusWhileDragging] if it's not specified in
/// [CupertinoScrollbarWithUseNotifier].
static const Radius defaultRadiusWhileDragging = Radius.circular(4.0);
/// The thickness of the scrollbar when it's being dragged by the user.
///
/// When the user starts dragging the scrollbar, the thickness will animate
/// from [thickness] to this value, then animate back when the user stops
/// dragging the scrollbar.
final double thicknessWhileDragging;
/// The radius of the scrollbar edges when the scrollbar is being dragged by
/// the user.
///
/// When the user starts dragging the scrollbar, the radius will animate
/// from [radius] to this value, then animate back when the user stops
/// dragging the scrollbar.
final Radius radiusWhileDragging;
@override
RawScrollbarState<CupertinoScrollbarWithUseNotifier> createState() =>
_CupertinoScrollbarState();
}
class _CupertinoScrollbarState
extends RawScrollbarState<CupertinoScrollbarWithUseNotifier> {
late AnimationController _thicknessAnimationController;
double get _thickness {
return widget.thickness! +
_thicknessAnimationController.value *
(widget.thicknessWhileDragging - widget.thickness!);
}
Radius get _radius {
return Radius.lerp(
widget.radius,
widget.radiusWhileDragging,
_thicknessAnimationController.value,
)!;
}
@override
void initState() {
super.initState();
_thicknessAnimationController = AnimationController(
vsync: this,
duration: _kScrollbarResizeDuration,
);
_thicknessAnimationController.addListener(() {
updateScrollbarPainter();
});
}
@override
void updateScrollbarPainter() {
scrollbarPainter
..color = CupertinoDynamicColor.resolve(_kScrollbarColor, context)
..textDirection = Directionality.of(context)
..thickness = _thickness
..mainAxisMargin = _kScrollbarMainAxisMargin
..crossAxisMargin = _kScrollbarCrossAxisMargin
..radius = _radius
..padding = MediaQuery.paddingOf(context)
..minLength = widget.minScrollbarLength
..minOverscrollLength = _kScrollbarMinOverscrollLength
..scrollbarOrientation = widget.scrollbarOrientation;
}
double _pressStartAxisPosition = 0.0;
// Long press event callbacks handle the gesture where the user long presses
// on the scrollbar thumb and then drags the scrollbar without releasing.
@override
void handleThumbPressStart(Offset localPosition) {
super.handleThumbPressStart(localPosition);
widget.inUseNotifier.value = true;
final Axis? direction = getScrollbarDirection();
if (direction == null) {
return;
}
_pressStartAxisPosition = switch (direction) {
Axis.vertical => localPosition.dy,
Axis.horizontal => localPosition.dx,
};
}
@override
void handleThumbPress() {
if (getScrollbarDirection() == null) {
return;
}
super.handleThumbPress();
_thicknessAnimationController.forward().then<void>(
(_) => HapticFeedback.mediumImpact(),
);
}
@override
void handleThumbPressEnd(Offset localPosition, Velocity velocity) {
widget.inUseNotifier.value = false;
final Axis? direction = getScrollbarDirection();
if (direction == null) {
return;
}
_thicknessAnimationController.reverse();
super.handleThumbPressEnd(localPosition, velocity);
final (double axisPosition, double axisVelocity) = switch (direction) {
Axis.horizontal => (localPosition.dx, velocity.pixelsPerSecond.dx),
Axis.vertical => (localPosition.dy, velocity.pixelsPerSecond.dy),
};
if (axisPosition != _pressStartAxisPosition && axisVelocity.abs() < 10) {
HapticFeedback.mediumImpact();
}
}
@override
void dispose() {
_thicknessAnimationController.dispose();
super.dispose();
}
}

View File

@@ -52,6 +52,7 @@ class _CustomScrollBarState extends State<CustomScrollBar> {
double? heightOfScrollbarDivider;
double? heightOfScrollTrack;
late bool _showScrollbarDivisions;
late bool _showThumb;
// Scrollbar's heigh is not fixed by default. If the scrollable is short
// enough, the scrollbar's height can go above the minimum length.
@@ -89,6 +90,13 @@ class _CustomScrollBarState extends State<CustomScrollBar> {
_showScrollbarDivisions = false;
}
if (widget.galleryGroups.groupLayouts.last.maxOffset >
widget.heighOfViewport * 3) {
_showThumb = true;
} else {
_showThumb = false;
}
if (_showScrollbarDivisions) {
getIntrinsicSizeOfWidget(const ScrollBarDivider(title: "Temp"), context)
.then((size) {
@@ -215,6 +223,7 @@ class _CustomScrollBarState extends State<CustomScrollBar> {
padding: EdgeInsets.only(
bottom: widget.bottomPadding.value,
top: widget.topPadding,
right: 4,
),
),
child: ScrollbarWithUseNotifer(
@@ -223,6 +232,9 @@ class _CustomScrollBarState extends State<CustomScrollBar> {
interactive: true,
inUseNotifier: widget.inUseNotifier,
minScrollbarLength: _kScrollbarMinLength,
showThumb: _showThumb,
radius: const Radius.circular(4),
thickness: 8,
child: widget.child,
),
),

View File

@@ -8,7 +8,6 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import "package:flutter/material.dart";
import "package:photos/ui/viewer/gallery/scrollbar/cupertino_scroll_bar_with_use_notifier.dart";
const double _kScrollbarThickness = 8.0;
const double _kScrollbarThicknessWithTrack = 12.0;
@@ -96,6 +95,7 @@ class ScrollbarWithUseNotifer extends StatelessWidget {
this.notificationPredicate,
this.interactive,
this.scrollbarOrientation,
this.showThumb,
});
/// {@macro flutter.widgets.Scrollbar.child}
@@ -155,25 +155,10 @@ class ScrollbarWithUseNotifer extends StatelessWidget {
final double minScrollbarLength;
final bool? showThumb;
@override
Widget build(BuildContext context) {
if (Theme.of(context).platform == TargetPlatform.iOS) {
return CupertinoScrollbarWithUseNotifier(
thumbVisibility: thumbVisibility ?? false,
thickness: thickness ?? CupertinoScrollbar.defaultThickness,
thicknessWhileDragging:
thickness ?? CupertinoScrollbar.defaultThicknessWhileDragging,
radius: radius ?? CupertinoScrollbar.defaultRadius,
radiusWhileDragging:
radius ?? CupertinoScrollbar.defaultRadiusWhileDragging,
controller: controller,
notificationPredicate: notificationPredicate,
scrollbarOrientation: scrollbarOrientation,
inUseNotifier: inUseNotifier,
minScrollbarLength: minScrollbarLength,
child: child,
);
}
return _MaterialScrollbar(
controller: controller,
thumbVisibility: thumbVisibility,
@@ -185,6 +170,7 @@ class ScrollbarWithUseNotifer extends StatelessWidget {
scrollbarOrientation: scrollbarOrientation,
inUseNotifier: inUseNotifier,
minScrollbarLength: minScrollbarLength,
showThumb: showThumb,
child: child,
);
}
@@ -193,10 +179,12 @@ class ScrollbarWithUseNotifer extends StatelessWidget {
class _MaterialScrollbar extends RawScrollbar {
final ValueNotifier<bool> inUseNotifier;
final double minScrollbarLength;
final bool? showThumb;
const _MaterialScrollbar({
required super.child,
required this.inUseNotifier,
required this.minScrollbarLength,
required this.showThumb,
super.controller,
super.thumbVisibility,
super.trackVisibility,
@@ -251,6 +239,9 @@ class _MaterialScrollbarState extends RawScrollbarState<_MaterialScrollbar> {
};
MaterialStateProperty<Color> get _thumbColor {
if (widget.showThumb == false) {
return MaterialStateProperty.all(const Color(0x00000000));
}
final Color onSurface = _colorScheme.onSurface;
final Brightness brightness = _colorScheme.brightness;
late Color dragColor;
@@ -291,6 +282,9 @@ class _MaterialScrollbarState extends RawScrollbarState<_MaterialScrollbar> {
}
MaterialStateProperty<Color> get _trackColor {
if (widget.showThumb == false) {
return MaterialStateProperty.all(const Color(0x00000000));
}
final Color onSurface = _colorScheme.onSurface;
final Brightness brightness = _colorScheme.brightness;
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
@@ -306,6 +300,9 @@ class _MaterialScrollbarState extends RawScrollbarState<_MaterialScrollbar> {
}
MaterialStateProperty<Color> get _trackBorderColor {
if (widget.showThumb == false) {
return MaterialStateProperty.all(const Color(0x00000000));
}
final Color onSurface = _colorScheme.onSurface;
final Brightness brightness = _colorScheme.brightness;
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {