merge: 将 develop 同步到 release/v1.0.0

This commit is contained in:
Zhou Weidong committed 2026-10-20 22:23:32 +08:00
commit 182b7e3ac2
5 files changed
+105 -65

No files matched your search

+4 -5
View File
@@ -11,11 +11,10 @@ import 'package:flutter/foundation.dart';
class AppConfig {
const AppConfig._();
/// 真机默认使用的开发机局域网地址。
/// 开发调试默认服务地址,当前直接指向公网。
///
/// 这个地址跟着电脑所在的网络走,换网络后要用
/// `ipconfig getifaddr en0` 重新确认。默认值只改这一行。
static const String devHostBaseUrl = 'http://192.168.31.187:8081';
/// 需要切换局域网联调时只改这一行,地址不要带结尾斜杠。
static const String devHostBaseUrl = 'http://39.162.50.99:8081';
/// 本机后端地址:通过 `adb reverse tcp:8081 tcp:8081` 映射到开发机,
/// 探测可达时 App 直连本机服务;不可达时回落到公网地址。
@@ -38,7 +37,7 @@ class AppConfig {
static const List<String> _probeCandidates = [
lanBaseUrl,
devHostBaseUrl,
publicBaseUrl,
if (devHostBaseUrl != publicBaseUrl) publicBaseUrl,
];
/// Build-time server URL supplied through `--dart-define=API_BASE_URL`.
+26 -28
View File
@@ -43,37 +43,35 @@ class AppBottomNav extends StatelessWidget {
@override
Widget build(BuildContext context) {
final bar = Container(
key: barKey,
height: AppDimens.navHeight,
decoration: BoxDecoration(
color: dark ? Colors.black : backgroundColor.withValues(alpha: 0.95),
border: Border(
top: BorderSide(color: dark ? Colors.white12 : AppColors.border),
),
),
child: Row(
children: [
for (final item in items)
_NavDestination(
item: item,
unselectedColor: dark ? Colors.white70 : AppColors.navUnselected,
),
],
),
);
if (dark) {
return ColoredBox(
color: Colors.black,
child: SafeArea(top: false, child: bar),
);
}
return ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 20, sigmaY: 20),
child: SafeArea(
top: false,
child: Container(
key: barKey,
height: AppDimens.navHeight,
decoration: BoxDecoration(
color: dark
? const Color(0xE6000000)
: backgroundColor.withValues(alpha: 0.95),
border: Border(
top: BorderSide(
color: dark ? Colors.white12 : AppColors.border,
),
),
),
child: Row(
children: [
for (final item in items)
_NavDestination(
item: item,
unselectedColor: dark
? Colors.white70
: AppColors.navUnselected,
),
],
),
),
),
child: SafeArea(top: false, child: bar),
),
);
}
+10 -31
View File
@@ -62,8 +62,8 @@ void main() {
);
});
test('should_use_the_configured_lan_address_for_device_default', () {
expect(AppConfig.devHostBaseUrl, 'http://192.168.31.187:8081');
test('should_use_the_configured_public_address_for_device_default', () {
expect(AppConfig.devHostBaseUrl, 'http://39.162.50.99:8081');
});
test('should_skip_probe_when_compiled_override_is_set', () async {
@@ -111,11 +111,7 @@ void main() {
},
);
expect(attempts, [
AppConfig.lanBaseUrl,
AppConfig.devHostBaseUrl,
AppConfig.publicBaseUrl,
]);
expect(attempts, [AppConfig.lanBaseUrl, AppConfig.devHostBaseUrl]);
expect(AppConfig.apiBaseUrl, AppConfig.publicBaseUrl);
});
@@ -133,7 +129,7 @@ void main() {
attempts.add(baseUrl);
active++;
if (active > maxActive) maxActive = active;
if (active == 3) allStarted.complete();
if (active == 2) allStarted.complete();
await allStarted.future;
active--;
return baseUrl == AppConfig.lanBaseUrl ||
@@ -143,17 +139,13 @@ void main() {
await probing.timeout(const Duration(seconds: 1));
expect(attempts, [
AppConfig.lanBaseUrl,
AppConfig.devHostBaseUrl,
AppConfig.publicBaseUrl,
]);
expect(maxActive, 3);
expect(attempts, [AppConfig.lanBaseUrl, AppConfig.devHostBaseUrl]);
expect(maxActive, 2);
expect(AppConfig.apiBaseUrl, AppConfig.lanBaseUrl);
},
);
test('should_probe_loopback_dev_host_then_public_in_order', () async {
test('should_probe_loopback_then_public_in_order', () async {
final attempts = <String>[];
await AppConfig.probeAndApplyBaseUrl(
@@ -164,11 +156,7 @@ void main() {
},
);
expect(attempts, [
AppConfig.lanBaseUrl,
AppConfig.devHostBaseUrl,
AppConfig.publicBaseUrl,
]);
expect(attempts, [AppConfig.lanBaseUrl, AppConfig.devHostBaseUrl]);
expect(AppConfig.apiBaseUrl, AppConfig.publicBaseUrl);
});
@@ -183,11 +171,7 @@ void main() {
},
);
expect(attempts, [
AppConfig.lanBaseUrl,
AppConfig.devHostBaseUrl,
AppConfig.publicBaseUrl,
]);
expect(attempts, [AppConfig.lanBaseUrl, AppConfig.devHostBaseUrl]);
expect(AppConfig.apiBaseUrl, AppConfig.devHostBaseUrl);
});
@@ -203,12 +187,7 @@ void main() {
},
);
expect(attempts, [
custom,
AppConfig.lanBaseUrl,
AppConfig.devHostBaseUrl,
AppConfig.publicBaseUrl,
]);
expect(attempts, [custom, AppConfig.lanBaseUrl, AppConfig.devHostBaseUrl]);
expect(AppConfig.apiBaseUrl, custom);
});
+64
View File
@@ -82,4 +82,68 @@ void main() {
await tester.tap(find.byKey(const Key('tab-theater')));
expect(theaterTaps, 1);
});
testWidgets('should_fill_dark_bottom_safe_area_with_black_background', (
tester,
) async {
const barKey = Key('dark-nav-bar');
await tester.pumpWidget(
MaterialApp(
home: MediaQuery(
data: const MediaQueryData(padding: EdgeInsets.only(bottom: 34)),
child: Scaffold(
bottomNavigationBar: AppBottomNav(
dark: true,
barKey: barKey,
items: [
AppBottomNavItem(
tabKey: const Key('tab-home'),
icon: Icons.movie_outlined,
selectedIcon: Icons.movie_rounded,
label: 'Home',
selected: true,
onTap: () {},
),
AppBottomNavItem(
tabKey: const Key('tab-theater'),
icon: Icons.explore_outlined,
selectedIcon: Icons.explore_rounded,
label: 'Theater',
onTap: () {},
),
AppBottomNavItem(
tabKey: const Key('tab-create'),
icon: Icons.add_box_outlined,
selectedIcon: Icons.add_box_rounded,
label: 'Create',
onTap: () {},
),
AppBottomNavItem(
tabKey: const Key('tab-mine'),
icon: Icons.person_outline_rounded,
selectedIcon: Icons.person_rounded,
label: 'Me',
onTap: () {},
),
],
),
),
),
),
);
expect(
tester.getSize(find.byType(AppBottomNav)).height,
AppDimens.navHeight + 34,
);
expect(tester.getSize(find.byKey(barKey)).height, AppDimens.navHeight);
final coloredBox = tester.widget<ColoredBox>(
find.descendant(
of: find.byType(AppBottomNav),
matching: find.byType(ColoredBox),
),
);
expect(coloredBox.color, Colors.black);
});
}
+1 -1
View File
@@ -53,7 +53,7 @@ void main() {
final decoration = bar.decoration as BoxDecoration;
final border = decoration.border as Border;
// 首页 feed 用深色导航。
expect(decoration.color, const Color(0xE6000000));
expect(decoration.color, Colors.black);
expect(border.top.color, Colors.white12);
expect(
tester