mirror of
https://github.com/bryangerlach/rdgen.git
synced 2025-11-29 00:23:27 +00:00
Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e46d0bd0ef | ||
|
|
67e2bc7df9 | ||
|
|
2e229d0800 | ||
|
|
89ee4822dd | ||
|
|
c429836057 | ||
|
|
6f1bb528bd | ||
|
|
13114d0bc3 | ||
|
|
56c4d9f0b7 | ||
|
|
6c7c1ed3e7 | ||
|
|
abbf4d899b | ||
|
|
3e22a34906 | ||
|
|
b4ec36c59a | ||
|
|
7d578df4c2 | ||
|
|
3169440af6 | ||
|
|
12b5fe1e30 | ||
|
|
23e91a5ea7 | ||
|
|
be47bcbe46 | ||
|
|
668998e390 | ||
|
|
fabbc91fae | ||
|
|
50082d5566 | ||
|
|
ac3d60cae1 | ||
|
|
6755dc1fa0 | ||
|
|
c53548dcce | ||
|
|
e36790addc | ||
|
|
94f1560196 | ||
|
|
6ac5f4b283 | ||
|
|
606a5ee956 | ||
|
|
2548477390 | ||
|
|
885523e2f9 | ||
|
|
253749df21 | ||
|
|
050f4b3130 | ||
|
|
cc59f1d58d | ||
|
|
a56f965344 | ||
|
|
a45bc0acdd | ||
|
|
5ea49e7a00 | ||
|
|
131ec1759d | ||
|
|
bcef3a4026 | ||
|
|
0240a905f9 | ||
|
|
8577a25657 | ||
|
|
465a9d3554 | ||
|
|
f0f67f5be1 | ||
|
|
2c1a5f93b5 | ||
|
|
55c41599be | ||
|
|
9f23f1c94a | ||
|
|
7479fbbd8f | ||
|
|
c0ede165ab | ||
|
|
78ec60d272 | ||
|
|
807f26360e | ||
|
|
bad75caf0b | ||
|
|
b76e34aa1c | ||
|
|
e3c41ee258 | ||
|
|
c76a63d269 | ||
|
|
88918cde01 | ||
|
|
6725aa21b0 | ||
|
|
1978be9edf | ||
|
|
4edff33ebd | ||
|
|
49fd150fe5 | ||
|
|
c8c1fac268 | ||
|
|
a91d66007d | ||
|
|
ca1aa3fcc5 | ||
|
|
409ed5cfa3 | ||
|
|
2ca25d3a39 | ||
|
|
0e975e73db | ||
|
|
62ac82ec2e | ||
|
|
fc239ef7b5 | ||
|
|
71eb691a52 | ||
|
|
256d647f04 | ||
|
|
7644222adf | ||
|
|
fdfebbb01a | ||
|
|
cd1915a4bf |
69
.github/workflows/build-web.yml
vendored
Normal file
69
.github/workflows/build-web.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
name: Build web
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
env:
|
||||||
|
FLUTTER_VERSION: "3.24.5"
|
||||||
|
TAG_NAME: "nightly"
|
||||||
|
VERSION: "1.3.9"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-rustdesk-web:
|
||||||
|
name: build-rustdesk-web
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
env:
|
||||||
|
RELEASE_NAME: web-basic
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Prepare env
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y wget npm
|
||||||
|
|
||||||
|
- name: Install flutter
|
||||||
|
uses: subosito/flutter-action@v2.12.0 #https://github.com/subosito/flutter-action/issues/277
|
||||||
|
with:
|
||||||
|
channel: "stable"
|
||||||
|
flutter-version: ${{ env.FLUTTER_VERSION }}
|
||||||
|
|
||||||
|
# https://rustdesk.com/docs/en/dev/build/web/
|
||||||
|
- name: Build web
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
pushd flutter/web/v2
|
||||||
|
npm install yarn -g
|
||||||
|
npm install typescript -g
|
||||||
|
npm install protoc -g
|
||||||
|
# Install protoc first, see: https://google.github.io/proto-lens/installing-protoc.html
|
||||||
|
npm install ts-proto
|
||||||
|
# Only works with vite <= 2.8, see: https://github.com/vitejs/vite/blob/main/docs/guide/build.md#chunking-strategy
|
||||||
|
npm install vite@2.8
|
||||||
|
yarn install && yarn build
|
||||||
|
popd
|
||||||
|
|
||||||
|
pushd flutter/web/v2
|
||||||
|
wget https://github.com/rustdesk/doc.rustdesk.com/releases/download/console/web_deps.tar.gz
|
||||||
|
tar xzf web_deps.tar.gz
|
||||||
|
popd
|
||||||
|
|
||||||
|
pushd flutter
|
||||||
|
flutter build web --release
|
||||||
|
cd build
|
||||||
|
#cp ../web/README.md web
|
||||||
|
# TODO: Remove the following line when the web is almost complete.
|
||||||
|
#echo -e "\n\nThis build is for preview and not full functionality." >> web/README.md
|
||||||
|
dir_name="rustdesk-${{ env.VERSION }}-${{ env.RELEASE_NAME }}"
|
||||||
|
mv web "${dir_name}" && tar czf "${dir_name}".tar.gz "${dir_name}"
|
||||||
|
sha256sum "${dir_name}".tar.gz
|
||||||
|
popd
|
||||||
|
|
||||||
|
- name: Upload APK artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: web
|
||||||
|
path: flutter/build/rustdesk-${{ env.VERSION }}-${{ env.RELEASE_NAME }}.tar.gz
|
||||||
3
.github/workflows/docker-build.yml
vendored
3
.github/workflows/docker-build.yml
vendored
@@ -20,6 +20,9 @@ jobs:
|
|||||||
elif [[ "${{ github.ref_type }}" == "tag" ]]; then
|
elif [[ "${{ github.ref_type }}" == "tag" ]]; then
|
||||||
echo "IMAGE_TAG=${{ github.ref_name }}" >> "$GITHUB_ENV"
|
echo "IMAGE_TAG=${{ github.ref_name }}" >> "$GITHUB_ENV"
|
||||||
echo "CREATE_IMAGE=true" >> "$GITHUB_ENV"
|
echo "CREATE_IMAGE=true" >> "$GITHUB_ENV"
|
||||||
|
elif [[ "${{ github.ref }}" == "refs/heads/master" ]]; then
|
||||||
|
echo "IMAGE_TAG=latest" >> "$GITHUB_ENV"
|
||||||
|
echo "CREATE_IMAGE=true" >> "$GITHUB_ENV"
|
||||||
else
|
else
|
||||||
echo "CREATE_IMAGE=false" >> "$GITHUB_ENV"
|
echo "CREATE_IMAGE=false" >> "$GITHUB_ENV"
|
||||||
fi
|
fi
|
||||||
|
|||||||
23
.github/workflows/generator-android.yml
vendored
23
.github/workflows/generator-android.yml
vendored
@@ -69,7 +69,8 @@ env:
|
|||||||
TAG_NAME: "${{ inputs.upload-tag }}"
|
TAG_NAME: "${{ inputs.upload-tag }}"
|
||||||
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
||||||
# vcpkg version: 2024.07.12
|
# vcpkg version: 2024.07.12
|
||||||
VCPKG_COMMIT_ID: "460551b0ec06be1ba6b918448bf3b0f44add813d"
|
VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"
|
||||||
|
ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836"
|
||||||
VERSION: "${{ fromJson(inputs.extras).version }}"
|
VERSION: "${{ fromJson(inputs.extras).version }}"
|
||||||
NDK_VERSION: "r27c"
|
NDK_VERSION: "r27c"
|
||||||
#signing keys env variable checks
|
#signing keys env variable checks
|
||||||
@@ -145,6 +146,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Report Status
|
- name: Report Status
|
||||||
uses: fjogeleit/http-request-action@v1
|
uses: fjogeleit/http-request-action@v1
|
||||||
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
url: ${{ env.STATUS_URL }}
|
url: ${{ env.STATUS_URL }}
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
@@ -167,6 +169,7 @@ jobs:
|
|||||||
libasound2-dev \
|
libasound2-dev \
|
||||||
libc6-dev \
|
libc6-dev \
|
||||||
libclang-dev \
|
libclang-dev \
|
||||||
|
libunwind-dev \
|
||||||
libgstreamer1.0-dev \
|
libgstreamer1.0-dev \
|
||||||
libgstreamer-plugins-base1.0-dev \
|
libgstreamer-plugins-base1.0-dev \
|
||||||
libgtk-3-dev \
|
libgtk-3-dev \
|
||||||
@@ -228,19 +231,11 @@ jobs:
|
|||||||
vcpkgGitCommitId: ${{ env.VCPKG_COMMIT_ID }}
|
vcpkgGitCommitId: ${{ env.VCPKG_COMMIT_ID }}
|
||||||
doNotCache: false
|
doNotCache: false
|
||||||
|
|
||||||
- name: Report Status
|
|
||||||
uses: fjogeleit/http-request-action@v1
|
|
||||||
with:
|
|
||||||
url: ${{ env.STATUS_URL }}
|
|
||||||
method: 'POST'
|
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "15% complete"}'
|
|
||||||
|
|
||||||
- name: Install vcpkg dependencies
|
- name: Install vcpkg dependencies
|
||||||
run: |
|
run: |
|
||||||
case ${{ matrix.job.target }} in
|
case ${{ matrix.job.target }} in
|
||||||
aarch64-linux-android)
|
aarch64-linux-android)
|
||||||
ANDROID_TARGET=arm64-v8a
|
ANDROID_TARGET=arm64-v8a
|
||||||
;;
|
;;
|
||||||
armv7-linux-androideabi)
|
armv7-linux-androideabi)
|
||||||
ANDROID_TARGET=armeabi-v7a
|
ANDROID_TARGET=armeabi-v7a
|
||||||
@@ -365,6 +360,7 @@ jobs:
|
|||||||
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
||||||
sed -i -e "s|const url = 'https://rustdesk.com/';|const url = '${{ fromJson(inputs.extras).urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart
|
sed -i -e "s|const url = 'https://rustdesk.com/';|const url = '${{ fromJson(inputs.extras).urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart
|
||||||
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart
|
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart
|
||||||
|
sed -i -e "s|child: Text('rustdesk.com',|child: Text('${{ fromJson(inputs.extras).urlLink }}',|" ./flutter/lib/mobile/pages/settings_page.dart
|
||||||
sed -i -e "s|https://rustdesk.com/privacy.html|${{ fromJson(inputs.extras).urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart
|
sed -i -e "s|https://rustdesk.com/privacy.html|${{ fromJson(inputs.extras).urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart
|
||||||
|
|
||||||
- name: change download link to custom
|
- name: change download link to custom
|
||||||
@@ -389,7 +385,7 @@ jobs:
|
|||||||
if: ${{ fromJson(inputs.extras).delayFix == 'true' }}
|
if: ${{ fromJson(inputs.extras).delayFix == 'true' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sed -i -e '/if !key.is_empty() && !token.is_empty() {/,/}/d' ./src/client.rs
|
sed -i -e 's|!key.is_empty()|false|' ./src/client.rs
|
||||||
|
|
||||||
- name: add cycle monitors to toolbar
|
- name: add cycle monitors to toolbar
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
@@ -417,9 +413,11 @@ jobs:
|
|||||||
if: fromJson(inputs.extras).removeNewVersionNotif == 'true'
|
if: fromJson(inputs.extras).removeNewVersionNotif == 'true'
|
||||||
run: |
|
run: |
|
||||||
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
|
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
|
||||||
|
sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs
|
||||||
|
|
||||||
- name: Report Status
|
- name: Report Status
|
||||||
uses: fjogeleit/http-request-action@v1
|
uses: fjogeleit/http-request-action@v1
|
||||||
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
url: ${{ env.STATUS_URL }}
|
url: ${{ env.STATUS_URL }}
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
@@ -474,6 +472,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Report Status
|
- name: Report Status
|
||||||
uses: fjogeleit/http-request-action@v1
|
uses: fjogeleit/http-request-action@v1
|
||||||
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
url: ${{ env.STATUS_URL }}
|
url: ${{ env.STATUS_URL }}
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
@@ -550,6 +549,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Report Status
|
- name: Report Status
|
||||||
uses: fjogeleit/http-request-action@v1
|
uses: fjogeleit/http-request-action@v1
|
||||||
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
url: ${{ env.STATUS_URL }}
|
url: ${{ env.STATUS_URL }}
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
@@ -585,6 +585,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Report Status
|
- name: Report Status
|
||||||
uses: fjogeleit/http-request-action@v1
|
uses: fjogeleit/http-request-action@v1
|
||||||
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
url: ${{ env.STATUS_URL }}
|
url: ${{ env.STATUS_URL }}
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
|
|||||||
202
.github/workflows/generator-linux.yml
vendored
202
.github/workflows/generator-linux.yml
vendored
@@ -69,7 +69,8 @@ env:
|
|||||||
TAG_NAME: "${{ inputs.upload-tag }}"
|
TAG_NAME: "${{ inputs.upload-tag }}"
|
||||||
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
||||||
# vcpkg version: 2024.07.12
|
# vcpkg version: 2024.07.12
|
||||||
VCPKG_COMMIT_ID: "460551b0ec06be1ba6b918448bf3b0f44add813d"
|
VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"
|
||||||
|
ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836"
|
||||||
VERSION: "${{ fromJson(inputs.extras).version }}"
|
VERSION: "${{ fromJson(inputs.extras).version }}"
|
||||||
NDK_VERSION: "r27c"
|
NDK_VERSION: "r27c"
|
||||||
#signing keys env variable checks
|
#signing keys env variable checks
|
||||||
@@ -98,7 +99,7 @@ jobs:
|
|||||||
arch: x86_64,
|
arch: x86_64,
|
||||||
target: x86_64-unknown-linux-gnu,
|
target: x86_64-unknown-linux-gnu,
|
||||||
distro: ubuntu18.04,
|
distro: ubuntu18.04,
|
||||||
on: ubuntu-20.04,
|
on: ubuntu-22.04,
|
||||||
deb_arch: amd64,
|
deb_arch: amd64,
|
||||||
vcpkg-triplet: x64-linux,
|
vcpkg-triplet: x64-linux,
|
||||||
}
|
}
|
||||||
@@ -130,6 +131,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Report Status
|
- name: Report Status
|
||||||
uses: fjogeleit/http-request-action@v1
|
uses: fjogeleit/http-request-action@v1
|
||||||
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
url: ${{ env.STATUS_URL }}
|
url: ${{ env.STATUS_URL }}
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
@@ -198,6 +200,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Report Status
|
- name: Report Status
|
||||||
uses: fjogeleit/http-request-action@v1
|
uses: fjogeleit/http-request-action@v1
|
||||||
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
url: ${{ env.STATUS_URL }}
|
url: ${{ env.STATUS_URL }}
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
@@ -222,7 +225,7 @@ jobs:
|
|||||||
- name: Install vcpkg dependencies
|
- name: Install vcpkg dependencies
|
||||||
if: matrix.job.arch == 'x86_64' || env.UPLOAD_ARTIFACT == 'true'
|
if: matrix.job.arch == 'x86_64' || env.UPLOAD_ARTIFACT == 'true'
|
||||||
run: |
|
run: |
|
||||||
sudo apt install -y libva-dev libvdpau-dev
|
sudo apt install -y libva-dev && apt show libva-dev
|
||||||
if ! $VCPKG_ROOT/vcpkg \
|
if ! $VCPKG_ROOT/vcpkg \
|
||||||
install \
|
install \
|
||||||
--triplet ${{ matrix.job.vcpkg-triplet }} \
|
--triplet ${{ matrix.job.vcpkg-triplet }} \
|
||||||
@@ -330,7 +333,7 @@ jobs:
|
|||||||
if: ${{ fromJson(inputs.extras).delayFix == 'true' }}
|
if: ${{ fromJson(inputs.extras).delayFix == 'true' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sed -i -e '/if !key.is_empty() && !token.is_empty() {/,/}/d' ./src/client.rs
|
sed -i -e 's|!key.is_empty()|false|' ./src/client.rs
|
||||||
|
|
||||||
- name: add cycle monitors to toolbar
|
- name: add cycle monitors to toolbar
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
@@ -358,6 +361,7 @@ jobs:
|
|||||||
if: fromJson(inputs.extras).removeNewVersionNotif == 'true'
|
if: fromJson(inputs.extras).removeNewVersionNotif == 'true'
|
||||||
run: |
|
run: |
|
||||||
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
|
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
|
||||||
|
sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs
|
||||||
|
|
||||||
- name: Restore bridge files
|
- name: Restore bridge files
|
||||||
if: matrix.job.arch == 'x86_64' || env.UPLOAD_ARTIFACT == 'true'
|
if: matrix.job.arch == 'x86_64' || env.UPLOAD_ARTIFACT == 'true'
|
||||||
@@ -368,6 +372,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Report Status
|
- name: Report Status
|
||||||
uses: fjogeleit/http-request-action@v1
|
uses: fjogeleit/http-request-action@v1
|
||||||
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
url: ${{ env.STATUS_URL }}
|
url: ${{ env.STATUS_URL }}
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
@@ -403,20 +408,19 @@ jobs:
|
|||||||
imagemagick \
|
imagemagick \
|
||||||
libayatana-appindicator3-dev \
|
libayatana-appindicator3-dev \
|
||||||
libasound2-dev \
|
libasound2-dev \
|
||||||
libclang-dev \
|
libclang-10-dev \
|
||||||
libgstreamer1.0-dev \
|
libgstreamer1.0-dev \
|
||||||
libgstreamer-plugins-base1.0-dev \
|
libgstreamer-plugins-base1.0-dev \
|
||||||
libgtk-3-dev \
|
libgtk-3-dev \
|
||||||
libpam0g-dev \
|
libpam0g-dev \
|
||||||
libpulse-dev \
|
libpulse-dev \
|
||||||
libva-dev \
|
libva-dev \
|
||||||
libvdpau-dev \
|
|
||||||
libxcb-randr0-dev \
|
libxcb-randr0-dev \
|
||||||
libxcb-shape0-dev \
|
libxcb-shape0-dev \
|
||||||
libxcb-xfixes0-dev \
|
libxcb-xfixes0-dev \
|
||||||
libxdo-dev \
|
libxdo-dev \
|
||||||
libxfixes-dev \
|
libxfixes-dev \
|
||||||
llvm-dev \
|
llvm-10-dev \
|
||||||
nasm \
|
nasm \
|
||||||
ninja-build \
|
ninja-build \
|
||||||
pkg-config \
|
pkg-config \
|
||||||
@@ -612,8 +616,16 @@ jobs:
|
|||||||
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-suse-${{ matrix.job.arch }}.rpm" ${{ inputs.apiServer }}/api/save_custom_client
|
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-suse-${{ matrix.job.arch }}.rpm" ${{ inputs.apiServer }}/api/save_custom_client
|
||||||
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.pkg.tar.zst" ${{ inputs.apiServer }}/api/save_custom_client || true
|
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.pkg.tar.zst" ${{ inputs.apiServer }}/api/save_custom_client || true
|
||||||
|
|
||||||
|
- name: Upload deb
|
||||||
|
uses: actions/upload-artifact@master
|
||||||
|
if: env.UPLOAD_ARTIFACT == 'true'
|
||||||
|
with:
|
||||||
|
name: ${{ inputs.filename }}-${{ matrix.job.arch }}.deb
|
||||||
|
path: ./output/${{ inputs.filename }}-${{ matrix.job.arch }}.deb
|
||||||
|
|
||||||
- name: Report Status
|
- name: Report Status
|
||||||
uses: fjogeleit/http-request-action@v1
|
uses: fjogeleit/http-request-action@v1
|
||||||
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
url: ${{ env.STATUS_URL }}
|
url: ${{ env.STATUS_URL }}
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
@@ -638,14 +650,186 @@ jobs:
|
|||||||
customHeaders: '{"Content-Type": "application/json"}'
|
customHeaders: '{"Content-Type": "application/json"}'
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation cancelled, try again"}'
|
data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation cancelled, try again"}'
|
||||||
|
|
||||||
|
build-appimage:
|
||||||
|
name: Build appimage ${{ matrix.job.target }}
|
||||||
|
needs: [build-rustdesk-linux]
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
job:
|
||||||
|
- { target: x86_64-unknown-linux-gnu, arch: x86_64 }
|
||||||
|
- { target: aarch64-unknown-linux-gnu, arch: aarch64 }
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
if: ${{ env.VERSION != 'master' }}
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: rustdesk/rustdesk
|
||||||
|
ref: refs/tags/${{ env.VERSION }}
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Checkout source code
|
||||||
|
if: ${{ env.VERSION == 'master' }}
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: rustdesk/rustdesk
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Download Binary
|
||||||
|
uses: actions/download-artifact@master
|
||||||
|
with:
|
||||||
|
name: ${{ inputs.filename }}-${{ matrix.job.arch }}.deb
|
||||||
|
path: .
|
||||||
|
|
||||||
|
- name: Rename Binary
|
||||||
|
run: |
|
||||||
|
mv ${{ inputs.filename }}-${{ matrix.job.arch }}.deb appimage/rustdesk.deb
|
||||||
|
|
||||||
|
- name: Build appimage package
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
# install libarchive-tools for bsdtar command used in AppImageBuilder.yml
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y libarchive-tools libfuse2
|
||||||
|
# set-up appimage-builder
|
||||||
|
sudo pip3 install git+https://github.com/rustdesk-org/appimage-builder.git
|
||||||
|
# run appimage-builder
|
||||||
|
pushd appimage
|
||||||
|
sudo appimage-builder --skip-tests --recipe ./AppImageBuilder-${{ matrix.job.arch }}.yml
|
||||||
|
sudo mv ./rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.AppImage ./${{ inputs.filename }}-${{ matrix.job.arch }}.AppImage
|
||||||
|
|
||||||
|
- name: send file to rdgen server
|
||||||
|
if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./appimage/${{ inputs.filename }}-${{ matrix.job.arch }}.AppImage" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client
|
||||||
|
|
||||||
|
- name: send file to api server
|
||||||
|
if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./appimage/${{ inputs.filename }}-${{ matrix.job.arch }}.AppImage" ${{ inputs.apiServer }}/api/save_custom_client
|
||||||
|
|
||||||
|
build-flatpak:
|
||||||
|
name: Build flatpak ${{ matrix.job.target }}${{ matrix.job.suffix }}
|
||||||
|
needs:
|
||||||
|
- build-rustdesk-linux
|
||||||
|
runs-on: ${{ matrix.job.on }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
job:
|
||||||
|
- {
|
||||||
|
target: x86_64-unknown-linux-gnu,
|
||||||
|
distro: ubuntu18.04,
|
||||||
|
on: ubuntu-22.04,
|
||||||
|
arch: x86_64,
|
||||||
|
suffix: "",
|
||||||
|
}
|
||||||
|
- {
|
||||||
|
target: aarch64-unknown-linux-gnu,
|
||||||
|
# try out newer flatpak since error of "error: Nothing matches org.freedesktop.Platform in remote flathub"
|
||||||
|
distro: ubuntu22.04,
|
||||||
|
on: ubuntu-22.04-arm,
|
||||||
|
arch: aarch64,
|
||||||
|
suffix: "",
|
||||||
|
}
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
if: ${{ env.VERSION != 'master' }}
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: rustdesk/rustdesk
|
||||||
|
ref: refs/tags/${{ env.VERSION }}
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Checkout source code
|
||||||
|
if: ${{ env.VERSION == 'master' }}
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: rustdesk/rustdesk
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Download Binary
|
||||||
|
uses: actions/download-artifact@master
|
||||||
|
with:
|
||||||
|
name: ${{ inputs.filename }}-${{ matrix.job.arch }}.deb
|
||||||
|
path: .
|
||||||
|
|
||||||
|
- name: Rename Binary
|
||||||
|
run: |
|
||||||
|
mv ${{ inputs.filename }}-${{ matrix.job.arch }}.deb flatpak/rustdesk.deb
|
||||||
|
|
||||||
|
- uses: rustdesk-org/run-on-arch-action@amd64-support
|
||||||
|
name: Build rustdesk flatpak package for ${{ matrix.job.arch }}
|
||||||
|
continue-on-error: true
|
||||||
|
timeout-minutes: 30
|
||||||
|
id: flatpak
|
||||||
|
with:
|
||||||
|
arch: ${{ matrix.job.arch }}
|
||||||
|
distro: ${{ matrix.job.distro }}
|
||||||
|
githubToken: ${{ github.token }}
|
||||||
|
setup: |
|
||||||
|
ls -l "${PWD}"
|
||||||
|
dockerRunArgs: |
|
||||||
|
--volume "${PWD}:/workspace"
|
||||||
|
shell: /bin/bash
|
||||||
|
install: |
|
||||||
|
apt-get update -y
|
||||||
|
apt-get install -y git flatpak flatpak-builder
|
||||||
|
run: |
|
||||||
|
# disable git safe.directory
|
||||||
|
git config --global --add safe.directory "*"
|
||||||
|
pushd /workspace
|
||||||
|
# flatpak deps
|
||||||
|
flatpak --user remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||||
|
# package
|
||||||
|
pushd flatpak
|
||||||
|
git clone https://github.com/flathub/shared-modules.git --depth=1
|
||||||
|
flatpak-builder --user --install-deps-from=flathub -y --force-clean --repo=repo ./build ./rustdesk.json
|
||||||
|
flatpak build-bundle ./repo ${{ inputs.filename }}-${{ matrix.job.arch }}.flatpak com.rustdesk.RustDesk
|
||||||
|
|
||||||
|
- name: send file to rdgen server
|
||||||
|
if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
|
||||||
|
continue-on-error: true
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./flatpak/${{ inputs.filename }}-${{ matrix.job.arch }}.flatpak" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client
|
||||||
|
|
||||||
|
- name: send file to api server
|
||||||
|
if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
|
||||||
|
continue-on-error: true
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./flatpak/${{ inputs.filename }}-${{ matrix.job.arch }}.flatpak" ${{ inputs.apiServer }}/api/save_custom_client
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
needs: build-rustdesk-linux
|
needs: [build-rustdesk-linux,build-flatpak,build-appimage]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
|
- name: Set rdgen value
|
||||||
|
if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
|
||||||
|
run: |
|
||||||
|
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Set rdgen value
|
||||||
|
if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
|
||||||
|
run: |
|
||||||
|
echo "STATUS_URL=${{ inputs.apiServer }}/api/updategh" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Report Status
|
- name: Report Status
|
||||||
uses: fjogeleit/http-request-action@v1
|
uses: fjogeleit/http-request-action@v1
|
||||||
with:
|
with:
|
||||||
url: ${{ env.STATUS_URL }}
|
url: ${{ env.STATUS_URL }}
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
customHeaders: '{"Content-Type": "application/json"}'
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "Success"}'
|
data: '{"uuid": "${{ inputs.uuid }}", "status": "Success"}'
|
||||||
|
|
||||||
|
- uses: geekyeggo/delete-artifact@v5
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
name: ${{ inputs.filename }}-*.deb
|
||||||
|
|||||||
84
.github/workflows/generator-macos.yml
vendored
84
.github/workflows/generator-macos.yml
vendored
@@ -69,7 +69,8 @@ env:
|
|||||||
TAG_NAME: "${{ inputs.upload-tag }}"
|
TAG_NAME: "${{ inputs.upload-tag }}"
|
||||||
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
||||||
# vcpkg version: 2024.07.12
|
# vcpkg version: 2024.07.12
|
||||||
VCPKG_COMMIT_ID: "460551b0ec06be1ba6b918448bf3b0f44add813d"
|
VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"
|
||||||
|
ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836"
|
||||||
VERSION: "${{ fromJson(inputs.extras).version }}"
|
VERSION: "${{ fromJson(inputs.extras).version }}"
|
||||||
NDK_VERSION: "r27c"
|
NDK_VERSION: "r27c"
|
||||||
#signing keys env variable checks
|
#signing keys env variable checks
|
||||||
@@ -77,7 +78,6 @@ env:
|
|||||||
MACOS_P12_BASE64: "${{ secrets.MACOS_P12_BASE64 }}"
|
MACOS_P12_BASE64: "${{ secrets.MACOS_P12_BASE64 }}"
|
||||||
UPLOAD_ARTIFACT: 'true'
|
UPLOAD_ARTIFACT: 'true'
|
||||||
SIGN_BASE_URL: "${{ secrets.SIGN_BASE_URL }}"
|
SIGN_BASE_URL: "${{ secrets.SIGN_BASE_URL }}"
|
||||||
STATUS_URL: "${{ secrets.GENURL }}/updategh"
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
generate-bridge:
|
generate-bridge:
|
||||||
@@ -85,9 +85,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
version: ${{ fromJson(inputs.extras).version }}
|
version: ${{ fromJson(inputs.extras).version }}
|
||||||
|
|
||||||
build-for-macos-flutter:
|
build-for-macos:
|
||||||
name: Build macOS
|
name: ${{ matrix.job.target }}
|
||||||
runs-on: macos-latest
|
runs-on: ${{ matrix.job.os }}
|
||||||
needs: [generate-bridge]
|
needs: [generate-bridge]
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@@ -102,12 +102,14 @@ jobs:
|
|||||||
}
|
}
|
||||||
- {
|
- {
|
||||||
target: aarch64-apple-darwin,
|
target: aarch64-apple-darwin,
|
||||||
os: macos-latest,
|
os: macos-14,
|
||||||
# extra-build-args: "--disable-flutter-texture-render", # disable this for mac, because we see a lot of users reporting flickering both on arm and x64, and we can not confirm if texture rendering has better performance if htere is no vram, https://github.com/rustdesk/rustdesk/issues/6296
|
# extra-build-args: "--disable-flutter-texture-render", # disable this for mac, because we see a lot of users reporting flickering both on arm and x64, and we can not confirm if texture rendering has better performance if htere is no vram, https://github.com/rustdesk/rustdesk/issues/6296
|
||||||
extra-build-args: "--screencapturekit",
|
extra-build-args: "--screencapturekit",
|
||||||
arch: aarch64,
|
arch: aarch64,
|
||||||
vcpkg-triplet: arm64-osx,
|
vcpkg-triplet: arm64-osx,
|
||||||
}
|
}
|
||||||
|
env:
|
||||||
|
STATUS_URL: ${{ fromJson(inputs.extras).rdgen == 'true' && format('{0}/updategh', secrets.GENURL) || format('{0}/api/updategh', inputs.apiServer) }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Export GitHub Actions cache environment variables
|
- name: Export GitHub Actions cache environment variables
|
||||||
@@ -117,16 +119,6 @@ jobs:
|
|||||||
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
|
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
|
||||||
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
|
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
|
||||||
|
|
||||||
- name: Set rdgen value
|
|
||||||
if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
|
|
||||||
run: |
|
|
||||||
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $env:GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Set rdgen value
|
|
||||||
if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
|
|
||||||
run: |
|
|
||||||
echo "STATUS_URL=${{ inputs.apiServer }}/api/updategh" >> $env:GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Report Status
|
- name: Report Status
|
||||||
uses: fjogeleit/http-request-action@v1
|
uses: fjogeleit/http-request-action@v1
|
||||||
with:
|
with:
|
||||||
@@ -150,12 +142,6 @@ jobs:
|
|||||||
repository: rustdesk/rustdesk
|
repository: rustdesk/rustdesk
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
- name: Restore bridge files
|
|
||||||
uses: actions/download-artifact@master
|
|
||||||
with:
|
|
||||||
name: bridge-artifact
|
|
||||||
path: ./
|
|
||||||
|
|
||||||
- name: Install imagemagick and potrace and nasm and and
|
- name: Install imagemagick and potrace and nasm and and
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@@ -205,7 +191,7 @@ jobs:
|
|||||||
find ./src/lang -name "*.rs" -exec sed -i '' -e 's|RustDesk|${{ inputs.appname }}|' {} \;
|
find ./src/lang -name "*.rs" -exec sed -i '' -e 's|RustDesk|${{ inputs.appname }}|' {} \;
|
||||||
sed -i '' -e 's|RustDesk|${{ inputs.appname }}|' ./src/lang/nl.rs
|
sed -i '' -e 's|RustDesk|${{ inputs.appname }}|' ./src/lang/nl.rs
|
||||||
|
|
||||||
sed -i '' -e 's|Homepage: https://rustdesk.com|Homepage: ${{ fromJson(inputs.extras).urlLink }}|' ./build.py
|
sed -i '' -e 's|https://rustdesk.com|${{ fromJson(inputs.extras).urlLink }}|' ./build.py
|
||||||
sed -i '' -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ fromJson(inputs.extras).urlLink }}'));|" ./flutter/lib/common.dart
|
sed -i '' -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ fromJson(inputs.extras).urlLink }}'));|" ./flutter/lib/common.dart
|
||||||
sed -i '' -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ fromJson(inputs.extras).urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
sed -i '' -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ fromJson(inputs.extras).urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
||||||
sed -i '' -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
sed -i '' -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
|
||||||
@@ -258,27 +244,35 @@ jobs:
|
|||||||
url: ${{ env.STATUS_URL }}
|
url: ${{ env.STATUS_URL }}
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
customHeaders: '{"Content-Type": "application/json"}'
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "10% complete"}'
|
data: '{"uuid": "${{ inputs.uuid }}", "status": "10% complete"}'
|
||||||
|
|
||||||
|
- name: Install build runtime
|
||||||
|
run: |
|
||||||
|
brew install llvm create-dmg nasm
|
||||||
|
# pkg-config is handled in a separate step, because it may be already installed by `macos-latest`(14.7.1) runner
|
||||||
|
if command -v pkg-config &>/dev/null; then
|
||||||
|
echo "pkg-config is already installed"
|
||||||
|
else
|
||||||
|
brew install pkg-config
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Install flutter
|
- name: Install flutter
|
||||||
uses: subosito/flutter-action@v2.12.0
|
uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
channel: "stable"
|
channel: "stable"
|
||||||
flutter-version: ${{ env.FLUTTER_VERSION }}
|
flutter-version: ${{ env.FLUTTER_VERSION }}
|
||||||
cache: true
|
|
||||||
|
|
||||||
- name: Patch flutter
|
- name: Patch flutter
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: |
|
run: |
|
||||||
cp .github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff $(dirname $(dirname $(which flutter)))
|
|
||||||
cd $(dirname $(dirname $(which flutter)))
|
cd $(dirname $(dirname $(which flutter)))
|
||||||
[[ "3.24.4" == 3.24.5 ]] && git apply flutter_3.24.4_dropdown_menu_enableFilter.diff
|
[[ "3.24.5" == ${{env.FLUTTER_VERSION}} ]] && git apply ${{ github.workspace }}/.github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff
|
||||||
|
|
||||||
- name: Workaround for flutter issue
|
- name: Workaround for flutter issue
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cd "$(dirname "$(which flutter)")"
|
cd "$(dirname "$(which flutter)")"
|
||||||
# https://github.com/flutter/flutter/issues/1.3.43
|
# https://github.com/flutter/flutter/issues/133533
|
||||||
sed -i -e 's/_setFramesEnabledState(false);/\/\/_setFramesEnabledState(false);/g' ../packages/flutter/lib/src/scheduler/binding.dart
|
sed -i -e 's/_setFramesEnabledState(false);/\/\/_setFramesEnabledState(false);/g' ../packages/flutter/lib/src/scheduler/binding.dart
|
||||||
grep -n '_setFramesEnabledState(false);' ../packages/flutter/lib/src/scheduler/binding.dart
|
grep -n '_setFramesEnabledState(false);' ../packages/flutter/lib/src/scheduler/binding.dart
|
||||||
|
|
||||||
@@ -289,7 +283,6 @@ jobs:
|
|||||||
targets: ${{ matrix.job.target }}
|
targets: ${{ matrix.job.target }}
|
||||||
components: "rustfmt"
|
components: "rustfmt"
|
||||||
|
|
||||||
|
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
with:
|
with:
|
||||||
prefix-key: ${{ matrix.job.os }}
|
prefix-key: ${{ matrix.job.os }}
|
||||||
@@ -445,7 +438,7 @@ jobs:
|
|||||||
if: ${{ fromJson(inputs.extras).delayFix == 'true' }}
|
if: ${{ fromJson(inputs.extras).delayFix == 'true' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sed -i '' -e '/if !key.is_empty() && !token.is_empty() {/,/}/d' ./src/client.rs
|
sed -i -e 's|!key.is_empty()|false|' ./src/client.rs
|
||||||
|
|
||||||
- name: add cycle monitors to toolbar
|
- name: add cycle monitors to toolbar
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
@@ -473,19 +466,7 @@ jobs:
|
|||||||
if: fromJson(inputs.extras).removeNewVersionNotif == 'true'
|
if: fromJson(inputs.extras).removeNewVersionNotif == 'true'
|
||||||
run: |
|
run: |
|
||||||
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
|
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
|
||||||
|
sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs
|
||||||
- name: Report Status
|
|
||||||
uses: fjogeleit/http-request-action@v1
|
|
||||||
with:
|
|
||||||
url: ${{ env.STATUS_URL }}
|
|
||||||
method: 'POST'
|
|
||||||
customHeaders: '{"Content-Type": "application/json"}'
|
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "15% complete"}'
|
|
||||||
|
|
||||||
|
|
||||||
- uses: Swatinem/rust-cache@v2
|
|
||||||
with:
|
|
||||||
prefix-key: ${{ matrix.job.os }}
|
|
||||||
|
|
||||||
- name: Report Status
|
- name: Report Status
|
||||||
uses: fjogeleit/http-request-action@v1
|
uses: fjogeleit/http-request-action@v1
|
||||||
@@ -495,12 +476,18 @@ jobs:
|
|||||||
customHeaders: '{"Content-Type": "application/json"}'
|
customHeaders: '{"Content-Type": "application/json"}'
|
||||||
data: '{"uuid": "${{ inputs.uuid }}", "status": "20% complete"}'
|
data: '{"uuid": "${{ inputs.uuid }}", "status": "20% complete"}'
|
||||||
|
|
||||||
|
- name: Restore bridge files
|
||||||
|
uses: actions/download-artifact@master
|
||||||
|
with:
|
||||||
|
name: bridge-artifact
|
||||||
|
path: ./
|
||||||
|
|
||||||
- name: Setup vcpkg with Github Actions binary cache
|
- name: Setup vcpkg with Github Actions binary cache
|
||||||
uses: lukka/run-vcpkg@v11
|
uses: lukka/run-vcpkg@v11
|
||||||
with:
|
with:
|
||||||
vcpkgGitCommitId: ${{ env.VCPKG_COMMIT_ID }}
|
vcpkgGitCommitId: ${{ env.VCPKG_COMMIT_ID }}
|
||||||
doNotCache: false
|
doNotCache: false
|
||||||
|
|
||||||
- name: Install vcpkg dependencies
|
- name: Install vcpkg dependencies
|
||||||
run: |
|
run: |
|
||||||
if ! $VCPKG_ROOT/vcpkg \
|
if ! $VCPKG_ROOT/vcpkg \
|
||||||
@@ -515,6 +502,7 @@ jobs:
|
|||||||
done
|
done
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
head -n 100 "${VCPKG_ROOT}/buildtrees/ffmpeg/build-${{ matrix.job.vcpkg-triplet }}-rel-out.log" || true
|
||||||
|
|
||||||
- name: Report Status
|
- name: Report Status
|
||||||
uses: fjogeleit/http-request-action@v1
|
uses: fjogeleit/http-request-action@v1
|
||||||
@@ -538,7 +526,7 @@ jobs:
|
|||||||
sed -i -e "s/MACOSX_DEPLOYMENT_TARGET = [0-9]*.[0-9]*;/MACOSX_DEPLOYMENT_TARGET = ${MIN_MACOS_VERSION};/" flutter/macos/Runner.xcodeproj/project.pbxproj
|
sed -i -e "s/MACOSX_DEPLOYMENT_TARGET = [0-9]*.[0-9]*;/MACOSX_DEPLOYMENT_TARGET = ${MIN_MACOS_VERSION};/" flutter/macos/Runner.xcodeproj/project.pbxproj
|
||||||
fi
|
fi
|
||||||
sed -i -e "s/RustDesk.app/\"${{ inputs.appname }}.app\"/" build.py
|
sed -i -e "s/RustDesk.app/\"${{ inputs.appname }}.app\"/" build.py
|
||||||
./build.py --flutter --hwcodec ${{ matrix.job.extra-build-args }}
|
./build.py --flutter --hwcodec --unix-file-copy-paste ${{ matrix.job.extra-build-args }}
|
||||||
|
|
||||||
# - name: Copy service file
|
# - name: Copy service file
|
||||||
# run: |
|
# run: |
|
||||||
|
|||||||
524
.github/workflows/generator-windows-x86.yml
vendored
Normal file
524
.github/workflows/generator-windows-x86.yml
vendored
Normal file
File diff suppressed because one or more lines are too long
89
.github/workflows/generator-windows.yml
vendored
89
.github/workflows/generator-windows.yml
vendored
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
|
|||||||
services:
|
services:
|
||||||
rdgen:
|
rdgen:
|
||||||
# use bryangerlach/rdgen:dev for the latest dev build
|
# use bryangerlach/rdgen:latest for the latest build
|
||||||
image: bryangerlach/rdgen:v0.3.1
|
image: bryangerlach/rdgen:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
SECRET_KEY: "django-insecure-!(t-!f#6g#sr%yfded9(xha)g+=!6craeez^cp+*&bz_7vdk61"
|
SECRET_KEY: "django-insecure-!(t-!f#6g#sr%yfded9(xha)g+=!6craeez^cp+*&bz_7vdk61"
|
||||||
|
|||||||
@@ -131,3 +131,5 @@ STATIC_URL = 'static/'
|
|||||||
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
|
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
|
||||||
|
|
||||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
|
|
||||||
|
DATA_UPLOAD_MAX_MEMORY_SIZE = None
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ from PIL import Image
|
|||||||
|
|
||||||
class GenerateForm(forms.Form):
|
class GenerateForm(forms.Form):
|
||||||
#Platform
|
#Platform
|
||||||
platform = forms.ChoiceField(choices=[('windows','Windows'),('linux','Linux (currently unavailable)'),('android','Android'),('macos','macOS')], initial='windows')
|
platform = forms.ChoiceField(choices=[('windows','Windows 64Bit'),('windows-x86','Windows 32Bit'),('linux','Linux'),('android','Android'),('macos','macOS')], initial='windows')
|
||||||
version = forms.ChoiceField(choices=[('master','nightly'),('1.3.9','1.3.9'),('1.3.8','1.3.8'),('1.3.7','1.3.7'),('1.3.6','1.3.6'),('1.3.5','1.3.5'),('1.3.4','1.3.4'),('1.3.3','1.3.3')], initial='1.3.9')
|
version = forms.ChoiceField(choices=[('master','nightly'),('1.4.3','1.4.3'),('1.4.2','1.4.2'),('1.4.1','1.4.1'),('1.4.0','1.4.0'),('1.3.9','1.3.9'),('1.3.8','1.3.8'),('1.3.7','1.3.7'),('1.3.6','1.3.6'),('1.3.5','1.3.5'),('1.3.4','1.3.4'),('1.3.3','1.3.3')], initial='1.4.3')
|
||||||
help_text="'master' is the development version (nightly build) with the latest features but may be less stable"
|
help_text="'master' is the development version (nightly build) with the latest features but may be less stable"
|
||||||
delayFix = forms.BooleanField(initial=True, required=False)
|
delayFix = forms.BooleanField(initial=True, required=False)
|
||||||
|
|
||||||
@@ -66,6 +66,10 @@ class GenerateForm(forms.Form):
|
|||||||
enableRecording = forms.BooleanField(initial=True, required=False)
|
enableRecording = forms.BooleanField(initial=True, required=False)
|
||||||
enableBlockingInput = forms.BooleanField(initial=True, required=False)
|
enableBlockingInput = forms.BooleanField(initial=True, required=False)
|
||||||
enableRemoteModi = forms.BooleanField(initial=False, required=False)
|
enableRemoteModi = forms.BooleanField(initial=False, required=False)
|
||||||
|
hidecm = forms.BooleanField(initial=False, required=False)
|
||||||
|
enablePrinter = forms.BooleanField(initial=True, required=False)
|
||||||
|
enableCamera = forms.BooleanField(initial=True, required=False)
|
||||||
|
enableTerminal = forms.BooleanField(initial=True, required=False)
|
||||||
|
|
||||||
#Other
|
#Other
|
||||||
removeWallpaper = forms.BooleanField(initial=True, required=False)
|
removeWallpaper = forms.BooleanField(initial=True, required=False)
|
||||||
@@ -76,7 +80,6 @@ class GenerateForm(forms.Form):
|
|||||||
#custom added features
|
#custom added features
|
||||||
cycleMonitor = forms.BooleanField(initial=False, required=False)
|
cycleMonitor = forms.BooleanField(initial=False, required=False)
|
||||||
xOffline = forms.BooleanField(initial=False, required=False)
|
xOffline = forms.BooleanField(initial=False, required=False)
|
||||||
hidecm = forms.BooleanField(initial=False, required=False)
|
|
||||||
removeNewVersionNotif = forms.BooleanField(initial=False, required=False)
|
removeNewVersionNotif = forms.BooleanField(initial=False, required=False)
|
||||||
|
|
||||||
def clean_iconfile(self):
|
def clean_iconfile(self):
|
||||||
|
|||||||
@@ -129,6 +129,8 @@
|
|||||||
{% if platform == 'windows' %}
|
{% if platform == 'windows' %}
|
||||||
<a href='/download?filename={{filename}}.exe&uuid={{uuid}}' class="download-link">Download {{filename}}.exe</a>
|
<a href='/download?filename={{filename}}.exe&uuid={{uuid}}' class="download-link">Download {{filename}}.exe</a>
|
||||||
<a href='/download?filename={{filename}}.msi&uuid={{uuid}}' class="download-link">Download {{filename}}.msi</a>
|
<a href='/download?filename={{filename}}.msi&uuid={{uuid}}' class="download-link">Download {{filename}}.msi</a>
|
||||||
|
{% elif platform == 'windows-x86' %}
|
||||||
|
<a href='/download?filename={{filename}}.exe&uuid={{uuid}}' class="download-link">Download {{filename}}.exe</a>
|
||||||
{% elif platform == 'linux' %}
|
{% elif platform == 'linux' %}
|
||||||
<a href='/download?filename={{filename}}-x86_64.deb&uuid={{uuid}}' class="download-link">Download {{filename}}-x86_64.deb</a>
|
<a href='/download?filename={{filename}}-x86_64.deb&uuid={{uuid}}' class="download-link">Download {{filename}}-x86_64.deb</a>
|
||||||
<a href='/download?filename={{filename}}-x86_64.rpm&uuid={{uuid}}' class="download-link">Download {{filename}}-x86_64.rpm</a>
|
<a href='/download?filename={{filename}}-x86_64.rpm&uuid={{uuid}}' class="download-link">Download {{filename}}-x86_64.rpm</a>
|
||||||
@@ -138,6 +140,10 @@
|
|||||||
<a href='/download?filename={{filename}}-aarch64.rpm&uuid={{uuid}}' class="download-link">Download {{filename}}-aarch64.rpm</a>
|
<a href='/download?filename={{filename}}-aarch64.rpm&uuid={{uuid}}' class="download-link">Download {{filename}}-aarch64.rpm</a>
|
||||||
<a href='/download?filename={{filename}}-suse-aarch64.rpm&uuid={{uuid}}' class="download-link">Download {{filename}}-suse-aarch64.rpm</a>
|
<a href='/download?filename={{filename}}-suse-aarch64.rpm&uuid={{uuid}}' class="download-link">Download {{filename}}-suse-aarch64.rpm</a>
|
||||||
<a href='/download?filename={{filename}}-aarch64.pkg.tar.zst&uuid={{uuid}}' class="download-link">Download {{filename}}-aarch64.pkg.tar.zst</a>
|
<a href='/download?filename={{filename}}-aarch64.pkg.tar.zst&uuid={{uuid}}' class="download-link">Download {{filename}}-aarch64.pkg.tar.zst</a>
|
||||||
|
<a href='/download?filename={{filename}}-x86_64.AppImage&uuid={{uuid}}' class="download-link">Download {{filename}}-x86_64.AppImage</a>
|
||||||
|
<a href='/download?filename={{filename}}-aarch64.AppImage&uuid={{uuid}}' class="download-link">Download {{filename}}-aarch64.AppImage</a>
|
||||||
|
<a href='/download?filename={{filename}}-x86_64.flatpak&uuid={{uuid}}' class="download-link">Download {{filename}}-x86_64.flatpak</a>
|
||||||
|
<a href='/download?filename={{filename}}-aarch64.flatpak&uuid={{uuid}}' class="download-link">Download {{filename}}-aarch64.flatpak</a>
|
||||||
{% elif platform == 'android' %}
|
{% elif platform == 'android' %}
|
||||||
<a href='/download?filename={{filename}}-aarch64.apk&uuid={{uuid}}' class="download-link">Download {{filename}}-aarch64.apk</a>
|
<a href='/download?filename={{filename}}-aarch64.apk&uuid={{uuid}}' class="download-link">Download {{filename}}-aarch64.apk</a>
|
||||||
<a href='/download?filename={{filename}}-x86_64.apk&uuid={{uuid}}' class="download-link">Download {{filename}}-x86_64.apk</a>
|
<a href='/download?filename={{filename}}-x86_64.apk&uuid={{uuid}}' class="download-link">Download {{filename}}-x86_64.apk</a>
|
||||||
@@ -173,7 +179,7 @@
|
|||||||
platformLogos.macos.style.display = 'block';
|
platformLogos.macos.style.display = 'block';
|
||||||
platformNote.textContent = 'Note: For macOS, you may need to adjust security settings to run the application.';
|
platformNote.textContent = 'Note: For macOS, you may need to adjust security settings to run the application.';
|
||||||
platformNote.style.display = 'block';
|
platformNote.style.display = 'block';
|
||||||
} else if (platform === 'windows') {
|
} else if (platform === 'windows' || platform === 'windows-x86') {
|
||||||
document.getElementById('pageTitle').textContent = 'Windows Build Generated';
|
document.getElementById('pageTitle').textContent = 'Windows Build Generated';
|
||||||
platformLogos.windows.style.display = 'block';
|
platformLogos.windows.style.display = 'block';
|
||||||
platformNote.textContent = 'Note: You might need to disable SmartScreen or adjust Windows security settings.';
|
platformNote.textContent = 'Note: You might need to disable SmartScreen or adjust Windows security settings.';
|
||||||
@@ -195,4 +201,4 @@
|
|||||||
updatePlatformUI();
|
updatePlatformUI();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>{{ ... }}
|
</html>{{ ... }}
|
||||||
|
|||||||
@@ -90,7 +90,26 @@
|
|||||||
transition: color 0.3s ease;
|
transition: color 0.3s ease;
|
||||||
}
|
}
|
||||||
.platform-icon:hover, .platform-icon.active {
|
.platform-icon:hover, .platform-icon.active {
|
||||||
color: #fff;
|
color: #2e52f7;
|
||||||
|
}
|
||||||
|
.text-64 {
|
||||||
|
font-size: 0.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
bottom: -0.2em;
|
||||||
|
right: -0.2em;
|
||||||
|
position: absolute;
|
||||||
|
color: white;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-32 {
|
||||||
|
font-size: 0.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
bottom: -0.2em;
|
||||||
|
right: -0.2em;
|
||||||
|
position: absolute;
|
||||||
|
color: white;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
}
|
}
|
||||||
.checkbox-group {
|
.checkbox-group {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -150,6 +169,58 @@
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.password-requirement {
|
||||||
|
display: none; /* Hidden by default */
|
||||||
|
color: orange;
|
||||||
|
font-size: 0.9em;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsor-button {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
background: linear-gradient(135deg, #00457C 0%, #0079C1 100%);
|
||||||
|
color: white;
|
||||||
|
padding: 12px 28px;
|
||||||
|
border-radius: 50px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 16px;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow: 0 4px 15px rgba(0, 69, 124, 0.2);
|
||||||
|
border: 2px solid rgba(255, 255, 255, 0.1);
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsor-button:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 8px 25px rgba(0, 69, 124, 0.3);
|
||||||
|
background: linear-gradient(135deg, #005AA7 0%, #0095EA 100%);
|
||||||
|
border-color: rgba(255, 255, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsor-button i {
|
||||||
|
margin-right: 12px;
|
||||||
|
font-size: 20px;
|
||||||
|
background: white;
|
||||||
|
color: #00457C;
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sponsor-button:hover i {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
color: #0095EA;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -175,13 +246,21 @@
|
|||||||
<div class="platform">
|
<div class="platform">
|
||||||
<h2><i class="fas fa-desktop"></i> Select Platform</h2>
|
<h2><i class="fas fa-desktop"></i> Select Platform</h2>
|
||||||
<div class="platform-icons">
|
<div class="platform-icons">
|
||||||
<i class="fab fa-windows platform-icon active" data-platform="windows"></i>
|
<span class="fa-stack fa-lg">
|
||||||
|
<i class="fab fa-windows fa-stack-2x platform-icon active" data-platform="windows"></i>
|
||||||
|
<strong class="fa-stack-1x text-64">64</strong>
|
||||||
|
</span>
|
||||||
|
<span class="fa-stack fa-lg">
|
||||||
|
<i class="fab fa-windows fa-stack-2x platform-icon" data-platform="windows-x86"></i>
|
||||||
|
<strong class="fa-stack-1x text-32">32</strong>
|
||||||
|
</span>
|
||||||
<i class="fab fa-linux platform-icon" data-platform="linux"></i>
|
<i class="fab fa-linux platform-icon" data-platform="linux"></i>
|
||||||
<i class="fab fa-android platform-icon" data-platform="android"></i>
|
<i class="fab fa-android platform-icon" data-platform="android"></i>
|
||||||
<i class="fab fa-apple platform-icon" data-platform="macos"></i>
|
<i class="fab fa-apple platform-icon" data-platform="macos"></i>
|
||||||
</div>
|
</div>
|
||||||
<select name="platform" id="id_platform">
|
<select name="platform" id="id_platform">
|
||||||
<option value="windows" selected>Windows</option>
|
<option value="windows" selected>Windows 64Bit</option>
|
||||||
|
<option value="windows-x86">Windows 32Bit</option>
|
||||||
<option value="linux">Linux</option>
|
<option value="linux">Linux</option>
|
||||||
<option value="android">Android</option>
|
<option value="android">Android</option>
|
||||||
<option value="macos">macOS</option>
|
<option value="macos">macOS</option>
|
||||||
@@ -233,6 +312,7 @@
|
|||||||
{{ form.runasadmin }}<br><br>
|
{{ form.runasadmin }}<br><br>
|
||||||
<label for="{{ form.passApproveMode.id_for_label }}">Password Approve mode:</label>
|
<label for="{{ form.passApproveMode.id_for_label }}">Password Approve mode:</label>
|
||||||
{{ form.passApproveMode }}<br><br>
|
{{ form.passApproveMode }}<br><br>
|
||||||
|
<div id="passwordRequirement" class="password-requirement">To use the hide connection window feature, please set a permanent password.</div>
|
||||||
<label for="{{ form.permanentPassword.id_for_label }}">Set Permanent Password:</label>
|
<label for="{{ form.permanentPassword.id_for_label }}">Set Permanent Password:</label>
|
||||||
{{ form.permanentPassword }} *The password is used as default, but can be changed by the client<br><br>
|
{{ form.permanentPassword }} *The password is used as default, but can be changed by the client<br><br>
|
||||||
|
|
||||||
@@ -241,7 +321,9 @@
|
|||||||
|
|
||||||
<label for="{{ form.enableDirectIP.id_for_label }}">{{ form.enableDirectIP }} Enable direct IP access</label><br>
|
<label for="{{ form.enableDirectIP.id_for_label }}">{{ form.enableDirectIP }} Enable direct IP access</label><br>
|
||||||
|
|
||||||
<label for="{{ form.autoClose.id_for_label }}">{{ form.autoClose }} Automatically close incoming sessions on user inactivity</label><br>
|
<label for="{{ form.autoClose.id_for_label }}">{{ form.autoClose }} Automatically close incoming sessions on user inactivity</label><br>
|
||||||
|
|
||||||
|
<label for="{{ form.hidecm.id_for_label }}">{{ form.hidecm }} Allow hiding the connection window from remote screen.</label><br>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section">
|
<div class="section">
|
||||||
@@ -263,7 +345,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2><i class="fas fa-lock"></i> Permissions</h2>
|
<h2><i class="fas fa-lock"></i> Permissions</h2>
|
||||||
The following Permissions can be set as default (the user can change the settins) or override (the settings cannot be changed).<br>
|
The following Permissions can be set as default (the user can change the settings) or override (the settings cannot be changed).<br>
|
||||||
{{ form.permissionsDorO }}
|
{{ form.permissionsDorO }}
|
||||||
<label for="{{ form.permissionsType.id_for_label }}">Permission type:</label>
|
<label for="{{ form.permissionsType.id_for_label }}">Permission type:</label>
|
||||||
{{ form.permissionsType }}<br><br>
|
{{ form.permissionsType }}<br><br>
|
||||||
@@ -277,17 +359,20 @@
|
|||||||
<label for="{{ form.enableRecording.id_for_label }}">{{ form.enableRecording }} Enable recording session</label>
|
<label for="{{ form.enableRecording.id_for_label }}">{{ form.enableRecording }} Enable recording session</label>
|
||||||
<label for="{{ form.enableBlockingInput.id_for_label }}">{{ form.enableBlockingInput }} Enable blocking user input</label>
|
<label for="{{ form.enableBlockingInput.id_for_label }}">{{ form.enableBlockingInput }} Enable blocking user input</label>
|
||||||
<label for="{{ form.enableRemoteModi.id_for_label }}">{{ form.enableRemoteModi }} Enable remote configuration modification</label>
|
<label for="{{ form.enableRemoteModi.id_for_label }}">{{ form.enableRemoteModi }} Enable remote configuration modification</label>
|
||||||
|
<label for="{{ form.enablePrinter.id_for_label }}">{{ form.enablePrinter }} Enable remote printer</label>
|
||||||
|
<label for="{{ form.enableCamera.id_for_label }}">{{ form.enableCamera }} Enable remote camera</label>
|
||||||
|
<label for="{{ form.enableTerminal.id_for_label }}">{{ form.enableTerminal }} Enable remote terminal</label>
|
||||||
</div><br>
|
</div><br>
|
||||||
<h2><i class="fas fa-code"></i> Code Changes</h2>
|
<h2><i class="fas fa-code"></i> Code Changes</h2>
|
||||||
<label for="{{ form.cycleMonitor.id_for_label }}">{{ form.cycleMonitor }} Add a button to cycle through available monitors to the minimized toolbar.</label><br>
|
<label for="{{ form.cycleMonitor.id_for_label }}">{{ form.cycleMonitor }} Add a button to cycle through available monitors to the minimized toolbar.</label><br>
|
||||||
<label for="{{ form.xOffline.id_for_label }}">{{ form.xOffline }} Display an X for offline devices in the addressbook.</label><br>
|
<label for="{{ form.xOffline.id_for_label }}">{{ form.xOffline }} Display an X for offline devices in the addressbook.</label><br>
|
||||||
<label for="{{ form.hidecm.id_for_label }}">{{ form.hidecm }} Allow hiding the connection window from remote screen.</label><br>
|
|
||||||
<label for="{{ form.removeNewVersionNotif.id_for_label }}">{{ form.removeNewVersionNotif }} Remove notification for new versions.</label><br>
|
<label for="{{ form.removeNewVersionNotif.id_for_label }}">{{ form.removeNewVersionNotif }} Remove notification for new versions.</label><br>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2><i class="fas fa-cog"></i> Other</h2>
|
<h2><i class="fas fa-cog"></i> Other</h2>
|
||||||
<label for="{{ form.removeWallpaper.id_for_label }}">{{ form.removeWallpaper }} Remove wallpaper during incoming sessions</label><br>
|
<label for="{{ form.removeWallpaper.id_for_label }}">{{ form.removeWallpaper }} Remove wallpaper during incoming sessions</label><br>
|
||||||
|
<a href="https://rustdesk.com/docs/en/self-host/client-configuration/advanced-settings/">Click here for a list of Default/Override settings</a>
|
||||||
<label for="{{ form.defaultManual.id_for_label }}">Default settings</label><br>
|
<label for="{{ form.defaultManual.id_for_label }}">Default settings</label><br>
|
||||||
{{ form.defaultManual }}<br><br>
|
{{ form.defaultManual }}<br><br>
|
||||||
<label for="{{ form.overrideManual.id_for_label }}">Override settings</label><br>
|
<label for="{{ form.overrideManual.id_for_label }}">Override settings</label><br>
|
||||||
@@ -297,10 +382,24 @@
|
|||||||
<div class="platform">
|
<div class="platform">
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<button type="submit"><i class="fas fa-rocket"></i> Generate Custom Client</button>
|
<button type="submit"><i class="fas fa-rocket"></i> Generate Custom Client</button>
|
||||||
<a href="https://github.com/bryangerlach/rdgen">Source Code on github</a>
|
|
||||||
<iframe src="https://github.com/sponsors/bryangerlach/button" title="Sponsor bryangerlach" height="32" width="114" style="border: 0; border-radius: 6px;"></iframe>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div style="text-align: center; margin: 30px 0;">
|
||||||
|
<a href="https://github.com/bryangerlach/rdgen"
|
||||||
|
target="_blank"
|
||||||
|
class="sponsor-button">
|
||||||
|
<i class="fab fa-github"></i>
|
||||||
|
Source Code on Github
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div style="text-align: center; margin: 30px 0;">
|
||||||
|
<a href="https://github.com/sponsors/bryangerlach?o=esb"
|
||||||
|
target="_blank"
|
||||||
|
class="sponsor-button">
|
||||||
|
<i class="fab fa-github"></i>
|
||||||
|
Donate
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<script>
|
<script>
|
||||||
document.querySelectorAll('.platform-icon').forEach(icon => {
|
document.querySelectorAll('.platform-icon').forEach(icon => {
|
||||||
@@ -316,6 +415,98 @@
|
|||||||
document.getElementById("{{ form.logofile.id_for_label }}").addEventListener('change', function(event) {
|
document.getElementById("{{ form.logofile.id_for_label }}").addEventListener('change', function(event) {
|
||||||
previewImage(event.target, 'logo-preview');
|
previewImage(event.target, 'logo-preview');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.getElementById("{{ form.hidecm.id_for_label }}").addEventListener('change',function() {
|
||||||
|
if (this.checked) {
|
||||||
|
document.getElementById("passwordRequirement").style.display = 'block';
|
||||||
|
document.getElementById("{{ form.permanentPassword.id_for_label }}").focus();
|
||||||
|
document.getElementById("{{ form.passApproveMode.id_for_label }}").value = 'password';
|
||||||
|
} else {
|
||||||
|
document.getElementById("passwordRequirement").style.display = 'none';
|
||||||
|
document.getElementById("{{ form.passApproveMode.id_for_label }}").value = 'password-click';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const enableKeyboard = document.getElementById("{{ form.enableKeyboard.id_for_label }}");
|
||||||
|
const enableClipboard = document.getElementById("{{ form.enableClipboard.id_for_label }}");
|
||||||
|
const enableFileTransfer = document.getElementById("{{ form.enableFileTransfer.id_for_label }}");
|
||||||
|
const enableAudio = document.getElementById("{{ form.enableAudio.id_for_label }}");
|
||||||
|
const enableTCP = document.getElementById("{{ form.enableTCP.id_for_label }}");
|
||||||
|
const enableRemoteRestart = document.getElementById("{{ form.enableRemoteRestart.id_for_label }}");
|
||||||
|
const enableRecording = document.getElementById("{{ form.enableRecording.id_for_label }}");
|
||||||
|
const enableBlockingInput = document.getElementById("{{ form.enableBlockingInput.id_for_label }}");
|
||||||
|
const enableRemoteModi = document.getElementById("{{ form.enableRemoteModi.id_for_label }}");
|
||||||
|
const enablePrinter = document.getElementById("{{ form.enablePrinter.id_for_label }}");
|
||||||
|
const enableCamera = document.getElementById("{{ form.enableCamera.id_for_label }}");
|
||||||
|
const enableTerminal = document.getElementById("{{ form.enableTerminal.id_for_label }}");
|
||||||
|
|
||||||
|
document.getElementById("{{ form.permissionsType.id_for_label }}").addEventListener('change', function() {
|
||||||
|
if (this.value === 'full') {
|
||||||
|
enableKeyboard.checked = true;
|
||||||
|
enableClipboard.checked = true;
|
||||||
|
enableFileTransfer.checked = true;
|
||||||
|
enableAudio.checked = true;
|
||||||
|
enableTCP.checked = true;
|
||||||
|
enableRemoteRestart.checked = true;
|
||||||
|
enableRecording.checked = true;
|
||||||
|
enableBlockingInput.checked = true;
|
||||||
|
enableRemoteModi.checked = true;
|
||||||
|
enablePrinter.checked = true;
|
||||||
|
enableCamera.checked = true;
|
||||||
|
enableTerminal.checked = true;
|
||||||
|
|
||||||
|
enableKeyboard.disabled = true;
|
||||||
|
enableClipboard.disabled = true;
|
||||||
|
enableFileTransfer.disabled = true;
|
||||||
|
enableAudio.disabled = true;
|
||||||
|
enableTCP.disabled = true;
|
||||||
|
enableRemoteRestart.disabled = true;
|
||||||
|
enableRecording.disabled = true;
|
||||||
|
enableBlockingInput.disabled = true;
|
||||||
|
enableRemoteModi.disabled = true;
|
||||||
|
enablePrinter.disabled = true;
|
||||||
|
enableCamera.disabled = true;
|
||||||
|
enableTerminal.disable = true;
|
||||||
|
} else if (this.value === 'view') {
|
||||||
|
enableKeyboard.checked = false;
|
||||||
|
enableClipboard.checked = false;
|
||||||
|
enableFileTransfer.checked = false;
|
||||||
|
enableAudio.checked = false;
|
||||||
|
enableTCP.checked = false;
|
||||||
|
enableRemoteRestart.checked = false;
|
||||||
|
enableRecording.checked = false;
|
||||||
|
enableBlockingInput.checked = false;
|
||||||
|
enableRemoteModi.checked = false;
|
||||||
|
enablePrinter.checked = false;
|
||||||
|
enableCamera.checked = false;
|
||||||
|
enableTerminal.checked = false;
|
||||||
|
|
||||||
|
enableKeyboard.disabled = true;
|
||||||
|
enableClipboard.disabled = true;
|
||||||
|
enableFileTransfer.disabled = true;
|
||||||
|
enableAudio.disabled = true;
|
||||||
|
enableTCP.disabled = true;
|
||||||
|
enableRemoteRestart.disabled = true;
|
||||||
|
enableRecording.disabled = true;
|
||||||
|
enableBlockingInput.disabled = true;
|
||||||
|
enableRemoteModi.disabled = true;
|
||||||
|
enablePrinter.disabled = true;
|
||||||
|
enableCamera.disabled = true;
|
||||||
|
enableTerminal.disable = true;
|
||||||
|
} else if (this.value === 'custom') {
|
||||||
|
enableKeyboard.disabled = false;
|
||||||
|
enableClipboard.disabled = false;
|
||||||
|
enableFileTransfer.disabled = false;
|
||||||
|
enableAudio.disabled = false;
|
||||||
|
enableTCP.disabled = false;
|
||||||
|
enableRemoteRestart.disabled = false;
|
||||||
|
enableRecording.disabled = false;
|
||||||
|
enableBlockingInput.disabled = false;
|
||||||
|
enableRemoteModi.disabled = false;
|
||||||
|
enablePrinter.checked = false;
|
||||||
|
enableCamera.checked = false;
|
||||||
|
enableTerminal.checked = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
function previewImage(input, previewContainerId) {
|
function previewImage(input, previewContainerId) {
|
||||||
if (input.files && input.files[0]) {
|
if (input.files && input.files[0]) {
|
||||||
var reader = new FileReader();
|
var reader = new FileReader();
|
||||||
|
|||||||
@@ -154,6 +154,7 @@
|
|||||||
const platform = '{{platform}}'.toLowerCase();
|
const platform = '{{platform}}'.toLowerCase();
|
||||||
const platformLogos = {
|
const platformLogos = {
|
||||||
'windows': document.getElementById('windowsLogo'),
|
'windows': document.getElementById('windowsLogo'),
|
||||||
|
'windows-x86': document.getElementById('windowsLogo'),
|
||||||
'macos': document.getElementById('macosLogo'),
|
'macos': document.getElementById('macosLogo'),
|
||||||
'linux': document.getElementById('linuxLogo'),
|
'linux': document.getElementById('linuxLogo'),
|
||||||
'android': document.getElementById('androidLogo')
|
'android': document.getElementById('androidLogo')
|
||||||
@@ -167,7 +168,7 @@
|
|||||||
document.getElementById('pageTitle').textContent = 'Generating MacOS Build';
|
document.getElementById('pageTitle').textContent = 'Generating MacOS Build';
|
||||||
platformLogos.macos.style.display = 'block';
|
platformLogos.macos.style.display = 'block';
|
||||||
document.getElementById('macosNote').style.display = 'block';
|
document.getElementById('macosNote').style.display = 'block';
|
||||||
} else if (platform === 'windows') {
|
} else if (platform === 'windows' | platform === 'windows-x86') {
|
||||||
document.getElementById('pageTitle').textContent = 'Generating Windows Build';
|
document.getElementById('pageTitle').textContent = 'Generating Windows Build';
|
||||||
platformLogos.windows.style.display = 'block';
|
platformLogos.windows.style.display = 'block';
|
||||||
} else if (platform === 'linux') {
|
} else if (platform === 'linux') {
|
||||||
@@ -214,4 +215,4 @@
|
|||||||
}, 5000); // 5000 milliseconds = 5 seconds
|
}, 5000); // 5000 milliseconds = 5 seconds
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ def generator_view(request):
|
|||||||
compname = form.cleaned_data['compname']
|
compname = form.cleaned_data['compname']
|
||||||
if not compname:
|
if not compname:
|
||||||
compname = "Purslane Ltd"
|
compname = "Purslane Ltd"
|
||||||
|
compname = compname.replace("&","\\&")
|
||||||
permPass = form.cleaned_data['permanentPassword']
|
permPass = form.cleaned_data['permanentPassword']
|
||||||
theme = form.cleaned_data['theme']
|
theme = form.cleaned_data['theme']
|
||||||
themeDorO = form.cleaned_data['themeDorO']
|
themeDorO = form.cleaned_data['themeDorO']
|
||||||
@@ -73,6 +74,9 @@ def generator_view(request):
|
|||||||
removeWallpaper = form.cleaned_data['removeWallpaper']
|
removeWallpaper = form.cleaned_data['removeWallpaper']
|
||||||
defaultManual = form.cleaned_data['defaultManual']
|
defaultManual = form.cleaned_data['defaultManual']
|
||||||
overrideManual = form.cleaned_data['overrideManual']
|
overrideManual = form.cleaned_data['overrideManual']
|
||||||
|
enablePrinter = form.cleaned_data['enablePrinter']
|
||||||
|
enableCamera = form.cleaned_data['enableCamera']
|
||||||
|
enableTerminal = form.cleaned_data['enableTerminal']
|
||||||
|
|
||||||
if all(char.isascii() for char in filename):
|
if all(char.isascii() for char in filename):
|
||||||
filename = re.sub(r'[^\w\s-]', '_', filename).strip()
|
filename = re.sub(r'[^\w\s-]', '_', filename).strip()
|
||||||
@@ -118,14 +122,18 @@ def generator_view(request):
|
|||||||
decodedCustom['password'] = permPass
|
decodedCustom['password'] = permPass
|
||||||
if theme != "system":
|
if theme != "system":
|
||||||
if themeDorO == "default":
|
if themeDorO == "default":
|
||||||
decodedCustom['default-settings']['theme'] = theme
|
if platform == "windows-x86":
|
||||||
|
decodedCustom['default-settings']['allow-darktheme'] = 'Y' if theme == "dark" else 'N'
|
||||||
|
else:
|
||||||
|
decodedCustom['default-settings']['theme'] = theme
|
||||||
elif themeDorO == "override":
|
elif themeDorO == "override":
|
||||||
decodedCustom['override-settings']['theme'] = theme
|
if platform == "windows-x86":
|
||||||
decodedCustom['approve-mode'] = passApproveMode
|
decodedCustom['override-settings']['allow-darktheme'] = 'Y' if theme == "dark" else 'N'
|
||||||
|
else:
|
||||||
|
decodedCustom['override-settings']['theme'] = theme
|
||||||
decodedCustom['enable-lan-discovery'] = 'N' if denyLan else 'Y'
|
decodedCustom['enable-lan-discovery'] = 'N' if denyLan else 'Y'
|
||||||
decodedCustom['direct-server'] = 'Y' if enableDirectIP else 'N'
|
#decodedCustom['direct-server'] = 'Y' if enableDirectIP else 'N'
|
||||||
decodedCustom['allow-auto-disconnect'] = 'Y' if autoClose else 'N'
|
decodedCustom['allow-auto-disconnect'] = 'Y' if autoClose else 'N'
|
||||||
decodedCustom['allow-remove-wallpaper'] = 'Y' if removeWallpaper else 'N'
|
|
||||||
if permissionsDorO == "default":
|
if permissionsDorO == "default":
|
||||||
decodedCustom['default-settings']['access-mode'] = permissionsType
|
decodedCustom['default-settings']['access-mode'] = permissionsType
|
||||||
decodedCustom['default-settings']['enable-keyboard'] = 'Y' if enableKeyboard else 'N'
|
decodedCustom['default-settings']['enable-keyboard'] = 'Y' if enableKeyboard else 'N'
|
||||||
@@ -137,6 +145,14 @@ def generator_view(request):
|
|||||||
decodedCustom['default-settings']['enable-record-session'] = 'Y' if enableRecording else 'N'
|
decodedCustom['default-settings']['enable-record-session'] = 'Y' if enableRecording else 'N'
|
||||||
decodedCustom['default-settings']['enable-block-input'] = 'Y' if enableBlockingInput else 'N'
|
decodedCustom['default-settings']['enable-block-input'] = 'Y' if enableBlockingInput else 'N'
|
||||||
decodedCustom['default-settings']['allow-remote-config-modification'] = 'Y' if enableRemoteModi else 'N'
|
decodedCustom['default-settings']['allow-remote-config-modification'] = 'Y' if enableRemoteModi else 'N'
|
||||||
|
decodedCustom['default-settings']['direct-server'] = 'Y' if enableDirectIP else 'N'
|
||||||
|
decodedCustom['default-settings']['verification-method'] = 'use-permanent-password' if hidecm else 'use-both-passwords'
|
||||||
|
decodedCustom['default-settings']['approve-mode'] = passApproveMode
|
||||||
|
decodedCustom['default-settings']['allow-hide-cm'] = 'Y' if hidecm else 'N'
|
||||||
|
decodedCustom['default-settings']['allow-remove-wallpaper'] = 'Y' if removeWallpaper else 'N'
|
||||||
|
decodedCustom['default-settings']['enable-remote-printer'] = 'Y' if enablePrinter else 'N'
|
||||||
|
decodedCustom['default-settings']['enable-camera'] = 'Y' if enableCamera else 'N'
|
||||||
|
decodedCustom['default-settings']['enable-terminal'] = 'Y' if enableTerminal else 'N'
|
||||||
else:
|
else:
|
||||||
decodedCustom['override-settings']['access-mode'] = permissionsType
|
decodedCustom['override-settings']['access-mode'] = permissionsType
|
||||||
decodedCustom['override-settings']['enable-keyboard'] = 'Y' if enableKeyboard else 'N'
|
decodedCustom['override-settings']['enable-keyboard'] = 'Y' if enableKeyboard else 'N'
|
||||||
@@ -148,6 +164,14 @@ def generator_view(request):
|
|||||||
decodedCustom['override-settings']['enable-record-session'] = 'Y' if enableRecording else 'N'
|
decodedCustom['override-settings']['enable-record-session'] = 'Y' if enableRecording else 'N'
|
||||||
decodedCustom['override-settings']['enable-block-input'] = 'Y' if enableBlockingInput else 'N'
|
decodedCustom['override-settings']['enable-block-input'] = 'Y' if enableBlockingInput else 'N'
|
||||||
decodedCustom['override-settings']['allow-remote-config-modification'] = 'Y' if enableRemoteModi else 'N'
|
decodedCustom['override-settings']['allow-remote-config-modification'] = 'Y' if enableRemoteModi else 'N'
|
||||||
|
decodedCustom['override-settings']['direct-server'] = 'Y' if enableDirectIP else 'N'
|
||||||
|
decodedCustom['override-settings']['verification-method'] = 'use-permanent-password' if hidecm else 'use-both-passwords'
|
||||||
|
decodedCustom['override-settings']['approve-mode'] = passApproveMode
|
||||||
|
decodedCustom['override-settings']['allow-hide-cm'] = 'Y' if hidecm else 'N'
|
||||||
|
decodedCustom['override-settings']['allow-remove-wallpaper'] = 'Y' if removeWallpaper else 'N'
|
||||||
|
decodedCustom['override-settings']['enable-remote-printer'] = 'Y' if enablePrinter else 'N'
|
||||||
|
decodedCustom['override-settings']['enable-camera'] = 'Y' if enableCamera else 'N'
|
||||||
|
decodedCustom['override-settings']['enable-terminal'] = 'Y' if enableTerminal else 'N'
|
||||||
|
|
||||||
for line in defaultManual.splitlines():
|
for line in defaultManual.splitlines():
|
||||||
k, value = line.split('=')
|
k, value = line.split('=')
|
||||||
@@ -174,16 +198,17 @@ def generator_view(request):
|
|||||||
extras['rdgen'] = 'true'
|
extras['rdgen'] = 'true'
|
||||||
extras['cycleMonitor'] = 'true' if cycleMonitor else 'false'
|
extras['cycleMonitor'] = 'true' if cycleMonitor else 'false'
|
||||||
extras['xOffline'] = 'true' if xOffline else 'false'
|
extras['xOffline'] = 'true' if xOffline else 'false'
|
||||||
extras['hidecm'] = 'true' if hidecm else 'false'
|
|
||||||
extras['removeNewVersionNotif'] = 'true' if removeNewVersionNotif else 'false'
|
extras['removeNewVersionNotif'] = 'true' if removeNewVersionNotif else 'false'
|
||||||
extras['compname'] = compname
|
extras['compname'] = compname
|
||||||
extra_input = json.dumps(extras)
|
extra_input = json.dumps(extras)
|
||||||
|
|
||||||
####from here run the github action, we need user, repo, access token.
|
####from here run the github action, we need user, repo, access token.
|
||||||
if platform == 'windows':
|
if platform == 'windows':
|
||||||
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-windows.yml/dispatches'
|
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-windows.yml/dispatches'
|
||||||
|
if platform == 'windows-x86':
|
||||||
|
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-windows-x86.yml/dispatches'
|
||||||
elif platform == 'linux':
|
elif platform == 'linux':
|
||||||
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-linux.yml/dispatches'
|
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-linux.yml/dispatches'
|
||||||
elif platform == 'android':
|
elif platform == 'android':
|
||||||
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-android.yml/dispatches'
|
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-android.yml/dispatches'
|
||||||
elif platform == 'macos':
|
elif platform == 'macos':
|
||||||
@@ -387,4 +412,4 @@ def save_custom_client(request):
|
|||||||
for chunk in file.chunks():
|
for chunk in file.chunks():
|
||||||
f.write(chunk)
|
f.write(chunk)
|
||||||
|
|
||||||
return HttpResponse("File saved successfully!")
|
return HttpResponse("File saved successfully!")
|
||||||
|
|||||||
Reference in New Issue
Block a user