flutter_sdk/example/lib/tabs/auth_tab.dart

234 lines
8.1 KiB
Dart
Raw Normal View History

2026-08-20 09:25:05 +08:00
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<AuthTab> createState() => _AuthTabState();
}
class _AuthTabState extends State<AuthTab> {
final _clientIdCtrl = TextEditingController();
final _clientSecretCtrl = TextEditingController();
static const _environmentUrl = 'https://cloud.skychip.top/sdk';
final _usernameCtrl = TextEditingController();
final _passwordCtrl = TextEditingController();
final List<String> _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<void> _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<void> _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<bool>(
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),
],
),
);
},
);
}
}