Support better window position memory
Add windows arm64 and linux arm64 build script Optimize some details
This commit is contained in:
5
.github/release_template.md
vendored
5
.github/release_template.md
vendored
@@ -31,9 +31,10 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>macOS (v10.15+)</td>
|
<td>macOS</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="https://github.com/chen08209/FlClash/releases/download/vVERSION/FlClash-VERSION-macos-amd64.dmg"><img src="https://img.shields.io/badge/DMG-Universal-ea005e.svg?logo=apple"></a><br>
|
<a href="https://github.com/chen08209/FlClash/releases/download/vVERSION/FlClash-VERSION-macos-arm64.dmg"><img src="https://img.shields.io/badge/DMG-Apple%20Silicon-%23000000.svg?logo=apple"></a><br>
|
||||||
|
<a href="https://github.com/chen08209/FlClash/releases/download/vVERSION/FlClash-VERSION-macos-amd64.dmg"><img src="https://img.shields.io/badge/DMG-Intel%20X64-%2300A9E0.svg?logo=apple"></a><br>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
67
.github/workflows/build.yaml
vendored
67
.github/workflows/build.yaml
vendored
@@ -84,6 +84,70 @@ jobs:
|
|||||||
path: ./dist
|
path: ./dist
|
||||||
overwrite: true
|
overwrite: true
|
||||||
|
|
||||||
|
changelog:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [ build ]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
if: ${{ !contains(github.ref, '+') }}
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
ref: refs/heads/main
|
||||||
|
|
||||||
|
- name: Generate
|
||||||
|
if: ${{ !contains(github.ref, '+') }}
|
||||||
|
run: |
|
||||||
|
tags=($(git tag --merged $(git rev-parse HEAD) --sort=-creatordate))
|
||||||
|
preTag=$(grep -oP '^## \K.*' CHANGELOG.md | head -n 1)
|
||||||
|
currentTag=""
|
||||||
|
for ((i = 0; i <= ${#tags[@]}; i++)); do
|
||||||
|
if (( i < ${#tags[@]} )); then
|
||||||
|
tag=${tags[$i]}
|
||||||
|
else
|
||||||
|
tag=""
|
||||||
|
fi
|
||||||
|
if [ -n "$currentTag" ]; then
|
||||||
|
if [ "$(echo -e "$currentTag\n$preTag" | sort -V | head -n 1)" == "$currentTag" ]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ -n "$currentTag" ]; then
|
||||||
|
echo "## $currentTag" >> NEW_CHANGELOG.md
|
||||||
|
echo "" >> NEW_CHANGELOG.md
|
||||||
|
if [ -n "$tag" ]; then
|
||||||
|
git log --pretty=format:"%B" "$tag..$currentTag" | awk 'NF {print "- " $0} !NF {print ""}' >> NEW_CHANGELOG.md
|
||||||
|
else
|
||||||
|
git log --pretty=format:"%B" "$currentTag" | awk 'NF {print "- " $0} !NF {print ""}' >> NEW_CHANGELOG.md
|
||||||
|
fi
|
||||||
|
echo "" >> NEW_CHANGELOG.md
|
||||||
|
fi
|
||||||
|
currentTag=$tag
|
||||||
|
done
|
||||||
|
cat CHANGELOG.md >> NEW_CHANGELOG.md
|
||||||
|
cat NEW_CHANGELOG.md > CHANGELOG.md
|
||||||
|
|
||||||
|
- name: Commit
|
||||||
|
if: ${{ !contains(github.ref, '+') }}
|
||||||
|
run: |
|
||||||
|
git add CHANGELOG.md
|
||||||
|
if ! git diff --cached --quiet; then
|
||||||
|
echo "Commit pushing"
|
||||||
|
git config --local user.email "chen08209@gmail.com"
|
||||||
|
git config --local user.name "chen08209"
|
||||||
|
git commit -m "Update changelog"
|
||||||
|
git push
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "Push succeeded"
|
||||||
|
else
|
||||||
|
echo "Push failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
upload:
|
upload:
|
||||||
permissions: write-all
|
permissions: write-all
|
||||||
needs: [ build ]
|
needs: [ build ]
|
||||||
@@ -177,4 +241,5 @@ jobs:
|
|||||||
user-email: 'github-actions[bot]@users.noreply.github.com'
|
user-email: 'github-actions[bot]@users.noreply.github.com'
|
||||||
target-branch: action-pr
|
target-branch: action-pr
|
||||||
commit-message: Update from ${{ github.ref_name }}
|
commit-message: Update from ${{ github.ref_name }}
|
||||||
target-directory: /tmp/
|
target-directory: /tmp/
|
||||||
|
|
||||||
|
|||||||
66
.github/workflows/change.yaml
vendored
66
.github/workflows/change.yaml
vendored
@@ -1,66 +0,0 @@
|
|||||||
name: changelog
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- 'v*'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
changelog:
|
|
||||||
if: ${{ !contains(github.ref, '+') }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Generate
|
|
||||||
run: |
|
|
||||||
tags=($(git tag --merged $(git rev-parse HEAD) --sort=-creatordate))
|
|
||||||
preTag=$(grep -oP '^## \K.*' CHANGELOG.md | head -n 1)
|
|
||||||
currentTag=""
|
|
||||||
for ((i = 0; i <= ${#tags[@]}; i++)); do
|
|
||||||
if (( i < ${#tags[@]} )); then
|
|
||||||
tag=${tags[$i]}
|
|
||||||
else
|
|
||||||
tag=""
|
|
||||||
fi
|
|
||||||
if [ -n "$currentTag" ]; then
|
|
||||||
if [ "$(echo -e "$currentTag\n$preTag" | sort -V | head -n 1)" == "$currentTag" ]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if [ -n "$currentTag" ]; then
|
|
||||||
echo "## $currentTag" >> NEW_CHANGELOG.md
|
|
||||||
echo "" >> NEW_CHANGELOG.md
|
|
||||||
if [ -n "$tag" ]; then
|
|
||||||
git log --pretty=format:"%B" "$tag..$currentTag" | awk 'NF {print "- " $0} !NF {print ""}' >> NEW_CHANGELOG.md
|
|
||||||
else
|
|
||||||
git log --pretty=format:"%B" "$currentTag" | awk 'NF {print "- " $0} !NF {print ""}' >> NEW_CHANGELOG.md
|
|
||||||
fi
|
|
||||||
echo "" >> NEW_CHANGELOG.md
|
|
||||||
fi
|
|
||||||
currentTag=$tag
|
|
||||||
done
|
|
||||||
cat CHANGELOG.md >> NEW_CHANGELOG.md
|
|
||||||
cat NEW_CHANGELOG.md > CHANGELOG.md
|
|
||||||
|
|
||||||
- name: Commit
|
|
||||||
run: |
|
|
||||||
git add CHANGELOG.md
|
|
||||||
if ! git diff --cached --quiet; then
|
|
||||||
echo "Commit pushing"
|
|
||||||
git config --local user.email "chen08209@gmail.com"
|
|
||||||
git config --local user.name "chen08209"
|
|
||||||
git commit -m "Update changelog"
|
|
||||||
git push
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
echo "Push succeeded"
|
|
||||||
else
|
|
||||||
echo "Push failed"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
34
CHANGELOG.md
34
CHANGELOG.md
@@ -1,3 +1,37 @@
|
|||||||
|
## v0.8.69
|
||||||
|
|
||||||
|
- Remake desktop
|
||||||
|
|
||||||
|
- Optimize change proxy
|
||||||
|
|
||||||
|
- Optimize network check
|
||||||
|
|
||||||
|
- Fix fallback issues
|
||||||
|
|
||||||
|
- Optimize lots of details
|
||||||
|
|
||||||
|
- Update change.yaml
|
||||||
|
|
||||||
|
- Fix android tile issues
|
||||||
|
|
||||||
|
- Fix windows tray issues
|
||||||
|
|
||||||
|
- Support setting bypassDomain
|
||||||
|
|
||||||
|
- Update flutter version
|
||||||
|
|
||||||
|
- Fix android service issues
|
||||||
|
|
||||||
|
- Fix macos dock exit button issues
|
||||||
|
|
||||||
|
- Add route address setting
|
||||||
|
|
||||||
|
- Optimize provider view
|
||||||
|
|
||||||
|
- Update changelog
|
||||||
|
|
||||||
|
- Update CHANGELOG.md
|
||||||
|
|
||||||
## v0.8.67
|
## v0.8.67
|
||||||
|
|
||||||
- Add android shortcuts
|
- Add android shortcuts
|
||||||
|
|||||||
29
README.md
29
README.md
@@ -34,6 +34,29 @@ on Mobile:
|
|||||||
|
|
||||||
✨ Support subscription link, Dark mode
|
✨ Support subscription link, Dark mode
|
||||||
|
|
||||||
|
## Use
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
⚠️ Make sure to install the following dependencies before using them
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt-get install appindicator3-0.1 libappindicator3-dev
|
||||||
|
sudo apt-get install keybinder-3.0
|
||||||
|
```
|
||||||
|
|
||||||
|
### Android
|
||||||
|
|
||||||
|
Support the following actions
|
||||||
|
|
||||||
|
```bash
|
||||||
|
com.follow.clash.action.START
|
||||||
|
|
||||||
|
com.follow.clash.action.STOP
|
||||||
|
|
||||||
|
com.follow.clash.action.CHANGE
|
||||||
|
```
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
|
|
||||||
<a href="https://chen08209.github.io/FlClash-fdroid-repo/repo?fingerprint=789D6D32668712EF7672F9E58DEEB15FBD6DCEEC5AE7A4371EA72F2AAE8A12FD"><img alt="Get it on F-Droid" src="snapshots/get-it-on-fdroid.svg" width="200px"/></a> <a href="https://github.com/chen08209/FlClash/releases"><img alt="Get it on GitHub" src="snapshots/get-it-on-github.svg" width="200px"/></a>
|
<a href="https://chen08209.github.io/FlClash-fdroid-repo/repo?fingerprint=789D6D32668712EF7672F9E58DEEB15FBD6DCEEC5AE7A4371EA72F2AAE8A12FD"><img alt="Get it on F-Droid" src="snapshots/get-it-on-fdroid.svg" width="200px"/></a> <a href="https://github.com/chen08209/FlClash/releases"><img alt="Get it on GitHub" src="snapshots/get-it-on-github.svg" width="200px"/></a>
|
||||||
@@ -70,7 +93,7 @@ on Mobile:
|
|||||||
3. Run build script
|
3. Run build script
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dart .\setup.dart
|
dart .\setup.dart windows --arch <arm64 | amd64>
|
||||||
```
|
```
|
||||||
|
|
||||||
- linux
|
- linux
|
||||||
@@ -80,7 +103,7 @@ on Mobile:
|
|||||||
2. Run build script
|
2. Run build script
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dart .\setup.dart
|
dart .\setup.dart linux --arch <arm64 | amd64>
|
||||||
```
|
```
|
||||||
|
|
||||||
- macOS
|
- macOS
|
||||||
@@ -90,7 +113,7 @@ on Mobile:
|
|||||||
2. Run build script
|
2. Run build script
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dart .\setup.dart
|
dart .\setup.dart macos --arch <arm64 | amd64>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Star
|
## Star
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
[](https://t.me/FlClash)
|
[](https://t.me/FlClash)
|
||||||
|
|
||||||
|
|
||||||
基于ClashMeta的多平台代理客户端,简单易用,开源无广告。
|
基于ClashMeta的多平台代理客户端,简单易用,开源无广告。
|
||||||
|
|
||||||
on Desktop:
|
on Desktop:
|
||||||
@@ -35,6 +34,29 @@ on Mobile:
|
|||||||
|
|
||||||
✨ 支持一键导入订阅, 深色模式
|
✨ 支持一键导入订阅, 深色模式
|
||||||
|
|
||||||
|
## Use
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
⚠️ 使用前请确保安装以下依赖
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt-get install appindicator3-0.1 libappindicator3-dev
|
||||||
|
sudo apt-get install keybinder-3.0
|
||||||
|
```
|
||||||
|
|
||||||
|
### Android
|
||||||
|
|
||||||
|
支持下列操作
|
||||||
|
|
||||||
|
```bash
|
||||||
|
com.follow.clash.action.START
|
||||||
|
|
||||||
|
com.follow.clash.action.STOP
|
||||||
|
|
||||||
|
com.follow.clash.action.CHANGE
|
||||||
|
```
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
|
|
||||||
<a href="https://chen08209.github.io/FlClash-fdroid-repo/repo?fingerprint=789D6D32668712EF7672F9E58DEEB15FBD6DCEEC5AE7A4371EA72F2AAE8A12FD"><img alt="Get it on F-Droid" src="snapshots/get-it-on-fdroid.svg" width="200px"/></a> <a href="https://github.com/chen08209/FlClash/releases"><img alt="Get it on GitHub" src="snapshots/get-it-on-github.svg" width="200px"/></a>
|
<a href="https://chen08209.github.io/FlClash-fdroid-repo/repo?fingerprint=789D6D32668712EF7672F9E58DEEB15FBD6DCEEC5AE7A4371EA72F2AAE8A12FD"><img alt="Get it on F-Droid" src="snapshots/get-it-on-fdroid.svg" width="200px"/></a> <a href="https://github.com/chen08209/FlClash/releases"><img alt="Get it on GitHub" src="snapshots/get-it-on-github.svg" width="200px"/></a>
|
||||||
@@ -71,7 +93,7 @@ on Mobile:
|
|||||||
3. 运行构建脚本
|
3. 运行构建脚本
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dart .\setup.dart
|
dart .\setup.dart windows --arch <arm64 | amd64>
|
||||||
```
|
```
|
||||||
|
|
||||||
- linux
|
- linux
|
||||||
@@ -81,7 +103,7 @@ on Mobile:
|
|||||||
2. 运行构建脚本
|
2. 运行构建脚本
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dart .\setup.dart
|
dart .\setup.dart linux --arch <arm64 | amd64>
|
||||||
```
|
```
|
||||||
|
|
||||||
- macOS
|
- macOS
|
||||||
@@ -91,7 +113,7 @@ on Mobile:
|
|||||||
2. 运行构建脚本
|
2. 运行构建脚本
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dart .\setup.dart
|
dart .\setup.dart macos --arch <arm64 | amd64>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Star History
|
## Star History
|
||||||
|
|||||||
@@ -72,6 +72,10 @@
|
|||||||
android:name=".TempActivity"
|
android:name=".TempActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:theme="@style/TransparentTheme">
|
android:theme="@style/TransparentTheme">
|
||||||
|
<intent-filter>
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<action android:name="${applicationId}.action.START" />
|
||||||
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<action android:name="${applicationId}.action.STOP" />
|
<action android:name="${applicationId}.action.STOP" />
|
||||||
@@ -88,7 +92,8 @@
|
|||||||
android:foregroundServiceType="specialUse"
|
android:foregroundServiceType="specialUse"
|
||||||
android:icon="@drawable/ic_stat_name"
|
android:icon="@drawable/ic_stat_name"
|
||||||
android:label="FlClash"
|
android:label="FlClash"
|
||||||
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
|
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
|
||||||
|
tools:targetApi="n">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.service.quicksettings.action.QS_TILE" />
|
<action android:name="android.service.quicksettings.action.QS_TILE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ enum class RunState {
|
|||||||
|
|
||||||
|
|
||||||
object GlobalState {
|
object GlobalState {
|
||||||
|
|
||||||
private val lock = ReentrantLock()
|
|
||||||
val runLock = ReentrantLock()
|
val runLock = ReentrantLock()
|
||||||
|
|
||||||
val runState: MutableLiveData<RunState> = MutableLiveData<RunState>(RunState.STOP)
|
val runState: MutableLiveData<RunState> = MutableLiveData<RunState>(RunState.STOP)
|
||||||
@@ -47,35 +45,46 @@ object GlobalState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun handleToggle(context: Context) {
|
fun handleToggle(context: Context) {
|
||||||
|
val starting = handleStart(context)
|
||||||
|
if (!starting) {
|
||||||
|
handleStop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handleStart(context: Context): Boolean {
|
||||||
if (runState.value == RunState.STOP) {
|
if (runState.value == RunState.STOP) {
|
||||||
runState.value = RunState.PENDING
|
runState.value = RunState.PENDING
|
||||||
|
runLock.lock()
|
||||||
val tilePlugin = getCurrentTilePlugin()
|
val tilePlugin = getCurrentTilePlugin()
|
||||||
if (tilePlugin != null) {
|
if (tilePlugin != null) {
|
||||||
tilePlugin.handleStart()
|
tilePlugin.handleStart()
|
||||||
} else {
|
} else {
|
||||||
initServiceEngine(context)
|
initServiceEngine(context)
|
||||||
}
|
}
|
||||||
} else {
|
return true
|
||||||
handleStop()
|
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun handleStop() {
|
fun handleStop() {
|
||||||
if (runState.value == RunState.START) {
|
if (runState.value == RunState.START) {
|
||||||
runState.value = RunState.PENDING
|
runState.value = RunState.PENDING
|
||||||
|
runLock.lock()
|
||||||
getCurrentTilePlugin()?.handleStop()
|
getCurrentTilePlugin()?.handleStop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun destroyServiceEngine() {
|
fun destroyServiceEngine() {
|
||||||
serviceEngine?.destroy()
|
runLock.withLock {
|
||||||
serviceEngine = null
|
serviceEngine?.destroy()
|
||||||
|
serviceEngine = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun initServiceEngine(context: Context) {
|
fun initServiceEngine(context: Context) {
|
||||||
if (serviceEngine != null) return
|
if (serviceEngine != null) return
|
||||||
lock.withLock {
|
destroyServiceEngine()
|
||||||
destroyServiceEngine()
|
runLock.withLock {
|
||||||
serviceEngine = FlutterEngine(context)
|
serviceEngine = FlutterEngine(context)
|
||||||
serviceEngine?.plugins?.add(VpnPlugin())
|
serviceEngine?.plugins?.add(VpnPlugin())
|
||||||
serviceEngine?.plugins?.add(AppPlugin())
|
serviceEngine?.plugins?.add(AppPlugin())
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ class TempActivity : Activity() {
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
when (intent.action) {
|
when (intent.action) {
|
||||||
|
wrapAction("START") -> {
|
||||||
|
GlobalState.handleStart(applicationContext)
|
||||||
|
}
|
||||||
|
|
||||||
wrapAction("STOP") -> {
|
wrapAction("STOP") -> {
|
||||||
GlobalState.handleStop()
|
GlobalState.handleStop()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import java.io.ByteArrayOutputStream
|
|||||||
import java.net.Inet4Address
|
import java.net.Inet4Address
|
||||||
import java.net.Inet6Address
|
import java.net.Inet6Address
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
import kotlin.coroutines.suspendCoroutine
|
import kotlin.coroutines.suspendCoroutine
|
||||||
|
|
||||||
@@ -179,4 +180,19 @@ suspend fun <T> MethodChannel.awaitResult(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ReentrantLock.safeLock() {
|
||||||
|
if (this.isLocked) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.lock()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ReentrantLock.safeUnlock() {
|
||||||
|
if (!this.isLocked) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.unlock()
|
||||||
}
|
}
|
||||||
@@ -46,8 +46,6 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
|
|||||||
|
|
||||||
private var activity: Activity? = null
|
private var activity: Activity? = null
|
||||||
|
|
||||||
private var toast: Toast? = null
|
|
||||||
|
|
||||||
private lateinit var context: Context
|
private lateinit var context: Context
|
||||||
|
|
||||||
private lateinit var channel: MethodChannel
|
private lateinit var channel: MethodChannel
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import com.follow.clash.GlobalState
|
|||||||
import com.follow.clash.RunState
|
import com.follow.clash.RunState
|
||||||
import com.follow.clash.extensions.getProtocol
|
import com.follow.clash.extensions.getProtocol
|
||||||
import com.follow.clash.extensions.resolveDns
|
import com.follow.clash.extensions.resolveDns
|
||||||
|
import com.follow.clash.models.Process
|
||||||
|
import com.follow.clash.models.VpnOptions
|
||||||
import com.follow.clash.services.FlClashService
|
import com.follow.clash.services.FlClashService
|
||||||
import com.follow.clash.services.FlClashVpnService
|
import com.follow.clash.services.FlClashVpnService
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
@@ -28,8 +30,6 @@ import kotlinx.coroutines.launch
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.net.InetSocketAddress
|
import java.net.InetSocketAddress
|
||||||
import kotlin.concurrent.withLock
|
import kotlin.concurrent.withLock
|
||||||
import com.follow.clash.models.Process
|
|
||||||
import com.follow.clash.models.VpnOptions
|
|
||||||
|
|
||||||
|
|
||||||
class VpnPlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
|
class VpnPlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
|
||||||
@@ -111,11 +111,9 @@ class VpnPlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
|
|||||||
|
|
||||||
"resolverProcess" -> {
|
"resolverProcess" -> {
|
||||||
val data = call.argument<String>("data")
|
val data = call.argument<String>("data")
|
||||||
val process =
|
val process = if (data != null) Gson().fromJson(
|
||||||
if (data != null) Gson().fromJson(
|
data, Process::class.java
|
||||||
data,
|
) else null
|
||||||
Process::class.java
|
|
||||||
) else null
|
|
||||||
val metadata = process?.metadata
|
val metadata = process?.metadata
|
||||||
if (metadata == null) {
|
if (metadata == null) {
|
||||||
result.success(null)
|
result.success(null)
|
||||||
@@ -173,9 +171,7 @@ class VpnPlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
|
|||||||
fun onUpdateNetwork() {
|
fun onUpdateNetwork() {
|
||||||
val dns = networks.flatMap { network ->
|
val dns = networks.flatMap { network ->
|
||||||
connectivity?.resolveDns(network) ?: emptyList()
|
connectivity?.resolveDns(network) ?: emptyList()
|
||||||
}
|
}.toSet().joinToString(",")
|
||||||
.toSet()
|
|
||||||
.joinToString(",")
|
|
||||||
scope.launch {
|
scope.launch {
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
flutterMethodChannel.invokeMethod("dnsChanged", dns)
|
flutterMethodChannel.invokeMethod("dnsChanged", dns)
|
||||||
@@ -239,8 +235,7 @@ class VpnPlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
|
|||||||
GlobalState.runState.value = RunState.START
|
GlobalState.runState.value = RunState.START
|
||||||
val fd = flClashService?.start(options)
|
val fd = flClashService?.start(options)
|
||||||
flutterMethodChannel.invokeMethod(
|
flutterMethodChannel.invokeMethod(
|
||||||
"started",
|
"started", fd
|
||||||
fd
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,13 +116,11 @@ class Other {
|
|||||||
return "assets/images/icon_white.png";
|
return "assets/images/icon_white.png";
|
||||||
}
|
}
|
||||||
final suffix = Platform.isWindows ? "ico" : "png";
|
final suffix = Platform.isWindows ? "ico" : "png";
|
||||||
if (Platform.isWindows) {
|
return "assets/images/icon.$suffix";
|
||||||
return "assets/images/icon.$suffix";
|
// return switch (brightness) {
|
||||||
}
|
// Brightness.dark => "assets/images/icon_white.$suffix",
|
||||||
return switch (brightness) {
|
// Brightness.light => "assets/images/icon_black.$suffix",
|
||||||
Brightness.dark => "assets/images/icon_white.$suffix",
|
// };
|
||||||
Brightness.light => "assets/images/icon_black.$suffix",
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int compareVersions(String version1, String version2) {
|
int compareVersions(String version1, String version2) {
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ class Tray {
|
|||||||
MenuItem.checkbox(
|
MenuItem.checkbox(
|
||||||
label: Intl.message(mode.name),
|
label: Intl.message(mode.name),
|
||||||
onClick: (_) {
|
onClick: (_) {
|
||||||
globalState.appController.clashConfig.mode = mode;
|
globalState.appController.changeMode(mode);
|
||||||
},
|
},
|
||||||
checked: mode == clashConfig.mode,
|
checked: mode == clashConfig.mode,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'dart:io';
|
|||||||
import 'package:fl_clash/common/common.dart';
|
import 'package:fl_clash/common/common.dart';
|
||||||
import 'package:fl_clash/models/config.dart';
|
import 'package:fl_clash/models/config.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:screen_retriever/screen_retriever.dart';
|
||||||
import 'package:window_manager/window_manager.dart';
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
class Window {
|
class Window {
|
||||||
@@ -23,6 +24,35 @@ class Window {
|
|||||||
);
|
);
|
||||||
if (!Platform.isMacOS || version > 10) {
|
if (!Platform.isMacOS || version > 10) {
|
||||||
await windowManager.setTitleBarStyle(TitleBarStyle.hidden);
|
await windowManager.setTitleBarStyle(TitleBarStyle.hidden);
|
||||||
|
final left = props.left ?? 0;
|
||||||
|
final top = props.top ?? 0;
|
||||||
|
final right = left + props.width;
|
||||||
|
final bottom = top + props.height;
|
||||||
|
if (left == 0 && top == 0) {
|
||||||
|
await windowManager.setAlignment(Alignment.center);
|
||||||
|
} else {
|
||||||
|
final displays = await screenRetriever.getAllDisplays();
|
||||||
|
final isPositionValid = displays.any(
|
||||||
|
(display) {
|
||||||
|
final displayBounds = Rect.fromLTWH(
|
||||||
|
display.visiblePosition!.dx,
|
||||||
|
display.visiblePosition!.dy,
|
||||||
|
display.size.width,
|
||||||
|
display.size.height,
|
||||||
|
);
|
||||||
|
return displayBounds.contains(Offset(left, top)) ||
|
||||||
|
displayBounds.contains(Offset(right, bottom));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (isPositionValid) {
|
||||||
|
await windowManager.setPosition(
|
||||||
|
Offset(
|
||||||
|
left,
|
||||||
|
top,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await windowManager.waitUntilReadyToShow(windowOptions, () async {
|
await windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||||
await windowManager.setPreventClose(true);
|
await windowManager.setPreventClose(true);
|
||||||
|
|||||||
@@ -582,6 +582,14 @@ class AppController {
|
|||||||
updateStatus(!appFlowingState.isStart);
|
updateStatus(!appFlowingState.isStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changeMode(Mode mode) {
|
||||||
|
clashConfig.mode = mode;
|
||||||
|
if (mode == Mode.global) {
|
||||||
|
config.updateCurrentGroupName(GroupName.GLOBAL.name);
|
||||||
|
}
|
||||||
|
addCheckIpNumDebounce();
|
||||||
|
}
|
||||||
|
|
||||||
updateAutoLaunch() {
|
updateAutoLaunch() {
|
||||||
config.appSetting = config.appSetting.copyWith(
|
config.appSetting = config.appSetting.copyWith(
|
||||||
autoLaunch: !config.appSetting.autoLaunch,
|
autoLaunch: !config.appSetting.autoLaunch,
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ class _ConnectionsFragmentState extends State<ConnectionsFragment> {
|
|||||||
timer = Timer.periodic(
|
timer = Timer.periodic(
|
||||||
const Duration(seconds: 1),
|
const Duration(seconds: 1),
|
||||||
(timer) async {
|
(timer) async {
|
||||||
|
if (!context.mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
connectionsNotifier.value = connectionsNotifier.value.copyWith(
|
connectionsNotifier.value = connectionsNotifier.value.copyWith(
|
||||||
connections: await clashCore.getConnections(),
|
connections: await clashCore.getConnections(),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,14 +10,6 @@ import 'package:provider/provider.dart';
|
|||||||
class OutboundMode extends StatelessWidget {
|
class OutboundMode extends StatelessWidget {
|
||||||
const OutboundMode({super.key});
|
const OutboundMode({super.key});
|
||||||
|
|
||||||
_changeMode(BuildContext context, Mode? value) async {
|
|
||||||
final appController = globalState.appController;
|
|
||||||
final clashConfig = appController.clashConfig;
|
|
||||||
if (value == null || clashConfig.mode == value) return;
|
|
||||||
clashConfig.mode = value;
|
|
||||||
appController.addCheckIpNumDebounce();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Selector<ClashConfig, Mode>(
|
return Selector<ClashConfig, Mode>(
|
||||||
@@ -50,7 +42,10 @@ class OutboundMode extends StatelessWidget {
|
|||||||
value: item,
|
value: item,
|
||||||
groupValue: mode,
|
groupValue: mode,
|
||||||
onChanged: (value) async {
|
onChanged: (value) async {
|
||||||
_changeMode(context, value);
|
if (value == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
globalState.appController.changeMode(value);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ class _ProxiesListFragmentState extends State<ProxiesListFragment> {
|
|||||||
headerState.currentIndex > state.groupNames.length - 1
|
headerState.currentIndex > state.groupNames.length - 1
|
||||||
? 0
|
? 0
|
||||||
: headerState.currentIndex;
|
: headerState.currentIndex;
|
||||||
if (index < 0) {
|
if (index < 0 || state.groupNames.isEmpty) {
|
||||||
return Container();
|
return Container();
|
||||||
}
|
}
|
||||||
return Stack(
|
return Stack(
|
||||||
|
|||||||
@@ -117,9 +117,11 @@ class ProxiesTabFragmentState extends State<ProxiesTabFragment>
|
|||||||
}
|
}
|
||||||
final currentGroup = currentGroups[index ?? _tabController!.index];
|
final currentGroup = currentGroups[index ?? _tabController!.index];
|
||||||
currentProxies = currentGroup.all;
|
currentProxies = currentGroup.all;
|
||||||
appController.config.updateCurrentGroupName(
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
currentGroup.name,
|
appController.config.updateCurrentGroupName(
|
||||||
);
|
currentGroup.name,
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_destroyTabController() {
|
_destroyTabController() {
|
||||||
@@ -129,6 +131,10 @@ class ProxiesTabFragmentState extends State<ProxiesTabFragment>
|
|||||||
}
|
}
|
||||||
|
|
||||||
_updateTabController(int length, int index) {
|
_updateTabController(int length, int index) {
|
||||||
|
if (length == 0) {
|
||||||
|
_destroyTabController();
|
||||||
|
return;
|
||||||
|
}
|
||||||
final realIndex = index == -1 ? 0 : index;
|
final realIndex = index == -1 ? 0 : index;
|
||||||
_tabController ??= TabController(
|
_tabController ??= TabController(
|
||||||
length: length,
|
length: length,
|
||||||
@@ -162,6 +168,9 @@ class ProxiesTabFragmentState extends State<ProxiesTabFragment>
|
|||||||
(item) => item == state.currentGroupName,
|
(item) => item == state.currentGroupName,
|
||||||
);
|
);
|
||||||
_updateTabController(state.groupNames.length, index);
|
_updateTabController(state.groupNames.length, index);
|
||||||
|
if (state.groupNames.isEmpty) {
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
final GroupNameKeyMap keyMap = {};
|
final GroupNameKeyMap keyMap = {};
|
||||||
final children = state.groupNames.map((groupName) {
|
final children = state.groupNames.map((groupName) {
|
||||||
keyMap[groupName] = GlobalObjectKey(groupName);
|
keyMap[groupName] = GlobalObjectKey(groupName);
|
||||||
@@ -281,12 +290,15 @@ class ProxyGroupViewState extends State<ProxyGroupView> {
|
|||||||
if (_controller.position.maxScrollExtent == 0) {
|
if (_controller.position.maxScrollExtent == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final sortedProxies = globalState.appController.getSortProxies(
|
||||||
|
currentProxies,
|
||||||
|
);
|
||||||
_controller.animateTo(
|
_controller.animateTo(
|
||||||
min(
|
min(
|
||||||
16 +
|
16 +
|
||||||
getScrollToSelectedOffset(
|
getScrollToSelectedOffset(
|
||||||
groupName: groupName,
|
groupName: groupName,
|
||||||
proxies: currentProxies,
|
proxies: sortedProxies,
|
||||||
),
|
),
|
||||||
_controller.position.maxScrollExtent,
|
_controller.position.maxScrollExtent,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -67,6 +67,12 @@ class _WindowContainerState extends State<WindowManager>
|
|||||||
@override
|
@override
|
||||||
Future<void> onWindowMoved() async {
|
Future<void> onWindowMoved() async {
|
||||||
super.onWindowMoved();
|
super.onWindowMoved();
|
||||||
|
final offset = await windowManager.getPosition();
|
||||||
|
final config = globalState.appController.config;
|
||||||
|
config.windowProps = config.windowProps.copyWith(
|
||||||
|
top: offset.dy,
|
||||||
|
left: offset.dx,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -212,9 +212,7 @@ class AppState with ChangeNotifier {
|
|||||||
case Mode.direct:
|
case Mode.direct:
|
||||||
return [];
|
return [];
|
||||||
case Mode.global:
|
case Mode.global:
|
||||||
return groups
|
return groups.toList();
|
||||||
.where((element) => element.name == GroupName.GLOBAL.name)
|
|
||||||
.toList();
|
|
||||||
case Mode.rule:
|
case Mode.rule:
|
||||||
return groups
|
return groups
|
||||||
.where((item) => item.hidden == false)
|
.where((item) => item.hidden == false)
|
||||||
|
|||||||
Submodule plugins/flutter_distributor updated: 98d508b088...7e7bcadf29
@@ -1002,7 +1002,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "0.28.0"
|
version: "0.28.0"
|
||||||
screen_retriever:
|
screen_retriever:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: screen_retriever
|
name: screen_retriever
|
||||||
sha256: "570dbc8e4f70bac451e0efc9c9bb19fa2d6799a11e6ef04f946d7886d2e23d0c"
|
sha256: "570dbc8e4f70bac451e0efc9c9bb19fa2d6799a11e6ef04f946d7886d2e23d0c"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: fl_clash
|
name: fl_clash
|
||||||
description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.
|
description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
version: 0.8.69+202412061
|
version: 0.8.70+202412091
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.1.0 <4.0.0'
|
sdk: '>=3.1.0 <4.0.0'
|
||||||
|
|
||||||
@@ -52,6 +52,7 @@ dependencies:
|
|||||||
uni_platform: ^0.1.3
|
uni_platform: ^0.1.3
|
||||||
device_info_plus: ^10.1.2
|
device_info_plus: ^10.1.2
|
||||||
connectivity_plus: ^6.1.0
|
connectivity_plus: ^6.1.0
|
||||||
|
screen_retriever: ^0.2.0
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|||||||
99
setup.dart
99
setup.dart
@@ -21,6 +21,22 @@ extension TargetExt on Target {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get same {
|
||||||
|
if (this == Target.android) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Platform.isWindows && this == Target.windows) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Platform.isLinux && this == Target.linux) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Platform.isMacOS && this == Target.macos) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
String get dynamicLibExtensionName {
|
String get dynamicLibExtensionName {
|
||||||
final String extensionName;
|
final String extensionName;
|
||||||
switch (this) {
|
switch (this) {
|
||||||
@@ -76,12 +92,27 @@ class Build {
|
|||||||
static List<BuildItem> get buildItems => [
|
static List<BuildItem> get buildItems => [
|
||||||
BuildItem(
|
BuildItem(
|
||||||
target: Target.macos,
|
target: Target.macos,
|
||||||
|
arch: Arch.arm64,
|
||||||
),
|
),
|
||||||
BuildItem(
|
BuildItem(
|
||||||
target: Target.windows,
|
target: Target.macos,
|
||||||
|
arch: Arch.amd64,
|
||||||
),
|
),
|
||||||
BuildItem(
|
BuildItem(
|
||||||
target: Target.linux,
|
target: Target.linux,
|
||||||
|
arch: Arch.arm64,
|
||||||
|
),
|
||||||
|
BuildItem(
|
||||||
|
target: Target.linux,
|
||||||
|
arch: Arch.amd64,
|
||||||
|
),
|
||||||
|
BuildItem(
|
||||||
|
target: Target.windows,
|
||||||
|
arch: Arch.amd64,
|
||||||
|
),
|
||||||
|
BuildItem(
|
||||||
|
target: Target.windows,
|
||||||
|
arch: Arch.arm64,
|
||||||
),
|
),
|
||||||
BuildItem(
|
BuildItem(
|
||||||
target: Target.android,
|
target: Target.android,
|
||||||
@@ -200,11 +231,10 @@ class Build {
|
|||||||
|
|
||||||
final Map<String, String> env = {};
|
final Map<String, String> env = {};
|
||||||
env["GOOS"] = item.target.os;
|
env["GOOS"] = item.target.os;
|
||||||
|
if (item.arch != null) {
|
||||||
|
env["GOARCH"] = item.arch!.name;
|
||||||
|
}
|
||||||
if (isLib) {
|
if (isLib) {
|
||||||
if (item.arch != null) {
|
|
||||||
env["GOARCH"] = item.arch!.name;
|
|
||||||
}
|
|
||||||
env["CGO_ENABLED"] = "1";
|
env["CGO_ENABLED"] = "1";
|
||||||
env["CC"] = _getCc(item);
|
env["CC"] = _getCc(item);
|
||||||
env["CFLAGS"] = "-O3 -Werror";
|
env["CFLAGS"] = "-O3 -Werror";
|
||||||
@@ -272,6 +302,11 @@ class Build {
|
|||||||
Build.getExecutable("flutter clean"),
|
Build.getExecutable("flutter clean"),
|
||||||
workingDirectory: distributorDir,
|
workingDirectory: distributorDir,
|
||||||
);
|
);
|
||||||
|
await exec(
|
||||||
|
name: "upgrade distributor",
|
||||||
|
Build.getExecutable("flutter pub upgrade"),
|
||||||
|
workingDirectory: distributorDir,
|
||||||
|
);
|
||||||
await exec(
|
await exec(
|
||||||
name: "get distributor",
|
name: "get distributor",
|
||||||
Build.getExecutable("dart pub global activate -s path $distributorDir"),
|
Build.getExecutable("dart pub global activate -s path $distributorDir"),
|
||||||
@@ -303,7 +338,7 @@ class BuildCommand extends Command {
|
|||||||
BuildCommand({
|
BuildCommand({
|
||||||
required this.target,
|
required this.target,
|
||||||
}) {
|
}) {
|
||||||
if (target == Target.android) {
|
if (target == Target.android || target == Target.linux) {
|
||||||
argParser.addOption(
|
argParser.addOption(
|
||||||
"arch",
|
"arch",
|
||||||
valueHelp: arches.map((e) => e.name).join(','),
|
valueHelp: arches.map((e) => e.name).join(','),
|
||||||
@@ -315,11 +350,10 @@ class BuildCommand extends Command {
|
|||||||
help: 'The $name build archName',
|
help: 'The $name build archName',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
argParser.addOption(
|
argParser.addOption(
|
||||||
"out",
|
"out",
|
||||||
valueHelp: [
|
valueHelp: [
|
||||||
"app",
|
if (target.same) "app",
|
||||||
"core",
|
"core",
|
||||||
].join(','),
|
].join(','),
|
||||||
help: 'The $name build arch',
|
help: 'The $name build arch',
|
||||||
@@ -337,7 +371,7 @@ class BuildCommand extends Command {
|
|||||||
.map((e) => e.arch!)
|
.map((e) => e.arch!)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
_getLinuxDependencies() async {
|
_getLinuxDependencies(Arch arch) async {
|
||||||
await Build.exec(
|
await Build.exec(
|
||||||
Build.getExecutable("sudo apt update -y"),
|
Build.getExecutable("sudo apt update -y"),
|
||||||
);
|
);
|
||||||
@@ -351,7 +385,7 @@ class BuildCommand extends Command {
|
|||||||
Build.getExecutable("sudo apt install -y rpm patchelf"),
|
Build.getExecutable("sudo apt install -y rpm patchelf"),
|
||||||
);
|
);
|
||||||
await Build.exec(
|
await Build.exec(
|
||||||
Build.getExecutable("sudo apt-get install -y libkeybinder-3.0"),
|
Build.getExecutable("sudo apt-get install -y libkeybinder-3.0-dev"),
|
||||||
);
|
);
|
||||||
await Build.exec(
|
await Build.exec(
|
||||||
Build.getExecutable("sudo apt install -y locate"),
|
Build.getExecutable("sudo apt install -y locate"),
|
||||||
@@ -359,9 +393,10 @@ class BuildCommand extends Command {
|
|||||||
await Build.exec(
|
await Build.exec(
|
||||||
Build.getExecutable("sudo apt install -y libfuse2"),
|
Build.getExecutable("sudo apt install -y libfuse2"),
|
||||||
);
|
);
|
||||||
|
final downloadName = arch == Arch.amd64 ? "x86_64" : "aarch_64";
|
||||||
await Build.exec(
|
await Build.exec(
|
||||||
Build.getExecutable(
|
Build.getExecutable(
|
||||||
"wget -O appimagetool https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage",
|
"wget -O appimagetool https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-$downloadName.AppImage",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
await Build.exec(
|
await Build.exec(
|
||||||
@@ -409,14 +444,14 @@ class BuildCommand extends Command {
|
|||||||
@override
|
@override
|
||||||
Future<void> run() async {
|
Future<void> run() async {
|
||||||
final mode = target == Target.android ? Mode.lib : Mode.core;
|
final mode = target == Target.android ? Mode.lib : Mode.core;
|
||||||
final String out = argResults?['out'] ?? 'app';
|
final String out = argResults?["out"] ?? (target.same ? "app" : "core");
|
||||||
Arch? arch;
|
final archName = argResults?["arch"];
|
||||||
var archName = argResults?['arch'];
|
final currentArches =
|
||||||
|
arches.where((element) => element.name == archName).toList();
|
||||||
|
final arch = currentArches.isEmpty ? null : currentArches.first;
|
||||||
|
|
||||||
if (target == Target.android) {
|
if (arch == null && target != Target.android) {
|
||||||
final currentArches =
|
throw "Invalid arch parameter";
|
||||||
arches.where((element) => element.name == archName).toList();
|
|
||||||
arch = currentArches.isEmpty ? null : currentArches.first;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await Build.buildCore(
|
await Build.buildCore(
|
||||||
@@ -440,13 +475,21 @@ class BuildCommand extends Command {
|
|||||||
targets: "exe,zip",
|
targets: "exe,zip",
|
||||||
args: "--description $archName",
|
args: "--description $archName",
|
||||||
);
|
);
|
||||||
|
return;
|
||||||
case Target.linux:
|
case Target.linux:
|
||||||
await _getLinuxDependencies();
|
final targetMap = {
|
||||||
|
Arch.arm64: "linux-arm64",
|
||||||
|
Arch.amd64: "linux-x64",
|
||||||
|
};
|
||||||
|
final defaultTarget = targetMap[arch];
|
||||||
|
await _getLinuxDependencies(arch!);
|
||||||
_buildDistributor(
|
_buildDistributor(
|
||||||
target: target,
|
target: target,
|
||||||
targets: "appimage,deb,rpm",
|
targets: "appimage,deb",
|
||||||
args: "--description $archName",
|
args:
|
||||||
|
"--description $archName --build-target-platform $defaultTarget",
|
||||||
);
|
);
|
||||||
|
return;
|
||||||
case Target.android:
|
case Target.android:
|
||||||
final targetMap = {
|
final targetMap = {
|
||||||
Arch.arm: "android-arm",
|
Arch.arm: "android-arm",
|
||||||
@@ -464,6 +507,7 @@ class BuildCommand extends Command {
|
|||||||
args:
|
args:
|
||||||
"--flutter-build-args split-per-abi --build-target-platform ${defaultTargets.join(",")}",
|
"--flutter-build-args split-per-abi --build-target-platform ${defaultTargets.join(",")}",
|
||||||
);
|
);
|
||||||
|
return;
|
||||||
case Target.macos:
|
case Target.macos:
|
||||||
await _getMacosDependencies();
|
await _getMacosDependencies();
|
||||||
_buildDistributor(
|
_buildDistributor(
|
||||||
@@ -471,6 +515,7 @@ class BuildCommand extends Command {
|
|||||||
targets: "dmg",
|
targets: "dmg",
|
||||||
args: "--description $archName",
|
args: "--description $archName",
|
||||||
);
|
);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -478,14 +523,8 @@ class BuildCommand extends Command {
|
|||||||
main(args) async {
|
main(args) async {
|
||||||
final runner = CommandRunner("setup", "build Application");
|
final runner = CommandRunner("setup", "build Application");
|
||||||
runner.addCommand(BuildCommand(target: Target.android));
|
runner.addCommand(BuildCommand(target: Target.android));
|
||||||
if (Platform.isWindows) {
|
runner.addCommand(BuildCommand(target: Target.linux));
|
||||||
runner.addCommand(BuildCommand(target: Target.windows));
|
runner.addCommand(BuildCommand(target: Target.windows));
|
||||||
}
|
runner.addCommand(BuildCommand(target: Target.macos));
|
||||||
if (Platform.isLinux) {
|
|
||||||
runner.addCommand(BuildCommand(target: Target.linux));
|
|
||||||
}
|
|
||||||
if (Platform.isMacOS) {
|
|
||||||
runner.addCommand(BuildCommand(target: Target.macos));
|
|
||||||
}
|
|
||||||
runner.run(args);
|
runner.run(args);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user