mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-07-29 07:18:49 +02:00
- SelectionModeMixin + CollapsingHeaderScrollMixin extracted; local/downloaded album screens now share AlbumTrackTile, AlbumScaffoldBody, DestructiveSelectionButton, HeaderMetaRow, and confirmAndDeleteTracks - track_detail_actions.dart: shared downloadSingleTrack, queueTracksSkippingDownloaded, download-all confirm, queued snackbar, release-date formatter, list footer, love-all - TtlCache<T> replaces the copied 10-minute static caches; album fetch branches share _applyAlbumMetadata - playlist error card now uses ErrorCard; formatMegabytes shared by queue tab and update dialog
37 lines
1.1 KiB
Dart
37 lines
1.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
/// Shared collapsing-header scroll behavior for album-style screens: owns the
|
|
/// [ScrollController] and flips [showTitleInAppBar] once the header has
|
|
/// scrolled out of view.
|
|
mixin CollapsingHeaderScrollMixin<T extends StatefulWidget> on State<T> {
|
|
final ScrollController scrollController = ScrollController();
|
|
bool showTitleInAppBar = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
scrollController.addListener(_onHeaderScroll);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
scrollController.removeListener(_onHeaderScroll);
|
|
scrollController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
double calculateExpandedHeight(BuildContext context) {
|
|
final mediaSize = MediaQuery.sizeOf(context);
|
|
return (mediaSize.height * 0.6).clamp(400.0, 580.0);
|
|
}
|
|
|
|
void _onHeaderScroll() {
|
|
final expandedHeight = calculateExpandedHeight(context);
|
|
final shouldShow =
|
|
scrollController.offset > (expandedHeight - kToolbarHeight - 20);
|
|
if (shouldShow != showTitleInAppBar) {
|
|
setState(() => showTitleInAppBar = shouldShow);
|
|
}
|
|
}
|
|
}
|