138 lines
4.4 KiB
Dart
138 lines
4.4 KiB
Dart
import 'package:flutter/foundation.dart';
|
|
|
|
import 'dart:convert';
|
|
|
|
import '../models/app_models.dart';
|
|
import 'runtime_models_connection.dart';
|
|
|
|
const int appUiStateSchemaVersion = 2;
|
|
|
|
class AppUiState {
|
|
const AppUiState({
|
|
required this.schemaVersion,
|
|
required this.assistantLastSessionKey,
|
|
required this.assistantNavigationDestinations,
|
|
required this.savedGatewayTargets,
|
|
});
|
|
|
|
final int schemaVersion;
|
|
final String assistantLastSessionKey;
|
|
final List<AssistantFocusEntry> assistantNavigationDestinations;
|
|
final List<String> savedGatewayTargets;
|
|
|
|
factory AppUiState.defaults() {
|
|
return const AppUiState(
|
|
schemaVersion: appUiStateSchemaVersion,
|
|
assistantLastSessionKey: '',
|
|
assistantNavigationDestinations: kAssistantNavigationDestinationDefaults,
|
|
savedGatewayTargets: <String>[],
|
|
);
|
|
}
|
|
|
|
AppUiState copyWith({
|
|
int? schemaVersion,
|
|
String? assistantLastSessionKey,
|
|
List<AssistantFocusEntry>? assistantNavigationDestinations,
|
|
List<String>? savedGatewayTargets,
|
|
}) {
|
|
return AppUiState(
|
|
schemaVersion: schemaVersion ?? this.schemaVersion,
|
|
assistantLastSessionKey:
|
|
assistantLastSessionKey ?? this.assistantLastSessionKey,
|
|
assistantNavigationDestinations:
|
|
assistantNavigationDestinations ??
|
|
this.assistantNavigationDestinations,
|
|
savedGatewayTargets: normalizeSavedGatewayTargets(
|
|
savedGatewayTargets ?? this.savedGatewayTargets,
|
|
),
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toJson() {
|
|
return <String, dynamic>{
|
|
'schemaVersion': schemaVersion,
|
|
'assistantLastSessionKey': assistantLastSessionKey,
|
|
'assistantNavigationDestinations': assistantNavigationDestinations
|
|
.map((item) => item.name)
|
|
.toList(growable: false),
|
|
'savedGatewayTargets': savedGatewayTargets,
|
|
};
|
|
}
|
|
|
|
factory AppUiState.fromJson(Map<String, dynamic> json) {
|
|
final parsedSchemaVersion = (json['schemaVersion'] as num?)?.toInt() ?? -1;
|
|
if (parsedSchemaVersion != appUiStateSchemaVersion) {
|
|
throw const FormatException('Unsupported app ui state schema version.');
|
|
}
|
|
final rawAssistantNavigationDestinations =
|
|
json['assistantNavigationDestinations'];
|
|
final assistantNavigationDestinations =
|
|
rawAssistantNavigationDestinations is List
|
|
? normalizeAssistantNavigationDestinations(
|
|
rawAssistantNavigationDestinations
|
|
.map(
|
|
(item) =>
|
|
AssistantFocusEntryCopy.fromJsonValue(item?.toString()),
|
|
)
|
|
.whereType<AssistantFocusEntry>(),
|
|
)
|
|
: kAssistantNavigationDestinationDefaults;
|
|
return AppUiState(
|
|
schemaVersion: parsedSchemaVersion,
|
|
assistantLastSessionKey: json['assistantLastSessionKey'] as String? ?? '',
|
|
assistantNavigationDestinations: assistantNavigationDestinations,
|
|
savedGatewayTargets: normalizeSavedGatewayTargets(
|
|
(json['savedGatewayTargets'] as List? ?? const <Object>[]).map(
|
|
(item) => item?.toString() ?? '',
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
static AppUiState fromJsonString(String? raw) {
|
|
if (raw == null || raw.trim().isEmpty) {
|
|
return AppUiState.defaults();
|
|
}
|
|
try {
|
|
final decoded = jsonDecode(raw);
|
|
if (decoded is! Map<String, dynamic>) {
|
|
return AppUiState.defaults();
|
|
}
|
|
return AppUiState.fromJson(decoded);
|
|
} catch (e, stackTrace) { debugPrint('Error: $e\n$stackTrace');
|
|
return AppUiState.defaults();
|
|
}
|
|
}
|
|
|
|
String toJsonString() => jsonEncode(toJson());
|
|
|
|
bool isGatewayTargetSaved(AssistantExecutionTarget target) {
|
|
const targetKey = 'gateway';
|
|
return targetKey.isNotEmpty && savedGatewayTargets.contains(targetKey);
|
|
}
|
|
|
|
AppUiState markGatewayTargetSaved(AssistantExecutionTarget target) {
|
|
const targetKey = 'gateway';
|
|
if (targetKey.isEmpty || savedGatewayTargets.contains(targetKey)) {
|
|
return this;
|
|
}
|
|
return copyWith(
|
|
savedGatewayTargets: <String>[...savedGatewayTargets, targetKey],
|
|
);
|
|
}
|
|
}
|
|
|
|
List<String> normalizeSavedGatewayTargets(Iterable<String> rawTargets) {
|
|
final normalized = <String>[];
|
|
final seen = <String>{};
|
|
for (final item in rawTargets) {
|
|
final normalizedTarget = item.trim().toLowerCase();
|
|
if (normalizedTarget != 'gateway' ||
|
|
!seen.add(normalizedTarget)) {
|
|
continue;
|
|
}
|
|
normalized.add(normalizedTarget);
|
|
}
|
|
return List<String>.unmodifiable(normalized);
|
|
}
|