refactor: deduplicate shared patterns, replace hardcoded colors
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -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._();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user