Compare commits
261 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
855d31f6df | ||
|
|
2995a28d5c | ||
|
|
f12000df52 | ||
|
|
3192f1bdc9 | ||
|
|
cee99c88f9 | ||
|
|
59e3bb07e7 | ||
|
|
eb76a004cc | ||
|
|
bba26afbba | ||
|
|
ce6846ba8f | ||
|
|
cd152c75e8 | ||
|
|
6794c380ad | ||
|
|
dad2daee4a | ||
|
|
3cdc627ea6 | ||
|
|
6c50b0f816 | ||
|
|
2ea8a024d1 | ||
|
|
a7a941a4d0 | ||
|
|
7c5b56cada | ||
|
|
9bee63241e | ||
|
|
91ff8060ca | ||
|
|
a96771685c | ||
|
|
e61c0ebf34 | ||
|
|
56843f07d2 | ||
|
|
e681aceb29 | ||
|
|
7891ed19e1 | ||
|
|
95c2d8efc4 | ||
|
|
3155054531 | ||
|
|
04e8498edb | ||
|
|
69ca8dbf97 | ||
|
|
b479f50005 | ||
|
|
2cb21bea17 | ||
|
|
63c421ae10 | ||
|
|
9fadf3a627 | ||
|
|
ba7c17513a | ||
|
|
8d227944cf | ||
|
|
a13d689b8c | ||
|
|
5f0b9781c6 | ||
|
|
02a36e997e | ||
|
|
9374b9d382 | ||
|
|
6ed3e71536 | ||
|
|
bbdf0955db | ||
|
|
a8cd68fce6 | ||
|
|
55a65a54dc | ||
|
|
90c1c10253 | ||
|
|
377a0fcb98 | ||
|
|
3f70e4ef91 | ||
|
|
17434ecaad | ||
|
|
a2daed0739 | ||
|
|
2406e0ddc8 | ||
|
|
5c6094c2f1 | ||
|
|
d3bddc0e54 | ||
|
|
8578063b0a | ||
|
|
27be876501 | ||
|
|
ab2721716a | ||
|
|
f26c591572 | ||
|
|
4d70fa086d | ||
|
|
f75a8efd8d | ||
|
|
10487caa30 | ||
|
|
6bf96a5f3a | ||
|
|
1a8b19ce43 | ||
|
|
6e2f0a0872 | ||
|
|
6d8b66cf52 | ||
|
|
8e2385448b | ||
|
|
d6de8b34a1 | ||
|
|
ad6a3b70aa | ||
|
|
782492857f | ||
|
|
f7c293084c | ||
|
|
90fdca1d1e | ||
|
|
b9b09778ad | ||
|
|
7f2833c4ac | ||
|
|
984f5a66d3 | ||
|
|
85af1a555f | ||
|
|
3ece7f30b4 | ||
|
|
5fffc3d48a | ||
|
|
133191685f | ||
|
|
b6013321ba | ||
|
|
fe46619a57 | ||
|
|
e7f4d6c0b3 | ||
|
|
3df1b699c5 | ||
|
|
ec409a5c93 | ||
|
|
c5bde3cde6 | ||
|
|
cb3a220254 | ||
|
|
e8e741a908 | ||
|
|
0f06a45b9a | ||
|
|
dbf573c8ec | ||
|
|
d1ff298cfa | ||
|
|
7fb7c57367 | ||
|
|
b6566e15fa | ||
|
|
6583904bd9 | ||
|
|
a34d2e4ad9 | ||
|
|
c65f47f1d7 | ||
|
|
262864fcd4 | ||
|
|
930576e28c | ||
|
|
352f604b81 | ||
|
|
a668731b46 | ||
|
|
2e2fe928b3 | ||
|
|
589381ef6c | ||
|
|
d1f0fe7116 | ||
|
|
0a91fcfccf | ||
|
|
a55f16e50d | ||
|
|
6a747f8ac1 | ||
|
|
f557af562f | ||
|
|
e84bae7d22 | ||
|
|
7ba581a2cd | ||
|
|
dbefebc7d8 | ||
|
|
010e1b89c5 | ||
|
|
4f6014a2b4 | ||
|
|
9d4197b237 | ||
|
|
8e481132f3 | ||
|
|
8347005fc4 | ||
|
|
8bc3c5aef2 | ||
|
|
5d41b1e94a | ||
|
|
32153bb2b1 | ||
|
|
3813678469 | ||
|
|
da8b528856 | ||
|
|
209847bf97 | ||
|
|
ddb110764e | ||
|
|
827247f4f7 | ||
|
|
ccd5803ec1 | ||
|
|
3ebf2f920e | ||
|
|
ab96a2c78a | ||
|
|
f0f7766005 | ||
|
|
12f0e8f37b | ||
|
|
58e87b0b6b | ||
|
|
4ada0a3838 | ||
|
|
c8ac9985bb | ||
|
|
07c65e816c | ||
|
|
e60fa3b9ce | ||
|
|
903bdb7a8f | ||
|
|
bde5c534d4 | ||
|
|
434baee9c0 | ||
|
|
1a0ba73dc1 | ||
|
|
13930669c5 | ||
|
|
0c9d18eeb1 | ||
|
|
c43e92211e | ||
|
|
0b2d69b118 | ||
|
|
983c4c7604 | ||
|
|
9b95a6df53 | ||
|
|
c4bb1907bf | ||
|
|
79067b7092 | ||
|
|
f4cd650f65 | ||
|
|
9b2a7d0860 | ||
|
|
d47bfacad7 | ||
|
|
a576c22543 | ||
|
|
a8aa53f6b4 | ||
|
|
ac0e4b9a7e | ||
|
|
6065338b49 | ||
|
|
a70d8148a0 | ||
|
|
7f5775c616 | ||
|
|
5c05075d36 | ||
|
|
01a68e3163 | ||
|
|
753ccd77be | ||
|
|
917d72cbe6 | ||
|
|
b7f3f70bce | ||
|
|
d0c00ff79d | ||
|
|
da494356f2 | ||
|
|
c8719a7421 | ||
|
|
1ad022a1fb | ||
|
|
e9b01c1658 | ||
|
|
3674fcf2e9 | ||
|
|
35994122b9 | ||
|
|
2323bee305 | ||
|
|
d48f99eb31 | ||
|
|
1576c680ca | ||
|
|
0b46d66ad0 | ||
|
|
f5605aa6a5 | ||
|
|
369bd805c9 | ||
|
|
61f1852db1 | ||
|
|
1a2b91b78a | ||
|
|
5b27e4a2c9 | ||
|
|
882f4aa252 | ||
|
|
e7a4964400 | ||
|
|
62e487abfe | ||
|
|
1f604460a0 | ||
|
|
8a53d80502 | ||
|
|
efcf98d0f8 | ||
|
|
b5ecd66d8e | ||
|
|
e1bacd5b77 | ||
|
|
179d1f7f05 | ||
|
|
e57f90a700 | ||
|
|
8a75924652 | ||
|
|
cbbcce6997 | ||
|
|
cbad0edc81 | ||
|
|
67513abc01 | ||
|
|
f93d53f574 | ||
|
|
32b014a283 | ||
|
|
50de5b676a | ||
|
|
799dea18be | ||
|
|
45e14398f3 | ||
|
|
120dbb257c | ||
|
|
98a8e5f853 | ||
|
|
912ec9927c | ||
|
|
00d80a603c | ||
|
|
6c0fc19381 | ||
|
|
8147b3611a | ||
|
|
8f7f231000 | ||
|
|
6360e4f553 | ||
|
|
dba37f3563 | ||
|
|
42ff7dcae3 | ||
|
|
d8878896e7 | ||
|
|
1723bc6af0 | ||
|
|
274ece410a | ||
|
|
fce3c6cff3 | ||
|
|
a613d96f79 | ||
|
|
8686d3145a | ||
|
|
c2ca657450 | ||
|
|
8c6ba4dc76 | ||
|
|
0bb41b8f90 | ||
|
|
eeacf5885d | ||
|
|
0bb67ad0fb | ||
|
|
e87bc27904 | ||
|
|
4de82acadf | ||
|
|
67921755d3 | ||
|
|
4600cb0715 | ||
|
|
63647166b0 | ||
|
|
24b4789f16 | ||
|
|
8e60860365 | ||
|
|
efe997e73d | ||
|
|
2f93efc1a5 | ||
|
|
cdcc7ff250 | ||
|
|
bd0b4c0857 | ||
|
|
1ae267e610 | ||
|
|
d2bf485db5 | ||
|
|
9b436a81af | ||
|
|
48ed904863 | ||
|
|
11a63612e4 | ||
|
|
e94bafe100 | ||
|
|
ff55b24bbb | ||
|
|
de11c7bfda | ||
|
|
e33e2b85f1 | ||
|
|
ff89270976 | ||
|
|
c63cb94e28 | ||
|
|
fad16516f0 | ||
|
|
d20f94c449 | ||
|
|
1d7fd54c6a | ||
|
|
06dd83f99e | ||
|
|
0914a832d7 | ||
|
|
2de0ca8130 | ||
|
|
db75c7f623 | ||
|
|
219803f01b | ||
|
|
c8a9468e3a | ||
|
|
27da4d7534 | ||
|
|
c8717de5f7 | ||
|
|
0508be5171 | ||
|
|
199472e4af | ||
|
|
37b86711a7 | ||
|
|
92c3ca0f9d | ||
|
|
42d2ca108a | ||
|
|
481f9165e4 | ||
|
|
e75e10ba5e | ||
|
|
0c8cf2d15b | ||
|
|
dbc5db4e98 | ||
|
|
c7eb98263a | ||
|
|
dc5630d3af | ||
|
|
e76c0b7e0f | ||
|
|
cc7b4b9578 | ||
|
|
f7f3a6b254 | ||
|
|
326fbd1d73 | ||
|
|
12344805f3 | ||
|
|
0eee1f8c16 | ||
|
|
64dc7a79b8 | ||
|
|
f9e5bf4953 |
@@ -1,21 +0,0 @@
|
||||
env:
|
||||
browser: true
|
||||
es2021: true
|
||||
node: true
|
||||
extends: eslint:recommended
|
||||
parserOptions:
|
||||
ecmaVersion: latest
|
||||
sourceType: module
|
||||
rules:
|
||||
indent:
|
||||
- error
|
||||
- tab
|
||||
linebreak-style:
|
||||
- error
|
||||
- unix
|
||||
quotes:
|
||||
- error
|
||||
- double
|
||||
semi:
|
||||
- error
|
||||
- never
|
||||
2
.github/FUNDING.yml
vendored
@@ -1 +1 @@
|
||||
liberapay: barbapapa
|
||||
custom: https://paypal.me/onderkin
|
||||
|
||||
20
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Report a bug in this project
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of the bug.
|
||||
|
||||
**Is your bug report related to another bug report? Please describe.**
|
||||
If yes, the issue number and an explanation of why the bug is related to this one.
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the bug report here.
|
||||
23
.github/ISSUE_TEMPLATE/download_problem.md
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: Download problem
|
||||
about: Report a difficulty in downloading a game
|
||||
title: ''
|
||||
labels: question
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the game you are trying to download**
|
||||
A clear and concise description of the bug.
|
||||
**App ID:** <app id>
|
||||
**Depot ID:** <depot id>
|
||||
**Manifest ID:** <manifest id>
|
||||
|
||||
**Show the error that DepotDownloader produces**
|
||||
A screenshot or a copy-paste wrapped in a code-block (` ``` `) of the DepotDownloader terminal output
|
||||
|
||||
**Do you own the game?**
|
||||
If no, you probably can't download the game. You must own the game on Steam to be able to download it.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the issue here.
|
||||
10
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -2,19 +2,19 @@
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
labels: feature
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
||||
21
.github/dependabot.yml
vendored
@@ -3,4 +3,23 @@ updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
ignore:
|
||||
- dependency-name: "*"
|
||||
update-types: ["version-update:semver-major"]
|
||||
groups:
|
||||
npm-deps:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
- package-ecosystem: "cargo"
|
||||
directory: "src-tauri/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
ignore:
|
||||
- dependency-name: "*"
|
||||
update-types: ["version-update:semver-major"]
|
||||
groups:
|
||||
cargo-deps:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
45
.github/workflows/build.yml
vendored
@@ -1,45 +0,0 @@
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Check out repositoty
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up nodejs
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Set up npm project
|
||||
run: npm install
|
||||
|
||||
- name: Build project
|
||||
run: npm run buildall
|
||||
|
||||
- name: Move x64 exe
|
||||
run: cp ./dist/SteamDepotDownloaderGUI*.exe ./SteamDepotDownloaderGUI-${{ github.run_number }}.exe
|
||||
|
||||
- name: Move x64 AppImage
|
||||
run: cp `ls -d1 dist/* | grep -E "SteamDepotDownloaderGUI-[0-9]+\.[0-9]+\.[0-9]+\.AppImage"` ./SteamDepotDownloaderGUI-${{ github.run_number }}.AppImage
|
||||
|
||||
- name: Move x64 zip
|
||||
run: cp `ls -d1 dist/* | grep -E "steamdepotdownloadergui-[0-9]+\.[0-9]+\.[0-9]+\.zip"` ./SteamDepotDownloaderGUI-${{ github.run_number }}.zip
|
||||
|
||||
- name: Move arm64 AppImage
|
||||
run: cp `ls -d1 dist/* | grep -E "SteamDepotDownloaderGUI-[0-9]+\.[0-9]+\.[0-9]+\-arm64.AppImage"` ./SteamDepotDownloaderGUI-${{ github.run_number }}.AppImage
|
||||
|
||||
- name: Move arm64 zip
|
||||
run: cp `ls -d1 dist/* | grep -E "steamdepotdownloadergui-[0-9]+\.[0-9]+\.[0-9]+\-arm64.zip"` ./SteamDepotDownloaderGUI-${{ github.run_number }}-arm64.zip
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: SteamDepotDownloaderGUI-${{ github.run_number }}
|
||||
path: SteamDepotDownloaderGUI-${{ github.run_number }}*.*
|
||||
101
.github/workflows/build_debug.yml
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
name: 'build_debug'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-tauri:
|
||||
permissions:
|
||||
contents: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: 'macos-latest'
|
||||
arch: 'aarch64'
|
||||
args: '--target aarch64-apple-darwin --bundles dmg'
|
||||
- platform: 'macos-latest'
|
||||
arch: 'x86_64'
|
||||
args: '--target x86_64-apple-darwin --bundles dmg'
|
||||
- platform: 'ubuntu-22.04'
|
||||
args: '--bundles appimage'
|
||||
- platform: 'windows-latest'
|
||||
args: ''
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: install dependencies (ubuntu only)
|
||||
if: matrix.platform == 'ubuntu-22.04'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
|
||||
|
||||
- name: setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: setup node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: lts/*
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: install Rust stable
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
|
||||
|
||||
- name: Rust cache
|
||||
uses: swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: './src-tauri -> target'
|
||||
|
||||
- name: install frontend dependencies
|
||||
# If you don't have `beforeBuildCommand` configured you may want to build your frontend here too.
|
||||
run: pnpm install # change this to npm or pnpm depending on which one you use.
|
||||
|
||||
- uses: tauri-apps/tauri-action@v0
|
||||
id: build
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
args: ${{ matrix.args }}
|
||||
includeUpdaterJson: false
|
||||
includeRelease: 'false'
|
||||
includeDebug: 'true'
|
||||
|
||||
- name: fix JSON
|
||||
if: matrix.platform != 'windows-latest'
|
||||
id: truncate_paths
|
||||
run: echo "paths=$(echo '${{ steps.build.outputs.artifactPaths }}' | sed 's/^..//' | sed 's/..$//')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: upload macos artifacts (M1)
|
||||
if: matrix.platform == 'macos-latest' && matrix.arch == 'aarch64'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macos-m1-artifacts
|
||||
path: ${{ steps.truncate_paths.outputs.paths }}
|
||||
|
||||
- name: upload macos artifacts (Intel)
|
||||
if: matrix.platform == 'macos-latest' && matrix.arch == 'x86_64'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macos-intel-artifacts
|
||||
path: ${{ steps.truncate_paths.outputs.paths }}
|
||||
|
||||
- name: upload linux artifacts
|
||||
if: matrix.platform == 'ubuntu-22.04'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: linux-artifacts
|
||||
path: ${{ steps.truncate_paths.outputs.paths }}
|
||||
|
||||
- name: upload windows artifacts
|
||||
if: matrix.platform == 'windows-latest'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: windows-artifacts
|
||||
path: "./src-tauri/target/debug/bundle/*" # fck windows
|
||||
|
||||
|
||||
99
.github/workflows/build_release.yml
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
name: 'build_release'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-tauri:
|
||||
permissions:
|
||||
contents: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: 'macos-latest'
|
||||
arch: 'aarch64'
|
||||
args: '--target aarch64-apple-darwin --bundles dmg'
|
||||
- platform: 'macos-latest'
|
||||
arch: 'x86_64'
|
||||
args: '--target x86_64-apple-darwin --bundles dmg'
|
||||
- platform: 'ubuntu-22.04'
|
||||
args: '--bundles appimage'
|
||||
- platform: 'windows-latest'
|
||||
args: ''
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: install dependencies (ubuntu only)
|
||||
if: matrix.platform == 'ubuntu-22.04'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
|
||||
|
||||
- name: setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: setup node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: lts/*
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: install Rust stable
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
|
||||
|
||||
- name: Rust cache
|
||||
uses: swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: './src-tauri -> target'
|
||||
|
||||
- name: install frontend dependencies
|
||||
# If you don't have `beforeBuildCommand` configured you may want to build your frontend here too.
|
||||
run: pnpm install # change this to npm or pnpm depending on which one you use.
|
||||
|
||||
- uses: tauri-apps/tauri-action@v0
|
||||
id: build
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
args: ${{ matrix.args }}
|
||||
includeUpdaterJson: false
|
||||
|
||||
- name: fix JSON
|
||||
if: matrix.platform != 'windows-latest'
|
||||
id: truncate_paths
|
||||
run: echo "paths=$(echo '${{ steps.build.outputs.artifactPaths }}' | sed 's/^..//' | sed 's/..$//')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: upload macos artifacts (M1)
|
||||
if: matrix.platform == 'macos-latest' && matrix.arch == 'aarch64'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macos-m1-artifacts
|
||||
path: ${{ steps.truncate_paths.outputs.paths }}
|
||||
|
||||
- name: upload macos artifacts (Intel)
|
||||
if: matrix.platform == 'macos-latest' && matrix.arch == 'x86_64'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macos-intel-artifacts
|
||||
path: ${{ steps.truncate_paths.outputs.paths }}
|
||||
|
||||
- name: upload linux artifacts
|
||||
if: matrix.platform == 'ubuntu-22.04'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: linux-artifacts
|
||||
path: ${{ steps.truncate_paths.outputs.paths }}
|
||||
|
||||
- name: upload windows artifacts
|
||||
if: matrix.platform == 'windows-latest'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: windows-artifacts
|
||||
path: "./src-tauri/target/release/bundle/*" # fck windows
|
||||
|
||||
|
||||
19
.github/workflows/github-repo-stats.yml
vendored
@@ -1,19 +0,0 @@
|
||||
name: github-repo-stats
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Run this once per day, towards the end of the day for keeping the most
|
||||
# recent data point most meaningful (hours are interpreted in UTC).
|
||||
- cron: "0 23 * * *"
|
||||
workflow_dispatch: # Allow for running this manually.
|
||||
|
||||
jobs:
|
||||
j1:
|
||||
name: github-repo-stats
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: run-ghrs
|
||||
# Use latest release.
|
||||
uses: jgehrcke/github-repo-stats@v1.4.1 # Don't use latest release for security reasons (what if the workflow gets taken over by a malicious party)
|
||||
with:
|
||||
ghtoken: ${{ secrets.ghrs_github_api_token }}
|
||||
151
.gitignore
vendored
@@ -4,138 +4,29 @@ logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
*.iml
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# VSCode directory for storing user settings
|
||||
.vscode
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
# IntelliJ
|
||||
.idea/
|
||||
|
||||
# SteamDepotDownloaderGUI specific directories
|
||||
/depotdownloader/
|
||||
/games/
|
||||
*.zip
|
||||
# SteamDepotDownloaderGUI files
|
||||
src-tauri/depotdownloader
|
||||
src-tauri/*.zip
|
||||
src-tauri/*.exe
|
||||
**/DepotDownloader
|
||||
**/DepotDownloader.xml
|
||||
6
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"tauri-apps.tauri-vscode",
|
||||
"rust-lang.rust-analyzer"
|
||||
]
|
||||
}
|
||||
138
README.md
@@ -1,112 +1,78 @@
|
||||
<div align="center">
|
||||
<h1>SteamDepotDownloaderGUI</h1>
|
||||
<h4>A graphical wrapper for DepotDownloader, designed to make downloading older versions of Steam games easy.</h4>
|
||||
|
||||
<h1 align="center">
|
||||
<br>
|
||||
SteamDepotDownloaderGUI
|
||||
<br>
|
||||
</h1>
|
||||
→ <a href="https://www.youtube.com/watch?v=H2COwT5OUOo" target="_blank"><b>Tutorial</b></a> ~
|
||||
<a href="https://depotdownloader.aphex.cc/" target="_blank"><b>Website</b></a> ~
|
||||
<a href="https://www.youtube.com/watch?v=ogiDAuH3VdY" target="_blank"><b>Example usage</b></a> ←
|
||||
</h4>
|
||||
|
||||
<h4 align="center">A graphical wrapper of Depotdownloader, designed to make downloading Steam depots easy. built on top of <a href="https://www.electronjs.org" target="_blank">Electron</a>.</h4>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/mmvanheusden/SteamDepotDownloaderGUI/releases/latest">
|
||||
<img src="https://img.shields.io/github/downloads/mmvanheusden/SteamDepotDownloaderGUI/total?color=orange&label=downloads"
|
||||
alt="Download count badge">
|
||||
</a>
|
||||
<a href="https://img.shields.io/github/last-commit/mmvanheusden/SteamDepotDownloaderGUI?color=crimson">
|
||||
<img src="https://img.shields.io/github/last-commit/mmvanheusden/SteamDepotDownloaderGUI?color=crimson"
|
||||
alt="Last contribution badge">
|
||||
</a>
|
||||
<a href="https://github.com/mmvanheusden/SteamDepotDownloaderGUI/releases/latest">
|
||||
<img src="https://img.shields.io/badge/Download -ffbd03?style=for-the-badge&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABmJLR0QA/wD/AP+gvaeTAAABd0lEQVRoge2XwUrDQBCGPz3Ee++2UBSvdsGbeLHeFX0lPQhei+8g2AfwSVREK+LJ1oqHUGjRQ7Z0laRJNtldKPPBwoTM7D9/sks2IAiCsKrsAK/AC7DtSmTd1cTAKbAJtIAzVyIuDURGvOFKxKUBL4iB0IiB0IiB0IiB0IiB0IiB0IiB0IgBoA08Ak+AKpCvdO6AGn416zBwDGyRGLljuQmlc9pAEzipKl6HgVtgpOMGSYOdlLyOvtfQ1yPgpgb9WlDAEPjRYwj0jet+yv0iy80ru8AHiyazxiewF6jHXPJMeG3+CoiBy5J1/5dTlWVzAXwD5yXrAJho4YlFbdqesFnzsa6PLWr/PD0bFPAA3GO/YXN7WMspLpLnktweVvooMTPiKDPLHabmLCtpmYF3I96v3E55Doz4zWaCaxYb6Bno4udNRMCR1pzr92wmagFfZH+UfI0xycHPim5gE2Pg0Lb5OU2SVzgAph6anmqtHhWevCAIgh9+AdLMtu/CZhHJAAAAAElFTkSuQmCC"
|
||||
alt="Download latest release badge">
|
||||
</a>
|
||||
<a href="https://visitor-badge.glitch.me/badge?page_id=mmvanheusden.SteamDepotDownloaderGUI">
|
||||
<img src="https://visitor-badge.glitch.me/badge?page_id=mmvanheusden.SteamDepotDownloaderGUI"
|
||||
alt="Visitor count badge">
|
||||
</a>
|
||||
<a href="https://liberapay.com/barbapapa">
|
||||
<img src="https://img.shields.io/badge/Donate-black?logo=liberapay"
|
||||
alt="Donation badge">
|
||||
</a>
|
||||
<a href="https://www.codefactor.io/repository/github/mmvanheusden/steamdepotdownloadergui/badge/master">
|
||||
<img src="https://www.codefactor.io/repository/github/mmvanheusden/steamdepotdownloadergui/badge/master"
|
||||
alt="CodeFactor badge">
|
||||
</a>
|
||||
</p>
|
||||
<a href="https://img.shields.io/github/last-commit/mmvanheusden/SteamDepotDownloaderGUI?color=crimson"><img src="https://img.shields.io/github/last-commit/mmvanheusden/SteamDepotDownloaderGUI?color=crimson" alt="Last contribution badge"></a>
|
||||
<a href="https://github.com/mmvanheusden/SteamDepotDownloaderGUI/releases/latest"><img src="https://img.shields.io/badge/Download -ffbd03?style=for-the-badge&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABmJLR0QA/wD/AP+gvaeTAAABd0lEQVRoge2XwUrDQBCGPz3Ee++2UBSvdsGbeLHeFX0lPQhei+8g2AfwSVREK+LJ1oqHUGjRQ7Z0laRJNtldKPPBwoTM7D9/sks2IAiCsKrsAK/AC7DtSmTd1cTAKbAJtIAzVyIuDURGvOFKxKUBL4iB0IiB0IiB0IiB0IiB0IiB0IiB0IgBoA08Ak+AKpCvdO6AGn416zBwDGyRGLljuQmlc9pAEzipKl6HgVtgpOMGSYOdlLyOvtfQ1yPgpgb9WlDAEPjRYwj0jet+yv0iy80ru8AHiyazxiewF6jHXPJMeG3+CoiBy5J1/5dTlWVzAXwD5yXrAJho4YlFbdqesFnzsa6PLWr/PD0bFPAA3GO/YXN7WMspLpLnktweVvooMTPiKDPLHabmLCtpmYF3I96v3E55Doz4zWaCaxYb6Bno4udNRMCR1pzr92wmagFfZH+UfI0xycHPim5gE2Pg0Lb5OU2SVzgAph6anmqtHhWevCAIgh9+AdLMtu/CZhHJAAAAAElFTkSuQmCC" alt="Download latest release badge"></a>
|
||||
<a href="https://github.com/mmvanheusden/SteamDepotDownloaderGUI/releases/latest"><img src="https://img.shields.io/github/downloads/mmvanheusden/SteamDepotDownloaderGUI/total?color=orange&label=downloads" alt="Download count badge"></a>
|
||||
|
||||
<p align="center">
|
||||
<a href="#features">Features</a> •
|
||||
<a href="#installation">Installation</a> •
|
||||
<a href="#how-to-use">How to use</a> •
|
||||
<a href="#credits">Credits</a> •
|
||||
<a href="#support">Support</a> •
|
||||
<a href="#contribute">Contribute</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img alt="Screenshot of the downloader interface" src="screenshot.png"
|
||||
style="max-width: 70%;"/>
|
||||
</p>
|
||||
<img src="https://github.com/user-attachments/assets/0a2debcc-617a-449d-971f-9e1cf1d5cb0b" alt="Steam downgrader interface" />
|
||||
</div>
|
||||
|
||||
## Features
|
||||
> ↓ *The downloader in action:*<br>
|
||||
> <img src="https://github.com/user-attachments/assets/8739f06e-a258-48b2-a684-ca8fcf84dd7e" alt="Steam downgrader process" style="width: 25svw;"/>
|
||||
|
||||
* Cross platform
|
||||
- Windows
|
||||
- <s>macOS</s>
|
||||
- Linux
|
||||
* Cross terminal
|
||||
- Gnome Terminal
|
||||
- cmd
|
||||
- Konsole
|
||||
- xfce4-terminal
|
||||
- Terminator
|
||||
- Manual: produce a script that can be copy pasted into a terminal of choice
|
||||
* Support for anonymous downloads
|
||||
### Cross-platform support
|
||||
| OS | Supported |
|
||||
|---------|-----------|
|
||||
| Windows | ✅ |
|
||||
| Linux | ✅ |
|
||||
| macOS | ✅ |
|
||||
|
||||
## Installation
|
||||
|
||||
If you haven't already, install [.NET SDK 6.0](https://dotnet.microsoft.com/en-us/download/dotnet/6.0) on your computer.
|
||||
From then, download the appropriate binary from [here](https://github.com/mmvanheusden/SteamDepotDownloaderGUI/releases/latest).
|
||||
> [!CAUTION]
|
||||
> This GitHub repository is the only official place to download this software.
|
||||
> If you have paid for this software, or downloaded this from a different place than here, **you are an idiot and at risk**.
|
||||
|
||||
|
||||
> **Note**
|
||||
> No support will be provided for binaries downloaded from unofficial mirrors like softpedia.
|
||||
### Windows
|
||||
Download the [latest Windows release](https://github.com/mmvanheusden/SteamDepotDownloaderGUI/releases/latest). There are multiple variants to choose from, but you are probably looking for the file that ends with **`.exe`**.
|
||||
|
||||
|
||||
## How to use
|
||||
### Linux
|
||||
You'll need at least one of the supported terminal emulators. You most likely already have one of these.
|
||||
Download the [latest Linux release](https://github.com/mmvanheusden/SteamDepotDownloaderGUI/releases/latest). There are multiple formats to choose from.
|
||||
|
||||
Enter everything you normally would in the DepotDownloader console and select your OS/terminal and click download
|
||||
## Tutorials
|
||||
* https://www.youtube.com/watch?v=H2COwT5OUOo How to download older versions of Steam games tutorial
|
||||
|
||||
* https://www.youtube.com/watch?v=ogiDAuH3VdY How to download older versions of Subnautica tutorial
|
||||
|
||||
|
||||
## Credits
|
||||
|
||||
This software uses the following open source packages:
|
||||
- [Electron](http://electron.atom.io/)
|
||||
- [Node.js](https://nodejs.org/)
|
||||
This software makes use of the following projects:
|
||||
- [**DepotDownloader**](https://github.com/SteamRE/DepotDownloader/)
|
||||
- [Tauri](https://tauri.app)
|
||||
- [Primer CSS](https://primer.style/css/)
|
||||
- [DepotDownloader](https://github.com/SteamRE/DepotDownloader/)
|
||||
- README inspired from [Markdownify](https://github.com/amitmerchant1990/electron-markdownify#readme)
|
||||
- [async-process](https://github.com/smol-rs/async-process)
|
||||
- [Hubut Sans](https://github.com/github/hubot-sans) under [license](https://github.com/github/hubot-sans/blob/05d5ea150c20e6434485db8ffd2277ed18a9e911/LICENSE)
|
||||
|
||||
|
||||
## Support
|
||||
## Donate
|
||||
You can donate [here](paypal.me/onderkin) or through the **donate** button in the interface.
|
||||
|
||||
Donations can be made through Liberapay :)
|
||||
|
||||
<a href="https://liberapay.com/barbapapa">
|
||||
<img src="https://img.shields.io/badge/Donate-black?logo=liberapay&style=for-the-badge"
|
||||
alt="Donation badge">
|
||||
</a>
|
||||
|
||||
## Contribute
|
||||
|
||||
If you want to contribute to SteamDepotDownloaderGUI, please make sure to follow
|
||||
the [contributing instructions and guidelines](contributing.md).
|
||||
|
||||
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
|
||||
|
||||
Please make sure to keep code consistent and cross-platform compatible.
|
||||
Every pull request is welcome! ;)
|
||||
Please cleanup the code using:
|
||||
```console
|
||||
$ pnpm eslint --fix src/
|
||||
```
|
||||
|
||||
|
||||
##### --
|
||||
|
||||
##### enjoy 😘
|
||||
<p align="center">
|
||||
<a href="https://www.gnu.org/licenses/gpl-3.0" target="_blank">
|
||||
<img src="https://github.com/mmvanheusden/SteamDepotDownloaderGUI/assets/50550545/b5649b7f-ea49-45c4-b0cd-5f3788dcd6ca" height="40px">
|
||||
</a>
|
||||
<a href="https://aphex.cc" target="_blank">
|
||||
<img src="https://github.com/mmvanheusden/SteamDepotDownloaderGUI/assets/50550545/83f5f3b2-2bf9-41aa-ab87-880466f785fe" height="40px">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
# SteamDepotDownloaderGUI development information
|
||||
|
||||
SteamDepotDownloaderGUI is a graphical user interface for DepotDownloader.
|
||||
|
||||
It is written in Node.js and uses the [electron](https://electronjs.org/) framework.
|
||||
The CSS framework is [Primer](https://primer.style).
|
||||
|
||||
## Setup development environment
|
||||
|
||||
**Note that these instructions may differ from operating system to operating system.**
|
||||
|
||||
* Install node.js, npm, and git on your computer.
|
||||
|
||||
* Clone the repository.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/mmvanheusden/SteamDepotDownloaderGUI
|
||||
```
|
||||
|
||||
* Move into the directory and install npm dependencies.
|
||||
|
||||
```bash
|
||||
cd SteamDepotDownloaderGUI
|
||||
npm install
|
||||
```
|
||||
|
||||
* **You are now ready to contribute**
|
||||
|
||||
## Testing the application
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
## Building the application
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
* If you are using macOS, you may build using the following command:
|
||||
|
||||
```bash
|
||||
npm run buildall
|
||||
```
|
||||
|
||||
This will build the application for all supported operating systems.
|
||||
|
||||
## Contributing Guidelines
|
||||
|
||||
Please make sure to keep code consistent and cross-platform compatible.
|
||||
|
||||
After you made a change, clean-up the code using your favorite code editor and run the following command:
|
||||
|
||||
```bash
|
||||
npx eslint *.js --fix
|
||||
```
|
||||
|
||||
Please make sure your git commit message is descriptive and contains the changes you made.
|
||||
|
||||
**Happy coding!**
|
||||
@@ -1,84 +0,0 @@
|
||||
const {
|
||||
preDownloadCheck,
|
||||
download,
|
||||
createCommand,
|
||||
runCommand,
|
||||
removeDir,
|
||||
removeFile,
|
||||
unzip
|
||||
} = require("./utils")
|
||||
|
||||
function submitForm() {
|
||||
// Check if the form is filled in and if dotnet is installed
|
||||
preDownloadCheck().then(async function () {
|
||||
document.getElementById("dotnetwarning").hidden = true
|
||||
document.getElementById("emptywarning").hidden = true
|
||||
console.info("dotnet found in PATH")
|
||||
|
||||
// Remove the old depotdownloader directory
|
||||
await removeDir("depotdownloader")
|
||||
|
||||
// Download the DepotDownloader binary, so it doesn't have to be included in the source code
|
||||
await download("https://github.com/SteamRE/DepotDownloader/releases/download/DepotDownloader_2.4.7/depotdownloader-2.4.7.zip")
|
||||
|
||||
// Unzip the DepotDownloader binary
|
||||
await unzip("depotdownloader-2.4.7.zip", "depotdownloader")
|
||||
|
||||
// Clean up the old files
|
||||
await removeFile("depotdownloader-2.4.7.zip")
|
||||
|
||||
// Run the final command
|
||||
await runCommand(createCommand())
|
||||
}).catch(function (error) {
|
||||
if (error === "noDotnet") {
|
||||
console.error("Dotnet not found in PATH")
|
||||
document.getElementById("emptywarning").hidden = true
|
||||
document.getElementById("dotnetwarning").hidden = false
|
||||
} else if (error === "emptyField") {
|
||||
console.error("Fill in all required fields")
|
||||
document.getElementById("dotnetwarning").hidden = true
|
||||
document.getElementById("emptywarning").hidden = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function submitDotnet() {
|
||||
const electron = require("electron")
|
||||
const os = process.platform.toString()
|
||||
document.getElementById("dotnetwarning").hidden = true
|
||||
if (os.includes("win")) {
|
||||
console.debug("Opened .NET download page for " + os.charAt(0).toUpperCase() + os.slice(1))
|
||||
void electron.shell.openExternal("https://aka.ms/dotnet/6.0/dotnet-sdk-win-x64.exe")
|
||||
}
|
||||
if (os.includes("linux")) {
|
||||
console.debug("Opened .NET download page for " + os.charAt(0).toUpperCase() + os.slice(1))
|
||||
void electron.shell.openExternal("https://docs.microsoft.com/en-us/dotnet/core/install/linux")
|
||||
}
|
||||
if (os.includes("darwin")) {
|
||||
console.debug("Opened .NET download page for" + os)
|
||||
//TODO: Apple Silicon(ARM64) URL
|
||||
void electron.shell.openExternal("https://aka.ms/dotnet/6.0/dotnet-sdk-osx-x64.pkg")
|
||||
}
|
||||
}
|
||||
|
||||
function openGitHubIssues() {
|
||||
const electron = require("electron")
|
||||
console.debug("Opened GitHub issues page")
|
||||
void electron.shell.openExternal("https://github.com/mmvanheusden/SteamDepotDownloaderGUI/issues/new")
|
||||
}
|
||||
|
||||
function openSteamDB() {
|
||||
const electron = require("electron")
|
||||
console.debug("Opened SteamDB instant search page")
|
||||
void electron.shell.openExternal("https://steamdb.info/instantsearch/")
|
||||
}
|
||||
|
||||
/* Everything below this line runs when the page is loaded */
|
||||
|
||||
// Add event listeners to the buttons
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
document.getElementById("dotnetalertbtn").addEventListener("click", submitDotnet)
|
||||
document.getElementById("downloadbtn").addEventListener("click", submitForm)
|
||||
document.getElementById("smbtn1").addEventListener("click", openGitHubIssues)
|
||||
document.getElementById("smbtn2").addEventListener("click", openSteamDB)
|
||||
})
|
||||
@@ -1,32 +0,0 @@
|
||||
appId: rocks.maarten.depotdownloader
|
||||
productName: SteamDepotDownloaderGUI
|
||||
copyright: Copyright © 2022 mmvanheusden | This work is free. Licensed under the GNU GPLv3 Public License
|
||||
|
||||
linux:
|
||||
executableName: SteamDepotDownloaderGUI
|
||||
category: Utility;FileTools;
|
||||
maintainer: mmvanheusden
|
||||
target:
|
||||
- target: AppImage
|
||||
arch:
|
||||
- x64
|
||||
- arm64
|
||||
- target: zip
|
||||
arch:
|
||||
- x64
|
||||
- arm64
|
||||
|
||||
# lmao mac building only works on mac
|
||||
mac:
|
||||
category: public.app-category.utilities
|
||||
target:
|
||||
- target: dmg
|
||||
arch:
|
||||
- x64
|
||||
|
||||
win:
|
||||
legalTrademarks: Copyright © 2022 mmvanheusden | This work is free. Licensed under the GNU GPLv3 Public License
|
||||
target:
|
||||
- target: portable
|
||||
arch:
|
||||
- x64
|
||||
26
eslint.config.js
Normal file
@@ -0,0 +1,26 @@
|
||||
// @ts-check
|
||||
|
||||
import eslint from '@eslint/js';
|
||||
import {defineConfig} from 'eslint/config';
|
||||
import tseslint from 'typescript-eslint';
|
||||
|
||||
export default defineConfig(
|
||||
eslint.configs.recommended,
|
||||
tseslint.configs.stylisticTypeChecked,
|
||||
{
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
project: 'tsconfig.json',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["src/**"],
|
||||
rules: {
|
||||
"semi": ["error", "always"], // semicolons
|
||||
"indent": ["error", "tab"], // tabs indents
|
||||
"linebreak-style": ["error", "unix"],
|
||||
"quotes": ["error", "double"],
|
||||
},
|
||||
},
|
||||
);
|
||||
129
index.html
@@ -1,129 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- automatic dark mode :) -->
|
||||
<html class="anim-fade-in" data-color-mode="auto" data-dark-theme="dark" data-light-theme="light" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport"/>
|
||||
<link href="https://unpkg.com/@primer/css@21.0.0/dist/primer.css" rel="stylesheet"/>
|
||||
<title>SteamDepotDownloaderGUI</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="downloader.js"></script>
|
||||
<div class="mx-auto">
|
||||
<div hidden id="dotnetwarning">
|
||||
<div class="flash flash-error mx-2 mt-2 color-shadow-medium" id="dotnetalert">
|
||||
<svg class="octicon" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8zm6.5-.25A.75.75 0 017.25 7h1a.75.75 0 01.75.75v2.75h.25a.75.75 0 010 1.5h-2a.75.75 0 010-1.5h.25v-2h-.25a.75.75 0 01-.75-.75zM8 6a1 1 0 100-2 1 1 0 000 2z"
|
||||
fill-rule="evenodd"></path>
|
||||
</svg>
|
||||
<code><span class="text-italic">dotnet</span></code> was not found.
|
||||
<button class="btn btn-sm flash-action" id="dotnetalertbtn">
|
||||
<svg class="octicon" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.47 10.78a.75.75 0 001.06 0l3.75-3.75a.75.75 0 00-1.06-1.06L8.75 8.44V1.75a.75.75 0 00-1.5
|
||||
0v6.69L4.78 5.97a.75.75 0 00-1.06 1.06l3.75 3.75zM3.75 13a.75.75 0 000 1.5h8.5a.75.75 0 000-1.5h-8.5z"
|
||||
fill-rule="evenodd"></path>
|
||||
</svg>
|
||||
<span class="text-bold">Download</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div hidden id="emptywarning">
|
||||
<div class="flash flash-warn mx-2 mt-2 color-shadow-medium" id="emptyalert">
|
||||
<svg class="octicon" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8zm6.5-.25A.75.75 0 017.25 7h1a.75.75 0 01.75.75v2.75h.25a.75.75 0 010 1.5h-2a.75.75 0 010-1.5h.25v-2h-.25a.75.75 0 01-.75-.75zM8 6a1 1 0 100-2 1 1 0 000 2z"
|
||||
fill-rule="evenodd"></path>
|
||||
</svg>Please fill in all required fields.
|
||||
</div>
|
||||
</div>
|
||||
<div class="f0-light text-center">Steam Depot Downloader</div>
|
||||
|
||||
<form id="theform">
|
||||
<div class="form-group mx-3 mt-1">
|
||||
<div class="form-group-header">
|
||||
<label for="username">Username</label>
|
||||
</div>
|
||||
<input class="form-control input-block" id="username" type="text" placeholder="Leave empty for anonymous download"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group mx-3 mt-1">
|
||||
<div class="form-group-header">
|
||||
<label for="password">Password</label>
|
||||
</div>
|
||||
<input class="form-control input-block" id="password" type="password" placeholder="Leave empty for anonymous download"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group mx-3 mt-1 required">
|
||||
<div class="form-group-header">
|
||||
<label for="appid">App ID</label>
|
||||
</div>
|
||||
<input class="form-control input-block" id="appid" type="number"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group mx-3 mt-1 required">
|
||||
<div class="form-group-header">
|
||||
<label for="depotid">Depot ID</label>
|
||||
</div>
|
||||
<input class="form-control input-block" id="depotid" type="number"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group mx-3 mt-1 required">
|
||||
<div class="form-group-header">
|
||||
<label for="manifestid">Manifest ID</label>
|
||||
</div>
|
||||
<input class="form-control input-block" id="manifestid" type="number"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group mx-3 mt-1 required">
|
||||
<div class="form-group-header ">
|
||||
<label for="osdropdown">Operating system</label>
|
||||
</div>
|
||||
|
||||
<div aria-label="Select your OS/terminal here." class="form-group-body tooltipped tooltipped-n">
|
||||
<select aria-label="Preference" class="form-select width-full" id="osdropdown">
|
||||
<option disabled>Choose your OS</option>
|
||||
<option>Windows</option>
|
||||
<option disabled>macOS (NOT YET IMPLEMENTED)</option>
|
||||
<option disabled>If you are using Linux</option>
|
||||
<option disabled>Select your terminal</option>
|
||||
<option>KDE Konsole</option>
|
||||
<option>Gnome Terminal</option>
|
||||
<option>Xfce Terminal</option>
|
||||
<option>Terminator</option>
|
||||
<option>Print command in console (CTRL-SHIFT-I)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="form-group mt-3 ml-3 mr-3">
|
||||
<button class="btn btn-block btn-primary" id="downloadbtn">
|
||||
<svg class="octicon" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.47 10.78a.75.75 0 001.06 0l3.75-3.75a.75.75 0 00-1.06-1.06L8.75 8.44V1.75a.75.75 0 00-1.5 0v6.69L4.78 5.97a.75.75 0 00-1.06 1.06l3.75 3.75zM3.75 13a.75.75 0 000 1.5h8.5a.75.75 0 000-1.5h-8.5z"
|
||||
fill-rule="evenodd"></path>
|
||||
</svg>
|
||||
Download
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div aria-label="Visit the GitHub issues website." class="btn btn-sm ml-3 tooltipped tooltipped-ne mb-1" id="smbtn1">
|
||||
<svg fill="#8B949E" height="16" style="display: inline-block; vertical-align: text-bottom;" viewBox="0 0 16 16"
|
||||
width="16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8zm9 3a1 1 0 11-2 0 1 1 0 012 0zM6.92 6.085c.081-.16.19-.299.34-.398.145-.097.371-.187.74-.187.28 0 .553.087.738.225A.613.613 0 019 6.25c0 .177-.04.264-.077.318a.956.956 0 01-.277.245c-.076.051-.158.1-.258.161l-.007.004a7.728 7.728 0 00-.313.195 2.416 2.416 0 00-.692.661.75.75 0 001.248.832.956.956 0 01.276-.245 6.3 6.3 0 01.26-.16l.006-.004c.093-.057.204-.123.313-.195.222-.149.487-.355.692-.662.214-.32.329-.702.329-1.15 0-.76-.36-1.348-.863-1.725A2.76 2.76 0 008 4c-.631 0-1.155.16-1.572.438-.413.276-.68.638-.849.977a.75.75 0 101.342.67z"
|
||||
fill-rule="evenodd"></path>
|
||||
</svg>
|
||||
Support
|
||||
</div>
|
||||
|
||||
<div aria-label="Visit the SteamDB instant search website." class="btn btn-sm ml-1 tooltipped tooltipped-n mb-1"
|
||||
id="smbtn2">
|
||||
<svg aria-hidden="true" class="octicon" height="14" viewBox="0 0 128 128" width="14"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M63.9 0C30.5 0 3.1 11.9.1 27.1l35.6 6.7c2.9-.9 6.2-1.3 9.6-1.3l16.7-10c-.2-2.5 1.3-5.1 4.7-7.2 4.8-3.1 12.3-4.8 19.9-4.8 5.2-.1 10.5.7 15 2.2 11.2 3.8 13.7 11.1 5.7 16.3-5.1 3.3-13.3 5-21.4 4.8l-22 7.9c-.2 1.6-1.3 3.1-3.4 4.5-5.9 3.8-17.4 4.7-25.6 1.9-3.6-1.2-6-3-7-4.8L2.5 38.4c2.3 3.6 6 6.9 10.8 9.8C5 53 0 59 0 65.5c0 6.4 4.8 12.3 12.9 17.1C4.8 87.3 0 93.2 0 99.6 0 115.3 28.6 128 64 128c35.3 0 64-12.7 64-28.4 0-6.4-4.8-12.3-12.9-17 8.1-4.8 12.9-10.7 12.9-17.1 0-6.5-5-12.6-13.4-17.4 8.3-5.1 13.3-11.4 13.3-18.2 0-16.5-28.7-29.9-64-29.9zm22.8 14.2c-5.2.1-10.2 1.2-13.4 3.3-5.5 3.6-3.8 8.5 3.8 11.1 7.6 2.6 18.1 1.8 23.6-1.8s3.8-8.5-3.8-11c-3.1-1-6.7-1.5-10.2-1.5zm.3 1.7c7.4 0 13.3 2.8 13.3 6.2 0 3.4-5.9 6.2-13.3 6.2s-13.3-2.8-13.3-6.2c0-3.4 5.9-6.2 13.3-6.2zM45.3 34.4c-1.6.1-3.1.2-4.6.4l9.1 1.7a10.8 5 0 1 1-8.1 9.3l-8.9-1.7c1 .9 2.4 1.7 4.3 2.4 6.4 2.2 15.4 1.5 20-1.5s3.2-7.2-3.2-9.3c-2.6-.9-5.7-1.3-8.6-1.3zM109 51v9.3c0 11-20.2 19.9-45 19.9-24.9 0-45-8.9-45-19.9v-9.2c11.5 5.3 27.4 8.6 44.9 8.6 17.6 0 33.6-3.3 45.2-8.7zm0 34.6v8.8c0 11-20.2 19.9-45 19.9-24.9 0-45-8.9-45-19.9v-8.8c11.6 5.1 27.4 8.2 45 8.2s33.5-3.1 45-8.2z"
|
||||
fill-rule="evenodd"></path>
|
||||
</svg>
|
||||
SteamDB
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
45
main.js
@@ -1,45 +0,0 @@
|
||||
const {app, BrowserWindow} = require("electron")
|
||||
|
||||
const createWindow = () => {
|
||||
// Create the browser window.
|
||||
const mainWindow = new BrowserWindow({
|
||||
autoHideMenuBar: true,
|
||||
resizable: false,
|
||||
width: 430,
|
||||
height: 590,
|
||||
useContentSize: true,
|
||||
maximizable: false,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile("index.html")
|
||||
|
||||
// Open the DevTools for debugging, only if not in production.
|
||||
if (!app.isPackaged) {
|
||||
mainWindow.webContents.openDevTools({mode: "detach"})
|
||||
}
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on("activate", () => {
|
||||
// On macOS it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
// for applications and their menu bar to stay active until the user quits
|
||||
// explicitly with Cmd + Q.
|
||||
app.on("window-all-closed", () => {
|
||||
if (process.platform !== "darwin") app.quit()
|
||||
})
|
||||
3607
package-lock.json
generated
65
package.json
@@ -1,41 +1,34 @@
|
||||
{
|
||||
"name": "steamdepotdownloadergui",
|
||||
"version": "2.1.1",
|
||||
"description": "DepotDownloader Electron frontend",
|
||||
"main": "main.js",
|
||||
"name": "vectum",
|
||||
"private": true,
|
||||
"version": "3.1.0",
|
||||
"type": "module",
|
||||
"license": "GPL-3.0-only",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "electron .",
|
||||
"build": "electron-builder -c electron-builder.yml -wl -p never",
|
||||
"buildall": "electron-builder -c electron-builder.yml -mwl -p never",
|
||||
"buildlinux": "electron-builder -c electron-builder.yml -l -p never",
|
||||
"buildwin": "electron-builder -c electron-builder.yml -w -p never",
|
||||
"buildmacos": "electron-builder -c electron-builder.yml -m -p never"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/mmvanheusden/SteamDepotDownloaderGUI.git"
|
||||
},
|
||||
"keywords": [
|
||||
"electron",
|
||||
"steam",
|
||||
"depotdownloader",
|
||||
"electron",
|
||||
"gui"
|
||||
],
|
||||
"author": "mmvanheusden",
|
||||
"license": "GPL-3.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/mmvanheusden/SteamDepotDownloaderGUI/issues"
|
||||
},
|
||||
"homepage": "https://github.com/mmvanheusden/SteamDepotDownloaderGUI#readme",
|
||||
"devDependencies": {
|
||||
"electron": "^24.0.0",
|
||||
"electron-builder": "^23.6.0",
|
||||
"eslint": "^8.37.0"
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"preview": "vite preview",
|
||||
"tauri": "tauri"
|
||||
},
|
||||
"dependencies": {
|
||||
"elecron": "^0.0.1-security",
|
||||
"follow-redirects": "^1.15.2"
|
||||
}
|
||||
"@tailwindcss/vite": "^4.1.18",
|
||||
"@tauri-apps/api": "2.9.1",
|
||||
"@tauri-apps/plugin-dialog": "2.6.0",
|
||||
"@tauri-apps/plugin-opener": "~2.5.3",
|
||||
"@tauri-apps/plugin-shell": "2.3.4",
|
||||
"@xterm/addon-fit": "^0.11.0",
|
||||
"@xterm/xterm": "^6.0.0",
|
||||
"jquery": "^4.0.0",
|
||||
"tailwindcss": "^4.1.18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.2",
|
||||
"@tauri-apps/cli": "2.9.6",
|
||||
"@types/jquery": "^3.5.33",
|
||||
"eslint": "^9.39.2",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.54.0",
|
||||
"vite": "^7.3.1"
|
||||
},
|
||||
"packageManager": "pnpm@10.28.2+sha512.41872f037ad22f7348e3b1debbaf7e867cfd448f2726d9cf74c08f19507c31d2c8e7a11525b983febc2df640b5438dee6023ebb1f84ed43cc2d654d2bc326264"
|
||||
}
|
||||
|
||||
2106
pnpm-lock.yaml
generated
Normal file
BIN
screenshot.png
|
Before Width: | Height: | Size: 53 KiB |
16
src-tauri/.gitignore
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
|
||||
# Generated by Tauri
|
||||
# will have schema files for capabilities auto-completion
|
||||
/gen/schemas
|
||||
|
||||
|
||||
# DepotDownloader
|
||||
depot/
|
||||
downloads/
|
||||
.DepotDownloader/
|
||||
Games/
|
||||
Depots/
|
||||
**/*.sh
|
||||
6121
src-tauri/Cargo.lock
generated
Normal file
45
src-tauri/Cargo.toml
Normal file
@@ -0,0 +1,45 @@
|
||||
[package]
|
||||
name = "vectum"
|
||||
version = "3.1.0"
|
||||
description = "Download older versions of Steam games with DepotDownloader"
|
||||
authors = ["mmvanheusden"]
|
||||
edition = "2021"
|
||||
license = "GPL-3.0-only"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.4.1", features = [] }
|
||||
|
||||
[dependencies]
|
||||
fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs", rev = "c4c45d503ea115a839aae718d02f79e7c7f0f673" }
|
||||
serde_json = "1.0.143"
|
||||
tauri = { version = "2.8.5", features = [] }
|
||||
tauri-plugin-shell = "2.3.1"
|
||||
tauri-plugin-dialog = "2.4.0"
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
derive-getters = "0.5.0"
|
||||
reqwest = { version = "0.13.1",features = ["blocking"] }
|
||||
zip = "7.2.0"
|
||||
tauri-plugin-opener = "2"
|
||||
portable-pty = "0.9.0"
|
||||
|
||||
|
||||
|
||||
# Bacon - https://dystroy.org/bacon/
|
||||
# Mold - https://github.com/rui314/mold#how-to-use
|
||||
# https://discord.com/channels/616186924390023171/731495028677148753/1254902668376150149
|
||||
[profile.dev]
|
||||
incremental = true
|
||||
opt-level = 1
|
||||
debug = 0
|
||||
|
||||
[profile.dev.package."*"]
|
||||
opt-level = 2
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1 # Allows LLVM to perform better optimization.
|
||||
lto = true # Enables link-time-optimizations.
|
||||
opt-level = 3 # Prioritizes small binary size. Use `3` if you prefer speed.
|
||||
panic = "abort" # Higher performance by disabling panic handlers.
|
||||
strip = true # Ensures debug symbols are removed.
|
||||
3
src-tauri/build.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
tauri_build::build()
|
||||
}
|
||||
31
src-tauri/capabilities/default.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "Capability for the main window",
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"shell:allow-open",
|
||||
"dialog:default",
|
||||
"shell:allow-execute",
|
||||
"shell:allow-spawn",
|
||||
{
|
||||
"identifier": "opener:allow-open-path",
|
||||
"allow": [
|
||||
{
|
||||
"path": "**"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "opener:allow-open-url",
|
||||
"allow": [
|
||||
{
|
||||
"url": "**"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
src-tauri/icons/128x128.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
src-tauri/icons/128x128@2x.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
src-tauri/icons/32x32.png
Normal file
|
After Width: | Height: | Size: 974 B |
BIN
src-tauri/icons/Square107x107Logo.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
src-tauri/icons/Square142x142Logo.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
src-tauri/icons/Square150x150Logo.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
src-tauri/icons/Square284x284Logo.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
src-tauri/icons/Square30x30Logo.png
Normal file
|
After Width: | Height: | Size: 903 B |
BIN
src-tauri/icons/Square310x310Logo.png
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
src-tauri/icons/Square44x44Logo.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src-tauri/icons/Square71x71Logo.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
src-tauri/icons/Square89x89Logo.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
src-tauri/icons/StoreLogo.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src-tauri/icons/icon.icns
Normal file
BIN
src-tauri/icons/icon.ico
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
src-tauri/icons/icon.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
111
src-tauri/src/depotdownloader.rs
Normal file
@@ -0,0 +1,111 @@
|
||||
use crate::get_os;
|
||||
use std::fs::File;
|
||||
use std::io::ErrorKind::AlreadyExists;
|
||||
use std::path::PathBuf;
|
||||
use std::{fs, io};
|
||||
use std::{io::Write, path::Path};
|
||||
|
||||
pub static DEPOTDOWNLOADER_VERSION: &str = "3.4.0";
|
||||
|
||||
|
||||
/**
|
||||
See: [`test_get_depotdownloader_url()`]
|
||||
*/
|
||||
pub fn get_depotdownloader_url() -> String {
|
||||
let arch = match std::env::consts::ARCH {
|
||||
"x86_64" => "x64",
|
||||
"aarch64" => "arm64",
|
||||
"arm" => "arm",
|
||||
_ => "x86_64",
|
||||
};
|
||||
|
||||
format!("https://github.com/SteamRE/DepotDownloader/releases/download/DepotDownloader_{}/DepotDownloader-{}-{}.zip", DEPOTDOWNLOADER_VERSION, get_os(), arch)
|
||||
}
|
||||
|
||||
/// Downloads a file. The file will be saved to the [`filename`] provided.
|
||||
pub async fn download_file(url: &str, filename: &Path) -> io::Result<()> {
|
||||
if filename.exists() {
|
||||
println!("DEBUG: Not downloading. File already exists.");
|
||||
return Err(io::Error::from(AlreadyExists));
|
||||
}
|
||||
|
||||
// Create any missing directories.
|
||||
if let Some(p) = filename.parent() {
|
||||
if !p.exists() {
|
||||
fs::create_dir_all(p)?;
|
||||
}
|
||||
}
|
||||
|
||||
let mut file = File::create(filename)?;
|
||||
let response = reqwest::get(url)
|
||||
.await
|
||||
.expect("Failed to contact internet.");
|
||||
|
||||
let content = response.bytes().await.unwrap();
|
||||
|
||||
file.write_all(&content)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Unzips DepotDownloader zips
|
||||
pub fn unzip(zip_file: &Path, working_dir: &PathBuf) -> io::Result<()> {
|
||||
let file = File::open(zip_file)?;
|
||||
let mut archive = zip::ZipArchive::new(file)?;
|
||||
|
||||
for i in 0..archive.len() {
|
||||
let mut file = archive.by_index(i)?;
|
||||
let outpath = match file.enclosed_name() {
|
||||
Some(path) => working_dir.join(path),
|
||||
None => continue,
|
||||
};
|
||||
|
||||
println!("Extracted {} from archive.", outpath.display());
|
||||
|
||||
if let Some(p) = outpath.parent() {
|
||||
if !p.exists() {
|
||||
fs::create_dir_all(p)?;
|
||||
}
|
||||
}
|
||||
let mut outfile = File::create(&outpath)?;
|
||||
io::copy(&mut file, &mut outfile)?;
|
||||
|
||||
// Copy over permissions from enclosed file to extracted file on UNIX systems.
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
|
||||
// If the mode `file.unix_mode()` is something (not None), copy it over to the extracted file.
|
||||
if let Some(mode) = file.unix_mode() {
|
||||
fs::set_permissions(&outpath, fs::Permissions::from_mode(mode))?;
|
||||
}
|
||||
|
||||
// Set executable permission.
|
||||
if outpath.file_name().unwrap() == "DepotDownloader" {
|
||||
fs::set_permissions(&outpath, fs::Permissions::from_mode(0o755))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use reqwest::blocking;
|
||||
|
||||
#[test]
|
||||
/// checks if all possible DepotDownloader URLs exist.
|
||||
fn test_get_depotdownloader_url() {
|
||||
for os in ["windows", "linux", "macos"].iter() {
|
||||
for arch in ["x64", "arm64", "arm"].iter() {
|
||||
if arch.eq(&"arm") && !os.eq(&"linux") {
|
||||
continue;
|
||||
}
|
||||
let url = format!("https://github.com/SteamRE/DepotDownloader/releases/download/DepotDownloader_{}/DepotDownloader-{}-{}.zip", DEPOTDOWNLOADER_VERSION, os, arch);
|
||||
println!("Testing DepotDownloader URL: {}", url);
|
||||
|
||||
assert!(blocking::get(url).unwrap().status().is_success());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
176
src-tauri/src/main.rs
Normal file
@@ -0,0 +1,176 @@
|
||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
mod depotdownloader;
|
||||
mod steam;
|
||||
mod terminal;
|
||||
|
||||
use crate::depotdownloader::{get_depotdownloader_url, DEPOTDOWNLOADER_VERSION};
|
||||
use crate::terminal::{async_read_from_pty, async_resize_pty, async_write_to_pty};
|
||||
use portable_pty::{native_pty_system, PtyPair, PtySize};
|
||||
use std::io::ErrorKind::AlreadyExists;
|
||||
use std::io::{BufReader, Read, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use std::time::Duration;
|
||||
use std::{env, thread};
|
||||
use tauri::async_runtime::Mutex;
|
||||
use tauri::{AppHandle, Emitter, Manager, State};
|
||||
|
||||
struct AppState {
|
||||
pty_pair: Arc<Mutex<PtyPair>>,
|
||||
writer: Arc<Mutex<Box<dyn Write + Send>>>,
|
||||
reader: Arc<Mutex<BufReader<Box<dyn Read + Send>>>>,
|
||||
}
|
||||
|
||||
|
||||
/// The first terminal found. Used as default terminal.
|
||||
static WORKING_DIR: OnceLock<PathBuf> = OnceLock::new();
|
||||
|
||||
/// This function is called every time the app is reloaded/started. It quickly populates the [`TERMINAL`] variable with a working terminal.
|
||||
#[tauri::command]
|
||||
async fn preload_vectum(app: AppHandle) {
|
||||
// Only fill these variables once.
|
||||
|
||||
if WORKING_DIR.get().is_none() {
|
||||
WORKING_DIR.set(Path::join(&app.path().local_data_dir().unwrap(), "SteamDepotDownloaderGUI")).expect("Failed to configure working directory")
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn start_download(steam_download: steam::SteamDownload, app: AppHandle, state: State<'_, AppState>) -> Result<(), String> {
|
||||
// Also change working directory
|
||||
// std::env::set_current_dir(&WORKING_DIR.get().unwrap()).unwrap();
|
||||
|
||||
println!("\n-------------------------DEBUG INFO------------------------");
|
||||
println!("received these values from frontend:");
|
||||
println!("\t- Username: {}", steam_download.username().as_ref().unwrap_or(&String::from("Not provided")));
|
||||
// println!("\t- Password: {}", steam_download.password().as_ref().unwrap_or(&String::from("Not provided"))); Don't log in prod lol
|
||||
println!("\t- App ID: {}", steam_download.app_id());
|
||||
println!("\t- Depot ID: {}", steam_download.depot_id());
|
||||
println!("\t- Manifest ID: {}", steam_download.manifest_id());
|
||||
println!("\t- Output Path: {}", steam_download.output_path());
|
||||
println!("\t- Working directory: {}", &WORKING_DIR.get().unwrap().display());
|
||||
println!("----------------------------------------------------------\n");
|
||||
|
||||
/* Build the command and spawn it in our terminal */
|
||||
let mut cmd = terminal::create_depotdownloader_command(&steam_download, WORKING_DIR.get().unwrap());
|
||||
|
||||
// add the $TERM env variable so we can use clear and other commands
|
||||
#[cfg(target_os = "windows")]
|
||||
cmd.env("TERM", "cygwin");
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
cmd.env("TERM", "xterm-256color");
|
||||
|
||||
let mut child = state
|
||||
.pty_pair
|
||||
.lock()
|
||||
.await
|
||||
.slave
|
||||
.spawn_command(cmd)
|
||||
.map_err(|err| err.to_string())?;
|
||||
|
||||
thread::spawn(move || {
|
||||
let status = child.wait().unwrap();
|
||||
println!("Command exited with status: {status}");
|
||||
app.emit("command-exited", {}).unwrap();
|
||||
// exit(status.exit_code() as i32)
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Downloads the DepotDownloader zip file from the internet based on the OS.
|
||||
#[tauri::command]
|
||||
async fn download_depotdownloader() {
|
||||
let url = get_depotdownloader_url();
|
||||
|
||||
// Where we store the DepotDownloader zip.
|
||||
let zip_filename = format!("DepotDownloader-v{}-{}.zip", DEPOTDOWNLOADER_VERSION, env::consts::OS);
|
||||
let depotdownloader_zip = Path::join(WORKING_DIR.get().unwrap(), Path::new(&zip_filename));
|
||||
|
||||
|
||||
if let Err(e) = depotdownloader::download_file(url.as_str(), depotdownloader_zip.as_path()).await {
|
||||
if e.kind() == AlreadyExists {
|
||||
println!("DepotDownloader already exists. Skipping download.");
|
||||
} else {
|
||||
println!("Failed to download DepotDownloader: {}", e);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
println!("Downloaded DepotDownloader for {} to {}", env::consts::OS, depotdownloader_zip.display());
|
||||
}
|
||||
|
||||
depotdownloader::unzip(depotdownloader_zip.as_path(), WORKING_DIR.get().unwrap()).unwrap();
|
||||
println!("Succesfully extracted DepotDownloader zip.");
|
||||
}
|
||||
|
||||
/// Checks internet connectivity using Google
|
||||
#[tauri::command]
|
||||
async fn internet_connection() -> bool {
|
||||
let client = reqwest::Client::builder().timeout(Duration::from_secs(5)).build().unwrap();
|
||||
|
||||
client.get("https://connectivitycheck.android.com/generate_204").send().await.is_ok()
|
||||
}
|
||||
|
||||
|
||||
pub fn get_os() -> &'static str {
|
||||
match env::consts::OS {
|
||||
"linux" => "linux",
|
||||
"macos" => "macos",
|
||||
"windows" => "windows",
|
||||
_ => "unknown",
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// macOS: change dir to documents because upon opening, our current dir by default is "/".
|
||||
// todo: Is this still needed ??
|
||||
/* if get_os() == "macos" {
|
||||
let _ = fix_path_env::fix();
|
||||
// let documents_dir = format!(
|
||||
// "{}/Documents/SteamDepotDownloaderGUI",
|
||||
// std::env::var_os("HOME").unwrap().to_str().unwrap()
|
||||
// );
|
||||
// let documents_dir = Path::new(&documents_dir);
|
||||
// // println!("{}", documents_dir.display());
|
||||
|
||||
// std::fs::create_dir_all(documents_dir).unwrap();
|
||||
// env::set_current_dir(documents_dir).unwrap();
|
||||
}*/
|
||||
|
||||
/* Initialize the pty system */
|
||||
let pty_system = native_pty_system();
|
||||
|
||||
let pty_pair = pty_system
|
||||
.openpty(PtySize {
|
||||
rows: 24,
|
||||
cols: 80,
|
||||
pixel_width: 0,
|
||||
pixel_height: 0,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let reader = pty_pair.master.try_clone_reader().unwrap();
|
||||
let writer = pty_pair.master.take_writer().unwrap();
|
||||
|
||||
println!();
|
||||
tauri::Builder::default()
|
||||
.manage(AppState {
|
||||
pty_pair: Arc::new(Mutex::new(pty_pair)),
|
||||
writer: Arc::new(Mutex::new(writer)),
|
||||
reader: Arc::new(Mutex::new(BufReader::new(reader))),
|
||||
})
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.plugin(tauri_plugin_dialog::init())
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
start_download,
|
||||
download_depotdownloader,
|
||||
internet_connection,
|
||||
preload_vectum,
|
||||
async_write_to_pty,
|
||||
async_read_from_pty,
|
||||
async_resize_pty,
|
||||
]).run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
40
src-tauri/src/steam.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
use derive_getters::Getters;
|
||||
use serde::Deserialize;
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
||||
/// Represents the data required to download a Steam depot.
|
||||
#[derive(Deserialize, Debug, Getters)]
|
||||
pub struct SteamDownload {
|
||||
username: Option<String>,
|
||||
password: Option<String>,
|
||||
app_id: String,
|
||||
depot_id: String,
|
||||
manifest_id: String,
|
||||
options: VectumOptions
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Getters)]
|
||||
pub struct VectumOptions {
|
||||
output_directory: Option<PathBuf>,
|
||||
directory_name: Option<String>
|
||||
}
|
||||
|
||||
|
||||
impl SteamDownload {
|
||||
/// If a username or password are not provided, the download is considered anonymous
|
||||
pub fn is_anonymous(&self) -> bool {
|
||||
self.username.is_none() || self.password.is_none()
|
||||
}
|
||||
|
||||
/// The directory where the download should happen
|
||||
pub fn output_path(&self) -> String {
|
||||
let sep = std::path::MAIN_SEPARATOR.to_string();
|
||||
match (&self.options.output_directory, &self.options.directory_name) {
|
||||
(Some(output_dir), Some(dir_name)) => format!("{}{}{}", output_dir.display(), sep, dir_name),
|
||||
(Some(output_dir), None) => format!("{}{}{}", output_dir.display(), sep, &self.manifest_id),
|
||||
(None, Some(dir_name)) => format!(".{}{}", sep, dir_name),
|
||||
(None, None) => format!(".{}{}", sep, &self.manifest_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
79
src-tauri/src/terminal.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
use std::io::BufRead;
|
||||
use std::path::PathBuf;
|
||||
use portable_pty::{CommandBuilder, PtySize};
|
||||
use tauri::State;
|
||||
use crate::AppState;
|
||||
use crate::steam::SteamDownload;
|
||||
|
||||
/* Parts of this file are derived from https://github.com/cablehead/tauri-xtermjs-nushell/blob/0bdd4a27ee2874de12e99bccd6c91d6ec5d28fbc/src-tauri/src/main.rs */
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn async_write_to_pty(data: &str, state: State<'_, AppState>) -> Result<(), ()> {
|
||||
write!(state.writer.lock().await, "{}", data).map_err(|_| ())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn async_read_from_pty(state: State<'_, AppState>) -> Result<Option<String>, ()> {
|
||||
let mut reader = state.reader.lock().await;
|
||||
let data = {
|
||||
// Read all available text
|
||||
let data = reader.fill_buf().map_err(|_| ())?;
|
||||
|
||||
// Send the data to the webview if necessary
|
||||
if !data.is_empty() {
|
||||
std::str::from_utf8(data)
|
||||
.map(|v| Some(v.to_string()))
|
||||
.map_err(|_| ())?
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(data) = &data {
|
||||
reader.consume(data.len());
|
||||
}
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn async_resize_pty(rows: u16, cols: u16, state: State<'_, AppState>) -> Result<(), ()> {
|
||||
state
|
||||
.pty_pair
|
||||
.lock()
|
||||
.await
|
||||
.master
|
||||
.resize(PtySize {
|
||||
rows,
|
||||
cols,
|
||||
..Default::default()
|
||||
})
|
||||
.map_err(|_| ())
|
||||
}
|
||||
|
||||
|
||||
/// Creates the DepotDownloader command necessary to download the requested manifest.
|
||||
pub fn create_depotdownloader_command(steam_download: &SteamDownload, cwd: &PathBuf) -> CommandBuilder {
|
||||
let depotdownloader_binary = if cfg!(windows) {
|
||||
"DepotDownloader.exe"
|
||||
} else {
|
||||
"DepotDownloader"
|
||||
};
|
||||
|
||||
let program = cwd.join(depotdownloader_binary);
|
||||
let mut command = CommandBuilder::new(program);
|
||||
|
||||
command.cwd(cwd);
|
||||
|
||||
if !steam_download.is_anonymous() {
|
||||
command.args(["-username", &steam_download.username().clone().unwrap()]);
|
||||
command.args(["-password", &steam_download.password().clone().unwrap()]);
|
||||
}
|
||||
|
||||
command.args(["-app", steam_download.app_id()]);
|
||||
command.args(["-depot", steam_download.depot_id()]);
|
||||
command.args(["-manifest", steam_download.manifest_id()]);
|
||||
command.args(["-dir", &steam_download.output_path()]);
|
||||
|
||||
command
|
||||
}
|
||||
37
src-tauri/tauri.conf.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"productName": "SteamDepotDownloaderGUI",
|
||||
"version": "3.1.0",
|
||||
"identifier": "net.oopium.depotdownloader",
|
||||
"build": {
|
||||
"beforeDevCommand": "pnpm dev",
|
||||
"devUrl": "http://localhost:1420",
|
||||
"beforeBuildCommand": "pnpm build",
|
||||
"frontendDist": "../dist"
|
||||
},
|
||||
"app": {
|
||||
"withGlobalTauri": true,
|
||||
"windows": [
|
||||
{
|
||||
"title": "SteamDepotDownloaderGUI",
|
||||
"width": 890,
|
||||
"height": 650,
|
||||
"resizable": false,
|
||||
"maximizable": false
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": null
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
]
|
||||
}
|
||||
}
|
||||
BIN
src/assets/Hubot-Sans.woff2
Normal file
BIN
src/assets/Windows.woff
Normal file
139
src/css/style.css
Normal file
@@ -0,0 +1,139 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
@font-face {
|
||||
font-family: 'Hubot Sans';
|
||||
src: url('../assets/Hubot-Sans.woff2') format('woff2 supports variations'),
|
||||
url('../assets/Hubot-Sans.woff2') format('woff2-variations');
|
||||
font-weight: 700;
|
||||
font-stretch: expanded;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Windows';
|
||||
src: url('../assets/Windows.woff') format('woff2 supports variations'),
|
||||
url('../assets/Windows.woff') format('woff2-variations');
|
||||
font-weight: 700;
|
||||
font-stretch: expanded;
|
||||
}
|
||||
|
||||
.f1-light {
|
||||
font-family: 'Hubot Sans', sans-serif;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.f2-light {
|
||||
font-family: 'Hubot Sans', sans-serif;
|
||||
}
|
||||
|
||||
/* The grey part */
|
||||
.settings-surrounding {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background-color: rgba(0, 0, 0, 0.33);
|
||||
}
|
||||
|
||||
.settings-content {
|
||||
position: relative;
|
||||
border-radius: 10px;
|
||||
overflow: auto;
|
||||
/*noinspection CssUnresolvedCustomProperty*/
|
||||
background-color: var(--bgColor-default, var(--color-canvas-default));
|
||||
margin: 1%;
|
||||
padding: 25px;
|
||||
border: 1.5px solid white;
|
||||
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1), 0 6px 20px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
[data-color-mode="light"] .settings-content {
|
||||
border: 1.5px solid black;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
[data-color-mode="auto"] .settings-content {
|
||||
border: 1.5px solid black;
|
||||
}
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
height: 1px;
|
||||
background: black linear-gradient(to right, #0c1016, #ccc, #0c1016);
|
||||
}
|
||||
|
||||
[data-color-mode="light"] hr {
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
[data-color-mode="auto"] hr {
|
||||
filter: invert(1);
|
||||
}
|
||||
}
|
||||
|
||||
.version-info {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
font-size: 0.9em;
|
||||
padding: 5px 10px;
|
||||
font-family: monospace;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.AnimatedEllipsis {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
vertical-align: bottom
|
||||
}
|
||||
|
||||
.AnimatedEllipsis::after {
|
||||
display: inline-block;
|
||||
content: "...";
|
||||
animation: AnimatedEllipsis-keyframes 1s steps(4, jump-none) infinite
|
||||
}
|
||||
|
||||
@keyframes AnimatedEllipsis-keyframes {
|
||||
0% {
|
||||
transform: translateX(-100%)
|
||||
}
|
||||
}
|
||||
|
||||
.opium-button {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
cursor: pointer;
|
||||
margin-left: 5px;
|
||||
margin-bottom: 4px;
|
||||
|
||||
border: 1px solid #000;
|
||||
background: linear-gradient(180deg, #8C8C8C 25%, #434343 75%);
|
||||
display: inline-block;
|
||||
font: 16px "Windows", monospace;
|
||||
padding: 2px 5px;
|
||||
color: darkred;
|
||||
text-decoration: none;
|
||||
|
||||
}
|
||||
|
||||
.opium-button:hover {
|
||||
cursor: zoom-in;
|
||||
background: linear-gradient(180deg, #b0b0b0 25%, #504f4f 75%);
|
||||
}
|
||||
|
||||
.opium-button:active {
|
||||
cursor: crosshair;
|
||||
border: 1px inset black;
|
||||
background: linear-gradient(180deg, #333232 25%, #504f4f 75%);
|
||||
}
|
||||
268
src/index.html
Normal file
@@ -0,0 +1,268 @@
|
||||
<!DOCTYPE html>
|
||||
<html data-color-mode="auto" data-dark-theme="dark" data-light-theme="light" id="theme" lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport"/>
|
||||
<title>SteamDepotDownloaderGUI</title>
|
||||
<link href="https://unpkg.com/@primer/css@21.3.6/dist/primer.css" rel="stylesheet"/>
|
||||
<link href="css/style.css" rel="stylesheet">
|
||||
<script defer src="./ts/preload.ts" type="module"></script>
|
||||
<script src="./ts/main.ts" type="module"></script>
|
||||
<script src="./ts/settings.ts" type="module"></script>
|
||||
<script src="../node_modules/@xterm/xterm/lib/xterm.js"></script>
|
||||
<link rel="stylesheet" href="../node_modules/@xterm/xterm/css/xterm.css" />
|
||||
</head>
|
||||
|
||||
<body class="select-none">
|
||||
<div class="f1-light text-center mb-1">Steam Depot Downloader</div>
|
||||
<div class="flex justify-between gap-2 w-svw flex-row">
|
||||
<div class="w-1/2 h-full" id="left-side">
|
||||
<div class="mx-auto">
|
||||
<form id="theform">
|
||||
<div class="form-group mx-3 mt-1">
|
||||
<div class="form-group-header">
|
||||
<label for="username">Username</label>
|
||||
</div>
|
||||
<input spellcheck="false" class="form-control input-block" id="username" placeholder="Leave empty for anonymous download"
|
||||
type="text"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group mx-3 mt-1">
|
||||
<div class="form-group-header">
|
||||
<label for="password">Password</label>
|
||||
</div>
|
||||
<input class="form-control input-block" id="password" placeholder="Leave empty for anonymous download"
|
||||
type="password"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group mx-3 mt-1 required">
|
||||
<div class="form-group-header">
|
||||
<label for="appid">App ID</label>
|
||||
</div>
|
||||
<input class="form-control input-block" id="appid" type="number"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group mx-3 mt-1 required">
|
||||
<div class="form-group-header">
|
||||
<label for="depotid">Depot ID</label>
|
||||
</div>
|
||||
<input class="form-control input-block" id="depotid" type="number"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group mx-3 mt-1 required">
|
||||
<div class="form-group-header">
|
||||
<label for="manifestid">Manifest ID</label>
|
||||
</div>
|
||||
<input class="form-control input-block" id="manifestid" type="number"/>
|
||||
</div>
|
||||
|
||||
<div class="mx-3 mt-1 required">
|
||||
<div class="form-group-header">
|
||||
<label>Download Location</label>
|
||||
</div>
|
||||
<div aria-label="Pick the path/location where the game will be downloaded to."
|
||||
class="form-control btn btn-sm tooltipped tooltipped-ne" id="pickpath">
|
||||
Set location
|
||||
</div>
|
||||
|
||||
<div aria-disabled="true" aria-label="Check the location that has been selected."
|
||||
class="form-control btn btn-sm ml-2 tooltipped tooltipped-ne" id="checkpath">
|
||||
Open location
|
||||
</div>
|
||||
|
||||
<span class="Label mt-1 ml-3 Label--warning" id="busy">
|
||||
<span aria-label="Application is executing a task. Please be patient."
|
||||
class="tooltipped tooltipped-n">Busy<span class="AnimatedEllipsis"></span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="mt-2" id="warning-banners">
|
||||
<div hidden id="dotnetwarning">
|
||||
<div class="flash flash-error mx-2 mt-2 color-shadow-medium" id="dotnetalert">
|
||||
<svg class="octicon" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8zm6.5-.25A.75.75 0 017.25 7h1a.75.75 0 01.75.75v2.75h.25a.75.75 0 010 1.5h-2a.75.75 0 010-1.5h.25v-2h-.25a.75.75 0 01-.75-.75zM8 6a1 1 0 100-2 1 1 0 000 2z"
|
||||
fill-rule="evenodd"></path>
|
||||
</svg>
|
||||
<code><span class="text-italic">dotnet</span></code> was not found.
|
||||
<button class="btn btn-sm flash-action" id="dotnetalertbtn">
|
||||
<svg class="octicon" height="16" viewBox="0 0 16 16" width="16"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.47 10.78a.75.75 0 001.06 0l3.75-3.75a.75.75 0 00-1.06-1.06L8.75 8.44V1.75a.75.75 0 00-1.5
|
||||
0v6.69L4.78 5.97a.75.75 0 00-1.06 1.06l3.75 3.75zM3.75 13a.75.75 0 000 1.5h8.5a.75.75 0 000-1.5h-8.5z"
|
||||
fill-rule="evenodd"></path>
|
||||
</svg>
|
||||
<span class="text-bold">Download</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div hidden id="emptywarning">
|
||||
<div class="flash flash-warn mx-2 mt-2 color-shadow-medium" id="emptyalert">
|
||||
<svg class="octicon" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8zm6.5-.25A.75.75 0 017.25 7h1a.75.75 0 01.75.75v2.75h.25a.75.75 0 010 1.5h-2a.75.75 0 010-1.5h.25v-2h-.25a.75.75 0 01-.75-.75zM8 6a1 1 0 100-2 1 1 0 000 2z"
|
||||
fill-rule="evenodd"></path>
|
||||
</svg>
|
||||
Please fill in all required fields.
|
||||
</div>
|
||||
</div>
|
||||
<div id="internet-btns">
|
||||
<div class="form-group mt-3 ml-3 mr-3">
|
||||
<div class="BtnGroup d-flex">
|
||||
<button class="BtnGroup-item btn btn-block btn-primary flex-1" id="downloadbtn">
|
||||
<svg class="octicon filter-red" height="16"
|
||||
style="display: inline-block; user-select: none; vertical-align: text-bottom;"
|
||||
viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M7.47 10.78a.75.75 0 001.06 0l3.75-3.75a.75.75 0 00-1.06-1.06L8.75 8.44V1.75a.75.75 0 00-1.5 0v6.69L4.78 5.97a.75.75 0 00-1.06 1.06l3.75 3.75zM3.75 13a.75.75 0 000 1.5h8.5a.75.75 0 000-1.5h-8.5z"
|
||||
fill-rule="evenodd"></path>
|
||||
</svg>
|
||||
Download
|
||||
</button>
|
||||
<button class="BtnGroup-item btn flex-0" id="settings-button">
|
||||
<svg fill="#8B949E" height="16"
|
||||
style="display: inline-block; user-select: none; vertical-align: text-bottom;"
|
||||
viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M8 0a8.2 8.2 0 0 1 .701.031C9.444.095 9.99.645 10.16 1.29l.288 1.107c.018.066.079.158.212.224.231.114.454.243.668.386.123.082.233.09.299.071l1.103-.303c.644-.176 1.392.021 1.82.63.27.385.506.792.704 1.218.315.675.111 1.422-.364 1.891l-.814.806c-.049.048-.098.147-.088.294.016.257.016.515 0 .772-.01.147.038.246.088.294l.814.806c.475.469.679 1.216.364 1.891a7.977 7.977 0 0 1-.704 1.217c-.428.61-1.176.807-1.82.63l-1.102-.302c-.067-.019-.177-.011-.3.071a5.909 5.909 0 0 1-.668.386c-.133.066-.194.158-.211.224l-.29 1.106c-.168.646-.715 1.196-1.458 1.26a8.006 8.006 0 0 1-1.402 0c-.743-.064-1.289-.614-1.458-1.26l-.289-1.106c-.018-.066-.079-.158-.212-.224a5.738 5.738 0 0 1-.668-.386c-.123-.082-.233-.09-.299-.071l-1.103.303c-.644.176-1.392-.021-1.82-.63a8.12 8.12 0 0 1-.704-1.218c-.315-.675-.111-1.422.363-1.891l.815-.806c.05-.048.098-.147.088-.294a6.214 6.214 0 0 1 0-.772c.01-.147-.038-.246-.088-.294l-.815-.806C.635 6.045.431 5.298.746 4.623a7.92 7.92 0 0 1 .704-1.217c.428-.61 1.176-.807 1.82-.63l1.102.302c.067.019.177.011.3-.071.214-.143.437-.272.668-.386.133-.066.194-.158.211-.224l.29-1.106C6.009.645 6.556.095 7.299.03 7.53.01 7.764 0 8 0Zm-.571 1.525c-.036.003-.108.036-.137.146l-.289 1.105c-.147.561-.549.967-.998 1.189-.173.086-.34.183-.5.29-.417.278-.97.423-1.529.27l-1.103-.303c-.109-.03-.175.016-.195.045-.22.312-.412.644-.573.99-.014.031-.021.11.059.19l.815.806c.411.406.562.957.53 1.456a4.709 4.709 0 0 0 0 .582c.032.499-.119 1.05-.53 1.456l-.815.806c-.081.08-.073.159-.059.19.162.346.353.677.573.989.02.03.085.076.195.046l1.102-.303c.56-.153 1.113-.008 1.53.27.161.107.328.204.501.29.447.222.85.629.997 1.189l.289 1.105c.029.109.101.143.137.146a6.6 6.6 0 0 0 1.142 0c.036-.003.108-.036.137-.146l.289-1.105c.147-.561.549-.967.998-1.189.173-.086.34-.183.5-.29.417-.278.97-.423 1.529-.27l1.103.303c.109.029.175-.016.195-.045.22-.313.411-.644.573-.99.014-.031.021-.11-.059-.19l-.815-.806c-.411-.406-.562-.957-.53-1.456a4.709 4.709 0 0 0 0-.582c-.032-.499.119-1.05.53-1.456l.815-.806c.081-.08.073-.159.059-.19a6.464 6.464 0 0 0-.573-.989c-.02-.03-.085-.076-.195-.046l-1.102.303c-.56.153-1.113.008-1.53-.27a4.44 4.44 0 0 0-.501-.29c-.447-.222-.85-.629-.997-1.189l-.289-1.105c-.029-.11-.101-.143-.137-.146a6.6 6.6 0 0 0-1.142 0ZM11 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0ZM9.5 8a1.5 1.5 0 1 0-3.001.001A1.5 1.5 0 0 0 9.5 8Z">
|
||||
</path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div hidden id="nopathwarning">
|
||||
<div class="flash flash-warn mx-2 mt-2 color-shadow-medium" id="emptyalert">
|
||||
<svg class="octicon" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8zm6.5-.25A.75.75 0 017.25 7h1a.75.75 0 01.75.75v2.75h.25a.75.75 0 010 1.5h-2a.75.75 0 010-1.5h.25v-2h-.25a.75.75 0 01-.75-.75zM8 6a1 1 0 100-2 1 1 0 000 2z"
|
||||
fill-rule="evenodd"></path>
|
||||
</svg>
|
||||
Please choose a download location.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flash mx-2 mt-2 color-shadow-medium" hidden id="downloadingnotice">
|
||||
<svg class="octicon" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM0 8a8 8 0 1116 0A8 8 0 010 8zm6.5-.25A.75.75 0 017.25 7h1a.75.75 0 01.75.75v2.75h.25a.75.75 0 010 1.5h-2a.75.75 0 010-1.5h.25v-2h-.25a.75.75 0 01-.75-.75zM8 6a1 1 0 100-2 1 1 0 000 2z"
|
||||
fill-rule="evenodd"></path>
|
||||
</svg>
|
||||
Downloading and extracting DepotDownloader<span class="AnimatedEllipsis"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-1/2 h-full px-2" id="right-side">
|
||||
<div class="mt-2 h-full w-full mx-auto">
|
||||
<div class="border border-gray-300 rounded-md bg-gray-900 text-white shadow shadow-blue-200">
|
||||
<div class="text-md font-semibold w-full inline-flex my-px items-center">
|
||||
<span class="text-center w-full">Download output</span>
|
||||
<button id="clear-terminal" class="disabled:pointer-events-none disabled:line-through disabled:text-gray-300 ml-auto py-px px-2 border-2 rounded-xs border-red-500/75 font-normal enabled:hover:bg-red-200/30 enabled:active:bg-red-200/50">
|
||||
Clear
|
||||
</button>
|
||||
</div>
|
||||
<div class="max-h-[70vh]" id="xtermjs"></div>
|
||||
</div>
|
||||
<div class="mt-3 justify-between flex flex-row gap-3">
|
||||
<div aria-label="Join the Discord server for rapid support." class="btn btn-sm tooltipped tooltipped-ne mb-1 w-full text-center items-center"
|
||||
id="smbtn1">
|
||||
|
||||
<svg fill="#8B949E" height="16" style="display: inline-block; vertical-align: text-bottom;" viewBox="0 0 16 16">
|
||||
<path d="M13.545 2.907a13.2 13.2 0 0 0-3.257-1.011.05.05 0 0 0-.052.025c-.141.25-.297.577-.406.833a12.2 12.2 0 0 0-3.658 0 8 8 0 0 0-.412-.833.05.05 0 0 0-.052-.025c-1.125.194-2.22.534-3.257 1.011a.04.04 0 0 0-.021.018C.356 6.024-.213 9.047.066 12.032q.003.022.021.037a13.3 13.3 0 0 0 3.995 2.02.05.05 0 0 0 .056-.019q.463-.63.818-1.329a.05.05 0 0 0-.01-.059l-.018-.011a9 9 0 0 1-1.248-.595.05.05 0 0 1-.02-.066l.015-.019q.127-.095.248-.195a.05.05 0 0 1 .051-.007c2.619 1.196 5.454 1.196 8.041 0a.05.05 0 0 1 .053.007q.121.1.248.195a.05.05 0 0 1-.004.085 8 8 0 0 1-1.249.594.05.05 0 0 0-.03.03.05.05 0 0 0 .003.041c.24.465.515.909.817 1.329a.05.05 0 0 0 .056.019 13.2 13.2 0 0 0 4.001-2.02.05.05 0 0 0 .021-.037c.334-3.451-.559-6.449-2.366-9.106a.03.03 0 0 0-.02-.019m-8.198 7.307c-.789 0-1.438-.724-1.438-1.612s.637-1.613 1.438-1.613c.807 0 1.45.73 1.438 1.613 0 .888-.637 1.612-1.438 1.612m5.316 0c-.788 0-1.438-.724-1.438-1.612s.637-1.613 1.438-1.613c.807 0 1.451.73 1.438 1.613 0 .888-.631 1.612-1.438 1.612"/>
|
||||
</svg>
|
||||
Discord
|
||||
</div>
|
||||
|
||||
<div aria-label="Visit the SteamDB instant search website."
|
||||
class="btn btn-sm tooltipped tooltipped-n mb-1 w-full text-center items-center" id="smbtn2">
|
||||
<svg aria-hidden="true" class="octicon" fill="#8B949E" height="16" viewBox="0 0 128 128" width="16"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M63.9 0C30.5 0 3.1 11.9.1 27.1l35.6 6.7c2.9-.9 6.2-1.3 9.6-1.3l16.7-10c-.2-2.5 1.3-5.1 4.7-7.2 4.8-3.1 12.3-4.8 19.9-4.8 5.2-.1 10.5.7 15 2.2 11.2 3.8 13.7 11.1 5.7 16.3-5.1 3.3-13.3 5-21.4 4.8l-22 7.9c-.2 1.6-1.3 3.1-3.4 4.5-5.9 3.8-17.4 4.7-25.6 1.9-3.6-1.2-6-3-7-4.8L2.5 38.4c2.3 3.6 6 6.9 10.8 9.8C5 53 0 59 0 65.5c0 6.4 4.8 12.3 12.9 17.1C4.8 87.3 0 93.2 0 99.6 0 115.3 28.6 128 64 128c35.3 0 64-12.7 64-28.4 0-6.4-4.8-12.3-12.9-17 8.1-4.8 12.9-10.7 12.9-17.1 0-6.5-5-12.6-13.4-17.4 8.3-5.1 13.3-11.4 13.3-18.2 0-16.5-28.7-29.9-64-29.9zm22.8 14.2c-5.2.1-10.2 1.2-13.4 3.3-5.5 3.6-3.8 8.5 3.8 11.1 7.6 2.6 18.1 1.8 23.6-1.8s3.8-8.5-3.8-11c-3.1-1-6.7-1.5-10.2-1.5zm.3 1.7c7.4 0 13.3 2.8 13.3 6.2 0 3.4-5.9 6.2-13.3 6.2s-13.3-2.8-13.3-6.2c0-3.4 5.9-6.2 13.3-6.2zM45.3 34.4c-1.6.1-3.1.2-4.6.4l9.1 1.7a10.8 5 0 1 1-8.1 9.3l-8.9-1.7c1 .9 2.4 1.7 4.3 2.4 6.4 2.2 15.4 1.5 20-1.5s3.2-7.2-3.2-9.3c-2.6-.9-5.7-1.3-8.6-1.3zM109 51v9.3c0 11-20.2 19.9-45 19.9-24.9 0-45-8.9-45-19.9v-9.2c11.5 5.3 27.4 8.6 44.9 8.6 17.6 0 33.6-3.3 45.2-8.7zm0 34.6v8.8c0 11-20.2 19.9-45 19.9-24.9 0-45-8.9-45-19.9v-8.8c11.6 5.1 27.4 8.2 45 8.2s33.5-3.1 45-8.2z"
|
||||
fill-rule="evenodd"></path>
|
||||
</svg>
|
||||
SteamDB
|
||||
</div>
|
||||
|
||||
<div aria-label="Donate to the author of SteamDepotDownloaderGUI."
|
||||
class="btn btn-sm tooltipped tooltipped-n mb-1 w-full text-center items-center" id="smbtn3">
|
||||
<svg fill="#8B949E" height="16" style="display: inline-block; vertical-align: text-bottom;"
|
||||
viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M2 2.75A2.75 2.75 0 0 1 4.75 0c.983 0 1.873.42 2.57 1.232.268.318.497.668.68 1.042.183-.375.411-.725.68-1.044C9.376.42 10.266 0 11.25 0a2.75 2.75 0 0 1 2.45 4h.55c.966 0 1.75.784 1.75 1.75v2c0 .698-.409 1.301-1 1.582v4.918A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V9.332C.409 9.05 0 8.448 0 7.75v-2C0 4.784.784 4 1.75 4h.55c-.192-.375-.3-.8-.3-1.25ZM7.25 9.5H2.5v4.75c0 .138.112.25.25.25h4.5Zm1.5 0v5h4.5a.25.25 0 0 0 .25-.25V9.5Zm0-4V8h5.5a.25.25 0 0 0 .25-.25v-2a.25.25 0 0 0-.25-.25Zm-7 0a.25.25 0 0 0-.25.25v2c0 .138.112.25.25.25h5.5V5.5h-5.5Zm3-4a1.25 1.25 0 0 0 0 2.5h2.309c-.233-.818-.542-1.401-.878-1.793-.43-.502-.915-.707-1.431-.707ZM8.941 4h2.309a1.25 1.25 0 0 0 0-2.5c-.516 0-1 .205-1.43.707-.337.392-.646.975-.879 1.793Z"
|
||||
fill-rule="evenodd"></path>
|
||||
</svg>
|
||||
Donate
|
||||
</div>
|
||||
|
||||
<div aria-label="View the official SteamDepotDownloaderGUI tutorials."
|
||||
class="btn btn-sm tooltipped tooltipped-nw mb-1 w-full text-center items-center" id="smbtn4">
|
||||
<svg fill="#8B949E" style="display: inline-block; vertical-align: text-bottom;" height="16" width="16">
|
||||
<path d="M0 3.75C0 2.784.784 2 1.75 2h12.5c.966 0 1.75.784 1.75 1.75v8.5A1.75 1.75 0 0 1 14.25 14H1.75A1.75 1.75 0 0 1 0 12.25Zm1.75-.25a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-8.5a.25.25 0 0 0-.25-.25Z"></path>
|
||||
<path d="M6 10.559V5.442a.25.25 0 0 1 .379-.215l4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559Z"></path>
|
||||
</svg>
|
||||
Tutorial
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-surrounding" id="settings-surrounding">
|
||||
<div class="settings-content mx-auto max-w-2/3 h-[85vh] mt-4" id="settings-content">
|
||||
<label class="version-info" id="version-info">UNKNOWN</label>
|
||||
<button class="opium-button" id="opium-btn">aphex</button>
|
||||
<h2><b>Settings</b></h2>
|
||||
<h4><b>Appearance</b></h4>
|
||||
<div class="form-group">
|
||||
<div class="form-group-header">
|
||||
<label>Theme</label>
|
||||
</div>
|
||||
<div class="form-group-body">
|
||||
<div class="BtnGroup">
|
||||
<button aria-selected="true" class="BtnGroup-item btn btn-sm" id="theme-auto" type="button">
|
||||
Auto
|
||||
</button>
|
||||
<button class="BtnGroup-item btn btn-sm" id="theme-light" type="button">
|
||||
Light
|
||||
</button>
|
||||
<button class="BtnGroup-item btn btn-sm" id="theme-dark" type="button">
|
||||
Dark
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h4><b>Output</b></h4>
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<div class="form-group-header">
|
||||
<label for="folder-name-custom-input">Game directory name</label>
|
||||
</div>
|
||||
<div class="form-group-body">
|
||||
<div class="BtnGroup">
|
||||
<button aria-selected="true" class="BtnGroup-item btn btn-sm" id="folder-name-appid"
|
||||
type="button">
|
||||
Manifest ID
|
||||
</button>
|
||||
<button class="BtnGroup-item btn btn-sm" id="folder-name-custom" type="button">
|
||||
Custom
|
||||
</button>
|
||||
</div>
|
||||
<br>
|
||||
<input class="form-control input-block mt-2" disabled
|
||||
id="folder-name-custom-input" placeholder="DepotDownloader output directory name"
|
||||
type="text">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
245
src/ts/main.ts
Normal file
@@ -0,0 +1,245 @@
|
||||
import $ from "jquery";
|
||||
import {invoke} from "@tauri-apps/api/core";
|
||||
import {open as openDialog} from "@tauri-apps/plugin-dialog";
|
||||
import {openPath, openUrl} from "@tauri-apps/plugin-opener";
|
||||
import "@xterm/xterm/css/xterm.css";
|
||||
import {Terminal} from "@xterm/xterm";
|
||||
import { FitAddon } from "@xterm/addon-fit";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
|
||||
/* Parts of this file are derived from https://github.com/cablehead/tauri-xtermjs-nushell/blob/0bdd4a27ee2874de12e99bccd6c91d6ec5d28fbc/src/main.ts */
|
||||
|
||||
function blockTerminalClearButton(state: boolean) {
|
||||
$("#clear-terminal").prop( "disabled", state );
|
||||
}
|
||||
|
||||
|
||||
function setLoadingState(state: boolean) {
|
||||
$("#busy").prop("hidden", !state);
|
||||
|
||||
// loop through all buttons and input fields and disable them
|
||||
for (const element of document.querySelectorAll("button, input, div[role='button']")) {
|
||||
if (element.closest("#settings-content")) continue;
|
||||
if (element.closest("#right-side")) continue;
|
||||
(element as any).disabled = state;
|
||||
}
|
||||
|
||||
// These elements need additional properties to be properly disabled
|
||||
$("#pickpath").prop("ariaDisabled", state);
|
||||
$("#downloadbtn").prop("ariaDisabled", state);
|
||||
|
||||
// disable internet buttons
|
||||
for (const element of document.querySelectorAll("#internet-btns div")) {
|
||||
element.ariaDisabled = String(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Returns list of IDs of invalid form fields
|
||||
const invalidFields = () => {
|
||||
const form = document.forms[0];
|
||||
|
||||
const invalidFields: string[] = [];
|
||||
for (const input of form) {
|
||||
const inputElement = input as HTMLInputElement;
|
||||
const valid = !(inputElement.value === "" && inputElement?.parentElement?.classList.contains("required"));
|
||||
if (!valid) {
|
||||
invalidFields.push(inputElement.id);
|
||||
}
|
||||
}
|
||||
// console.debug(`[${invalidFields.join(", ")}] fields invalid/empty`);
|
||||
|
||||
return invalidFields;
|
||||
};
|
||||
|
||||
const registerTerminal: (terminalElement: HTMLElement) => Promise<Terminal> = async (terminalElement: HTMLElement) => {
|
||||
const fitAddon = new FitAddon();
|
||||
const term = new Terminal({
|
||||
fontSize: 10,
|
||||
cursorBlink: true,
|
||||
rows: 100,
|
||||
cols: 100,
|
||||
theme: {
|
||||
background: "rgb(33, 33, 33)",
|
||||
},
|
||||
});
|
||||
term.loadAddon(fitAddon);
|
||||
term.open(terminalElement);
|
||||
async function fitTerminal() {
|
||||
fitAddon.fit();
|
||||
void invoke<string>("async_resize_pty", {
|
||||
rows: term.rows,
|
||||
cols: term.cols,
|
||||
});
|
||||
}
|
||||
|
||||
// Write data from pty into the terminal
|
||||
function writeToTerminal(data: string) {
|
||||
return new Promise<void>((r) => {
|
||||
term.write(data, () => r());
|
||||
});
|
||||
}
|
||||
|
||||
// Write data from the terminal to the pty
|
||||
function writeToPty(data: string) {
|
||||
void invoke("async_write_to_pty", {
|
||||
data,
|
||||
});
|
||||
}
|
||||
term.onData(writeToPty);
|
||||
addEventListener("resize", fitTerminal);
|
||||
await fitTerminal();
|
||||
|
||||
async function readFromPty() {
|
||||
const data = await invoke<string>("async_read_from_pty");
|
||||
|
||||
if (data) {
|
||||
await writeToTerminal(data);
|
||||
}
|
||||
window.requestAnimationFrame(readFromPty);
|
||||
}
|
||||
|
||||
window.requestAnimationFrame(readFromPty);
|
||||
|
||||
return term;
|
||||
};
|
||||
|
||||
|
||||
$(async () => {
|
||||
let terminal = await registerTerminal($("#xtermjs")[0]);
|
||||
let downloadDirectory: string | null;
|
||||
|
||||
// Startup logic
|
||||
setLoadingState(true);
|
||||
await invoke("preload_vectum");
|
||||
setLoadingState(false);
|
||||
|
||||
$("#clear-terminal").on("click", async () => {
|
||||
terminal.reset()
|
||||
})
|
||||
|
||||
$("#pickpath").on("click", async () => {
|
||||
// Open a dialog
|
||||
downloadDirectory = await openDialog({
|
||||
title: "Choose where to save the game download.",
|
||||
multiple: false,
|
||||
directory: true,
|
||||
canCreateDirectories: true
|
||||
});
|
||||
|
||||
if (downloadDirectory == null) {
|
||||
// user cancelled
|
||||
$("#checkpath").prop("ariaDisabled", true);
|
||||
$("#checkpath").prop("disabled", true);
|
||||
return;
|
||||
}
|
||||
|
||||
$("#checkpath").prop("ariaDisabled", false);
|
||||
$("#checkpath").prop("disabled", false);
|
||||
$("#downloadbtn").prop("ariaDisabled", false);
|
||||
$("#nopathwarning").prop("hidden", true);
|
||||
|
||||
|
||||
console.log(downloadDirectory);
|
||||
});
|
||||
|
||||
$("#checkpath").on("click", async () => {
|
||||
console.log(`Checking path: ${downloadDirectory}`);
|
||||
|
||||
if (downloadDirectory != null) {
|
||||
await openPath(downloadDirectory);
|
||||
} else {
|
||||
$("#checkpath").prop("ariaDisabled", true);
|
||||
}
|
||||
});
|
||||
|
||||
$("#downloadbtn").on("click", async () => {
|
||||
console.log("download button clicked");
|
||||
|
||||
if (invalidFields().length > 0) {
|
||||
// Loop through invalid fields. If there are any, make those "errored" and block the download button.
|
||||
for (const id of invalidFields()) {
|
||||
document.getElementById(id)?.parentElement?.classList.toggle("errored", true);
|
||||
}
|
||||
$("#emptywarning").prop("hidden", false);
|
||||
$("#downloadbtn").prop("ariaDisabled", true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (downloadDirectory == null) {
|
||||
$("#nopathwarning").prop("hidden", false);
|
||||
$("#downloadbtn").prop("ariaDisabled", true);
|
||||
return;
|
||||
}
|
||||
|
||||
setLoadingState(true);
|
||||
$("#downloadingnotice").prop("hidden", false);
|
||||
$("#busy").prop("hidden", true); // Don't show the loader this time.
|
||||
|
||||
const directoryNameChoice = $("#folder-name-custom-input").val();
|
||||
|
||||
// Output path w/ directories chosen is: {downloadDirectory}/{directoryNameChoice}
|
||||
const vectumOptions = {
|
||||
output_directory: downloadDirectory || null, // if not specified let backend choose a path.
|
||||
directory_name: directoryNameChoice || null,
|
||||
};
|
||||
|
||||
const steamDownload = {
|
||||
// String || null translate to Some(String) || None
|
||||
username: String($("#username").val()).trim() || null,
|
||||
password: String($("#password").val()).trim() || null,
|
||||
app_id: $("#appid").val(),
|
||||
depot_id: $("#depotid").val(),
|
||||
manifest_id: $("#manifestid").val(),
|
||||
options: vectumOptions
|
||||
};
|
||||
|
||||
// console.debug(steamDownload);
|
||||
await invoke("download_depotdownloader");
|
||||
|
||||
$("#downloadingnotice").prop("hidden", true);
|
||||
setLoadingState(false);
|
||||
|
||||
console.debug("DepotDownloader download process completed. Starting game download...");
|
||||
|
||||
setLoadingState(true);
|
||||
await invoke("start_download", {steamDownload: steamDownload});
|
||||
|
||||
// Block clear terminal button (to avoid clearing ongoing download logs)
|
||||
blockTerminalClearButton(true);
|
||||
console.log("Send frontend data over to backend. Ready for next download.");
|
||||
});
|
||||
|
||||
$("#settings-button").on("click", async () => {
|
||||
$("#settings-surrounding").toggle();
|
||||
});
|
||||
|
||||
$("#settings-surrounding").on("click", (event) => {
|
||||
if (event.target === document.getElementById("settings-surrounding")) {
|
||||
$("#settings-surrounding").toggle();
|
||||
}
|
||||
});
|
||||
|
||||
$("#opium-btn").on("click", () => {
|
||||
openUrl("https://aphex.cc/index.html");
|
||||
});
|
||||
|
||||
|
||||
document.forms[0].addEventListener("input", (event) => {
|
||||
// Remove errored class. This is a bad way to do it, but it works for now.
|
||||
const target = event.target as HTMLElement;
|
||||
target?.parentElement?.classList.toggle("errored", false);
|
||||
|
||||
// If there are no more invalid fields, hide the warning and enable the download button again
|
||||
if (invalidFields().length === 0) {
|
||||
$("#emptywarning").prop("hidden", true);
|
||||
$("#downloadbtn").prop("ariaDisabled", false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
listen<string>("command-exited", () => {
|
||||
setLoadingState(false);
|
||||
blockTerminalClearButton(false);
|
||||
});
|
||||
34
src/ts/preload.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import {message} from "@tauri-apps/plugin-dialog";
|
||||
import {invoke} from "@tauri-apps/api/core";
|
||||
import $ from "jquery";
|
||||
import {openUrl} from "@tauri-apps/plugin-opener";
|
||||
|
||||
|
||||
$(async () => {
|
||||
/* eslint-disable indent */
|
||||
switch (await invoke("internet_connection")) {
|
||||
case false: {
|
||||
await message("No internet connection! Can't proceed.", {
|
||||
title: "SteamDepotDownloaderGUI", kind: "error", okLabel: "Close"
|
||||
});
|
||||
}
|
||||
}
|
||||
/* eslint-enable indent */
|
||||
|
||||
// discord
|
||||
$("#smbtn1").on("click", () => {
|
||||
openUrl("https://discord.com/invite/3qCt4DT5qe");
|
||||
});
|
||||
// steamdb
|
||||
$("#smbtn2").on("click", () => {
|
||||
openUrl("https://steamdb.info/instantsearch");
|
||||
});
|
||||
// donate
|
||||
$("#smbtn3").on("click", () => {
|
||||
openUrl("https://paypal.me/onderkin");
|
||||
});
|
||||
// tutorial
|
||||
$("#smbtn4").on("click", () => {
|
||||
openUrl("https://youtube.com/playlist?list=PLRAjc5plLScj967hnsYX-I3Vjw9C1v7Ca");
|
||||
});
|
||||
});
|
||||
47
src/ts/settings.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import {getVersion} from "@tauri-apps/api/app";
|
||||
import $ from "jquery";
|
||||
import {openUrl} from "@tauri-apps/plugin-opener";
|
||||
|
||||
|
||||
$(async () => {
|
||||
$("#version-info").text(`v${await getVersion()}`);
|
||||
|
||||
$("#theme-auto").on("click", () => {
|
||||
setTheme("auto");
|
||||
});
|
||||
$("#theme-light").on("click", () => {
|
||||
setTheme("light");
|
||||
});
|
||||
$("#theme-dark").on("click", () => {
|
||||
setTheme("dark");
|
||||
});
|
||||
|
||||
$("#folder-name-appid").on("click", () => {
|
||||
$("#folder-name-custom").attr("aria-selected", "false");
|
||||
$("#folder-name-appid").attr("aria-selected", "true");
|
||||
$("#folder-name-custom-input").prop("disabled", true);
|
||||
$("#folder-name-custom-input").val("");
|
||||
});
|
||||
|
||||
// todo: fix folder-name-custom-input not disabled on untouched app state
|
||||
|
||||
$("#folder-name-custom").on("click", () => {
|
||||
$("#folder-name-appid").attr("aria-selected", "false");
|
||||
$("#folder-name-custom").attr("aria-selected", "true");
|
||||
$("#folder-name-custom-input").prop("disabled", false);
|
||||
});
|
||||
|
||||
console.log(await getVersion());
|
||||
|
||||
$("#version-info").on("click", async () => {
|
||||
await openUrl(`https://github.com/mmvanheusden/SteamDepotDownloaderGUI/releases/v${await getVersion()}`);
|
||||
});
|
||||
});
|
||||
|
||||
function setTheme(theme: string) {
|
||||
$("#theme-auto").attr("aria-selected", String(theme === "auto"));
|
||||
$("#theme-light").attr("aria-selected", String(theme === "light"));
|
||||
$("#theme-dark").attr("aria-selected", String(theme === "dark"));
|
||||
$("#theme").attr("data-color-mode", theme);
|
||||
localStorage.theme = theme;
|
||||
}
|
||||
27
tsconfig.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": [
|
||||
"ES2020",
|
||||
"DOM",
|
||||
"DOM.Iterable"
|
||||
],
|
||||
"skipLibCheck": true,
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
}
|
||||
221
utils.js
@@ -1,221 +0,0 @@
|
||||
/**
|
||||
* Checks if dotnet is installed in the system path
|
||||
* @returns {Promise<unknown>} A promise that resolves to true if dotnet is installed, false otherwise
|
||||
*/
|
||||
function preDownloadCheck() {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Check if all fields are filled
|
||||
const formInputs = document.forms["theform"]
|
||||
|
||||
let unfilledFields = 0
|
||||
for (const input of formInputs) {
|
||||
const isInvalid = input.value === "" && input.parentElement.classList.contains("required")
|
||||
input.parentElement.classList.toggle("errored", isInvalid) // toggle the 'errored' class depending on if isInvalid is true or false.
|
||||
if (isInvalid) unfilledFields++
|
||||
}
|
||||
if (unfilledFields > 0) {
|
||||
reject("emptyField")
|
||||
return
|
||||
}
|
||||
|
||||
// Check if dotnet is installed, depending on the platform
|
||||
if (process.platform.toString().includes("win")) {
|
||||
// Windows
|
||||
const {exec} = require("child_process")
|
||||
const command = "dotnet.exe --version"
|
||||
exec(command, function (error) {
|
||||
if (error) {
|
||||
reject("noDotnet")
|
||||
} else {
|
||||
resolve(true)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// Linux
|
||||
const {exec} = require("child_process")
|
||||
const command = "dotnet --version"
|
||||
exec(command, function (error) {
|
||||
if (error) {
|
||||
reject("noDotnet")
|
||||
} else {
|
||||
resolve(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a file from a url, saving it to the current directory (__dirname)
|
||||
* @param url The url to download from
|
||||
* @returns {Promise<unknown>} A promise that resolves when the download is finished, or rejects if something fails
|
||||
*/
|
||||
function download(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const {https} = require("follow-redirects") /* Using follow-redirects to follow redirects */
|
||||
const fs = require("fs")
|
||||
const path = require("path")
|
||||
const file = fs.createWriteStream(platformpath() + path.sep + url.split("/").pop())
|
||||
https.get(url, function (response) {
|
||||
response.pipe(file)
|
||||
file.on("finish", function () {
|
||||
file.close()
|
||||
resolve()
|
||||
})
|
||||
file.on("error", function (error) {
|
||||
console.error(error)
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a file from the current directory
|
||||
* @param file The filename to remove
|
||||
* @returns {Promise<unknown>} A promise that resolves when the file is removed, or rejects if something fails
|
||||
*/
|
||||
function removeFile(file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const fs = require("fs")
|
||||
const path = require("path")
|
||||
fs.unlink(platformpath() + path.sep + file, function (error) {
|
||||
if (error) {
|
||||
reject(error)
|
||||
console.error(error)
|
||||
} else resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a directory from the current directory
|
||||
* @param dir The directory to remove
|
||||
* @returns {Promise<unknown>} A promise that resolves when the directory is removed, or rejects if something fails
|
||||
*/
|
||||
function removeDir(dir,) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const fs = require("fs")
|
||||
const path = require("path")
|
||||
fs.rm(platformpath() + path.sep + dir, {recursive: true, force: true}, function (error) {
|
||||
if (error) {
|
||||
reject(error)
|
||||
console.error(error)
|
||||
} else resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Unzip a file to the current directory
|
||||
* @param file The file to unzip, preferably a .zip file
|
||||
* @param target The target directory to unzip to
|
||||
* @returns {Promise<unknown>} A promise that resolves when the unzip is complete, or rejects if something fails
|
||||
*/
|
||||
function unzip(file, target) {
|
||||
const {exec} = require("child_process")
|
||||
const path = require("path")
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (process.platform.toString().includes("win")) {
|
||||
const command = "powershell.exe -Command Expand-Archive -Path " + platformpath() + path.sep + file + " -Destination " + platformpath() + path.sep + target
|
||||
exec(command, function (error) {
|
||||
if (error) {
|
||||
reject(error)
|
||||
console.error(error)
|
||||
} else resolve()
|
||||
})
|
||||
} else {
|
||||
const command = "unzip -o " + file + " -d ./" + target + "/"
|
||||
exec(command, function (error) {
|
||||
if (error) {
|
||||
reject(error)
|
||||
console.error(error)
|
||||
} else resolve()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a command based on the operating system/terminal being selected and the form values
|
||||
* @returns {string} The final command to run
|
||||
*/
|
||||
const createCommand = () => {
|
||||
// Import path so \ can be put in a string
|
||||
const path = require("path")
|
||||
|
||||
// The values inputted by the user in the form
|
||||
let username = document.forms["theform"]["username"].value
|
||||
let password = document.forms["theform"]["password"].value
|
||||
let appid = document.forms["theform"]["appid"].value
|
||||
let depotid = document.forms["theform"]["depotid"].value
|
||||
let manifestid = document.forms["theform"]["manifestid"].value
|
||||
let osdropdown = document.getElementById("osdropdown")
|
||||
|
||||
// if either the username or password fields are empty, anonymous login is used
|
||||
let anonymous = username === "" || password === ""
|
||||
|
||||
// Allows enormous strings like &$§"&$="§$/"(§NJUIDW>;!%?aQ52V?*['YsDnRy|(+Q 1h6BmnDQp,(Xr&Th _fMMm|*1T5a^HBuJr)EYKdA$~V*9N~74zg3hf9ZH(!HR"§RH§"H(R being used as password
|
||||
password = password.replace(/"/g, "\"\"")
|
||||
|
||||
// build the username and password flags into one string, allowing for anonymous login
|
||||
let userpass = anonymous ? "" : `-username ${username} -password "${password}"`
|
||||
|
||||
const finalPath = platformpath() + path.sep + "games" + path.sep + appid
|
||||
|
||||
// The final command to run, returned by this function
|
||||
if (osdropdown.options[osdropdown.selectedIndex].text.includes("Gnome")) {
|
||||
return `gnome-terminal -e 'bash -c "dotnet ./depotdownloader/DepotDownloader.dll ${userpass} -app ${appid} -depot ${depotid} -manifest ${manifestid} -dir ${finalPath}/ -max-servers 50 -max-downloads 16";bash'`
|
||||
} else if (osdropdown.options[osdropdown.selectedIndex].text.includes("Windows")) {
|
||||
return `start cmd.exe /k dotnet ${platformpath()}${path.sep}depotdownloader${path.sep}DepotDownloader.dll ${userpass} -app ${appid} -depot ${depotid} -manifest ${manifestid} -dir ${finalPath}/ -max-servers 50 -max-downloads 16`
|
||||
} else if (osdropdown.options[osdropdown.selectedIndex].text.includes("macOS")) {
|
||||
return `osascript -c 'tell application "Terminal" to do script 'dotnet ./depotdownloader/DepotDownloader.dll ${userpass} -app ${appid} -depot ${depotid} -manifest ${manifestid} -dir ${finalPath}/ -max-servers 50 -max-downloads 16'`
|
||||
} else if (osdropdown.options[osdropdown.selectedIndex].text.includes("Konsole")) {
|
||||
return `konsole --hold -e "dotnet ./depotdownloader/DepotDownloader.dll ${userpass} -app ${appid} -depot ${depotid} -manifest ${manifestid} -dir ${finalPath}/ -max-servers 50 -max-downloads 16"`
|
||||
} else if (osdropdown.options[osdropdown.selectedIndex].text.includes("Xfce")) {
|
||||
return `xfce4-terminal -H -e "dotnet ./depotdownloader/DepotDownloader.dll ${userpass} -app ${appid} -depot ${depotid} -manifest ${manifestid} -dir ${finalPath}/ -max-servers 50 -max-downloads 16"`
|
||||
} else if (osdropdown.options[osdropdown.selectedIndex].text.includes("Terminator")) {
|
||||
return `terminator -e 'bash -c "dotnet ./depotdownloader/DepotDownloader.dll ${userpass} -app ${appid} -depot ${depotid} -manifest ${manifestid} -dir ${finalPath}/ -max-servers 50 -max-downloads 16";bash'`
|
||||
} else if (osdropdown.options[osdropdown.selectedIndex].text.includes("Print command")) {
|
||||
console.log(`COPY-PASTE THE FOLLOWING INTO YOUR TERMINAL OF CHOICE:\n\ndotnet ${platformpath()}/depotdownloader/DepotDownloader.dll ${userpass} -app ${appid} -depot ${depotid} -manifest ${manifestid} -dir ${finalPath} -max-servers 50 -max-downloads 16`)
|
||||
return "echo hello"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a command in a separate process, printing errors and debugging info to the console
|
||||
* @param command The command to run
|
||||
* @returns {Promise<unknown>} A promise that resolves when the command is complete or rejects if something fails
|
||||
*/
|
||||
function runCommand(command) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const {exec} = require("child_process")
|
||||
exec(command, function (error) {
|
||||
if (error) {
|
||||
const msg = "Running command failed with error:\n" + error
|
||||
reject(msg)
|
||||
} else resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path where the actual program is being run from, depending on the operating system.
|
||||
* Because __dirname is inconsistent across operating systems, this function is used to get the correct path
|
||||
* @returns {string} The absolute path
|
||||
*/
|
||||
const platformpath = () => {
|
||||
if ((__dirname.includes("AppData") || __dirname.includes("Temp")) && process.platform.toString().includes("win")) {
|
||||
// Windows portable exe
|
||||
return process.env.PORTABLE_EXECUTABLE_DIR
|
||||
} else if (__dirname.includes("/tmp/") && process.platform.toString().includes("linux")) {
|
||||
// Linux AppImage
|
||||
return process.cwd()
|
||||
} else {
|
||||
// .zip binary
|
||||
return __dirname
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {preDownloadCheck, download, createCommand, runCommand, removeDir, removeFile, unzip, platformpath}
|
||||
39
vite.config.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import {defineConfig} from "vite";
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
|
||||
// @ts-expect-error process is a nodejs global
|
||||
const host = process.env.TAURI_DEV_HOST;
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(async () => ({
|
||||
|
||||
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
|
||||
//
|
||||
// 1. prevent vite from obscuring rust errors
|
||||
clearScreen: false,
|
||||
// 2. tauri expects a fixed port, fail if that port is not available
|
||||
server: {
|
||||
port: 1420,
|
||||
strictPort: true,
|
||||
host: host || false,
|
||||
hmr: host
|
||||
? {
|
||||
protocol: "ws",
|
||||
host,
|
||||
port: 1421,
|
||||
}
|
||||
: undefined,
|
||||
watch: {
|
||||
// 3. tell vite to ignore watching `src-tauri`
|
||||
ignored: ["**/src-tauri/**"],
|
||||
}
|
||||
},
|
||||
root: "src",
|
||||
build: {
|
||||
outDir: '../dist',
|
||||
emptyOutDir: true,
|
||||
},
|
||||
plugins: [
|
||||
tailwindcss(),
|
||||
]
|
||||
}));
|
||||