Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions lib/core/config/app_config.dart
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import 'dart:io' show Platform;

import 'package:flutter/foundation.dart' show kIsWeb;

/// App 設定:API 位址可透過 --dart-define=API_BASE=... 覆寫。
/// 未覆寫時依平台給「模擬器連本機後端」的預設值:
/// Android 模擬器是 10.0.2.2,iOS/macOS 模擬器是 127.0.0.1(10.0.2.2 只有 Android 模擬器認得)。
/// Web 是瀏覽器直接連,用 localhost。
/// 真機一律請帶 --dart-define=API_BASE=http://<電腦區網 IP>:8080。
class AppConfig {
static const _apiBaseOverride = String.fromEnvironment('API_BASE');

static String get apiBase {
if (_apiBaseOverride.isNotEmpty) return _apiBaseOverride;

// kIsWeb 是編譯期常數,這一行讓下面的 dart:io 分支在 web build 被整段
// 消除。少了它,沒帶 --dart-define=API_BASE 在瀏覽器開啟就會噴
// 「Unsupported operation: Platform._operatingSystem」——那個訊息完全
// 看不出跟 API 位址有關,排查成本很高。
if (kIsWeb) return 'http://localhost:8080';

return (Platform.isIOS || Platform.isMacOS)
? 'http://127.0.0.1:8080'
: 'http://10.0.2.2:8080';
Expand Down
62 changes: 62 additions & 0 deletions lib/core/platform/web_unsupported.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import 'package:flutter/material.dart';

/// 司機端不支援 web,這裡負責「講清楚」而不是讓它在半路炸掉。
///
/// 司機端依賴背景定位、系統定位權限對話框與 `dart:io` 的 `Platform`,
/// 這些在瀏覽器都沒有對應實作。沒有這道攔截的話,`flutter run -d chrome`
/// (預設進入點就是司機端)會噴
/// 「Unsupported operation: Platform._operatingSystem」——訊息完全看不出
/// 是「平台選錯了」,排查成本很高。
void runDriverWebUnsupportedApp() {
runApp(const _WebUnsupportedApp());
}

class _WebUnsupportedApp extends StatelessWidget {
const _WebUnsupportedApp();

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fleet 司機',
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 460),
child: Padding(
padding: const EdgeInsets.all(32),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'司機端不支援瀏覽器',
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: 12),
const Text(
'司機端需要背景定位與系統定位權限,瀏覽器沒有對應能力。'
'請改跑 Android 或 iOS。',
),
const SizedBox(height: 20),
const Text('瀏覽器只支援乘客端:'),
const SizedBox(height: 6),
SelectableText(
'flutter run -d chrome -t lib/main_customer.dart',
style: TextStyle(
fontFamily: 'monospace',
backgroundColor: Colors.black.withValues(alpha: 0.06),
),
),
],
),
),
),
),
),
);
}
}
9 changes: 9 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';

import 'package:line_fleet_app/core/platform/web_unsupported.dart';
import 'package:line_fleet_app/core/push/firebase_push_service.dart';
import 'package:line_fleet_app/driver/app.dart';

/// 預設入口:司機端
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();

// 司機端在瀏覽器不可能運作,先攔下來給明確訊息,別讓它在 dart:io 半路炸。
if (kIsWeb) {
runDriverWebUnsupportedApp();
return;
}

final push = await createDriverPushService();
runApp(DriverApp(pushService: push));
}
9 changes: 9 additions & 0 deletions lib/main_driver.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';

import 'package:line_fleet_app/core/platform/web_unsupported.dart';
import 'package:line_fleet_app/core/push/firebase_push_service.dart';
import 'package:line_fleet_app/driver/app.dart';

Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();

// 司機端在瀏覽器不可能運作,先攔下來給明確訊息,別讓它在 dart:io 半路炸。
if (kIsWeb) {
runDriverWebUnsupportedApp();
return;
}

final push = await createDriverPushService();
runApp(DriverApp(pushService: push));
}
31 changes: 31 additions & 0 deletions test/core/config/app_config_web_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
@TestOn('browser')
library;

import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter_test/flutter_test.dart';
import 'package:line_fleet_app/core/config/app_config.dart';

/// 這支測試必須在瀏覽器裡跑才有意義:
///
/// ```bash
/// flutter test --platform chrome test/core/config/app_config_web_test.dart
/// ```
///
/// 一般的 `flutter test` 跑在 Dart VM 上,`kIsWeb` 恆為 false,
/// 把 AppConfig 裡的 kIsWeb 防線整條拔掉也不會紅——那種測試等於沒有。
/// `@TestOn('browser')` 讓 VM 執行時直接跳過,不會偽裝成通過。
void main() {
test('確認真的跑在 web 上,否則本檔的斷言沒有意義', () {
expect(kIsWeb, isTrue);
});

test('沒帶 --dart-define=API_BASE 時,apiBase 不會碰到 dart:io', () {
// 防線被拔掉的話,這裡會噴
// 「Unsupported operation: Platform._operatingSystem」。
expect(AppConfig.apiBase, 'http://localhost:8080');
});

test('wsBase 由 apiBase 推導,同樣不得碰到 dart:io', () {
expect(AppConfig.wsBase, 'ws://localhost:8080');
});
}
Loading