Compare commits

..

15 Commits

Author SHA1 Message Date
chen08209
658727dd79 Update build.yml 2024-06-16 13:18:55 +08:00
chen08209
f7abf6446c Fix android vpn close issues
Add requests page

Fix checkUpdate dark mode style error

Fix quickStart error open app

Add memory proxies tab index

Support hidden group

Optimize logs
2024-06-16 13:06:34 +08:00
chen08209
5ab4dd0cbd Fix externalController hot load error 2024-06-13 19:22:26 +08:00
chen08209
35f7279fcb Add tcp concurrent switch
Add system proxy switch

Add geodata loader switch

Add external controller switch

Add auto gc on trim memory

Fix android notification error
2024-06-13 17:04:57 +08:00
chen08209
86572cc960 Fix ipv6 error 2024-06-12 19:07:54 +08:00
chen08209
ee22709d49 Fix android udp direct error
Add ipv6 switch

Add access all selected button

Remove android low version splash
2024-06-12 18:29:58 +08:00
chen08209
0a2ad63f38 Update version 2024-06-10 19:11:04 +08:00
chen08209
2ec12c9363 Add allowBypass
Fix Android only pick .text file issues
2024-06-10 19:09:58 +08:00
chen08209
a3c2dc786c Fix search issues 2024-06-09 21:48:17 +08:00
chen08209
7acf9c6db3 Fix LoadBalance, Relay load error 2024-06-09 20:53:36 +08:00
chen08209
8074547fb4 Fix build.yml4 2024-06-09 19:56:51 +08:00
chen08209
8a01e04871 Fix build.yml3 2024-06-09 19:49:51 +08:00
chen08209
7ddcdd9828 Fix build.yml2 2024-06-09 19:49:14 +08:00
chen08209
d89ed076fd Fix build.yml 2024-06-09 19:46:05 +08:00
chen08209
f4c3b06cd5 Add search function at access control
Fix the issues with the profile add button to cover the edit button

Adapt LoadBalance and Relay

Add arm

Fix android notification icon error
2024-06-09 19:25:14 +08:00
29 changed files with 475 additions and 346 deletions

View File

@@ -15,7 +15,6 @@ enum class RunState {
class GlobalState {
companion object {
val runState: MutableLiveData<RunState> = MutableLiveData<RunState>(RunState.STOP)
var runTime: Date? = null
var flutterEngine: FlutterEngine? = null
fun getCurrentTilePlugin(): TilePlugin? =
flutterEngine?.plugins?.get(TilePlugin::class.java) as TilePlugin?

View File

@@ -25,7 +25,6 @@ import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import java.util.Date
class ProxyPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware {
@@ -94,10 +93,6 @@ class ProxyPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAwar
}
}
"GetRunTimeStamp" -> {
result.success(GlobalState.runTime?.time)
}
"startForeground" -> {
title = call.argument<String>("title") as String
content = call.argument<String>("content") as String
@@ -123,7 +118,6 @@ class ProxyPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAwar
if (GlobalState.runState.value == RunState.START) return;
flClashVpnService?.start(port, props)
GlobalState.runState.value = RunState.START
GlobalState.runTime = Date()
startAfter()
}
@@ -132,7 +126,6 @@ class ProxyPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAwar
flClashVpnService?.stop()
unbindService()
GlobalState.runState.value = RunState.STOP;
GlobalState.runTime = null;
}
@SuppressLint("ForegroundServiceType")

View File

@@ -82,13 +82,13 @@ type Delay struct {
}
type Process struct {
Id int64 `json:"id"`
Metadata *constant.Metadata `json:"metadata"`
Id int64 `json:"id"`
Metadata constant.Metadata `json:"metadata"`
}
type ProcessMapItem struct {
Id int64 `json:"id"`
Value string `json:"value"`
Id int64 `json:"id"`
Value *string `json:"value"`
}
type Now struct {
@@ -396,6 +396,8 @@ func applyConfig(isPatch bool) {
if isPatch {
patchConfig(cfg.General)
} else {
runtime.GC()
executor.Shutdown()
hub.UltraApplyConfig(cfg, true)
}
}

View File

@@ -13,7 +13,6 @@ const (
Now MessageType = "now"
Process MessageType = "process"
Request MessageType = "request"
Run MessageType = "run"
)
type Message struct {
@@ -21,18 +20,11 @@ type Message struct {
Data interface{} `json:"data"`
}
func (message *Message) Json() (string, error) {
data, err := json.Marshal(message)
return string(data), err
func (message *Message) Json() string {
data, _ := json.Marshal(message)
return string(data)
}
func SendMessage(message Message) {
if Port == nil {
return
}
s, err := message.Json()
if err != nil {
return
}
SendToPort(*Port, s)
SendToPort(*Port, message.Json())
}

42
core/platform/limit.go Normal file
View File

@@ -0,0 +1,42 @@
//go:build android
package platform
import "syscall"
var nullFd int
var maxFdCount int
func init() {
fd, err := syscall.Open("/dev/null", syscall.O_WRONLY, 0644)
if err != nil {
panic(err.Error())
}
nullFd = fd
var limit syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
maxFdCount = 1024
} else {
maxFdCount = int(limit.Cur)
}
maxFdCount = maxFdCount / 4 * 3
}
func ShouldBlockConnection() bool {
fd, err := syscall.Dup(nullFd)
if err != nil {
return true
}
_ = syscall.Close(fd)
if fd > maxFdCount {
return true
}
return false
}

171
core/platform/procfs.go Normal file
View File

@@ -0,0 +1,171 @@
//go:build android
package platform
import (
"bufio"
"encoding/binary"
"encoding/hex"
"fmt"
"net"
"os"
"strconv"
"strings"
"unsafe"
)
var netIndexOfLocal = -1
var netIndexOfUid = -1
var nativeEndian binary.ByteOrder
func QuerySocketUidFromProcFs(source, _ net.Addr) int {
if netIndexOfLocal < 0 || netIndexOfUid < 0 {
return -1
}
network := source.Network()
if strings.HasSuffix(network, "4") || strings.HasSuffix(network, "6") {
network = network[:len(network)-1]
}
path := "/proc/net/" + network
var sIP net.IP
var sPort int
switch s := source.(type) {
case *net.TCPAddr:
sIP = s.IP
sPort = s.Port
case *net.UDPAddr:
sIP = s.IP
sPort = s.Port
default:
return -1
}
sIP = sIP.To16()
if sIP == nil {
return -1
}
uid := doQuery(path+"6", sIP, sPort)
if uid == -1 {
sIP = sIP.To4()
if sIP == nil {
return -1
}
uid = doQuery(path, sIP, sPort)
}
return uid
}
func doQuery(path string, sIP net.IP, sPort int) int {
file, err := os.Open(path)
if err != nil {
return -1
}
defer file.Close()
reader := bufio.NewReader(file)
var bytes [2]byte
binary.BigEndian.PutUint16(bytes[:], uint16(sPort))
local := fmt.Sprintf("%s:%s", hex.EncodeToString(nativeEndianIP(sIP)), hex.EncodeToString(bytes[:]))
for {
row, _, err := reader.ReadLine()
if err != nil {
return -1
}
fields := strings.Fields(string(row))
if len(fields) <= netIndexOfLocal || len(fields) <= netIndexOfUid {
continue
}
if strings.EqualFold(local, fields[netIndexOfLocal]) {
uid, err := strconv.Atoi(fields[netIndexOfUid])
if err != nil {
return -1
}
return uid
}
}
}
func nativeEndianIP(ip net.IP) []byte {
result := make([]byte, len(ip))
for i := 0; i < len(ip); i += 4 {
value := binary.BigEndian.Uint32(ip[i:])
nativeEndian.PutUint32(result[i:], value)
}
return result
}
func init() {
file, err := os.Open("/proc/net/tcp")
if err != nil {
return
}
defer file.Close()
reader := bufio.NewReader(file)
header, _, err := reader.ReadLine()
if err != nil {
return
}
columns := strings.Fields(string(header))
var txQueue, rxQueue, tr, tmWhen bool
for idx, col := range columns {
offset := 0
if txQueue && rxQueue {
offset--
}
if tr && tmWhen {
offset--
}
switch col {
case "tx_queue":
txQueue = true
case "rx_queue":
rxQueue = true
case "tr":
tr = true
case "tm->when":
tmWhen = true
case "local_address":
netIndexOfLocal = idx + offset
case "uid":
netIndexOfUid = idx + offset
}
}
}
func init() {
var x uint32 = 0x01020304
if *(*byte)(unsafe.Pointer(&x)) == 0x01 {
nativeEndian = binary.BigEndian
} else {
nativeEndian = binary.LittleEndian
}
}

View File

@@ -9,30 +9,16 @@ import (
"errors"
"github.com/metacubex/mihomo/component/process"
"github.com/metacubex/mihomo/constant"
"sync"
"github.com/metacubex/mihomo/log"
"sync/atomic"
"time"
)
type ProcessMap struct {
m sync.Map
}
var (
counter int64
)
func (cm *ProcessMap) Store(key int64, value string) {
cm.m.Store(key, value)
}
func (cm *ProcessMap) Load(key int64) (string, bool) {
value, ok := cm.m.Load(key)
if !ok || value == nil {
return "", false
}
return value.(string), true
}
var counter int64 = 0
var processMap ProcessMap
var processMap = make(map[int64]*string)
func init() {
process.DefaultPackageNameResolver = func(metadata *constant.Metadata) (string, error) {
@@ -43,24 +29,31 @@ func init() {
timeout := time.After(200 * time.Millisecond)
bridge.SendMessage(bridge.Message{
message := &bridge.Message{
Type: bridge.Process,
Data: Process{
Id: id,
Metadata: metadata,
Metadata: *metadata,
},
})
}
bridge.SendMessage(*message)
for {
select {
case <-timeout:
return "", errors.New("package resolver timeout")
default:
value, exists := processMap.Load(id)
value, exists := processMap[counter]
if exists {
return value, nil
if value != nil {
log.Infoln("[PKG] %s --> %s by [%s]", metadata.SourceAddress(), metadata.RemoteAddress(), *value)
return *value, nil
} else {
return "", process.ErrInvalidNetwork
}
}
time.Sleep(20 * time.Millisecond)
time.Sleep(10 * time.Millisecond)
}
}
}
@@ -68,15 +61,12 @@ func init() {
//export setProcessMap
func setProcessMap(s *C.char) {
if s == nil {
return
}
go func() {
paramsString := C.GoString(s)
var processMapItem = &ProcessMapItem{}
err := json.Unmarshal([]byte(paramsString), processMapItem)
if err == nil {
processMap.Store(processMapItem.Id, processMapItem.Value)
processMap[processMapItem.Id] = processMapItem.Value
}
}()
}

View File

@@ -4,10 +4,13 @@ package main
import "C"
import (
"core/platform"
t "core/tun"
"errors"
"github.com/metacubex/mihomo/component/dialer"
"github.com/metacubex/mihomo/log"
"golang.org/x/sync/semaphore"
"strconv"
"sync"
"syscall"
"time"
@@ -15,11 +18,16 @@ import (
var tunLock sync.Mutex
var tun *t.Tun
var runTime *time.Time
//export startTUN
func startTUN(fd C.int) {
tunLock.Lock()
now := time.Now()
runTime = &now
go func() {
tunLock.Lock()
defer tunLock.Unlock()
if tun != nil {
@@ -35,8 +43,6 @@ func startTUN(fd C.int) {
closer, err := t.Start(f, gateway, portal, dns)
applyConfig(true)
if err != nil {
log.Errorln("startTUN error: %v", err)
tempTun.Close()
@@ -45,18 +51,30 @@ func startTUN(fd C.int) {
tempTun.Closer = closer
tun = tempTun
applyConfig(true)
}()
}
//export getRunTime
func getRunTime() *C.char {
if runTime == nil {
return C.CString("")
}
return C.CString(strconv.FormatInt(runTime.UnixMilli(), 10))
}
//export stopTun
func stopTun() {
tunLock.Lock()
runTime = nil
go func() {
tunLock.Lock()
defer tunLock.Unlock()
if tun != nil {
tun.Close()
applyConfig(true)
tun = nil
}
}()
@@ -64,6 +82,9 @@ func stopTun() {
func init() {
dialer.DefaultSocketHook = func(network, address string, conn syscall.RawConn) error {
if platform.ShouldBlockConnection() {
return errors.New("blocked")
}
return conn.Control(func(fd uintptr) {
if tun != nil {
tun.MarkSocket(int(fd))

View File

@@ -99,7 +99,7 @@ class ClashCore {
final groupNames = [
UsedProxy.GLOBAL.name,
...(proxies[UsedProxy.GLOBAL.name]["all"] as List).where((e) {
final proxy = proxies[e] ?? {};
final proxy = proxies[e];
return GroupTypeExtension.valueList.contains(proxy['type']) && proxy['hidden'] != true;
})
];

View File

@@ -19,8 +19,6 @@ abstract mixin class ClashMessageListener {
void onRequest(Connection connection) {}
void onNow(Now now) {}
void onRun(String runTime) {}
}
class ClashMessage {
@@ -53,9 +51,6 @@ class ClashMessage {
case MessageType.request:
listener.onRequest(Connection.fromJson(m.data));
break;
case MessageType.run:
listener.onRun(m.data);
break;
}
}
});

View File

@@ -278,7 +278,7 @@ class AppController {
config: config,
clashConfig: clashConfig,
);
},title: appLocalizations.init);
});
} else {
await globalState.applyProfile(
appState: appState,

View File

@@ -56,7 +56,7 @@ enum ProfileType { file, url }
enum ResultType { success, error }
enum MessageType { log, tun, delay, process, now, request, run }
enum MessageType { log, tun, delay, process, now, request }
enum FindProcessMode { always, off }

View File

@@ -39,7 +39,7 @@ class _ConfigFragmentState extends State<ConfigFragment> {
}
}
Widget _buildAppSection() {
_buildAppSection() {
final items = [
if (Platform.isAndroid)
Selector<Config, bool>(
@@ -150,7 +150,7 @@ class _ConfigFragmentState extends State<ConfigFragment> {
);
}
Widget _buildGeneralSection() {
_buildGeneralSection() {
final items = [
Selector<ClashConfig, LogLevel>(
selector: (_, clashConfig) => clashConfig.logLevel,
@@ -335,56 +335,14 @@ class _ConfigFragmentState extends State<ConfigFragment> {
);
}
Widget _buildMoreSection() {
final items = [
if (false)
Selector<ClashConfig, bool>(
selector: (_, clashConfig) => clashConfig.tun.enable,
builder: (_, tunEnable, __) {
return ListItem.switchItem(
leading: const Icon(
Icons.important_devices_outlined
),
title: Text(appLocalizations.tun),
subtitle: Text(appLocalizations.tunDesc),
delegate: SwitchDelegate(
value: tunEnable,
onChanged: (bool value) async {
final clashConfig = context.read<ClashConfig>();
clashConfig.tun = Tun(enable: value);
globalState.appController.updateClashConfigDebounce();
},
),
);
},
),
];
if(items.isEmpty) return Container();
return Section(
title: appLocalizations.general,
child: Column(
children: [
for (final item in items) ...[
item,
if (items.last != item)
const Divider(
height: 0,
)
]
],
),
);
}
@override
Widget build(BuildContext context) {
List<Widget> items = [
_buildAppSection(),
_buildGeneralSection(),
_buildMoreSection(),
];
return ListView.builder(
padding: const EdgeInsets.only(bottom: 32),
padding: const EdgeInsets.only(bottom: 16),
itemBuilder: (_, index) {
return Container(
alignment: Alignment.center,

View File

@@ -181,6 +181,5 @@
"requestsDesc": "View recently requested data",
"nullRequestsDesc": "No proxy or no request",
"findProcessMode": "Find process",
"findProcessModeDesc": "There is a risk of flashback after opening",
"init": "Init"
"findProcessModeDesc": "There is a risk of flashback after opening"
}

View File

@@ -181,6 +181,5 @@
"requestsDesc": "查看最近请求数据",
"nullRequestsDesc": "未开启代理或者没有请求",
"findProcessMode": "查找进程",
"findProcessModeDesc": "开启后存在闪退风险",
"init": "初始化"
"findProcessModeDesc": "开启后存在闪退风险"
}

View File

@@ -142,7 +142,6 @@ class MessageLookup extends MessageLookupByLibrary {
"hours": MessageLookupByLibrary.simpleMessage("Hours"),
"importFromURL":
MessageLookupByLibrary.simpleMessage("Import from URL"),
"init": MessageLookupByLibrary.simpleMessage("Init"),
"ipCheckTimeout":
MessageLookupByLibrary.simpleMessage("Ip check timeout"),
"ipv6Desc": MessageLookupByLibrary.simpleMessage(

View File

@@ -116,7 +116,6 @@ class MessageLookup extends MessageLookupByLibrary {
"goDownload": MessageLookupByLibrary.simpleMessage("前往下载"),
"hours": MessageLookupByLibrary.simpleMessage("小时"),
"importFromURL": MessageLookupByLibrary.simpleMessage("从URL导入"),
"init": MessageLookupByLibrary.simpleMessage("初始化"),
"ipCheckTimeout": MessageLookupByLibrary.simpleMessage("Ip检测超时"),
"ipv6Desc": MessageLookupByLibrary.simpleMessage("开启后将可以接收ipv6流量"),
"just": MessageLookupByLibrary.simpleMessage("刚刚"),

View File

@@ -1879,16 +1879,6 @@ class AppLocalizations {
args: [],
);
}
/// `Init`
String get init {
return Intl.message(
'Init',
name: 'init',
desc: '',
args: [],
);
}
}
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> {

View File

@@ -54,18 +54,21 @@ Future<void> vpnService() async {
int.parse(fd),
);
}));
await globalState.init(
appState: appState,
config: config,
clashConfig: clashConfig,
);
await globalState.applyProfile(
appState: appState,
config: config,
clashConfig: clashConfig,
);
if (appState.isInit) {
await globalState.applyProfile(
appState: appState,
config: config,
clashConfig: clashConfig,
);
} else {
exit(0);
}
final appLocalizations = await AppLocalizations.load(
other.getLocaleForString(config.locale) ??
@@ -86,18 +89,19 @@ Future<void> vpnService() async {
];
}
handleStart();
tile?.addListener(
TileListenerWithVpn(
onStop: () async {
await app?.tip(appLocalizations.stopVpn);
await globalState.stopSystemProxy();
clashCore.shutdown();
exit(0);
},
),
);
if (appState.isInit) {
handleStart();
tile?.addListener(
TileListenerWithVpn(
onStop: () async {
await app?.tip(appLocalizations.stopVpn);
await globalState.stopSystemProxy();
clashCore.shutdown();
exit(0);
},
),
);
}
}
class ClashMessageListenerWithVpn with ClashMessageListener {

View File

@@ -70,7 +70,7 @@ class Config extends ChangeNotifier {
_isMinimizeOnExit = true,
_isAccessControl = false,
_autoCheckUpdate = true,
_systemProxy = true,
_systemProxy = false,
_accessControl = const AccessControl(),
_isAnimateToPage = true,
_allowBypass = true;

View File

@@ -79,7 +79,7 @@ class Process with _$Process {
class ProcessMapItem with _$ProcessMapItem {
const factory ProcessMapItem({
required int id,
required String value,
String? value,
}) = _ProcessMapItem;
factory ProcessMapItem.fromJson(Map<String, Object?> json) =>

View File

@@ -1013,7 +1013,7 @@ ProcessMapItem _$ProcessMapItemFromJson(Map<String, dynamic> json) {
/// @nodoc
mixin _$ProcessMapItem {
int get id => throw _privateConstructorUsedError;
String get value => throw _privateConstructorUsedError;
String? get value => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
@@ -1027,7 +1027,7 @@ abstract class $ProcessMapItemCopyWith<$Res> {
ProcessMapItem value, $Res Function(ProcessMapItem) then) =
_$ProcessMapItemCopyWithImpl<$Res, ProcessMapItem>;
@useResult
$Res call({int id, String value});
$Res call({int id, String? value});
}
/// @nodoc
@@ -1044,17 +1044,17 @@ class _$ProcessMapItemCopyWithImpl<$Res, $Val extends ProcessMapItem>
@override
$Res call({
Object? id = null,
Object? value = null,
Object? value = freezed,
}) {
return _then(_value.copyWith(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
value: null == value
value: freezed == value
? _value.value
: value // ignore: cast_nullable_to_non_nullable
as String,
as String?,
) as $Val);
}
}
@@ -1067,7 +1067,7 @@ abstract class _$$ProcessMapItemImplCopyWith<$Res>
__$$ProcessMapItemImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({int id, String value});
$Res call({int id, String? value});
}
/// @nodoc
@@ -1082,17 +1082,17 @@ class __$$ProcessMapItemImplCopyWithImpl<$Res>
@override
$Res call({
Object? id = null,
Object? value = null,
Object? value = freezed,
}) {
return _then(_$ProcessMapItemImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
value: null == value
value: freezed == value
? _value.value
: value // ignore: cast_nullable_to_non_nullable
as String,
as String?,
));
}
}
@@ -1100,7 +1100,7 @@ class __$$ProcessMapItemImplCopyWithImpl<$Res>
/// @nodoc
@JsonSerializable()
class _$ProcessMapItemImpl implements _ProcessMapItem {
const _$ProcessMapItemImpl({required this.id, required this.value});
const _$ProcessMapItemImpl({required this.id, this.value});
factory _$ProcessMapItemImpl.fromJson(Map<String, dynamic> json) =>
_$$ProcessMapItemImplFromJson(json);
@@ -1108,7 +1108,7 @@ class _$ProcessMapItemImpl implements _ProcessMapItem {
@override
final int id;
@override
final String value;
final String? value;
@override
String toString() {
@@ -1144,9 +1144,8 @@ class _$ProcessMapItemImpl implements _ProcessMapItem {
}
abstract class _ProcessMapItem implements ProcessMapItem {
const factory _ProcessMapItem(
{required final int id,
required final String value}) = _$ProcessMapItemImpl;
const factory _ProcessMapItem({required final int id, final String? value}) =
_$ProcessMapItemImpl;
factory _ProcessMapItem.fromJson(Map<String, dynamic> json) =
_$ProcessMapItemImpl.fromJson;
@@ -1154,7 +1153,7 @@ abstract class _ProcessMapItem implements ProcessMapItem {
@override
int get id;
@override
String get value;
String? get value;
@override
@JsonKey(ignore: true)
_$$ProcessMapItemImplCopyWith<_$ProcessMapItemImpl> get copyWith =>

View File

@@ -57,7 +57,6 @@ const _$MessageTypeEnumMap = {
MessageType.process: 'process',
MessageType.now: 'now',
MessageType.request: 'request',
MessageType.run: 'run',
};
_$DelayImpl _$$DelayImplFromJson(Map<String, dynamic> json) => _$DelayImpl(
@@ -96,7 +95,7 @@ Map<String, dynamic> _$$ProcessImplToJson(_$ProcessImpl instance) =>
_$ProcessMapItemImpl _$$ProcessMapItemImplFromJson(Map<String, dynamic> json) =>
_$ProcessMapItemImpl(
id: (json['id'] as num).toInt(),
value: json['value'] as String,
value: json['value'] as String?,
);
Map<String, dynamic> _$$ProcessMapItemImplToJson(

View File

@@ -56,10 +56,6 @@ class Proxy extends ProxyPlatform {
return await methodChannel.invokeMethod<bool?>("SetProtect", {'fd': fd});
}
Future<int?> getRunTimeStamp() async {
return await methodChannel.invokeMethod<int?>("GetRunTimeStamp");
}
Future<bool?> startForeground({
required String title,
required String content,
@@ -79,19 +75,8 @@ class Proxy extends ProxyPlatform {
}
}
// updateStartTime() async {
// startTime = clashCore.getRunTime();
// }
updateStartTime() async {
startTime = await getRunTime();
}
Future<DateTime?> getRunTime() async {
final runTimeStamp = await getRunTimeStamp();
return runTimeStamp != null
? DateTime.fromMillisecondsSinceEpoch(runTimeStamp)
: null;
startTime = clashCore.getRunTime();
}
}

View File

@@ -1,7 +1,6 @@
import 'package:fl_clash/clash/clash.dart';
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/models/models.dart';
import 'package:fl_clash/plugins/proxy.dart';
import 'package:fl_clash/state.dart';
import 'package:flutter/material.dart';
import 'package:fl_clash/plugins/app.dart';
@@ -62,7 +61,7 @@ class _ClashMessageContainerState extends State<ClashMessageContainer>
clashCore.setProcessMap(
ProcessMapItem(
id: process.id,
value: packageName ?? "",
value: packageName,
),
);
super.onProcess(process);
@@ -73,10 +72,4 @@ class _ClashMessageContainerState extends State<ClashMessageContainer>
globalState.appController.appState.addRequest(connection);
super.onRequest(connection);
}
@override
void onRun(String runTime) async {
// proxy?.updateStartTime();
super.onRun(runTime);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
name: fl_clash
description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.
publish_to: 'none'
version: 0.8.24
version: 0.8.22
environment:
sdk: '>=3.1.0 <4.0.0'

View File

@@ -61,21 +61,21 @@ class Build {
arch: Arch.amd64,
archName: 'amd64',
),
BuildLibItem(
platform: PlatformType.android,
arch: Arch.arm,
archName: 'armeabi-v7a',
),
// BuildLibItem(
// platform: PlatformType.android,
// arch: Arch.arm,
// archName: 'armeabi-v7a',
// ),
BuildLibItem(
platform: PlatformType.android,
arch: Arch.arm64,
archName: 'arm64-v8a',
),
BuildLibItem(
platform: PlatformType.android,
arch: Arch.amd64,
archName: 'x86_64',
),
// BuildLibItem(
// platform: PlatformType.android,
// arch: Arch.amd64,
// archName: 'x86_64',
// ),
BuildLibItem(
platform: PlatformType.linux,
arch: Arch.amd64,