Auto-Anmeldung: doppelten Login-Request beim App-Start verhindert (Race durch IndexedStack)

Betraf alle drei Nutzer (Dustin, Baka, Tinker), nicht nur einen: IndexedStack
baut Download-Tab und YT-Suche beim App-Start gleichzeitig, beide loesen
unabhaengig voneinander autoAnmelden() aus. Ohne In-Flight-Absicherung gingen
zwei fast-gleichzeitige Login-Requests an denselben Server, von denen einer
abgelehnt wurde - obwohl die Zugangsdaten korrekt waren.

- BakaAuth.autoAnmelden() haengt einen ueberlappenden Aufruf jetzt an den
  bereits laufenden Login-Versuch an, statt einen zweiten Request zu senden.
- Anmelde-Dialog im Download-Tab zeigt den tatsaechlich bekannten
  Navidrome-Benutzernamen statt immer "Baka" vorauszufuellen.
- Navidrome-Dialog in den Einstellungen waehlt den zuletzt bekannten
  Benutzer vor statt immer "Baka".
This commit is contained in:
Hermes (Server)
2026-08-29 11:31:28 +02:00
parent 2cabe36a6c
commit 609ca37ede
5 changed files with 67 additions and 5 deletions
+8 -3
View File
@@ -679,9 +679,10 @@ class _YouTubeBereichState extends State<_YouTubeBereich> {
}
Future<void> _anmelden() async {
final nav = context.read<DownloadService>().navidrome;
await showDialog(
context: context,
builder: (_) => const _AnmeldeDialog(),
builder: (_) => _AnmeldeDialog(benutzer: nav.benutzer),
);
}
@@ -869,14 +870,18 @@ class _YouTubeBereichState extends State<_YouTubeBereich> {
/// Fragt Benutzername und Passwort ab und gibt beides zurück.
class _AnmeldeDialog extends StatefulWidget {
const _AnmeldeDialog();
const _AnmeldeDialog({this.benutzer = ''});
/// Bereits bekannter Navidrome-Benutzername (leer, falls keiner bekannt) —
/// vorausgefüllt statt immer "Baka" zu zeigen, egal wer die App nutzt.
final String benutzer;
@override
State<_AnmeldeDialog> createState() => _AnmeldeDialogState();
}
class _AnmeldeDialogState extends State<_AnmeldeDialog> {
final _benutzer = TextEditingController(text: 'Baka');
late final _benutzer = TextEditingController(text: widget.benutzer);
final _passwort = TextEditingController();
bool _sichtbar = false;
bool _verbindet = false;
+9 -1
View File
@@ -48,6 +48,12 @@ class BakaAuth extends ChangeNotifier {
String? _token;
String _benutzer = '';
/// Laufender Login-Versuch aus [autoAnmelden] — solange er offen ist,
/// hängt sich ein überlappender Aufruf daran statt einen zweiten
/// Request loszuschicken (Race Condition: mehrere Tabs im IndexedStack
/// lösen beim App-Start gleichzeitig autoAnmelden aus).
Future<void>? _laufenderAutoLogin;
bool get istAngemeldet => _token != null && _token!.isNotEmpty;
String get benutzer => _benutzer;
@@ -108,7 +114,9 @@ class BakaAuth extends ChangeNotifier {
/// authentifizierten Aufruf ohnehin automatisch.
Future<void> autoAnmelden(String benutzer, String passwort) async {
if (istAngemeldet || benutzer.isEmpty || passwort.isEmpty) return;
await anmelden(benutzer, passwort);
_laufenderAutoLogin ??= anmelden(benutzer, passwort)
.whenComplete(() => _laufenderAutoLogin = null);
await _laufenderAutoLogin;
}
Future<void> abmelden() async {
+6 -1
View File
@@ -346,7 +346,12 @@ class _SettingsScreenState extends State<SettingsScreen> {
void _zeigeNavidromeDialog() {
final urlCtrl = TextEditingController(text: 'https://musik.baka-net.de');
final passCtrl = TextEditingController();
String selectedUser = 'Baka';
// Vorauswahl: der zuletzt bekannte Navidrome-Benutzer, falls er einer
// der drei Server-User ist — sonst Fallback "Baka".
const bekannteBenutzer = ['Baka', 'Tinker', 'Dustin'];
String selectedUser = bekannteBenutzer.contains(_navidrome.benutzer)
? _navidrome.benutzer
: 'Baka';
bool verbindet = false;
bool obscure = true;
String? fehler;