initial commit
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'connection.freezed.dart';
|
||||
part 'connection.g.dart';
|
||||
|
||||
/// A saved NodeMaster API endpoint. Client-side only — has no server-side
|
||||
/// counterpart. `baseUrl` excludes the `/v1` suffix (added by
|
||||
/// [NodeMasterApiClient]) and any trailing slash, e.g.
|
||||
/// `https://edge-01.local:8080`.
|
||||
@freezed
|
||||
sealed class Connection with _$Connection {
|
||||
const factory Connection({
|
||||
required String id,
|
||||
required String name,
|
||||
required String baseUrl,
|
||||
}) = _Connection;
|
||||
|
||||
factory Connection.fromJson(Map<String, dynamic> json) => _$ConnectionFromJson(json);
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'connection.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$Connection {
|
||||
|
||||
String get id; String get name; String get baseUrl;
|
||||
/// Create a copy of Connection
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$ConnectionCopyWith<Connection> get copyWith => _$ConnectionCopyWithImpl<Connection>(this as Connection, _$identity);
|
||||
|
||||
/// Serializes this Connection to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is Connection&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.baseUrl, baseUrl) || other.baseUrl == baseUrl));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,name,baseUrl);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Connection(id: $id, name: $name, baseUrl: $baseUrl)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $ConnectionCopyWith<$Res> {
|
||||
factory $ConnectionCopyWith(Connection value, $Res Function(Connection) _then) = _$ConnectionCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, String name, String baseUrl
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$ConnectionCopyWithImpl<$Res>
|
||||
implements $ConnectionCopyWith<$Res> {
|
||||
_$ConnectionCopyWithImpl(this._self, this._then);
|
||||
|
||||
final Connection _self;
|
||||
final $Res Function(Connection) _then;
|
||||
|
||||
/// Create a copy of Connection
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = null,Object? baseUrl = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
as String,baseUrl: null == baseUrl ? _self.baseUrl : baseUrl // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [Connection].
|
||||
extension ConnectionPatterns on Connection {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _Connection value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _Connection() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _Connection value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _Connection():
|
||||
return $default(_that);}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _Connection value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _Connection() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String name, String baseUrl)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _Connection() when $default != null:
|
||||
return $default(_that.id,_that.name,_that.baseUrl);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String name, String baseUrl) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _Connection():
|
||||
return $default(_that.id,_that.name,_that.baseUrl);}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String name, String baseUrl)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _Connection() when $default != null:
|
||||
return $default(_that.id,_that.name,_that.baseUrl);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _Connection implements Connection {
|
||||
const _Connection({required this.id, required this.name, required this.baseUrl});
|
||||
factory _Connection.fromJson(Map<String, dynamic> json) => _$ConnectionFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@override final String name;
|
||||
@override final String baseUrl;
|
||||
|
||||
/// Create a copy of Connection
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$ConnectionCopyWith<_Connection> get copyWith => __$ConnectionCopyWithImpl<_Connection>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$ConnectionToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Connection&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.baseUrl, baseUrl) || other.baseUrl == baseUrl));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,name,baseUrl);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Connection(id: $id, name: $name, baseUrl: $baseUrl)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$ConnectionCopyWith<$Res> implements $ConnectionCopyWith<$Res> {
|
||||
factory _$ConnectionCopyWith(_Connection value, $Res Function(_Connection) _then) = __$ConnectionCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, String name, String baseUrl
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$ConnectionCopyWithImpl<$Res>
|
||||
implements _$ConnectionCopyWith<$Res> {
|
||||
__$ConnectionCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _Connection _self;
|
||||
final $Res Function(_Connection) _then;
|
||||
|
||||
/// Create a copy of Connection
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = null,Object? baseUrl = null,}) {
|
||||
return _then(_Connection(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
as String,baseUrl: null == baseUrl ? _self.baseUrl : baseUrl // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,20 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'connection.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_Connection _$ConnectionFromJson(Map<String, dynamic> json) => _Connection(
|
||||
id: json['id'] as String,
|
||||
name: json['name'] as String,
|
||||
baseUrl: json['baseUrl'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ConnectionToJson(_Connection instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'name': instance.name,
|
||||
'baseUrl': instance.baseUrl,
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
import '../utils/shared_preferences_provider.dart';
|
||||
import 'connection.dart';
|
||||
import 'connection_storage.dart';
|
||||
|
||||
part 'connection_providers.g.dart';
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
ConnectionStorage connectionStorage(Ref ref) {
|
||||
return ConnectionStorage(ref.watch(sharedPreferencesProvider));
|
||||
}
|
||||
|
||||
/// The full list of saved connections. Mutations persist immediately.
|
||||
@Riverpod(keepAlive: true)
|
||||
class SavedConnections extends _$SavedConnections {
|
||||
@override
|
||||
List<Connection> build() => ref.watch(connectionStorageProvider).readConnections();
|
||||
|
||||
Future<void> add(Connection connection) async {
|
||||
state = [...state, connection];
|
||||
await ref.read(connectionStorageProvider).writeConnections(state);
|
||||
}
|
||||
|
||||
Future<void> update(Connection connection) async {
|
||||
state = [
|
||||
for (final c in state)
|
||||
if (c.id == connection.id) connection else c,
|
||||
];
|
||||
await ref.read(connectionStorageProvider).writeConnections(state);
|
||||
}
|
||||
|
||||
Future<void> remove(String id) async {
|
||||
state = state.where((c) => c.id != id).toList(growable: false);
|
||||
await ref.read(connectionStorageProvider).writeConnections(state);
|
||||
final activeId = ref.read(activeConnectionIdProvider);
|
||||
if (activeId == id) {
|
||||
await ref.read(activeConnectionIdProvider.notifier).setActive(
|
||||
state.isEmpty ? null : state.first.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The id of the currently active connection, or null if none is selected
|
||||
/// (e.g. first launch with nothing configured yet).
|
||||
@Riverpod(keepAlive: true)
|
||||
class ActiveConnectionId extends _$ActiveConnectionId {
|
||||
@override
|
||||
String? build() {
|
||||
final stored = ref.watch(connectionStorageProvider).readActiveConnectionId();
|
||||
final connections = ref.watch(savedConnectionsProvider);
|
||||
if (stored != null && connections.any((c) => c.id == stored)) return stored;
|
||||
return connections.isEmpty ? null : connections.first.id;
|
||||
}
|
||||
|
||||
Future<void> setActive(String? id) async {
|
||||
state = id;
|
||||
await ref.read(connectionStorageProvider).writeActiveConnectionId(id);
|
||||
}
|
||||
}
|
||||
|
||||
/// The currently active [Connection], or null if none is configured.
|
||||
/// Everything in `core/network` derives from this — switching it rebuilds
|
||||
/// the API client and, transitively, every provider that watches it.
|
||||
@riverpod
|
||||
Connection? activeConnection(Ref ref) {
|
||||
final id = ref.watch(activeConnectionIdProvider);
|
||||
if (id == null) return null;
|
||||
final connections = ref.watch(savedConnectionsProvider);
|
||||
for (final c in connections) {
|
||||
if (c.id == id) return c;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'connection_providers.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint, type=warning
|
||||
|
||||
@ProviderFor(connectionStorage)
|
||||
const connectionStorageProvider = ConnectionStorageProvider._();
|
||||
|
||||
final class ConnectionStorageProvider
|
||||
extends
|
||||
$FunctionalProvider<
|
||||
ConnectionStorage,
|
||||
ConnectionStorage,
|
||||
ConnectionStorage
|
||||
>
|
||||
with $Provider<ConnectionStorage> {
|
||||
const ConnectionStorageProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'connectionStorageProvider',
|
||||
isAutoDispose: false,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$connectionStorageHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$ProviderElement<ConnectionStorage> $createElement(
|
||||
$ProviderPointer pointer,
|
||||
) => $ProviderElement(pointer);
|
||||
|
||||
@override
|
||||
ConnectionStorage create(Ref ref) {
|
||||
return connectionStorage(ref);
|
||||
}
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(ConnectionStorage value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<ConnectionStorage>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$connectionStorageHash() => r'0faf909e3978260785f2f8ce4bc41f101e27ad66';
|
||||
|
||||
/// The full list of saved connections. Mutations persist immediately.
|
||||
|
||||
@ProviderFor(SavedConnections)
|
||||
const savedConnectionsProvider = SavedConnectionsProvider._();
|
||||
|
||||
/// The full list of saved connections. Mutations persist immediately.
|
||||
final class SavedConnectionsProvider
|
||||
extends $NotifierProvider<SavedConnections, List<Connection>> {
|
||||
/// The full list of saved connections. Mutations persist immediately.
|
||||
const SavedConnectionsProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'savedConnectionsProvider',
|
||||
isAutoDispose: false,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$savedConnectionsHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
SavedConnections create() => SavedConnections();
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(List<Connection> value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<List<Connection>>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$savedConnectionsHash() => r'2595280b9ef1f5835ecce70b791a901a51aaf8e8';
|
||||
|
||||
/// The full list of saved connections. Mutations persist immediately.
|
||||
|
||||
abstract class _$SavedConnections extends $Notifier<List<Connection>> {
|
||||
List<Connection> build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final created = build();
|
||||
final ref = this.ref as $Ref<List<Connection>, List<Connection>>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<List<Connection>, List<Connection>>,
|
||||
List<Connection>,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleValue(ref, created);
|
||||
}
|
||||
}
|
||||
|
||||
/// The id of the currently active connection, or null if none is selected
|
||||
/// (e.g. first launch with nothing configured yet).
|
||||
|
||||
@ProviderFor(ActiveConnectionId)
|
||||
const activeConnectionIdProvider = ActiveConnectionIdProvider._();
|
||||
|
||||
/// The id of the currently active connection, or null if none is selected
|
||||
/// (e.g. first launch with nothing configured yet).
|
||||
final class ActiveConnectionIdProvider
|
||||
extends $NotifierProvider<ActiveConnectionId, String?> {
|
||||
/// The id of the currently active connection, or null if none is selected
|
||||
/// (e.g. first launch with nothing configured yet).
|
||||
const ActiveConnectionIdProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'activeConnectionIdProvider',
|
||||
isAutoDispose: false,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$activeConnectionIdHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
ActiveConnectionId create() => ActiveConnectionId();
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(String? value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<String?>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$activeConnectionIdHash() =>
|
||||
r'ac8b7d48bc04e6f9245b23c83a15e11a539e1fc8';
|
||||
|
||||
/// The id of the currently active connection, or null if none is selected
|
||||
/// (e.g. first launch with nothing configured yet).
|
||||
|
||||
abstract class _$ActiveConnectionId extends $Notifier<String?> {
|
||||
String? build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final created = build();
|
||||
final ref = this.ref as $Ref<String?, String?>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<String?, String?>,
|
||||
String?,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleValue(ref, created);
|
||||
}
|
||||
}
|
||||
|
||||
/// The currently active [Connection], or null if none is configured.
|
||||
/// Everything in `core/network` derives from this — switching it rebuilds
|
||||
/// the API client and, transitively, every provider that watches it.
|
||||
|
||||
@ProviderFor(activeConnection)
|
||||
const activeConnectionProvider = ActiveConnectionProvider._();
|
||||
|
||||
/// The currently active [Connection], or null if none is configured.
|
||||
/// Everything in `core/network` derives from this — switching it rebuilds
|
||||
/// the API client and, transitively, every provider that watches it.
|
||||
|
||||
final class ActiveConnectionProvider
|
||||
extends $FunctionalProvider<Connection?, Connection?, Connection?>
|
||||
with $Provider<Connection?> {
|
||||
/// The currently active [Connection], or null if none is configured.
|
||||
/// Everything in `core/network` derives from this — switching it rebuilds
|
||||
/// the API client and, transitively, every provider that watches it.
|
||||
const ActiveConnectionProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'activeConnectionProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$activeConnectionHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$ProviderElement<Connection?> $createElement($ProviderPointer pointer) =>
|
||||
$ProviderElement(pointer);
|
||||
|
||||
@override
|
||||
Connection? create(Ref ref) {
|
||||
return activeConnection(ref);
|
||||
}
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(Connection? value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<Connection?>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$activeConnectionHash() => r'544cf6f795b35636cbfc497e6379a84b1e8f5b88';
|
||||
@@ -0,0 +1,41 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'connection.dart';
|
||||
|
||||
const _connectionsKey = 'connections';
|
||||
const _activeConnectionIdKey = 'active_connection_id';
|
||||
|
||||
/// Reads/writes the saved connection list and active-connection id to
|
||||
/// [SharedPreferences] as a plain JSON-encoded array. Not a secret store —
|
||||
/// the API has no auth, so there's nothing sensitive in a saved base URL.
|
||||
class ConnectionStorage {
|
||||
const ConnectionStorage(this._prefs);
|
||||
|
||||
final SharedPreferences _prefs;
|
||||
|
||||
List<Connection> readConnections() {
|
||||
final raw = _prefs.getString(_connectionsKey);
|
||||
if (raw == null || raw.isEmpty) return const [];
|
||||
final decoded = jsonDecode(raw) as List<dynamic>;
|
||||
return decoded
|
||||
.map((e) => Connection.fromJson(e as Map<String, dynamic>))
|
||||
.toList(growable: false);
|
||||
}
|
||||
|
||||
Future<void> writeConnections(List<Connection> connections) async {
|
||||
final encoded = jsonEncode(connections.map((c) => c.toJson()).toList());
|
||||
await _prefs.setString(_connectionsKey, encoded);
|
||||
}
|
||||
|
||||
String? readActiveConnectionId() => _prefs.getString(_activeConnectionIdKey);
|
||||
|
||||
Future<void> writeActiveConnectionId(String? id) async {
|
||||
if (id == null) {
|
||||
await _prefs.remove(_activeConnectionIdKey);
|
||||
} else {
|
||||
await _prefs.setString(_activeConnectionIdKey, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user