123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- import 'dart:async';
- import 'package:connectivity_plus/connectivity_plus.dart';
- import 'package:fis_common/http/options.dart';
- import 'package:fis_jsonrpc/http_pool.dart';
- import 'package:flutter/foundation.dart';
- import 'package:flutter/material.dart';
- import 'package:vitalapp/architecture/network_connectivity.dart';
- import 'package:vitalapp/global.dart';
- import 'package:vitalapp/pages/help/help_dialog.dart';
- import 'package:fis_common/logger/logger.dart';
- import 'package:vitalapp/rpc.dart';
- import 'package:wifi_iot/wifi_iot.dart';
- class HeaderStatusBar extends StatelessWidget {
- const HeaderStatusBar({super.key});
- @override
- Widget build(BuildContext context) {
- return Row(
- mainAxisSize: MainAxisSize.min,
- crossAxisAlignment: CrossAxisAlignment.center,
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- _NetStatusWidget(),
- const SizedBox(width: 2),
- IconButton(
- onPressed: () {
- HelpDialog.show();
- },
- padding: EdgeInsets.all(0),
- icon: const Icon(Icons.help, size: 36, color: Colors.white),
- ),
- ],
- );
- }
- }
- class _NetStatusWidget extends StatefulWidget {
- @override
- State<StatefulWidget> createState() => _NetStatusWidgetState();
- }
- class _NetStatusWidgetState extends State<_NetStatusWidget> {
- Timer? _waitTimer;
- bool _isOnline = false;
- bool _isServerConnectable = true;
- @override
- void initState() {
- super.initState();
- _isOnline = kIsOnline;
- WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
- netChecker.onlineChangedEvent.addListener(_onlineChanged);
- if (_isOnline) {
- _checkServerConnectable();
- }
- });
- }
- @override
- void dispose() {
- netChecker.onlineChangedEvent.removeListener(_onlineChanged);
- super.dispose();
- }
- @override
- Widget build(BuildContext context) {
- return Tooltip(
- triggerMode: TooltipTriggerMode.tap,
- message: _buildTipsText(),
- child: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- _buildIcon(),
- _buildWifiName(),
- ],
- ),
- );
- }
- String _buildTipsText() {
- if (_isOnline) {
- if (_isServerConnectable) {
- return "网络已连接";
- } else {
- return "无法连接服务器";
- }
- } else {
- if (_waitTimer == null) {
- return "网络已断开";
- } else {
- return "网络等待中";
- }
- }
- }
- Widget _buildIcon() {
- if (_isOnline) {
- if (!_isServerConnectable) {
- return Icon(Icons.wifi_off_outlined, size: 36, color: Colors.red);
- }
- if (netChecker.status == ConnectivityResult.mobile) {
- return _NetworkIcon4G();
- }
- return Icon(Icons.wifi, size: 36, color: Colors.green);
- }
- if (_waitTimer == null) {
- return Icon(Icons.wifi_off_outlined, size: 36, color: Colors.red);
- } else {
- return SizedBox(width: 36, height: 36, child: _NetWaitingWidget());
- }
- }
- Widget _buildWifiName() {
- if (netChecker.status != ConnectivityResult.wifi) {
- return const SizedBox();
- }
- return _WifiNameWidget();
- }
- void _onlineChanged(_, e) {
- if (_isOnline != e) {
- setState(() {
- _isOnline = e;
- });
- }
- if (e) {
- _stopWaitNetRecover();
- _checkServerConnectable();
- } else {
- _waitNetRecover();
- }
- }
- void _waitNetRecover() {
- if (_waitTimer != null) {
- return;
- }
- logger.i("HeaderStatusBar - Wait network start.");
- print("HeaderStatusBar - Wait network start.");
- _waitTimer = Timer(const Duration(milliseconds: 5 * 1000), () {
- setState(() {
- _waitTimer = null;
- });
- logger.i("HeaderStatusBar - Wait network done.");
- print("HeaderStatusBar - Wait network done.");
- });
- }
- void _stopWaitNetRecover() {
- if (_waitTimer != null) {
- _waitTimer?.cancel();
- _waitTimer = null;
- logger.i("HeaderStatusBar - Wait network abort.");
- print("HeaderStatusBar - Wait network abort.");
- }
- }
- Future<void> _checkServerConnectable() async {
- final result = await _tryConnectRpcOnce();
- setState(() {
- _isServerConnectable = result;
- });
- }
- /// 检验服务有效性
- Future<bool> _tryConnectRpcOnce() async {
- print("${netChecker.status} _tryConnectRpcOnce: ${DateTime.now()}");
- try {
- final reqJson =
- '{"jsonrpc":"2.0","method":"VerifyAccountAsync","params":[{"UserName": "abc123"}],"id":1}';
- var response = await jrpcHttpPool.getClient(
- rpc.currentHostAddress,
- // timeout: 1000, // 设置了但没生效
- headers: {'content-type': "text/plain"},
- ).post(
- '/IVitalLoginService',
- data: reqJson,
- options: FHttpScopedOptions(timeout: 1000),
- );
- print(response);
- return true;
- } catch (e) {
- print("Http unknown error:${e}");
- }
- return false;
- }
- }
- class _NetWaitingWidget extends StatefulWidget {
- @override
- State<_NetWaitingWidget> createState() => _NetWaitingWidgetState();
- }
- class _NetWaitingWidgetState extends State<_NetWaitingWidget> {
- static final _color = Colors.orange.shade200;
- bool _isShow = false;
- Timer? _timer;
- @override
- void initState() {
- super.initState();
- WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
- _timer = Timer.periodic(const Duration(milliseconds: 1000), (timer) {
- setState(() {
- _isShow = !_isShow;
- });
- });
- });
- }
- @override
- void dispose() {
- _timer?.cancel();
- _timer = null;
- super.dispose();
- }
- @override
- Widget build(BuildContext context) {
- return Stack(
- children: [
- Icon(
- Icons.wifi,
- size: 36,
- color: _isShow ? _color : _color.withOpacity(.4),
- ),
- const Center(
- child: Padding(
- padding: EdgeInsets.all(8),
- child: CircularProgressIndicator(
- strokeWidth: 4,
- color: Colors.white,
- ),
- ),
- ),
- ],
- );
- }
- }
- class _NetworkIcon4G extends StatelessWidget {
- @override
- Widget build(BuildContext context) {
- return Expanded(
- child: Column(
- children: [
- Transform.translate(
- offset: Offset(-4, 10),
- child: Text(
- "4G",
- style: TextStyle(
- fontSize: 18,
- color: Colors.white,
- ),
- ),
- ),
- Transform.translate(
- offset: Offset(0, -6),
- child: Transform.scale(
- scaleX: 1.2,
- child: Icon(
- Icons.signal_cellular_alt_rounded,
- size: 36,
- color: Colors.green,
- ),
- ),
- ),
- ],
- ),
- );
- }
- }
- class _WifiNameWidget extends StatelessWidget {
- @override
- Widget build(BuildContext context) {
- return FutureBuilder(
- builder: (context, snapshot) {
- if (snapshot.hasData &&
- snapshot.data != null &&
- snapshot.data!.isNotEmpty) {
- return Container(
- constraints: BoxConstraints(maxWidth: 120),
- child: Text(
- _breakWord(snapshot.data!),
- style: TextStyle(
- fontSize: 16,
- color: Colors.white,
- ),
- overflow: TextOverflow.ellipsis,
- ),
- );
- }
- return const SizedBox();
- },
- future: WiFiForIoTPlugin.getSSID(),
- );
- }
- /// 插入零宽空格
- static String _breakWord(String word) {
- if (word.isEmpty) return word;
- String breakWord = ' ';
- for (var element in word.runes) {
- breakWord += String.fromCharCode(element);
- breakWord += '\u200B';
- }
- return breakWord;
- }
- }
|