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
9 changes: 8 additions & 1 deletion lib/views/dashboard/dashboard.dart
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,14 @@ class _DashboardViewState extends ConsumerState<DashboardView> {
(isEdit) => CommonScaffold(
title: appLocalizations.dashboard,
actions: _buildActions(isEdit),
floatingActionButton: const StartButton(),
floatingActionButton: Row(
mainAxisSize: MainAxisSize.min,
children: const [
LaunchBrowserButton(),
SizedBox(width: 8),
StartButton(),
],
),
body: Align(
alignment: Alignment.topCenter,
child: SingleChildScrollView(
Expand Down
71 changes: 71 additions & 0 deletions lib/views/dashboard/widgets/start_button.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:io';

import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/controller.dart';
import 'package:fl_clash/enum/enum.dart';
Expand Down Expand Up @@ -135,3 +137,72 @@ class _StartButtonState extends ConsumerState<StartButton>
);
}
}

class LaunchBrowserButton extends ConsumerWidget {
const LaunchBrowserButton({super.key});

Future<void> _launchWithProxy(int port) async {
final proxyArg = '--proxy-server=http://127.0.0.1:$port';
if (system.isWindows) {
// Follow v2rayN style: start browser with proxy args.
await Process.start('cmd', ['/c', 'start', '', 'msedge', proxyArg]);
return;
}
if (system.isMacOS) {
await Process.start('open', [
'-a',
'Google Chrome',
'--args',
proxyArg,
]);
return;
}
if (system.isLinux) {
final commands = [
'google-chrome',
'google-chrome-stable',
'chromium-browser',
'chromium',
];
for (final command in commands) {
try {
await Process.start(command, [proxyArg]);
return;
} catch (_) {
// try next command
}
}
throw 'Chrome is not found on this Linux system.';
}
}

@override
Widget build(BuildContext context, WidgetRef ref) {
if (system.isAndroid) {
return const SizedBox.shrink();
}
final hasProfile = ref.watch(
profilesProvider.select((state) => state.isNotEmpty),
);
if (!hasProfile) {
return const SizedBox.shrink();
}
final isStart = ref.watch(isStartProvider);
final port = ref.watch(proxyStateProvider.select((state) => state.port));
return FloatingActionButton(
heroTag: null,
mini: true,
tooltip: 'Launch browser with proxy',
onPressed: !isStart
? null
: () async {
try {
await _launchWithProxy(port);
} catch (e) {
globalState.showNotifier('Launch browser failed: $e');
}
},
child: const Icon(Icons.language),
);
}
}