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/widgets/melo_header.dart
T
Hermes (Server) 8b6a04ead8 Fix: Review-Findings korrigiert (Tag-Leiste, Profil, Singleton u.a.)
CRIT:
- Tag-Leiste: Toggle-Kopf 'Tags & Filter' eingebaut (war unerreichbar) + TagStats
- Profil: Cloud-Count vor Dialog aufloesen (kein 'Instance of Future' mehr)
HIGH:
- CloudEinstellungen: toten Sync-Timer entfernt (echter Timer im ViewModel)
- StatistikCard + RecentWidget jetzt eingebaut (gesamtMB/gesamtMin endlich genutzt)
- CloudService als Singleton (konsistenter Token-Zustand in allen Services)
MED/LOW:
- Playlist-Erkennung nur noch via list= Parameter
- Player: fehlende Quelle wird geloggt statt still
- song_tile: null-ID-Guard vor Tag-Dialog
- Scanner-Log mit Exception-Objekt
- FavoritenService: anzahlFavoriten() fuer StatistikCard
2026-07-31 15:42:54 +02:00

89 lines
3.1 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 '../utils/farb_theme.dart';
class MeloHeader extends StatelessWidget {
final VoidCallback onDownload;
final VoidCallback onSearch;
final VoidCallback? onServer;
final VoidCallback? onSettings;
const MeloHeader({super.key, required this.onDownload, required this.onSearch, this.onServer, this.onSettings});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(20, 12, 20, 4),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ShaderMask(
shaderCallback: (bounds) => const LinearGradient(
colors: [Colors.white, MeloTheme.rot],
).createShader(bounds),
child: const Text('Melo', style: TextStyle(
fontSize: 28, fontWeight: FontWeight.w700, color: Colors.white)),
),
const Text('Deine Musik. Deine Art.', style: TextStyle(fontSize: 12, color: MeloTheme.textSekundaer)),
],
),
Row(children: [
if (onServer != null) ...[
_btn(Icons.cloud, onServer!),
const SizedBox(width: 8),
],
_btn(Icons.download, onDownload),
const SizedBox(width: 8),
_btn(Icons.search, onSearch),
if (onSettings != null) ...[
const SizedBox(width: 8),
_btn(Icons.settings, onSettings!),
],
]),
],
),
const SizedBox(height: 8),
// Suchleiste immer sichtbar
TextField(
onSubmitted: (wert) {
if (wert.isNotEmpty) onSearch();
},
style: const TextStyle(color: Colors.white, fontSize: 14),
decoration: InputDecoration(
hintText: '🔍 Song, Künstler oder Tag suchen...',
hintStyle: TextStyle(color: Colors.grey.shade600, fontSize: 13),
prefixIcon: Icon(Icons.search, size: 18, color: MeloTheme.rot.withValues(alpha: 0.6)),
filled: true,
fillColor: MeloTheme.dunkel1,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide.none,
),
contentPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 12),
),
),
],
),
);
}
Widget _btn(IconData icon, VoidCallback onTap) {
return Container(
width: 40, height: 40,
decoration: BoxDecoration(
color: MeloTheme.dunkel1,
borderRadius: BorderRadius.circular(12),
),
child: IconButton(
icon: Icon(icon, size: 18, color: MeloTheme.rot),
onPressed: onTap,
),
);
}
}