mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-10 02:20:28 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19aad9bc9c | ||
|
|
2d0cc1c877 | ||
|
|
dc94a1004c | ||
|
|
1385f62fb0 | ||
|
|
34fc886662 | ||
|
|
c651263747 | ||
|
|
96a4526bc8 | ||
|
|
97cf8ff0c5 | ||
|
|
70c16195ef | ||
|
|
eb9d966855 | ||
|
|
0e3ca912a7 | ||
|
|
b3e372326f | ||
|
|
0100f0131d | ||
|
|
e4c3b449a4 |
No files matched your search
@@ -210,7 +210,7 @@ jobs:
|
||||
flutter-version: ${{ env.FLUTTER_VERSION }}
|
||||
- run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y ninja-build libgtk-3-dev
|
||||
sudo apt-get install -y ninja-build libgtk-3-dev libayatana-appindicator3-dev
|
||||
- name: Build
|
||||
env:
|
||||
VERSION: ${{ needs.get-release.outputs.tag_name }}
|
||||
@@ -310,7 +310,7 @@ jobs:
|
||||
VERSION: ${{ needs.get-release.outputs.tag_name }}
|
||||
run: |
|
||||
cd ui/flutter
|
||||
flutter build web
|
||||
flutter build web --web-renderer html
|
||||
cd ../../
|
||||
cp -r ui/flutter/build/web cmd/web/dist
|
||||
mkdir -p dist/zip
|
||||
|
||||
@@ -72,7 +72,7 @@ jobs:
|
||||
flutter-version: ${{ env.FLUTTER_VERSION }}
|
||||
- run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y ninja-build libgtk-3-dev
|
||||
sudo apt-get install -y ninja-build libgtk-3-dev libayatana-appindicator3-dev
|
||||
- name: Build
|
||||
run: |
|
||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/linux/bundle/lib/libgopeed.so github.com/GopeedLab/gopeed/bind/desktop
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ WORKDIR /app
|
||||
COPY ./ui/flutter/pubspec.yaml ./ui/flutter/pubspec.lock ./
|
||||
RUN flutter pub get
|
||||
COPY ./ui/flutter ./
|
||||
RUN flutter build web
|
||||
RUN flutter build web --web-renderer html
|
||||
|
||||
FROM golang:1.19.3 AS go
|
||||
WORKDIR /app
|
||||
|
||||
@@ -80,7 +80,7 @@ This project is divided into two parts, the front end uses `flutter`, the back e
|
||||
### Clone
|
||||
|
||||
```bash
|
||||
git clone [email protected]:monkeyWie/gopeed.git
|
||||
git clone [email protected]:GopeedLab/gopeed.git
|
||||
```
|
||||
|
||||
### Contributing
|
||||
@@ -153,6 +153,18 @@ go build -tags nosqlite,web -ldflags="-s -w" -o bin/ github.com/GopeedLab/gopeed
|
||||
go run cmd/web/main.go
|
||||
```
|
||||
|
||||
## Thanks
|
||||
|
||||
### Contributors
|
||||
|
||||
<a href="https://github.com/GopeedLab/gopeed/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=GopeedLab/gopeed" />
|
||||
</a>
|
||||
|
||||
### JetBrains
|
||||
|
||||
[](https://www.jetbrains.com/?from=gopeed)
|
||||
|
||||
## License
|
||||
|
||||
[GPLv3](LICENSE)
|
||||
+13
-1
@@ -79,7 +79,7 @@ docker-compose up -d
|
||||
### 克隆项目
|
||||
|
||||
```bash
|
||||
git clone [email protected]:monkeyWie/gopeed.git
|
||||
git clone [email protected]:GopeedLab/gopeed.git
|
||||
```
|
||||
|
||||
### 贡献代码
|
||||
@@ -152,6 +152,18 @@ go build -tags nosqlite,web -ldflags="-s -w" -o bin/ github.com/GopeedLab/gopeed
|
||||
go run cmd/web/main.go
|
||||
```
|
||||
|
||||
## 感谢
|
||||
|
||||
### 贡献者
|
||||
|
||||
<a href="https://github.com/GopeedLab/gopeed/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=GopeedLab/gopeed" />
|
||||
</a>
|
||||
|
||||
### JetBrains
|
||||
|
||||
[](https://www.jetbrains.com/?from=gopeed)
|
||||
|
||||
## 开源许可
|
||||
|
||||
基于 [GPLv3](LICENSE) 协议开源。
|
||||
@@ -0,0 +1 @@
|
||||
<svg height="105" viewBox="0 0 105 105" width="105" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="99.03" x2="61.54" y1="59.18" y2="90.91"><stop offset="0" stop-color="#087cfa"/><stop offset=".02" stop-color="#0d7bfa"/><stop offset=".37" stop-color="#5566f9"/><stop offset=".66" stop-color="#8a57f8"/><stop offset=".88" stop-color="#ab4ef7"/><stop offset="1" stop-color="#b74af7"/></linearGradient><linearGradient id="b" x1="37.54" x2="60.33" xlink:href="#a" y1="34.26" y2="8.33"/><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="17.84" x2="87.09" y1="88.36" y2="43.86"><stop offset="0" stop-color="#087cfa"/><stop offset=".1" stop-color="#1598d3"/><stop offset=".22" stop-color="#23b6aa"/><stop offset=".35" stop-color="#2dcc8b"/><stop offset=".46" stop-color="#35dd74"/><stop offset=".57" stop-color="#39e767"/><stop offset=".67" stop-color="#3bea62"/></linearGradient><path d="m89.06 41.63 11.44 25.37-19.58 33.5-12.06-29.28z" fill="url(#a)"/><path d="m68.86 71.22 12.06 29.28-30.34-10.43z" fill="#b74af7"/><path d="m72.13 31.61-6.22-27.11h-34.49l-26.92 41.18 7.79 18.92-7.79 17.27 55.75-47.43z" fill="url(#b)"/><path d="m100.5 24.88-40.25 9.56-55.75 47.43 35.96 18.63 28.4-29.28z" fill="url(#c)"/><path d="m22.5 22.5h60v60h-60z"/><g fill="#fff"><path d="m28.13 71.25h22.5v3.75h-22.5z"/><path d="m26.44 42.81v-.07a12.7 12.7 0 0 1 12.97-12.74 13.62 13.62 0 0 1 9.73 3.39l-3.43 4.14a9.13 9.13 0 0 0 -6.47-2.53c-4 0-7.11 3.5-7.11 7.7v.07c0 4.53 3.11 7.85 7.5 7.85a8.67 8.67 0 0 0 5.12-1.49v-3.56h-5.48v-4.7h10.73v10.74a16.07 16.07 0 0 1 -10.57 3.93c-7.69 0-12.99-5.41-12.99-12.73z"/><path d="m52.3 42.81v-.07a12.79 12.79 0 0 1 13.19-12.74c7.63 0 13.11 5.69 13.11 12.72v.07a12.79 12.79 0 0 1 -13.18 12.8c-7.64-.05-13.12-5.74-13.12-12.78zm20.61 0v-.07a7.51 7.51 0 0 0 -7.49-7.74 7.4 7.4 0 0 0 -7.42 7.67v.07a7.52 7.52 0 0 0 7.5 7.78 7.4 7.4 0 0 0 7.41-7.71z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
+1
-8
@@ -13,14 +13,7 @@ import (
|
||||
const progressWidth = 20
|
||||
|
||||
func main() {
|
||||
//args := parse()
|
||||
var dir = "./"
|
||||
var connections = 8
|
||||
args := &args{
|
||||
url: "https://sel-kor-ping.vultr.com/vultr.com.100MB.bin",
|
||||
dir: &dir,
|
||||
connections: &connections,
|
||||
}
|
||||
args := parse()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
|
||||
@@ -66,8 +66,8 @@ require (
|
||||
github.com/tidwall/btree v1.3.1 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838 // indirect
|
||||
golang.org/x/exp v0.0.0-20220428152302-39d4317da171 // indirect
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
)
|
||||
@@ -7,7 +7,6 @@ crawshaw.io/sqlite v0.3.3-0.20210127221821-98b1f83c5508 h1:fILCBBFnjnrQ0whVJlGhf
|
||||
crawshaw.io/sqlite v0.3.3-0.20210127221821-98b1f83c5508/go.mod h1:igAO5JulrQ1DbdZdtVq48mnZUBAPOeFzer7VhDWNtW4=
|
||||
filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/RoaringBitmap/roaring v0.4.7/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w=
|
||||
github.com/RoaringBitmap/roaring v0.4.17/go.mod h1:D3qVegWTmfCaX4Bl5CrBE9hfrSrrXIr8KVNvRsDi1NI=
|
||||
github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
|
||||
@@ -316,7 +315,6 @@ github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDW
|
||||
github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
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.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
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.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
@@ -324,30 +322,19 @@ go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838 h1:71vQrMauZZhcTVK6KdYM+rklehEEwb3E+ZhaE5jrPrE=
|
||||
golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
||||
golang.org/x/exp v0.0.0-20220428152302-39d4317da171 h1:TfdoLivD44QwvssI9Sv1xwa5DcL5XQr4au4sZ2F2NV4=
|
||||
golang.org/x/exp v0.0.0-20220428152302-39d4317da171/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20220928052126-fa6bcb076835 h1:v6yt1xSu+4xV0fPEmB8s2BHdOaoU0SSZrVQzj6pRvqk=
|
||||
golang.org/x/mobile v0.0.0-20220928052126-fa6bcb076835/go.mod h1:M32cGdzp91A8Ex9qQtyZinr19EYxzkFqDjW2oyHzTDQ=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57 h1:LQmS1nU0twXLA96Kt7U9qtHJEbBk3z6Q0V4UXjZkpr4=
|
||||
golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||
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=
|
||||
@@ -365,12 +352,12 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
||||
golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -380,7 +367,6 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
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-20210220032951-036812b2e83c/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/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -405,9 +391,9 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -422,13 +408,9 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||
golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023 h1:0c3L82FDQ5rt1bjTBlchS8t6RQ6299/+5bWMnRLh+uI=
|
||||
golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
@@ -128,7 +128,7 @@ func (f *Fetcher) Resolve(req *base.Request) error {
|
||||
contentDisposition := httpResp.Header.Get(base.HttpHeaderContentDisposition)
|
||||
if contentDisposition != "" {
|
||||
_, params, _ := mime.ParseMediaType(contentDisposition)
|
||||
filename := params["filePath"]
|
||||
filename := params["filename"]
|
||||
if filename != "" {
|
||||
file.Name = filename
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
func TestFetcher_Resolve(t *testing.T) {
|
||||
testResolve(test.StartTestFileServer, &base.Resource{
|
||||
testResolve(test.StartTestFileServer, test.BuildName, &base.Resource{
|
||||
Name: test.BuildName,
|
||||
Size: test.BuildSize,
|
||||
Range: true,
|
||||
@@ -26,7 +26,18 @@ func TestFetcher_Resolve(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}, t)
|
||||
testResolve(test.StartTestChunkedServer, &base.Resource{
|
||||
testResolve(test.StartTestCustomServer, "disposition", &base.Resource{
|
||||
Name: test.BuildName,
|
||||
Size: test.BuildSize,
|
||||
Range: false,
|
||||
Files: []*base.FileInfo{
|
||||
{
|
||||
Name: test.BuildName,
|
||||
Size: test.BuildSize,
|
||||
},
|
||||
},
|
||||
}, t)
|
||||
testResolve(test.StartTestCustomServer, test.BuildName, &base.Resource{
|
||||
Name: test.BuildName,
|
||||
Size: 0,
|
||||
Range: false,
|
||||
@@ -39,12 +50,12 @@ func TestFetcher_Resolve(t *testing.T) {
|
||||
}, t)
|
||||
}
|
||||
|
||||
func testResolve(startTestServer func() net.Listener, want *base.Resource, t *testing.T) {
|
||||
func testResolve(startTestServer func() net.Listener, path string, want *base.Resource, t *testing.T) {
|
||||
listener := startTestServer()
|
||||
defer listener.Close()
|
||||
fetcher := buildFetcher()
|
||||
err := fetcher.Resolve(&base.Request{
|
||||
URL: "http://" + listener.Addr().String() + "/" + test.BuildName,
|
||||
URL: "http://" + listener.Addr().String() + "/" + path,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -75,7 +86,7 @@ func TestFetcher_DownloadContinue(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFetcher_DownloadChunked(t *testing.T) {
|
||||
listener := test.StartTestChunkedServer()
|
||||
listener := test.StartTestCustomServer()
|
||||
defer listener.Close()
|
||||
// chunked编码下载
|
||||
downloadNormal(listener, 1, t)
|
||||
|
||||
@@ -46,7 +46,7 @@ func StartTestSlowFileServer(delay time.Duration) net.Listener {
|
||||
})
|
||||
}
|
||||
|
||||
func StartTestChunkedServer() net.Listener {
|
||||
func StartTestCustomServer() net.Listener {
|
||||
return startTestServer(func() http.Handler {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/"+BuildName, func(writer http.ResponseWriter, request *http.Request) {
|
||||
@@ -57,6 +57,17 @@ func StartTestChunkedServer() net.Listener {
|
||||
defer file.Close()
|
||||
io.Copy(writer, file)
|
||||
})
|
||||
mux.HandleFunc("/disposition", func(writer http.ResponseWriter, request *http.Request) {
|
||||
writer.Header().Set("Content-Disposition", "attachment; filename=\""+BuildName+"\"")
|
||||
writer.Header().Set("Content-Type", "application/octet-stream")
|
||||
writer.Header().Set("Content-Length", fmt.Sprintf("%d", BuildSize))
|
||||
file, err := os.Open(BuildFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer file.Close()
|
||||
io.Copy(writer, file)
|
||||
})
|
||||
return mux
|
||||
})
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/GopeedLab/gopeed/pkg/base"
|
||||
"github.com/GopeedLab/gopeed/pkg/util"
|
||||
gonanoid "github.com/matoous/go-nanoid/v2"
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
@@ -332,6 +333,41 @@ func (d *Downloader) Continue(id string) (err error) {
|
||||
return d.doContinue(task)
|
||||
}
|
||||
|
||||
func (d *Downloader) PauseAll() (err error) {
|
||||
d.lock.Lock()
|
||||
defer d.lock.Unlock()
|
||||
for _, task := range d.tasks {
|
||||
if task.Status == base.DownloadStatusRunning {
|
||||
if err = d.doPause(task, base.DownloadStatusPause); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Downloader) ContinueAll() (err error) {
|
||||
d.lock.Lock()
|
||||
defer d.lock.Unlock()
|
||||
runningCount := 0
|
||||
continueTasks := make([]*Task, 0)
|
||||
for _, task := range d.tasks {
|
||||
if task.Status == base.DownloadStatusRunning {
|
||||
runningCount++
|
||||
} else if task.Status != base.DownloadStatusDone {
|
||||
continueTasks = append(continueTasks, task)
|
||||
}
|
||||
}
|
||||
// calculate how many tasks can be continued, can't exceed maxRunning
|
||||
continueCount := int(math.Min(float64(d.cfg.MaxRunning-runningCount), float64(len(continueTasks))))
|
||||
for i := 0; i < continueCount; i++ {
|
||||
if err = d.doContinue(continueTasks[i]); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Downloader) Delete(id string, force bool) (err error) {
|
||||
d.lock.Lock()
|
||||
defer d.lock.Unlock()
|
||||
|
||||
@@ -74,6 +74,22 @@ func ContinueTask(w http.ResponseWriter, r *http.Request) {
|
||||
WriteJson(w, model.NewNilResult())
|
||||
}
|
||||
|
||||
func PauseAllTask(w http.ResponseWriter, r *http.Request) {
|
||||
if err := Downloader.PauseAll(); err != nil {
|
||||
WriteJson(w, model.NewErrorResult(err.Error()))
|
||||
return
|
||||
}
|
||||
WriteJson(w, model.NewNilResult())
|
||||
}
|
||||
|
||||
func ContinueAllTask(w http.ResponseWriter, r *http.Request) {
|
||||
if err := Downloader.ContinueAll(); err != nil {
|
||||
WriteJson(w, model.NewErrorResult(err.Error()))
|
||||
return
|
||||
}
|
||||
WriteJson(w, model.NewNilResult())
|
||||
}
|
||||
|
||||
func DeleteTask(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
taskId := vars["id"]
|
||||
|
||||
@@ -85,6 +85,8 @@ func BuildServer(startCfg *model.StartConfig) (*http.Server, net.Listener, error
|
||||
r.Methods(http.MethodPost).Path("/api/v1/tasks").HandlerFunc(CreateTask)
|
||||
r.Methods(http.MethodPut).Path("/api/v1/tasks/{id}/pause").HandlerFunc(PauseTask)
|
||||
r.Methods(http.MethodPut).Path("/api/v1/tasks/{id}/continue").HandlerFunc(ContinueTask)
|
||||
r.Methods(http.MethodPut).Path("/api/v1/tasks/pause").HandlerFunc(PauseAllTask)
|
||||
r.Methods(http.MethodPut).Path("/api/v1/tasks/continue").HandlerFunc(ContinueAllTask)
|
||||
r.Methods(http.MethodDelete).Path("/api/v1/tasks/{id}").HandlerFunc(DeleteTask)
|
||||
r.Methods(http.MethodGet).Path("/api/v1/tasks/{id}").HandlerFunc(GetTask)
|
||||
r.Methods(http.MethodGet).Path("/api/v1/tasks").HandlerFunc(GetTasks)
|
||||
|
||||
@@ -144,6 +144,39 @@ func TestPauseAndContinueTask(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestPauseAllAndContinueALLTasks(t *testing.T) {
|
||||
doTest(func() {
|
||||
cfg, err := Downloader.GetConfig()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
createAndPause := func() {
|
||||
taskId := httpRequestCheckOk[string](http.MethodPost, "/api/v1/tasks", createReq)
|
||||
httpRequestCheckOk[*download.Task](http.MethodGet, "/api/v1/tasks/"+taskId, nil)
|
||||
}
|
||||
|
||||
total := cfg.MaxRunning + 2
|
||||
for i := 0; i < total; i++ {
|
||||
createAndPause()
|
||||
}
|
||||
|
||||
// continue all
|
||||
httpRequestCheckOk[any](http.MethodPut, "/api/v1/tasks/continue", nil)
|
||||
tasks := httpRequestCheckOk[[]*download.Task](http.MethodGet, fmt.Sprintf("/api/v1/tasks?status=%s", base.DownloadStatusRunning), nil)
|
||||
if len(tasks) != cfg.MaxRunning {
|
||||
t.Errorf("ContinueAllTasks() got = %v, want %v", len(tasks), cfg.MaxRunning)
|
||||
}
|
||||
// pause all
|
||||
httpRequestCheckOk[any](http.MethodPut, "/api/v1/tasks/pause", nil)
|
||||
tasks = httpRequestCheckOk[[]*download.Task](http.MethodGet, fmt.Sprintf("/api/v1/tasks?status=%s,%s", base.DownloadStatusReady, base.DownloadStatusPause), nil)
|
||||
if len(tasks) != total {
|
||||
t.Errorf("PauseAllTasks() got = %v, want %v", len(tasks), total)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestDeleteTask(t *testing.T) {
|
||||
doTest(func() {
|
||||
taskId := httpRequestCheckOk[string](http.MethodPost, "/api/v1/tasks", createReq)
|
||||
@@ -275,6 +308,16 @@ func doTest(handler func()) {
|
||||
Stop()
|
||||
}()
|
||||
defer Downloader.Clear()
|
||||
defer func() {
|
||||
tasks := Downloader.GetTasks()
|
||||
taskIds := make([]string, len(tasks))
|
||||
for i, task := range tasks {
|
||||
taskIds[i] = task.ID
|
||||
}
|
||||
for _, id := range taskIds {
|
||||
Downloader.Delete(id, true)
|
||||
}
|
||||
}()
|
||||
taskReq.URL = "http://" + fileListener.Addr().String() + "/" + test.BuildName
|
||||
handler()
|
||||
}
|
||||
|
||||
@@ -12,9 +12,54 @@
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:exported="true"
|
||||
android:hardwareAccelerated="true"
|
||||
android:launchMode="singleTop"
|
||||
android:launchMode="singleInstance"
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data
|
||||
android:scheme="file"
|
||||
android:host="*"
|
||||
android:pathPattern=".*torrent" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data
|
||||
android:scheme="file"
|
||||
android:host="*"
|
||||
android:mimeType="application/x-bittorrent" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data
|
||||
android:scheme="content"
|
||||
android:host="*"
|
||||
android:pathPattern=".*torrent" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data
|
||||
android:scheme="content"
|
||||
android:host="*"
|
||||
android:mimeType="application/x-bittorrent" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data
|
||||
android:scheme="magnet" />
|
||||
</intent-filter>
|
||||
|
||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||
the Android process has started. This theme is visible to the user
|
||||
while the Flutter UI initializes. After that, this theme continues
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.6.10'
|
||||
ext.kotlin_version = '1.8.22'
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
"downloading": "downloading",
|
||||
"downloaded": "downloaded",
|
||||
"setting": "Setting",
|
||||
"donate": "Donate",
|
||||
"exit": "Exit",
|
||||
"create": "Create Task",
|
||||
"downloadLink": "Download Link",
|
||||
"downloadLinkValid": "Please enter the download link",
|
||||
@@ -48,6 +50,8 @@
|
||||
"notSet": "NS",
|
||||
"set": "SET",
|
||||
"effectAfterRestart": "Effect after restart",
|
||||
"startAll": "Start All",
|
||||
"pauseAll": "Pause All",
|
||||
"deleteTask": "Delete Task",
|
||||
"deleteTaskTip": "Keep downloaded files",
|
||||
"delete": "Delete",
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
"selectAll": "انتخاب همه",
|
||||
"task": "کار",
|
||||
"setting": "تنظیمات",
|
||||
"donate": "کمک مالی",
|
||||
"exit": "خروج",
|
||||
"create": "ایجاد کار",
|
||||
"downloading": "دانلود کردن",
|
||||
"downloaded": "دانلود شدن",
|
||||
@@ -45,6 +47,8 @@
|
||||
"notSet": "NS",
|
||||
"set": "SET",
|
||||
"effectAfterRestart": "Effect after restart",
|
||||
"startAll": "شروع همه",
|
||||
"pauseAll": "توقف همه",
|
||||
"deleteTask": "پاک کردن کار",
|
||||
"deleteTaskTip": "فایل های دانلود شده را نگه دارد",
|
||||
"delete": "پاک کردن",
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
"downloading": "Загрузка",
|
||||
"downloaded": "Загружено",
|
||||
"setting": "Настройки",
|
||||
"donate": "Пожертвовать",
|
||||
"exit": "Выход",
|
||||
"create": "Создать задачу",
|
||||
"downloadLink": "Ссылка для скачивание",
|
||||
"downloadLinkValid": "Пожалуйста, введите ссылку для скачивания",
|
||||
@@ -48,6 +50,8 @@
|
||||
"notSet": "Не установлено",
|
||||
"set": "Установлено",
|
||||
"effectAfterRestart": "Эффект после перезагрузки",
|
||||
"startAll": "Запустить все",
|
||||
"pauseAll": "Приостановить все",
|
||||
"deleteTask": "Удалить задачу",
|
||||
"deleteTaskTip": "Сохранить загруженные файлы",
|
||||
"delete": "Удалить",
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
"downloading": "下载中",
|
||||
"downloaded": "已完成",
|
||||
"setting": "设置",
|
||||
"donate": "打赏",
|
||||
"exit": "退出",
|
||||
"create": "创建任务",
|
||||
"downloadLink": "下载链接",
|
||||
"downloadLinkValid": "请输入下载链接",
|
||||
@@ -48,6 +50,8 @@
|
||||
"notSet": "未设置",
|
||||
"set": "已设置",
|
||||
"effectAfterRestart": "此配置项将在重启应用后生效",
|
||||
"startAll": "全部开始",
|
||||
"pauseAll": "全部暂停",
|
||||
"deleteTask": "删除任务",
|
||||
"deleteTaskTip": "保留已下载的文件",
|
||||
"delete": "删除",
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 9.9 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
@@ -111,6 +111,14 @@ Future<void> continueTask(String id) async {
|
||||
return _parse(() => _client.dio.put("/api/v1/tasks/$id/continue"), null);
|
||||
}
|
||||
|
||||
Future<void> pauseAllTasks() async {
|
||||
return _parse(() => _client.dio.put("/api/v1/tasks/pause"), null);
|
||||
}
|
||||
|
||||
Future<void> continueAllTasks() async {
|
||||
return _parse(() => _client.dio.put("/api/v1/tasks/continue"), null);
|
||||
}
|
||||
|
||||
Future<void> deleteTask(String id, bool force) async {
|
||||
return _parse(
|
||||
() => _client.dio.delete("/api/v1/tasks/$id?force=$force"), null);
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:app_links/app_links.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:tray_manager/tray_manager.dart';
|
||||
import 'package:uri_to_file/uri_to_file.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
import '../../../../api/api.dart';
|
||||
import '../../../../api/model/downloader_config.dart';
|
||||
@@ -12,7 +18,9 @@ import '../../../../core/common/start_config.dart';
|
||||
import '../../../../generated/locales.g.dart';
|
||||
import '../../../../util/localeManager.dart';
|
||||
import '../../../../util/log_util.dart';
|
||||
import '../../../../util/package_info.dart';
|
||||
import '../../../../util/util.dart';
|
||||
import '../../../routes/app_pages.dart';
|
||||
|
||||
const _startConfigNetwork = "start.network";
|
||||
const _startConfigAddress = "start.address";
|
||||
@@ -55,13 +63,153 @@ final allTrackerSubscribeUrlCdns = Map.fromIterable(allTrackerSubscribeUrls,
|
||||
return ret;
|
||||
});
|
||||
|
||||
class AppController extends GetxController {
|
||||
class AppController extends GetxController with WindowListener, TrayListener {
|
||||
static StartConfig? _defaultStartConfig;
|
||||
|
||||
final startConfig = StartConfig().obs;
|
||||
final runningPort = 0.obs;
|
||||
final downloaderConfig = DownloaderConfig().obs;
|
||||
|
||||
late AppLinks _appLinks;
|
||||
StreamSubscription<Uri>? _linkSubscription;
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
try {
|
||||
_initDeepLinks();
|
||||
} catch (e) {
|
||||
logger.w("initDeepLinks error", e);
|
||||
}
|
||||
try {
|
||||
_initWindows();
|
||||
} catch (e) {
|
||||
logger.w("initWindows error", e);
|
||||
}
|
||||
try {
|
||||
_initTray();
|
||||
} catch (e) {
|
||||
logger.w("initTray error", e);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
_linkSubscription?.cancel();
|
||||
trayManager.removeListener(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void onWindowClose() async {
|
||||
final isPreventClose = await windowManager.isPreventClose();
|
||||
if (isPreventClose) {
|
||||
windowManager.hide();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onTrayIconMouseDown() {
|
||||
windowManager.show();
|
||||
}
|
||||
|
||||
@override
|
||||
void onTrayIconRightMouseDown() {
|
||||
trayManager.popUpContextMenu();
|
||||
}
|
||||
|
||||
Future<void> _initDeepLinks() async {
|
||||
// currently only support android
|
||||
if (!Util.isAndroid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_appLinks = AppLinks();
|
||||
|
||||
// Handle link when app is in warm state (front or background)
|
||||
_linkSubscription = _appLinks.uriLinkStream.listen((uri) async {
|
||||
await _toCreate(uri);
|
||||
});
|
||||
|
||||
// Check initial link if app was in cold state (terminated)
|
||||
final uri = await _appLinks.getInitialAppLink();
|
||||
if (uri != null) {
|
||||
await _toCreate(uri);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _initWindows() async {
|
||||
if (!Util.isDesktop()) {
|
||||
return;
|
||||
}
|
||||
windowManager.addListener(this);
|
||||
}
|
||||
|
||||
Future<void> _initTray() async {
|
||||
if (!Util.isDesktop()) {
|
||||
return;
|
||||
}
|
||||
if (Util.isWindows()) {
|
||||
await trayManager.setIcon('assets/tray_icon/icon.ico');
|
||||
} else if (Util.isMacos()) {
|
||||
await trayManager.setIcon('assets/tray_icon/icon_mac.png',
|
||||
isTemplate: true);
|
||||
} else {
|
||||
await trayManager.setIcon('assets/tray_icon/icon.png');
|
||||
}
|
||||
final menu = Menu(items: [
|
||||
MenuItem(
|
||||
label: "create".tr,
|
||||
onClick: (menuItem) async => {
|
||||
await windowManager.show(),
|
||||
await Get.rootDelegate.offAndToNamed(Routes.CREATE),
|
||||
},
|
||||
),
|
||||
MenuItem.separator(),
|
||||
MenuItem(
|
||||
label: "startAll".tr,
|
||||
onClick: (menuItem) async => {continueAllTasks()},
|
||||
),
|
||||
MenuItem(
|
||||
label: "pauseAll".tr,
|
||||
onClick: (menuItem) async => {pauseAllTasks()},
|
||||
),
|
||||
MenuItem(
|
||||
label: 'setting'.tr,
|
||||
onClick: (menuItem) async => {
|
||||
await windowManager.show(),
|
||||
await Get.rootDelegate.offAndToNamed(Routes.SETTING),
|
||||
},
|
||||
),
|
||||
MenuItem.separator(),
|
||||
MenuItem(
|
||||
label: 'donate'.tr,
|
||||
onClick: (menuItem) => {
|
||||
launchUrl(
|
||||
Uri.parse(
|
||||
"https://github.com/GopeedLab/gopeed/blob/main/.donate/index.md#donate"),
|
||||
mode: LaunchMode.externalApplication)
|
||||
},
|
||||
),
|
||||
MenuItem(
|
||||
label: '${"version".tr}(${packageInfo.version})',
|
||||
),
|
||||
MenuItem.separator(),
|
||||
MenuItem(
|
||||
label: 'exit'.tr,
|
||||
onClick: (menuItem) => {windowManager.destroy()},
|
||||
),
|
||||
]);
|
||||
await trayManager.setContextMenu(menu);
|
||||
trayManager.addListener(this);
|
||||
}
|
||||
|
||||
Future<void> _toCreate(Uri uri) async {
|
||||
final path = uri.scheme == "magnet"
|
||||
? uri.toString()
|
||||
: (await toFile(uri.toString())).path;
|
||||
await Get.rootDelegate.offAndToNamed(Routes.CREATE, arguments: path);
|
||||
}
|
||||
|
||||
String runningAddress() {
|
||||
if (startConfig.value.network == 'unix') {
|
||||
return startConfig.value.address;
|
||||
|
||||
@@ -5,4 +5,5 @@ class CreateController extends GetxController {
|
||||
final RxList fileInfos = [].obs;
|
||||
final RxList selectedIndexes = [].obs;
|
||||
final RxList openedFolders = [].obs;
|
||||
final isResolving = false.obs;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:desktop_drop/desktop_drop.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../../../api/model/resolve_result.dart';
|
||||
@@ -11,8 +12,8 @@ import '../../../../api/model/request.dart';
|
||||
import '../../../../util/message.dart';
|
||||
import '../../../../util/util.dart';
|
||||
import '../../../routes/app_pages.dart';
|
||||
import '../../../views/views/directory_selector.dart';
|
||||
import '../../../views/views/file_list_view.dart';
|
||||
import '../../../views/directory_selector.dart';
|
||||
import '../../../views/file_list_view.dart';
|
||||
import '../../app/controllers/app_controller.dart';
|
||||
import '../controllers/create_controller.dart';
|
||||
|
||||
@@ -26,6 +27,14 @@ class CreateView extends GetView<CreateController> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final String? filePath = Get.rootDelegate.arguments();
|
||||
if (_urlController.text.isEmpty && filePath != null) {
|
||||
_urlController.text = filePath;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
await _doResolve();
|
||||
});
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: IconButton(
|
||||
@@ -45,21 +54,42 @@ class CreateView extends GetView<CreateController> {
|
||||
autovalidateMode: AutovalidateMode.always,
|
||||
child: Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
autofocus: true,
|
||||
controller: _urlController,
|
||||
minLines: 1,
|
||||
maxLines: 30,
|
||||
decoration: InputDecoration(
|
||||
hintText: _hitText(),
|
||||
hintStyle: const TextStyle(fontSize: 12),
|
||||
labelText: 'downloadLink'.tr,
|
||||
icon: const Icon(Icons.link)),
|
||||
validator: (v) {
|
||||
return v!.trim().isNotEmpty
|
||||
? null
|
||||
: 'downloadLinkValid'.tr;
|
||||
}),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
autofocus: true,
|
||||
controller: _urlController,
|
||||
minLines: 1,
|
||||
maxLines: 30,
|
||||
decoration: InputDecoration(
|
||||
hintText: _hitText(),
|
||||
hintStyle: const TextStyle(fontSize: 12),
|
||||
labelText: 'downloadLink'.tr,
|
||||
icon: const Icon(Icons.link),
|
||||
suffixIcon: IconButton(
|
||||
onPressed: _urlController.clear,
|
||||
icon: const Icon(Icons.clear),
|
||||
),
|
||||
),
|
||||
validator: (v) {
|
||||
return v!.trim().isNotEmpty
|
||||
? null
|
||||
: 'downloadLinkValid'.tr;
|
||||
}),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.folder_open),
|
||||
onPressed: () async {
|
||||
var pr = await FilePicker.platform.pickFiles(
|
||||
type: FileType.custom,
|
||||
allowedExtensions: ["torrent"]);
|
||||
if (pr != null) {
|
||||
_urlController.text = pr.files[0].path ?? "";
|
||||
}
|
||||
}),
|
||||
],
|
||||
),
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(15.0),
|
||||
@@ -70,21 +100,7 @@ class CreateView extends GetView<CreateController> {
|
||||
),
|
||||
child: RoundedLoadingButton(
|
||||
color: Get.theme.colorScheme.secondary,
|
||||
onPressed: () async {
|
||||
try {
|
||||
_confirmController.start();
|
||||
if (_resolveFormKey.currentState!.validate()) {
|
||||
final rr = await resolve(Request(
|
||||
url: _urlController.text,
|
||||
));
|
||||
await _showResolveDialog(rr);
|
||||
}
|
||||
} catch (e) {
|
||||
showErrorMessage(e);
|
||||
} finally {
|
||||
_confirmController.reset();
|
||||
}
|
||||
},
|
||||
onPressed: _doResolve,
|
||||
controller: _confirmController,
|
||||
child: Text('confirm'.tr),
|
||||
),
|
||||
@@ -98,6 +114,27 @@ class CreateView extends GetView<CreateController> {
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _doResolve() async {
|
||||
if (controller.isResolving.value) {
|
||||
return;
|
||||
}
|
||||
controller.isResolving.value = true;
|
||||
try {
|
||||
_confirmController.start();
|
||||
if (_resolveFormKey.currentState!.validate()) {
|
||||
final rr = await resolve(Request(
|
||||
url: _urlController.text,
|
||||
));
|
||||
await _showResolveDialog(rr);
|
||||
}
|
||||
} catch (e) {
|
||||
showErrorMessage(e);
|
||||
} finally {
|
||||
_confirmController.reset();
|
||||
controller.isResolving.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
String _hitText() {
|
||||
return 'downloadLinkHit'.trParams({
|
||||
'append': Util.isDesktop() ? 'downloadLinkHitDesktop'.tr : '',
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../../routes/app_pages.dart';
|
||||
import '../../../views/views/responsive_builder.dart';
|
||||
import '../../../views/responsive_builder.dart';
|
||||
import '../controllers/home_controller.dart';
|
||||
|
||||
class HomeView extends GetView<HomeController> {
|
||||
@@ -11,6 +11,15 @@ class HomeView extends GetView<HomeController> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GetRouterOutlet.builder(builder: (context, delegate, currentRoute) {
|
||||
switch (currentRoute?.location) {
|
||||
case Routes.SETTING:
|
||||
controller.currentIndex.value = 1;
|
||||
break;
|
||||
default:
|
||||
controller.currentIndex.value = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
// extendBody: true,
|
||||
body: Row(
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:badges/badges.dart' as badges;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../../../util/message.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:badges/badges.dart' as badges;
|
||||
|
||||
import '../../../../generated/locales.g.dart';
|
||||
import '../../../../util/localeManager.dart';
|
||||
import '../../../../util/message.dart';
|
||||
import '../../../../util/package_info.dart';
|
||||
import '../../../../util/util.dart';
|
||||
import '../../../views/views/check_list_view.dart';
|
||||
import '../../../views/views/directory_selector.dart';
|
||||
import '../../../views/views/outlined_button_loading.dart';
|
||||
import '../../../views/check_list_view.dart';
|
||||
import '../../../views/directory_selector.dart';
|
||||
import '../../../views/outlined_button_loading.dart';
|
||||
import '../../app/controllers/app_controller.dart';
|
||||
import '../controllers/setting_controller.dart';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../../views/views/buid_task_list_view.dart';
|
||||
import '../../../views/buid_task_list_view.dart';
|
||||
import '../controllers/task_downloaded_controller.dart';
|
||||
|
||||
class TaskDownloadedView extends GetView<TaskDownloadedController> {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../../views/views/buid_task_list_view.dart';
|
||||
import '../../../views/buid_task_list_view.dart';
|
||||
import '../controllers/task_downloading_controller.dart';
|
||||
|
||||
class TaskDownloadingView extends GetView<TaskDownloadingController> {
|
||||
|
||||
+8
-8
@@ -3,14 +3,14 @@ import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import '../../../api/api.dart';
|
||||
import '../../../api/model/task.dart';
|
||||
import '../../../util/file_explorer.dart';
|
||||
import '../../../util/file_icon.dart';
|
||||
import '../../../util/icons.dart';
|
||||
import '../../../util/message.dart';
|
||||
import '../../../util/util.dart';
|
||||
import '../../routes/app_pages.dart';
|
||||
import '../../api/api.dart';
|
||||
import '../../api/model/task.dart';
|
||||
import '../../util/file_explorer.dart';
|
||||
import '../../util/file_icon.dart';
|
||||
import '../../util/icons.dart';
|
||||
import '../../util/message.dart';
|
||||
import '../../util/util.dart';
|
||||
import '../routes/app_pages.dart';
|
||||
|
||||
class BuildTaskListView extends GetView {
|
||||
final List<Task> tasks;
|
||||
File renamed without changes.
+9
-11
@@ -2,8 +2,8 @@ import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../../util/mac_secure_util.dart';
|
||||
import '../../../util/util.dart';
|
||||
import '../../util/mac_secure_util.dart';
|
||||
import '../../util/util.dart';
|
||||
|
||||
class DirectorySelector extends StatefulWidget {
|
||||
final TextEditingController controller;
|
||||
@@ -35,19 +35,17 @@ class _DirectorySelectorState extends State<DirectorySelector> {
|
||||
return v!.trim().isNotEmpty ? null : 'downloadDirValid'.tr;
|
||||
},
|
||||
)),
|
||||
!Util.isDesktop()
|
||||
? null
|
||||
: IconButton(
|
||||
Util.isDesktop() || Util.isAndroid()
|
||||
? IconButton(
|
||||
icon: const Icon(Icons.folder_open),
|
||||
onPressed: () async {
|
||||
if (GetPlatform.isDesktop) {
|
||||
var dir = await FilePicker.platform.getDirectoryPath();
|
||||
if (dir != null) {
|
||||
widget.controller.text = dir;
|
||||
MacSecureUtil.saveBookmark(dir);
|
||||
}
|
||||
var dir = await FilePicker.platform.getDirectoryPath();
|
||||
if (dir != null) {
|
||||
widget.controller.text = dir;
|
||||
MacSecureUtil.saveBookmark(dir);
|
||||
}
|
||||
})
|
||||
: null
|
||||
].where((e) => e != null).map((e) => e!).toList(),
|
||||
);
|
||||
}
|
||||
+6
-6
@@ -3,14 +3,14 @@ import 'dart:ui' as ui;
|
||||
import 'package:fluent_ui/fluent_ui.dart' as fluent;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../../api/model/resource.dart';
|
||||
import '../../api/model/resource.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import '../../../util/file_icon.dart';
|
||||
import '../../../util/icons.dart';
|
||||
import '../../../util/util.dart';
|
||||
import '../../modules/app/controllers/app_controller.dart';
|
||||
import '../../modules/create/controllers/create_controller.dart';
|
||||
import '../../util/file_icon.dart';
|
||||
import '../../util/icons.dart';
|
||||
import '../../util/util.dart';
|
||||
import '../modules/app/controllers/app_controller.dart';
|
||||
import '../modules/create/controllers/create_controller.dart';
|
||||
|
||||
class FileListView extends GetView {
|
||||
final List<FileInfo> files;
|
||||
File renamed without changes.
File renamed without changes.
@@ -23,6 +23,8 @@ class LocaleKeys {
|
||||
static const downloading = 'downloading';
|
||||
static const downloaded = 'downloaded';
|
||||
static const setting = 'setting';
|
||||
static const donate = 'donate';
|
||||
static const exit = 'exit';
|
||||
static const create = 'create';
|
||||
static const downloadLink = 'downloadLink';
|
||||
static const downloadLinkValid = 'downloadLinkValid';
|
||||
@@ -62,6 +64,8 @@ class LocaleKeys {
|
||||
static const notSet = 'notSet';
|
||||
static const set = 'set';
|
||||
static const effectAfterRestart = 'effectAfterRestart';
|
||||
static const startAll = 'startAll';
|
||||
static const pauseAll = 'pauseAll';
|
||||
static const deleteTask = 'deleteTask';
|
||||
static const deleteTaskTip = 'deleteTaskTip';
|
||||
static const delete = 'delete';
|
||||
@@ -82,6 +86,8 @@ class Locales {
|
||||
'downloading': 'downloading',
|
||||
'downloaded': 'downloaded',
|
||||
'setting': 'Setting',
|
||||
'donate': 'Donate',
|
||||
'exit': 'Exit',
|
||||
'create': 'Create Task',
|
||||
'downloadLink': 'Download Link',
|
||||
'downloadLinkValid': 'Please enter the download link',
|
||||
@@ -123,6 +129,8 @@ class Locales {
|
||||
'notSet': 'NS',
|
||||
'set': 'SET',
|
||||
'effectAfterRestart': 'Effect after restart',
|
||||
'startAll': 'Start All',
|
||||
'pauseAll': 'Pause All',
|
||||
'deleteTask': 'Delete Task',
|
||||
'deleteTaskTip': 'Keep downloaded files',
|
||||
'delete': 'Delete',
|
||||
@@ -139,6 +147,8 @@ class Locales {
|
||||
'selectAll': 'انتخاب همه',
|
||||
'task': 'کار',
|
||||
'setting': 'تنظیمات',
|
||||
'donate': 'کمک مالی',
|
||||
'exit': 'خروج',
|
||||
'create': 'ایجاد کار',
|
||||
'downloading': 'دانلود کردن',
|
||||
'downloaded': 'دانلود شدن',
|
||||
@@ -178,6 +188,8 @@ class Locales {
|
||||
'notSet': 'NS',
|
||||
'set': 'SET',
|
||||
'effectAfterRestart': 'Effect after restart',
|
||||
'startAll': 'شروع همه',
|
||||
'pauseAll': 'توقف همه',
|
||||
'deleteTask': 'پاک کردن کار',
|
||||
'deleteTaskTip': 'فایل های دانلود شده را نگه دارد',
|
||||
'delete': 'پاک کردن',
|
||||
@@ -196,6 +208,8 @@ class Locales {
|
||||
'downloading': 'Загрузка',
|
||||
'downloaded': 'Загружено',
|
||||
'setting': 'Настройки',
|
||||
'donate': 'Пожертвовать',
|
||||
'exit': 'Выход',
|
||||
'create': 'Создать задачу',
|
||||
'downloadLink': 'Ссылка для скачивание',
|
||||
'downloadLinkValid': 'Пожалуйста, введите ссылку для скачивания',
|
||||
@@ -237,6 +251,8 @@ class Locales {
|
||||
'notSet': 'Не установлено',
|
||||
'set': 'Установлено',
|
||||
'effectAfterRestart': 'Эффект после перезагрузки',
|
||||
'startAll': 'Запустить все',
|
||||
'pauseAll': 'Приостановить все',
|
||||
'deleteTask': 'Удалить задачу',
|
||||
'deleteTaskTip': 'Сохранить загруженные файлы',
|
||||
'delete': 'Удалить',
|
||||
@@ -255,6 +271,8 @@ class Locales {
|
||||
'downloading': '下载中',
|
||||
'downloaded': '已完成',
|
||||
'setting': '设置',
|
||||
'donate': '打赏',
|
||||
'exit': '退出',
|
||||
'create': '创建任务',
|
||||
'downloadLink': '下载链接',
|
||||
'downloadLinkValid': '请输入下载链接',
|
||||
@@ -294,6 +312,8 @@ class Locales {
|
||||
'notSet': '未设置',
|
||||
'set': '已设置',
|
||||
'effectAfterRestart': '此配置项将在重启应用后生效',
|
||||
'startAll': '全部开始',
|
||||
'pauseAll': '全部暂停',
|
||||
'deleteTask': '删除任务',
|
||||
'deleteTaskTip': '保留已下载的文件',
|
||||
'delete': '删除',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
import 'api/api.dart' as api;
|
||||
import 'app/modules/app/controllers/app_controller.dart';
|
||||
@@ -11,6 +12,7 @@ import 'util/localeManager.dart';
|
||||
import 'util/log_util.dart';
|
||||
import 'util/mac_secure_util.dart';
|
||||
import 'util/package_info.dart';
|
||||
import 'util/util.dart';
|
||||
|
||||
void main() async {
|
||||
await init();
|
||||
@@ -21,6 +23,19 @@ void main() async {
|
||||
|
||||
Future<void> init() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
if (Util.isDesktop()) {
|
||||
await windowManager.ensureInitialized();
|
||||
const windowOptions = WindowOptions(
|
||||
size: Size(1024, 768),
|
||||
center: true,
|
||||
skipTaskbar: false,
|
||||
);
|
||||
windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||
await windowManager.show();
|
||||
await windowManager.focus();
|
||||
await windowManager.setPreventClose(true);
|
||||
});
|
||||
}
|
||||
|
||||
final controller = Get.put(AppController());
|
||||
try {
|
||||
|
||||
@@ -41,6 +41,10 @@ class Util {
|
||||
return Platform.isWindows || Platform.isLinux || Platform.isMacOS;
|
||||
}
|
||||
|
||||
static isWindows() {
|
||||
return !kIsWeb && Platform.isWindows;
|
||||
}
|
||||
|
||||
static isMacos() {
|
||||
return !kIsWeb && Platform.isMacOS;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,19 @@ import FlutterMacOS
|
||||
@NSApplicationMain
|
||||
class AppDelegate: FlutterAppDelegate {
|
||||
override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
override func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
|
||||
if !flag {
|
||||
for window in NSApp.windows {
|
||||
if !window.isVisible {
|
||||
window.setIsVisible(true)
|
||||
}
|
||||
window.makeKeyAndOrderFront(self)
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,14 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
app_links:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: app_links
|
||||
sha256: d572dcdff49c4cfcfa6f315e2683e518ec6eb54e084d01e51d9631a4dcc1b5e8
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.4.2"
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -518,6 +526,14 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
menu_base:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: menu_base
|
||||
sha256: "820368014a171bd1241030278e6c2617354f492f5c703d7b7d4570a6b8b84405"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.1.1"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -710,6 +726,14 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.27.5"
|
||||
screen_retriever:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: screen_retriever
|
||||
sha256: "4931f226ca158123ccd765325e9fbf360bfed0af9b460a10f960f9bb13d58323"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.1.6"
|
||||
scroll_pos:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -798,6 +822,14 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
shortid:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shortid
|
||||
sha256: d0b40e3dbb50497dad107e19c54ca7de0d1a274eb9b4404991e443dadb9ebedb
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.1.2"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@@ -891,6 +923,14 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
tray_manager:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: tray_manager
|
||||
sha256: b1975a05e0c6999e983cf9a58a6a098318c896040ccebac5398a3cc9e43b9c69
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -899,6 +939,14 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
uri_to_file:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: uri_to_file
|
||||
sha256: "84afd633b1492fc465c768141e1a29edd519061bf99935b6b4d0d5de8ec7c108"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
url_launcher:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -995,6 +1043,14 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "4.1.4"
|
||||
window_manager:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: window_manager
|
||||
sha256: "95096fede562cbb65f30d38b62d819a458f59ba9fe4a317f6cee669710f6676b"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.3.4"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -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.1+1
|
||||
version: 1.3.3+1
|
||||
|
||||
environment:
|
||||
sdk: ">=2.17.6 <3.0.0"
|
||||
@@ -53,6 +53,10 @@ dependencies:
|
||||
fluent_ui: ^4.4.0
|
||||
path: any
|
||||
badges: ^3.0.3
|
||||
app_links: ^3.4.2
|
||||
uri_to_file: ^0.2.0
|
||||
window_manager: ^0.3.4
|
||||
tray_manager: ^0.2.0
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
@@ -83,9 +87,8 @@ flutter:
|
||||
uses-material-design: true
|
||||
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
# assets:
|
||||
# - macos/Frameworks/libgopeed.dylib
|
||||
# - macos/lib/libgopeed.dylib
|
||||
assets:
|
||||
- assets/tray_icon/
|
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
|
||||
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
||||
_In_ wchar_t *command_line, _In_ int show_command) {
|
||||
HWND hwnd = ::FindWindow(L"FLUTTER_RUNNER_WIN32_WINDOW", L"gopeed");
|
||||
if (hwnd != NULL) {
|
||||
::ShowWindow(hwnd, SW_NORMAL);
|
||||
::SetForegroundWindow(hwnd);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
// Attach to console when present (e.g., 'flutter run') or create a
|
||||
// new console when running with a debugger.
|
||||
if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
|
||||
|
||||
Reference in new issue
Block a user