chore: dart format
This commit is contained in:
+6
-8
@@ -813,11 +813,7 @@ class _TrackerProfileBootstrap extends StatefulWidget {
|
||||
final List<Future<void> Function(String? uuid)> onProfileChanged;
|
||||
final VoidCallback? onFirstMount;
|
||||
|
||||
const _TrackerProfileBootstrap({
|
||||
required this.child,
|
||||
required this.onProfileChanged,
|
||||
this.onFirstMount,
|
||||
});
|
||||
const _TrackerProfileBootstrap({required this.child, required this.onProfileChanged, this.onFirstMount});
|
||||
|
||||
@override
|
||||
State<_TrackerProfileBootstrap> createState() => _TrackerProfileBootstrapState();
|
||||
@@ -851,9 +847,11 @@ class _TrackerProfileBootstrapState extends State<_TrackerProfileBootstrap> {
|
||||
if (uuid == _lastUuid) return;
|
||||
_lastUuid = uuid;
|
||||
for (final fn in widget.onProfileChanged) {
|
||||
unawaited(fn(uuid).catchError((Object e, StackTrace s) {
|
||||
appLogger.w('Tracker profile bootstrap failed', error: e, stackTrace: s);
|
||||
}));
|
||||
unawaited(
|
||||
fn(uuid).catchError((Object e, StackTrace s) {
|
||||
appLogger.w('Tracker profile bootstrap failed', error: e, stackTrace: s);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,9 +12,6 @@ class AnimeIds {
|
||||
|
||||
const AnimeIds({this.mal, this.anilist, this.simkl});
|
||||
|
||||
factory AnimeIds.fromFribb(FribbMappingRow row) => AnimeIds(
|
||||
mal: row.malId,
|
||||
anilist: row.anilistId,
|
||||
simkl: row.simklId,
|
||||
);
|
||||
factory AnimeIds.fromFribb(FribbMappingRow row) =>
|
||||
AnimeIds(mal: row.malId, anilist: row.anilistId, simkl: row.simklId);
|
||||
}
|
||||
|
||||
@@ -32,9 +32,5 @@ class TraktIds {
|
||||
tvdb: (json['tvdb'] as num?)?.toInt(),
|
||||
);
|
||||
|
||||
factory TraktIds.fromExternal(PlexExternalIds ids) => TraktIds(
|
||||
imdb: ids.imdb,
|
||||
tmdb: ids.tmdb,
|
||||
tvdb: ids.tvdb,
|
||||
);
|
||||
factory TraktIds.fromExternal(PlexExternalIds ids) => TraktIds(imdb: ids.imdb, tmdb: ids.tmdb, tvdb: ids.tvdb);
|
||||
}
|
||||
|
||||
@@ -83,10 +83,7 @@ class TrackersProvider extends ChangeNotifier {
|
||||
Future<bool> connectMal({required void Function(OAuthProxyStart) onCodeReady}) => _runConnect<MalSession>(
|
||||
service: TrackerService.mal,
|
||||
alreadyConnected: isMalConnected,
|
||||
authorize: () => _malAuth.authorize(
|
||||
onCodeReady: onCodeReady,
|
||||
shouldCancel: () => _cancelRequested,
|
||||
),
|
||||
authorize: () => _malAuth.authorize(onCodeReady: onCodeReady, shouldCancel: () => _cancelRequested),
|
||||
enrich: _enrichMal,
|
||||
store: malAccountStore,
|
||||
assign: (s) {
|
||||
@@ -103,10 +100,7 @@ class TrackersProvider extends ChangeNotifier {
|
||||
Future<bool> connectAnilist({required void Function(OAuthProxyStart) onCodeReady}) => _runConnect<AnilistSession>(
|
||||
service: TrackerService.anilist,
|
||||
alreadyConnected: isAnilistConnected,
|
||||
authorize: () => _anilistAuth.authorize(
|
||||
onCodeReady: onCodeReady,
|
||||
shouldCancel: () => _cancelRequested,
|
||||
),
|
||||
authorize: () => _anilistAuth.authorize(onCodeReady: onCodeReady, shouldCancel: () => _cancelRequested),
|
||||
enrich: _enrichAnilist,
|
||||
store: anilistAccountStore,
|
||||
assign: (s) {
|
||||
@@ -123,10 +117,7 @@ class TrackersProvider extends ChangeNotifier {
|
||||
Future<bool> connectSimkl({required void Function(DeviceCode code) onCodeReady}) => _runConnect<SimklSession>(
|
||||
service: TrackerService.simkl,
|
||||
alreadyConnected: isSimklConnected,
|
||||
authorize: () => _simklAuth.authorize(
|
||||
onCodeReady: onCodeReady,
|
||||
shouldCancel: () => _cancelRequested,
|
||||
),
|
||||
authorize: () => _simklAuth.authorize(onCodeReady: onCodeReady, shouldCancel: () => _cancelRequested),
|
||||
enrich: _enrichSimkl,
|
||||
store: simklAccountStore,
|
||||
assign: (s) {
|
||||
|
||||
@@ -53,10 +53,7 @@ class TraktAccountProvider extends ChangeNotifier {
|
||||
try {
|
||||
return await runConnectPipeline<TraktSession>(
|
||||
logLabel: 'Trakt',
|
||||
authorize: () => _auth.authorize(
|
||||
onCodeReady: onCodeReady,
|
||||
shouldCancel: () => _cancelRequested,
|
||||
),
|
||||
authorize: () => _auth.authorize(onCodeReady: onCodeReady, shouldCancel: () => _cancelRequested),
|
||||
enrich: _enrichUsername,
|
||||
save: (s) => _store.save(_activeUserUuid, s),
|
||||
assign: _setSessionAndRebind,
|
||||
|
||||
@@ -154,9 +154,7 @@ class _TrackerLibraryFilterScreenState extends State<TrackerLibraryFilterScreen>
|
||||
|
||||
return FocusedScrollScaffold(
|
||||
title: title,
|
||||
slivers: [
|
||||
SliverList(delegate: SliverChildListDelegate(children)),
|
||||
],
|
||||
slivers: [SliverList(delegate: SliverChildListDelegate(children))],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -198,9 +198,7 @@ class _TrackerSettingsScreenState extends State<TrackerSettingsScreen> {
|
||||
ListTile(
|
||||
leading: const AppIcon(Symbols.account_circle_rounded, fill: 1),
|
||||
title: Text(
|
||||
username != null
|
||||
? t.trackers.connectedAs(username: username)
|
||||
: widget.config.displayName,
|
||||
username != null ? t.trackers.connectedAs(username: username) : widget.config.displayName,
|
||||
),
|
||||
),
|
||||
SettingsSectionHeader(t.settings.behavior),
|
||||
@@ -231,10 +229,7 @@ class _TrackerSettingsScreenState extends State<TrackerSettingsScreen> {
|
||||
const Divider(height: 32),
|
||||
ListTile(
|
||||
leading: AppIcon(Symbols.link_off_rounded, fill: 1, color: Theme.of(context).colorScheme.error),
|
||||
title: Text(
|
||||
t.common.disconnect,
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.error),
|
||||
),
|
||||
title: Text(t.common.disconnect, style: TextStyle(color: Theme.of(context).colorScheme.error)),
|
||||
onTap: () => _disconnect(account),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
@@ -27,9 +27,9 @@ class TrackersSettingsScreen extends StatelessWidget {
|
||||
padding: const EdgeInsets.fromLTRB(16, 8, 16, 16),
|
||||
child: Text(
|
||||
t.trackers.hubSubtitle,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.bodyMedium?.copyWith(color: Theme.of(context).colorScheme.onSurfaceVariant),
|
||||
),
|
||||
),
|
||||
_trakt(),
|
||||
|
||||
@@ -162,4 +162,3 @@ class _TraktSettingsScreenState extends State<TraktSettingsScreen> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -402,11 +402,13 @@ class DownloadManagerService {
|
||||
final saf = SafStorageService.instance;
|
||||
final children = await saf.list(dirUri);
|
||||
if (children != null && children.isNotEmpty) {
|
||||
await Future.wait(children.map((child) {
|
||||
return child.isDir
|
||||
? _deleteSafDirRecursive(child.uri, description: description)
|
||||
: saf.delete(child.uri, isDir: false);
|
||||
}));
|
||||
await Future.wait(
|
||||
children.map((child) {
|
||||
return child.isDir
|
||||
? _deleteSafDirRecursive(child.uri, description: description)
|
||||
: saf.delete(child.uri, isDir: false);
|
||||
}),
|
||||
);
|
||||
}
|
||||
await _tryDeleteSaf(dirUri, isDir: true, description: description);
|
||||
}
|
||||
@@ -1491,24 +1493,16 @@ class DownloadManagerService {
|
||||
final isSaf = _storageService.isUsingSaf;
|
||||
switch (metadata.mediaType) {
|
||||
case PlexMediaType.episode:
|
||||
isSaf
|
||||
? await _deleteEpisodeFilesSaf(metadata, serverId)
|
||||
: await _deleteEpisodeFiles(metadata, serverId);
|
||||
isSaf ? await _deleteEpisodeFilesSaf(metadata, serverId) : await _deleteEpisodeFiles(metadata, serverId);
|
||||
break;
|
||||
case PlexMediaType.season:
|
||||
isSaf
|
||||
? await _deleteSeasonFilesSaf(metadata, serverId)
|
||||
: await _deleteSeasonFiles(metadata, serverId);
|
||||
isSaf ? await _deleteSeasonFilesSaf(metadata, serverId) : await _deleteSeasonFiles(metadata, serverId);
|
||||
break;
|
||||
case PlexMediaType.show:
|
||||
isSaf
|
||||
? await _deleteShowFilesSaf(metadata, serverId)
|
||||
: await _deleteShowFiles(metadata, serverId);
|
||||
isSaf ? await _deleteShowFilesSaf(metadata, serverId) : await _deleteShowFiles(metadata, serverId);
|
||||
break;
|
||||
case PlexMediaType.movie:
|
||||
isSaf
|
||||
? await _deleteMovieFilesSaf(metadata, serverId)
|
||||
: await _deleteMovieFiles(metadata, serverId);
|
||||
isSaf ? await _deleteMovieFilesSaf(metadata, serverId) : await _deleteMovieFiles(metadata, serverId);
|
||||
break;
|
||||
default:
|
||||
appLogger.w('Unknown type for deletion: ${metadata.type}');
|
||||
|
||||
@@ -1567,10 +1567,12 @@ class SettingsService extends BaseSharedPreferencesService {
|
||||
prefs.remove(_keyEnableMalScrobble),
|
||||
prefs.remove(_keyEnableAnilistScrobble),
|
||||
prefs.remove(_keyEnableSimklScrobble),
|
||||
...TrackerService.values.expand((s) => [
|
||||
prefs.remove('$_prefixTrackerLibraryFilterMode${s.name}'),
|
||||
prefs.remove('$_prefixTrackerLibraryFilterIds${s.name}'),
|
||||
]),
|
||||
...TrackerService.values.expand(
|
||||
(s) => [
|
||||
prefs.remove('$_prefixTrackerLibraryFilterMode${s.name}'),
|
||||
prefs.remove('$_prefixTrackerLibraryFilterIds${s.name}'),
|
||||
],
|
||||
),
|
||||
prefs.remove(_keyAutoPip),
|
||||
prefs.remove(_keyMatchContentFrameRate),
|
||||
prefs.remove(_keyTunneledPlayback),
|
||||
|
||||
@@ -12,12 +12,7 @@ class AnilistSession {
|
||||
final String? username;
|
||||
final int createdAt;
|
||||
|
||||
const AnilistSession({
|
||||
required this.accessToken,
|
||||
required this.expiresAt,
|
||||
required this.createdAt,
|
||||
this.username,
|
||||
});
|
||||
const AnilistSession({required this.accessToken, required this.expiresAt, required this.createdAt, this.username});
|
||||
|
||||
bool get isExpired => DateTime.now().millisecondsSinceEpoch ~/ 1000 >= expiresAt;
|
||||
|
||||
@@ -50,11 +45,7 @@ class AnilistSession {
|
||||
factory AnilistSession.fromProxyResult(OAuthProxyResult r) {
|
||||
final createdAt = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||
final expiresIn = r.expiresIn ?? 365 * 24 * 60 * 60;
|
||||
return AnilistSession(
|
||||
accessToken: r.accessToken,
|
||||
expiresAt: createdAt + expiresIn,
|
||||
createdAt: createdAt,
|
||||
);
|
||||
return AnilistSession(accessToken: r.accessToken, expiresAt: createdAt + expiresIn, createdAt: createdAt);
|
||||
}
|
||||
|
||||
String encode() => json.encode(toJson());
|
||||
|
||||
@@ -16,8 +16,7 @@ import 'device_code_poller.dart' as poller;
|
||||
abstract class DeviceCodeAuthServiceBase<T> {
|
||||
final http.Client httpClient;
|
||||
|
||||
DeviceCodeAuthServiceBase({http.Client? httpClient})
|
||||
: httpClient = httpClient ?? platform.createPlatformClient();
|
||||
DeviceCodeAuthServiceBase({http.Client? httpClient}) : httpClient = httpClient ?? platform.createPlatformClient();
|
||||
|
||||
void dispose() => httpClient.close();
|
||||
|
||||
@@ -33,17 +32,10 @@ abstract class DeviceCodeAuthServiceBase<T> {
|
||||
/// Drive the full flow. Invokes [onCodeReady] once with the code so the UI
|
||||
/// can render the dialog, then polls until the user authorizes, denies, or
|
||||
/// the code expires. Returns null on denied/expired/cancel.
|
||||
Future<T?> authorize({
|
||||
required void Function(DeviceCode code) onCodeReady,
|
||||
bool Function()? shouldCancel,
|
||||
}) async {
|
||||
Future<T?> authorize({required void Function(DeviceCode code) onCodeReady, bool Function()? shouldCancel}) async {
|
||||
final code = await createDeviceCode();
|
||||
onCodeReady(code);
|
||||
await for (final event in poller.pollDeviceCode(
|
||||
code,
|
||||
shouldCancel: shouldCancel,
|
||||
probe: () => probe(code),
|
||||
)) {
|
||||
await for (final event in poller.pollDeviceCode(code, shouldCancel: shouldCancel, probe: () => probe(code))) {
|
||||
if (event is DevicePollSuccess) return buildSession(event.tokenResponse);
|
||||
if (event is DevicePollDenied || event is DevicePollExpired) return null;
|
||||
}
|
||||
|
||||
@@ -156,10 +156,7 @@ class FribbMappingStore {
|
||||
final client = platform.createPlatformClient();
|
||||
try {
|
||||
final res = await client
|
||||
.get(
|
||||
Uri.parse(_sourceUrl),
|
||||
headers: {'If-None-Match': ?etag, 'Accept': 'application/json'},
|
||||
)
|
||||
.get(Uri.parse(_sourceUrl), headers: {'If-None-Match': ?etag, 'Accept': 'application/json'})
|
||||
.timeout(_requestTimeout);
|
||||
await prefs.setInt(_prefsLastCheckKey, now);
|
||||
|
||||
|
||||
@@ -127,7 +127,9 @@ class MalClient {
|
||||
String? encoded;
|
||||
if (formBody != null) {
|
||||
headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||
encoded = formBody.entries.map((e) => '${Uri.encodeQueryComponent(e.key)}=${Uri.encodeQueryComponent(e.value)}').join('&');
|
||||
encoded = formBody.entries
|
||||
.map((e) => '${Uri.encodeQueryComponent(e.key)}=${Uri.encodeQueryComponent(e.value)}')
|
||||
.join('&');
|
||||
} else if (body != null) {
|
||||
headers['Content-Type'] = 'application/json';
|
||||
encoded = json.encode(body);
|
||||
|
||||
@@ -21,10 +21,7 @@ class SimklAuthService extends DeviceCodeAuthServiceBase<SimklSession> {
|
||||
@override
|
||||
Future<DeviceCode> createDeviceCode() async {
|
||||
final uri = Uri.parse(SimklConstants.pinUrl).replace(
|
||||
queryParameters: {
|
||||
'client_id': SimklConstants.clientId,
|
||||
'redirect': '${OAuthProxyClient.baseUrl}/auth/done',
|
||||
},
|
||||
queryParameters: {'client_id': SimklConstants.clientId, 'redirect': '${OAuthProxyClient.baseUrl}/auth/done'},
|
||||
);
|
||||
final res = await httpClient.get(uri, headers: SimklConstants.headers()).timeout(const Duration(seconds: 15));
|
||||
if (res.statusCode != 200) {
|
||||
|
||||
@@ -17,11 +17,7 @@ class SimklSession {
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'access_token': accessToken,
|
||||
'username': username,
|
||||
'created_at': createdAt,
|
||||
};
|
||||
Map<String, dynamic> toJson() => {'access_token': accessToken, 'username': username, 'created_at': createdAt};
|
||||
|
||||
factory SimklSession.fromJson(Map<String, dynamic> json) => SimklSession(
|
||||
accessToken: json['access_token'] as String,
|
||||
|
||||
@@ -21,11 +21,7 @@ class TrackerCoordinator {
|
||||
|
||||
TrackerCoordinator._();
|
||||
|
||||
late final List<Tracker> _trackers = [
|
||||
MalTracker.instance,
|
||||
AnilistTracker.instance,
|
||||
SimklTracker.instance,
|
||||
];
|
||||
late final List<Tracker> _trackers = [MalTracker.instance, AnilistTracker.instance, SimklTracker.instance];
|
||||
|
||||
/// Resolver persists across episode swaps so back-to-back episodes of the
|
||||
/// same show reuse the cached IDs. Cleared only on profile switch.
|
||||
@@ -113,16 +109,16 @@ class TrackerCoordinator {
|
||||
}
|
||||
|
||||
Future<void> _dispatchMarkWatched(TrackerContext ctx) async {
|
||||
final active = _trackers.where(
|
||||
(t) => t.canScrobble && t.shouldScrobbleForLibrary(ctx.libraryGlobalKey),
|
||||
final active = _trackers.where((t) => t.canScrobble && t.shouldScrobbleForLibrary(ctx.libraryGlobalKey));
|
||||
await Future.wait(
|
||||
active.map((t) async {
|
||||
try {
|
||||
await t.markWatched(ctx);
|
||||
} catch (e) {
|
||||
appLogger.d('${t.name}: markWatched failed', error: e);
|
||||
}
|
||||
}),
|
||||
);
|
||||
await Future.wait(active.map((t) async {
|
||||
try {
|
||||
await t.markWatched(ctx);
|
||||
} catch (e) {
|
||||
appLogger.d('${t.name}: markWatched failed', error: e);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
Future<TrackerContext?> _buildContext(PlexMetadata metadata) async {
|
||||
|
||||
@@ -34,12 +34,9 @@ class TrackerIdResolver {
|
||||
/// un-matched item doesn't re-hit Plex every position update.
|
||||
final Map<String, TrackerIds?> _cache = {};
|
||||
|
||||
TrackerIdResolver(
|
||||
this._client, {
|
||||
bool Function()? needsFribb,
|
||||
FribbMappingStore? store,
|
||||
}) : _needsFribb = needsFribb ?? _returnTrue,
|
||||
_store = store ?? FribbMappingStore.instance;
|
||||
TrackerIdResolver(this._client, {bool Function()? needsFribb, FribbMappingStore? store})
|
||||
: _needsFribb = needsFribb ?? _returnTrue,
|
||||
_store = store ?? FribbMappingStore.instance;
|
||||
|
||||
static bool _returnTrue() => true;
|
||||
|
||||
|
||||
@@ -111,8 +111,7 @@ class TraktSyncService {
|
||||
if (kind == null) return;
|
||||
|
||||
final settings = SettingsService.instanceOrNull;
|
||||
if (settings != null &&
|
||||
!settings.isLibraryAllowedForTracker(TrackerService.trakt, event.librarySectionGlobalKey)) {
|
||||
if (settings != null && !settings.isLibraryAllowedForTracker(TrackerService.trakt, event.librarySectionGlobalKey)) {
|
||||
appLogger.d('Trakt sync: library filtered out for ${event.ratingKey}');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -18,12 +18,7 @@ class DeviceCodeDialog extends StatelessWidget {
|
||||
final String serviceName;
|
||||
final VoidCallback onCancel;
|
||||
|
||||
const DeviceCodeDialog({
|
||||
super.key,
|
||||
required this.code,
|
||||
required this.serviceName,
|
||||
required this.onCancel,
|
||||
});
|
||||
const DeviceCodeDialog({super.key, required this.code, required this.serviceName, required this.onCancel});
|
||||
|
||||
Future<void> _open() async {
|
||||
final url = code.verificationUrlComplete ?? code.verificationUrl;
|
||||
@@ -78,9 +73,7 @@ class DeviceCodeDialog extends StatelessWidget {
|
||||
children: [
|
||||
const SizedBox(width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2)),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(t.trackers.deviceCode.waitingForAuthorization, style: theme.textTheme.bodySmall),
|
||||
),
|
||||
Expanded(child: Text(t.trackers.deviceCode.waitingForAuthorization, style: theme.textTheme.bodySmall)),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
@@ -18,12 +18,7 @@ class OAuthProxyDialog extends StatelessWidget {
|
||||
final String serviceName;
|
||||
final VoidCallback onCancel;
|
||||
|
||||
const OAuthProxyDialog({
|
||||
super.key,
|
||||
required this.start,
|
||||
required this.serviceName,
|
||||
required this.onCancel,
|
||||
});
|
||||
const OAuthProxyDialog({super.key, required this.start, required this.serviceName, required this.onCancel});
|
||||
|
||||
Future<void> _open() async {
|
||||
await launchUrl(Uri.parse(start.url), mode: LaunchMode.externalApplication);
|
||||
@@ -53,12 +48,7 @@ class OAuthProxyDialog extends StatelessWidget {
|
||||
dimension: 220,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: QrImageView(
|
||||
data: start.url,
|
||||
size: 220,
|
||||
version: QrVersions.auto,
|
||||
backgroundColor: Colors.white,
|
||||
),
|
||||
child: QrImageView(data: start.url, size: 220, version: QrVersions.auto, backgroundColor: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -92,9 +82,7 @@ class OAuthProxyDialog extends StatelessWidget {
|
||||
children: [
|
||||
const SizedBox(width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2)),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(t.trackers.deviceCode.waitingForAuthorization, style: theme.textTheme.bodySmall),
|
||||
),
|
||||
Expanded(child: Text(t.trackers.deviceCode.waitingForAuthorization, style: theme.textTheme.bodySmall)),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user