v2.47 — Cloud-Verbindung beim App-Start + Live-Status-Anzeige (Verbinde→Verbunden)
## CloudService - CloudStatus-Enum (verbinde/verbunden/fehler), CloudService extends ChangeNotifier - verbinde(): Login+Status beim App-Start, setzt Status, notifyListeners - Getter status/statusText/istVerbunden/verbindungGestartet - Bestehende Methoden behalten — nur status() → statusDaten() umbenannt (Namenskonflikt mit neuem status-Getter) ## Home-Screen - _cloud.verbinde() in initState (feuern-und-vergessen) — Verbindung steht beim App-Start, nicht erst beim Tab-Öffnen ## Cloud-Screen - initState verbindet nicht mehr selbst — zeigt Service-Status via ListenableBuilder - Status wechselt live: 'Verbinde...' (gelb) → 'Verbunden' (grün) / 'Keine Verbindung' (rot) - Serverdaten (Playlists/Favoriten/Zähler) laden automatisch, sobald Service verbunden - Refresh-Button re-verbindet + lädt Zähler neu - Fallback: ungestarteter Service (Einstellungen-Screen) wird beim Öffnen gestartet
This commit is contained in:
+109
-80
@@ -7,7 +7,6 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import '../utils/farb_theme.dart';
|
||||
import '../utils/sanitize.dart';
|
||||
import '../services/cloud_service.dart';
|
||||
import '../services/auth_service.dart';
|
||||
import '../database/db_helper.dart';
|
||||
import '../services/melo_logger.dart';
|
||||
import '../main.dart'; // notificationsPlugin
|
||||
@@ -31,7 +30,7 @@ class _CloudScreenState extends State<CloudScreen> {
|
||||
bool _ladt = false;
|
||||
String? _status;
|
||||
bool _statusOk = false;
|
||||
bool _verbunden = false;
|
||||
bool _serverDatenGeladen = false;
|
||||
|
||||
// ─── Sync-Einstellungen ───
|
||||
bool _autoSync = true;
|
||||
@@ -66,15 +65,24 @@ class _CloudScreenState extends State<CloudScreen> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_status = 'Verbinde...';
|
||||
_verbindeCloud();
|
||||
_ladeStatus();
|
||||
// Verbindung stellt der CloudService beim App-Start her (MeloHome.initState).
|
||||
// Hier nur Settings laden + Serverdaten, sobald der Service verbunden ist.
|
||||
_ladeSettings();
|
||||
_ladeServerDaten();
|
||||
if (widget.cloud.istVerbunden) {
|
||||
_serverDatenGeladen = true;
|
||||
_ladeServerDaten();
|
||||
_ladeStatus();
|
||||
} else if (!widget.cloud.verbindungGestartet) {
|
||||
// Fallback: Service wurde noch nicht gestartet (z.B. eigener Service
|
||||
// aus den Einstellungen) — Verbindung hier anstoßen.
|
||||
widget.cloud.verbinde();
|
||||
}
|
||||
widget.cloud.addListener(_onCloudStatus);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
widget.cloud.removeListener(_onCloudStatus);
|
||||
_syncTimer?.cancel();
|
||||
_renameTitleCtrl.dispose();
|
||||
_renameArtistCtrl.dispose();
|
||||
@@ -83,16 +91,14 @@ class _CloudScreenState extends State<CloudScreen> {
|
||||
|
||||
// ─── Verbindung ───
|
||||
|
||||
Future<void> _verbindeCloud() async {
|
||||
final user = AuthService().benutzer;
|
||||
if (user.isNotEmpty) {
|
||||
final ok = await widget.cloud.login(user);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_verbunden = ok;
|
||||
if (!ok) _setzeStatus('Cloud-Login fehlgeschlagen', ok: false);
|
||||
});
|
||||
}
|
||||
/// Reagiert auf Status-Änderungen des CloudService: sobald verbunden,
|
||||
/// werden Serverdaten + Zähler nachgeladen.
|
||||
void _onCloudStatus() {
|
||||
if (!mounted) return;
|
||||
if (widget.cloud.istVerbunden && !_serverDatenGeladen) {
|
||||
_serverDatenGeladen = true;
|
||||
_ladeServerDaten();
|
||||
_ladeStatus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +121,7 @@ class _CloudScreenState extends State<CloudScreen> {
|
||||
}
|
||||
|
||||
Future<void> _ladeServerDaten() async {
|
||||
if (!_verbunden) return;
|
||||
if (!widget.cloud.istVerbunden) return;
|
||||
// Paralleles Laden
|
||||
await Future.wait([
|
||||
_ladePlaylists(),
|
||||
@@ -511,14 +517,11 @@ class _CloudScreenState extends State<CloudScreen> {
|
||||
// ─── Status ───
|
||||
|
||||
Future<void> _ladeStatus() async {
|
||||
final st = await widget.cloud.status();
|
||||
final st = await widget.cloud.statusDaten();
|
||||
final syncSt = await widget.cloud.syncStatus();
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_serverCount = st?['total'] ?? 0;
|
||||
_verbunden = st != null;
|
||||
_statusOk = st != null;
|
||||
_status = st != null ? 'Verbunden' : 'Keine Verbindung (Token?)';
|
||||
|
||||
if (syncSt != null) {
|
||||
final counts = syncSt['counts'];
|
||||
@@ -672,13 +675,20 @@ class _CloudScreenState extends State<CloudScreen> {
|
||||
IconButton(
|
||||
icon: const Icon(Icons.refresh, color: Colors.grey, size: 20),
|
||||
onPressed: () async {
|
||||
await widget.cloud.verbinde();
|
||||
await _ladeStatus();
|
||||
await _ladeServerDaten();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
body: _syncLaeuft ? _syncFortschrittWidget() : _contentWidget(),
|
||||
// ListenableBuilder: Status kommt live vom CloudService
|
||||
// ('Verbinde...' → 'Verbunden'/'Keine Verbindung')
|
||||
body: ListenableBuilder(
|
||||
listenable: widget.cloud,
|
||||
builder: (context, _) =>
|
||||
_syncLaeuft ? _syncFortschrittWidget() : _contentWidget(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -774,47 +784,64 @@ class _CloudScreenState extends State<CloudScreen> {
|
||||
child: CircularProgressIndicator(color: MeloTheme.rot)),
|
||||
),
|
||||
|
||||
// Status-Text
|
||||
if (_status != null && !_ladt)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 12),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: _statusOk
|
||||
? const Color(0xFF0D3B1E)
|
||||
: const Color(0xFF3B0D0D),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
_statusOk
|
||||
? Icons.check_circle
|
||||
: Icons.info_outline,
|
||||
size: 16,
|
||||
color: _statusOk
|
||||
? const Color(0xFF4CAF50)
|
||||
: const Color(0xFFEF5350),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
_status!,
|
||||
style: TextStyle(
|
||||
color: _statusOk
|
||||
? const Color(0xFFA5D6A7)
|
||||
: const Color(0xFFEF9A9A),
|
||||
fontSize: 13,
|
||||
// Status-Text: transiente Meldungen (Upload-Fortschritt, Sync-Ergebnis)
|
||||
// haben Vorrang — sonst kommt der Verbindungsstatus live vom Service
|
||||
// ('Verbinde...' → 'Verbunden' / 'Keine Verbindung')
|
||||
if (!_ladt) ...[
|
||||
Builder(builder: (context) {
|
||||
final hatTransientStatus = _status != null;
|
||||
final verbindet = widget.cloud.status == CloudStatus.verbinde;
|
||||
final statusOk =
|
||||
hatTransientStatus ? _statusOk : widget.cloud.istVerbunden;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 12),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: statusOk
|
||||
? const Color(0xFF0D3B1E)
|
||||
: verbindet
|
||||
? const Color(0xFF3B2A0D)
|
||||
: const Color(0xFF3B0D0D),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
statusOk
|
||||
? Icons.check_circle
|
||||
: verbindet
|
||||
? Icons.sync
|
||||
: Icons.info_outline,
|
||||
size: 16,
|
||||
color: statusOk
|
||||
? const Color(0xFF4CAF50)
|
||||
: verbindet
|
||||
? const Color(0xFFFFA726)
|
||||
: const Color(0xFFEF5350),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
_status ?? widget.cloud.statusText,
|
||||
style: TextStyle(
|
||||
color: statusOk
|
||||
? const Color(0xFFA5D6A7)
|
||||
: verbindet
|
||||
? const Color(0xFFFFCC80)
|
||||
: const Color(0xFFEF9A9A),
|
||||
fontSize: 13,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
|
||||
const SizedBox(height: 24),
|
||||
|
||||
@@ -947,26 +974,28 @@ class _CloudScreenState extends State<CloudScreen> {
|
||||
],
|
||||
),
|
||||
),
|
||||
// Verbindungsstatus-Indikator
|
||||
Container(
|
||||
width: 12,
|
||||
height: 12,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: _verbunden
|
||||
? const Color(0xFF4CAF50)
|
||||
: const Color(0xFFEF5350),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: (_verbunden
|
||||
? const Color(0xFF4CAF50)
|
||||
: const Color(0xFFEF5350))
|
||||
.withValues(alpha: 0.5),
|
||||
blurRadius: 8,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Verbindungsstatus-Indikator (live vom CloudService)
|
||||
Builder(builder: (context) {
|
||||
final farbe = widget.cloud.istVerbunden
|
||||
? const Color(0xFF4CAF50)
|
||||
: widget.cloud.status == CloudStatus.verbinde
|
||||
? const Color(0xFFFFA726)
|
||||
: const Color(0xFFEF5350);
|
||||
return Container(
|
||||
width: 12,
|
||||
height: 12,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: farbe,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: farbe.withValues(alpha: 0.5),
|
||||
blurRadius: 8,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user