mirror of
https://github.com/EasyTier/astral.git
synced 2025-05-19 10:30:24 +00:00
切换官方服务器
更换为官方服务器,提升稳定性。 移除模拟延迟 改为直接检测连接,优化体验。 修复延迟计算 从 peer 获取最小延迟(μs→ms),无效时用路由延迟。 修复管理员权限 解决管理员操作无权限问题。 配置存储位置调整 将配置信息改为运行目录,方便管理。 查看 NAT 类型 添加功能检测并显示 NAT 类型。 修复页面状态丢失 解决缩放导致导航栏移动时页面状态丢失问题。 优化延迟检测 始终检测延迟,移除暂停/开始功能,简化逻辑。 最小化通知 应用最小化时提供通知,提醒用户状态。 增加客户端搜索功能 添加客户端搜索功能,支持快速查找内容或设备。
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 7.2 KiB |
+16
-4
@@ -6,6 +6,7 @@ import 'dart:io';
|
|||||||
import 'screens/Home.dart';
|
import 'screens/Home.dart';
|
||||||
import 'config/themeconfiguration.dart';
|
import 'config/themeconfiguration.dart';
|
||||||
import 'config/app_config.dart';
|
import 'config/app_config.dart';
|
||||||
|
import 'package:astral/utils/up.dart'; // 添加这行导入
|
||||||
|
|
||||||
// 定义应用程序的主要StatefulWidget
|
// 定义应用程序的主要StatefulWidget
|
||||||
class MyApp extends StatefulWidget {
|
class MyApp extends StatefulWidget {
|
||||||
@@ -38,6 +39,17 @@ class _MyAppState extends State<MyApp> {
|
|||||||
|
|
||||||
// 初始化系统托盘
|
// 初始化系统托盘
|
||||||
initSystemTray();
|
initSystemTray();
|
||||||
|
|
||||||
|
// 添加版本检查(在下一帧执行确保context可用)
|
||||||
|
Future.microtask(() {
|
||||||
|
final updateChecker = UpdateChecker(
|
||||||
|
owner: 'ldoubil',
|
||||||
|
repo: 'astral',
|
||||||
|
);
|
||||||
|
if (mounted) {
|
||||||
|
updateChecker.scheckForUpdates(context);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化系统托盘
|
// 初始化系统托盘
|
||||||
@@ -88,10 +100,10 @@ class _MyAppState extends State<MyApp> {
|
|||||||
// 更改主题色的方法
|
// 更改主题色的方法
|
||||||
void changeSeedColor(Color color) {
|
void changeSeedColor(Color color) {
|
||||||
// 使用 Future.microtask 延迟状态更新,避免在当前帧中触发重建
|
// 使用 Future.microtask 延迟状态更新,避免在当前帧中触发重建
|
||||||
setState(() {
|
setState(() {
|
||||||
_seedColor = color;
|
_seedColor = color;
|
||||||
AppConfig().setSeedColor(color);
|
AppConfig().setSeedColor(color);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更改底部导航栏选中索引的方法
|
// 更改底部导航栏选中索引的方法
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ class _InfoPageState extends State<InfoPage>
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
AppInfoUtil.getFullVersion(),
|
AppInfoUtil.getVersion(),
|
||||||
style: Theme.of(context).textTheme.bodyLarge,
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
+82
-57
@@ -120,62 +120,89 @@ class _HomePageState extends State<HomePage> {
|
|||||||
roomName: roomName,
|
roomName: roomName,
|
||||||
roomPassword: roomPassword,
|
roomPassword: roomPassword,
|
||||||
severurl: Serverip);
|
severurl: Serverip);
|
||||||
// 模拟连接过程,2秒后连接成功
|
|
||||||
Future.delayed(const Duration(seconds: 2), () {
|
// 添加连接超时计数器
|
||||||
|
int connectionTimeoutCounter = 0;
|
||||||
|
|
||||||
|
// 不再使用固定延迟模拟连接成功,而是通过定时检查IP来确定连接状态
|
||||||
|
timer = Timer.periodic(const Duration(seconds: 1), (timer) async {
|
||||||
// 检查组件是否仍然挂载
|
// 检查组件是否仍然挂载
|
||||||
if (!mounted) return;
|
if (!mounted) {
|
||||||
|
timer.cancel();
|
||||||
if (isRunning) {
|
return;
|
||||||
// 确保用户没有在连接过程中取消
|
|
||||||
setState(() {
|
|
||||||
_connectionState = ConnectionState.connected;
|
|
||||||
// 连接成功后开始计时
|
|
||||||
|
|
||||||
timer = Timer.periodic(const Duration(seconds: 1), (timer) async {
|
|
||||||
// 检查组件是否仍然挂载
|
|
||||||
if (!mounted) {
|
|
||||||
timer.cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final info = await getRunningInfo();
|
|
||||||
// 打印运行信息的详细内容
|
|
||||||
// print("运行信息详情:${info}");
|
|
||||||
Runin runin = parseRunin(info);
|
|
||||||
// 获取网络状态
|
|
||||||
// 获取网络状态
|
|
||||||
final networkStatus = await getNetworkStatus();
|
|
||||||
km.nodes = networkStatus.nodes;
|
|
||||||
|
|
||||||
// 更新网络流量数据
|
|
||||||
_updateNetworkStats(networkStatus.nodes);
|
|
||||||
|
|
||||||
// print('设备名称: ${runin.devName}');
|
|
||||||
// print(
|
|
||||||
// '设备ID: ${_intToIpv4String(runin.myNodeInfo?.virtualIpv4?.address?.addr ?? 0)}');
|
|
||||||
final int? version =
|
|
||||||
runin.myNodeInfo?.virtualIpv4?.address?.addr;
|
|
||||||
if (version != null) {
|
|
||||||
String ipStr = _intToIpv4String(version);
|
|
||||||
// 检查IP不为0.0.0.0且与当前IP不同时才更新
|
|
||||||
if (ipStr != "0.0.0.0" && publicIP != ipStr) {
|
|
||||||
km.virtualIP = ipStr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 再次检查组件是否仍然挂载
|
|
||||||
if (!mounted) {
|
|
||||||
timer.cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
runningTime += const Duration(seconds: 1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final info = await getRunningInfo();
|
||||||
|
Runin runin = parseRunin(info);
|
||||||
|
|
||||||
|
// 获取网络状态
|
||||||
|
final networkStatus = await getNetworkStatus();
|
||||||
|
final km = Provider.of<KM>(context, listen: false);
|
||||||
|
km.nodes = networkStatus.nodes;
|
||||||
|
|
||||||
|
// 更新网络流量数据
|
||||||
|
_updateNetworkStats(networkStatus.nodes);
|
||||||
|
|
||||||
|
final int? version = runin.myNodeInfo?.virtualIpv4?.address?.addr;
|
||||||
|
if (version != null) {
|
||||||
|
String ipStr = _intToIpv4String(version);
|
||||||
|
// 检查IP不为0.0.0.0时认为连接成功
|
||||||
|
if (ipStr != "0.0.0.0") {
|
||||||
|
if (publicIP != ipStr) {
|
||||||
|
km.virtualIP = ipStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果当前状态还是连接中,则更新为已连接
|
||||||
|
if (_connectionState == ConnectionState.connecting) {
|
||||||
|
setState(() {
|
||||||
|
_connectionState = ConnectionState.connected;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置超时计数器
|
||||||
|
connectionTimeoutCounter = 0;
|
||||||
|
} else if (_connectionState == ConnectionState.connecting) {
|
||||||
|
// 只在连接状态下增加超时计数
|
||||||
|
connectionTimeoutCounter++;
|
||||||
|
|
||||||
|
// 如果连续10秒都是0.0.0.0,判断为连接失败
|
||||||
|
if (connectionTimeoutCounter >= 10) {
|
||||||
|
// 停止连接并显示失败消息
|
||||||
|
timer.cancel();
|
||||||
|
setState(() {
|
||||||
|
isRunning = false;
|
||||||
|
_connectionState = ConnectionState.notStarted;
|
||||||
|
runningTime = Duration.zero;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 关闭服务器连接
|
||||||
|
closeAllServer();
|
||||||
|
|
||||||
|
// 显示连接失败提示
|
||||||
|
if (mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(
|
||||||
|
content: Text('连接失败,请检查网络或房间信息后重试'),
|
||||||
|
duration: Duration(seconds: 3),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 再次检查组件是否仍然挂载
|
||||||
|
if (!mounted) {
|
||||||
|
timer.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
runningTime += const Duration(seconds: 1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
// 移除原来的Future.delayed模拟连接成功的代码
|
||||||
} else {
|
} else {
|
||||||
// 停止时重置状态
|
// 停止时重置状态
|
||||||
_connectionState = ConnectionState.notStarted;
|
_connectionState = ConnectionState.notStarted;
|
||||||
@@ -217,7 +244,7 @@ class _HomePageState extends State<HomePage> {
|
|||||||
|
|
||||||
// 再次检查挂载状态,确保在setState前组件仍然挂载
|
// 再次检查挂载状态,确保在setState前组件仍然挂载
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
|
||||||
// 计算速度 (字节/秒 转换为 MB/秒)
|
// 计算速度 (字节/秒 转换为 MB/秒)
|
||||||
setState(() {
|
setState(() {
|
||||||
_uploadBytes = totalUploadBytes;
|
_uploadBytes = totalUploadBytes;
|
||||||
@@ -881,7 +908,7 @@ class _HomePageState extends State<HomePage> {
|
|||||||
// 添加版本信息卡片
|
// 添加版本信息卡片
|
||||||
Widget _buildVersionInfoCard(ColorScheme colorScheme) {
|
Widget _buildVersionInfoCard(ColorScheme colorScheme) {
|
||||||
// 这里可以从配置或API获取实际版本号
|
// 这里可以从配置或API获取实际版本号
|
||||||
final String appVersion = AppInfoUtil.getFullVersion();
|
final String appVersion = AppInfoUtil.getVersion();
|
||||||
|
|
||||||
return FloatingCard(
|
return FloatingCard(
|
||||||
colorScheme: colorScheme,
|
colorScheme: colorScheme,
|
||||||
@@ -940,5 +967,3 @@ Widget _buildVersionItem(
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+249
-204
@@ -18,6 +18,7 @@ class PlayerInfo {
|
|||||||
final int receivedPackets; // 接收包数量
|
final int receivedPackets; // 接收包数量
|
||||||
final double packetLossRate; // 丢包率(%)
|
final double packetLossRate; // 丢包率(%)
|
||||||
final String etVersion; // ET版本
|
final String etVersion; // ET版本
|
||||||
|
final String natType; // 添加NAT类型
|
||||||
|
|
||||||
PlayerInfo({
|
PlayerInfo({
|
||||||
required this.name,
|
required this.name,
|
||||||
@@ -30,6 +31,7 @@ class PlayerInfo {
|
|||||||
required this.receivedPackets,
|
required this.receivedPackets,
|
||||||
required this.packetLossRate,
|
required this.packetLossRate,
|
||||||
required this.etVersion,
|
required this.etVersion,
|
||||||
|
required this.natType, // 添加NAT类型参数
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,13 +46,43 @@ class RoomPage extends StatefulWidget {
|
|||||||
|
|
||||||
class _RoomPageState extends State<RoomPage> {
|
class _RoomPageState extends State<RoomPage> {
|
||||||
List<PlayerInfo> players = [];
|
List<PlayerInfo> players = [];
|
||||||
|
List<PlayerInfo> filteredPlayers = []; // 添加过滤后的玩家列表
|
||||||
bool isLoading = true;
|
bool isLoading = true;
|
||||||
// 移除布局类型状态变量
|
String searchQuery = ''; // 添加搜索查询字符串
|
||||||
|
TextEditingController searchController = TextEditingController(); // 添加搜索控制器
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
|
searchController.addListener(_onSearchChanged); // 添加搜索监听器
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
searchController.removeListener(_onSearchChanged); // 移除搜索监听器
|
||||||
|
searchController.dispose(); // 释放控制器资源
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索变化处理函数
|
||||||
|
void _onSearchChanged() {
|
||||||
|
setState(() {
|
||||||
|
searchQuery = searchController.text;
|
||||||
|
_filterPlayers(); // 过滤玩家列表
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 过滤玩家列表
|
||||||
|
void _filterPlayers() {
|
||||||
|
if (searchQuery.isEmpty) {
|
||||||
|
filteredPlayers = List.from(players); // 如果搜索为空,显示所有玩家
|
||||||
|
} else {
|
||||||
|
filteredPlayers = players
|
||||||
|
.where((player) =>
|
||||||
|
player.name.toLowerCase().contains(searchQuery.toLowerCase()))
|
||||||
|
.toList(); // 根据名称过滤玩家
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -60,7 +92,22 @@ class _RoomPageState extends State<RoomPage> {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('房间成员'),
|
title: const Text('房间成员'),
|
||||||
// 移除布局切换按钮
|
actions: [
|
||||||
|
// 添加搜索按钮
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.search),
|
||||||
|
onPressed: () {
|
||||||
|
showSearch(
|
||||||
|
context: context,
|
||||||
|
delegate: _PlayerSearchDelegate(
|
||||||
|
players: players,
|
||||||
|
colorScheme: colorScheme,
|
||||||
|
buildPlayerListItem: _buildPlayerListItem,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
body: Consumer<KM>(
|
body: Consumer<KM>(
|
||||||
builder: (context, km, child) {
|
builder: (context, km, child) {
|
||||||
@@ -190,6 +237,9 @@ class _RoomPageState extends State<RoomPage> {
|
|||||||
packetLossRate = double.parse(packetLossRate.toStringAsFixed(1));
|
packetLossRate = double.parse(packetLossRate.toStringAsFixed(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取NAT类型
|
||||||
|
String natType = _mapNatType(node.nat);
|
||||||
|
|
||||||
// 创建PlayerInfo对象
|
// 创建PlayerInfo对象
|
||||||
nodePlayerInfos.add(
|
nodePlayerInfos.add(
|
||||||
PlayerInfo(
|
PlayerInfo(
|
||||||
@@ -203,6 +253,7 @@ class _RoomPageState extends State<RoomPage> {
|
|||||||
receivedPackets: receivedPackets,
|
receivedPackets: receivedPackets,
|
||||||
packetLossRate: packetLossRate,
|
packetLossRate: packetLossRate,
|
||||||
etVersion: node.version, // 获取版本信息
|
etVersion: node.version, // 获取版本信息
|
||||||
|
natType: natType, // 添加NAT类型
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -211,6 +262,7 @@ class _RoomPageState extends State<RoomPage> {
|
|||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
players = nodePlayerInfos;
|
players = nodePlayerInfos;
|
||||||
|
_filterPlayers(); // 更新过滤后的玩家列表
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -223,176 +275,6 @@ class _RoomPageState extends State<RoomPage> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构建玩家信息卡片
|
|
||||||
Widget _buildPlayerCard(PlayerInfo player, ColorScheme colorScheme) {
|
|
||||||
// 根据延迟值确定颜色
|
|
||||||
Color latencyColor = _getLatencyColor(player.latency);
|
|
||||||
|
|
||||||
// 根据连接类型选择图标
|
|
||||||
IconData connectionIcon = _getConnectionIcon(player.connectionType);
|
|
||||||
|
|
||||||
return FloatingCard(
|
|
||||||
colorScheme: colorScheme,
|
|
||||||
maxWidth: 600,
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
// 玩家名称和连接类型
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Icon(Icons.person, color: colorScheme.primary, size: 22),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
player.name,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 18, fontWeight: FontWeight.bold),
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: _getConnectionTypeColor(
|
|
||||||
player.connectionType, colorScheme),
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
connectionIcon,
|
|
||||||
size: 14,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 4),
|
|
||||||
Text(
|
|
||||||
player.connectionType,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
|
|
||||||
// IP地址
|
|
||||||
_buildInfoRow(
|
|
||||||
Icons.lan,
|
|
||||||
'IP地址',
|
|
||||||
player.ip,
|
|
||||||
colorScheme,
|
|
||||||
showCopyButton: true,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
|
|
||||||
// 延迟信息
|
|
||||||
_buildInfoRow(
|
|
||||||
Icons.speed,
|
|
||||||
'延迟',
|
|
||||||
'${player.latency} ms',
|
|
||||||
colorScheme,
|
|
||||||
valueColor: latencyColor,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
|
|
||||||
// ET版本
|
|
||||||
_buildInfoRow(
|
|
||||||
Icons.memory,
|
|
||||||
'ET版本',
|
|
||||||
player.etVersion,
|
|
||||||
colorScheme,
|
|
||||||
),
|
|
||||||
|
|
||||||
const Divider(height: 24),
|
|
||||||
|
|
||||||
// 网络数据部分标题
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Icon(Icons.data_usage, color: colorScheme.primary, size: 18),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
Text(
|
|
||||||
'网络数据',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: colorScheme.primary,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
|
|
||||||
// 网络数据信息 - 优化对齐方式
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: _buildNetworkDataItemAligned(
|
|
||||||
'上传',
|
|
||||||
'${player.uploadSpeed} KB/s',
|
|
||||||
Icons.upload,
|
|
||||||
colorScheme.primary,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: _buildNetworkDataItemAligned(
|
|
||||||
'下载',
|
|
||||||
'${player.downloadSpeed} KB/s',
|
|
||||||
Icons.download,
|
|
||||||
colorScheme.secondary,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: _buildNetworkDataItemAligned(
|
|
||||||
'发送包',
|
|
||||||
'${player.sentPackets}',
|
|
||||||
Icons.send,
|
|
||||||
colorScheme.primary,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: _buildNetworkDataItemAligned(
|
|
||||||
'接收包',
|
|
||||||
'${player.receivedPackets}',
|
|
||||||
Icons.call_received,
|
|
||||||
colorScheme.secondary,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
const Divider(height: 24),
|
|
||||||
|
|
||||||
// 丢包率信息
|
|
||||||
_buildInfoRow(
|
|
||||||
Icons.error_outline,
|
|
||||||
'丢包率',
|
|
||||||
'${player.packetLossRate}%',
|
|
||||||
colorScheme,
|
|
||||||
valueColor: _getPacketLossColor(player.packetLossRate),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建列表项视图
|
// 构建列表项视图
|
||||||
Widget _buildPlayerListItem(PlayerInfo player, ColorScheme colorScheme) {
|
Widget _buildPlayerListItem(PlayerInfo player, ColorScheme colorScheme) {
|
||||||
// 根据延迟值确定颜色
|
// 根据延迟值确定颜色
|
||||||
@@ -492,6 +374,15 @@ class _RoomPageState extends State<RoomPage> {
|
|||||||
colorScheme,
|
colorScheme,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
|
// NAT类型
|
||||||
|
_buildInfoRow(
|
||||||
|
_getNatTypeIcon(player.natType),
|
||||||
|
'NAT类型',
|
||||||
|
player.natType,
|
||||||
|
colorScheme,
|
||||||
|
valueColor: _getNatTypeColor(player.natType),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
|
||||||
// 丢包率信息
|
// 丢包率信息
|
||||||
_buildInfoRow(
|
_buildInfoRow(
|
||||||
@@ -632,6 +523,16 @@ class _RoomPageState extends State<RoomPage> {
|
|||||||
player.etVersion,
|
player.etVersion,
|
||||||
colorScheme,
|
colorScheme,
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
|
||||||
|
// NAT类型
|
||||||
|
_buildInfoRow(
|
||||||
|
_getNatTypeIcon(player.natType),
|
||||||
|
'NAT类型',
|
||||||
|
player.natType,
|
||||||
|
colorScheme,
|
||||||
|
valueColor: _getNatTypeColor(player.natType),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -799,38 +700,6 @@ class _RoomPageState extends State<RoomPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构建对齐的网络数据项
|
|
||||||
Widget _buildNetworkDataItemAligned(
|
|
||||||
String label,
|
|
||||||
String value,
|
|
||||||
IconData icon,
|
|
||||||
Color color,
|
|
||||||
) {
|
|
||||||
return Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Icon(icon, size: 22, color: color),
|
|
||||||
const SizedBox(height: 6),
|
|
||||||
Text(
|
|
||||||
label,
|
|
||||||
style: const TextStyle(fontSize: 13),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 2),
|
|
||||||
Text(
|
|
||||||
value,
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: color,
|
|
||||||
fontSize: 14,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据延迟值获取颜色
|
// 根据延迟值获取颜色
|
||||||
Color _getLatencyColor(int latency) {
|
Color _getLatencyColor(int latency) {
|
||||||
if (latency < 50) {
|
if (latency < 50) {
|
||||||
@@ -907,4 +776,180 @@ class _RoomPageState extends State<RoomPage> {
|
|||||||
return Colors.grey;
|
return Colors.grey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 将NAT类型转换为中文
|
||||||
|
String _mapNatType(String natType) {
|
||||||
|
switch (natType) {
|
||||||
|
case 'Unknown':
|
||||||
|
return '未知';
|
||||||
|
case 'OpenInternet':
|
||||||
|
return '开放网络';
|
||||||
|
case 'NoPat':
|
||||||
|
return '无PAT';
|
||||||
|
case 'FullCone':
|
||||||
|
return '全锥形';
|
||||||
|
case 'Restricted':
|
||||||
|
return '受限锥形';
|
||||||
|
case 'PortRestricted':
|
||||||
|
return '端口受限锥形';
|
||||||
|
case 'Symmetric':
|
||||||
|
return '对称型';
|
||||||
|
case 'SymUdpFirewall':
|
||||||
|
return '对称UDP防火墙';
|
||||||
|
case 'SymmetricEasyInc':
|
||||||
|
return '对称递增型';
|
||||||
|
case 'SymmetricEasyDec':
|
||||||
|
return '对称递减型';
|
||||||
|
default:
|
||||||
|
return '未知';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据NAT类型获取图标
|
||||||
|
IconData _getNatTypeIcon(String natType) {
|
||||||
|
if (natType.contains('开放') || natType.contains('全锥形')) {
|
||||||
|
return Icons.public;
|
||||||
|
} else if (natType.contains('受限')) {
|
||||||
|
return Icons.shield;
|
||||||
|
} else if (natType.contains('端口受限')) {
|
||||||
|
return Icons.security;
|
||||||
|
} else if (natType.contains('对称')) {
|
||||||
|
return Icons.sync_alt;
|
||||||
|
} else if (natType.contains('防火墙')) {
|
||||||
|
return Icons.fireplace;
|
||||||
|
} else if (natType.contains('递增')) {
|
||||||
|
return Icons.trending_up;
|
||||||
|
} else if (natType.contains('递减')) {
|
||||||
|
return Icons.trending_down;
|
||||||
|
} else if (natType.contains('无PAT')) {
|
||||||
|
return Icons.router;
|
||||||
|
} else {
|
||||||
|
return Icons.help_outline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据NAT类型获取颜色
|
||||||
|
Color _getNatTypeColor(String natType) {
|
||||||
|
if (natType.contains('开放') ||
|
||||||
|
natType.contains('全锥形') ||
|
||||||
|
natType.contains('无PAT')) {
|
||||||
|
return Colors.green;
|
||||||
|
} else if (natType.contains('受限') || natType.contains('端口受限')) {
|
||||||
|
return Colors.orange;
|
||||||
|
} else if (natType.contains('对称') || natType.contains('防火墙')) {
|
||||||
|
return Colors.red;
|
||||||
|
} else {
|
||||||
|
return Colors.grey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 玩家搜索委托类
|
||||||
|
class _PlayerSearchDelegate extends SearchDelegate<String> {
|
||||||
|
final List<PlayerInfo> players;
|
||||||
|
final ColorScheme colorScheme;
|
||||||
|
final Function(PlayerInfo, ColorScheme) buildPlayerListItem;
|
||||||
|
|
||||||
|
_PlayerSearchDelegate({
|
||||||
|
required this.players,
|
||||||
|
required this.colorScheme,
|
||||||
|
required this.buildPlayerListItem,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Widget> buildActions(BuildContext context) {
|
||||||
|
return [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.clear),
|
||||||
|
onPressed: () {
|
||||||
|
// 如果搜索框为空,直接返回
|
||||||
|
if (query.isEmpty) {
|
||||||
|
close(context, '');
|
||||||
|
} else {
|
||||||
|
// 否则清空搜索内容
|
||||||
|
query = '';
|
||||||
|
showSuggestions(context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget buildLeading(BuildContext context) {
|
||||||
|
return IconButton(
|
||||||
|
icon: const Icon(Icons.arrow_back),
|
||||||
|
onPressed: () {
|
||||||
|
close(context, '');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget buildResults(BuildContext context) {
|
||||||
|
return _buildSearchResults(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget buildSuggestions(BuildContext context) {
|
||||||
|
return _buildSearchResults(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改方法签名,添加 BuildContext 参数
|
||||||
|
Widget _buildSearchResults(BuildContext context) {
|
||||||
|
final filteredPlayers = query.isEmpty
|
||||||
|
? players
|
||||||
|
: players
|
||||||
|
.where((player) =>
|
||||||
|
player.name.toLowerCase().contains(query.toLowerCase()))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
if (filteredPlayers.isEmpty) {
|
||||||
|
return Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.search_off,
|
||||||
|
size: 64,
|
||||||
|
color: colorScheme.primary.withOpacity(0.6),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text(
|
||||||
|
'未找到匹配的玩家',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: colorScheme.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
'尝试使用其他搜索关键词',
|
||||||
|
style: TextStyle(
|
||||||
|
color: colorScheme.onSurface.withOpacity(0.7),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加对屏幕宽度的检测
|
||||||
|
return LayoutBuilder(
|
||||||
|
builder: (context, constraints) {
|
||||||
|
// 使用约束条件获取当前宽度
|
||||||
|
return ListView.builder(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
itemCount: filteredPlayers.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 16.0),
|
||||||
|
child: buildPlayerListItem(filteredPlayers[index], colorScheme),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'package:astral/utils/app_info.dart';
|
||||||
|
import 'package:astral/utils/up.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '../config/app_config.dart';
|
import '../config/app_config.dart';
|
||||||
import '../utils/ping_util.dart';
|
import '../utils/ping_util.dart';
|
||||||
@@ -11,6 +13,11 @@ class SettingsPage extends StatefulWidget {
|
|||||||
State<SettingsPage> createState() => _SettingsPageState();
|
State<SettingsPage> createState() => _SettingsPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final updateChecker = UpdateChecker(
|
||||||
|
owner: 'ldoubil',
|
||||||
|
repo: 'astral',
|
||||||
|
);
|
||||||
|
|
||||||
class _SettingsPageState extends State<SettingsPage> {
|
class _SettingsPageState extends State<SettingsPage> {
|
||||||
bool _notificationsEnabled = true;
|
bool _notificationsEnabled = true;
|
||||||
double _fontSize = 16.0;
|
double _fontSize = 16.0;
|
||||||
@@ -221,6 +228,7 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
// updateChecker.checkForUpdates(context);
|
||||||
serverIP = Provider.of<KM>(context).virtualIP;
|
serverIP = Provider.of<KM>(context).virtualIP;
|
||||||
return ListView(
|
return ListView(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
@@ -347,18 +355,16 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
Card(
|
Card(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
const ListTile(
|
ListTile(
|
||||||
leading: Icon(Icons.info),
|
leading: Icon(Icons.info),
|
||||||
title: Text('应用版本'),
|
title: Text('应用版本'),
|
||||||
subtitle: Text('灰度版本'),
|
subtitle: Text(AppInfoUtil.getVersion()),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.update),
|
leading: const Icon(Icons.update),
|
||||||
title: const Text('检查更新'),
|
title: const Text('检查更新'),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
updateChecker.checkForUpdates(context);
|
||||||
const SnackBar(content: Text('灰度版本不支持更新')),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -0,0 +1,291 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:math';
|
||||||
|
import 'package:astral/utils/app_info.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
|
class UpdateChecker {
|
||||||
|
/// GitHub 仓库所有者
|
||||||
|
final String owner;
|
||||||
|
|
||||||
|
/// GitHub 仓库名称
|
||||||
|
final String repo;
|
||||||
|
|
||||||
|
/// 可选:指定检查的分支名称,默认为 'main'
|
||||||
|
final String branch;
|
||||||
|
|
||||||
|
UpdateChecker({
|
||||||
|
required this.owner,
|
||||||
|
required this.repo,
|
||||||
|
this.branch = 'main',
|
||||||
|
});
|
||||||
|
|
||||||
|
/// 检查更新
|
||||||
|
Future<void> scheckForUpdates(BuildContext context) async {
|
||||||
|
try {
|
||||||
|
final releaseInfo = await _fetchLatestRelease();
|
||||||
|
if (releaseInfo == null) {
|
||||||
|
_showUpdateDialog(
|
||||||
|
// 添加空值处理
|
||||||
|
context,
|
||||||
|
'检查更新失败',
|
||||||
|
'无法获取最新版本信息',
|
||||||
|
'https://github.com/$owner/$repo/releases',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前应用版本
|
||||||
|
final currentVersion = await _getCurrentVersion();
|
||||||
|
|
||||||
|
// 比较版本号,如果有新版本则显示更新弹窗
|
||||||
|
if (_shouldUpdate(currentVersion, releaseInfo['tag_name'])) {
|
||||||
|
_showUpdateDialog(
|
||||||
|
context,
|
||||||
|
releaseInfo['tag_name'],
|
||||||
|
releaseInfo['body'] ?? '新版本已发布',
|
||||||
|
releaseInfo['html_url'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
_showUpdateDialog(
|
||||||
|
context,
|
||||||
|
'更新检查失败',
|
||||||
|
'检查更新时发生错误: $e',
|
||||||
|
'https://github.com/$owner/$repo/releases',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> checkForUpdates(BuildContext context) async {
|
||||||
|
try {
|
||||||
|
final releaseInfo = await _fetchLatestRelease();
|
||||||
|
if (releaseInfo == null) {
|
||||||
|
_showUpdateDialog(
|
||||||
|
// 添加空值处理
|
||||||
|
context,
|
||||||
|
'检查更新失败',
|
||||||
|
'无法获取最新版本信息',
|
||||||
|
'https://github.com/$owner/$repo/releases',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前应用版本
|
||||||
|
final currentVersion = await _getCurrentVersion();
|
||||||
|
|
||||||
|
// 比较版本号,如果有新版本则显示更新弹窗
|
||||||
|
if (_shouldUpdate(currentVersion, releaseInfo['tag_name'])) {
|
||||||
|
_showUpdateDialog(
|
||||||
|
context,
|
||||||
|
releaseInfo['tag_name'],
|
||||||
|
releaseInfo['body'] ?? '新版本已发布',
|
||||||
|
releaseInfo['html_url'],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
_showUpdateDialog(
|
||||||
|
context,
|
||||||
|
'当前已是最新版本',
|
||||||
|
'当前版本为: $currentVersion',
|
||||||
|
'https://github.com/$owner/$repo/releases',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
_showUpdateDialog(
|
||||||
|
context,
|
||||||
|
'更新检查失败',
|
||||||
|
'检查更新时发生错误: $e',
|
||||||
|
'https://github.com/$owner/$repo/releases',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取最新发布版本信息
|
||||||
|
Future<Map<String, dynamic>?> _fetchLatestRelease() async {
|
||||||
|
try {
|
||||||
|
// 添加异常捕获
|
||||||
|
final response = await http.get(
|
||||||
|
Uri.parse('https://api.github.com/repos/$owner/$repo/releases'),
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/vnd.github.v3+json',
|
||||||
|
'User-Agent': 'astral',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final List<dynamic> releases = json.decode(response.body);
|
||||||
|
if (releases.isEmpty) return null;
|
||||||
|
|
||||||
|
// 获取第一个发布版本(最新版本)
|
||||||
|
return releases[0];
|
||||||
|
} else {
|
||||||
|
debugPrint('获取最新版本失败: ${response.statusCode}');
|
||||||
|
return {
|
||||||
|
// 返回错误信息
|
||||||
|
'tag_name': '错误 ${response.statusCode}',
|
||||||
|
'body': '请求GitHub API失败',
|
||||||
|
'html_url': 'https://github.com/$owner/$repo/releases'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('网络请求异常: $e');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取当前应用版本
|
||||||
|
Future<String> _getCurrentVersion() async {
|
||||||
|
try {
|
||||||
|
return AppInfoUtil.getVersion();
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('获取版本信息失败: $e');
|
||||||
|
return "0.0.0"; // 返回默认版本号避免后续比较崩溃
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 比较版本号,判断是否需要更新
|
||||||
|
bool _shouldUpdate(String currentVersion, String latestVersion) {
|
||||||
|
// 确保版本号格式正确(添加v前缀如果没有)
|
||||||
|
final current = currentVersion.startsWith('v')
|
||||||
|
? currentVersion.substring(1)
|
||||||
|
: currentVersion;
|
||||||
|
final latest = latestVersion.startsWith('v')
|
||||||
|
? latestVersion.substring(1)
|
||||||
|
: latestVersion;
|
||||||
|
|
||||||
|
// 处理预发布版本标签(如 -alpha, -beta 等)
|
||||||
|
String currentClean = current;
|
||||||
|
String latestClean = latest;
|
||||||
|
|
||||||
|
if (current.contains('-')) {
|
||||||
|
currentClean = current.split('-')[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (latest.contains('-')) {
|
||||||
|
latestClean = latest.split('-')[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分割版本号为数组
|
||||||
|
final currentParts = currentClean.split('.');
|
||||||
|
final latestParts = latestClean.split('.');
|
||||||
|
|
||||||
|
// 比较主版本号、次版本号和修订号
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
final currentPart =
|
||||||
|
i < currentParts.length ? int.parse(currentParts[i]) : 0;
|
||||||
|
final latestPart = i < latestParts.length ? int.parse(latestParts[i]) : 0;
|
||||||
|
|
||||||
|
if (latestPart > currentPart) {
|
||||||
|
return true;
|
||||||
|
} else if (latestPart < currentPart) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 版本号相同,检查预发布标签
|
||||||
|
if (current.contains('-') && !latest.contains('-')) {
|
||||||
|
// 当前是预发布版本,而最新是正式版本
|
||||||
|
return true;
|
||||||
|
} else if (!current.contains('-') && latest.contains('-')) {
|
||||||
|
// 当前是正式版本,而最新是预发布版本
|
||||||
|
return false;
|
||||||
|
} else if (current.contains('-') && latest.contains('-')) {
|
||||||
|
// 两者都是预发布版本,比较预发布标签
|
||||||
|
final currentPreRelease = current.split('-')[1];
|
||||||
|
final latestPreRelease = latest.split('-')[1];
|
||||||
|
|
||||||
|
// 简单比较预发布标签(alpha < beta < rc)
|
||||||
|
if (currentPreRelease.startsWith('alpha') &&
|
||||||
|
(latestPreRelease.startsWith('beta') ||
|
||||||
|
latestPreRelease.startsWith('rc'))) {
|
||||||
|
return true;
|
||||||
|
} else if (currentPreRelease.startsWith('beta') &&
|
||||||
|
latestPreRelease.startsWith('rc')) {
|
||||||
|
return true;
|
||||||
|
} else if (currentPreRelease == latestPreRelease) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果预发布标签包含数字(如 beta.1, beta.2),则比较数字部分
|
||||||
|
if (currentPreRelease.contains('.') &&
|
||||||
|
latestPreRelease.contains('.') &&
|
||||||
|
currentPreRelease.split('.')[0] == latestPreRelease.split('.')[0]) {
|
||||||
|
try {
|
||||||
|
final currentNum = int.parse(currentPreRelease.split('.')[1]);
|
||||||
|
final latestNum = int.parse(latestPreRelease.split('.')[1]);
|
||||||
|
return latestNum > currentNum;
|
||||||
|
} catch (e) {
|
||||||
|
// 解析失败,返回简单比较结果
|
||||||
|
return latestPreRelease.compareTo(currentPreRelease) > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认比较预发布标签的字符串
|
||||||
|
return latestPreRelease.compareTo(currentPreRelease) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // 版本相同,不需要更新
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 显示更新弹窗
|
||||||
|
void _showUpdateDialog(
|
||||||
|
BuildContext context,
|
||||||
|
String version,
|
||||||
|
String releaseNotes,
|
||||||
|
String downloadUrl,
|
||||||
|
) {
|
||||||
|
final isLatestVersion = version.contains("当前已是最新版本");
|
||||||
|
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: Text(isLatestVersion ? version : '发现新版本: $version'),
|
||||||
|
content: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
if (!isLatestVersion) Text('更新内容:'),
|
||||||
|
if (!isLatestVersion) const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
releaseNotes,
|
||||||
|
style: const TextStyle(fontSize: 14),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: const Text('稍后再说'),
|
||||||
|
),
|
||||||
|
if (!isLatestVersion) // 仅在新版本弹窗显示更新按钮
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
_launchUrl(downloadUrl);
|
||||||
|
},
|
||||||
|
child: const Text('立即更新'),
|
||||||
|
),
|
||||||
|
if (isLatestVersion) // 最新版本显示确认按钮
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: const Text('确定'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 打开浏览器跳转到下载链接
|
||||||
|
Future<void> _launchUrl(String url) async {
|
||||||
|
final uri = Uri.parse(url);
|
||||||
|
if (await canLaunchUrl(uri)) {
|
||||||
|
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||||
|
} else {
|
||||||
|
debugPrint('无法打开链接: $url');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,21 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:window_manager/window_manager.dart';
|
import 'package:window_manager/window_manager.dart';
|
||||||
import '../config/app_config.dart';
|
import '../config/app_config.dart';
|
||||||
import 'package:tray_manager/tray_manager.dart';
|
import 'package:windows_notification/notification_message.dart';
|
||||||
|
import 'package:windows_notification/windows_notification.dart';
|
||||||
|
|
||||||
|
// Create an instance of Windows Notification with your application name
|
||||||
|
// application id must be null in packaged mode
|
||||||
|
final _winNotifyPlugin = WindowsNotification(applicationId: 'Astral');
|
||||||
|
// create new NotificationMessage instance with id, title, body, and images
|
||||||
|
NotificationMessage message = NotificationMessage.fromPluginTemplate(
|
||||||
|
"astral_minimized",
|
||||||
|
"Astral 已最小化到托盘",
|
||||||
|
"应用程序正在后台运行,点击托盘图标可以恢复窗口",
|
||||||
|
// largeImage: "assets/images/icon.ico",
|
||||||
|
// image: file_path
|
||||||
|
);
|
||||||
|
|
||||||
class WindowControls extends StatelessWidget {
|
class WindowControls extends StatelessWidget {
|
||||||
const WindowControls({super.key});
|
const WindowControls({super.key});
|
||||||
|
|
||||||
@@ -26,17 +40,18 @@ class WindowControls extends StatelessWidget {
|
|||||||
tooltip: '最大化/还原',
|
tooltip: '最大化/还原',
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.close),
|
icon: const Icon(Icons.close),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (AppConfig().closeToTray) {
|
if (AppConfig().closeToTray) {
|
||||||
await windowManager.hide(); // 隐藏主窗口
|
await windowManager.hide(); // 隐藏主窗口
|
||||||
await trayManager.setToolTip('FLN2N 正在后台运行'); // 设置托盘提示
|
// 替换托盘提示为系统通知
|
||||||
} else {
|
_winNotifyPlugin.showNotificationPluginTemplate(message);
|
||||||
windowManager.close();
|
} else {
|
||||||
}
|
windowManager.close();
|
||||||
},
|
}
|
||||||
tooltip: '关闭',
|
},
|
||||||
),
|
tooltip: '关闭',
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
[ ] 更换为官方服务器
|
[x] 更换为官方服务器
|
||||||
[ ] 添加服务器多选
|
[x] 移除模拟延迟(对其实不用等待2秒的那个是模拟的我给忘了)->改为检测是否成功连接
|
||||||
[ ] 移除模拟延迟(对其实不用等待2秒的那个是模拟的我给忘了)->改为检测是否成功连接
|
[x] 修复延迟计算:从peer连接获取最小延迟(μs->ms),无效则用路由延迟
|
||||||
[ ] 修复延迟计算:从peer连接获取最小延迟(μs->ms),无效则用路由延迟
|
|
||||||
[x] 管理员问题没权限
|
[x] 管理员问题没权限
|
||||||
[ ] 配置信息改为运行目录
|
[x] 配置信息改为运行目录
|
||||||
[ ] 看nat类型
|
[x] 看nat类型
|
||||||
[x] 缩放尺寸让导航栏变为底部会导致页面状态丢失
|
[x] 缩放尺寸让导航栏变为底部会导致页面状态丢失
|
||||||
[x] 服务器始终检测延迟,去除暂停和开始反正也不怎么影响性能多此一举还增加复杂度😜
|
[x] 服务器始终检测延迟,去除暂停和开始反正也不怎么影响性能多此一举还增加复杂度😜
|
||||||
[x] 增加自动更新检测 和自动更新
|
[x] 最小化提供通知
|
||||||
|
[x] 可以直接搜索玩家
|
||||||
|
[ ] 增加自动更新检测 和自动更新
|
||||||
[ ] 那就打包两个版本 一个便携版(配置文件随软件) 一个安装版(配置文件随软件)
|
[ ] 那就打包两个版本 一个便携版(配置文件随软件) 一个安装版(配置文件随软件)
|
||||||
@@ -185,6 +185,14 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.1"
|
||||||
|
dbus:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: dbus
|
||||||
|
sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "0.7.11"
|
||||||
equatable:
|
equatable:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -259,6 +267,38 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.0.0"
|
version: "5.0.0"
|
||||||
|
flutter_local_notifications:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_local_notifications
|
||||||
|
sha256: d59eeafd6df92174b1d5f68fc9d66634c97ce2e7cfe2293476236547bb19bbbd
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "19.0.0"
|
||||||
|
flutter_local_notifications_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_local_notifications_linux
|
||||||
|
sha256: e3c277b2daab8e36ac5a6820536668d07e83851aeeb79c446e525a70710770a5
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "6.0.0"
|
||||||
|
flutter_local_notifications_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_local_notifications_platform_interface
|
||||||
|
sha256: "2569b973fc9d1f63a37410a9f7c1c552081226c597190cb359ef5d5762d1631c"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "9.0.0"
|
||||||
|
flutter_local_notifications_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_local_notifications_windows
|
||||||
|
sha256: f8fc0652a601f83419d623c85723a3e82ad81f92b33eaa9bcc21ea1b94773e6e
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
flutter_localizations:
|
flutter_localizations:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -532,6 +572,14 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.0"
|
version: "2.3.0"
|
||||||
|
petitparser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: petitparser
|
||||||
|
sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "6.1.0"
|
||||||
platform:
|
platform:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -808,6 +856,14 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.4"
|
version: "0.7.4"
|
||||||
|
timezone:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: timezone
|
||||||
|
sha256: ffc9d5f4d1193534ef051f9254063fa53d588609418c84299956c3db9383587d
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "0.10.0"
|
||||||
timing:
|
timing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -976,6 +1032,14 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.3"
|
version: "0.4.3"
|
||||||
|
windows_notification:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: windows_notification
|
||||||
|
sha256: be3e650874615f315402c9b9f3656e29af156709c4b5cc272cb4ca0ab7ba94a8
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.0"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -984,6 +1048,14 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.0"
|
||||||
|
xml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xml
|
||||||
|
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "6.5.0"
|
||||||
yaml:
|
yaml:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ dependencies:
|
|||||||
url_launcher: ^6.3.1
|
url_launcher: ^6.3.1
|
||||||
package_info_plus: ^8.3.0 # 添加这一行
|
package_info_plus: ^8.3.0 # 添加这一行
|
||||||
yaml: ^3.1.2
|
yaml: ^3.1.2
|
||||||
|
flutter_local_notifications: ^19.0.0
|
||||||
|
windows_notification: ^1.3.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
@@ -5,56 +5,56 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: _fe_analyzer_shared
|
name: _fe_analyzer_shared
|
||||||
sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051
|
sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "64.0.0"
|
version: "67.0.0"
|
||||||
adaptive_number:
|
adaptive_number:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: adaptive_number
|
name: adaptive_number
|
||||||
sha256: "3a567544e9b5c9c803006f51140ad544aedc79604fd4f3f2c1380003f97c1d77"
|
sha256: "3a567544e9b5c9c803006f51140ad544aedc79604fd4f3f2c1380003f97c1d77"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
analyzer:
|
analyzer:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: analyzer
|
name: analyzer
|
||||||
sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893"
|
sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.2.0"
|
version: "6.4.1"
|
||||||
args:
|
args:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: args
|
name: args
|
||||||
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
|
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.2"
|
version: "2.4.2"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: async
|
name: async
|
||||||
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
|
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.11.0"
|
version: "2.13.0"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: boolean_selector
|
name: boolean_selector
|
||||||
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
|
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.2"
|
||||||
collection:
|
collection:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: collection
|
name: collection
|
||||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.18.0"
|
version: "1.18.0"
|
||||||
convert:
|
convert:
|
||||||
@@ -62,23 +62,23 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: convert
|
name: convert
|
||||||
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
|
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.1"
|
version: "3.1.1"
|
||||||
coverage:
|
coverage:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: coverage
|
name: coverage
|
||||||
sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097"
|
sha256: e3493833ea012784c740e341952298f1cc77f1f01b1bbc3eb4eecf6984fb7f43
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.6.3"
|
version: "1.11.1"
|
||||||
crypto:
|
crypto:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: crypto
|
name: crypto
|
||||||
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.3"
|
version: "3.0.3"
|
||||||
ed25519_edwards:
|
ed25519_edwards:
|
||||||
@@ -86,7 +86,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: ed25519_edwards
|
name: ed25519_edwards
|
||||||
sha256: "6ce0112d131327ec6d42beede1e5dfd526069b18ad45dcf654f15074ad9276cd"
|
sha256: "6ce0112d131327ec6d42beede1e5dfd526069b18ad45dcf654f15074ad9276cd"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.1"
|
version: "0.3.1"
|
||||||
file:
|
file:
|
||||||
@@ -94,47 +94,47 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: file
|
name: file
|
||||||
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
|
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.1.4"
|
version: "6.1.4"
|
||||||
fixnum:
|
fixnum:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: fixnum
|
name: fixnum
|
||||||
sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1"
|
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.1"
|
||||||
frontend_server_client:
|
frontend_server_client:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: frontend_server_client
|
name: frontend_server_client
|
||||||
sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612"
|
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.2.0"
|
version: "4.0.0"
|
||||||
github:
|
github:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: github
|
name: github
|
||||||
sha256: "9966bc13bf612342e916b0a343e95e5f046c88f602a14476440e9b75d2295411"
|
sha256: "9966bc13bf612342e916b0a343e95e5f046c88f602a14476440e9b75d2295411"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "9.17.0"
|
version: "9.17.0"
|
||||||
glob:
|
glob:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: glob
|
name: glob
|
||||||
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
|
sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.3"
|
||||||
hex:
|
hex:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: hex
|
name: hex
|
||||||
sha256: "4e7cd54e4b59ba026432a6be2dd9d96e4c5205725194997193bf871703b82c4a"
|
sha256: "4e7cd54e4b59ba026432a6be2dd9d96e4c5205725194997193bf871703b82c4a"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0"
|
version: "0.2.0"
|
||||||
http:
|
http:
|
||||||
@@ -142,55 +142,55 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: http
|
name: http
|
||||||
sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525"
|
sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.0"
|
||||||
http_multi_server:
|
http_multi_server:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: http_multi_server
|
name: http_multi_server
|
||||||
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
|
sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.2.1"
|
version: "3.2.2"
|
||||||
http_parser:
|
http_parser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: http_parser
|
name: http_parser
|
||||||
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
|
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.2"
|
version: "4.0.2"
|
||||||
io:
|
io:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: io
|
name: io
|
||||||
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
|
sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "1.0.5"
|
||||||
js:
|
js:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: js
|
name: js
|
||||||
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.7"
|
version: "0.7.2"
|
||||||
json_annotation:
|
json_annotation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: json_annotation
|
name: json_annotation
|
||||||
sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467
|
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.8.1"
|
version: "4.9.0"
|
||||||
lints:
|
lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: lints
|
name: lints
|
||||||
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
|
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.1"
|
||||||
logging:
|
logging:
|
||||||
@@ -198,55 +198,55 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: logging
|
name: logging
|
||||||
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
|
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.2.0"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.16"
|
version: "0.12.17"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
|
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.1"
|
version: "1.16.0"
|
||||||
mime:
|
mime:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: mime
|
name: mime
|
||||||
sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
|
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "2.0.0"
|
||||||
node_preamble:
|
node_preamble:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: node_preamble
|
name: node_preamble
|
||||||
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
|
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.2"
|
version: "2.0.2"
|
||||||
package_config:
|
package_config:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: package_config
|
name: package_config
|
||||||
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
|
sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.2.0"
|
||||||
path:
|
path:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path
|
name: path
|
||||||
sha256: "2ad4cddff7f5cc0e2d13069f2a3f7a73ca18f66abd6f5ecf215219cdb3638edb"
|
sha256: "2ad4cddff7f5cc0e2d13069f2a3f7a73ca18f66abd6f5ecf215219cdb3638edb"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.0"
|
version: "1.8.0"
|
||||||
petitparser:
|
petitparser:
|
||||||
@@ -254,7 +254,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: petitparser
|
name: petitparser
|
||||||
sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
|
sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.4.0"
|
version: "5.4.0"
|
||||||
pool:
|
pool:
|
||||||
@@ -262,23 +262,23 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: pool
|
name: pool
|
||||||
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
|
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.1"
|
version: "1.5.1"
|
||||||
pub_semver:
|
pub_semver:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: pub_semver
|
name: pub_semver
|
||||||
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
|
sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.2.0"
|
||||||
shelf:
|
shelf:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shelf
|
name: shelf
|
||||||
sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
|
sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.1"
|
version: "1.4.1"
|
||||||
shelf_packages_handler:
|
shelf_packages_handler:
|
||||||
@@ -286,168 +286,184 @@ packages:
|
|||||||
description:
|
description:
|
||||||
name: shelf_packages_handler
|
name: shelf_packages_handler
|
||||||
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
|
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.2"
|
version: "3.0.2"
|
||||||
shelf_static:
|
shelf_static:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shelf_static
|
name: shelf_static
|
||||||
sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e
|
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.2"
|
version: "1.1.3"
|
||||||
shelf_web_socket:
|
shelf_web_socket:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shelf_web_socket
|
name: shelf_web_socket
|
||||||
sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1"
|
sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.4"
|
version: "3.0.0"
|
||||||
source_map_stack_trace:
|
source_map_stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: source_map_stack_trace
|
name: source_map_stack_trace
|
||||||
sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae"
|
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.2"
|
||||||
source_maps:
|
source_maps:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: source_maps
|
name: source_maps
|
||||||
sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703"
|
sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.10.12"
|
version: "0.10.13"
|
||||||
source_span:
|
source_span:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: source_span
|
name: source_span
|
||||||
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.10.0"
|
version: "1.10.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: stack_trace
|
name: stack_trace
|
||||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.11.1"
|
version: "1.12.1"
|
||||||
stream_channel:
|
stream_channel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: stream_channel
|
name: stream_channel
|
||||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.4"
|
||||||
string_scanner:
|
string_scanner:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: string_scanner
|
name: string_scanner
|
||||||
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
|
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.4.1"
|
||||||
term_glyph:
|
term_glyph:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: term_glyph
|
name: term_glyph
|
||||||
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
|
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.1"
|
version: "1.2.2"
|
||||||
test:
|
test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: test
|
name: test
|
||||||
sha256: "9b0dd8e36af4a5b1569029949d50a52cb2a2a2fdaa20cebb96e6603b9ae241f9"
|
sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.24.6"
|
version: "1.25.15"
|
||||||
test_api:
|
test_api:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.1"
|
version: "0.7.4"
|
||||||
test_core:
|
test_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_core
|
name: test_core
|
||||||
sha256: "4bef837e56375537055fdbbbf6dd458b1859881f4c7e6da936158f77d61ab265"
|
sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.6"
|
version: "0.6.8"
|
||||||
toml:
|
toml:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: toml
|
name: toml
|
||||||
sha256: "157c5dca5160fced243f3ce984117f729c788bb5e475504f3dbcda881accee44"
|
sha256: "157c5dca5160fced243f3ce984117f729c788bb5e475504f3dbcda881accee44"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.14.0"
|
version: "0.14.0"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: typed_data
|
name: typed_data
|
||||||
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
|
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.2"
|
version: "1.4.0"
|
||||||
version:
|
version:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: version
|
name: version
|
||||||
sha256: "2307e23a45b43f96469eeab946208ed63293e8afca9c28cd8b5241ff31c55f55"
|
sha256: "2307e23a45b43f96469eeab946208ed63293e8afca9c28cd8b5241ff31c55f55"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.0"
|
version: "3.0.0"
|
||||||
vm_service:
|
vm_service:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vm_service
|
name: vm_service
|
||||||
sha256: "0fae432c85c4ea880b33b497d32824b97795b04cdaa74d270219572a1f50268d"
|
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "11.9.0"
|
version: "15.0.0"
|
||||||
watcher:
|
watcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: watcher
|
name: watcher
|
||||||
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
|
sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.1"
|
||||||
|
web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web
|
||||||
|
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.1"
|
||||||
|
web_socket:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web_socket
|
||||||
|
sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.6"
|
||||||
web_socket_channel:
|
web_socket_channel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: web_socket_channel
|
name: web_socket_channel
|
||||||
sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
|
sha256: "0b8e2457400d8a859b7b2030786835a28a8e80836ef64402abef392ff4f1d0e5"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.0"
|
version: "3.0.2"
|
||||||
webkit_inspection_protocol:
|
webkit_inspection_protocol:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: webkit_inspection_protocol
|
name: webkit_inspection_protocol
|
||||||
sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d"
|
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.2.1"
|
||||||
yaml:
|
yaml:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: yaml
|
name: yaml
|
||||||
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "3.1.2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.0.0 <4.0.0"
|
dart: ">=3.7.0-0 <4.0.0"
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <tray_manager/tray_manager_plugin.h>
|
#include <tray_manager/tray_manager_plugin.h>
|
||||||
#include <url_launcher_windows/url_launcher_windows.h>
|
#include <url_launcher_windows/url_launcher_windows.h>
|
||||||
#include <window_manager/window_manager_plugin.h>
|
#include <window_manager/window_manager_plugin.h>
|
||||||
|
#include <windows_notification/windows_notification_plugin_c_api.h>
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar(
|
ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar(
|
||||||
@@ -23,4 +24,6 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
|||||||
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||||
WindowManagerPluginRegisterWithRegistrar(
|
WindowManagerPluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("WindowManagerPlugin"));
|
registry->GetRegistrarForPlugin("WindowManagerPlugin"));
|
||||||
|
WindowsNotificationPluginCApiRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("WindowsNotificationPluginCApi"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
tray_manager
|
tray_manager
|
||||||
url_launcher_windows
|
url_launcher_windows
|
||||||
window_manager
|
window_manager
|
||||||
|
windows_notification
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
flutter_local_notifications_windows
|
||||||
rust_lib_fltier
|
rust_lib_fltier
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user