This repository has been archived on 2026-08-19. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
melo-app/lib/screens/settings_screen.dart
T
Dustin 148ff4f21b v2.51.4 — Review-Fix MED-1: „Musik scannen“ aus Einstellungen startet Scanner
## MED-1 (settings_screen.dart)
- Erweitert-Push wird awaited; Ergebnis 'scanner' wird an MeloHome weitergereicht
- onScan-Closure poppt nur noch den Erweitert-Screen, SettingsScreen propagiert
  das Ergebnis per eigenem Navigator.pop (mit State-Context + mounted-Guard)
2026-08-05 08:09:43 +02:00

267 lines
8.7 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:flutter/material.dart';
import '../config/app_config.dart';
import '../utils/farb_theme.dart';
import 'cloud_screen.dart';
import 'recap_screen.dart';
import 'erweitert_screen.dart';
import '../services/cloud_service.dart';
/// Vollwertiger Einstellungen-Screen kein Popup mehr
class SettingsScreen extends StatefulWidget {
const SettingsScreen({super.key});
@override
State<SettingsScreen> createState() => _SettingsScreenState();
}
class _SettingsScreenState extends State<SettingsScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: MeloTheme.schwarz,
appBar: AppBar(
backgroundColor: MeloTheme.dunkel1,
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.white, size: 22),
onPressed: () => Navigator.pop(context),
),
title: const Row(
children: [
Icon(Icons.settings, color: MeloTheme.rot, size: 20),
SizedBox(width: 10),
Text(
'Einstellungen',
style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.w600),
),
],
),
),
body: ListView(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
children: [
// ─── Sektion: Verbindung ───
_sektionHeader('Verbindung'),
_einstellungsKachel(
icon: Icons.cloud_outlined,
titel: 'Cloud Sync',
untertitel: 'Auto-Sync, Upload & Download',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => CloudScreen(cloud: CloudService()),
),
);
},
),
_einstellungsKachel(
icon: Icons.dns_outlined,
titel: 'Musikserver',
untertitel: 'Navidrome Musik-Server verbinden',
onTap: () {
// Signal zum Öffnen des Server-Browsers
Navigator.pop(context, 'server');
},
),
const SizedBox(height: 8),
// ─── Sektion: Daten ───
_sektionHeader('Daten & Privatsphäre'),
_einstellungsKachel(
icon: Icons.auto_graph,
titel: 'Jahres-Recap',
untertitel: 'Deine Hörstatistiken wie Spotify Wrapped',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => const RecapScreen()),
);
},
),
const SizedBox(height: 8),
// ─── Sektion: Erweitert (Technik) ───
_sektionHeader('Erweitert'),
_einstellungsKachel(
icon: Icons.handyman_outlined,
titel: 'Erweitert',
untertitel: 'Logs, Diagnose, Entwickler & Scanner',
onTap: () async {
// Erweitert-Screen öffnen. „Musik scannen“ (onScan) schließt den
// Erweitert-Screen mit dem Ergebnis 'scanner' → hier awaiten und
// das Ergebnis an MeloHome weiterreichen, das den Scanner startet.
final result = await Navigator.push<String>(
context,
MaterialPageRoute(
builder: (_) => ErweitertScreen(
onScan: () {
Navigator.pop(context, 'scanner');
},
),
),
);
if (!mounted || result != 'scanner') return;
Navigator.pop(this.context, 'scanner');
},
),
_einstellungsKachel(
icon: Icons.article_outlined,
titel: 'Logs',
untertitel: 'App-Logbuch im Speicher ansehen',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => const LogViewerScreen()),
);
},
),
_einstellungsKachel(
icon: Icons.bug_report_outlined,
titel: 'Entwickler',
untertitel: 'Version, URLs & technische Details',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => const EntwicklerScreen()),
);
},
),
const SizedBox(height: 8),
// ─── Sektion: Info ───
_sektionHeader('Info'),
Container(
decoration: BoxDecoration(
color: MeloTheme.dunkel1,
borderRadius: BorderRadius.circular(14),
border: Border.all(color: MeloTheme.dunkel2),
),
child: Column(
children: [
_infoZeile('Version', '2.51'),
const Divider(color: MeloTheme.dunkel2, height: 1),
_infoZeile('Theme', 'Schwarz + Rot'),
const Divider(color: MeloTheme.dunkel2, height: 1),
_infoZeile('Auth', AppConfig.authUrl),
const Divider(color: MeloTheme.dunkel2, height: 1),
_infoZeile('Cloud', AppConfig.cloudUrl),
],
),
),
const SizedBox(height: 24),
// ─── Abmelden ───
SizedBox(
width: double.infinity,
height: 48,
child: OutlinedButton.icon(
onPressed: () {
Navigator.pop(context, 'logout');
},
icon: const Icon(Icons.logout, size: 18),
label: const Text('Abmelden', style: TextStyle(fontSize: 14)),
style: OutlinedButton.styleFrom(
foregroundColor: MeloTheme.rot,
side: const BorderSide(color: MeloTheme.rot),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)),
),
),
),
const SizedBox(height: 32),
],
),
);
}
Widget _sektionHeader(String titel) {
return Padding(
padding: const EdgeInsets.fromLTRB(4, 16, 4, 8),
child: Text(
titel,
style: const TextStyle(
color: MeloTheme.textSekundaer,
fontSize: 11,
fontWeight: FontWeight.w600,
letterSpacing: 1.2,
),
),
);
}
Widget _einstellungsKachel({
required IconData icon,
required String titel,
required String untertitel,
required VoidCallback onTap,
}) {
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Material(
color: MeloTheme.dunkel1,
borderRadius: BorderRadius.circular(14),
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(14),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14),
border: Border.all(color: MeloTheme.dunkel2),
),
child: Row(
children: [
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: MeloTheme.dunkel2,
borderRadius: BorderRadius.circular(10),
),
child: Icon(icon, color: MeloTheme.rot, size: 20),
),
const SizedBox(width: 14),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
titel,
style: const TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.w500),
),
const SizedBox(height: 2),
Text(
untertitel,
style: const TextStyle(color: MeloTheme.textSekundaer, fontSize: 12),
),
],
),
),
const Icon(Icons.chevron_right, color: MeloTheme.textSekundaer, size: 20),
],
),
),
),
),
);
}
Widget _infoZeile(String label, String wert) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: Row(
children: [
Text(
label,
style: const TextStyle(color: MeloTheme.textSekundaer, fontSize: 13),
),
const Spacer(),
Text(
wert,
style: const TextStyle(color: Colors.white70, fontSize: 13),
),
],
),
);
}
}