import 'dart:io'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/material.dart'; import 'package:flutter_sdk/starcloud_flutter_sdk.dart'; import '../global.dart'; import '../l10n.dart'; import '../widgets/common_widgets.dart'; class AuthTab extends StatefulWidget { const AuthTab({super.key}); @override State createState() => _AuthTabState(); } class _AuthTabState extends State { final _clientIdCtrl = TextEditingController(); final _clientSecretCtrl = TextEditingController(); static const _environmentUrl = 'https://cloud.skychip.top/sdk'; final _usernameCtrl = TextEditingController(); final _passwordCtrl = TextEditingController(); final List _log = []; bool _sdkReady = false; bool _cloudUserReady = false; bool _loggingIn = false; void _log_(String msg) { final ts = DateTime.now().toIso8601String().substring(11, 19); setState(() => _log.add('[$ts] $msg')); } void _initSdk() { final id = _clientIdCtrl.text.trim(); if (id.isEmpty) { _log_(S.isEn ? 'Please fill Client ID' : '请先填写 Client ID'); return; } try { StarCloudClient.instance.auth.init( clientId: id, clientSecret: _clientSecretCtrl.text.trim(), environmentUrl: _environmentUrl, ); setState(() => _sdkReady = true); _log_(S.isEn ? 'SDK Init Success' : 'SDK 初始化成功'); } catch (e) { _log_('${S.isEn ? "Failed" : "失败"}: $e'); } } Future _createDemoCloudAccount() async { setState(() => _loggingIn = true); _log_(S.isEn ? 'Creating SDK cloud account...' : '正在创建 SDK 星云测试账户...'); try { final cloudUser = await StarCloudClient.instance.auth.createCloudUser(); StarCloudClient.instance.auth.setCloudAccounts([cloudUser]); sdkCloudAccountReady.value = true; pairedLockId.value = null; pairedLock.value = null; setState(() => _cloudUserReady = true); _log_(S.isEn ? 'SDK cloud account is ready. You can scan and pair.' : 'SDK 星云账户已就绪。现在可扫描并绑定锁。'); } catch (e) { _log_('${S.isEn ? "Failed" : "失败"}: $e'); } finally { if (mounted) setState(() => _loggingIn = false); } } Future _loginLockService() async { final username = _usernameCtrl.text.trim(); final password = _passwordCtrl.text; if (username.isEmpty || password.isEmpty) { _log_(S.isEn ? 'Please fill username and password' : '请填写用户名和密码'); return; } setState(() => _loggingIn = true); _log_(S.isEn ? 'Signing in...' : '正在登录...'); try { String deviceBrand = Platform.isAndroid ? 'android' : 'ios'; String deviceModel = 'unknown'; String deviceVersion = 'unknown'; try { final deviceInfo = DeviceInfoPlugin(); if (Platform.isAndroid) { final android = await deviceInfo.androidInfo; deviceBrand = android.brand; deviceModel = android.model; deviceVersion = android.version.release; } else if (Platform.isIOS) { final ios = await deviceInfo.iosInfo; deviceBrand = 'Apple'; deviceModel = ios.utsname.machine; deviceVersion = ios.systemVersion; } } catch (_) { // 设备信息只用于服务端风控,无法读取时使用默认值继续登录。 } // lock.skychip.top token 只用于 WiFi 网关配置,不能替代 SDK 云账户。 final lockServiceToken = await StarCloudClient.instance.auth.loginLockService( username: username, password: password, deviceBrand: deviceBrand, deviceModel: deviceModel, deviceVersion: deviceVersion, ); lockServiceAccessToken.value = lockServiceToken; signedInAccount.value = username; _log_(S.isEn ? 'WiFi authorization is ready.' : 'WiFi 网关授权登录成功。'); } catch (e) { _log_('${S.isEn ? "Failed" : "失败"}: $e'); } finally { if (mounted) setState(() => _loggingIn = false); } } @override void dispose() { _clientIdCtrl.dispose(); _clientSecretCtrl.dispose(); _usernameCtrl.dispose(); _passwordCtrl.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return ValueListenableBuilder( valueListenable: S.langNotifier, builder: (context, isEn, _) { return SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Card( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), child: Wrap( spacing: 8, children: [ StatusChip(label: S.sdkStatus, ready: _sdkReady), StatusChip( label: S.cloudUserStatus, ready: _cloudUserReady), ], ), ), ), const SizedBox(height: 16), TextField( controller: _clientIdCtrl, decoration: InputDecoration( labelText: S.clientId, border: const OutlineInputBorder(), prefixIcon: const Icon(Icons.badge_outlined)), ), const SizedBox(height: 12), TextField( controller: _clientSecretCtrl, obscureText: true, decoration: InputDecoration( labelText: S.clientSecret, border: const OutlineInputBorder(), prefixIcon: const Icon(Icons.key_outlined)), ), const SizedBox(height: 12), const SizedBox(height: 16), ElevatedButton.icon( onPressed: _initSdk, icon: const Icon(Icons.settings), label: Text(S.step1Init)), const SizedBox(height: 16), ElevatedButton.icon( onPressed: _sdkReady && !_loggingIn ? _createDemoCloudAccount : null, icon: const Icon(Icons.person_add_outlined), label: Text( _loggingIn ? S.btnProcessing : S.btnCreateTestCloudAccount, ), ), const SizedBox(height: 16), TextField( controller: _usernameCtrl, keyboardType: TextInputType.emailAddress, decoration: InputDecoration( labelText: S.accountLabel, border: const OutlineInputBorder(), prefixIcon: const Icon(Icons.person_outline), ), ), const SizedBox(height: 12), TextField( controller: _passwordCtrl, obscureText: true, onSubmitted: (_) => _sdkReady && !_loggingIn ? _loginLockService() : null, decoration: InputDecoration( labelText: S.passwordLabel, border: const OutlineInputBorder(), prefixIcon: const Icon(Icons.password), ), ), const SizedBox(height: 8), ElevatedButton.icon( onPressed: _sdkReady && !_loggingIn ? _loginLockService : null, icon: _loggingIn ? const SizedBox( width: 18, height: 18, child: CircularProgressIndicator(strokeWidth: 2), ) : const Icon(Icons.login), label: Text( _loggingIn ? S.btnProcessing : S.btnLoginForWifiAuthorization, )), const SizedBox(height: 16), LogArea(log: _log), ], ), ); }, ); } }