From 0a71bfc97ed21267b27af51b6314912d0ffab1c2 Mon Sep 17 00:00:00 2001 From: 0chencc <19362246+0Chencc@users.noreply.github.com> Date: Sun, 8 Feb 2026 19:03:56 +0900 Subject: [PATCH] feat: migrate to PKCE auth flow with custom Client ID support - Replace Authorization Code Flow with PKCE (no client_secret needed) - Hardcode default client_id in AppConfig, remove setup guide screen - Add custom Client ID option in Settings > Advanced Options and Login screen - Unify all auth/token/playback code via effectiveSpotifyClientIdProvider - TokenRefreshService rebuilds when client_id changes - Add l10n keys for zh/en/ja - Add iOS screenshot, update READMEs --- README.md | 8 +- README_en.md | 2 +- README_ja.md | 2 +- img/ios.png | Bin 0 -> 271504 bytes lib/app.dart | 52 +- lib/application/di/auth_providers.dart | 21 +- lib/application/di/core_providers.dart | 23 +- .../providers/credentials_provider.dart | 142 +-- .../providers/focus_session_provider.dart | 15 +- .../providers/playback_provider.dart | 5 +- lib/core/config/app_config.dart | 3 + lib/core/constants/app_constants.dart | 7 +- lib/core/services/oauth_service.dart | 23 +- lib/core/services/token_refresh_service.dart | 30 +- lib/core/utils/pkce_utils.dart | 24 + .../credentials_local_datasource.dart | 75 +- .../credentials_shared_prefs_datasource.dart | 52 +- .../repositories/auth_repository_impl.dart | 67 +- lib/l10n/app_en.arb | 376 +------- lib/l10n/app_ja.arb | 151 +--- lib/l10n/app_localizations.dart | 446 +-------- lib/l10n/app_localizations_en.dart | 240 +---- lib/l10n/app_localizations_ja.dart | 233 +---- lib/l10n/app_localizations_zh.dart | 228 +---- lib/l10n/app_zh.arb | 151 +--- lib/presentation/screens/login_screen.dart | 252 ++++-- .../screens/setup_guide_screen.dart | 855 ------------------ .../widgets/settings/about_section.dart | 4 - .../settings/api_credentials_section.dart | 229 +++-- pubspec.lock | 2 +- pubspec.yaml | 1 + 31 files changed, 742 insertions(+), 2977 deletions(-) create mode 100644 img/ios.png create mode 100644 lib/core/utils/pkce_utils.dart delete mode 100644 lib/presentation/screens/setup_guide_screen.dart diff --git a/README.md b/README.md index 373156a..b8a35db 100644 --- a/README.md +++ b/README.md @@ -130,12 +130,12 @@ FullStop 的**迷你模式**让播放器化身为屏幕角落的一抹优雅— ## 开始使用 ### 准备工作 -1. **Spotify Premium** 订阅。 -2. 一个 Spotify 开发者 App 的 `Client ID` 和 `Secret`。 +1. **Spotify Premium** 订阅。 +2. 下载并打开 FullStop,点击「连接 Spotify」即可完成授权。无需任何额外配置。 ### 安装 (iOS) -1. 在 [Releases](https://github.com/0Chencc/FullStop/releases) 下载最新的 `.ipa` 文件。 -2. 使用 **AltStore**、**Sideloadly** 或 **TrollStore** 进行自签安装。 +1. 在 [Releases](https://github.com/0Chencc/FullStop/releases) 下载最新的 `.ipa` 文件。 +2. 使用 **AltStore**、**Sideloadly** 或 **TrollStore** 进行自签安装。 --- diff --git a/README_en.md b/README_en.md index ae3e448..8b9f169 100644 --- a/README_en.md +++ b/README_en.md @@ -133,7 +133,7 @@ Click the picture-in-picture button in the title bar, and the window shrinks ins ### Prerequisites 1. **Spotify Premium** subscription. -2. A Spotify Developer App with `Client ID` and `Secret`. +2. Download and open FullStop, click "Connect with Spotify" to authorize. No additional configuration needed. ### Installation (iOS) 1. Download the latest `.ipa` file from [Releases](https://github.com/0Chencc/FullStop/releases). diff --git a/README_ja.md b/README_ja.md index 6e5ae9a..8d20614 100644 --- a/README_ja.md +++ b/README_ja.md @@ -133,7 +133,7 @@ FullStopの**ミニモード**は、プレーヤーを画面の隅にそっと ### 必要なもの 1. **Spotify Premium** サブスクリプション。 -2. Spotify開発者アプリの `Client ID` と `Secret`。 +2. FullStop をダウンロードして開き、「Spotify に接続」をクリックするだけで認証完了。追加の設定は不要です。 ### インストール (iOS) 1. [Releases](https://github.com/0Chencc/FullStop/releases) から最新の `.ipa` ファイルをダウンロード。 diff --git a/img/ios.png b/img/ios.png new file mode 100644 index 0000000000000000000000000000000000000000..f0b3be37171c4a0d586c5c160880bfdde269d7fe GIT binary patch literal 271504 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 literal 0 HcmV?d00001 diff --git a/lib/app.dart b/lib/app.dart index 72838ad..172f0a6 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -6,7 +6,6 @@ import 'package:window_manager/window_manager.dart'; import 'l10n/app_localizations.dart'; import 'application/di/core_providers.dart' show sharedPrefsProvider; import 'application/providers/auth_provider.dart'; -import 'application/providers/credentials_provider.dart'; import 'application/providers/locale_provider.dart'; import 'application/providers/navigation_provider.dart'; import 'application/providers/playback_provider.dart'; @@ -14,7 +13,6 @@ import 'domain/entities/playback_state.dart'; import 'core/services/system_tray_service.dart'; import 'presentation/screens/home_screen.dart'; import 'presentation/screens/login_screen.dart'; -import 'presentation/screens/setup_guide_screen.dart'; import 'presentation/themes/app_theme.dart'; import 'presentation/widgets/custom_title_bar.dart'; import 'presentation/widgets/mini_player_content.dart'; @@ -191,7 +189,7 @@ class _AppShellState extends ConsumerState<_AppShell> with WindowListener { key: _navigatorKey, onGenerateRoute: (settings) { return MaterialPageRoute( - builder: (context) => const _AppRouter(), + builder: (context) => const _AuthRouter(), settings: settings, ); }, @@ -216,55 +214,19 @@ class _AppShellState extends ConsumerState<_AppShell> with WindowListener { ], ); } - return const _AppRouter(); + return const _AuthRouter(); } } -class _AppRouter extends ConsumerStatefulWidget { - const _AppRouter(); +/// Routes directly to auth flow — no setup guard needed with PKCE. +class _AuthRouter extends ConsumerStatefulWidget { + const _AuthRouter(); @override - ConsumerState<_AppRouter> createState() => _AppRouterState(); + ConsumerState<_AuthRouter> createState() => _AuthRouterState(); } -class _AppRouterState extends ConsumerState<_AppRouter> { - bool _setupComplete = false; - - void _onSetupComplete() { - setState(() { - _setupComplete = true; - }); - // After setup, check auth status - ref.read(authProvider.notifier).checkAuthStatus(); - } - - @override - Widget build(BuildContext context) { - final credentialsState = ref.watch(credentialsProvider); - - // Show loading while checking credentials - if (credentialsState.isLoading) { - return const Scaffold(body: Center(child: CircularProgressIndicator())); - } - - // If credentials not configured and setup not complete, show setup guide - if (!credentialsState.hasSpotifyCredentials && !_setupComplete) { - return SetupGuideScreen(onSetupComplete: _onSetupComplete); - } - - // Credentials are configured, show auth flow - return const _AuthWrapper(); - } -} - -class _AuthWrapper extends ConsumerStatefulWidget { - const _AuthWrapper(); - - @override - ConsumerState<_AuthWrapper> createState() => _AuthWrapperState(); -} - -class _AuthWrapperState extends ConsumerState<_AuthWrapper> { +class _AuthRouterState extends ConsumerState<_AuthRouter> { bool _hasCheckedAuth = false; @override diff --git a/lib/application/di/auth_providers.dart b/lib/application/di/auth_providers.dart index d7e3c01..14505de 100644 --- a/lib/application/di/auth_providers.dart +++ b/lib/application/di/auth_providers.dart @@ -8,6 +8,7 @@ import '../../data/datasources/credentials_shared_prefs_datasource.dart'; import '../../data/repositories/auth_repository_impl.dart'; import '../../domain/entities/proxy_settings.dart'; import '../../domain/repositories/auth_repository.dart'; +import '../providers/credentials_provider.dart'; import 'core_providers.dart'; import 'spotify_providers.dart'; @@ -50,17 +51,17 @@ final oauthServiceProvider = Provider((ref) { // Auth Repository final authRepositoryProvider = Provider((ref) { final localDataSource = ref.watch(authLocalDataSourceProvider); - final credentialsDataSource = ref.watch(credentialsLocalDataSourceProvider); final apiClient = ref.watch(spotifyApiClientProvider); final dio = ref.watch(authDioProvider); final oauthService = ref.watch(oauthServiceProvider); + final clientId = ref.watch(effectiveSpotifyClientIdProvider); return AuthRepositoryImpl( localDataSource: localDataSource, - credentialsDataSource: credentialsDataSource, apiClient: apiClient, dio: dio, oauthService: oauthService, + clientId: clientId, ); }); @@ -73,8 +74,6 @@ class _PlaceholderCredentialsDataSource implements CredentialsLocalDataSource { @override Future clearAppProxySettings() async {} @override - Future clearSpotifyCredentials() async {} - @override Future getAudioFeaturesEnabled() async => false; @override Future getGetSongBpmApiKey() async => null; @@ -89,25 +88,23 @@ class _PlaceholderCredentialsDataSource implements CredentialsLocalDataSource { @override Future getAppProxySettings() async => const AppProxySettings(); @override - Future getSpotifyClientId() async => null; - @override - Future getSpotifyClientSecret() async => null; - @override Future hasGetSongBpmApiKey() async => false; @override Future hasLlmConfig() async => false; @override - Future hasSpotifyCredentials() async => false; - @override Future saveAppProxySettings(AppProxySettings config) async {} @override Future saveLlmCredentials({String apiKey = '', required String model, required String baseUrl}) async {} @override - Future saveSpotifyCredentials({required String clientId, required String clientSecret}) async {} - @override Future setAudioFeaturesEnabled(bool enabled) async {} @override Future setGetSongBpmApiKey(String apiKey) async {} @override Future setGpuAccelerationEnabled(bool enabled) async {} + @override + Future getCustomSpotifyClientId() async => null; + @override + Future saveCustomSpotifyClientId(String clientId) async {} + @override + Future clearCustomSpotifyClientId() async {} } diff --git a/lib/application/di/core_providers.dart b/lib/application/di/core_providers.dart index f69c39f..1ed977d 100644 --- a/lib/application/di/core_providers.dart +++ b/lib/application/di/core_providers.dart @@ -13,14 +13,13 @@ import '../../core/services/token_refresh_service.dart'; import '../../core/services/url_launcher_service.dart'; import '../../core/services/window_service.dart'; import '../../core/utils/logger.dart'; +import '../providers/credentials_provider.dart'; import '../../data/datasources/auth_local_datasource.dart'; import '../../data/datasources/auth_shared_prefs_datasource.dart'; -import '../../data/datasources/credentials_local_datasource.dart'; import '../../domain/entities/proxy_settings.dart'; import '../../data/services/app_links_deep_link_service.dart'; import '../../data/services/default_url_launcher_service.dart'; import '../../data/services/window_manager_service.dart'; -import 'auth_providers.dart' show credentialsLocalDataSourceProvider; // SharedPreferences provider for macOS/iOS final sharedPrefsProvider = FutureProvider((ref) async { @@ -99,17 +98,21 @@ final authDioProvider = Provider((ref) { // Token Refresh Service (lazily initialized to avoid circular dependencies) TokenRefreshService? _tokenRefreshService; +String? _lastTokenRefreshClientId; TokenRefreshService _getOrCreateTokenRefreshService( AuthLocalDataSource authDataSource, - CredentialsLocalDataSource credentialsDataSource, Dio authDio, + String clientId, ) { - _tokenRefreshService ??= TokenRefreshService( - authDataSource: authDataSource, - credentialsDataSource: credentialsDataSource, - dio: authDio, - ); + if (_tokenRefreshService == null || _lastTokenRefreshClientId != clientId) { + _tokenRefreshService = TokenRefreshService( + clientId: clientId, + authDataSource: authDataSource, + dio: authDio, + ); + _lastTokenRefreshClientId = clientId; + } return _tokenRefreshService!; } @@ -150,12 +153,12 @@ final apiDioProvider = Provider((ref) { // Get fresh data sources for token refresh final authLocalDataSource = ref.read(authLocalDataSourceProvider); - final credentialsDataSource = ref.read(credentialsLocalDataSourceProvider); + final clientId = ref.read(effectiveSpotifyClientIdProvider); final tokenRefreshService = _getOrCreateTokenRefreshService( authLocalDataSource, - credentialsDataSource, authDio, + clientId, ); final newToken = await tokenRefreshService.refreshToken(); diff --git a/lib/application/providers/credentials_provider.dart b/lib/application/providers/credentials_provider.dart index 106087b..52357d2 100644 --- a/lib/application/providers/credentials_provider.dart +++ b/lib/application/providers/credentials_provider.dart @@ -1,58 +1,48 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; +import '../../core/config/app_config.dart'; import '../../data/datasources/credentials_local_datasource.dart'; import '../di/injection_container.dart'; /// State for credentials configuration class CredentialsState { final bool isLoading; - final bool hasSpotifyCredentials; final bool hasLlmConfig; - final String? spotifyClientId; - final String? spotifyClientSecret; final String? llmApiKey; final String? llmModel; final String? llmBaseUrl; + final String? customSpotifyClientId; final String? error; const CredentialsState({ this.isLoading = true, - this.hasSpotifyCredentials = false, this.hasLlmConfig = false, - this.spotifyClientId, - this.spotifyClientSecret, this.llmApiKey, this.llmModel, this.llmBaseUrl, + this.customSpotifyClientId, this.error, }); CredentialsState copyWith({ bool? isLoading, - bool? hasSpotifyCredentials, bool? hasLlmConfig, - String? spotifyClientId, - String? spotifyClientSecret, String? llmApiKey, String? llmModel, String? llmBaseUrl, + String? customSpotifyClientId, String? error, - bool clearSpotifyCredentials = false, bool clearLlmConfig = false, + bool clearCustomClientId = false, }) { return CredentialsState( isLoading: isLoading ?? this.isLoading, - hasSpotifyCredentials: - hasSpotifyCredentials ?? this.hasSpotifyCredentials, hasLlmConfig: hasLlmConfig ?? this.hasLlmConfig, - spotifyClientId: clearSpotifyCredentials - ? null - : (spotifyClientId ?? this.spotifyClientId), - spotifyClientSecret: clearSpotifyCredentials - ? null - : (spotifyClientSecret ?? this.spotifyClientSecret), llmApiKey: clearLlmConfig ? null : (llmApiKey ?? this.llmApiKey), llmModel: clearLlmConfig ? null : (llmModel ?? this.llmModel), llmBaseUrl: clearLlmConfig ? null : (llmBaseUrl ?? this.llmBaseUrl), + customSpotifyClientId: clearCustomClientId + ? null + : (customSpotifyClientId ?? this.customSpotifyClientId), error: error, ); } @@ -68,83 +58,25 @@ class CredentialsNotifier extends StateNotifier { Future _checkCredentials() async { try { - final hasSpotify = await _dataSource.hasSpotifyCredentials(); final hasLlm = await _dataSource.hasLlmConfig(); - final clientId = await _dataSource.getSpotifyClientId(); - final clientSecret = await _dataSource.getSpotifyClientSecret(); final llmApiKey = await _dataSource.getLlmApiKey(); final llmModel = await _dataSource.getLlmModel(); final llmBaseUrl = await _dataSource.getLlmBaseUrl(); + final customClientId = await _dataSource.getCustomSpotifyClientId(); state = state.copyWith( isLoading: false, - hasSpotifyCredentials: hasSpotify, hasLlmConfig: hasLlm, - spotifyClientId: clientId, - spotifyClientSecret: clientSecret, llmApiKey: llmApiKey, llmModel: llmModel, llmBaseUrl: llmBaseUrl, + customSpotifyClientId: customClientId, ); } catch (e) { state = state.copyWith(isLoading: false, error: e.toString()); } } - Future saveSpotifyCredentials({ - required String clientId, - required String clientSecret, - }) async { - try { - state = state.copyWith(isLoading: true, error: null); - - // Validate inputs - if (clientId.trim().isEmpty || clientSecret.trim().isEmpty) { - state = state.copyWith( - isLoading: false, - error: 'Client ID and Client Secret are required', - ); - return false; - } - - await _dataSource.saveSpotifyCredentials( - clientId: clientId.trim(), - clientSecret: clientSecret.trim(), - ); - - state = state.copyWith( - isLoading: false, - hasSpotifyCredentials: true, - spotifyClientId: clientId.trim(), - spotifyClientSecret: clientSecret.trim(), - ); - return true; - } catch (e) { - state = state.copyWith( - isLoading: false, - error: 'Failed to save credentials: $e', - ); - return false; - } - } - - Future clearSpotifyCredentials() async { - try { - state = state.copyWith(isLoading: true); - await _dataSource.clearSpotifyCredentials(); - state = state.copyWith( - isLoading: false, - hasSpotifyCredentials: false, - clearSpotifyCredentials: true, - ); - } catch (e) { - state = state.copyWith( - isLoading: false, - error: 'Failed to clear credentials: $e', - ); - } - } - Future saveLlmCredentials({ String apiKey = '', required String model, @@ -202,6 +134,26 @@ class CredentialsNotifier extends StateNotifier { } } + Future saveCustomSpotifyClientId(String clientId) async { + try { + await _dataSource.saveCustomSpotifyClientId(clientId.trim()); + state = state.copyWith(customSpotifyClientId: clientId.trim()); + return true; + } catch (e) { + state = state.copyWith(error: 'Failed to save custom Client ID: $e'); + return false; + } + } + + Future clearCustomSpotifyClientId() async { + try { + await _dataSource.clearCustomSpotifyClientId(); + state = state.copyWith(clearCustomClientId: true); + } catch (e) { + state = state.copyWith(error: 'Failed to clear custom Client ID: $e'); + } + } + Future refresh() async { await _checkCredentials(); } @@ -213,30 +165,12 @@ final credentialsProvider = return CredentialsNotifier(ref.watch(credentialsLocalDataSourceProvider)); }); -/// Helper provider to get Spotify credentials for API calls -final spotifyCredentialsProvider = FutureProvider(( - ref, -) async { - final dataSource = ref.watch(credentialsLocalDataSourceProvider); - final clientId = await dataSource.getSpotifyClientId(); - final clientSecret = await dataSource.getSpotifyClientSecret(); - - if (clientId == null || - clientId.isEmpty || - clientSecret == null || - clientSecret.isEmpty) { - return null; - } - - return SpotifyCredentials(clientId: clientId, clientSecret: clientSecret); +/// Derived provider that returns the effective Spotify Client ID +/// (custom > default) +final effectiveSpotifyClientIdProvider = Provider((ref) { + final creds = ref.watch(credentialsProvider); + final custom = creds.customSpotifyClientId; + return (custom != null && custom.isNotEmpty) + ? custom + : AppConfig.spotifyClientId; }); - -class SpotifyCredentials { - final String clientId; - final String clientSecret; - - const SpotifyCredentials({ - required this.clientId, - required this.clientSecret, - }); -} diff --git a/lib/application/providers/focus_session_provider.dart b/lib/application/providers/focus_session_provider.dart index 849739b..7a7d748 100644 --- a/lib/application/providers/focus_session_provider.dart +++ b/lib/application/providers/focus_session_provider.dart @@ -1,13 +1,13 @@ import 'package:dartz/dartz.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../core/errors/failures.dart'; +import 'credentials_provider.dart'; import '../../core/services/device_activation_service.dart'; import '../../domain/entities/focus_session.dart'; import '../../domain/entities/track.dart'; import '../../domain/repositories/focus_session_repository.dart'; import '../../domain/usecases/focus/play_focus_session.dart'; import '../di/injection_container.dart'; -import 'credentials_provider.dart'; enum FocusSessionStatus { initial, loading, success, error } @@ -132,18 +132,13 @@ class FocusSessionNotifier extends StateNotifier { ); try { - final futureRepo = ref.read(focusSessionRepositoryProvider.future); - final futureCredentials = ref.read(spotifyCredentialsProvider.future); - - final parallelResults = await (futureRepo, futureCredentials).wait; - final focusRepoAsync = parallelResults.$1; - final credentials = parallelResults.$2; + final focusRepoAsync = await ref.read(focusSessionRepositoryProvider.future); final playbackRepo = ref.read(playbackRepositoryProvider); final playUseCase = PlayFocusSession( focusRepository: focusRepoAsync, playbackRepository: playbackRepo, - clientId: credentials?.clientId, + clientId: ref.read(effectiveSpotifyClientIdProvider), ); final result = await playUseCase( @@ -197,11 +192,9 @@ class FocusSessionNotifier extends StateNotifier { state = state.copyWith(optimisticIsPlaying: true); final playbackRepo = ref.read(playbackRepositoryProvider); - final credentials = await ref.read(spotifyCredentialsProvider.future); - final activationService = DeviceActivationService.instance( playbackRepository: playbackRepo, - clientId: credentials?.clientId, + clientId: ref.read(effectiveSpotifyClientIdProvider), ); String? deviceId; diff --git a/lib/application/providers/playback_provider.dart b/lib/application/providers/playback_provider.dart index 6268c8b..bb1a492 100644 --- a/lib/application/providers/playback_provider.dart +++ b/lib/application/providers/playback_provider.dart @@ -2,11 +2,11 @@ import 'dart:async'; import 'dart:io'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../core/errors/failures.dart'; +import 'credentials_provider.dart'; import '../../core/services/device_activation_service.dart'; import '../../core/utils/logger.dart'; import '../../domain/entities/playback_state.dart'; import '../di/injection_container.dart'; -import 'credentials_provider.dart'; import 'focus_session_provider.dart'; /// Result of a like/unlike operation @@ -218,12 +218,11 @@ class PlaybackNotifier extends StateNotifier { /// Used when resuming a paused session Future resume() async { final playbackRepo = ref.read(playbackRepositoryProvider); - final credentials = await ref.read(spotifyCredentialsProvider.future); // Ensure we have an active device before resuming final activationService = DeviceActivationService.instance( playbackRepository: playbackRepo, - clientId: credentials?.clientId, + clientId: ref.read(effectiveSpotifyClientIdProvider), ); String? deviceId; diff --git a/lib/core/config/app_config.dart b/lib/core/config/app_config.dart index 90a840b..87e84bb 100644 --- a/lib/core/config/app_config.dart +++ b/lib/core/config/app_config.dart @@ -1,4 +1,7 @@ class AppConfig { + // Spotify Client ID (public client — safe to embed, PKCE replaces client_secret) + static const String spotifyClientId = '94fcde08534f4025a402cd2bba93e1f0'; + // Custom URL scheme for OAuth callback static const String urlScheme = 'fullstop'; diff --git a/lib/core/constants/app_constants.dart b/lib/core/constants/app_constants.dart index 84d7bbe..ac41445 100644 --- a/lib/core/constants/app_constants.dart +++ b/lib/core/constants/app_constants.dart @@ -6,10 +6,6 @@ class AppConstants { static const String tokenExpiryKey = 'spotify_token_expiry'; static const String userProfileKey = 'user_profile'; - // API Credentials keys - static const String spotifyClientIdKey = 'spotify_client_id'; - static const String spotifyClientSecretKey = 'spotify_client_secret'; - // LLM Config keys static const String llmProviderKey = 'llm_provider'; static const String llmApiKeyKey = 'llm_api_key'; @@ -28,6 +24,9 @@ class AppConstants { static const String audioFeaturesEnabledKey = 'audio_features_enabled'; static const String gpuAccelerationEnabledKey = 'gpu_acceleration_enabled'; + // Custom Spotify Client ID + static const String customSpotifyClientIdKey = 'custom_spotify_client_id'; + // GetSongBPM API static const String getSongBpmApiKeyKey = 'getsongbpm_api_key'; diff --git a/lib/core/services/oauth_service.dart b/lib/core/services/oauth_service.dart index ccbf634..61f96fc 100644 --- a/lib/core/services/oauth_service.dart +++ b/lib/core/services/oauth_service.dart @@ -3,6 +3,7 @@ import 'package:dartz/dartz.dart'; import '../config/app_config.dart'; import '../errors/failures.dart'; import '../utils/logger.dart'; +import '../utils/pkce_utils.dart'; import 'deep_link_service.dart'; import 'url_launcher_service.dart'; @@ -16,8 +17,13 @@ class AuthCancelledException implements Exception { class OAuthAuthorizationResult { final String code; final String state; + final String codeVerifier; - const OAuthAuthorizationResult({required this.code, required this.state}); + const OAuthAuthorizationResult({ + required this.code, + required this.state, + required this.codeVerifier, + }); } /// Abstract OAuth service interface @@ -45,6 +51,7 @@ class SpotifyOAuthService implements OAuthService { Completer? _activeCompleter; bool _isCancelled = false; String? _expectedState; + String? _codeVerifier; bool _isAuthenticating = false; SpotifyOAuthService({ @@ -73,6 +80,7 @@ class SpotifyOAuthService implements OAuthService { _linkSubscription = null; _activeCompleter = null; _expectedState = null; + _codeVerifier = null; _isAuthenticating = false; } @@ -166,6 +174,10 @@ class SpotifyOAuthService implements OAuthService { final scopeString = scopes.join(' '); _expectedState = DateTime.now().millisecondsSinceEpoch.toString(); + // PKCE: generate code_verifier and derive code_challenge + _codeVerifier = PkceUtils.generateCodeVerifier(); + final codeChallenge = PkceUtils.generateCodeChallenge(_codeVerifier!); + return Uri.parse(AppConfig.spotifyAuthUrl).replace( queryParameters: { 'client_id': clientId, @@ -174,6 +186,8 @@ class SpotifyOAuthService implements OAuthService { 'scope': scopeString, 'state': _expectedState, 'show_dialog': 'true', + 'code_challenge_method': 'S256', + 'code_challenge': codeChallenge, }, ); } @@ -198,6 +212,7 @@ class SpotifyOAuthService implements OAuthService { Uri callbackUri, ) async { final expectedState = _expectedState; + final codeVerifier = _codeVerifier!; await _linkSubscription?.cancel(); _linkSubscription = null; @@ -238,6 +253,10 @@ class SpotifyOAuthService implements OAuthService { _isAuthenticating = false; AppLogger.info('OAuth authorization completed successfully'); - return Right(OAuthAuthorizationResult(code: code, state: returnedState!)); + return Right(OAuthAuthorizationResult( + code: code, + state: returnedState!, + codeVerifier: codeVerifier, + )); } } diff --git a/lib/core/services/token_refresh_service.dart b/lib/core/services/token_refresh_service.dart index 43d7d58..ce991cc 100644 --- a/lib/core/services/token_refresh_service.dart +++ b/lib/core/services/token_refresh_service.dart @@ -1,24 +1,22 @@ -import 'dart:convert'; import 'package:dio/dio.dart'; import '../config/app_config.dart'; import '../utils/logger.dart'; import '../../data/datasources/auth_local_datasource.dart'; -import '../../data/datasources/credentials_local_datasource.dart'; /// Service responsible for refreshing Spotify access tokens. /// This is a low-level service used by the Dio interceptor. class TokenRefreshService { final AuthLocalDataSource authDataSource; - final CredentialsLocalDataSource credentialsDataSource; final Dio dio; + final String clientId; bool _isRefreshing = false; Future? _refreshFuture; TokenRefreshService({ required this.authDataSource, - required this.credentialsDataSource, required this.dio, + required this.clientId, }); /// Attempts to refresh the access token. @@ -49,27 +47,15 @@ class TokenRefreshService { return null; } - final clientId = await credentialsDataSource.getSpotifyClientId(); - final clientSecret = await credentialsDataSource.getSpotifyClientSecret(); - - if (clientId == null || - clientId.isEmpty || - clientSecret == null || - clientSecret.isEmpty) { - AppLogger.warning('No Spotify credentials available for token refresh'); - return null; - } - - final credentials = base64Encode(utf8.encode('$clientId:$clientSecret')); - final response = await dio.post( AppConfig.spotifyTokenUrl, - data: {'grant_type': 'refresh_token', 'refresh_token': refreshToken}, + data: { + 'grant_type': 'refresh_token', + 'refresh_token': refreshToken, + 'client_id': clientId, + }, options: Options( - headers: { - 'Authorization': 'Basic $credentials', - 'Content-Type': 'application/x-www-form-urlencoded', - }, + headers: {'Content-Type': 'application/x-www-form-urlencoded'}, contentType: Headers.formUrlEncodedContentType, ), ); diff --git a/lib/core/utils/pkce_utils.dart b/lib/core/utils/pkce_utils.dart new file mode 100644 index 0000000..fb2cc02 --- /dev/null +++ b/lib/core/utils/pkce_utils.dart @@ -0,0 +1,24 @@ +import 'dart:convert'; +import 'dart:math'; +import 'package:crypto/crypto.dart'; + +class PkceUtils { + static const _charset = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~'; + + /// Generate a cryptographically random code verifier (43-128 characters). + static String generateCodeVerifier([int length = 128]) { + final random = Random.secure(); + return List.generate( + length, + (_) => _charset[random.nextInt(_charset.length)], + ).join(); + } + + /// Compute code_challenge = BASE64URL(SHA256(code_verifier)). + static String generateCodeChallenge(String codeVerifier) { + final bytes = utf8.encode(codeVerifier); + final digest = sha256.convert(bytes); + return base64Url.encode(digest.bytes).replaceAll('=', ''); + } +} diff --git a/lib/data/datasources/credentials_local_datasource.dart b/lib/data/datasources/credentials_local_datasource.dart index 0aca226..b769cca 100644 --- a/lib/data/datasources/credentials_local_datasource.dart +++ b/lib/data/datasources/credentials_local_datasource.dart @@ -4,15 +4,6 @@ import '../../domain/entities/proxy_settings.dart'; /// Data source for storing and retrieving API credentials securely abstract class CredentialsLocalDataSource { - Future getSpotifyClientId(); - Future getSpotifyClientSecret(); - Future saveSpotifyCredentials({ - required String clientId, - required String clientSecret, - }); - Future clearSpotifyCredentials(); - Future hasSpotifyCredentials(); - // LLM credentials (optional) Future getLlmApiKey(); Future getLlmModel(); @@ -36,6 +27,11 @@ abstract class CredentialsLocalDataSource { Future getGpuAccelerationEnabled(); Future setGpuAccelerationEnabled(bool enabled); + // Custom Spotify Client ID + Future getCustomSpotifyClientId(); + Future saveCustomSpotifyClientId(String clientId); + Future clearCustomSpotifyClientId(); + // GetSongBPM API Future getGetSongBpmApiKey(); Future setGetSongBpmApiKey(String apiKey); @@ -48,48 +44,6 @@ class CredentialsLocalDataSourceImpl implements CredentialsLocalDataSource { CredentialsLocalDataSourceImpl(this._secureStorage); - // Spotify credentials - @override - Future getSpotifyClientId() async { - return await _secureStorage.read(key: AppConstants.spotifyClientIdKey); - } - - @override - Future getSpotifyClientSecret() async { - return await _secureStorage.read(key: AppConstants.spotifyClientSecretKey); - } - - @override - Future saveSpotifyCredentials({ - required String clientId, - required String clientSecret, - }) async { - await _secureStorage.write( - key: AppConstants.spotifyClientIdKey, - value: clientId, - ); - await _secureStorage.write( - key: AppConstants.spotifyClientSecretKey, - value: clientSecret, - ); - } - - @override - Future clearSpotifyCredentials() async { - await _secureStorage.delete(key: AppConstants.spotifyClientIdKey); - await _secureStorage.delete(key: AppConstants.spotifyClientSecretKey); - } - - @override - Future hasSpotifyCredentials() async { - final clientId = await getSpotifyClientId(); - final clientSecret = await getSpotifyClientSecret(); - return clientId != null && - clientId.isNotEmpty && - clientSecret != null && - clientSecret.isNotEmpty; - } - // LLM credentials @override Future getLlmApiKey() async { @@ -236,6 +190,25 @@ class CredentialsLocalDataSourceImpl implements CredentialsLocalDataSource { ); } + // Custom Spotify Client ID + @override + Future getCustomSpotifyClientId() async { + return await _secureStorage.read(key: AppConstants.customSpotifyClientIdKey); + } + + @override + Future saveCustomSpotifyClientId(String clientId) async { + await _secureStorage.write( + key: AppConstants.customSpotifyClientIdKey, + value: clientId, + ); + } + + @override + Future clearCustomSpotifyClientId() async { + await _secureStorage.delete(key: AppConstants.customSpotifyClientIdKey); + } + // GetSongBPM API @override Future getGetSongBpmApiKey() async { diff --git a/lib/data/datasources/credentials_shared_prefs_datasource.dart b/lib/data/datasources/credentials_shared_prefs_datasource.dart index bc6ad35..9b78cfa 100644 --- a/lib/data/datasources/credentials_shared_prefs_datasource.dart +++ b/lib/data/datasources/credentials_shared_prefs_datasource.dart @@ -10,42 +10,6 @@ class CredentialsSharedPrefsDataSource implements CredentialsLocalDataSource { CredentialsSharedPrefsDataSource(this._prefs); - // Spotify credentials - @override - Future getSpotifyClientId() async { - return _prefs.getString(AppConstants.spotifyClientIdKey); - } - - @override - Future getSpotifyClientSecret() async { - return _prefs.getString(AppConstants.spotifyClientSecretKey); - } - - @override - Future saveSpotifyCredentials({ - required String clientId, - required String clientSecret, - }) async { - await _prefs.setString(AppConstants.spotifyClientIdKey, clientId); - await _prefs.setString(AppConstants.spotifyClientSecretKey, clientSecret); - } - - @override - Future clearSpotifyCredentials() async { - await _prefs.remove(AppConstants.spotifyClientIdKey); - await _prefs.remove(AppConstants.spotifyClientSecretKey); - } - - @override - Future hasSpotifyCredentials() async { - final clientId = await getSpotifyClientId(); - final clientSecret = await getSpotifyClientSecret(); - return clientId != null && - clientId.isNotEmpty && - clientSecret != null && - clientSecret.isNotEmpty; - } - // LLM credentials @override Future getLlmApiKey() async { @@ -167,6 +131,22 @@ class CredentialsSharedPrefsDataSource implements CredentialsLocalDataSource { ); } + // Custom Spotify Client ID + @override + Future getCustomSpotifyClientId() async { + return _prefs.getString(AppConstants.customSpotifyClientIdKey); + } + + @override + Future saveCustomSpotifyClientId(String clientId) async { + await _prefs.setString(AppConstants.customSpotifyClientIdKey, clientId); + } + + @override + Future clearCustomSpotifyClientId() async { + await _prefs.remove(AppConstants.customSpotifyClientIdKey); + } + // GetSongBPM API @override Future getGetSongBpmApiKey() async { diff --git a/lib/data/repositories/auth_repository_impl.dart b/lib/data/repositories/auth_repository_impl.dart index f2f010d..c296036 100644 --- a/lib/data/repositories/auth_repository_impl.dart +++ b/lib/data/repositories/auth_repository_impl.dart @@ -1,4 +1,3 @@ -import 'dart:convert'; import 'package:dartz/dartz.dart'; import 'package:dio/dio.dart'; import '../../core/config/app_config.dart'; @@ -9,22 +8,21 @@ import '../../core/utils/logger.dart'; import '../../domain/entities/user.dart'; import '../../domain/repositories/auth_repository.dart'; import '../datasources/auth_local_datasource.dart'; -import '../datasources/credentials_local_datasource.dart'; import '../datasources/spotify_api_client.dart'; class AuthRepositoryImpl implements AuthRepository { final AuthLocalDataSource localDataSource; - final CredentialsLocalDataSource credentialsDataSource; final SpotifyApiClient apiClient; final Dio dio; final OAuthService oauthService; + final String clientId; AuthRepositoryImpl({ required this.localDataSource, - required this.credentialsDataSource, required this.apiClient, required this.dio, required this.oauthService, + required this.clientId, }); @override @@ -35,34 +33,18 @@ class AuthRepositoryImpl implements AuthRepository { @override Future> authenticate() async { try { - // Get credentials from secure storage - final clientId = await credentialsDataSource.getSpotifyClientId(); - final clientSecret = await credentialsDataSource.getSpotifyClientSecret(); - - if (clientId == null || - clientId.isEmpty || - clientSecret == null || - clientSecret.isEmpty) { - return const Left( - AuthFailure( - message: - 'Spotify API credentials not configured. Please set up your credentials first.', - ), - ); - } - - // Use OAuth service to get authorization code + // Use OAuth service to get authorization code (with PKCE code_verifier) final authResult = await oauthService.authorize( clientId: clientId, scopes: AppConfig.spotifyScopes, ); return authResult.fold((failure) => Left(failure), (result) async { - // Exchange code for tokens + // Exchange code for tokens using PKCE final tokenResponse = await _exchangeCodeForTokens( result.code, clientId, - clientSecret, + result.codeVerifier, ); AppLogger.info('Authentication completed successfully'); @@ -77,11 +59,9 @@ class AuthRepositoryImpl implements AuthRepository { Future> _exchangeCodeForTokens( String code, String clientId, - String clientSecret, + String codeVerifier, ) async { - final credentials = base64Encode(utf8.encode('$clientId:$clientSecret')); - - AppLogger.info('Exchanging code for tokens...'); + AppLogger.info('Exchanging code for tokens (PKCE)...'); AppLogger.info('Client ID: ${clientId.substring(0, 4)}...${clientId.substring(clientId.length - 4)}'); AppLogger.info('Redirect URI: ${AppConfig.spotifyRedirectUri}'); AppLogger.info('Code: ${code.substring(0, 10)}...'); @@ -93,12 +73,11 @@ class AuthRepositoryImpl implements AuthRepository { 'grant_type': 'authorization_code', 'code': code, 'redirect_uri': AppConfig.spotifyRedirectUri, + 'client_id': clientId, + 'code_verifier': codeVerifier, }, options: Options( - headers: { - 'Authorization': 'Basic $credentials', - 'Content-Type': 'application/x-www-form-urlencoded', - }, + headers: {'Content-Type': 'application/x-www-form-urlencoded'}, contentType: Headers.formUrlEncodedContentType, ), ); @@ -134,29 +113,15 @@ class AuthRepositoryImpl implements AuthRepository { return const Left(AuthFailure(message: 'No refresh token available')); } - // Get credentials from secure storage - final clientId = await credentialsDataSource.getSpotifyClientId(); - final clientSecret = await credentialsDataSource.getSpotifyClientSecret(); - - if (clientId == null || - clientId.isEmpty || - clientSecret == null || - clientSecret.isEmpty) { - return const Left( - AuthFailure(message: 'Spotify API credentials not configured.'), - ); - } - - final credentials = base64Encode(utf8.encode('$clientId:$clientSecret')); - final response = await dio.post( AppConfig.spotifyTokenUrl, - data: {'grant_type': 'refresh_token', 'refresh_token': refreshToken}, + data: { + 'grant_type': 'refresh_token', + 'refresh_token': refreshToken, + 'client_id': clientId, + }, options: Options( - headers: { - 'Authorization': 'Basic $credentials', - 'Content-Type': 'application/x-www-form-urlencoded', - }, + headers: {'Content-Type': 'application/x-www-form-urlencoded'}, contentType: Headers.formUrlEncodedContentType, ), ); diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 9d08a80..046ba6b 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -71,21 +71,6 @@ "description": "Snackbar message when error is copied" }, - "reconfigureCredentials": "Reconfigure Credentials", - "@reconfigureCredentials": { - "description": "Button to reconfigure API credentials" - }, - - "apiConfigured": "API configured", - "@apiConfigured": { - "description": "Status text when API is configured" - }, - - "change": "Change", - "@change": { - "description": "Change button text" - }, - "credentialsStayOnDevice": "Your credentials stay on your device", "@credentialsStayOnDevice": { "description": "Security info text" @@ -216,52 +201,6 @@ "description": "Next track button" }, - "setupGuide": "Setup Guide", - "@setupGuide": { - "description": "Setup guide screen title" - }, - - - "setupDescription": "To get started, you'll need to create a Spotify Developer App and enter your credentials.", - "@setupDescription": { - "description": "Setup description text" - }, - - "step1Title": "Go to Spotify Developer Dashboard", - "@step1Title": { - "description": "Setup step 1 title" - }, - - "step2Title": "Create a new app", - "@step2Title": { - "description": "Setup step 2 title" - }, - - "step3Title": "Add redirect URI", - "@step3Title": { - "description": "Setup step 3 title" - }, - - "step4Title": "Copy your credentials", - "@step4Title": { - "description": "Setup step 4 title" - }, - - "clientId": "Client ID", - "@clientId": { - "description": "Client ID field label" - }, - - "clientSecret": "Client Secret", - "@clientSecret": { - "description": "Client Secret field label" - }, - - "saveAndContinue": "Save & Continue", - "@saveAndContinue": { - "description": "Save and continue button" - }, - "errorInvalidClient": "Invalid API credentials. Please check your Client ID and Secret.", "@errorInvalidClient": { "description": "Invalid client error message" @@ -1293,16 +1232,6 @@ "description": "Privacy section description" }, - "privacyOAuthSecurity": "OAuth Security", - "@privacyOAuthSecurity": { - "description": "Privacy section title" - }, - - "privacyOAuthSecurityDesc": "Authentication uses a local HTTP server on ports 8888-8891, 8080, or 3000 with CSRF protection via state parameter.", - "@privacyOAuthSecurityDesc": { - "description": "Privacy section description" - }, - "privacyYouControl": "You Control Your Data", "@privacyYouControl": { "description": "Privacy section title" @@ -1318,261 +1247,6 @@ "description": "Close button text" }, - "welcomeToFullStop": "Welcome to FullStop", - "@welcomeToFullStop": { - "description": "Welcome message on setup screen" - }, - - "updateCredentials": "Update Credentials", - "@updateCredentials": { - "description": "Title when reconfiguring credentials" - }, - - "connectSpotifyToStart": "Connect your Spotify account to get started", - "@connectSpotifyToStart": { - "description": "Subtitle on setup screen" - }, - - "updateSpotifyCredentials": "Update your Spotify API credentials", - "@updateSpotifyCredentials": { - "description": "Subtitle when reconfiguring" - }, - - "credentialsSecurelyStored": "Your credentials are stored securely on your device only", - "@credentialsSecurelyStored": { - "description": "Security notice text" - }, - - "privacyPolicy": "Privacy Policy", - "@privacyPolicy": { - "description": "Privacy policy tooltip" - }, - - "step1CreateApp": "Step 1: Create a Spotify App", - "@step1CreateApp": { - "description": "Setup step 1 title" - }, - - "openDeveloperDashboard": "Open Spotify Developer Dashboard", - "@openDeveloperDashboard": { - "description": "Button to open Spotify developer dashboard" - }, - - "openDeveloperDashboardHint": "Click the button below to open the Spotify Developer Dashboard in your browser.", - "@openDeveloperDashboardHint": { - "description": "Hint for opening developer dashboard" - }, - - "createNewApp": "Create a New App", - "@createNewApp": { - "description": "Instruction to create new app" - }, - - "createNewAppDesc": "Click \"Create App\" and fill in:\n• App name: Any name (e.g., \"My Focus App\")\n• App description: Personal use\n• Website: Leave empty or use any URL\n• Check \"Web API\" option", - "@createNewAppDesc": { - "description": "Instructions for creating new app" - }, - - "createNewAppDescShort": "Click \"Create App\" and fill in the following fields. Check \"Web API\" option.", - "@createNewAppDescShort": { - "description": "Short instructions for creating new app" - }, - - "appNameLabel": "App name", - "@appNameLabel": { - "description": "Label for app name field" - }, - - "appNameCopied": "App name copied!", - "@appNameCopied": { - "description": "Toast when app name is copied" - }, - - "appDescriptionLabel": "App description", - "@appDescriptionLabel": { - "description": "Label for app description field" - }, - - "appDescriptionCopied": "App description copied!", - "@appDescriptionCopied": { - "description": "Toast when app description is copied" - }, - - "redirectUriLabel": "Redirect URI", - "@redirectUriLabel": { - "description": "Label for redirect URI field" - }, - - "setRedirectUri": "Set Redirect URI (IMPORTANT!)", - "@setRedirectUri": { - "description": "Redirect URI setup instruction" - }, - - "setRedirectUriDesc": "In \"Redirect URIs\" field, add this EXACT URI:", - "@setRedirectUriDesc": { - "description": "Redirect URI setup description" - }, - - "copy": "Copy", - "@copy": { - "description": "Copy button text" - }, - - "redirectUriCopied": "Redirect URI copied!", - "@redirectUriCopied": { - "description": "Toast when redirect URI is copied" - }, - - "redirectUriWarning": "Click \"Add\" after pasting, then click \"Save\" at the bottom!", - "@redirectUriWarning": { - "description": "Warning about saving redirect URI" - }, - - "step2EnterCredentials": "Step 2: Enter Your Credentials", - "@step2EnterCredentials": { - "description": "Setup step 2 title" - }, - - "updateYourCredentials": "Update Your Credentials", - "@updateYourCredentials": { - "description": "Title when updating credentials" - }, - - "findCredentialsHint": "Find your credentials in the app settings page on the Spotify Developer Dashboard.", - "@findCredentialsHint": { - "description": "Hint for finding credentials" - }, - - "modifyCredentialsHint": "Modify the credentials below. Leave unchanged if correct.", - "@modifyCredentialsHint": { - "description": "Hint when modifying credentials" - }, - - "enterClientId": "Enter your Client ID", - "@enterClientId": { - "description": "Client ID field placeholder" - }, - - "clientIdRequired": "Client ID is required", - "@clientIdRequired": { - "description": "Validation error for empty client ID" - }, - - "clientIdTooShort": "Client ID seems too short", - "@clientIdTooShort": { - "description": "Validation error for short client ID" - }, - - "enterClientSecret": "Enter your Client Secret", - "@enterClientSecret": { - "description": "Client Secret field placeholder" - }, - - "clientSecretRequired": "Client Secret is required", - "@clientSecretRequired": { - "description": "Validation error for empty client secret" - }, - - "clientSecretTooShort": "Client Secret seems too short", - "@clientSecretTooShort": { - "description": "Validation error for short client secret" - }, - - "whereToFindCredentials": "Where to find these?", - "@whereToFindCredentials": { - "description": "Help section title" - }, - - "whereToFindCredentialsDesc": "In your Spotify app's Settings page, you'll see Client ID. Click \"View client secret\" to reveal the secret.", - "@whereToFindCredentialsDesc": { - "description": "Help section description" - }, - - "step3ReadyToConnect": "Step 3: Ready to Connect", - "@step3ReadyToConnect": { - "description": "Setup step 3 title" - }, - - "credentialsSaved": "Credentials Saved!", - "@credentialsSaved": { - "description": "Success message when credentials are saved" - }, - - "waitingForCredentials": "Waiting for Credentials", - "@waitingForCredentials": { - "description": "Waiting state message" - }, - - "credentialsSavedDesc": "Your Spotify API credentials have been securely stored. You can now connect to Spotify.", - "@credentialsSavedDesc": { - "description": "Success description" - }, - - "waitingForCredentialsDesc": "Please go back to Step 2 and enter your credentials.", - "@waitingForCredentialsDesc": { - "description": "Hint when waiting for credentials" - }, - - "spotifyPremiumRequired": "Spotify Premium Required", - "@spotifyPremiumRequired": { - "description": "Premium requirement notice" - }, - - "spotifyPremiumRequiredDesc": "This app requires Spotify Premium for playback control features.", - "@spotifyPremiumRequiredDesc": { - "description": "Premium requirement description" - }, - - "back": "Back", - "@back": { - "description": "Back button text" - }, - - "nextEnterCredentials": "Next: Enter Credentials", - "@nextEnterCredentials": { - "description": "Next button text for step 1" - }, - - "saveCredentials": "Save Credentials", - "@saveCredentials": { - "description": "Save credentials button text" - }, - - "updateCredentialsButton": "Update Credentials", - "@updateCredentialsButton": { - "description": "Update credentials button text" - }, - - "connectToSpotify": "Connect to Spotify", - "@connectToSpotify": { - "description": "Final connect button text" - }, - - "reconfigureApiCredentials": "Reconfigure API Credentials", - "@reconfigureApiCredentials": { - "description": "Button to reconfigure API" - }, - - "changeClientIdSecret": "Change your Client ID and Secret", - "@changeClientIdSecret": { - "description": "Subtitle for reconfigure option" - }, - - "reconfigureDialogTitle": "Reconfigure API Credentials", - "@reconfigureDialogTitle": { - "description": "Dialog title for reconfigure" - }, - - "reconfigureDialogContent": "This will clear your current API credentials and log you out.\n\nYou will need to enter your Client ID and Secret again.", - "@reconfigureDialogContent": { - "description": "Dialog content for reconfigure" - }, - - "reconfigure": "Reconfigure", - "@reconfigure": { - "description": "Reconfigure button text" - }, - "redirectUriForSpotifyApp": "Redirect URI for Spotify App", "@redirectUriForSpotifyApp": { "description": "Label for redirect URI info" @@ -1591,11 +1265,6 @@ } }, - "notConfigured": "Not configured", - "@notConfigured": { - "description": "Status when API is not configured" - }, - "llmOpenAiCompatible": "OpenAI-Compatible API", "@llmOpenAiCompatible": { "description": "LLM section title" @@ -1710,11 +1379,6 @@ } }, - "connectionFailed": "Connection Failed", - "@connectionFailed": { - "description": "Connection failed dialog title" - }, - "request": "Request:", "@request": { "description": "Request label in error dialog" @@ -1763,5 +1427,45 @@ "exitMiniPlayer": "Exit Mini Player", "@exitMiniPlayer": { "description": "Tooltip for exiting mini player mode" + }, + + "advancedOptions": "Advanced Options", + "@advancedOptions": { + "description": "Advanced options section title" + }, + + "customClientId": "Custom Client ID", + "@customClientId": { + "description": "Custom Spotify Client ID field label" + }, + + "customClientIdDescription": "The shared Client ID may be rate-limited by Spotify under heavy usage. You can create your own app on Spotify Developer Dashboard and use your own Client ID.", + "@customClientIdDescription": { + "description": "Description explaining why custom Client ID may be needed" + }, + + "customClientIdHint": "Enter your Spotify Client ID", + "@customClientIdHint": { + "description": "Hint for custom Client ID input" + }, + + "customClientIdSaved": "Custom Client ID saved", + "@customClientIdSaved": { + "description": "Toast when custom Client ID is saved" + }, + + "customClientIdCleared": "Restored to default Client ID", + "@customClientIdCleared": { + "description": "Toast when custom Client ID is cleared" + }, + + "useDefaultClient": "Use Default", + "@useDefaultClient": { + "description": "Button to clear custom Client ID and use default" + }, + + "customClientIdReauthRequired": "Switching Client ID requires re-login. Log out now?", + "@customClientIdReauthRequired": { + "description": "Dialog message when Client ID changes requiring re-authentication" } } diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb index f825e70..c89e3f0 100644 --- a/lib/l10n/app_ja.arb +++ b/lib/l10n/app_ja.arb @@ -29,12 +29,6 @@ "errorCopied": "エラーメッセージをクリップボードにコピーしました", - "reconfigureCredentials": "認証情報を再設定", - - "apiConfigured": "API設定済み", - - "change": "変更", - "credentialsStayOnDevice": "認証情報はお使いのデバイスにのみ保存されます", "controlsExistingSession": "既存のSpotifyセッションを操作します", @@ -87,25 +81,6 @@ "next": "次へ", - "setupGuide": "セットアップガイド", - - - "setupDescription": "まず、Spotify開発者アプリを作成し、認証情報を入力する必要があります。", - - "step1Title": "Spotify開発者ダッシュボードにアクセス", - - "step2Title": "新しいアプリを作成", - - "step3Title": "リダイレクトURIを追加", - - "step4Title": "認証情報をコピー", - - "clientId": "Client ID", - - "clientSecret": "Client Secret", - - "saveAndContinue": "保存して続行", - "errorInvalidClient": "API認証情報が無効です。Client IDとSecretを確認してください。", "errorRedirectUri": "リダイレクトURIが一致しません!SpotifyアプリにリダイレクトURIが正しく設定されていることを確認してください。", @@ -417,126 +392,18 @@ "privacyNoDataCollectionDesc": "使用状況分析、再生履歴、個人情報を収集、保存、送信することはありません。", - "privacyOAuthSecurity": "OAuthセキュリティ", - - "privacyOAuthSecurityDesc": "認証はポート8888-8891、8080、または3000のローカルHTTPサーバーを使用し、stateパラメータによるCSRF保護を行います。", - "privacyYouControl": "データはあなたの管理下に", "privacyYouControlDesc": "設定ページからいつでもクレデンシャルを削除できます。アプリをアンインストールすると、すべての保存データが削除されます。", "close": "閉じる", - "welcomeToFullStop": "FullStopへようこそ", - - "updateCredentials": "クレデンシャルを更新", - - "connectSpotifyToStart": "Spotifyアカウントを接続して開始", - - "updateSpotifyCredentials": "Spotify APIクレデンシャルを更新", - - "credentialsSecurelyStored": "クレデンシャルはデバイスにのみ安全に保存されます", - - "privacyPolicy": "プライバシーポリシー", - - "step1CreateApp": "ステップ1:Spotifyアプリを作成", - - "openDeveloperDashboard": "Spotify開発者ダッシュボードを開く", - - "openDeveloperDashboardHint": "下のボタンをクリックして、ブラウザでSpotify開発者ダッシュボードを開きます。", - - "createNewApp": "新しいアプリを作成", - - "createNewAppDesc": "「Create App」をクリックして入力:\n• App name:任意の名前(例:「My Focus App」)\n• App description:個人使用\n• Website:空欄またはURLを入力\n• 「Web API」オプションをチェック", - - "createNewAppDescShort": "「Create App」をクリックして以下のフィールドを入力し、「Web API」オプションをチェック。", - - "appNameLabel": "App name(アプリ名)", - - "appNameCopied": "アプリ名をコピーしました!", - - "appDescriptionLabel": "App description(アプリの説明)", - - "appDescriptionCopied": "アプリの説明をコピーしました!", - - "redirectUriLabel": "Redirect URI(リダイレクトURI)", - - "setRedirectUri": "リダイレクトURIを設定(重要!)", - - "setRedirectUriDesc": "「Redirect URIs」フィールドに以下のURIを追加:", - - "copy": "コピー", - - "redirectUriCopied": "リダイレクトURIをコピーしました!", - - "redirectUriWarning": "貼り付け後「Add」をクリックし、下の「Save」をクリック!", - - "step2EnterCredentials": "ステップ2:クレデンシャルを入力", - - "updateYourCredentials": "クレデンシャルを更新", - - "findCredentialsHint": "Spotify開発者ダッシュボードのアプリ設定ページでクレデンシャルを確認できます。", - - "modifyCredentialsHint": "以下のクレデンシャルを変更してください。正しい場合は変更不要です。", - - "enterClientId": "Client IDを入力", - - "clientIdRequired": "Client IDは必須です", - - "clientIdTooShort": "Client IDが短すぎます", - - "enterClientSecret": "Client Secretを入力", - - "clientSecretRequired": "Client Secretは必須です", - - "clientSecretTooShort": "Client Secretが短すぎます", - - "whereToFindCredentials": "どこで見つけられますか?", - - "whereToFindCredentialsDesc": "SpotifyアプリのSettingsページでClient IDが表示されます。「View client secret」をクリックしてシークレットを表示します。", - - "step3ReadyToConnect": "ステップ3:接続準備完了", - - "credentialsSaved": "クレデンシャルを保存しました!", - - "waitingForCredentials": "クレデンシャルを待機中", - - "credentialsSavedDesc": "Spotify APIクレデンシャルが安全に保存されました。Spotifyに接続できます。", - - "waitingForCredentialsDesc": "ステップ2に戻ってクレデンシャルを入力してください。", - - "spotifyPremiumRequired": "Spotify Premiumが必要", - - "spotifyPremiumRequiredDesc": "このアプリの再生コントロール機能にはSpotify Premiumが必要です。", - - "back": "戻る", - - "nextEnterCredentials": "次へ:クレデンシャルを入力", - - "saveCredentials": "クレデンシャルを保存", - - "updateCredentialsButton": "クレデンシャルを更新", - - "connectToSpotify": "Spotifyに接続", - - "reconfigureApiCredentials": "APIクレデンシャルを再設定", - - "changeClientIdSecret": "Client IDとSecretを変更", - - "reconfigureDialogTitle": "APIクレデンシャルを再設定", - - "reconfigureDialogContent": "現在のAPIクレデンシャルを削除してログアウトします。\n\nClient IDとSecretを再入力する必要があります。", - - "reconfigure": "再設定", - "redirectUriForSpotifyApp": "SpotifyアプリのリダイレクトURI", "spotifyApi": "Spotify API", "configured": "設定済み({clientId})", - "notConfigured": "未設定", - "llmOpenAiCompatible": "OpenAI互換API", "llmOpenAiCompatibleDesc": "OpenAI、Ollama、その他のOpenAI互換APIで動作します。\nOllamaなどのローカルモデルではAPI Keyは不要です。", @@ -599,5 +466,21 @@ "miniPlayer": "ミニプレーヤー", - "exitMiniPlayer": "ミニプレーヤーを終了" + "exitMiniPlayer": "ミニプレーヤーを終了", + + "advancedOptions": "詳細オプション", + + "customClientId": "カスタム Client ID", + + "customClientIdDescription": "共有 Client ID は Spotify のレート制限を受ける可能性があります。Spotify Developer Dashboard で独自のアプリを作成し、自分の Client ID を使用できます。", + + "customClientIdHint": "Spotify Client ID を入力", + + "customClientIdSaved": "カスタム Client ID を保存しました", + + "customClientIdCleared": "デフォルトの Client ID に戻しました", + + "useDefaultClient": "デフォルトを使用", + + "customClientIdReauthRequired": "Client ID の切り替えには再ログインが必要です。今すぐログアウトしますか?" } diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index 65e618e..32b6874 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -172,7 +172,7 @@ abstract class AppLocalizations { /// **'Click to cancel and return to login screen'** String get cancelHint; - /// Connection failed dialog title + /// Error title /// /// In en, this message translates to: /// **'Connection Failed'** @@ -184,24 +184,6 @@ abstract class AppLocalizations { /// **'Error message copied to clipboard'** String get errorCopied; - /// Button to reconfigure API credentials - /// - /// In en, this message translates to: - /// **'Reconfigure Credentials'** - String get reconfigureCredentials; - - /// Status text when API is configured - /// - /// In en, this message translates to: - /// **'API configured'** - String get apiConfigured; - - /// Change button text - /// - /// In en, this message translates to: - /// **'Change'** - String get change; - /// Security info text /// /// In en, this message translates to: @@ -358,60 +340,6 @@ abstract class AppLocalizations { /// **'Next'** String get next; - /// Setup guide screen title - /// - /// In en, this message translates to: - /// **'Setup Guide'** - String get setupGuide; - - /// Setup description text - /// - /// In en, this message translates to: - /// **'To get started, you\'ll need to create a Spotify Developer App and enter your credentials.'** - String get setupDescription; - - /// Setup step 1 title - /// - /// In en, this message translates to: - /// **'Go to Spotify Developer Dashboard'** - String get step1Title; - - /// Setup step 2 title - /// - /// In en, this message translates to: - /// **'Create a new app'** - String get step2Title; - - /// Setup step 3 title - /// - /// In en, this message translates to: - /// **'Add redirect URI'** - String get step3Title; - - /// Setup step 4 title - /// - /// In en, this message translates to: - /// **'Copy your credentials'** - String get step4Title; - - /// Client ID field label - /// - /// In en, this message translates to: - /// **'Client ID'** - String get clientId; - - /// Client Secret field label - /// - /// In en, this message translates to: - /// **'Client Secret'** - String get clientSecret; - - /// Save and continue button - /// - /// In en, this message translates to: - /// **'Save & Continue'** - String get saveAndContinue; - /// Invalid client error message /// /// In en, this message translates to: @@ -1540,18 +1468,6 @@ abstract class AppLocalizations { /// **'We do not collect, store, or transmit any usage analytics, listening history, or personal information.'** String get privacyNoDataCollectionDesc; - /// Privacy section title - /// - /// In en, this message translates to: - /// **'OAuth Security'** - String get privacyOAuthSecurity; - - /// Privacy section description - /// - /// In en, this message translates to: - /// **'Authentication uses a local HTTP server on ports 8888-8891, 8080, or 3000 with CSRF protection via state parameter.'** - String get privacyOAuthSecurityDesc; - /// Privacy section title /// /// In en, this message translates to: @@ -1570,312 +1486,6 @@ abstract class AppLocalizations { /// **'Close'** String get close; - /// Welcome message on setup screen - /// - /// In en, this message translates to: - /// **'Welcome to FullStop'** - String get welcomeToFullStop; - - /// Title when reconfiguring credentials - /// - /// In en, this message translates to: - /// **'Update Credentials'** - String get updateCredentials; - - /// Subtitle on setup screen - /// - /// In en, this message translates to: - /// **'Connect your Spotify account to get started'** - String get connectSpotifyToStart; - - /// Subtitle when reconfiguring - /// - /// In en, this message translates to: - /// **'Update your Spotify API credentials'** - String get updateSpotifyCredentials; - - /// Security notice text - /// - /// In en, this message translates to: - /// **'Your credentials are stored securely on your device only'** - String get credentialsSecurelyStored; - - /// Privacy policy tooltip - /// - /// In en, this message translates to: - /// **'Privacy Policy'** - String get privacyPolicy; - - /// Setup step 1 title - /// - /// In en, this message translates to: - /// **'Step 1: Create a Spotify App'** - String get step1CreateApp; - - /// Button to open Spotify developer dashboard - /// - /// In en, this message translates to: - /// **'Open Spotify Developer Dashboard'** - String get openDeveloperDashboard; - - /// Hint for opening developer dashboard - /// - /// In en, this message translates to: - /// **'Click the button below to open the Spotify Developer Dashboard in your browser.'** - String get openDeveloperDashboardHint; - - /// Instruction to create new app - /// - /// In en, this message translates to: - /// **'Create a New App'** - String get createNewApp; - - /// Instructions for creating new app - /// - /// In en, this message translates to: - /// **'Click \"Create App\" and fill in:\n• App name: Any name (e.g., \"My Focus App\")\n• App description: Personal use\n• Website: Leave empty or use any URL\n• Check \"Web API\" option'** - String get createNewAppDesc; - - /// Short instructions for creating new app - /// - /// In en, this message translates to: - /// **'Click \"Create App\" and fill in the following fields. Check \"Web API\" option.'** - String get createNewAppDescShort; - - /// Label for app name field - /// - /// In en, this message translates to: - /// **'App name'** - String get appNameLabel; - - /// Toast when app name is copied - /// - /// In en, this message translates to: - /// **'App name copied!'** - String get appNameCopied; - - /// Label for app description field - /// - /// In en, this message translates to: - /// **'App description'** - String get appDescriptionLabel; - - /// Toast when app description is copied - /// - /// In en, this message translates to: - /// **'App description copied!'** - String get appDescriptionCopied; - - /// Label for redirect URI field - /// - /// In en, this message translates to: - /// **'Redirect URI'** - String get redirectUriLabel; - - /// Redirect URI setup instruction - /// - /// In en, this message translates to: - /// **'Set Redirect URI (IMPORTANT!)'** - String get setRedirectUri; - - /// Redirect URI setup description - /// - /// In en, this message translates to: - /// **'In \"Redirect URIs\" field, add this EXACT URI:'** - String get setRedirectUriDesc; - - /// Copy button text - /// - /// In en, this message translates to: - /// **'Copy'** - String get copy; - - /// Toast when redirect URI is copied - /// - /// In en, this message translates to: - /// **'Redirect URI copied!'** - String get redirectUriCopied; - - /// Warning about saving redirect URI - /// - /// In en, this message translates to: - /// **'Click \"Add\" after pasting, then click \"Save\" at the bottom!'** - String get redirectUriWarning; - - /// Setup step 2 title - /// - /// In en, this message translates to: - /// **'Step 2: Enter Your Credentials'** - String get step2EnterCredentials; - - /// Title when updating credentials - /// - /// In en, this message translates to: - /// **'Update Your Credentials'** - String get updateYourCredentials; - - /// Hint for finding credentials - /// - /// In en, this message translates to: - /// **'Find your credentials in the app settings page on the Spotify Developer Dashboard.'** - String get findCredentialsHint; - - /// Hint when modifying credentials - /// - /// In en, this message translates to: - /// **'Modify the credentials below. Leave unchanged if correct.'** - String get modifyCredentialsHint; - - /// Client ID field placeholder - /// - /// In en, this message translates to: - /// **'Enter your Client ID'** - String get enterClientId; - - /// Validation error for empty client ID - /// - /// In en, this message translates to: - /// **'Client ID is required'** - String get clientIdRequired; - - /// Validation error for short client ID - /// - /// In en, this message translates to: - /// **'Client ID seems too short'** - String get clientIdTooShort; - - /// Client Secret field placeholder - /// - /// In en, this message translates to: - /// **'Enter your Client Secret'** - String get enterClientSecret; - - /// Validation error for empty client secret - /// - /// In en, this message translates to: - /// **'Client Secret is required'** - String get clientSecretRequired; - - /// Validation error for short client secret - /// - /// In en, this message translates to: - /// **'Client Secret seems too short'** - String get clientSecretTooShort; - - /// Help section title - /// - /// In en, this message translates to: - /// **'Where to find these?'** - String get whereToFindCredentials; - - /// Help section description - /// - /// In en, this message translates to: - /// **'In your Spotify app\'s Settings page, you\'ll see Client ID. Click \"View client secret\" to reveal the secret.'** - String get whereToFindCredentialsDesc; - - /// Setup step 3 title - /// - /// In en, this message translates to: - /// **'Step 3: Ready to Connect'** - String get step3ReadyToConnect; - - /// Success message when credentials are saved - /// - /// In en, this message translates to: - /// **'Credentials Saved!'** - String get credentialsSaved; - - /// Waiting state message - /// - /// In en, this message translates to: - /// **'Waiting for Credentials'** - String get waitingForCredentials; - - /// Success description - /// - /// In en, this message translates to: - /// **'Your Spotify API credentials have been securely stored. You can now connect to Spotify.'** - String get credentialsSavedDesc; - - /// Hint when waiting for credentials - /// - /// In en, this message translates to: - /// **'Please go back to Step 2 and enter your credentials.'** - String get waitingForCredentialsDesc; - - /// Premium requirement notice - /// - /// In en, this message translates to: - /// **'Spotify Premium Required'** - String get spotifyPremiumRequired; - - /// Premium requirement description - /// - /// In en, this message translates to: - /// **'This app requires Spotify Premium for playback control features.'** - String get spotifyPremiumRequiredDesc; - - /// Back button text - /// - /// In en, this message translates to: - /// **'Back'** - String get back; - - /// Next button text for step 1 - /// - /// In en, this message translates to: - /// **'Next: Enter Credentials'** - String get nextEnterCredentials; - - /// Save credentials button text - /// - /// In en, this message translates to: - /// **'Save Credentials'** - String get saveCredentials; - - /// Update credentials button text - /// - /// In en, this message translates to: - /// **'Update Credentials'** - String get updateCredentialsButton; - - /// Final connect button text - /// - /// In en, this message translates to: - /// **'Connect to Spotify'** - String get connectToSpotify; - - /// Button to reconfigure API - /// - /// In en, this message translates to: - /// **'Reconfigure API Credentials'** - String get reconfigureApiCredentials; - - /// Subtitle for reconfigure option - /// - /// In en, this message translates to: - /// **'Change your Client ID and Secret'** - String get changeClientIdSecret; - - /// Dialog title for reconfigure - /// - /// In en, this message translates to: - /// **'Reconfigure API Credentials'** - String get reconfigureDialogTitle; - - /// Dialog content for reconfigure - /// - /// In en, this message translates to: - /// **'This will clear your current API credentials and log you out.\n\nYou will need to enter your Client ID and Secret again.'** - String get reconfigureDialogContent; - - /// Reconfigure button text - /// - /// In en, this message translates to: - /// **'Reconfigure'** - String get reconfigure; - /// Label for redirect URI info /// /// In en, this message translates to: @@ -1894,12 +1504,6 @@ abstract class AppLocalizations { /// **'Configured ({clientId})'** String configured(String clientId); - /// Status when API is not configured - /// - /// In en, this message translates to: - /// **'Not configured'** - String get notConfigured; - /// LLM section title /// /// In en, this message translates to: @@ -2085,6 +1689,54 @@ abstract class AppLocalizations { /// In en, this message translates to: /// **'Exit Mini Player'** String get exitMiniPlayer; + + /// Advanced options section title + /// + /// In en, this message translates to: + /// **'Advanced Options'** + String get advancedOptions; + + /// Custom Spotify Client ID field label + /// + /// In en, this message translates to: + /// **'Custom Client ID'** + String get customClientId; + + /// Description explaining why custom Client ID may be needed + /// + /// In en, this message translates to: + /// **'The shared Client ID may be rate-limited by Spotify under heavy usage. You can create your own app on Spotify Developer Dashboard and use your own Client ID.'** + String get customClientIdDescription; + + /// Hint for custom Client ID input + /// + /// In en, this message translates to: + /// **'Enter your Spotify Client ID'** + String get customClientIdHint; + + /// Toast when custom Client ID is saved + /// + /// In en, this message translates to: + /// **'Custom Client ID saved'** + String get customClientIdSaved; + + /// Toast when custom Client ID is cleared + /// + /// In en, this message translates to: + /// **'Restored to default Client ID'** + String get customClientIdCleared; + + /// Button to clear custom Client ID and use default + /// + /// In en, this message translates to: + /// **'Use Default'** + String get useDefaultClient; + + /// Dialog message when Client ID changes requiring re-authentication + /// + /// In en, this message translates to: + /// **'Switching Client ID requires re-login. Log out now?'** + String get customClientIdReauthRequired; } class _AppLocalizationsDelegate diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index fdcca59..82609c9 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -53,15 +53,6 @@ class AppLocalizationsEn extends AppLocalizations { @override String get errorCopied => 'Error message copied to clipboard'; - @override - String get reconfigureCredentials => 'Reconfigure Credentials'; - - @override - String get apiConfigured => 'API configured'; - - @override - String get change => 'Change'; - @override String get credentialsStayOnDevice => 'Your credentials stay on your device'; @@ -141,34 +132,6 @@ class AppLocalizationsEn extends AppLocalizations { @override String get next => 'Next'; - @override - String get setupGuide => 'Setup Guide'; - - @override - String get setupDescription => - 'To get started, you\'ll need to create a Spotify Developer App and enter your credentials.'; - - @override - String get step1Title => 'Go to Spotify Developer Dashboard'; - - @override - String get step2Title => 'Create a new app'; - - @override - String get step3Title => 'Add redirect URI'; - - @override - String get step4Title => 'Copy your credentials'; - - @override - String get clientId => 'Client ID'; - - @override - String get clientSecret => 'Client Secret'; - - @override - String get saveAndContinue => 'Save & Continue'; - @override String get errorInvalidClient => 'Invalid API credentials. Please check your Client ID and Secret.'; @@ -816,13 +779,6 @@ class AppLocalizationsEn extends AppLocalizations { String get privacyNoDataCollectionDesc => 'We do not collect, store, or transmit any usage analytics, listening history, or personal information.'; - @override - String get privacyOAuthSecurity => 'OAuth Security'; - - @override - String get privacyOAuthSecurityDesc => - 'Authentication uses a local HTTP server on ports 8888-8891, 8080, or 3000 with CSRF protection via state parameter.'; - @override String get privacyYouControl => 'You Control Your Data'; @@ -833,173 +789,6 @@ class AppLocalizationsEn extends AppLocalizations { @override String get close => 'Close'; - @override - String get welcomeToFullStop => 'Welcome to FullStop'; - - @override - String get updateCredentials => 'Update Credentials'; - - @override - String get connectSpotifyToStart => - 'Connect your Spotify account to get started'; - - @override - String get updateSpotifyCredentials => 'Update your Spotify API credentials'; - - @override - String get credentialsSecurelyStored => - 'Your credentials are stored securely on your device only'; - - @override - String get privacyPolicy => 'Privacy Policy'; - - @override - String get step1CreateApp => 'Step 1: Create a Spotify App'; - - @override - String get openDeveloperDashboard => 'Open Spotify Developer Dashboard'; - - @override - String get openDeveloperDashboardHint => - 'Click the button below to open the Spotify Developer Dashboard in your browser.'; - - @override - String get createNewApp => 'Create a New App'; - - @override - String get createNewAppDesc => - 'Click \"Create App\" and fill in:\n• App name: Any name (e.g., \"My Focus App\")\n• App description: Personal use\n• Website: Leave empty or use any URL\n• Check \"Web API\" option'; - - @override - String get createNewAppDescShort => - 'Click \"Create App\" and fill in the following fields. Check \"Web API\" option.'; - - @override - String get appNameLabel => 'App name'; - - @override - String get appNameCopied => 'App name copied!'; - - @override - String get appDescriptionLabel => 'App description'; - - @override - String get appDescriptionCopied => 'App description copied!'; - - @override - String get redirectUriLabel => 'Redirect URI'; - - @override - String get setRedirectUri => 'Set Redirect URI (IMPORTANT!)'; - - @override - String get setRedirectUriDesc => - 'In \"Redirect URIs\" field, add this EXACT URI:'; - - @override - String get copy => 'Copy'; - - @override - String get redirectUriCopied => 'Redirect URI copied!'; - - @override - String get redirectUriWarning => - 'Click \"Add\" after pasting, then click \"Save\" at the bottom!'; - - @override - String get step2EnterCredentials => 'Step 2: Enter Your Credentials'; - - @override - String get updateYourCredentials => 'Update Your Credentials'; - - @override - String get findCredentialsHint => - 'Find your credentials in the app settings page on the Spotify Developer Dashboard.'; - - @override - String get modifyCredentialsHint => - 'Modify the credentials below. Leave unchanged if correct.'; - - @override - String get enterClientId => 'Enter your Client ID'; - - @override - String get clientIdRequired => 'Client ID is required'; - - @override - String get clientIdTooShort => 'Client ID seems too short'; - - @override - String get enterClientSecret => 'Enter your Client Secret'; - - @override - String get clientSecretRequired => 'Client Secret is required'; - - @override - String get clientSecretTooShort => 'Client Secret seems too short'; - - @override - String get whereToFindCredentials => 'Where to find these?'; - - @override - String get whereToFindCredentialsDesc => - 'In your Spotify app\'s Settings page, you\'ll see Client ID. Click \"View client secret\" to reveal the secret.'; - - @override - String get step3ReadyToConnect => 'Step 3: Ready to Connect'; - - @override - String get credentialsSaved => 'Credentials Saved!'; - - @override - String get waitingForCredentials => 'Waiting for Credentials'; - - @override - String get credentialsSavedDesc => - 'Your Spotify API credentials have been securely stored. You can now connect to Spotify.'; - - @override - String get waitingForCredentialsDesc => - 'Please go back to Step 2 and enter your credentials.'; - - @override - String get spotifyPremiumRequired => 'Spotify Premium Required'; - - @override - String get spotifyPremiumRequiredDesc => - 'This app requires Spotify Premium for playback control features.'; - - @override - String get back => 'Back'; - - @override - String get nextEnterCredentials => 'Next: Enter Credentials'; - - @override - String get saveCredentials => 'Save Credentials'; - - @override - String get updateCredentialsButton => 'Update Credentials'; - - @override - String get connectToSpotify => 'Connect to Spotify'; - - @override - String get reconfigureApiCredentials => 'Reconfigure API Credentials'; - - @override - String get changeClientIdSecret => 'Change your Client ID and Secret'; - - @override - String get reconfigureDialogTitle => 'Reconfigure API Credentials'; - - @override - String get reconfigureDialogContent => - 'This will clear your current API credentials and log you out.\n\nYou will need to enter your Client ID and Secret again.'; - - @override - String get reconfigure => 'Reconfigure'; - @override String get redirectUriForSpotifyApp => 'Redirect URI for Spotify App'; @@ -1011,9 +800,6 @@ class AppLocalizationsEn extends AppLocalizations { return 'Configured ($clientId)'; } - @override - String get notConfigured => 'Not configured'; - @override String get llmOpenAiCompatible => 'OpenAI-Compatible API'; @@ -1120,4 +906,30 @@ class AppLocalizationsEn extends AppLocalizations { @override String get exitMiniPlayer => 'Exit Mini Player'; + + @override + String get advancedOptions => 'Advanced Options'; + + @override + String get customClientId => 'Custom Client ID'; + + @override + String get customClientIdDescription => + 'The shared Client ID may be rate-limited by Spotify under heavy usage. You can create your own app on Spotify Developer Dashboard and use your own Client ID.'; + + @override + String get customClientIdHint => 'Enter your Spotify Client ID'; + + @override + String get customClientIdSaved => 'Custom Client ID saved'; + + @override + String get customClientIdCleared => 'Restored to default Client ID'; + + @override + String get useDefaultClient => 'Use Default'; + + @override + String get customClientIdReauthRequired => + 'Switching Client ID requires re-login. Log out now?'; } diff --git a/lib/l10n/app_localizations_ja.dart b/lib/l10n/app_localizations_ja.dart index 25811ed..e842730 100644 --- a/lib/l10n/app_localizations_ja.dart +++ b/lib/l10n/app_localizations_ja.dart @@ -50,15 +50,6 @@ class AppLocalizationsJa extends AppLocalizations { @override String get errorCopied => 'エラーメッセージをクリップボードにコピーしました'; - @override - String get reconfigureCredentials => '認証情報を再設定'; - - @override - String get apiConfigured => 'API設定済み'; - - @override - String get change => '変更'; - @override String get credentialsStayOnDevice => '認証情報はお使いのデバイスにのみ保存されます'; @@ -137,33 +128,6 @@ class AppLocalizationsJa extends AppLocalizations { @override String get next => '次へ'; - @override - String get setupGuide => 'セットアップガイド'; - - @override - String get setupDescription => 'まず、Spotify開発者アプリを作成し、認証情報を入力する必要があります。'; - - @override - String get step1Title => 'Spotify開発者ダッシュボードにアクセス'; - - @override - String get step2Title => '新しいアプリを作成'; - - @override - String get step3Title => 'リダイレクトURIを追加'; - - @override - String get step4Title => '認証情報をコピー'; - - @override - String get clientId => 'Client ID'; - - @override - String get clientSecret => 'Client Secret'; - - @override - String get saveAndContinue => '保存して続行'; - @override String get errorInvalidClient => 'API認証情報が無効です。Client IDとSecretを確認してください。'; @@ -804,13 +768,6 @@ class AppLocalizationsJa extends AppLocalizations { String get privacyNoDataCollectionDesc => '使用状況分析、再生履歴、個人情報を収集、保存、送信することはありません。'; - @override - String get privacyOAuthSecurity => 'OAuthセキュリティ'; - - @override - String get privacyOAuthSecurityDesc => - '認証はポート8888-8891、8080、または3000のローカルHTTPサーバーを使用し、stateパラメータによるCSRF保護を行います。'; - @override String get privacyYouControl => 'データはあなたの管理下に'; @@ -821,167 +778,6 @@ class AppLocalizationsJa extends AppLocalizations { @override String get close => '閉じる'; - @override - String get welcomeToFullStop => 'FullStopへようこそ'; - - @override - String get updateCredentials => 'クレデンシャルを更新'; - - @override - String get connectSpotifyToStart => 'Spotifyアカウントを接続して開始'; - - @override - String get updateSpotifyCredentials => 'Spotify APIクレデンシャルを更新'; - - @override - String get credentialsSecurelyStored => 'クレデンシャルはデバイスにのみ安全に保存されます'; - - @override - String get privacyPolicy => 'プライバシーポリシー'; - - @override - String get step1CreateApp => 'ステップ1:Spotifyアプリを作成'; - - @override - String get openDeveloperDashboard => 'Spotify開発者ダッシュボードを開く'; - - @override - String get openDeveloperDashboardHint => - '下のボタンをクリックして、ブラウザでSpotify開発者ダッシュボードを開きます。'; - - @override - String get createNewApp => '新しいアプリを作成'; - - @override - String get createNewAppDesc => - '「Create App」をクリックして入力:\n• App name:任意の名前(例:「My Focus App」)\n• App description:個人使用\n• Website:空欄またはURLを入力\n• 「Web API」オプションをチェック'; - - @override - String get createNewAppDescShort => - '「Create App」をクリックして以下のフィールドを入力し、「Web API」オプションをチェック。'; - - @override - String get appNameLabel => 'App name(アプリ名)'; - - @override - String get appNameCopied => 'アプリ名をコピーしました!'; - - @override - String get appDescriptionLabel => 'App description(アプリの説明)'; - - @override - String get appDescriptionCopied => 'アプリの説明をコピーしました!'; - - @override - String get redirectUriLabel => 'Redirect URI(リダイレクトURI)'; - - @override - String get setRedirectUri => 'リダイレクトURIを設定(重要!)'; - - @override - String get setRedirectUriDesc => '「Redirect URIs」フィールドに以下のURIを追加:'; - - @override - String get copy => 'コピー'; - - @override - String get redirectUriCopied => 'リダイレクトURIをコピーしました!'; - - @override - String get redirectUriWarning => '貼り付け後「Add」をクリックし、下の「Save」をクリック!'; - - @override - String get step2EnterCredentials => 'ステップ2:クレデンシャルを入力'; - - @override - String get updateYourCredentials => 'クレデンシャルを更新'; - - @override - String get findCredentialsHint => - 'Spotify開発者ダッシュボードのアプリ設定ページでクレデンシャルを確認できます。'; - - @override - String get modifyCredentialsHint => '以下のクレデンシャルを変更してください。正しい場合は変更不要です。'; - - @override - String get enterClientId => 'Client IDを入力'; - - @override - String get clientIdRequired => 'Client IDは必須です'; - - @override - String get clientIdTooShort => 'Client IDが短すぎます'; - - @override - String get enterClientSecret => 'Client Secretを入力'; - - @override - String get clientSecretRequired => 'Client Secretは必須です'; - - @override - String get clientSecretTooShort => 'Client Secretが短すぎます'; - - @override - String get whereToFindCredentials => 'どこで見つけられますか?'; - - @override - String get whereToFindCredentialsDesc => - 'SpotifyアプリのSettingsページでClient IDが表示されます。「View client secret」をクリックしてシークレットを表示します。'; - - @override - String get step3ReadyToConnect => 'ステップ3:接続準備完了'; - - @override - String get credentialsSaved => 'クレデンシャルを保存しました!'; - - @override - String get waitingForCredentials => 'クレデンシャルを待機中'; - - @override - String get credentialsSavedDesc => - 'Spotify APIクレデンシャルが安全に保存されました。Spotifyに接続できます。'; - - @override - String get waitingForCredentialsDesc => 'ステップ2に戻ってクレデンシャルを入力してください。'; - - @override - String get spotifyPremiumRequired => 'Spotify Premiumが必要'; - - @override - String get spotifyPremiumRequiredDesc => - 'このアプリの再生コントロール機能にはSpotify Premiumが必要です。'; - - @override - String get back => '戻る'; - - @override - String get nextEnterCredentials => '次へ:クレデンシャルを入力'; - - @override - String get saveCredentials => 'クレデンシャルを保存'; - - @override - String get updateCredentialsButton => 'クレデンシャルを更新'; - - @override - String get connectToSpotify => 'Spotifyに接続'; - - @override - String get reconfigureApiCredentials => 'APIクレデンシャルを再設定'; - - @override - String get changeClientIdSecret => 'Client IDとSecretを変更'; - - @override - String get reconfigureDialogTitle => 'APIクレデンシャルを再設定'; - - @override - String get reconfigureDialogContent => - '現在のAPIクレデンシャルを削除してログアウトします。\n\nClient IDとSecretを再入力する必要があります。'; - - @override - String get reconfigure => '再設定'; - @override String get redirectUriForSpotifyApp => 'SpotifyアプリのリダイレクトURI'; @@ -993,9 +789,6 @@ class AppLocalizationsJa extends AppLocalizations { return '設定済み($clientId)'; } - @override - String get notConfigured => '未設定'; - @override String get llmOpenAiCompatible => 'OpenAI互換API'; @@ -1095,4 +888,30 @@ class AppLocalizationsJa extends AppLocalizations { @override String get exitMiniPlayer => 'ミニプレーヤーを終了'; + + @override + String get advancedOptions => '詳細オプション'; + + @override + String get customClientId => 'カスタム Client ID'; + + @override + String get customClientIdDescription => + '共有 Client ID は Spotify のレート制限を受ける可能性があります。Spotify Developer Dashboard で独自のアプリを作成し、自分の Client ID を使用できます。'; + + @override + String get customClientIdHint => 'Spotify Client ID を入力'; + + @override + String get customClientIdSaved => 'カスタム Client ID を保存しました'; + + @override + String get customClientIdCleared => 'デフォルトの Client ID に戻しました'; + + @override + String get useDefaultClient => 'デフォルトを使用'; + + @override + String get customClientIdReauthRequired => + 'Client ID の切り替えには再ログインが必要です。今すぐログアウトしますか?'; } diff --git a/lib/l10n/app_localizations_zh.dart b/lib/l10n/app_localizations_zh.dart index 40e2d3a..2910347 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -50,15 +50,6 @@ class AppLocalizationsZh extends AppLocalizations { @override String get errorCopied => '错误信息已复制到剪贴板'; - @override - String get reconfigureCredentials => '重新配置凭据'; - - @override - String get apiConfigured => 'API 已配置'; - - @override - String get change => '更改'; - @override String get credentialsStayOnDevice => '您的凭据仅保存在本地设备'; @@ -137,33 +128,6 @@ class AppLocalizationsZh extends AppLocalizations { @override String get next => '下一首'; - @override - String get setupGuide => '设置向导'; - - @override - String get setupDescription => '首先,您需要创建一个 Spotify 开发者应用并输入您的凭据。'; - - @override - String get step1Title => '前往 Spotify 开发者控制台'; - - @override - String get step2Title => '创建新应用'; - - @override - String get step3Title => '添加重定向 URI'; - - @override - String get step4Title => '复制您的凭据'; - - @override - String get clientId => 'Client ID'; - - @override - String get clientSecret => 'Client Secret'; - - @override - String get saveAndContinue => '保存并继续'; - @override String get errorInvalidClient => 'API 凭据无效。请检查您的 Client ID 和 Secret。'; @@ -801,13 +765,6 @@ class AppLocalizationsZh extends AppLocalizations { @override String get privacyNoDataCollectionDesc => '我们不收集、存储或传输任何使用分析、播放历史或个人信息。'; - @override - String get privacyOAuthSecurity => 'OAuth 安全'; - - @override - String get privacyOAuthSecurityDesc => - '身份验证使用本地 HTTP 服务器(端口 8888-8891、8080 或 3000),并通过 state 参数进行 CSRF 保护。'; - @override String get privacyYouControl => '数据由您掌控'; @@ -817,163 +774,6 @@ class AppLocalizationsZh extends AppLocalizations { @override String get close => '关闭'; - @override - String get welcomeToFullStop => '欢迎使用 FullStop'; - - @override - String get updateCredentials => '更新凭据'; - - @override - String get connectSpotifyToStart => '连接您的 Spotify 账户以开始使用'; - - @override - String get updateSpotifyCredentials => '更新您的 Spotify API 凭据'; - - @override - String get credentialsSecurelyStored => '您的凭据仅安全存储在您的设备上'; - - @override - String get privacyPolicy => '隐私政策'; - - @override - String get step1CreateApp => '第一步:创建 Spotify 应用'; - - @override - String get openDeveloperDashboard => '打开 Spotify 开发者控制台'; - - @override - String get openDeveloperDashboardHint => '点击下方按钮,在浏览器中打开 Spotify 开发者控制台。'; - - @override - String get createNewApp => '创建新应用'; - - @override - String get createNewAppDesc => - '点击「Create App」并填写:\n• App name:任意名称(如 \"My Focus App\")\n• App description:个人使用\n• Website:留空或填写任意 URL\n• 勾选「Web API」选项'; - - @override - String get createNewAppDescShort => '点击「Create App」并填写以下字段,勾选「Web API」选项。'; - - @override - String get appNameLabel => 'App name(应用名称)'; - - @override - String get appNameCopied => '应用名称已复制!'; - - @override - String get appDescriptionLabel => 'App description(应用描述)'; - - @override - String get appDescriptionCopied => '应用描述已复制!'; - - @override - String get redirectUriLabel => 'Redirect URI(重定向 URI)'; - - @override - String get setRedirectUri => '设置重定向 URI(重要!)'; - - @override - String get setRedirectUriDesc => '在「Redirect URIs」字段中添加以下 URI:'; - - @override - String get copy => '复制'; - - @override - String get redirectUriCopied => '重定向 URI 已复制!'; - - @override - String get redirectUriWarning => '粘贴后点击「Add」,然后点击底部的「Save」!'; - - @override - String get step2EnterCredentials => '第二步:输入凭据'; - - @override - String get updateYourCredentials => '更新您的凭据'; - - @override - String get findCredentialsHint => '在 Spotify 开发者控制台的应用设置页面中找到您的凭据。'; - - @override - String get modifyCredentialsHint => '修改下方凭据,如正确则无需更改。'; - - @override - String get enterClientId => '输入您的 Client ID'; - - @override - String get clientIdRequired => 'Client ID 为必填项'; - - @override - String get clientIdTooShort => 'Client ID 似乎太短'; - - @override - String get enterClientSecret => '输入您的 Client Secret'; - - @override - String get clientSecretRequired => 'Client Secret 为必填项'; - - @override - String get clientSecretTooShort => 'Client Secret 似乎太短'; - - @override - String get whereToFindCredentials => '在哪里找到这些?'; - - @override - String get whereToFindCredentialsDesc => - '在您的 Spotify 应用设置页面中,您会看到 Client ID。点击「View client secret」查看密钥。'; - - @override - String get step3ReadyToConnect => '第三步:准备连接'; - - @override - String get credentialsSaved => '凭据已保存!'; - - @override - String get waitingForCredentials => '等待输入凭据'; - - @override - String get credentialsSavedDesc => '您的 Spotify API 凭据已安全存储。现在可以连接 Spotify 了。'; - - @override - String get waitingForCredentialsDesc => '请返回第二步输入您的凭据。'; - - @override - String get spotifyPremiumRequired => '需要 Spotify Premium'; - - @override - String get spotifyPremiumRequiredDesc => - '本应用需要 Spotify Premium 订阅才能使用播放控制功能。'; - - @override - String get back => '返回'; - - @override - String get nextEnterCredentials => '下一步:输入凭据'; - - @override - String get saveCredentials => '保存凭据'; - - @override - String get updateCredentialsButton => '更新凭据'; - - @override - String get connectToSpotify => '连接 Spotify'; - - @override - String get reconfigureApiCredentials => '重新配置 API 凭据'; - - @override - String get changeClientIdSecret => '更改您的 Client ID 和 Secret'; - - @override - String get reconfigureDialogTitle => '重新配置 API 凭据'; - - @override - String get reconfigureDialogContent => - '这将清除当前的 API 凭据并登出。\n\n您需要重新输入 Client ID 和 Secret。'; - - @override - String get reconfigure => '重新配置'; - @override String get redirectUriForSpotifyApp => 'Spotify 应用的重定向 URI'; @@ -985,9 +785,6 @@ class AppLocalizationsZh extends AppLocalizations { return '已配置($clientId)'; } - @override - String get notConfigured => '未配置'; - @override String get llmOpenAiCompatible => 'OpenAI 兼容 API'; @@ -1087,4 +884,29 @@ class AppLocalizationsZh extends AppLocalizations { @override String get exitMiniPlayer => '退出迷你播放器'; + + @override + String get advancedOptions => '高级选项'; + + @override + String get customClientId => '自定义 Client ID'; + + @override + String get customClientIdDescription => + '公用 Client ID 在高频请求时可能被 Spotify 限流。你可以在 Spotify Developer Dashboard 创建自己的应用,使用自己的 Client ID。'; + + @override + String get customClientIdHint => '输入你的 Spotify Client ID'; + + @override + String get customClientIdSaved => '自定义 Client ID 已保存'; + + @override + String get customClientIdCleared => '已恢复使用默认 Client ID'; + + @override + String get useDefaultClient => '使用默认'; + + @override + String get customClientIdReauthRequired => '切换 Client ID 后需要重新登录,是否立即退出登录?'; } diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index e5ba787..84ebfcb 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -29,12 +29,6 @@ "errorCopied": "错误信息已复制到剪贴板", - "reconfigureCredentials": "重新配置凭据", - - "apiConfigured": "API 已配置", - - "change": "更改", - "credentialsStayOnDevice": "您的凭据仅保存在本地设备", "controlsExistingSession": "控制您现有的 Spotify 会话", @@ -87,25 +81,6 @@ "next": "下一首", - "setupGuide": "设置向导", - - - "setupDescription": "首先,您需要创建一个 Spotify 开发者应用并输入您的凭据。", - - "step1Title": "前往 Spotify 开发者控制台", - - "step2Title": "创建新应用", - - "step3Title": "添加重定向 URI", - - "step4Title": "复制您的凭据", - - "clientId": "Client ID", - - "clientSecret": "Client Secret", - - "saveAndContinue": "保存并继续", - "errorInvalidClient": "API 凭据无效。请检查您的 Client ID 和 Secret。", "errorRedirectUri": "重定向 URI 不匹配!请确保您的 Spotify 应用配置了正确的重定向 URI。", @@ -475,126 +450,18 @@ "privacyNoDataCollectionDesc": "我们不收集、存储或传输任何使用分析、播放历史或个人信息。", - "privacyOAuthSecurity": "OAuth 安全", - - "privacyOAuthSecurityDesc": "身份验证使用本地 HTTP 服务器(端口 8888-8891、8080 或 3000),并通过 state 参数进行 CSRF 保护。", - "privacyYouControl": "数据由您掌控", "privacyYouControlDesc": "您可以随时在设置页面清除凭据。卸载应用将删除所有存储的数据。", "close": "关闭", - "welcomeToFullStop": "欢迎使用 FullStop", - - "updateCredentials": "更新凭据", - - "connectSpotifyToStart": "连接您的 Spotify 账户以开始使用", - - "updateSpotifyCredentials": "更新您的 Spotify API 凭据", - - "credentialsSecurelyStored": "您的凭据仅安全存储在您的设备上", - - "privacyPolicy": "隐私政策", - - "step1CreateApp": "第一步:创建 Spotify 应用", - - "openDeveloperDashboard": "打开 Spotify 开发者控制台", - - "openDeveloperDashboardHint": "点击下方按钮,在浏览器中打开 Spotify 开发者控制台。", - - "createNewApp": "创建新应用", - - "createNewAppDesc": "点击「Create App」并填写:\n• App name:任意名称(如 \"My Focus App\")\n• App description:个人使用\n• Website:留空或填写任意 URL\n• 勾选「Web API」选项", - - "createNewAppDescShort": "点击「Create App」并填写以下字段,勾选「Web API」选项。", - - "appNameLabel": "App name(应用名称)", - - "appNameCopied": "应用名称已复制!", - - "appDescriptionLabel": "App description(应用描述)", - - "appDescriptionCopied": "应用描述已复制!", - - "redirectUriLabel": "Redirect URI(重定向 URI)", - - "setRedirectUri": "设置重定向 URI(重要!)", - - "setRedirectUriDesc": "在「Redirect URIs」字段中添加以下 URI:", - - "copy": "复制", - - "redirectUriCopied": "重定向 URI 已复制!", - - "redirectUriWarning": "粘贴后点击「Add」,然后点击底部的「Save」!", - - "step2EnterCredentials": "第二步:输入凭据", - - "updateYourCredentials": "更新您的凭据", - - "findCredentialsHint": "在 Spotify 开发者控制台的应用设置页面中找到您的凭据。", - - "modifyCredentialsHint": "修改下方凭据,如正确则无需更改。", - - "enterClientId": "输入您的 Client ID", - - "clientIdRequired": "Client ID 为必填项", - - "clientIdTooShort": "Client ID 似乎太短", - - "enterClientSecret": "输入您的 Client Secret", - - "clientSecretRequired": "Client Secret 为必填项", - - "clientSecretTooShort": "Client Secret 似乎太短", - - "whereToFindCredentials": "在哪里找到这些?", - - "whereToFindCredentialsDesc": "在您的 Spotify 应用设置页面中,您会看到 Client ID。点击「View client secret」查看密钥。", - - "step3ReadyToConnect": "第三步:准备连接", - - "credentialsSaved": "凭据已保存!", - - "waitingForCredentials": "等待输入凭据", - - "credentialsSavedDesc": "您的 Spotify API 凭据已安全存储。现在可以连接 Spotify 了。", - - "waitingForCredentialsDesc": "请返回第二步输入您的凭据。", - - "spotifyPremiumRequired": "需要 Spotify Premium", - - "spotifyPremiumRequiredDesc": "本应用需要 Spotify Premium 订阅才能使用播放控制功能。", - - "back": "返回", - - "nextEnterCredentials": "下一步:输入凭据", - - "saveCredentials": "保存凭据", - - "updateCredentialsButton": "更新凭据", - - "connectToSpotify": "连接 Spotify", - - "reconfigureApiCredentials": "重新配置 API 凭据", - - "changeClientIdSecret": "更改您的 Client ID 和 Secret", - - "reconfigureDialogTitle": "重新配置 API 凭据", - - "reconfigureDialogContent": "这将清除当前的 API 凭据并登出。\n\n您需要重新输入 Client ID 和 Secret。", - - "reconfigure": "重新配置", - "redirectUriForSpotifyApp": "Spotify 应用的重定向 URI", "spotifyApi": "Spotify API", "configured": "已配置({clientId})", - "notConfigured": "未配置", - "llmOpenAiCompatible": "OpenAI 兼容 API", "llmOpenAiCompatibleDesc": "支持 OpenAI、Ollama 及其他 OpenAI 兼容 API。\n本地模型(如 Ollama)可不填 API Key。", @@ -657,5 +524,21 @@ "miniPlayer": "迷你播放器", - "exitMiniPlayer": "退出迷你播放器" + "exitMiniPlayer": "退出迷你播放器", + + "advancedOptions": "高级选项", + + "customClientId": "自定义 Client ID", + + "customClientIdDescription": "公用 Client ID 在高频请求时可能被 Spotify 限流。你可以在 Spotify Developer Dashboard 创建自己的应用,使用自己的 Client ID。", + + "customClientIdHint": "输入你的 Spotify Client ID", + + "customClientIdSaved": "自定义 Client ID 已保存", + + "customClientIdCleared": "已恢复使用默认 Client ID", + + "useDefaultClient": "使用默认", + + "customClientIdReauthRequired": "切换 Client ID 后需要重新登录,是否立即退出登录?" } diff --git a/lib/presentation/screens/login_screen.dart b/lib/presentation/screens/login_screen.dart index b260150..a53416c 100644 --- a/lib/presentation/screens/login_screen.dart +++ b/lib/presentation/screens/login_screen.dart @@ -6,15 +6,27 @@ import '../../application/providers/auth_provider.dart'; import '../../application/providers/credentials_provider.dart'; import '../themes/app_theme.dart'; import '../widgets/app_logo.dart'; -import 'setup_guide_screen.dart'; -class LoginScreen extends ConsumerWidget { +class LoginScreen extends ConsumerStatefulWidget { const LoginScreen({super.key}); @override - Widget build(BuildContext context, WidgetRef ref) { + ConsumerState createState() => _LoginScreenState(); +} + +class _LoginScreenState extends ConsumerState { + bool _advancedExpanded = false; + final _clientIdController = TextEditingController(); + + @override + void dispose() { + _clientIdController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { final authState = ref.watch(authProvider); - final credentialsState = ref.watch(credentialsProvider); final isLoading = authState.status == AuthStatus.loading; return Scaffold( @@ -56,50 +68,6 @@ class LoginScreen extends ConsumerWidget { ), const SizedBox(height: 48), - // Credentials status - if (credentialsState.hasSpotifyCredentials && !isLoading) - Container( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - decoration: BoxDecoration( - color: AppTheme.spotifyGreen.withValues(alpha: 0.1), - borderRadius: BorderRadius.circular(20), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - Icons.check_circle, - size: 16, - color: AppTheme.spotifyGreen, - ), - const SizedBox(width: 8), - Text( - AppLocalizations.of(context)!.apiConfigured, - style: TextStyle( - fontSize: 12, - color: AppTheme.spotifyGreen, - ), - ), - const SizedBox(width: 8), - GestureDetector( - onTap: () => _showReconfigureDialog(context, ref), - child: Text( - AppLocalizations.of(context)!.change, - style: TextStyle( - fontSize: 12, - color: AppTheme.spotifyGreen, - decoration: TextDecoration.underline, - ), - ), - ), - ], - ), - ), - const SizedBox(height: 24), - // Loading state with cancel option if (isLoading) _buildLoadingState(context, ref), @@ -119,6 +87,11 @@ class LoginScreen extends ConsumerWidget { ), ), ), + const SizedBox(height: 16), + + // Advanced options (custom Client ID) + if (!isLoading) _buildAdvancedSection(context), + const SizedBox(height: 24), // Info section @@ -156,6 +129,168 @@ class LoginScreen extends ConsumerWidget { ); } + Widget _buildAdvancedSection(BuildContext context) { + final l10n = AppLocalizations.of(context)!; + final creds = ref.watch(credentialsProvider); + final hasCustom = + creds.customSpotifyClientId != null && + creds.customSpotifyClientId!.isNotEmpty; + final effectiveClientId = ref.watch(effectiveSpotifyClientIdProvider); + + return Column( + children: [ + // Clickable row to expand/collapse + InkWell( + borderRadius: BorderRadius.circular(8), + onTap: () { + setState(() { + _advancedExpanded = !_advancedExpanded; + if (_advancedExpanded && hasCustom) { + _clientIdController.text = creds.customSpotifyClientId!; + } + }); + }, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 4), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.tune, + size: 16, + color: AppTheme.spotifyLightGray, + ), + const SizedBox(width: 6), + Text( + l10n.advancedOptions, + style: TextStyle( + fontSize: 13, + color: AppTheme.spotifyLightGray, + ), + ), + Icon( + _advancedExpanded ? Icons.expand_less : Icons.expand_more, + size: 18, + color: AppTheme.spotifyLightGray, + ), + ], + ), + ), + ), + if (_advancedExpanded) ...[ + const SizedBox(height: 8), + Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: AppTheme.spotifyDarkGray, + borderRadius: BorderRadius.circular(12), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Current status + Row( + children: [ + Icon(Icons.key, size: 16, color: AppTheme.spotifyLightGray), + const SizedBox(width: 8), + Expanded( + child: Text( + l10n.configured(_maskClientId(effectiveClientId)), + style: TextStyle( + fontSize: 12, + color: hasCustom + ? AppTheme.spotifyGreen + : AppTheme.spotifyLightGray, + ), + ), + ), + ], + ), + const SizedBox(height: 12), + Text( + l10n.customClientIdDescription, + style: TextStyle( + fontSize: 12, + color: AppTheme.spotifyLightGray.withValues(alpha: 0.8), + ), + ), + const SizedBox(height: 12), + TextField( + controller: _clientIdController, + decoration: InputDecoration( + labelText: l10n.customClientId, + hintText: l10n.customClientIdHint, + border: const OutlineInputBorder(), + isDense: true, + suffixIcon: hasCustom + ? IconButton( + icon: const Icon(Icons.clear, size: 18), + tooltip: l10n.useDefaultClient, + onPressed: () => _clearCustomClientId(l10n), + ) + : null, + ), + style: const TextStyle(fontFamily: 'monospace', fontSize: 13), + ), + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + if (hasCustom) + TextButton( + onPressed: () => _clearCustomClientId(l10n), + child: Text(l10n.useDefaultClient), + ), + const SizedBox(width: 8), + FilledButton( + onPressed: () => _saveCustomClientId(l10n), + child: Text(l10n.save), + ), + ], + ), + ], + ), + ), + ], + ], + ); + } + + Future _saveCustomClientId(AppLocalizations l10n) async { + final value = _clientIdController.text.trim(); + if (value.isEmpty) return; + + final notifier = ref.read(credentialsProvider.notifier); + final success = await notifier.saveCustomSpotifyClientId(value); + + if (!mounted) return; + + if (success) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(l10n.customClientIdSaved)), + ); + } + } + + Future _clearCustomClientId(AppLocalizations l10n) async { + final notifier = ref.read(credentialsProvider.notifier); + await notifier.clearCustomSpotifyClientId(); + _clientIdController.clear(); + + if (!mounted) return; + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(l10n.customClientIdCleared)), + ); + } + + String _maskClientId(String clientId) { + if (clientId.length < 8) return '****'; + return '${clientId.substring(0, 4)}...${clientId.substring(clientId.length - 4)}'; + } + Widget _buildLoadingState(BuildContext context, WidgetRef ref) { return Container( padding: const EdgeInsets.all(24), @@ -265,19 +400,6 @@ class LoginScreen extends ConsumerWidget { ); } - void _showReconfigureDialog(BuildContext context, WidgetRef ref) { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => SetupGuideScreen( - isReconfiguring: true, - onSetupComplete: () { - Navigator.of(context).pop(); - }, - ), - ), - ); - } - String _getErrorMessage(BuildContext context, String? error) { final l10n = AppLocalizations.of(context)!; if (error == null) return 'An unknown error occurred'; @@ -378,14 +500,6 @@ class LoginScreen extends ConsumerWidget { style: TextStyle(color: Colors.red.shade300, fontSize: 12), textAlign: TextAlign.center, ), - // Show reconfigure option on auth error - const SizedBox(height: 12), - TextButton.icon( - onPressed: () => _showReconfigureDialog(context, ref), - icon: const Icon(Icons.settings, size: 16), - label: Text(l10n.reconfigureCredentials), - style: TextButton.styleFrom(foregroundColor: Colors.red.shade300), - ), ], ), ); diff --git a/lib/presentation/screens/setup_guide_screen.dart b/lib/presentation/screens/setup_guide_screen.dart deleted file mode 100644 index 908433a..0000000 --- a/lib/presentation/screens/setup_guide_screen.dart +++ /dev/null @@ -1,855 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:fullstop/l10n/app_localizations.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:url_launcher/url_launcher.dart'; -import '../../application/providers/credentials_provider.dart'; -import '../../core/config/app_config.dart'; -import '../themes/app_theme.dart'; -import '../widgets/app_logo.dart'; - -class SetupGuideScreen extends ConsumerStatefulWidget { - final VoidCallback onSetupComplete; - final bool isReconfiguring; - - const SetupGuideScreen({ - super.key, - required this.onSetupComplete, - this.isReconfiguring = false, - }); - - @override - ConsumerState createState() => _SetupGuideScreenState(); -} - -class _SetupGuideScreenState extends ConsumerState { - final _formKey = GlobalKey(); - final _clientIdController = TextEditingController(); - final _clientSecretController = TextEditingController(); - bool _obscureSecret = true; - int _currentStep = 0; - bool _hasLoadedExistingCredentials = false; - - @override - void initState() { - super.initState(); - // If reconfiguring, start at step 2 (credentials entry) - if (widget.isReconfiguring) { - _currentStep = 1; - } - } - - @override - void dispose() { - _clientIdController.dispose(); - _clientSecretController.dispose(); - super.dispose(); - } - - void _loadExistingCredentials(CredentialsState credentialsState) { - if (!_hasLoadedExistingCredentials && widget.isReconfiguring) { - // Pre-fill existing credentials - if (credentialsState.spotifyClientId != null) { - _clientIdController.text = credentialsState.spotifyClientId!; - } - if (credentialsState.spotifyClientSecret != null) { - _clientSecretController.text = credentialsState.spotifyClientSecret!; - } - _hasLoadedExistingCredentials = true; - } - } - - @override - Widget build(BuildContext context) { - final credentialsState = ref.watch(credentialsProvider); - final l10n = AppLocalizations.of(context)!; - - // Load existing credentials when reconfiguring - _loadExistingCredentials(credentialsState); - - return Scaffold( - body: SafeArea( - child: Column( - children: [ - // Header - Padding( - padding: const EdgeInsets.all(24), - child: Column( - children: [ - const AppLogo(size: 80), - const SizedBox(height: 16), - Text( - widget.isReconfiguring - ? l10n.updateCredentials - : l10n.welcomeToFullStop, - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 8), - Text( - widget.isReconfiguring - ? l10n.updateSpotifyCredentials - : l10n.connectSpotifyToStart, - style: TextStyle( - fontSize: 14, - color: AppTheme.spotifyLightGray, - ), - textAlign: TextAlign.center, - ), - ], - ), - ), - - // Security Notice - _buildSecurityNotice(), - - const SizedBox(height: 16), - - // Main content - Expanded( - child: SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Column( - children: [ - _buildStepIndicator(), - const SizedBox(height: 24), - _buildCurrentStepContent(credentialsState), - const SizedBox(height: 24), - ], - ), - ), - ), - - // Navigation buttons - _buildNavigationButtons(credentialsState), - ], - ), - ), - ); - } - - Widget _buildSecurityNotice() { - final l10n = AppLocalizations.of(context)!; - return Container( - margin: const EdgeInsets.symmetric(horizontal: 24), - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: AppTheme.spotifyGreen.withValues(alpha: 0.1), - borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppTheme.spotifyGreen.withValues(alpha: 0.3)), - ), - child: Row( - children: [ - const Icon(Icons.security, color: AppTheme.spotifyGreen, size: 20), - const SizedBox(width: 12), - Expanded( - child: Text( - l10n.credentialsSecurelyStored, - style: TextStyle(fontSize: 12, color: AppTheme.spotifyLightGray), - ), - ), - IconButton( - icon: const Icon(Icons.info_outline, size: 18), - color: AppTheme.spotifyGreen, - onPressed: () => _showPrivacyPolicy(context), - tooltip: l10n.privacyPolicy, - ), - ], - ), - ); - } - - Widget _buildStepIndicator() { - return Row( - children: [ - for (int i = 0; i < 3; i++) ...[ - if (i > 0) - Expanded( - child: Container( - height: 2, - color: i <= _currentStep - ? AppTheme.spotifyGreen - : AppTheme.spotifyDarkGray, - ), - ), - GestureDetector( - onTap: () => setState(() => _currentStep = i), - child: Container( - width: 32, - height: 32, - decoration: BoxDecoration( - color: i <= _currentStep - ? AppTheme.spotifyGreen - : AppTheme.spotifyDarkGray, - shape: BoxShape.circle, - ), - child: Center( - child: i < _currentStep - ? const Icon( - Icons.check, - size: 18, - color: AppTheme.spotifyBlack, - ) - : Text( - '${i + 1}', - style: TextStyle( - color: i <= _currentStep - ? AppTheme.spotifyBlack - : AppTheme.spotifyLightGray, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ), - ], - ], - ); - } - - Widget _buildCurrentStepContent(CredentialsState credentialsState) { - switch (_currentStep) { - case 0: - return _buildStep1CreateApp(); - case 1: - return _buildStep2EnterCredentials(credentialsState); - case 2: - return _buildStep3Confirm(credentialsState); - default: - return const SizedBox(); - } - } - - Widget _buildStep1CreateApp() { - final l10n = AppLocalizations.of(context)!; - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - l10n.step1CreateApp, - style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - const SizedBox(height: 16), - _buildInstructionCard( - icon: Icons.open_in_new, - title: '1. ${l10n.openDeveloperDashboard}', - description: l10n.openDeveloperDashboardHint, - child: SizedBox( - width: double.infinity, - child: ElevatedButton.icon( - onPressed: () => - _launchUrl('https://developer.spotify.com/dashboard'), - icon: const Icon(Icons.open_in_browser), - label: Text(l10n.openDeveloperDashboard), - ), - ), - ), - const SizedBox(height: 12), - _buildInstructionCard( - icon: Icons.add_circle_outline, - title: '2. ${l10n.createNewApp}', - description: l10n.createNewAppDescShort, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 8), - _buildCopyableField( - label: l10n.appNameLabel, - value: 'FullStop', - onCopied: () => _showCopiedSnackbar(l10n.appNameCopied), - ), - const SizedBox(height: 8), - _buildCopyableField( - label: l10n.appDescriptionLabel, - value: 'FullStop Custom API Client', - onCopied: () => _showCopiedSnackbar(l10n.appDescriptionCopied), - ), - const SizedBox(height: 8), - _buildCopyableField( - label: l10n.redirectUriLabel, - value: AppConfig.spotifyRedirectUri, - onCopied: () => _showCopiedSnackbar(l10n.redirectUriCopied), - isHighlighted: true, - ), - const SizedBox(height: 12), - Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: Colors.orange.withValues(alpha: 0.1), - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: Colors.orange.withValues(alpha: 0.5), - ), - ), - child: Row( - children: [ - const Icon( - Icons.warning_amber, - color: Colors.orange, - size: 16, - ), - const SizedBox(width: 8), - Expanded( - child: Text( - l10n.redirectUriWarning, - style: TextStyle( - fontSize: 11, - color: Colors.orange.shade300, - ), - ), - ), - ], - ), - ), - ], - ), - ), - ], - ); - } - - Widget _buildCopyableField({ - required String label, - required String value, - required VoidCallback onCopied, - bool isHighlighted = false, - }) { - final l10n = AppLocalizations.of(context)!; - return Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), - decoration: BoxDecoration( - color: AppTheme.spotifyBlack, - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: AppTheme.spotifyLightGray.withValues(alpha: 0.3), - width: 1, - ), - ), - child: Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - label, - style: TextStyle( - fontSize: 10, - color: AppTheme.spotifyLightGray, - ), - ), - const SizedBox(height: 2), - SelectableText( - value, - style: TextStyle( - fontFamily: 'monospace', - color: isHighlighted - ? AppTheme.spotifyGreen - : AppTheme.spotifyWhite, - fontSize: 13, - fontWeight: isHighlighted - ? FontWeight.bold - : FontWeight.normal, - ), - ), - ], - ), - ), - IconButton( - onPressed: () { - Clipboard.setData(ClipboardData(text: value)); - onCopied(); - }, - icon: const Icon(Icons.copy, size: 18), - color: AppTheme.spotifyGreen, - tooltip: l10n.copy, - padding: EdgeInsets.zero, - constraints: const BoxConstraints(minWidth: 36, minHeight: 36), - ), - ], - ), - ); - } - - void _showCopiedSnackbar(String message) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(message), - duration: const Duration(seconds: 2), - backgroundColor: AppTheme.spotifyGreen, - ), - ); - } - - Widget _buildStep2EnterCredentials(CredentialsState credentialsState) { - final l10n = AppLocalizations.of(context)!; - return Form( - key: _formKey, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - widget.isReconfiguring - ? l10n.updateYourCredentials - : l10n.step2EnterCredentials, - style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - const SizedBox(height: 8), - Text( - widget.isReconfiguring - ? l10n.modifyCredentialsHint - : l10n.findCredentialsHint, - style: TextStyle(fontSize: 14, color: AppTheme.spotifyLightGray), - ), - const SizedBox(height: 24), - - // Client ID field - Text( - l10n.clientId, - style: const TextStyle(fontWeight: FontWeight.w500), - ), - const SizedBox(height: 8), - TextFormField( - controller: _clientIdController, - style: const TextStyle(color: AppTheme.spotifyWhite), - decoration: InputDecoration( - hintText: l10n.enterClientId, - prefixIcon: const Icon(Icons.key), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - ), - filled: true, - fillColor: AppTheme.spotifyDarkGray, - ), - validator: (value) { - if (value == null || value.trim().isEmpty) { - return l10n.clientIdRequired; - } - if (value.trim().length < 10) { - return l10n.clientIdTooShort; - } - return null; - }, - ), - const SizedBox(height: 16), - - // Client Secret field - Text( - l10n.clientSecret, - style: const TextStyle(fontWeight: FontWeight.w500), - ), - const SizedBox(height: 8), - TextFormField( - controller: _clientSecretController, - obscureText: _obscureSecret, - style: const TextStyle(color: AppTheme.spotifyWhite), - decoration: InputDecoration( - hintText: l10n.enterClientSecret, - prefixIcon: const Icon(Icons.lock), - suffixIcon: IconButton( - icon: Icon( - _obscureSecret ? Icons.visibility : Icons.visibility_off, - ), - onPressed: () { - setState(() => _obscureSecret = !_obscureSecret); - }, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(12), - ), - filled: true, - fillColor: AppTheme.spotifyDarkGray, - ), - validator: (value) { - if (value == null || value.trim().isEmpty) { - return l10n.clientSecretRequired; - } - if (value.trim().length < 10) { - return l10n.clientSecretTooShort; - } - return null; - }, - ), - const SizedBox(height: 16), - - // Help text - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.blue.withValues(alpha: 0.1), - borderRadius: BorderRadius.circular(8), - border: Border.all(color: Colors.blue.withValues(alpha: 0.3)), - ), - child: Row( - children: [ - const Icon(Icons.help_outline, color: Colors.blue, size: 20), - const SizedBox(width: 12), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - l10n.whereToFindCredentials, - style: const TextStyle( - fontWeight: FontWeight.bold, - color: Colors.blue, - ), - ), - const SizedBox(height: 4), - Text( - l10n.whereToFindCredentialsDesc, - style: TextStyle( - fontSize: 12, - color: AppTheme.spotifyLightGray, - ), - ), - ], - ), - ), - ], - ), - ), - - if (credentialsState.error != null) ...[ - const SizedBox(height: 16), - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.red.withValues(alpha: 0.1), - borderRadius: BorderRadius.circular(8), - border: Border.all(color: Colors.red.withValues(alpha: 0.3)), - ), - child: Row( - children: [ - const Icon(Icons.error_outline, color: Colors.red, size: 20), - const SizedBox(width: 8), - Expanded( - child: Text( - credentialsState.error!, - style: const TextStyle(color: Colors.red, fontSize: 12), - ), - ), - ], - ), - ), - ], - ], - ), - ); - } - - Widget _buildStep3Confirm(CredentialsState credentialsState) { - final l10n = AppLocalizations.of(context)!; - final isConfigured = credentialsState.hasSpotifyCredentials; - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - l10n.step3ReadyToConnect, - style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - const SizedBox(height: 24), - - // Status card - Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - color: isConfigured - ? AppTheme.spotifyGreen.withValues(alpha: 0.1) - : AppTheme.spotifyDarkGray, - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: isConfigured - ? AppTheme.spotifyGreen - : AppTheme.spotifyLightGray.withValues(alpha: 0.3), - ), - ), - child: Column( - children: [ - Icon( - isConfigured ? Icons.check_circle : Icons.pending, - size: 64, - color: isConfigured - ? AppTheme.spotifyGreen - : AppTheme.spotifyLightGray, - ), - const SizedBox(height: 16), - Text( - isConfigured - ? l10n.credentialsSaved - : l10n.waitingForCredentials, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: isConfigured - ? AppTheme.spotifyGreen - : AppTheme.spotifyWhite, - ), - ), - const SizedBox(height: 8), - Text( - isConfigured - ? l10n.credentialsSavedDesc - : l10n.waitingForCredentialsDesc, - style: TextStyle( - fontSize: 14, - color: AppTheme.spotifyLightGray, - ), - textAlign: TextAlign.center, - ), - if (isConfigured && credentialsState.spotifyClientId != null) ...[ - const SizedBox(height: 12), - Text( - '${l10n.clientId}: ${_maskString(credentialsState.spotifyClientId!)}', - style: TextStyle( - fontSize: 12, - color: AppTheme.spotifyLightGray, - fontFamily: 'monospace', - ), - ), - ], - ], - ), - ), - - const SizedBox(height: 24), - - // Requirements reminder - _buildInstructionCard( - icon: Icons.workspace_premium, - title: l10n.spotifyPremiumRequired, - description: l10n.spotifyPremiumRequiredDesc, - ), - ], - ); - } - - Widget _buildInstructionCard({ - required IconData icon, - required String title, - required String description, - Widget? child, - }) { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: AppTheme.spotifyDarkGray, - borderRadius: BorderRadius.circular(12), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Icon(icon, size: 20, color: AppTheme.spotifyGreen), - const SizedBox(width: 12), - Expanded( - child: Text( - title, - style: const TextStyle(fontWeight: FontWeight.bold), - ), - ), - ], - ), - const SizedBox(height: 8), - Padding( - padding: const EdgeInsets.only(left: 32), - child: Text( - description, - style: TextStyle( - fontSize: 13, - color: AppTheme.spotifyLightGray, - height: 1.5, - ), - ), - ), - if (child != null) ...[ - const SizedBox(height: 8), - Padding(padding: const EdgeInsets.only(left: 32), child: child), - ], - ], - ), - ); - } - - Widget _buildNavigationButtons(CredentialsState credentialsState) { - final l10n = AppLocalizations.of(context)!; - return Container( - padding: const EdgeInsets.all(24), - decoration: BoxDecoration( - color: AppTheme.spotifyDarkGray, - border: Border( - top: BorderSide( - color: AppTheme.spotifyLightGray.withValues(alpha: 0.2), - ), - ), - ), - child: Row( - children: [ - // Back/Cancel button - if (_currentStep > 0 || widget.isReconfiguring) - Expanded( - child: OutlinedButton( - onPressed: () { - if (_currentStep > 0) { - setState(() => _currentStep--); - } else if (widget.isReconfiguring) { - Navigator.of(context).pop(); - } - }, - child: Text( - _currentStep == 0 && widget.isReconfiguring - ? l10n.cancel - : l10n.back, - ), - ), - ) - else - const Spacer(), - - const SizedBox(width: 16), - - // Next/Save/Finish button - Expanded(flex: 2, child: _buildPrimaryButton(credentialsState)), - ], - ), - ); - } - - Widget _buildPrimaryButton(CredentialsState credentialsState) { - final l10n = AppLocalizations.of(context)!; - if (_currentStep == 0) { - return ElevatedButton( - onPressed: () => setState(() => _currentStep++), - child: Text(l10n.nextEnterCredentials), - ); - } else if (_currentStep == 1) { - return ElevatedButton( - onPressed: credentialsState.isLoading ? null : _saveCredentials, - child: credentialsState.isLoading - ? const SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator(strokeWidth: 2), - ) - : Text( - widget.isReconfiguring - ? l10n.updateCredentialsButton - : l10n.saveCredentials, - ), - ); - } else { - return ElevatedButton( - onPressed: credentialsState.hasSpotifyCredentials - ? () { - // Call the callback first - widget.onSetupComplete(); - // Then navigate using our own context - if (mounted) { - Navigator.of(context).popUntil((route) => route.isFirst); - } - } - : null, - child: Text(l10n.connectToSpotify), - ); - } - } - - Future _saveCredentials() async { - if (!_formKey.currentState!.validate()) return; - - final success = await ref - .read(credentialsProvider.notifier) - .saveSpotifyCredentials( - clientId: _clientIdController.text.trim(), - clientSecret: _clientSecretController.text.trim(), - ); - - if (success && mounted) { - setState(() => _currentStep = 2); - } - } - - String _maskString(String value) { - if (value.length <= 8) return '****'; - return '${value.substring(0, 4)}...${value.substring(value.length - 4)}'; - } - - Future _launchUrl(String url) async { - final uri = Uri.parse(url); - if (await canLaunchUrl(uri)) { - await launchUrl(uri, mode: LaunchMode.externalApplication); - } - } - - void _showPrivacyPolicy(BuildContext context) { - final l10n = AppLocalizations.of(context)!; - showDialog( - context: context, - builder: (dialogContext) => AlertDialog( - backgroundColor: AppTheme.spotifyDarkGray, - title: Text(l10n.aboutPrivacySecurity), - content: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - _buildPrivacySection( - l10n.privacySecureStorage, - l10n.privacySecureStorageDesc, - ), - _buildPrivacySection( - l10n.privacyDirectConnection, - l10n.privacyDirectConnectionDesc, - ), - _buildPrivacySection( - l10n.privacyNoDataCollection, - l10n.privacyNoDataCollectionDesc, - ), - _buildPrivacySection( - l10n.privacyYouControl, - l10n.privacyYouControlDesc, - ), - ], - ), - ), - actions: [ - TextButton( - onPressed: () => Navigator.pop(dialogContext), - child: Text(l10n.close), - ), - ], - ), - ); - } - - Widget _buildPrivacySection(String title, String content) { - return Padding( - padding: const EdgeInsets.only(bottom: 16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: const TextStyle( - fontWeight: FontWeight.bold, - color: AppTheme.spotifyGreen, - ), - ), - const SizedBox(height: 4), - Text( - content, - style: TextStyle( - fontSize: 13, - color: AppTheme.spotifyLightGray, - height: 1.4, - ), - ), - ], - ), - ); - } -} diff --git a/lib/presentation/widgets/settings/about_section.dart b/lib/presentation/widgets/settings/about_section.dart index d862143..094bb57 100644 --- a/lib/presentation/widgets/settings/about_section.dart +++ b/lib/presentation/widgets/settings/about_section.dart @@ -358,10 +358,6 @@ class AboutSection extends StatelessWidget { l10n.privacyNoDataCollection, l10n.privacyNoDataCollectionDesc, ), - _buildPrivacySection( - l10n.privacyOAuthSecurity, - l10n.privacyOAuthSecurityDesc, - ), _buildPrivacySection( l10n.privacyYouControl, l10n.privacyYouControlDesc, diff --git a/lib/presentation/widgets/settings/api_credentials_section.dart b/lib/presentation/widgets/settings/api_credentials_section.dart index 9951c38..8f3748c 100644 --- a/lib/presentation/widgets/settings/api_credentials_section.dart +++ b/lib/presentation/widgets/settings/api_credentials_section.dart @@ -3,18 +3,35 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:fullstop/l10n/app_localizations.dart'; import '../../../application/providers/auth_provider.dart'; import '../../../application/providers/credentials_provider.dart'; -import '../../../application/providers/playback_provider.dart'; import '../../../core/config/app_config.dart'; -import '../../screens/setup_guide_screen.dart'; import '../../themes/app_theme.dart'; -class ApiCredentialsSection extends ConsumerWidget { +class ApiCredentialsSection extends ConsumerStatefulWidget { const ApiCredentialsSection({super.key}); @override - Widget build(BuildContext context, WidgetRef ref) { + ConsumerState createState() => + _ApiCredentialsSectionState(); +} + +class _ApiCredentialsSectionState extends ConsumerState { + bool _advancedExpanded = false; + final _clientIdController = TextEditingController(); + + @override + void dispose() { + _clientIdController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; - final credentialsState = ref.watch(credentialsProvider); + final effectiveClientId = ref.watch(effectiveSpotifyClientIdProvider); + final creds = ref.watch(credentialsProvider); + final hasCustom = + creds.customSpotifyClientId != null && + creds.customSpotifyClientId!.isNotEmpty; return Column( children: [ @@ -22,27 +39,153 @@ class ApiCredentialsSection extends ConsumerWidget { leading: const Icon(Icons.key), title: Text(l10n.spotifyApi), subtitle: Text( - credentialsState.hasSpotifyCredentials - ? l10n.configured( - _maskClientId(credentialsState.spotifyClientId), - ) - : l10n.notConfigured, + l10n.configured(_maskClientId(effectiveClientId)), ), - trailing: credentialsState.hasSpotifyCredentials - ? Icon(Icons.check_circle, color: AppTheme.spotifyGreen) - : const Icon(Icons.warning, color: Colors.orange), + trailing: Icon(Icons.check_circle, color: AppTheme.spotifyGreen), ), + _buildRedirectUriInfo(context), + // Advanced options ListTile( - leading: const Icon(Icons.refresh), - title: Text(l10n.reconfigureApiCredentials), - subtitle: Text(l10n.changeClientIdSecret), - onTap: () => _showReconfigureDialog(context, ref), + leading: const Icon(Icons.tune), + title: Text(l10n.advancedOptions), + trailing: Icon( + _advancedExpanded ? Icons.expand_less : Icons.expand_more, + ), + onTap: () { + setState(() { + _advancedExpanded = !_advancedExpanded; + if (_advancedExpanded && hasCustom) { + _clientIdController.text = creds.customSpotifyClientId!; + } + }); + }, ), - _buildRedirectUriInfo(context), + if (_advancedExpanded) + _buildAdvancedOptions(context, l10n, hasCustom), ], ); } + Widget _buildAdvancedOptions( + BuildContext context, + AppLocalizations l10n, + bool hasCustom, + ) { + return Container( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceContainerHighest.withValues( + alpha: 0.5, + ), + borderRadius: BorderRadius.circular(8), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + l10n.customClientIdDescription, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + const SizedBox(height: 12), + TextField( + controller: _clientIdController, + decoration: InputDecoration( + labelText: l10n.customClientId, + hintText: l10n.customClientIdHint, + border: const OutlineInputBorder(), + isDense: true, + suffixIcon: hasCustom + ? IconButton( + icon: const Icon(Icons.clear, size: 18), + tooltip: l10n.useDefaultClient, + onPressed: () => _clearCustomClientId(context, l10n), + ) + : null, + ), + style: const TextStyle(fontFamily: 'monospace', fontSize: 13), + ), + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + if (hasCustom) + TextButton( + onPressed: () => _clearCustomClientId(context, l10n), + child: Text(l10n.useDefaultClient), + ), + const SizedBox(width: 8), + FilledButton( + onPressed: () => _saveCustomClientId(context, l10n), + child: Text(l10n.save), + ), + ], + ), + ], + ), + ); + } + + Future _saveCustomClientId( + BuildContext context, + AppLocalizations l10n, + ) async { + final value = _clientIdController.text.trim(); + if (value.isEmpty) return; + + final notifier = ref.read(credentialsProvider.notifier); + final success = await notifier.saveCustomSpotifyClientId(value); + + if (!context.mounted) return; + + if (success) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(l10n.customClientIdSaved)), + ); + _showReauthDialog(context, l10n); + } + } + + Future _clearCustomClientId( + BuildContext context, + AppLocalizations l10n, + ) async { + final notifier = ref.read(credentialsProvider.notifier); + await notifier.clearCustomSpotifyClientId(); + _clientIdController.clear(); + + if (!context.mounted) return; + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(l10n.customClientIdCleared)), + ); + _showReauthDialog(context, l10n); + } + + void _showReauthDialog(BuildContext context, AppLocalizations l10n) { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(l10n.customClientIdReauthRequired), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: Text(l10n.cancel), + ), + FilledButton( + onPressed: () { + Navigator.of(context).pop(); + ref.read(authProvider.notifier).logout(); + }, + child: Text(l10n.logout), + ), + ], + ), + ); + } + Widget _buildRedirectUriInfo(BuildContext context) { final l10n = AppLocalizations.of(context)!; return Container( @@ -86,54 +229,8 @@ class ApiCredentialsSection extends ConsumerWidget { ); } - String _maskClientId(String? clientId) { - if (clientId == null || clientId.length < 8) return '****'; + String _maskClientId(String clientId) { + if (clientId.length < 8) return '****'; return '${clientId.substring(0, 4)}...${clientId.substring(clientId.length - 4)}'; } - - void _showReconfigureDialog(BuildContext context, WidgetRef ref) { - final l10n = AppLocalizations.of(context)!; - showDialog( - context: context, - builder: (dialogContext) => AlertDialog( - backgroundColor: AppTheme.spotifyDarkGray, - title: Text(l10n.reconfigureDialogTitle), - content: Text(l10n.reconfigureDialogContent), - actions: [ - TextButton( - onPressed: () => Navigator.pop(dialogContext), - child: Text(l10n.cancel), - ), - ElevatedButton( - onPressed: () async { - Navigator.pop(dialogContext); - // Stop playback polling first to prevent 401 errors - ref.read(playbackProvider.notifier).stopPolling(); - await ref - .read(credentialsProvider.notifier) - .clearSpotifyCredentials(); - await ref.read(authProvider.notifier).logout(); - // Navigate to SetupGuideScreen with isReconfiguring flag - if (context.mounted) { - Navigator.of(context).pushReplacement( - MaterialPageRoute( - builder: (_) => SetupGuideScreen( - isReconfiguring: true, - // Pass a no-op callback since navigation is handled by pushReplacement - // The SetupGuideScreen will navigate back when setup is complete - onSetupComplete: () { - // Navigation is handled inside SetupGuideScreen using its own context - }, - ), - ), - ); - } - }, - style: ElevatedButton.styleFrom(backgroundColor: Colors.orange), - child: Text(l10n.reconfigure), - ), - ], - ), - ); - } } diff --git a/pubspec.lock b/pubspec.lock index e09173e..286f516 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -218,7 +218,7 @@ packages: source: hosted version: "3.1.2" crypto: - dependency: transitive + dependency: "direct main" description: name: crypto sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf diff --git a/pubspec.yaml b/pubspec.yaml index 800c544..7a1346b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,6 +39,7 @@ dependencies: logger: ^2.0.2+1 url_launcher: ^6.2.4 path: ^1.9.0 + crypto: ^3.0.3 path_provider: ^2.1.2 # Image Caching