Files
2026-07-14 11:11:36 +08:00

158 lines
3.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../core/contracts/server.dart';
import '../../providers/di_providers.dart';
import '../../providers/server_provider.dart';
import '../../providers/session_provider.dart';
import 'adaptive_modal.dart';
import 'connection_form.dart';
class EditingServer {
final String id;
final String baseUrl;
final String? userName;
final String? password;
final String? displayName;
final String iconUrl;
const EditingServer({
required this.id,
required this.baseUrl,
this.userName,
this.password,
this.displayName,
this.iconUrl = '',
});
factory EditingServer.fromServer(EmbyServer s) => EditingServer(
id: s.id,
baseUrl: s.baseUrl,
displayName: s.name,
iconUrl: s.iconUrl,
);
}
class _AddServerDialogContent extends ConsumerStatefulWidget {
final EditingServer? editingServer;
const _AddServerDialogContent({this.editingServer});
@override
ConsumerState<_AddServerDialogContent> createState() =>
_AddServerDialogContentState();
}
class _AddServerDialogContentState
extends ConsumerState<_AddServerDialogContent> {
bool _loading = false;
String? _error;
bool get _isEdit => widget.editingServer != null;
Future<void> _handleConnect(
String url,
String username,
String password,
String? displayName,
String iconUrl,
) async {
setState(() {
_loading = true;
_error = null;
});
try {
final probeUc = await ref.read(probeServerUseCaseProvider.future);
final probeResult = await probeUc.execute(
EmbyServerProbeReq(baseUrl: url),
);
final gw = await ref.read(embyGatewayProvider.future);
await gw.authenticateByName(
baseUrl: url,
username: username,
password: password,
);
final name = (displayName != null && displayName.isNotEmpty)
? displayName
: probeResult.serverName;
final server = await ref
.read(serverListProvider.notifier)
.save(
EmbyServerSaveReq(
id: widget.editingServer?.id,
name: name,
baseUrl: url,
iconUrl: iconUrl,
),
);
if (_isEdit) {
await ref.read(sessionProvider.notifier).logout(serverId: server.id);
}
await ref
.read(sessionProvider.notifier)
.login(serverId: server.id, username: username, password: password);
if (!mounted) return;
Navigator.of(context).pop(server);
} catch (e) {
if (mounted) setState(() => _error = e.toString());
} finally {
if (mounted) setState(() => _loading = false);
}
}
void _handleClose() {
if (_loading) return;
Navigator.of(context).pop();
}
@override
Widget build(BuildContext context) {
final editing = widget.editingServer;
return PopScope(
canPop: !_loading,
child: SingleChildScrollView(
padding: const EdgeInsets.fromLTRB(24, 20, 24, 24),
child: ConnectionForm(
mode: _isEdit ? 'edit' : 'add',
initialUrl: editing?.baseUrl,
initialUsername: editing?.userName,
initialPassword: editing?.password,
initialDisplayName: editing?.displayName,
initialIconUrl: editing?.iconUrl ?? '',
onConnect: _handleConnect,
onCancel: _handleClose,
loading: _loading,
error: _error,
),
),
);
}
}
Future<EmbyServer?> showAddServerModal(
BuildContext context, {
EmbyServer? initial,
EditingServer? editingServer,
}) async {
final target =
editingServer ??
(initial != null ? EditingServer.fromServer(initial) : null);
return showAdaptiveModal<EmbyServer>(
context: context,
maxWidth: 520,
compactMaxHeightFactor: 0.92,
builder: (_) => _AddServerDialogContent(editingServer: target),
);
}