修复切换设备每次 都选中在第一个
This commit is contained in:
@@ -23,12 +23,11 @@ class AuthCubit extends Cubit<AuthState> {
|
||||
final TcpClient tcp;
|
||||
final AppUserCubit appCubit;
|
||||
final NetMessageDispatcher dispatcher;
|
||||
final AuthTcpDatasource _authTcpDatasource;
|
||||
final AuthTcpDatasource _authTcpDatasource;
|
||||
|
||||
StreamSubscription? _kickOutSub; // 新增:用于管理监听生命周期
|
||||
|
||||
AuthCubit(this.storage, this.tcp, this.appCubit, this.dispatcher, this._authTcpDatasource)
|
||||
: super(AuthInitial()) {
|
||||
AuthCubit(this.storage, this.tcp, this.appCubit, this.dispatcher, this._authTcpDatasource) : super(AuthInitial()) {
|
||||
// Cubit 一启动就开始监听 TCP 的“自动逻辑”
|
||||
_listenToAuthResponse();
|
||||
}
|
||||
@@ -53,7 +52,7 @@ class AuthCubit extends Cubit<AuthState> {
|
||||
Future<void> loginSuccess(UserEntity user) async {
|
||||
await storage.saveUser(user);
|
||||
await tcp.connect(host: TCPConsts.TCP_IP, port: TCPConsts.TCP_PORT);
|
||||
await _authTcpDatasource.sendAuthPacket();//包括发送认证包和获取列表和切换函数
|
||||
await _authTcpDatasource.sendAuthPacket(); //包括发送认证包和获取列表和切换函数
|
||||
tcp.startHeartbeat(interval: const Duration(seconds: 4)); //启动心跳
|
||||
appCubit.setAuth(user);
|
||||
emit(AuthAuthenticated(user));
|
||||
@@ -75,7 +74,7 @@ class AuthCubit extends Cubit<AuthState> {
|
||||
// 假设 0x12 是踢下线或多设备登录提醒
|
||||
_kickOutSub = dispatcher.onJsonMessage(0x12).listen((json) {
|
||||
// 如果后端发来指令确认需要退出
|
||||
// print('>>> [AUTH] 收到 0x12: $json'); //
|
||||
// print('>>> [AUTH] 收到 0x12: $json'); //
|
||||
logout();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -45,7 +45,8 @@ class DevicesCubit extends Cubit<DevicesState> {
|
||||
this._selectWorkRecordUseCase,
|
||||
this._saveWorkRecordUseCase,
|
||||
this._generatePathUseCase,
|
||||
this._routePlanningUseCase, this._bindDeviceUseCase
|
||||
this._routePlanningUseCase,
|
||||
this._bindDeviceUseCase,
|
||||
) : super(const DevicesState());
|
||||
|
||||
Future<void> unbindDevice(String deviceId, String deviceName) async {
|
||||
@@ -126,24 +127,42 @@ class DevicesCubit extends Cubit<DevicesState> {
|
||||
}
|
||||
}
|
||||
|
||||
// 获取所有设备列表
|
||||
// 获取所有设备列表
|
||||
Future<void> fetchAllDevices(String username) async {
|
||||
emit(state.copyWith(isLoading: true));
|
||||
|
||||
try {
|
||||
// 网络请求获取列表
|
||||
// 🔥 关键步骤1:记录刷新前的选中设备标识(用 deviceName 作为唯一标识)
|
||||
final String? oldSelectedDeviceName = state.selectedDevice?.deviceName;
|
||||
|
||||
// 网络请求获取新列表
|
||||
var resultEither = await _getUserDeviceUseCase.call(GetUserDeviceParams(username));
|
||||
|
||||
resultEither.fold(
|
||||
(failure) => emit(
|
||||
resultEither.fold((failure) => emit(state.copyWith(isLoading: false, errorMessage: failure.message)), (deviceList) {
|
||||
// 🔥 关键步骤2:匹配新列表中对应的旧选中设备
|
||||
DeviceEntity? newSelectedDevice;
|
||||
if (oldSelectedDeviceName != null && deviceList.isNotEmpty) {
|
||||
// 在新列表中查找和旧选中设备名称一致的设备
|
||||
newSelectedDevice = deviceList.firstWhere(
|
||||
(device) => device.deviceName == oldSelectedDeviceName,
|
||||
// 如果找不到(如设备已解绑),返回 null
|
||||
orElse: () => deviceList.first, // 兜底:选中第一个
|
||||
);
|
||||
} else {
|
||||
// 无旧选中设备,默认选中第一个
|
||||
newSelectedDevice = deviceList.isNotEmpty ? deviceList.first : null;
|
||||
}
|
||||
|
||||
// 🔥 关键步骤3:更新状态,使用匹配后的选中设备
|
||||
emit(
|
||||
state.copyWith(
|
||||
devices: deviceList,
|
||||
selectedDevice: newSelectedDevice, // 保留旧选中设备
|
||||
isLoading: false,
|
||||
errorMessage: failure.message, //
|
||||
),
|
||||
),
|
||||
(deviceList) {
|
||||
emit(state.copyWith(devices: deviceList, selectedDevice: deviceList.isNotEmpty ? deviceList.first : null, isLoading: false));
|
||||
},
|
||||
);
|
||||
);
|
||||
});
|
||||
} catch (e) {
|
||||
emit(state.copyWith(isLoading: false, errorMessage: e.toString()));
|
||||
}
|
||||
@@ -178,6 +197,7 @@ class DevicesCubit extends Cubit<DevicesState> {
|
||||
selectDevice(device);
|
||||
}, (r) => emit(state.copyWith(isLoading: false, selectedDevice: device)));
|
||||
}
|
||||
|
||||
/// 绑定设备
|
||||
Future<void> bindDevice(String deviceId, String deviceAlias) async {
|
||||
emit(state.copyWith(isLoading: true, errorMessage: ''));
|
||||
@@ -186,34 +206,23 @@ class DevicesCubit extends Cubit<DevicesState> {
|
||||
final result = await _bindDeviceUseCase.call(params);
|
||||
result.fold(
|
||||
// 失败处理
|
||||
(failure) => emit(state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: failure.message ?? '绑定设备失败',
|
||||
)),
|
||||
(failure) => emit(state.copyWith(isLoading: false, errorMessage: failure.message ?? '绑定设备失败')),
|
||||
// 成功处理(返回 int 状态码)
|
||||
(successCode) {
|
||||
(successCode) {
|
||||
if (successCode == 1) {
|
||||
emit(state.copyWith(isLoading: false, errorMessage: ''));
|
||||
// 绑定成功后刷新设备列表
|
||||
//fetchAllDevices(state.?.username ?? '');
|
||||
//fetchAllDevices(state.?.username ?? '');
|
||||
} else {
|
||||
emit(state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: '绑定失败:状态码 $successCode',
|
||||
));
|
||||
emit(state.copyWith(isLoading: false, errorMessage: '绑定失败:状态码 $successCode'));
|
||||
}
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
emit(state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: '绑定异常:${e.toString()}',
|
||||
));
|
||||
emit(state.copyWith(isLoading: false, errorMessage: '绑定异常:${e.toString()}'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// 获取设备位置
|
||||
Future<void> getDeviceLocation(DeviceEntity device) async {
|
||||
emit(state.copyWith(isLoading: true));
|
||||
@@ -282,60 +291,35 @@ class DevicesCubit extends Cubit<DevicesState> {
|
||||
|
||||
result.fold((failure) => emit(state.copyWith(errorMessage: failure.message)), (pathData) => emit(state.copyWith(generatedPath: pathData)));
|
||||
}
|
||||
// 开始路径规划
|
||||
|
||||
// 开始路径规划
|
||||
Future<void> startRoutePlanning(Queue<DeviceAddPathPointModel> locationQueue) async {
|
||||
emit(state.copyWith(isLoading: true));
|
||||
final result = await _routePlanningUseCase.startRoutePlanning(locationQueue);
|
||||
result.fold(
|
||||
(failure) => emit(state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: failure.message ?? '路径规划启动失败',
|
||||
)),
|
||||
(_) => emit(state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: '',
|
||||
)),
|
||||
(failure) => emit(state.copyWith(isLoading: false, errorMessage: failure.message ?? '路径规划启动失败')),
|
||||
(_) => emit(state.copyWith(isLoading: false, errorMessage: '')),
|
||||
);
|
||||
}
|
||||
|
||||
// 暂停
|
||||
// 暂停
|
||||
Future<void> pauseRoutePlanning() async {
|
||||
emit(state.copyWith(isLoading: true));
|
||||
final result = await _routePlanningUseCase.pauseRPWork();
|
||||
result.fold(
|
||||
(failure) => emit(state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: failure.message ?? '暂停失败',
|
||||
)),
|
||||
(_) => emit(state.copyWith(isLoading: false)),
|
||||
);
|
||||
result.fold((failure) => emit(state.copyWith(isLoading: false, errorMessage: failure.message ?? '暂停失败')), (_) => emit(state.copyWith(isLoading: false)));
|
||||
}
|
||||
|
||||
// 恢复
|
||||
// 恢复
|
||||
Future<void> resumeRoutePlanning() async {
|
||||
emit(state.copyWith(isLoading: true));
|
||||
final result = await _routePlanningUseCase.resumeRPWork();
|
||||
result.fold(
|
||||
(failure) => emit(state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: failure.message ?? '恢复失败',
|
||||
)),
|
||||
(_) => emit(state.copyWith(isLoading: false)),
|
||||
);
|
||||
result.fold((failure) => emit(state.copyWith(isLoading: false, errorMessage: failure.message ?? '恢复失败')), (_) => emit(state.copyWith(isLoading: false)));
|
||||
}
|
||||
|
||||
// 停止
|
||||
// 停止
|
||||
Future<void> stopRoutePlanning() async {
|
||||
emit(state.copyWith(isLoading: true));
|
||||
final result = await _routePlanningUseCase.stopRoutePlanning();
|
||||
result.fold(
|
||||
(failure) => emit(state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: failure.message ?? '停止失败',
|
||||
)),
|
||||
(_) => emit(state.copyWith(isLoading: false)),
|
||||
);
|
||||
result.fold((failure) => emit(state.copyWith(isLoading: false, errorMessage: failure.message ?? '停止失败')), (_) => emit(state.copyWith(isLoading: false)));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -52,14 +52,7 @@ class ImmersionHeader extends StatelessWidget {
|
||||
// 机器大图
|
||||
Transform.translate(
|
||||
offset: const Offset(30, 80), // 正数向右移动(例如 20 像素),负数向左
|
||||
child: Center(
|
||||
child: Image.asset(
|
||||
'assets/images/car.png',
|
||||
width: 330,
|
||||
height: 190,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
child: Center(child: Image.asset('assets/images/car.png', width: 330, height: 190, fit: BoxFit.contain)),
|
||||
),
|
||||
|
||||
// 顶部状态信息
|
||||
@@ -78,28 +71,12 @@ class ImmersionHeader extends StatelessWidget {
|
||||
mainAxisSize: MainAxisSize.min, // 尽可能收缩高度
|
||||
children: [
|
||||
// 设备名称和电量
|
||||
Text(
|
||||
_formatName(device.displayName),
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.w900,
|
||||
),
|
||||
),
|
||||
Text(_formatName(device.displayName), style: GoogleFonts.roboto(fontSize: 22, fontWeight: FontWeight.w900)),
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'${device.onlineStatus == 1 ? "100" : "--"} %',
|
||||
style: GoogleFonts.roboto(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w900,
|
||||
),
|
||||
),
|
||||
const Icon(
|
||||
Icons.chevron_right,
|
||||
size: 20,
|
||||
color: Colors.grey,
|
||||
),
|
||||
Text('${device.onlineStatus == 1 ? "100" : "--"} %', style: GoogleFonts.roboto(fontSize: 24, fontWeight: FontWeight.w900)),
|
||||
const Icon(Icons.chevron_right, size: 20, color: Colors.grey),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -123,9 +100,7 @@ class ImmersionHeader extends StatelessWidget {
|
||||
_buildCircleIcon(Icons.sync, () {
|
||||
// 1. 触发 Cubit 请求最新设备列表
|
||||
// 假设你的 username 存储在 AuthCubit 或类似的全局状态中
|
||||
final username =
|
||||
context.read<AppUserCubit>().state.user?.username ??
|
||||
"";
|
||||
final username = context.read<AppUserCubit>().state.user?.username ?? "";
|
||||
context.read<DevicesCubit>().fetchAllDevices(username);
|
||||
|
||||
// 2. 弹出窗口(窗口内部会根据状态显示转圈或列表)
|
||||
@@ -151,22 +126,14 @@ class ImmersionHeader extends StatelessWidget {
|
||||
// 在 offWhite 背景下,标签用纯白色会显得更精致
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
BoxShadow(color: Colors.black.withOpacity(0.02), blurRadius: 4),
|
||||
],
|
||||
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.02), blurRadius: 4)],
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
CircleAvatar(
|
||||
radius: 3,
|
||||
backgroundColor: isOnline ? Colors.green : Colors.grey,
|
||||
),
|
||||
CircleAvatar(radius: 3, backgroundColor: isOnline ? Colors.green : Colors.grey),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
isOnline ? "在线" : "离线",
|
||||
style: const TextStyle(fontSize: 12, color: Colors.black54),
|
||||
),
|
||||
Text(isOnline ? "在线" : "离线", style: const TextStyle(fontSize: 12, color: Colors.black54)),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -177,10 +144,7 @@ class ImmersionHeader extends StatelessWidget {
|
||||
return Container(
|
||||
width: 120,
|
||||
height: 6,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blueAccent,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
decoration: BoxDecoration(color: Colors.blueAccent, borderRadius: BorderRadius.circular(5)),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -205,11 +169,7 @@ class ImmersionHeader extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Icon(
|
||||
icon,
|
||||
size: 30,
|
||||
color: isAccent ? Colors.blue : Colors.black54,
|
||||
),
|
||||
child: Icon(icon, size: 30, color: isAccent ? Colors.blue : Colors.black54),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -235,21 +195,11 @@ class ImmersionHeader extends StatelessWidget {
|
||||
margin: const EdgeInsets.symmetric(vertical: 12),
|
||||
width: 36,
|
||||
height: 5,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[300],
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
),
|
||||
const Text(
|
||||
"切换设备",
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
decoration: BoxDecoration(color: Colors.grey[300], borderRadius: BorderRadius.circular(10)),
|
||||
),
|
||||
const Text("切换设备", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
height: 0.5,
|
||||
margin: const EdgeInsets.symmetric(horizontal: 20),
|
||||
color: Colors.grey.withOpacity(0.1),
|
||||
),
|
||||
Container(height: 0.5, margin: const EdgeInsets.symmetric(horizontal: 20), color: Colors.grey.withOpacity(0.1)),
|
||||
|
||||
// 💡 动态内容区
|
||||
Expanded(
|
||||
@@ -264,10 +214,7 @@ class ImmersionHeader extends StatelessWidget {
|
||||
children: [
|
||||
const CircularProgressIndicator(color: Colors.blue),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
"加载中...",
|
||||
style: TextStyle(color: Colors.grey[600]),
|
||||
),
|
||||
Text("加载中...", style: TextStyle(color: Colors.grey[600])),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -275,26 +222,26 @@ class ImmersionHeader extends StatelessWidget {
|
||||
|
||||
// 2. 列表展示
|
||||
if (state.devices.isEmpty) {
|
||||
return const Center(child: Text("暂无可用设备"));
|
||||
return const Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.description_outlined, size: 60, color: Colors.grey),
|
||||
SizedBox(height: 16),
|
||||
Text('暂无设备', style: TextStyle(fontSize: 16, color: Colors.grey)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
// 💡 底部留出安全距离,防止最后一条滚不上来
|
||||
padding: EdgeInsets.only(
|
||||
bottom: MediaQuery.of(context).padding.bottom + 20,
|
||||
top: 10,
|
||||
),
|
||||
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom + 20, top: 10),
|
||||
itemCount: state.devices.length,
|
||||
itemBuilder: (context, index) {
|
||||
// 传入当前选中的 ID 方便做 UI 区分
|
||||
final isSelected =
|
||||
state.selectedDevice?.deviceName ==
|
||||
state.devices[index].deviceName;
|
||||
return _buildDeviceItem(
|
||||
state.devices[index],
|
||||
context,
|
||||
isSelected,
|
||||
);
|
||||
final isSelected = state.selectedDevice?.deviceName == state.devices[index].deviceName;
|
||||
return _buildDeviceItem(state.devices[index], context, isSelected);
|
||||
},
|
||||
);
|
||||
},
|
||||
@@ -307,11 +254,7 @@ class ImmersionHeader extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDeviceItem(
|
||||
DeviceEntity device,
|
||||
BuildContext context,
|
||||
bool isSelected,
|
||||
) {
|
||||
Widget _buildDeviceItem(DeviceEntity device, BuildContext context, bool isSelected) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
print("跳转到详情页: ${device.deviceAlias}");
|
||||
@@ -323,29 +266,14 @@ class ImmersionHeader extends StatelessWidget {
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
// 💡 如果是当前选中设备,边框颜色略深
|
||||
border: Border.all(
|
||||
color: isSelected
|
||||
? Colors.blue.withOpacity(0.5)
|
||||
: Colors.grey.withOpacity(0.3),
|
||||
width: isSelected ? 1.5 : 1,
|
||||
),
|
||||
border: Border.all(color: isSelected ? Colors.blue.withOpacity(0.5) : Colors.grey.withOpacity(0.3), width: isSelected ? 1.5 : 1),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
boxShadow: [
|
||||
if (isSelected)
|
||||
BoxShadow(color: Colors.blue.withOpacity(0.05), blurRadius: 4),
|
||||
],
|
||||
boxShadow: [if (isSelected) BoxShadow(color: Colors.blue.withOpacity(0.05), blurRadius: 4)],
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
// 设备图片
|
||||
Transform.translate(
|
||||
offset: const Offset(10, 0),
|
||||
child: Image.asset(
|
||||
'assets/images/car.png',
|
||||
width: 100,
|
||||
height: 80,
|
||||
),
|
||||
),
|
||||
Transform.translate(offset: const Offset(10, 0), child: Image.asset('assets/images/car.png', width: 100, height: 80)),
|
||||
const SizedBox(width: 12),
|
||||
// 设备信息
|
||||
Expanded(
|
||||
@@ -354,17 +282,11 @@ class ImmersionHeader extends StatelessWidget {
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.circle,
|
||||
color: device.isOnline ? Colors.green : Colors.grey,
|
||||
size: 12,
|
||||
),
|
||||
Icon(Icons.circle, color: device.isOnline ? Colors.green : Colors.grey, size: 12),
|
||||
const SizedBox(width: 4),
|
||||
Flexible(
|
||||
child: Text(
|
||||
(device.deviceAlias?.trim() ?? '').isEmpty
|
||||
? '未知设备'
|
||||
: device.deviceAlias!,
|
||||
(device.deviceAlias?.trim() ?? '').isEmpty ? '未知设备' : device.deviceAlias!,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
// 关键属性:处理文本溢出
|
||||
maxLines: 2, // 最多显示2行
|
||||
@@ -375,10 +297,7 @@ class ImmersionHeader extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
const Text(
|
||||
"点击查看详情",
|
||||
style: TextStyle(color: Colors.grey, fontSize: 12),
|
||||
),
|
||||
const Text("点击查看详情", style: TextStyle(color: Colors.grey, fontSize: 12)),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -390,9 +309,7 @@ class ImmersionHeader extends StatelessWidget {
|
||||
? null
|
||||
: () async {
|
||||
// 💡 执行切换逻辑
|
||||
await context.read<DevicesCubit>().switchDevice(
|
||||
device,
|
||||
);
|
||||
await context.read<DevicesCubit>().switchDevice(device);
|
||||
// 切换成功后,UI 会自动更新(因为 BlocBuilder 在监听),我们可以关闭弹窗
|
||||
if (context.mounted) {
|
||||
Navigator.pop(context);
|
||||
@@ -408,10 +325,7 @@ class ImmersionHeader extends StatelessWidget {
|
||||
const SizedBox(height: 8),
|
||||
CCPrimaryButton(
|
||||
onPressed: () {
|
||||
context.push(
|
||||
RoutePaths.machineDetails,
|
||||
extra: device,
|
||||
); // 把当前点击的这个设备对象传过去
|
||||
context.push(RoutePaths.machineDetails, extra: device); // 把当前点击的这个设备对象传过去
|
||||
print("通过按钮进入详情,设备名称:$device");
|
||||
},
|
||||
|
||||
|
||||
@@ -69,11 +69,7 @@ class MyApp extends StatelessWidget {
|
||||
BlocProvider<DeviceStatusBloc>(create: (_) => sl<DeviceStatusBloc>()),
|
||||
// 其他 Cubit...
|
||||
],
|
||||
child: MaterialApp.router(
|
||||
title: 'Maibu Satabot',
|
||||
theme: AppTheme.lightTheme,
|
||||
routerConfig: sl<GoRouter>(),
|
||||
),
|
||||
child: MaterialApp.router(title: 'Maibu Satabot', theme: AppTheme.lightTheme, routerConfig: sl<GoRouter>()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user