refactor: deduplicate shared patterns, replace hardcoded colors

This commit is contained in:
edde746
2026-03-03 22:43:00 +01:00
parent 8f3d52142d
commit cd2ab9d9cd
42 changed files with 685 additions and 612 deletions
+5 -27
View File
@@ -5,33 +5,27 @@ import 'platform_detector.dart';
/// Utility class for calculating consistent grid sizes across the app
class GridSizeCalculator {
/// Screen width breakpoint for tablet devices
static const double tabletBreakpoint = ScreenBreakpoints.tablet;
/// Screen width breakpoint for desktop devices
static const double desktopBreakpoint = ScreenBreakpoints.desktop;
/// Calculates the maximum cross-axis extent for grid items based on screen size and density
static double getMaxCrossAxisExtent(BuildContext context, LibraryDensity density) {
final screenWidth = MediaQuery.of(context).size.width;
final isTV = PlatformDetector.isTV();
final isDesktop = screenWidth > desktopBreakpoint;
final isTablet = screenWidth > tabletBreakpoint && screenWidth <= desktopBreakpoint;
final isDesktopOrLarger = ScreenBreakpoints.isDesktopOrLarger(screenWidth);
final isTablet = ScreenBreakpoints.isTablet(screenWidth);
switch (density) {
case LibraryDensity.comfortable:
if (isTV) return GridLayoutConstants.comfortableTV;
if (isDesktop) return GridLayoutConstants.comfortableDesktop;
if (isDesktopOrLarger) return GridLayoutConstants.comfortableDesktop;
if (isTablet) return GridLayoutConstants.comfortableTablet;
return GridLayoutConstants.comfortableMobile;
case LibraryDensity.compact:
if (isTV) return GridLayoutConstants.compactTV;
if (isDesktop) return GridLayoutConstants.compactDesktop;
if (isDesktopOrLarger) return GridLayoutConstants.compactDesktop;
if (isTablet) return GridLayoutConstants.compactTablet;
return GridLayoutConstants.compactMobile;
case LibraryDensity.normal:
if (isTV) return GridLayoutConstants.normalTV;
if (isDesktop) return GridLayoutConstants.normalDesktop;
if (isDesktopOrLarger) return GridLayoutConstants.normalDesktop;
if (isTablet) return GridLayoutConstants.normalTablet;
return GridLayoutConstants.normalMobile;
}
@@ -106,22 +100,6 @@ class GridSizeCalculator {
}
}
/// Returns whether the current screen is a desktop-sized screen
static bool isDesktop(BuildContext context) {
return MediaQuery.of(context).size.width > desktopBreakpoint;
}
/// Returns whether the current screen is a tablet-sized screen
static bool isTablet(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
return screenWidth > tabletBreakpoint && screenWidth <= desktopBreakpoint;
}
/// Returns whether the current screen is a mobile-sized screen
static bool isMobile(BuildContext context) {
return MediaQuery.of(context).size.width <= tabletBreakpoint;
}
/// Calculates the number of columns for a given available width.
///
/// Uses the same formula as Flutter's SliverGridDelegateWithMaxCrossAxisExtent:
+18
View File
@@ -0,0 +1,18 @@
import 'package:dio/dio.dart';
/// Creates a plain [Dio] instance with sensible default timeouts for ad-hoc
/// HTTP requests that don't go through [PlexClient].
///
/// Use this instead of bare `Dio()` so every call site gets consistent timeout
/// behaviour without duplicating configuration.
Dio createHttpClient({
Duration connectTimeout = const Duration(seconds: 10),
Duration receiveTimeout = const Duration(seconds: 30),
}) {
return Dio(
BaseOptions(
connectTimeout: connectTimeout,
receiveTimeout: receiveTimeout,
),
);
}
+19 -4
View File
@@ -1,10 +1,25 @@
import 'codec_utils.dart';
import '../models/plex_media_info.dart' show buildTrackLabel;
/// Builds a track label from parts with the standard `' · '` joiner pattern.
///
/// Shared by both Plex track models and MPV track label utilities.
/// If [title] is non-empty it is added first, then [language], then [extraParts].
/// Falls back to `'$fallbackPrefix ${index + 1}'` when no parts are available.
String buildTrackLabel({
String? title,
String? language,
List<String> extraParts = const [],
required int index,
String fallbackPrefix = 'Track',
}) {
final parts = <String>[];
if (title != null && title.isNotEmpty) parts.add(title);
if (language != null && language.isNotEmpty) parts.add(language);
parts.addAll(extraParts);
return parts.isEmpty ? '$fallbackPrefix ${index + 1}' : parts.join(' · ');
}
/// Utility for building track labels for audio and subtitle tracks.
///
/// Delegates to the shared [buildTrackLabel] function so Plex-model and
/// MPV-player label logic stays consistent.
class TrackLabelBuilder {
TrackLabelBuilder._();