mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
feat: Save profile defaults per device
This commit is contained in:
@@ -5,22 +5,22 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.00024">
|
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.00103">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="0.554978">
|
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="1.372199">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="2: build_app" time="100.17557">
|
<testcase classname="fastlane.lanes" name="2: build_app" time="121.394124">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="3: upload_to_app_store" time="264.49426">
|
<testcase classname="fastlane.lanes" name="3: upload_to_app_store" time="365.414242">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
@@ -29,7 +31,9 @@ import '../widgets/connection_dialog.dart';
|
|||||||
import '../utils/battery_display_helper.dart';
|
import '../utils/battery_display_helper.dart';
|
||||||
import '../services/developer_mode_service.dart';
|
import '../services/developer_mode_service.dart';
|
||||||
import '../services/mesh_map_nodes_service.dart';
|
import '../services/mesh_map_nodes_service.dart';
|
||||||
|
import '../services/profile_device_key_resolver.dart';
|
||||||
import '../services/profile_manager.dart';
|
import '../services/profile_manager.dart';
|
||||||
|
import '../services/profile_workspace_coordinator.dart';
|
||||||
import '../services/profiles_feature_service.dart';
|
import '../services/profiles_feature_service.dart';
|
||||||
|
|
||||||
enum _HomeTab { messages, contacts, sensors, map }
|
enum _HomeTab { messages, contacts, sensors, map }
|
||||||
@@ -60,6 +64,7 @@ class _HomeScreenState extends State<HomeScreen>
|
|||||||
with TickerProviderStateMixin, WidgetsBindingObserver {
|
with TickerProviderStateMixin, WidgetsBindingObserver {
|
||||||
late TabController _tabController;
|
late TabController _tabController;
|
||||||
late final AppProvider _appProvider;
|
late final AppProvider _appProvider;
|
||||||
|
late final ConnectionProvider _connectionProvider;
|
||||||
int _currentIndex = 0;
|
int _currentIndex = 0;
|
||||||
bool _isMapFullscreen = false;
|
bool _isMapFullscreen = false;
|
||||||
bool _showRxTxIndicators = true;
|
bool _showRxTxIndicators = true;
|
||||||
@@ -68,6 +73,7 @@ class _HomeScreenState extends State<HomeScreen>
|
|||||||
bool _isContactsEnabled = true;
|
bool _isContactsEnabled = true;
|
||||||
bool _isSensorsEnabled = false;
|
bool _isSensorsEnabled = false;
|
||||||
AppLifecycleState _lifecycleState = AppLifecycleState.resumed;
|
AppLifecycleState _lifecycleState = AppLifecycleState.resumed;
|
||||||
|
String? _lastProfileDeviceKey;
|
||||||
|
|
||||||
List<_HomeTab> get _enabledTabs {
|
List<_HomeTab> get _enabledTabs {
|
||||||
return [
|
return [
|
||||||
@@ -91,6 +97,8 @@ class _HomeScreenState extends State<HomeScreen>
|
|||||||
super.initState();
|
super.initState();
|
||||||
WidgetsBinding.instance.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
_appProvider = context.read<AppProvider>();
|
_appProvider = context.read<AppProvider>();
|
||||||
|
_connectionProvider = context.read<ConnectionProvider>();
|
||||||
|
_connectionProvider.addListener(_handleConnectionProviderChanged);
|
||||||
_isMapEnabled = _appProvider.isMapEnabled;
|
_isMapEnabled = _appProvider.isMapEnabled;
|
||||||
_isContactsEnabled = _appProvider.isContactsEnabled;
|
_isContactsEnabled = _appProvider.isContactsEnabled;
|
||||||
_isSensorsEnabled = _appProvider.isSensorsEnabled;
|
_isSensorsEnabled = _appProvider.isSensorsEnabled;
|
||||||
@@ -108,6 +116,10 @@ class _HomeScreenState extends State<HomeScreen>
|
|||||||
_showPermissionDialog();
|
_showPermissionDialog();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
_handleConnectionProviderChanged();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _initTabController() {
|
void _initTabController() {
|
||||||
@@ -223,6 +235,36 @@ class _HomeScreenState extends State<HomeScreen>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _handleConnectionProviderChanged() {
|
||||||
|
final deviceKey = ProfileDeviceKeyResolver.resolve(
|
||||||
|
deviceInfo: _connectionProvider.deviceInfo,
|
||||||
|
connectionMode: _connectionProvider.connectionMode,
|
||||||
|
);
|
||||||
|
if (_lastProfileDeviceKey == deviceKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_lastProfileDeviceKey = deviceKey;
|
||||||
|
if (deviceKey == null || !mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unawaited(
|
||||||
|
context
|
||||||
|
.read<ProfileWorkspaceCoordinator>()
|
||||||
|
.syncActiveProfileForCurrentDevice(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_connectionProvider.removeListener(_handleConnectionProviderChanged);
|
||||||
|
WidgetsBinding.instance.removeObserver(this);
|
||||||
|
_appProvider.setFastLocationUiActive(false);
|
||||||
|
_appProvider.removeListener(_handleAppProviderChanged);
|
||||||
|
_tabController.removeListener(_onTabChanged);
|
||||||
|
_tabController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
void _openLiveTraffic(ConnectionProvider provider) {
|
void _openLiveTraffic(ConnectionProvider provider) {
|
||||||
openLiveTrafficScreen(context, provider);
|
openLiveTrafficScreen(context, provider);
|
||||||
}
|
}
|
||||||
@@ -257,16 +299,6 @@ class _HomeScreenState extends State<HomeScreen>
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
WidgetsBinding.instance.removeObserver(this);
|
|
||||||
_appProvider.setFastLocationUiActive(false);
|
|
||||||
_appProvider.removeListener(_handleAppProviderChanged);
|
|
||||||
_tabController.removeListener(_onTabChanged);
|
|
||||||
_tabController.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _showPermissionDialog() {
|
void _showPermissionDialog() {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
|
||||||
@@ -402,10 +434,7 @@ class _HomeScreenState extends State<HomeScreen>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildMiniSignalBars({
|
Widget _buildMiniSignalBars({required int activeBars, required Color color}) {
|
||||||
required int activeBars,
|
|
||||||
required Color color,
|
|
||||||
}) {
|
|
||||||
final inactive = Colors.grey.withValues(alpha: 0.3);
|
final inactive = Colors.grey.withValues(alpha: 0.3);
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -1033,7 +1062,8 @@ class _HomeScreenState extends State<HomeScreen>
|
|||||||
deviceInfo.signalRssi != null) ...[
|
deviceInfo.signalRssi != null) ...[
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
_buildMiniSignalBars(
|
_buildMiniSignalBars(
|
||||||
activeBars: BatteryDisplayHelper.getSignalBars(
|
activeBars:
|
||||||
|
BatteryDisplayHelper.getSignalBars(
|
||||||
deviceInfo.signalRssi!,
|
deviceInfo.signalRssi!,
|
||||||
),
|
),
|
||||||
color: signalColor,
|
color: signalColor,
|
||||||
|
|||||||
29
lib/services/profile_device_key_resolver.dart
Normal file
29
lib/services/profile_device_key_resolver.dart
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import '../models/device_info.dart';
|
||||||
|
|
||||||
|
class ProfileDeviceKeyResolver {
|
||||||
|
static String? resolve({
|
||||||
|
required DeviceInfo deviceInfo,
|
||||||
|
required ConnectionMode connectionMode,
|
||||||
|
}) {
|
||||||
|
final publicKey = deviceInfo.publicKey;
|
||||||
|
if (publicKey != null && publicKey.isNotEmpty) {
|
||||||
|
final hex = publicKey
|
||||||
|
.map((byte) => byte.toRadixString(16).padLeft(2, '0'))
|
||||||
|
.join();
|
||||||
|
if (hex.isNotEmpty) {
|
||||||
|
return 'pk:$hex';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final deviceId = deviceInfo.deviceId?.trim();
|
||||||
|
if (deviceId == null || deviceId.isEmpty) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connectionMode == ConnectionMode.usb && deviceId == 'usb') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'id:$deviceId';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,11 +9,14 @@ import 'profiles_feature_service.dart';
|
|||||||
class ProfileManager with ChangeNotifier {
|
class ProfileManager with ChangeNotifier {
|
||||||
static const String _profilesKey = 'profiles_library';
|
static const String _profilesKey = 'profiles_library';
|
||||||
static const String activeProfileIdKey = 'profiles_active_profile_id';
|
static const String activeProfileIdKey = 'profiles_active_profile_id';
|
||||||
|
static const String _deviceProfileDefaultsKey =
|
||||||
|
'profiles_device_active_profile_ids';
|
||||||
static const String _transferHistoryKey = 'profiles_transfer_history';
|
static const String _transferHistoryKey = 'profiles_transfer_history';
|
||||||
|
|
||||||
final List<ConfigProfile> _customProfiles = <ConfigProfile>[];
|
final List<ConfigProfile> _customProfiles = <ConfigProfile>[];
|
||||||
final List<ProfileTransferRecord> _transferHistory =
|
final List<ProfileTransferRecord> _transferHistory =
|
||||||
<ProfileTransferRecord>[];
|
<ProfileTransferRecord>[];
|
||||||
|
final Map<String, String> _deviceProfileDefaults = <String, String>{};
|
||||||
bool _isInitialized = false;
|
bool _isInitialized = false;
|
||||||
bool _profilesEnabled = false;
|
bool _profilesEnabled = false;
|
||||||
String _activeProfileId = ConfigProfile.defaultProfileId;
|
String _activeProfileId = ConfigProfile.defaultProfileId;
|
||||||
@@ -37,6 +40,19 @@ class ProfileManager with ChangeNotifier {
|
|||||||
_activeProfileId =
|
_activeProfileId =
|
||||||
prefs.getString(activeProfileIdKey) ?? ConfigProfile.defaultProfileId;
|
prefs.getString(activeProfileIdKey) ?? ConfigProfile.defaultProfileId;
|
||||||
|
|
||||||
|
final deviceDefaultsJson = prefs.getString(_deviceProfileDefaultsKey);
|
||||||
|
if (deviceDefaultsJson != null && deviceDefaultsJson.isNotEmpty) {
|
||||||
|
final decoded = jsonDecode(deviceDefaultsJson);
|
||||||
|
if (decoded is Map<String, dynamic>) {
|
||||||
|
_deviceProfileDefaults
|
||||||
|
..clear()
|
||||||
|
..addAll(
|
||||||
|
decoded.map((key, value) => MapEntry(key, value?.toString() ?? ''))
|
||||||
|
..removeWhere((key, value) => value.isEmpty),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final profilesJson = prefs.getString(_profilesKey);
|
final profilesJson = prefs.getString(_profilesKey);
|
||||||
if (profilesJson != null && profilesJson.isNotEmpty) {
|
if (profilesJson != null && profilesJson.isNotEmpty) {
|
||||||
final decoded = jsonDecode(profilesJson) as List<dynamic>;
|
final decoded = jsonDecode(profilesJson) as List<dynamic>;
|
||||||
@@ -90,9 +106,30 @@ class ProfileManager with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> setActiveProfileId(String id) async {
|
Future<void> setActiveProfileId(String id) async {
|
||||||
|
await setActiveProfileIdForDevice(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
String profileIdForDevice(String? deviceKey) {
|
||||||
|
if (deviceKey == null || deviceKey.isEmpty) {
|
||||||
|
return _activeProfileId;
|
||||||
|
}
|
||||||
|
return _deviceProfileDefaults[deviceKey] ?? ConfigProfile.defaultProfileId;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setActiveProfileIdForDevice(
|
||||||
|
String id, {
|
||||||
|
String? deviceKey,
|
||||||
|
}) async {
|
||||||
_activeProfileId = id;
|
_activeProfileId = id;
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
await prefs.setString(activeProfileIdKey, id);
|
await prefs.setString(activeProfileIdKey, id);
|
||||||
|
if (deviceKey != null && deviceKey.isNotEmpty) {
|
||||||
|
_deviceProfileDefaults[deviceKey] = id;
|
||||||
|
await prefs.setString(
|
||||||
|
_deviceProfileDefaultsKey,
|
||||||
|
jsonEncode(_deviceProfileDefaults),
|
||||||
|
);
|
||||||
|
}
|
||||||
ProfileStorageScope.setScope(
|
ProfileStorageScope.setScope(
|
||||||
profilesEnabled: _profilesEnabled,
|
profilesEnabled: _profilesEnabled,
|
||||||
activeProfileId: _activeProfileId,
|
activeProfileId: _activeProfileId,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import 'contact_storage_service.dart';
|
|||||||
import 'device_config_applicator.dart';
|
import 'device_config_applicator.dart';
|
||||||
import 'message_storage_service.dart';
|
import 'message_storage_service.dart';
|
||||||
import 'profile_manager.dart';
|
import 'profile_manager.dart';
|
||||||
|
import 'profile_device_key_resolver.dart';
|
||||||
import 'profiles_feature_service.dart';
|
import 'profiles_feature_service.dart';
|
||||||
import 'map_workspace_snapshot_service.dart';
|
import 'map_workspace_snapshot_service.dart';
|
||||||
|
|
||||||
@@ -63,6 +64,7 @@ class ProfileWorkspaceCoordinator {
|
|||||||
final DeviceConfigApplicator _deviceConfigApplicator;
|
final DeviceConfigApplicator _deviceConfigApplicator;
|
||||||
final MessageStorageService _messageStorageService;
|
final MessageStorageService _messageStorageService;
|
||||||
final ContactStorageService _contactStorageService;
|
final ContactStorageService _contactStorageService;
|
||||||
|
bool _isSyncingDeviceProfile = false;
|
||||||
|
|
||||||
Future<void> setProfilesEnabled(bool enabled) async {
|
Future<void> setProfilesEnabled(bool enabled) async {
|
||||||
final wasEnabled = profileManager.profilesEnabled;
|
final wasEnabled = profileManager.profilesEnabled;
|
||||||
@@ -77,6 +79,14 @@ class ProfileWorkspaceCoordinator {
|
|||||||
activeProfileId: enabled ? profileManager.activeProfileId : 'default',
|
activeProfileId: enabled ? profileManager.activeProfileId : 'default',
|
||||||
);
|
);
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
|
final deviceKey = _currentDeviceProfileKey;
|
||||||
|
final targetProfileId = profileManager.profileIdForDevice(deviceKey);
|
||||||
|
if (targetProfileId != profileManager.activeProfileId) {
|
||||||
|
await profileManager.setActiveProfileIdForDevice(
|
||||||
|
targetProfileId,
|
||||||
|
deviceKey: deviceKey,
|
||||||
|
);
|
||||||
|
}
|
||||||
if (wasEnabled) {
|
if (wasEnabled) {
|
||||||
await openProfile(profileManager.activeProfileId);
|
await openProfile(profileManager.activeProfileId);
|
||||||
} else {
|
} else {
|
||||||
@@ -181,9 +191,13 @@ class ProfileWorkspaceCoordinator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> openProfile(String profileId) async {
|
Future<void> openProfile(String profileId) async {
|
||||||
|
final deviceKey = _currentDeviceProfileKey;
|
||||||
await _saveActiveCustomProfileSnapshot();
|
await _saveActiveCustomProfileSnapshot();
|
||||||
await connectionProvider.disconnect();
|
await connectionProvider.disconnect();
|
||||||
await profileManager.setActiveProfileId(profileId);
|
await profileManager.setActiveProfileIdForDevice(
|
||||||
|
profileId,
|
||||||
|
deviceKey: deviceKey,
|
||||||
|
);
|
||||||
await _switchRuntimeScope(profileId);
|
await _switchRuntimeScope(profileId);
|
||||||
|
|
||||||
final profile = await resolveProfile(profileId);
|
final profile = await resolveProfile(profileId);
|
||||||
@@ -271,6 +285,49 @@ class ProfileWorkspaceCoordinator {
|
|||||||
return imported;
|
return imported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> syncActiveProfileForCurrentDevice() async {
|
||||||
|
if (!profileManager.profilesEnabled || _isSyncingDeviceProfile) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final deviceKey = _currentDeviceProfileKey;
|
||||||
|
if (deviceKey == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final targetProfileId = profileManager.profileIdForDevice(deviceKey);
|
||||||
|
if (targetProfileId == profileManager.activeProfileId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isSyncingDeviceProfile = true;
|
||||||
|
try {
|
||||||
|
await _persistCurrentState();
|
||||||
|
await profileManager.setActiveProfileIdForDevice(
|
||||||
|
targetProfileId,
|
||||||
|
deviceKey: deviceKey,
|
||||||
|
);
|
||||||
|
await _switchRuntimeScope(targetProfileId);
|
||||||
|
|
||||||
|
final profile = await resolveProfile(targetProfileId);
|
||||||
|
await _appConfigSnapshotService.apply(
|
||||||
|
profile.sections.appSettings,
|
||||||
|
appProvider,
|
||||||
|
);
|
||||||
|
await _mapWorkspaceSnapshotService.apply(
|
||||||
|
profile.sections.mapWorkspace,
|
||||||
|
mapProvider: mapProvider,
|
||||||
|
drawingProvider: drawingProvider,
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
_isSyncingDeviceProfile = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String? get _currentDeviceProfileKey => ProfileDeviceKeyResolver.resolve(
|
||||||
|
deviceInfo: connectionProvider.deviceInfo,
|
||||||
|
connectionMode: connectionProvider.connectionMode,
|
||||||
|
);
|
||||||
|
|
||||||
Future<void> _switchRuntimeScope(String profileId) async {
|
Future<void> _switchRuntimeScope(String profileId) async {
|
||||||
final runtimeProfilesEnabled = profileManager.profilesEnabled;
|
final runtimeProfilesEnabled = profileManager.profilesEnabled;
|
||||||
ProfileStorageScope.setScope(
|
ProfileStorageScope.setScope(
|
||||||
|
|||||||
@@ -82,5 +82,42 @@ void main() {
|
|||||||
expect(reloaded.activeProfileId, profile.id);
|
expect(reloaded.activeProfileId, profile.id);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test('stores per-device default profiles independently', () async {
|
||||||
|
final manager = ProfileManager();
|
||||||
|
await manager.initialize();
|
||||||
|
await manager.setProfilesEnabled(true);
|
||||||
|
|
||||||
|
final profile = ConfigProfile(
|
||||||
|
id: 'profile-alpha',
|
||||||
|
name: 'Alpha',
|
||||||
|
createdAt: DateTime.parse('2026-03-16T12:00:00Z'),
|
||||||
|
updatedAt: DateTime.parse('2026-03-16T12:00:00Z'),
|
||||||
|
sections: const ConfigProfileSections(),
|
||||||
|
);
|
||||||
|
|
||||||
|
await manager.upsertProfile(profile);
|
||||||
|
await manager.setActiveProfileIdForDevice(
|
||||||
|
profile.id,
|
||||||
|
deviceKey: 'pk:device-a',
|
||||||
|
);
|
||||||
|
await manager.setActiveProfileIdForDevice(
|
||||||
|
ConfigProfile.defaultProfileId,
|
||||||
|
deviceKey: 'pk:device-b',
|
||||||
|
);
|
||||||
|
|
||||||
|
final reloaded = ProfileManager();
|
||||||
|
await reloaded.initialize();
|
||||||
|
|
||||||
|
expect(reloaded.profileIdForDevice('pk:device-a'), profile.id);
|
||||||
|
expect(
|
||||||
|
reloaded.profileIdForDevice('pk:device-b'),
|
||||||
|
ConfigProfile.defaultProfileId,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
reloaded.profileIdForDevice('pk:device-c'),
|
||||||
|
ConfigProfile.defaultProfileId,
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,6 +184,39 @@ void main() {
|
|||||||
expect(manager.activeProfileId, target.id);
|
expect(manager.activeProfileId, target.id);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test('syncActiveProfileForCurrentDevice uses per-device default', () async {
|
||||||
|
final manager = ProfileManager();
|
||||||
|
await manager.initialize();
|
||||||
|
await manager.setProfilesEnabled(true);
|
||||||
|
|
||||||
|
final alpha = ConfigProfile(
|
||||||
|
id: 'profile-alpha',
|
||||||
|
name: 'Alpha',
|
||||||
|
createdAt: DateTime.parse('2026-03-16T12:00:00Z'),
|
||||||
|
updatedAt: DateTime.parse('2026-03-16T12:00:00Z'),
|
||||||
|
sections: const ConfigProfileSections(),
|
||||||
|
);
|
||||||
|
await manager.upsertProfile(alpha);
|
||||||
|
await manager.setActiveProfileIdForDevice(
|
||||||
|
alpha.id,
|
||||||
|
deviceKey: 'pk:01020304',
|
||||||
|
);
|
||||||
|
await manager.setActiveProfileId(ConfigProfile.defaultProfileId);
|
||||||
|
|
||||||
|
final connectionProvider = _FakeConnectionProvider(
|
||||||
|
deviceInfo: DeviceInfo(publicKey: Uint8List.fromList([1, 2, 3, 4])),
|
||||||
|
);
|
||||||
|
final coordinator = _buildCoordinator(
|
||||||
|
profileManager: manager,
|
||||||
|
connectionProvider: connectionProvider,
|
||||||
|
);
|
||||||
|
|
||||||
|
await coordinator.syncActiveProfileForCurrentDevice();
|
||||||
|
|
||||||
|
expect(manager.activeProfileId, alpha.id);
|
||||||
|
expect(connectionProvider.disconnectCallCount, 0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,10 +298,18 @@ class _FakeDeviceConfigApplicator extends DeviceConfigApplicator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _FakeConnectionProvider implements ConnectionProvider {
|
class _FakeConnectionProvider implements ConnectionProvider {
|
||||||
|
_FakeConnectionProvider({
|
||||||
|
DeviceInfo? deviceInfo,
|
||||||
|
this.connectionMode = ConnectionMode.ble,
|
||||||
|
}) : deviceInfo = deviceInfo ?? DeviceInfo();
|
||||||
|
|
||||||
int disconnectCallCount = 0;
|
int disconnectCallCount = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
DeviceInfo get deviceInfo => DeviceInfo();
|
final DeviceInfo deviceInfo;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final ConnectionMode connectionMode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> disconnect() async {
|
Future<void> disconnect() async {
|
||||||
|
|||||||
Reference in New Issue
Block a user