Merge branch 'hiddify:main' into main

This commit is contained in:
Alireza Farvardin
2024-03-15 13:08:42 +03:30
committed by GitHub
11 changed files with 553 additions and 42 deletions

View File

@@ -70,7 +70,11 @@ android-prepare: get-geo-assets get gen translate android-libs
android-apk-prepare:android-prepare
android-aab-prepare:android-prepare
.PHONY: protos
protos:
make -C libcore -f Makefile protos
protoc --dart_out=grpc:lib/singbox/generated --proto_path=libcore/protos libcore/protos/*.proto
macos-install-dependencies:
brew install create-dmg tree

View File

@@ -10,6 +10,7 @@ import io.nekohasekai.libbox.Libbox
import io.nekohasekai.mobile.Mobile
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@@ -22,6 +23,7 @@ class MethodHandler(private val scope: CoroutineScope) : FlutterPlugin,
const val channelName = "com.hiddify.app/method"
enum class Trigger(val method: String) {
Setup("setup"),
ParseConfig("parse_config"),
ChangeConfigOptions("change_config_options"),
GenerateConfig("generate_config"),
@@ -49,6 +51,15 @@ class MethodHandler(private val scope: CoroutineScope) : FlutterPlugin,
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
Trigger.Setup.method -> {
GlobalScope.launch {
result.runCatching {
Mobile.setup()
success("")
}
}
}
Trigger.ParseConfig.method -> {
scope.launch(Dispatchers.IO) {
result.runCatching {

View File

@@ -0,0 +1,274 @@
//
// Generated code. Do not modify.
// source: core.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
class ParseConfigRequest extends $pb.GeneratedMessage {
factory ParseConfigRequest({
$core.String? tempPath,
$core.String? path,
$core.bool? debug,
}) {
final $result = create();
if (tempPath != null) {
$result.tempPath = tempPath;
}
if (path != null) {
$result.path = path;
}
if (debug != null) {
$result.debug = debug;
}
return $result;
}
ParseConfigRequest._() : super();
factory ParseConfigRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory ParseConfigRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ParseConfigRequest', package: const $pb.PackageName(_omitMessageNames ? '' : 'ConfigOptions'), createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'tempPath', protoName: 'tempPath')
..aOS(2, _omitFieldNames ? '' : 'path')
..aOB(3, _omitFieldNames ? '' : 'debug')
..hasRequiredFields = false
;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
ParseConfigRequest clone() => ParseConfigRequest()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
ParseConfigRequest copyWith(void Function(ParseConfigRequest) updates) => super.copyWith((message) => updates(message as ParseConfigRequest)) as ParseConfigRequest;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static ParseConfigRequest create() => ParseConfigRequest._();
ParseConfigRequest createEmptyInstance() => create();
static $pb.PbList<ParseConfigRequest> createRepeated() => $pb.PbList<ParseConfigRequest>();
@$core.pragma('dart2js:noInline')
static ParseConfigRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ParseConfigRequest>(create);
static ParseConfigRequest? _defaultInstance;
@$pb.TagNumber(1)
$core.String get tempPath => $_getSZ(0);
@$pb.TagNumber(1)
set tempPath($core.String v) { $_setString(0, v); }
@$pb.TagNumber(1)
$core.bool hasTempPath() => $_has(0);
@$pb.TagNumber(1)
void clearTempPath() => clearField(1);
@$pb.TagNumber(2)
$core.String get path => $_getSZ(1);
@$pb.TagNumber(2)
set path($core.String v) { $_setString(1, v); }
@$pb.TagNumber(2)
$core.bool hasPath() => $_has(1);
@$pb.TagNumber(2)
void clearPath() => clearField(2);
@$pb.TagNumber(3)
$core.bool get debug => $_getBF(2);
@$pb.TagNumber(3)
set debug($core.bool v) { $_setBool(2, v); }
@$pb.TagNumber(3)
$core.bool hasDebug() => $_has(2);
@$pb.TagNumber(3)
void clearDebug() => clearField(3);
}
class ParseConfigResponse extends $pb.GeneratedMessage {
factory ParseConfigResponse({
$core.String? error,
}) {
final $result = create();
if (error != null) {
$result.error = error;
}
return $result;
}
ParseConfigResponse._() : super();
factory ParseConfigResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory ParseConfigResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ParseConfigResponse', package: const $pb.PackageName(_omitMessageNames ? '' : 'ConfigOptions'), createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'error')
..hasRequiredFields = false
;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
ParseConfigResponse clone() => ParseConfigResponse()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
ParseConfigResponse copyWith(void Function(ParseConfigResponse) updates) => super.copyWith((message) => updates(message as ParseConfigResponse)) as ParseConfigResponse;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static ParseConfigResponse create() => ParseConfigResponse._();
ParseConfigResponse createEmptyInstance() => create();
static $pb.PbList<ParseConfigResponse> createRepeated() => $pb.PbList<ParseConfigResponse>();
@$core.pragma('dart2js:noInline')
static ParseConfigResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ParseConfigResponse>(create);
static ParseConfigResponse? _defaultInstance;
@$pb.TagNumber(1)
$core.String get error => $_getSZ(0);
@$pb.TagNumber(1)
set error($core.String v) { $_setString(0, v); }
@$pb.TagNumber(1)
$core.bool hasError() => $_has(0);
@$pb.TagNumber(1)
void clearError() => clearField(1);
}
class GenerateConfigRequest extends $pb.GeneratedMessage {
factory GenerateConfigRequest({
$core.String? path,
$core.bool? debug,
}) {
final $result = create();
if (path != null) {
$result.path = path;
}
if (debug != null) {
$result.debug = debug;
}
return $result;
}
GenerateConfigRequest._() : super();
factory GenerateConfigRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory GenerateConfigRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'GenerateConfigRequest', package: const $pb.PackageName(_omitMessageNames ? '' : 'ConfigOptions'), createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'path')
..aOB(2, _omitFieldNames ? '' : 'debug')
..hasRequiredFields = false
;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
GenerateConfigRequest clone() => GenerateConfigRequest()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
GenerateConfigRequest copyWith(void Function(GenerateConfigRequest) updates) => super.copyWith((message) => updates(message as GenerateConfigRequest)) as GenerateConfigRequest;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static GenerateConfigRequest create() => GenerateConfigRequest._();
GenerateConfigRequest createEmptyInstance() => create();
static $pb.PbList<GenerateConfigRequest> createRepeated() => $pb.PbList<GenerateConfigRequest>();
@$core.pragma('dart2js:noInline')
static GenerateConfigRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<GenerateConfigRequest>(create);
static GenerateConfigRequest? _defaultInstance;
@$pb.TagNumber(1)
$core.String get path => $_getSZ(0);
@$pb.TagNumber(1)
set path($core.String v) { $_setString(0, v); }
@$pb.TagNumber(1)
$core.bool hasPath() => $_has(0);
@$pb.TagNumber(1)
void clearPath() => clearField(1);
@$pb.TagNumber(2)
$core.bool get debug => $_getBF(1);
@$pb.TagNumber(2)
set debug($core.bool v) { $_setBool(1, v); }
@$pb.TagNumber(2)
$core.bool hasDebug() => $_has(1);
@$pb.TagNumber(2)
void clearDebug() => clearField(2);
}
class GenerateConfigResponse extends $pb.GeneratedMessage {
factory GenerateConfigResponse({
$core.String? config,
$core.String? error,
}) {
final $result = create();
if (config != null) {
$result.config = config;
}
if (error != null) {
$result.error = error;
}
return $result;
}
GenerateConfigResponse._() : super();
factory GenerateConfigResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory GenerateConfigResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'GenerateConfigResponse', package: const $pb.PackageName(_omitMessageNames ? '' : 'ConfigOptions'), createEmptyInstance: create)
..aOS(1, _omitFieldNames ? '' : 'config')
..aOS(2, _omitFieldNames ? '' : 'error')
..hasRequiredFields = false
;
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
GenerateConfigResponse clone() => GenerateConfigResponse()..mergeFromMessage(this);
@$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
GenerateConfigResponse copyWith(void Function(GenerateConfigResponse) updates) => super.copyWith((message) => updates(message as GenerateConfigResponse)) as GenerateConfigResponse;
$pb.BuilderInfo get info_ => _i;
@$core.pragma('dart2js:noInline')
static GenerateConfigResponse create() => GenerateConfigResponse._();
GenerateConfigResponse createEmptyInstance() => create();
static $pb.PbList<GenerateConfigResponse> createRepeated() => $pb.PbList<GenerateConfigResponse>();
@$core.pragma('dart2js:noInline')
static GenerateConfigResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<GenerateConfigResponse>(create);
static GenerateConfigResponse? _defaultInstance;
@$pb.TagNumber(1)
$core.String get config => $_getSZ(0);
@$pb.TagNumber(1)
set config($core.String v) { $_setString(0, v); }
@$pb.TagNumber(1)
$core.bool hasConfig() => $_has(0);
@$pb.TagNumber(1)
void clearConfig() => clearField(1);
@$pb.TagNumber(2)
$core.String get error => $_getSZ(1);
@$pb.TagNumber(2)
set error($core.String v) { $_setString(1, v); }
@$pb.TagNumber(2)
$core.bool hasError() => $_has(1);
@$pb.TagNumber(2)
void clearError() => clearField(2);
}
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');

View File

@@ -0,0 +1,11 @@
//
// Generated code. Do not modify.
// source: core.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import

View File

@@ -0,0 +1,79 @@
//
// Generated code. Do not modify.
// source: core.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
import 'dart:async' as $async;
import 'dart:core' as $core;
import 'package:grpc/service_api.dart' as $grpc;
import 'package:protobuf/protobuf.dart' as $pb;
import 'core.pb.dart' as $0;
export 'core.pb.dart';
@$pb.GrpcServiceName('ConfigOptions.CoreService')
class CoreServiceClient extends $grpc.Client {
static final _$parseConfig = $grpc.ClientMethod<$0.ParseConfigRequest, $0.ParseConfigResponse>(
'/ConfigOptions.CoreService/ParseConfig',
($0.ParseConfigRequest value) => value.writeToBuffer(),
($core.List<$core.int> value) => $0.ParseConfigResponse.fromBuffer(value));
static final _$generateFullConfig = $grpc.ClientMethod<$0.GenerateConfigRequest, $0.GenerateConfigResponse>(
'/ConfigOptions.CoreService/GenerateFullConfig',
($0.GenerateConfigRequest value) => value.writeToBuffer(),
($core.List<$core.int> value) => $0.GenerateConfigResponse.fromBuffer(value));
CoreServiceClient($grpc.ClientChannel channel,
{$grpc.CallOptions? options,
$core.Iterable<$grpc.ClientInterceptor>? interceptors})
: super(channel, options: options,
interceptors: interceptors);
$grpc.ResponseFuture<$0.ParseConfigResponse> parseConfig($0.ParseConfigRequest request, {$grpc.CallOptions? options}) {
return $createUnaryCall(_$parseConfig, request, options: options);
}
$grpc.ResponseFuture<$0.GenerateConfigResponse> generateFullConfig($0.GenerateConfigRequest request, {$grpc.CallOptions? options}) {
return $createUnaryCall(_$generateFullConfig, request, options: options);
}
}
@$pb.GrpcServiceName('ConfigOptions.CoreService')
abstract class CoreServiceBase extends $grpc.Service {
$core.String get $name => 'ConfigOptions.CoreService';
CoreServiceBase() {
$addMethod($grpc.ServiceMethod<$0.ParseConfigRequest, $0.ParseConfigResponse>(
'ParseConfig',
parseConfig_Pre,
false,
false,
($core.List<$core.int> value) => $0.ParseConfigRequest.fromBuffer(value),
($0.ParseConfigResponse value) => value.writeToBuffer()));
$addMethod($grpc.ServiceMethod<$0.GenerateConfigRequest, $0.GenerateConfigResponse>(
'GenerateFullConfig',
generateFullConfig_Pre,
false,
false,
($core.List<$core.int> value) => $0.GenerateConfigRequest.fromBuffer(value),
($0.GenerateConfigResponse value) => value.writeToBuffer()));
}
$async.Future<$0.ParseConfigResponse> parseConfig_Pre($grpc.ServiceCall call, $async.Future<$0.ParseConfigRequest> request) async {
return parseConfig(call, await request);
}
$async.Future<$0.GenerateConfigResponse> generateFullConfig_Pre($grpc.ServiceCall call, $async.Future<$0.GenerateConfigRequest> request) async {
return generateFullConfig(call, await request);
}
$async.Future<$0.ParseConfigResponse> parseConfig($grpc.ServiceCall call, $0.ParseConfigRequest request);
$async.Future<$0.GenerateConfigResponse> generateFullConfig($grpc.ServiceCall call, $0.GenerateConfigRequest request);
}

View File

@@ -0,0 +1,77 @@
//
// Generated code. Do not modify.
// source: core.proto
//
// @dart = 2.12
// ignore_for_file: annotate_overrides, camel_case_types, comment_references
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
import 'dart:convert' as $convert;
import 'dart:core' as $core;
import 'dart:typed_data' as $typed_data;
@$core.Deprecated('Use parseConfigRequestDescriptor instead')
const ParseConfigRequest$json = {
'1': 'ParseConfigRequest',
'2': [
{'1': 'tempPath', '3': 1, '4': 1, '5': 9, '10': 'tempPath'},
{'1': 'path', '3': 2, '4': 1, '5': 9, '10': 'path'},
{'1': 'debug', '3': 3, '4': 1, '5': 8, '10': 'debug'},
],
};
/// Descriptor for `ParseConfigRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List parseConfigRequestDescriptor = $convert.base64Decode(
'ChJQYXJzZUNvbmZpZ1JlcXVlc3QSGgoIdGVtcFBhdGgYASABKAlSCHRlbXBQYXRoEhIKBHBhdG'
'gYAiABKAlSBHBhdGgSFAoFZGVidWcYAyABKAhSBWRlYnVn');
@$core.Deprecated('Use parseConfigResponseDescriptor instead')
const ParseConfigResponse$json = {
'1': 'ParseConfigResponse',
'2': [
{'1': 'error', '3': 1, '4': 1, '5': 9, '9': 0, '10': 'error', '17': true},
],
'8': [
{'1': '_error'},
],
};
/// Descriptor for `ParseConfigResponse`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List parseConfigResponseDescriptor = $convert.base64Decode(
'ChNQYXJzZUNvbmZpZ1Jlc3BvbnNlEhkKBWVycm9yGAEgASgJSABSBWVycm9yiAEBQggKBl9lcn'
'Jvcg==');
@$core.Deprecated('Use generateConfigRequestDescriptor instead')
const GenerateConfigRequest$json = {
'1': 'GenerateConfigRequest',
'2': [
{'1': 'path', '3': 1, '4': 1, '5': 9, '10': 'path'},
{'1': 'debug', '3': 2, '4': 1, '5': 8, '10': 'debug'},
],
};
/// Descriptor for `GenerateConfigRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List generateConfigRequestDescriptor = $convert.base64Decode(
'ChVHZW5lcmF0ZUNvbmZpZ1JlcXVlc3QSEgoEcGF0aBgBIAEoCVIEcGF0aBIUCgVkZWJ1ZxgCIA'
'EoCFIFZGVidWc=');
@$core.Deprecated('Use generateConfigResponseDescriptor instead')
const GenerateConfigResponse$json = {
'1': 'GenerateConfigResponse',
'2': [
{'1': 'config', '3': 1, '4': 1, '5': 9, '10': 'config'},
{'1': 'error', '3': 2, '4': 1, '5': 9, '9': 0, '10': 'error', '17': true},
],
'8': [
{'1': '_error'},
],
};
/// Descriptor for `GenerateConfigResponse`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List generateConfigResponseDescriptor = $convert.base64Decode(
'ChZHZW5lcmF0ZUNvbmZpZ1Jlc3BvbnNlEhYKBmNvbmZpZxgBIAEoCVIGY29uZmlnEhkKBWVycm'
'9yGAIgASgJSABSBWVycm9yiAEBQggKBl9lcnJvcg==');

View File

@@ -0,0 +1,48 @@
import 'package:fpdart/fpdart.dart';
import 'package:grpc/grpc.dart';
import 'package:hiddify/singbox/generated/core.pbgrpc.dart';
import 'package:hiddify/singbox/service/singbox_service.dart';
abstract class CoreSingboxService extends CoreServiceClient
implements SingboxService {
CoreSingboxService()
: super(
ClientChannel(
'localhost',
port: 7078,
options: const ChannelOptions(
credentials: ChannelCredentials.insecure(),
),
),
);
@override
TaskEither<String, Unit> validateConfigByPath(
String path,
String tempPath,
bool debug,
) {
return TaskEither(
() async {
final response = await parseConfig(
ParseConfigRequest(tempPath: tempPath, path: path, debug: false),
);
if (response.error != "") return left(response.error);
return right(unit);
},
);
}
@override
TaskEither<String, String> generateFullConfigByPath(String path) {
return TaskEither(
() async {
final response = await generateFullConfig(
GenerateConfigRequest(path: path, debug: false),
);
if (response.error != "") return left(response.error);
return right(response.config);
},
);
}
}

View File

@@ -9,11 +9,14 @@ import 'package:hiddify/singbox/model/singbox_outbound.dart';
import 'package:hiddify/singbox/model/singbox_stats.dart';
import 'package:hiddify/singbox/model/singbox_status.dart';
import 'package:hiddify/singbox/model/warp_account.dart';
import 'package:hiddify/singbox/service/core_singbox_service.dart';
import 'package:hiddify/singbox/service/singbox_service.dart';
import 'package:hiddify/utils/custom_loggers.dart';
import 'package:rxdart/rxdart.dart';
class PlatformSingboxService with InfraLogger implements SingboxService {
class PlatformSingboxService extends CoreSingboxService
with InfraLogger
implements SingboxService {
static const channelPrefix = "com.hiddify.app";
static const methodChannel = MethodChannel("$channelPrefix/method");
@@ -46,30 +49,9 @@ class PlatformSingboxService with InfraLogger implements SingboxService {
TaskEither<String, Unit> setup(Directories directories, bool debug) {
return TaskEither(
() async {
if (!Platform.isIOS) {
return right(unit);
}
await methodChannel.invokeMethod("setup");
return right(unit);
},
);
}
@override
TaskEither<String, Unit> validateConfigByPath(
String path,
String tempPath,
bool debug,
) {
return TaskEither(
() async {
final message = await methodChannel.invokeMethod<String>(
"parse_config",
{"path": path, "tempPath": tempPath, "debug": debug},
);
if (message == null || message.isEmpty) return right(unit);
return left(message);
return right(unit);
},
);
}
@@ -88,23 +70,6 @@ class PlatformSingboxService with InfraLogger implements SingboxService {
);
}
@override
TaskEither<String, String> generateFullConfigByPath(String path) {
return TaskEither(
() async {
loggy.debug("generating full config by path");
final configJson = await methodChannel.invokeMethod<String>(
"generate_config",
{"path": path},
);
if (configJson == null || configJson.isEmpty) {
return left("null response");
}
return right(configJson);
},
);
}
@override
TaskEither<String, Unit> start(
String path,

Submodule libcore updated: ec9efac57c...85cc81a46a

View File

@@ -718,6 +718,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.4.1"
google_identity_services_web:
dependency: transitive
description:
name: google_identity_services_web
sha256: "9482364c9f8b7bd36902572ebc3a7c2b5c8ee57a9c93e6eb5099c1a9ec5265d8"
url: "https://pub.dev"
source: hosted
version: "0.3.1+1"
googleapis_auth:
dependency: transitive
description:
name: googleapis_auth
sha256: cafc46446574fd42826aa4cd4d623c94482598fda0a5a5649bf2781bcbc09258
url: "https://pub.dev"
source: hosted
version: "1.5.0"
graphs:
dependency: transitive
description:
@@ -726,6 +742,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.1"
grpc:
dependency: "direct main"
description:
name: grpc
sha256: e93ee3bce45c134bf44e9728119102358c7cd69de7832d9a874e2e74eb8cab40
url: "https://pub.dev"
source: hosted
version: "3.2.4"
hooks_riverpod:
dependency: "direct main"
description:
@@ -750,6 +774,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.1"
http2:
dependency: transitive
description:
name: http2
sha256: "9ced024a160b77aba8fb8674e38f70875e321d319e6f303ec18e87bd5a4b0c1d"
url: "https://pub.dev"
source: hosted
version: "2.3.0"
http_multi_server:
dependency: transitive
description:
@@ -1214,6 +1246,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.0"
protobuf:
dependency: "direct main"
description:
name: protobuf
sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d"
url: "https://pub.dev"
source: hosted
version: "3.1.0"
protocol_handler:
dependency: "direct main"
description:

View File

@@ -80,6 +80,8 @@ dependencies:
# circle_flags: ^4.0.2
circle_flags:
git: https://github.com/hiddify-com/flutter_circle_flags.git
protobuf: ^3.1.0
grpc: ^3.2.4
dev_dependencies:
flutter_test: