chore: format
This commit is contained in:
@@ -137,9 +137,7 @@ class BackKeyPressTracker {
|
||||
/// fallback in case our tracking drifted out of sync.
|
||||
static bool get isBackKeyDown {
|
||||
if (_isBackKeyDown) return true;
|
||||
return HardwareKeyboard.instance.logicalKeysPressed.any(
|
||||
(key) => key.isBackKey,
|
||||
);
|
||||
return HardwareKeyboard.instance.logicalKeysPressed.any((key) => key.isBackKey);
|
||||
}
|
||||
|
||||
static bool handleKeyEvent(KeyEvent event) {
|
||||
|
||||
@@ -141,8 +141,9 @@ class VideoPlayerScreenState extends State<VideoPlayerScreen> with WidgetsBindin
|
||||
final partId = _currentMediaInfo?.partId;
|
||||
if (partId == null || widget.isOffline) return null;
|
||||
final client = _getClientForMetadata(context);
|
||||
return '${client.config.baseUrl}/library/parts/$partId/indexes/sd/${time.inMilliseconds}'
|
||||
.withPlexToken(client.config.token);
|
||||
return '${client.config.baseUrl}/library/parts/$partId/indexes/sd/${time.inMilliseconds}'.withPlexToken(
|
||||
client.config.token,
|
||||
);
|
||||
}
|
||||
|
||||
final ValueNotifier<bool> _isBuffering = ValueNotifier<bool>(false); // Track if video is currently buffering
|
||||
|
||||
@@ -213,8 +213,7 @@ class DownloadManagerService {
|
||||
if (inner is SocketException) return true;
|
||||
if (inner is HttpException) return true;
|
||||
final msg = inner?.toString() ?? '';
|
||||
if (msg.contains('Connection closed') ||
|
||||
msg.contains('Connection reset')) {
|
||||
if (msg.contains('Connection closed') || msg.contains('Connection reset')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -256,9 +255,7 @@ class DownloadManagerService {
|
||||
Future<void> recoverInterruptedDownloads() async {
|
||||
try {
|
||||
final allDownloads = await _database.select(_database.downloadedMedia).get();
|
||||
final interrupted = allDownloads.where(
|
||||
(item) => item.status == DownloadStatus.downloading.index,
|
||||
).toList();
|
||||
final interrupted = allDownloads.where((item) => item.status == DownloadStatus.downloading.index).toList();
|
||||
|
||||
if (interrupted.isEmpty) return;
|
||||
|
||||
@@ -648,8 +645,7 @@ class DownloadManagerService {
|
||||
responseType: ResponseType.stream,
|
||||
headers: headers,
|
||||
// Prevent Dio from throwing on 206/416
|
||||
validateStatus: (status) =>
|
||||
status != null && (status >= 200 && status < 300 || status == 416),
|
||||
validateStatus: (status) => status != null && (status >= 200 && status < 300 || status == 416),
|
||||
),
|
||||
cancelToken: cancelToken,
|
||||
);
|
||||
@@ -687,9 +683,7 @@ class DownloadManagerService {
|
||||
totalBytes = match != null ? int.parse(match.group(1)!) : -1;
|
||||
} else {
|
||||
final contentLength = response.headers.value('content-length');
|
||||
totalBytes = contentLength != null
|
||||
? int.parse(contentLength) + offset
|
||||
: -1;
|
||||
totalBytes = contentLength != null ? int.parse(contentLength) + offset : -1;
|
||||
}
|
||||
appLogger.i('Resuming download at $offset/$totalBytes for $globalKey');
|
||||
} else {
|
||||
@@ -719,15 +713,11 @@ class DownloadManagerService {
|
||||
final now = DateTime.now();
|
||||
if (now.difference(lastUpdate).inMilliseconds >= 500) {
|
||||
final elapsed = now.difference(lastUpdate).inMilliseconds / 1000.0;
|
||||
final bytesPerSecond = elapsed > 0
|
||||
? (receivedBytes - lastReportedBytes) / elapsed
|
||||
: 0.0;
|
||||
final bytesPerSecond = elapsed > 0 ? (receivedBytes - lastReportedBytes) / elapsed : 0.0;
|
||||
lastUpdate = now;
|
||||
lastReportedBytes = receivedBytes;
|
||||
|
||||
final progress = totalBytes > 0
|
||||
? ((receivedBytes / totalBytes) * 100).round()
|
||||
: 0;
|
||||
final progress = totalBytes > 0 ? ((receivedBytes / totalBytes) * 100).round() : 0;
|
||||
|
||||
_progressController.add(
|
||||
DownloadProgress(
|
||||
@@ -741,9 +731,7 @@ class DownloadManagerService {
|
||||
),
|
||||
);
|
||||
|
||||
_database
|
||||
.updateDownloadProgress(globalKey, progress, receivedBytes, totalBytes)
|
||||
.catchError((e) {
|
||||
_database.updateDownloadProgress(globalKey, progress, receivedBytes, totalBytes).catchError((e) {
|
||||
appLogger.w('Failed to update download progress in DB', error: e);
|
||||
});
|
||||
}
|
||||
@@ -757,9 +745,7 @@ class DownloadManagerService {
|
||||
if (totalBytes > 0) {
|
||||
final actualSize = await partFile.length();
|
||||
if (actualSize != totalBytes) {
|
||||
throw Exception(
|
||||
'Download size mismatch: expected $totalBytes bytes but got $actualSize',
|
||||
);
|
||||
throw Exception('Download size mismatch: expected $totalBytes bytes but got $actualSize');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -775,12 +761,8 @@ class DownloadManagerService {
|
||||
// Ignore flush errors during error handling
|
||||
}
|
||||
// Persist current progress to DB for resume
|
||||
final progress = totalBytes > 0
|
||||
? ((receivedBytes / totalBytes) * 100).round()
|
||||
: 0;
|
||||
await _database
|
||||
.updateDownloadProgress(globalKey, progress, receivedBytes, totalBytes)
|
||||
.catchError((dbErr) {
|
||||
final progress = totalBytes > 0 ? ((receivedBytes / totalBytes) * 100).round() : 0;
|
||||
await _database.updateDownloadProgress(globalKey, progress, receivedBytes, totalBytes).catchError((dbErr) {
|
||||
appLogger.w('Failed to persist progress on error', error: dbErr);
|
||||
});
|
||||
rethrow;
|
||||
|
||||
@@ -13,9 +13,7 @@ import '../utils/connection_constants.dart';
|
||||
/// E.g. `192.168.1.50` → `192.***.***.50`, `my.server.example.com` → `my.***.***. com`.
|
||||
String _redactHost(String host) {
|
||||
// Strip brackets from IPv6
|
||||
final bare = host.startsWith('[') && host.endsWith(']')
|
||||
? host.substring(1, host.length - 1)
|
||||
: host;
|
||||
final bare = host.startsWith('[') && host.endsWith(']') ? host.substring(1, host.length - 1) : host;
|
||||
|
||||
// IPv6
|
||||
if (bare.contains(':')) {
|
||||
@@ -413,17 +411,17 @@ class PlexServer {
|
||||
);
|
||||
|
||||
for (final conn in connections) {
|
||||
final redactedUri = conn.uri.replaceAll(
|
||||
RegExp(r'//[^:/]+'),
|
||||
'//${_redactHost(conn.address)}',
|
||||
final redactedUri = conn.uri.replaceAll(RegExp(r'//[^:/]+'), '//${_redactHost(conn.address)}');
|
||||
appLogger.d(
|
||||
'Raw API connection',
|
||||
error: {
|
||||
'uri': redactedUri,
|
||||
'address': _redactHost(conn.address),
|
||||
'local': conn.local,
|
||||
'relay': conn.relay,
|
||||
'protocol': conn.protocol,
|
||||
},
|
||||
);
|
||||
appLogger.d('Raw API connection', error: {
|
||||
'uri': redactedUri,
|
||||
'address': _redactHost(conn.address),
|
||||
'local': conn.local,
|
||||
'relay': conn.relay,
|
||||
'protocol': conn.protocol,
|
||||
});
|
||||
}
|
||||
|
||||
_ConnectionCandidate? firstCandidate;
|
||||
@@ -460,13 +458,16 @@ class PlexServer {
|
||||
completedTests++;
|
||||
|
||||
if (!result.success) {
|
||||
appLogger.w('Connection candidate failed', error: {
|
||||
'url': candidate.url,
|
||||
'type': candidate.connection.displayType,
|
||||
'https': candidate.isHttps,
|
||||
'error': result.error,
|
||||
'latencyMs': result.latencyMs,
|
||||
});
|
||||
appLogger.w(
|
||||
'Connection candidate failed',
|
||||
error: {
|
||||
'url': candidate.url,
|
||||
'type': candidate.connection.displayType,
|
||||
'https': candidate.isHttps,
|
||||
'error': result.error,
|
||||
'latencyMs': result.latencyMs,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (result.success && !completer.isCompleted) {
|
||||
@@ -481,11 +482,14 @@ class PlexServer {
|
||||
|
||||
firstCandidate = await completer.future;
|
||||
if (firstCandidate == null) {
|
||||
appLogger.e('No working server connections after race', error: {
|
||||
'server': name,
|
||||
'candidateCount': totalCandidates,
|
||||
'types': candidates.map((c) => c.connection.displayType).toSet().toList(),
|
||||
});
|
||||
appLogger.e(
|
||||
'No working server connections after race',
|
||||
error: {
|
||||
'server': name,
|
||||
'candidateCount': totalCandidates,
|
||||
'types': candidates.map((c) => c.connection.displayType).toSet().toList(),
|
||||
},
|
||||
);
|
||||
return; // No working connections found
|
||||
}
|
||||
appLogger.i(
|
||||
|
||||
@@ -174,10 +174,10 @@ class PlexClient {
|
||||
error = e.type == DioExceptionType.connectionTimeout
|
||||
? 'Connection timeout'
|
||||
: e.type == DioExceptionType.receiveTimeout
|
||||
? 'Receive timeout'
|
||||
: e.type == DioExceptionType.connectionError
|
||||
? 'Connection error'
|
||||
: e.type.name;
|
||||
? 'Receive timeout'
|
||||
: e.type == DioExceptionType.connectionError
|
||||
? 'Connection error'
|
||||
: e.type.name;
|
||||
if (e.response?.statusCode != null) {
|
||||
error += ' (HTTP ${e.response!.statusCode})';
|
||||
}
|
||||
|
||||
@@ -43,10 +43,7 @@ class _TvColorPickerState extends State<TvColorPicker> {
|
||||
_saturation = (hsv.saturation * 100).round();
|
||||
_value = (hsv.value * 100).round();
|
||||
_hexController = TextEditingController(text: _currentHex());
|
||||
_hexFocusNode = FocusNode(
|
||||
debugLabel: 'TvColorPicker_hex',
|
||||
onKeyEvent: _handleHexKeyEvent,
|
||||
);
|
||||
_hexFocusNode = FocusNode(debugLabel: 'TvColorPicker_hex', onKeyEvent: _handleHexKeyEvent);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -459,6 +459,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.33"
|
||||
flutter_svg:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_svg
|
||||
sha256: "87fbd7c534435b6c5d9d98b01e1fd527812b82e68ddd8bd35fc45ed0fa8f0a95"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.3"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
@@ -742,6 +750,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
path_parsing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_parsing
|
||||
sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
path_provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -1307,6 +1323,30 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.5.2"
|
||||
vector_graphics:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics
|
||||
sha256: a4f059dc26fc8295b5921376600a194c4ec7d55e72f2fe4c7d2831e103d461e6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.19"
|
||||
vector_graphics_codec:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics_codec
|
||||
sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.13"
|
||||
vector_graphics_compiler:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics_compiler
|
||||
sha256: "201e876b5d52753626af64b6359cd13ac6011b80728731428fd34bc840f71c9b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.20"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -47,6 +47,7 @@ dependencies:
|
||||
web_socket_channel: ^3.0.1
|
||||
in_app_review: ^2.0.11
|
||||
dart_discord_presence: ^1.1.0
|
||||
flutter_svg: ^2.2.3
|
||||
|
||||
|
||||
dev_dependencies:
|
||||
@@ -68,6 +69,7 @@ flutter:
|
||||
- assets/go-noto-current-regular.ttf
|
||||
- assets/shaders/nvscaler/
|
||||
- assets/shaders/anime4k/
|
||||
- assets/rating_icons/
|
||||
|
||||
flutter_launcher_icons:
|
||||
android: true
|
||||
|
||||
Reference in New Issue
Block a user