Compare commits
2 Commits
df50fbb8cd
...
3f7b38a59b
| Author | SHA1 | Date | |
|---|---|---|---|
| 3f7b38a59b | |||
|
|
2fabae8738 |
@ -20,7 +20,5 @@
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>13.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@ -2,12 +2,15 @@ import Flutter
|
||||
import UIKit
|
||||
|
||||
@main
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
|
||||
override func application(
|
||||
_ application: UIApplication,
|
||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||
) -> Bool {
|
||||
GeneratedPluginRegistrant.register(with: self)
|
||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
}
|
||||
|
||||
func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
|
||||
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
@ -24,6 +26,42 @@
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSBluetoothAlwaysUsageDescription</key>
|
||||
<string>需要蓝牙权限来搜索和连接您的设备</string>
|
||||
<key>NSBluetoothPeripheralUsageDescription</key>
|
||||
<string>需要蓝牙权限来搜索和连接您的设备</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>需要位置权限以扫描附近的蓝牙设备</string>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
<false/>
|
||||
<key>UISceneConfigurations</key>
|
||||
<dict>
|
||||
<key>UIWindowSceneSessionRoleApplication</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UISceneClassName</key>
|
||||
<string>UIWindowScene</string>
|
||||
<key>UISceneConfigurationName</key>
|
||||
<string>flutter</string>
|
||||
<key>UISceneDelegateClassName</key>
|
||||
<string>FlutterSceneDelegate</string>
|
||||
<key>UISceneStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UILaunchScreen</key>
|
||||
<dict>
|
||||
<key>UIColorName</key>
|
||||
<string>LaunchBackgroundColor</string>
|
||||
<key>UIImageName</key>
|
||||
<string>LaunchImage</string>
|
||||
</dict>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
@ -41,22 +79,5 @@
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>NSBluetoothAlwaysUsageDescription</key>
|
||||
<string>需要蓝牙权限来搜索和连接您的设备</string>
|
||||
<key>NSBluetoothPeripheralUsageDescription</key>
|
||||
<string>需要蓝牙权限来搜索和连接您的设备</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>需要位置权限以扫描附近的蓝牙设备</string>
|
||||
<key>UILaunchScreen</key>
|
||||
<dict>
|
||||
<key>UIColorName</key>
|
||||
<string>LaunchBackgroundColor</string>
|
||||
<key>UIImageName</key>
|
||||
<string>LaunchImage</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@ -5,6 +5,7 @@ import '../../features/auth/presentation/pages/login_page.dart';
|
||||
import '../../pages/bluetooth_page.dart';
|
||||
import '../../pages/device_control_page.dart';
|
||||
import '../../pages/home_page.dart';
|
||||
import '../../pages/product_selection_page.dart';
|
||||
import '../../pages/profile/profile_page.dart';
|
||||
import '../../pages/webview_page.dart';
|
||||
import '../../pages/wifi_config_page.dart';
|
||||
@ -48,6 +49,10 @@ GoRouter goRouter(Ref ref) {
|
||||
extra: state.extra as Map<String, dynamic>?,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/product-selection',
|
||||
builder: (context, state) => const ProductSelectionPage(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/device-control',
|
||||
builder: (context, state) => const DeviceControlPage(),
|
||||
|
||||
@ -48,4 +48,4 @@ final class GoRouterProvider
|
||||
}
|
||||
}
|
||||
|
||||
String _$goRouterHash() => r'8e620e452bb81f2c6ed87b136283a9e508dca2e9';
|
||||
String _$goRouterHash() => r'9f77a00bcbc90890c4b6594a9709288e5206c7d8';
|
||||
|
||||
@ -30,12 +30,12 @@ Map<String, dynamic> _$DeviceTypeToJson(_DeviceType instance) =>
|
||||
_DeviceInfo _$DeviceInfoFromJson(Map<String, dynamic> json) => _DeviceInfo(
|
||||
id: (json['id'] as num).toInt(),
|
||||
sn: json['sn'] as String,
|
||||
deviceType: (json['device_type'] is Map<String, dynamic>)
|
||||
? DeviceType.fromJson(json['device_type'] as Map<String, dynamic>)
|
||||
: null,
|
||||
deviceTypeInfo: (json['device_type_info'] is Map<String, dynamic>)
|
||||
? DeviceType.fromJson(json['device_type_info'] as Map<String, dynamic>)
|
||||
: null,
|
||||
deviceType: json['device_type'] == null
|
||||
? null
|
||||
: DeviceType.fromJson(json['device_type'] as Map<String, dynamic>),
|
||||
deviceTypeInfo: json['device_type_info'] == null
|
||||
? null
|
||||
: DeviceType.fromJson(json['device_type_info'] as Map<String, dynamic>),
|
||||
macAddress: json['mac_address'] as String?,
|
||||
name: json['name'] as String? ?? '',
|
||||
status: json['status'] as String? ?? 'in_stock',
|
||||
|
||||
@ -21,6 +21,7 @@ class DeviceController extends _$DeviceController {
|
||||
Future<bool> bindDevice(String sn, {int? spiritId}) async {
|
||||
final repository = ref.read(deviceRepositoryProvider);
|
||||
final result = await repository.bindDevice(sn, spiritId: spiritId);
|
||||
if (!ref.mounted) return false;
|
||||
return result.fold(
|
||||
(failure) => false,
|
||||
(bindingId) {
|
||||
@ -33,6 +34,7 @@ class DeviceController extends _$DeviceController {
|
||||
Future<bool> unbindDevice(int userDeviceId) async {
|
||||
final repository = ref.read(deviceRepositoryProvider);
|
||||
final result = await repository.unbindDevice(userDeviceId);
|
||||
if (!ref.mounted) return false;
|
||||
return result.fold(
|
||||
(failure) => false,
|
||||
(_) {
|
||||
@ -48,6 +50,7 @@ class DeviceController extends _$DeviceController {
|
||||
Future<bool> updateSpirit(int userDeviceId, int spiritId) async {
|
||||
final repository = ref.read(deviceRepositoryProvider);
|
||||
final result = await repository.updateSpirit(userDeviceId, spiritId);
|
||||
if (!ref.mounted) return false;
|
||||
return result.fold(
|
||||
(failure) => false,
|
||||
(updated) {
|
||||
@ -78,6 +81,7 @@ class DeviceDetailController extends _$DeviceDetailController {
|
||||
Future<bool> updateSettings(Map<String, dynamic> settings) async {
|
||||
final repository = ref.read(deviceRepositoryProvider);
|
||||
final result = await repository.updateSettings(userDeviceId, settings);
|
||||
if (!ref.mounted) return false;
|
||||
return result.fold(
|
||||
(failure) => false,
|
||||
(_) {
|
||||
@ -90,6 +94,7 @@ class DeviceDetailController extends _$DeviceDetailController {
|
||||
Future<bool> configWifi(String ssid) async {
|
||||
final repository = ref.read(deviceRepositoryProvider);
|
||||
final result = await repository.configWifi(userDeviceId, ssid);
|
||||
if (!ref.mounted) return false;
|
||||
return result.fold(
|
||||
(failure) => false,
|
||||
(_) {
|
||||
|
||||
@ -36,7 +36,7 @@ final class DeviceControllerProvider
|
||||
DeviceController create() => DeviceController();
|
||||
}
|
||||
|
||||
String _$deviceControllerHash() => r'9b39117bd54964ba0035aad0eca10250454efaa7';
|
||||
String _$deviceControllerHash() => r'3f73a13c7f93fecb9fe781efc4ee305b6186639e';
|
||||
|
||||
/// 管理用户设备列表
|
||||
|
||||
|
||||
@ -1,17 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import '../widgets/animated_gradient_background.dart';
|
||||
import '../widgets/ios_toast.dart';
|
||||
import '../features/device/presentation/controllers/device_controller.dart';
|
||||
import '../features/device/domain/entities/device.dart';
|
||||
|
||||
class ProductSelectionPage extends StatefulWidget {
|
||||
class ProductSelectionPage extends ConsumerStatefulWidget {
|
||||
const ProductSelectionPage({super.key});
|
||||
|
||||
@override
|
||||
State<ProductSelectionPage> createState() => _ProductSelectionPageState();
|
||||
ConsumerState<ProductSelectionPage> createState() => _ProductSelectionPageState();
|
||||
}
|
||||
|
||||
class _ProductSelectionPageState extends State<ProductSelectionPage> {
|
||||
class _ProductSelectionPageState extends ConsumerState<ProductSelectionPage> {
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
|
||||
@override
|
||||
@ -28,12 +31,30 @@ class _ProductSelectionPageState extends State<ProductSelectionPage> {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/// 产品 ID 到后端 product_code 的映射
|
||||
static const Map<String, List<String>> _productCodeMap = {
|
||||
'capybara': ['KPBL-ON'],
|
||||
'badge-ai': ['DZBJ-ON'],
|
||||
'badge-basic': ['DZBJ-OFF'],
|
||||
};
|
||||
|
||||
/// 查找用户是否已绑定该产品类型的设备
|
||||
UserDevice? _findBoundDevice(String productId, List<UserDevice> devices) {
|
||||
final codes = _productCodeMap[productId];
|
||||
if (codes == null || codes.isEmpty) return null;
|
||||
for (final device in devices) {
|
||||
final dt = device.device.deviceType ?? device.device.deviceTypeInfo;
|
||||
if (dt != null && codes.contains(dt.productCode)) {
|
||||
return device;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static final List<Map<String, dynamic>> _products = [
|
||||
{
|
||||
'id': 'capybara',
|
||||
'name': '毛绒机芯',
|
||||
'status': '已连接',
|
||||
'statusColor': const Color(0xFF10B981),
|
||||
'icon': 'assets/www/Capybara.png',
|
||||
'isPng': true,
|
||||
'hasTag': true,
|
||||
@ -45,13 +66,10 @@ class _ProductSelectionPageState extends State<ProductSelectionPage> {
|
||||
end: Alignment.centerRight,
|
||||
),
|
||||
'shadowColor': const Color(0xFFC9A07A),
|
||||
'selected': true,
|
||||
},
|
||||
{
|
||||
'id': 'badge-ai',
|
||||
'name': '电子吧唧 AI',
|
||||
'status': '离线',
|
||||
'statusColor': const Color(0xFFE5E7EB),
|
||||
'icon': 'assets/www/icons/icon-product-badge.svg',
|
||||
'isPng': false,
|
||||
'hasTag': true,
|
||||
@ -63,13 +81,10 @@ class _ProductSelectionPageState extends State<ProductSelectionPage> {
|
||||
end: Alignment.centerRight,
|
||||
),
|
||||
'shadowColor': const Color(0xFF6366F1),
|
||||
'selected': false,
|
||||
},
|
||||
{
|
||||
'id': 'badge-basic',
|
||||
'name': '普通吧唧',
|
||||
'status': '未配对',
|
||||
'statusColor': const Color(0xFFE5E7EB),
|
||||
'icon': 'assets/www/icons/icon-product-badge.svg',
|
||||
'isPng': false,
|
||||
'hasTag': false,
|
||||
@ -80,13 +95,10 @@ class _ProductSelectionPageState extends State<ProductSelectionPage> {
|
||||
end: Alignment.centerRight,
|
||||
),
|
||||
'shadowColor': const Color(0xFFA78BFA),
|
||||
'selected': false,
|
||||
},
|
||||
{
|
||||
'id': 'bracelet',
|
||||
'name': 'AI 手链',
|
||||
'status': '点击扫描',
|
||||
'statusColor': const Color(0xFFE5E7EB),
|
||||
'icon': 'assets/www/icons/icon-product-badge.svg',
|
||||
'isPng': false,
|
||||
'hasTag': true,
|
||||
@ -98,13 +110,10 @@ class _ProductSelectionPageState extends State<ProductSelectionPage> {
|
||||
end: Alignment.centerRight,
|
||||
),
|
||||
'shadowColor': const Color(0xFFE07B54),
|
||||
'selected': false,
|
||||
},
|
||||
{
|
||||
'id': 'vsinger',
|
||||
'name': '洛天依',
|
||||
'status': '去下载专属 APP →',
|
||||
'statusColor': Colors.transparent,
|
||||
'icon': 'assets/www/icons/icon-product-luo.svg',
|
||||
'isPng': false,
|
||||
'hasTag': false,
|
||||
@ -115,13 +124,10 @@ class _ProductSelectionPageState extends State<ProductSelectionPage> {
|
||||
end: Alignment.centerRight,
|
||||
),
|
||||
'shadowColor': const Color(0xFF2DD4BF),
|
||||
'selected': false,
|
||||
},
|
||||
{
|
||||
'id': 'nightlight',
|
||||
'name': 'AI 星空夜灯',
|
||||
'status': '未配对',
|
||||
'statusColor': const Color(0xFFE5E7EB),
|
||||
'icon': 'assets/www/icons/icon-product-badge.svg',
|
||||
'isPng': false,
|
||||
'hasTag': true,
|
||||
@ -133,13 +139,10 @@ class _ProductSelectionPageState extends State<ProductSelectionPage> {
|
||||
end: Alignment.centerRight,
|
||||
),
|
||||
'shadowColor': const Color(0xFF7C3AED),
|
||||
'selected': false,
|
||||
},
|
||||
{
|
||||
'id': 'feeder',
|
||||
'name': '智能喂食器',
|
||||
'status': '点击扫描',
|
||||
'statusColor': const Color(0xFFE5E7EB),
|
||||
'icon': 'assets/www/icons/icon-product-badge.svg',
|
||||
'isPng': false,
|
||||
'hasTag': false,
|
||||
@ -150,24 +153,24 @@ class _ProductSelectionPageState extends State<ProductSelectionPage> {
|
||||
end: Alignment.centerRight,
|
||||
),
|
||||
'shadowColor': const Color(0xFFE11D48),
|
||||
'selected': false,
|
||||
},
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final safeTop = MediaQuery.of(context).padding.top;
|
||||
// 头部高度 = safeArea + padding + 按钮高度 + padding
|
||||
final headerHeight = safeTop + 12 + 40 + 12;
|
||||
|
||||
// 获取用户已绑定的设备列表
|
||||
final devicesAsync = ref.watch(deviceControllerProvider);
|
||||
final devices = devicesAsync.value ?? [];
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
body: Stack(
|
||||
children: [
|
||||
// 1. 全屏流动背景
|
||||
const AnimatedGradientBackground(),
|
||||
|
||||
// 2. 列表
|
||||
ScrollConfiguration(
|
||||
behavior: ScrollConfiguration.of(context).copyWith(
|
||||
scrollbars: false,
|
||||
@ -178,17 +181,28 @@ class _ProductSelectionPageState extends State<ProductSelectionPage> {
|
||||
itemCount: _products.length,
|
||||
separatorBuilder: (_, __) => const SizedBox(height: 16),
|
||||
itemBuilder: (context, index) {
|
||||
final product = _products[index];
|
||||
final boundDevice = _findBoundDevice(product['id'] as String, devices);
|
||||
return _FadeOnScrollCard(
|
||||
key: ValueKey(_products[index]['id']),
|
||||
product: _products[index],
|
||||
key: ValueKey(product['id']),
|
||||
product: product,
|
||||
isBound: boundDevice != null,
|
||||
fadeStartY: headerHeight + 16,
|
||||
fadeEndY: safeTop,
|
||||
onTap: () {
|
||||
if (boundDevice != null) {
|
||||
// 已绑定 → 直接进入设备控制页
|
||||
context.go('/device-control');
|
||||
} else {
|
||||
// 未绑定 → 跳转蓝牙搜索页
|
||||
context.go('/bluetooth');
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
// 3. 头部 — 统一规范:返回按钮 + 居中标题
|
||||
Positioned(
|
||||
top: 0,
|
||||
left: 0,
|
||||
@ -198,7 +212,6 @@ class _ProductSelectionPageState extends State<ProductSelectionPage> {
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
// 居中标题
|
||||
Text(
|
||||
'选择产品',
|
||||
style: GoogleFonts.outfit(
|
||||
@ -207,7 +220,6 @@ class _ProductSelectionPageState extends State<ProductSelectionPage> {
|
||||
color: const Color(0xFF1F2937),
|
||||
),
|
||||
),
|
||||
// 左侧返回按钮
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: GestureDetector(
|
||||
@ -238,17 +250,21 @@ class _ProductSelectionPageState extends State<ProductSelectionPage> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 带滚动渐隐的卡片包装器 — 纯 Opacity,无 ShaderMask,无 widget 切换
|
||||
/// 带滚动渐隐的卡片包装器
|
||||
class _FadeOnScrollCard extends StatefulWidget {
|
||||
final Map<String, dynamic> product;
|
||||
final double fadeStartY; // 卡片顶部到此位置开始淡出
|
||||
final double fadeEndY; // 卡片顶部到此位置完全消失
|
||||
final bool isBound;
|
||||
final double fadeStartY;
|
||||
final double fadeEndY;
|
||||
final VoidCallback onTap;
|
||||
|
||||
const _FadeOnScrollCard({
|
||||
super.key,
|
||||
required this.product,
|
||||
required this.isBound,
|
||||
required this.fadeStartY,
|
||||
required this.fadeEndY,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -279,7 +295,11 @@ class _FadeOnScrollCardState extends State<_FadeOnScrollCard> {
|
||||
return Opacity(
|
||||
key: _posKey,
|
||||
opacity: opacity,
|
||||
child: _ProductCard(product: widget.product),
|
||||
child: _ProductCard(
|
||||
product: widget.product,
|
||||
isBound: widget.isBound,
|
||||
onTap: widget.onTap,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -287,22 +307,20 @@ class _FadeOnScrollCardState extends State<_FadeOnScrollCard> {
|
||||
/// 产品卡片
|
||||
class _ProductCard extends StatelessWidget {
|
||||
final Map<String, dynamic> product;
|
||||
final bool isBound;
|
||||
final VoidCallback onTap;
|
||||
|
||||
const _ProductCard({super.key, required this.product});
|
||||
const _ProductCard({
|
||||
super.key,
|
||||
required this.product,
|
||||
required this.isBound,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool isSelected = product['selected'] == true;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
if (isSelected) {
|
||||
Navigator.of(context).pop();
|
||||
} else {
|
||||
AppToast.show(
|
||||
context, '${product['name']} 离线或未配对', isError: true);
|
||||
}
|
||||
},
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
height: 120,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 20),
|
||||
@ -343,18 +361,16 @@ class _ProductCard extends StatelessWidget {
|
||||
const SizedBox(height: 6),
|
||||
Row(
|
||||
children: [
|
||||
if ((product['statusColor'] as Color) !=
|
||||
Colors.transparent)
|
||||
Container(
|
||||
width: 7,
|
||||
height: 7,
|
||||
margin: const EdgeInsets.only(right: 6),
|
||||
decoration: BoxDecoration(
|
||||
color: product['id'] == 'capybara'
|
||||
color: isBound
|
||||
? const Color(0xFF34D399)
|
||||
: Colors.white.withOpacity(0.5),
|
||||
shape: BoxShape.circle,
|
||||
boxShadow: product['id'] == 'capybara'
|
||||
boxShadow: isBound
|
||||
? [
|
||||
BoxShadow(
|
||||
color: const Color(0xFF34D399)
|
||||
@ -365,7 +381,7 @@ class _ProductCard extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
Text(
|
||||
product['status'],
|
||||
isBound ? '已连接' : '点击配对',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.white.withOpacity(0.85)),
|
||||
|
||||
@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'product_selection_page.dart';
|
||||
import '../widgets/glass_dialog.dart';
|
||||
import '../widgets/animated_gradient_background.dart';
|
||||
import '../widgets/ios_toast.dart';
|
||||
@ -494,10 +493,7 @@ class _SettingsPageState extends ConsumerState<SettingsPage> {
|
||||
.unbindDevice(_userDeviceId!);
|
||||
if (mounted) {
|
||||
if (success) {
|
||||
Navigator.pop(context); // close settings
|
||||
Navigator.of(context).pushReplacement(
|
||||
MaterialPageRoute(builder: (context) => const ProductSelectionPage()),
|
||||
);
|
||||
context.go('/product-selection');
|
||||
} else {
|
||||
AppToast.show(context, '解绑失败', isError: true);
|
||||
}
|
||||
|
||||
@ -132,10 +132,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
|
||||
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
version: "1.4.1"
|
||||
checked_yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -644,14 +644,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.2"
|
||||
json_annotation:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -736,18 +728,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
|
||||
sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.17"
|
||||
version: "0.12.18"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
||||
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.11.1"
|
||||
version: "0.13.0"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1205,26 +1197,26 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test
|
||||
sha256: "75906bf273541b676716d1ca7627a17e4c4070a3a16272b7a3dc7da3b9f3f6b7"
|
||||
sha256: "54c516bbb7cee2754d327ad4fca637f78abfc3cbcc5ace83b3eda117e42cd71a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.26.3"
|
||||
version: "1.29.0"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
|
||||
sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.7"
|
||||
version: "0.7.9"
|
||||
test_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_core
|
||||
sha256: "0cc24b5ff94b38d2ae73e1eb43cc302b77964fbf67abad1e296025b78deb53d0"
|
||||
sha256: "394f07d21f0f2255ec9e3989f21e54d3c7dc0e6e9dbce160e5a9c1a6be0e2943"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.12"
|
||||
version: "0.6.15"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user