mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-02-02 06:46:22 +01:00
Merge branch 'scrollbar-month-label' into dev
This commit is contained in:
commit
cf2e0e4c48
5 changed files with 110 additions and 10 deletions
|
@ -33,6 +33,7 @@ import 'package:nc_photos/platform/features.dart' as features;
|
|||
import 'package:nc_photos/platform/k.dart' as platform_k;
|
||||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:nc_photos/pref_util.dart' as pref_util;
|
||||
import 'package:visibility_detector/visibility_detector.dart';
|
||||
|
||||
Future<void> initAppLaunch() async {
|
||||
if (_hasInitedInThisIsolate) {
|
||||
|
@ -51,6 +52,7 @@ Future<void> initAppLaunch() async {
|
|||
_initSelfSignedCertManager();
|
||||
}
|
||||
_initDiContainer();
|
||||
_initVisibilityDetector();
|
||||
|
||||
_hasInitedInThisIsolate = true;
|
||||
}
|
||||
|
@ -172,6 +174,10 @@ void _initDiContainer() {
|
|||
));
|
||||
}
|
||||
|
||||
void _initVisibilityDetector() {
|
||||
VisibilityDetectorController.instance.updateInterval = Duration.zero;
|
||||
}
|
||||
|
||||
final _log = Logger("app_init");
|
||||
var _hasInitedInThisIsolate = false;
|
||||
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import 'dart:collection';
|
||||
import 'dart:math' as math;
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:draggable_scrollbar/draggable_scrollbar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:kiwi/kiwi.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/account.dart';
|
||||
|
@ -31,6 +34,7 @@ import 'package:nc_photos/service.dart' as service;
|
|||
import 'package:nc_photos/share_handler.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/throttler.dart';
|
||||
import 'package:nc_photos/use_case/sync_favorite.dart';
|
||||
import 'package:nc_photos/widget/album_browser_util.dart' as album_browser_util;
|
||||
import 'package:nc_photos/widget/builder/photo_list_item_builder.dart';
|
||||
|
@ -46,6 +50,7 @@ import 'package:nc_photos/widget/selection_app_bar.dart';
|
|||
import 'package:nc_photos/widget/settings.dart';
|
||||
import 'package:nc_photos/widget/viewer.dart';
|
||||
import 'package:nc_photos/widget/zoom_menu_button.dart';
|
||||
import 'package:visibility_detector/visibility_detector.dart';
|
||||
|
||||
class HomePhotos extends StatefulWidget {
|
||||
const HomePhotos({
|
||||
|
@ -105,6 +110,17 @@ class _HomePhotosState extends State<HomePhotos>
|
|||
});
|
||||
}
|
||||
|
||||
@override
|
||||
onVisibilityChanged(VisibilityInfo info, int index, SelectableItem item) {
|
||||
if (info.visibleFraction >= 0.2) {
|
||||
_visibleItems.add(_VisibleItem(index, item));
|
||||
} else {
|
||||
_visibleItems.remove(_VisibleItem(index, item));
|
||||
}
|
||||
_visibilityThrottler.trigger(
|
||||
maxResponceTime: const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
void _initBloc() {
|
||||
if (_bloc.state is ScanAccountDirBlocInit) {
|
||||
_log.info("[_initBloc] Initialize bloc");
|
||||
|
@ -138,6 +154,8 @@ class _HomePhotosState extends State<HomePhotos>
|
|||
// status bar + app bar
|
||||
topOffset: _calcAppBarExtent(context),
|
||||
bottomOffset: _calcBottomAppBarExtent(context),
|
||||
labelTextBuilder: (_) => _buildScrollLabel(context),
|
||||
labelPadding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
child: ScrollConfiguration(
|
||||
behavior: ScrollConfiguration.of(context)
|
||||
.copyWith(scrollbars: false),
|
||||
|
@ -163,6 +181,7 @@ class _HomePhotosState extends State<HomePhotos>
|
|||
_itemListMaxExtent = value;
|
||||
});
|
||||
},
|
||||
isEnableVisibilityCallback: true,
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(
|
||||
|
@ -318,6 +337,32 @@ class _HomePhotosState extends State<HomePhotos>
|
|||
);
|
||||
}
|
||||
|
||||
Widget _buildScrollLabel(BuildContext context) {
|
||||
final date = _visibleItems
|
||||
.sorted()
|
||||
.firstWhereOrNull((e) => e.item is PhotoListFileItem)
|
||||
?.item
|
||||
.as<PhotoListFileItem>()
|
||||
?.file
|
||||
.bestDateTime;
|
||||
if (date != null) {
|
||||
final text = DateFormat(DateFormat.YEAR_ABBR_MONTH,
|
||||
Localizations.localeOf(context).languageCode)
|
||||
.format(date.toLocal());
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: Text(
|
||||
text,
|
||||
style: const TextStyle(
|
||||
color: AppTheme.primaryTextColorLight,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return const SizedBox();
|
||||
}
|
||||
}
|
||||
|
||||
void _onStateChange(BuildContext context, ScanAccountDirBlocState state) {
|
||||
if (state is ScanAccountDirBlocInit) {
|
||||
itemStreamListItems = [];
|
||||
|
@ -640,6 +685,16 @@ class _HomePhotosState extends State<HomePhotos>
|
|||
|
||||
double? _itemListMaxExtent;
|
||||
|
||||
final _visibleItems = HashSet<_VisibleItem>();
|
||||
late final _visibilityThrottler = Throttler(onTriggered: (_) {
|
||||
// label text is always 1 frame behind, so we need to update the text for
|
||||
// the last frame
|
||||
if (mounted) {
|
||||
_log.fine("[_visibilityThrottler] Update screen");
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
|
||||
late final _prefUpdatedListener =
|
||||
AppEventListener<PrefUpdatedEvent>(_onPrefUpdated);
|
||||
|
||||
|
@ -946,3 +1001,19 @@ enum _SelectionMenuOption {
|
|||
delete,
|
||||
download,
|
||||
}
|
||||
|
||||
class _VisibleItem implements Comparable<_VisibleItem> {
|
||||
const _VisibleItem(this.index, this.item);
|
||||
|
||||
@override
|
||||
operator ==(Object other) => other is _VisibleItem && other.index == index;
|
||||
|
||||
@override
|
||||
compareTo(_VisibleItem other) => index.compareTo(other.index);
|
||||
|
||||
@override
|
||||
get hashCode => index.hashCode;
|
||||
|
||||
final int index;
|
||||
final SelectableItem item;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import 'package:nc_photos/session_storage.dart';
|
|||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/widget/measurable_item_list.dart';
|
||||
import 'package:nc_photos/widget/selectable.dart';
|
||||
import 'package:visibility_detector/visibility_detector.dart';
|
||||
|
||||
abstract class SelectableItem {
|
||||
const SelectableItem();
|
||||
|
@ -33,6 +34,10 @@ mixin SelectableItemStreamListMixin<T extends StatefulWidget> on State<T> {
|
|||
@protected
|
||||
void onItemTap(SelectableItem item, int index);
|
||||
|
||||
@protected
|
||||
void onVisibilityChanged(
|
||||
VisibilityInfo info, int index, SelectableItem item) {}
|
||||
|
||||
@protected
|
||||
Widget buildItemStreamListOuter(
|
||||
BuildContext context, {
|
||||
|
@ -57,6 +62,7 @@ mixin SelectableItemStreamListMixin<T extends StatefulWidget> on State<T> {
|
|||
required double maxCrossAxisExtent,
|
||||
double mainAxisSpacing = 0,
|
||||
ValueChanged<double?>? onMaxExtentChanged,
|
||||
bool isEnableVisibilityCallback = false,
|
||||
}) {
|
||||
final Widget content;
|
||||
if (onMaxExtentChanged != null) {
|
||||
|
@ -64,7 +70,8 @@ mixin SelectableItemStreamListMixin<T extends StatefulWidget> on State<T> {
|
|||
key: _listKey,
|
||||
maxCrossAxisExtent: maxCrossAxisExtent,
|
||||
itemCount: _items.length,
|
||||
itemBuilder: _buildItem,
|
||||
itemBuilder: (context, i) =>
|
||||
_buildItem(context, i, isEnableVisibilityCallback),
|
||||
staggeredTileBuilder: (index) => _items[index].staggeredTile,
|
||||
mainAxisSpacing: mainAxisSpacing,
|
||||
onMaxExtentChanged: onMaxExtentChanged,
|
||||
|
@ -74,7 +81,8 @@ mixin SelectableItemStreamListMixin<T extends StatefulWidget> on State<T> {
|
|||
key: ObjectKey(maxCrossAxisExtent),
|
||||
maxCrossAxisExtent: maxCrossAxisExtent,
|
||||
itemCount: _items.length,
|
||||
itemBuilder: _buildItem,
|
||||
itemBuilder: (context, i) =>
|
||||
_buildItem(context, i, isEnableVisibilityCallback),
|
||||
staggeredTileBuilder: (index) => _items[index].staggeredTile,
|
||||
mainAxisSpacing: mainAxisSpacing,
|
||||
);
|
||||
|
@ -127,11 +135,12 @@ mixin SelectableItemStreamListMixin<T extends StatefulWidget> on State<T> {
|
|||
?.updateListHeight());
|
||||
}
|
||||
|
||||
Widget _buildItem(BuildContext context, int index) {
|
||||
Widget _buildItem(
|
||||
BuildContext context, int index, bool isEnableVisibilityCallback) {
|
||||
final item = _items[index];
|
||||
final content = item.buildWidget(context);
|
||||
Widget content = item.buildWidget(context);
|
||||
if (item.isSelectable) {
|
||||
return Selectable(
|
||||
content = Selectable(
|
||||
isSelected: _selectedItems.contains(item),
|
||||
iconSize: 32,
|
||||
onTap: () => _onItemTap(item, index),
|
||||
|
@ -140,9 +149,15 @@ mixin SelectableItemStreamListMixin<T extends StatefulWidget> on State<T> {
|
|||
: () => _onItemLongPress(item, index),
|
||||
child: content,
|
||||
);
|
||||
} else {
|
||||
return content;
|
||||
}
|
||||
if (isEnableVisibilityCallback) {
|
||||
content = VisibilityDetector(
|
||||
key: Key("$index"),
|
||||
child: content,
|
||||
onVisibilityChanged: (info) => onVisibilityChanged(info, index, item),
|
||||
);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
void _onItemTap(SelectableItem item, int index) {
|
||||
|
|
|
@ -294,8 +294,8 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: "v0.1.0-nc-photos-3"
|
||||
resolved-ref: "805fb925a6129f693abaa8f30ebb11900543ffc8"
|
||||
ref: "v0.1.0-nc-photos-5"
|
||||
resolved-ref: a1a34c57a069dc1cffa9759f86ffab2e0c7420ca
|
||||
url: "https://gitlab.com/nc-photos/flutter-draggable-scrollbar"
|
||||
source: git
|
||||
version: "0.1.0"
|
||||
|
@ -1199,6 +1199,13 @@ packages:
|
|||
url: "https://gitlab.com/nc-photos/flutter-plugins"
|
||||
source: git
|
||||
version: "2.0.4"
|
||||
visibility_detector:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: visibility_detector
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.2"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -43,7 +43,7 @@ dependencies:
|
|||
draggable_scrollbar:
|
||||
git:
|
||||
url: https://gitlab.com/nc-photos/flutter-draggable-scrollbar
|
||||
ref: v0.1.0-nc-photos-3
|
||||
ref: v0.1.0-nc-photos-5
|
||||
equatable: ^2.0.0
|
||||
event_bus: ^2.0.0
|
||||
exifdart:
|
||||
|
@ -97,6 +97,7 @@ dependencies:
|
|||
url: https://gitlab.com/nc-photos/flutter-plugins
|
||||
ref: video_player-v2.2.6-nc-photos-2
|
||||
path: packages/video_player/video_player
|
||||
visibility_detector: ^0.2.2
|
||||
wakelock: ^0.5.2
|
||||
woozy_search: ^2.0.3
|
||||
xml: ^5.0.2
|
||||
|
|
Loading…
Reference in a new issue