Compare commits
1 Commits
v0.8.83-pr
...
v0.8.83-pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af361a086a |
@@ -245,6 +245,7 @@ abstract class ClashHandlerInterface with ClashInterface {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Future<bool> crash() {
|
||||
return invoke<bool>(
|
||||
|
||||
@@ -71,9 +71,9 @@ class ClashService extends ClashHandlerInterface {
|
||||
}
|
||||
}, (error, stack) {
|
||||
commonPrint.log(error.toString());
|
||||
if (error is SocketException) {
|
||||
if(error is SocketException){
|
||||
globalState.showNotifier(error.toString());
|
||||
// globalState.appController.restartCore();
|
||||
globalState.appController.restartCore();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -16,8 +16,7 @@ const browserUa =
|
||||
const packageName = "com.follow.clash";
|
||||
final unixSocketPath = "/tmp/FlClashSocket_${Random().nextInt(10000)}.sock";
|
||||
const helperPort = 47890;
|
||||
const maxTextScale = 1.4;
|
||||
const minTextScale = 0.8;
|
||||
const helperTag = "2024125";
|
||||
final baseInfoEdgeInsets = EdgeInsets.symmetric(
|
||||
vertical: 16.ap,
|
||||
horizontal: 16.ap,
|
||||
|
||||
@@ -130,7 +130,7 @@ class Request {
|
||||
if (response.statusCode != HttpStatus.ok) {
|
||||
return false;
|
||||
}
|
||||
return (response.data as String) == globalState.helperToken;
|
||||
return (response.data as String) == helperTag;
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -396,9 +396,9 @@ class AppController {
|
||||
handleExit() async {
|
||||
try {
|
||||
await updateStatus(false);
|
||||
await proxy?.stopProxy();
|
||||
await clashCore.shutdown();
|
||||
await clashService?.destroy();
|
||||
await proxy?.stopProxy();
|
||||
await savePreferences();
|
||||
} finally {
|
||||
system.exit();
|
||||
@@ -487,10 +487,10 @@ class AppController {
|
||||
Future<void> _initCore() async {
|
||||
final isInit = await clashCore.isInit;
|
||||
if (!isInit) {
|
||||
await clashCore.init();
|
||||
await clashCore.setState(
|
||||
globalState.getCoreState(),
|
||||
);
|
||||
await clashCore.init();
|
||||
}
|
||||
await applyProfile();
|
||||
}
|
||||
|
||||
@@ -123,13 +123,8 @@ class _ProxiesFragmentState extends ConsumerState<ProxiesFragment>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final proxiesType = ref.watch(
|
||||
proxiesStyleSettingProvider.select(
|
||||
(state) => state.type,
|
||||
),
|
||||
);
|
||||
|
||||
ref.watch(themeSettingProvider.select((state) => state.textScale));
|
||||
final proxiesType =
|
||||
ref.watch(proxiesStyleSettingProvider.select((state) => state.type));
|
||||
return switch (proxiesType) {
|
||||
ProxiesType.tab => ProxiesTabFragment(
|
||||
key: _proxiesTabKey,
|
||||
|
||||
@@ -147,21 +147,22 @@ class _GeoDataListItemState extends State<GeoDataListItem> {
|
||||
FutureBuilder<FileInfo>(
|
||||
future: _getGeoFileLastModified(geoItem.fileName),
|
||||
builder: (_, snapshot) {
|
||||
final height = globalState.measure.bodyMediumHeight;
|
||||
return SizedBox(
|
||||
height: height,
|
||||
child: snapshot.data == null
|
||||
? SizedBox(
|
||||
width: height,
|
||||
height: height,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
height: 24,
|
||||
child: FadeThroughBox(
|
||||
key: Key("fade_box_${geoItem.label}"),
|
||||
child: snapshot.data == null
|
||||
? const SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
snapshot.data!.desc,
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
snapshot.data!.desc,
|
||||
style: context.textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -526,8 +526,8 @@ class _TextScaleFactorItem extends ConsumerWidget {
|
||||
data: _SliderDefaultsM3(context),
|
||||
child: Slider(
|
||||
padding: EdgeInsets.zero,
|
||||
min: minTextScale,
|
||||
max: maxTextScale,
|
||||
min: 0.8,
|
||||
max: 1.2,
|
||||
value: textScale.scale,
|
||||
onChanged: (value) {
|
||||
ref.read(themeSettingProvider.notifier).updateState(
|
||||
|
||||
@@ -27,7 +27,6 @@ Future<void> main() async {
|
||||
await android?.init();
|
||||
await window?.init(version);
|
||||
globalState.isPre = const String.fromEnvironment("APP_ENV") != 'stable';
|
||||
globalState.helperToken = const String.fromEnvironment("HELPER_TOKEN");
|
||||
HttpOverrides.global = FlClashHttpOverrides();
|
||||
runApp(ProviderScope(
|
||||
child: const Application(),
|
||||
|
||||
@@ -23,9 +23,9 @@ class ThemeManager extends ConsumerWidget {
|
||||
final double textScaleFactor = max(
|
||||
min(
|
||||
textScale.enable ? textScale.scale : defaultTextScaleFactor,
|
||||
maxTextScale,
|
||||
1.2,
|
||||
),
|
||||
minTextScale,
|
||||
0.8,
|
||||
);
|
||||
|
||||
globalState.measure = Measure.of(context, textScaleFactor);
|
||||
|
||||
@@ -127,7 +127,6 @@ class _EditorPageState extends ConsumerState<EditorPage> {
|
||||
);
|
||||
},
|
||||
popup: CommonPopupMenu(
|
||||
minWidth: 180,
|
||||
items: [
|
||||
PopupMenuItemData(
|
||||
icon: Icons.search,
|
||||
@@ -190,7 +189,7 @@ class _EditorPageState extends ConsumerState<EditorPage> {
|
||||
shortcutsActivatorsBuilder: DefaultCodeShortcutsActivatorsBuilder(),
|
||||
controller: _controller,
|
||||
style: CodeEditorStyle(
|
||||
fontSize: 14.ap,
|
||||
fontSize: 14,
|
||||
fontFamily: FontFamily.jetBrainsMono.value,
|
||||
codeTheme: CodeHighlightTheme(
|
||||
languages: {
|
||||
|
||||
@@ -30,7 +30,6 @@ class GlobalState {
|
||||
late Config config;
|
||||
late AppState appState;
|
||||
bool isPre = true;
|
||||
String? helperToken;
|
||||
late PackageInfo packageInfo;
|
||||
Function? updateCurrentDelayDebounce;
|
||||
late Measure measure;
|
||||
|
||||
@@ -279,7 +279,7 @@ packages:
|
||||
source: hosted
|
||||
version: "0.3.4+2"
|
||||
crypto:
|
||||
dependency: "direct dev"
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
|
||||
|
||||
@@ -66,7 +66,6 @@ dev_dependencies:
|
||||
riverpod_generator: ^2.6.3
|
||||
custom_lint: ^0.7.0
|
||||
riverpod_lint: ^2.6.3
|
||||
crypto: ^3.0.3
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
||||
14
services/helper/Cargo.lock
generated
14
services/helper/Cargo.lock
generated
@@ -1,6 +1,6 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
@@ -284,7 +284,6 @@ dependencies = [
|
||||
"anyhow",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"sha2",
|
||||
"tokio",
|
||||
"warp",
|
||||
"windows-service",
|
||||
@@ -823,17 +822,6 @@ dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.2"
|
||||
|
||||
@@ -14,11 +14,10 @@ anyhow = "1.0.93"
|
||||
warp = "0.3.7"
|
||||
serde = { version = "1.0.215", features = ["derive"] }
|
||||
once_cell = "1.20.2"
|
||||
sha2 = "0.10.8"
|
||||
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
codegen-units = 1
|
||||
lto = true
|
||||
opt-level = "s"
|
||||
opt-level = "s"
|
||||
@@ -1,4 +0,0 @@
|
||||
fn main() {
|
||||
let version = std::env::var("TOKEN").unwrap_or_default();
|
||||
println!("cargo:rustc-env=TOKEN={}", version);
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
use once_cell::sync::Lazy;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::collections::VecDeque;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, Error, Read};
|
||||
use std::{io, thread};
|
||||
use std::io::BufRead;
|
||||
use std::process::{Command, Stdio};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::{io, thread};
|
||||
use warp::{Filter, Reply};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
const LISTEN_PORT: u16 = 47890;
|
||||
|
||||
@@ -17,31 +15,10 @@ pub struct StartParams {
|
||||
pub arg: String,
|
||||
}
|
||||
|
||||
fn sha256_file(path: &str) -> Result<String, Error> {
|
||||
let mut file = File::open(path)?;
|
||||
let mut hasher = Sha256::new();
|
||||
let mut buffer = [0; 4096];
|
||||
|
||||
loop {
|
||||
let bytes_read = file.read(&mut buffer)?;
|
||||
if bytes_read == 0 {
|
||||
break;
|
||||
}
|
||||
hasher.update(&buffer[..bytes_read]);
|
||||
}
|
||||
|
||||
Ok(format!("{:x}", hasher.finalize()))
|
||||
}
|
||||
|
||||
static LOGS: Lazy<Arc<Mutex<VecDeque<String>>>> =
|
||||
Lazy::new(|| Arc::new(Mutex::new(VecDeque::with_capacity(100))));
|
||||
static PROCESS: Lazy<Arc<Mutex<Option<std::process::Child>>>> =
|
||||
Lazy::new(|| Arc::new(Mutex::new(None)));
|
||||
static LOGS: Lazy<Arc<Mutex<VecDeque<String>>>> = Lazy::new(|| Arc::new(Mutex::new(VecDeque::with_capacity(100))));
|
||||
static PROCESS: Lazy<Arc<Mutex<Option<std::process::Child>>>> = Lazy::new(|| Arc::new(Mutex::new(None)));
|
||||
|
||||
fn start(start_params: StartParams) -> impl Reply {
|
||||
if sha256_file(start_params.path.as_str()).unwrap_or("".to_string()) != env!("TOKEN") {
|
||||
return "Only FlClashCore is allowed to run.".to_string();
|
||||
}
|
||||
stop();
|
||||
let mut process = PROCESS.lock().unwrap();
|
||||
match Command::new(&start_params.path)
|
||||
@@ -96,29 +73,38 @@ fn log_message(message: String) {
|
||||
|
||||
fn get_logs() -> impl Reply {
|
||||
let log_buffer = LOGS.lock().unwrap();
|
||||
let value = log_buffer
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n");
|
||||
let value = log_buffer.iter().cloned().collect::<Vec<String>>().join("\n");
|
||||
warp::reply::with_header(value, "Content-Type", "text/plain")
|
||||
}
|
||||
|
||||
pub async fn run_service() -> anyhow::Result<()> {
|
||||
let api_ping = warp::get().and(warp::path("ping")).map(|| env!("TOKEN"));
|
||||
let api_ping = warp::get()
|
||||
.and(warp::path("ping"))
|
||||
.map(|| "2024125");
|
||||
|
||||
let api_start = warp::post()
|
||||
.and(warp::path("start"))
|
||||
.and(warp::body::json())
|
||||
.map(|start_params: StartParams| start(start_params));
|
||||
.map(|start_params: StartParams| {
|
||||
start(start_params)
|
||||
});
|
||||
|
||||
let api_stop = warp::post().and(warp::path("stop")).map(|| stop());
|
||||
let api_stop = warp::post()
|
||||
.and(warp::path("stop"))
|
||||
.map(|| stop());
|
||||
|
||||
let api_logs = warp::get().and(warp::path("logs")).map(|| get_logs());
|
||||
let api_logs = warp::get()
|
||||
.and(warp::path("logs"))
|
||||
.map(|| get_logs());
|
||||
|
||||
warp::serve(api_ping.or(api_start).or(api_stop).or(api_logs))
|
||||
warp::serve(
|
||||
api_ping
|
||||
.or(api_start)
|
||||
.or(api_stop)
|
||||
.or(api_logs)
|
||||
)
|
||||
.run(([127, 0, 0, 1], LISTEN_PORT))
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
44
setup.dart
44
setup.dart
@@ -5,7 +5,6 @@ import 'dart:io';
|
||||
|
||||
import 'package:args/command_runner.dart';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:crypto/crypto.dart';
|
||||
|
||||
enum Target {
|
||||
windows,
|
||||
@@ -196,16 +195,7 @@ class Build {
|
||||
if (exitCode != 0 && name != null) throw "$name error";
|
||||
}
|
||||
|
||||
static Future<String?> calcSha256(String filePath) async {
|
||||
final file = File(filePath);
|
||||
if (!await file.exists()) {
|
||||
return null;
|
||||
}
|
||||
final stream = file.openRead();
|
||||
return sha256.convert(await stream.reduce((a, b) => a + b)).toString();
|
||||
}
|
||||
|
||||
static Future<List<String>> buildCore({
|
||||
static buildCore({
|
||||
required Mode mode,
|
||||
required Target target,
|
||||
Arch? arch,
|
||||
@@ -219,8 +209,6 @@ class Build {
|
||||
},
|
||||
).toList();
|
||||
|
||||
final List<String> corePaths = [];
|
||||
|
||||
for (final item in items) {
|
||||
final outFileDir = join(
|
||||
outDir,
|
||||
@@ -240,7 +228,6 @@ class Build {
|
||||
outFileDir,
|
||||
fileName,
|
||||
);
|
||||
corePaths.add(outPath);
|
||||
|
||||
final Map<String, String> env = {};
|
||||
env["GOOS"] = item.target.os;
|
||||
@@ -271,11 +258,9 @@ class Build {
|
||||
workingDirectory: _coreDir,
|
||||
);
|
||||
}
|
||||
|
||||
return corePaths;
|
||||
}
|
||||
|
||||
static buildHelper(Target target, String token) async {
|
||||
static buildHelper(Target target) async {
|
||||
await exec(
|
||||
[
|
||||
"cargo",
|
||||
@@ -284,9 +269,6 @@ class Build {
|
||||
"--features",
|
||||
"windows-service",
|
||||
],
|
||||
environment: {
|
||||
"TOKEN": token,
|
||||
},
|
||||
name: "build helper",
|
||||
workingDirectory: _servicesDir,
|
||||
);
|
||||
@@ -296,15 +278,13 @@ class Build {
|
||||
"release",
|
||||
"helper${target.executableExtensionName}",
|
||||
);
|
||||
final targetPath = join(
|
||||
outDir,
|
||||
target.name,
|
||||
"FlClashHelperService${target.executableExtensionName}",
|
||||
);
|
||||
final targetPath = join(outDir, target.name,
|
||||
"FlClashHelperService${target.executableExtensionName}");
|
||||
await File(outPath).copy(targetPath);
|
||||
}
|
||||
|
||||
static List<String> getExecutable(String command) {
|
||||
print(command);
|
||||
return command.split(" ");
|
||||
}
|
||||
|
||||
@@ -486,28 +466,26 @@ class BuildCommand extends Command {
|
||||
throw "Invalid arch parameter";
|
||||
}
|
||||
|
||||
final corePaths = await Build.buildCore(
|
||||
await Build.buildCore(
|
||||
target: target,
|
||||
arch: arch,
|
||||
mode: mode,
|
||||
);
|
||||
|
||||
if (target == Target.windows) {
|
||||
await Build.buildHelper(target);
|
||||
}
|
||||
|
||||
if (out != "app") {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (target) {
|
||||
case Target.windows:
|
||||
final token = await Build.calcSha256(corePaths.first);
|
||||
if (token == null) {
|
||||
throw "Core not exists";
|
||||
}
|
||||
Build.buildHelper(target, token);
|
||||
_buildDistributor(
|
||||
target: target,
|
||||
targets: "exe,zip",
|
||||
args:
|
||||
" --description $archName --build-dart-define=HELPER_TOKEN=$token",
|
||||
args: " --description $archName",
|
||||
env: env,
|
||||
);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user