Compare commits

...
24 Commits
Author SHA1 Message Date
liwei 82d316af83 ci: fix go version env 2023-10-08 16:42:33 +08:00
liwei 150953a033 chore: upgrade go version to 1.20 2023-10-08 16:40:53 +08:00
liwei f30ad6641f ci: fix xgo version 2023-10-08 16:04:24 +08:00
liwei 7019f18635 release: v1.3.13 2023-10-08 15:36:13 +08:00
Levi c0338c3d8e feat: auto recognize magnet uri (#230) 2023-10-08 15:29:19 +08:00
Levi fe55f1bd54 feat: adapts to Android 14 (#229) 2023-10-06 11:51:12 +08:00
liwei 48f8c60672 ci: disable auto translate 2023-09-22 15:34:45 +08:00
Elliot cc97cedf0f feat: improve zh-TW translate (#224) 2023-09-21 22:08:19 +08:00
Levi a7d855f65a release: v1.3.12 2023-09-20 16:33:47 +08:00
Levi f0f16b3c80 ci: disable translate 2023-09-20 16:32:02 +08:00
Levi 3459b474db feat: file open on mobile (#223) 2023-09-20 16:29:08 +08:00
Tracey Lesley d28fcef0a7 feat: default http User-Agent header (#26) 2023-09-13 10:03:26 +08:00
Elliot d694c08635 feat: add zh-TW.json translate (#209) 2023-09-08 09:19:55 +08:00
liwei a7c61a668e chore: update donate doc 2023-09-07 09:32:33 +08:00
Levi 09aea55b49 release: v1.3.11 2023-09-04 13:57:47 +08:00
Levi c0cd2d7255 feat: task file manage (#196)
1. support view task file list
2. support share file on android and iOS
2023-09-04 13:51:30 +08:00
Levi b00f4a1ed0 feat: ios support (#194) 2023-09-04 11:28:07 +08:00
Levi 06766eea56 feat: auto get create url from clipboard (#193) 2023-09-02 11:32:28 +08:00
Levi 0f0c8f27bd feat: adjust size of resource dialog (#192) 2023-09-02 11:26:26 +08:00
liwei 45cf62f88d release: v1.3.10 2023-08-26 09:17:22 +08:00
Levi 6e9d3499d9 fix: drop file crash on Windows (#189) 2023-08-26 08:58:10 +08:00
Levi b6d60f6bdf fix: http download timeout (#188) 2023-08-25 18:42:10 +08:00
Levi e1684e755a fix: go install fail (#184) 2023-08-16 17:05:20 +08:00
Tracey Lesley e63cfca82a fix:current writes map (#182) 2023-08-12 13:45:01 +08:00
68 changed files with 1031 additions and 287 deletions

No files matched your search

+4 -4
View File
@@ -1,20 +1,20 @@
## Donate
Thank you for your support! 🙏
🙏 Thank you for considering a donation to Gopeed project! Your support helps us continue to develop and maintain our software.
<div style="text-align: center;">
<table>
<tr>
<th>微信</th>
<th>支付宝</th>
<th>PayPal</th>
<th>Ko-fi</th>
<th>PayPal</th>
</tr>
<tr>
<td><img src="/.donate/qr/wechatpay.jpg" alt="wechatpay" width="300" /></td>
<td><img src="/.donate/qr/alipay.jpg" alt="alipay" width="300" /></td>
<td><a href="https://paypal.me/monkeyWie" target="_blank">Click Me</a></td>
<td><a href="https://ko-fi.com/gopeed" target="_blank">Click Me</a></td>
<td><a href="https://paypal.me/monkeyWie" target="_blank">Click Me</a></td>
</table>
</div>
@@ -24,4 +24,4 @@ Thank you for your support! 🙏
- **ETH:** 0x928a7fd2398c941Ac6713704e606Fa414595e3A0
- **Matic:** 0x928a7fd2398c941Ac6713704e606Fa414595e3A0
- **BNB:** 0x928a7fd2398c941Ac6713704e606Fa414595e3A0
- **USDT(ERC20)**: 0x928a7fd2398c941Ac6713704e606Fa414595e3A0
- **USDT(ERC20)**: 0x928a7fd2398c941Ac6713704e606Fa414595e3A0
+40 -9
View File
@@ -4,7 +4,7 @@ on:
workflow_dispatch:
env:
GO_VERSION: 1.19
GO_VERSION: "1.20"
FLUTTER_VERSION: 3.10.6
permissions:
@@ -39,7 +39,7 @@ jobs:
VERSION: ${{ needs.get-release.outputs.tag_name }}
run: |
Invoke-WebRequest -Uri "https://github.com/jrsoftware/issrc/raw/main/Files/Languages/Unofficial/ChineseSimplified.isl" -OutFile "ChineseSimplified.isl"
mv ChineseSimplified.isl "C:\Program Files (x86)\Inno Setup 6\Languages\"
mv ChineseSimplified.isl "C:\Program Files (x86)\Inno Setup 6\Languages\"
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/windows/libgopeed.dll github.com/GopeedLab/gopeed/bind/desktop
cd ui/flutter
@@ -90,7 +90,7 @@ jobs:
SolidCompression=yes
WizardStyle=modern
LanguageDetectionMethod=uilanguage
ShowLanguageDialog=yes
ShowLanguageDialog=yes
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
@@ -133,9 +133,8 @@ jobs:
go-version: ${{ env.GO_VERSION }}
- name: Build
run: |
docker pull techknowlogick/xgo:go-1.19.x
go install src.techknowlogick.com/xgo@latest
xgo --targets=darwin/arm64 -tags="nosqlite" -ldflags="-w -s" -buildmode=c-shared -pkg=bind/desktop -out=libgopeed .
xgo -go go-$GO_VERSION.x --targets=darwin/arm64 -tags="nosqlite" -ldflags="-w -s" -buildmode=c-shared -pkg=bind/desktop -out=libgopeed .
mv libgopeed-*.dylib libgopeed.dylib
- uses: actions/upload-artifact@v3
with:
@@ -166,7 +165,7 @@ jobs:
VERSION: ${{ needs.get-release.outputs.tag_name }}
run: |
PROJECT_DIR=$(pwd)
# amd64 lib
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/lib-amd64/libgopeed.dylib github.com/GopeedLab/gopeed/bind/desktop
# universal binary
@@ -221,13 +220,13 @@ jobs:
mkdir -p debian/gui
cp assets/icon/icon_1024.png debian/gui/gopeed.png
cat>debian/debian.yaml<<EOF
flutter_app:
flutter_app:
command: gopeed
arch: x64
parent: /usr/local/lib
control:
Package: gopeed
Version: ${VERSION:1}
Version: ${VERSION:1}
Architecture: amd64
Essential: no
Priority: optional
@@ -238,7 +237,7 @@ jobs:
cat>debian/gui/gopeed.desktop<<EOF
[Desktop Entry]
Version=${VERSION:1}
Version=${VERSION:1}
Name=Gopeed
GenericName=Gopeed
Comment=High speed downloader that supports all platforms.
@@ -294,6 +293,38 @@ jobs:
upload_url: ${{ needs.get-release.outputs.upload_url }}
asset_path: ui/flutter/dist/*
overwrite: true
build-ios:
runs-on: macos-latest
needs: [get-release]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: ${{ env.GO_VERSION }}
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
- name: Build
env:
VERSION: ${{ needs.get-release.outputs.tag_name }}
run: |
go install golang.org/x/mobile/cmd/gomobile@latest
go get golang.org/x/mobile/bind
gomobile init
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/ios/Frameworks/Libgopeed.xcframework -target=ios github.com/GopeedLab/gopeed/bind/mobile
cd ui/flutter
flutter build ios --no-codesign
mkdir Payload
cp -r build/ios/iphoneos/Runner.app Payload
zip -r -y Payload.zip Payload/Runner.app
mkdir dist
mv Payload.zip dist/Gopeed-$VERSION-ios.ipa
- name: Upload
uses: shogo82148/actions-upload-release-asset@v1
with:
upload_url: ${{ needs.get-release.outputs.upload_url }}
asset_path: ui/flutter/dist/*
overwrite: true
build-web:
runs-on: ubuntu-latest
needs: [get-release]
+1 -1
View File
@@ -17,7 +17,7 @@ on:
- "Dockerfile"
env:
GO_VERSION: 1.19
GO_VERSION: "1.20"
permissions:
contents: write
+1 -1
View File
@@ -27,7 +27,7 @@ on:
- "go.sum"
env:
GO_VERSION: 1.19
GO_VERSION: "1.20"
FLUTTER_VERSION: 3.10.6
jobs:
-30
View File
@@ -1,30 +0,0 @@
name: 'translator'
on:
issues:
types: [opened, edited]
issue_comment:
types: [created, edited]
discussion:
types: [created, edited]
discussion_comment:
types: [created, edited]
pull_request_target:
types: [opened, edited]
pull_request_review_comment:
types: [created, edited]
jobs:
translate:
permissions:
issues: write
discussions: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: lizheming/[email protected]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
IS_MODIFY_TITLE: true
APPEND_TRANSLATION: true
+30
View File
@@ -0,0 +1,30 @@
# name: 'translator'
# on:
# issues:
# types: [opened, edited]
# issue_comment:
# types: [created, edited]
# discussion:
# types: [created, edited]
# discussion_comment:
# types: [created, edited]
# pull_request_target:
# types: [opened, edited]
# pull_request_review_comment:
# types: [created, edited]
# jobs:
# translate:
# permissions:
# issues: write
# discussions: write
# pull-requests: write
# runs-on: ubuntu-latest
# steps:
# - uses: lizheming/[email protected]
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# with:
# IS_MODIFY_TITLE: true
# APPEND_TRANSLATION: true
+12 -2
View File
@@ -7,6 +7,8 @@
![](_docs/img/banner.png)
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/R6R6IJGN6)
[English](/README.md) | [中文](/README_zh-CN.md) | [日本語](/README_ja-JP.md)
## Introduction
@@ -23,7 +25,7 @@ Visit ✈ [Official Website](https://gopeed.com) | 📖 [Develop Docs](https://d
- [x] macos
- [x] linux
- [x] android
- [ ] ios
- [x] ios
- [x] web
- [x] docker
@@ -138,6 +140,14 @@ cd ui/flutter
flutter build apk
```
- ios
```bash
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/ios/Frameworks/Libgopeed.xcframework -target=ios github.com/GopeedLab/gopeed/bind/mobile
cd ui/flutter
flutter build ios --no-codesign
```
#### Web
command:
@@ -152,7 +162,7 @@ go build -tags nosqlite,web -ldflags="-s -w" -o bin/ github.com/GopeedLab/gopeed
go run cmd/web/main.go
```
## Thanks
## Credits
### Contributors
+11 -1
View File
@@ -7,6 +7,8 @@
![](_docs/img/banner.png)
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/R6R6IJGN6)
[English](/README.md) | [中文](/README_zh-CN.md) | [日本語](/README_ja-JP.md)
## はじめに
@@ -23,7 +25,7 @@ Gopeed (正式名 Go Speed) は `Golang` + `Flutter` によって開発された
- [x] macos
- [x] linux
- [x] android
- [ ] ios
- [x] ios
- [x] web
- [x] docker
@@ -138,6 +140,14 @@ cd ui/flutter
flutter build apk
```
- ios
```bash
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/ios/Frameworks/Libgopeed.xcframework -target=ios github.com/GopeedLab/gopeed/bind/mobile
cd ui/flutter
flutter build ios --no-codesign
```
#### Web
コマンド:
+11 -1
View File
@@ -7,6 +7,8 @@
![](_docs/img/banner.png)
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/R6R6IJGN6)
[English](/README.md) | [中文](/README_zh-CN.md) | [日本語](/README_ja-JP.md)
## 介绍
@@ -23,7 +25,7 @@ Gopeed(全称 Go Speed),是一款由`Golang`+`Flutter`开发的高速下
- [x] macos
- [x] linux
- [x] android
- [ ] ios
- [x] ios
- [x] web
- [x] docker
@@ -138,6 +140,14 @@ cd ui/flutter
flutter build apk
```
- ios
```bash
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/ios/Frameworks/Libgopeed.xcframework -target=ios github.com/GopeedLab/gopeed/bind/mobile
cd ui/flutter
flutter build ios --no-codesign
```
#### Web 端
构建命令:
+6 -8
View File
@@ -1,20 +1,18 @@
module github.com/GopeedLab/gopeed
go 1.19
go 1.20
require (
github.com/anacrolix/missinggo/v2 v2.7.2-0.20230527121029-a582b4f397b9
github.com/anacrolix/torrent v1.52.3
github.com/anacrolix/torrent v1.52.5
github.com/gorilla/handlers v1.5.1
github.com/gorilla/mux v1.8.0
github.com/matoous/go-nanoid/v2 v2.0.0
github.com/virtuald/go-paniclog v0.0.0-20190812204905-43a7fa316459
go.etcd.io/bbolt v1.3.6
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde
go.etcd.io/bbolt v1.3.7-0.20231005155708-db45d0d6b1f6
golang.org/x/sync v0.3.0
)
replace github.com/anacrolix/torrent => github.com/monkeyWie/torrent v1.52.5-alpha
require (
crawshaw.io/sqlite v0.3.3-0.20220618202545-d1964889ea3c // indirect
github.com/RoaringBitmap/roaring v1.2.3 // indirect
@@ -24,7 +22,7 @@ require (
github.com/anacrolix/dht/v2 v2.19.2-0.20221121215055-066ad8494444 // indirect
github.com/anacrolix/envpprof v1.2.1 // indirect
github.com/anacrolix/generics v0.0.0-20230428105757-683593396d68 // indirect
github.com/anacrolix/go-libutp v1.2.0 // indirect
github.com/anacrolix/go-libutp v1.3.1 // indirect
github.com/anacrolix/log v0.14.0 // indirect
github.com/anacrolix/missinggo v1.3.0 // indirect
github.com/anacrolix/missinggo/perf v1.0.0 // indirect
@@ -76,6 +74,6 @@ require (
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/exp v0.0.0-20220613132600-b0d781184e0d // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect
)
+14 -13
View File
@@ -35,12 +35,12 @@ github.com/anacrolix/envpprof v1.2.1 h1:25TJe6t/i0AfzzldiGFKCpD+s+dk8lONBcacJZB2
github.com/anacrolix/envpprof v1.2.1/go.mod h1:My7T5oSqVfEn4MD4Meczkw/f5lSIndGAKu/0SM/rkf4=
github.com/anacrolix/generics v0.0.0-20230428105757-683593396d68 h1:fyXlBfnlFzZSFckJ8QLb2lfmWfY++4RiUnae7ZMuv0A=
github.com/anacrolix/generics v0.0.0-20230428105757-683593396d68/go.mod h1:ff2rHB/joTV03aMSSn/AZNnaIpUw0h3njetGsaXcMy8=
github.com/anacrolix/go-libutp v1.2.0 h1:sjxoB+/ARiKUR7IK/6wLWyADIBqGmu1fm0xo+8Yy7u0=
github.com/anacrolix/go-libutp v1.2.0/go.mod h1:RrJ3KcaDcf9Jqp33YL5V/5CBEc6xMc7aJL8wXfuWL50=
github.com/anacrolix/go-libutp v1.3.1 h1:idJzreNLl+hNjGC3ZnUOjujEaryeOGgkwHLqSGoige0=
github.com/anacrolix/go-libutp v1.3.1/go.mod h1:heF41EC8kN0qCLMokLBVkB8NXiLwx3t8R8810MTNI5o=
github.com/anacrolix/log v0.3.0/go.mod h1:lWvLTqzAnCWPJA08T2HCstZi0L1y2Wyvm3FJgwU9jwU=
github.com/anacrolix/log v0.6.0/go.mod h1:lWvLTqzAnCWPJA08T2HCstZi0L1y2Wyvm3FJgwU9jwU=
github.com/anacrolix/log v0.10.0/go.mod h1:s5yBP/j046fm9odtUTbHOfDUq/zh1W8OkPpJtnX0oQI=
github.com/anacrolix/log v0.10.1-0.20220123034749-3920702c17f8/go.mod h1:GmnE2c0nvz8pOIPUSC9Rawgefy1sDXqposC2wgtBZE4=
github.com/anacrolix/log v0.13.1/go.mod h1:D4+CvN8SnruK6zIFS/xPoRJmtvtnxs+CSfDQ+BFxZ68=
github.com/anacrolix/log v0.14.0 h1:mYhTSemILe/Z8tIxbGdTIWWpPspI8W/fhZHpoFbDaL0=
github.com/anacrolix/log v0.14.0/go.mod h1:1OmJESOtxQGNMlUO5rcv96Vpp9mfMqXXbe2RdinFLdY=
github.com/anacrolix/lsan v0.0.0-20211126052245-807000409a62 h1:P04VG6Td13FHMgS5ZBcJX23NPC/fiC4cp9bXwYujdYM=
@@ -73,6 +73,8 @@ github.com/anacrolix/sync v0.4.0/go.mod h1:BbecHL6jDSExojhNtgTFSBcdGerzNc64tz3DC
github.com/anacrolix/tagflag v0.0.0-20180109131632-2146c8d41bf0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw=
github.com/anacrolix/tagflag v1.0.0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw=
github.com/anacrolix/tagflag v1.1.0/go.mod h1:Scxs9CV10NQatSmbyjqmqmeQNwGzlNe0CMUMIxqHIG8=
github.com/anacrolix/torrent v1.52.5 h1:jWowdx+EU6zFVfBwmnL0d3H4J6vTFEGOrHI35YdfIT8=
github.com/anacrolix/torrent v1.52.5/go.mod h1:CcM8oPMYye5J42cSqJrmUpqwRFgSsJQ1jCEHwygqnqQ=
github.com/anacrolix/upnp v0.1.3-0.20220123035249-922794e51c96 h1:QAVZ3pN/J4/UziniAhJR2OZ9Ox5kOY2053tBbbqUPYA=
github.com/anacrolix/upnp v0.1.3-0.20220123035249-922794e51c96/go.mod h1:Wa6n8cYIdaG35x15aH3Zy6d03f7P728QfdcDeD/IEOs=
github.com/anacrolix/utp v0.1.0 h1:FOpQOmIwYsnENnz7tAGohA+r6iXpRjrq8ssKSre2Cp4=
@@ -210,8 +212,6 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/monkeyWie/torrent v1.52.5-alpha h1:JnGTtfwrnrxaMdpzDgHbzfLEnXhkmldnk0iyka+2Ntw=
github.com/monkeyWie/torrent v1.52.5-alpha/go.mod h1:yBUcBuIOlttGEgAW/6gamzQGD+k2+wUh65fOPPzxvC4=
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
@@ -324,8 +324,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg=
github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
@@ -337,8 +337,8 @@ github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPyS
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
go.etcd.io/bbolt v1.3.7-0.20231005155708-db45d0d6b1f6 h1:NkHVT1GBVV9hUj1iWglFxAuNlvLHELFn71U2H7aOIog=
go.etcd.io/bbolt v1.3.7-0.20231005155708-db45d0d6b1f6/go.mod h1:tDI2vlr15+D9cyN3odhFrZJi3oJj8HlHaOEFPrUiGSY=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -365,7 +365,6 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180524181706-dfa909b99c79/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -404,8 +403,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde h1:ejfdSekXMDxDLbRrJMwUk6KnSLZ2McaUCVcIKM+N6jc=
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -422,7 +421,6 @@ golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -435,12 +433,14 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -448,6 +448,7 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U=
golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+7 -5
View File
@@ -17,7 +17,6 @@ import (
"os"
"path"
"strconv"
"time"
)
type RequestError struct {
@@ -85,13 +84,14 @@ func (f *Fetcher) Resolve(req *base.Request) error {
return err
}
client := buildClient()
// 只访问一个字节,测试资源是否支持Range请求
// send Range request to check whether the server supports breakpoint continuation
// just test one byte, Range: bytes=0-0
httpReq.Header.Set(base.HttpHeaderRange, fmt.Sprintf(base.HttpHeaderRangeFormat, 0, 0))
httpResp, err := client.Do(httpReq)
if err != nil {
return err
}
// 拿到响应头就关闭,不用加defer
// close response body immediately
httpResp.Body.Close()
res := &base.Resource{
Range: false,
@@ -395,8 +395,7 @@ func buildClient() *http.Client {
// Cookie handle
jar, _ := cookiejar.New(nil)
return &http.Client{
Jar: jar,
Timeout: time.Second * 60,
Jar: jar,
}
}
@@ -429,6 +428,9 @@ func buildRequest(ctx context.Context, req *base.Request) (httpReq *http.Request
body = bytes.NewBufferString(extra.Body)
}
}
if _, ok := headers[base.HttpHeaderUserAgent]; !ok {
headers[base.HttpHeaderUserAgent] = []string{base.AgentName}
}
if ctx != nil {
httpReq, err = http.NewRequestWithContext(ctx, method, url.String(), body)
+5
View File
@@ -19,6 +19,11 @@ const (
HttpHeaderContentLength = "Content-Length"
HttpHeaderContentRange = "Content-Range"
HttpHeaderContentDisposition = "Content-Disposition"
HttpHeaderUserAgent = "User-Agent"
HttpHeaderRangeFormat = "bytes=%d-%d"
)
const (
AgentName = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"
)
+18 -6
View File
@@ -47,8 +47,9 @@ type Downloader struct {
tasks []*Task
listener Listener
lock *sync.Mutex
closed atomic.Bool
lock *sync.Mutex
fetcherMapLock *sync.RWMutex
closed atomic.Bool
}
func NewDownloader(cfg *DownloaderConfig) *Downloader {
@@ -63,8 +64,9 @@ func NewDownloader(cfg *DownloaderConfig) *Downloader {
fetchBuilders: make(map[string]fetcher.FetcherBuilder),
fetcherMap: make(map[string]fetcher.Fetcher),
storage: cfg.Storage,
lock: &sync.Mutex{},
storage: cfg.Storage,
lock: &sync.Mutex{},
fetcherMapLock: &sync.RWMutex{},
}
for _, f := range cfg.FetchBuilders {
for _, p := range f.Schemes() {
@@ -198,7 +200,9 @@ func (d *Downloader) Resolve(req *base.Request) (rr *ResolveResult, err error) {
if err != nil {
return
}
d.fetcherMapLock.Lock()
d.fetcherMap[rrId] = fetcher
d.fetcherMapLock.Unlock()
rr = &ResolveResult{
ID: rrId,
Res: fetcher.Meta().Res,
@@ -218,11 +222,17 @@ func (d *Downloader) Create(rrId string, opts *base.Options) (taskId string, err
if opts == nil {
opts = &base.Options{}
}
d.fetcherMapLock.RLock()
fetcher, ok := d.fetcherMap[rrId]
d.fetcherMapLock.RUnlock()
if !ok {
return "", errors.New("invalid resource id")
}
defer delete(d.fetcherMap, rrId)
defer func() {
d.fetcherMapLock.Lock()
delete(d.fetcherMap, rrId)
d.fetcherMapLock.Unlock()
}()
meta := fetcher.Meta()
meta.Opts = opts
@@ -518,7 +528,9 @@ func (d *Downloader) watch(task *Task) {
d.emit(EventKeyDone, task)
}
d.emit(EventKeyFinally, task, err)
d.notifyRunning()
if task.Status == EventKeyDone {
d.notifyRunning()
}
}
func (d *Downloader) restoreFetcher(task *Task) error {
@@ -31,12 +31,8 @@ class MainActivity : FlutterActivity() {
}
}
"stop" -> {
try {
Libgopeed.stop()
result.success(null)
} catch (e: Exception) {
result.error("ERROR", e.message, null)
}
Libgopeed.stop()
result.success(null)
}
else -> {
result.notImplemented()
+1 -1
View File
@@ -29,7 +29,7 @@
"downloadDirValid": "请选择下载目录",
"connections": "连接数",
"maxRunning": "最大下载数",
"items": "@count 条",
"items": "@count 项",
"subscribeTracker": "订阅 Tracker",
"subscribeFail": "订阅失败,请检查网络或稍后重试",
"update": "更新",
+63
View File
@@ -0,0 +1,63 @@
{
"label": "中文 (正體) ",
"error": "錯誤",
"tip": "提示",
"confirm": "確定",
"cancel": "取消",
"selectAll": "全選",
"task": "任務",
"downloading": "下載中",
"downloaded": "已完成",
"setting": "設定",
"donate": "斗內",
"exit": "離開",
"create": "新增任務",
"advancedOptions": "進階選項",
"downloadLink": "下載鏈接",
"downloadLinkValid": "請輸入下載鏈接",
"downloadLinkHit": "請輸入下載鏈接,支援 HTTP/HTTPS/MAGNET@append",
"downloadLinkHitDesktop": ",也可以通過拖拽Torrent文件至此以新增任務",
"download": "下載",
"noFileSelected": "沒有選取的文件",
"noStoragePermission": "沒有存儲權限",
"selectFile": "選擇文件",
"rename": "重命名",
"basic": "基礎",
"advanced": "進階",
"general": "通用設定",
"downloadDir": "下載目録",
"downloadDirValid": "請選擇下載目録",
"connections": "同時連接數量",
"maxRunning": "最大同時下載數",
"items": "@count 項",
"subscribeTracker": "已訂閲的 Tracker",
"subscribeFail": "訂閲失敗",
"update": "更新",
"updateDaily": "每日自動更新",
"lastUpdate": "上次更新時間: @time",
"addTracker": "增加新的 Tracker",
"addTrackerHit": "請輸入 Tracker 服務器地址,每行一條",
"ui": "介面",
"theme": "佈景主題",
"themeSystem": "跟隨系統",
"themeLight": "亮色主題",
"themeDark": "暗色主題",
"locale": "語言",
"about": "關於",
"homepage": "訪問主頁",
"version": "版本資訊",
"protocol": "通訊協定",
"port": "端口",
"apiToken": "接口 Token",
"notSet": "尚未設定",
"set": "已設定",
"effectAfterRestart": "該選項將在重新啓動軟體後生效",
"startAll": "全部開始",
"pauseAll": "全部暫停",
"deleteTask": "刪除任務",
"deleteTaskTip": "保留已經下載的文件",
"delete": "刪除",
"newVersionTitle": "發現新版本 @version",
"newVersionUpdate": "立刻更新",
"newVersionLater": "稍後更新"
}
@@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>9.0</string>
<string>11.0</string>
</dict>
</plist>
+1 -1
View File
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'
# platform :ios, '11.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
+52
View File
@@ -0,0 +1,52 @@
PODS:
- file_selector_ios (0.0.1):
- Flutter
- Flutter (1.0.0)
- package_info_plus (0.4.5):
- Flutter
- path_provider_ios (0.0.1):
- Flutter
- permission_handler_apple (9.0.4):
- Flutter
- shared_preferences_ios (0.0.1):
- Flutter
- url_launcher_ios (0.0.1):
- Flutter
DEPENDENCIES:
- file_selector_ios (from `.symlinks/plugins/file_selector_ios/ios`)
- Flutter (from `Flutter`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
EXTERNAL SOURCES:
file_selector_ios:
:path: ".symlinks/plugins/file_selector_ios/ios"
Flutter:
:path: Flutter
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_ios:
:path: ".symlinks/plugins/path_provider_ios/ios"
permission_handler_apple:
:path: ".symlinks/plugins/permission_handler_apple/ios"
shared_preferences_ios:
:path: ".symlinks/plugins/shared_preferences_ios/ios"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
SPEC CHECKSUMS:
file_selector_ios: 6e9b6d7300556c730f224905726f0a2d5d874e51
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
COCOAPODS: 1.11.3
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@@ -13,28 +13,36 @@
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
D081C25C294826C0006EB10B /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D081C25B294826C0006EB10B /* libc++.tbd */; };
D0E623A929482D160001185E /* Libgopeed.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0E623A729482D030001185E /* Libgopeed.xcframework */; };
D0E623AA29482D160001185E /* Libgopeed.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D0E623A729482D030001185E /* Libgopeed.xcframework */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
DCA5B0FA95A8007ADEDACA1B /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 70BC8D37FAC641C7F20125E8 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
buildActionMask = 8;
dstPath = "";
dstSubfolderSpec = 10;
files = (
D0E623AA29482D160001185E /* Libgopeed.xcframework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
25B61E78A388C87913468FD6 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
70BC8D37FAC641C7F20125E8 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
97232923D357E56CAA39281D /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -42,6 +50,9 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
BC90D28B9068C663815415CC /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
D081C25B294826C0006EB10B /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
D0E623A729482D030001185E /* Libgopeed.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Libgopeed.xcframework; path = Frameworks/Libgopeed.xcframework; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -49,6 +60,9 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D0E623A929482D160001185E /* Libgopeed.xcframework in Frameworks */,
D081C25C294826C0006EB10B /* libc++.tbd in Frameworks */,
DCA5B0FA95A8007ADEDACA1B /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -72,6 +86,8 @@
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
ADF7F433B4BC23D6C18AB78B /* Pods */,
B4A1CBAC5AA50208793CFF34 /* Frameworks */,
);
sourceTree = "<group>";
};
@@ -98,6 +114,26 @@
path = Runner;
sourceTree = "<group>";
};
ADF7F433B4BC23D6C18AB78B /* Pods */ = {
isa = PBXGroup;
children = (
97232923D357E56CAA39281D /* Pods-Runner.debug.xcconfig */,
BC90D28B9068C663815415CC /* Pods-Runner.release.xcconfig */,
25B61E78A388C87913468FD6 /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
B4A1CBAC5AA50208793CFF34 /* Frameworks */ = {
isa = PBXGroup;
children = (
D0E623A729482D030001185E /* Libgopeed.xcframework */,
D081C25B294826C0006EB10B /* libc++.tbd */,
70BC8D37FAC641C7F20125E8 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -105,12 +141,14 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
F3093A8F123671F8F587626F /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
DDA801E9D83E2E88398514D3 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@@ -127,7 +165,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1300;
LastUpgradeCheck = 1430;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@@ -171,10 +209,12 @@
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
@@ -185,6 +225,7 @@
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@@ -197,6 +238,45 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
DDA801E9D83E2E88398514D3 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
F3093A8F123671F8F587626F /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -272,7 +352,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -288,6 +368,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = JH48DS925K;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
@@ -349,7 +430,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -398,7 +479,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -416,6 +497,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = JH48DS925K;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
@@ -438,6 +520,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = JH48DS925K;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1300"
LastUpgradeVersion = "1430"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -4,4 +4,7 @@
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
+32 -7
View File
@@ -1,13 +1,38 @@
import UIKit
import Flutter
import Libgopeed
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let batteryChannel = FlutterMethodChannel(name: "gopeed.com/libgopeed",
binaryMessenger: controller.binaryMessenger)
batteryChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
switch call.method {
case "start":
let args = call.arguments as? Dictionary<String, Any>
let cfg = args?["cfg"] as? String
let portPrt = UnsafeMutablePointer<Int>.allocate(capacity: MemoryLayout<Int>.stride)
var error: NSError?
if LibgopeedStart(cfg, portPrt, &error){
result(portPrt.pointee)
}else{
result(FlutterError(code: "ERROR", message: error.debugDescription, details: nil))
}
case "stop":
LibgopeedStop()
result(nil)
default:
result(FlutterMethodNotImplemented)
}
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 564 B

After

Width:  |  Height:  |  Size: 714 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

+8 -3
View File
@@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
@@ -12,8 +14,6 @@
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>gopeed</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
@@ -24,6 +24,11 @@
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
@@ -43,7 +48,7 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>
@@ -225,7 +225,7 @@ class AppController extends GetxController with WindowListener, TrayListener {
return _defaultStartConfig!;
}
_defaultStartConfig = StartConfig();
if (!Util.isUnix()) {
if (!Util.supportUnixSocket()) {
// not support unix socket, use tcp
_defaultStartConfig!.network = "tcp";
_defaultStartConfig!.address = "127.0.0.1:0";
@@ -13,6 +13,7 @@ class CreateController extends GetxController
final isResolving = false.obs;
final showAdvanced = false.obs;
late TabController advancedTabController;
final oldUrl = "".obs;
final fileDataUri = "".obs;
@override
@@ -30,6 +30,8 @@ class CreateView extends GetView<CreateController> {
final _httpRefererController = TextEditingController();
final _btTrackerController = TextEditingController();
final _availableSchemes = ["http:", "https:", "magnet:"];
CreateView({Key? key}) : super(key: key);
@override
@@ -37,8 +39,27 @@ class CreateView extends GetView<CreateController> {
final String? filePath = Get.rootDelegate.arguments();
if (_urlController.text.isEmpty && filePath != null) {
_urlController.text = filePath;
WidgetsBinding.instance.addPostFrameCallback((_) async {
await _doResolve();
_urlController.selection = TextSelection.fromPosition(
TextPosition(offset: _urlController.text.length));
}
// if no file path, read from clipboard
if (filePath?.isEmpty ?? true) {
Clipboard.getData('text/plain').then((value) {
if (value?.text?.isNotEmpty ?? false) {
if (_availableSchemes
.where((e) =>
value!.text!.startsWith(e) ||
value.text!.startsWith(e.toUpperCase()))
.isNotEmpty) {
_urlController.text = value!.text!;
_urlController.selection = TextSelection.fromPosition(
TextPosition(offset: _urlController.text.length));
return;
}
recognizeMagnetUri(value!.text!);
}
});
}
@@ -60,158 +81,183 @@ class CreateView extends GetView<CreateController> {
final bytes = await details.files[0].readAsBytes();
controller.setFileDataUri(bytes);
},
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0),
child: Form(
key: _resolveFormKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(children: [
Row(children: [
Expanded(
child: TextFormField(
autofocus: true,
controller: _urlController,
minLines: 1,
maxLines: 5,
decoration: InputDecoration(
hintText: _hitText(),
hintStyle: const TextStyle(fontSize: 12),
labelText: 'downloadLink'.tr,
icon: const Icon(Icons.link),
suffixIcon: IconButton(
onPressed: () {
_urlController.clear();
controller.clearFileDataUri();
},
icon: const Icon(Icons.clear),
),
),
validator: (v) {
return v!.trim().isNotEmpty
? null
: 'downloadLinkValid'.tr;
},
onChanged: (v) async {
controller.clearFileDataUri();
},
),
),
IconButton(
icon: const Icon(Icons.folder_open),
onPressed: () async {
var pr = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ["torrent"]);
if (pr != null) {
if (!Util.isWeb()) {
_urlController.text = pr.files[0].path ?? "";
return;
}
_urlController.text = pr.files[0].name;
controller.setFileDataUri(pr.files[0].bytes!);
}
}),
]
//.where((e) => e != null).map((e) => e!).toList(),
),
Obx(() => Visibility(
visible: controller.showAdvanced.value,
child: Padding(
padding: const EdgeInsets.only(left: 40, top: 15),
child: Column(
children: [
TabBar(
controller: controller.advancedTabController,
tabs: const [
Tab(
text: 'HTTP',
),
Tab(
text: 'BitTorrent',
)
],
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0),
child: Form(
key: _resolveFormKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(children: [
Row(children: [
Expanded(
child: TextFormField(
autofocus: true,
controller: _urlController,
minLines: 1,
maxLines: 5,
decoration: InputDecoration(
hintText: _hitText(),
hintStyle: const TextStyle(fontSize: 12),
labelText: 'downloadLink'.tr,
icon: const Icon(Icons.link),
suffixIcon: IconButton(
onPressed: () {
_urlController.clear();
controller.clearFileDataUri();
},
icon: const Icon(Icons.clear),
),
AutoScaleTabBarView(
controller: controller.advancedTabController,
children: [
Column(
children: [
TextFormField(
controller: _httpUaController,
decoration: const InputDecoration(
labelText: 'User-Agent',
)),
TextFormField(
controller: _httpCookieController,
decoration: const InputDecoration(
labelText: 'Cookie',
)),
TextFormField(
controller: _httpRefererController,
decoration: const InputDecoration(
labelText: 'Referer',
)),
],
),
Column(
children: [
TextFormField(
controller: _btTrackerController,
maxLines: 5,
decoration: InputDecoration(
labelText: 'Trakers',
hintText: 'addTrackerHit'.tr,
)),
],
)
],
)
],
),
))),
Center(
child: Padding(
padding: const EdgeInsets.only(top: 15),
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(right: 10),
child: TextButton(
onPressed: () {
controller.showAdvanced.value =
!controller.showAdvanced.value;
},
child:
Row(mainAxisSize: MainAxisSize.min, children: [
Obx(() => Checkbox(
value: controller.showAdvanced.value,
onChanged: (bool? value) {
controller.showAdvanced.value =
value ?? false;
},
)),
Text('advancedOptions'.tr),
]),
),
validator: (v) {
return v!.trim().isNotEmpty
? null
: 'downloadLinkValid'.tr;
},
onChanged: (v) async {
controller.clearFileDataUri();
if (controller.oldUrl.value.isEmpty) {
recognizeMagnetUri(v);
}
controller.oldUrl.value = v;
},
),
SizedBox(
width: 150,
child: RoundedLoadingButton(
color: Get.theme.colorScheme.secondary,
onPressed: _doResolve,
controller: _confirmController,
child: Text('confirm'.tr),
),
IconButton(
icon: const Icon(Icons.folder_open),
onPressed: () async {
var pr = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ["torrent"]);
if (pr != null) {
if (!Util.isWeb()) {
_urlController.text = pr.files[0].path ?? "";
return;
}
_urlController.text = pr.files[0].name;
controller.setFileDataUri(pr.files[0].bytes!);
}
}),
]
//.where((e) => e != null).map((e) => e!).toList(),
),
Obx(() => Visibility(
visible: controller.showAdvanced.value,
child: Padding(
padding: const EdgeInsets.only(left: 40, top: 15),
child: Column(
children: [
TabBar(
controller: controller.advancedTabController,
tabs: const [
Tab(
text: 'HTTP',
),
Tab(
text: 'BitTorrent',
)
],
),
AutoScaleTabBarView(
controller: controller.advancedTabController,
children: [
Column(
children: [
TextFormField(
controller: _httpUaController,
decoration: const InputDecoration(
labelText: 'User-Agent',
)),
TextFormField(
controller: _httpCookieController,
decoration: const InputDecoration(
labelText: 'Cookie',
)),
TextFormField(
controller: _httpRefererController,
decoration: const InputDecoration(
labelText: 'Referer',
)),
],
),
Column(
children: [
TextFormField(
controller: _btTrackerController,
maxLines: 5,
decoration: InputDecoration(
labelText: 'Trakers',
hintText: 'addTrackerHit'.tr,
)),
],
)
],
)
],
),
),
],
),
)),
]))),
))),
Center(
child: Padding(
padding: const EdgeInsets.only(top: 15),
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(right: 10),
child: TextButton(
onPressed: () {
controller.showAdvanced.value =
!controller.showAdvanced.value;
},
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Obx(() => Checkbox(
value: controller.showAdvanced.value,
onChanged: (bool? value) {
controller.showAdvanced.value =
value ?? false;
},
)),
Text('advancedOptions'.tr),
]),
),
),
SizedBox(
width: 150,
child: RoundedLoadingButton(
color: Get.theme.colorScheme.secondary,
onPressed: _doResolve,
controller: _confirmController,
child: Text('confirm'.tr),
),
),
],
),
)),
]))),
),
),
);
}
// recognize magnet uri, if length == 40, auto add magnet prefix
recognizeMagnetUri(String text) {
if (text.length != 40) {
return;
}
final exp = RegExp(r"[0-9a-fA-F]+");
if (exp.hasMatch(text)) {
final uri = "magnet:?xt=urn:btih:$text";
_urlController.text = uri;
_urlController.selection = TextSelection.fromPosition(
TextPosition(offset: _urlController.text.length));
}
}
Future<void> _doResolve() async {
if (controller.isResolving.value) {
return;
@@ -280,7 +326,7 @@ class CreateView extends GetView<CreateController> {
var width = MediaQuery.of(context).size.width;
return SizedBox(
height: height * 0.5,
height: height * 0.75,
width: width,
child: Form(
key: createFormKey,
@@ -334,21 +334,21 @@ class SettingView extends GetView<SettingController> {
width: 150,
child: DropdownButtonFormField<String>(
value: startCfg.value.network,
onChanged: (value) async {
startCfg.update((val) {
val!.network = value!;
});
onChanged: Util.isDesktop()
? (value) async {
startCfg.update((val) {
val!.network = value!;
});
await debounceSave(needRestart: true);
},
await debounceSave(needRestart: true);
}
: null,
items: [
!Util.isMobile()
? const DropdownMenuItem<String>(
value: 'tcp',
child: Text('TCP'),
)
: null,
Util.isUnix()
const DropdownMenuItem<String>(
value: 'tcp',
child: Text('TCP'),
),
Util.supportUnixSocket()
? const DropdownMenuItem<String>(
value: 'unix',
child: Text('Unix'),
@@ -0,0 +1,12 @@
import 'package:get/get.dart';
import '../controllers/task_files_controller.dart';
class TaskFilesBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut<TaskFilesController>(
() => TaskFilesController(),
);
}
}
@@ -0,0 +1,86 @@
import 'package:get/get.dart';
import '../../../../api/api.dart';
import '../../../../api/model/resource.dart';
import '../../../../api/model/task.dart';
class FileItem {
final bool isDirectory;
final String path;
final String name;
final int size;
FileItem(this.isDirectory, this.path, this.name, this.size);
String get fullPath => "${path == "/" ? path : "$path/"}$name";
}
class TaskFilesController extends GetxController {
final Map<String, List<FileItem>> _dirMap = {};
final task = Rx<Task?>(null);
final fileList = <FileItem>[].obs;
@override
void onInit() async {
super.onInit();
final taskId = Get.rootDelegate.parameters['id'];
final tasks = await getTasks([]);
task.value = tasks.firstWhere((element) => element.id == taskId);
parseDirMap(task.value!.meta.res.files);
toDir("/");
}
void parseDirMap(List<FileInfo> fileList) {
for (final file in fileList) {
String dir = file.path;
if (!dir.startsWith("/")) {
dir = "/$dir";
}
if (!_dirMap.containsKey(dir)) {
_dirMap[dir] = [];
}
_dirMap[dir]!.add(FileItem(false, dir, file.name, file.size));
void findParent(String dir) {
final parentDirIndex = dir.lastIndexOf("/");
String parentDir =
parentDirIndex == 0 ? "/" : dir.substring(0, parentDirIndex);
if (!_dirMap.containsKey(parentDir)) {
_dirMap[parentDir] = [];
}
String dirName = dir.substring(dir.lastIndexOf("/") + 1);
if (!_dirMap[parentDir]!.any((element) => element.name == dirName)) {
_dirMap[parentDir]!.add(FileItem(true, parentDir, dirName, 0));
}
}
while (dir != "/" && dir != "") {
findParent(dir);
dir = dir.substring(0, dir.lastIndexOf("/"));
}
}
// sort children, directories first then files, alphabetically
_dirMap.forEach((key, value) {
value.sort((a, b) {
if (a.isDirectory && !b.isDirectory) {
return -1;
} else if (!a.isDirectory && b.isDirectory) {
return 1;
} else {
return a.name.compareTo(b.name);
}
});
});
}
void toDir(String dir) {
fileList.value = _dirMap[dir]?.toList() ?? [];
}
int dirItemCount(String dir) {
return _dirMap[dir]?.length ?? 0;
}
}
@@ -0,0 +1,112 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:open_file/open_file.dart';
import 'package:share_plus/share_plus.dart';
import '../../../../util/file_icon.dart';
import '../../../../util/icons.dart';
import '../../../../util/util.dart';
import '../../../views/breadcrumb_view.dart';
import '../controllers/task_files_controller.dart';
class TaskFilesView extends GetView<TaskFilesController> {
const TaskFilesView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => Get.rootDelegate.popRoute()),
// actions: [],
title: Obx(() => Text(controller.task.value?.meta.res.name ?? "")),
),
body: Obx(() {
final fileList = controller.fileList;
final breadcrumbItems = ["/"];
if (fileList.isNotEmpty) {
final file = fileList.first;
final path = file.path.substring(1);
if (path.isNotEmpty) {
final pathArr = path.split("/");
for (int i = 0; i < pathArr.length; i++) {
breadcrumbItems.add(pathArr[i]);
}
}
}
return Column(
children: [
Breadcrumb(
items: breadcrumbItems,
onItemTap: (index) {
final targetDirArr = <String>[];
for (int i = 0; i <= index; i++) {
targetDirArr.add(breadcrumbItems[i]);
}
controller
.toDir(targetDirArr.join("/").replaceFirst('//', '/'));
}).paddingOnly(left: 16, top: 16, bottom: 8),
Expanded(
child: ListView.builder(
itemBuilder: (context, index) {
final meta = controller.task.value!.meta;
final file = fileList[index];
return ListTile(
leading: file.isDirectory
? const Icon(Icons.folder)
: Icon(FaIcons.allIcons[findIcon(file.name)]),
title: Text(fileList[index].name),
subtitle: file.isDirectory
? Text('items'.trParams({
'count': controller
.dirItemCount(file.fullPath)
.toString()
}))
: Text(Util.fmtByte(file.size)),
trailing: file.isDirectory
? null
: SizedBox(
width: 100,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
IconButton(
icon: const Icon(Icons.play_circle),
onPressed: () {
OpenFile.open(
Util.safePathJoin([
meta.opts.path,
meta.res.rootDir,
file.fullPath
]),
);
}),
IconButton(
icon: const Icon(Icons.share),
onPressed: () {
final xfile = XFile(Util.safePathJoin([
meta.opts.path,
meta.res.rootDir,
file.fullPath
]));
Share.shareXFiles([xfile]);
})
],
),
),
onTap: () {
if (file.isDirectory) {
controller.toDir(file.fullPath);
}
},
);
},
itemCount: controller.fileList.length,
),
)
],
);
}));
}
}
+10 -1
View File
@@ -1,4 +1,5 @@
import 'package:get/get.dart';
import 'package:gopeed/app/modules/task/views/task_files_view.dart';
import 'package:gopeed/app/modules/task/views/task_view.dart';
import '../modules/create/bindings/create_binding.dart';
@@ -10,6 +11,7 @@ import '../modules/root/views/root_view.dart';
import '../modules/setting/bindings/setting_binding.dart';
import '../modules/setting/views/setting_view.dart';
import '../modules/task/bindings/task_binding.dart';
import '../modules/task/bindings/task_files_binding.dart';
part 'app_routes.dart';
@@ -37,7 +39,14 @@ class AppPages {
name: _Paths.TASK,
page: () => const TaskView(),
transition: Transition.noTransition,
binding: TaskBinding()),
binding: TaskBinding(),
children: [
GetPage(
name: _Paths.TASK_FILES,
page: () => const TaskFilesView(),
transition: Transition.noTransition,
binding: TaskFilesBinding()),
]),
GetPage(
name: _Paths.SETTING,
page: () => const SettingView(),
@@ -7,6 +7,7 @@ abstract class Routes {
static const HOME = _Paths.HOME;
static const CREATE = _Paths.CREATE;
static const TASK = _Paths.HOME + _Paths.TASK;
static const TASK_FILES = TASK + _Paths.TASK_FILES;
static const SETTING = _Paths.HOME + _Paths.SETTING;
}
@@ -16,5 +17,6 @@ abstract class _Paths {
static const HOME = '/home';
static const CREATE = '/create';
static const TASK = '/task';
static const TASK_FILES = '/files';
static const SETTING = '/setting';
}
@@ -0,0 +1,59 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class Breadcrumb extends StatelessWidget {
final List<String> items;
final Function(int)? onItemTap;
final TextStyle textStyle;
final TextStyle activeTextStyle;
const Breadcrumb({
super.key,
required this.items,
this.onItemTap,
this.textStyle = const TextStyle(fontSize: 16),
this.activeTextStyle =
const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
});
@override
Widget build(BuildContext context) {
List<Widget> children = [];
for (int i = 0; i < items.length; i++) {
children.add(
GestureDetector(
onTap: () {
if (onItemTap != null) {
onItemTap!(i);
}
},
child: Text(
items[i],
style: i == items.length - 1 ? activeTextStyle : textStyle,
),
),
);
if (i != items.length - 1) {
children.add(const Text(" > "));
}
}
return Row(
children: [
...(children.length == 1
? children.sublist(0, 1)
: children.sublist(0, 2)),
children.length > 2
? Expanded(
child: SingleChildScrollView(
reverse: true,
scrollDirection: Axis.horizontal,
child: Row(
children: children.sublist(2),
),
),
)
: null,
].where((e) => e != null).map((e) => e!).toList(),
).paddingOnly(right: 12);
}
}
@@ -1,7 +1,6 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:gopeed/api/model/meta.dart';
import 'package:gopeed/api/model/resource.dart';
import 'package:path/path.dart' as path;
import '../../api/api.dart';
@@ -109,11 +108,16 @@ class BuildTaskListView extends GetView {
List<Widget> buildActions() {
final list = <Widget>[];
if (isDone()) {
if (Util.isDesktop()) {
if (Util.isDesktop() || Util.isMobile()) {
list.add(IconButton(
icon: const Icon(Icons.folder_open),
onPressed: () async {
await FileExplorer.openAndSelectFile(buildExplorerUrl(task));
onPressed: () {
if (Util.isDesktop()) {
FileExplorer.openAndSelectFile(buildExplorerUrl(task));
} else {
Get.rootDelegate
.toNamed(Routes.TASK_FILES, parameters: {'id': task.id});
}
},
));
}
@@ -35,7 +35,7 @@ class _DirectorySelectorState extends State<DirectorySelector> {
return v!.trim().isNotEmpty ? null : 'downloadDirValid'.tr;
},
)),
Util.isDesktop() || Util.isAndroid()
!Util.isWeb() && !Util.isIOS()
? IconButton(
icon: const Icon(Icons.folder_open),
onPressed: () async {
+65 -1
View File
@@ -9,6 +9,7 @@ class AppTranslation {
'ja_JP': Locales.ja_JP,
'ru_RU': Locales.ru_RU,
'zh_CN': Locales.zh_CN,
'zh_TW': Locales.zh_TW,
};
}
@@ -357,7 +358,7 @@ class Locales {
'downloadDirValid': '请选择下载目录',
'connections': '连接数',
'maxRunning': '最大下载数',
'items': '@count 条',
'items': '@count 项',
'subscribeTracker': '订阅 Tracker',
'subscribeFail': '订阅失败,请检查网络或稍后重试',
'update': '更新',
@@ -389,4 +390,67 @@ class Locales {
'newVersionUpdate': '立即下载',
'newVersionLater': '稍后再说',
};
static const zh_TW = {
'label': '中文 (正體) ',
'error': '錯誤',
'tip': '提示',
'confirm': '確定',
'cancel': '取消',
'selectAll': '全選',
'task': '任務',
'downloading': '下載中',
'downloaded': '已完成',
'setting': '設定',
'donate': '斗內',
'exit': '離開',
'create': '新增任務',
'advancedOptions': '進階選項',
'downloadLink': '下載鏈接',
'downloadLinkValid': '請輸入下載鏈接',
'downloadLinkHit': '請輸入下載鏈接,支援 HTTP/HTTPS/MAGNET@append',
'downloadLinkHitDesktop': ',也可以通過拖拽Torrent文件至此以新增任務',
'download': '下載',
'noFileSelected': '沒有選取的文件',
'noStoragePermission': '沒有存儲權限',
'selectFile': '選擇文件',
'rename': '重命名',
'basic': '基礎',
'advanced': '進階',
'general': '通用設定',
'downloadDir': '下載目録',
'downloadDirValid': '請選擇下載目録',
'connections': '同時連接數量',
'maxRunning': '最大同時下載數',
'items': '@count 項',
'subscribeTracker': '已訂閲的 Tracker',
'subscribeFail': '訂閲失敗',
'update': '更新',
'updateDaily': '每日自動更新',
'lastUpdate': '上次更新時間: @time',
'addTracker': '增加新的 Tracker',
'addTrackerHit': '請輸入 Tracker 服務器地址,每行一條',
'ui': '介面',
'theme': '佈景主題',
'themeSystem': '跟隨系統',
'themeLight': '亮色主題',
'themeDark': '暗色主題',
'locale': '語言',
'about': '關於',
'homepage': '訪問主頁',
'version': '版本資訊',
'protocol': '通訊協定',
'port': '端口',
'apiToken': '接口 Token',
'notSet': '尚未設定',
'set': '已設定',
'effectAfterRestart': '該選項將在重新啓動軟體後生效',
'startAll': '全部開始',
'pauseAll': '全部暫停',
'deleteTask': '刪除任務',
'deleteTaskTip': '保留已經下載的文件',
'delete': '刪除',
'newVersionTitle': '發現新版本 @version',
'newVersionUpdate': '立刻更新',
'newVersionLater': '稍後更新',
};
}
+13 -6
View File
@@ -12,6 +12,13 @@ class Util {
return path;
}
static String safePathJoin(List<String> paths) {
return paths
.map((e) => safeDir(e))
.join("/")
.replaceAll(RegExp(r'//'), "/");
}
static String fmtByte(int byte) {
if (byte < 0) {
return "0 B";
@@ -53,15 +60,15 @@ class Util {
return !kIsWeb && Platform.isMacOS;
}
static isUnix() {
static isWeb() {
return kIsWeb;
}
static supportUnixSocket() {
if (kIsWeb) {
return false;
}
return !Platform.isWindows;
}
static isWeb() {
return kIsWeb;
return Platform.isLinux || Platform.isMacOS || Platform.isAndroid;
}
static List<String> textToLines(String text) {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 672 B

After

Width:  |  Height:  |  Size: 709 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

+34 -2
View File
@@ -245,10 +245,10 @@ packages:
dependency: "direct main"
description:
name: desktop_drop
sha256: "4ca4d960f4b11c032e9adfd2a0a8ac615bc3fddb4cbe73dcf840dd8077582186"
sha256: ebba9c9cb0b54385998a977d741cc06fd8324878c08d5a36e9da61cd56b04cc6
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.4.1"
version: "0.4.3"
dio:
dependency: "direct main"
description:
@@ -565,6 +565,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.4"
open_file:
dependency: "direct main"
description:
name: open_file
sha256: a5a32d44acb7c899987d0999e1e3cbb0a0f1adebbf41ac813ec6d2d8faa0af20
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.3.2"
package_config:
dependency: transitive
description:
@@ -757,6 +765,22 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.4.0"
share_plus:
dependency: "direct main"
description:
name: share_plus
sha256: "6cec740fa0943a826951223e76218df002804adb588235a8910dc3d6b0654e11"
url: "https://pub.flutter-io.cn"
source: hosted
version: "7.1.0"
share_plus_platform_interface:
dependency: transitive
description:
name: share_plus_platform_interface
sha256: "357412af4178d8e11d14f41723f80f12caea54cf0d5cd29af9dcdab85d58aea7"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.3.0"
shared_preferences:
dependency: "direct main"
description:
@@ -1018,6 +1042,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.7"
uuid:
dependency: transitive
description:
name: uuid
sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.7"
vector_math:
dependency: transitive
description:
+7 -3
View File
@@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.3.9+1
version: 1.3.13+1
environment:
sdk: '>=3.0.0 <4.0.0'
@@ -48,7 +48,7 @@ dependencies:
url_launcher: ^6.1.6
shared_preferences: ^2.2.0
logger: ^1.3.0
desktop_drop: ^0.4.1
desktop_drop: ^0.4.3
package_info_plus: ^4.0.0
fluent_ui: ^4.4.0
path: any
@@ -58,6 +58,8 @@ dependencies:
window_manager: ^0.3.4
tray_manager: ^0.2.0
autoscale_tabbarview: ^1.0.2
share_plus: ^7.1.0
open_file: ^3.3.2
dev_dependencies:
flutter_test:
sdk: flutter
@@ -114,8 +116,10 @@ flutter:
# flutter pub run flutter_launcher_icons:main
flutter_icons:
image_path_android: "assets/icon/icon_1024.png"
image_path: "assets/icon/icon_1024.png"
android: true # can specify file name here e.g. "ic_launcher"
ios: true
remove_alpha_ios: true
web:
generate: true
image_path: "assets/icon/icon_1024.png"