feat(useragent): added connection info setup screen

This commit is contained in:
hdbg
2026-03-15 14:51:39 +01:00
parent 16d5b9a233
commit ec0e8a980c
25 changed files with 800 additions and 2441 deletions

View File

@@ -0,0 +1,51 @@
import 'package:arbiter/features/server_info_storage.dart';
import 'package:cryptography/cryptography.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'server_info.g.dart';
@riverpod
ServerInfoStorage serverInfoStorage(Ref ref) {
return const SecureServerInfoStorage();
}
@Riverpod(keepAlive: true)
class ServerInfo extends _$ServerInfo {
@override
Future<StoredServerInfo?> build() {
final storage = ref.watch(serverInfoStorageProvider);
return storage.load();
}
Future<void> save({
required String address,
required int port,
required List<int> caCert,
}) async {
final storage = ref.read(serverInfoStorageProvider);
final fingerprint = await _fingerprint(caCert);
final serverInfo = StoredServerInfo(
address: address,
port: port,
caCertFingerprint: fingerprint,
);
state = await AsyncValue.guard(() async {
await storage.save(serverInfo);
return serverInfo;
});
}
Future<void> clear() async {
final storage = ref.read(serverInfoStorageProvider);
state = await AsyncValue.guard(() async {
await storage.clear();
return null;
});
}
Future<String> _fingerprint(List<int> caCert) async {
final digest = await Sha256().hash(caCert);
return digest.bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join();
}
}

View File

@@ -0,0 +1,102 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'server_info.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint, type=warning
@ProviderFor(serverInfoStorage)
final serverInfoStorageProvider = ServerInfoStorageProvider._();
final class ServerInfoStorageProvider
extends
$FunctionalProvider<
ServerInfoStorage,
ServerInfoStorage,
ServerInfoStorage
>
with $Provider<ServerInfoStorage> {
ServerInfoStorageProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'serverInfoStorageProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$serverInfoStorageHash();
@$internal
@override
$ProviderElement<ServerInfoStorage> $createElement(
$ProviderPointer pointer,
) => $ProviderElement(pointer);
@override
ServerInfoStorage create(Ref ref) {
return serverInfoStorage(ref);
}
/// {@macro riverpod.override_with_value}
Override overrideWithValue(ServerInfoStorage value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<ServerInfoStorage>(value),
);
}
}
String _$serverInfoStorageHash() => r'fc06865e7314b1a2493c5de1a9347923a3d21c5c';
@ProviderFor(ServerInfo)
final serverInfoProvider = ServerInfoProvider._();
final class ServerInfoProvider
extends $AsyncNotifierProvider<ServerInfo, StoredServerInfo?> {
ServerInfoProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'serverInfoProvider',
isAutoDispose: false,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$serverInfoHash();
@$internal
@override
ServerInfo create() => ServerInfo();
}
String _$serverInfoHash() => r'6e94f52de03259695a2166b766004eec60ff45fa';
abstract class _$ServerInfo extends $AsyncNotifier<StoredServerInfo?> {
FutureOr<StoredServerInfo?> build();
@$mustCallSuper
@override
void runBuild() {
final ref =
this.ref as $Ref<AsyncValue<StoredServerInfo?>, StoredServerInfo?>;
final element =
ref.element
as $ClassProviderElement<
AnyNotifier<AsyncValue<StoredServerInfo?>, StoredServerInfo?>,
AsyncValue<StoredServerInfo?>,
Object?,
Object?
>;
element.handleCreate(ref, build);
}
}