From d555a7f14635170089216b1e4548aee827660c5d Mon Sep 17 00:00:00 2001 From: Dustin Date: Sun, 2 Aug 2026 15:48:08 +0200 Subject: [PATCH] =?UTF-8?q?v2.36=20=E2=80=94=20Sprint=201:=20Behebe=20Issu?= =?UTF-8?q?es=20#1=20(Zur=C3=BCck-Button),=20#5=20(Ausgeloggt),=20#4=20(Be?= =?UTF-8?q?rechtigungen)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue #1: CloudScreen Zurück-Button — onZurueck Callback statt Navigator.pop() - CloudScreen erhält VoidCallback? onZurueck Parameter - Bei onZurueck != null → Callback (Tab-Wechsel in home_screen) - Fallback: Navigator.pop(context) für Standalone-Nutzung Issue #5: Token wird nur bei HTTP 401 gelöscht - _tokenOnlinePruefen(): nur statusCode == 401 → false - 5xx, andere Fehler, Netzwerkfehler → true (Token behalten) - Verhindert Ausloggen bei temporären Server-Problemen Issue #4: Android 13+ Berechtigungen beim App-Start - main.dart: frageSpeicherZugriff() + POST_NOTIFICATIONS nach Auth-Init - musik_scanner.dart: Permission-Check vor externen Ordnern in _sammleMusikPfade() Build: ⏭️ (no APK) --- lib/main.dart | 12 ++++++++++++ lib/screens/cloud_screen.dart | 11 +++++++++-- lib/screens/home_screen.dart | 5 ++++- lib/services/auth_service.dart | 6 +++++- lib/services/musik_scanner.dart | 5 ++++- 5 files changed, 34 insertions(+), 5 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 901e161..8efded1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,12 +1,15 @@ import 'package:flutter/material.dart'; +import 'dart:io' show Platform; import 'package:audio_service/audio_service.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:permission_handler/permission_handler.dart'; import 'database/db_helper.dart'; import 'services/favoriten_service.dart'; import 'services/auth_service.dart'; import 'services/cloud_service.dart'; import 'services/melo_logger.dart'; import 'services/audio_handler.dart'; +import 'services/musik_scanner.dart'; import 'utils/farb_theme.dart'; import 'screens/home_screen.dart'; import 'screens/login_screen.dart'; @@ -37,6 +40,15 @@ void main() async { // Auth initialisieren (Token aus SharedPreferences laden + online validieren) await AuthService().initialisieren(); + // Android-Berechtigungen beim Start abfragen (Issue #4) + // Speicherzugriff für Musik-Scan (READ_MEDIA_AUDIO / Storage) + await MusikScanner().frageSpeicherZugriff(); + + // POST_NOTIFICATIONS für Android 13+ (Notifications für Downloads, Player) + if (Platform.isAndroid) { + await Permission.notification.request(); + } + // Auto-Sync beim Start (wenn eingeloggt und Auto-Sync aktiv) _starteAutoSyncFallsNoetig(); diff --git a/lib/screens/cloud_screen.dart b/lib/screens/cloud_screen.dart index 68b471d..58449aa 100644 --- a/lib/screens/cloud_screen.dart +++ b/lib/screens/cloud_screen.dart @@ -13,7 +13,8 @@ import '../services/melo_logger.dart'; /// Playlisten, Favoriten, Auto-Sync, Persistent Login, Benutzerdefinierte Namen class CloudScreen extends StatefulWidget { final CloudService cloud; - const CloudScreen({super.key, required this.cloud}); + final VoidCallback? onZurueck; + const CloudScreen({super.key, required this.cloud, this.onZurueck}); @override State createState() => _CloudScreenState(); @@ -590,7 +591,13 @@ class _CloudScreenState extends State { backgroundColor: MeloTheme.dunkel1, leading: IconButton( icon: const Icon(Icons.arrow_back, color: Colors.white, size: 22), - onPressed: () => Navigator.pop(context), + onPressed: () { + if (widget.onZurueck != null) { + widget.onZurueck!(); + } else { + Navigator.pop(context); + } + }, ), title: const Row( children: [ diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index 60e9474..0f4158a 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -303,7 +303,10 @@ class _MeloHomeState extends State { onSongsChanged: _vm.ladeSongs, ) : _aktiverTab == 4 - ? CloudScreen(cloud: _cloud) + ? CloudScreen( + cloud: _cloud, + onZurueck: () => setState(() => _aktiverTab = 0), + ) : Column( children: [ MeloHeader(onDownload: _zeigeDownloadDialog, onSearch: _zeigeSuche, onServer: _zeigeServerBrowser), diff --git a/lib/services/auth_service.dart b/lib/services/auth_service.dart index 9f92681..4edc2e5 100644 --- a/lib/services/auth_service.dart +++ b/lib/services/auth_service.dart @@ -69,7 +69,11 @@ class AuthService { headers: authHeader, ) .timeout(const Duration(seconds: 5)); - return response.statusCode == 200; + if (response.statusCode == 200) return true; + // Nur bei explizitem 401 (abgelaufen/ungültig) den Token löschen. + // Bei 5xx, anderen Fehlern oder temporären Server-Problemen Token behalten. + if (response.statusCode == 401) return false; + return true; } catch (_) { // Bei Netzwerkfehler: Token lokal akzeptieren (Offline-Modus) return true; diff --git a/lib/services/musik_scanner.dart b/lib/services/musik_scanner.dart index d05b184..ea7e751 100644 --- a/lib/services/musik_scanner.dart +++ b/lib/services/musik_scanner.dart @@ -135,8 +135,11 @@ class MusikScanner { MeloLogger().fehler('scanner_intern_pfad', e); } - // 2. Externe System-Ordner (nur Android) + // 2. Externe System-Ordner (nur Android, nur wenn Berechtigung vorhanden) if (Platform.isAndroid) { + final hatZugriff = await frageSpeicherZugriff(); + if (!hatZugriff) return pfade.toList(); + final ordner = [ '/storage/emulated/0/Music', '/storage/emulated/0/Download',