import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../providers/trakt_scrobble_status_provider.dart'; import '../../../providers/trakt_settings_provider.dart'; import '../../../shared/widgets/app_inline_alert.dart'; import '../../../shared/widgets/app_loading_ring.dart'; import '../widgets/settings_card.dart'; class TraktSettingsTab extends ConsumerWidget { final void Function(String message, {AppAlertTone tone}) onFeedback; const TraktSettingsTab({super.key, required this.onFeedback}); @override Widget build(BuildContext context, WidgetRef ref) { final trakt = ref.watch(traktSettingsProvider); return SettingsTabScroll( children: [ trakt.when( data: (data) => TraktSection(state: data, onFeedback: onFeedback), loading: () => const Padding( padding: EdgeInsets.symmetric(vertical: 32), child: Center(child: AppLoadingRing()), ), error: (e, _) => SettingsCard(children: [settingsLoadError(e)]), ), ], ); } } class TraktSection extends ConsumerStatefulWidget { final TraktState state; final void Function(String message, {AppAlertTone tone}) onFeedback; const TraktSection({ super.key, required this.state, required this.onFeedback, }); @override ConsumerState createState() => TraktSectionState(); } class TraktSectionState extends ConsumerState { bool _busy = false; @override Widget build(BuildContext context) { final s = widget.state; if (s.isConnected) { return SettingsCard( children: [ SettingRow( title: '已连接', subtitle: s.username.isEmpty ? 'Trakt 账号' : '@${s.username}', trailing: const Icon( Icons.check_circle, size: 18, color: Color(0xFF52C41A), ), ), SettingRow( title: '断开连接', subtitle: '清除本地保存的 Trakt 令牌', trailing: _busy ? const AppLoadingRing(size: 18) : const Icon(Icons.logout, size: 18), onTap: _busy ? null : _disconnect, ), ], ); } return SettingsCard( children: [ SettingRow( title: '连接 Trakt', subtitle: '通过浏览器授权你的 Trakt 账号', trailing: _busy ? const AppLoadingRing(size: 18) : const Icon(Icons.open_in_new, size: 18), onTap: _busy ? null : _connect, ), ], ); } Future _connect() async { setState(() => _busy = true); String? message; var tone = AppAlertTone.success; try { await ref.read(traktSettingsProvider.notifier).connect(); message = '已连接 Trakt'; unawaited(ref.read(traktScrobbleStatusProvider.notifier).retryPending()); } on TraktConnectException catch (e) { message = e.message; tone = AppAlertTone.error; } catch (_) { message = '连接失败'; tone = AppAlertTone.error; } if (!mounted) return; setState(() => _busy = false); _toast(message, tone: tone); } Future _disconnect() async { setState(() => _busy = true); await ref.read(traktSettingsProvider.notifier).disconnect(); if (!mounted) return; setState(() => _busy = false); _toast('已断开 Trakt', tone: AppAlertTone.success); } void _toast(String message, {AppAlertTone tone = AppAlertTone.info}) { widget.onFeedback(message, tone: tone); } }