Compare commits

..
41 Commits
Author SHA1 Message Date
Levi 1b0178fed9 release: v1.6.7 2025-01-17 08:25:24 +08:00
Levi 83febe0a00 feat: support creating tasks using gopeed scheme (#876) 2025-01-16 18:49:32 +08:00
Levi 987580d400 fix: windows uninstall icon (#875) 2025-01-16 18:48:46 +08:00
Levi 0919936050 feat: support custom http request headers (#868) 2025-01-16 00:19:50 +08:00
Levi acc7ed8f6b feat: torrent scheme deep link and file associations (#866) 2025-01-16 00:02:00 +08:00
Levi ccb3267fba feat: update flutter to v3.24 (#865) 2025-01-06 18:34:50 +08:00
Levi 1249493a8a feat: improve file_tree_view display on mobile (#862) 2024-12-30 20:35:39 +08:00
Levi 107141bbe7 fix: not disabling the context menu on the browser (#861) 2024-12-30 20:17:33 +08:00
Levi b329fee107 release: v1.6.6 2024-12-27 19:11:18 +08:00
Levi 3ce95f21fd fix: some torrents can not resovle (#857) 2024-12-27 19:06:17 +08:00
Levi f54ed5df5a feat: batch operation task (#860) 2024-12-27 18:52:23 +08:00
Levi 727b7edb84 feat: file tree view responsive support (#856) 2024-12-27 11:34:56 +08:00
Levi f5891ee03d feat: add batch create tips (#858) 2024-12-27 11:17:17 +08:00
Levi 724276ac69 release: v1.6.5 2024-12-25 22:56:09 +08:00
Levi a3f559c8e5 feat: improve file select tree view (#853) 2024-12-25 22:55:33 +08:00
Levi edd189a8a8 fix: failed to delete a running task (#852) 2024-12-24 22:23:20 +08:00
Levi c970378fd7 fix: http download retries too many times (#849) 2024-12-24 20:28:04 +08:00
Levi 8b61343aef fix: extension task missing fields (#850) 2024-12-23 01:58:29 +08:00
Levi 2cb93a03e2 perf: extension onStart hook will block task create (#844) 2024-12-21 09:58:33 +08:00
Levi 81dfc073a6 release: v1.6.4 2024-12-09 20:30:33 +08:00
Levi 427921ccab perf: write to disk only when progress updated (#839) 2024-12-09 20:29:50 +08:00
Levi f4876c8a0e fix: HTTP fetch crash when modified request extra via extension (#832) 2024-12-08 12:07:08 +08:00
Navy.Wang 35a3625b11 feat: add QNAP platform build (#828) 2024-11-29 13:38:17 +08:00
ilkei dc9b501e35 feat: optimize docker build (#827) 2024-11-27 13:40:28 +08:00
Levi 85fe92a378 release: v1.6.3 2024-11-18 18:54:46 +08:00
Levi 983d9ad09e fix: windows location fix patch not effect (#819) 2024-11-18 18:54:15 +08:00
Levi d9f757aaf0 fix: revert flutter version to v3.16.8 (#821) 2024-11-18 18:31:25 +08:00
Levi cd409fcfb9 ci: add build tests for all platforms (#812) 2024-11-15 12:06:51 +08:00
Levi 366244fa5d fix: android build on go 1.23 (#813) 2024-11-15 11:43:55 +08:00
Levi 7a2e9b4fd1 release: v1.6.2 2024-11-14 23:45:08 +08:00
Levi 203385d3f8 fix: use golang 1.23 standard library to collect crash logs (#807) 2024-11-14 00:54:34 +08:00
Levi aaf73dec24 fix: proxy config reload panic (#808) 2024-11-14 00:36:21 +08:00
Ricky 2523282a89 feat(http): add option to skip SSL certificate verification (#801) 2024-11-12 10:30:21 +08:00
Levi 3384f5197a fix: download path in docker-compose.yml (#798) 2024-11-05 09:55:25 +08:00
Levi cd77665f02 fix: avoid request locatoin permisson on windows (#787) 2024-10-19 16:55:23 +08:00
Levi a22b431150 feat: upgrade flutter to v3.24.3 (#791) 2024-10-19 12:12:41 +08:00
Levi eb7c9ad7f2 release: v1.6.1 2024-10-16 18:31:56 +08:00
Levi ea11fc38f1 ci: fix windows build version (#785) 2024-10-16 18:30:41 +08:00
towermom9 1be16e9f2c feat: Updated the indonesian translation (#777) 2024-10-10 13:18:11 +08:00
Ayase 1d86d14a20 fix: open files on linux (#765) 2024-10-03 21:40:49 +08:00
𝗦𝗵𝗟𝗲𝗿𝗣 5ad15cc4ac feat: Update tr_tr.dart (#754) 2024-09-23 09:19:45 +08:00
96 changed files with 2804 additions and 3901 deletions

No files matched your search

+66 -30
View File
@@ -4,17 +4,17 @@ on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
platform: platform:
description: 'Build platform' description: "Build platform"
required: true required: true
default: 'all' default: "all"
test: test:
description: 'Test mode' description: "Test mode"
required: true required: true
default: "false" default: "false"
env: env:
GO_VERSION: "1.22" GO_VERSION: "1.23"
FLUTTER_VERSION: "3.16.8" FLUTTER_VERSION: "3.24.5"
permissions: permissions:
contents: write contents: write
@@ -35,7 +35,7 @@ jobs:
build-windows: build-windows:
if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'windows' }} if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'windows' }}
runs-on: windows-latest runs-on: windows-latest
needs: [ get-release ] needs: [get-release]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
@@ -51,7 +51,7 @@ jobs:
Invoke-WebRequest -Uri "https://github.com/jrsoftware/issrc/raw/main/Files/Languages/Unofficial/ChineseSimplified.isl" -OutFile "ChineseSimplified.isl" 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 -X github.com/GopeedLab/gopeed/pkg/base.Version=$VERSION" -buildmode=c-shared -o ui/flutter/windows/libgopeed.dll github.com/GopeedLab/gopeed/bind/desktop go build -tags nosqlite -ldflags="-w -s -X github.com/GopeedLab/gopeed/pkg/base.Version=$env:VERSION" -buildmode=c-shared -o ui/flutter/windows/libgopeed.dll github.com/GopeedLab/gopeed/bind/desktop
cd ui/flutter cd ui/flutter
$TAG = "v$env:VERSION" $TAG = "v$env:VERSION"
flutter build windows flutter build windows
@@ -97,11 +97,13 @@ jobs:
PrivilegesRequired=lowest PrivilegesRequired=lowest
OutputBaseFilename=gopeed OutputBaseFilename=gopeed
SetupIconFile=..\..\assets\icon\icon.ico SetupIconFile=..\..\assets\icon\icon.ico
UninstallDisplayIcon={app}\{#MyAppExeName}
Compression=lzma Compression=lzma
SolidCompression=yes SolidCompression=yes
WizardStyle=modern WizardStyle=modern
LanguageDetectionMethod=uilanguage LanguageDetectionMethod=uilanguage
ShowLanguageDialog=yes ShowLanguageDialog=yes
CloseApplications=force
[Languages] [Languages]
Name: "english"; MessagesFile: "compiler:Default.isl" Name: "english"; MessagesFile: "compiler:Default.isl"
@@ -111,7 +113,7 @@ jobs:
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files] [Files]
Source: ".\x64\runner\Release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs Source: ".\x64\runner\Release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs;
; NOTE: Don't use "Flags: ignoreversion" on any shared system files ; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[UninstallDelete] [UninstallDelete]
@@ -120,7 +122,7 @@ jobs:
[Icons] [Icons]
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
[Run] [Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
"@ > setup.iss "@ > setup.iss
@@ -137,7 +139,7 @@ jobs:
build-macos-arm64-lib: build-macos-arm64-lib:
if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'macos' }} if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'macos' }}
runs-on: macos-latest runs-on: macos-latest
needs: [ get-release ] needs: [get-release]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
@@ -155,7 +157,7 @@ jobs:
build-macos: build-macos:
if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'macos' }} if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'macos' }}
runs-on: macos-13 runs-on: macos-13
needs: [ get-release, build-macos-arm64-lib ] needs: [get-release, build-macos-arm64-lib]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
@@ -214,7 +216,7 @@ jobs:
build-linux: build-linux:
if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'linux' }} if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'linux' }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [ get-release ] needs: [get-release]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
@@ -252,7 +254,7 @@ jobs:
build-snap: build-snap:
if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'snap' }} if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'snap' }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [ get-release ] needs: [get-release]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
@@ -268,31 +270,31 @@ jobs:
run: | run: |
go build -tags nosqlite -ldflags="-w -s -X github.com/GopeedLab/gopeed/pkg/base.Version=$VERSION" -buildmode=c-shared -o ui/flutter/linux/bundle/lib/libgopeed.so github.com/GopeedLab/gopeed/bind/desktop go build -tags nosqlite -ldflags="-w -s -X github.com/GopeedLab/gopeed/pkg/base.Version=$VERSION" -buildmode=c-shared -o ui/flutter/linux/bundle/lib/libgopeed.so github.com/GopeedLab/gopeed/bind/desktop
cd ui/flutter cd ui/flutter
sudo snap install snapcraft --classic sudo snap install snapcraft --classic
mkdir -p snap/gui mkdir -p snap/gui
cp assets/icon/icon.svg snap/gui/gopeed.svg cp assets/icon/icon.svg snap/gui/gopeed.svg
cat>snap/snapcraft.yaml<<EOF cat>snap/snapcraft.yaml<<EOF
name: gopeed name: gopeed
version: $VERSION version: $VERSION
summary: A modern download manager summary: A modern download manager
description: High speed downloader that supports all platforms. description: High speed downloader that supports all platforms.
confinement: strict confinement: strict
base: core22 base: core22
grade: stable grade: stable
architectures: architectures:
- build-on: amd64 - build-on: amd64
build-for: amd64 build-for: amd64
slots: slots:
dbus-gopeed: dbus-gopeed:
interface: dbus interface: dbus
bus: session bus: session
name: com.gopeed.gopeed name: com.gopeed.gopeed
apps: apps:
gopeed: gopeed:
command: bin/gopeed command: bin/gopeed
@@ -345,10 +347,10 @@ jobs:
mkdir -p \$CRAFT_PART_INSTALL/bin/ mkdir -p \$CRAFT_PART_INSTALL/bin/
cp -r build/linux/*/release/bundle/* \$CRAFT_PART_INSTALL/bin/ cp -r build/linux/*/release/bundle/* \$CRAFT_PART_INSTALL/bin/
EOF EOF
cp linux/assets/com.gopeed.Gopeed.desktop snap/gui/gopeed.desktop cp linux/assets/com.gopeed.Gopeed.desktop snap/gui/gopeed.desktop
sed -i 's/Icon=com.gopeed.Gopeed/Icon=\${SNAP}\/meta\/gui\/gopeed.svg/g' snap/gui/gopeed.desktop sed -i 's/Icon=com.gopeed.Gopeed/Icon=\${SNAP}\/meta\/gui\/gopeed.svg/g' snap/gui/gopeed.desktop
snapcraft --use-lxd snapcraft --use-lxd
# Snapcraft login # Snapcraft login
@@ -357,7 +359,7 @@ jobs:
build-android: build-android:
if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'android' }} if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'android' }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [ get-release ] needs: [get-release]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
@@ -366,7 +368,7 @@ jobs:
- uses: actions/setup-java@v3 - uses: actions/setup-java@v3
with: with:
distribution: "zulu" distribution: "zulu"
java-version: "11" java-version: "17"
- uses: subosito/flutter-action@v2 - uses: subosito/flutter-action@v2
with: with:
flutter-version: ${{ env.FLUTTER_VERSION }} flutter-version: ${{ env.FLUTTER_VERSION }}
@@ -380,7 +382,7 @@ jobs:
go install golang.org/x/mobile/cmd/gomobile@latest go install golang.org/x/mobile/cmd/gomobile@latest
go get golang.org/x/mobile/bind go get golang.org/x/mobile/bind
gomobile init gomobile init
gomobile bind -tags nosqlite -ldflags="-w -s -X github.com/GopeedLab/gopeed/pkg/base.Version=$VERSION" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg=com.gopeed github.com/GopeedLab/gopeed/bind/mobile gomobile bind -tags nosqlite -ldflags="-w -s -checklinkname=0 -X github.com/GopeedLab/gopeed/pkg/base.Version=$VERSION" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg=com.gopeed github.com/GopeedLab/gopeed/bind/mobile
cd ui/flutter cd ui/flutter
echo $APK_KEYSTORE | base64 -di > android/app/upload-keystore.jks echo $APK_KEYSTORE | base64 -di > android/app/upload-keystore.jks
flutter build apk flutter build apk
@@ -395,7 +397,7 @@ jobs:
build-ios: build-ios:
if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'ios' }} if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'ios' }}
runs-on: macos-latest runs-on: macos-latest
needs: [ get-release ] needs: [get-release]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
@@ -428,7 +430,7 @@ jobs:
build-web: build-web:
if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'web' }} if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'web' }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [ get-release ] needs: [get-release]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
@@ -441,12 +443,13 @@ jobs:
env: env:
VERSION: ${{ needs.get-release.outputs.version }} VERSION: ${{ needs.get-release.outputs.version }}
run: | run: |
VERSION=${VERSION:-$(date +%y%m%d%H%M)} # Use current time as version if not specified
cd ui/flutter cd ui/flutter
flutter build web --web-renderer html flutter build web --no-web-resources-cdn
cd ../../ cd ../../
cp -r ui/flutter/build/web cmd/web/dist cp -r ui/flutter/build/web cmd/web/dist
mkdir -p dist/zip mkdir -p dist/zip
goos_arr=(windows darwin linux) goos_arr=(windows darwin linux)
goarch_arr=(386 amd64 arm64) goarch_arr=(386 amd64 arm64)
export CGO_ENABLED=0 export CGO_ENABLED=0
@@ -468,6 +471,39 @@ jobs:
|| true || true
done done
done done
sudo apt update -y
sudo apt install -y pv python2 bsdmainutils
wget -O qdk2_0.32.bionic_amd64.deb "https://github.com/qnap-dev/qdk2/releases/download/v0.32/qdk2_0.32.bionic_amd64.deb"
dpkg -X qdk2_0.32.bionic_amd64.deb qdk2 # Direct installs will fail due to missing dependencies!
[[ -d qdk2 ]] || exit 1
export PATH=$(pwd)/qdk2/usr/bin:$(pwd)/qdk2/usr/share/qdk2/QDK/bin:${PATH}
wget -O Gopeed.template.tar.gz "https://github.com/GopeedLab/QpkgBuild/raw/refs/heads/master/template/Gopeed.template.tar.gz"
tar -zxf Gopeed.template.tar.gz
[[ -d Gopeed ]] || exit 1
goos=linux
goarch_arr=(amd64 arm64)
for goarch in "${goarch_arr[@]}"; do
qarch=x86_64
[[ "${goarch}" == "arm64" ]] && qarch=arm_64
name=gopeed-web-v${VERSION}-${goos}-${goarch}
cp dist/${name}/${name}/* Gopeed/${qarch}/
done
cd Gopeed
sed -i -e 's/__QPKG_VER__/${VERSION}/g' qpkg.cfg
qbuild || exit 1
for f in build/*; do echo ">>> build=[${f}]"; done
goos=qnap
goarch_arr=(amd64 arm64)
for goarch in "${goarch_arr[@]}"; do
qarch=x86_64
[[ "${goarch}" == "arm64" ]] && qarch=arm_64
sname=Gopeed_${VERSION}_${qarch}.qpkg
dname=gopeed-${goos}-v${VERSION}-${goarch}.qpkg
echo "sname=${sname}, dname=${dname}"
[[ -f build/${sname} ]] && cp -ra build/${sname} ../dist/zip/${dname}
done
for f in ../dist/zip/*; do echo ">>> dist=[${f}]"; done
cd ..
- name: Upload - name: Upload
uses: shogo82148/actions-upload-release-asset@v1 uses: shogo82148/actions-upload-release-asset@v1
with: with:
@@ -477,7 +513,7 @@ jobs:
build-docker: build-docker:
if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'docker' }} if: ${{ github.event.inputs.platform == 'all' || github.event.inputs.platform == 'docker' }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [ get-release ] needs: [get-release]
steps: steps:
- name: Remove unnecessary files - name: Remove unnecessary files
run: | run: |
@@ -499,7 +535,7 @@ jobs:
- name: Build flutter web - name: Build flutter web
run: | run: |
cd ui/flutter cd ui/flutter
flutter build web --web-renderer html flutter build web --no-web-resources-cdn
cd ../../ cd ../../
rm -rf cmd/web/dist rm -rf cmd/web/dist
cp -r ui/flutter/build/web cmd/web/dist cp -r ui/flutter/build/web cmd/web/dist
+1 -1
View File
@@ -17,7 +17,7 @@ on:
- "Dockerfile" - "Dockerfile"
env: env:
GO_VERSION: "1.22" GO_VERSION: "1.23"
permissions: permissions:
contents: write contents: write
+97 -11
View File
@@ -27,8 +27,8 @@ on:
- "go.sum" - "go.sum"
env: env:
GO_VERSION: "1.22" GO_VERSION: "1.23"
FLUTTER_VERSION: "3.16.8" FLUTTER_VERSION: "3.24.5"
jobs: jobs:
# lint: # lint:
@@ -58,11 +58,45 @@ jobs:
with: with:
files: ./coverage.txt files: ./coverage.txt
token: ${{ secrets.CODECOV_UPLOAD_TOKEN }} token: ${{ secrets.CODECOV_UPLOAD_TOKEN }}
build: build-desktop:
name: Build check name: Build desktop check
runs-on: ubuntu-latest runs-on: ${{ matrix.os }}
# needs: [lint, test] strategy:
needs: [test] matrix:
os: [ windows-latest, macos-latest, ubuntu-latest ]
needs: [ test ]
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 }}
- if: runner.os == 'windows-latest'
run: |
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
flutter build windows
- if: runner.os == 'macos-latest'
run: |
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/macos/Frameworks/libgopeed.dylib github.com/GopeedLab/gopeed/bind/desktop
cd ui/flutter
flutter build macos
- if: runner.os == 'ubuntu-latest'
run: |
sudo apt-get update -y
sudo apt-get install -y ninja-build libgtk-3-dev libayatana-appindicator3-dev
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/linux/bundle/lib/libgopeed.so github.com/GopeedLab/gopeed/bind/desktop
cd ui/flutter
flutter build linux
build-mobile:
name: Build mobile check
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ macos-latest, ubuntu-latest ]
needs: [ test ]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-go@v4 - uses: actions/setup-go@v4
@@ -72,10 +106,62 @@ jobs:
with: with:
flutter-version: ${{ env.FLUTTER_VERSION }} flutter-version: ${{ env.FLUTTER_VERSION }}
- run: | - run: |
sudo apt-get update -y go install golang.org/x/mobile/cmd/gomobile@latest
sudo apt-get install -y ninja-build libgtk-3-dev libayatana-appindicator3-dev go get golang.org/x/mobile/bind
gomobile init
- if: runner.os == 'macOS'
run: |
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 ipa --no-codesign
- if: runner.os == 'Linux'
uses: actions/setup-java@v3
with:
distribution: "zulu"
java-version: "17"
- if: runner.os == 'Linux'
run: |
gomobile bind -tags nosqlite -ldflags="-w -s -checklinkname=0" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg=com.gopeed github.com/GopeedLab/gopeed/bind/mobile
cd ui/flutter
flutter build apk
build-web:
name: Build web check
runs-on: ubuntu-latest
needs: [ test ]
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 - name: Build
run: | 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
cd ui/flutter cd ui/flutter
flutter build linux flutter build web --no-web-resources-cdn
cd ../../
rm -rf cmd/web/dist
cp -r ui/flutter/build/web cmd/web/dist
go build -tags nosqlite,web -ldflags="-s -w" github.com/GopeedLab/gopeed/cmd/web
build-docker:
name: Build docker check
runs-on: ubuntu-latest
needs: [ test ]
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
run: |
cd ui/flutter
flutter build web --no-web-resources-cdn
cd ../../
rm -rf cmd/web/dist
cp -r ui/flutter/build/web cmd/web/dist
docker build -t gopeed .
+3 -4
View File
@@ -1,4 +1,4 @@
FROM golang:1.22.6 AS go FROM golang:1.23.3 AS go
WORKDIR /app WORKDIR /app
COPY ./go.mod ./go.sum ./ COPY ./go.mod ./go.sum ./
RUN go mod download RUN go mod download
@@ -8,14 +8,13 @@ RUN CGO_ENABLED=0 go build -tags nosqlite,web \
-ldflags="-s -w -X github.com/GopeedLab/gopeed/pkg/base.Version=$VERSION -X github.com/GopeedLab/gopeed/pkg/base.InDocker=true" \ -ldflags="-s -w -X github.com/GopeedLab/gopeed/pkg/base.Version=$VERSION -X github.com/GopeedLab/gopeed/pkg/base.InDocker=true" \
-o dist/gopeed github.com/GopeedLab/gopeed/cmd/web -o dist/gopeed github.com/GopeedLab/gopeed/cmd/web
FROM alpine:3.14.2 FROM alpine:3.18
LABEL maintainer="monkeyWie" LABEL maintainer="monkeyWie"
WORKDIR /app WORKDIR /app
COPY --from=go /app/dist/gopeed ./ COPY --from=go /app/dist/gopeed ./
COPY entrypoint.sh ./entrypoint.sh COPY entrypoint.sh ./entrypoint.sh
RUN apk update && \ RUN apk update && \
apk upgrade --no-cache && \ apk add --no-cache su-exec ; \
apk add --no-cache bash su-exec; \
chmod +x ./entrypoint.sh && \ chmod +x ./entrypoint.sh && \
rm -rf /var/cache/apk/* rm -rf /var/cache/apk/*
VOLUME ["/app/storage"] VOLUME ["/app/storage"]
+8 -3
View File
@@ -71,6 +71,11 @@ Visit ✈ [Official Website](https://gopeed.com) | 📖 [Official Docs](https://
<td><code>IPA</code></td> <td><code>IPA</code></td>
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-ios.ipa">Link</a></td> <td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-ios.ipa">Link</a></td>
</tr> </tr>
<tr>
<td>Qnap</td>
<td><code>QPKG</code></td>
<td><a href="https://gopeed.com/api/download?tpl=gopeed-qnap-$version-amd64.qpkg">Link</a></td>
</tr>
<tr> <tr>
<td>Web</td> <td>Web</td>
<td></td> <td></td>
@@ -114,8 +119,8 @@ This project is divided into two parts, the front end uses `flutter`, the back e
### Environment ### Environment
1. Golang 1.22+ 1. Golang 1.23+
2. Flutter 3.16+ 2. Flutter 3.24+
### Clone ### Clone
@@ -174,7 +179,7 @@ command:
- android - android
```bash ```bash
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg="com.gopeed" github.com/GopeedLab/gopeed/bind/mobile gomobile bind -tags nosqlite -ldflags="-w -s -checklinkname=0" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg="com.gopeed" github.com/GopeedLab/gopeed/bind/mobile
cd ui/flutter cd ui/flutter
flutter build apk flutter build apk
``` ```
+8 -3
View File
@@ -71,6 +71,11 @@ Gopeed (正式名 Go Speed) は `Golang` + `Flutter` によって開発された
<td><code>IPA</code></td> <td><code>IPA</code></td>
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-ios.ipa">Link</a></td> <td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-ios.ipa">Link</a></td>
</tr> </tr>
<tr>
<td>Qnap</td>
<td><code>QPKG</code></td>
<td><a href="https://gopeed.com/api/download?tpl=gopeed-qnap-$version-amd64.qpkg">Link</a></td>
</tr>
<tr> <tr>
<td>Web</td> <td>Web</td>
<td></td> <td></td>
@@ -102,8 +107,8 @@ Gopeed (正式名 Go Speed) は `Golang` + `Flutter` によって開発された
### 環境 ### 環境
1. Go 言語 1.22+ 1. Go 言語 1.23+
2. Flutter 3.16+ 2. Flutter 3.24+
### クローン ### クローン
@@ -162,7 +167,7 @@ gomobile init
- android - android
```bash ```bash
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg="com.gopeed" github.com/GopeedLab/gopeed/bind/mobile gomobile bind -tags nosqlite -ldflags="-w -s -checklinkname=0" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg="com.gopeed" github.com/GopeedLab/gopeed/bind/mobile
cd ui/flutter cd ui/flutter
flutter build apk flutter build apk
``` ```
+9 -4
View File
@@ -71,6 +71,11 @@ Truy cập ✈ [Trang web chính thức](https://gopeed.com) | 📖 [Tài liệu
<td><code>IPA</code></td> <td><code>IPA</code></td>
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-ios.ipa">Liên kết</a></td> <td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-ios.ipa">Liên kết</a></td>
</tr> </tr>
<tr>
<td>Qnap</td>
<td><code>QPKG</code></td>
<td><a href="https://gopeed.com/api/download?tpl=gopeed-qnap-$version-amd64.qpkg">Liên kết</a></td>
</tr>
<tr> <tr>
<td>Web</td> <td>Web</td>
<td></td> <td></td>
@@ -110,8 +115,8 @@ Dự án này được chia thành hai phần, phần giao diện sử dụng `f
### Environment ### Environment
1. Golang 1.22+ 1. Golang 1.23+
2. Flutter 3.16+ 2. Flutter 3.24+
### Clone ### Clone
@@ -170,7 +175,7 @@ command:
- android - android
```bash ```bash
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg="com.gopeed" github.com/GopeedLab/gopeed/bind/mobile gomobile bind -tags nosqlite -ldflags="-w -s -checklinkname=0" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg="com.gopeed" github.com/GopeedLab/gopeed/bind/mobile
cd ui/flutter cd ui/flutter
flutter build apk flutter build apk
``` ```
@@ -210,4 +215,4 @@ go build -tags nosqlite,web -ldflags="-s -w" -o bin/ github.com/GopeedLab/gopeed
## Giấy phép ## Giấy phép
[GPLv3](LICENSE) [GPLv3](LICENSE)
+8 -3
View File
@@ -71,6 +71,11 @@ Gopeed(全称 Go Speed),直译过来中文名叫做`够快下载器`(不
<td><code>IPA</code></td> <td><code>IPA</code></td>
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-ios.ipa">前往</a></td> <td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-ios.ipa">前往</a></td>
</tr> </tr>
<tr>
<td>Qnap</td>
<td><code>QPKG</code></td>
<td><a href="https://gopeed.com/api/download?tpl=gopeed-qnap-$version-amd64.qpkg">前往</a></td>
</tr>
<tr> <tr>
<td>Web</td> <td>Web</td>
<td></td> <td></td>
@@ -114,8 +119,8 @@ Gopeed 还提供了浏览器扩展用于接管浏览器下载,支持 Chrome、
### 环境要求 ### 环境要求
1. Golang 1.22+ 1. Golang 1.23+
2. Flutter 3.16+ 2. Flutter 3.24+
### 克隆项目 ### 克隆项目
@@ -174,7 +179,7 @@ gomobile init
- android - android
```bash ```bash
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg="com.gopeed" github.com/GopeedLab/gopeed/bind/mobile gomobile bind -tags nosqlite -ldflags="-w -s -checklinkname=0" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg="com.gopeed" github.com/GopeedLab/gopeed/bind/mobile
cd ui/flutter cd ui/flutter
flutter build apk flutter build apk
``` ```
+9 -4
View File
@@ -71,6 +71,11 @@ Gopeed(全稱 Go Speed),是一款使用`Golang`+`Flutter`編寫的高速
<td><code>IPA</code></td> <td><code>IPA</code></td>
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-ios.ipa">前往</a></td> <td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-ios.ipa">前往</a></td>
</tr> </tr>
<tr>
<td>Qnap</td>
<td><code>QPKG</code></td>
<td><a href="https://gopeed.com/api/download?tpl=gopeed-qnap-$version-amd64.qpkg">前往</a></td>
</tr>
<tr> <tr>
<td>Web</td> <td>Web</td>
<td></td> <td></td>
@@ -86,7 +91,7 @@ Gopeed(全稱 Go Speed),是一款使用`Golang`+`Flutter`編寫的高速
更多關於安裝的內容請參考[安裝文檔](https://docs.gopeed.com/zh/install.html) 更多關於安裝的內容請參考[安裝文檔](https://docs.gopeed.com/zh/install.html)
### 使用CLI安裝 ### 使用 CLI 安裝
使用`go install`安裝: 使用`go install`安裝:
@@ -110,8 +115,8 @@ go install github.com/GopeedLab/gopeed/cmd/gopeed@latest
### 開發環境 ### 開發環境
1. Golang 1.22+ 1. Golang 1.23+
2. Flutter 3.16+ 2. Flutter 3.24+
### 克隆項目 ### 克隆項目
@@ -170,7 +175,7 @@ gomobile init
- android - android
```bash ```bash
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg="com.gopeed" github.com/GopeedLab/gopeed/bind/mobile gomobile bind -tags nosqlite -ldflags="-w -s -checklinkname=0" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg="com.gopeed" github.com/GopeedLab/gopeed/bind/mobile
cd ui/flutter cd ui/flutter
flutter build apk flutter build apk
``` ```
+14 -11
View File
@@ -1,12 +1,15 @@
version: '3'
services: services:
gopeed: gopeed:
container_name: gopeed container_name: gopeed
ports: ports:
- "9999:9999" # HTTP port (host:container) - 9999:9999 # HTTP port (host:container)
image: liwei2633/gopeed environment:
volumes: - PUID=0
- ~/gopeed/Downloads:/root/Downloads # mount download path - PGID=0
#- ~/gopeed/storage:/app/storage # if you need to mount storage path, uncomment this line - UMASK=022
restart: unless-stopped volumes:
- ~/gopeed/Downloads:/app/Downloads # mount download path
#- ~/gopeed/storage:/app/storage # if you need to mount storage path, uncomment this line
restart: unless-stopped
image: liwei2633/gopeed
# command: -u Username -p Password # optional authentication
+48 -49
View File
@@ -1,10 +1,12 @@
module github.com/GopeedLab/gopeed module github.com/GopeedLab/gopeed
go 1.22 go 1.23.0
toolchain go1.23.1
require ( require (
github.com/anacrolix/missinggo/v2 v2.7.3 github.com/anacrolix/missinggo/v2 v2.8.0
github.com/anacrolix/torrent v1.56.1 github.com/anacrolix/torrent v1.57.2-0.20241017235801-4d8437a05621
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
github.com/dop251/goja v0.0.0-20240919115326-6c7d1df7ff05 github.com/dop251/goja v0.0.0-20240919115326-6c7d1df7ff05
github.com/dop251/goja_nodejs v0.0.0-20240728170619-29b559befffc github.com/dop251/goja_nodejs v0.0.0-20240728170619-29b559befffc
@@ -16,11 +18,10 @@ require (
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529 github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529
github.com/rs/zerolog v1.31.0 github.com/rs/zerolog v1.31.0
github.com/virtuald/go-paniclog v0.0.0-20190812204905-43a7fa316459
github.com/xiaoqidun/setft v0.0.0-20220310121541-be86327699ad github.com/xiaoqidun/setft v0.0.0-20220310121541-be86327699ad
go.etcd.io/bbolt v1.3.10 go.etcd.io/bbolt v1.3.11
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f
golang.org/x/sync v0.8.0 golang.org/x/sync v0.9.0
) )
require ( require (
@@ -31,48 +32,48 @@ require (
github.com/acomagu/bufpipe v1.0.4 // indirect github.com/acomagu/bufpipe v1.0.4 // indirect
github.com/ajwerner/btree v0.0.0-20211221152037-f427b3e689c0 // indirect github.com/ajwerner/btree v0.0.0-20211221152037-f427b3e689c0 // indirect
github.com/alecthomas/atomic v0.1.0-alpha2 // indirect github.com/alecthomas/atomic v0.1.0-alpha2 // indirect
github.com/anacrolix/chansync v0.5.1 // indirect github.com/anacrolix/chansync v0.6.0 // indirect
github.com/anacrolix/dht/v2 v2.21.1 // indirect github.com/anacrolix/dht/v2 v2.22.0 // indirect
github.com/anacrolix/envpprof v1.3.0 // indirect github.com/anacrolix/envpprof v1.4.0 // indirect
github.com/anacrolix/generics v0.0.2 // indirect github.com/anacrolix/generics v0.0.3-0.20240902042256-7fb2702ef0ca // indirect
github.com/anacrolix/go-libutp v1.3.1 // indirect github.com/anacrolix/go-libutp v1.3.1 // indirect
github.com/anacrolix/log v0.15.2 // indirect github.com/anacrolix/log v0.16.0 // indirect
github.com/anacrolix/missinggo v1.3.0 // indirect github.com/anacrolix/missinggo v1.3.0 // indirect
github.com/anacrolix/missinggo/perf v1.0.0 // indirect github.com/anacrolix/missinggo/perf v1.0.0 // indirect
github.com/anacrolix/mmsg v1.0.0 // indirect github.com/anacrolix/mmsg v1.1.1 // indirect
github.com/anacrolix/multiless v0.3.1-0.20221221005021-2d12701f83f7 // indirect github.com/anacrolix/multiless v0.4.0 // indirect
github.com/anacrolix/stm v0.5.0 // indirect github.com/anacrolix/stm v0.5.0 // indirect
github.com/anacrolix/sync v0.5.1 // indirect github.com/anacrolix/sync v0.5.3 // indirect
github.com/anacrolix/upnp v0.1.4 // indirect github.com/anacrolix/upnp v0.1.4 // indirect
github.com/anacrolix/utp v0.2.0 // indirect github.com/anacrolix/utp v0.2.0 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/benbjohnson/immutable v0.4.3 // indirect github.com/benbjohnson/immutable v0.4.3 // indirect
github.com/bits-and-blooms/bitset v1.13.0 // indirect github.com/bits-and-blooms/bitset v1.15.0 // indirect
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 // indirect github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 // indirect
github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect
github.com/cloudflare/circl v1.3.3 // indirect github.com/cloudflare/circl v1.3.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dlclark/regexp2 v1.11.4 // indirect github.com/dlclark/regexp2 v1.11.4 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect
github.com/edsrzf/mmap-go v1.1.0 // indirect github.com/edsrzf/mmap-go v1.2.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect
github.com/felixge/httpsnoop v1.0.1 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.4.1 // indirect github.com/go-git/go-billy/v5 v5.4.1 // indirect
github.com/go-llsqlite/adapter v0.1.0 // indirect github.com/go-llsqlite/adapter v0.1.0 // indirect
github.com/go-llsqlite/crawshaw v0.5.3 // indirect github.com/go-llsqlite/crawshaw v0.5.5 // indirect
github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-sourcemap/sourcemap v2.1.4+incompatible // indirect github.com/go-sourcemap/sourcemap v2.1.4+incompatible // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/btree v1.1.2 // indirect github.com/google/btree v1.1.3 // indirect
github.com/google/pprof v0.0.0-20240910150728-a0b0bb1d4134 // indirect github.com/google/pprof v0.0.0-20240910150728-a0b0bb1d4134 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect github.com/gorilla/websocket v1.5.3 // indirect
github.com/huandu/xstrings v1.5.0 // indirect github.com/huandu/xstrings v1.5.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/klauspost/cpuid/v2 v2.2.9 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect github.com/minio/sha256-simd v1.0.1 // indirect
@@ -81,48 +82,46 @@ require (
github.com/multiformats/go-multihash v0.2.3 // indirect github.com/multiformats/go-multihash v0.2.3 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect github.com/multiformats/go-varint v0.0.7 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/pion/datachannel v1.5.8 // indirect github.com/pion/datachannel v1.5.9 // indirect
github.com/pion/dtls/v2 v2.2.12 // indirect github.com/pion/dtls/v3 v3.0.4 // indirect
github.com/pion/ice/v2 v2.3.31 // indirect github.com/pion/ice/v4 v4.0.2 // indirect
github.com/pion/interceptor v0.1.29 // indirect github.com/pion/interceptor v0.1.37 // indirect
github.com/pion/logging v0.2.2 // indirect github.com/pion/logging v0.2.2 // indirect
github.com/pion/mdns v0.0.12 // indirect github.com/pion/mdns/v2 v2.0.7 // indirect
github.com/pion/randutil v0.1.0 // indirect github.com/pion/randutil v0.1.0 // indirect
github.com/pion/rtcp v1.2.14 // indirect github.com/pion/rtcp v1.2.14 // indirect
github.com/pion/rtp v1.8.7 // indirect github.com/pion/rtp v1.8.9 // indirect
github.com/pion/sctp v1.8.19 // indirect github.com/pion/sctp v1.8.33 // indirect
github.com/pion/sdp/v3 v3.0.9 // indirect github.com/pion/sdp/v3 v3.0.9 // indirect
github.com/pion/srtp/v2 v2.0.20 // indirect github.com/pion/srtp/v3 v3.0.4 // indirect
github.com/pion/stun v0.6.1 // indirect github.com/pion/stun/v3 v3.0.0 // indirect
github.com/pion/transport/v2 v2.2.9 // indirect github.com/pion/transport/v3 v3.0.7 // indirect
github.com/pion/turn/v2 v2.1.6 // indirect github.com/pion/turn/v4 v4.0.0 // indirect
github.com/pion/webrtc/v3 v3.2.50 // indirect github.com/pion/webrtc/v4 v4.0.2 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/protolambda/ctxlock v0.1.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/sergi/go-diff v1.1.0 // indirect github.com/sergi/go-diff v1.1.0 // indirect
github.com/skeema/knownhosts v1.2.0 // indirect github.com/skeema/knownhosts v1.2.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/stretchr/testify v1.9.0 // indirect
github.com/tidwall/btree v1.7.0 // indirect github.com/tidwall/btree v1.7.0 // indirect
github.com/wlynxg/anet v0.0.3 // indirect github.com/wlynxg/anet v0.0.5 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect
go.opentelemetry.io/otel v1.28.0 // indirect go.opentelemetry.io/otel v1.32.0 // indirect
go.opentelemetry.io/otel/metric v1.28.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect
go.opentelemetry.io/otel/trace v1.28.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect
golang.org/x/crypto v0.25.0 // indirect golang.org/x/crypto v0.29.0 // indirect
golang.org/x/mod v0.19.0 // indirect golang.org/x/mod v0.22.0 // indirect
golang.org/x/net v0.27.0 // indirect golang.org/x/net v0.31.0 // indirect
golang.org/x/sys v0.22.0 // indirect golang.org/x/sys v0.27.0 // indirect
golang.org/x/text v0.18.0 // indirect golang.org/x/text v0.20.0 // indirect
golang.org/x/time v0.5.0 // indirect golang.org/x/time v0.8.0 // indirect
golang.org/x/tools v0.23.0 // indirect golang.org/x/tools v0.27.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.3.0 // indirect lukechampine.com/blake3 v1.3.0 // indirect
modernc.org/libc v1.55.6 // indirect modernc.org/libc v1.61.0 // indirect
modernc.org/mathutil v1.6.0 // indirect modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect modernc.org/memory v1.8.0 // indirect
modernc.org/sqlite v1.31.1 // indirect modernc.org/sqlite v1.33.1 // indirect
zombiezen.com/go/sqlite v1.3.0 // indirect zombiezen.com/go/sqlite v1.4.0 // indirect
) )
+177 -135
View File
@@ -7,6 +7,8 @@ dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU=
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
@@ -35,26 +37,27 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/anacrolix/chansync v0.5.1 h1:j+R9DtotkXm40VFjZ8rJTSJkg2Gv1ldZt8kl96lyJJ0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/anacrolix/chansync v0.5.1/go.mod h1:DZsatdsdXxD0WiwcGl0nJVwyjCKMDv+knl1q2iBjA2k= github.com/anacrolix/chansync v0.6.0 h1:/aQVvZ1yLRhmqEYrr9dC92JwzNBQ/SNnFi4uk+fTkQY=
github.com/anacrolix/dht/v2 v2.21.1 h1:s1rKkfLLcmBHKv4v/mtMkIeHIEptzEFiB6xVu54+5/o= github.com/anacrolix/chansync v0.6.0/go.mod h1:DZsatdsdXxD0WiwcGl0nJVwyjCKMDv+knl1q2iBjA2k=
github.com/anacrolix/dht/v2 v2.21.1/go.mod h1:SDGC+sEs1pnO2sJGYuhvIis7T8749dDHNfcjtdH4e3g= github.com/anacrolix/dht/v2 v2.22.0 h1:wat5FLdT25vltHsjX377GBrpK9o6L2QVn541bIguCYo=
github.com/anacrolix/dht/v2 v2.22.0/go.mod h1:shbBjhgvezqsJoE+hMo/ezHYQFF18V9jUllNIP5xV9k=
github.com/anacrolix/envpprof v0.0.0-20180404065416-323002cec2fa/go.mod h1:KgHhUaQMc8cC0+cEflSgCFNFbKwi5h54gqtVn8yhP7c= github.com/anacrolix/envpprof v0.0.0-20180404065416-323002cec2fa/go.mod h1:KgHhUaQMc8cC0+cEflSgCFNFbKwi5h54gqtVn8yhP7c=
github.com/anacrolix/envpprof v1.0.0/go.mod h1:KgHhUaQMc8cC0+cEflSgCFNFbKwi5h54gqtVn8yhP7c= github.com/anacrolix/envpprof v1.0.0/go.mod h1:KgHhUaQMc8cC0+cEflSgCFNFbKwi5h54gqtVn8yhP7c=
github.com/anacrolix/envpprof v1.1.0/go.mod h1:My7T5oSqVfEn4MD4Meczkw/f5lSIndGAKu/0SM/rkf4= github.com/anacrolix/envpprof v1.1.0/go.mod h1:My7T5oSqVfEn4MD4Meczkw/f5lSIndGAKu/0SM/rkf4=
github.com/anacrolix/envpprof v1.3.0 h1:WJt9bpuT7A/CDCxPOv/eeZqHWlle/Y0keJUvc6tcJDk= github.com/anacrolix/envpprof v1.4.0 h1:QHeIcrgHcRChhnxR8l6rlaLlRQx9zd7Q2NII6Zbt83w=
github.com/anacrolix/envpprof v1.3.0/go.mod h1:7QIG4CaX1uexQ3tqd5+BRa/9e2D02Wcertl6Yh0jCB0= github.com/anacrolix/envpprof v1.4.0/go.mod h1:7QIG4CaX1uexQ3tqd5+BRa/9e2D02Wcertl6Yh0jCB0=
github.com/anacrolix/generics v0.0.0-20230113004304-d6428d516633/go.mod h1:ff2rHB/joTV03aMSSn/AZNnaIpUw0h3njetGsaXcMy8= github.com/anacrolix/generics v0.0.0-20230113004304-d6428d516633/go.mod h1:ff2rHB/joTV03aMSSn/AZNnaIpUw0h3njetGsaXcMy8=
github.com/anacrolix/generics v0.0.2 h1:UbtD+KntUGxeGYMC4RwhsETieL9ixGdSptJQRhdy7No= github.com/anacrolix/generics v0.0.3-0.20240902042256-7fb2702ef0ca h1:aiiGqSQWjtVNdi8zUMfA//IrM8fPkv2bWwZVPbDe0wg=
github.com/anacrolix/generics v0.0.2/go.mod h1:ff2rHB/joTV03aMSSn/AZNnaIpUw0h3njetGsaXcMy8= github.com/anacrolix/generics v0.0.3-0.20240902042256-7fb2702ef0ca/go.mod h1:MN3ve08Z3zSV/rTuX/ouI4lNdlfTxgdafQJiLzyNRB8=
github.com/anacrolix/go-libutp v1.3.1 h1:idJzreNLl+hNjGC3ZnUOjujEaryeOGgkwHLqSGoige0= 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/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.3.0/go.mod h1:lWvLTqzAnCWPJA08T2HCstZi0L1y2Wyvm3FJgwU9jwU=
github.com/anacrolix/log v0.6.0/go.mod h1:lWvLTqzAnCWPJA08T2HCstZi0L1y2Wyvm3FJgwU9jwU= github.com/anacrolix/log v0.6.0/go.mod h1:lWvLTqzAnCWPJA08T2HCstZi0L1y2Wyvm3FJgwU9jwU=
github.com/anacrolix/log v0.13.1/go.mod h1:D4+CvN8SnruK6zIFS/xPoRJmtvtnxs+CSfDQ+BFxZ68= github.com/anacrolix/log v0.13.1/go.mod h1:D4+CvN8SnruK6zIFS/xPoRJmtvtnxs+CSfDQ+BFxZ68=
github.com/anacrolix/log v0.14.2/go.mod h1:1OmJESOtxQGNMlUO5rcv96Vpp9mfMqXXbe2RdinFLdY= github.com/anacrolix/log v0.14.2/go.mod h1:1OmJESOtxQGNMlUO5rcv96Vpp9mfMqXXbe2RdinFLdY=
github.com/anacrolix/log v0.15.2 h1:LTSf5Wm6Q4GNWPFMBP7NPYV6UBVZzZLKckL+/Lj72Oo= github.com/anacrolix/log v0.16.0 h1:DSuyb5kAJwl3Y0X1TRcStVrTS9ST9b0BHW+7neE4Xho=
github.com/anacrolix/log v0.15.2/go.mod h1:m0poRtlr41mriZlXBQ9SOVZ8yZBkLjOkDhd5Li5pITA= github.com/anacrolix/log v0.16.0/go.mod h1:m0poRtlr41mriZlXBQ9SOVZ8yZBkLjOkDhd5Li5pITA=
github.com/anacrolix/lsan v0.0.0-20211126052245-807000409a62 h1:P04VG6Td13FHMgS5ZBcJX23NPC/fiC4cp9bXwYujdYM= github.com/anacrolix/lsan v0.0.0-20211126052245-807000409a62 h1:P04VG6Td13FHMgS5ZBcJX23NPC/fiC4cp9bXwYujdYM=
github.com/anacrolix/lsan v0.0.0-20211126052245-807000409a62/go.mod h1:66cFKPCO7Sl4vbFnAaSq7e4OXtdMhRSBagJGWgmpJbM= github.com/anacrolix/lsan v0.0.0-20211126052245-807000409a62/go.mod h1:66cFKPCO7Sl4vbFnAaSq7e4OXtdMhRSBagJGWgmpJbM=
github.com/anacrolix/missinggo v0.0.0-20180725070939-60ef2fbf63df/go.mod h1:kwGiTUTZ0+p4vAz3VbAI5a30t2YbvemcmspjKwrAz5s= github.com/anacrolix/missinggo v0.0.0-20180725070939-60ef2fbf63df/go.mod h1:kwGiTUTZ0+p4vAz3VbAI5a30t2YbvemcmspjKwrAz5s=
@@ -67,25 +70,26 @@ github.com/anacrolix/missinggo/perf v1.0.0 h1:7ZOGYziGEBytW49+KmYGTaNfnwUqP1HBsy
github.com/anacrolix/missinggo/perf v1.0.0/go.mod h1:ljAFWkBuzkO12MQclXzZrosP5urunoLS0Cbvb4V0uMQ= github.com/anacrolix/missinggo/perf v1.0.0/go.mod h1:ljAFWkBuzkO12MQclXzZrosP5urunoLS0Cbvb4V0uMQ=
github.com/anacrolix/missinggo/v2 v2.2.0/go.mod h1:o0jgJoYOyaoYQ4E2ZMISVa9c88BbUBVQQW4QeRkNCGY= github.com/anacrolix/missinggo/v2 v2.2.0/go.mod h1:o0jgJoYOyaoYQ4E2ZMISVa9c88BbUBVQQW4QeRkNCGY=
github.com/anacrolix/missinggo/v2 v2.5.1/go.mod h1:WEjqh2rmKECd0t1VhQkLGTdIWXO6f6NLjp5GlMZ+6FA= github.com/anacrolix/missinggo/v2 v2.5.1/go.mod h1:WEjqh2rmKECd0t1VhQkLGTdIWXO6f6NLjp5GlMZ+6FA=
github.com/anacrolix/missinggo/v2 v2.7.3 h1:Ee//CmZBMadeNiYB/hHo9ly2PFOEZ4Fhsbnug3rDAIE=
github.com/anacrolix/missinggo/v2 v2.7.3/go.mod h1:mIEtp9pgaXqt8VQ3NQxFOod/eQ1H0D1XsZzKUQfwtac= github.com/anacrolix/missinggo/v2 v2.7.3/go.mod h1:mIEtp9pgaXqt8VQ3NQxFOod/eQ1H0D1XsZzKUQfwtac=
github.com/anacrolix/missinggo/v2 v2.8.0 h1:6pGnVOlR6TWL9JM5Msyezij8YHU3+oHO7r82Eql/kpA=
github.com/anacrolix/missinggo/v2 v2.8.0/go.mod h1:vVO5FEziQm+NFmJesc7StpkquZk+WJFCaL0Wp//2sa0=
github.com/anacrolix/mmsg v0.0.0-20180515031531-a4a3ba1fc8bb/go.mod h1:x2/ErsYUmT77kezS63+wzZp8E3byYB0gzirM/WMBLfw= github.com/anacrolix/mmsg v0.0.0-20180515031531-a4a3ba1fc8bb/go.mod h1:x2/ErsYUmT77kezS63+wzZp8E3byYB0gzirM/WMBLfw=
github.com/anacrolix/mmsg v1.0.0 h1:btC7YLjOn29aTUAExJiVUhQOuf/8rhm+/nWCMAnL3Hg= github.com/anacrolix/mmsg v1.1.1 h1:4ce/3I5kM7qSF6T5A8MOmDCfac3UqYlk5Bzh5XsWebM=
github.com/anacrolix/mmsg v1.0.0/go.mod h1:x8kRaJY/dCrY9Al0PEcj1mb/uFHwP6GCJ9fLl4thEPc= github.com/anacrolix/mmsg v1.1.1/go.mod h1:lPCXEN1eDDQtKktdKEzdw+roswx6wWPpeXAl/WpWVDU=
github.com/anacrolix/multiless v0.3.1-0.20221221005021-2d12701f83f7 h1:lOtCD+LzoD1g7bowhYJNR++uV+FyY5bTZXKwnPex9S8= github.com/anacrolix/multiless v0.4.0 h1:lqSszHkliMsZd2hsyrDvHOw4AbYWa+ijQ66LzbjqWjM=
github.com/anacrolix/multiless v0.3.1-0.20221221005021-2d12701f83f7/go.mod h1:zJv1JF9AqdZiHwxqPgjuOZDGWER6nyE48WBCi/OOrMM= github.com/anacrolix/multiless v0.4.0/go.mod h1:zJv1JF9AqdZiHwxqPgjuOZDGWER6nyE48WBCi/OOrMM=
github.com/anacrolix/stm v0.2.0/go.mod h1:zoVQRvSiGjGoTmbM0vSLIiaKjWtNPeTvXUSdJQA4hsg= github.com/anacrolix/stm v0.2.0/go.mod h1:zoVQRvSiGjGoTmbM0vSLIiaKjWtNPeTvXUSdJQA4hsg=
github.com/anacrolix/stm v0.5.0 h1:9df1KBpttF0TzLgDq51Z+TEabZKMythqgx89f1FQJt8= github.com/anacrolix/stm v0.5.0 h1:9df1KBpttF0TzLgDq51Z+TEabZKMythqgx89f1FQJt8=
github.com/anacrolix/stm v0.5.0/go.mod h1:MOwrSy+jCm8Y7HYfMAwPj7qWVu7XoVvjOiYwJmpeB/M= github.com/anacrolix/stm v0.5.0/go.mod h1:MOwrSy+jCm8Y7HYfMAwPj7qWVu7XoVvjOiYwJmpeB/M=
github.com/anacrolix/sync v0.0.0-20180808010631-44578de4e778/go.mod h1:s735Etp3joe/voe2sdaXLcqDdJSay1O0OPnM0ystjqk= github.com/anacrolix/sync v0.0.0-20180808010631-44578de4e778/go.mod h1:s735Etp3joe/voe2sdaXLcqDdJSay1O0OPnM0ystjqk=
github.com/anacrolix/sync v0.3.0/go.mod h1:BbecHL6jDSExojhNtgTFSBcdGerzNc64tz3DCOj/I0g= github.com/anacrolix/sync v0.3.0/go.mod h1:BbecHL6jDSExojhNtgTFSBcdGerzNc64tz3DCOj/I0g=
github.com/anacrolix/sync v0.5.1 h1:FbGju6GqSjzVoTgcXTUKkF041lnZkG5P0C3T5RL3SGc= github.com/anacrolix/sync v0.5.3 h1:iyMUiRRzTnD15+YQYxmDoobGdIbmUxdD4TNO67aCMYI=
github.com/anacrolix/sync v0.5.1/go.mod h1:BbecHL6jDSExojhNtgTFSBcdGerzNc64tz3DCOj/I0g= github.com/anacrolix/sync v0.5.3/go.mod h1:S51SPBetDsINK/KSNJtZkfM78s5rMeiO11/GNK6Rmh4=
github.com/anacrolix/tagflag v0.0.0-20180109131632-2146c8d41bf0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw= 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.0.0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw=
github.com/anacrolix/tagflag v1.1.0/go.mod h1:Scxs9CV10NQatSmbyjqmqmeQNwGzlNe0CMUMIxqHIG8= github.com/anacrolix/tagflag v1.1.0/go.mod h1:Scxs9CV10NQatSmbyjqmqmeQNwGzlNe0CMUMIxqHIG8=
github.com/anacrolix/torrent v1.56.1 h1:QeJMOP0NuhpQ5dATsOqEL0vUO85aPMNMGP2FACNt0Eg= github.com/anacrolix/torrent v1.57.2-0.20241017235801-4d8437a05621 h1:h8YDIq0VGMrFVBqdd1FgBzF6AXbSaTyosk40++Ub9dE=
github.com/anacrolix/torrent v1.56.1/go.mod h1:5DMHbeIM1TuC5wTQ99XieKKLiYZYz6iB2lyZpKZEr6w= github.com/anacrolix/torrent v1.57.2-0.20241017235801-4d8437a05621/go.mod h1:n3SjHIE8oHXeH0Px0d5FXQ7cU4IgbEfTroen6B9KWJk=
github.com/anacrolix/upnp v0.1.4 h1:+2t2KA6QOhm/49zeNyeVwDu1ZYS9dB9wfxyVvh/wk7U= github.com/anacrolix/upnp v0.1.4 h1:+2t2KA6QOhm/49zeNyeVwDu1ZYS9dB9wfxyVvh/wk7U=
github.com/anacrolix/upnp v0.1.4/go.mod h1:Qyhbqo69gwNWvEk1xNTXsS5j7hMHef9hdr984+9fIic= github.com/anacrolix/upnp v0.1.4/go.mod h1:Qyhbqo69gwNWvEk1xNTXsS5j7hMHef9hdr984+9fIic=
github.com/anacrolix/utp v0.2.0 h1:65Cdmr6q9WSw2KsM+rtJFu7rqDzLl2bdysf4KlNPcFI= github.com/anacrolix/utp v0.2.0 h1:65Cdmr6q9WSw2KsM+rtJFu7rqDzLl2bdysf4KlNPcFI=
@@ -104,8 +108,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bits-and-blooms/bitset v1.12.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bits-and-blooms/bitset v1.12.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.15.0 h1:DiCRMscZsGyYePE9AR3sVhKqUXCt5IZvkX5AfAc5xLQ=
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bits-and-blooms/bitset v1.15.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/bradfitz/iter v0.0.0-20140124041915-454541ec3da2/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo= github.com/bradfitz/iter v0.0.0-20140124041915-454541ec3da2/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo=
github.com/bradfitz/iter v0.0.0-20190303215204-33e6a9893b0c/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo= github.com/bradfitz/iter v0.0.0-20190303215204-33e6a9893b0c/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo=
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 h1:GKTyiRCL6zVf5wWaqKnf+7Qs6GbEPfd4iMOitWzXJx8= github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 h1:GKTyiRCL6zVf5wWaqKnf+7Qs6GbEPfd4iMOitWzXJx8=
@@ -114,6 +118,9 @@ github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7N
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY=
github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic=
github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
@@ -125,8 +132,6 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo= github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dop251/goja v0.0.0-20240806095544-3491d4a58fbe h1:jwFJkgsdelB87ohlXaAGSd05Cb5ALDFa9iW9IGRHcRM=
github.com/dop251/goja v0.0.0-20240806095544-3491d4a58fbe/go.mod h1:DF+w/nLMIkvRpyhd/0K+Okbh3fVZBtXLwRtS/ccAa5w=
github.com/dop251/goja v0.0.0-20240919115326-6c7d1df7ff05 h1:oK4+QcKsczZjHYTHD0JAdkvq5w74JEkG95J0XNBx/BI= github.com/dop251/goja v0.0.0-20240919115326-6c7d1df7ff05 h1:oK4+QcKsczZjHYTHD0JAdkvq5w74JEkG95J0XNBx/BI=
github.com/dop251/goja v0.0.0-20240919115326-6c7d1df7ff05/go.mod h1:MxLav0peU43GgvwVgNbLAj1s/bSGboKkhuULvq/7hx4= github.com/dop251/goja v0.0.0-20240919115326-6c7d1df7ff05/go.mod h1:MxLav0peU43GgvwVgNbLAj1s/bSGboKkhuULvq/7hx4=
github.com/dop251/goja_nodejs v0.0.0-20240728170619-29b559befffc h1:MKYt39yZJi0Z9xEeRmDX2L4ocE0ETKcHKw6MVL3R+co= github.com/dop251/goja_nodejs v0.0.0-20240728170619-29b559befffc h1:MKYt39yZJi0Z9xEeRmDX2L4ocE0ETKcHKw6MVL3R+co=
@@ -138,8 +143,8 @@ github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+m
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= github.com/edsrzf/mmap-go v1.2.0 h1:hXLYlkbaPzt1SaQk+anYwKSRNhufIDCchSPkUD6dD84=
github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/edsrzf/mmap-go v1.2.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819 h1:RIB4cRk+lBqKK3Oy0r2gRX4ui7tuhiZq2SuTtTCi0/0= github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819 h1:RIB4cRk+lBqKK3Oy0r2gRX4ui7tuhiZq2SuTtTCi0/0=
github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
@@ -169,17 +174,21 @@ github.com/go-git/go-git/v5 v5.8.1 h1:Zo79E4p7TRk0xoRgMq0RShiTHGKcKI4+DI6BfJc/Q+
github.com/go-git/go-git/v5 v5.8.1/go.mod h1:FHFuoD6yGz5OSKEBK+aWN9Oah0q54Jxl0abmj6GnqAo= github.com/go-git/go-git/v5 v5.8.1/go.mod h1:FHFuoD6yGz5OSKEBK+aWN9Oah0q54Jxl0abmj6GnqAo=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-llsqlite/adapter v0.1.0 h1:wGSQNsu/rtYeu/lqZNZQMjwUdEF3OW66xTLvsFwJQUw= github.com/go-llsqlite/adapter v0.1.0 h1:wGSQNsu/rtYeu/lqZNZQMjwUdEF3OW66xTLvsFwJQUw=
github.com/go-llsqlite/adapter v0.1.0/go.mod h1:DADrR88ONKPPeSGjFp5iEN55Arx3fi2qXZeKCYDpbmU= github.com/go-llsqlite/adapter v0.1.0/go.mod h1:DADrR88ONKPPeSGjFp5iEN55Arx3fi2qXZeKCYDpbmU=
github.com/go-llsqlite/crawshaw v0.5.3 h1:PmHXJjjxHodMoFWs3dEcJ1I1m9a+J0TCMNiHjGbXy1o= github.com/go-llsqlite/crawshaw v0.5.5 h1:sXnRkiV26MBv++lbPbzp+ZzFcTqzVMxftO8yHyFvwUA=
github.com/go-llsqlite/crawshaw v0.5.3/go.mod h1:/YJdV7uBQaYDE0fwe4z3wwJIZBJxdYzd38ICggWqtaE= github.com/go-llsqlite/crawshaw v0.5.5/go.mod h1:/YJdV7uBQaYDE0fwe4z3wwJIZBJxdYzd38ICggWqtaE=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
github.com/go-sourcemap/sourcemap v2.1.4+incompatible h1:a+iTbH5auLKxaNwQFg0B+TCYl6lbukKPc7b5x0n1s6Q= github.com/go-sourcemap/sourcemap v2.1.4+incompatible h1:a+iTbH5auLKxaNwQFg0B+TCYl6lbukKPc7b5x0n1s6Q=
github.com/go-sourcemap/sourcemap v2.1.4+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sourcemap/sourcemap v2.1.4+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
@@ -200,25 +209,29 @@ github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:x
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
github.com/google/pprof v0.0.0-20240910150728-a0b0bb1d4134 h1:c5FlPPgxOn7kJz3VoPLkQYQXGBS3EklQ4Zfi57uOuqQ= github.com/google/pprof v0.0.0-20240910150728-a0b0bb1d4134 h1:c5FlPPgxOn7kJz3VoPLkQYQXGBS3EklQ4Zfi57uOuqQ=
github.com/google/pprof v0.0.0-20240910150728-a0b0bb1d4134/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/pprof v0.0.0-20240910150728-a0b0bb1d4134/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@@ -241,21 +254,29 @@ github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbc
github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4=
github.com/huandu/xstrings v1.3.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
@@ -280,6 +301,7 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
@@ -297,6 +319,7 @@ github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsC
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
@@ -306,50 +329,38 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pion/datachannel v1.5.8 h1:ph1P1NsGkazkjrvyMfhRBUAWMxugJjq2HfQifaOoSNo= github.com/pion/datachannel v1.5.9 h1:LpIWAOYPyDrXtU+BW7X0Yt/vGtYxtXQ8ql7dFfYUVZA=
github.com/pion/datachannel v1.5.8/go.mod h1:PgmdpoaNBLX9HNzNClmdki4DYW5JtI7Yibu8QzbL3tI= github.com/pion/datachannel v1.5.9/go.mod h1:kDUuk4CU4Uxp82NH4LQZbISULkX/HtzKa4P7ldf9izE=
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= github.com/pion/dtls/v3 v3.0.4 h1:44CZekewMzfrn9pmGrj5BNnTMDCFwr+6sLH+cCuLM7U=
github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk= github.com/pion/dtls/v3 v3.0.4/go.mod h1:R373CsjxWqNPf6MEkfdy3aSe9niZvL/JaKlGeFphtMg=
github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= github.com/pion/ice/v4 v4.0.2 h1:1JhBRX8iQLi0+TfcavTjPjI6GO41MFn4CeTBX+Y9h5s=
github.com/pion/ice/v2 v2.3.31 h1:qag/YqiOn5qPi0kgeVdsytxjx8szuriWSIeXKu8dDQc= github.com/pion/ice/v4 v4.0.2/go.mod h1:DCdqyzgtsDNYN6/3U8044j3U7qsJ9KFJC92VnOWHvXg=
github.com/pion/ice/v2 v2.3.31/go.mod h1:8fac0+qftclGy1tYd/nfwfHC729BLaxtVqMdMVCAVPU= github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI=
github.com/pion/interceptor v0.1.29 h1:39fsnlP1U8gw2JzOFWdfCU82vHvhW9o0rZnZF56wF+M= github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y=
github.com/pion/interceptor v0.1.29/go.mod h1:ri+LGNjRUc5xUNtDEPzfdkmSqISixVTBF/z/Zms/6T4=
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
github.com/pion/mdns v0.0.12 h1:CiMYlY+O0azojWDmxdNr7ADGrnZ+V6Ilfner+6mSVK8= github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM=
github.com/pion/mdns v0.0.12/go.mod h1:VExJjv8to/6Wqm1FXK+Ii/Z9tsVk/F5sD/N70cnYFbk= github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA=
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
github.com/pion/rtcp v1.2.12/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4=
github.com/pion/rtcp v1.2.14 h1:KCkGV3vJ+4DAJmvP0vaQShsb0xkRfWkO540Gy102KyE= github.com/pion/rtcp v1.2.14 h1:KCkGV3vJ+4DAJmvP0vaQShsb0xkRfWkO540Gy102KyE=
github.com/pion/rtcp v1.2.14/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4= github.com/pion/rtcp v1.2.14/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4=
github.com/pion/rtp v1.8.3/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= github.com/pion/rtp v1.8.9 h1:E2HX740TZKaqdcPmf4pw6ZZuG8u5RlMMt+l3dxeu6Wk=
github.com/pion/rtp v1.8.7 h1:qslKkG8qxvQ7hqaxkmL7Pl0XcUm+/Er7nMnu6Vq+ZxM= github.com/pion/rtp v1.8.9/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU=
github.com/pion/rtp v1.8.7/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= github.com/pion/sctp v1.8.33 h1:dSE4wX6uTJBcNm8+YlMg7lw1wqyKHggsP5uKbdj+NZw=
github.com/pion/sctp v1.8.19 h1:2CYuw+SQ5vkQ9t0HdOPccsCz1GQMDuVy5PglLgKVBW8= github.com/pion/sctp v1.8.33/go.mod h1:beTnqSzewI53KWoG3nqB282oDMGrhNxBdb+JZnkCwRM=
github.com/pion/sctp v1.8.19/go.mod h1:P6PbDVA++OJMrVNg2AL3XtYHV4uD6dvfyOovCgMs0PE=
github.com/pion/sdp/v3 v3.0.9 h1:pX++dCHoHUwq43kuwf3PyJfHlwIj4hXA7Vrifiq0IJY= github.com/pion/sdp/v3 v3.0.9 h1:pX++dCHoHUwq43kuwf3PyJfHlwIj4hXA7Vrifiq0IJY=
github.com/pion/sdp/v3 v3.0.9/go.mod h1:B5xmvENq5IXJimIO4zfp6LAe1fD9N+kFv+V/1lOdz8M= github.com/pion/sdp/v3 v3.0.9/go.mod h1:B5xmvENq5IXJimIO4zfp6LAe1fD9N+kFv+V/1lOdz8M=
github.com/pion/srtp/v2 v2.0.20 h1:HNNny4s+OUmG280ETrCdgFndp4ufx3/uy85EawYEhTk= github.com/pion/srtp/v3 v3.0.4 h1:2Z6vDVxzrX3UHEgrUyIGM4rRouoC7v+NiF1IHtp9B5M=
github.com/pion/srtp/v2 v2.0.20/go.mod h1:0KJQjA99A6/a0DOVTu1PhDSw0CXF2jTkqOoMg3ODqdA= github.com/pion/srtp/v3 v3.0.4/go.mod h1:1Jx3FwDoxpRaTh1oRV8A/6G1BnFL+QI82eK4ms8EEJQ=
github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw=
github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU=
github.com/pion/transport v0.13.1 h1:/UH5yLeQtwm2VZIPjxwnNFxjS4DFhyLfS4GlfuKUzfA= github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0=
github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
github.com/pion/transport/v2 v2.2.3/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM=
github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA=
github.com/pion/transport/v2 v2.2.8/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E= github.com/pion/webrtc/v4 v4.0.2 h1:fBwm5/hqSUybrCWl0DDBSTDrpbkcgkqpeLmXw9CsBQA=
github.com/pion/transport/v2 v2.2.9 h1:WEDygVovkJlV2CCunM9KS2kds+kcl7zdIefQA5y/nkE= github.com/pion/webrtc/v4 v4.0.2/go.mod h1:moylBT2A4dNoEaYBCdV1nThM3TLwRHzWszIG+eSPaqQ=
github.com/pion/transport/v2 v2.2.9/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E=
github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0=
github.com/pion/transport/v3 v3.0.2 h1:r+40RJR25S9w3jbA6/5uEPTzcdn7ncyU44RWCbHkLg4=
github.com/pion/transport/v3 v3.0.2/go.mod h1:nIToODoOlb5If2jF9y2Igfx3PFYWfuXi37m0IlWa/D0=
github.com/pion/turn/v2 v2.1.3/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY=
github.com/pion/turn/v2 v2.1.6 h1:Xr2niVsiPTB0FPtt+yAWKFUkU1eotQbGgpTIld4x1Gc=
github.com/pion/turn/v2 v2.1.6/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY=
github.com/pion/webrtc/v3 v3.2.50 h1:C/rwL2mBfCxHv6tlLzDAO3krJpQXfVx8A8WHnGJ2j34=
github.com/pion/webrtc/v3 v3.2.50/go.mod h1:dytYYoSBy7ZUWhJMbndx9UckgYvzNAfL7xgVnrIKxqo=
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
@@ -363,6 +374,8 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -370,18 +383,26 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/protolambda/ctxlock v0.1.0 h1:rCUY3+vRdcdZXqT07iXgyr744J2DU2LCBIXowYAjBCE=
github.com/protolambda/ctxlock v0.1.0/go.mod h1:vefhX6rIZH8rsg5ZpOJfEDYQOppZi19SfPiGOFrNnwM=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529 h1:18kd+8ZUlt/ARXhljq+14TwAoKa61q6dX8jtwOf6DH8= github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529 h1:18kd+8ZUlt/ARXhljq+14TwAoKa61q6dX8jtwOf6DH8=
github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529/go.mod h1:qe5TWALJ8/a1Lqznoc5BDHpYX/8HU60Hm2AwRmqzxqA= github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529/go.mod h1:qe5TWALJ8/a1Lqznoc5BDHpYX/8HU60Hm2AwRmqzxqA=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
@@ -393,6 +414,7 @@ github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJCpM= github.com/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJCpM=
github.com/skeema/knownhosts v1.2.0/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo= github.com/skeema/knownhosts v1.2.0/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo=
@@ -417,7 +439,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/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.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
@@ -426,57 +447,55 @@ github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EU
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/virtuald/go-paniclog v0.0.0-20190812204905-43a7fa316459 h1:x9pIfbdIjnw+Ylb2vE27Gtqb7BDmfR+nLcJwvbJh98U=
github.com/virtuald/go-paniclog v0.0.0-20190812204905-43a7fa316459/go.mod h1:nFvuG3SWu3VWqobG3cX8nt57wXU0OOFapeCs/8axIuM=
github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= 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/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/wlynxg/anet v0.0.3 h1:PvR53psxFXstc12jelG6f1Lv4MWqE0tI76/hHGjh9rg= github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/xiaoqidun/setft v0.0.0-20220310121541-be86327699ad h1:QtuWk6dsrNXc/ugwCBEN0jG52q/4tXRzMvZm4fH6T9g= github.com/xiaoqidun/setft v0.0.0-20220310121541-be86327699ad h1:QtuWk6dsrNXc/ugwCBEN0jG52q/4tXRzMvZm4fH6T9g=
github.com/xiaoqidun/setft v0.0.0-20220310121541-be86327699ad/go.mod h1:Jj8p9bgKGTPQ+M8CdUMS9p7Mmdoxa3OAcAjJQBu0CcI= github.com/xiaoqidun/setft v0.0.0-20220310121541-be86327699ad/go.mod h1:Jj8p9bgKGTPQ+M8CdUMS9p7Mmdoxa3OAcAjJQBu0CcI=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=
go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= 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.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/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-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20220428152302-39d4317da171/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= golang.org/x/exp v0.0.0-20220428152302-39d4317da171/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 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-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-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/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.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/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-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -488,6 +507,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@@ -496,12 +517,8 @@ golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 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/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= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -510,11 +527,13 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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-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-20201207232520-09787c993a3a/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-20210220032951-036812b2e83c/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-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -527,12 +546,18 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -541,25 +566,16 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -568,15 +584,10 @@ 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.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -584,11 +595,12 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o=
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -607,6 +619,8 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -622,6 +636,7 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
@@ -631,29 +646,56 @@ honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
modernc.org/cc/v3 v3.37.0/go.mod h1:vtL+3mdHx/wcj3iEGz84rQa8vEqR6XM84v5Lcvfph20=
modernc.org/cc/v3 v3.38.1/go.mod h1:vtL+3mdHx/wcj3iEGz84rQa8vEqR6XM84v5Lcvfph20=
modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ= modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ=
modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
modernc.org/ccgo/v4 v4.20.5 h1:s04akhT2dysD0DFOlv9fkQ6oUTLPYgMnnDk9oaqjszM= modernc.org/ccgo/v3 v3.0.0-20220904174949-82d86e1b6d56/go.mod h1:YSXjPL62P2AMSxBphRHPn7IkzhVHqkvOnRKAKh+W6ZI=
modernc.org/ccgo/v4 v4.20.5/go.mod h1:fYXClPUMWxWaz1Xj5sHbzW/ZENEFeuHLToqBxUk41nE= modernc.org/ccgo/v3 v3.0.0-20220910160915-348f15de615a/go.mod h1:8p47QxPkdugex9J4n9P2tLZ9bK01yngIVp00g4nomW0=
modernc.org/ccgo/v3 v3.16.13-0.20221017192402-261537637ce8/go.mod h1:fUB3Vn0nVPReA+7IG7yZDfjv1TMWjhQP8gCxrFAtL5g=
modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
modernc.org/ccgo/v4 v4.21.0 h1:kKPI3dF7RIag8YcToh5ZwDcVMIv6VGa0ED5cvh0LMW4=
modernc.org/ccgo/v4 v4.21.0/go.mod h1:h6kt6H/A2+ew/3MW/p6KEoQmrq/i3pr0J/SiwiaF/g0=
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
modernc.org/gc/v2 v2.4.3 h1:Ik4ZcMbC7aY4ZDPUhzXVXi7GMub9QcXLTfXn3mWpNw8= modernc.org/gc/v2 v2.5.0 h1:bJ9ChznK1L1mUtAQtxi0wi5AtAs5jQuw4PrPHO5pb6M=
modernc.org/gc/v2 v2.4.3/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= modernc.org/gc/v2 v2.5.0/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
modernc.org/libc v1.55.6 h1:WfOvqnRFSjVT3WZIAVzGkKcYSk/toAXXnPAMWnTKBZc= modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v1.55.6/go.mod h1:JXguUpMkbw1gknxspNE9XaG+kk9hDAAnBxpA6KGLiyA= modernc.org/libc v1.17.4/go.mod h1:WNg2ZH56rDEwdropAJeZPQkXmDwh+JCA1s/htl6r2fA=
modernc.org/libc v1.18.0/go.mod h1:vj6zehR5bfc98ipowQOM2nIDUZnVew/wNC/2tOGS+q0=
modernc.org/libc v1.19.0/go.mod h1:ZRfIaEkgrYgZDl6pa4W39HgN5G/yDW+NRmNKZBDFrk0=
modernc.org/libc v1.20.3/go.mod h1:ZRfIaEkgrYgZDl6pa4W39HgN5G/yDW+NRmNKZBDFrk0=
modernc.org/libc v1.21.4/go.mod h1:przBsL5RDOZajTVslkugzLBj1evTue36jEomFQOoYuI=
modernc.org/libc v1.21.5/go.mod h1:przBsL5RDOZajTVslkugzLBj1evTue36jEomFQOoYuI=
modernc.org/libc v1.61.0 h1:eGFcvWpqlnoGwzZeZe3PWJkkKbM/3SUGyk1DVZQ0TpE=
modernc.org/libc v1.61.0/go.mod h1:DvxVX89wtGTu+r72MLGhygpfi3aUGgZRdAYGCAVVud0=
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
modernc.org/memory v1.3.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
modernc.org/sqlite v1.31.1 h1:XVU0VyzxrYHlBhIs1DiEgSl0ZtdnPtbLVy8hSkzxGrs= modernc.org/sqlite v1.20.0/go.mod h1:EsYz8rfOvLCiYTy5ZFsOYzoCcRMu98YYkwAcCw5YIYw=
modernc.org/sqlite v1.31.1/go.mod h1:UqoylwmTb9F+IqXERT8bW9zzOWN8qwAIcLdzeBZs4hA= modernc.org/sqlite v1.33.1 h1:trb6Z3YYoeM9eDL1O8do81kP+0ejv+YzgyFo+Gwy0nM=
modernc.org/sqlite v1.33.1/go.mod h1:pXV2xHxhzXZsgT/RtTFAPY6JJDEvOTcTdwADQCCWD4k=
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
modernc.org/tcl v1.15.0/go.mod h1:xRoGotBZ6dU+Zo2tca+2EqVEeMmOUBzHnhIwq4YrVnE=
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
zombiezen.com/go/sqlite v1.3.0 h1:98g1gnCm+CNz6AuQHu0gqyw7gR2WU3O3PJufDOStpUs= modernc.org/z v1.7.0/go.mod h1:hVdgNMh8ggTuRG1rGU8x+xGRFfiQUIAw0ZqlPy8+HyQ=
zombiezen.com/go/sqlite v1.3.0/go.mod h1:yRl27//s/9aXU3RWs8uFQwjkTG9gYNGEls6+6SvrclY= zombiezen.com/go/sqlite v0.12.0/go.mod h1:RKdRR9xoQDSnB47yy7G4PtrjGZJtupb/SyEbJZLaRes=
zombiezen.com/go/sqlite v1.4.0 h1:N1s3RIljwtp4541Y8rM880qgGIgq3fTD2yks1xftnKU=
zombiezen.com/go/sqlite v1.4.0/go.mod h1:0w9F1DN9IZj9AcLS9YDKMboubCACkwYCGkzoy3eG5ik=
+26 -7
View File
@@ -11,7 +11,9 @@ import (
"github.com/GopeedLab/gopeed/pkg/util" "github.com/GopeedLab/gopeed/pkg/util"
"github.com/anacrolix/torrent" "github.com/anacrolix/torrent"
"github.com/anacrolix/torrent/metainfo" "github.com/anacrolix/torrent/metainfo"
"io"
"net/url" "net/url"
"os"
"path/filepath" "path/filepath"
"strings" "strings"
"sync" "sync"
@@ -359,17 +361,34 @@ func (f *Fetcher) addTorrent(req *base.Request, fromUpload bool) (err error) {
schema := util.ParseSchema(req.URL) schema := util.ParseSchema(req.URL)
if schema == "MAGNET" { if schema == "MAGNET" {
f.torrent, err = client.AddMagnet(req.URL) f.torrent, err = client.AddMagnet(req.URL)
} else if schema == "DATA" { } else {
_, data := util.ParseDataUri(req.URL) var reader io.Reader
buf := bytes.NewBuffer(data) if schema == "FILE" {
fileUrl, _ := url.Parse(req.URL)
filePath := fileUrl.Path[1:]
reader, err = os.Open(filePath)
if err != nil {
return
}
} else if schema == "DATA" {
_, data := util.ParseDataUri(req.URL)
reader = bytes.NewBuffer(data)
} else {
reader, err = os.Open(req.URL)
if err != nil {
return
}
defer reader.(io.Closer).Close()
}
var metaInfo *metainfo.MetaInfo var metaInfo *metainfo.MetaInfo
metaInfo, err = metainfo.Load(buf) metaInfo, err = metainfo.Load(reader)
if err != nil { // Hotfix for https://github.com/anacrolix/torrent/issues/992, ignore "expected EOF" error
// TODO remove this after the issue is fixed
if err != nil && !strings.Contains(err.Error(), "expected EOF") {
return err return err
} }
f.torrent, err = client.AddTorrent(metaInfo) f.torrent, err = client.AddTorrent(metaInfo)
} else {
f.torrent, err = client.AddTorrentFromFile(req.URL)
} }
if err != nil { if err != nil {
return return
+22 -2
View File
@@ -11,6 +11,7 @@ import (
gohttp "net/http" gohttp "net/http"
"net/url" "net/url"
"os" "os"
"path/filepath"
"reflect" "reflect"
"testing" "testing"
) )
@@ -96,7 +97,7 @@ func doResolve(t *testing.T, fetcher fetcher.Fetcher) {
Hash: "8a55cfbd5ca5d11507364765936c4f9e55b253ed", Hash: "8a55cfbd5ca5d11507364765936c4f9e55b253ed",
} }
if !reflect.DeepEqual(want, fetcher.Meta().Res) { if !reflect.DeepEqual(want, fetcher.Meta().Res) {
t.Errorf("Resolve() got = %v, want %v", fetcher.Meta().Res, want) t.Errorf("Resolve Single File Resolve() got = %v, want %v", fetcher.Meta().Res, want)
} }
}) })
@@ -136,10 +137,29 @@ func doResolve(t *testing.T, fetcher fetcher.Fetcher) {
Hash: "ccbc92b0cd8deec16a2ef4be242a8c9243b1cedb", Hash: "ccbc92b0cd8deec16a2ef4be242a8c9243b1cedb",
} }
if !reflect.DeepEqual(want, fetcher.Meta().Res) { if !reflect.DeepEqual(want, fetcher.Meta().Res) {
t.Errorf("Resolve() got = %v, want %v", fetcher.Meta().Res, want) t.Errorf("Resolve Multi Files Resolve() got = %v, want %v", fetcher.Meta().Res, want)
} }
}) })
t.Run("Resolve Unclean Torrent", func(t *testing.T) {
err := fetcher.Resolve(&base.Request{
URL: "./testdata/test.unclean.torrent",
})
if err != nil {
t.Errorf("Resolve Unclean Torrent Resolve() got = %v, want nil", err)
}
})
t.Run("Resolve file scheme Torrent", func(t *testing.T) {
file, _ := filepath.Abs("./testdata/test.unclean.torrent")
uri := "file:///" + file
err := fetcher.Resolve(&base.Request{
URL: uri,
})
if err != nil {
t.Errorf("Resolve file scheme Torrent Resolve() got = %v, want nil", err)
}
})
} }
func TestFetcherManager_ParseName(t *testing.T) { func TestFetcherManager_ParseName(t *testing.T) {
+2 -1
View File
@@ -3,6 +3,7 @@
package bt package bt
import ( import (
"context"
"fmt" "fmt"
"github.com/anacrolix/torrent/storage" "github.com/anacrolix/torrent/storage"
"io" "io"
@@ -53,7 +54,7 @@ func (fs fileClientImpl) Close() error {
return fs.opts.PieceCompletion.Close() return fs.opts.PieceCompletion.Close()
} }
func (fs fileClientImpl) OpenTorrent(info *metainfo.Info, infoHash metainfo.Hash) (_ storage.TorrentImpl, err error) { func (fs fileClientImpl) OpenTorrent(ctx context.Context, info *metainfo.Info, infoHash metainfo.Hash) (_ storage.TorrentImpl, err error) {
upvertedFiles := info.UpvertedFiles() upvertedFiles := info.UpvertedFiles()
files := make([]file, 0, len(upvertedFiles)) files := make([]file, 0, len(upvertedFiles))
for _, fileInfo := range upvertedFiles { for _, fileInfo := range upvertedFiles {
Binary file not shown.
+50 -28
View File
@@ -3,10 +3,12 @@ package http
import ( import (
"bytes" "bytes"
"context" "context"
"crypto/tls"
"errors" "errors"
"fmt" "fmt"
"io" "io"
"mime" "mime"
"net"
"net/http" "net/http"
"net/http/cookiejar" "net/http/cookiejar"
"net/url" "net/url"
@@ -24,6 +26,9 @@ import (
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
const connectTimeout = 15 * time.Second
const readTimeout = 15 * time.Second
type RequestError struct { type RequestError struct {
Code int Code int
Msg string Msg string
@@ -102,9 +107,9 @@ func (f *Fetcher) Resolve(req *base.Request) error {
if base.HttpCodePartialContent == httpResp.StatusCode || (base.HttpCodeOK == httpResp.StatusCode && httpResp.Header.Get(base.HttpHeaderAcceptRanges) == base.HttpHeaderBytes && strings.HasPrefix(httpResp.Header.Get(base.HttpHeaderContentRange), base.HttpHeaderBytes)) { if base.HttpCodePartialContent == httpResp.StatusCode || (base.HttpCodeOK == httpResp.StatusCode && httpResp.Header.Get(base.HttpHeaderAcceptRanges) == base.HttpHeaderBytes && strings.HasPrefix(httpResp.Header.Get(base.HttpHeaderContentRange), base.HttpHeaderBytes)) {
// response 206 status code, support breakpoint continuation // response 206 status code, support breakpoint continuation
res.Range = true res.Range = true
// 解析资源大小: bytes 0-1000/1001 => 1001 // parse content length from Content-Range header, eg: bytes 0-1000/1001 or bytes 0-0/*
contentTotal := path.Base(httpResp.Header.Get(base.HttpHeaderContentRange)) contentTotal := path.Base(httpResp.Header.Get(base.HttpHeaderContentRange))
if contentTotal != "" { if contentTotal != "" && contentTotal != "*" {
parse, err := strconv.ParseInt(contentTotal, 10, 64) parse, err := strconv.ParseInt(contentTotal, 10, 64)
if err != nil { if err != nil {
return err return err
@@ -145,7 +150,7 @@ func (f *Fetcher) Resolve(req *base.Request) error {
file.Name = filename file.Name = filename
} }
} }
// Get file filePath by URL // get file filePath by URL
if file.Name == "" { if file.Name == "" {
file.Name = path.Base(httpReq.URL.Path) file.Name = path.Base(httpReq.URL.Path)
} }
@@ -161,9 +166,6 @@ func (f *Fetcher) Resolve(req *base.Request) error {
func (f *Fetcher) Create(opts *base.Options) error { func (f *Fetcher) Create(opts *base.Options) error {
f.meta.Opts = opts f.meta.Opts = opts
if err := base.ParseReqExtra[fhttp.ReqExtra](f.meta.Req); err != nil {
return err
}
if err := base.ParseOptsExtra[fhttp.OptsExtra](f.meta.Opts); err != nil { if err := base.ParseOptsExtra[fhttp.OptsExtra](f.meta.Opts); err != nil {
return err return err
} }
@@ -197,6 +199,12 @@ func (f *Fetcher) Start() (err error) {
if err != nil { if err != nil {
return err return err
} }
// Avoid request extra modified by extension
if err = base.ParseReqExtra[fhttp.ReqExtra](f.meta.Req); err != nil {
return err
}
if f.chunks == nil { if f.chunks == nil {
f.chunks = f.splitChunk() f.chunks = f.splitChunk()
} }
@@ -246,23 +254,42 @@ func (f *Fetcher) Wait() (err error) {
return <-f.doneCh return <-f.doneCh
} }
type fetchResult struct {
err error
}
func (f *Fetcher) fetch() { func (f *Fetcher) fetch() {
var ctx context.Context var ctx context.Context
ctx, f.cancel = context.WithCancel(context.Background()) ctx, f.cancel = context.WithCancel(context.Background())
f.eg, _ = errgroup.WithContext(ctx) f.eg, _ = errgroup.WithContext(ctx)
chunkErrs := make([]error, len(f.chunks))
for i := 0; i < len(f.chunks); i++ { for i := 0; i < len(f.chunks); i++ {
i := i i := i
f.eg.Go(func() error { f.eg.Go(func() error {
return f.fetchChunk(i, ctx) err := f.fetchChunk(i, ctx)
// if canceled, fail fast
if errors.Is(err, context.Canceled) {
return err
}
chunkErrs[i] = err
return nil
}) })
} }
go func() { go func() {
err := f.eg.Wait() err := f.eg.Wait()
// check if canceled // error returned only if canceled, just return
if errors.Is(err, context.Canceled) { if err != nil {
return return
} }
// check all fetch results, if any error, return
for _, chunkErr := range chunkErrs {
if chunkErr != nil {
err = chunkErr
break
}
}
f.file.Close() f.file.Close()
// Update file last modified time // Update file last modified time
if f.config.UseServerCtime && f.meta.Res.Files[0].Ctime != nil { if f.config.UseServerCtime && f.meta.Res.Files[0].Ctime != nil {
@@ -285,24 +312,11 @@ func (f *Fetcher) fetchChunk(index int, ctx context.Context) (err error) {
for { for {
// if chunk is completed, return // if chunk is completed, return
if f.meta.Res.Range && chunk.Downloaded >= chunk.End-chunk.Begin+1 { if f.meta.Res.Range && chunk.Downloaded >= chunk.End-chunk.Begin+1 {
return return nil
} }
if chunk.retryTimes >= maxRetries { if chunk.retryTimes >= maxRetries {
if !f.meta.Res.Range { return
return
}
// check if all failed
allFailed := true
for _, c := range f.chunks {
if chunk.Downloaded < chunk.End-chunk.Begin+1 && c.retryTimes < maxRetries {
allFailed = false
break
}
}
if allFailed {
return
}
} }
var ( var (
@@ -329,10 +343,9 @@ func (f *Fetcher) fetchChunk(index int, ctx context.Context) (err error) {
err = NewRequestError(resp.StatusCode, resp.Status) err = NewRequestError(resp.StatusCode, resp.Status)
return err return err
} }
// Http request success, reset retry times reader := NewTimeoutReader(resp.Body, readTimeout)
chunk.retryTimes = 0
for { for {
n, err := resp.Body.Read(buf) n, err := reader.Read(buf)
if n > 0 { if n > 0 {
_, err := f.file.WriteAt(buf[:n], chunk.Begin+chunk.Downloaded) _, err := f.file.WriteAt(buf[:n], chunk.Begin+chunk.Downloaded)
if err != nil { if err != nil {
@@ -347,7 +360,6 @@ func (f *Fetcher) fetchChunk(index int, ctx context.Context) (err error) {
return err return err
} }
} }
return nil
}() }()
if err != nil { if err != nil {
// If canceled, do not retry // If canceled, do not retry
@@ -415,6 +427,10 @@ func (f *Fetcher) buildRequest(ctx context.Context, req *base.Request) (httpReq
return return
} }
httpReq.Header = headers httpReq.Header = headers
// Override Host header
if host := headers.Get(base.HttpHeaderHost); host != "" {
httpReq.Host = host
}
return httpReq, nil return httpReq, nil
} }
@@ -448,7 +464,13 @@ func (f *Fetcher) splitChunk() (chunks []*chunk) {
func (f *Fetcher) buildClient() *http.Client { func (f *Fetcher) buildClient() *http.Client {
transport := &http.Transport{ transport := &http.Transport{
DialContext: (&net.Dialer{
Timeout: connectTimeout,
}).DialContext,
Proxy: f.ctl.GetProxy(f.meta.Req.Proxy), Proxy: f.ctl.GetProxy(f.meta.Req.Proxy),
TLSClientConfig: &tls.Config{
InsecureSkipVerify: f.meta.Req.SkipVerifyCert,
},
} }
// Cookie handle // Cookie handle
jar, _ := cookiejar.New(nil) jar, _ := cookiejar.New(nil)
+24
View File
@@ -11,6 +11,7 @@ import (
"net" "net"
gohttp "net/http" gohttp "net/http"
"net/url" "net/url"
"strings"
"testing" "testing"
"time" "time"
) )
@@ -59,6 +60,21 @@ func TestFetcher_Resolve(t *testing.T) {
} }
} }
func TestFetcher_ResolveWithHostHeader(t *testing.T) {
fetcher := buildFetcher()
err := fetcher.Resolve(&base.Request{
URL: "https://bing.com",
Extra: &http.ReqExtra{
Header: map[string]string{
"Host": "test",
},
},
})
if err == nil || !strings.Contains(err.Error(), "400") {
t.Errorf("Resolve() got = %v, want %v", err, "400")
}
}
func testResolve(startTestServer func() net.Listener, path string, want *base.Resource, t *testing.T) { func testResolve(startTestServer func() net.Listener, path string, want *base.Resource, t *testing.T) {
listener := startTestServer() listener := startTestServer()
defer listener.Close() defer listener.Close()
@@ -132,6 +148,14 @@ func TestFetcher_DownloadLimit(t *testing.T) {
downloadNormal(listener, 8, t) downloadNormal(listener, 8, t)
} }
func TestFetcher_DownloadResponseBodyReadTimeout(t *testing.T) {
listener := test.StartTestLimitServer(16, readTimeout.Milliseconds()+5000)
defer listener.Close()
downloadError(listener, 1, t)
downloadError(listener, 4, t)
}
func TestFetcher_DownloadResume(t *testing.T) { func TestFetcher_DownloadResume(t *testing.T) {
listener := test.StartTestFileServer() listener := test.StartTestFileServer()
defer listener.Close() defer listener.Close()
+40
View File
@@ -0,0 +1,40 @@
package http
import (
"context"
"io"
"time"
)
type TimeoutReader struct {
reader io.Reader
timeout time.Duration
}
func NewTimeoutReader(r io.Reader, timeout time.Duration) *TimeoutReader {
return &TimeoutReader{
reader: r,
timeout: timeout,
}
}
func (tr *TimeoutReader) Read(p []byte) (n int, err error) {
ctx, cancel := context.WithTimeout(context.Background(), tr.timeout)
defer cancel()
done := make(chan struct{})
var readErr error
var bytesRead int
go func() {
bytesRead, readErr = tr.reader.Read(p)
close(done)
}()
select {
case <-done:
return bytesRead, readErr
case <-ctx.Done():
return 0, ctx.Err()
}
}
@@ -0,0 +1,51 @@
package http
import (
"bytes"
"context"
"errors"
"io"
"testing"
"time"
)
func TestTimeoutReader_Read(t *testing.T) {
data := []byte("Hello, World!")
reader := bytes.NewReader(data)
timeoutReader := NewTimeoutReader(reader, 1*time.Second)
buf := make([]byte, len(data))
n, err := timeoutReader.Read(buf)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if n != len(data) {
t.Fatalf("expected to read %d bytes, read %d", len(data), n)
}
if !bytes.Equal(buf, data) {
t.Fatalf("expected %s, got %s", data, buf)
}
}
func TestTimeoutReader_ReadTimeout(t *testing.T) {
reader := &slowReader{delay: 2 * time.Second}
timeoutReader := NewTimeoutReader(reader, 1*time.Second)
buf := make([]byte, 8192)
_, err := timeoutReader.Read(buf)
if err == nil {
t.Fatal("expected timeout error, got nil")
}
if !errors.Is(err, context.DeadlineExceeded) {
t.Fatalf("expected %v, got %v", context.DeadlineExceeded, err)
}
}
type slowReader struct {
delay time.Duration
}
func (sr *slowReader) Read(p []byte) (n int, err error) {
time.Sleep(sr.delay)
return 0, io.EOF
}
+30 -19
View File
@@ -4,6 +4,7 @@ import (
"context" "context"
"crypto/rand" "crypto/rand"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"github.com/GopeedLab/gopeed/pkg/base" "github.com/GopeedLab/gopeed/pkg/base"
"github.com/armon/go-socks5" "github.com/armon/go-socks5"
@@ -36,7 +37,7 @@ const (
) )
func StartTestFileServer() net.Listener { func StartTestFileServer() net.Listener {
return startTestServer(func() http.Handler { return startTestServer(func(sl *shutdownListener) http.Handler {
return http.FileServer(http.Dir(Dir)) return http.FileServer(http.Dir(Dir))
}) })
} }
@@ -52,7 +53,7 @@ func (s *SlowFileServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
} }
func StartTestSlowFileServer(delay time.Duration) net.Listener { func StartTestSlowFileServer(delay time.Duration) net.Listener {
return startTestServer(func() http.Handler { return startTestServer(func(sl *shutdownListener) http.Handler {
return &SlowFileServer{ return &SlowFileServer{
delay: delay, delay: delay,
handler: http.FileServer(http.Dir(Dir)), handler: http.FileServer(http.Dir(Dir)),
@@ -61,7 +62,7 @@ func StartTestSlowFileServer(delay time.Duration) net.Listener {
} }
func StartTestCustomServer() net.Listener { func StartTestCustomServer() net.Listener {
return startTestServer(func() http.Handler { return startTestServer(func(sl *shutdownListener) http.Handler {
mux := http.NewServeMux() mux := http.NewServeMux()
mux.HandleFunc("/"+BuildName, func(writer http.ResponseWriter, request *http.Request) { mux.HandleFunc("/"+BuildName, func(writer http.ResponseWriter, request *http.Request) {
file, err := os.Open(BuildFile) file, err := os.Open(BuildFile)
@@ -88,7 +89,7 @@ func StartTestCustomServer() net.Listener {
func StartTestRetryServer() net.Listener { func StartTestRetryServer() net.Listener {
counter := 0 counter := 0
return startTestServer(func() http.Handler { return startTestServer(func(sl *shutdownListener) http.Handler {
mux := http.NewServeMux() mux := http.NewServeMux()
mux.HandleFunc("/"+BuildName, func(writer http.ResponseWriter, request *http.Request) { mux.HandleFunc("/"+BuildName, func(writer http.ResponseWriter, request *http.Request) {
counter++ counter++
@@ -108,7 +109,7 @@ func StartTestRetryServer() net.Listener {
} }
func StartTestPostServer() net.Listener { func StartTestPostServer() net.Listener {
return startTestServer(func() http.Handler { return startTestServer(func(sl *shutdownListener) http.Handler {
mux := http.NewServeMux() mux := http.NewServeMux()
mux.HandleFunc("/"+BuildName, func(writer http.ResponseWriter, request *http.Request) { mux.HandleFunc("/"+BuildName, func(writer http.ResponseWriter, request *http.Request) {
if request.Method == "POST" && request.Header.Get("Authorization") != "" { if request.Method == "POST" && request.Header.Get("Authorization") != "" {
@@ -132,7 +133,7 @@ func StartTestPostServer() net.Listener {
func StartTestErrorServer() net.Listener { func StartTestErrorServer() net.Listener {
counter := 0 counter := 0
return startTestServer(func() http.Handler { return startTestServer(func(sl *shutdownListener) http.Handler {
mux := http.NewServeMux() mux := http.NewServeMux()
mux.HandleFunc("/"+BuildName, func(writer http.ResponseWriter, request *http.Request) { mux.HandleFunc("/"+BuildName, func(writer http.ResponseWriter, request *http.Request) {
counter++ counter++
@@ -149,7 +150,7 @@ func StartTestErrorServer() net.Listener {
func StartTestLimitServer(maxConnections int32, delay int64) net.Listener { func StartTestLimitServer(maxConnections int32, delay int64) net.Listener {
var connections atomic.Int32 var connections atomic.Int32
return startTestServer(func() http.Handler { return startTestServer(func(sl *shutdownListener) http.Handler {
mux := http.NewServeMux() mux := http.NewServeMux()
mux.HandleFunc("/"+BuildName, func(writer http.ResponseWriter, request *http.Request) { mux.HandleFunc("/"+BuildName, func(writer http.ResponseWriter, request *http.Request) {
defer func() { defer func() {
@@ -165,12 +166,14 @@ func StartTestLimitServer(maxConnections int32, delay int64) net.Listener {
if r == "" { if r == "" {
writer.Header().Set("Content-Length", fmt.Sprintf("%d", BuildSize)) writer.Header().Set("Content-Length", fmt.Sprintf("%d", BuildSize))
writer.WriteHeader(200) writer.WriteHeader(200)
(writer.(http.Flusher)).Flush()
file, err := os.Open(BuildFile) file, err := os.Open(BuildFile)
if err != nil { if err != nil {
panic(err) panic(err)
} }
defer file.Close() defer file.Close()
slowCopy(writer, file, delay) slowCopy(sl, writer, file, delay)
} else { } else {
// split range // split range
s := strings.Split(r, "=") s := strings.Split(r, "=")
@@ -204,6 +207,8 @@ func StartTestLimitServer(maxConnections int32, delay int64) net.Listener {
writer.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", start, end, BuildSize)) writer.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", start, end, BuildSize))
writer.Header().Set("Accept-Ranges", "bytes") writer.Header().Set("Accept-Ranges", "bytes")
writer.WriteHeader(206) writer.WriteHeader(206)
(writer.(http.Flusher)).Flush()
file, err := os.Open(BuildFile) file, err := os.Open(BuildFile)
if err != nil { if err != nil {
writer.WriteHeader(500) writer.WriteHeader(500)
@@ -211,7 +216,7 @@ func StartTestLimitServer(maxConnections int32, delay int64) net.Listener {
} }
defer file.Close() defer file.Close()
file.Seek(start, 0) file.Seek(start, 0)
slowCopyN(writer, file, end-start+1, delay) slowCopyN(sl, writer, file, end-start+1, delay)
} }
}) })
return mux return mux
@@ -219,9 +224,12 @@ func StartTestLimitServer(maxConnections int32, delay int64) net.Listener {
} }
// slowCopyN copies n bytes from src to dst, speed limit is bytes per second // slowCopyN copies n bytes from src to dst, speed limit is bytes per second
func slowCopy(dst io.Writer, src io.Reader, delay int64) (written int64, err error) { func slowCopy(sl *shutdownListener, dst io.Writer, src io.Reader, delay int64) (written int64, err error) {
buf := make([]byte, 32*1024) buf := make([]byte, 32*1024)
for { for {
if sl.isShutdown {
return 0, errors.New("server shutdown")
}
nr, er := src.Read(buf) nr, er := src.Read(buf)
if nr > 0 { if nr > 0 {
nw, ew := dst.Write(buf[0:nr]) nw, ew := dst.Write(buf[0:nr])
@@ -250,8 +258,8 @@ func slowCopy(dst io.Writer, src io.Reader, delay int64) (written int64, err err
return written, err return written, err
} }
func slowCopyN(dst io.Writer, src io.Reader, n int64, delay int64) (written int64, err error) { func slowCopyN(sl *shutdownListener, dst io.Writer, src io.Reader, n int64, delay int64) (written int64, err error) {
written, err = slowCopy(dst, io.LimitReader(src, n), delay) written, err = slowCopy(sl, dst, io.LimitReader(src, n), delay)
if written == n { if written == n {
return n, nil return n, nil
} }
@@ -262,7 +270,7 @@ func slowCopyN(dst io.Writer, src io.Reader, n int64, delay int64) (written int6
return return
} }
func startTestServer(serverHandle func() http.Handler) net.Listener { func startTestServer(serverHandle func(sl *shutdownListener) http.Handler) net.Listener {
listener, err := net.Listen("tcp", "127.0.0.1:0") listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil { if err != nil {
panic(err) panic(err)
@@ -272,7 +280,7 @@ func startTestServer(serverHandle func() http.Handler) net.Listener {
panic(err) panic(err)
} }
defer file.Close() defer file.Close()
// 随机生成一个文件 // Write random data
l := int64(8192) l := int64(8192)
buf := make([]byte, l) buf := make([]byte, l)
size := int64(0) size := int64(0)
@@ -289,21 +297,24 @@ func startTestServer(serverHandle func() http.Handler) net.Listener {
size += l size += l
} }
server := &http.Server{} server := &http.Server{}
server.Handler = serverHandle() sl := &shutdownListener{
go server.Serve(listener)
return &shutdownListener{
server: server, server: server,
Listener: listener, Listener: listener,
} }
server.Handler = serverHandle(sl)
go server.Serve(listener)
return sl
} }
type shutdownListener struct { type shutdownListener struct {
server *http.Server server *http.Server
isShutdown bool
net.Listener net.Listener
} }
func (c *shutdownListener) Close() error { func (c *shutdownListener) Close() error {
c.isShutdown = true
closeErr := c.server.Shutdown(context.Background()) closeErr := c.server.Shutdown(context.Background())
if err := ifExistAndRemove(BuildFile); err != nil { if err := ifExistAndRemove(BuildFile); err != nil {
fmt.Println(err) fmt.Println(err)
+1
View File
@@ -15,6 +15,7 @@ const (
HttpCodeOK = 200 HttpCodeOK = 200
HttpCodePartialContent = 206 HttpCodePartialContent = 206
HttpHeaderHost = "Host"
HttpHeaderRange = "Range" HttpHeaderRange = "Range"
HttpHeaderAcceptRanges = "Accept-Ranges" HttpHeaderAcceptRanges = "Accept-Ranges"
HttpHeaderContentLength = "Content-Length" HttpHeaderContentLength = "Content-Length"
+14 -2
View File
@@ -7,6 +7,7 @@ import (
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
"net/http" "net/http"
"net/url" "net/url"
"sync"
"time" "time"
) )
@@ -18,6 +19,8 @@ type Request struct {
Labels map[string]string `json:"labels"` Labels map[string]string `json:"labels"`
// Proxy is special proxy config for request // Proxy is special proxy config for request
Proxy *RequestProxy `json:"proxy"` Proxy *RequestProxy `json:"proxy"`
// SkipVerifyCert is the flag that skip verify cert
SkipVerifyCert bool `json:"skipVerifyCert"`
} }
func (r *Request) Validate() error { func (r *Request) Validate() error {
@@ -221,7 +224,7 @@ func (cfg *DownloaderProxyConfig) ToHandler() func(r *http.Request) (*url.URL, e
return nil return nil
} }
if cfg.System { if cfg.System {
ieproxy.ReloadConf() safeProxyReloadConf()
return ieproxy.GetProxyFunc() return ieproxy.GetProxyFunc()
} }
if cfg.Scheme == "" || cfg.Host == "" { if cfg.Scheme == "" || cfg.Host == "" {
@@ -236,7 +239,7 @@ func (cfg *DownloaderProxyConfig) ToUrl() *url.URL {
return nil return nil
} }
if cfg.System { if cfg.System {
ieproxy.ReloadConf() safeProxyReloadConf()
static := ieproxy.GetConf().Static static := ieproxy.GetConf().Static
if static.Active && len(static.Protocols) > 0 { if static.Active && len(static.Protocols) > 0 {
// If only one protocol, use it // If only one protocol, use it
@@ -262,6 +265,15 @@ func (cfg *DownloaderProxyConfig) ToUrl() *url.URL {
return util.BuildProxyUrl(cfg.Scheme, cfg.Host, cfg.Usr, cfg.Pwd) return util.BuildProxyUrl(cfg.Scheme, cfg.Host, cfg.Usr, cfg.Pwd)
} }
var prcLock sync.Mutex
func safeProxyReloadConf() {
prcLock.Lock()
defer prcLock.Unlock()
ieproxy.ReloadConf()
}
func parseUrlSafe(rawUrl string) *url.URL { func parseUrlSafe(rawUrl string) *url.URL {
u, err := url.Parse(rawUrl) u, err := url.Parse(rawUrl)
if err != nil { if err != nil {
+30 -18
View File
@@ -11,12 +11,12 @@ import (
gonanoid "github.com/matoous/go-nanoid/v2" gonanoid "github.com/matoous/go-nanoid/v2"
"github.com/rs/zerolog" "github.com/rs/zerolog"
"github.com/rs/zerolog/pkgerrors" "github.com/rs/zerolog/pkgerrors"
"github.com/virtuald/go-paniclog"
"math" "math"
gohttp "net/http" gohttp "net/http"
"net/url" "net/url"
"os" "os"
"path/filepath" "path/filepath"
"runtime/debug"
"sort" "sort"
"strings" "strings"
"sync" "sync"
@@ -204,33 +204,29 @@ func (d *Downloader) Setup() error {
current := task.fetcher.Progress().TotalDownloaded() current := task.fetcher.Progress().TotalDownloaded()
tick := float64(d.cfg.RefreshInterval) / 1000 tick := float64(d.cfg.RefreshInterval) / 1000
downloadDataChanged := false
if task.Status == base.DownloadStatusRunning { if task.Status == base.DownloadStatusRunning {
downloadDataChanged = current != task.Progress.Downloaded
task.Progress.Used = task.timer.Used() task.Progress.Used = task.timer.Used()
task.Progress.Speed = task.calcSpeed(task.speedArr, current-task.Progress.Downloaded, tick) task.Progress.Speed = task.calcSpeed(task.speedArr, current-task.Progress.Downloaded, tick)
task.Progress.Downloaded = current task.Progress.Downloaded = current
} }
uploadDataChanged := false
if task.Uploading { if task.Uploading {
uploader := task.fetcher.(fetcher.Uploader) uploader := task.fetcher.(fetcher.Uploader)
currentUploaded := uploader.UploadedBytes() currentUploaded := uploader.UploadedBytes()
uploadDataChanged = currentUploaded != task.Progress.Uploaded
task.Progress.UploadSpeed = task.calcSpeed(task.uploadSpeedArr, currentUploaded-task.Progress.Uploaded, tick) task.Progress.UploadSpeed = task.calcSpeed(task.uploadSpeedArr, currentUploaded-task.Progress.Uploaded, tick)
task.Progress.Uploaded = currentUploaded task.Progress.Uploaded = currentUploaded
} }
d.emit(EventKeyProgress, task) d.emit(EventKeyProgress, task)
// store fetcher progress // store fetcher progress when download/upload data changed
data, err := task.fetcherManager.Store(task.fetcher) if !downloadDataChanged && !uploadDataChanged {
if err != nil {
d.Logger.Error().Stack().Err(err).Msgf("serialize fetcher failed: %s", task.ID)
return
}
if err := d.storage.Put(bucketSave, task.ID, data); err != nil {
d.Logger.Error().Stack().Err(err).Msgf("persist fetcher failed: %s", task.ID)
return
}
if err := d.storage.Put(bucketTask, task.ID, task); err != nil {
d.Logger.Error().Stack().Err(err).Msgf("persist task failed: %s", task.ID)
return return
} }
d.saveTask(task)
}() }()
} }
} }
@@ -273,6 +269,23 @@ func (d *Downloader) setupFetcher(fm fetcher.FetcherManager, fetcher fetcher.Fet
fetcher.Setup(ctl) fetcher.Setup(ctl)
} }
func (d *Downloader) saveTask(task *Task) error {
data, err := task.fetcherManager.Store(task.fetcher)
if err != nil {
d.Logger.Error().Stack().Err(err).Msgf("serialize fetcher failed: %s", task.ID)
return err
}
if err := d.storage.Put(bucketSave, task.ID, data); err != nil {
d.Logger.Error().Stack().Err(err).Msgf("persist fetcher failed: %s", task.ID)
return err
}
if err := d.storage.Put(bucketTask, task.ID, task); err != nil {
d.Logger.Error().Stack().Err(err).Msgf("persist task failed: %s", task.ID)
return err
}
return nil
}
func (d *Downloader) Resolve(req *base.Request) (rr *ResolveResult, err error) { func (d *Downloader) Resolve(req *base.Request) (rr *ResolveResult, err error) {
rrId, err := gonanoid.New() rrId, err := gonanoid.New()
if err != nil { if err != nil {
@@ -813,7 +826,7 @@ func (d *Downloader) watch(task *Task) {
} }
// When delete a not resolved task, need check if the task resource is nil // When delete a not resolved task, need check if the task resource is nil
if task.Meta.Res == nil { if task.Meta.Res == nil || d.GetTask(task.ID) == nil {
return return
} }
@@ -1005,8 +1018,6 @@ func (d *Downloader) doStart(task *Task) (err error) {
return return
} }
isCreate = task.Status == base.DownloadStatusReady isCreate = task.Status == base.DownloadStatusReady
d.triggerOnStart(task)
task.updateStatus(base.DownloadStatusRunning) task.updateStatus(base.DownloadStatusRunning)
return return
@@ -1023,6 +1034,7 @@ func (d *Downloader) doStart(task *Task) (err error) {
task.lock.Lock() task.lock.Lock()
defer task.lock.Unlock() defer task.lock.Unlock()
d.triggerOnStart(task)
if task.Meta.Res == nil { if task.Meta.Res == nil {
err := task.fetcher.Resolve(task.Meta.Req) err := task.fetcher.Resolve(task.Meta.Req)
if err != nil { if err != nil {
@@ -1064,7 +1076,7 @@ func (d *Downloader) doStart(task *Task) (err error) {
if err := task.fetcher.Start(); err != nil { if err := task.fetcher.Start(); err != nil {
return err return err
} }
if err := d.storage.Put(bucketTask, task.ID, task.clone()); err != nil { if err := d.saveTask(task); err != nil {
return err return err
} }
d.emit(EventKeyStart, task) d.emit(EventKeyStart, task)
@@ -1130,7 +1142,7 @@ func logPanic(logDir string) {
if err != nil { if err != nil {
return return
} }
paniclog.RedirectStderr(f) debug.SetCrashOutput(f, debug.CrashOptions{})
} }
func (d *Downloader) buildFetcher(url string) (fetcher.Fetcher, error) { func (d *Downloader) buildFetcher(url string) (fetcher.Fetcher, error) {
+8 -6
View File
@@ -702,20 +702,22 @@ type OnDoneContext struct {
Task *Task `json:"task"` Task *Task `json:"task"`
} }
// ExtensionTask is a wrapper of Task, it's used to interact with extension scripts.
// Avoid extension scripts modifying task directly, use ExtensionTask to encapsulate task,
// only some fields can be modified, such as request info.
type ExtensionTask struct { type ExtensionTask struct {
*Task
download *Downloader download *Downloader
*Task
} }
func NewExtensionTask(download *Downloader, task *Task) *ExtensionTask { func NewExtensionTask(download *Downloader, task *Task) *ExtensionTask {
// restricts extension scripts to only modify request info
newTask := task.clone() newTask := task.clone()
// Assign the pointer of the properties that the extension supports modification newTask.Meta.Req = task.Meta.Req
newTask.Meta = task.Meta
newTask.Status = task.Status
return &ExtensionTask{ return &ExtensionTask{
Task: newTask,
download: download, download: download,
Task: newTask,
} }
} }
-1
View File
@@ -10,7 +10,6 @@ import (
func ParseSchema(url string) string { func ParseSchema(url string) string {
index := strings.Index(url, ":") index := strings.Index(url, ":")
// if no schema or windows path like C:\a.txt, return FILE
if index == -1 || index == 1 { if index == -1 || index == 1 {
return "" return ""
} }
Binary file not shown.
Binary file not shown.
+21 -4
View File
@@ -129,12 +129,20 @@ Future<void> continueTask(String id) async {
return _parse(() => _client.dio.put("/api/v1/tasks/$id/continue"), null); return _parse(() => _client.dio.put("/api/v1/tasks/$id/continue"), null);
} }
Future<void> pauseAllTasks() async { Future<void> pauseAllTasks(List<String>? ids) async {
return _parse(() => _client.dio.put("/api/v1/tasks/pause"), null); return _parse(
() => _client.dio.put("/api/v1/tasks/pause", queryParameters: {
"id": ids,
}),
null);
} }
Future<void> continueAllTasks() async { Future<void> continueAllTasks(List<String>? ids) async {
return _parse(() => _client.dio.put("/api/v1/tasks/continue"), null); return _parse(
() => _client.dio.put("/api/v1/tasks/continue", queryParameters: {
"id": ids,
}),
null);
} }
Future<void> deleteTask(String id, bool force) async { Future<void> deleteTask(String id, bool force) async {
@@ -142,6 +150,15 @@ Future<void> deleteTask(String id, bool force) async {
() => _client.dio.delete("/api/v1/tasks/$id?force=$force"), null); () => _client.dio.delete("/api/v1/tasks/$id?force=$force"), null);
} }
Future<void> deleteTasks(List<String>? ids, bool force) async {
return _parse(
() => _client.dio.delete("/api/v1/tasks", queryParameters: {
"id": ids,
"force": force,
}),
null);
}
Future<DownloaderConfig> getConfig() async { Future<DownloaderConfig> getConfig() async {
return _parse(() => _client.dio.get("/api/v1/config"), return _parse(() => _client.dio.get("/api/v1/config"),
(data) => DownloaderConfig.fromJson(data)); (data) => DownloaderConfig.fromJson(data));
@@ -80,6 +80,7 @@ class ExtraConfig {
String locale; String locale;
bool lastDeleteTaskKeep; bool lastDeleteTaskKeep;
bool defaultDirectDownload; bool defaultDirectDownload;
bool defaultBtClient;
ExtraConfigBt bt = ExtraConfigBt(); ExtraConfigBt bt = ExtraConfigBt();
@@ -88,6 +89,7 @@ class ExtraConfig {
this.locale = '', this.locale = '',
this.lastDeleteTaskKeep = false, this.lastDeleteTaskKeep = false,
this.defaultDirectDownload = false, this.defaultDirectDownload = false,
this.defaultBtClient = true,
}); });
factory ExtraConfig.fromJson(Map<String, dynamic>? json) => factory ExtraConfig.fromJson(Map<String, dynamic>? json) =>
@@ -73,6 +73,7 @@ ExtraConfig _$ExtraConfigFromJson(Map<String, dynamic> json) => ExtraConfig(
locale: json['locale'] as String? ?? '', locale: json['locale'] as String? ?? '',
lastDeleteTaskKeep: json['lastDeleteTaskKeep'] as bool? ?? false, lastDeleteTaskKeep: json['lastDeleteTaskKeep'] as bool? ?? false,
defaultDirectDownload: json['defaultDirectDownload'] as bool? ?? false, defaultDirectDownload: json['defaultDirectDownload'] as bool? ?? false,
defaultBtClient: json['defaultBtClient'] as bool? ?? true,
)..bt = ExtraConfigBt.fromJson(json['bt'] as Map<String, dynamic>); )..bt = ExtraConfigBt.fromJson(json['bt'] as Map<String, dynamic>);
Map<String, dynamic> _$ExtraConfigToJson(ExtraConfig instance) => Map<String, dynamic> _$ExtraConfigToJson(ExtraConfig instance) =>
@@ -81,6 +82,7 @@ Map<String, dynamic> _$ExtraConfigToJson(ExtraConfig instance) =>
'locale': instance.locale, 'locale': instance.locale,
'lastDeleteTaskKeep': instance.lastDeleteTaskKeep, 'lastDeleteTaskKeep': instance.lastDeleteTaskKeep,
'defaultDirectDownload': instance.defaultDirectDownload, 'defaultDirectDownload': instance.defaultDirectDownload,
'defaultBtClient': instance.defaultBtClient,
'bt': instance.bt.toJson(), 'bt': instance.bt.toJson(),
}; };
+9 -5
View File
@@ -10,8 +10,8 @@ class Options {
Object? extra; Object? extra;
Options({ Options({
required this.name, this.name = '',
required this.path, this.path = '',
this.selectFiles = const [], this.selectFiles = const [],
this.extra, this.extra,
}); });
@@ -24,12 +24,16 @@ class Options {
@JsonSerializable() @JsonSerializable()
class OptsExtraHttp { class OptsExtraHttp {
int connections = 0; int connections;
bool autoTorrent = false; bool autoTorrent;
OptsExtraHttp(); OptsExtraHttp({
this.connections = 0,
this.autoTorrent = false,
});
factory OptsExtraHttp.fromJson(Map<String, dynamic> json) => factory OptsExtraHttp.fromJson(Map<String, dynamic> json) =>
_$OptsExtraHttpFromJson(json); _$OptsExtraHttpFromJson(json);
Map<String, dynamic> toJson() => _$OptsExtraHttpToJson(this); Map<String, dynamic> toJson() => _$OptsExtraHttpToJson(this);
} }
+7 -6
View File
@@ -7,10 +7,10 @@ part of 'options.dart';
// ************************************************************************** // **************************************************************************
Options _$OptionsFromJson(Map<String, dynamic> json) => Options( Options _$OptionsFromJson(Map<String, dynamic> json) => Options(
name: json['name'] as String, name: json['name'] as String? ?? '',
path: json['path'] as String, path: json['path'] as String? ?? '',
selectFiles: (json['selectFiles'] as List<dynamic>?) selectFiles: (json['selectFiles'] as List<dynamic>?)
?.map((e) => e as int) ?.map((e) => (e as num).toInt())
.toList() ?? .toList() ??
const [], const [],
extra: json['extra'], extra: json['extra'],
@@ -34,9 +34,10 @@ Map<String, dynamic> _$OptionsToJson(Options instance) {
} }
OptsExtraHttp _$OptsExtraHttpFromJson(Map<String, dynamic> json) => OptsExtraHttp _$OptsExtraHttpFromJson(Map<String, dynamic> json) =>
OptsExtraHttp() OptsExtraHttp(
..connections = json['connections'] as int connections: (json['connections'] as num?)?.toInt() ?? 0,
..autoTorrent = json['autoTorrent'] as bool; autoTorrent: json['autoTorrent'] as bool? ?? false,
);
Map<String, dynamic> _$OptsExtraHttpToJson(OptsExtraHttp instance) => Map<String, dynamic> _$OptsExtraHttpToJson(OptsExtraHttp instance) =>
<String, dynamic>{ <String, dynamic>{
+28 -13
View File
@@ -6,14 +6,16 @@ part 'request.g.dart';
class Request { class Request {
String url; String url;
Object? extra; Object? extra;
Map<String, String>? labels = {}; Map<String, String>? labels;
RequestProxy? proxy; RequestProxy? proxy;
bool skipVerifyCert;
Request({ Request({
required this.url, required this.url,
this.extra, this.extra,
this.labels, this.labels,
this.proxy, this.proxy,
this.skipVerifyCert = false,
}); });
factory Request.fromJson(Map<String, dynamic> json) => factory Request.fromJson(Map<String, dynamic> json) =>
@@ -24,11 +26,15 @@ class Request {
@JsonSerializable() @JsonSerializable()
class ReqExtraHttp { class ReqExtraHttp {
String method = 'GET'; String method;
Map<String, String> header = {}; Map<String, String> header;
String body = ''; String body;
ReqExtraHttp(); ReqExtraHttp({
this.method = 'GET',
this.header = const {},
this.body = '',
});
factory ReqExtraHttp.fromJson(Map<String, dynamic> json) => factory ReqExtraHttp.fromJson(Map<String, dynamic> json) =>
_$ReqExtraHttpFromJson(json); _$ReqExtraHttpFromJson(json);
@@ -38,9 +44,11 @@ class ReqExtraHttp {
@JsonSerializable() @JsonSerializable()
class ReqExtraBt { class ReqExtraBt {
List<String> trackers = []; List<String> trackers;
ReqExtraBt(); ReqExtraBt({
this.trackers = const [],
});
factory ReqExtraBt.fromJson(Map<String, dynamic> json) => factory ReqExtraBt.fromJson(Map<String, dynamic> json) =>
_$ReqExtraBtFromJson(json); _$ReqExtraBtFromJson(json);
@@ -56,15 +64,22 @@ enum RequestProxyMode {
@JsonSerializable() @JsonSerializable()
class RequestProxy { class RequestProxy {
RequestProxyMode mode = RequestProxyMode.follow; RequestProxyMode mode;
String scheme = 'http'; String scheme;
String host = ''; String host;
String usr = ''; String usr;
String pwd = ''; String pwd;
RequestProxy(); RequestProxy({
this.mode = RequestProxyMode.follow,
this.scheme = 'http',
this.host = '',
this.usr = '',
this.pwd = '',
});
factory RequestProxy.fromJson(Map<String, dynamic> json) => factory RequestProxy.fromJson(Map<String, dynamic> json) =>
_$RequestProxyFromJson(json); _$RequestProxyFromJson(json);
Map<String, dynamic> toJson() => _$RequestProxyToJson(this); Map<String, dynamic> toJson() => _$RequestProxyToJson(this);
} }
+24 -13
View File
@@ -15,6 +15,7 @@ Request _$RequestFromJson(Map<String, dynamic> json) => Request(
proxy: json['proxy'] == null proxy: json['proxy'] == null
? null ? null
: RequestProxy.fromJson(json['proxy'] as Map<String, dynamic>), : RequestProxy.fromJson(json['proxy'] as Map<String, dynamic>),
skipVerifyCert: json['skipVerifyCert'] as bool? ?? false,
); );
Map<String, dynamic> _$RequestToJson(Request instance) { Map<String, dynamic> _$RequestToJson(Request instance) {
@@ -31,13 +32,18 @@ Map<String, dynamic> _$RequestToJson(Request instance) {
writeNotNull('extra', instance.extra); writeNotNull('extra', instance.extra);
writeNotNull('labels', instance.labels); writeNotNull('labels', instance.labels);
writeNotNull('proxy', instance.proxy?.toJson()); writeNotNull('proxy', instance.proxy?.toJson());
val['skipVerifyCert'] = instance.skipVerifyCert;
return val; return val;
} }
ReqExtraHttp _$ReqExtraHttpFromJson(Map<String, dynamic> json) => ReqExtraHttp() ReqExtraHttp _$ReqExtraHttpFromJson(Map<String, dynamic> json) => ReqExtraHttp(
..method = json['method'] as String method: json['method'] as String? ?? 'GET',
..header = Map<String, String>.from(json['header'] as Map) header: (json['header'] as Map<String, dynamic>?)?.map(
..body = json['body'] as String; (k, e) => MapEntry(k, e as String),
) ??
const {},
body: json['body'] as String? ?? '',
);
Map<String, dynamic> _$ReqExtraHttpToJson(ReqExtraHttp instance) => Map<String, dynamic> _$ReqExtraHttpToJson(ReqExtraHttp instance) =>
<String, dynamic>{ <String, dynamic>{
@@ -46,21 +52,26 @@ Map<String, dynamic> _$ReqExtraHttpToJson(ReqExtraHttp instance) =>
'body': instance.body, 'body': instance.body,
}; };
ReqExtraBt _$ReqExtraBtFromJson(Map<String, dynamic> json) => ReqExtraBt() ReqExtraBt _$ReqExtraBtFromJson(Map<String, dynamic> json) => ReqExtraBt(
..trackers = trackers: (json['trackers'] as List<dynamic>?)
(json['trackers'] as List<dynamic>).map((e) => e as String).toList(); ?.map((e) => e as String)
.toList() ??
const [],
);
Map<String, dynamic> _$ReqExtraBtToJson(ReqExtraBt instance) => Map<String, dynamic> _$ReqExtraBtToJson(ReqExtraBt instance) =>
<String, dynamic>{ <String, dynamic>{
'trackers': instance.trackers, 'trackers': instance.trackers,
}; };
RequestProxy _$RequestProxyFromJson(Map<String, dynamic> json) => RequestProxy() RequestProxy _$RequestProxyFromJson(Map<String, dynamic> json) => RequestProxy(
..mode = $enumDecode(_$RequestProxyModeEnumMap, json['mode']) mode: $enumDecodeNullable(_$RequestProxyModeEnumMap, json['mode']) ??
..scheme = json['scheme'] as String RequestProxyMode.follow,
..host = json['host'] as String scheme: json['scheme'] as String? ?? 'http',
..usr = json['usr'] as String host: json['host'] as String? ?? '',
..pwd = json['pwd'] as String; usr: json['usr'] as String? ?? '',
pwd: json['pwd'] as String? ?? '',
);
Map<String, dynamic> _$RequestProxyToJson(RequestProxy instance) => Map<String, dynamic> _$RequestProxyToJson(RequestProxy instance) =>
<String, dynamic>{ <String, dynamic>{
+1 -1
View File
@@ -11,7 +11,7 @@ Result<T> _$ResultFromJson<T>(
T Function(Object? json) fromJsonT, T Function(Object? json) fromJsonT,
) => ) =>
Result<T>( Result<T>(
code: json['code'] as int, code: (json['code'] as num).toInt(),
msg: json['msg'] as String?, msg: json['msg'] as String?,
data: _$nullableGenericFromJson(json['data'], fromJsonT), data: _$nullableGenericFromJson(json['data'], fromJsonT),
); );
@@ -16,6 +16,7 @@ import 'package:window_manager/window_manager.dart';
import '../../../../api/api.dart'; import '../../../../api/api.dart';
import '../../../../api/model/downloader_config.dart'; import '../../../../api/model/downloader_config.dart';
import '../../../../api/model/request.dart';
import '../../../../core/common/start_config.dart'; import '../../../../core/common/start_config.dart';
import '../../../../core/libgopeed_boot.dart'; import '../../../../core/libgopeed_boot.dart';
import '../../../../database/database.dart'; import '../../../../database/database.dart';
@@ -27,6 +28,9 @@ import '../../../../util/log_util.dart';
import '../../../../util/package_info.dart'; import '../../../../util/package_info.dart';
import '../../../../util/util.dart'; import '../../../../util/util.dart';
import '../../../routes/app_pages.dart'; import '../../../routes/app_pages.dart';
import '../../create/controllers/create_controller.dart';
import '../../create/dto/create_router_params.dart';
import '../../redirect/views/redirect_view.dart';
const unixSocketPath = 'gopeed.sock'; const unixSocketPath = 'gopeed.sock';
@@ -160,8 +164,7 @@ class AppController extends GetxController with WindowListener, TrayListener {
} }
Future<void> _initDeepLinks() async { Future<void> _initDeepLinks() async {
// currently only support android if (Util.isWeb()) {
if (!Util.isAndroid()) {
return; return;
} }
@@ -169,13 +172,13 @@ class AppController extends GetxController with WindowListener, TrayListener {
// Handle link when app is in warm state (front or background) // Handle link when app is in warm state (front or background)
_linkSubscription = _appLinks.uriLinkStream.listen((uri) async { _linkSubscription = _appLinks.uriLinkStream.listen((uri) async {
await _toCreate(uri); await _handleDeepLink(uri);
}); });
// Check initial link if app was in cold state (terminated) // Check initial link if app was in cold state (terminated)
final uri = await _appLinks.getInitialAppLink(); final uri = await _appLinks.getInitialLink();
if (uri != null) { if (uri != null) {
await _toCreate(uri); await _handleDeepLink(uri);
} }
} }
@@ -218,11 +221,11 @@ class AppController extends GetxController with WindowListener, TrayListener {
), ),
MenuItem( MenuItem(
label: "startAll".tr, label: "startAll".tr,
onClick: (menuItem) async => {continueAllTasks()}, onClick: (menuItem) async => {continueAllTasks(null)},
), ),
MenuItem( MenuItem(
label: "pauseAll".tr, label: "pauseAll".tr,
onClick: (menuItem) async => {pauseAllTasks()}, onClick: (menuItem) async => {pauseAllTasks(null)},
), ),
MenuItem( MenuItem(
label: 'setting'.tr, label: 'setting'.tr,
@@ -304,13 +307,38 @@ class AppController extends GetxController with WindowListener, TrayListener {
} }
} }
Future<void> _toCreate(Uri uri) async { Future<void> _handleDeepLink(Uri uri) async {
final path = (uri.scheme == "magnet" || if (uri.scheme == "gopeed") {
uri.scheme == "http" || if (uri.path == "/create") {
uri.scheme == "https") final params = uri.queryParameters["params"];
? uri.toString() if (params?.isNotEmpty == true) {
: (await toFile(uri.toString())).path; final paramsJson = String.fromCharCodes(base64Decode(params!));
await Get.rootDelegate.offAndToNamed(Routes.CREATE, arguments: path); Get.rootDelegate.offAndToNamed(Routes.REDIRECT,
arguments: RedirectArgs(Routes.CREATE,
arguments:
CreateRouterParams.fromJson(jsonDecode(paramsJson))));
return;
}
Get.rootDelegate.offAndToNamed(Routes.CREATE);
return;
}
Get.rootDelegate.offAndToNamed(Routes.HOME);
return;
}
String path;
if (uri.scheme == "magnet" ||
uri.scheme == "http" ||
uri.scheme == "https") {
path = uri.toString();
} else if (uri.scheme == "file") {
path = Util.isWindows() ? uri.path.substring(1) : uri.path;
} else {
path = (await toFile(uri.toString())).path;
}
Get.rootDelegate.offAndToNamed(Routes.REDIRECT,
arguments: RedirectArgs(Routes.CREATE,
arguments: CreateRouterParams(req: Request(url: path))));
} }
String runningAddress() { String runningAddress() {
@@ -9,7 +9,6 @@ import '../../app/controllers/app_controller.dart';
class CreateController extends GetxController class CreateController extends GetxController
with GetSingleTickerProviderStateMixin { with GetSingleTickerProviderStateMixin {
// final files = [].obs;
final RxList fileInfos = [].obs; final RxList fileInfos = [].obs;
final RxList openedFolders = [].obs; final RxList openedFolders = [].obs;
final selectedIndexes = <int>[].obs; final selectedIndexes = <int>[].obs;
@@ -0,0 +1,24 @@
import 'package:json_annotation/json_annotation.dart';
import '../../../../api/model/options.dart';
import '../../../../api/model/request.dart';
part 'create_router_params.g.dart';
@JsonSerializable(explicitToJson: true)
class CreateRouterParams {
Request? req;
Options? opt;
CreateRouterParams({
this.req,
this.opt,
});
factory CreateRouterParams.fromJson(
Map<String, dynamic> json,
) =>
_$CreateRouterParamsFromJson(json);
Map<String, dynamic> toJson() => _$CreateRouterParamsToJson(this);
}
@@ -0,0 +1,31 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'create_router_params.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
CreateRouterParams _$CreateRouterParamsFromJson(Map<String, dynamic> json) =>
CreateRouterParams(
req: json['req'] == null
? null
: Request.fromJson(json['req'] as Map<String, dynamic>),
opt: json['opt'] == null
? null
: Options.fromJson(json['opt'] as Map<String, dynamic>),
);
Map<String, dynamic> _$CreateRouterParamsToJson(CreateRouterParams instance) {
final val = <String, dynamic>{};
void writeNotNull(String key, dynamic value) {
if (value != null) {
val[key] = value;
}
}
writeNotNull('req', instance.req?.toJson());
writeNotNull('opt', instance.opt?.toJson());
return val;
}
@@ -1,4 +1,6 @@
import 'package:autoscale_tabbarview/autoscale_tabbarview.dart'; import 'dart:convert';
import 'package:contentsize_tabbarview/contentsize_tabbarview.dart';
import 'package:desktop_drop/desktop_drop.dart'; import 'package:desktop_drop/desktop_drop.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -12,6 +14,7 @@ import '../../../../api/model/create_task.dart';
import '../../../../api/model/options.dart'; import '../../../../api/model/options.dart';
import '../../../../api/model/request.dart'; import '../../../../api/model/request.dart';
import '../../../../api/model/resolve_result.dart'; import '../../../../api/model/resolve_result.dart';
import '../../../../api/model/task.dart';
import '../../../../database/database.dart'; import '../../../../database/database.dart';
import '../../../../util/input_formatter.dart'; import '../../../../util/input_formatter.dart';
import '../../../../util/message.dart'; import '../../../../util/message.dart';
@@ -19,10 +22,11 @@ import '../../../../util/util.dart';
import '../../../routes/app_pages.dart'; import '../../../routes/app_pages.dart';
import '../../../views/compact_checkbox.dart'; import '../../../views/compact_checkbox.dart';
import '../../../views/directory_selector.dart'; import '../../../views/directory_selector.dart';
import '../../../views/file_list_view.dart'; import '../../../views/file_tree_view.dart';
import '../../app/controllers/app_controller.dart'; import '../../app/controllers/app_controller.dart';
import '../../history/views/history_view.dart'; import '../../history/views/history_view.dart';
import '../controllers/create_controller.dart'; import '../controllers/create_controller.dart';
import '../dto/create_router_params.dart';
class CreateView extends GetView<CreateController> { class CreateView extends GetView<CreateController> {
final _confirmFormKey = GlobalKey<FormState>(); final _confirmFormKey = GlobalKey<FormState>();
@@ -36,13 +40,26 @@ class CreateView extends GetView<CreateController> {
final _proxyPortController = TextEditingController(); final _proxyPortController = TextEditingController();
final _proxyUsrController = TextEditingController(); final _proxyUsrController = TextEditingController();
final _proxyPwdController = TextEditingController(); final _proxyPwdController = TextEditingController();
final _httpUaController = TextEditingController(); final _httpHeaderControllers = [
final _httpCookieController = TextEditingController(); (
final _httpRefererController = TextEditingController(); name: TextEditingController(text: "User-Agent"),
value: TextEditingController()
),
(
name: TextEditingController(text: "Cookie"),
value: TextEditingController()
),
(
name: TextEditingController(text: "Referer"),
value: TextEditingController()
),
];
final _btTrackerController = TextEditingController(); final _btTrackerController = TextEditingController();
final _availableSchemes = ["http:", "https:", "magnet:"]; final _availableSchemes = ["http:", "https:", "magnet:"];
final _skipVerifyCertController = false.obs;
CreateView({Key? key}) : super(key: key); CreateView({Key? key}) : super(key: key);
@override @override
@@ -58,32 +75,91 @@ class CreateView extends GetView<CreateController> {
_pathController.text = appController.downloaderConfig.value.downloadDir; _pathController.text = appController.downloaderConfig.value.downloadDir;
} }
final String? filePath = Get.rootDelegate.arguments(); final CreateRouterParams? routerParams = Get.rootDelegate.arguments();
if (_urlController.text.isEmpty) { if (routerParams?.req?.url.isNotEmpty ?? false) {
if (filePath?.isNotEmpty ?? false) { // get url from route arguments
// get file path from route arguments final url = routerParams!.req!.url;
_urlController.text = filePath!; _urlController.text = url;
_urlController.selection = TextSelection.fromPosition( _urlController.selection = TextSelection.fromPosition(
TextPosition(offset: _urlController.text.length)); TextPosition(offset: _urlController.text.length));
} else { final uppercaseUrl = url.toUpperCase();
// read clipboard Protocol? protocol;
Clipboard.getData('text/plain').then((value) { if (uppercaseUrl.startsWith("HTTP:") ||
if (value?.text?.isNotEmpty ?? false) { uppercaseUrl.startsWith("HTTPS:")) {
if (_availableSchemes protocol = Protocol.http;
.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!);
}
});
} }
if (uppercaseUrl.startsWith("MAGNET:") ||
uppercaseUrl.endsWith(".TORRENT")) {
protocol = Protocol.bt;
}
if (protocol != null) {
final extraHandlers = {
Protocol.http: () {
final reqExtra = ReqExtraHttp.fromJson(
jsonDecode(jsonEncode(routerParams.req!.extra)));
_httpHeaderControllers.clear();
reqExtra.header.forEach((key, value) {
_httpHeaderControllers.add(
(
name: TextEditingController(text: key),
value: TextEditingController(text: value),
),
);
});
_skipVerifyCertController.value = routerParams.req!.skipVerifyCert;
},
Protocol.bt: () {
final reqExtra = ReqExtraBt.fromJson(
jsonDecode(jsonEncode(routerParams.req!.extra)));
_btTrackerController.text = reqExtra.trackers.join("\n");
},
};
if (routerParams.req?.extra != null) {
extraHandlers[protocol]?.call();
}
// handle options
if (routerParams.opt != null) {
_renameController.text = routerParams.opt!.name;
_pathController.text = routerParams.opt!.path;
final optionsHandlers = {
Protocol.http: () {
final opt = routerParams.opt!;
_renameController.text = opt.name;
_pathController.text = opt.path;
if (opt.extra != null) {
final optsExtraHttp =
OptsExtraHttp.fromJson(jsonDecode(jsonEncode(opt.extra)));
_connectionsController.text =
optsExtraHttp.connections.toString();
}
},
Protocol.bt: null,
};
if (routerParams.opt?.extra != null) {
optionsHandlers[protocol]?.call();
}
}
}
} else if (_urlController.text.isEmpty) {
// read clipboard
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!);
}
});
} }
return Scaffold( return Scaffold(
@@ -434,40 +510,105 @@ class CreateView extends GetView<CreateController> {
) )
], ],
), ),
AutoScaleTabBarView( DefaultTabController(
controller: controller.advancedTabController, length: 2,
children: [ child: ContentSizeTabBarView(
Column( controller:
children: [ controller.advancedTabController,
TextFormField( children: [
controller: _httpUaController, Column(
decoration: const InputDecoration( children: [
labelText: 'User-Agent', ..._httpHeaderControllers.map((e) {
)), return Row(
TextFormField( children: [
controller: _httpCookieController, Flexible(
decoration: const InputDecoration( child: TextFormField(
labelText: 'Cookie', controller: e.name,
)), decoration: InputDecoration(
TextFormField( hintText:
controller: _httpRefererController, 'httpHeaderName'.tr,
decoration: const InputDecoration( ),
labelText: 'Referer', ),
)), ),
], const Padding(
), padding: EdgeInsets.only(
Column( left: 10)),
children: [ Flexible(
TextFormField( child: TextFormField(
controller: _btTrackerController, controller: e.value,
maxLines: 5, decoration: InputDecoration(
decoration: InputDecoration( hintText:
labelText: 'Trackers', 'httpHeaderValue'.tr,
hintText: 'addTrackerHit'.tr, ),
)), ),
], ),
) const Padding(
], padding: EdgeInsets.only(
left: 10)),
IconButton(
icon: const Icon(Icons.add),
onPressed: () {
_httpHeaderControllers.add(
(
name:
TextEditingController(),
value:
TextEditingController(),
),
);
controller.showAdvanced
.update((val) => val);
},
),
IconButton(
icon:
const Icon(Icons.remove),
onPressed: () {
if (_httpHeaderControllers
.length <=
1) {
return;
}
_httpHeaderControllers
.remove(e);
controller.showAdvanced
.update((val) => val);
},
),
],
);
}),
Padding(
padding:
const EdgeInsets.only(top: 10),
child: CompactCheckbox(
label: 'skipVerifyCert'.tr,
value: _skipVerifyCertController
.value,
onChanged: (bool? value) {
_skipVerifyCertController
.value = value ?? false;
},
textStyle: const TextStyle(
color: Colors.grey,
),
),
),
],
),
Column(
children: [
TextFormField(
controller: _btTrackerController,
maxLines: 5,
decoration: InputDecoration(
labelText: 'Trackers',
hintText: 'addTrackerHit'.tr,
)),
],
)
],
),
) )
], ],
).paddingOnly(top: 16), ).paddingOnly(top: 16),
@@ -578,7 +719,11 @@ class CreateView extends GetView<CreateController> {
await Future.wait(urls.map((url) { await Future.wait(urls.map((url) {
return createTask(CreateTask( return createTask(CreateTask(
req: Request( req: Request(
url: url, extra: parseReqExtra(url), proxy: parseProxy()), url: url,
extra: parseReqExtra(url),
proxy: parseProxy(),
skipVerifyCert: _skipVerifyCertController.value,
),
opt: Options( opt: Options(
name: isMultiLine ? "" : _renameController.text, name: isMultiLine ? "" : _renameController.text,
path: _pathController.text, path: _pathController.text,
@@ -592,6 +737,7 @@ class CreateView extends GetView<CreateController> {
url: submitUrl, url: submitUrl,
extra: parseReqExtra(_urlController.text), extra: parseReqExtra(_urlController.text),
proxy: parseProxy(), proxy: parseProxy(),
skipVerifyCert: _skipVerifyCertController.value,
)); ));
await _showResolveDialog(rr); await _showResolveDialog(rr);
} }
@@ -621,12 +767,10 @@ class CreateView extends GetView<CreateController> {
if (controller.showAdvanced.value) { if (controller.showAdvanced.value) {
switch (controller.advancedTabController.index) { switch (controller.advancedTabController.index) {
case 0: case 0:
final header = { final header = Map<String, String>.fromEntries(_httpHeaderControllers
"User-Agent": _httpUaController.text, .map((e) => MapEntry(e.name.text, e.value.text)));
"Cookie": _httpCookieController.text, header.removeWhere(
"Referer": _httpRefererController.text, (key, value) => key.trim().isEmpty || value.trim().isEmpty);
};
header.removeWhere((key, value) => value.trim().isEmpty);
if (header.isNotEmpty) { if (header.isNotEmpty) {
reqExtra = ReqExtraHttp()..header = header; reqExtra = ReqExtraHttp()..header = header;
} }
@@ -675,7 +819,13 @@ class CreateView extends GetView<CreateController> {
child: Form( child: Form(
key: createFormKey, key: createFormKey,
autovalidateMode: AutovalidateMode.always, autovalidateMode: AutovalidateMode.always,
child: FileListView(files: rr.res.files)), child: FileTreeView(
files: rr.res.files,
initialValues: rr.res.files.asMap().keys.toList(),
onSelectionChanged: (List<int> values) {
controller.selectedIndexes.value = values;
},
)),
); );
}, },
), ),
@@ -0,0 +1,12 @@
import 'package:get/get.dart';
import '../controllers/redirect_controller.dart';
class RedirectBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut<RedirectController>(
() => RedirectController(),
);
}
}
@@ -0,0 +1,3 @@
import 'package:get/get.dart';
class RedirectController extends GetxController {}
@@ -0,0 +1,27 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/redirect_controller.dart';
class RedirectArgs {
final String page;
final dynamic arguments;
RedirectArgs(this.page, {this.arguments});
}
class RedirectView extends GetView<RedirectController> {
const RedirectView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final redirectArgs = Get.rootDelegate.arguments() as RedirectArgs;
// Waiting for previous page controller to delete, avoid deleting controller that route page after redirect
WidgetsBinding.instance.addPostFrameCallback((_) async {
await Future.delayed(const Duration(milliseconds: 350));
Get.rootDelegate
.offAndToNamed(redirectArgs.page, arguments: redirectArgs.arguments);
});
return const SizedBox();
}
}
@@ -17,6 +17,7 @@ import '../../../../util/locale_manager.dart';
import '../../../../util/log_util.dart'; import '../../../../util/log_util.dart';
import '../../../../util/message.dart'; import '../../../../util/message.dart';
import '../../../../util/package_info.dart'; import '../../../../util/package_info.dart';
import '../../../../util/scheme_register/scheme_register.dart';
import '../../../../util/util.dart'; import '../../../../util/util.dart';
import '../../../views/check_list_view.dart'; import '../../../views/check_list_view.dart';
import '../../../views/directory_selector.dart'; import '../../../views/directory_selector.dart';
@@ -111,7 +112,7 @@ class SettingView extends GetView<SettingController> {
}); });
final buildDefaultDirectDownload = final buildDefaultDirectDownload =
_buildConfigItem('defaultDirectDownload'.tr, () { _buildConfigItem('defaultDirectDownload', () {
return appController.downloaderConfig.value.extra.defaultDirectDownload return appController.downloaderConfig.value.extra.defaultDirectDownload
? 'on'.tr ? 'on'.tr
: 'off'.tr; : 'off'.tr;
@@ -161,7 +162,7 @@ class SettingView extends GetView<SettingController> {
// Currently auto startup only support Windows and Linux // Currently auto startup only support Windows and Linux
final buildAutoStartup = !Util.isWindows() && !Util.isLinux() final buildAutoStartup = !Util.isWindows() && !Util.isLinux()
? () => null ? () => null
: _buildConfigItem('launchAtStartup'.tr, () { : _buildConfigItem('launchAtStartup', () {
return appController.autoStartup.value ? 'on'.tr : 'off'.tr; return appController.autoStartup.value ? 'on'.tr : 'off'.tr;
}, (Key key) { }, (Key key) {
return Container( return Container(
@@ -229,8 +230,9 @@ class SettingView extends GetView<SettingController> {
], ],
); );
}); });
final buildHttpUseServerCtime = _buildConfigItem('useServerCtime'.tr, final buildHttpUseServerCtime = _buildConfigItem(
() => httpConfig.useServerCtime ? 'on'.tr : 'off'.tr, (Key key) { 'useServerCtime', () => httpConfig.useServerCtime ? 'on'.tr : 'off'.tr,
(Key key) {
return Container( return Container(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: Switch( child: Switch(
@@ -420,6 +422,37 @@ class SettingView extends GetView<SettingController> {
].where((e) => e != null).map((e) => e!).toList(), ].where((e) => e != null).map((e) => e!).toList(),
); );
}); });
final buildBtDefaultClientConfig = !Util.isWindows()
? () => null
: _buildConfigItem('setAsDefaultBtClient', () {
return appController.downloaderConfig.value.extra.defaultBtClient
? 'on'.tr
: 'off'.tr;
}, (Key key) {
return Container(
alignment: Alignment.centerLeft,
child: Switch(
value:
appController.downloaderConfig.value.extra.defaultBtClient,
onChanged: (bool value) async {
try {
if (value) {
registerDefaultTorrentClient();
} else {
unregisterDefaultTorrentClient();
}
appController.downloaderConfig.update((val) {
val!.extra.defaultBtClient = value;
});
await debounceSave();
} catch (e) {
showErrorMessage(e);
logger.e('register default torrent client fail', e);
}
},
),
);
});
// ui config items start // ui config items start
final buildTheme = _buildConfigItem( final buildTheme = _buildConfigItem(
@@ -947,6 +980,7 @@ class SettingView extends GetView<SettingController> {
buildBtTrackerSubscribeUrls(), buildBtTrackerSubscribeUrls(),
buildBtTrackers(), buildBtTrackers(),
buildBtSeedConfig(), buildBtSeedConfig(),
buildBtDefaultClientConfig(),
]), ]),
)), )),
Text('ui'.tr), Text('ui'.tr),
@@ -1,4 +1,6 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:gopeed/api/model/task.dart'; import 'package:gopeed/api/model/task.dart';
@@ -6,5 +8,20 @@ class TaskController extends GetxController {
final tabIndex = 0.obs; final tabIndex = 0.obs;
final scaffoldKey = GlobalKey<ScaffoldState>(); final scaffoldKey = GlobalKey<ScaffoldState>();
final selectTask = Rx<Task?>(null); final selectTask = Rx<Task?>(null);
final copyUrlDone = false.obs;
@override
void onInit() {
super.onInit();
if (kIsWeb) {
BrowserContextMenu.disableContextMenu();
}
}
@override
void onClose() {
super.onClose();
if (kIsWeb) {
BrowserContextMenu.enableContextMenu();
}
}
} }
@@ -9,5 +9,13 @@ class TaskDownloadingController extends TaskListController {
Status.pause, Status.pause,
Status.wait, Status.wait,
Status.error Status.error
], (a, b) => b.createdAt.compareTo(a.createdAt)); ], (a, b) {
if (a.status == Status.running && b.status != Status.running) {
return -1;
} else if (a.status != Status.running && b.status == Status.running) {
return 1;
} else {
return b.updatedAt.compareTo(a.updatedAt);
}
});
} }
@@ -12,6 +12,7 @@ abstract class TaskListController extends GetxController {
TaskListController(this.statuses, this.compare); TaskListController(this.statuses, this.compare);
final tasks = <Task>[].obs; final tasks = <Task>[].obs;
final selectedTaskIds = <String>[].obs;
final isRunning = false.obs; final isRunning = false.obs;
late final Timer _timer; late final Timer _timer;
@@ -9,6 +9,7 @@ class TaskDownloadedView extends GetView<TaskDownloadedController> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BuildTaskListView(tasks: controller.tasks); return BuildTaskListView(
tasks: controller.tasks, selectedTaskIds: controller.selectedTaskIds);
} }
} }
@@ -9,6 +9,7 @@ class TaskDownloadingView extends GetView<TaskDownloadingController> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BuildTaskListView(tasks: controller.tasks); return BuildTaskListView(
tasks: controller.tasks, selectedTaskIds: controller.selectedTaskIds);
} }
} }
@@ -7,10 +7,9 @@ import 'package:url_launcher/url_launcher.dart';
import '../../../../api/api.dart' as api; import '../../../../api/api.dart' as api;
import '../../../../util/browser_download/browser_download.dart'; import '../../../../util/browser_download/browser_download.dart';
import '../../../../util/file_icon.dart';
import '../../../../util/icons.dart';
import '../../../../util/util.dart'; import '../../../../util/util.dart';
import '../../../views/breadcrumb_view.dart'; import '../../../views/breadcrumb_view.dart';
import '../../../views/file_icon.dart';
import '../controllers/task_files_controller.dart'; import '../controllers/task_files_controller.dart';
class TaskFilesView extends GetView<TaskFilesController> { class TaskFilesView extends GetView<TaskFilesController> {
@@ -65,9 +64,8 @@ class TaskFilesView extends GetView<TaskFilesController> {
[meta.opts.path, meta.res!.name, fileRelativePath]); [meta.opts.path, meta.res!.name, fileRelativePath]);
final fileName = basename(filePath); final fileName = basename(filePath);
return ListTile( return ListTile(
leading: file.isDirectory leading:
? const Icon(Icons.folder) Icon(fileIcon(fileName, isFolder: file.isDirectory)),
: Icon(FaIcons.allIcons[findIcon(fileName)]),
title: Text(fileName), title: Text(fileName),
subtitle: file.isDirectory subtitle: file.isDirectory
? Text('items'.trParams({ ? Text('items'.trParams({
+9 -2
View File
@@ -1,6 +1,4 @@
import 'package:get/get.dart'; 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'; import '../modules/create/bindings/create_binding.dart';
import '../modules/create/views/create_view.dart'; import '../modules/create/views/create_view.dart';
@@ -8,12 +6,16 @@ import '../modules/extension/bindings/extension_binding.dart';
import '../modules/extension/views/extension_view.dart'; import '../modules/extension/views/extension_view.dart';
import '../modules/home/bindings/home_binding.dart'; import '../modules/home/bindings/home_binding.dart';
import '../modules/home/views/home_view.dart'; import '../modules/home/views/home_view.dart';
import '../modules/redirect/bindings/redirect_binding.dart';
import '../modules/redirect/views/redirect_view.dart';
import '../modules/root/bindings/root_binding.dart'; import '../modules/root/bindings/root_binding.dart';
import '../modules/root/views/root_view.dart'; import '../modules/root/views/root_view.dart';
import '../modules/setting/bindings/setting_binding.dart'; import '../modules/setting/bindings/setting_binding.dart';
import '../modules/setting/views/setting_view.dart'; import '../modules/setting/views/setting_view.dart';
import '../modules/task/bindings/task_binding.dart'; import '../modules/task/bindings/task_binding.dart';
import '../modules/task/bindings/task_files_binding.dart'; import '../modules/task/bindings/task_files_binding.dart';
import '../modules/task/views/task_files_view.dart';
import '../modules/task/views/task_view.dart';
part 'app_routes.dart'; part 'app_routes.dart';
@@ -68,6 +70,11 @@ class AppPages {
page: () => CreateView(), page: () => CreateView(),
binding: CreateBinding(), binding: CreateBinding(),
), ),
GetPage(
name: _Paths.REDIRECT,
page: () => const RedirectView(),
binding: RedirectBinding(),
),
]), ]),
]; ];
} }
@@ -3,6 +3,7 @@ part of 'app_pages.dart';
abstract class Routes { abstract class Routes {
Routes._(); Routes._();
static const ROOT = _Paths.ROOT; static const ROOT = _Paths.ROOT;
static const HOME = _Paths.HOME; static const HOME = _Paths.HOME;
static const CREATE = _Paths.CREATE; static const CREATE = _Paths.CREATE;
@@ -10,10 +11,12 @@ abstract class Routes {
static const TASK_FILES = TASK + _Paths.TASK_FILES; static const TASK_FILES = TASK + _Paths.TASK_FILES;
static const EXTENSION = _Paths.HOME + _Paths.EXTENSION; static const EXTENSION = _Paths.HOME + _Paths.EXTENSION;
static const SETTING = _Paths.HOME + _Paths.SETTING; static const SETTING = _Paths.HOME + _Paths.SETTING;
static const REDIRECT = _Paths.REDIRECT;
} }
abstract class _Paths { abstract class _Paths {
_Paths._(); _Paths._();
static const ROOT = '/'; static const ROOT = '/';
static const HOME = '/home'; static const HOME = '/home';
static const CREATE = '/create'; static const CREATE = '/create';
@@ -21,4 +24,5 @@ abstract class _Paths {
static const TASK_FILES = '/files'; static const TASK_FILES = '/files';
static const EXTENSION = '/extension'; static const EXTENSION = '/extension';
static const SETTING = '/setting'; static const SETTING = '/setting';
static const REDIRECT = '/redirect';
} }
+155 -49
View File
@@ -1,24 +1,28 @@
import 'package:contextmenu_plus/contextmenu_plus.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
import '../../api/api.dart'; import '../../api/api.dart';
import '../../api/model/task.dart'; import '../../api/model/task.dart';
import '../../util/file_icon.dart';
import '../../util/icons.dart';
import '../../util/message.dart'; import '../../util/message.dart';
import '../../util/util.dart'; import '../../util/util.dart';
import '../modules/app/controllers/app_controller.dart'; import '../modules/app/controllers/app_controller.dart';
import '../modules/task/controllers/task_controller.dart'; import '../modules/task/controllers/task_controller.dart';
import '../modules/task/controllers/task_downloaded_controller.dart';
import '../modules/task/controllers/task_downloading_controller.dart';
import '../modules/task/views/task_view.dart'; import '../modules/task/views/task_view.dart';
import '../routes/app_pages.dart'; import '../routes/app_pages.dart';
import 'file_icon.dart';
class BuildTaskListView extends GetView { class BuildTaskListView extends GetView {
final List<Task> tasks; final List<Task> tasks;
final List<String> selectedTaskIds;
const BuildTaskListView({ const BuildTaskListView({
Key? key, Key? key,
required this.tasks, required this.tasks,
required this.selectedTaskIds,
}) : super(key: key); }) : super(key: key);
@override @override
@@ -57,11 +61,15 @@ class BuildTaskListView extends GetView {
return task.status == Status.running; return task.status == Status.running;
} }
bool isSelect() {
return selectedTaskIds.contains(task.id);
}
bool isFolderTask() { bool isFolderTask() {
return task.isFolder; return task.isFolder;
} }
Future<void> showDeleteDialog(String id) { Future<void> showDeleteDialog(List<String> ids) {
final appController = Get.find<AppController>(); final appController = Get.find<AppController>();
final context = Get.context!; final context = Get.context!;
@@ -70,7 +78,8 @@ class BuildTaskListView extends GetView {
context: context, context: context,
barrierDismissible: false, barrierDismissible: false,
builder: (_) => AlertDialog( builder: (_) => AlertDialog(
title: Text('deleteTask'.tr), title: Text(
'deleteTask'.trParams({'count': ids.length.toString()})),
content: Obx(() => CheckboxListTile( content: Obx(() => CheckboxListTile(
value: appController value: appController
.downloaderConfig.value.extra.lastDeleteTaskKeep, .downloaderConfig.value.extra.lastDeleteTaskKeep,
@@ -96,7 +105,7 @@ class BuildTaskListView extends GetView {
final force = !appController final force = !appController
.downloaderConfig.value.extra.lastDeleteTaskKeep; .downloaderConfig.value.extra.lastDeleteTaskKeep;
await appController.saveConfig(); await appController.saveConfig();
await deleteTask(id, force); await deleteTasks(ids, force);
Get.back(); Get.back();
} catch (e) { } catch (e) {
showErrorMessage(e); showErrorMessage(e);
@@ -144,12 +153,35 @@ class BuildTaskListView extends GetView {
list.add(IconButton( list.add(IconButton(
icon: const Icon(Icons.delete), icon: const Icon(Icons.delete),
onPressed: () { onPressed: () {
showDeleteDialog(task.id); showDeleteDialog([task.id]);
}, },
)); ));
return list; return list;
} }
Widget buildContextItem(IconData icon, String label, Function() onTap,
{bool enabled = true}) {
return ListTile(
dense: true,
visualDensity: const VisualDensity(vertical: -1),
minLeadingWidth: 12,
leading: Icon(icon, size: 18),
title: Text(label,
style: const TextStyle(
fontWeight: FontWeight.bold, // Make the text bold
)),
onTap: () async {
Get.back();
try {
await onTap();
} catch (e) {
showErrorMessage(e);
}
},
enabled: enabled,
);
}
double getProgress() { double getProgress() {
final totalSize = task.meta.res?.size ?? 0; final totalSize = task.meta.res?.size ?? 0;
return totalSize <= 0 ? 0 : task.progress.downloaded / totalSize; return totalSize <= 0 ? 0 : task.progress.downloaded / totalSize;
@@ -168,53 +200,127 @@ class BuildTaskListView extends GetView {
} }
final taskController = Get.find<TaskController>(); final taskController = Get.find<TaskController>();
final taskListController = taskController.tabIndex.value == 0
? Get.find<TaskDownloadingController>()
: Get.find<TaskDownloadedController>();
return Card( // Filter selected task ids that are still in the task list
elevation: 4.0, filterSelectedTaskIds(Iterable<String> selectedTaskIds) => selectedTaskIds
child: InkWell( .where((id) => tasks.any((task) => task.id == id))
onTap: () { .toList();
taskController.scaffoldKey.currentState?.openEndDrawer();
taskController.selectTask.value = task; return ContextMenuArea(
}, width: 140,
onDoubleTap: () { builder: (context) => [
task.open(); buildContextItem(Icons.checklist, 'selectAll'.tr, () {
}, if (tasks.isEmpty) return;
child: Column(
mainAxisSize: MainAxisSize.min, if (selectedTaskIds.isNotEmpty) {
children: [ taskListController.selectedTaskIds([]);
ListTile( } else {
title: Text(task.name), taskListController.selectedTaskIds(tasks.map((e) => e.id).toList());
leading: isFolderTask() }
? const Icon(FaIcons.folder) }),
: Icon(FaIcons.allIcons[findIcon(task.name)])), buildContextItem(Icons.check, 'select'.tr, () {
Row( if (isSelect()) {
taskListController.selectedTaskIds(taskListController
.selectedTaskIds
.where((element) => element != task.id)
.toList());
} else {
taskListController.selectedTaskIds(
[...taskListController.selectedTaskIds, task.id]);
}
}),
const Divider(
indent: 8,
endIndent: 8,
),
buildContextItem(Icons.play_arrow, 'continue'.tr, () async {
try {
await continueAllTasks(filterSelectedTaskIds(
{...taskListController.selectedTaskIds, task.id}));
} finally {
taskListController.selectedTaskIds([]);
}
}, enabled: !isDone() && !isRunning()),
buildContextItem(Icons.pause, 'pause'.tr, () async {
try {
await pauseAllTasks(filterSelectedTaskIds(
{...taskListController.selectedTaskIds, task.id}));
} finally {
taskListController.selectedTaskIds([]);
}
}, enabled: !isDone() && isRunning()),
buildContextItem(Icons.delete, 'delete'.tr, () async {
try {
await showDeleteDialog(filterSelectedTaskIds(
{...taskListController.selectedTaskIds, task.id}));
} finally {
taskListController.selectedTaskIds([]);
}
}),
],
child: Obx(
() => Card(
elevation: 4.0,
shape: isSelect()
? RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
side: BorderSide(
color: Theme.of(context).colorScheme.primary,
width: 2.0,
),
)
: null,
child: InkWell(
onTap: () {
taskController.scaffoldKey.currentState?.openEndDrawer();
taskController.selectTask.value = task;
},
onDoubleTap: () {
task.open();
},
child: Column(
mainAxisSize: MainAxisSize.min,
children: [ children: [
Expanded( ListTile(
flex: 1, title: Text(task.name),
child: Text( leading: Icon(
getProgressText(), fileIcon(task.name,
style: Get.textTheme.bodyLarge isFolder: isFolderTask(),
?.copyWith(color: Get.theme.disabledColor), isBitTorrent: task.protocol == Protocol.bt),
).padding(left: 18)),
Expanded(
flex: 1,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text("${Util.fmtByte(task.progress.speed)} / s",
style: Get.textTheme.titleSmall),
...buildActions()
],
)), )),
Row(
children: [
Expanded(
flex: 1,
child: Text(
getProgressText(),
style: Get.textTheme.bodyLarge
?.copyWith(color: Get.theme.disabledColor),
).padding(left: 18)),
Expanded(
flex: 1,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text("${Util.fmtByte(task.progress.speed)} / s",
style: Get.textTheme.titleSmall),
...buildActions()
],
)),
],
),
isDone()
? Container()
: LinearProgressIndicator(
value: getProgress(),
),
], ],
), ),
isDone() )).padding(horizontal: 14, top: 8),
? Container() ),
: LinearProgressIndicator( );
value: getProgress(),
),
],
),
)).padding(horizontal: 14, top: 8);
} }
} }
+76
View File
@@ -0,0 +1,76 @@
import 'package:flutter/material.dart';
import '../../icon/gopeed_icons.dart';
final Map<IconData, List<String>> iconConfigMap = {
Gopeed.install: ['exe', 'msi', 'dmg', 'deb', 'rpm'],
Gopeed.android: ['apk'],
Gopeed.app_store_ios: ['ipa'],
Gopeed.file_bt: ['torrent'],
Gopeed.cd: ['iso'],
Gopeed.html5: ['html', 'htm'],
Gopeed.file_alt: ['txt', 'md', 'log', 'csv', 'tsv', 'json', 'yaml', 'yml'],
Gopeed.file_pdf: ['pdf'],
Gopeed.file_word: ['doc', 'docx'],
Gopeed.file_excel: ['xls', 'xlsx'],
Gopeed.file_powerpoint: ['ppt', 'pptx'],
Gopeed.file_archive: ['zip', 'rar', '7z', 'tar', 'gz', 'bz2', 'xz'],
Gopeed.file_image: [
'jpg',
'jpeg',
'png',
'gif',
'bmp',
'tiff',
'svg',
'webp'
],
Gopeed.file_audio: ['mp3', 'wav', 'flac', 'aac', 'ogg', 'wma', 'm4a'],
Gopeed.file_video: ['mp4', 'avi', 'mkv', 'mov', 'wmv', 'flv', 'webm'],
Gopeed.file_code: [
'js',
'css',
'json',
'xml',
'java',
'cpp',
'dart',
'py',
'rb',
'php',
'ts',
'swift',
'go',
'rs'
],
Gopeed.file: [''],
};
final Map<String, IconData> _iconCache = Map.fromEntries(
iconConfigMap.entries.expand(
(entry) => entry.value.map((ext) => MapEntry(ext, entry.key)),
),
);
String fileExt(String? name) {
if (name == null) {
return '';
}
final ext = name.split('.').last;
if (ext.length > 8) {
return '';
}
return ext.toLowerCase();
}
IconData fileIcon(String? name,
{bool isFolder = false, bool isBitTorrent = false}) {
if (isFolder) {
return isBitTorrent ? Gopeed.folder_bt : Gopeed.folder;
}
final ext = fileExt(name);
return _iconCache[ext] ?? Gopeed.file;
}
@@ -1,303 +0,0 @@
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 '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';
class FileListView extends GetView {
final List<FileInfo> files;
FileListView({
Key? key,
required this.files,
}) : super(key: key);
final parentController = Get.find<CreateController>();
final appController = Get.find<AppController>();
List findChildFileIdsR(List children) {
List res = [];
for (var k in children) {
if (parentController.fileInfos[k]['type'] == 'folder') {
res.addAll(
findChildFileIdsR(parentController.fileInfos[k]['children']));
} else {
res.add(parentController.fileInfos[k]['fileId']);
}
}
return res;
}
void clearDescendantFolderSizeR(int id) {
if (parentController.fileInfos[id]['type'] == 'folder') {
parentController.fileInfos[id]['size'] = 0;
for (var childId in parentController.fileInfos[id]['children']) {
clearDescendantFolderSizeR(childId);
}
}
}
void reduceAncestorFolderSizeR(int id, int size) {
int parentId = parentController.fileInfos[id]['parentId'];
if (parentId != -1) {
parentController.fileInfos[parentId]['size'] -= size;
reduceAncestorFolderSizeR(parentId, size);
}
}
int addDescendantFolderSizeR(int id) {
if (parentController.fileInfos[id]['type'] == 'folder') {
for (var childId in parentController.fileInfos[id]['children']) {
parentController.fileInfos[id]['size'] +=
addDescendantFolderSizeR(childId);
}
}
return parentController.fileInfos[id]['size'];
}
void addAncestorFolderSizeR(int id, int size) {
int parentId = parentController.fileInfos[id]['parentId'];
if (parentId != -1) {
parentController.fileInfos[parentId]['size'] += size;
addAncestorFolderSizeR(parentId, size);
}
}
List<fluent.TreeViewItem> buildTreeViewItemsR(int level, int parentId) {
List<fluent.TreeViewItem> res = [];
List children = parentController.fileInfos
.where((e) => e['level'] == level && e['parentId'] == parentId)
.toList();
for (int j = 0; j < children.length; j++) {
Map fileInfo = children[j];
if (fileInfo['type'] == 'folder') {
// folder
res.add(fluent.TreeViewItem(
// expanded: false, bug on init
value: fileInfo['id'],
onInvoked: (item, reason) async {
if (reason == fluent.TreeViewItemInvokeReason.selectionToggle) {
List childrenIds = findChildFileIdsR(fileInfo['children']);
if (item.selected == true) {
parentController.selectedIndexes.addAll(childrenIds.cast());
parentController.fileInfos[fileInfo['id']]['size'] = 0;
addDescendantFolderSizeR(item.value);
addAncestorFolderSizeR(item.value, fileInfo['size']);
parentController.fileInfos.refresh();
} else {
parentController.selectedIndexes
.removeWhere((index) => childrenIds.contains(index));
reduceAncestorFolderSizeR(item.value, fileInfo['size']);
clearDescendantFolderSizeR(item.value);
parentController.fileInfos.refresh();
}
}
},
leading: Obx(() {
return parentController.openedFolders.contains(fileInfo['id'])
? const Icon(FaIcons.folder_open,
color: Colors.lightBlueAccent)
: const Icon(FaIcons.folder, color: Colors.lightBlueAccent);
}),
onExpandToggle: (fluent.TreeViewItem item, bool getExpanded) async {
getExpanded
? parentController.openedFolders.add(item.value)
: parentController.openedFolders.remove(item.value);
},
content: Row(mainAxisAlignment: MainAxisAlignment.end, children: [
Expanded(
child: Text(
fileInfo['name'],
overflow: TextOverflow.ellipsis,
// style: context.textTheme.titleSmall,
),
),
Obx(() {
return parentController.fileInfos[fileInfo['id']]['size'] != 0
? Text(
Util.fmtByte(
parentController.fileInfos[fileInfo['id']]['size']),
// style: context.textTheme.labelMedium,
overflow: TextOverflow.ellipsis,
)
: const SizedBox.shrink();
})
]),
children: buildTreeViewItemsR(
// parentController.fileInfos.where((e) => e['level'] > level).toList(),
level + 1,
fileInfo['id'])));
} else {
// file
res.add(fluent.TreeViewItem(
value: {'id': fileInfo['id'], 'fileId': fileInfo['fileId']},
selected: fileInfo['selected'],
onInvoked: (item, reason) async {
if (reason == fluent.TreeViewItemInvokeReason.selectionToggle) {
if (item.selected == true) {
parentController.selectedIndexes.add(item.value['fileId']);
addAncestorFolderSizeR(item.value['id'], fileInfo['size']);
parentController.fileInfos.refresh();
} else {
parentController.selectedIndexes.remove(item.value['fileId']);
reduceAncestorFolderSizeR(item.value['id'], fileInfo['size']);
parentController.fileInfos.refresh();
}
}
},
collapsable: false,
leading: fileInfo['name'].lastIndexOf('.') == -1
? Icon(
FaIcons.doc,
color: appController.downloaderConfig.value.extra.themeMode ==
'dark'
? Colors.white
: Colors.black45,
)
: Icon(
FaIcons.allIcons[findIcon(fileInfo['name'])],
color: appController.downloaderConfig.value.extra.themeMode ==
'dark'
? Colors.white
: Colors.black45,
),
content: Row(mainAxisAlignment: MainAxisAlignment.end, children: [
Expanded(
child: Text(
fileInfo['name'],
overflow: TextOverflow.ellipsis,
// style: context.textTheme.titleSmall,
)),
fileInfo['size'] > 0
? Text(
Util.fmtByte(
fileInfo['size'],
),
// style: context.textTheme.labelMedium,
overflow: TextOverflow.ellipsis,
)
: const SizedBox.shrink(),
]),
));
}
}
return res;
}
List<fluent.TreeViewItem> get items {
List infos = [];
int idNext = 0;
List selectedFileIds = [];
List openedFolders = [];
//make fileInfos list
for (var i = 0; i < files.length; i++) {
//parentId -1 means path root
int parentId = -1;
List folders = path.split(files[i].path);
for (var folder in folders) {
int indexInInfos = infos.lastIndexWhere((fileInfo) =>
fileInfo['name'] == folder && fileInfo['parentId'] == parentId);
if (indexInInfos != -1) {
// folder exists
parentId = infos[indexInInfos]['id'];
// add size
infos[indexInInfos]['size'] += files[i].size;
} else {
// parent not exist
// create one and add index to parent's children
infos.add({
'level': folders.indexOf(folder),
'id': idNext,
'type': 'folder',
'name': folder,
'size': files[i].size,
'parentId': parentId,
'children': [],
});
openedFolders.add(idNext);
if (parentId != -1) {
infos[parentId]['children'].add(idNext);
}
parentId = idNext;
idNext++;
}
}
//add one file, add index to parent
infos.add({
'id': idNext,
'type': 'file',
'fileId': i,
'level': folders.length,
'name': files[i].name,
'size': files[i].size,
'parentId': parentId,
//TODO add unselected logic
'selected': true
});
selectedFileIds.add(i);
if (parentId != -1) {
infos[parentId]['children'].add(idNext);
}
idNext++;
}
parentController.fileInfos.value = infos;
parentController.selectedIndexes.value = selectedFileIds.cast();
parentController.openedFolders.value = openedFolders;
List<fluent.TreeViewItem> treeItems = buildTreeViewItemsR(0, -1);
return treeItems;
}
@override
Widget build(BuildContext context) {
return fluent.FluentTheme(
data: appController.downloaderConfig.value.extra.themeMode == 'system'
? fluent.FluentThemeData(brightness: ui.window.platformBrightness)
: appController.downloaderConfig.value.extra.themeMode == 'light'
? fluent.FluentThemeData(brightness: Brightness.light)
: fluent.FluentThemeData(brightness: Brightness.dark),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Padding(padding: EdgeInsets.only(top: 10)),
Text(
'selectFile'.tr,
// style: TextStyle(color: themeData.hintColor),
),
Expanded(
child: Container(
margin: const EdgeInsets.only(top: 10),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey, width: 1),
borderRadius: BorderRadius.circular(5)),
child: fluent.TreeView(
selectionMode: fluent.TreeViewSelectionMode.multiple,
shrinkWrap: false,
// addRepaintBoundaries: false,
usePrototypeItem: true,
// cacheExtent: 20,
// onItemInvoked: (item, reason) async => {},
onSecondaryTap: (item, details) async {
debugPrint(
'onSecondaryTap $item at ${details.globalPosition}');
},
// onSelectionChanged: (selectedItems) async => {},
narrowSpacing: true,
items: items,
// scrollPrimary: true,
))),
],
));
}
}
@@ -0,0 +1,296 @@
import 'package:checkable_treeview/checkable_treeview.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:toggle_switch/toggle_switch.dart';
import '../../api/model/resource.dart';
import '../../icon/gopeed_icons.dart';
import '../../util/util.dart';
import 'file_icon.dart';
import 'responsive_builder.dart';
import 'sort_icon_button.dart';
const _toggleSwitchIcons = [
Gopeed.file_video,
Gopeed.file_audio,
Gopeed.file_image,
];
const _sizeGapWidth = 72.0;
class FileTreeView extends StatefulWidget {
final List<FileInfo> files;
final List<int> initialValues;
final Function(List<int>) onSelectionChanged;
const FileTreeView(
{Key? key,
required this.files,
required this.initialValues,
required this.onSelectionChanged})
: super(key: key);
@override
State<FileTreeView> createState() => _FileTreeViewState();
}
class _FileTreeViewState extends State<FileTreeView> {
late GlobalKey<TreeViewState<int>> key;
late int totalSize;
int? toggleSwitchIndex;
@override
void initState() {
super.initState();
key = GlobalKey<TreeViewState<int>>();
totalSize = widget.files
.fold(0, (previousValue, element) => previousValue + element.size);
widget.onSelectionChanged(widget.initialValues);
}
@override
Widget build(BuildContext context) {
final selectedFileCount =
key.currentState?.getSelectedValues().where((e) => e != null).length ??
widget.files.length;
final selectedFileSize = calcSelectedSize(null);
final filterRow = InkWell(
onTap: () {},
child: ToggleSwitch(
minHeight: 32,
cornerRadius: 8,
doubleTapDisable: true,
inactiveBgColor: Theme.of(context).dividerColor,
activeBgColor: [Theme.of(context).colorScheme.primary],
initialLabelIndex: toggleSwitchIndex,
icons: _toggleSwitchIcons,
onToggle: (index) {
toggleSwitchIndex = index;
if (index == null) {
key.currentState?.setSelectedValues(List.empty());
return;
}
final iconFileExtArr = iconConfigMap[_toggleSwitchIcons[index]] ?? [];
final selectedFileIndexes = widget.files
.asMap()
.entries
.where((e) => iconFileExtArr.contains(fileExt(e.value.name)))
.map((e) => e.key)
.toList();
key.currentState?.setSelectedValues(selectedFileIndexes);
},
),
);
final countRow = Row(
children: [
Text('fileSelectedCount'.tr),
Text(
selectedFileCount.toString(),
style: Theme.of(context).textTheme.bodySmall,
),
const SizedBox(width: 12),
Text('fileSelectedSize'.tr),
Text(
selectedFileCount > 0 && selectedFileSize == 0
? 'unknown'.tr
: Util.fmtByte(selectedFileSize),
style: Theme.of(context).textTheme.bodySmall,
),
],
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Theme.of(context).dividerColor),
borderRadius: BorderRadius.circular(4),
),
child: TreeView(
key: key,
nodes: buildTreeNodes(),
showExpandCollapseButton: true,
showSelectAll: true,
onSelectionChanged: (selectedValues) {
setState(() {});
widget.onSelectionChanged(selectedValues
.where((e) => e != null)
.map((e) => e!)
.toList());
},
selectAllTrailing: (context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text('name'.tr),
SortIconButton(
onStateChanged: (state) {
switch (state) {
case SortState.asc:
key.currentState?.sort((p0, p1) {
return (p0.label as Text)
.data!
.compareTo((p1.label as Text).data!);
});
break;
case SortState.desc:
key.currentState?.sort((p0, p1) {
return (p1.label as Text)
.data!
.compareTo((p0.label as Text).data!);
});
break;
default:
key.currentState?.sort(null);
break;
}
},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text('size'.tr),
SortIconButton(
onStateChanged: (state) {
switch (state) {
case SortState.asc:
key.currentState?.sort((p0, p1) {
return calcSelectedSize(p0)
.compareTo(calcSelectedSize(p1));
});
break;
case SortState.desc:
key.currentState?.sort((p0, p1) {
return calcSelectedSize(p1)
.compareTo(calcSelectedSize(p0));
});
break;
default:
key.currentState?.sort(null);
break;
}
},
),
],
)
],
);
},
),
),
),
const SizedBox(height: 12),
!ResponsiveBuilder.isNarrow(context)
? Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
filterRow,
countRow,
],
)
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
filterRow,
const SizedBox(height: 8),
countRow,
],
),
],
);
}
int calcSelectedSize(TreeNode<int>? node) {
if (key.currentState == null) {
return widget.files
.fold(0, (previousValue, element) => previousValue + element.size);
}
final selectedFileIndexes = node == null
? key.currentState?.getSelectedValues()
: (node.value != null
? [node.value]
: key.currentState?.getChildSelectedValues(node));
if (selectedFileIndexes == null) return 0;
return selectedFileIndexes.where((e) => e != null).map((e) => e!).fold(0,
(previousValue, element) => previousValue + widget.files[element].size);
}
List<TreeNode<int>> buildTreeNodes() {
final List<TreeNode<int>> rootNodes = [];
final Map<String, TreeNode<int>> dirNodes = {};
for (var i = 0; i < widget.files.length; i++) {
final file = widget.files[i];
final parts = file.path.split('/');
String currentPath = '';
TreeNode<int>? parentNode;
// Create or get directory nodes
for (final part in parts) {
if (part.isEmpty) continue;
currentPath += '/$part';
if (!dirNodes.containsKey(currentPath)) {
final node = TreeNode<int>(
label: Text(part),
icon: Icon(
fileIcon(part, isFolder: true),
size: 18,
),
trailing: (context, node) {
final size = calcSelectedSize(node);
return size > 0
? Text(Util.fmtByte(calcSelectedSize(node)),
style: Theme.of(context).textTheme.bodySmall)
: const SizedBox(width: _sizeGapWidth);
},
children: [],
);
dirNodes[currentPath] = node;
if (parentNode == null) {
rootNodes.add(node);
} else {
parentNode.children.add(node);
}
}
parentNode = dirNodes[currentPath];
}
// Create file node using file.name
final fileNode = TreeNode<int>(
label: Text(file.name),
value: i,
icon: Icon(fileIcon(file.name, isFolder: false), size: 18),
trailing: (context, node) {
return file.size > 0
? Text(Util.fmtByte(file.size),
style: Theme.of(context).textTheme.bodySmall)
: const SizedBox(width: _sizeGapWidth);
},
isSelected: widget.initialValues.contains(i),
children: [],
);
// Add file node to parent or root
if (parentNode != null) {
parentNode.children.add(fileNode);
} else {
rootNodes.add(fileNode);
}
}
return rootNodes;
}
}
@@ -0,0 +1,102 @@
import 'package:flutter/material.dart';
import '../../icon/gopeed_icons.dart';
enum SortState { none, asc, desc }
class SortIconButton extends StatefulWidget {
final double size;
final Color? color;
final Color? activeColor;
final SortState initialState;
final Function(SortState) onStateChanged;
const SortIconButton({
Key? key,
this.size = 18.0,
this.color,
this.activeColor,
this.initialState = SortState.none,
required this.onStateChanged,
}) : super(key: key);
@override
State<SortIconButton> createState() => _SortIconState();
}
class _SortIconState extends State<SortIconButton> {
late SortState _currentState;
@override
void initState() {
super.initState();
_currentState = widget.initialState;
}
void _toggleState() {
setState(() {
switch (_currentState) {
case SortState.none:
_currentState = SortState.asc;
break;
case SortState.asc:
_currentState = SortState.desc;
break;
case SortState.desc:
_currentState = SortState.none;
break;
}
});
widget.onStateChanged(_currentState);
}
@override
Widget build(BuildContext context) {
return InkWell(
customBorder: const CircleBorder(),
onTap: _toggleState,
child: SizedBox(
width: widget.size,
height: widget.size,
child: _currentState == SortState.none
? Icon(
Gopeed.sort,
size: widget.size,
color: widget.color,
)
: Column(
children: [
ClipRect(
child: Align(
alignment: Alignment.topCenter,
heightFactor: 0.5,
child: Icon(
Gopeed.sort,
size: widget.size,
color: _currentState == SortState.asc
? (widget.activeColor ??
Theme.of(context).colorScheme.primary)
: widget.color,
),
),
),
ClipRect(
child: Align(
alignment: Alignment.bottomCenter,
heightFactor: 0.5,
child: Icon(
Gopeed.sort,
size: widget.size,
color: _currentState == SortState.desc
? (widget.activeColor ??
Theme.of(context).colorScheme.primary)
: widget.color,
),
),
),
],
),
),
);
}
}
@@ -11,7 +11,7 @@ StartConfig _$StartConfigFromJson(Map<String, dynamic> json) => StartConfig()
..address = json['address'] as String ..address = json['address'] as String
..storage = json['storage'] as String ..storage = json['storage'] as String
..storageDir = json['storageDir'] as String ..storageDir = json['storageDir'] as String
..refreshInterval = json['refreshInterval'] as int ..refreshInterval = (json['refreshInterval'] as num).toInt()
..apiToken = json['apiToken'] as String; ..apiToken = json['apiToken'] as String;
Map<String, dynamic> _$StartConfigToJson(StartConfig instance) => Map<String, dynamic> _$StartConfigToJson(StartConfig instance) =>
+14 -3
View File
@@ -8,6 +8,7 @@ const enUS = {
'on': 'On', 'on': 'On',
'off': 'Off', 'off': 'Off',
'selectAll': 'Select All', 'selectAll': 'Select All',
'select': 'Select',
'task': 'Tasks', 'task': 'Tasks',
'downloading': 'downloading', 'downloading': 'downloading',
'downloaded': 'downloaded', 'downloaded': 'downloaded',
@@ -20,8 +21,7 @@ const enUS = {
'followSettings': 'Follow Settings', 'followSettings': 'Follow Settings',
'downloadLink': 'Download Link', 'downloadLink': 'Download Link',
'downloadLinkValid': 'Please enter the download link', 'downloadLinkValid': 'Please enter the download link',
'downloadLinkHit': 'downloadLinkHit': 'Please enter the download link, one per line@append',
'Please enter the download link, HTTP/HTTPS/MAGNET supported@append',
'downloadLinkHitDesktop': ', or drag the torrent file here directly', 'downloadLinkHitDesktop': ', or drag the torrent file here directly',
'download': 'Download', 'download': 'Download',
'noFileSelected': 'Please select at least one file to continue.', 'noFileSelected': 'Please select at least one file to continue.',
@@ -65,9 +65,11 @@ const enUS = {
'developer': 'Developer', 'developer': 'Developer',
'logDirectory': 'Log Directory', 'logDirectory': 'Log Directory',
'show': 'Show', 'show': 'Show',
'continue': 'Continue',
'pause': 'Pause',
'startAll': 'Start All', 'startAll': 'Start All',
'pauseAll': 'Pause All', 'pauseAll': 'Pause All',
'deleteTask': 'Delete Task', 'deleteTask': 'Delete @count tasks',
'deleteTaskTip': 'Keep downloaded files', 'deleteTaskTip': 'Keep downloaded files',
'delete': 'Delete', 'delete': 'Delete',
'newVersionTitle': 'Discover new version @version', 'newVersionTitle': 'Discover new version @version',
@@ -103,9 +105,18 @@ const enUS = {
'seedKeep': 'Keep seeding until manually stopped', 'seedKeep': 'Keep seeding until manually stopped',
'seedRatio': 'Seed ratio', 'seedRatio': 'Seed ratio',
'seedTime': 'Seed time (minutes)', 'seedTime': 'Seed time (minutes)',
'setAsDefaultBtClient': 'Set as the default BT client',
'taskDetail': 'Task Detail', 'taskDetail': 'Task Detail',
'taskName': 'Task Name', 'taskName': 'Task Name',
'taskUrl': 'Task URL', 'taskUrl': 'Task URL',
'downloadPath': 'Download Path', 'downloadPath': 'Download Path',
'skipVerifyCert': 'Skip Certificate Verification',
'name': 'Name',
'size': 'Size',
'unknown': 'Unknown',
'fileSelectedCount': 'Files: ',
'fileSelectedSize': 'Size: ',
'httpHeaderName': 'Header Name',
'httpHeaderValue': 'Header Value',
}, },
}; };
+2 -1
View File
@@ -63,7 +63,7 @@ const esES = {
'show': 'Mostrar', 'show': 'Mostrar',
'startAll': 'Iniciar Todo', 'startAll': 'Iniciar Todo',
'pauseAll': 'Pausar Todo', 'pauseAll': 'Pausar Todo',
'deleteTask': 'Eliminar Tarea', 'deleteTask': 'Eliminar @count tareas',
'deleteTaskTip': 'Mantener archivos descargados', 'deleteTaskTip': 'Mantener archivos descargados',
'delete': 'Eliminar', 'delete': 'Eliminar',
'newVersionTitle': 'Nueva versión @version disponible', 'newVersionTitle': 'Nueva versión @version disponible',
@@ -103,5 +103,6 @@ const esES = {
'taskName': 'Nombre de la Tarea', 'taskName': 'Nombre de la Tarea',
'taskUrl': 'URL de la Tarea', 'taskUrl': 'URL de la Tarea',
'downloadPath': 'Ruta de Descarga', 'downloadPath': 'Ruta de Descarga',
'skipVerifyCert': 'Omitir Verificación de Certificado',
}, },
}; };
+2 -1
View File
@@ -51,7 +51,7 @@ const faIR = {
'effectAfterRestart': 'Effect after restart', 'effectAfterRestart': 'Effect after restart',
'startAll': 'شروع همه', 'startAll': 'شروع همه',
'pauseAll': 'توقف همه', 'pauseAll': 'توقف همه',
'deleteTask': 'پاک کردن کار', 'deleteTask': 'حذف @count کار',
'deleteTaskTip': 'فایل های دانلود شده را نگه دارد', 'deleteTaskTip': 'فایل های دانلود شده را نگه دارد',
'delete': 'پاک کردن', 'delete': 'پاک کردن',
'newVersionTitle': '@version عنوان: کشف نسخه جدید', 'newVersionTitle': '@version عنوان: کشف نسخه جدید',
@@ -61,5 +61,6 @@ const faIR = {
'thanksDesc': 'thanksDesc':
'از تمامی افرادی که در ساخت و توسعه‌ی جامعه‌ی Gopeed مشارکت کرده‌اند، سپاسگزاری می‌کنیم!', 'از تمامی افرادی که در ساخت و توسعه‌ی جامعه‌ی Gopeed مشارکت کرده‌اند، سپاسگزاری می‌کنیم!',
'browserExtension': 'فایل های دانلود شده را نگه دارد', 'browserExtension': 'فایل های دانلود شده را نگه دارد',
'skipVerifyCert': 'رد کردن تأیید گواهینامه',
} }
}; };
+2 -1
View File
@@ -61,7 +61,7 @@ const frFR = {
'show': 'Afficher', 'show': 'Afficher',
'startAll': 'Tout démarrer', 'startAll': 'Tout démarrer',
'pauseAll': 'Tout suspendre', 'pauseAll': 'Tout suspendre',
'deleteTask': 'Supprimer la tâche', 'deleteTask': 'Supprimer @count tâches',
'deleteTaskTip': 'Conserver les fichiers téléchargés', 'deleteTaskTip': 'Conserver les fichiers téléchargés',
'delete': 'Supprimer', 'delete': 'Supprimer',
'newVersionTitle': 'Nouvelle version @version disponible', 'newVersionTitle': 'Nouvelle version @version disponible',
@@ -92,5 +92,6 @@ const frFR = {
'thanksDesc': 'Merci à tous les contributeurs qui ont aidé à construire et développer la communauté Gopeed !', 'thanksDesc': 'Merci à tous les contributeurs qui ont aidé à construire et développer la communauté Gopeed !',
'browserExtension': 'Extension du navigateur', 'browserExtension': 'Extension du navigateur',
'launchAtStartup': 'Lancer au démarrage', 'launchAtStartup': 'Lancer au démarrage',
'skipVerifyCert': 'Bypass Verifikasi Sertifikat',
}, },
}; };
+14 -1
View File
@@ -17,6 +17,7 @@ const idID = {
'create': 'Membuat Tugas', 'create': 'Membuat Tugas',
'directDownload': 'Unduhan Langsung', 'directDownload': 'Unduhan Langsung',
'advancedOptions': 'Pengaturan Lanjutan', 'advancedOptions': 'Pengaturan Lanjutan',
'followSettings': 'Mengikuti Pengaturan',
'downloadLink': 'Tautan Unduhan', 'downloadLink': 'Tautan Unduhan',
'downloadLinkValid': 'Silakan masukkan tautan unduhan', 'downloadLinkValid': 'Silakan masukkan tautan unduhan',
'downloadLinkHit': 'downloadLinkHit':
@@ -35,6 +36,7 @@ const idID = {
'connections': 'Koneksi', 'connections': 'Koneksi',
'useServerCtime': 'Gunakan waktu server untuk pembuatan file', 'useServerCtime': 'Gunakan waktu server untuk pembuatan file',
'maxRunning': 'Tugas Maksimum yang Berjalan', 'maxRunning': 'Tugas Maksimum yang Berjalan',
'defaultDirectDownload': 'Pilih unduhan langsung sebagai opsi standar',
'items': '@count items', 'items': '@count items',
'subscribeTracker': 'Berlangganan Tracker', 'subscribeTracker': 'Berlangganan Tracker',
'subscribeFail': 'subscribeFail':
@@ -60,10 +62,12 @@ const idID = {
'set': 'ATUR', 'set': 'ATUR',
'portInUse': 'Port [@port] sedang digunakan, silakan ubah port', 'portInUse': 'Port [@port] sedang digunakan, silakan ubah port',
'effectAfterRestart': 'Berlaku setelah restart', 'effectAfterRestart': 'Berlaku setelah restart',
'developer': 'Pengembang',
'logDirectory': 'Direktori Log',
'show': 'Tampilkan', 'show': 'Tampilkan',
'startAll': 'Mulai Semua', 'startAll': 'Mulai Semua',
'pauseAll': 'Jeda Semua', 'pauseAll': 'Jeda Semua',
'deleteTask': 'Hapus Tugas', 'deleteTask': 'Hapus @count Tugas',
'deleteTaskTip': 'Simpan file yang terunduh', 'deleteTaskTip': 'Simpan file yang terunduh',
'delete': 'Hapus', 'delete': 'Hapus',
'newVersionTitle': 'Temukan versi batu @version', 'newVersionTitle': 'Temukan versi batu @version',
@@ -95,5 +99,14 @@ const idID = {
'Terima kasih kepada semua kontributor yang telah membantu membangun dan mengembangkan komunitas Gopeed!', 'Terima kasih kepada semua kontributor yang telah membantu membangun dan mengembangkan komunitas Gopeed!',
'browserExtension': 'Ekstensi Perambanan', 'browserExtension': 'Ekstensi Perambanan',
'launchAtStartup': 'Luncurkan saat Startup', 'launchAtStartup': 'Luncurkan saat Startup',
'seedConfig': 'Konfigurasi Seed',
'seedKeep': 'Terus seeding hingga dihentikan secara manual',
'seedRatio': 'Rasio Seed',
'seedTime': 'Waktu Seed (menit)',
'taskDetail': 'Detail Tugas',
'taskName': 'Nama Tugas',
'taskUrl': 'URL Tugas',
'downloadPath': 'Direktori Unduhan',
'skipVerifyCert': 'Lupakan verifikasi sertifikat',
}, },
}; };
+2 -1
View File
@@ -64,7 +64,7 @@ const itIT = {
'show': 'Mostra', 'show': 'Mostra',
'startAll': 'Avvia tutti', 'startAll': 'Avvia tutti',
'pauseAll': 'Mtti in pausa tutti', 'pauseAll': 'Mtti in pausa tutti',
'deleteTask': 'Elimina attività', 'deleteTask': 'Elimina @count attività',
'deleteTaskTip': 'Conserva i file scaricati', 'deleteTaskTip': 'Conserva i file scaricati',
'delete': 'Elimina', 'delete': 'Elimina',
'newVersionTitle': 'Scopri la nuova versione @version', 'newVersionTitle': 'Scopri la nuova versione @version',
@@ -96,5 +96,6 @@ const itIT = {
'Grazie a tutti i contributori che hanno contribuito a costruire e sviluppare la comunità Gopeed!', 'Grazie a tutti i contributori che hanno contribuito a costruire e sviluppare la comunità Gopeed!',
'browserExtension': 'Estensione del browser', 'browserExtension': 'Estensione del browser',
'launchAtStartup': "Lancia all'avvio", 'launchAtStartup': "Lancia all'avvio",
'skipVerifyCert': 'Salta la verifica del certificato',
}, },
}; };
+2 -1
View File
@@ -53,7 +53,7 @@ const jaJP = {
'effectAfterRestart': '再起動後の効果', 'effectAfterRestart': '再起動後の効果',
'startAll': 'すべてを開始', 'startAll': 'すべてを開始',
'pauseAll': 'すべてを一時停止', 'pauseAll': 'すべてを一時停止',
'deleteTask': 'タスクを削除', 'deleteTask': '@count タスクを削除',
'deleteTaskTip': 'ダウンロードしたファイルを保持', 'deleteTaskTip': 'ダウンロードしたファイルを保持',
'delete': '削除', 'delete': '削除',
'newVersionTitle': '新しいバージョン @version を発見する', 'newVersionTitle': '新しいバージョン @version を発見する',
@@ -62,5 +62,6 @@ const jaJP = {
'thanks': '感謝', 'thanks': '感謝',
'thanksDesc': 'Gopeedコミュニティの建設に協力してくださったすべての貢献者の方々に感謝します!', 'thanksDesc': 'Gopeedコミュニティの建設に協力してくださったすべての貢献者の方々に感謝します!',
'browserExtension': 'ブラウザ拡張機能', 'browserExtension': 'ブラウザ拡張機能',
'skipVerifyCert': '証明書の検証をスキップ',
} }
}; };
+2 -1
View File
@@ -62,7 +62,7 @@ const plPL = {
'show': 'Pokaż', 'show': 'Pokaż',
'startAll': 'Zacznij wszystkie', 'startAll': 'Zacznij wszystkie',
'pauseAll': 'Zatrzymaj wszystkie', 'pauseAll': 'Zatrzymaj wszystkie',
'deleteTask': 'Usuń zadanie', 'deleteTask': 'Usuń @count zadania',
'deleteTaskTip': 'Zachowaj pobrane pliki', 'deleteTaskTip': 'Zachowaj pobrane pliki',
'delete': 'Usuń', 'delete': 'Usuń',
'newVersionTitle': 'Sprawdź aktualizację @version', 'newVersionTitle': 'Sprawdź aktualizację @version',
@@ -94,5 +94,6 @@ const plPL = {
'Dziękuję wszystkim za pomoc przy powstawaniu aplikacji Gopeed!', 'Dziękuję wszystkim za pomoc przy powstawaniu aplikacji Gopeed!',
'browserExtension': 'Wtyczka dla przeglądarki', 'browserExtension': 'Wtyczka dla przeglądarki',
'launchAtStartup': 'Uruchom na starcie', 'launchAtStartup': 'Uruchom na starcie',
'skipVerifyCert': 'Pomiń weryfikację certyfikatu',
}, },
}; };
+2 -1
View File
@@ -57,7 +57,7 @@ const ruRU = {
'effectAfterRestart': 'Эффект после перезагрузки', 'effectAfterRestart': 'Эффект после перезагрузки',
'startAll': 'Запустить все', 'startAll': 'Запустить все',
'pauseAll': 'Приостановить все', 'pauseAll': 'Приостановить все',
'deleteTask': 'Удалить задачу', 'deleteTask': 'Удалить @count задач',
'deleteTaskTip': 'Сохранить загруженные файлы', 'deleteTaskTip': 'Сохранить загруженные файлы',
'delete': 'Удалить', 'delete': 'Удалить',
'newVersionTitle': 'Обнаружена новая версия @version', 'newVersionTitle': 'Обнаружена новая версия @version',
@@ -77,5 +77,6 @@ const ruRU = {
'thanksDesc': 'thanksDesc':
'Благодарим всех участников за их вклад в строительство и развитие сообщества Gopeed!', 'Благодарим всех участников за их вклад в строительство и развитие сообщества Gopeed!',
'browserExtension': 'Расширение браузера', 'browserExtension': 'Расширение браузера',
'skipVerifyCert': 'Пропустить проверку сертификата',
} }
}; };
+2 -1
View File
@@ -63,7 +63,7 @@ const taTA = {
'show': 'காட்டு', 'show': 'காட்டு',
'startAll': 'அனைத்தையும் தொடங்கு', 'startAll': 'அனைத்தையும் தொடங்கு',
'pauseAll': 'அனைத்தையும் நிறுத்திவை', 'pauseAll': 'அனைத்தையும் நிறுத்திவை',
'deleteTask': 'பணியை நீக்கு', 'deleteTask': 'பணிகளை நீக்கு @count',
'deleteTaskTip': 'பதிவிறக்கம் செய்யப்பட்ட கோப்புகளை வைத்திரு', 'deleteTaskTip': 'பதிவிறக்கம் செய்யப்பட்ட கோப்புகளை வைத்திரு',
'delete': 'நீக்கு', 'delete': 'நீக்கு',
'newVersionTitle': 'புதிய பதிப்பைக் கண்டறியவும் @version', 'newVersionTitle': 'புதிய பதிப்பைக் கண்டறியவும் @version',
@@ -95,5 +95,6 @@ const taTA = {
'Gopeed சமூகத்தை உருவாக்கவும் மற்றும் மேம்படுத்த உதவிய அனைத்து பங்களிப்பாளர்களுக்கும் நன்றி!', 'Gopeed சமூகத்தை உருவாக்கவும் மற்றும் மேம்படுத்த உதவிய அனைத்து பங்களிப்பாளர்களுக்கும் நன்றி!',
'browserExtension': 'உலாவி நீட்டிப்பு', 'browserExtension': 'உலாவி நீட்டிப்பு',
'launchAtStartup': 'தொடக்கத்தின் போது இயங்கு', 'launchAtStartup': 'தொடக்கத்தின் போது இயங்கு',
'skipVerifyCert': 'திருத்தி சான்று சரிபார்க்கவும்',
}, },
}; };
+17 -7
View File
@@ -17,10 +17,10 @@ const trTR = {
'create': 'Görev oluştur', 'create': 'Görev oluştur',
'directDownload': 'Doğrudan indir', 'directDownload': 'Doğrudan indir',
'advancedOptions': 'Gelişmiş ayarlar', 'advancedOptions': 'Gelişmiş ayarlar',
'followSettings': 'Ayarları takip et',
'downloadLink': 'İndirme bağlantısı', 'downloadLink': 'İndirme bağlantısı',
'downloadLinkValid': 'Lütfen indirme bağlantısını girin', 'downloadLinkValid': 'Lütfen indirme bağlantısını girin',
'downloadLinkHit': 'downloadLinkHit': 'Lütfen indirme bağlantısını girin, HTTP/HTTPS/MAGNET desteklenir@append',
'Lütfen indirme bağlantısını girin, HTTP/HTTPS/MAGNET desteklenir@append',
'downloadLinkHitDesktop': ', veya torrent dosyasını doğrudan buraya sürükleyin', 'downloadLinkHitDesktop': ', veya torrent dosyasını doğrudan buraya sürükleyin',
'download': 'İndir', 'download': 'İndir',
'noFileSelected': 'Devam etmek için lütfen en az bir dosya seçin.', 'noFileSelected': 'Devam etmek için lütfen en az bir dosya seçin.',
@@ -35,10 +35,10 @@ const trTR = {
'connections': 'Bağlantılar', 'connections': 'Bağlantılar',
'useServerCtime': 'Dosya oluşturma için sunucu saatini kullan', 'useServerCtime': 'Dosya oluşturma için sunucu saatini kullan',
'maxRunning': 'Maksimum çalışan görev sayısı', 'maxRunning': 'Maksimum çalışan görev sayısı',
'defaultDirectDownload': 'Doğrudan indir seçili olsun',
'items': '@count tane', 'items': '@count tane',
'subscribeTracker': 'İzleyiciye abone ol', 'subscribeTracker': 'İzleyiciye abone ol',
'subscribeFail': 'subscribeFail': 'Abone olunamadı, lütfen ağı kontrol edin veya daha sonra tekrar deneyin',
'Abone olunamadı, lütfen ağı kontrol edin veya daha sonra tekrar deneyin',
'update': 'Güncelle', 'update': 'Güncelle',
'updateDaily': 'Günlük olarak güncelle', 'updateDaily': 'Günlük olarak güncelle',
'lastUpdate': 'Son güncellenme tarihi: @time', 'lastUpdate': 'Son güncellenme tarihi: @time',
@@ -60,10 +60,12 @@ const trTR = {
'set': 'AYARLI', 'set': 'AYARLI',
'portInUse': 'Bağlantı noktası [@port] kullanımda, lütfen bağlantı noktasını değiştirin', 'portInUse': 'Bağlantı noktası [@port] kullanımda, lütfen bağlantı noktasını değiştirin',
'effectAfterRestart': 'Yeniden başlatma sonrası etki edecektir', 'effectAfterRestart': 'Yeniden başlatma sonrası etki edecektir',
'developer': 'Geliştirici',
'logDirectory': 'Kayıt dizini',
'show': 'Göster', 'show': 'Göster',
'startAll': 'Hepsini başlat', 'startAll': 'Hepsini başlat',
'pauseAll': 'Hepsini durdur', 'pauseAll': 'Hepsini durdur',
'deleteTask': 'Görevleri sil', 'deleteTask': '@count görevi sil',
'deleteTaskTip': 'İndirilen dosyaları sakla', 'deleteTaskTip': 'İndirilen dosyaları sakla',
'delete': 'Sil', 'delete': 'Sil',
'newVersionTitle': 'Yeni sürümü keşfet @version', 'newVersionTitle': 'Yeni sürümü keşfet @version',
@@ -91,9 +93,17 @@ const trTR = {
'username': 'Kullanıcı adı', 'username': 'Kullanıcı adı',
'password': 'Şifre', 'password': 'Şifre',
'thanks': 'Teşekkürler', 'thanks': 'Teşekkürler',
'thanksDesc': 'thanksDesc': 'Gopeed topluluğunun oluşmasına ve gelişmesine yardımcı olan tüm katılımcılara teşekkürler!',
'Gopeed topluluğunun oluşmasına ve gelişmesine yardımcı olan tüm katılımcılara teşekkürler!',
'browserExtension': 'Tarayıcı uzantısı', 'browserExtension': 'Tarayıcı uzantısı',
'launchAtStartup': 'Başlangıçta başlat', 'launchAtStartup': 'Başlangıçta başlat',
'seedConfig': 'Seed ayarları',
'seedKeep': 'Manuel durdurulana kadar seed etmeye devam et',
'seedRatio': 'Seed oranı',
'seedTime': 'Seed süresi (dakika)',
'taskDetail': 'Görev detayı',
'taskName': 'Görev adı',
'taskUrl': 'Görev URL',
'downloadPath': 'İndirme yolu',
'skipVerifyCert': 'Sertifika doğrulamasını atla',
}, },
}; };
+2 -1
View File
@@ -61,7 +61,7 @@ const viVN = {
'effectAfterRestart': 'Hiệu lực sau khi khởi động lại', 'effectAfterRestart': 'Hiệu lực sau khi khởi động lại',
'startAll': 'Bắt đầu tất cả', 'startAll': 'Bắt đầu tất cả',
'pauseAll': 'Tạm dừng tất cả', 'pauseAll': 'Tạm dừng tất cả',
'deleteTask': 'Xóa nhiệm vụ', 'deleteTask': 'Xóa @count nhiệm vụ',
'deleteTaskTip': 'Giữ các tệp đã tải về', 'deleteTaskTip': 'Giữ các tệp đã tải về',
'delete': 'Xóa', 'delete': 'Xóa',
'newVersionTitle': 'Khám phá phiên bản mới @version', 'newVersionTitle': 'Khám phá phiên bản mới @version',
@@ -89,5 +89,6 @@ const viVN = {
'thanksDesc': 'thanksDesc':
'Cảm ơn tất cả những người đóng góp đã giúp xây dựng và phát triển cộng đồng Gopeed!', 'Cảm ơn tất cả những người đóng góp đã giúp xây dựng và phát triển cộng đồng Gopeed!',
'browserExtension': 'Tiện ích mở rộng trình duyệt', 'browserExtension': 'Tiện ích mở rộng trình duyệt',
'skipVerifyCert': 'Bỏ qua xác thực chứng chỉ',
}, },
}; };
+14 -2
View File
@@ -8,6 +8,7 @@ const zhCN = {
'on': '开启', 'on': '开启',
'off': '关闭', 'off': '关闭',
'selectAll': '全选', 'selectAll': '全选',
'select': '选择',
'task': '任务', 'task': '任务',
'downloading': '下载中', 'downloading': '下载中',
'downloaded': '已完成', 'downloaded': '已完成',
@@ -20,7 +21,7 @@ const zhCN = {
'followSettings': '跟随设置', 'followSettings': '跟随设置',
'downloadLink': '下载链接', 'downloadLink': '下载链接',
'downloadLinkValid': '请输入下载链接', 'downloadLinkValid': '请输入下载链接',
'downloadLinkHit': '请输入下载链接,支持 HTTP/HTTPS/MAGNET@append', 'downloadLinkHit': '请输入下载链接,支持批量下载,每行一个链接@append',
'downloadLinkHitDesktop': ',也可以直接拖拽种子文件到此处', 'downloadLinkHitDesktop': ',也可以直接拖拽种子文件到此处',
'download': '下载', 'download': '下载',
'noFileSelected': '请至少选择一个文件下载', 'noFileSelected': '请至少选择一个文件下载',
@@ -63,9 +64,11 @@ const zhCN = {
'developer': '开发者', 'developer': '开发者',
'logDirectory': '日志目录', 'logDirectory': '日志目录',
'show': '显示', 'show': '显示',
'continue': '继续',
'pause': '暂停',
'startAll': '全部开始', 'startAll': '全部开始',
'pauseAll': '全部暂停', 'pauseAll': '全部暂停',
'deleteTask': '删除任务', 'deleteTask': '删除 @count 个任务',
'deleteTaskTip': '保留已下载的文件', 'deleteTaskTip': '保留已下载的文件',
'delete': '删除', 'delete': '删除',
'newVersionTitle': '发现新版本 @version', 'newVersionTitle': '发现新版本 @version',
@@ -100,9 +103,18 @@ const zhCN = {
'seedKeep': '持续做种直到手动停止', 'seedKeep': '持续做种直到手动停止',
'seedRatio': '做种分享率', 'seedRatio': '做种分享率',
'seedTime': '做种时间(分钟)', 'seedTime': '做种时间(分钟)',
'setAsDefaultBtClient': '设为系统默认 BT 客户端',
'taskDetail': '任务详情', 'taskDetail': '任务详情',
'taskName': '任务名称', 'taskName': '任务名称',
'taskUrl': '任务链接', 'taskUrl': '任务链接',
'downloadPath': '下载路径', 'downloadPath': '下载路径',
'skipVerifyCert': '跳过证书验证',
'name': '名称',
'size': '大小',
'unknown': '未知',
'fileSelectedCount': '文件数:',
'fileSelectedSize': '大小:',
'httpHeaderName': '请求头名称',
'httpHeaderValue': '请求头值',
} }
}; };
+14 -2
View File
@@ -8,6 +8,7 @@ const zhTW = {
'on': '開啟', 'on': '開啟',
'off': '關閉', 'off': '關閉',
'selectAll': '全選', 'selectAll': '全選',
'select': '選擇',
'task': '任務', 'task': '任務',
'downloading': '下載中', 'downloading': '下載中',
'downloaded': '已下載', 'downloaded': '已下載',
@@ -20,7 +21,7 @@ const zhTW = {
'followSettings': '跟隨設定', 'followSettings': '跟隨設定',
'downloadLink': '下載連結', 'downloadLink': '下載連結',
'downloadLinkValid': '請輸入下載連結', 'downloadLinkValid': '請輸入下載連結',
'downloadLinkHit': '請輸入下載連結,支援 HTTP/HTTPS/MAGNET@append', 'downloadLinkHit': '請輸入下載連結,支援批量下載,每行一個連結@append',
'downloadLinkHitDesktop': ',或直接拖曳種子檔到此處', 'downloadLinkHitDesktop': ',或直接拖曳種子檔到此處',
'download': '下載', 'download': '下載',
'noFileSelected': '請至少選擇一個檔案以繼續。', 'noFileSelected': '請至少選擇一個檔案以繼續。',
@@ -63,9 +64,11 @@ const zhTW = {
'developer': '開發者', 'developer': '開發者',
'logDirectory': '日誌目錄', 'logDirectory': '日誌目錄',
'show': '顯示', 'show': '顯示',
'continue': '繼續',
'pause': '暫停',
'startAll': '全部開始', 'startAll': '全部開始',
'pauseAll': '全部暫停', 'pauseAll': '全部暫停',
'deleteTask': '刪除任務', 'deleteTask': '刪除 @count 個任務',
'deleteTaskTip': '保留已下載的檔案', 'deleteTaskTip': '保留已下載的檔案',
'delete': '刪除', 'delete': '刪除',
'newVersionTitle': '發現新版本 @version', 'newVersionTitle': '發現新版本 @version',
@@ -100,9 +103,18 @@ const zhTW = {
'seedKeep': '持續做種直到手動停止', 'seedKeep': '持續做種直到手動停止',
'seedRatio': '做種分享率', 'seedRatio': '做種分享率',
'seedTime': '做種時間(分鐘)', 'seedTime': '做種時間(分鐘)',
'setAsDefaultBtClient': '設為系統預設 BT 客戶端',
'taskDetail': '任務詳情', 'taskDetail': '任務詳情',
'taskName': '任務名稱', 'taskName': '任務名稱',
'taskUrl': '任務連結', 'taskUrl': '任務連結',
'downloadPath': '下載路徑', 'downloadPath': '下載路徑',
'skipVerifyCert': '跳過憑證驗證',
'name': '名稱',
'size': '大小',
'unknown': '未知',
'fileSelectedCount': '文件數:',
'fileSelectedSize': '大小:',
'httpHeaderName': '標頭名稱',
'httpHeaderValue': '標頭值',
} }
}; };
+56
View File
@@ -0,0 +1,56 @@
/// Flutter icons Gopeed
/// Copyright (C) 2024 by original authors @ fluttericon.com, fontello.com
/// This font was generated by FlutterIcon.com, which is derived from Fontello.
///
/// To use this font, place it in your fonts/ directory and include the
/// following in your pubspec.yaml
///
/// flutter:
/// fonts:
/// - family: Gopeed
/// fonts:
/// - asset: fonts/Gopeed.ttf
///
///
/// * Entypo, Copyright (C) 2012 by Daniel Bruce
/// Author: Daniel Bruce
/// License: SIL (http://scripts.sil.org/OFL)
/// Homepage: http://www.entypo.com
/// * Zocial, Copyright (C) 2012 by Sam Collins
/// Author: Sam Collins
/// License: MIT (http://opensource.org/licenses/mit-license.php)
/// Homepage: http://zocial.smcllns.com/
/// * Font Awesome 5, Copyright (C) 2016 by Dave Gandy
/// Author: Dave Gandy
/// License: SIL (https://github.com/FortAwesome/Font-Awesome/blob/master/LICENSE.txt)
/// Homepage: http://fortawesome.github.com/Font-Awesome/
///
import 'package:flutter/widgets.dart';
class Gopeed {
Gopeed._();
static const _kFontFam = 'Gopeed';
static const String? _kFontPkg = null;
static const IconData install = IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData android = IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData cd = IconData(0xe802, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData folder_bt = IconData(0xe803, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData file_bt = IconData(0xe804, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData folder = IconData(0xf07b, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData sort = IconData(0xf0dc, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData html5 = IconData(0xf13b, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData file = IconData(0xf15b, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData file_alt = IconData(0xf15c, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData file_pdf = IconData(0xf1c1, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData file_word = IconData(0xf1c2, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData file_excel = IconData(0xf1c3, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData file_powerpoint = IconData(0xf1c4, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData file_image = IconData(0xf1c5, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData file_archive = IconData(0xf1c6, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData file_audio = IconData(0xf1c7, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData file_video = IconData(0xf1c8, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData file_code = IconData(0xf1c9, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData app_store_ios = IconData(0xf370, fontFamily: _kFontFam, fontPackage: _kFontPkg);
}
+10
View File
@@ -14,6 +14,7 @@ import 'util/locale_manager.dart';
import 'util/log_util.dart'; import 'util/log_util.dart';
import 'util/mac_secure_util.dart'; import 'util/mac_secure_util.dart';
import 'util/package_info.dart'; import 'util/package_info.dart';
import 'util/scheme_register/scheme_register.dart';
import 'util/util.dart'; import 'util/util.dart';
class Args { class Args {
@@ -81,6 +82,15 @@ Future<void> init(Args args) async {
logger.e("libgopeed init fail", e); logger.e("libgopeed init fail", e);
} }
try {
registerUrlScheme("gopeed");
if (controller.downloaderConfig.value.extra.defaultBtClient) {
registerDefaultTorrentClient();
}
} catch (e) {
logger.e("register scheme fail", e);
}
try { try {
await controller.loadDownloaderConfig(); await controller.loadDownloaderConfig();
MacSecureUtil.loadBookmark(); MacSecureUtil.loadBookmark();
+76
View File
@@ -0,0 +1,76 @@
import 'dart:core';
import 'package:checkable_treeview/checkable_treeview.dart';
import 'package:flutter/material.dart';
import '../api/model/resource.dart';
import '../app/views/file_icon.dart';
import 'util.dart';
extension ListFileInfoExtension on List<FileInfo> {
List<TreeNode<int>> toTreeNodes() {
final List<TreeNode<int>> rootNodes = [];
final Map<String, TreeNode<int>> dirNodes = {};
var nodeIndex = 0;
for (var i = 0; i < length; i++) {
final file = this[i];
final parts = file.path.split('/');
String currentPath = '';
TreeNode<int>? parentNode;
// Create or get directory nodes
for (final part in parts) {
if (part.isEmpty) continue;
currentPath += '/$part';
if (!dirNodes.containsKey(currentPath)) {
final node = TreeNode<int>(
value: nodeIndex++,
label: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(file.name),
Text(Util.fmtByte(file.size)),
],
),
icon: Icon(
fileIcon(part, isFolder: true),
size: 18,
),
children: [],
);
dirNodes[currentPath] = node;
if (parentNode == null) {
rootNodes.add(node);
} else {
parentNode.children.add(node);
}
}
parentNode = dirNodes[currentPath];
}
// Create file node using file.name
final fileNode = TreeNode<int>(
value: nodeIndex++,
label: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(file.name),
Text(Util.fmtByte(file.size)),
],
),
icon: Icon(fileIcon(file.name, isFolder: false), size: 18),
children: [],
);
// Add file node to parent or root
if (parentNode != null) {
parentNode.children.add(fileNode);
} else {
rootNodes.add(fileNode);
}
}
return rootNodes;
}
}
+22 -18
View File
@@ -21,29 +21,33 @@ class FileExplorer {
} else if (Platform.isMacOS) { } else if (Platform.isMacOS) {
Process.run('open', ['-R', filePath]); Process.run('open', ['-R', filePath]);
} else if (Platform.isLinux) { } else if (Platform.isLinux) {
if (await _isUbuntuOrDebian()) { _linuxOpen(filePath);
Process.run('xdg-open', [filePath]); }
} else if (await _isCentOS()) { }
Process.run('nautilus', ['--select', filePath]);
static Future<void> _linuxOpen(String filePath) async {
if (await Process.run('which', ['xdg-open'])
.then((value) => value.exitCode == 0)) {
final result = await Process.run('xdg-open', [filePath]);
if (result.exitCode != 0) {
_openWithFileManager(filePath);
} }
} else {
_openWithFileManager(filePath);
} }
} }
static Future<bool> _isUbuntuOrDebian() async { static Future<void> _openWithFileManager(String filePath) async {
final result = await Process.run('lsb_release', ['-i']); final desktop = Platform.environment['XDG_CURRENT_DESKTOP'];
if (result.exitCode != 0) { if (desktop == null) {
return false; throw Exception('XDG_CURRENT_DESKTOP is not set');
} }
final output = result.stdout.toString().toLowerCase(); if (desktop == 'GNOME') {
return output.contains('ubuntu') || output.contains('debian'); await Process.run('nautilus', ['--select', filePath]);
} } else if (desktop == 'KDE') {
await Process.run('dolphin', ['--select', filePath]);
static Future<bool> _isCentOS() async { } else {
final result = await Process.run('cat', ['/etc/os-release']); throw Exception('Unsupported desktop environment');
if (result.exitCode != 0) {
return false;
} }
final output = result.stdout.toString().toLowerCase();
return output.contains('centos');
} }
} }
-296
View File
@@ -1,296 +0,0 @@
findIcon(String filename) {
String res = 'file';
String ext = filename.substring(filename.lastIndexOf('.') + 1);
for (var iconMap in iconMaps) {
if (iconMap['extensions'].contains(ext)) {
res = iconMap['thumbnail'];
break;
}
}
return res;
}
const List iconMaps = [
//media
{
'extensions': [
'jpg',
'png',
'gif',
'bmp',
'jpeg',
'jpe',
'jif',
'jfif',
'jfi',
'webp',
'tiff',
'tif',
'ico',
'svg',
'webp'
],
'type': 'Image',
'thumbnail': 'file_image'
},
{
'extensions': [
'mp4',
'webm',
'mpg',
'mp2',
'mpeg',
'mpe',
'mpv',
'ocg',
'm4p',
'm4v',
'avi',
'wmv',
'mov',
'qt',
'flv',
'swf',
'mkv',
'rmvb',
'rm',
'vob',
'3gp',
'm4s',
'ts'
],
'type': 'Video',
'thumbnail': 'file_video'
},
{
'extensions': [
'mp3',
'ogg',
'ogm',
'wav',
'.aac',
'.ape',
'.flac',
'.flav',
'.m4a',
'.wma'
],
'type': 'Audio',
'thumbnail': 'file_audio'
},
//compressed
{
'extensions': [
'7z',
'brotli',
'bzip2',
'gz',
'gzip',
'rar',
'tgz',
'xz',
'zip',
'zstd',
'deb',
'msi',
'snap',
'iso',
'dmg',
'dockerfile',
'dockerignore'
],
'type': 'Archive',
'thumbnail': 'file_archive'
},
//office relative
{
'extensions': ['pdf'],
'type': 'Portable Document Format',
'thumbnail': 'file_pdf'
},
{
'extensions': ['txt', 'docb', 'rtf'],
'type': 'Document',
'thumbnail': 'doc_text'
},
{
'extensions': ['doc', 'docm', 'dot', 'dotm', 'docx'],
'type': 'Word Document',
'thumbnail': 'file_word'
},
{
'extensions': ['xlsx', 'xls', 'xlsb', 'xls', 'ods', 'fods', 'csv'],
'type': 'Excel Document',
'thumbnail': 'file_excel'
},
{
'extensions': [
'pot',
'potm',
'potx',
'ppam',
'pps',
'ppsm',
'ppsx',
'ppt',
'pptn',
'pptx'
],
'type': 'Powerpoint Document',
'thumbnail': 'file_powerpoint'
},
//windows
{
'extensions': ['exe'],
'type': 'Microsoft',
'thumbnail': 'windows'
},
//android
{
'extensions': ['apk'],
'type': 'Android',
'thumbnail': 'android'
},
//other
{
'extensions': ['lnk'],
'type': 'Shortcut',
'thumbnail': 'link_ext'
},
{
'extensions': [
'ini',
'dlc',
'config',
'conf',
'properties',
'prop',
'settings',
'option',
'props',
'toml',
'prefs',
'sln.dotsettings',
'sln.dotsettings.user',
'cfg'
],
'type': 'Settings',
'thumbnail': 'cog_alt'
},
{
'extensions': ['html', 'htm', 'xhtml', 'html_vm'],
'type': 'html',
'thumbnail': 'html5'
},
//code relative
// {
// 'extensions': ['sh', 'bat'],
// 'type': 'Batch',
// 'thumbnail': 'power_shell'
// },
// {
// 'extensions': [
// 'js',
// 'jsx',
// 'json',
// 'tsbuildinfo',
// 'json5',
// 'jsonl',
// 'ndjson'
// ],
// 'type': 'JavaScript',
// 'thumbnail': 'js'
// },
// {
// 'extensions': ['ts', 'tsx'],
// 'type': 'TypeScript',
// 'thumbnail': 'type_script_language'
// },
//
// {
// 'extensions': ['asp', 'aspx', 'php', 'jsp'],
// 'type': 'HyperText Markup Language',
// 'thumbnail': 'file_a_s_p_x'
// },
// {
// 'extensions': [
// 'accdb',
// 'db',
// 'db3',
// 'mdb',
// 'pdb',
// 'pgsql',
// 'pkb',
// 'pks',
// 'postgres',
// 'psql',
// 'sql',
// 'sqlite',
// 'sqlite3'
// ],
// 'type': 'Database',
// 'thumbnail': 'database'
// },
//
// {
// 'extensions': ['exe'],
// 'type': 'Executable',
// 'thumbnail': 'product'
// },
// {
// 'extensions': [
// 'c',
// 'h',
// 'cc',
// 'cpp',
// 'cxx',
// 'c++',
// 'cp',
// 'mm',
// 'mii',
// 'ii',
// 'dart',
// 'go'
// ],
// 'type': 'other Program language',
// 'thumbnail': 'file_code'
// },
// {
// 'extensions': ['py', 'py3', 'pyc', 'pylintrc', 'python-version'],
// 'type': 'Python Program',
// 'thumbnail': 'py'
// },
// {
// 'extensions': ['md', 'markdown', 'rst'],
// 'type': 'Markdown',
// 'thumbnail': 'mark_down_language'
// },
// {
// 'extensions': ['yml', 'yaml'],
// 'type': 'Yet Anoter Markup Language',
// 'thumbnail': 'file_y_m_l'
// },
//
// {
// 'type': 'Visual Studio',
// 'extensions': [
// 'csproj',
// 'ruleset',
// 'sln',
// 'suo',
// 'vb',
// 'vbs',
// 'vcxitems',
// 'vcxitems.filters',
// 'vcxproj',
// 'vcxproj.filters'
// ],
// 'thumbnail': 'visual_studio_for_windows'
// },
// {
// 'extensions': ['java'],
// 'type': 'Java Program',
// 'thumbnail': 'file_j_a_v_a'
// },
];
File diff suppressed because it is too large. Load diff
+10 -3
View File
@@ -8,9 +8,16 @@ void showErrorMessage(msg) {
Get.snackbar(title, msg.msg!); Get.snackbar(title, msg.msg!);
return; return;
} }
if (msg is Exception && (msg as dynamic).message is Result) { if (msg is Exception) {
Get.snackbar(title, ((msg as dynamic).message as Result).msg!); final message = (msg as dynamic).message;
return; if (message is Result) {
Get.snackbar(title, ((msg as dynamic).message as Result).msg!);
return;
}
if (message is String) {
Get.snackbar(title, message);
return;
}
} }
Get.snackbar(title, msg.toString()); Get.snackbar(title, msg.toString());
} }
@@ -0,0 +1,93 @@
import 'dart:io';
import 'package:win32_registry/win32_registry.dart';
import '../../util.dart';
doRegisterUrlScheme(String scheme) {
if (Util.isWindows()) {
final schemeKey = 'Software\\Classes\\$scheme';
final appPath = Platform.resolvedExecutable;
_upsertRegistry(
schemeKey,
'URL Protocol',
'',
);
_upsertRegistry(
'$schemeKey\\shell\\open\\command',
'',
'"$appPath" "%1"',
);
}
}
doUnregisterUrlScheme(String scheme) {
if (Util.isWindows()) {
Registry.currentUser
.deleteKey('Software\\Classes\\$scheme', recursive: true);
}
}
const _torrentRegKey = 'Software\\Classes\\.torrent';
const _torrentRegValue = 'Gopeed_torrent';
const _torrentAppRegKey = 'Software\\Classes\\$_torrentRegValue';
/// Register as the system's default torrent client
/// 1. Register the scheme "magnet"
/// 2. Register the file type ".torrent"
doRegisterDefaultTorrentClient() {
if (Util.isWindows()) {
doRegisterUrlScheme("magnet");
final appPath = Platform.resolvedExecutable;
final iconPath =
'${File(appPath).parent.path}\\data\\flutter_assets\\assets\\tray_icon\\icon.ico';
_upsertRegistry(
_torrentRegKey,
'',
_torrentRegValue,
);
_upsertRegistry(
_torrentAppRegKey,
'',
'Torrent file',
);
_upsertRegistry(
'$_torrentAppRegKey\\DefaultIcon',
'',
iconPath,
);
_upsertRegistry(
'$_torrentAppRegKey\\shell\\open\\command',
'',
'"$appPath" "file:///%1"',
);
}
}
doUnregisterDefaultTorrentClient() {
if (Util.isWindows()) {
doUnregisterUrlScheme("magnet");
Registry.currentUser.deleteKey(_torrentRegKey, recursive: true);
Registry.currentUser.deleteKey(_torrentAppRegKey, recursive: true);
}
}
// Add Windows registry key and value if not exists
_upsertRegistry(String keyPath, String valueName, String value) {
RegistryKey regKey;
try {
regKey = Registry.openPath(RegistryHive.currentUser,
path: keyPath, desiredAccessRights: AccessRights.allAccess);
} catch (e) {
regKey = Registry.currentUser.createKey(keyPath);
}
if (regKey.getValueAsString(valueName) != value) {
regKey
.createValue(RegistryValue(valueName, RegistryValueType.string, value));
}
regKey.close();
}
@@ -0,0 +1,11 @@
import 'scheme_register_stub.dart'
if (dart.library.io) 'entry/scheme_register_native.dart';
registerUrlScheme(String scheme) => doRegisterUrlScheme(scheme);
unregisterUrlScheme(String scheme) => doUnregisterUrlScheme(scheme);
registerDefaultTorrentClient() => doRegisterDefaultTorrentClient();
unregisterDefaultTorrentClient() => doUnregisterDefaultTorrentClient();
@@ -0,0 +1,7 @@
doRegisterUrlScheme(String scheme) => throw UnimplementedError();
doUnregisterUrlScheme(String scheme) => throw UnimplementedError();
doRegisterDefaultTorrentClient() => throw UnimplementedError();
doUnregisterDefaultTorrentClient() => throw UnimplementedError();
@@ -11,4 +11,5 @@ Exec=gopeed
Icon=com.gopeed.Gopeed Icon=com.gopeed.Gopeed
Type=Application Type=Application
Categories=Utility;Internet Categories=Utility;Internet
Keywords=Bittorrent;Downloader; Keywords=Bittorrent;Downloader;
MimeType=x-scheme-handler/gopeed;x-scheme-handler/magnet;application/x-bittorrent;
+11 -4
View File
@@ -17,6 +17,13 @@ G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
// Implements GApplication::activate. // Implements GApplication::activate.
static void my_application_activate(GApplication* application) { static void my_application_activate(GApplication* application) {
MyApplication* self = MY_APPLICATION(application); MyApplication* self = MY_APPLICATION(application);
GList* windows = gtk_application_get_windows(GTK_APPLICATION(application));
if (windows) {
gtk_window_present(GTK_WINDOW(windows->data));
return;
}
GtkWindow* window = GtkWindow* window =
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
@@ -48,8 +55,7 @@ static void my_application_activate(GApplication* application) {
} }
gtk_window_set_default_size(window, 1280, 720); gtk_window_set_default_size(window, 1280, 720);
//gtk_widget_show(GTK_WIDGET(window)); gtk_widget_show(GTK_WIDGET(window));
gtk_widget_realize(GTK_WIDGET(window));
g_autoptr(FlDartProject) project = fl_dart_project_new(); g_autoptr(FlDartProject) project = fl_dart_project_new();
fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
@@ -59,6 +65,7 @@ static void my_application_activate(GApplication* application) {
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
fl_register_plugins(FL_PLUGIN_REGISTRY(view)); fl_register_plugins(FL_PLUGIN_REGISTRY(view));
gtk_widget_hide(GTK_WIDGET(window));
gtk_widget_grab_focus(GTK_WIDGET(view)); gtk_widget_grab_focus(GTK_WIDGET(view));
} }
@@ -79,7 +86,7 @@ static gboolean my_application_local_command_line(GApplication* application, gch
g_application_activate(application); g_application_activate(application);
*exit_status = 0; *exit_status = 0;
return TRUE; return FALSE;
} }
// Implements GObject::dispose. // Implements GObject::dispose.
@@ -100,6 +107,6 @@ static void my_application_init(MyApplication* self) {}
MyApplication* my_application_new() { MyApplication* my_application_new() {
return MY_APPLICATION(g_object_new(my_application_get_type(), return MY_APPLICATION(g_object_new(my_application_get_type(),
"application-id", APPLICATION_ID, "application-id", APPLICATION_ID,
"flags", G_APPLICATION_NON_UNIQUE, "flags", G_APPLICATION_HANDLES_COMMAND_LINE | G_APPLICATION_HANDLES_OPEN,
nullptr)); nullptr));
} }
@@ -14,4 +14,9 @@ categories:
- Network - Network
- Utility - Utility
supported_mime_type:
- x-scheme-handler/gopeed
- x-scheme-handler/magnet
- application/x-bittorrent
startup_notify: true startup_notify: true
@@ -28,4 +28,9 @@ categories:
- Network - Network
- Utility - Utility
supported_mime_type:
- x-scheme-handler/gopeed
- x-scheme-handler/magnet
- application/x-bittorrent
startup_notify: true startup_notify: true
+11 -5
View File
@@ -3,6 +3,8 @@ PODS:
- FlutterMacOS - FlutterMacOS
- desktop_drop (0.0.1): - desktop_drop (0.0.1):
- FlutterMacOS - FlutterMacOS
- device_info_plus (0.0.1):
- FlutterMacOS
- FlutterMacOS (1.0.0) - FlutterMacOS (1.0.0)
- macos_secure_bookmarks (0.0.3): - macos_secure_bookmarks (0.0.3):
- FlutterMacOS - FlutterMacOS
@@ -28,6 +30,7 @@ PODS:
DEPENDENCIES: DEPENDENCIES:
- app_links (from `Flutter/ephemeral/.symlinks/plugins/app_links/macos`) - app_links (from `Flutter/ephemeral/.symlinks/plugins/app_links/macos`)
- desktop_drop (from `Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos`) - desktop_drop (from `Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos`)
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
- FlutterMacOS (from `Flutter/ephemeral`) - FlutterMacOS (from `Flutter/ephemeral`)
- macos_secure_bookmarks (from `Flutter/ephemeral/.symlinks/plugins/macos_secure_bookmarks/macos`) - macos_secure_bookmarks (from `Flutter/ephemeral/.symlinks/plugins/macos_secure_bookmarks/macos`)
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
@@ -44,6 +47,8 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/app_links/macos :path: Flutter/ephemeral/.symlinks/plugins/app_links/macos
desktop_drop: desktop_drop:
:path: Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos :path: Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos
device_info_plus:
:path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos
FlutterMacOS: FlutterMacOS:
:path: Flutter/ephemeral :path: Flutter/ephemeral
macos_secure_bookmarks: macos_secure_bookmarks:
@@ -68,15 +73,16 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS: SPEC CHECKSUMS:
app_links: 10e0a0ab602ffaf34d142cd4862f29d34b303b2a app_links: 10e0a0ab602ffaf34d142cd4862f29d34b303b2a
desktop_drop: 69eeff437544aa619c8db7f4481b3a65f7696898 desktop_drop: 69eeff437544aa619c8db7f4481b3a65f7696898
device_info_plus: 74e614483d05c89290d30a4c8feae15d555f7427
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
macos_secure_bookmarks: cff041c4b377fa00941bb901aaec4d27fac5edf2 macos_secure_bookmarks: cff041c4b377fa00941bb901aaec4d27fac5edf2
package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce package_info_plus: f5790acc797bf17c3e959e9d6cf162cc68ff7523
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38 screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38
share_plus: 76dd39142738f7a68dd57b05093b5e8193f220f7 share_plus: fd717ef89a2801d3491e737630112b80c310640e
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
tray_manager: 9064e219c56d75c476e46b9a21182087930baf90 tray_manager: 9064e219c56d75c476e46b9a21182087930baf90
url_launcher_macos: 5f437abeda8c85500ceb03f5c1938a8c5a705399 url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404
window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8 window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8
PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7
@@ -206,7 +206,7 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastSwiftUpdateCheck = 0920; LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 1430; LastUpgradeCheck = 1510;
ORGANIZATIONNAME = ""; ORGANIZATIONNAME = "";
TargetAttributes = { TargetAttributes = {
33CC10EC2044A3C60003C045 = { 33CC10EC2044A3C60003C045 = {
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1430" LastUpgradeVersion = "1510"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
+29 -1
View File
@@ -1,8 +1,22 @@
import Cocoa import Cocoa
import FlutterMacOS import FlutterMacOS
import app_links
@NSApplicationMain @main
class AppDelegate: FlutterAppDelegate { class AppDelegate: FlutterAppDelegate {
public override func application(_ application: NSApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([any NSUserActivityRestoring]) -> Void) -> Bool {
guard let url = AppLinks.shared.getUniversalLink(userActivity) else {
return false
}
AppLinks.shared.handleLink(link: url.absoluteString)
return false // Returning true will stop the propagation to other packages
}
override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return false return false
} }
@@ -19,4 +33,18 @@ class AppDelegate: FlutterAppDelegate {
} }
return true return true
} }
override func application(_ sender: NSApplication, openFile filename: String) -> Bool {
let url = URL(fileURLWithPath: filename)
AppLinks.shared.handleLink(link: url.absoluteString)
return false;
}
override func application(_ application: NSApplication, open urls: [URL]) {
// Only handle the first file
if(urls.isEmpty) {
return
}
AppLinks.shared.handleLink(link: urls.first!.absoluteString)
}
} }
+93 -29
View File
@@ -1,32 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string></string> <string></string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string> <string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string> <string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string> <string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string> <string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string>$(PRODUCT_COPYRIGHT)</string> <string>$(PRODUCT_COPYRIGHT)</string>
<key>NSMainNibFile</key> <key>NSMainNibFile</key>
<string>MainMenu</string> <string>MainMenu</string>
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>
<string>NSApplication</string> <string>NSApplication</string>
</dict> <key>CFBundleURLTypes</key>
</plist> <array>
<dict>
<key>CFBundleURLName</key>
<string>gopeed</string>
<key>CFBundleURLSchemes</key>
<array>
<string>gopeed</string>
</array>
</dict>
<dict>
<key>CFBundleURLName</key>
<string>magnet</string>
<key>CFBundleURLSchemes</key>
<array>
<string>magnet</string>
</array>
</dict>
</array>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>torrent</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>icon</string>
<key>CFBundleTypeName</key>
<string>BitTorrent Document</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSTypeIsPackage</key>
<false />
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>org.bittorrent.torrent</string>
</array>
</dict>
</array>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeIdentifier</key>
<string>org.bittorrent.torrent</string>
<key>UTTypeDescription</key>
<string>Torrent File</string>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>torrent</string>
</array>
<key>public.mime-type</key>
<string>application/x-bittorrent</string>
</dict>
</dict>
</array>
</dict>
</plist>
+272 -162
View File
@@ -5,26 +5,71 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: _fe_analyzer_shared name: _fe_analyzer_shared
sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051 sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "64.0.0" version: "72.0.0"
_macros:
dependency: transitive
description: dart
source: sdk
version: "0.3.2"
after_layout:
dependency: transitive
description:
name: after_layout
sha256: "95a1cb2ca1464f44f14769329fbf15987d20ab6c88f8fc5d359bd362be625f29"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
analyzer: analyzer:
dependency: transitive dependency: transitive
description: description:
name: analyzer name: analyzer
sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893" sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.2.0" version: "6.7.0"
animations:
dependency: transitive
description:
name: animations
sha256: d3d6dcfb218225bbe68e87ccf6378bbb2e32a94900722c5f81611dad089911cb
url: "https://pub.dev"
source: hosted
version: "2.0.11"
app_links: app_links:
dependency: "direct main" dependency: "direct main"
description: description:
name: app_links name: app_links
sha256: "3ced568a5d9e309e99af71285666f1f3117bddd0bd5b3317979dccc1a40cada4" sha256: "433df2e61b10519407475d7f69e470789d23d593f28224c38ba1068597be7950"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.5.1" version: "6.3.3"
app_links_linux:
dependency: transitive
description:
name: app_links_linux
sha256: f5f7173a78609f3dfd4c2ff2c95bd559ab43c80a87dc6a095921d96c05688c81
url: "https://pub.dev"
source: hosted
version: "1.0.3"
app_links_platform_interface:
dependency: transitive
description:
name: app_links_platform_interface
sha256: "05f5379577c513b534a29ddea68176a4d4802c46180ee8e2e966257158772a3f"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
app_links_web:
dependency: transitive
description:
name: app_links_web
sha256: af060ed76183f9e2b87510a9480e56a5352b6c249778d07bd2c95fc35632a555
url: "https://pub.dev"
source: hosted
version: "1.0.4"
archive: archive:
dependency: transitive dependency: transitive
description: description:
@@ -37,10 +82,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: args name: args
sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.5.0" version: "2.6.0"
async: async:
dependency: transitive dependency: transitive
description: description:
@@ -49,14 +94,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.11.0" version: "2.11.0"
autoscale_tabbarview:
dependency: "direct main"
description:
name: autoscale_tabbarview
sha256: "29449e8876185acc4763cc6cf26ffcc3f842f42f1502d5964c6d85f489ee1bc4"
url: "https://pub.dev"
source: hosted
version: "1.0.2"
badges: badges:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -93,10 +130,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build_daemon name: build_daemon
sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.1" version: "4.0.2"
build_resolvers: build_resolvers:
dependency: transitive dependency: transitive
description: description:
@@ -109,18 +146,18 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22" sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.9" version: "2.4.13"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
name: build_runner_core name: build_runner_core
sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.3.0" version: "7.3.2"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
@@ -145,6 +182,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "1.3.0"
checkable_treeview:
dependency: "direct main"
description:
name: checkable_treeview
sha256: "3d7543e2c93a968864a57ca0666fc3b5827d89d13b22cb637a427596032f9272"
url: "https://pub.dev"
source: hosted
version: "1.3.1"
checked_yaml: checked_yaml:
dependency: transitive dependency: transitive
description: description:
@@ -185,6 +230,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.18.0" version: "1.18.0"
contentsize_tabbarview:
dependency: "direct main"
description:
name: contentsize_tabbarview
sha256: "4a3cf5e3a17bb5ebe5ee56d55c518f4dde7db639334b79f874f03ecea4755b22"
url: "https://pub.dev"
source: hosted
version: "0.0.2"
context_menus: context_menus:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -193,30 +246,38 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.0" version: "1.2.0"
contextmenu_plus:
dependency: "direct main"
description:
name: contextmenu_plus
sha256: c4c3a11633ba98b6e325e80942cd6ca29269b246e307b0a43514ae4f9c8bcc7f
url: "https://pub.dev"
source: hosted
version: "1.0.1"
convert: convert:
dependency: transitive dependency: transitive
description: description:
name: convert name: convert
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.1" version: "3.1.2"
cross_file: cross_file:
dependency: transitive dependency: transitive
description: description:
name: cross_file name: cross_file
sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.3+8" version: "0.3.4+2"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
name: crypto name: crypto
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.3" version: "3.0.6"
cupertino_icons: cupertino_icons:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -229,10 +290,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: dart_style name: dart_style
sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.6" version: "2.3.7"
desktop_drop: desktop_drop:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -245,10 +306,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: device_info_plus name: device_info_plus
sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110" sha256: c4af09051b4f0508f6c1dc0a5c085bf014d5c9a4a0678ce1799c2b4d716387a0
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.1.2" version: "11.1.0"
device_info_plus_platform_interface: device_info_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -261,18 +322,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: dio name: dio
sha256: e17f6b3097b8c51b72c74c9f071a605c47bcc8893839bd66732457a5ebe73714 sha256: "5598aa796bbf4699afd5c67c0f5f6e2ed542afc956884b9cd58c306966efc260"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.5.0+1" version: "5.7.0"
dio_web_adapter: dio_web_adapter:
dependency: transitive dependency: transitive
description: description:
name: dio_web_adapter name: dio_web_adapter
sha256: "36c5b2d79eb17cdae41e974b7a8284fec631651d2a6f39a8a2ff22327e90aeac" sha256: "33259a9276d6cea88774a0000cfae0d861003497755969c92faa223108620dc8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.1" version: "2.0.0"
expandable_page_view:
dependency: transitive
description:
name: expandable_page_view
sha256: "210dc6961cfc29f7ed42867824eb699c9a4b9b198a7c04b8bdc1c05844969dc6"
url: "https://pub.dev"
source: hosted
version: "1.0.17"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:
@@ -285,10 +354,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: ffi name: ffi
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.0" version: "2.1.3"
ffigen: ffigen:
dependency: "direct dev" dependency: "direct dev"
description: description:
@@ -309,26 +378,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: file_picker name: file_picker
sha256: "9d6e95ec73abbd31ec54d0e0df8a961017e165aba1395e462e5b31ea0c165daf" sha256: "167bb619cdddaa10ef2907609feb8a79c16dfa479d3afaf960f8e223f754bf12"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.3.1" version: "8.1.2"
fixnum: fixnum:
dependency: transitive dependency: transitive
description: description:
name: fixnum name: fixnum
sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.0" version: "1.1.1"
fluent_ui: fluent_ui:
dependency: "direct main" dependency: "direct main"
description: description:
name: fluent_ui name: fluent_ui
sha256: a8c76cb501303d108cb9bd33e516da7cfd078031ff427d68eab6069bf4492a2c sha256: e7804bf3bbb3ecf9e77d5498181dc36375f5ca736ccfb3862fea17c50050eb89
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.8.7" version: "4.9.2"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@@ -346,10 +415,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_form_builder name: flutter_form_builder
sha256: "560eb5e367d81170c6ade1e7ae63ecc5167936ae2cdfaae8a345e91bce19d2f2" sha256: c278ef69b08957d484f83413f0e77b656a39b7a7bb4eb8a295da3a820ecc6545
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.2.1" version: "9.5.0"
flutter_launcher_icons: flutter_launcher_icons:
dependency: "direct dev" dependency: "direct dev"
description: description:
@@ -375,10 +444,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: flutter_plugin_android_lifecycle name: flutter_plugin_android_lifecycle
sha256: "8cf40eebf5dec866a6d1956ad7b4f7016e6c0cc69847ab946833b7d43743809f" sha256: "9b78450b89f059e96c9ebb355fa6b3df1d6b330436e0b885fb49594c41721398"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.19" version: "2.0.23"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@@ -393,10 +462,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: form_builder_validators name: form_builder_validators
sha256: "19aa5282b7cede82d0025ab031a98d0554b84aa2ba40f12013471a3b3e22bf02" sha256: c61ed7b1deecf0e1ebe49e2fa79e3283937c5a21c7e48e3ed9856a4a14e1191a
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.1.0" version: "11.0.0"
frontend_server_client: frontend_server_client:
dependency: transitive dependency: transitive
description: description:
@@ -425,10 +494,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: graphs name: graphs
sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.1" version: "2.3.2"
gtk: gtk:
dependency: transitive dependency: transitive
description: description:
@@ -449,10 +518,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: http name: http
sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.0" version: "1.2.2"
http_multi_server: http_multi_server:
dependency: transitive dependency: transitive
description: description:
@@ -473,18 +542,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: image name: image
sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8" sha256: f31d52537dc417fdcde36088fdf11d191026fd5e4fae742491ebd40e5a8bea7d
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.2.0" version: "4.3.0"
intl: intl:
dependency: transitive dependency: transitive
description: description:
name: intl name: intl
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.18.1" version: "0.19.0"
io: io:
dependency: transitive dependency: transitive
description: description:
@@ -521,10 +590,34 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: launch_at_startup name: launch_at_startup
sha256: "93fc5638e088290004fae358bae691486673d469957d461d9dae5b12248593eb" sha256: "1f8a75520913d1038630049e6c44a2575a23ffd28cc8b14fdf37401d1d21de84"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.2" version: "0.3.1"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
url: "https://pub.dev"
source: hosted
version: "10.0.5"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
url: "https://pub.dev"
source: hosted
version: "3.0.5"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
lecle_downloads_path_provider: lecle_downloads_path_provider:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -561,10 +654,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: logging name: logging
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.0" version: "1.3.0"
logging_appenders: logging_appenders:
dependency: transitive dependency: transitive
description: description:
@@ -573,14 +666,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.1" version: "1.3.1"
lottie:
dependency: "direct main"
description:
name: lottie
sha256: "893da7a0022ec2fcaa616f34529a081f617e86cc501105b856e5a3184c58c7c2"
url: "https://pub.dev"
source: hosted
version: "1.4.3"
macos_secure_bookmarks: macos_secure_bookmarks:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -589,22 +674,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.1" version: "0.2.1"
macros:
dependency: transitive
description:
name: macros
sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
url: "https://pub.dev"
source: hosted
version: "0.1.2-main.4"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.12.16" version: "0.12.16+1"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
name: material_color_utilities name: material_color_utilities
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.0" version: "0.11.1"
math_expressions: math_expressions:
dependency: transitive dependency: transitive
description: description:
@@ -625,26 +718,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.10.0" version: "1.15.0"
mime: mime:
dependency: transitive dependency: transitive
description: description:
name: mime name: mime
sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.5" version: "2.0.0"
open_filex: open_filex:
dependency: "direct main" dependency: "direct main"
description: description:
name: open_filex name: open_filex
sha256: "74e2280754cf8161e860746c3181db2c996d6c1909c7057b738ede4a469816b8" sha256: ba425ea49affd0a98a234aa9344b9ea5d4c4f7625a1377961eae9fe194c3d523
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.4.0" version: "4.5.0"
package_config: package_config:
dependency: transitive dependency: transitive
description: description:
@@ -657,26 +750,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: package_info_plus name: package_info_plus
sha256: "7e76fad405b3e4016cd39d08f455a4eb5199723cf594cd1b8916d47140d93017" sha256: df3eb3e0aed5c1107bb0fdb80a8e82e778114958b1c5ac5644fb1ac9cae8a998
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.2.0" version: "8.1.0"
package_info_plus_platform_interface: package_info_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: package_info_plus_platform_interface name: package_info_plus_platform_interface
sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6" sha256: ac1f4a4847f1ade8e6a87d1f39f5d7c67490738642e2542f559ec38c37489a66
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.1" version: "3.0.1"
path: path:
dependency: "direct main" dependency: "direct main"
description: description:
name: path name: path
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.8.3" version: "1.9.0"
path_provider: path_provider:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -689,18 +782,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: path_provider_android name: path_provider_android
sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.4" version: "2.2.12"
path_provider_foundation: path_provider_foundation:
dependency: transitive dependency: transitive
description: description:
name: path_provider_foundation name: path_provider_foundation
sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.2" version: "2.4.0"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
@@ -737,10 +830,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: permission_handler_android name: permission_handler_android
sha256: "76e4ab092c1b240d31177bb64d2b0bea43f43d0e23541ec866151b9f7b2490fa" sha256: "71bbecfee799e65aff7c744761a57e817e73b738fedf62ab7afd5593da21f9f1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "12.0.12" version: "12.0.13"
permission_handler_apple: permission_handler_apple:
dependency: transitive dependency: transitive
description: description:
@@ -753,25 +846,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: permission_handler_html name: permission_handler_html
sha256: "54bf176b90f6eddd4ece307e2c06cf977fb3973719c35a93b85cc7093eb6070d" sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.1" version: "0.1.3+5"
permission_handler_platform_interface: permission_handler_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: permission_handler_platform_interface name: permission_handler_platform_interface
sha256: fe0ffe274d665be8e34f9c59705441a7d248edebbe5d9e3ec2665f88b79358ea sha256: e9c8eadee926c4532d0305dff94b85bf961f16759c3af791486613152af4b4f9
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.2.2" version: "4.2.3"
permission_handler_windows: permission_handler_windows:
dependency: transitive dependency: "direct overridden"
description: description:
name: permission_handler_windows path: permission_handler_windows
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" ref: "35fc72c30262b9b49e1965b48a7524b44ba9daa7"
url: "https://pub.dev" resolved-ref: "35fc72c30262b9b49e1965b48a7524b44ba9daa7"
source: hosted url: "https://github.com/monkeyWie/flutter-permission-handler.git"
source: git
version: "0.2.1" version: "0.2.1"
petitparser: petitparser:
dependency: transitive dependency: transitive
@@ -785,10 +879,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: platform name: platform
sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.5" version: "3.1.6"
plugin_platform_interface: plugin_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -825,10 +919,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: quiver name: quiver
sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 sha256: ea0b925899e64ecdfbf9c7becb60d5b50e706ade44a85b2363be2a22d88117d2
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.1" version: "3.2.2"
recase: recase:
dependency: transitive dependency: transitive
description: description:
@@ -873,50 +967,50 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: share_plus name: share_plus
sha256: "3ef39599b00059db0990ca2e30fca0a29d8b37aae924d60063f8e0184cf20900" sha256: "334fcdf0ef9c0df0e3b428faebcac9568f35c747d59831474b2fc56e156d244e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.2.2" version: "10.1.0"
share_plus_platform_interface: share_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: share_plus_platform_interface name: share_plus_platform_interface
sha256: "251eb156a8b5fa9ce033747d73535bf53911071f8d3b6f4f0b578505ce0d4496" sha256: c57c0bbfec7142e3a0f55633be504b796af72e60e3c791b44d5a017b985f7a48
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.4.0" version: "5.0.1"
shared_preferences: shared_preferences:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences name: shared_preferences
sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180 sha256: "746e5369a43170c25816cc472ee016d3a66bc13fcf430c0bc41ad7b4b2922051"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.3" version: "2.3.2"
shared_preferences_android: shared_preferences_android:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_android name: shared_preferences_android
sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2" sha256: "3b9febd815c9ca29c9e3520d50ec32f49157711e143b7a4ca039eb87e8ade5ab"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.2" version: "2.3.3"
shared_preferences_foundation: shared_preferences_foundation:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_foundation name: shared_preferences_foundation
sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c" sha256: "07e050c7cd39bad516f8d64c455f04508d09df104be326d8c02551590a0d513d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.5" version: "2.5.3"
shared_preferences_linux: shared_preferences_linux:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_linux name: shared_preferences_linux
sha256: "2ba0510d3017f91655b7543e9ee46d48619de2a2af38e5c790423f7007c7ccc1" sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.0" version: "2.4.1"
shared_preferences_platform_interface: shared_preferences_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -929,18 +1023,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_web name: shared_preferences_web
sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21" sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.2" version: "2.4.2"
shared_preferences_windows: shared_preferences_windows:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_windows name: shared_preferences_windows
sha256: "398084b47b7f92110683cac45c6dc4aae853db47e470e5ddcd52cab7f7196ab2" sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.0" version: "2.4.1"
shelf: shelf:
dependency: transitive dependency: transitive
description: description:
@@ -953,10 +1047,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: shelf_web_socket name: shelf_web_socket
sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.4" version: "2.0.0"
shortid: shortid:
dependency: transitive dependency: transitive
description: description:
@@ -1054,10 +1148,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.6.1" version: "0.7.2"
timing: timing:
dependency: transitive dependency: transitive
description: description:
@@ -1078,66 +1172,66 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: tray_manager name: tray_manager
sha256: c9a63fd88bd3546287a7eb8ccc978d707eef82c775397af17dda3a4f4c039e64 sha256: bdc3ac6c36f3d12d871459e4a9822705ce5a1165a17fa837103bc842719bf3f7
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.3" version: "0.2.4"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
name: typed_data name: typed_data
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.2" version: "1.4.0"
uri_to_file: uri_to_file:
dependency: "direct main" dependency: "direct main"
description: description:
name: uri_to_file name: uri_to_file
sha256: "84afd633b1492fc465c768141e1a29edd519061bf99935b6b4d0d5de8ec7c108" sha256: cbbb38f975d22311efacc9a53cdcb806708606666d8092314b81c5cb7983b700
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.0" version: "1.0.0"
url_launcher: url_launcher:
dependency: "direct main" dependency: "direct main"
description: description:
name: url_launcher name: url_launcher
sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.0" version: "6.3.1"
url_launcher_android: url_launcher_android:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_android name: url_launcher_android
sha256: "17cd5e205ea615e2c6ea7a77323a11712dffa0720a8a90540db57a01347f9ad9" sha256: "8fc3bae0b68c02c47c5c86fa8bfa74471d42687b0eded01b78de87872db745e2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.2" version: "6.3.12"
url_launcher_ios: url_launcher_ios:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_ios name: url_launcher_ios
sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.2.4" version: "6.3.1"
url_launcher_linux: url_launcher_linux:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_linux name: url_launcher_linux
sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.1" version: "3.2.0"
url_launcher_macos: url_launcher_macos:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_macos name: url_launcher_macos
sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de" sha256: "769549c999acdb42b8bcfa7c43d72bf79a382ca7441ab18a808e101149daf672"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.0" version: "3.2.1"
url_launcher_platform_interface: url_launcher_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -1150,26 +1244,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_web name: url_launcher_web
sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.3" version: "2.3.3"
url_launcher_windows: url_launcher_windows:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_windows name: url_launcher_windows
sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185" sha256: "44cf3aabcedde30f2dba119a9dea3b0f2672fbe6fa96e85536251d678216b3c4"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.2" version: "3.1.3"
uuid: uuid:
dependency: transitive dependency: transitive
description: description:
name: uuid name: uuid
sha256: "83d37c7ad7aaf9aa8e275490669535c8080377cfa7a7004c24dfac53afffaa90" sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.4.2" version: "4.5.1"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:
@@ -1178,6 +1272,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.1.4"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
url: "https://pub.dev"
source: hosted
version: "14.2.5"
watcher: watcher:
dependency: transitive dependency: transitive
description: description:
@@ -1190,50 +1292,58 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: web name: web
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.0" version: "1.1.0"
web_socket:
dependency: transitive
description:
name: web_socket
sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
url: "https://pub.dev"
source: hosted
version: "0.1.6"
web_socket_channel: web_socket_channel:
dependency: transitive dependency: transitive
description: description:
name: web_socket_channel name: web_socket_channel
sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.0" version: "3.0.1"
win32: win32:
dependency: transitive dependency: transitive
description: description:
name: win32 name: win32
sha256: "5a751eddf9db89b3e5f9d50c20ab8612296e4e8db69009788d6c8b060a84191c" sha256: "2294c64768987ea280b43a3d8357d42d5679f3e2b5b69b602be45b2abbd165b0"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.1.4" version: "5.6.1"
win32_registry: win32_registry:
dependency: transitive dependency: "direct main"
description: description:
name: win32_registry name: win32_registry
sha256: "1c52f994bdccb77103a6231ad4ea331a244dbcef5d1f37d8462f713143b0bfae" sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.0" version: "1.1.5"
window_manager: window_manager:
dependency: "direct main" dependency: "direct main"
description: description:
name: window_manager name: window_manager
sha256: "8699323b30da4cdbe2aa2e7c9de567a6abd8a97d9a5c850a3c86dcd0b34bbfbf" sha256: ab8b2a7f97543d3db2b506c9d875e637149d48ee0c6a5cb5f5fd6e0dac463792
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.9" version: "0.4.2"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
name: xdg_directories name: xdg_directories
sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.4" version: "1.1.0"
xml: xml:
dependency: transitive dependency: transitive
description: description:
@@ -1259,5 +1369,5 @@ packages:
source: hosted source: hosted
version: "2.2.1" version: "2.2.1"
sdks: sdks:
dart: ">=3.2.0 <4.0.0" dart: ">=3.5.0 <4.0.0"
flutter: ">=3.16.0" flutter: ">=3.24.0"
+36 -28
View File
@@ -15,10 +15,10 @@ 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. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.6.0+1 version: 1.6.7+1
environment: environment:
sdk: '>=3.0.0 <4.0.0' sdk: ">=3.0.0 <4.0.0"
# Dependencies specify other packages that your package needs in order to work. # Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions # To automatically upgrade your package dependencies to the latest versions
@@ -35,40 +35,48 @@ dependencies:
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2 cupertino_icons: ^1.0.2
get: ^4.6.5 get: ^4.6.6
lottie: ^1.4.2
styled_widget: ^0.4.0+3 styled_widget: ^0.4.0+3
context_menus: ^1.0.2 context_menus: ^1.2.0
json_annotation: ^4.8.1 json_annotation: ^4.8.1
dio: ^5.2.1 dio: ^5.2.1
path_provider: ^2.1.1 path_provider: ^2.1.4
file_picker: 5.3.1 file_picker: ^8.1.2
macos_secure_bookmarks: ^0.2.1 macos_secure_bookmarks: ^0.2.1
rounded_loading_button_plus: ^3.0.1 rounded_loading_button_plus: ^3.0.1
url_launcher: ^6.1.6 url_launcher: ^6.3.1
logger: ^1.3.0 logger: ^1.4.0
desktop_drop: ^0.4.3 desktop_drop: ^0.4.4
package_info_plus: ^4.0.0 package_info_plus: ^8.1.0
fluent_ui: ^4.4.0 fluent_ui: ^4.9.2
path: any path: ^1.9.0
badges: ^3.0.3 badges: ^3.0.3
app_links: ^3.4.2 app_links: ^6.3.3
uri_to_file: ^0.2.0 uri_to_file: ^1.0.0
window_manager: ^0.3.4 window_manager: ^0.4.2
autoscale_tabbarview: ^1.0.2 share_plus: ^10.1.0
share_plus: ^7.1.0 flutter_form_builder: ^9.5.0
flutter_form_builder: ^9.1.1 form_builder_validators: ^11.0.0
form_builder_validators: ^9.0.0
flutter_foreground_task: ^8.2.0 flutter_foreground_task: ^8.2.0
open_filex: ^4.3.4 open_filex: ^4.5.0
tray_manager: ^0.2.3 tray_manager: ^0.2.4
lecle_downloads_path_provider: ^0.0.2+8 lecle_downloads_path_provider: ^0.0.2+8
hive: ^2.2.3 hive: ^2.2.3
launch_at_startup: ^0.2.2 launch_at_startup: ^0.3.1
args: ^2.5.0 args: ^2.5.0
toggle_switch: ^2.3.0 toggle_switch: ^2.3.0
permission_handler: ^11.3.1 permission_handler: ^11.3.1
device_info_plus: ^9.1.2 device_info_plus: ^11.1.0
checkable_treeview: ^1.3.1
contextmenu_plus: ^1.0.1
contentsize_tabbarview: ^0.0.2
win32_registry: ^1.1.5
dependency_overrides:
permission_handler_windows:
git:
url: https://github.com/monkeyWie/flutter-permission-handler.git
ref: 35fc72c30262b9b49e1965b48a7524b44ba9daa7
path: permission_handler_windows
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
@@ -112,9 +120,9 @@ flutter:
# list giving the asset and other descriptors for the font. For # list giving the asset and other descriptors for the font. For
# example: # example:
fonts: fonts:
- family: FontAwesome - family: Gopeed
fonts: fonts:
- asset: assets/fonts/FontAwesome.ttf - asset: assets/fonts/Gopeed.ttf
# - family: Trajan Pro # - family: Trajan Pro
# fonts: # fonts:
# - asset: fonts/TrajanPro.ttf # - asset: fonts/TrajanPro.ttf
@@ -144,7 +152,7 @@ flutter_icons:
ffigen: ffigen:
name: LibgopeedBind name: LibgopeedBind
description: Bindings to gopeed library. description: Bindings to gopeed library.
output: 'lib/core/ffi/libgopeed_bind.dart' output: "lib/core/ffi/libgopeed_bind.dart"
headers: headers:
entry-points: entry-points:
- 'include/libgopeed.h' - "include/libgopeed.h"
+5 -25
View File
@@ -18,41 +18,21 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible"> <meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="A new Flutter project."> <meta name="description" content="A modern download manager.">
<!-- iOS meta tags & icons --> <!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="gopeed"> <meta name="apple-mobile-web-app-title" content="Gopeed">
<link rel="apple-touch-icon" href="icons/Icon-192.png"> <link rel="apple-touch-icon" href="icons/Icon-192.png">
<!-- Favicon --> <!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png"/> <link rel="icon" type="image/png" href="favicon.png"/>
<title>gopeed</title> <title>Gopeed</title>
<link rel="manifest" href="manifest.json"> <link rel="manifest" href="manifest.json">
<script>
// The value below is injected by flutter build, do not touch.
var serviceWorkerVersion = null;
</script>
<!-- This script adds the flutter initialization JS code -->
<script src="flutter.js" defer></script>
</head> </head>
<body> <body>
<script> <script src="flutter_bootstrap.js" async></script>
window.addEventListener('load', function(ev) {
// Download main.dart.js
_flutter.loader.loadEntrypoint({
serviceWorker: {
serviceWorkerVersion: serviceWorkerVersion,
}
}).then(function(engineInitializer) {
return engineInitializer.initializeEngine();
}).then(function(appRunner) {
return appRunner.runApp();
});
});
</script>
</body> </body>
</html> </html>
+40
View File
@@ -4,9 +4,49 @@
#include "flutter_window.h" #include "flutter_window.h"
#include "utils.h" #include "utils.h"
#include "app_links/app_links_plugin_c_api.h"
bool SendAppLinkToInstance(const std::wstring& title) {
// Find our exact window
HWND hwnd = ::FindWindow(L"FLUTTER_RUNNER_WIN32_WINDOW", title.c_str());
if (hwnd) {
// Dispatch new link to current window
SendAppLink(hwnd);
// (Optional) Restore our window to front in same state
WINDOWPLACEMENT place = { sizeof(WINDOWPLACEMENT) };
GetWindowPlacement(hwnd, &place);
switch(place.showCmd) {
case SW_SHOWMAXIMIZED:
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
break;
case SW_SHOWMINIMIZED:
ShowWindow(hwnd, SW_RESTORE);
break;
default:
ShowWindow(hwnd, SW_NORMAL);
break;
}
SetWindowPos(0, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);
SetForegroundWindow(hwnd);
// END (Optional) Restore
// Window has been found, don't create another one.
return true;
}
return false;
}
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
_In_ wchar_t *command_line, _In_ int show_command) { _In_ wchar_t *command_line, _In_ int show_command) {
if (SendAppLinkToInstance(L"gopeed")) {
return EXIT_SUCCESS;
}
HWND hwnd = ::FindWindow(L"FLUTTER_RUNNER_WIN32_WINDOW", L"gopeed"); HWND hwnd = ::FindWindow(L"FLUTTER_RUNNER_WIN32_WINDOW", L"gopeed");
if (hwnd != NULL) { if (hwnd != NULL) {
::ShowWindow(hwnd, SW_NORMAL); ::ShowWindow(hwnd, SW_NORMAL);