Merged 1.3.x_branch into master
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -5,3 +5,5 @@ build/
|
|||||||
chrome_data/
|
chrome_data/
|
||||||
dist/
|
dist/
|
||||||
/.cache
|
/.cache
|
||||||
|
/temp.json
|
||||||
|
/.eslintcache
|
||||||
|
|||||||
14
.vim/coc-settings.json
Normal file
14
.vim/coc-settings.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"HKEY",
|
||||||
|
"HKLM",
|
||||||
|
"Redistributable",
|
||||||
|
"Skylinks",
|
||||||
|
"Skynet",
|
||||||
|
"Unmount",
|
||||||
|
"msiexec",
|
||||||
|
"relver",
|
||||||
|
"siaprime",
|
||||||
|
"skylink"
|
||||||
|
]
|
||||||
|
}
|
||||||
7
.vimrc
Normal file
7
.vimrc
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
set autoread
|
||||||
|
set path+=.,public/**,src/**,test/**
|
||||||
|
if has('win32')
|
||||||
|
let &makeprg="create_dist.cmd"
|
||||||
|
else
|
||||||
|
let &makeprg="./create_dist.sh"
|
||||||
|
endif
|
||||||
25
CHANGELOG.md
25
CHANGELOG.md
@@ -1,4 +1,29 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
## 1.3.2
|
||||||
|
* \#48: Support pinning files to cache
|
||||||
|
* Fixed Skynet export display
|
||||||
|
* Properly detect existing remote
|
||||||
|
* Reduced number of Linux binaries to:
|
||||||
|
* CentOS 7
|
||||||
|
* Solus
|
||||||
|
* S3 mount support [disabled]
|
||||||
|
|
||||||
|
## 1.3.1
|
||||||
|
* \#45: Skynet mount support
|
||||||
|
|
||||||
|
## 1.3.0
|
||||||
|
* \#38: Enhance new repertory release available notification
|
||||||
|
* \#46: Fix Mount Manager unmount and mount detection
|
||||||
|
* Skynet support
|
||||||
|
* Synchronize UI major/minor version with `repertory` major/minor version
|
||||||
|
* Added `Password` component
|
||||||
|
* Reduced number of Linux binaries to:
|
||||||
|
* CentOS 7
|
||||||
|
* Debian 9
|
||||||
|
* Debian 10
|
||||||
|
* Solus
|
||||||
|
* Added `FocusTrap` to modals
|
||||||
|
|
||||||
## 1.1.4
|
## 1.1.4
|
||||||
* \#39: Cleanup old releases and UI upgrades
|
* \#39: Cleanup old releases and UI upgrades
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Repertory UI MIT License
|
# Repertory UI MIT License
|
||||||
### Copyright <2018-2019> <scott.e.graves@protonmail.com>
|
### Copyright <2018-2020> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
|||||||
54
README.md
54
README.md
@@ -1,57 +1,39 @@
|
|||||||
# Repertory UI
|
# Repertory UI
|
||||||

|

|
||||||
|
|
||||||
## GUI for [Repertory](https://bitbucket.org/blockstorage/repertory)
|
## GUI for [Repertory](https://bitbucket.org/blockstorage/repertory)
|
||||||
Repertory allows you to mount Sia and/or ScPrime blockchain storage solutions via FUSE on Linux/OS X or via WinFSP on Windows.
|
Repertory allows you to mount Sia, Skynet and/or ScPrime blockchain storage solutions via FUSE on Linux/OS X or via WinFSP on Windows.
|
||||||
|
|
||||||
# Windows Issue
|
|
||||||
If you're experiencing slow copy, read, and/or write, please install the following UI version. This is a special build that includes WinFSP 2020.2:
|
|
||||||
|
|
||||||
* [Repertory UI v1.1.5 Windows 64-bit](https://bitbucket.org/blockstorage/repertory-testing/downloads/repertory-ui_1.1.5_win.exe)
|
|
||||||
|
|
||||||
# Discord Invite
|
|
||||||
* [Repertory Discord](https://discord.gg/f2rCfqRgrJ)
|
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
* Sia >=1.4.1
|
* Sia >=1.4.1
|
||||||
* ScPrime >=1.4.1.2
|
* ScPrime >=1.4.1.2
|
||||||
|
|
||||||
## Downloads
|
## Downloads
|
||||||
* **Repertory UI v1.1.4 Linux 64-bit** [<Download\>](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_linux_x86_64.AppImage)
|
* **Repertory UI v1.3.2 Linux
|
||||||
* NOTE: Linux distributions require `fuse` and `libfuse` to be installed.
|
64-bit** [<Download\>](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.2_linux_x86_64.AppImage)
|
||||||
* **Repertory UI v1.1.4 OS X 64-bit** [<Download\>](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_mac.dmg)
|
* NOTE: Linux distributions require `fuse` and `libfuse` to be installed.
|
||||||
* **Repertory UI v1.1.4 Windows 64-bit** [<Download\>](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_win.exe)
|
* **Repertory UI v1.3.2 OS X
|
||||||
|
64-bit** [<Download\>](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.2_mac.dmg)
|
||||||
|
* **Repertory UI v1.3.2 Windows
|
||||||
|
64-bit** [<Download\>](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.2_win.exe)
|
||||||
|
|
||||||
## Supported Platforms
|
## Supported Platforms
|
||||||
* OS X 64-bit
|
* OS X 64-bit
|
||||||
* Windows 64-bit
|
* Windows 64-bit
|
||||||
* Linux 64-bit Distributions:
|
* Linux 64-bit Distributions:
|
||||||
* Antergos
|
* Antergos
|
||||||
* Uses `Ubuntu 18.10` binaries for compatibility
|
|
||||||
* Arch Linux
|
* Arch Linux
|
||||||
* Bodhi 5.0.0
|
* Bodhi 5.0.0
|
||||||
* CentOS 7
|
* CentOS 7, 8
|
||||||
* CentOS 8
|
* Debian 9, 10
|
||||||
* Debian 9
|
* Elementary OS 5.0, 5.1
|
||||||
* Debian 10
|
* Fedora 28, 29, 30, 31, 32, 33
|
||||||
* Elementary OS 5.0
|
* Linux Mint 19, 19.1, 19.2, 19.3, 20, 20.1
|
||||||
* Fedora 28
|
|
||||||
* Fedora 29
|
|
||||||
* Fedora 30
|
|
||||||
* Fedora 31
|
|
||||||
* Linux Mint 19
|
|
||||||
* Linux Mint 19.1
|
|
||||||
* Linux Mint 19.2
|
|
||||||
* Manjaro
|
* Manjaro
|
||||||
* Uses `Ubuntu 18.10` binaries for compatibility
|
* OpenSUSE Leap 15.0, 15.1
|
||||||
* OpenSUSE Leap 15.0
|
|
||||||
* OpenSUSE Leap 15.1
|
|
||||||
* OpenSUSE Tumbleweed
|
* OpenSUSE Tumbleweed
|
||||||
* Solus
|
* Solus
|
||||||
* Ubuntu 18.04
|
* Ubuntu 18.04, 18.10, 19.04, 19.10, 20.04
|
||||||
* Ubuntu 18.10
|
|
||||||
* Ubuntu 19.04
|
|
||||||
* Ubuntu 19.10
|
|
||||||
|
|
||||||
## Issues/Suggestions
|
## Issues/Suggestions
|
||||||
Please submit [here](https://bitbucket.org/blockstorage/repertory-ui/issues?status=new&status=open)
|
Please submit [here](https://bitbucket.org/blockstorage/repertory-ui/issues?status=new&status=open)
|
||||||
@@ -63,10 +45,6 @@ This feature allows you to share your mounts with other PC's and mount them remo
|
|||||||
### Connecting to a Remote Mount
|
### Connecting to a Remote Mount
|
||||||
[Watch Demo](src/assets/images/Connect_To_Remote.gif)
|
[Watch Demo](src/assets/images/Connect_To_Remote.gif)
|
||||||
|
|
||||||
## The FAQ of One
|
|
||||||
### My distro isn't listed... Why?
|
|
||||||
It may still function properly as long as it derives from one listed above. I do plan to test more, so this list should grow over time.
|
|
||||||
|
|
||||||
## Tips
|
## Tips
|
||||||
* BTC: 1CMvhGaJfH95VS4CTS6dJYDs8kwYXTUCEA
|
* BTC: 1CMvhGaJfH95VS4CTS6dJYDs8kwYXTUCEA
|
||||||
* SC: c5510db5c2e85794b9cb81851daa57d6dfd5b4e42cd02789442e8789cd6492b07c754b2056ed
|
* SC: c5510db5c2e85794b9cb81851daa57d6dfd5b4e42cd02789442e8789cd6492b07c754b2056ed
|
||||||
|
|||||||
@@ -4,7 +4,12 @@ setlocal EnableDelayedExpansion
|
|||||||
set ROOT=%~dp0%
|
set ROOT=%~dp0%
|
||||||
set /a ENABLE_UPLOAD=%1
|
set /a ENABLE_UPLOAD=%1
|
||||||
set BITBUCKET_AUTH=%2
|
set BITBUCKET_AUTH=%2
|
||||||
|
set BITBUCKET_TESTING=%3
|
||||||
|
if "%BITBUCKET_TESTING%" == "1" (
|
||||||
|
set REPOSITORY=repertory-testing
|
||||||
|
) else (
|
||||||
|
set REPOSITORY=repertory-ui
|
||||||
|
)
|
||||||
set OPENSSL_BIN="c:\OpenSSL-Win64\bin\openssl.exe"
|
set OPENSSL_BIN="c:\OpenSSL-Win64\bin\openssl.exe"
|
||||||
if NOT EXIST %OPENSSL_BIN% (
|
if NOT EXIST %OPENSSL_BIN% (
|
||||||
set OPENSSL_BIN="c:\Program Files\OpenSSL-Win64\bin\openssl.exe"
|
set OPENSSL_BIN="c:\Program Files\OpenSSL-Win64\bin\openssl.exe"
|
||||||
@@ -41,23 +46,17 @@ pushd "%ROOT%"
|
|||||||
|
|
||||||
del /q upload_response.json 1>NUL 2>&1
|
del /q upload_response.json 1>NUL 2>&1
|
||||||
|
|
||||||
("%CURL_BIN%" -F name="%OUT_FILE%" -F anonymous=true -F file="@%OUT_FILE%" https://pixeldrain.com/api/file > upload_response.json) || (
|
|
||||||
call :PIXEL_RESPONSE 0
|
|
||||||
)
|
|
||||||
call :PIXEL_RESPONSE 1
|
|
||||||
set PIXEL_LOCATION=https://pixeldrain.com/api/file/!PIXEL_ID!
|
|
||||||
|
|
||||||
call :UPLOAD_TO_BITBUCKET "%OUT_FILE%"
|
call :UPLOAD_TO_BITBUCKET "%OUT_FILE%"
|
||||||
call :UPLOAD_TO_BITBUCKET "%OUT_FILE%.sha256"
|
call :UPLOAD_TO_BITBUCKET "%OUT_FILE%.sha256"
|
||||||
call :UPLOAD_TO_BITBUCKET "%OUT_FILE%.sig"
|
call :UPLOAD_TO_BITBUCKET "%OUT_FILE%.sig"
|
||||||
set BITBUCKET_LOCATION=https://bitbucket.org/blockstorage/repertory-ui/downloads/%OUT_FILE%
|
set BITBUCKET_LOCATION=https://bitbucket.org/blockstorage/%REPOSITORY%/downloads/%OUT_FILE%
|
||||||
|
|
||||||
del /q releases.json 1>NUL 2>&1
|
del /q releases.json 1>NUL 2>&1
|
||||||
|
|
||||||
("%JQ_BIN%" ".Versions.win32|=(.+ ["""%APP_VER%"""]|unique)" ..\releases.json>releases_temp.json && move /Y releases_temp.json releases.json 1>NUL 2>&1) || (call :ERROR "Update releases.json Versions failed")
|
("%JQ_BIN%" ".Versions.win32|=(.+ ["""%APP_VER%"""]|unique)" ..\releases.json>releases_temp.json && move /Y releases_temp.json releases.json 1>NUL 2>&1) || (call :ERROR "Update releases.json Versions failed")
|
||||||
("%JQ_BIN%" ".Locations.win32."""%APP_VER%""".sig="""!APP_SIG!"""" releases.json>releases_temp.json && move /Y releases_temp.json releases.json 1>NUL 2>&1) || (call :ERROR "Update releases.json sig failed")
|
("%JQ_BIN%" ".Locations.win32."""%APP_VER%""".sig="""!APP_SIG!"""" releases.json>releases_temp.json && move /Y releases_temp.json releases.json 1>NUL 2>&1) || (call :ERROR "Update releases.json sig failed")
|
||||||
("%JQ_BIN%" ".Locations.win32."""%APP_VER%""".sha256="""!APP_SHA256!"""" releases.json>releases_temp.json && move /Y releases_temp.json releases.json 1>NUL 2>&1) || (call :ERROR "Update releases.json sha256 failed")
|
("%JQ_BIN%" ".Locations.win32."""%APP_VER%""".sha256="""!APP_SHA256!"""" releases.json>releases_temp.json && move /Y releases_temp.json releases.json 1>NUL 2>&1) || (call :ERROR "Update releases.json sha256 failed")
|
||||||
("%JQ_BIN%" ".Locations.win32."""%APP_VER%""".urls=["""!PIXEL_LOCATION!""","""!BITBUCKET_LOCATION!"""]" releases.json>releases_temp.json && move /Y releases_temp.json releases.json 1>NUL 2>&1) || (call :ERROR "Update releases.json URL failed")
|
("%JQ_BIN%" ".Locations.win32."""%APP_VER%""".urls=["""!BITBUCKET_LOCATION!"""]" releases.json>releases_temp.json && move /Y releases_temp.json releases.json 1>NUL 2>&1) || (call :ERROR "Update releases.json URL failed")
|
||||||
)
|
)
|
||||||
popd
|
popd
|
||||||
) || (
|
) || (
|
||||||
@@ -70,36 +69,12 @@ goto :END
|
|||||||
set %~1=!%~1:"=!
|
set %~1=!%~1:"=!
|
||||||
goto :EOF
|
goto :EOF
|
||||||
|
|
||||||
:PIXEL_RESPONSE
|
|
||||||
set PIXEL_RESPONSE=
|
|
||||||
if %1==1 (
|
|
||||||
for /f "delims=" %%i in ('%JQ_BIN% .success upload_response.json') do (
|
|
||||||
if "%%i" == "false" (
|
|
||||||
for /f "delims=" %%i in ('%JQ_BIN% .message upload_response.json') do (
|
|
||||||
set PIXEL_RESPONSE=!PIXEL_RESPONSE!%%i
|
|
||||||
)
|
|
||||||
call :ERROR "Upload to pixeldrain failed: !PIXEL_RESPONSE!"
|
|
||||||
) else (
|
|
||||||
for /f "delims=" %%i in ('%JQ_BIN% .id upload_response.json') do (
|
|
||||||
set PIXEL_ID=%%i
|
|
||||||
call :NO_QUOTES PIXEL_ID
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
) else (
|
|
||||||
for /f "delims=" %%i in ('type upload_response.json') do (
|
|
||||||
set PIXEL_RESPONSE=!PIXEL_RESPONSE!%%i
|
|
||||||
)
|
|
||||||
call :ERROR "Upload to pixeldrain failed: !PIXEL_RESPONSE!"
|
|
||||||
)
|
|
||||||
goto :EOF
|
|
||||||
|
|
||||||
:UPLOAD_TO_BITBUCKET
|
:UPLOAD_TO_BITBUCKET
|
||||||
set SOURCE_FILE=%1
|
set SOURCE_FILE=%1
|
||||||
call :NO_QUOTES SOURCE_FILE
|
call :NO_QUOTES SOURCE_FILE
|
||||||
call :NO_QUOTES BITBUCKET_AUTH
|
call :NO_QUOTES BITBUCKET_AUTH
|
||||||
echo "Uploading !SOURCE_FILE! to Bitbucket"
|
echo "Uploading !SOURCE_FILE! to Bitbucket %REPOSITORY%"
|
||||||
(curl --fail -u "!BITBUCKET_AUTH!" -X POST https://api.bitbucket.org/2.0/repositories/blockstorage/repertory-ui/downloads -F files="@!SOURCE_FILE!" > upload_response.json) || (call :ERROR "Upload to Bitbucket failed: %SOURCE_FILE%")
|
(curl --fail -u "!BITBUCKET_AUTH!" -X POST https://api.bitbucket.org/2.0/repositories/blockstorage/%REPOSITORY%/downloads -F files="@!SOURCE_FILE!" > upload_response.json) || (call :ERROR "Upload to Bitbucket %REPOSITORY% failed: %SOURCE_FILE%")
|
||||||
goto :EOF
|
goto :EOF
|
||||||
|
|
||||||
:ERROR
|
:ERROR
|
||||||
|
|||||||
@@ -7,6 +7,13 @@ export PATH
|
|||||||
|
|
||||||
ENABLE_UPLOAD=$1
|
ENABLE_UPLOAD=$1
|
||||||
BITBUCKET_AUTH=$2
|
BITBUCKET_AUTH=$2
|
||||||
|
BITBUCKET_TESTING=$3
|
||||||
|
|
||||||
|
if [ "$BITBUCKET_TESTING" = "1" ]; then
|
||||||
|
REPOSITORY=repertory-testing
|
||||||
|
else
|
||||||
|
REPOSITORY=repertory-ui
|
||||||
|
fi
|
||||||
|
|
||||||
PRIVATE_KEY=../../blockstorage_dev_private.pem
|
PRIVATE_KEY=../../blockstorage_dev_private.pem
|
||||||
PUBLIC_KEY=../blockstorage_dev_public.pem
|
PUBLIC_KEY=../blockstorage_dev_public.pem
|
||||||
@@ -19,7 +26,7 @@ if beginsWith darwin "$OSTYPE"; then
|
|||||||
JQ_EXEC=jq-osx-amd64
|
JQ_EXEC=jq-osx-amd64
|
||||||
SHA256_EXEC="shasum -a 256 -b"
|
SHA256_EXEC="shasum -a 256 -b"
|
||||||
else
|
else
|
||||||
DISTRO_LIST="arch centos7 centos8 debian9 debian10 fedora28 fedora29 fedora30 fedora31 opensuse15 opensuse15.1 solus tumbleweed ubuntu18.04 ubuntu18.10 ubuntu19.04 ubuntu19.10"
|
DISTRO_LIST="centos7 debian9 debian10 solus"
|
||||||
OUT_FILE=repertory-ui_${APP_VER}_linux_x86_64.AppImage
|
OUT_FILE=repertory-ui_${APP_VER}_linux_x86_64.AppImage
|
||||||
BASE64_EXEC="base64 -w0"
|
BASE64_EXEC="base64 -w0"
|
||||||
JQ_EXEC=jq-linux64
|
JQ_EXEC=jq-linux64
|
||||||
@@ -33,7 +40,8 @@ exit_script() {
|
|||||||
|
|
||||||
upload_to_bitbucket() {
|
upload_to_bitbucket() {
|
||||||
SOURCE_FILE=$1
|
SOURCE_FILE=$1
|
||||||
curl --fail -u "${BITBUCKET_AUTH}" -X POST https://api.bitbucket.org/2.0/repositories/blockstorage/repertory-ui/downloads -F files=@${SOURCE_FILE} > upload_response.json || exit_script "Upload to Bitbucket failed: ${SOURCE_FILE}"
|
echo "Uploading ${SOURCE_FILE} to Bitbucket ${REPOSITORY}"
|
||||||
|
curl --fail -u "${BITBUCKET_AUTH}" -X POST https://api.bitbucket.org/2.0/repositories/blockstorage/${REPOSITORY}/downloads -F files=@${SOURCE_FILE} > upload_response.json || exit_script "Upload to Bitbucket failed: ${SOURCE_FILE}"
|
||||||
}
|
}
|
||||||
|
|
||||||
chmod +x "bin/${JQ_EXEC}" || exit_script "chmod +x ${JQ_EXEC} failed"
|
chmod +x "bin/${JQ_EXEC}" || exit_script "chmod +x ${JQ_EXEC} failed"
|
||||||
@@ -52,30 +60,20 @@ if npm run dist; then
|
|||||||
APP_SHA256=$(cat ${OUT_FILE}.sha256 | awk '{print $1;}')
|
APP_SHA256=$(cat ${OUT_FILE}.sha256 | awk '{print $1;}')
|
||||||
|
|
||||||
rm -f upload_response.json 1>/dev/null 2>&1
|
rm -f upload_response.json 1>/dev/null 2>&1
|
||||||
curl --fail -F name="${OUT_FILE}" -F anonymous=true -F file="@${OUT_FILE}" https://pixeldrain.com/api/file > upload_response.json || exit_script "Upload to Pixeldrain failed"
|
|
||||||
|
|
||||||
PIXEL_SUCCESS=$(${JQ_EXEC} .success upload_response.json)
|
upload_to_bitbucket "${OUT_FILE}"
|
||||||
if [ "${PIXEL_SUCCESS}" = "false" ]; then
|
upload_to_bitbucket "${OUT_FILE}.sha256"
|
||||||
PIXEL_MESSAGE=$(${JQ_EXEC} .message upload_response.json)
|
upload_to_bitbucket "${OUT_FILE}.sig"
|
||||||
exit_script "${PIXEL_MESSAGE}"
|
BITBUCKET_LOCATION=https://bitbucket.org/blockstorage/${REPOSITORY}/downloads/${OUT_FILE}
|
||||||
else
|
|
||||||
PIXEL_ID=$(${JQ_EXEC} .id upload_response.json|sed s/\"//g)
|
|
||||||
PIXEL_LOCATION=https://pixeldrain.com/api/file/${PIXEL_ID}
|
|
||||||
|
|
||||||
upload_to_bitbucket "${OUT_FILE}"
|
cp -f ../releases.json ./releases.json
|
||||||
upload_to_bitbucket "${OUT_FILE}.sha256"
|
for DISTRONAME in ${DISTRO_LIST}; do
|
||||||
upload_to_bitbucket "${OUT_FILE}.sig"
|
${JQ_EXEC} ".Versions[\"${DISTRONAME}\"]|=(.+ [\"${APP_VER}\"]|unique)" releases.json > releases_temp.json || exit_script "Update releases.json Versions failed"
|
||||||
BITBUCKET_LOCATION=https://bitbucket.org/blockstorage/repertory-ui/downloads/${OUT_FILE}
|
${JQ_EXEC} ".Locations[\"${DISTRONAME}\"].\"${APP_VER}\".sig=\"${APP_SIG}\"" releases_temp.json > releases.json || exit_script "Update releases.json sig failed"
|
||||||
|
${JQ_EXEC} ".Locations[\"${DISTRONAME}\"].\"${APP_VER}\".sha256=\"${APP_SHA256}\"" releases.json > releases_temp.json || exit_script "Update releases.json sha256 failed"
|
||||||
cp -f ../releases.json ./releases.json
|
${JQ_EXEC} ".Locations[\"${DISTRONAME}\"].\"${APP_VER}\".urls=[\"${BITBUCKET_LOCATION}\"]" releases_temp.json > releases.json || exit_script "Update releases.json URL failed"
|
||||||
for DISTRONAME in ${DISTRO_LIST}; do
|
done
|
||||||
${JQ_EXEC} ".Versions[\"${DISTRONAME}\"]|=(.+ [\"${APP_VER}\"]|unique)" releases.json > releases_temp.json || exit_script "Update releases.json Versions failed"
|
rm -f releases_temp.json
|
||||||
${JQ_EXEC} ".Locations[\"${DISTRONAME}\"].\"${APP_VER}\".sig=\"${APP_SIG}\"" releases_temp.json > releases.json || exit_script "Update releases.json sig failed"
|
|
||||||
${JQ_EXEC} ".Locations[\"${DISTRONAME}\"].\"${APP_VER}\".sha256=\"${APP_SHA256}\"" releases.json > releases_temp.json || exit_script "Update releases.json sha256 failed"
|
|
||||||
${JQ_EXEC} ".Locations[\"${DISTRONAME}\"].\"${APP_VER}\".urls=[\"${PIXEL_LOCATION}\",\"${BITBUCKET_LOCATION}\"]" releases_temp.json > releases.json || exit_script "Update releases.json URL failed"
|
|
||||||
done
|
|
||||||
rm -f releases_temp.json
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
cd -
|
cd -
|
||||||
else
|
else
|
||||||
|
|||||||
52
package.json
52
package.json
@@ -1,43 +1,43 @@
|
|||||||
{
|
{
|
||||||
"name": "repertory-ui",
|
"name": "repertory-ui",
|
||||||
"version": "1.1.4",
|
"version": "1.3.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"author": "scott.e.graves@protonmail.com",
|
"author": "scott.e.graves@protonmail.com",
|
||||||
"description": "GUI for Repertory - Repertory allows you to mount Sia and/or ScPrime blockchain storage solutions via FUSE on Linux/OS X or via WinFSP on Windows.",
|
"description": "GUI for Repertory - Repertory allows you to mount Sia, Skynet, and/or ScPrime storage solutions via FUSE on Linux/OS X or via WinFSP on Windows.",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "^1.2.27",
|
"@fortawesome/fontawesome-svg-core": "^1.2.32",
|
||||||
"@fortawesome/free-solid-svg-icons": "^5.12.1",
|
"@fortawesome/free-solid-svg-icons": "^5.15.1",
|
||||||
"@fortawesome/react-fontawesome": "^0.1.8",
|
"@fortawesome/react-fontawesome": "^0.1.13",
|
||||||
"@reduxjs/toolkit": "^1.2.4",
|
"@reduxjs/toolkit": "^1.5.0",
|
||||||
"auto-launch": "^5.0.5",
|
"auto-launch": "^5.0.5",
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.21.0",
|
||||||
"devtron": "^1.4.0",
|
"devtron": "^1.4.0",
|
||||||
"electron-debug": "^3.0.1",
|
"electron-debug": "^3.1.0",
|
||||||
"electron-log": "^4.0.6",
|
"electron-log": "^4.3.0",
|
||||||
|
"focus-trap-react": "^8.3.2",
|
||||||
"font-awesome": "^4.7.0",
|
"font-awesome": "^4.7.0",
|
||||||
"node-schedule": "^1.3.2",
|
"node-cron": "^1.2.1",
|
||||||
"randomstring": "^1.1.5",
|
"randomstring": "^1.1.5",
|
||||||
"react": "^16.12.0",
|
"react": "^16.14.0",
|
||||||
"react-dom": "^16.12.0",
|
"react-checkbox-tree": "^1.6.0",
|
||||||
"react-loader-spinner": "^3.1.5",
|
"react-dom": "^16.14.0",
|
||||||
"react-redux": "^7.1.3",
|
"react-loader-spinner": "^3.1.14",
|
||||||
"react-scripts": "3.3.1",
|
"react-redux": "^7.2.2",
|
||||||
"react-tooltip": "^4.0.3",
|
"react-scripts": "4.0.3",
|
||||||
|
"react-tooltip": "^4.2.11",
|
||||||
"redux": "^4.0.5",
|
"redux": "^4.0.5",
|
||||||
"redux-thunk": "^2.3.0",
|
"redux-thunk": "^2.3.0",
|
||||||
"unzipper": "^0.10.8",
|
"unzipper": "^0.10.11",
|
||||||
"winreg": "^1.2.4"
|
"winreg": "^1.2.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^7.0.0",
|
"babel-loader": "8.1.0",
|
||||||
"electron": "^5.0.13",
|
"cross-env": "^7.0.3",
|
||||||
"electron-builder": "^20.44.4",
|
"electron": "5.0.13",
|
||||||
"extract-text-webpack-plugin": "^3.0.2",
|
"electron-builder": "22.9.1",
|
||||||
"fibers": "^4.0.2",
|
"electron-webpack": "^2.8.2",
|
||||||
"node-sass": "^4.13.1",
|
"webpack": "4.44.2",
|
||||||
"sass": "^1.25.0",
|
"webpack-dev-server": "3.11.1"
|
||||||
"typescript": "^3.7.5",
|
|
||||||
"webpack-browser-plugin": "^1.0.20"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
|
|||||||
84
public/detect_linux.sh
Normal file → Executable file
84
public/detect_linux.sh
Normal file → Executable file
@@ -8,89 +8,23 @@ resetDistVer() {
|
|||||||
DISTVER=
|
DISTVER=
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ -f /etc/centos-release ]; then
|
IS_ARM=`(uname -a | grep aarch64) 1>/dev/null 2>&1 && echo 1`
|
||||||
. /etc/os-release
|
|
||||||
if [ "$VERSION_ID" = "7" ]; then
|
|
||||||
DISTNAME=centos
|
|
||||||
DISTVER=7
|
|
||||||
elif [ "$VERSION_ID" = "8" ]; then
|
|
||||||
DISTNAME=centos
|
|
||||||
DISTVER=8
|
|
||||||
else
|
|
||||||
resetDistVer
|
|
||||||
fi
|
|
||||||
elif [ -f /etc/fedora-release ]; then
|
|
||||||
. /etc/os-release
|
|
||||||
if [ "$VERSION_ID" != "31" ] && [ "$VERSION_ID" != "30" ] && [ "$VERSION_ID" != "29" ] && [ "$VERSION_ID" != "28" ]; then
|
|
||||||
resetDistVer
|
|
||||||
else
|
|
||||||
DISTNAME=fedora
|
|
||||||
DISTVER=$VERSION_ID
|
|
||||||
fi
|
|
||||||
elif [ -f /etc/solus-release ]; then
|
|
||||||
DISTNAME=solus
|
|
||||||
elif [ -f /etc/lsb-release ]; then
|
|
||||||
. /etc/lsb-release
|
|
||||||
DISTNAME=$(echo ${DISTRIB_ID} | awk '{print tolower($0)}')
|
|
||||||
DISTVER=${DISTRIB_RELEASE}
|
|
||||||
if [ "$DISTNAME" != "ubuntu" ]; then
|
|
||||||
if [ "$DISTNAME" = "linuxmint" ]; then
|
|
||||||
if [ "$DISTVER" = "19" ] || [ "$DISTVER" = "19.1" ] || [ "$DISTVER" = "19.2" ]; then
|
|
||||||
DISTNAME=ubuntu
|
|
||||||
DISTVER=18.04
|
|
||||||
else
|
|
||||||
resetDistVer
|
|
||||||
fi
|
|
||||||
elif [ "$DISTNAME" = "elementary" ]; then
|
|
||||||
if [ "$DISTVER" = "5.0" ]; then
|
|
||||||
DISTNAME=ubuntu
|
|
||||||
DISTVER=18.04
|
|
||||||
else
|
|
||||||
resetDistVer
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
resetDistVer
|
|
||||||
fi
|
|
||||||
elif [ "$DISTVER" != "18.04" ] && [ "$DISTVER" != "18.10" ] && [ "$DISTVER" != "19.04" ] && [ "$DISTVER" != "19.10" ]; then
|
|
||||||
resetDistVer
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$DISTNAME" = "unknown" ] && [ -f /etc/debian_version ]; then
|
if [ -f /etc/solus-release ]; then
|
||||||
|
DISTNAME=solus
|
||||||
|
elif [ "$IS_ARM" = "1" ] && [ -f /etc/debian_version ]; then
|
||||||
DISTNAME=debian
|
DISTNAME=debian
|
||||||
DISTVER=$(head -1 /etc/debian_version|awk -F. '{print $1}')
|
DISTVER=$(head -1 /etc/debian_version|awk -F. '{print $1}')
|
||||||
if [ "$DISTVER" != "9" ] && [ "$DISTVER" != "10" ]; then
|
if [ "$DISTVER" != "9" ] && [ "$DISTVER" != "10" ]; then
|
||||||
resetDistVer
|
if [ $(grep sid /etc/debian_version) ]; then
|
||||||
fi
|
DISTVER=10
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$DISTNAME" = "unknown" ]; then
|
|
||||||
if [ -f /etc/os-release ]; then
|
|
||||||
. /etc/os-release
|
|
||||||
if [ "$ID" = "arch" ]; then
|
|
||||||
DISTNAME=arch
|
|
||||||
elif [ "$ID" = "antergos" ] || [ "$ID" = "manjaro" ]; then
|
|
||||||
DISTNAME=ubuntu
|
|
||||||
DISTVER=18.10
|
|
||||||
elif [ "$ID" = "opensuse-leap" ]; then
|
|
||||||
if [ "$VERSION_ID" = "15.0" ]; then
|
|
||||||
DISTNAME=opensuse
|
|
||||||
DISTVER=15
|
|
||||||
elif [ "$VERSION_ID" = "15.1" ]; then
|
|
||||||
DISTNAME=opensuse
|
|
||||||
DISTVER=15.1
|
|
||||||
else
|
|
||||||
resetDistVer
|
|
||||||
fi
|
|
||||||
elif [ "$ID" = "opensuse-tumbleweed" ]; then
|
|
||||||
DISTNAME=tumbleweed
|
|
||||||
DISTVER=
|
|
||||||
else
|
else
|
||||||
resetDistVer
|
resetDistVer
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
resetDistVer
|
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
DISTNAME=centos7
|
||||||
|
DISTVER=
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ${DISTNAME}${DISTVER}
|
echo ${DISTNAME}${DISTVER}
|
||||||
|
|||||||
@@ -33,8 +33,10 @@ const DependencyIPC = require('../src/renderer/ipc/DependencyIPC');
|
|||||||
const DownloadIPC = require('../src/renderer/ipc/DownloadIPC');
|
const DownloadIPC = require('../src/renderer/ipc/DownloadIPC');
|
||||||
const FilesystemIPC = require('../src/renderer/ipc/FilesystemIPC');
|
const FilesystemIPC = require('../src/renderer/ipc/FilesystemIPC');
|
||||||
const MountsIPC = require('../src/renderer/ipc/MountsIPC');
|
const MountsIPC = require('../src/renderer/ipc/MountsIPC');
|
||||||
|
const PinnedIPC = require('../src/renderer/ipc/PinnedIPC');
|
||||||
const PlatformIPC = require('../src/renderer/ipc/PlatformIPC');
|
const PlatformIPC = require('../src/renderer/ipc/PlatformIPC');
|
||||||
const ReleaseIPC = require('../src/renderer/ipc/ReleaseIPC');
|
const ReleaseIPC = require('../src/renderer/ipc/ReleaseIPC');
|
||||||
|
const SkynetIPC = require('../src/renderer/ipc/SkynetIPC');
|
||||||
const StateIPC = require('../src/renderer/ipc/StateIPC');
|
const StateIPC = require('../src/renderer/ipc/StateIPC');
|
||||||
const SystemIPC = require('../src/renderer/ipc/SystemIPC');
|
const SystemIPC = require('../src/renderer/ipc/SystemIPC');
|
||||||
const UpgradeIPC = require('../src/renderer/ipc/UpgradeIPC');
|
const UpgradeIPC = require('../src/renderer/ipc/UpgradeIPC');
|
||||||
@@ -199,7 +201,7 @@ const createWindow = () => {
|
|||||||
autoLauncher
|
autoLauncher
|
||||||
.isEnabled()
|
.isEnabled()
|
||||||
.then((enabled) => {
|
.then((enabled) => {
|
||||||
trayContextMenu.items[1].checked = enabled;
|
trayContextMenu.items[2].checked = enabled;
|
||||||
mainWindowTray.setToolTip('Repertory UI');
|
mainWindowTray.setToolTip('Repertory UI');
|
||||||
mainWindowTray.setContextMenu(trayContextMenu)
|
mainWindowTray.setContextMenu(trayContextMenu)
|
||||||
})
|
})
|
||||||
@@ -308,16 +310,31 @@ if (!instanceLock) {
|
|||||||
configurePrimaryApp();
|
configurePrimaryApp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AppFunctions = {
|
||||||
|
closeApplication,
|
||||||
|
detectScript,
|
||||||
|
dialog,
|
||||||
|
getCleanupReleases: () => cleanupReleases,
|
||||||
|
getMainWindow,
|
||||||
|
saveUiSettings,
|
||||||
|
setIsInstalling,
|
||||||
|
setTrayImage,
|
||||||
|
setWindowVisibility,
|
||||||
|
standardIPCReply,
|
||||||
|
unmountAllDrives: MountsIPC.unmountAllDrives,
|
||||||
|
};
|
||||||
|
|
||||||
AppIPC.addListeners(ipcMain, closeApplication, setWindowVisibility);
|
AppIPC.addListeners(ipcMain, AppFunctions);
|
||||||
ConfigIPC.addListeners(ipcMain, standardIPCReply);
|
ConfigIPC.addListeners(ipcMain, AppFunctions);
|
||||||
DaemonIPC.addListeners(ipcMain, standardIPCReply);
|
DaemonIPC.addListeners(ipcMain, AppFunctions);
|
||||||
DependencyIPC.addListeners(ipcMain, standardIPCReply);
|
DependencyIPC.addListeners(ipcMain, AppFunctions);
|
||||||
DownloadIPC.addListeners(ipcMain, standardIPCReply);
|
DownloadIPC.addListeners(ipcMain, AppFunctions);
|
||||||
FilesystemIPC.addListeners(ipcMain, getMainWindow, dialog);
|
FilesystemIPC.addListeners(ipcMain, AppFunctions);
|
||||||
MountsIPC.addListeners(ipcMain, setTrayImage, standardIPCReply);
|
MountsIPC.addListeners(ipcMain, AppFunctions);
|
||||||
PlatformIPC.addListeners(ipcMain, detectScript, saveUiSettings);
|
PinnedIPC.addListeners(ipcMain, AppFunctions);
|
||||||
ReleaseIPC.addListeners(ipcMain, () => cleanupReleases, standardIPCReply);
|
PlatformIPC.addListeners(ipcMain, AppFunctions);
|
||||||
StateIPC.addListeners(ipcMain);
|
ReleaseIPC.addListeners(ipcMain, AppFunctions);
|
||||||
SystemIPC.addListeners(ipcMain, closeApplication);
|
SkynetIPC.addListeners(ipcMain, AppFunctions);
|
||||||
UpgradeIPC.addListeners(ipcMain, setIsInstalling, MountsIPC.unmountAllDrives, standardIPCReply);
|
StateIPC.addListeners(ipcMain, AppFunctions);
|
||||||
|
SystemIPC.addListeners(ipcMain, AppFunctions);
|
||||||
|
UpgradeIPC.addListeners(ipcMain, AppFunctions);
|
||||||
|
|||||||
261
releases.json
261
releases.json
@@ -1,259 +1,84 @@
|
|||||||
{
|
{
|
||||||
"Locations": {
|
"Locations": {
|
||||||
"arch": {
|
|
||||||
"1.1.4": {
|
|
||||||
"sha256": "85347471f33dd41a35eb296cda03590d451322cd54a077cef470ccbfe52a141b",
|
|
||||||
"sig": "CGialiJMT6nETdGgP3vQvsXSWQYUEX7j7Cck0NSiW0cE4A1kW3mabM2I/5Yt4NwkDqBIAXofPyUd1JQ4UrF8cijfLNv3ECSaDJs7bWrISDr3Z8ti0uZnN3RUdJDCYDvAWBVqGC82Q1fmLkYJhd33o2B9DzjmvO+i7+buNyDB3dBIY5Fa3rnLKsIY7WB5EASBG3TzDlsZOtLvNgKo/3fLJP2RFyczSVCFZeHlppJbyXCakj50eCNbxjP6SLaD3oE+M0xGvyPyKTk0OGoJTGKM13q30WKbM6cMfL87BbUueGkBFDZeNMWU8Mz/fdGG21WqNN1p7k3CilJJQz7ZEE9bBhlsIX5j5rvL2qNYJoQbJQbxVjyoWHOOlqA62WUTOZhyiHD3OWQ58Fd9JqGDiIhg+ChIBWzyEXNdE6GQr7/qEiAQDbEsU06WOzfj3uxAV//iy/noalpyhlnr0TUu5xKSnoR7jQhCtvOdlrmgs8y+mTEpwDjXCR0S7jDxp+cEbVHb57Rl8N5thVrOs5RQfshhcqwBR/scCM9iCr0v3D7uyGMinTBT3A8lwerN8iO17FhtEerovn4Zhg2p7quZRiUcYLdx4EOlIMWuORyDk3s0S4VZ27t92NYwMlwMA1TbUQ/XuN1oZaQQ9ipSDjNDDVZto3Q4vwlqL3g1TIs1JyxfHkwUTpuFjg3ZqY+uRNxeJTDlj9JHXiAIZ+VeBggB7EixKE+wMi1A6a+Si/ZpBbroK5gP1gODShXYUN4eGmodxqF2/gVrJcimEeHkyBZ74dZIa9gTSIOxeo1OS70fFU+hQy9/V0/q4PElPZn+EzLTGknWh1EDmqReZ1svv0tYf0Ve/l5szhdNGsb2LUEZ7G/r0Bs7fyQjA5YZI+byOPTSA1Q9vlT63sodpBRDURWkqTRFRPWlaEY2kMZu/vJ422PSjK51X4EPHWmpOkDkxFzx2WAs2rKZ9QXCkU0RGu0Ctial/zNVhm20eVklcuIirEnmUK9Kod0KBmjl+U6U6jHvlhOEC4zp2QcDsrLSQu7gDHvJWbYmaKBTiXrEvk52G/EN9aD86Am5k0bwPU5ktj8z38+5sxVns1R4e9J1WaZgD2dtFvpSxJbjVf09AZHIeyNw/BRu3GfJU6dX6KJVMCMtN+R5xv/ZckylI355R4nrf+7PLNsGg2tqlemvHiwdQkOb3/TOLrJpO94JRjm9k16huysztkpgJIGyKvHXT6z1A3cwCoJzrK7sQ1awedPvO+N8UGJ7kXHRgLLhQ2yWfZfIsD/s0Ji5GFrItm1nlqHAd/ZFh82jNKmvh6+n42l5TimH9Q0Cf+7bK5Y7SVYzhSAW2B8ivHsPMpAkLJ6d17ZMxtrr4/Q=",
|
|
||||||
"urls": [
|
|
||||||
"https://pixeldrain.com/api/file/KfWzWfxp",
|
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_linux_x86_64.AppImage"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"centos7": {
|
"centos7": {
|
||||||
"1.1.4": {
|
"1.3.2": {
|
||||||
"sha256": "85347471f33dd41a35eb296cda03590d451322cd54a077cef470ccbfe52a141b",
|
"sha256": "a8b9bff91d0f0685041737cfa40b4bc8ef765d24419104f3dd90f977023e7858",
|
||||||
"sig": "CGialiJMT6nETdGgP3vQvsXSWQYUEX7j7Cck0NSiW0cE4A1kW3mabM2I/5Yt4NwkDqBIAXofPyUd1JQ4UrF8cijfLNv3ECSaDJs7bWrISDr3Z8ti0uZnN3RUdJDCYDvAWBVqGC82Q1fmLkYJhd33o2B9DzjmvO+i7+buNyDB3dBIY5Fa3rnLKsIY7WB5EASBG3TzDlsZOtLvNgKo/3fLJP2RFyczSVCFZeHlppJbyXCakj50eCNbxjP6SLaD3oE+M0xGvyPyKTk0OGoJTGKM13q30WKbM6cMfL87BbUueGkBFDZeNMWU8Mz/fdGG21WqNN1p7k3CilJJQz7ZEE9bBhlsIX5j5rvL2qNYJoQbJQbxVjyoWHOOlqA62WUTOZhyiHD3OWQ58Fd9JqGDiIhg+ChIBWzyEXNdE6GQr7/qEiAQDbEsU06WOzfj3uxAV//iy/noalpyhlnr0TUu5xKSnoR7jQhCtvOdlrmgs8y+mTEpwDjXCR0S7jDxp+cEbVHb57Rl8N5thVrOs5RQfshhcqwBR/scCM9iCr0v3D7uyGMinTBT3A8lwerN8iO17FhtEerovn4Zhg2p7quZRiUcYLdx4EOlIMWuORyDk3s0S4VZ27t92NYwMlwMA1TbUQ/XuN1oZaQQ9ipSDjNDDVZto3Q4vwlqL3g1TIs1JyxfHkwUTpuFjg3ZqY+uRNxeJTDlj9JHXiAIZ+VeBggB7EixKE+wMi1A6a+Si/ZpBbroK5gP1gODShXYUN4eGmodxqF2/gVrJcimEeHkyBZ74dZIa9gTSIOxeo1OS70fFU+hQy9/V0/q4PElPZn+EzLTGknWh1EDmqReZ1svv0tYf0Ve/l5szhdNGsb2LUEZ7G/r0Bs7fyQjA5YZI+byOPTSA1Q9vlT63sodpBRDURWkqTRFRPWlaEY2kMZu/vJ422PSjK51X4EPHWmpOkDkxFzx2WAs2rKZ9QXCkU0RGu0Ctial/zNVhm20eVklcuIirEnmUK9Kod0KBmjl+U6U6jHvlhOEC4zp2QcDsrLSQu7gDHvJWbYmaKBTiXrEvk52G/EN9aD86Am5k0bwPU5ktj8z38+5sxVns1R4e9J1WaZgD2dtFvpSxJbjVf09AZHIeyNw/BRu3GfJU6dX6KJVMCMtN+R5xv/ZckylI355R4nrf+7PLNsGg2tqlemvHiwdQkOb3/TOLrJpO94JRjm9k16huysztkpgJIGyKvHXT6z1A3cwCoJzrK7sQ1awedPvO+N8UGJ7kXHRgLLhQ2yWfZfIsD/s0Ji5GFrItm1nlqHAd/ZFh82jNKmvh6+n42l5TimH9Q0Cf+7bK5Y7SVYzhSAW2B8ivHsPMpAkLJ6d17ZMxtrr4/Q=",
|
"sig": "CBEtKUDJwjPrchhNXvzulpfaBWFElDD+Kn9b14oF426IuKncsmqTWUesG3cT/beDk1onaDOhDIchyan6iW/BCdB+sVAuGAoRpm2lJ4lWba7ZPnXP7H10uIjVf1xASwIciP4jpAUPo0bO8hi9kqu1zkF9GeVHHb+SXlLhDP31wN7kHwgb/MeZ95/NqfucumYcwfFOZOnofSKaGQwHpbypy57YzyVCf/NzQDnYC46lcH9xVMmbgodT+y5MIIF0kkSJn0DbSfxLVMWTx1pnZUzJ7J827EKUgAS4d4uLI7ShskS+d84i8rNV9gXgqwYkqDvYbdFi7ArJZB7GJtyZ4VPTqRqGfxwF8rL3K0ml+635DfEXiHN8MbTuqwLHD2giChOfsdAAV4ngJ8xg7+Th8dqpgC92GXoOjNK7GSAyrOFsQ7xeqdVOBZMNk/dHVAb9eCTbPIsOjGFTAzOk8n3roM8naDUOq7PefUj1Jb2EGVhWnwS2ngvhNfRggZmmr3l9IElddaHro0JpnubsFmiAa+akV0P8VLb1jjpIJRfr2CIEnPTQbT4UQ1DdBitgkWiPbagTp8BQF1YGcVZ8jc9mbOxmF46z0MyuMQZjDHw2Vai0uPsoLIJHhy3I7nJqsnEw6gQX/l1VGj9wPHeaqMgGYGFykFfvVssh0CH45tUCdWL6Q9Hgx8+yLw0Lky/HIGMQc0qZUM9ute/9Buifd9cOK8+S5PaA0Zg0G/pIY6fThtO86wKJQnoPeiuBkJ9yXc20ZGrfb39Qnf2nZxrPyVl2iQJlven6CDBxc88henxzvxK61bXUynK8zHVuoIAC7ejWZEbPOqDV3DOOSVDz1+eq1MU2KZ4JmaLipzbdy/y+ph1TnCGwdL9R3s+xLYSaxA+ybhQVNXHhQ7+eZD6CWXytaIVYe8giL1ki8oN/18Bm1B2dVxCZ4KKbAToFpBOGvW+w8JFAC5nBK5aj2BGWEocyWQ1XIJmqVBd8RSOMYVYjQOhVnIvyJxOqvnrLUoRzJruj8R/riuCSMnfq17ykpjCzoNzIjvimCPyAib9kdWx7M8dyOS9Sls2sMLwJvDcsGi/FfuGqBmV2v28XagRZz70iypqNaIUrj4CShfz8e110su3BtLQHr1O6yffxy+whbB7w+ogZ6gz86AZ/63Zz6xbLIk4wuNx1UL/ZuRMGq4xOW/7zRpOYYSe/h98YFd9/UTcoi8Osjl+o1eVup6YWVeDvOG69uqwfID8XHivJnEV2NVFx8fbb6fHSrMg/QbjSngdyQ3b+5rWiZG01DGCDB5RFOvEKY24qrXXWQGAx+JXbj+/7xYWts+/Fv7hSqvpvf7H8aVCoOKXGtjJiy+K/9tAJJLQDAzo=",
|
||||||
"urls": [
|
"urls": [
|
||||||
"https://pixeldrain.com/api/file/KfWzWfxp",
|
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.2_linux_x86_64.AppImage"
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_linux_x86_64.AppImage"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"centos8": {
|
|
||||||
"1.1.4": {
|
|
||||||
"sha256": "85347471f33dd41a35eb296cda03590d451322cd54a077cef470ccbfe52a141b",
|
|
||||||
"sig": "CGialiJMT6nETdGgP3vQvsXSWQYUEX7j7Cck0NSiW0cE4A1kW3mabM2I/5Yt4NwkDqBIAXofPyUd1JQ4UrF8cijfLNv3ECSaDJs7bWrISDr3Z8ti0uZnN3RUdJDCYDvAWBVqGC82Q1fmLkYJhd33o2B9DzjmvO+i7+buNyDB3dBIY5Fa3rnLKsIY7WB5EASBG3TzDlsZOtLvNgKo/3fLJP2RFyczSVCFZeHlppJbyXCakj50eCNbxjP6SLaD3oE+M0xGvyPyKTk0OGoJTGKM13q30WKbM6cMfL87BbUueGkBFDZeNMWU8Mz/fdGG21WqNN1p7k3CilJJQz7ZEE9bBhlsIX5j5rvL2qNYJoQbJQbxVjyoWHOOlqA62WUTOZhyiHD3OWQ58Fd9JqGDiIhg+ChIBWzyEXNdE6GQr7/qEiAQDbEsU06WOzfj3uxAV//iy/noalpyhlnr0TUu5xKSnoR7jQhCtvOdlrmgs8y+mTEpwDjXCR0S7jDxp+cEbVHb57Rl8N5thVrOs5RQfshhcqwBR/scCM9iCr0v3D7uyGMinTBT3A8lwerN8iO17FhtEerovn4Zhg2p7quZRiUcYLdx4EOlIMWuORyDk3s0S4VZ27t92NYwMlwMA1TbUQ/XuN1oZaQQ9ipSDjNDDVZto3Q4vwlqL3g1TIs1JyxfHkwUTpuFjg3ZqY+uRNxeJTDlj9JHXiAIZ+VeBggB7EixKE+wMi1A6a+Si/ZpBbroK5gP1gODShXYUN4eGmodxqF2/gVrJcimEeHkyBZ74dZIa9gTSIOxeo1OS70fFU+hQy9/V0/q4PElPZn+EzLTGknWh1EDmqReZ1svv0tYf0Ve/l5szhdNGsb2LUEZ7G/r0Bs7fyQjA5YZI+byOPTSA1Q9vlT63sodpBRDURWkqTRFRPWlaEY2kMZu/vJ422PSjK51X4EPHWmpOkDkxFzx2WAs2rKZ9QXCkU0RGu0Ctial/zNVhm20eVklcuIirEnmUK9Kod0KBmjl+U6U6jHvlhOEC4zp2QcDsrLSQu7gDHvJWbYmaKBTiXrEvk52G/EN9aD86Am5k0bwPU5ktj8z38+5sxVns1R4e9J1WaZgD2dtFvpSxJbjVf09AZHIeyNw/BRu3GfJU6dX6KJVMCMtN+R5xv/ZckylI355R4nrf+7PLNsGg2tqlemvHiwdQkOb3/TOLrJpO94JRjm9k16huysztkpgJIGyKvHXT6z1A3cwCoJzrK7sQ1awedPvO+N8UGJ7kXHRgLLhQ2yWfZfIsD/s0Ji5GFrItm1nlqHAd/ZFh82jNKmvh6+n42l5TimH9Q0Cf+7bK5Y7SVYzhSAW2B8ivHsPMpAkLJ6d17ZMxtrr4/Q=",
|
|
||||||
"urls": [
|
|
||||||
"https://pixeldrain.com/api/file/KfWzWfxp",
|
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_linux_x86_64.AppImage"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"darwin": {
|
"darwin": {
|
||||||
"1.1.4": {
|
"1.3.2": {
|
||||||
"sha256": "8c91046a83b689564355be3e0a3e194ab986c4633f112696e33e4bb7ebd7e46e",
|
"sha256": "d8e5749a43541edaeaa91cbc81c42fb21c8e4c8446c9c1dff0a8e3a0efc23270",
|
||||||
"sig": "BBds0xSaIqr2rns+cSr90bmxtfy2aIGNVcKgRfMYYqDntV5SkWxD8ivqPglFiLQA/jfgd5A8DjMJs4FA6FDvF1ZFcfgZLFw94OT1M3jPJ7cf5Izv1EQb+5AV7SK8H7DACDixcgKDDXO0WARmeqNXJZzyxkny8XKIiGDwLbmrXfFVuKPSLucbf6eaTem+xJHjQPzP9FH4Lwf9kbQxis2/PIT63yflQdM9CAAvfZUB4YUCOF5T8I43uNV2YDR0Z+k5FLTBexJDORDRixbrldWqNo7NQlNMR+26LY2IBppQqOMtDw9cpcfPj8bNgkWsZkFk/eOcrcpc8ENQodGxb01JahKJ20g9soJEAOhiFW3TOxzOLNq8cQFdKYgJv2K68lav/QzVPD6n14Bsr3+5mkX4fE1GmmN1HLgFO+JbD25qDrS4ExKR5TJ2Zdu136n/Mxbj2apYDhWtU8X6OD86F29m348XDonC9Fn+vzoE2M4xNKptMhukem7NFG7Z03v6+J73PaVM1NldARMGgVUYFA6QTn6Ns55YEXnsHoSoreHmgl5y3s8eRo0/oehv0cpPG6shCz71+YlVG/IgbKWIgYZ0jj03Cdsgv/XyadiwfCI9Q7uvl368Vlbuad4mqttMTZwHeZlKikTYb74QDyXqVoz0Q2ij7WET7MkXpA3++hDrPIN5Cb8qi/YuMp63w6TLfz4c/ZCQeje+0d7x6p63Z7TObEXDyBgdUAphX3T/u4pkEjXQKsfNRh8jaFOXU3z+hG8+IXjrZtLcDEzqICZ8JJCrkklgliTM1ECiekvJ9jwXTN2ClrzLQ3qhX8N+8jkvQ+yZxGxH+3rOX55RyW4OcMYUYvDpTtNHncVvABBlRvPGEGxtA7RMDTzOGe0lk70y07al6iFKDktaoYSFlcH+pUw7ifDZamefxlKDmtrMOMNmnrm+v8WH0g0MG8qy/nGPxv5dFIl9gAC/rvRElxX8FpA7y18i7fQ0IfhpaC58gZZADkF0nFOW15N7zwjS3qnhAGCBCBEDwlFG9brD71qjShtodgnz+GvrDvtqGTwNRllnZXSHPCWe33BOHy2c30LwE8vJq+ChVaJobCA9P8ipgZv/gAuZz7LNFc/Uong5TyKZk2uXun3XF1Qkw+ogBpl9aqMWIySZhkDnBcZjjE9pL/FQAkO1H90+zNnSdSAKZQaPckxLSyqHXxb4P7Da4nj3tad609NcxEzsz3dpEJTuYlqLqmO5kJmy29jNUHhQQdPCuKJtdm/coz3kWtC+uR6/SMnhviGnc7tQUqyb6HfGywKbmoAM93NHSGxNGyNMU+VJ20/YK1lmVFo3Pg/wq+aX35utcjQafpATqHeOeDw26fnZxBs=",
|
"sig": "AKXLbLDnkBlB2b8dKLPZ5Vr9bcbv1dCvYGJTCltxYRJkOBzmQMTJ+ADKAtQQCfZKtNji+Dez28A401BMUY7xBd3Sh4FDnmNv64Q2zfqxQpOkhdrK8KcwK2aFCFbWn3vTnU3GBk2IXqGY8qIeR4d/v2UaBnnpK0EulztxPXojLz0pA6DVndJOodItoE6OUNohPd5MTWh5ewpjXJN+VKeao3ABkXgCzYLH/SSYCyi8ZFH8Ija20HJk8ST2QIokmRQGk5MDcyxylyWkusGOf7yn9M6vdtHNfrHfWXGxnMTuaw9+YNTuxZNDgIFpmoVx4t7HSoNti+ZZwyo+1jtDeh0xPmdEGpnZOY7zp94zlh4zP9Cx5cYg6W5/NQKQzDtlUZlELqR8Kwoa/bDCwWeSkifGqEJT2Yezs9r5llSoIh8PrxLkmdaX2vkOvaRYYE0kvdO2MllT8SSyYkum/9eD8uA52IYbUliJqfAf43gOj9n0ooRcCo45lBY5PIUB44XBLEGK15OuarybSyaBDMFbc3HWh1A9jB9kSPctnMMJMNMsocTI5AEN8eRbLyF7z01WE+nB7JDS8NW3+QRFyQInxdXpcGeKO6riuSO7aXHLWAZvUVSxThSuV7JtsugtUnIsP9ah7njtcVHOSEcUG3U2WxZRbe6PG5pdjS4Px+E9Yx35zLSwo39TcwLb2fM7mQKREsH0fUrRd4WN1T0pWOuzDlWSq4pfDXWdO8y828l8XVJzw5LUH9U0F7qAiuzEVQIYJ+xjjAp4JVJXBof4iWeW4N+7PYgntEgr94Ti6rjb6BrKWdl4B+9j79EkC2yLWafcGnryUaSfOFDFiB8Upf6NQ+a1TxY5ufFe1JfuI58rchUZi4SjNdyFMat4GSdTI6I513ZVcohBb1KVIxEM0u38hJqKIFx3stWMZrLvyFH9ceqzXzVQCIDE31usUKFsXallWMQyB2kIy7qoif7zmDhdJQZboD7ZHsTrcSK1u9D+h3oG1poN+AULmhgYZNT11ktRiVUbmzDS0qA7lnF8dcsuthj0vHP0/BFN6a7ljQuwDVY1xoeCf+RobfNWucK2MLxmqV1z9nO4jpdy/GfC/5ln4Tev+5luo5ux0BXXXAWuzGyQ0QK+13k3lIUwxsDNou0dMDHJPaMavBjmlm0Uf5esZdSIU9U2sdfuO+j/6enwGvESlrKmBCsdPatHREP931dGPZCsF1m30OylV+m7WhBh9w6AbklmjHNCZu3C2Ln23gOKGX8HpQ9nnaPCicmlfSyBjPoKVtDCACVbjwRfTJ+UXCocrCVSbAhskOSvlq050QFQcZO5DzFWdeTfG6x6MrqdSelYThjy5xn8AXuqsFSLIdYpCAQ=",
|
||||||
"urls": [
|
"urls": [
|
||||||
"https://pixeldrain.com/api/file/68WJfKsz",
|
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.2_mac.dmg"
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_mac.dmg"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"debian9": {
|
|
||||||
"1.1.4": {
|
|
||||||
"sha256": "85347471f33dd41a35eb296cda03590d451322cd54a077cef470ccbfe52a141b",
|
|
||||||
"sig": "CGialiJMT6nETdGgP3vQvsXSWQYUEX7j7Cck0NSiW0cE4A1kW3mabM2I/5Yt4NwkDqBIAXofPyUd1JQ4UrF8cijfLNv3ECSaDJs7bWrISDr3Z8ti0uZnN3RUdJDCYDvAWBVqGC82Q1fmLkYJhd33o2B9DzjmvO+i7+buNyDB3dBIY5Fa3rnLKsIY7WB5EASBG3TzDlsZOtLvNgKo/3fLJP2RFyczSVCFZeHlppJbyXCakj50eCNbxjP6SLaD3oE+M0xGvyPyKTk0OGoJTGKM13q30WKbM6cMfL87BbUueGkBFDZeNMWU8Mz/fdGG21WqNN1p7k3CilJJQz7ZEE9bBhlsIX5j5rvL2qNYJoQbJQbxVjyoWHOOlqA62WUTOZhyiHD3OWQ58Fd9JqGDiIhg+ChIBWzyEXNdE6GQr7/qEiAQDbEsU06WOzfj3uxAV//iy/noalpyhlnr0TUu5xKSnoR7jQhCtvOdlrmgs8y+mTEpwDjXCR0S7jDxp+cEbVHb57Rl8N5thVrOs5RQfshhcqwBR/scCM9iCr0v3D7uyGMinTBT3A8lwerN8iO17FhtEerovn4Zhg2p7quZRiUcYLdx4EOlIMWuORyDk3s0S4VZ27t92NYwMlwMA1TbUQ/XuN1oZaQQ9ipSDjNDDVZto3Q4vwlqL3g1TIs1JyxfHkwUTpuFjg3ZqY+uRNxeJTDlj9JHXiAIZ+VeBggB7EixKE+wMi1A6a+Si/ZpBbroK5gP1gODShXYUN4eGmodxqF2/gVrJcimEeHkyBZ74dZIa9gTSIOxeo1OS70fFU+hQy9/V0/q4PElPZn+EzLTGknWh1EDmqReZ1svv0tYf0Ve/l5szhdNGsb2LUEZ7G/r0Bs7fyQjA5YZI+byOPTSA1Q9vlT63sodpBRDURWkqTRFRPWlaEY2kMZu/vJ422PSjK51X4EPHWmpOkDkxFzx2WAs2rKZ9QXCkU0RGu0Ctial/zNVhm20eVklcuIirEnmUK9Kod0KBmjl+U6U6jHvlhOEC4zp2QcDsrLSQu7gDHvJWbYmaKBTiXrEvk52G/EN9aD86Am5k0bwPU5ktj8z38+5sxVns1R4e9J1WaZgD2dtFvpSxJbjVf09AZHIeyNw/BRu3GfJU6dX6KJVMCMtN+R5xv/ZckylI355R4nrf+7PLNsGg2tqlemvHiwdQkOb3/TOLrJpO94JRjm9k16huysztkpgJIGyKvHXT6z1A3cwCoJzrK7sQ1awedPvO+N8UGJ7kXHRgLLhQ2yWfZfIsD/s0Ji5GFrItm1nlqHAd/ZFh82jNKmvh6+n42l5TimH9Q0Cf+7bK5Y7SVYzhSAW2B8ivHsPMpAkLJ6d17ZMxtrr4/Q=",
|
|
||||||
"urls": [
|
|
||||||
"https://pixeldrain.com/api/file/KfWzWfxp",
|
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_linux_x86_64.AppImage"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"debian10": {
|
|
||||||
"1.1.4": {
|
|
||||||
"sha256": "85347471f33dd41a35eb296cda03590d451322cd54a077cef470ccbfe52a141b",
|
|
||||||
"sig": "CGialiJMT6nETdGgP3vQvsXSWQYUEX7j7Cck0NSiW0cE4A1kW3mabM2I/5Yt4NwkDqBIAXofPyUd1JQ4UrF8cijfLNv3ECSaDJs7bWrISDr3Z8ti0uZnN3RUdJDCYDvAWBVqGC82Q1fmLkYJhd33o2B9DzjmvO+i7+buNyDB3dBIY5Fa3rnLKsIY7WB5EASBG3TzDlsZOtLvNgKo/3fLJP2RFyczSVCFZeHlppJbyXCakj50eCNbxjP6SLaD3oE+M0xGvyPyKTk0OGoJTGKM13q30WKbM6cMfL87BbUueGkBFDZeNMWU8Mz/fdGG21WqNN1p7k3CilJJQz7ZEE9bBhlsIX5j5rvL2qNYJoQbJQbxVjyoWHOOlqA62WUTOZhyiHD3OWQ58Fd9JqGDiIhg+ChIBWzyEXNdE6GQr7/qEiAQDbEsU06WOzfj3uxAV//iy/noalpyhlnr0TUu5xKSnoR7jQhCtvOdlrmgs8y+mTEpwDjXCR0S7jDxp+cEbVHb57Rl8N5thVrOs5RQfshhcqwBR/scCM9iCr0v3D7uyGMinTBT3A8lwerN8iO17FhtEerovn4Zhg2p7quZRiUcYLdx4EOlIMWuORyDk3s0S4VZ27t92NYwMlwMA1TbUQ/XuN1oZaQQ9ipSDjNDDVZto3Q4vwlqL3g1TIs1JyxfHkwUTpuFjg3ZqY+uRNxeJTDlj9JHXiAIZ+VeBggB7EixKE+wMi1A6a+Si/ZpBbroK5gP1gODShXYUN4eGmodxqF2/gVrJcimEeHkyBZ74dZIa9gTSIOxeo1OS70fFU+hQy9/V0/q4PElPZn+EzLTGknWh1EDmqReZ1svv0tYf0Ve/l5szhdNGsb2LUEZ7G/r0Bs7fyQjA5YZI+byOPTSA1Q9vlT63sodpBRDURWkqTRFRPWlaEY2kMZu/vJ422PSjK51X4EPHWmpOkDkxFzx2WAs2rKZ9QXCkU0RGu0Ctial/zNVhm20eVklcuIirEnmUK9Kod0KBmjl+U6U6jHvlhOEC4zp2QcDsrLSQu7gDHvJWbYmaKBTiXrEvk52G/EN9aD86Am5k0bwPU5ktj8z38+5sxVns1R4e9J1WaZgD2dtFvpSxJbjVf09AZHIeyNw/BRu3GfJU6dX6KJVMCMtN+R5xv/ZckylI355R4nrf+7PLNsGg2tqlemvHiwdQkOb3/TOLrJpO94JRjm9k16huysztkpgJIGyKvHXT6z1A3cwCoJzrK7sQ1awedPvO+N8UGJ7kXHRgLLhQ2yWfZfIsD/s0Ji5GFrItm1nlqHAd/ZFh82jNKmvh6+n42l5TimH9Q0Cf+7bK5Y7SVYzhSAW2B8ivHsPMpAkLJ6d17ZMxtrr4/Q=",
|
|
||||||
"urls": [
|
|
||||||
"https://pixeldrain.com/api/file/KfWzWfxp",
|
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_linux_x86_64.AppImage"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"fedora28": {
|
|
||||||
"1.1.4": {
|
|
||||||
"sha256": "85347471f33dd41a35eb296cda03590d451322cd54a077cef470ccbfe52a141b",
|
|
||||||
"sig": "CGialiJMT6nETdGgP3vQvsXSWQYUEX7j7Cck0NSiW0cE4A1kW3mabM2I/5Yt4NwkDqBIAXofPyUd1JQ4UrF8cijfLNv3ECSaDJs7bWrISDr3Z8ti0uZnN3RUdJDCYDvAWBVqGC82Q1fmLkYJhd33o2B9DzjmvO+i7+buNyDB3dBIY5Fa3rnLKsIY7WB5EASBG3TzDlsZOtLvNgKo/3fLJP2RFyczSVCFZeHlppJbyXCakj50eCNbxjP6SLaD3oE+M0xGvyPyKTk0OGoJTGKM13q30WKbM6cMfL87BbUueGkBFDZeNMWU8Mz/fdGG21WqNN1p7k3CilJJQz7ZEE9bBhlsIX5j5rvL2qNYJoQbJQbxVjyoWHOOlqA62WUTOZhyiHD3OWQ58Fd9JqGDiIhg+ChIBWzyEXNdE6GQr7/qEiAQDbEsU06WOzfj3uxAV//iy/noalpyhlnr0TUu5xKSnoR7jQhCtvOdlrmgs8y+mTEpwDjXCR0S7jDxp+cEbVHb57Rl8N5thVrOs5RQfshhcqwBR/scCM9iCr0v3D7uyGMinTBT3A8lwerN8iO17FhtEerovn4Zhg2p7quZRiUcYLdx4EOlIMWuORyDk3s0S4VZ27t92NYwMlwMA1TbUQ/XuN1oZaQQ9ipSDjNDDVZto3Q4vwlqL3g1TIs1JyxfHkwUTpuFjg3ZqY+uRNxeJTDlj9JHXiAIZ+VeBggB7EixKE+wMi1A6a+Si/ZpBbroK5gP1gODShXYUN4eGmodxqF2/gVrJcimEeHkyBZ74dZIa9gTSIOxeo1OS70fFU+hQy9/V0/q4PElPZn+EzLTGknWh1EDmqReZ1svv0tYf0Ve/l5szhdNGsb2LUEZ7G/r0Bs7fyQjA5YZI+byOPTSA1Q9vlT63sodpBRDURWkqTRFRPWlaEY2kMZu/vJ422PSjK51X4EPHWmpOkDkxFzx2WAs2rKZ9QXCkU0RGu0Ctial/zNVhm20eVklcuIirEnmUK9Kod0KBmjl+U6U6jHvlhOEC4zp2QcDsrLSQu7gDHvJWbYmaKBTiXrEvk52G/EN9aD86Am5k0bwPU5ktj8z38+5sxVns1R4e9J1WaZgD2dtFvpSxJbjVf09AZHIeyNw/BRu3GfJU6dX6KJVMCMtN+R5xv/ZckylI355R4nrf+7PLNsGg2tqlemvHiwdQkOb3/TOLrJpO94JRjm9k16huysztkpgJIGyKvHXT6z1A3cwCoJzrK7sQ1awedPvO+N8UGJ7kXHRgLLhQ2yWfZfIsD/s0Ji5GFrItm1nlqHAd/ZFh82jNKmvh6+n42l5TimH9Q0Cf+7bK5Y7SVYzhSAW2B8ivHsPMpAkLJ6d17ZMxtrr4/Q=",
|
|
||||||
"urls": [
|
|
||||||
"https://pixeldrain.com/api/file/KfWzWfxp",
|
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_linux_x86_64.AppImage"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"fedora29": {
|
|
||||||
"1.1.4": {
|
|
||||||
"sha256": "85347471f33dd41a35eb296cda03590d451322cd54a077cef470ccbfe52a141b",
|
|
||||||
"sig": "CGialiJMT6nETdGgP3vQvsXSWQYUEX7j7Cck0NSiW0cE4A1kW3mabM2I/5Yt4NwkDqBIAXofPyUd1JQ4UrF8cijfLNv3ECSaDJs7bWrISDr3Z8ti0uZnN3RUdJDCYDvAWBVqGC82Q1fmLkYJhd33o2B9DzjmvO+i7+buNyDB3dBIY5Fa3rnLKsIY7WB5EASBG3TzDlsZOtLvNgKo/3fLJP2RFyczSVCFZeHlppJbyXCakj50eCNbxjP6SLaD3oE+M0xGvyPyKTk0OGoJTGKM13q30WKbM6cMfL87BbUueGkBFDZeNMWU8Mz/fdGG21WqNN1p7k3CilJJQz7ZEE9bBhlsIX5j5rvL2qNYJoQbJQbxVjyoWHOOlqA62WUTOZhyiHD3OWQ58Fd9JqGDiIhg+ChIBWzyEXNdE6GQr7/qEiAQDbEsU06WOzfj3uxAV//iy/noalpyhlnr0TUu5xKSnoR7jQhCtvOdlrmgs8y+mTEpwDjXCR0S7jDxp+cEbVHb57Rl8N5thVrOs5RQfshhcqwBR/scCM9iCr0v3D7uyGMinTBT3A8lwerN8iO17FhtEerovn4Zhg2p7quZRiUcYLdx4EOlIMWuORyDk3s0S4VZ27t92NYwMlwMA1TbUQ/XuN1oZaQQ9ipSDjNDDVZto3Q4vwlqL3g1TIs1JyxfHkwUTpuFjg3ZqY+uRNxeJTDlj9JHXiAIZ+VeBggB7EixKE+wMi1A6a+Si/ZpBbroK5gP1gODShXYUN4eGmodxqF2/gVrJcimEeHkyBZ74dZIa9gTSIOxeo1OS70fFU+hQy9/V0/q4PElPZn+EzLTGknWh1EDmqReZ1svv0tYf0Ve/l5szhdNGsb2LUEZ7G/r0Bs7fyQjA5YZI+byOPTSA1Q9vlT63sodpBRDURWkqTRFRPWlaEY2kMZu/vJ422PSjK51X4EPHWmpOkDkxFzx2WAs2rKZ9QXCkU0RGu0Ctial/zNVhm20eVklcuIirEnmUK9Kod0KBmjl+U6U6jHvlhOEC4zp2QcDsrLSQu7gDHvJWbYmaKBTiXrEvk52G/EN9aD86Am5k0bwPU5ktj8z38+5sxVns1R4e9J1WaZgD2dtFvpSxJbjVf09AZHIeyNw/BRu3GfJU6dX6KJVMCMtN+R5xv/ZckylI355R4nrf+7PLNsGg2tqlemvHiwdQkOb3/TOLrJpO94JRjm9k16huysztkpgJIGyKvHXT6z1A3cwCoJzrK7sQ1awedPvO+N8UGJ7kXHRgLLhQ2yWfZfIsD/s0Ji5GFrItm1nlqHAd/ZFh82jNKmvh6+n42l5TimH9Q0Cf+7bK5Y7SVYzhSAW2B8ivHsPMpAkLJ6d17ZMxtrr4/Q=",
|
|
||||||
"urls": [
|
|
||||||
"https://pixeldrain.com/api/file/KfWzWfxp",
|
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_linux_x86_64.AppImage"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"fedora30": {
|
|
||||||
"1.1.4": {
|
|
||||||
"sha256": "85347471f33dd41a35eb296cda03590d451322cd54a077cef470ccbfe52a141b",
|
|
||||||
"sig": "CGialiJMT6nETdGgP3vQvsXSWQYUEX7j7Cck0NSiW0cE4A1kW3mabM2I/5Yt4NwkDqBIAXofPyUd1JQ4UrF8cijfLNv3ECSaDJs7bWrISDr3Z8ti0uZnN3RUdJDCYDvAWBVqGC82Q1fmLkYJhd33o2B9DzjmvO+i7+buNyDB3dBIY5Fa3rnLKsIY7WB5EASBG3TzDlsZOtLvNgKo/3fLJP2RFyczSVCFZeHlppJbyXCakj50eCNbxjP6SLaD3oE+M0xGvyPyKTk0OGoJTGKM13q30WKbM6cMfL87BbUueGkBFDZeNMWU8Mz/fdGG21WqNN1p7k3CilJJQz7ZEE9bBhlsIX5j5rvL2qNYJoQbJQbxVjyoWHOOlqA62WUTOZhyiHD3OWQ58Fd9JqGDiIhg+ChIBWzyEXNdE6GQr7/qEiAQDbEsU06WOzfj3uxAV//iy/noalpyhlnr0TUu5xKSnoR7jQhCtvOdlrmgs8y+mTEpwDjXCR0S7jDxp+cEbVHb57Rl8N5thVrOs5RQfshhcqwBR/scCM9iCr0v3D7uyGMinTBT3A8lwerN8iO17FhtEerovn4Zhg2p7quZRiUcYLdx4EOlIMWuORyDk3s0S4VZ27t92NYwMlwMA1TbUQ/XuN1oZaQQ9ipSDjNDDVZto3Q4vwlqL3g1TIs1JyxfHkwUTpuFjg3ZqY+uRNxeJTDlj9JHXiAIZ+VeBggB7EixKE+wMi1A6a+Si/ZpBbroK5gP1gODShXYUN4eGmodxqF2/gVrJcimEeHkyBZ74dZIa9gTSIOxeo1OS70fFU+hQy9/V0/q4PElPZn+EzLTGknWh1EDmqReZ1svv0tYf0Ve/l5szhdNGsb2LUEZ7G/r0Bs7fyQjA5YZI+byOPTSA1Q9vlT63sodpBRDURWkqTRFRPWlaEY2kMZu/vJ422PSjK51X4EPHWmpOkDkxFzx2WAs2rKZ9QXCkU0RGu0Ctial/zNVhm20eVklcuIirEnmUK9Kod0KBmjl+U6U6jHvlhOEC4zp2QcDsrLSQu7gDHvJWbYmaKBTiXrEvk52G/EN9aD86Am5k0bwPU5ktj8z38+5sxVns1R4e9J1WaZgD2dtFvpSxJbjVf09AZHIeyNw/BRu3GfJU6dX6KJVMCMtN+R5xv/ZckylI355R4nrf+7PLNsGg2tqlemvHiwdQkOb3/TOLrJpO94JRjm9k16huysztkpgJIGyKvHXT6z1A3cwCoJzrK7sQ1awedPvO+N8UGJ7kXHRgLLhQ2yWfZfIsD/s0Ji5GFrItm1nlqHAd/ZFh82jNKmvh6+n42l5TimH9Q0Cf+7bK5Y7SVYzhSAW2B8ivHsPMpAkLJ6d17ZMxtrr4/Q=",
|
|
||||||
"urls": [
|
|
||||||
"https://pixeldrain.com/api/file/KfWzWfxp",
|
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_linux_x86_64.AppImage"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"fedora31": {
|
|
||||||
"1.1.4": {
|
|
||||||
"sha256": "85347471f33dd41a35eb296cda03590d451322cd54a077cef470ccbfe52a141b",
|
|
||||||
"sig": "CGialiJMT6nETdGgP3vQvsXSWQYUEX7j7Cck0NSiW0cE4A1kW3mabM2I/5Yt4NwkDqBIAXofPyUd1JQ4UrF8cijfLNv3ECSaDJs7bWrISDr3Z8ti0uZnN3RUdJDCYDvAWBVqGC82Q1fmLkYJhd33o2B9DzjmvO+i7+buNyDB3dBIY5Fa3rnLKsIY7WB5EASBG3TzDlsZOtLvNgKo/3fLJP2RFyczSVCFZeHlppJbyXCakj50eCNbxjP6SLaD3oE+M0xGvyPyKTk0OGoJTGKM13q30WKbM6cMfL87BbUueGkBFDZeNMWU8Mz/fdGG21WqNN1p7k3CilJJQz7ZEE9bBhlsIX5j5rvL2qNYJoQbJQbxVjyoWHOOlqA62WUTOZhyiHD3OWQ58Fd9JqGDiIhg+ChIBWzyEXNdE6GQr7/qEiAQDbEsU06WOzfj3uxAV//iy/noalpyhlnr0TUu5xKSnoR7jQhCtvOdlrmgs8y+mTEpwDjXCR0S7jDxp+cEbVHb57Rl8N5thVrOs5RQfshhcqwBR/scCM9iCr0v3D7uyGMinTBT3A8lwerN8iO17FhtEerovn4Zhg2p7quZRiUcYLdx4EOlIMWuORyDk3s0S4VZ27t92NYwMlwMA1TbUQ/XuN1oZaQQ9ipSDjNDDVZto3Q4vwlqL3g1TIs1JyxfHkwUTpuFjg3ZqY+uRNxeJTDlj9JHXiAIZ+VeBggB7EixKE+wMi1A6a+Si/ZpBbroK5gP1gODShXYUN4eGmodxqF2/gVrJcimEeHkyBZ74dZIa9gTSIOxeo1OS70fFU+hQy9/V0/q4PElPZn+EzLTGknWh1EDmqReZ1svv0tYf0Ve/l5szhdNGsb2LUEZ7G/r0Bs7fyQjA5YZI+byOPTSA1Q9vlT63sodpBRDURWkqTRFRPWlaEY2kMZu/vJ422PSjK51X4EPHWmpOkDkxFzx2WAs2rKZ9QXCkU0RGu0Ctial/zNVhm20eVklcuIirEnmUK9Kod0KBmjl+U6U6jHvlhOEC4zp2QcDsrLSQu7gDHvJWbYmaKBTiXrEvk52G/EN9aD86Am5k0bwPU5ktj8z38+5sxVns1R4e9J1WaZgD2dtFvpSxJbjVf09AZHIeyNw/BRu3GfJU6dX6KJVMCMtN+R5xv/ZckylI355R4nrf+7PLNsGg2tqlemvHiwdQkOb3/TOLrJpO94JRjm9k16huysztkpgJIGyKvHXT6z1A3cwCoJzrK7sQ1awedPvO+N8UGJ7kXHRgLLhQ2yWfZfIsD/s0Ji5GFrItm1nlqHAd/ZFh82jNKmvh6+n42l5TimH9Q0Cf+7bK5Y7SVYzhSAW2B8ivHsPMpAkLJ6d17ZMxtrr4/Q=",
|
|
||||||
"urls": [
|
|
||||||
"https://pixeldrain.com/api/file/KfWzWfxp",
|
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_linux_x86_64.AppImage"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"opensuse15": {
|
|
||||||
"1.1.4": {
|
|
||||||
"sha256": "85347471f33dd41a35eb296cda03590d451322cd54a077cef470ccbfe52a141b",
|
|
||||||
"sig": "CGialiJMT6nETdGgP3vQvsXSWQYUEX7j7Cck0NSiW0cE4A1kW3mabM2I/5Yt4NwkDqBIAXofPyUd1JQ4UrF8cijfLNv3ECSaDJs7bWrISDr3Z8ti0uZnN3RUdJDCYDvAWBVqGC82Q1fmLkYJhd33o2B9DzjmvO+i7+buNyDB3dBIY5Fa3rnLKsIY7WB5EASBG3TzDlsZOtLvNgKo/3fLJP2RFyczSVCFZeHlppJbyXCakj50eCNbxjP6SLaD3oE+M0xGvyPyKTk0OGoJTGKM13q30WKbM6cMfL87BbUueGkBFDZeNMWU8Mz/fdGG21WqNN1p7k3CilJJQz7ZEE9bBhlsIX5j5rvL2qNYJoQbJQbxVjyoWHOOlqA62WUTOZhyiHD3OWQ58Fd9JqGDiIhg+ChIBWzyEXNdE6GQr7/qEiAQDbEsU06WOzfj3uxAV//iy/noalpyhlnr0TUu5xKSnoR7jQhCtvOdlrmgs8y+mTEpwDjXCR0S7jDxp+cEbVHb57Rl8N5thVrOs5RQfshhcqwBR/scCM9iCr0v3D7uyGMinTBT3A8lwerN8iO17FhtEerovn4Zhg2p7quZRiUcYLdx4EOlIMWuORyDk3s0S4VZ27t92NYwMlwMA1TbUQ/XuN1oZaQQ9ipSDjNDDVZto3Q4vwlqL3g1TIs1JyxfHkwUTpuFjg3ZqY+uRNxeJTDlj9JHXiAIZ+VeBggB7EixKE+wMi1A6a+Si/ZpBbroK5gP1gODShXYUN4eGmodxqF2/gVrJcimEeHkyBZ74dZIa9gTSIOxeo1OS70fFU+hQy9/V0/q4PElPZn+EzLTGknWh1EDmqReZ1svv0tYf0Ve/l5szhdNGsb2LUEZ7G/r0Bs7fyQjA5YZI+byOPTSA1Q9vlT63sodpBRDURWkqTRFRPWlaEY2kMZu/vJ422PSjK51X4EPHWmpOkDkxFzx2WAs2rKZ9QXCkU0RGu0Ctial/zNVhm20eVklcuIirEnmUK9Kod0KBmjl+U6U6jHvlhOEC4zp2QcDsrLSQu7gDHvJWbYmaKBTiXrEvk52G/EN9aD86Am5k0bwPU5ktj8z38+5sxVns1R4e9J1WaZgD2dtFvpSxJbjVf09AZHIeyNw/BRu3GfJU6dX6KJVMCMtN+R5xv/ZckylI355R4nrf+7PLNsGg2tqlemvHiwdQkOb3/TOLrJpO94JRjm9k16huysztkpgJIGyKvHXT6z1A3cwCoJzrK7sQ1awedPvO+N8UGJ7kXHRgLLhQ2yWfZfIsD/s0Ji5GFrItm1nlqHAd/ZFh82jNKmvh6+n42l5TimH9Q0Cf+7bK5Y7SVYzhSAW2B8ivHsPMpAkLJ6d17ZMxtrr4/Q=",
|
|
||||||
"urls": [
|
|
||||||
"https://pixeldrain.com/api/file/KfWzWfxp",
|
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_linux_x86_64.AppImage"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"opensuse15.1": {
|
|
||||||
"1.1.4": {
|
|
||||||
"sha256": "85347471f33dd41a35eb296cda03590d451322cd54a077cef470ccbfe52a141b",
|
|
||||||
"sig": "CGialiJMT6nETdGgP3vQvsXSWQYUEX7j7Cck0NSiW0cE4A1kW3mabM2I/5Yt4NwkDqBIAXofPyUd1JQ4UrF8cijfLNv3ECSaDJs7bWrISDr3Z8ti0uZnN3RUdJDCYDvAWBVqGC82Q1fmLkYJhd33o2B9DzjmvO+i7+buNyDB3dBIY5Fa3rnLKsIY7WB5EASBG3TzDlsZOtLvNgKo/3fLJP2RFyczSVCFZeHlppJbyXCakj50eCNbxjP6SLaD3oE+M0xGvyPyKTk0OGoJTGKM13q30WKbM6cMfL87BbUueGkBFDZeNMWU8Mz/fdGG21WqNN1p7k3CilJJQz7ZEE9bBhlsIX5j5rvL2qNYJoQbJQbxVjyoWHOOlqA62WUTOZhyiHD3OWQ58Fd9JqGDiIhg+ChIBWzyEXNdE6GQr7/qEiAQDbEsU06WOzfj3uxAV//iy/noalpyhlnr0TUu5xKSnoR7jQhCtvOdlrmgs8y+mTEpwDjXCR0S7jDxp+cEbVHb57Rl8N5thVrOs5RQfshhcqwBR/scCM9iCr0v3D7uyGMinTBT3A8lwerN8iO17FhtEerovn4Zhg2p7quZRiUcYLdx4EOlIMWuORyDk3s0S4VZ27t92NYwMlwMA1TbUQ/XuN1oZaQQ9ipSDjNDDVZto3Q4vwlqL3g1TIs1JyxfHkwUTpuFjg3ZqY+uRNxeJTDlj9JHXiAIZ+VeBggB7EixKE+wMi1A6a+Si/ZpBbroK5gP1gODShXYUN4eGmodxqF2/gVrJcimEeHkyBZ74dZIa9gTSIOxeo1OS70fFU+hQy9/V0/q4PElPZn+EzLTGknWh1EDmqReZ1svv0tYf0Ve/l5szhdNGsb2LUEZ7G/r0Bs7fyQjA5YZI+byOPTSA1Q9vlT63sodpBRDURWkqTRFRPWlaEY2kMZu/vJ422PSjK51X4EPHWmpOkDkxFzx2WAs2rKZ9QXCkU0RGu0Ctial/zNVhm20eVklcuIirEnmUK9Kod0KBmjl+U6U6jHvlhOEC4zp2QcDsrLSQu7gDHvJWbYmaKBTiXrEvk52G/EN9aD86Am5k0bwPU5ktj8z38+5sxVns1R4e9J1WaZgD2dtFvpSxJbjVf09AZHIeyNw/BRu3GfJU6dX6KJVMCMtN+R5xv/ZckylI355R4nrf+7PLNsGg2tqlemvHiwdQkOb3/TOLrJpO94JRjm9k16huysztkpgJIGyKvHXT6z1A3cwCoJzrK7sQ1awedPvO+N8UGJ7kXHRgLLhQ2yWfZfIsD/s0Ji5GFrItm1nlqHAd/ZFh82jNKmvh6+n42l5TimH9Q0Cf+7bK5Y7SVYzhSAW2B8ivHsPMpAkLJ6d17ZMxtrr4/Q=",
|
|
||||||
"urls": [
|
|
||||||
"https://pixeldrain.com/api/file/KfWzWfxp",
|
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_linux_x86_64.AppImage"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"solus": {
|
"solus": {
|
||||||
"1.1.4": {
|
"1.3.2": {
|
||||||
"sha256": "85347471f33dd41a35eb296cda03590d451322cd54a077cef470ccbfe52a141b",
|
"sha256": "a8b9bff91d0f0685041737cfa40b4bc8ef765d24419104f3dd90f977023e7858",
|
||||||
"sig": "CGialiJMT6nETdGgP3vQvsXSWQYUEX7j7Cck0NSiW0cE4A1kW3mabM2I/5Yt4NwkDqBIAXofPyUd1JQ4UrF8cijfLNv3ECSaDJs7bWrISDr3Z8ti0uZnN3RUdJDCYDvAWBVqGC82Q1fmLkYJhd33o2B9DzjmvO+i7+buNyDB3dBIY5Fa3rnLKsIY7WB5EASBG3TzDlsZOtLvNgKo/3fLJP2RFyczSVCFZeHlppJbyXCakj50eCNbxjP6SLaD3oE+M0xGvyPyKTk0OGoJTGKM13q30WKbM6cMfL87BbUueGkBFDZeNMWU8Mz/fdGG21WqNN1p7k3CilJJQz7ZEE9bBhlsIX5j5rvL2qNYJoQbJQbxVjyoWHOOlqA62WUTOZhyiHD3OWQ58Fd9JqGDiIhg+ChIBWzyEXNdE6GQr7/qEiAQDbEsU06WOzfj3uxAV//iy/noalpyhlnr0TUu5xKSnoR7jQhCtvOdlrmgs8y+mTEpwDjXCR0S7jDxp+cEbVHb57Rl8N5thVrOs5RQfshhcqwBR/scCM9iCr0v3D7uyGMinTBT3A8lwerN8iO17FhtEerovn4Zhg2p7quZRiUcYLdx4EOlIMWuORyDk3s0S4VZ27t92NYwMlwMA1TbUQ/XuN1oZaQQ9ipSDjNDDVZto3Q4vwlqL3g1TIs1JyxfHkwUTpuFjg3ZqY+uRNxeJTDlj9JHXiAIZ+VeBggB7EixKE+wMi1A6a+Si/ZpBbroK5gP1gODShXYUN4eGmodxqF2/gVrJcimEeHkyBZ74dZIa9gTSIOxeo1OS70fFU+hQy9/V0/q4PElPZn+EzLTGknWh1EDmqReZ1svv0tYf0Ve/l5szhdNGsb2LUEZ7G/r0Bs7fyQjA5YZI+byOPTSA1Q9vlT63sodpBRDURWkqTRFRPWlaEY2kMZu/vJ422PSjK51X4EPHWmpOkDkxFzx2WAs2rKZ9QXCkU0RGu0Ctial/zNVhm20eVklcuIirEnmUK9Kod0KBmjl+U6U6jHvlhOEC4zp2QcDsrLSQu7gDHvJWbYmaKBTiXrEvk52G/EN9aD86Am5k0bwPU5ktj8z38+5sxVns1R4e9J1WaZgD2dtFvpSxJbjVf09AZHIeyNw/BRu3GfJU6dX6KJVMCMtN+R5xv/ZckylI355R4nrf+7PLNsGg2tqlemvHiwdQkOb3/TOLrJpO94JRjm9k16huysztkpgJIGyKvHXT6z1A3cwCoJzrK7sQ1awedPvO+N8UGJ7kXHRgLLhQ2yWfZfIsD/s0Ji5GFrItm1nlqHAd/ZFh82jNKmvh6+n42l5TimH9Q0Cf+7bK5Y7SVYzhSAW2B8ivHsPMpAkLJ6d17ZMxtrr4/Q=",
|
"sig": "CBEtKUDJwjPrchhNXvzulpfaBWFElDD+Kn9b14oF426IuKncsmqTWUesG3cT/beDk1onaDOhDIchyan6iW/BCdB+sVAuGAoRpm2lJ4lWba7ZPnXP7H10uIjVf1xASwIciP4jpAUPo0bO8hi9kqu1zkF9GeVHHb+SXlLhDP31wN7kHwgb/MeZ95/NqfucumYcwfFOZOnofSKaGQwHpbypy57YzyVCf/NzQDnYC46lcH9xVMmbgodT+y5MIIF0kkSJn0DbSfxLVMWTx1pnZUzJ7J827EKUgAS4d4uLI7ShskS+d84i8rNV9gXgqwYkqDvYbdFi7ArJZB7GJtyZ4VPTqRqGfxwF8rL3K0ml+635DfEXiHN8MbTuqwLHD2giChOfsdAAV4ngJ8xg7+Th8dqpgC92GXoOjNK7GSAyrOFsQ7xeqdVOBZMNk/dHVAb9eCTbPIsOjGFTAzOk8n3roM8naDUOq7PefUj1Jb2EGVhWnwS2ngvhNfRggZmmr3l9IElddaHro0JpnubsFmiAa+akV0P8VLb1jjpIJRfr2CIEnPTQbT4UQ1DdBitgkWiPbagTp8BQF1YGcVZ8jc9mbOxmF46z0MyuMQZjDHw2Vai0uPsoLIJHhy3I7nJqsnEw6gQX/l1VGj9wPHeaqMgGYGFykFfvVssh0CH45tUCdWL6Q9Hgx8+yLw0Lky/HIGMQc0qZUM9ute/9Buifd9cOK8+S5PaA0Zg0G/pIY6fThtO86wKJQnoPeiuBkJ9yXc20ZGrfb39Qnf2nZxrPyVl2iQJlven6CDBxc88henxzvxK61bXUynK8zHVuoIAC7ejWZEbPOqDV3DOOSVDz1+eq1MU2KZ4JmaLipzbdy/y+ph1TnCGwdL9R3s+xLYSaxA+ybhQVNXHhQ7+eZD6CWXytaIVYe8giL1ki8oN/18Bm1B2dVxCZ4KKbAToFpBOGvW+w8JFAC5nBK5aj2BGWEocyWQ1XIJmqVBd8RSOMYVYjQOhVnIvyJxOqvnrLUoRzJruj8R/riuCSMnfq17ykpjCzoNzIjvimCPyAib9kdWx7M8dyOS9Sls2sMLwJvDcsGi/FfuGqBmV2v28XagRZz70iypqNaIUrj4CShfz8e110su3BtLQHr1O6yffxy+whbB7w+ogZ6gz86AZ/63Zz6xbLIk4wuNx1UL/ZuRMGq4xOW/7zRpOYYSe/h98YFd9/UTcoi8Osjl+o1eVup6YWVeDvOG69uqwfID8XHivJnEV2NVFx8fbb6fHSrMg/QbjSngdyQ3b+5rWiZG01DGCDB5RFOvEKY24qrXXWQGAx+JXbj+/7xYWts+/Fv7hSqvpvf7H8aVCoOKXGtjJiy+K/9tAJJLQDAzo=",
|
||||||
"urls": [
|
"urls": [
|
||||||
"https://pixeldrain.com/api/file/KfWzWfxp",
|
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.2_linux_x86_64.AppImage"
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_linux_x86_64.AppImage"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tumbleweed": {
|
|
||||||
"1.1.4": {
|
|
||||||
"sha256": "85347471f33dd41a35eb296cda03590d451322cd54a077cef470ccbfe52a141b",
|
|
||||||
"sig": "CGialiJMT6nETdGgP3vQvsXSWQYUEX7j7Cck0NSiW0cE4A1kW3mabM2I/5Yt4NwkDqBIAXofPyUd1JQ4UrF8cijfLNv3ECSaDJs7bWrISDr3Z8ti0uZnN3RUdJDCYDvAWBVqGC82Q1fmLkYJhd33o2B9DzjmvO+i7+buNyDB3dBIY5Fa3rnLKsIY7WB5EASBG3TzDlsZOtLvNgKo/3fLJP2RFyczSVCFZeHlppJbyXCakj50eCNbxjP6SLaD3oE+M0xGvyPyKTk0OGoJTGKM13q30WKbM6cMfL87BbUueGkBFDZeNMWU8Mz/fdGG21WqNN1p7k3CilJJQz7ZEE9bBhlsIX5j5rvL2qNYJoQbJQbxVjyoWHOOlqA62WUTOZhyiHD3OWQ58Fd9JqGDiIhg+ChIBWzyEXNdE6GQr7/qEiAQDbEsU06WOzfj3uxAV//iy/noalpyhlnr0TUu5xKSnoR7jQhCtvOdlrmgs8y+mTEpwDjXCR0S7jDxp+cEbVHb57Rl8N5thVrOs5RQfshhcqwBR/scCM9iCr0v3D7uyGMinTBT3A8lwerN8iO17FhtEerovn4Zhg2p7quZRiUcYLdx4EOlIMWuORyDk3s0S4VZ27t92NYwMlwMA1TbUQ/XuN1oZaQQ9ipSDjNDDVZto3Q4vwlqL3g1TIs1JyxfHkwUTpuFjg3ZqY+uRNxeJTDlj9JHXiAIZ+VeBggB7EixKE+wMi1A6a+Si/ZpBbroK5gP1gODShXYUN4eGmodxqF2/gVrJcimEeHkyBZ74dZIa9gTSIOxeo1OS70fFU+hQy9/V0/q4PElPZn+EzLTGknWh1EDmqReZ1svv0tYf0Ve/l5szhdNGsb2LUEZ7G/r0Bs7fyQjA5YZI+byOPTSA1Q9vlT63sodpBRDURWkqTRFRPWlaEY2kMZu/vJ422PSjK51X4EPHWmpOkDkxFzx2WAs2rKZ9QXCkU0RGu0Ctial/zNVhm20eVklcuIirEnmUK9Kod0KBmjl+U6U6jHvlhOEC4zp2QcDsrLSQu7gDHvJWbYmaKBTiXrEvk52G/EN9aD86Am5k0bwPU5ktj8z38+5sxVns1R4e9J1WaZgD2dtFvpSxJbjVf09AZHIeyNw/BRu3GfJU6dX6KJVMCMtN+R5xv/ZckylI355R4nrf+7PLNsGg2tqlemvHiwdQkOb3/TOLrJpO94JRjm9k16huysztkpgJIGyKvHXT6z1A3cwCoJzrK7sQ1awedPvO+N8UGJ7kXHRgLLhQ2yWfZfIsD/s0Ji5GFrItm1nlqHAd/ZFh82jNKmvh6+n42l5TimH9Q0Cf+7bK5Y7SVYzhSAW2B8ivHsPMpAkLJ6d17ZMxtrr4/Q=",
|
|
||||||
"urls": [
|
|
||||||
"https://pixeldrain.com/api/file/KfWzWfxp",
|
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_linux_x86_64.AppImage"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ubuntu18.04": {
|
|
||||||
"1.1.4": {
|
|
||||||
"sha256": "85347471f33dd41a35eb296cda03590d451322cd54a077cef470ccbfe52a141b",
|
|
||||||
"sig": "CGialiJMT6nETdGgP3vQvsXSWQYUEX7j7Cck0NSiW0cE4A1kW3mabM2I/5Yt4NwkDqBIAXofPyUd1JQ4UrF8cijfLNv3ECSaDJs7bWrISDr3Z8ti0uZnN3RUdJDCYDvAWBVqGC82Q1fmLkYJhd33o2B9DzjmvO+i7+buNyDB3dBIY5Fa3rnLKsIY7WB5EASBG3TzDlsZOtLvNgKo/3fLJP2RFyczSVCFZeHlppJbyXCakj50eCNbxjP6SLaD3oE+M0xGvyPyKTk0OGoJTGKM13q30WKbM6cMfL87BbUueGkBFDZeNMWU8Mz/fdGG21WqNN1p7k3CilJJQz7ZEE9bBhlsIX5j5rvL2qNYJoQbJQbxVjyoWHOOlqA62WUTOZhyiHD3OWQ58Fd9JqGDiIhg+ChIBWzyEXNdE6GQr7/qEiAQDbEsU06WOzfj3uxAV//iy/noalpyhlnr0TUu5xKSnoR7jQhCtvOdlrmgs8y+mTEpwDjXCR0S7jDxp+cEbVHb57Rl8N5thVrOs5RQfshhcqwBR/scCM9iCr0v3D7uyGMinTBT3A8lwerN8iO17FhtEerovn4Zhg2p7quZRiUcYLdx4EOlIMWuORyDk3s0S4VZ27t92NYwMlwMA1TbUQ/XuN1oZaQQ9ipSDjNDDVZto3Q4vwlqL3g1TIs1JyxfHkwUTpuFjg3ZqY+uRNxeJTDlj9JHXiAIZ+VeBggB7EixKE+wMi1A6a+Si/ZpBbroK5gP1gODShXYUN4eGmodxqF2/gVrJcimEeHkyBZ74dZIa9gTSIOxeo1OS70fFU+hQy9/V0/q4PElPZn+EzLTGknWh1EDmqReZ1svv0tYf0Ve/l5szhdNGsb2LUEZ7G/r0Bs7fyQjA5YZI+byOPTSA1Q9vlT63sodpBRDURWkqTRFRPWlaEY2kMZu/vJ422PSjK51X4EPHWmpOkDkxFzx2WAs2rKZ9QXCkU0RGu0Ctial/zNVhm20eVklcuIirEnmUK9Kod0KBmjl+U6U6jHvlhOEC4zp2QcDsrLSQu7gDHvJWbYmaKBTiXrEvk52G/EN9aD86Am5k0bwPU5ktj8z38+5sxVns1R4e9J1WaZgD2dtFvpSxJbjVf09AZHIeyNw/BRu3GfJU6dX6KJVMCMtN+R5xv/ZckylI355R4nrf+7PLNsGg2tqlemvHiwdQkOb3/TOLrJpO94JRjm9k16huysztkpgJIGyKvHXT6z1A3cwCoJzrK7sQ1awedPvO+N8UGJ7kXHRgLLhQ2yWfZfIsD/s0Ji5GFrItm1nlqHAd/ZFh82jNKmvh6+n42l5TimH9Q0Cf+7bK5Y7SVYzhSAW2B8ivHsPMpAkLJ6d17ZMxtrr4/Q=",
|
|
||||||
"urls": [
|
|
||||||
"https://pixeldrain.com/api/file/KfWzWfxp",
|
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_linux_x86_64.AppImage"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ubuntu18.10": {
|
|
||||||
"1.1.4": {
|
|
||||||
"sha256": "85347471f33dd41a35eb296cda03590d451322cd54a077cef470ccbfe52a141b",
|
|
||||||
"sig": "CGialiJMT6nETdGgP3vQvsXSWQYUEX7j7Cck0NSiW0cE4A1kW3mabM2I/5Yt4NwkDqBIAXofPyUd1JQ4UrF8cijfLNv3ECSaDJs7bWrISDr3Z8ti0uZnN3RUdJDCYDvAWBVqGC82Q1fmLkYJhd33o2B9DzjmvO+i7+buNyDB3dBIY5Fa3rnLKsIY7WB5EASBG3TzDlsZOtLvNgKo/3fLJP2RFyczSVCFZeHlppJbyXCakj50eCNbxjP6SLaD3oE+M0xGvyPyKTk0OGoJTGKM13q30WKbM6cMfL87BbUueGkBFDZeNMWU8Mz/fdGG21WqNN1p7k3CilJJQz7ZEE9bBhlsIX5j5rvL2qNYJoQbJQbxVjyoWHOOlqA62WUTOZhyiHD3OWQ58Fd9JqGDiIhg+ChIBWzyEXNdE6GQr7/qEiAQDbEsU06WOzfj3uxAV//iy/noalpyhlnr0TUu5xKSnoR7jQhCtvOdlrmgs8y+mTEpwDjXCR0S7jDxp+cEbVHb57Rl8N5thVrOs5RQfshhcqwBR/scCM9iCr0v3D7uyGMinTBT3A8lwerN8iO17FhtEerovn4Zhg2p7quZRiUcYLdx4EOlIMWuORyDk3s0S4VZ27t92NYwMlwMA1TbUQ/XuN1oZaQQ9ipSDjNDDVZto3Q4vwlqL3g1TIs1JyxfHkwUTpuFjg3ZqY+uRNxeJTDlj9JHXiAIZ+VeBggB7EixKE+wMi1A6a+Si/ZpBbroK5gP1gODShXYUN4eGmodxqF2/gVrJcimEeHkyBZ74dZIa9gTSIOxeo1OS70fFU+hQy9/V0/q4PElPZn+EzLTGknWh1EDmqReZ1svv0tYf0Ve/l5szhdNGsb2LUEZ7G/r0Bs7fyQjA5YZI+byOPTSA1Q9vlT63sodpBRDURWkqTRFRPWlaEY2kMZu/vJ422PSjK51X4EPHWmpOkDkxFzx2WAs2rKZ9QXCkU0RGu0Ctial/zNVhm20eVklcuIirEnmUK9Kod0KBmjl+U6U6jHvlhOEC4zp2QcDsrLSQu7gDHvJWbYmaKBTiXrEvk52G/EN9aD86Am5k0bwPU5ktj8z38+5sxVns1R4e9J1WaZgD2dtFvpSxJbjVf09AZHIeyNw/BRu3GfJU6dX6KJVMCMtN+R5xv/ZckylI355R4nrf+7PLNsGg2tqlemvHiwdQkOb3/TOLrJpO94JRjm9k16huysztkpgJIGyKvHXT6z1A3cwCoJzrK7sQ1awedPvO+N8UGJ7kXHRgLLhQ2yWfZfIsD/s0Ji5GFrItm1nlqHAd/ZFh82jNKmvh6+n42l5TimH9Q0Cf+7bK5Y7SVYzhSAW2B8ivHsPMpAkLJ6d17ZMxtrr4/Q=",
|
|
||||||
"urls": [
|
|
||||||
"https://pixeldrain.com/api/file/KfWzWfxp",
|
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_linux_x86_64.AppImage"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ubuntu19.04": {
|
|
||||||
"1.1.4": {
|
|
||||||
"sha256": "85347471f33dd41a35eb296cda03590d451322cd54a077cef470ccbfe52a141b",
|
|
||||||
"sig": "CGialiJMT6nETdGgP3vQvsXSWQYUEX7j7Cck0NSiW0cE4A1kW3mabM2I/5Yt4NwkDqBIAXofPyUd1JQ4UrF8cijfLNv3ECSaDJs7bWrISDr3Z8ti0uZnN3RUdJDCYDvAWBVqGC82Q1fmLkYJhd33o2B9DzjmvO+i7+buNyDB3dBIY5Fa3rnLKsIY7WB5EASBG3TzDlsZOtLvNgKo/3fLJP2RFyczSVCFZeHlppJbyXCakj50eCNbxjP6SLaD3oE+M0xGvyPyKTk0OGoJTGKM13q30WKbM6cMfL87BbUueGkBFDZeNMWU8Mz/fdGG21WqNN1p7k3CilJJQz7ZEE9bBhlsIX5j5rvL2qNYJoQbJQbxVjyoWHOOlqA62WUTOZhyiHD3OWQ58Fd9JqGDiIhg+ChIBWzyEXNdE6GQr7/qEiAQDbEsU06WOzfj3uxAV//iy/noalpyhlnr0TUu5xKSnoR7jQhCtvOdlrmgs8y+mTEpwDjXCR0S7jDxp+cEbVHb57Rl8N5thVrOs5RQfshhcqwBR/scCM9iCr0v3D7uyGMinTBT3A8lwerN8iO17FhtEerovn4Zhg2p7quZRiUcYLdx4EOlIMWuORyDk3s0S4VZ27t92NYwMlwMA1TbUQ/XuN1oZaQQ9ipSDjNDDVZto3Q4vwlqL3g1TIs1JyxfHkwUTpuFjg3ZqY+uRNxeJTDlj9JHXiAIZ+VeBggB7EixKE+wMi1A6a+Si/ZpBbroK5gP1gODShXYUN4eGmodxqF2/gVrJcimEeHkyBZ74dZIa9gTSIOxeo1OS70fFU+hQy9/V0/q4PElPZn+EzLTGknWh1EDmqReZ1svv0tYf0Ve/l5szhdNGsb2LUEZ7G/r0Bs7fyQjA5YZI+byOPTSA1Q9vlT63sodpBRDURWkqTRFRPWlaEY2kMZu/vJ422PSjK51X4EPHWmpOkDkxFzx2WAs2rKZ9QXCkU0RGu0Ctial/zNVhm20eVklcuIirEnmUK9Kod0KBmjl+U6U6jHvlhOEC4zp2QcDsrLSQu7gDHvJWbYmaKBTiXrEvk52G/EN9aD86Am5k0bwPU5ktj8z38+5sxVns1R4e9J1WaZgD2dtFvpSxJbjVf09AZHIeyNw/BRu3GfJU6dX6KJVMCMtN+R5xv/ZckylI355R4nrf+7PLNsGg2tqlemvHiwdQkOb3/TOLrJpO94JRjm9k16huysztkpgJIGyKvHXT6z1A3cwCoJzrK7sQ1awedPvO+N8UGJ7kXHRgLLhQ2yWfZfIsD/s0Ji5GFrItm1nlqHAd/ZFh82jNKmvh6+n42l5TimH9Q0Cf+7bK5Y7SVYzhSAW2B8ivHsPMpAkLJ6d17ZMxtrr4/Q=",
|
|
||||||
"urls": [
|
|
||||||
"https://pixeldrain.com/api/file/KfWzWfxp",
|
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_linux_x86_64.AppImage"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ubuntu19.10": {
|
|
||||||
"1.1.4": {
|
|
||||||
"sha256": "85347471f33dd41a35eb296cda03590d451322cd54a077cef470ccbfe52a141b",
|
|
||||||
"sig": "CGialiJMT6nETdGgP3vQvsXSWQYUEX7j7Cck0NSiW0cE4A1kW3mabM2I/5Yt4NwkDqBIAXofPyUd1JQ4UrF8cijfLNv3ECSaDJs7bWrISDr3Z8ti0uZnN3RUdJDCYDvAWBVqGC82Q1fmLkYJhd33o2B9DzjmvO+i7+buNyDB3dBIY5Fa3rnLKsIY7WB5EASBG3TzDlsZOtLvNgKo/3fLJP2RFyczSVCFZeHlppJbyXCakj50eCNbxjP6SLaD3oE+M0xGvyPyKTk0OGoJTGKM13q30WKbM6cMfL87BbUueGkBFDZeNMWU8Mz/fdGG21WqNN1p7k3CilJJQz7ZEE9bBhlsIX5j5rvL2qNYJoQbJQbxVjyoWHOOlqA62WUTOZhyiHD3OWQ58Fd9JqGDiIhg+ChIBWzyEXNdE6GQr7/qEiAQDbEsU06WOzfj3uxAV//iy/noalpyhlnr0TUu5xKSnoR7jQhCtvOdlrmgs8y+mTEpwDjXCR0S7jDxp+cEbVHb57Rl8N5thVrOs5RQfshhcqwBR/scCM9iCr0v3D7uyGMinTBT3A8lwerN8iO17FhtEerovn4Zhg2p7quZRiUcYLdx4EOlIMWuORyDk3s0S4VZ27t92NYwMlwMA1TbUQ/XuN1oZaQQ9ipSDjNDDVZto3Q4vwlqL3g1TIs1JyxfHkwUTpuFjg3ZqY+uRNxeJTDlj9JHXiAIZ+VeBggB7EixKE+wMi1A6a+Si/ZpBbroK5gP1gODShXYUN4eGmodxqF2/gVrJcimEeHkyBZ74dZIa9gTSIOxeo1OS70fFU+hQy9/V0/q4PElPZn+EzLTGknWh1EDmqReZ1svv0tYf0Ve/l5szhdNGsb2LUEZ7G/r0Bs7fyQjA5YZI+byOPTSA1Q9vlT63sodpBRDURWkqTRFRPWlaEY2kMZu/vJ422PSjK51X4EPHWmpOkDkxFzx2WAs2rKZ9QXCkU0RGu0Ctial/zNVhm20eVklcuIirEnmUK9Kod0KBmjl+U6U6jHvlhOEC4zp2QcDsrLSQu7gDHvJWbYmaKBTiXrEvk52G/EN9aD86Am5k0bwPU5ktj8z38+5sxVns1R4e9J1WaZgD2dtFvpSxJbjVf09AZHIeyNw/BRu3GfJU6dX6KJVMCMtN+R5xv/ZckylI355R4nrf+7PLNsGg2tqlemvHiwdQkOb3/TOLrJpO94JRjm9k16huysztkpgJIGyKvHXT6z1A3cwCoJzrK7sQ1awedPvO+N8UGJ7kXHRgLLhQ2yWfZfIsD/s0Ji5GFrItm1nlqHAd/ZFh82jNKmvh6+n42l5TimH9Q0Cf+7bK5Y7SVYzhSAW2B8ivHsPMpAkLJ6d17ZMxtrr4/Q=",
|
|
||||||
"urls": [
|
|
||||||
"https://pixeldrain.com/api/file/KfWzWfxp",
|
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_linux_x86_64.AppImage"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"win32": {
|
"win32": {
|
||||||
"1.1.4": {
|
"1.3.1": {
|
||||||
"sha256": "c942d2779e7da597605d9fb8fa2876f9c82e5255ee859dac47d209e64f6d1707",
|
"sig": "29b91fcba36fc7cac38837674559c6af1169b3dc54bd57284c3ecf44a1af869d",
|
||||||
"sig": "AhYYFZxYLVibiRvc0PyOSnU+CWoaVwWvKfMWibdYsxINuwPUMVRjvXe2dPB8ghqe3qODw4XswZnwu7BwqTbCwaEDNdj8f4kpmd0cNnFTP4jP9q0qKcM4thOq1rCr8VuptS8UsTT0UXVqExf2K06efyrG1GYjeTG9LJpCJ5YFiet2vrarqHap/FiRjgVhRcE6mkoDPLj+eu9z9AFPQ4uNrMazFgHj7Vbq4H+oEIwMiuC6umbd3xGBSvlmudp3OONYrybwIuMpqaUPv874eFQOfrlYVPadAr9vn6QxFEjl1rBkd9xQNte/CBYNe1/fD5p0iLjJOAqz24cgZCMpKsRUOpgJcwf7NVU819Ymbu9/zVtBJ2F/T2wg2o8wTyymWqTdMSEDZu0fUb3StHzcrEqFzAHckyDF6d6qrKBXc8bzs0T85FQUZUqzoZng3b+Y2xtSoaiJA/6Es+Qx6t1T7dXqtN7xu43ZRrNNLcLG/FtHx8X7UuAzNt4FL5kbPM3EMtK1J3gsDpTQSsLKPKTWZXuEfUOCI/b1psL3YcsQv9Ta1o2I9bGqYTJtsGTvCkXG20KoqcqXiYFyGWTnztd8jcPhvxjI9aI0sblOTMN4lBmkNroOkSu39/+z8UvsKgioE1FNmjr5edtqbXdJ2C/6PZITKe3Hl+sfJDHinn3QhYp/Hl9gzL64KD2lJRiM7rCWYfyUvMnwewG5aQvkE/Jf9t05DYCX9rwbUoz8QSV/HBGOXrrDpo+tJeZ74FbaNVlW4IApnpSdQpVqwdJCf7rdPwOm13DvkgSDjlz02BdLKk93X0fX4zCGnF/RNYw4meLkbs0UmrDml9hCfEHRjrYJe0i9GqRwyBH9kp+sbBTYcomZgro24pEQRXi6DoK5xjpu8K+ywAAjWFn7vrZQeuNTmw5Itib2xQQnFzbg/u35KFXvaZ6c0MBi+rIwUQTqOO1l6U6PN5+U7imRxDKvy6y1GsusJGXee4HATJiZc/5PCRK42A2YJ1NBHDJOm0aLcx8oboYtmvGOIObAcpEIkfrDdykxBvpxFPBW6AXacj5vwi0Io+1TjB7aXmyRiOGV/nzerUdFTtnbkvgOLIGiOy+B3NN6b8WZVkbubcaWBqW0yuHwVcRJtsbhtiLhGXc4n3iFPR+1gJCHd0rUKF2HKs3MALk4Gh/V1rZqY7iklceEJkMgCHwKZ56vIYiNkwT5uco0UNEpOAedAfRMBAvs1WQuyltdYlDL/9XwPfc6Wg7BHL1wfmq/wFaE4kKtbEXM+Esh9GmLXPcsNrDU71hkhTTl0edmXlp4f8olJjJxas0YerwyVvhIDlG9RSV0PewYIWnLevb9kA9xAGmFbgp4yfyWAqC2ORY=",
|
"sha256":"BLy7sutkbfkK39sOPPlDdn8DVoorVC7NiEl7LvCqp9Dcnt+6afmszRLFYNu0ipu2krN8HdA2uCqCS2lAlNwOzGzkCGN6RHfobHRqj/HObNrWsvGKSp+Vdt96J76TmrV/gjPGLJOBq5dobBGmN1KJSrkLpWj6IOoEuR4/7WkSJah4XWMIfVlPAZKwP6yNv6OaYqjIy74geKkoCI5/mmwDzUX/T8M3DsdSbm3kuYJ0S3E3mEO2lGH++nxDDPMdA2yjFbBwHU2RFQShbL7jB/AqodSrIU4wOstbRWiF34KUZ/KYG+ZFvwEBshbgDoZQyNbVmFDD86g/sEatnQRpN7juGBWwScgPfoTbdl9y0lf5U85dicOe7+iholAUVprLuPk9Y3NVXoBFM9g9mkqgMVoYoSUgh/BJBnomDgvt1pd4Id/CO26buhSU28fRbQ/c8i+x5zdsfqN7p/64sj/2Xp0HQMwFmc3IotjDEtUTcfI+VGP62pJLMao5vheZ8JU05GXn7ZA7Sojfov9luuoajguukXHEclaxgWKyo0u/ZcowExrKpkegxui6v/3+W/pTv/cSg01CFyJTMTvT9cT7O0bWSdUcxOgpYptV5wVOdglUm/aQscqtDVaVv90ZMNldQ2YVI6wuFTIcUpWNCa/r5oIcGVWWrxBu9uq0jLF3AoTNpLeLJuJL37KacJwNqNDUolG6bwdjvAI1cpcy7fGrzbGE95pPmHpruVfKpLpSQ7tKnT5dV9H2gQz63gl/QzvVGnov0pLUNuJwQQhdvcGZXnVcB96u0i8GBacr4WZVhhJWGWk/u5zx5ganXcXYkodDLN4zpI/aV/TdW2QH2xN8OOmQOZ8yZS9toS0vcIUeoT6eQUg5clJniKtivUv2GSldGzKG9xk3s/2IQlivOX2BxnTSYaP1AkWTUSyJeXcEYbYytLiFrMj875NxeYfKD74SGfxWh//NWyzL7GG/q8G77xw/1s4LorzhSN5jifyPgtSWI4h3WaSu6nfLJHioujAEMDwhkwP9mPmPmBUbTveKWdTZy7YQGGN+4DMJLoGQnx0qBbsIOWfmt+/cjQ72Sx8V7oRzElSohxg9q/oCKkMo4f1JuS1kOGasbPnXjjjuWTX1bOeQ86TjBi+wSt1Y5VgifvyfEdEeDvvwrcm2Cp3NnWYAXhqE5tgVUIYLEtsbHaAtWOv4XSlp8EISd1XIDeTADHNonEEWUWGjNJvylQ05iGUjQny6CObSN3gNbwL0xO/gI1o1+SR4HsM5u2leIKaD5hU/6OdsorVX53b1xPNLyLrDr1uMgfM6lGgCyrs8DY5hVIujIycTSEbaAGpMA2+ovzpa9jO/cZ0/slMMf55Roic2yCQ=",
|
||||||
"urls": [
|
"urls": [
|
||||||
"https://pixeldrain.com/api/file/h5HoAqxF",
|
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.2_win.exe"
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.1.4_win.exe"
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"debian9": {
|
||||||
|
"1.3.2": {
|
||||||
|
"sig": "CBEtKUDJwjPrchhNXvzulpfaBWFElDD+Kn9b14oF426IuKncsmqTWUesG3cT/beDk1onaDOhDIchyan6iW/BCdB+sVAuGAoRpm2lJ4lWba7ZPnXP7H10uIjVf1xASwIciP4jpAUPo0bO8hi9kqu1zkF9GeVHHb+SXlLhDP31wN7kHwgb/MeZ95/NqfucumYcwfFOZOnofSKaGQwHpbypy57YzyVCf/NzQDnYC46lcH9xVMmbgodT+y5MIIF0kkSJn0DbSfxLVMWTx1pnZUzJ7J827EKUgAS4d4uLI7ShskS+d84i8rNV9gXgqwYkqDvYbdFi7ArJZB7GJtyZ4VPTqRqGfxwF8rL3K0ml+635DfEXiHN8MbTuqwLHD2giChOfsdAAV4ngJ8xg7+Th8dqpgC92GXoOjNK7GSAyrOFsQ7xeqdVOBZMNk/dHVAb9eCTbPIsOjGFTAzOk8n3roM8naDUOq7PefUj1Jb2EGVhWnwS2ngvhNfRggZmmr3l9IElddaHro0JpnubsFmiAa+akV0P8VLb1jjpIJRfr2CIEnPTQbT4UQ1DdBitgkWiPbagTp8BQF1YGcVZ8jc9mbOxmF46z0MyuMQZjDHw2Vai0uPsoLIJHhy3I7nJqsnEw6gQX/l1VGj9wPHeaqMgGYGFykFfvVssh0CH45tUCdWL6Q9Hgx8+yLw0Lky/HIGMQc0qZUM9ute/9Buifd9cOK8+S5PaA0Zg0G/pIY6fThtO86wKJQnoPeiuBkJ9yXc20ZGrfb39Qnf2nZxrPyVl2iQJlven6CDBxc88henxzvxK61bXUynK8zHVuoIAC7ejWZEbPOqDV3DOOSVDz1+eq1MU2KZ4JmaLipzbdy/y+ph1TnCGwdL9R3s+xLYSaxA+ybhQVNXHhQ7+eZD6CWXytaIVYe8giL1ki8oN/18Bm1B2dVxCZ4KKbAToFpBOGvW+w8JFAC5nBK5aj2BGWEocyWQ1XIJmqVBd8RSOMYVYjQOhVnIvyJxOqvnrLUoRzJruj8R/riuCSMnfq17ykpjCzoNzIjvimCPyAib9kdWx7M8dyOS9Sls2sMLwJvDcsGi/FfuGqBmV2v28XagRZz70iypqNaIUrj4CShfz8e110su3BtLQHr1O6yffxy+whbB7w+ogZ6gz86AZ/63Zz6xbLIk4wuNx1UL/ZuRMGq4xOW/7zRpOYYSe/h98YFd9/UTcoi8Osjl+o1eVup6YWVeDvOG69uqwfID8XHivJnEV2NVFx8fbb6fHSrMg/QbjSngdyQ3b+5rWiZG01DGCDB5RFOvEKY24qrXXWQGAx+JXbj+/7xYWts+/Fv7hSqvpvf7H8aVCoOKXGtjJiy+K/9tAJJLQDAzo=",
|
||||||
|
"sha256": "a8b9bff91d0f0685041737cfa40b4bc8ef765d24419104f3dd90f977023e7858",
|
||||||
|
"urls": [
|
||||||
|
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.2_linux_x86_64.AppImage"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"debian10": {
|
||||||
|
"1.3.2": {
|
||||||
|
"sig": "CBEtKUDJwjPrchhNXvzulpfaBWFElDD+Kn9b14oF426IuKncsmqTWUesG3cT/beDk1onaDOhDIchyan6iW/BCdB+sVAuGAoRpm2lJ4lWba7ZPnXP7H10uIjVf1xASwIciP4jpAUPo0bO8hi9kqu1zkF9GeVHHb+SXlLhDP31wN7kHwgb/MeZ95/NqfucumYcwfFOZOnofSKaGQwHpbypy57YzyVCf/NzQDnYC46lcH9xVMmbgodT+y5MIIF0kkSJn0DbSfxLVMWTx1pnZUzJ7J827EKUgAS4d4uLI7ShskS+d84i8rNV9gXgqwYkqDvYbdFi7ArJZB7GJtyZ4VPTqRqGfxwF8rL3K0ml+635DfEXiHN8MbTuqwLHD2giChOfsdAAV4ngJ8xg7+Th8dqpgC92GXoOjNK7GSAyrOFsQ7xeqdVOBZMNk/dHVAb9eCTbPIsOjGFTAzOk8n3roM8naDUOq7PefUj1Jb2EGVhWnwS2ngvhNfRggZmmr3l9IElddaHro0JpnubsFmiAa+akV0P8VLb1jjpIJRfr2CIEnPTQbT4UQ1DdBitgkWiPbagTp8BQF1YGcVZ8jc9mbOxmF46z0MyuMQZjDHw2Vai0uPsoLIJHhy3I7nJqsnEw6gQX/l1VGj9wPHeaqMgGYGFykFfvVssh0CH45tUCdWL6Q9Hgx8+yLw0Lky/HIGMQc0qZUM9ute/9Buifd9cOK8+S5PaA0Zg0G/pIY6fThtO86wKJQnoPeiuBkJ9yXc20ZGrfb39Qnf2nZxrPyVl2iQJlven6CDBxc88henxzvxK61bXUynK8zHVuoIAC7ejWZEbPOqDV3DOOSVDz1+eq1MU2KZ4JmaLipzbdy/y+ph1TnCGwdL9R3s+xLYSaxA+ybhQVNXHhQ7+eZD6CWXytaIVYe8giL1ki8oN/18Bm1B2dVxCZ4KKbAToFpBOGvW+w8JFAC5nBK5aj2BGWEocyWQ1XIJmqVBd8RSOMYVYjQOhVnIvyJxOqvnrLUoRzJruj8R/riuCSMnfq17ykpjCzoNzIjvimCPyAib9kdWx7M8dyOS9Sls2sMLwJvDcsGi/FfuGqBmV2v28XagRZz70iypqNaIUrj4CShfz8e110su3BtLQHr1O6yffxy+whbB7w+ogZ6gz86AZ/63Zz6xbLIk4wuNx1UL/ZuRMGq4xOW/7zRpOYYSe/h98YFd9/UTcoi8Osjl+o1eVup6YWVeDvOG69uqwfID8XHivJnEV2NVFx8fbb6fHSrMg/QbjSngdyQ3b+5rWiZG01DGCDB5RFOvEKY24qrXXWQGAx+JXbj+/7xYWts+/Fv7hSqvpvf7H8aVCoOKXGtjJiy+K/9tAJJLQDAzo=",
|
||||||
|
"sha256": "a8b9bff91d0f0685041737cfa40b4bc8ef765d24419104f3dd90f977023e7858",
|
||||||
|
"urls": [
|
||||||
|
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.2_linux_x86_64.AppImage"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Versions": {
|
"Versions": {
|
||||||
"arch": [
|
|
||||||
"1.1.4"
|
|
||||||
],
|
|
||||||
"centos7": [
|
"centos7": [
|
||||||
"1.1.4"
|
"1.3.2"
|
||||||
],
|
],
|
||||||
"darwin": [
|
"darwin": [
|
||||||
"1.1.4"
|
"1.3.2"
|
||||||
],
|
|
||||||
"debian9": [
|
|
||||||
"1.1.4"
|
|
||||||
],
|
|
||||||
"debian10": [
|
|
||||||
"1.1.4"
|
|
||||||
],
|
|
||||||
"fedora28": [
|
|
||||||
"1.1.4"
|
|
||||||
],
|
|
||||||
"fedora29": [
|
|
||||||
"1.1.4"
|
|
||||||
],
|
|
||||||
"fedora30": [
|
|
||||||
"1.1.4"
|
|
||||||
],
|
|
||||||
"fedora31": [
|
|
||||||
"1.1.4"
|
|
||||||
],
|
],
|
||||||
"linux": [
|
"linux": [
|
||||||
"unavailable"
|
"unavailable"
|
||||||
],
|
],
|
||||||
"opensuse15": [
|
|
||||||
"1.1.4"
|
|
||||||
],
|
|
||||||
"opensuse15.1": [
|
|
||||||
"1.1.4"
|
|
||||||
],
|
|
||||||
"solus": [
|
"solus": [
|
||||||
"1.1.4"
|
"1.3.2"
|
||||||
],
|
|
||||||
"tumbleweed": [
|
|
||||||
"1.1.4"
|
|
||||||
],
|
|
||||||
"ubuntu18.04": [
|
|
||||||
"1.1.4"
|
|
||||||
],
|
|
||||||
"ubuntu18.10": [
|
|
||||||
"1.1.4"
|
|
||||||
],
|
|
||||||
"ubuntu19.04": [
|
|
||||||
"1.1.4"
|
|
||||||
],
|
|
||||||
"ubuntu19.10": [
|
|
||||||
"1.1.4"
|
|
||||||
],
|
],
|
||||||
"unknown": [
|
"unknown": [
|
||||||
"unavailable"
|
"unavailable"
|
||||||
],
|
],
|
||||||
"win32": [
|
"win32": [
|
||||||
"1.1.4"
|
"1.3.2"
|
||||||
],
|
],
|
||||||
"centos8": [
|
"debian9": [
|
||||||
"1.1.4"
|
"1.3.2"
|
||||||
|
],
|
||||||
|
"debian10": [
|
||||||
|
"1.3.2"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,13 @@ import InfoDetails from './components/InfoDetails/InfoDetails';
|
|||||||
import IPCContainer from './containers/IPCContainer/IPCContainer';
|
import IPCContainer from './containers/IPCContainer/IPCContainer';
|
||||||
import Loading from './components/UI/Loading/Loading';
|
import Loading from './components/UI/Loading/Loading';
|
||||||
import MountItems from './containers/MountItems/MountItems';
|
import MountItems from './containers/MountItems/MountItems';
|
||||||
|
import NewReleases from './components/NewReleases/NewReleases';
|
||||||
import {notifyError} from './redux/actions/error_actions';
|
import {notifyError} from './redux/actions/error_actions';
|
||||||
import Reboot from './components/Reboot/Reboot';
|
import Reboot from './components/Reboot/Reboot';
|
||||||
|
import {
|
||||||
|
setDismissNewReleasesAvailable,
|
||||||
|
setNewReleasesAvailable
|
||||||
|
} from './redux/actions/release_version_actions';
|
||||||
import ReleaseVersionDisplay from './components/ReleaseVersionDisplay/ReleaseVersionDisplay';
|
import ReleaseVersionDisplay from './components/ReleaseVersionDisplay/ReleaseVersionDisplay';
|
||||||
import {
|
import {
|
||||||
displaySelectAppPlatform,
|
displaySelectAppPlatform,
|
||||||
@@ -28,9 +33,13 @@ import {
|
|||||||
} from './redux/actions/release_version_actions';
|
} from './redux/actions/release_version_actions';
|
||||||
import YesNo from './components/YesNo/YesNo';
|
import YesNo from './components/YesNo/YesNo';
|
||||||
import {createModalConditionally} from './utils';
|
import {createModalConditionally} from './utils';
|
||||||
|
import SkynetImport from './containers/SkynetImport/SkynetImport';
|
||||||
|
import ApplicationBusy from './components/ApplicationBusy/ApplicationBusy';
|
||||||
|
import SkynetExport from './containers/SkynetExport/SkynetExport';
|
||||||
|
import PinnedManager from './containers/PinnedManager/PinnedManager';
|
||||||
|
|
||||||
const Constants = require('./constants');
|
const Constants = require('./constants');
|
||||||
const Scheduler = require('node-schedule');
|
const Scheduler = require('node-cron');
|
||||||
|
|
||||||
class App extends IPCContainer {
|
class App extends IPCContainer {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@@ -46,7 +55,7 @@ class App extends IPCContainer {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
detectUpgrades();
|
detectUpgrades();
|
||||||
this.scheduledUpdateJob = Scheduler.scheduleJob('23 11 * * *', detectUpgrades);
|
this.scheduledUpdateJob = Scheduler.schedule('23 11 * * *', detectUpgrades);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
@@ -54,15 +63,15 @@ class App extends IPCContainer {
|
|||||||
(prevProps.ReleaseVersion !== this.props.ReleaseVersion) ||
|
(prevProps.ReleaseVersion !== this.props.ReleaseVersion) ||
|
||||||
(prevProps.VersionLookup !== this.props.VersionLookup)) {
|
(prevProps.VersionLookup !== this.props.VersionLookup)) {
|
||||||
this.props.saveState();
|
this.props.saveState();
|
||||||
} else if (Object.keys(this.props.ProviderState).filter(k=> {
|
} else if (Object.keys(this.props.ProviderState).filter(k => {
|
||||||
return this.props.ProviderState[k] !== prevProps.ProviderState[k];
|
return this.props.ProviderState[k] !== prevProps.ProviderState[k];
|
||||||
}).length > 0) {
|
}).length > 0) {
|
||||||
this.props.saveState();
|
this.props.saveState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
Scheduler.cancelJob(this.scheduledUpdateJob);
|
this.scheduledUpdateJob.stop();
|
||||||
super.componentWillUnmount();
|
super.componentWillUnmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +81,15 @@ class App extends IPCContainer {
|
|||||||
this.props.VersionLookup[Constants.RELEASE_TYPES[this.props.Release]][this.props.ReleaseVersion];
|
this.props.VersionLookup[Constants.RELEASE_TYPES[this.props.Release]][this.props.ReleaseVersion];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleUpgradeIconClicked = () => {
|
||||||
|
if (this.props.UpgradeAvailable) {
|
||||||
|
this.props.setDismissUIUpgrade(false)
|
||||||
|
} else if (this.props.NewReleasesAvailable2.length > 0) {
|
||||||
|
this.props.setNewReleasesAvailable(this.props.NewReleasesAvailable2);
|
||||||
|
this.props.setDismissNewReleasesAvailable(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const selectedVersion = this.getSelectedVersion();
|
const selectedVersion = this.getSelectedVersion();
|
||||||
|
|
||||||
@@ -89,13 +107,30 @@ class App extends IPCContainer {
|
|||||||
!missingDependencies &&
|
!missingDependencies &&
|
||||||
!this.props.InstallActive;
|
!this.props.InstallActive;
|
||||||
|
|
||||||
const remoteSupported = this.props.LocationsLookup[selectedVersion] &&
|
const remoteSupported = this.props.LocationsLookup[selectedVersion] &&
|
||||||
this.props.LocationsLookup[selectedVersion].supports_remote;
|
this.props.LocationsLookup[selectedVersion].supports_remote;
|
||||||
|
|
||||||
|
const s3Supported = this.props.LocationsLookup[selectedVersion] &&
|
||||||
|
this.props.LocationsLookup[selectedVersion].s3_support;
|
||||||
|
|
||||||
|
const skynetSupported = this.props.LocationsLookup[selectedVersion] &&
|
||||||
|
this.props.LocationsLookup[selectedVersion].skynet_support;
|
||||||
|
|
||||||
|
const scPrimeSupported = this.props.LocationsLookup[selectedVersion] &&
|
||||||
|
this.props.LocationsLookup[selectedVersion].siaprime_support;
|
||||||
|
|
||||||
|
const siaSupported = this.props.LocationsLookup[selectedVersion] &&
|
||||||
|
this.props.LocationsLookup[selectedVersion].sia_support;
|
||||||
|
|
||||||
const showConfig = !missingDependencies &&
|
const showConfig = !missingDependencies &&
|
||||||
|
!this.props.DisplayPinnedManager &&
|
||||||
this.props.DisplayConfiguration &&
|
this.props.DisplayConfiguration &&
|
||||||
!this.props.RebootRequired;
|
!this.props.RebootRequired;
|
||||||
|
|
||||||
|
const showPinnedManager = !missingDependencies &&
|
||||||
|
!this.props.RebootRequired &&
|
||||||
|
this.props.DisplayPinnedManager;
|
||||||
|
|
||||||
const showUpgrade = this.props.UpgradeAvailable &&
|
const showUpgrade = this.props.UpgradeAvailable &&
|
||||||
!this.props.DisplayError &&
|
!this.props.DisplayError &&
|
||||||
!showConfig &&
|
!showConfig &&
|
||||||
@@ -111,15 +146,61 @@ class App extends IPCContainer {
|
|||||||
!this.props.DismissDependencies &&
|
!this.props.DismissDependencies &&
|
||||||
this.props.AllowMount;
|
this.props.AllowMount;
|
||||||
|
|
||||||
const configDisplay = createModalConditionally(showConfig, <Configuration version={selectedVersion} remoteSupported={remoteSupported} />);
|
const showNewReleases = !showConfig &&
|
||||||
|
!this.props.DisplayConfirmYesNo &&
|
||||||
|
!showDependencies &&
|
||||||
|
!this.props.DownloadActive &&
|
||||||
|
!this.props.DisplayError &&
|
||||||
|
!this.props.DisplayInfo &&
|
||||||
|
!this.props.InstallActive &&
|
||||||
|
!this.props.RebootRequired &&
|
||||||
|
!this.props.DisplaySelectAppPlatform &&
|
||||||
|
!showUpgrade &&
|
||||||
|
!this.props.DismissNewReleasesAvailable &&
|
||||||
|
(this.props.NewReleasesAvailable.length > 0);
|
||||||
|
|
||||||
|
const showSkynetImport = !showConfig &&
|
||||||
|
!showDependencies &&
|
||||||
|
!this.props.DownloadActive &&
|
||||||
|
!showNewReleases &&
|
||||||
|
!this.props.RebootRequired &&
|
||||||
|
!this.props.DisplaySelectAppPlatform &&
|
||||||
|
!showUpgrade &&
|
||||||
|
this.props.DisplayImport;
|
||||||
|
|
||||||
|
const showSkynetExport = !showConfig &&
|
||||||
|
!showDependencies &&
|
||||||
|
!this.props.DownloadActive &&
|
||||||
|
!showNewReleases &&
|
||||||
|
!this.props.RebootRequired &&
|
||||||
|
!this.props.DisplaySelectAppPlatform &&
|
||||||
|
!showUpgrade &&
|
||||||
|
this.props.DisplayExport;
|
||||||
|
|
||||||
|
const configDisplay = createModalConditionally(showConfig, <Configuration
|
||||||
|
version={selectedVersion}
|
||||||
|
s3Supported={s3Supported}
|
||||||
|
remoteSupported={remoteSupported}/>);
|
||||||
|
const pinnedManagerDisplay = createModalConditionally(showPinnedManager, <PinnedManager
|
||||||
|
version={selectedVersion}/>)
|
||||||
const confirmDisplay = createModalConditionally(this.props.DisplayConfirmYesNo, <YesNo/>);
|
const confirmDisplay = createModalConditionally(this.props.DisplayConfirmYesNo, <YesNo/>);
|
||||||
const dependencyDisplay = createModalConditionally(showDependencies, <DependencyList/>);
|
const dependencyDisplay = createModalConditionally(showDependencies,
|
||||||
const downloadDisplay = createModalConditionally(this.props.DownloadActive, <DownloadProgress/>);
|
<DependencyList/>, false, this.props.InstallActive);
|
||||||
|
const downloadDisplay = createModalConditionally(this.props.DownloadActive,
|
||||||
|
<DownloadProgress/>, false, true);
|
||||||
const errorDisplay = createModalConditionally(this.props.DisplayError, <ErrorDetails/>, true);
|
const errorDisplay = createModalConditionally(this.props.DisplayError, <ErrorDetails/>, true);
|
||||||
const infoDisplay = createModalConditionally(this.props.DisplayInfo, <InfoDetails/>, true);
|
const infoDisplay = createModalConditionally(this.props.DisplayInfo, <InfoDetails/>, true);
|
||||||
const rebootDisplay = createModalConditionally(this.props.RebootRequired, <Reboot />);
|
const newReleasesDisplay = createModalConditionally(showNewReleases, <NewReleases/>);
|
||||||
const selectAppPlatformDisplay = createModalConditionally(this.props.DisplaySelectAppPlatform, <SelectAppPlatform/>);
|
const rebootDisplay = createModalConditionally(this.props.RebootRequired, <Reboot/>);
|
||||||
|
const selectAppPlatformDisplay = createModalConditionally(this.props.DisplaySelectAppPlatform,
|
||||||
|
<SelectAppPlatform/>);
|
||||||
const upgradeDisplay = createModalConditionally(showUpgrade, <UpgradeUI/>);
|
const upgradeDisplay = createModalConditionally(showUpgrade, <UpgradeUI/>);
|
||||||
|
const importDisplay = createModalConditionally(showSkynetImport, <SkynetImport
|
||||||
|
version={selectedVersion}/>);
|
||||||
|
const exportDisplay = createModalConditionally(showSkynetExport, <SkynetExport
|
||||||
|
version={selectedVersion}/>)
|
||||||
|
const appBusyDisplay = createModalConditionally(this.props.AppBusy,
|
||||||
|
<ApplicationBusy/>, false, true, this.props.AppBusyTransparent);
|
||||||
|
|
||||||
let mainContent = [];
|
let mainContent = [];
|
||||||
if (this.props.DisplaySelectAppPlatform || !this.props.AppReady) {
|
if (this.props.DisplaySelectAppPlatform || !this.props.AppReady) {
|
||||||
@@ -142,7 +223,18 @@ class App extends IPCContainer {
|
|||||||
mainContent.push((
|
mainContent.push((
|
||||||
<Box dxStyle={{padding: 'var(--default_spacing)', height: 'auto'}}
|
<Box dxStyle={{padding: 'var(--default_spacing)', height: 'auto'}}
|
||||||
key={'md_' + key++}>
|
key={'md_' + key++}>
|
||||||
<MountItems remoteSupported={remoteSupported}/>
|
<MountItems s3Supported={s3Supported}
|
||||||
|
remoteSupported={remoteSupported}
|
||||||
|
scPrimeSupported={scPrimeSupported}
|
||||||
|
siaSupported={siaSupported}
|
||||||
|
skynetSupported={skynetSupported}/>
|
||||||
|
</Box>
|
||||||
|
));
|
||||||
|
} else if (selectedVersion !== 'unavailable') {
|
||||||
|
mainContent.push((
|
||||||
|
<Box dxStyle={{padding: 'var(--default_spacing)', height: '170px'}}
|
||||||
|
key={'md_' + key++}>
|
||||||
|
<Loading/>
|
||||||
</Box>
|
</Box>
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -162,12 +254,13 @@ class App extends IPCContainer {
|
|||||||
textAlign={'center'}
|
textAlign={'center'}
|
||||||
type={'Heading1'}/>
|
type={'Heading1'}/>
|
||||||
<UpgradeIcon
|
<UpgradeIcon
|
||||||
available={this.props.UpgradeAvailable}
|
available={this.props.UpgradeAvailable || (this.props.NewReleasesAvailable2.length > 0)}
|
||||||
clicked={()=>this.props.setDismissUIUpgrade(false)}
|
newReleases={!this.props.UpgradeAvailable && (this.props.NewReleasesAvailable2.length > 0)}
|
||||||
|
clicked={this.handleUpgradeIconClicked}
|
||||||
col={dimensions => dimensions.columns - 6}
|
col={dimensions => dimensions.columns - 6}
|
||||||
colSpan={5}
|
colSpan={5}
|
||||||
row={1}
|
row={1}
|
||||||
rowSpan={remain=>remain - 1}/>
|
rowSpan={remain => remain - 1}/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
</div>
|
</div>
|
||||||
@@ -175,14 +268,19 @@ class App extends IPCContainer {
|
|||||||
{mainContent}
|
{mainContent}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{importDisplay}
|
||||||
|
{exportDisplay}
|
||||||
|
{newReleasesDisplay}
|
||||||
{selectAppPlatformDisplay}
|
{selectAppPlatformDisplay}
|
||||||
{dependencyDisplay}
|
{dependencyDisplay}
|
||||||
{upgradeDisplay}
|
{upgradeDisplay}
|
||||||
|
{pinnedManagerDisplay}
|
||||||
{configDisplay}
|
{configDisplay}
|
||||||
{infoDisplay}
|
{infoDisplay}
|
||||||
{confirmDisplay}
|
{confirmDisplay}
|
||||||
{downloadDisplay}
|
{downloadDisplay}
|
||||||
{rebootDisplay}
|
{rebootDisplay}
|
||||||
|
{appBusyDisplay}
|
||||||
{errorDisplay}
|
{errorDisplay}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -194,19 +292,27 @@ const mapStateToProps = state => {
|
|||||||
AllowDownload: state.download.AllowDownload,
|
AllowDownload: state.download.AllowDownload,
|
||||||
AllowMount: state.common.AllowMount,
|
AllowMount: state.common.AllowMount,
|
||||||
AppPlatform: state.common.AppPlatform,
|
AppPlatform: state.common.AppPlatform,
|
||||||
|
AppBusy: state.common.AppBusy,
|
||||||
|
AppBusyTransparent: state.common.AppBusyTransparent,
|
||||||
AppReady: state.common.AppReady,
|
AppReady: state.common.AppReady,
|
||||||
DismissDependencies: state.install.DismissDependencies,
|
DismissDependencies: state.install.DismissDependencies,
|
||||||
DisplayConfiguration: state.mounts.DisplayConfiguration,
|
DisplayConfiguration: state.mounts.DisplayConfiguration,
|
||||||
DisplayConfirmYesNo: state.common.DisplayConfirmYesNo,
|
DisplayConfirmYesNo: state.common.DisplayConfirmYesNo,
|
||||||
DisplayError: state.error.DisplayError,
|
DisplayError: state.error.DisplayError,
|
||||||
|
DisplayExport: state.skynet.DisplayExport,
|
||||||
|
DisplayImport: state.skynet.DisplayImport,
|
||||||
DisplayInfo: state.error.DisplayInfo,
|
DisplayInfo: state.error.DisplayInfo,
|
||||||
|
DisplayPinnedManager: state.pinned.DisplayPinnedManager,
|
||||||
DisplaySelectAppPlatform: state.common.DisplaySelectAppPlatform,
|
DisplaySelectAppPlatform: state.common.DisplaySelectAppPlatform,
|
||||||
|
DismissNewReleasesAvailable: state.relver.DismissNewReleasesAvailable,
|
||||||
DownloadActive: state.download.DownloadActive,
|
DownloadActive: state.download.DownloadActive,
|
||||||
InstallActive: state.install.InstallActive,
|
InstallActive: state.install.InstallActive,
|
||||||
InstalledVersion: state.relver.InstalledVersion,
|
InstalledVersion: state.relver.InstalledVersion,
|
||||||
LocationsLookup: state.relver.LocationsLookup,
|
LocationsLookup: state.relver.LocationsLookup,
|
||||||
MissingDependencies: state.install.MissingDependencies,
|
MissingDependencies: state.install.MissingDependencies,
|
||||||
MountsBusy: state.mounts.MountsBusy,
|
MountsBusy: state.mounts.MountsBusy,
|
||||||
|
NewReleasesAvailable: state.relver.NewReleasesAvailable,
|
||||||
|
NewReleasesAvailable2: state.relver.NewReleasesAvailable2,
|
||||||
Platform: state.common.Platform,
|
Platform: state.common.Platform,
|
||||||
ProviderState: state.mounts.ProviderState,
|
ProviderState: state.mounts.ProviderState,
|
||||||
RebootRequired: state.common.RebootRequired,
|
RebootRequired: state.common.RebootRequired,
|
||||||
@@ -222,9 +328,11 @@ const mapStateToProps = state => {
|
|||||||
const mapDispatchToProps = dispatch => {
|
const mapDispatchToProps = dispatch => {
|
||||||
return {
|
return {
|
||||||
displaySelectAppPlatform: display => dispatch(displaySelectAppPlatform(display)),
|
displaySelectAppPlatform: display => dispatch(displaySelectAppPlatform(display)),
|
||||||
loadReleases: ()=> dispatch(loadReleases()),
|
loadReleases: () => dispatch(loadReleases()),
|
||||||
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
|
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
|
||||||
saveState: () => dispatch(saveState()),
|
saveState: () => dispatch(saveState()),
|
||||||
|
setDismissNewReleasesAvailable: dismiss => dispatch(setDismissNewReleasesAvailable(dismiss)),
|
||||||
|
setNewReleasesAvailable: items => dispatch(setNewReleasesAvailable(items)),
|
||||||
setDismissUIUpgrade: dismiss => dispatch(setDismissUIUpgrade(dismiss)),
|
setDismissUIUpgrade: dismiss => dispatch(setDismissUIUpgrade(dismiss)),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 70 KiB |
@@ -30,12 +30,19 @@
|
|||||||
"EventLevel": "Internally, events are fired during certain operations. This setting determines which events should be logged to repertory.log. Valid values are Error, Warn, Normal, Debug, and Verbose.",
|
"EventLevel": "Internally, events are fired during certain operations. This setting determines which events should be logged to repertory.log. Valid values are Error, Warn, Normal, Debug, and Verbose.",
|
||||||
"EvictionDelaySeconds": "Number of seconds to wait after all file handles are closed before allowing file to be evicted from cache.",
|
"EvictionDelaySeconds": "Number of seconds to wait after all file handles are closed before allowing file to be evicted from cache.",
|
||||||
"EvictionDelayMinutes": "Number of minutes to wait after all file handles are closed before allowing file to be evicted from cache.",
|
"EvictionDelayMinutes": "Number of minutes to wait after all file handles are closed before allowing file to be evicted from cache.",
|
||||||
|
"EvictionUsesAccessedTime": "Use oldest accessed time instead of oldest modified time when evicting files.",
|
||||||
"MaxCacheSizeBytes": "This value specifies the maximum amount of local space to consume before files are removed from cache. EnableMaxCacheSize must also be set to true for this value to take affect.",
|
"MaxCacheSizeBytes": "This value specifies the maximum amount of local space to consume before files are removed from cache. EnableMaxCacheSize must also be set to true for this value to take affect.",
|
||||||
|
"MaxUploadCount": "Maximum number of simultaneous uploads.",
|
||||||
"MinimumRedundancy": "Files are elected for removal once this value has been reached. Be aware that this value cannot be set to less than 1.5x.",
|
"MinimumRedundancy": "Files are elected for removal once this value has been reached. Be aware that this value cannot be set to less than 1.5x.",
|
||||||
"OnlineCheckRetrySeconds": "Number of seconds to wait for Sia/ScPrime daemon to become available/connectable.",
|
"OnlineCheckRetrySeconds": "Number of seconds to wait for Sia/ScPrime daemon to become available/connectable.",
|
||||||
"OrphanedFileRetentionDays": "Repertory attempts to keep modifications between Sia-UI and the mounted location in sync as much as possible. In the event a file is removed from Sia-UI, it will be marked as orphaned in Repertory and moved into an 'orphaned' directory within Repertory's data directory. This setting specifies the number of days this file is retained before final deletion.",
|
"OrphanedFileRetentionDays": "Repertory attempts to keep modifications between Sia-UI and the mounted location in sync as much as possible. In the event a file is removed from Sia-UI, it will be marked as orphaned in Repertory and moved into an 'orphaned' directory within Repertory's data directory. This setting specifies the number of days this file is retained before final deletion.",
|
||||||
"PreferredDownloadType": "Repertory supports 3 download modes for reading files that are not cached locally: full file allocation, ring buffer mode and direct mode.\n\nFull file allocation mode pre-allocates the entire file prior to downloading. This mode is required for writes but also ensures the best performance when reading data.\n\nRing buffer mode utilizes a fixed size file buffer to enable a reasonable amount of seeking. This alleviates the need to fully allocate a file. By default, it is 512MiB. When the buffer is full, it attempts to maintain the ability to seek 50% ahead or behind the current read location without the need to re-download data from Sia/ScPrime.\n\nDirect mode utilizes no disk space. All data is read directly from Sia/ScPrime.\n\nPreferred download type modes are:\n\nFallback - If there isn't enough local space to allocate the full file, ring buffer mode is used. If there isn't enough local space to create the ring buffer's file, then direct mode is used.\nRingBuffer - Full file allocation is always bypassed; however, if there isn't enough space to create the ring buffer's file, then direct mode will be chosen.\nDirect - All files will be read directly from Sia/ScPrime.",
|
"PreferredDownloadType": "Repertory supports 3 download modes for reading files that are not cached locally: full file allocation, ring buffer mode and direct mode.\n\nFull file allocation mode pre-allocates the entire file prior to downloading. This mode is required for writes but also ensures the best performance when reading data.\n\nRing buffer mode utilizes a fixed size file buffer to enable a reasonable amount of seeking. This alleviates the need to fully allocate a file. By default, it is 512MiB. When the buffer is full, it attempts to maintain the ability to seek 50% ahead or behind the current read location without the need to re-download data from Sia/ScPrime.\n\nDirect mode utilizes no disk space. All data is read directly from Sia/ScPrime.\n\nPreferred download type modes are:\n\nFallback - If there isn't enough local space to allocate the full file, ring buffer mode is used. If there isn't enough local space to create the ring buffer's file, then direct mode is used.\nRingBuffer - Full file allocation is always bypassed; however, if there isn't enough space to create the ring buffer's file, then direct mode will be chosen.\nDirect - All files will be read directly from Sia/ScPrime.",
|
||||||
"ReadAheadCount": "This value specifies the number of read-ahead chunks to use when downloading a file. This is a per-open file setting and will result in the creation of an equal number of threads.",
|
"ReadAheadCount": "This value specifies the number of read-ahead chunks to use when downloading a file. This is a per-open file setting and will result in the creation of an equal number of threads.",
|
||||||
|
"RetryReadCount": "Number of times to retry a failed read operation. A 1 second delay is used between retries. This setting applies to downloads only.",
|
||||||
"RingBufferFileSize": "The size of the ring buffer file in MiB. Default is 512. Valid values are: 64, 128, 256, 512, 1024."
|
"RingBufferFileSize": "The size of the ring buffer file in MiB. Default is 512. Valid values are: 64, 128, 256, 512, 1024."
|
||||||
|
},
|
||||||
|
"SkynetConfig": {
|
||||||
|
"EncryptionToken": "Encryption token used to encrypt files in Skynet. Set this value once as it applies to all files stored.",
|
||||||
|
"PortalList": "List of Skynet portals used to load-balance uploads and downloads."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
21
src/components/ApplicationBusy/ApplicationBusy.js
Normal file
21
src/components/ApplicationBusy/ApplicationBusy.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Box from '../UI/Box/Box';
|
||||||
|
import Loader from 'react-loader-spinner';
|
||||||
|
import Text from '../UI/Text/Text';
|
||||||
|
|
||||||
|
export default ({title}) => {
|
||||||
|
return (
|
||||||
|
<Box dxStyle={{padding: 'var(--default_spacing)'}}>
|
||||||
|
<Text
|
||||||
|
text={title || 'Please Wait...'}
|
||||||
|
textAlign={'center'}
|
||||||
|
type={'Heading1'}/>
|
||||||
|
<div style={{paddingLeft: 'calc(50% - 16px)', paddingTop: 'var(--default_spacing)'}}>
|
||||||
|
<Loader color={'var(--heading_text_color)'}
|
||||||
|
height={32}
|
||||||
|
width={32}
|
||||||
|
type='TailSpin'/>
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -22,9 +22,9 @@ export default connect(mapStateToProps)(props => {
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{props.AllowDownload ?
|
{props.AllowDownload ?
|
||||||
<a href={void(0)}
|
<a href={'#'}
|
||||||
className={'DependencyLink'}
|
className={'DependencyLink'}
|
||||||
onClick={()=>{props.onDownload(); return false;}}><u>Install</u></a> :
|
onClick={()=>{props.onDownload(); return false;}}><u>Install</u></a> :
|
||||||
'Installing...'}
|
'Installing...'}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -31,15 +31,13 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
let dismissDisplay;
|
const dismissDisplay = (
|
||||||
if (props.AllowDismissDependencies) {
|
<div style={{float: 'right', margin: 0, paddingRight: '4px', boxSizing: 'border-box', display: 'block'}}>
|
||||||
dismissDisplay = (
|
<a href={'#'}
|
||||||
<div style={{float: 'right', margin: 0, paddingRight: '4px', boxSizing: 'border-box', display: 'block'}}>
|
onClick={props.AllowDismissDependencies ? () => props.setDismissDependencies(true) : e => e.preventDefault()}
|
||||||
<b style={{cursor: 'pointer'}}
|
style={{cursor: props.AllowDismissDependencies ? 'pointer' : 'no-drop'}}>X</a>
|
||||||
onClick={()=>props.setDismissDependencies(true)}>X
|
</div>
|
||||||
</b>
|
);
|
||||||
</div>);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box dxStyle={{width: '300px', height: 'auto', padding: '5px'}}>
|
<Box dxStyle={{width: '300px', height: 'auto', padding: '5px'}}>
|
||||||
|
|||||||
@@ -6,6 +6,14 @@
|
|||||||
.InfoDetailsContent {
|
.InfoDetailsContent {
|
||||||
max-height: 60vh;
|
max-height: 60vh;
|
||||||
min-width: 80vw;
|
min-width: 80vw;
|
||||||
|
max-width: 90vw;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: pre-line;
|
||||||
margin-bottom: var(--default_spacing);
|
margin-bottom: var(--default_spacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.InfoDetailsContent.Alternate {
|
||||||
|
white-space: pre;
|
||||||
|
hyphens: none;
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,11 +18,48 @@ const mapDispatchToProps = dispatch => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
||||||
|
let msg = props.InfoMessage.message;
|
||||||
|
const classes = ['InfoDetailsContent'];
|
||||||
|
|
||||||
|
let changed = true;
|
||||||
|
let copyable = false;
|
||||||
|
while (changed) {
|
||||||
|
changed = false;
|
||||||
|
if (msg.startsWith('!alternate!')) {
|
||||||
|
classes.push('Alternate');
|
||||||
|
msg = msg.substr('!alternate!'.length);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (msg.startsWith('!copyable!')) {
|
||||||
|
classes.push('Copyable');
|
||||||
|
msg = msg.substr('!copyable!'.length);
|
||||||
|
copyable = changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const scrollToTop = textArea => {
|
||||||
|
if (!textArea.firstClick) {
|
||||||
|
textArea.firstClick = true;
|
||||||
|
textArea.scrollTop = 0;
|
||||||
|
textArea.setSelectionRange(0, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box dxDark dxStyle={{padding: 'var(--default_spacing)'}}>
|
<Box dxDark dxStyle={{padding: 'var(--default_spacing)'}}>
|
||||||
<h1 className={'InfoDetailsHeading'}>{props.InfoMessage.title}</h1>
|
<h1 className={'InfoDetailsHeading'}>{props.InfoMessage.title}</h1>
|
||||||
<div className={'InfoDetailsContent'}>
|
<div className={classes.join(' ')}>
|
||||||
<p style={{textAlign: 'left', whiteSpace: 'pre-line'}}>{props.InfoMessage.message}</p>
|
{
|
||||||
|
copyable ? (
|
||||||
|
<textarea autoFocus
|
||||||
|
rows={9}
|
||||||
|
value={msg}
|
||||||
|
className={'SkynetImportTextArea'}
|
||||||
|
onClick={e => scrollToTop(e.target)}/>
|
||||||
|
) : (
|
||||||
|
<p style={{textAlign: 'left'}}>{msg}</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<Button clicked={props.dismissInfo}>Dismiss</Button>
|
<Button clicked={props.dismissInfo}>Dismiss</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
57
src/components/NewReleases/NewRelease/NewRelease.js
Normal file
57
src/components/NewReleases/NewRelease/NewRelease.js
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {connect} from 'react-redux';
|
||||||
|
import * as Constants from '../../../constants';
|
||||||
|
import Button from '../../UI/Button/Button';
|
||||||
|
import {formatLinesForDisplay, getChangesForRepertoryVersion} from '../../../utils';
|
||||||
|
import {
|
||||||
|
notifyError,
|
||||||
|
notifyInfo
|
||||||
|
} from '../../../redux/actions/error_actions';
|
||||||
|
import {installReleaseByVersion} from '../../../redux/actions/install_actions';
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
installReleaseByVersion: (release, version) => dispatch(installReleaseByVersion(release, version)),
|
||||||
|
notifyError: msg => dispatch(notifyError(msg)),
|
||||||
|
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(null, mapDispatchToProps)(({dismiss, release, lastItem, notifyError, notifyInfo, installReleaseByVersion}) => {
|
||||||
|
const title = '[' + Constants.RELEASE_TYPES[release.Release] + '] ' + release.Display;
|
||||||
|
const installReleaseVersion = () => {
|
||||||
|
dismiss();
|
||||||
|
installReleaseByVersion(release.Release, release.Version);
|
||||||
|
};
|
||||||
|
const displayChanges = async () => {
|
||||||
|
try {
|
||||||
|
const lines = await getChangesForRepertoryVersion(release.VersionString);
|
||||||
|
notifyInfo(title, formatLinesForDisplay(lines));
|
||||||
|
} catch (e) {
|
||||||
|
notifyError(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2>{title}</h2>
|
||||||
|
<table cellSpacing={0} cellPadding={0} width="97%">
|
||||||
|
<tbody>
|
||||||
|
<tr style={{height: '4px'}}/>
|
||||||
|
<tr>
|
||||||
|
<td width="50%">
|
||||||
|
<Button buttonStyles={{width: '100%'}} clicked={displayChanges}>Changes</Button>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div style={{width: 'var(--default_spacing)'}}/>
|
||||||
|
</td>
|
||||||
|
<td width="50%">
|
||||||
|
<Button buttonStyles={{width: '100%'}} clicked={installReleaseVersion}>Install</Button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{lastItem ? null : <tr style={{height: 'var(--default_spacing)'}}/>}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
11
src/components/NewReleases/NewReleases.css
Normal file
11
src/components/NewReleases/NewReleases.css
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
.NewReleasesHeading {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.NewReleasesContent {
|
||||||
|
max-height: 60vh;
|
||||||
|
min-width: 50vw;
|
||||||
|
overflow-y: auto;
|
||||||
|
margin-bottom: var(--default_spacing);
|
||||||
|
}
|
||||||
38
src/components/NewReleases/NewReleases.js
Normal file
38
src/components/NewReleases/NewReleases.js
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {connect} from 'react-redux';
|
||||||
|
import Box from '../UI/Box/Box';
|
||||||
|
import Button from '../UI/Button/Button';
|
||||||
|
import NewRelease from './NewRelease/NewRelease';
|
||||||
|
import './NewReleases.css';
|
||||||
|
import {setDismissNewReleasesAvailable} from '../../redux/actions/release_version_actions';
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
return {
|
||||||
|
NewReleasesAvailable: state.relver.NewReleasesAvailable,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
dismissNewReleasesAvailable: () => dispatch(setDismissNewReleasesAvailable(true)),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
||||||
|
const newReleases = props.NewReleasesAvailable.map((i, idx) => {
|
||||||
|
return <NewRelease dismiss={props.dismissNewReleasesAvailable}
|
||||||
|
key={'new_release_' + i.Release + '_' + i.Version}
|
||||||
|
lastItem={idx === (props.NewReleasesAvailable.length - 1)}
|
||||||
|
release={i} />;
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box dxDark dxStyle={{padding: 'var(--default_spacing)'}}>
|
||||||
|
<h1 className={'NewReleasesHeading'}>New Repertory Versions Available</h1>
|
||||||
|
<div className={'NewReleasesContent'}>
|
||||||
|
{newReleases}
|
||||||
|
</div>
|
||||||
|
<Button clicked={props.dismissNewReleasesAvailable}>Dismiss</Button>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
});
|
||||||
@@ -12,6 +12,7 @@ import {downloadItem} from '../../redux/actions/download_actions';
|
|||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
return {
|
return {
|
||||||
|
AllowMount: state.common.AllowMount,
|
||||||
AppPlatform: state.common.AppPlatform,
|
AppPlatform: state.common.AppPlatform,
|
||||||
DismissDependencies: state.install.DismissDependencies,
|
DismissDependencies: state.install.DismissDependencies,
|
||||||
DownloadActive: state.download.DownloadActive,
|
DownloadActive: state.download.DownloadActive,
|
||||||
@@ -35,6 +36,12 @@ const mapDispatchToProps = dispatch => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
||||||
|
const getSelectedVersion = () => {
|
||||||
|
return (props.ReleaseVersion === -1) ?
|
||||||
|
'unavailable' :
|
||||||
|
props.VersionLookup[Constants.RELEASE_TYPES[props.Release]][props.ReleaseVersion];
|
||||||
|
};
|
||||||
|
|
||||||
const handleDownloadRelease = () => {
|
const handleDownloadRelease = () => {
|
||||||
const fileName = props.version + '.zip';
|
const fileName = props.version + '.zip';
|
||||||
props.downloadItem(fileName, Constants.INSTALL_TYPES.Release, props.LocationsLookup[props.version].urls);
|
props.downloadItem(fileName, Constants.INSTALL_TYPES.Release, props.LocationsLookup[props.version].urls);
|
||||||
@@ -52,7 +59,10 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const text = props.InstalledVersion + ' [' + props.AppPlatform + ']';
|
const text = props.InstalledVersion + ' [' + props.AppPlatform + ']';
|
||||||
const disabled = props.DownloadActive || props.InstallActive || props.MountsBusy;
|
const disabled = props.DownloadActive ||
|
||||||
|
props.InstallActive ||
|
||||||
|
props.MountsBusy ||
|
||||||
|
(!props.AllowMount && (getSelectedVersion() !== 'unavailable')) ;
|
||||||
const releaseExtracting = (props.InstallType === Constants.INSTALL_TYPES.Release);
|
const releaseExtracting = (props.InstallType === Constants.INSTALL_TYPES.Release);
|
||||||
|
|
||||||
let optionsDisplay = [];
|
let optionsDisplay = [];
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import './Button.css';
|
|||||||
export default props => {
|
export default props => {
|
||||||
return (
|
return (
|
||||||
<button disabled={props.disabled}
|
<button disabled={props.disabled}
|
||||||
|
autoFocus={props.autoFocus}
|
||||||
className={'Button'}
|
className={'Button'}
|
||||||
style={props.buttonStyles}
|
style={props.buttonStyles}
|
||||||
onClick={props.clicked}>{props.children}</button>
|
onClick={props.clicked}>{props.children}</button>
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ label.CheckBoxLabel .CheckBoxCheckMark:after {
|
|||||||
top: 1px;
|
top: 1px;
|
||||||
width: 5px;
|
width: 5px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
border: solid var(--heading_text_color);
|
border: solid var(--heading_other_text_color);
|
||||||
border-width: 0 3px 3px 0;
|
border-width: 0 3px 3px 0;
|
||||||
-webkit-transform: rotate(45deg);
|
-webkit-transform: rotate(45deg);
|
||||||
-ms-transform: rotate(45deg);
|
-ms-transform: rotate(45deg);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export default props => {
|
|||||||
<div className={'CheckBoxOwner'}>
|
<div className={'CheckBoxOwner'}>
|
||||||
<label className='CheckBoxLabel'>{props.label}
|
<label className='CheckBoxLabel'>{props.label}
|
||||||
<input checked={JSON.parse(props.checked)}
|
<input checked={JSON.parse(props.checked)}
|
||||||
|
autoFocus={props.autoFocus}
|
||||||
disabled={props.disabled}
|
disabled={props.disabled}
|
||||||
onChange={props.changed}
|
onChange={props.changed}
|
||||||
type='checkbox'/>
|
type='checkbox'/>
|
||||||
|
|||||||
@@ -6,30 +6,18 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.DropDownSelect {
|
.DropDownSelect, .DropDownSelect.Alt {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
border-radius: var(--border_radius);
|
border-radius: var(--border_radius);
|
||||||
background: rgba(10, 10, 20, 0.75);
|
background: var(--control_background);
|
||||||
border-color: rgba(10, 10, 20, 0.9);
|
|
||||||
color: var(--text_color);
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.DropDownSelect.Alt {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: block;
|
|
||||||
margin: 0;
|
|
||||||
padding: 2px;
|
|
||||||
border-radius: var(--border_radius);
|
|
||||||
background: rgba(160, 160, 160, 0.1);
|
|
||||||
border: none;
|
border: none;
|
||||||
color: var(--text_color);
|
color: var(--text_color);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
outline: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.DropDownSelect.Auto {
|
.DropDownSelect.Auto {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export default props => {
|
|||||||
return (
|
return (
|
||||||
<div className={'DropDown'}>
|
<div className={'DropDown'}>
|
||||||
<select className={'DropDownSelect' + (props.auto ? ' Auto ' : '') + (props.alt ? ' Alt ' : '') }
|
<select className={'DropDownSelect' + (props.auto ? ' Auto ' : '') + (props.alt ? ' Alt ' : '') }
|
||||||
|
autoFocus={props.autoFocus}
|
||||||
disabled={props.disabled}
|
disabled={props.disabled}
|
||||||
onChange={props.changed}
|
onChange={props.changed}
|
||||||
value={props.selected}>
|
value={props.selected}>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
import './Loading.css'
|
import './Loading.css'
|
||||||
import Loader from 'react-loader-spinner';
|
import Loader from 'react-loader-spinner';
|
||||||
|
|
||||||
export default props => {
|
export default () => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={'Loading'}>
|
className={'Loading'}>
|
||||||
|
|||||||
@@ -8,6 +8,10 @@
|
|||||||
z-index: 2000;
|
z-index: 2000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Modal.Transparent {
|
||||||
|
background-color: rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
.ModalContent {
|
.ModalContent {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import './Modal.css'
|
import './Modal.css'
|
||||||
|
import FocusTrap from 'focus-trap-react';
|
||||||
|
|
||||||
export default props => {
|
export default props => {
|
||||||
let modalStyles = [];
|
let modalStyles = [];
|
||||||
@@ -11,12 +13,19 @@ export default props => {
|
|||||||
contentStyles.push('ModalCritical');
|
contentStyles.push('ModalCritical');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (props.transparent) {
|
||||||
|
modalStyles.push('Transparent');
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<FocusTrap active={!props.disableFocusTrap}>
|
||||||
className={modalStyles.join(' ')}
|
<div
|
||||||
onClick={props.clicked}>
|
className={modalStyles.join(' ')}
|
||||||
<div className={contentStyles.join(' ')}>
|
onClick={props.clicked}>
|
||||||
{props.children}
|
<div className={contentStyles.join(' ')}>
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>);
|
</FocusTrap>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
@@ -17,5 +17,9 @@
|
|||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
opacity: 0.65;
|
color: var(--heading_text_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.UpgradeIcon.Release {
|
||||||
|
color: var(--heading_other_text_color);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,13 +1,19 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './UpgradeIcon.css';
|
import './UpgradeIcon.css';
|
||||||
import availableImage from '../../assets/images/release_available.png';
|
|
||||||
import ReactTooltip from 'react-tooltip';
|
import ReactTooltip from 'react-tooltip';
|
||||||
|
import {faExclamationTriangle} from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||||
|
|
||||||
export default props => {
|
export default props => {
|
||||||
|
const styles = ['UpgradeIcon'];
|
||||||
let placement = 'left';
|
let placement = 'left';
|
||||||
let toolTipText = 'UI Upgrade Available';
|
let toolTipText = 'UI Upgrade Available';
|
||||||
if (props.release) {
|
if (props.release) {
|
||||||
placement='bottom';
|
placement='bottom';
|
||||||
|
styles.push('Release');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.release || props.newReleases) {
|
||||||
toolTipText = 'New Release Available';
|
toolTipText = 'New Release Available';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,10 +22,11 @@ export default props => {
|
|||||||
(
|
(
|
||||||
<div className={'UpgradeIconOwner'}>
|
<div className={'UpgradeIconOwner'}>
|
||||||
<p data-tip='' data-for={placement}>
|
<p data-tip='' data-for={placement}>
|
||||||
<img alt=''
|
<a href={'#'}
|
||||||
onClick={props.clicked}
|
className={styles.join(' ')}
|
||||||
src={availableImage}
|
onClick={props.clicked}>
|
||||||
className={'UpgradeIcon'}/>
|
<FontAwesomeIcon icon={faExclamationTriangle}/>
|
||||||
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<ReactTooltip id={placement} place={placement}>{toolTipText}</ReactTooltip>
|
<ReactTooltip id={placement} place={placement}>{toolTipText}</ReactTooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
165
src/constants.js
165
src/constants.js
@@ -1,63 +1,110 @@
|
|||||||
Object.defineProperty(exports, "__esModule", {
|
Object.defineProperty(exports, '__esModule', {value : true});
|
||||||
value: true
|
exports.DEV_PUBLIC_KEY =
|
||||||
});
|
'-----BEGIN PUBLIC KEY-----\n' +
|
||||||
exports.DEV_PUBLIC_KEY = '-----BEGIN PUBLIC KEY-----\n' +
|
'MIIEIjANBgkqhkiG9w0BAQEFAAOCBA8AMIIECgKCBAEKfZmq5mMAtD4kSt2Gc/5J\n' +
|
||||||
'MIIEIjANBgkqhkiG9w0BAQEFAAOCBA8AMIIECgKCBAEKfZmq5mMAtD4kSt2Gc/5J\n' +
|
'H+HHTYtUZE6YYvsvz8TNG/bNL67ZtNRyaoMyhLTfIN4rPBNLUfD+owNS+u5Yk+lS\n' +
|
||||||
'H+HHTYtUZE6YYvsvz8TNG/bNL67ZtNRyaoMyhLTfIN4rPBNLUfD+owNS+u5Yk+lS\n' +
|
'ZLYyOuhoCZIFefayYqKLr42G8EeuRbx0IMzXmJtN0a4rqxlWhkYufJubpdQ+V4DF\n' +
|
||||||
'ZLYyOuhoCZIFefayYqKLr42G8EeuRbx0IMzXmJtN0a4rqxlWhkYufJubpdQ+V4DF\n' +
|
'oeupcPdIATaadCKVeZC7A0G0uaSwoiAVMG5dZqjQW7F2LoQm3PhNkPvAybIJ6vBy\n' +
|
||||||
'oeupcPdIATaadCKVeZC7A0G0uaSwoiAVMG5dZqjQW7F2LoQm3PhNkPvAybIJ6vBy\n' +
|
'LqdBegS1JrDn43x/pvQHzLO+l+FIG23D1F7iF+yZm3DkzBdcmi/mOMYs/rXZpBym\n' +
|
||||||
'LqdBegS1JrDn43x/pvQHzLO+l+FIG23D1F7iF+yZm3DkzBdcmi/mOMYs/rXZpBym\n' +
|
'2/kTuSGh5buuJCeyOwR8N3WdvXw6+KHMU/wWU8qTCTT87mYbzH4YR8HgkjkLHxAO\n' +
|
||||||
'2/kTuSGh5buuJCeyOwR8N3WdvXw6+KHMU/wWU8qTCTT87mYbzH4YR8HgkjkLHxAO\n' +
|
'5waHK6vMu0TxugCdJmVV6BSbiarJsh66VRosn7+6hlq6AdgksxqCeNELZBS+LBki\n' +
|
||||||
'5waHK6vMu0TxugCdJmVV6BSbiarJsh66VRosn7+6hlq6AdgksxqCeNELZBS+LBki\n' +
|
'tb5hKyL+jNZnaHiR0U7USWtmnqZG6FVVRzlCnxP7tZo5O5Ex9AAFGz5JzOzsFNbv\n' +
|
||||||
'tb5hKyL+jNZnaHiR0U7USWtmnqZG6FVVRzlCnxP7tZo5O5Ex9AAFGz5JzOzsFNbv\n' +
|
'xwQ0zqaTQOze+MJbkda7JfRoC6TncD0+3hoXsiaF4mCn8PqUCn0DwhglcRucZlST\n' +
|
||||||
'xwQ0zqaTQOze+MJbkda7JfRoC6TncD0+3hoXsiaF4mCn8PqUCn0DwhglcRucZlST\n' +
|
'ZvDNDo1WAtxPJebb3aS6uymNhBIquQbVAWxVO4eTrOYEgutxwkHE3yO3is+ogp8d\n' +
|
||||||
'ZvDNDo1WAtxPJebb3aS6uymNhBIquQbVAWxVO4eTrOYEgutxwkHE3yO3is+ogp8d\n' +
|
'xot7f/+vzlbsbIDyuZBDe0fFkbTIMTU48QuUUVZpRKmKZTHQloz4EHqminbfX1sh\n' +
|
||||||
'xot7f/+vzlbsbIDyuZBDe0fFkbTIMTU48QuUUVZpRKmKZTHQloz4EHqminbfX1sh\n' +
|
'M7wvDkpJEtqbc0VnG/BukUzP6e7Skvgc7eF1sI3+8jH8du2rivZeZAl7Q2f+L9JA\n' +
|
||||||
'M7wvDkpJEtqbc0VnG/BukUzP6e7Skvgc7eF1sI3+8jH8du2rivZeZAl7Q2f+L9JA\n' +
|
'BY9pjaxttxsud7V5jeFi4tKuDHi21/XhSjlJK2c2C4AiUEK5/WhtGbQ5JjmcOjRq\n' +
|
||||||
'BY9pjaxttxsud7V5jeFi4tKuDHi21/XhSjlJK2c2C4AiUEK5/WhtGbQ5JjmcOjRq\n' +
|
'yXFRqLlerzOcop2kbtU3Ar230wOx3Dj23Wg8++lV3LU4U9vMR/t0qnSbCSGJys7m\n' +
|
||||||
'yXFRqLlerzOcop2kbtU3Ar230wOx3Dj23Wg8++lV3LU4U9vMR/t0qnSbCSGJys7m\n' +
|
'ax2JpFlTwj/0wYuTlVFoNQHZJ1cdfyRiRBY4Ou7XO0W5hcBBKiYsC+neEeMMHdCe\n' +
|
||||||
'ax2JpFlTwj/0wYuTlVFoNQHZJ1cdfyRiRBY4Ou7XO0W5hcBBKiYsC+neEeMMHdCe\n' +
|
'iTDIW/ojcVTdFovl+sq3n1u4SBknE90JC/3H+TPE1s2iB+fwORVg0KPosQSNDS0A\n' +
|
||||||
'iTDIW/ojcVTdFovl+sq3n1u4SBknE90JC/3H+TPE1s2iB+fwORVg0KPosQSNDS0A\n' +
|
'7iK6AZCDC3YooFo+OzHkYMt9uLkXiXMSLx70az+qlIwOzVHKxCo7W/QpeKCXUCRZ\n' +
|
||||||
'7iK6AZCDC3YooFo+OzHkYMt9uLkXiXMSLx70az+qlIwOzVHKxCo7W/QpeKCXUCRZ\n' +
|
'MMdlYEUs1PC8x2qIRUEVHuJ0XMTKNyOHmzVLuLK93wUWbToh+rdDxnbhX+emuESn\n' +
|
||||||
'MMdlYEUs1PC8x2qIRUEVHuJ0XMTKNyOHmzVLuLK93wUWbToh+rdDxnbhX+emuESn\n' +
|
'XH6aKiUwX4olEVKSylRUQw8nVckZGVWXzLDlgpzDrLHC8J8qHzFt7eCqOdiqsxhZ\n' +
|
||||||
'XH6aKiUwX4olEVKSylRUQw8nVckZGVWXzLDlgpzDrLHC8J8qHzFt7eCqOdiqsxhZ\n' +
|
'x1U5LtugxwSWncTZ7vlKl0DuC/AWB7SuDi7bGRMSVp2n+MnD1VLKlsCclHXjIciE\n' +
|
||||||
'x1U5LtugxwSWncTZ7vlKl0DuC/AWB7SuDi7bGRMSVp2n+MnD1VLKlsCclHXjIciE\n' +
|
'W29n3G3lJ/sOta2sxqLd0j1XBQddrFXl5b609sIY81ocHqu8P2hRu5CpqJ/sGZC5\n' +
|
||||||
'W29n3G3lJ/sOta2sxqLd0j1XBQddrFXl5b609sIY81ocHqu8P2hRu5CpqJ/sGZC5\n' +
|
'mMH3segHBkRj0xJcfOxceRLj1a+ULIIR3xL/3f8s5Id25TDo/nqBoCvu5PeCpo6L\n' +
|
||||||
'mMH3segHBkRj0xJcfOxceRLj1a+ULIIR3xL/3f8s5Id25TDo/nqBoCvu5PeCpo6L\n' +
|
'9wIDAQAB\n' +
|
||||||
'9wIDAQAB\n' +
|
'-----END PUBLIC KEY-----';
|
||||||
'-----END PUBLIC KEY-----';
|
|
||||||
|
|
||||||
const REPERTORY_BRANCH = 'master';
|
const _REPERTORY_BRANCH = 'master';
|
||||||
const REPERTORY_UI_BRANCH = 'master';
|
const _REPERTORY_UI_BRANCH = 'master';
|
||||||
|
|
||||||
exports.RELEASES_URL = 'https://bitbucket.org/blockstorage/repertory/raw/' + REPERTORY_BRANCH + '/releases_1.1.json';
|
exports.REPERTORY_BRANCH = _REPERTORY_BRANCH;
|
||||||
exports.UI_RELEASES_URL = 'https://bitbucket.org/blockstorage/repertory-ui/raw/' + REPERTORY_UI_BRANCH + '/releases.json';
|
exports.REPERTORY_UI_BRANCH = _REPERTORY_UI_BRANCH;
|
||||||
|
|
||||||
exports.LINUX_DETECT_SCRIPT_URL = 'https://bitbucket.org/blockstorage/repertory/raw/' + REPERTORY_BRANCH + '/detect_linux.sh';
|
exports.RELEASES_URL = 'https://bitbucket.org/blockstorage/repertory/raw/' +
|
||||||
|
_REPERTORY_BRANCH + '/releases_1.3.json';
|
||||||
|
exports.UI_RELEASES_URL =
|
||||||
|
'https://bitbucket.org/blockstorage/repertory-ui/raw/' +
|
||||||
|
_REPERTORY_UI_BRANCH + '/releases.json';
|
||||||
|
|
||||||
|
exports.LINUX_DETECT_SCRIPT_URL =
|
||||||
|
'https://bitbucket.org/blockstorage/repertory/raw/' + _REPERTORY_BRANCH +
|
||||||
|
'/detect_linux2.sh';
|
||||||
|
|
||||||
exports.LINUX_SELECTABLE_PLATFORMS = [
|
exports.LINUX_SELECTABLE_PLATFORMS = [
|
||||||
'ubuntu18.04',
|
'centos7',
|
||||||
'ubuntu18.10',
|
];
|
||||||
'ubuntu19.04',
|
|
||||||
'ubuntu19.10'
|
exports.WINFSP_VERSION_NAMES = [
|
||||||
|
'WinFsp 2019',
|
||||||
|
'WinFsp 2019.0',
|
||||||
|
'WinFsp 2019.1',
|
||||||
|
'WinFsp 2019.2',
|
||||||
|
'WinFsp 2019.3',
|
||||||
|
'WinFsp 2019.3 B1',
|
||||||
|
'WinFsp 2019.3 B2',
|
||||||
|
'WinFsp 2019.3 B3',
|
||||||
|
'WinFsp 2019.3 B4',
|
||||||
|
'WinFsp 2019.3 B5',
|
||||||
|
'WinFsp 2020',
|
||||||
|
'WinFsp 2020.0',
|
||||||
|
'WinFsp 2020.1',
|
||||||
|
'WinFsp 2020.2',
|
||||||
|
'WinFsp 2021 B1',
|
||||||
|
'WinFsp 2021 B2',
|
||||||
|
'WinFsp 2021 Beta1',
|
||||||
|
'WinFsp 2021 Beta2',
|
||||||
];
|
];
|
||||||
|
|
||||||
exports.DATA_LOCATIONS = {
|
exports.DATA_LOCATIONS = {
|
||||||
linux: '~/.local/repertory/ui',
|
linux : '~/.local/repertory/ui',
|
||||||
darwin: '~/Library/Application Support/repertory/ui',
|
darwin : '~/Library/Application Support/repertory/ui',
|
||||||
win32: '%LOCALAPPDATA%\\repertory\\ui'
|
win32 : '%LOCALAPPDATA%\\repertory\\ui'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.REPERTORY_LOCATIONS = {
|
||||||
|
linux : '~/.local/repertory',
|
||||||
|
darwin : '~/Library/Application Support/repertory',
|
||||||
|
win32 : '%LOCALAPPDATA%\\repertory'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.S3_PROVIDER_LIST = [
|
||||||
|
'Filebase',
|
||||||
|
];
|
||||||
|
|
||||||
|
exports.S3_REGION_PROVIDER_REGION = [
|
||||||
|
'us-east-1',
|
||||||
|
];
|
||||||
|
|
||||||
|
exports.S3_PROVIDER_URL = {
|
||||||
|
'Filebase' : 'https://s3.filebase.com',
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.PROVIDER_LIST = [
|
exports.PROVIDER_LIST = [
|
||||||
'Sia',
|
'Sia',
|
||||||
'ScPrime'
|
'Skynet',
|
||||||
|
'ScPrime',
|
||||||
];
|
];
|
||||||
|
|
||||||
exports.PROVIDER_ARG = {
|
exports.PROVIDER_ARG = {
|
||||||
sia: '',
|
sia : '',
|
||||||
scprime: '-sp'
|
skynet : '-sk',
|
||||||
|
scprime : '-sp',
|
||||||
|
s3 : '-s3',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.DEFAULT_RELEASE = 0;
|
||||||
exports.RELEASE_TYPES = [
|
exports.RELEASE_TYPES = [
|
||||||
'Release',
|
'Release',
|
||||||
'RC',
|
'RC',
|
||||||
@@ -66,10 +113,10 @@ exports.RELEASE_TYPES = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
exports.INSTALL_TYPES = {
|
exports.INSTALL_TYPES = {
|
||||||
Dependency: 'dependency',
|
Dependency : 'dependency',
|
||||||
Release: 'release',
|
Release : 'release',
|
||||||
TestRelease: 'test_release',
|
TestRelease : 'test_release',
|
||||||
Upgrade: 'upgrade',
|
Upgrade : 'upgrade',
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.IPC_Browse_Directory = 'browse_directory';
|
exports.IPC_Browse_Directory = 'browse_directory';
|
||||||
@@ -96,6 +143,9 @@ exports.IPC_Download_File = 'download_file';
|
|||||||
exports.IPC_Download_File_Complete = 'download_file_complete';
|
exports.IPC_Download_File_Complete = 'download_file_complete';
|
||||||
exports.IPC_Download_File_Progress = 'download_file_progress';
|
exports.IPC_Download_File_Progress = 'download_file_progress';
|
||||||
|
|
||||||
|
exports.IPC_Export_Skylinks = 'export_skylinks';
|
||||||
|
exports.IPC_Export_Skylinks_Reply = 'export_skylinks_reply';
|
||||||
|
|
||||||
exports.IPC_Extract_Release = 'extract_release';
|
exports.IPC_Extract_Release = 'extract_release';
|
||||||
exports.IPC_Extract_Release_Complete = 'extract_release_complete';
|
exports.IPC_Extract_Release_Complete = 'extract_release_complete';
|
||||||
|
|
||||||
@@ -105,12 +155,27 @@ exports.IPC_Get_Config_Reply = 'get_config_reply';
|
|||||||
exports.IPC_Get_Config_Template = 'get_config_template';
|
exports.IPC_Get_Config_Template = 'get_config_template';
|
||||||
exports.IPC_Get_Config_Template_Reply = 'get_config_template_reply';
|
exports.IPC_Get_Config_Template_Reply = 'get_config_template_reply';
|
||||||
|
|
||||||
|
exports.IPC_Get_Directory_Items = 'get_directory_items';
|
||||||
|
exports.IPC_Get_Directory_Items_Reply = 'get_directory_items_reply';
|
||||||
|
|
||||||
|
exports.IPC_Get_Pinned_Files = 'get_pinned_files';
|
||||||
|
exports.IPC_Get_Pinned_Files_Reply = 'get_pinned_files_reply';
|
||||||
|
|
||||||
|
exports.IPC_Get_Pinned_Files_Status = 'get_pinned_files_status';
|
||||||
|
exports.IPC_Get_Pinned_Files_Status_Reply = 'get_pinned_files_status_reply';
|
||||||
|
|
||||||
exports.IPC_Get_Platform = 'get_platform';
|
exports.IPC_Get_Platform = 'get_platform';
|
||||||
exports.IPC_Get_Platform_Reply = 'get_platform_reply';
|
exports.IPC_Get_Platform_Reply = 'get_platform_reply';
|
||||||
|
|
||||||
exports.IPC_Get_State = 'get_state';
|
exports.IPC_Get_State = 'get_state';
|
||||||
exports.IPC_Get_State_Reply = 'get_state_reply';
|
exports.IPC_Get_State_Reply = 'get_state_reply';
|
||||||
|
|
||||||
|
exports.IPC_Grab_Skynet_Tree = 'grab_skynet_tree';
|
||||||
|
exports.IPC_Grab_Skynet_Tree_Reply = 'grab_skynet_tree_reply';
|
||||||
|
|
||||||
|
exports.IPC_Import_Skylinks = 'import_skylinks';
|
||||||
|
exports.IPC_Import_Skylinks_Reply = 'import_skylinks_reply';
|
||||||
|
|
||||||
exports.IPC_Install_Dependency = 'install_dependency';
|
exports.IPC_Install_Dependency = 'install_dependency';
|
||||||
exports.IPC_Install_Dependency_Reply = 'install_dependency_reply';
|
exports.IPC_Install_Dependency_Reply = 'install_dependency_reply';
|
||||||
|
|
||||||
@@ -120,13 +185,15 @@ exports.IPC_Install_Upgrade_Reply = 'install_upgrade_reply';
|
|||||||
exports.IPC_Mount_Drive = 'mount_drive';
|
exports.IPC_Mount_Drive = 'mount_drive';
|
||||||
exports.IPC_Mount_Drive_Reply = 'mount_drive_reply';
|
exports.IPC_Mount_Drive_Reply = 'mount_drive_reply';
|
||||||
|
|
||||||
exports.IPC_Remove_Remote_Mount = 'remove_remote_mount';
|
exports.IPC_Remove_Mount = 'remove_mount';
|
||||||
exports.IPC_Remove_Remote_Mount_Reply = 'remove_remote_mount_reply';
|
exports.IPC_Remove_Mount_Reply = 'remove_mount_reply';
|
||||||
|
|
||||||
exports.IPC_Reboot_System = 'reboot_system';
|
exports.IPC_Reboot_System = 'reboot_system';
|
||||||
|
|
||||||
exports.IPC_Save_State = 'save_state';
|
exports.IPC_Save_State = 'save_state';
|
||||||
|
|
||||||
|
exports.IPC_Set_Pinned = 'set_pinned';
|
||||||
|
|
||||||
exports.IPC_Show_Window = 'show_window';
|
exports.IPC_Show_Window = 'show_window';
|
||||||
|
|
||||||
exports.IPC_Set_Config_Values = 'set_config_values';
|
exports.IPC_Set_Config_Values = 'set_config_values';
|
||||||
|
|||||||
13
src/containers/AddMount/AddMount.css
Normal file
13
src/containers/AddMount/AddMount.css
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
.AddRemoteMount {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.AddMountButtons {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.AddMountButton {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
246
src/containers/AddMount/AddMount.js
Normal file
246
src/containers/AddMount/AddMount.js
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {Component} from 'react';
|
||||||
|
import './AddMount.css';
|
||||||
|
import {connect} from 'react-redux';
|
||||||
|
import Button from '../../components/UI/Button/Button';
|
||||||
|
import Box from '../../components/UI/Box/Box';
|
||||||
|
import Text from '../../components/UI/Text/Text';
|
||||||
|
import {notifyError} from '../../redux/actions/error_actions';
|
||||||
|
import {addRemoteMount, addS3Mount} from '../../redux/actions/mount_actions';
|
||||||
|
import {createModalConditionally} from '../../utils';
|
||||||
|
import DropDown from '../../components/UI/DropDown/DropDown';
|
||||||
|
import * as Constants from '../../constants';
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
return {
|
||||||
|
RemoteMounts: state.mounts.RemoteMounts,
|
||||||
|
S3Mounts: state.mounts.S3Mounts,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
addRemoteMount: (hostNameOrIp, port, token) => dispatch(addRemoteMount(hostNameOrIp, port, token)),
|
||||||
|
addS3Mount: (name, accessKey, secretKey, region, bucketName, url) => dispatch(addS3Mount(name, accessKey, secretKey, region, bucketName, url)),
|
||||||
|
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const default_state = {
|
||||||
|
AccessKey: '',
|
||||||
|
BucketName: '',
|
||||||
|
DisplayRemote: false,
|
||||||
|
DisplayS3: false,
|
||||||
|
HostNameOrIp: '',
|
||||||
|
Name: '',
|
||||||
|
Port: 20000,
|
||||||
|
Provider: Constants.S3_PROVIDER_LIST[0],
|
||||||
|
Region: Constants.S3_REGION_PROVIDER_REGION[0],
|
||||||
|
SecretKey: '',
|
||||||
|
Token: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(class extends Component {
|
||||||
|
state = {
|
||||||
|
...default_state,
|
||||||
|
};
|
||||||
|
|
||||||
|
addRemoteMount = () => {
|
||||||
|
if (this.state.HostNameOrIp.length === 0) {
|
||||||
|
this.props.notifyError('Hostname or IP cannot be empty.');
|
||||||
|
} else {
|
||||||
|
const provider = 'Remote' + this.state.HostNameOrIp + ':' + this.state.Port;
|
||||||
|
if (this.props.RemoteMounts.includes(provider)) {
|
||||||
|
this.props.notifyError('Remote host already exists');
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
DisplayRemote: false
|
||||||
|
}, () => {
|
||||||
|
this.props.addRemoteMount(this.state.HostNameOrIp, this.state.Port, this.state.Token);
|
||||||
|
this.setState({
|
||||||
|
...default_state,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
addS3Mount = () => {
|
||||||
|
if (this.state.Name.length === 0) {
|
||||||
|
this.props.notifyError('Name cannot be empty.');
|
||||||
|
} else if (this.state.AccessKey.length === 0) {
|
||||||
|
this.props.notifyError('AccessKey cannot be empty.');
|
||||||
|
} else if (this.state.SecretKey.length === 0) {
|
||||||
|
this.props.notifyError('SecretKey cannot be empty.')
|
||||||
|
} else {
|
||||||
|
const provider = 'S3' + this.state.Name;
|
||||||
|
if (this.props.S3Mounts.includes(provider)) {
|
||||||
|
this.props.notifyError('Remote host already exists');
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
DisplayS3: false
|
||||||
|
}, () => {
|
||||||
|
this.props.addS3Mount(this.state.Name, this.state.AccessKey, this.state.SecretKey,
|
||||||
|
this.state.Region, this.state.BucketName, Constants.S3_PROVIDER_URL[this.state.Provider]);
|
||||||
|
this.setState({
|
||||||
|
...default_state,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handleAddS3Mount = () => {
|
||||||
|
this.setState({
|
||||||
|
DisplayRemote: false,
|
||||||
|
DisplayS3: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
handleAddRemoteMount = () => {
|
||||||
|
this.setState({
|
||||||
|
DisplayRemote: true,
|
||||||
|
DisplayS3: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const displayAddRemote = createModalConditionally(this.state.DisplayRemote, (
|
||||||
|
<Box dxDark
|
||||||
|
dxStyle={{width: 'auto', height: 'auto', padding: 'var(--default_spacing)'}}>
|
||||||
|
<h1 style={{textAlign: 'center', paddingBottom: 'var(--default_spacing)'}}>Add Remote
|
||||||
|
Mount</h1>
|
||||||
|
<Text text={'Hostname or IP'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}/>
|
||||||
|
<input onChange={e => this.setState({HostNameOrIp: e.target.value.trim()})}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.HostNameOrIp}/>
|
||||||
|
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
||||||
|
<Text text={'Port'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}/>
|
||||||
|
<input max={65535}
|
||||||
|
min={1025}
|
||||||
|
onChange={e => this.setState({Port: e.target.value})}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
type={'number'}
|
||||||
|
value={this.state.Port}/>
|
||||||
|
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
||||||
|
<Text text={'Remote Token'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}/>
|
||||||
|
<input onChange={e => this.setState({Token: e.target.value})}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.Token}/>
|
||||||
|
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
||||||
|
<div style={{display: 'flex', flexDirection: 'row'}}>
|
||||||
|
<Button buttonStyles={{width: '100%'}}
|
||||||
|
clicked={() => this.addRemoteMount()}>OK</Button>
|
||||||
|
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
||||||
|
<Button buttonStyles={{width: '100%'}}
|
||||||
|
clicked={() => this.setState({DisplayRemote: false})}>Cancel</Button>
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
|
));
|
||||||
|
|
||||||
|
const displayAddS3 = createModalConditionally(this.state.DisplayS3, (
|
||||||
|
<Box dxDark
|
||||||
|
dxStyle={{width: 'auto', height: 'auto', padding: 'var(--default_spacing)'}}>
|
||||||
|
<h1 style={{textAlign: 'center', paddingBottom: 'var(--default_spacing)'}}>Add S3
|
||||||
|
Mount</h1>
|
||||||
|
<div style={{display: 'flex', flexDirection: 'row'}}>
|
||||||
|
<Text text={'Name'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}/>
|
||||||
|
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
||||||
|
<Text text={'Provider'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}/>
|
||||||
|
</div>
|
||||||
|
<div style={{display: 'flex', flexDirection: 'row'}}>
|
||||||
|
<input onChange={e => this.setState({Name: e.target.value.trim()})}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{width: '100%'}}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.Name}/>
|
||||||
|
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
||||||
|
<DropDown changed={e => this.setState({Provider: e.target.value})}
|
||||||
|
items={Constants.S3_PROVIDER_LIST}
|
||||||
|
selected={this.state.Provider}/>
|
||||||
|
</div>
|
||||||
|
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
||||||
|
<div style={{display: 'flex', flexDirection: 'row'}}>
|
||||||
|
<Text text={'Bucket Name (optional)'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}/>
|
||||||
|
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
||||||
|
<Text text={'Region'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}/>
|
||||||
|
</div>
|
||||||
|
<div style={{display: 'flex', flexDirection: 'row'}}>
|
||||||
|
<input onChange={e => this.setState({BucketName: e.target.value})}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{width: '100%'}}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.BucketName}/>
|
||||||
|
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
||||||
|
<input onChange={e => this.setState({Region: e.target.value})}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.Region}/>
|
||||||
|
</div>
|
||||||
|
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
||||||
|
<div style={{display: 'flex', flexDirection: 'row'}}>
|
||||||
|
<Text text={'Access Key'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}/>
|
||||||
|
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
||||||
|
<Text text={'Secret Key'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}/>
|
||||||
|
</div>
|
||||||
|
<div style={{display: 'flex', flexDirection: 'row'}}>
|
||||||
|
<input onChange={e => this.setState({AccessKey: e.target.value})}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.AccessKey}/>
|
||||||
|
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
||||||
|
<input onChange={e => this.setState({SecretKey: e.target.value})}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.SecretKey}/>
|
||||||
|
</div>
|
||||||
|
<div style={{paddingTop: 'calc(var(--default_spacing) * 2)'}}/>
|
||||||
|
<div style={{display: 'flex', flexDirection: 'row'}}>
|
||||||
|
<div style={{width: '200%'}}/>
|
||||||
|
<Button buttonStyles={{width: '100%'}}
|
||||||
|
clicked={() => this.addS3Mount()}>OK</Button>
|
||||||
|
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
||||||
|
<Button buttonStyles={{width: '100%'}}
|
||||||
|
clicked={() => this.setState({DisplayS3: false})}>Cancel</Button>
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
|
));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={'AddMount'}>
|
||||||
|
{displayAddRemote}
|
||||||
|
{displayAddS3}
|
||||||
|
<div className={'AddMountButtons'}>
|
||||||
|
{this.props.remoteSupported ?
|
||||||
|
<Button className={'AddMountButton'}
|
||||||
|
clicked={this.handleAddRemoteMount}>Add Remote Mount</Button> : null}
|
||||||
|
{this.props.remoteSupported && this.props.s3Supported ?
|
||||||
|
<div style={{paddingRight: 'var(--default_spacing)'}}/> : null}
|
||||||
|
{this.props.s3Supported ?
|
||||||
|
<Button className={'AddMountButton'}
|
||||||
|
clicked={this.handleAddS3Mount}>Add S3 Mount</Button> : null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
.AddRemoteMount {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import {Component} from 'react';
|
|
||||||
import './AddRemoteMount.css';
|
|
||||||
import {connect} from 'react-redux';
|
|
||||||
import Button from '../../components/UI/Button/Button';
|
|
||||||
import Box from '../../components/UI/Box/Box';
|
|
||||||
import Text from '../../components/UI/Text/Text';
|
|
||||||
import {notifyError} from '../../redux/actions/error_actions';
|
|
||||||
import {addRemoteMount} from '../../redux/actions/mount_actions';
|
|
||||||
import {createModalConditionally} from '../../utils';
|
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
|
||||||
return {
|
|
||||||
RemoteMounts: state.mounts.RemoteMounts,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
|
||||||
return {
|
|
||||||
addRemoteMount: (hostNameOrIp, port, token) => dispatch(addRemoteMount(hostNameOrIp, port, token)),
|
|
||||||
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(class extends Component {
|
|
||||||
state = {
|
|
||||||
Display: false,
|
|
||||||
HostNameOrIp: '',
|
|
||||||
Port: 20000,
|
|
||||||
Token: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
addRemoteMount = () => {
|
|
||||||
if (this.state.HostNameOrIp.length === 0) {
|
|
||||||
this.props.notifyError('Hostname or IP cannot be empty.');
|
|
||||||
} else {
|
|
||||||
const provider = 'Remote' + this.state.HostNameOrIp + ':' + this.state.Port;
|
|
||||||
if (this.props.RemoteMounts.includes(provider)) {
|
|
||||||
this.props.notifyError('Remote host already exists');
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
Display: false
|
|
||||||
}, () => {
|
|
||||||
this.props.addRemoteMount(this.state.HostNameOrIp, this.state.Port, this.state.Token);
|
|
||||||
this.setState({
|
|
||||||
HostNameOrIp: '',
|
|
||||||
Port: 20000,
|
|
||||||
Token: '',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
handleAddRemoteMount = () => {
|
|
||||||
this.setState({
|
|
||||||
Display: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const displayAdd = createModalConditionally(this.state.Display, (
|
|
||||||
<Box dxDark
|
|
||||||
dxStyle={{width: 'auto', height: 'auto', padding: 'var(--default_spacing)'}}>
|
|
||||||
<h1 style={{color: 'var(--text_color_error)', textAlign: 'center', paddingBottom: 'var(--default_spacing)'}}>Add Remote Mount</h1>
|
|
||||||
<Text text={'Hostname or IP'}
|
|
||||||
textAlign={'left'}
|
|
||||||
type={'Heading1'}/>
|
|
||||||
<input onChange={e => this.setState({HostNameOrIp: e.target.value.trim()})}
|
|
||||||
className={'ConfigurationItemInput'}
|
|
||||||
type={'text'}
|
|
||||||
value={this.state.HostNameOrIp}/>
|
|
||||||
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
|
||||||
<Text text={'Port'}
|
|
||||||
textAlign={'left'}
|
|
||||||
type={'Heading1'}/>
|
|
||||||
<input max={65535}
|
|
||||||
min={1025}
|
|
||||||
onChange={e => this.setState({Port: e.target.value})}
|
|
||||||
className={'ConfigurationItemInput'}
|
|
||||||
type={'number'}
|
|
||||||
value={this.state.Port}/>
|
|
||||||
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
|
||||||
<Text text={'Remote Token'}
|
|
||||||
textAlign={'left'}
|
|
||||||
type={'Heading1'}/>
|
|
||||||
<input onChange={e => this.setState({Token: e.target.value})}
|
|
||||||
className={'ConfigurationItemInput'}
|
|
||||||
type={'text'}
|
|
||||||
value={this.state.Token}/>
|
|
||||||
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
|
||||||
<table cellSpacing={1}
|
|
||||||
width="100%">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td width="50%">
|
|
||||||
<Button buttonStyles={{width: '100%'}}
|
|
||||||
clicked={() => this.addRemoteMount()}>OK</Button>
|
|
||||||
</td>
|
|
||||||
<td width="50%">
|
|
||||||
<Button buttonStyles={{width: '100%'}}
|
|
||||||
clicked={() => this.setState({Display: false})}>Cancel</Button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</Box>
|
|
||||||
));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={'AddRemoteMount'}>
|
|
||||||
{displayAdd}
|
|
||||||
<Button clicked={this.handleAddRemoteMount}>Add Remote Mount</Button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -4,3 +4,7 @@
|
|||||||
padding: var(--default_spacing);
|
padding: var(--default_spacing);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ConfigurationLink {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import Modal from '../../components/UI/Modal/Modal';
|
|||||||
import IPCContainer from '../IPCContainer/IPCContainer';
|
import IPCContainer from '../IPCContainer/IPCContainer';
|
||||||
import {displayConfiguration} from '../../redux/actions/mount_actions';
|
import {displayConfiguration} from '../../redux/actions/mount_actions';
|
||||||
import {notifyError} from '../../redux/actions/error_actions';
|
import {notifyError} from '../../redux/actions/error_actions';
|
||||||
|
import {displayPinnedManager} from '../../redux/actions/pinned_manager_actions';
|
||||||
|
|
||||||
const Constants = require('../../constants');
|
const Constants = require('../../constants');
|
||||||
|
|
||||||
@@ -27,11 +28,21 @@ class Configuration extends IPCContainer {
|
|||||||
Template: {}
|
Template: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
checkItemChanged = (itemA, itemB) => {
|
||||||
|
if (itemA.type === 'string_array') {
|
||||||
|
if (itemA.value.length !== itemB.value.length) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return itemA.value.filter(i => !itemB.value.includes(i)).length !== 0;
|
||||||
|
}
|
||||||
|
return itemA.value !== itemB.value;
|
||||||
|
};
|
||||||
|
|
||||||
checkSaveRequired = () => {
|
checkSaveRequired = () => {
|
||||||
const changedItems = [];
|
const changedItems = [];
|
||||||
let i = 0;
|
let i = 0;
|
||||||
for (const item of this.state.ItemList) {
|
for (const item of this.state.ItemList) {
|
||||||
if (this.state.OriginalItemList[i++].value !== item.value) {
|
if (this.checkItemChanged(this.state.OriginalItemList[i++], item)) {
|
||||||
changedItems.push(item);
|
changedItems.push(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -41,7 +52,7 @@ class Configuration extends IPCContainer {
|
|||||||
const changedObjectItems = [];
|
const changedObjectItems = [];
|
||||||
let j = 0;
|
let j = 0;
|
||||||
for (const item of this.state.ObjectLookup[key]) {
|
for (const item of this.state.ObjectLookup[key]) {
|
||||||
if (this.state.OriginalObjectLookup[key][j++].value !== item.value) {
|
if (this.checkItemChanged(this.state.OriginalObjectLookup[key][j++], item)) {
|
||||||
changedObjectItems.push(item);
|
changedObjectItems.push(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,6 +83,7 @@ class Configuration extends IPCContainer {
|
|||||||
this.sendRequest(Constants.IPC_Get_Config_Template, {
|
this.sendRequest(Constants.IPC_Get_Config_Template, {
|
||||||
Provider: this.props.DisplayConfiguration,
|
Provider: this.props.DisplayConfiguration,
|
||||||
Remote: this.props.DisplayRemoteConfiguration,
|
Remote: this.props.DisplayRemoteConfiguration,
|
||||||
|
S3: this.props.DisplayS3Configuration,
|
||||||
Version: this.props.version,
|
Version: this.props.version,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -84,26 +96,29 @@ class Configuration extends IPCContainer {
|
|||||||
createItemList = (config, template) => {
|
createItemList = (config, template) => {
|
||||||
const objectList = [];
|
const objectList = [];
|
||||||
const itemList = Object
|
const itemList = Object
|
||||||
.keys(config)
|
.keys(config)
|
||||||
.map(key => {
|
.map(key => {
|
||||||
return {
|
return {
|
||||||
advanced: template[key] ? template[key].advanced : false,
|
advanced: template[key] ? template[key].advanced : false,
|
||||||
hide_remote: template[key] ? template[key].hide_remote : false,
|
hide_remote: template[key] ? template[key].hide_remote : false,
|
||||||
label: key,
|
label: key,
|
||||||
remote: template[key] ? template[key].remote : false,
|
remote: template[key] ? template[key].remote : false,
|
||||||
value: (template[key] && (template[key].type === 'object')) ?
|
type: template[key] ? template[key].type : null,
|
||||||
|
value: (template[key] && (template[key].type === 'object')) ?
|
||||||
|
config[key] :
|
||||||
|
(template[key] && (template[key].type === 'string_array')) ?
|
||||||
config[key] :
|
config[key] :
|
||||||
config[key].toString(),
|
config[key].toString(),
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter(i=> {
|
.filter(i => {
|
||||||
let ret = template[i.label];
|
let ret = template[i.label];
|
||||||
if (ret && (template[i.label].type === 'object')) {
|
if (ret && (template[i.label].type === 'object')) {
|
||||||
objectList.push(i);
|
objectList.push(i);
|
||||||
ret = false;
|
ret = false;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
ObjectList: objectList,
|
ObjectList: objectList,
|
||||||
ItemList: itemList,
|
ItemList: itemList,
|
||||||
@@ -114,7 +129,7 @@ class Configuration extends IPCContainer {
|
|||||||
const itemList = [
|
const itemList = [
|
||||||
...this.state.ItemList
|
...this.state.ItemList
|
||||||
];
|
];
|
||||||
itemList[idx].value = target.value.toString();
|
itemList[idx].value = target.type === 'textarea' ? target.string_array : target.value.toString();
|
||||||
this.setState({
|
this.setState({
|
||||||
ItemList: itemList
|
ItemList: itemList
|
||||||
});
|
});
|
||||||
@@ -128,7 +143,7 @@ class Configuration extends IPCContainer {
|
|||||||
...this.state.ObjectLookup,
|
...this.state.ObjectLookup,
|
||||||
};
|
};
|
||||||
|
|
||||||
itemList[idx].value = target.value.toString();
|
itemList[idx].value = target.type === 'textarea' ? target.string_array : target.value.toString();
|
||||||
objectLookup[name] = itemList;
|
objectLookup[name] = itemList;
|
||||||
this.setState({
|
this.setState({
|
||||||
ObjectLookup: objectLookup,
|
ObjectLookup: objectLookup,
|
||||||
@@ -163,6 +178,8 @@ class Configuration extends IPCContainer {
|
|||||||
ObjectLookup: objectLookup,
|
ObjectLookup: objectLookup,
|
||||||
OriginalItemList: itemListCopy,
|
OriginalItemList: itemListCopy,
|
||||||
OriginalObjectLookup: objectLookupCopy,
|
OriginalObjectLookup: objectLookupCopy,
|
||||||
|
}, () => {
|
||||||
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.props.notifyError(arg.data.Error);
|
this.props.notifyError(arg.data.Error);
|
||||||
@@ -173,10 +190,11 @@ class Configuration extends IPCContainer {
|
|||||||
if (arg.data.Success) {
|
if (arg.data.Success) {
|
||||||
this.setState({
|
this.setState({
|
||||||
Template: arg.data.Template,
|
Template: arg.data.Template,
|
||||||
}, ()=> {
|
}, () => {
|
||||||
this.sendRequest(Constants.IPC_Get_Config, {
|
this.sendRequest(Constants.IPC_Get_Config, {
|
||||||
Provider: this.props.DisplayConfiguration,
|
Provider: this.props.DisplayConfiguration,
|
||||||
Remote: this.props.DisplayRemoteConfiguration,
|
Remote: this.props.DisplayRemoteConfiguration,
|
||||||
|
S3: this.props.DisplayS3Configuration,
|
||||||
Version: this.props.version,
|
Version: this.props.version,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -196,12 +214,14 @@ class Configuration extends IPCContainer {
|
|||||||
saveAndClose = () => {
|
saveAndClose = () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
Saving: true,
|
Saving: true,
|
||||||
}, ()=> {
|
}, () => {
|
||||||
const changedItems = [];
|
const changedItems = [];
|
||||||
for (const item of this.state.ChangedItems) {
|
for (const item of this.state.ChangedItems) {
|
||||||
changedItems.push({
|
changedItems.push({
|
||||||
Name: item.label,
|
Name: item.label,
|
||||||
Value: item.value,
|
Value: item.type === 'string_array' ?
|
||||||
|
item.value.join(';') :
|
||||||
|
item.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +230,9 @@ class Configuration extends IPCContainer {
|
|||||||
for (const item of this.state.ChangedObjectLookup[key]) {
|
for (const item of this.state.ChangedObjectLookup[key]) {
|
||||||
changedItems.push({
|
changedItems.push({
|
||||||
Name: key + '.' + item.label,
|
Name: key + '.' + item.label,
|
||||||
Value: item.value,
|
Value: item.type === 'string_array' ?
|
||||||
|
item.value.join(';') :
|
||||||
|
item.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,6 +242,7 @@ class Configuration extends IPCContainer {
|
|||||||
Items: changedItems,
|
Items: changedItems,
|
||||||
Provider: this.props.DisplayConfiguration,
|
Provider: this.props.DisplayConfiguration,
|
||||||
Remote: this.props.DisplayRemoteConfiguration,
|
Remote: this.props.DisplayRemoteConfiguration,
|
||||||
|
S3: this.props.DisplayS3Configuration,
|
||||||
Version: this.props.version,
|
Version: this.props.version,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -251,44 +274,39 @@ class Configuration extends IPCContainer {
|
|||||||
<Modal>
|
<Modal>
|
||||||
<Box dxStyle={{width: '40vw', padding: 'var(--default_spacing)'}}>
|
<Box dxStyle={{width: '40vw', padding: 'var(--default_spacing)'}}>
|
||||||
<h1 style={{width: '100%', textAlign: 'center'}}>Save Changes?</h1>
|
<h1 style={{width: '100%', textAlign: 'center'}}>Save Changes?</h1>
|
||||||
<table width='100%'><tbody>
|
<table width='100%'>
|
||||||
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td align='center' width='50%'><Button clicked={this.saveAndClose} disabled={this.state.Saving}>Yes</Button></td>
|
<td align='center' width='50%'><Button clicked={this.saveAndClose}
|
||||||
<td align='center' width='50%'><Button clicked={this.props.hideConfiguration} disabled={this.state.Saving}>No</Button></td>
|
disabled={this.state.Saving}>Yes</Button>
|
||||||
|
</td>
|
||||||
|
<td align='center' width='50%'><Button clicked={this.props.hideConfiguration}
|
||||||
|
disabled={this.state.Saving}>No</Button></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody></table>
|
</tbody>
|
||||||
|
</table>
|
||||||
</Box>
|
</Box>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const configurationItems = this.state.ItemList
|
let autoFocus = true;
|
||||||
.map((k, i) => {
|
|
||||||
return (
|
|
||||||
((!this.state.IsRemoteMount || !k.hide_remote) && (!k.advanced || (this.state.ShowAdvanced && k.advanced))) ?
|
|
||||||
<ConfigurationItem advanced={k.advanced}
|
|
||||||
changed={e=>this.handleItemChanged(e, i)}
|
|
||||||
grouping={'Settings'}
|
|
||||||
items={this.state.Template[k.label].items}
|
|
||||||
key={i}
|
|
||||||
label={k.label}
|
|
||||||
template={this.state.Template[k.label]}
|
|
||||||
value={k.value}/> :
|
|
||||||
null)
|
|
||||||
});
|
|
||||||
|
|
||||||
let objectItems = [];
|
let objectItems = [];
|
||||||
for (const key of Object.keys(this.state.ObjectLookup)) {
|
for (const key of Object.keys(this.state.ObjectLookup)) {
|
||||||
objectItems.push((
|
objectItems.push((
|
||||||
<div key={key}>
|
<div key={key}>
|
||||||
<h1>{key}</h1>
|
<h2>{key}</h2>
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
this.state.ObjectLookup[key].map((k, i) => {
|
this.state.ObjectLookup[key].map((k, i) => {
|
||||||
|
const shouldFocus = autoFocus;
|
||||||
|
autoFocus = false;
|
||||||
return (
|
return (
|
||||||
(!k.advanced || (this.state.ShowAdvanced && k.advanced && !k.remote) || this.showRemoteConfigItem(k, this.state.ObjectLookup[key])) ?
|
(!k.advanced || (this.state.ShowAdvanced && k.advanced && !k.remote) || this.showRemoteConfigItem(k, this.state.ObjectLookup[key])) ?
|
||||||
<ConfigurationItem advanced={k.advanced}
|
<ConfigurationItem advanced={k.advanced}
|
||||||
changed={e=>this.handleObjectItemChanged(e, key, i)}
|
autoFocus={shouldFocus}
|
||||||
|
changed={e => this.handleObjectItemChanged(e, key, i)}
|
||||||
grouping={key}
|
grouping={key}
|
||||||
items={this.state.Template[key].template[k.label].items}
|
items={this.state.Template[key].template[k.label].items}
|
||||||
key={i}
|
key={i}
|
||||||
@@ -304,21 +322,56 @@ class Configuration extends IPCContainer {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const configurationItems = this.state.ItemList
|
||||||
|
.map((k, i) => {
|
||||||
|
const shouldFocus = autoFocus;
|
||||||
|
autoFocus = false;
|
||||||
|
return (
|
||||||
|
((!this.state.IsRemoteMount || !k.hide_remote) && (!k.advanced || (this.state.ShowAdvanced && k.advanced))) ?
|
||||||
|
<ConfigurationItem advanced={k.advanced}
|
||||||
|
autoFocus={shouldFocus}
|
||||||
|
changed={e => this.handleItemChanged(e, i)}
|
||||||
|
grouping={'Settings'}
|
||||||
|
items={this.state.Template[k.label].items}
|
||||||
|
key={i}
|
||||||
|
label={k.label}
|
||||||
|
template={this.state.Template[k.label]}
|
||||||
|
value={k.value}/> :
|
||||||
|
null
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'Configuration'}>
|
<div className={'Configuration'}>
|
||||||
{confirmSave}
|
{confirmSave}
|
||||||
<Box dxDark dxStyle={{padding: 'var(--default_spacing)'}}>
|
<Box dxDark dxStyle={{padding: 'var(--default_spacing)'}}>
|
||||||
<div style={{float: 'right', margin: 0, padding: 0, marginTop: '-4px', boxSizing: 'border-box', display: 'block'}}>
|
<div style={{
|
||||||
<b style={{cursor: 'pointer'}}
|
float: 'right',
|
||||||
onClick={this.checkSaveRequired}>X</b>
|
margin: 0,
|
||||||
|
padding: 0,
|
||||||
|
marginTop: '-4px',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
display: 'block'
|
||||||
|
}}>
|
||||||
|
<a href={'#'}
|
||||||
|
onClick={this.checkSaveRequired}
|
||||||
|
style={{cursor: 'pointer'}}>X</a>
|
||||||
</div>
|
</div>
|
||||||
<h1 style={{width: '100%', textAlign: 'center'}}>{(
|
<h1 style={{width: '100%', textAlign: 'center'}}>{(
|
||||||
this.props.DisplayRemoteConfiguration ?
|
this.props.DisplayRemoteConfiguration ?
|
||||||
this.props.DisplayConfiguration.substr(6) :
|
this.props.DisplayConfiguration.substr(6) :
|
||||||
this.props.DisplayConfiguration) + ' Configuration'}</h1>
|
this.props.DisplayConfiguration) + ' Configuration '}
|
||||||
|
</h1>
|
||||||
<div style={{overflowY: 'auto', height: '90%'}}>
|
<div style={{overflowY: 'auto', height: '90%'}}>
|
||||||
|
{this.props.MState.Mounted && (configurationItems.length > 0) ? <Button
|
||||||
|
buttonStyles={{width: 'auto', height: 'auto', marginLeft: 'auto', marginRight: '4px'}}
|
||||||
|
clicked={() => {
|
||||||
|
this.props.displayPinnedManager(true);
|
||||||
|
return false;
|
||||||
|
}}> Pinned File Manager... </Button> : null}
|
||||||
|
<div style={{marginBottom: '4px'}}/>
|
||||||
{objectItems}
|
{objectItems}
|
||||||
{(configurationItems.length > 0) ? <h1>Settings</h1> : null}
|
{(configurationItems.length > 0) ? <h2>Settings</h2> : null}
|
||||||
{configurationItems}
|
{configurationItems}
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -331,12 +384,15 @@ const mapStateToProps = state => {
|
|||||||
return {
|
return {
|
||||||
DisplayConfiguration: state.mounts.DisplayConfiguration,
|
DisplayConfiguration: state.mounts.DisplayConfiguration,
|
||||||
DisplayRemoteConfiguration: state.mounts.DisplayRemoteConfiguration,
|
DisplayRemoteConfiguration: state.mounts.DisplayRemoteConfiguration,
|
||||||
|
DisplayS3Configuration: state.mounts.DisplayS3Configuration,
|
||||||
|
MState: state.mounts.MountState[state.mounts.DisplayConfiguration],
|
||||||
Platform: state.common.Platform,
|
Platform: state.common.Platform,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
const mapDispatchToProps = dispatch => {
|
||||||
return {
|
return {
|
||||||
|
displayPinnedManager: display => dispatch(displayPinnedManager(display)),
|
||||||
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
|
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
|
||||||
hideConfiguration: () => dispatch(displayConfiguration(null, false)),
|
hideConfiguration: () => dispatch(displayConfiguration(null, false)),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ input.ConfigurationItemInput {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
border-radius: var(--border_radius);
|
border-radius: var(--border_radius);
|
||||||
background: rgba(160, 160, 160, 0.1);
|
background: var(--control_background);
|
||||||
border: none;
|
border: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
@@ -16,6 +16,23 @@ input.ConfigurationItemInput {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textarea.ConfigurationItemInput {
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
padding: 2px;
|
||||||
|
border-radius: var(--border_radius);
|
||||||
|
background: var(--control_background);
|
||||||
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
outline: none;
|
||||||
|
color: var(--text_color);
|
||||||
|
box-sizing: border-box;
|
||||||
|
resize: none;
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow:-moz-scrollbars-horizontal;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
.ConfigurationInfo {
|
.ConfigurationInfo {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
@@ -4,13 +4,18 @@ import CheckBox from '../../../components/UI/CheckBox/CheckBox';
|
|||||||
import {connect} from 'react-redux';
|
import {connect} from 'react-redux';
|
||||||
import {faInfoCircle} from '@fortawesome/free-solid-svg-icons';
|
import {faInfoCircle} from '@fortawesome/free-solid-svg-icons';
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||||
import {notifyInfo} from '../../../redux/actions/error_actions';
|
import {
|
||||||
|
notifyError,
|
||||||
|
notifyInfo
|
||||||
|
} from '../../../redux/actions/error_actions';
|
||||||
import settings from '../../../assets/settings';
|
import settings from '../../../assets/settings';
|
||||||
import DropDown from '../../../components/UI/DropDown/DropDown';
|
import DropDown from '../../../components/UI/DropDown/DropDown';
|
||||||
|
import Password from '../../../containers/UI/Password/Password';
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
const mapDispatchToProps = dispatch => {
|
||||||
return {
|
return {
|
||||||
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg))
|
notifyError: msg => dispatch(notifyError(msg)),
|
||||||
|
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -18,7 +23,9 @@ export default connect(null, mapDispatchToProps)(props => {
|
|||||||
const handleChanged = (e) => {
|
const handleChanged = (e) => {
|
||||||
const target = e.target;
|
const target = e.target;
|
||||||
if (target.type === 'checkbox') {
|
if (target.type === 'checkbox') {
|
||||||
target.value = e.target.checked ? "true" : "false";
|
target.value = e.target.checked ? 'true' : 'false';
|
||||||
|
} else if (target.type === 'textarea') {
|
||||||
|
e.target.string_array = String(e.target.value).replace(/\r\n/g,'\n').split('\n');
|
||||||
}
|
}
|
||||||
props.changed(target);
|
props.changed(target);
|
||||||
};
|
};
|
||||||
@@ -30,49 +37,71 @@ export default connect(null, mapDispatchToProps)(props => {
|
|||||||
props.notifyInfo(props.label, description);
|
props.notifyInfo(props.label, description);
|
||||||
};
|
};
|
||||||
|
|
||||||
infoDisplay = <a href={void(0)}
|
infoDisplay = <a href={'#'}
|
||||||
className={'ConfigurationInfo'}
|
className={'ConfigurationInfo'}
|
||||||
onClick={()=>{displayInfo(); return false;}}><FontAwesomeIcon icon={faInfoCircle}/></a>;
|
onClick={()=>{displayInfo(); return false;}}><FontAwesomeIcon icon={faInfoCircle}/></a>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let data;
|
let data;
|
||||||
switch (props.template.type) {
|
switch (props.template.type) {
|
||||||
case "bool":
|
case 'bool':
|
||||||
data = <CheckBox changed={handleChanged}
|
data = <CheckBox changed={handleChanged}
|
||||||
checked={props.value}
|
checked={props.value}
|
||||||
disabled={props.readOnly}/>;
|
disabled={props.readOnly}
|
||||||
|
autoFocus={props.autoFocus}/>;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "double":
|
case 'double':
|
||||||
data = <input min={0.0}
|
data = <input min={0.0}
|
||||||
|
autoFocus={props.autoFocus}
|
||||||
disabled={props.readOnly}
|
disabled={props.readOnly}
|
||||||
onChange={e=>handleChanged(e)}
|
onChange={e=>handleChanged(e)}
|
||||||
step={"0.01"}
|
step={'0.01'}
|
||||||
className={'ConfigurationItemInput'}
|
className={'ConfigurationItemInput'}
|
||||||
type={'number'}
|
type={'number'}
|
||||||
value={parseFloat(props.value).toFixed(2)}/>;
|
value={parseFloat(props.value).toFixed(2)}/>;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "list":
|
case 'list':
|
||||||
data = <DropDown alt
|
data = <DropDown alt
|
||||||
auto
|
auto
|
||||||
|
autoFocus={props.autoFocus}
|
||||||
changed={handleChanged}
|
changed={handleChanged}
|
||||||
disabled={props.readOnly}
|
disabled={props.readOnly}
|
||||||
items={props.items}
|
items={props.items}
|
||||||
selected={props.value} />;
|
selected={props.value} />;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "string":
|
case 'string':
|
||||||
data = <input onChange={e=>handleChanged(e)}
|
if (props.template.subtype === 'password') {
|
||||||
className={'ConfigurationItemInput'}
|
data = (
|
||||||
|
<Password autoFocus={props.autoFocus}
|
||||||
|
changed={s => handleChanged({
|
||||||
|
target: {
|
||||||
|
type: 'password',
|
||||||
|
value: s,
|
||||||
|
},
|
||||||
|
})}
|
||||||
disabled={props.readOnly}
|
disabled={props.readOnly}
|
||||||
type={'text'}
|
mismatchHandler={() => props.notifyError('Passwords do not match')}
|
||||||
value={props.value}/>;
|
value={props.value} />
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
data = (
|
||||||
|
<input onChange={e => handleChanged(e)}
|
||||||
|
autoFocus={props.autoFocus}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
disabled={props.readOnly}
|
||||||
|
type={'text'}
|
||||||
|
value={props.value}/>
|
||||||
|
);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "uint8":
|
case 'uint8':
|
||||||
data = <input max={255}
|
data = <input max={255}
|
||||||
min={0}
|
min={0}
|
||||||
|
autoFocus={props.autoFocus}
|
||||||
disabled={props.readOnly}
|
disabled={props.readOnly}
|
||||||
onChange={e=>handleChanged(e)}
|
onChange={e=>handleChanged(e)}
|
||||||
className={'ConfigurationItemInput'}
|
className={'ConfigurationItemInput'}
|
||||||
@@ -80,9 +109,10 @@ export default connect(null, mapDispatchToProps)(props => {
|
|||||||
value={props.value}/>;
|
value={props.value}/>;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "uint16":
|
case 'uint16':
|
||||||
data = <input max={65535}
|
data = <input max={65535}
|
||||||
min={0}
|
min={0}
|
||||||
|
autoFocus={props.autoFocus}
|
||||||
disabled={props.readOnly}
|
disabled={props.readOnly}
|
||||||
onChange={e=>handleChanged(e)}
|
onChange={e=>handleChanged(e)}
|
||||||
className={'ConfigurationItemInput'}
|
className={'ConfigurationItemInput'}
|
||||||
@@ -90,9 +120,10 @@ export default connect(null, mapDispatchToProps)(props => {
|
|||||||
value={props.value}/>;
|
value={props.value}/>;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "uint32":
|
case 'uint32':
|
||||||
data = <input max={4294967295}
|
data = <input max={4294967295}
|
||||||
min={0}
|
min={0}
|
||||||
|
autoFocus={props.autoFocus}
|
||||||
disabled={props.readOnly}
|
disabled={props.readOnly}
|
||||||
onChange={e=>handleChanged(e)}
|
onChange={e=>handleChanged(e)}
|
||||||
className={'ConfigurationItemInput'}
|
className={'ConfigurationItemInput'}
|
||||||
@@ -100,9 +131,10 @@ export default connect(null, mapDispatchToProps)(props => {
|
|||||||
value={props.value}/>;
|
value={props.value}/>;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "uint64":
|
case 'uint64':
|
||||||
data = <input max={18446744073709551615}
|
data = <input max={18446744073709551615}
|
||||||
min={0}
|
min={0}
|
||||||
|
autoFocus={props.autoFocus}
|
||||||
disabled={props.readOnly}
|
disabled={props.readOnly}
|
||||||
onChange={e=>handleChanged(e)}
|
onChange={e=>handleChanged(e)}
|
||||||
className={'ConfigurationItemInput'}
|
className={'ConfigurationItemInput'}
|
||||||
@@ -110,6 +142,33 @@ export default connect(null, mapDispatchToProps)(props => {
|
|||||||
value={props.value}/>;
|
value={props.value}/>;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'string_array':
|
||||||
|
data = (
|
||||||
|
<textarea autoFocus={props.autoFocus}
|
||||||
|
disabled={props.readOnly}
|
||||||
|
rows={4}
|
||||||
|
cols={36}
|
||||||
|
onChange={e=>handleChanged(e)}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
value={props.value.join('\n')} />
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'password':
|
||||||
|
data = (
|
||||||
|
<Password autoFocus={props.autoFocus}
|
||||||
|
changed={s => handleChanged({
|
||||||
|
target: {
|
||||||
|
type: 'password',
|
||||||
|
value: s,
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
disabled={props.readOnly}
|
||||||
|
mismatchHandler={() => props.notifyError('Passwords do not match')}
|
||||||
|
value={props.value} />
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
data = <div>{props.value}</div>;
|
data = <div>{props.value}</div>;
|
||||||
}
|
}
|
||||||
@@ -121,8 +180,8 @@ export default connect(null, mapDispatchToProps)(props => {
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
{infoDisplay ?
|
{infoDisplay ?
|
||||||
<td width='100%'>{infoDisplay} {props.label}</td> :
|
<td width='100%' valign={'top'}>{infoDisplay} {props.label}</td> :
|
||||||
<td width='100%'>{props.label}</td>}
|
<td width='100%' valign={'top'}>{props.label}</td>}
|
||||||
<td>{data}</td>
|
<td>{data}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -8,7 +8,15 @@ import Text from '../../../components/UI/Text/Text';
|
|||||||
import Grid from '../../../components/UI/Grid/Grid';
|
import Grid from '../../../components/UI/Grid/Grid';
|
||||||
import configureImage from '../../../assets/images/configure.png';
|
import configureImage from '../../../assets/images/configure.png';
|
||||||
import RootElem from '../../../components/UI/RootElem/RootElem';
|
import RootElem from '../../../components/UI/RootElem/RootElem';
|
||||||
import {displayConfiguration, removeRemoteMount, setProviderState} from '../../../redux/actions/mount_actions';
|
import {
|
||||||
|
displayConfiguration,
|
||||||
|
removeMount,
|
||||||
|
setProviderState
|
||||||
|
} from '../../../redux/actions/mount_actions';
|
||||||
|
import {
|
||||||
|
displaySkynetExport,
|
||||||
|
displaySkynetImport,
|
||||||
|
} from '../../../redux/actions/skynet_actions'
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||||
import { faTrashAlt} from '@fortawesome/free-solid-svg-icons';
|
import { faTrashAlt} from '@fortawesome/free-solid-svg-icons';
|
||||||
import CheckBox from '../../../components/UI/CheckBox/CheckBox';
|
import CheckBox from '../../../components/UI/CheckBox/CheckBox';
|
||||||
@@ -23,8 +31,10 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
const mapDispatchToProps = dispatch => {
|
||||||
return {
|
return {
|
||||||
displayConfiguration: (provider, remote) => dispatch(displayConfiguration(provider, remote)),
|
displayConfiguration: (provider, remote, s3) => dispatch(displayConfiguration(provider, remote, s3)),
|
||||||
removeRemoteMount: provider => dispatch(removeRemoteMount(provider)),
|
displaySkynetExport: display => dispatch(displaySkynetExport(display)),
|
||||||
|
displaySkynetImport: display => dispatch(displaySkynetImport(display)),
|
||||||
|
removeMount: provider => dispatch(removeMount(provider)),
|
||||||
setProviderState: (provider, state) => dispatch(setProviderState(provider, state)),
|
setProviderState: (provider, state) => dispatch(setProviderState(provider, state)),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -53,7 +63,9 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|||||||
rowSpan={6}>
|
rowSpan={6}>
|
||||||
<img alt=''
|
<img alt=''
|
||||||
height={'16px'}
|
height={'16px'}
|
||||||
onClick={props.MState.AllowMount ? ()=>props.displayConfiguration(props.provider, props.remote) : e=>{e.preventDefault();}}
|
onClick={props.MState.AllowMount ? () => props.displayConfiguration(props.provider, props.remote, props.s3) : e => {
|
||||||
|
e.preventDefault();
|
||||||
|
}}
|
||||||
src={configureImage}
|
src={configureImage}
|
||||||
style={{padding: 0, border: 0, margin: 0, ...pointer}}
|
style={{padding: 0, border: 0, margin: 0, ...pointer}}
|
||||||
width={'16px'}/>
|
width={'16px'}/>
|
||||||
@@ -110,12 +122,13 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|||||||
width={19}/>;
|
width={19}/>;
|
||||||
|
|
||||||
const actionsDisplay = (
|
const actionsDisplay = (
|
||||||
<Button clicked={()=>props.clicked(props.provider, props.remote, !props.MState.Mounted, props.PState.MountLocation)}
|
<Button
|
||||||
col={inputColumnSpan + 2}
|
clicked={() => props.clicked(props.provider, props.remote, props.s3, !props.MState.Mounted, props.PState.MountLocation)}
|
||||||
colSpan={21}
|
col={inputColumnSpan + 2}
|
||||||
disabled={!props.MState.AllowMount}
|
colSpan={21}
|
||||||
row={secondRow}
|
disabled={!props.MState.AllowMount}
|
||||||
rowSpan={7}>
|
row={secondRow}
|
||||||
|
rowSpan={7}>
|
||||||
{buttonDisplay}
|
{buttonDisplay}
|
||||||
</Button>);
|
</Button>);
|
||||||
|
|
||||||
@@ -125,7 +138,8 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|||||||
row={secondRow}
|
row={secondRow}
|
||||||
rowSpan={7}>
|
rowSpan={7}>
|
||||||
<CheckBox changed={handleAutoMountChanged}
|
<CheckBox changed={handleAutoMountChanged}
|
||||||
checked={props.PState.AutoMount} label={'Auto-mount'}/>
|
checked={props.PState.AutoMount}
|
||||||
|
label={'Auto-mount'}/>
|
||||||
</RootElem>
|
</RootElem>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -141,26 +155,28 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let removeControl;
|
let removeControl;
|
||||||
if (props.remote) {
|
if (props.allowRemove) {
|
||||||
const removeDisabled = !props.MState.AllowMount || props.MState.Mounted;
|
const removeDisabled = !props.MState.AllowMount || props.MState.Mounted;
|
||||||
const removeStyle = {
|
const removeStyle = {
|
||||||
cursor: removeDisabled ? 'no-drop' : 'pointer'
|
cursor: removeDisabled ? 'no-drop' : 'pointer'
|
||||||
};
|
};
|
||||||
const handleRemoveMount = () => {
|
const handleRemoveMount = () => {
|
||||||
if (!removeDisabled) {
|
if (!removeDisabled) {
|
||||||
props.removeRemoteMount(props.provider);
|
props.removeMount(props.provider);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
removeControl = (
|
removeControl = (
|
||||||
<a col={dimensions=>dimensions.columns - 6}
|
<RootElem col={dimensions=>dimensions.columns - 6}
|
||||||
href={void(0)}
|
row={secondRow + 3}>
|
||||||
onClick={handleRemoveMount}
|
<a href={'#'}
|
||||||
row={secondRow + 3}
|
onClick={handleRemoveMount}
|
||||||
style={removeStyle}>
|
style={removeStyle}>
|
||||||
<FontAwesomeIcon icon={faTrashAlt}/>
|
<FontAwesomeIcon icon={faTrashAlt}/>
|
||||||
</a>);
|
</a>
|
||||||
|
</RootElem>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isSkynet = (props.provider === 'Skynet');
|
||||||
return (
|
return (
|
||||||
<div className={'MountItem'}>
|
<div className={'MountItem'}>
|
||||||
<Grid noScroll>
|
<Grid noScroll>
|
||||||
@@ -168,8 +184,32 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|||||||
<Text
|
<Text
|
||||||
col={configButton ? 6 : 0}
|
col={configButton ? 6 : 0}
|
||||||
rowSpan={5}
|
rowSpan={5}
|
||||||
text={props.remote ? props.provider.substr(6) : props.provider}
|
colSpan={90}
|
||||||
type={'Heading1'}/>
|
text={props.remote ? props.provider.substr(6) : props.s3 ? props.provider.substr(2) : isSkynet ? props.provider + ' [EXPERIMENTAL]' : props.provider}
|
||||||
|
textAlign={'Left'}
|
||||||
|
type={'Heading2'}/>
|
||||||
|
{(isSkynet && (props.MState.Mounted)) ? (
|
||||||
|
<a href={'#'}
|
||||||
|
col={(configButton ? 24 : 18) + 34}
|
||||||
|
onClick={props.MState.AllowMount ? () => props.displaySkynetExport(true) : e => {
|
||||||
|
e.preventDefault();
|
||||||
|
}}
|
||||||
|
rowSpan={5}
|
||||||
|
style={{...pointer, fontWeight: 'normal'}}>
|
||||||
|
<u>Export</u>
|
||||||
|
</a>
|
||||||
|
) : null}
|
||||||
|
{(isSkynet && (props.MState.Mounted)) ? (
|
||||||
|
<a href={'#'}
|
||||||
|
col={(configButton ? 24 + 13 : 18 + 13) + 34}
|
||||||
|
onClick={props.MState.AllowMount ? () => props.displaySkynetImport(true) : e => {
|
||||||
|
e.preventDefault();
|
||||||
|
}}
|
||||||
|
rowSpan={5}
|
||||||
|
style={{...pointer, fontWeight: 'normal'}}>
|
||||||
|
<u>Import</u>
|
||||||
|
</a>
|
||||||
|
) : null}
|
||||||
{inputControls}
|
{inputControls}
|
||||||
{actionsDisplay}
|
{actionsDisplay}
|
||||||
{autoMountControl}
|
{autoMountControl}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import AddRemoteMount from '../AddRemoteMount/AddRemoteMount';
|
import AddMount from '../AddMount/AddMount';
|
||||||
import Box from '../../components/UI/Box/Box';
|
import Box from '../../components/UI/Box/Box';
|
||||||
import Button from '../../components/UI/Button/Button';
|
import Button from '../../components/UI/Button/Button';
|
||||||
import {connect} from 'react-redux';
|
import {connect} from 'react-redux';
|
||||||
@@ -80,6 +80,7 @@ class MountItems extends IPCContainer {
|
|||||||
|
|
||||||
this.sendRequest(Constants.IPC_Detect_Mount, {
|
this.sendRequest(Constants.IPC_Detect_Mount, {
|
||||||
RemoteMounts: this.props.RemoteMounts,
|
RemoteMounts: this.props.RemoteMounts,
|
||||||
|
S3Mounts: this.props.S3Mounts,
|
||||||
Provider: provider,
|
Provider: provider,
|
||||||
Version: this.props.InstalledVersion,
|
Version: this.props.InstalledVersion,
|
||||||
});
|
});
|
||||||
@@ -94,7 +95,7 @@ class MountItems extends IPCContainer {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
displayRetryMount = (provider, remote, mountLocation, msg) => {
|
displayRetryMount = (provider, remote, s3, mountLocation, msg) => {
|
||||||
if (!this.state.RetryItems[provider]) {
|
if (!this.state.RetryItems[provider]) {
|
||||||
let retryItems = {
|
let retryItems = {
|
||||||
...this.state.RetryItems
|
...this.state.RetryItems
|
||||||
@@ -121,7 +122,7 @@ class MountItems extends IPCContainer {
|
|||||||
const retrySeconds = retryItems[provider].RetrySeconds - 1;
|
const retrySeconds = retryItems[provider].RetrySeconds - 1;
|
||||||
if (retrySeconds === 0) {
|
if (retrySeconds === 0) {
|
||||||
this.cancelRetryMount(provider, () => {
|
this.cancelRetryMount(provider, () => {
|
||||||
this.handleMountUnMount(provider, remote,true, mountLocation);
|
this.handleMountUnMount(provider, remote, s3, true, mountLocation);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
retryItems[provider].RetrySeconds = retrySeconds;
|
retryItems[provider].RetrySeconds = retrySeconds;
|
||||||
@@ -152,17 +153,18 @@ class MountItems extends IPCContainer {
|
|||||||
this.props.setProviderState(provider, state);
|
this.props.setProviderState(provider, state);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleMountUnMount = (provider, remote, mount, location) => {
|
handleMountUnMount = (provider, remote, s3, mount, location) => {
|
||||||
if (!location || (location.trim().length === 0)) {
|
if (!location || (location.trim().length === 0)) {
|
||||||
this.props.notifyError('Mount location is not set');
|
this.props.notifyError('Mount location is not set');
|
||||||
} else {
|
} else {
|
||||||
let allowAction = true;
|
let allowAction = true;
|
||||||
if (mount) {
|
if (mount) {
|
||||||
let result = remote ?
|
let result = remote || s3 || provider === 'Skynet' ?
|
||||||
{Valid: true, Success: true} :
|
{Valid: true, Success: true} :
|
||||||
this.sendSyncRequest(Constants.IPC_Check_Daemon_Version, {
|
this.sendSyncRequest(Constants.IPC_Check_Daemon_Version, {
|
||||||
Provider: provider,
|
Provider: provider,
|
||||||
Remote: remote,
|
Remote: remote,
|
||||||
|
S3: s3,
|
||||||
Version: this.props.InstalledVersion
|
Version: this.props.InstalledVersion
|
||||||
}).data;
|
}).data;
|
||||||
if (result.Success) {
|
if (result.Success) {
|
||||||
@@ -179,11 +181,11 @@ class MountItems extends IPCContainer {
|
|||||||
} else {
|
} else {
|
||||||
allowAction = false;
|
allowAction = false;
|
||||||
if ((result.Code === new Uint32Array([-1])[0]) || (result.Code === new Uint8Array([-1])[0])) {
|
if ((result.Code === new Uint32Array([-1])[0]) || (result.Code === new Uint8Array([-1])[0])) {
|
||||||
this.displayRetryMount(provider, remote, location, 'Failed to connect to ' + provider + ' daemon');
|
this.displayRetryMount(provider, remote, s3, location, 'Failed to connect to ' + provider + ' daemon');
|
||||||
} else if ((result.Code === new Uint32Array([-3])[0]) || (result.Code === new Uint8Array([-3])[0])) {
|
} else if ((result.Code === new Uint32Array([-3])[0]) || (result.Code === new Uint8Array([-3])[0])) {
|
||||||
this.displayRetryMount(provider, remote, location, 'Incompatible ' + provider + ' daemon. Please upgrade ' + provider + '.');
|
this.displayRetryMount(provider, remote, s3, location, 'Incompatible ' + provider + ' daemon. Please upgrade ' + provider + '.');
|
||||||
} else {
|
} else {
|
||||||
this.displayRetryMount(provider, remote, location, 'Version check failed: ' + result.Error);
|
this.displayRetryMount(provider, remote, s3, location, 'Version check failed: ' + result.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -191,7 +193,7 @@ class MountItems extends IPCContainer {
|
|||||||
if (this.props.Platform === 'win32') {
|
if (this.props.Platform === 'win32') {
|
||||||
this.props.notifyError('Failed to launch repertory. Please install Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019.');
|
this.props.notifyError('Failed to launch repertory. Please install Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019.');
|
||||||
} else {
|
} else {
|
||||||
this.displayRetryMount(provider, remote, location, 'Version check failed: ' + result.Error);
|
this.displayRetryMount(provider, remote, s3, location, 'Version check failed: ' + result.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -205,6 +207,7 @@ class MountItems extends IPCContainer {
|
|||||||
Location: location,
|
Location: location,
|
||||||
Provider: provider,
|
Provider: provider,
|
||||||
Remote: remote,
|
Remote: remote,
|
||||||
|
S3: s3,
|
||||||
Version: this.props.InstalledVersion,
|
Version: this.props.InstalledVersion,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -212,6 +215,7 @@ class MountItems extends IPCContainer {
|
|||||||
Location: location,
|
Location: location,
|
||||||
Provider: provider,
|
Provider: provider,
|
||||||
Remote: remote,
|
Remote: remote,
|
||||||
|
S3: s3,
|
||||||
Version: this.props.InstalledVersion,
|
Version: this.props.InstalledVersion,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -219,10 +223,27 @@ class MountItems extends IPCContainer {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
getProviderList = () => {
|
getProviderList = providersOnly => {
|
||||||
|
const providerList = Constants.PROVIDER_LIST.filter(i => {
|
||||||
|
return ((i === 'Skynet') && this.props.skynetSupported) ||
|
||||||
|
((i === 'ScPrime') && this.props.scPrimeSupported) ||
|
||||||
|
((i === 'Sia') && this.props.siaSupported);
|
||||||
|
});
|
||||||
|
|
||||||
|
let remoteList = [];
|
||||||
|
if (this.props.remoteSupported && !providersOnly) {
|
||||||
|
remoteList = [...this.props.RemoteMounts];
|
||||||
|
}
|
||||||
|
|
||||||
|
let s3List = [];
|
||||||
|
if (this.props.s3Supported && !providersOnly) {
|
||||||
|
s3List = [...this.props.S3Mounts];
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
...Constants.PROVIDER_LIST,
|
...providerList,
|
||||||
...this.props.RemoteMounts,
|
...remoteList,
|
||||||
|
...s3List,
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -298,7 +319,7 @@ class MountItems extends IPCContainer {
|
|||||||
this.props.ProviderState[provider].AutoMount &&
|
this.props.ProviderState[provider].AutoMount &&
|
||||||
!mounted &&
|
!mounted &&
|
||||||
(location.length > 0)) {
|
(location.length > 0)) {
|
||||||
this.handleMountUnMount(provider, this.props.RemoteMounts.includes(provider),true, location);
|
this.handleMountUnMount(provider, this.props.RemoteMounts.includes(provider), this.props.S3Mounts.includes(provider), true, location);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -325,7 +346,11 @@ class MountItems extends IPCContainer {
|
|||||||
retryDisplay = (
|
retryDisplay = (
|
||||||
<Modal>
|
<Modal>
|
||||||
<Box dxDark dxStyle={{padding: 'var(--default_spacing)', minWidth: '70vw'}}>
|
<Box dxDark dxStyle={{padding: 'var(--default_spacing)', minWidth: '70vw'}}>
|
||||||
<h1 style={{textAlign: 'center', paddingBottom: 'var(--default_spacing)', color: 'var(--text_color_error)'}}>Mount Failed</h1>
|
<h1 style={{
|
||||||
|
textAlign: 'center',
|
||||||
|
paddingBottom: 'var(--default_spacing)',
|
||||||
|
color: 'var(--text_color_error)'
|
||||||
|
}}>Mount Failed</h1>
|
||||||
{retryList}
|
{retryList}
|
||||||
</Box>
|
</Box>
|
||||||
</Modal>
|
</Modal>
|
||||||
@@ -333,15 +358,17 @@ class MountItems extends IPCContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let footerItems = [];
|
let footerItems = [];
|
||||||
if (this.props.remoteSupported) {
|
if (this.props.remoteSupported || this.props.s3Supported) {
|
||||||
footerItems.push(<AddRemoteMount key={'hi_' + footerItems.length}/>);
|
footerItems.push(<AddMount remoteSupported={this.props.remoteSupported}
|
||||||
|
s3Supported={this.props.s3Supported}
|
||||||
|
key={'hi_' + footerItems.length}/>);
|
||||||
} else {
|
} else {
|
||||||
footerItems.push(<div key={'hi_' + footerItems.length}
|
footerItems.push(<div key={'hi_' + footerItems.length}
|
||||||
style={{height: '27px'}}/>);
|
style={{height: '27px'}}/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
let items = [];
|
let items = [];
|
||||||
for (const provider of Constants.PROVIDER_LIST) {
|
for (const provider of this.getProviderList(true)) {
|
||||||
items.push((
|
items.push((
|
||||||
<MountItem allowRemove={false}
|
<MountItem allowRemove={false}
|
||||||
browseClicked={this.handleBrowseLocation}
|
browseClicked={this.handleBrowseLocation}
|
||||||
@@ -368,15 +395,31 @@ class MountItems extends IPCContainer {
|
|||||||
items.push(<div key={'it_' + items.length}
|
items.push(<div key={'it_' + items.length}
|
||||||
style={{paddingTop: 'var(--default_spacing)'}}/>)
|
style={{paddingTop: 'var(--default_spacing)'}}/>)
|
||||||
}
|
}
|
||||||
items.splice(items.length - 1, 1);
|
|
||||||
} else {
|
|
||||||
items.splice(items.length - 1, 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.props.s3Supported) {
|
||||||
|
for (const provider of this.props.S3Mounts) {
|
||||||
|
items.push((
|
||||||
|
<MountItem allowRemove={true}
|
||||||
|
browseClicked={this.handleBrowseLocation}
|
||||||
|
changed={e => this.handleMountLocationChanged(provider, e.target.value)}
|
||||||
|
clicked={this.handleMountUnMount}
|
||||||
|
key={'it_' + items.length}
|
||||||
|
provider={provider}
|
||||||
|
s3/>
|
||||||
|
));
|
||||||
|
items.push(<div key={'it_' + items.length}
|
||||||
|
style={{paddingTop: 'var(--default_spacing)'}}/>)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
items.splice(items.length - 1, 1);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{margin: 0, padding: 0}}>
|
<div style={{margin: 0, padding: 0}}>
|
||||||
{retryDisplay}
|
{retryDisplay}
|
||||||
<div className={this.props.remoteSupported ? 'MountItemsRemote' : 'MountItems'}>
|
<div
|
||||||
|
className={this.props.remoteSupported || this.props.s3Supported ? 'MountItemsRemote' : 'MountItems'}>
|
||||||
{items}
|
{items}
|
||||||
</div>
|
</div>
|
||||||
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
||||||
@@ -394,6 +437,7 @@ const mapStateToProps = state => {
|
|||||||
Platform: state.common.Platform,
|
Platform: state.common.Platform,
|
||||||
ProviderState: state.mounts.ProviderState,
|
ProviderState: state.mounts.ProviderState,
|
||||||
RemoteMounts: state.mounts.RemoteMounts,
|
RemoteMounts: state.mounts.RemoteMounts,
|
||||||
|
S3Mounts: state.mounts.S3Mounts,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
44
src/containers/PinnedManager/PinnedManager.css
Normal file
44
src/containers/PinnedManager/PinnedManager.css
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
.PinnedManager {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PinnedManagerActiveDirectory {
|
||||||
|
margin-top: var(--default_spacing);
|
||||||
|
margin-bottom: var(--default_spacing);
|
||||||
|
padding: 2px;
|
||||||
|
width: calc(100% - 4px);
|
||||||
|
overflow: auto;
|
||||||
|
text-align: left;
|
||||||
|
border-radius: var(--border_radius);
|
||||||
|
background: var(--control_background);
|
||||||
|
}
|
||||||
|
|
||||||
|
.PinnedManagerClose {
|
||||||
|
float: right;
|
||||||
|
flex: 0;
|
||||||
|
padding: 0;
|
||||||
|
margin-top: -4px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PinnedManagerHeading {
|
||||||
|
flex: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PinnedManagerItems {
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PinnedManagerItemsOwner {
|
||||||
|
margin: 0;
|
||||||
|
padding: var(--default_spacing);
|
||||||
|
border-radius: var(--border_radius);
|
||||||
|
background: var(--control_background);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
180
src/containers/PinnedManager/PinnedManager.js
Normal file
180
src/containers/PinnedManager/PinnedManager.js
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import './PinnedManager.css';
|
||||||
|
import {connect} from 'react-redux';
|
||||||
|
import IPCContainer from '../IPCContainer/IPCContainer';
|
||||||
|
import {notifyApplicationBusy} from '../../redux/actions/common_actions';
|
||||||
|
import {notifyError, notifyInfo} from '../../redux/actions/error_actions';
|
||||||
|
import Box from '../../components/UI/Box/Box';
|
||||||
|
import {displayPinnedManager} from '../../redux/actions/pinned_manager_actions';
|
||||||
|
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||||
|
import {faFolder} from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import Button from '../../components/UI/Button/Button';
|
||||||
|
import CheckBox from '../../components/UI/CheckBox/CheckBox';
|
||||||
|
|
||||||
|
const Constants = require('../../constants');
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
return {
|
||||||
|
DisplayConfiguration: state.mounts.DisplayConfiguration,
|
||||||
|
DisplayRemoteConfiguration: state.mounts.DisplayRemoteConfiguration,
|
||||||
|
DisplayS3Configuration: state.mounts.DisplayS3Configuration,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
displayPinnedManager: display => dispatch(displayPinnedManager(display)),
|
||||||
|
notifyApplicationBusy: busy => dispatch(notifyApplicationBusy(busy, true)),
|
||||||
|
notifyError: (msg, cb) => dispatch(notifyError(msg, false, cb)),
|
||||||
|
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(class extends IPCContainer {
|
||||||
|
state = {
|
||||||
|
active_directory: '/',
|
||||||
|
items: [],
|
||||||
|
previous: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.setRequestHandler(Constants.IPC_Get_Directory_Items_Reply, this.onGetDirectoryItemsReply);
|
||||||
|
this.grabDirectoryItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
super.componentWillUnmount();
|
||||||
|
}
|
||||||
|
|
||||||
|
grabDirectoryItems = () => {
|
||||||
|
this.sendRequest(Constants.IPC_Get_Directory_Items, {
|
||||||
|
Provider: this.props.DisplayConfiguration,
|
||||||
|
Remote: this.props.DisplayRemoteConfiguration,
|
||||||
|
S3: this.props.DisplayS3Configuration,
|
||||||
|
Version: this.props.version,
|
||||||
|
Path: this.state.active_directory,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onGetDirectoryItemsReply = (_, {data}) => {
|
||||||
|
if (data.Success) {
|
||||||
|
const items = data.Items
|
||||||
|
.filter(i => i.path !== '.' && (this.state.active_directory !== '/' || (i.path.substr(0, 1) !== '.')))
|
||||||
|
.map(i => {
|
||||||
|
return {
|
||||||
|
...i,
|
||||||
|
name: i.path === '..' ? i.path : i.path.substr(i.path.lastIndexOf('/') + 1),
|
||||||
|
meta: {
|
||||||
|
...i.meta,
|
||||||
|
pinned: i.meta.pinned === '1',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.setState({
|
||||||
|
items,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.props.notifyError(data.Error, () => {
|
||||||
|
this.props.displayPinnedManager(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createDirectory = (name, path, idx, total, item_idx) => {
|
||||||
|
const style = {}
|
||||||
|
if (item_idx + 1 !== total) {
|
||||||
|
style.marginBottom = '4px';
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div key={'dir_' + idx} style={{...style}}>
|
||||||
|
<Button buttonStyles={{textAlign: 'left'}}
|
||||||
|
clicked={() => {
|
||||||
|
const previous = [...this.state.previous];
|
||||||
|
if (path === '..') {
|
||||||
|
path = previous.pop();
|
||||||
|
} else {
|
||||||
|
previous.push(this.state.active_directory);
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
items: [],
|
||||||
|
active_directory: path,
|
||||||
|
previous,
|
||||||
|
}, () => {
|
||||||
|
this.grabDirectoryItems();
|
||||||
|
});
|
||||||
|
}}>
|
||||||
|
<FontAwesomeIcon icon={faFolder}
|
||||||
|
fixedWidth
|
||||||
|
color={'var(--heading_text_color)'}
|
||||||
|
style={{padding: 0, margin: 0}}/>
|
||||||
|
{name}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
createFile = (name, path, pinned, idx, total, item_idx) => {
|
||||||
|
const style = {textAlign: 'left'}
|
||||||
|
if (item_idx + 1 !== total) {
|
||||||
|
style.marginBottom = '2px';
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div key={'file_' + idx} style={{...style}}>
|
||||||
|
<CheckBox checked={pinned}
|
||||||
|
changed={() => {
|
||||||
|
const items = JSON.parse(JSON.stringify(this.state.items));
|
||||||
|
const pinned = items[item_idx].meta.pinned = !items[item_idx].meta.pinned;
|
||||||
|
this.setState({
|
||||||
|
items
|
||||||
|
}, () => {
|
||||||
|
this.sendSyncRequest(Constants.IPC_Set_Pinned, {
|
||||||
|
Provider: this.props.DisplayConfiguration,
|
||||||
|
Remote: this.props.DisplayRemoteConfiguration,
|
||||||
|
S3: this.props.DisplayS3Configuration,
|
||||||
|
Version: this.props.version,
|
||||||
|
Path: path,
|
||||||
|
Pinned: pinned,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
label={name}/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let idx = 0;
|
||||||
|
return (
|
||||||
|
<Box dxDark dxStyle={{
|
||||||
|
height: 'calc(100vh - (var(--default_spacing) * 4)',
|
||||||
|
padding: 'var(--default_spacing)',
|
||||||
|
width: 'calc(100vw - (var(--default_spacing) * 4)'
|
||||||
|
}}>
|
||||||
|
<div className={'PinnedManager'}>
|
||||||
|
<div className={'PinnedManagerHeading'}>
|
||||||
|
<div className={'PinnedManagerClose'}>
|
||||||
|
<a href={'#'}
|
||||||
|
onClick={() => this.props.displayPinnedManager(false)}
|
||||||
|
style={{cursor: 'pointer', flex: '0'}}>X</a>
|
||||||
|
</div>
|
||||||
|
<h1 style={{width: '100%', textAlign: 'center'}}>{'Pinned File Manager'}</h1>
|
||||||
|
<div className={'PinnedManagerActiveDirectory'}>
|
||||||
|
<b> {this.state.active_directory}</b>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={'PinnedManagerItemsOwner'}>
|
||||||
|
<div className={'PinnedManagerItems'}>
|
||||||
|
{
|
||||||
|
this.state.items.map((i, k) => {
|
||||||
|
return i.directory ?
|
||||||
|
this.createDirectory(i.name, i.path, idx++, this.state.items.length, k) :
|
||||||
|
this.createFile(i.name, i.path, i.meta.pinned, idx++, this.state.items.length, k);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
});
|
||||||
21
src/containers/SkynetExport/SkynetExport.css
Normal file
21
src/containers/SkynetExport/SkynetExport.css
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
.SkynetExportHeading {
|
||||||
|
text-align: center;
|
||||||
|
padding-bottom: var(--default_spacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
.SkynetExportList {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: auto;
|
||||||
|
height: calc(90vh - 80px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.SkynetExportTree {
|
||||||
|
display: inline-flex;
|
||||||
|
overflow-x: scroll;
|
||||||
|
overflow-y: scroll;
|
||||||
|
white-space: nowrap;
|
||||||
|
height: calc(90vh - 80px);
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
235
src/containers/SkynetExport/SkynetExport.js
Normal file
235
src/containers/SkynetExport/SkynetExport.js
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import './SkynetExport.css';
|
||||||
|
import CheckboxTree from 'react-checkbox-tree';
|
||||||
|
import {connect} from 'react-redux';
|
||||||
|
import IPCContainer from '../IPCContainer/IPCContainer';
|
||||||
|
import {notifyApplicationBusy} from '../../redux/actions/common_actions';
|
||||||
|
import {notifyError, notifyInfo} from '../../redux/actions/error_actions';
|
||||||
|
import Box from '../../components/UI/Box/Box';
|
||||||
|
import {displaySkynetExport} from '../../redux/actions/skynet_actions';
|
||||||
|
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||||
|
import {
|
||||||
|
faCheckSquare, faChevronDown,
|
||||||
|
faChevronRight, faFile, faFolder, faFolderOpen,
|
||||||
|
faHSquare, faMinusSquare, faPlusSquare,
|
||||||
|
faSquare
|
||||||
|
} from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import Button from '../../components/UI/Button/Button';
|
||||||
|
|
||||||
|
const Constants = require('../../constants');
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
return {
|
||||||
|
AppBusy: state.common.AppBusy,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
displaySkynetExport: display => dispatch(displaySkynetExport(display)),
|
||||||
|
notifyApplicationBusy: busy => dispatch(notifyApplicationBusy(busy, true)),
|
||||||
|
notifyError: msg => dispatch(notifyError(msg)),
|
||||||
|
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(class extends IPCContainer {
|
||||||
|
state = {
|
||||||
|
checked: [],
|
||||||
|
clicked: {},
|
||||||
|
expanded: [],
|
||||||
|
nodes: [],
|
||||||
|
second_stage: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.setRequestHandler(Constants.IPC_Grab_Skynet_Tree_Reply, this.onGrabSkynetTreeReply);
|
||||||
|
this.setRequestHandler(Constants.IPC_Export_Skylinks_Reply, this.onExportSkylinksReply);
|
||||||
|
this.sendRequest(Constants.IPC_Grab_Skynet_Tree, {Version: this.props.version});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
super.componentWillUnmount();
|
||||||
|
}
|
||||||
|
|
||||||
|
createNodes = items => {
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
name: '',
|
||||||
|
path: '',
|
||||||
|
directory: true/false,
|
||||||
|
children: [],
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
const ret = [];
|
||||||
|
for (const item of items) {
|
||||||
|
const treeItem = {
|
||||||
|
label: item.name,
|
||||||
|
path: item.path,
|
||||||
|
value: item.name === '/' ? 0 : item.path ? item.path : JSON.stringify(item),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (item.directory) {
|
||||||
|
treeItem.children = this.createNodes(item.children);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.push(treeItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleNavigation = () => {
|
||||||
|
if (this.state.second_stage) {
|
||||||
|
this.props.notifyApplicationBusy(true);
|
||||||
|
this.sendRequest(Constants.IPC_Export_Skylinks, {
|
||||||
|
Version: this.props.version,
|
||||||
|
Paths: this.state.checked,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (this.state.checked.length === 0) {
|
||||||
|
this.props.notifyError('No files have been checked');
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
second_stage: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onExportSkylinksReply = (_, arg) => {
|
||||||
|
this.props.notifyApplicationBusy(false);
|
||||||
|
if (arg.data.Success) {
|
||||||
|
this.setState({
|
||||||
|
checked: [],
|
||||||
|
clicked: {},
|
||||||
|
expanded: [],
|
||||||
|
nodes: [],
|
||||||
|
second_stage: false,
|
||||||
|
}, () => {
|
||||||
|
this.props.notifyInfo('Skylink Exports', '!alternate!!copyable!' + JSON.stringify(arg.data.Result.success, null, 2));
|
||||||
|
this.sendRequest(Constants.IPC_Grab_Skynet_Tree, {Version: this.props.version});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.props.notifyError(arg.data.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onGrabSkynetTreeReply = (_, arg) => {
|
||||||
|
if (arg.data.Success) {
|
||||||
|
this.setState({
|
||||||
|
checked: [],
|
||||||
|
expanded: [0],
|
||||||
|
nodes: this.createNodes(arg.data.Result),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
checked: [],
|
||||||
|
expanded: [],
|
||||||
|
nodes: [],
|
||||||
|
}, () => {
|
||||||
|
this.props.notifyError(arg.data.Error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return this.props.AppBusy ? (<div/>) : (
|
||||||
|
<Box dxDark dxStyle={{
|
||||||
|
height: '90vh',
|
||||||
|
padding: 'var(--default_spacing)',
|
||||||
|
width: 'calc(100vw - (var(--default_spacing) * 4)'
|
||||||
|
}}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
float: 'right',
|
||||||
|
margin: 0,
|
||||||
|
padding: 0,
|
||||||
|
marginTop: '-4px',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
display: 'block'
|
||||||
|
}}>
|
||||||
|
<a href={'#'}
|
||||||
|
onClick={() => this.props.displaySkynetExport(false)}
|
||||||
|
style={{cursor: 'pointer'}}>X</a>
|
||||||
|
</div>
|
||||||
|
<h1
|
||||||
|
className={'SkynetExportHeading'}>{this.state.second_stage ? 'Verify Exports' : 'Export Files'}</h1>
|
||||||
|
<div className={this.state.second_stage ? 'SkynetExportList' : 'SkynetExportTree'}>
|
||||||
|
{
|
||||||
|
this.state.second_stage ?
|
||||||
|
this.state.checked.map(path => {
|
||||||
|
return (
|
||||||
|
<input readOnly
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
key={path}
|
||||||
|
style={{width: '100%', marginBottom: 'var(--default_spacing)'}}
|
||||||
|
type={'text'}
|
||||||
|
value={path}/>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
: (
|
||||||
|
<CheckboxTree checked={this.state.checked}
|
||||||
|
expanded={this.state.expanded}
|
||||||
|
expandOnClick
|
||||||
|
showExpandAll
|
||||||
|
icons={{
|
||||||
|
check: <FontAwesomeIcon icon={faCheckSquare} fixedWidth
|
||||||
|
style={{padding: 0, margin: 0}}/>,
|
||||||
|
uncheck: <FontAwesomeIcon icon={faSquare} fixedWidth
|
||||||
|
style={{padding: 0, margin: 0}}/>,
|
||||||
|
halfCheck: <FontAwesomeIcon icon={faHSquare} fixedWidth
|
||||||
|
style={{padding: 0, margin: 0}}/>,
|
||||||
|
expandClose: <FontAwesomeIcon icon={faChevronRight} fixedWidth
|
||||||
|
style={{padding: 0, margin: 0}}/>,
|
||||||
|
expandOpen: <FontAwesomeIcon icon={faChevronDown} fixedWidth
|
||||||
|
style={{padding: 0, margin: 0}}/>,
|
||||||
|
expandAll: <FontAwesomeIcon icon={faPlusSquare} fixedWidth
|
||||||
|
style={{padding: 0, margin: 0}}/>,
|
||||||
|
collapseAll: <FontAwesomeIcon icon={faMinusSquare} fixedWidth
|
||||||
|
style={{padding: 0, margin: 0}}/>,
|
||||||
|
parentClose: <FontAwesomeIcon icon={faFolder}
|
||||||
|
fixedWidth
|
||||||
|
color={'var(--heading_text_color)'}
|
||||||
|
style={{padding: 0, margin: 0}}/>,
|
||||||
|
parentOpen: <FontAwesomeIcon icon={faFolderOpen}
|
||||||
|
fixedWidth
|
||||||
|
color={'var(--heading_text_color)'}
|
||||||
|
style={{padding: 0, margin: 0}}/>,
|
||||||
|
leaf: <FontAwesomeIcon icon={faFile}
|
||||||
|
fixedWidth
|
||||||
|
color={'var(--text_color)'}
|
||||||
|
style={{padding: 0, margin: 0}}/>
|
||||||
|
}}
|
||||||
|
nodes={this.state.nodes}
|
||||||
|
onClick={clicked => this.setState({clicked})}
|
||||||
|
onCheck={checked => this.setState({checked})}
|
||||||
|
onExpand={expanded => this.setState({expanded})}/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div style={{display: 'flex', justifyContent: 'flex-end'}}>
|
||||||
|
{
|
||||||
|
this.state.second_stage ?
|
||||||
|
<Button buttonStyles={{
|
||||||
|
height: 'auto',
|
||||||
|
marginLeft: 'var(--default_spacing)',
|
||||||
|
marginTop: 'var(--default_spacing)',
|
||||||
|
width: 'auto'
|
||||||
|
}} clicked={() => this.setState({
|
||||||
|
second_stage: false,
|
||||||
|
})}>{'Back'}</Button> :
|
||||||
|
null
|
||||||
|
}
|
||||||
|
<Button buttonStyles={{
|
||||||
|
height: 'auto',
|
||||||
|
marginLeft: 'var(--default_spacing)',
|
||||||
|
marginTop: 'var(--default_spacing)',
|
||||||
|
width: 'auto'
|
||||||
|
}}
|
||||||
|
clicked={this.handleNavigation}>{this.state.second_stage ? 'Export' : 'Next'}</Button>
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
7
src/containers/SkynetImport/ImportList/Import/Import.css
Normal file
7
src/containers/SkynetImport/ImportList/Import/Import.css
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
.ImportOwner {
|
||||||
|
display: flex;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin: 0;
|
||||||
|
padding-bottom: var(--default_spacing);
|
||||||
|
}
|
||||||
24
src/containers/SkynetImport/ImportList/Import/Import.js
Normal file
24
src/containers/SkynetImport/ImportList/Import/Import.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import './Import.css'
|
||||||
|
|
||||||
|
export default ({data}) => {
|
||||||
|
return (
|
||||||
|
<div className={'ImportOwner'}>
|
||||||
|
<input readOnly
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{maxWidth: 'calc(33.33% - var(--default_spacing)', marginRight: 'var(--default_spacing)'}}
|
||||||
|
type={'text'}
|
||||||
|
value={data.directory}/>
|
||||||
|
<input readOnly
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{maxWidth: 'calc(33.33% - calc(var(--default_spacing) / 2))'}}
|
||||||
|
type={'text'}
|
||||||
|
value={data.skylink}/>
|
||||||
|
<input readOnly
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{maxWidth: 'calc(33.33% - calc(var(--default_spacing) / 2))', marginLeft: 'var(--default_spacing)'}}
|
||||||
|
type={'text'}
|
||||||
|
value={data.token}/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
13
src/containers/SkynetImport/ImportList/ImportList.css
Normal file
13
src/containers/SkynetImport/ImportList/ImportList.css
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
.ImportListOwner {
|
||||||
|
max-height: 56vh;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ImportListHeader {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
29
src/containers/SkynetImport/ImportList/ImportList.js
Normal file
29
src/containers/SkynetImport/ImportList/ImportList.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import './ImportList.css'
|
||||||
|
import Import from './Import/Import'
|
||||||
|
import Text from '../../../components/UI/Text/Text';
|
||||||
|
|
||||||
|
export default ({imports_array}) => {
|
||||||
|
let key = 0;
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className={'ImportListHeader'}>
|
||||||
|
<Text type={'Heading1'} text={'Directory'} style={{minWidth: '33.33%', maxWidth: '33.33%'}}/>
|
||||||
|
<Text type={'Heading1'} text={'Skylink'} style={{minWidth: '33.33%', maxWidth: '33.33%'}}/>
|
||||||
|
<Text type={'Heading1'} text={'Token'} style={{minWidth: '33.33%', maxWidth: '33.33%'}}/>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
<div className={'ImportListOwner'}>
|
||||||
|
{
|
||||||
|
imports_array.map(data => {
|
||||||
|
return (
|
||||||
|
<div key={'import_' + key++}>
|
||||||
|
<Import data={data}/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
31
src/containers/SkynetImport/SkynetImport.css
Normal file
31
src/containers/SkynetImport/SkynetImport.css
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
.SkynetImportTextArea {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 2px;
|
||||||
|
border-radius: var(--border_radius);
|
||||||
|
background: var(--control_background);
|
||||||
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
outline: none;
|
||||||
|
color: var(--text_color);
|
||||||
|
box-sizing: border-box;
|
||||||
|
resize: none;
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow: -moz-scrollbars-horizontal;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SkynetImportButtons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SkynetActionButtons {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.SkynetImportHeading {
|
||||||
|
text-align: center;
|
||||||
|
padding-bottom: var(--default_spacing);
|
||||||
|
}
|
||||||
228
src/containers/SkynetImport/SkynetImport.js
Normal file
228
src/containers/SkynetImport/SkynetImport.js
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {connect} from 'react-redux';
|
||||||
|
import './SkynetImport.css'
|
||||||
|
import Box from '../../components/UI/Box/Box';
|
||||||
|
import Button from '../../components/UI/Button/Button';
|
||||||
|
import {displaySkynetImport} from '../../redux/actions/skynet_actions';
|
||||||
|
import ImportList from './ImportList/ImportList'
|
||||||
|
import IPCContainer from '../IPCContainer/IPCContainer';
|
||||||
|
import {notifyApplicationBusy} from '../../redux/actions/common_actions';
|
||||||
|
import {
|
||||||
|
notifyError,
|
||||||
|
notifyInfo
|
||||||
|
} from '../../redux/actions/error_actions';
|
||||||
|
|
||||||
|
const Constants = require('../../constants');
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
return {
|
||||||
|
AppBusy: state.common.AppBusy,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
displaySkynetImport: display => dispatch(displaySkynetImport(display)),
|
||||||
|
notifyApplicationBusy: busy => dispatch(notifyApplicationBusy(busy, true)),
|
||||||
|
notifyError: msg => dispatch(notifyError(msg)),
|
||||||
|
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(class extends IPCContainer {
|
||||||
|
|
||||||
|
state = {
|
||||||
|
import_text: '',
|
||||||
|
imports_array: [],
|
||||||
|
second_stage: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.setRequestHandler(Constants.IPC_Import_Skylinks_Reply, this.onImportSkylinksReply);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
super.componentWillUnmount();
|
||||||
|
}
|
||||||
|
|
||||||
|
displaySyntax = () => {
|
||||||
|
const msg = '!alternate!To import Skylinks into the root directory, list each Skylink on a new line:\n' +
|
||||||
|
' AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA\n' +
|
||||||
|
' AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg\n' +
|
||||||
|
'\n' +
|
||||||
|
'To import Skylinks into new or existing directories, use the following syntax:\n' +
|
||||||
|
' directory="/my/sub/dir",skylink="AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA"\n' +
|
||||||
|
' directory="/my/sub/dir2",skylink="AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg"\n' +
|
||||||
|
'\n' +
|
||||||
|
'You can also specify a password if this in an encrypted Repertory Skylink:\n' +
|
||||||
|
' directory="/my/sub/dir",skylink="AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA",token="My Password"\n' +
|
||||||
|
' directory="/my/sub/dir",skylink="AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg",token="My Password"\n' +
|
||||||
|
'\n' +
|
||||||
|
'To import Skylinks using JSON syntax:\n' +
|
||||||
|
' [\n' +
|
||||||
|
' {\n' +
|
||||||
|
' "directory": "/",\n' +
|
||||||
|
' "skylink": "AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA",\n' +
|
||||||
|
' "token": "My Password"\n' +
|
||||||
|
' },\n' +
|
||||||
|
' {\n' +
|
||||||
|
' "directory": "/my/sub/dir",\n' +
|
||||||
|
' "skylink": "AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg",\n' +
|
||||||
|
' "token": "My Password"\n' +
|
||||||
|
' }\n' +
|
||||||
|
' ]';
|
||||||
|
this.props.notifyInfo('Import Syntax', msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleNavigation = () => {
|
||||||
|
if (this.state.second_stage) {
|
||||||
|
try {
|
||||||
|
this.props.notifyApplicationBusy(true);
|
||||||
|
this.sendRequest(Constants.IPC_Import_Skylinks, {
|
||||||
|
Version: this.props.version,
|
||||||
|
JsonArray: this.state.imports_array,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
this.props.notifyApplicationBusy(false);
|
||||||
|
this.props.notifyError(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const items = this.state.import_text.split('\n');
|
||||||
|
let importsArray = [];
|
||||||
|
try {
|
||||||
|
for (let item of items) {
|
||||||
|
item = item.trim();
|
||||||
|
if (item.startsWith('[')) {
|
||||||
|
importsArray = JSON.parse(this.state.import_text.trim());
|
||||||
|
break;
|
||||||
|
} else if (item.indexOf('=') >= 0) {
|
||||||
|
const parts = item.split(',')
|
||||||
|
let importItem = {
|
||||||
|
directory: '/',
|
||||||
|
skylink: '',
|
||||||
|
token: '',
|
||||||
|
};
|
||||||
|
for (let part of parts) {
|
||||||
|
part = part.trim();
|
||||||
|
const pair = part.split('=');
|
||||||
|
if (pair.length !== 2) {
|
||||||
|
throw new Error('Invalid syntax for import: directory="",skylink="",token=""');
|
||||||
|
}
|
||||||
|
importItem = {
|
||||||
|
...importItem,
|
||||||
|
[pair[0].trim()]: pair[1].trim().replace(/"/g, ''),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!importItem.skylink) {
|
||||||
|
throw new Error('Invalid syntax for import: directory="",skylink="",token=""');
|
||||||
|
}
|
||||||
|
importsArray.push(importItem);
|
||||||
|
} else if (item.length > 0) {
|
||||||
|
importsArray.push({
|
||||||
|
directory: '/',
|
||||||
|
skylink: item,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (importsArray.length === 0) {
|
||||||
|
throw new Error('Nothing to import');
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
imports_array: importsArray,
|
||||||
|
second_stage: true,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
this.props.notifyError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onImportSkylinksReply = (_, arg) => {
|
||||||
|
this.props.notifyApplicationBusy(false);
|
||||||
|
if (arg.data.Success) {
|
||||||
|
const failedImportsArray = this.state.imports_array.filter(i => {
|
||||||
|
return arg.data.Result.failed.includes(i.skylink);
|
||||||
|
});
|
||||||
|
const count = this.state.imports_array.length;
|
||||||
|
this.setState({
|
||||||
|
import_text: failedImportsArray.length > 0 ? JSON.stringify(failedImportsArray, null, 2) : '',
|
||||||
|
imports_array: [],
|
||||||
|
second_stage: false,
|
||||||
|
}, () => {
|
||||||
|
if (failedImportsArray.length > 0) {
|
||||||
|
this.props.notifyError(`Failed to import ${failedImportsArray.length} item(s)`);
|
||||||
|
} else {
|
||||||
|
this.props.notifyInfo('Import Result', `Successfully imported ${count} item(s)`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.props.notifyError(arg.data.Error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return this.props.AppBusy ? (<div/>) : (
|
||||||
|
<Box dxDark dxStyle={{
|
||||||
|
height: 'auto',
|
||||||
|
padding: 'var(--default_spacing)',
|
||||||
|
width: 'calc(100vw - (var(--default_spacing) * 4)'
|
||||||
|
}}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
float: 'right',
|
||||||
|
margin: 0,
|
||||||
|
padding: 0,
|
||||||
|
marginTop: '-4px',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
display: 'block'
|
||||||
|
}}>
|
||||||
|
<a href={'#'}
|
||||||
|
onClick={() => this.props.displaySkynetImport(false)}
|
||||||
|
style={{cursor: 'pointer'}}>X</a>
|
||||||
|
</div>
|
||||||
|
<h1
|
||||||
|
className={'SkynetImportHeading'}>{this.state.second_stage ? 'Verify Imports' : 'Import List'}</h1>
|
||||||
|
{
|
||||||
|
this.state.second_stage ? (
|
||||||
|
<ImportList imports_array={this.state.imports_array}/>
|
||||||
|
) : (
|
||||||
|
<textarea autoFocus={true}
|
||||||
|
className={'SkynetImportTextArea'}
|
||||||
|
onChange={e => this.setState({
|
||||||
|
import_text: e.target.value,
|
||||||
|
})}
|
||||||
|
value={this.state.import_text}
|
||||||
|
rows={10}/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<div className={'SkynetImportButtons'}>
|
||||||
|
<Button
|
||||||
|
buttonStyles={{height: 'auto', marginTop: 'var(--default_spacing)', width: 'auto'}}
|
||||||
|
clicked={this.displaySyntax}>Import Syntax...</Button>
|
||||||
|
<div className={'SkynetActionButtons'}>
|
||||||
|
{
|
||||||
|
this.state.second_stage ?
|
||||||
|
<Button buttonStyles={{
|
||||||
|
height: 'auto',
|
||||||
|
marginLeft: 'var(--default_spacing)',
|
||||||
|
marginTop: 'var(--default_spacing)',
|
||||||
|
width: 'auto'
|
||||||
|
}} clicked={() => this.setState({
|
||||||
|
second_stage: false,
|
||||||
|
})}>{'Back'}</Button> :
|
||||||
|
null
|
||||||
|
}
|
||||||
|
<Button buttonStyles={{
|
||||||
|
height: 'auto',
|
||||||
|
marginLeft: 'var(--default_spacing)',
|
||||||
|
marginTop: 'var(--default_spacing)',
|
||||||
|
width: 'auto'
|
||||||
|
}}
|
||||||
|
clicked={this.handleNavigation}>{this.state.second_stage ? 'Import' : 'Next'}</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
34
src/containers/UI/Password/Password.css
Normal file
34
src/containers/UI/Password/Password.css
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
.PasswordOwner {
|
||||||
|
padding: 0;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
display: flex;
|
||||||
|
justify-content: left;
|
||||||
|
align-content: center;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.PasswordInput {
|
||||||
|
display: block;
|
||||||
|
margin-right: var(--default_spacing);
|
||||||
|
padding: 2px;
|
||||||
|
border-radius: var(--border_radius);
|
||||||
|
background: var(--control_background);
|
||||||
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
outline: none;
|
||||||
|
color: var(--text_color);
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PasswordShowHide {
|
||||||
|
padding-top: 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
min-width: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.PasswordLink {
|
||||||
|
margin-right: var(--default_spacing);
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
135
src/containers/UI/Password/Password.js
Normal file
135
src/containers/UI/Password/Password.js
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
import React, {Component} from 'react';
|
||||||
|
import './Password.css';
|
||||||
|
import {faEye, faEyeSlash} from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||||
|
|
||||||
|
export default class extends Component {
|
||||||
|
state = {
|
||||||
|
button_text: 'clear',
|
||||||
|
password: '',
|
||||||
|
password2: '',
|
||||||
|
show_password: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (!this.props.value || (this.props.value.length === 0)) {
|
||||||
|
this.setState({
|
||||||
|
...this.state,
|
||||||
|
button_text: 'set',
|
||||||
|
password: '',
|
||||||
|
password2: '',
|
||||||
|
show_password: false,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
...this.state,
|
||||||
|
button_text: 'clear',
|
||||||
|
password: this.props.value,
|
||||||
|
password2: '',
|
||||||
|
show_password: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleActionClick = () => {
|
||||||
|
if (!this.props.disabled) {
|
||||||
|
switch (this.state.button_text) {
|
||||||
|
case 'clear':
|
||||||
|
this.setState({
|
||||||
|
...this.state,
|
||||||
|
button_text: 'set',
|
||||||
|
password: '',
|
||||||
|
password2: '',
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'confirm':
|
||||||
|
if (this.state.password === this.state.password2) {
|
||||||
|
this.props.changed(this.state.password);
|
||||||
|
this.setState({
|
||||||
|
...this.state,
|
||||||
|
button_text: this.state.password && this.state.password.length > 0 ? 'clear' : 'set',
|
||||||
|
password2: '',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
...this.state,
|
||||||
|
button_text: 'set',
|
||||||
|
password: '',
|
||||||
|
password2: '',
|
||||||
|
}, () => {
|
||||||
|
if (this.props.mismatchHandler) {
|
||||||
|
this.props.mismatchHandler();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'set':
|
||||||
|
this.setState({
|
||||||
|
...this.state,
|
||||||
|
button_text: 'confirm',
|
||||||
|
password2: '',
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handlePasswordChanged = e => {
|
||||||
|
if (this.state.button_text === 'set') {
|
||||||
|
this.setState({
|
||||||
|
...this.state,
|
||||||
|
password: e.target.value,
|
||||||
|
});
|
||||||
|
} else if (this.state.button_text === 'confirm') {
|
||||||
|
this.setState({
|
||||||
|
...this.state,
|
||||||
|
password2: e.target.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handlePasswordKeyUp = e => {
|
||||||
|
if ((e.keyCode === 13) && ((this.state.button_text === 'confirm') || (this.state.button_text === 'set'))) {
|
||||||
|
this.handleActionClick();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handleShowHideClick = () => {
|
||||||
|
this.setState({
|
||||||
|
...this.state,
|
||||||
|
show_password: !this.state.show_password,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className={'PasswordOwner'} style={{...this.props.style}}>
|
||||||
|
{
|
||||||
|
this.props.readOnly ? null : <a href={'#'}
|
||||||
|
className={'PasswordLink'}
|
||||||
|
onClick={this.handleActionClick}>
|
||||||
|
<u>{this.state.button_text}</u>
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
<input autoFocus={this.props.autoFocus}
|
||||||
|
readOnly={this.props.readOnly}
|
||||||
|
className={'PasswordInput'}
|
||||||
|
disabled={this.props.readOnly || (this.state.button_text === 'clear')}
|
||||||
|
onChange={this.handlePasswordChanged}
|
||||||
|
onKeyUp={this.handlePasswordKeyUp}
|
||||||
|
type={this.state.show_password ? 'text' : 'password'}
|
||||||
|
value={(this.state.button_text === 'confirm') ? this.state.password2 : this.state.password}/>
|
||||||
|
<a href={'#'}
|
||||||
|
className={'PasswordShowHide'}
|
||||||
|
onClick={this.handleShowHideClick}>
|
||||||
|
<FontAwesomeIcon icon={this.state.show_password ? faEye : faEyeSlash} fixedWidth/>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
1044
src/helpers.js
1044
src/helpers.js
File diff suppressed because it is too large
Load Diff
@@ -8,11 +8,11 @@
|
|||||||
--control_transparent_background: rgba(10, 10, 16, 0.5);
|
--control_transparent_background: rgba(10, 10, 16, 0.5);
|
||||||
--control_dark_transparent_background: rgba(10, 10, 16, 0.7);
|
--control_dark_transparent_background: rgba(10, 10, 16, 0.7);
|
||||||
|
|
||||||
--text_color: rgba(200, 200, 240, 0.7);
|
--text_color: rgba(200, 200, 240, 0.65);
|
||||||
--text_color_hover: rgba(200, 200, 225, 0.7);
|
--text_color_hover: rgba(200, 200, 225, 0.65);
|
||||||
--text_color_error: rgba(203, 120, 120, 0.7);
|
--text_color_error: rgba(203, 120, 120, 0.8);
|
||||||
--heading_text_color: rgba(132, 160, 230, 0.7);
|
--heading_text_color: rgba(132, 160, 230, 0.8);
|
||||||
--heading_other_text_color: var(--heading_text_color);
|
--heading_other_text_color: rgba(132, 160, 230, 0.65);
|
||||||
--text_color_transition: color 0.3s;
|
--text_color_transition: color 0.3s;
|
||||||
|
|
||||||
--default_font_size: 14px;
|
--default_font_size: 14px;
|
||||||
@@ -30,6 +30,9 @@
|
|||||||
|
|
||||||
a {
|
a {
|
||||||
outline: 0;
|
outline: 0;
|
||||||
|
color: var(--text_color);
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
html, body {
|
html, body {
|
||||||
@@ -80,6 +83,7 @@ p {
|
|||||||
|
|
||||||
.scrollable-content, ::-webkit-scrollbar {
|
.scrollable-content, ::-webkit-scrollbar {
|
||||||
width: 8px;
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrollable-content, ::-webkit-scrollbar * {
|
.scrollable-content, ::-webkit-scrollbar * {
|
||||||
@@ -89,3 +93,7 @@ p {
|
|||||||
.scrollable-content, ::-webkit-scrollbar-thumb {
|
.scrollable-content, ::-webkit-scrollbar-thumb {
|
||||||
background: var(--control_background_hover) !important;
|
background: var(--control_background_hover) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scrollbar-corner, ::-webkit-scrollbar-corner {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|||||||
27
src/index.js
27
src/index.js
@@ -1,14 +1,18 @@
|
|||||||
|
import './index.css';
|
||||||
|
import 'react-checkbox-tree/lib/react-checkbox-tree.css';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import './index.css';
|
|
||||||
import App from './App';
|
|
||||||
import createAppStore from './redux/store/createAppStore';
|
|
||||||
import {getIPCRenderer} from './utils';
|
|
||||||
import packageJson from '../package.json';
|
|
||||||
import {Provider} from 'react-redux';
|
import {Provider} from 'react-redux';
|
||||||
import {setActiveRelease} from './redux/actions/release_version_actions';
|
|
||||||
|
import packageJson from '../package.json';
|
||||||
|
|
||||||
|
import App from './App.jsx';
|
||||||
import {setProviderState} from './redux/actions/mount_actions';
|
import {setProviderState} from './redux/actions/mount_actions';
|
||||||
|
import {setActiveRelease} from './redux/actions/release_version_actions';
|
||||||
|
import createAppStore from './redux/store/createAppStore';
|
||||||
import * as serviceWorker from './serviceWorker';
|
import * as serviceWorker from './serviceWorker';
|
||||||
|
import {getIPCRenderer} from './utils';
|
||||||
|
|
||||||
const Constants = require('./constants');
|
const Constants = require('./constants');
|
||||||
|
|
||||||
@@ -16,22 +20,22 @@ const ipcRenderer = getIPCRenderer();
|
|||||||
let store;
|
let store;
|
||||||
|
|
||||||
if (ipcRenderer) {
|
if (ipcRenderer) {
|
||||||
ipcRenderer.once(Constants.IPC_Get_Platform_Reply, (event, platformInfo) => {
|
ipcRenderer.once(Constants.IPC_Get_Platform_Reply, (_, platformInfo) => {
|
||||||
if (platformInfo.Platform === 'linux') {
|
if (platformInfo.Platform === 'linux') {
|
||||||
const root = document.documentElement;
|
const root = document.documentElement;
|
||||||
root.style.setProperty('--default_font_size', '15.3px');
|
root.style.setProperty('--default_font_size', '15.3px');
|
||||||
}
|
}
|
||||||
|
|
||||||
ipcRenderer.once(Constants.IPC_Get_State_Reply, (event, result) => {
|
ipcRenderer.once(Constants.IPC_Get_State_Reply, (_, result) => {
|
||||||
if (result.data) {
|
if (result.data) {
|
||||||
store = createAppStore(platformInfo, packageJson.version, result.data);
|
store = createAppStore(platformInfo, packageJson.version, result.data);
|
||||||
store.dispatch(setActiveRelease(result.data.Release, result.data.Version));
|
|
||||||
const providerList = [
|
const providerList = [
|
||||||
...Constants.PROVIDER_LIST,
|
...Constants.PROVIDER_LIST,
|
||||||
...store.getState().mounts.RemoteMounts,
|
...store.getState().mounts.RemoteMounts,
|
||||||
|
...store.getState().mounts.S3Mounts,
|
||||||
];
|
];
|
||||||
for (const provider of providerList) {
|
for (const provider of providerList) {
|
||||||
let state = result.data[provider] || store.getState().mounts.ProviderState[provider];
|
const state = result.data[provider];
|
||||||
if (state.AutoMount === undefined) {
|
if (state.AutoMount === undefined) {
|
||||||
state['AutoMount'] = false;
|
state['AutoMount'] = false;
|
||||||
}
|
}
|
||||||
@@ -40,6 +44,8 @@ if (ipcRenderer) {
|
|||||||
}
|
}
|
||||||
store.dispatch(setProviderState(provider, state));
|
store.dispatch(setProviderState(provider, state));
|
||||||
}
|
}
|
||||||
|
store.dispatch(
|
||||||
|
setActiveRelease(result.data.Release, result.data.Version));
|
||||||
} else {
|
} else {
|
||||||
store = createAppStore(platformInfo, packageJson.version, {});
|
store = createAppStore(platformInfo, packageJson.version, {});
|
||||||
}
|
}
|
||||||
@@ -55,4 +61,3 @@ if (ipcRenderer) {
|
|||||||
});
|
});
|
||||||
ipcRenderer.send(Constants.IPC_Get_Platform);
|
ipcRenderer.send(Constants.IPC_Get_Platform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,17 @@ const handleConfirmYesNo = (show, titleOrConfirmed, resolve) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const NOTIFY_APPLICATION_BUSY = 'common/notifyApplicationBusy';
|
||||||
|
export const notifyApplicationBusy = (busy, transparent) => {
|
||||||
|
return {
|
||||||
|
type: NOTIFY_APPLICATION_BUSY,
|
||||||
|
payload: {
|
||||||
|
busy,
|
||||||
|
transparent
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const notifyRebootRequired = createAction('common/notifyRebootRequired');
|
export const notifyRebootRequired = createAction('common/notifyRebootRequired');
|
||||||
|
|
||||||
export const rebootSystem = () => {
|
export const rebootSystem = () => {
|
||||||
|
|||||||
@@ -5,14 +5,16 @@ import {
|
|||||||
getSelectedVersionFromState
|
getSelectedVersionFromState
|
||||||
} from '../../utils';
|
} from '../../utils';
|
||||||
import {notifyError} from './error_actions';
|
import {notifyError} from './error_actions';
|
||||||
import {setAllowDownload} from './download_actions';
|
import {downloadItem, setAllowDownload} from './download_actions';
|
||||||
import {
|
import {
|
||||||
loadReleases,
|
loadReleases,
|
||||||
setActiveRelease,
|
setActiveRelease,
|
||||||
setInstalledVersion,
|
setInstalledVersion,
|
||||||
setReleaseUpgradeAvailable
|
setReleaseUpgradeAvailable,
|
||||||
|
setNewReleasesAvailable2,
|
||||||
} from './release_version_actions';
|
} from './release_version_actions';
|
||||||
import {
|
import {
|
||||||
|
confirmYesNo,
|
||||||
displaySelectAppPlatform,
|
displaySelectAppPlatform,
|
||||||
setAllowMount,
|
setAllowMount,
|
||||||
setApplicationReady,
|
setApplicationReady,
|
||||||
@@ -21,6 +23,7 @@ import {
|
|||||||
showWindow,
|
showWindow,
|
||||||
shutdownApplication
|
shutdownApplication
|
||||||
} from './common_actions';
|
} from './common_actions';
|
||||||
|
import {unmountAll} from './mount_actions';
|
||||||
|
|
||||||
const ipcRenderer = getIPCRenderer();
|
const ipcRenderer = getIPCRenderer();
|
||||||
|
|
||||||
@@ -32,13 +35,15 @@ export const checkInstalled = (dependencies, version) => {
|
|||||||
const installedVersion = result.Success && result.Exists ? result.Version : 'none';
|
const installedVersion = result.Success && result.Exists ? result.Version : 'none';
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
||||||
|
const release = state.relver.Release;
|
||||||
|
let version = state.relver.Version;
|
||||||
|
|
||||||
let upgradeAvailable = false;
|
let upgradeAvailable = false;
|
||||||
if (installedVersion !== 'none') {
|
if (installedVersion !== 'none') {
|
||||||
const latestVersion = state.relver.VersionLookup[Constants.RELEASE_TYPES[state.relver.Release]].length - 1;
|
const latestVersion = state.relver.VersionLookup[Constants.RELEASE_TYPES[release]].length - 1;
|
||||||
let version = state.relver.Version;
|
|
||||||
if (version === -1) {
|
if (version === -1) {
|
||||||
version = latestVersion;
|
version = latestVersion;
|
||||||
dispatch(setActiveRelease(state.relver.Release, version));
|
dispatch(setActiveRelease(release, version));
|
||||||
} else {
|
} else {
|
||||||
upgradeAvailable = version !== latestVersion;
|
upgradeAvailable = version !== latestVersion;
|
||||||
}
|
}
|
||||||
@@ -48,8 +53,18 @@ export const checkInstalled = (dependencies, version) => {
|
|||||||
dispatch(setMissingDependencies(result.Dependencies));
|
dispatch(setMissingDependencies(result.Dependencies));
|
||||||
dispatch(setAllowDownload(true));
|
dispatch(setAllowDownload(true));
|
||||||
dispatch(setAllowMount(true));
|
dispatch(setAllowMount(true));
|
||||||
|
|
||||||
|
const autoInstallRelease = getState().install.AutoInstallRelease;
|
||||||
|
dispatch(setAutoInstallRelease(false));
|
||||||
|
|
||||||
if (result.Dependencies && (result.Dependencies.length > 0)) {
|
if (result.Dependencies && (result.Dependencies.length > 0)) {
|
||||||
dispatch(showWindow());
|
dispatch(showWindow());
|
||||||
|
} else if ((installedVersion === 'none') && autoInstallRelease) {
|
||||||
|
dispatch(setAllowMount(false));
|
||||||
|
const versionString = getState().relver.VersionLookup[Constants.RELEASE_TYPES[release]][version];
|
||||||
|
const urls = getState().relver.LocationsLookup[versionString].urls;
|
||||||
|
const fileName = versionString + '.zip';
|
||||||
|
dispatch(downloadItem(fileName, Constants.INSTALL_TYPES.Release, urls));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -140,7 +155,7 @@ export const installDependency = (source, url, isWinFSP) => {
|
|||||||
export const installAndTestRelease = (source, version, appPlatform) => {
|
export const installAndTestRelease = (source, version, appPlatform) => {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
if (ipcRenderer && getState().install.InstallTestActive) {
|
if (ipcRenderer && getState().install.InstallTestActive) {
|
||||||
const extractReleaseComplete = (event, arg) => {
|
const extractReleaseComplete = () => {
|
||||||
ipcRenderer.send(Constants.IPC_Delete_File, {
|
ipcRenderer.send(Constants.IPC_Delete_File, {
|
||||||
FilePath: source,
|
FilePath: source,
|
||||||
});
|
});
|
||||||
@@ -174,6 +189,31 @@ export const installAndTestRelease = (source, version, appPlatform) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const installReleaseByVersion = (release, version) => {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
const install = () => {
|
||||||
|
if (getState().download.AllowDownload && !getState().download.DownloadActive) {
|
||||||
|
dispatch(setAutoInstallRelease(true));
|
||||||
|
dispatch(setActiveRelease(release, version));
|
||||||
|
} else {
|
||||||
|
notifyError('Download is active. Unable to install release.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (getState().mounts.MountsBusy) {
|
||||||
|
dispatch(confirmYesNo('Unmount all drives?'))
|
||||||
|
.then(confirmed => {
|
||||||
|
if (confirmed) {
|
||||||
|
dispatch(unmountAll(install));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => notifyError(error));
|
||||||
|
} else {
|
||||||
|
install();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const installRelease = source => {
|
export const installRelease = source => {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
if (ipcRenderer && !getState().install.InstallActive) {
|
if (ipcRenderer && !getState().install.InstallActive) {
|
||||||
@@ -185,6 +225,11 @@ export const installRelease = source => {
|
|||||||
FilePath: source,
|
FilePath: source,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (arg.data.Success) {
|
||||||
|
localStorage.setItem('previous_releases', localStorage.getItem('releases'));
|
||||||
|
dispatch(setNewReleasesAvailable2([]));
|
||||||
|
}
|
||||||
|
|
||||||
dispatch(setInstallComplete(arg.data));
|
dispatch(setInstallComplete(arg.data));
|
||||||
dispatch(checkVersionInstalled());
|
dispatch(checkVersionInstalled());
|
||||||
};
|
};
|
||||||
@@ -231,6 +276,7 @@ export const installUpgrade = (source, sha256, signature, skipVerification) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const setAutoInstallRelease = createAction('install/setAutoInstallRelease');
|
||||||
export const setDismissDependencies = createAction('install/setDismissDependencies');
|
export const setDismissDependencies = createAction('install/setDismissDependencies');
|
||||||
export const setInstallActive = createAction('install/setInstallActive');
|
export const setInstallActive = createAction('install/setInstallActive');
|
||||||
export const setInstallTestActive = createAction('install/setInstallTestActive');
|
export const setInstallTestActive = createAction('install/setInstallTestActive');
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import * as Constants from '../../constants';
|
|
||||||
import {createAction} from '@reduxjs/toolkit';
|
import {createAction} from '@reduxjs/toolkit';
|
||||||
|
|
||||||
|
import * as Constants from '../../constants';
|
||||||
import {getIPCRenderer} from '../../utils';
|
import {getIPCRenderer} from '../../utils';
|
||||||
import {
|
|
||||||
confirmYesNo,
|
import {confirmYesNo, saveState} from './common_actions';
|
||||||
saveState
|
|
||||||
} from './common_actions';
|
|
||||||
import {notifyError} from './error_actions';
|
import {notifyError} from './error_actions';
|
||||||
|
|
||||||
export const addRemoteMount = (hostNameOrIp, port, token) => {
|
export const addRemoteMount = (hostNameOrIp, port, token) => {
|
||||||
@@ -12,18 +11,20 @@ export const addRemoteMount = (hostNameOrIp, port, token) => {
|
|||||||
const ipcRenderer = getIPCRenderer();
|
const ipcRenderer = getIPCRenderer();
|
||||||
|
|
||||||
const provider = 'Remote' + hostNameOrIp + ':' + port;
|
const provider = 'Remote' + hostNameOrIp + ':' + port;
|
||||||
dispatch(addRemoteMount2(provider));
|
|
||||||
dispatch(setBusy(true));
|
dispatch(setBusy(true));
|
||||||
|
|
||||||
ipcRenderer.once(Constants.IPC_Set_Config_Values_Reply, (_, arg) => {
|
ipcRenderer.once(Constants.IPC_Set_Config_Values_Reply, (_, arg) => {
|
||||||
if (arg.data.Success) {
|
if (arg.data.Success) {
|
||||||
|
dispatch(addRemoteMount2(provider));
|
||||||
ipcRenderer.send(Constants.IPC_Detect_Mount, {
|
ipcRenderer.send(Constants.IPC_Detect_Mount, {
|
||||||
Provider: provider,
|
Provider: provider,
|
||||||
RemoteMounts: getState().mounts.RemoteMounts,
|
RemoteMounts: getState().mounts.RemoteMounts,
|
||||||
|
S3Mounts: getState().mounts.S3Mounts,
|
||||||
Version: getState().relver.InstalledVersion,
|
Version: getState().relver.InstalledVersion,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
dispatch(notifyError('Failed to set \'RemoteToken\': ' + arg.data.Error));
|
dispatch(
|
||||||
|
notifyError('Failed to set \'RemoteToken\': ' + arg.data.Error));
|
||||||
dispatch(setBusy(false));
|
dispatch(setBusy(false));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -42,112 +43,129 @@ export const addRemoteMount = (hostNameOrIp, port, token) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const addS3Mount = (name, accessKey, secretKey, region, bucketName, url) => {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
const ipcRenderer = getIPCRenderer();
|
||||||
|
const provider = 'S3' + name;
|
||||||
|
dispatch(setBusy(true));
|
||||||
|
|
||||||
|
ipcRenderer.once(Constants.IPC_Set_Config_Values_Reply, (_, arg) => {
|
||||||
|
if (arg.data.Success) {
|
||||||
|
dispatch(addS3Mount2(provider));
|
||||||
|
ipcRenderer.send(Constants.IPC_Detect_Mount, {
|
||||||
|
Provider: provider,
|
||||||
|
RemoteMounts: getState().mounts.RemoteMounts,
|
||||||
|
S3Mounts: getState().mounts.S3Mounts,
|
||||||
|
Version: getState().relver.InstalledVersion,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
dispatch(
|
||||||
|
notifyError('Failed to create S3 instance: ' + arg.data.Error));
|
||||||
|
dispatch(setBusy(false));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcRenderer.send(Constants.IPC_Set_Config_Values, {
|
||||||
|
Items: [
|
||||||
|
{Name: 'S3Config.AccessKey', Value: accessKey},
|
||||||
|
{Name: 'S3Config.SecretKey', Value: secretKey},
|
||||||
|
{Name: 'S3Config.Region', Value: region},
|
||||||
|
{Name: 'S3Config.BucketName', Value: bucketName},
|
||||||
|
{Name: 'S3Config.URL', Value: url},
|
||||||
|
],
|
||||||
|
Provider: provider,
|
||||||
|
S3: true,
|
||||||
|
Version: getState().relver.InstalledVersion,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const addRemoteMount2 = createAction('mounts/addRemoteMount2');
|
export const addRemoteMount2 = createAction('mounts/addRemoteMount2');
|
||||||
|
export const addS3Mount2 = createAction('mounts/addS3Mount2');
|
||||||
|
|
||||||
export const DISPLAY_CONFIGURATION = 'mounts/displayConfiguration';
|
export const DISPLAY_CONFIGURATION = 'mounts/displayConfiguration';
|
||||||
export const displayConfiguration = (provider, remote) => {
|
export const displayConfiguration = (provider, remote, s3) => {
|
||||||
return {
|
return {
|
||||||
type: DISPLAY_CONFIGURATION,
|
type: DISPLAY_CONFIGURATION,
|
||||||
payload: {
|
payload: {
|
||||||
provider,
|
provider,
|
||||||
remote,
|
remote,
|
||||||
|
s3,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const removeRemoteMount = provider => {
|
export const removeMount = provider => {
|
||||||
return dispatch => {
|
return dispatch => {
|
||||||
dispatch(confirmYesNo('Delete [' + provider.substr(6) + ']?'))
|
const isRemote = provider.startsWith('Remote');
|
||||||
.then(confirmed => {
|
dispatch(confirmYesNo('Delete [' + provider.substr(isRemote ? 6 : 2) + ']?'))
|
||||||
if (confirmed) {
|
.then(confirmed => {
|
||||||
dispatch(removeRemoteMount2(provider));
|
if (confirmed) {
|
||||||
}
|
dispatch(removeMount2(provider));
|
||||||
});
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeRemoteMount2 = provider => {
|
const removeMount2 = provider => {
|
||||||
return dispatch => {
|
return dispatch => {
|
||||||
const ipcRenderer = getIPCRenderer();
|
const ipcRenderer = getIPCRenderer();
|
||||||
ipcRenderer.once(Constants.IPC_Remove_Remote_Mount_Reply, (_, arg) => {
|
ipcRenderer.once(Constants.IPC_Remove_Mount_Reply, (_, arg) => {
|
||||||
if (arg.data.Success) {
|
if (arg.data.Success) {
|
||||||
dispatch(removeRemoteMount3(provider));
|
dispatch(removeMount3(provider));
|
||||||
dispatch(saveState());
|
dispatch(saveState());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ipcRenderer.send(Constants.IPC_Remove_Remote_Mount, provider.substr(6));
|
const isRemote = provider.startsWith('Remote');
|
||||||
|
ipcRenderer.send(Constants.IPC_Remove_Mount, {
|
||||||
|
Remote: isRemote,
|
||||||
|
Name: provider.substr(isRemote ? 6 : 2)
|
||||||
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const removeRemoteMount3 = createAction('mounts/removeRemoteMount3');
|
export const removeMount3 = createAction('mounts/removeMount3');
|
||||||
|
|
||||||
export const RESET_MOUNTS_STATE = 'mounts/resetMountsState';
|
export const RESET_MOUNTS_STATE = 'mounts/resetMountsState';
|
||||||
export const resetMountsState = () => {
|
export const resetMountsState = () => {
|
||||||
return {
|
return {type: RESET_MOUNTS_STATE, payload: null,}
|
||||||
type: RESET_MOUNTS_STATE,
|
|
||||||
payload: null,
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SET_ALLOW_MOUNT = 'mounts/setAllowMount';
|
export const SET_ALLOW_MOUNT = 'mounts/setAllowMount';
|
||||||
export const setAllowMount = (provider, allow) => {
|
export const setAllowMount =
|
||||||
return {
|
(provider,
|
||||||
type: SET_ALLOW_MOUNT,
|
allow) => {
|
||||||
payload: {
|
return {type: SET_ALLOW_MOUNT, payload: {provider, allow}};
|
||||||
provider,
|
|
||||||
allow
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
export const SET_AUTO_MOUNT_PROCESSED = 'mounts/setAutoMountProcessed';
|
export const SET_AUTO_MOUNT_PROCESSED = 'mounts/setAutoMountProcessed';
|
||||||
export const setAutoMountProcessed = (provider, processed) => {
|
export const setAutoMountProcessed = (provider, processed) => {
|
||||||
return {
|
return {type: SET_AUTO_MOUNT_PROCESSED, payload: {provider, processed}};
|
||||||
type: SET_AUTO_MOUNT_PROCESSED,
|
|
||||||
payload: {
|
|
||||||
provider,
|
|
||||||
processed
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setBusy = createAction('mounts/setBusy');
|
export const setBusy = createAction('mounts/setBusy');
|
||||||
|
|
||||||
export const SET_MOUNT_STATE = 'mounts/setMountState';
|
export const SET_MOUNT_STATE = 'mounts/setMountState';
|
||||||
export const setMountState = (provider, state) => {
|
export const setMountState =
|
||||||
return {
|
(provider,
|
||||||
type: SET_MOUNT_STATE,
|
state) => {
|
||||||
payload: {
|
return {type: SET_MOUNT_STATE, payload: {provider, state}};
|
||||||
provider,
|
|
||||||
state
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
export const SET_MOUNTED = 'mounts/setMounted';
|
export const SET_MOUNTED = 'mounts/setMounted';
|
||||||
export const setMounted = (provider, mounted) => {
|
export const setMounted =
|
||||||
return {
|
(provider,
|
||||||
type: SET_MOUNTED,
|
mounted) => {
|
||||||
payload: {
|
return {type: SET_MOUNTED, payload: {provider, mounted}};
|
||||||
provider,
|
|
||||||
mounted
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
export const SET_PROVIDER_STATE = 'mounts/setProviderState';
|
export const SET_PROVIDER_STATE = 'mounts/setProviderState';
|
||||||
export const setProviderState = (provider, state) => {
|
export const setProviderState = (provider, state) => {
|
||||||
return {
|
return {type: SET_PROVIDER_STATE, payload: {provider, state}}
|
||||||
type: SET_PROVIDER_STATE,
|
|
||||||
payload: {
|
|
||||||
provider,
|
|
||||||
state
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const unmountAll = completedCallback => {
|
export const unmountAll = completedCallback => {
|
||||||
return (dispatch, getState) => {
|
return dispatch => {
|
||||||
const ipcRenderer = getIPCRenderer();
|
const ipcRenderer = getIPCRenderer();
|
||||||
const unmountedCallback = () => {
|
const unmountedCallback = () => {
|
||||||
dispatch(resetMountsState());
|
dispatch(resetMountsState());
|
||||||
|
|||||||
4
src/redux/actions/pinned_manager_actions.js
Normal file
4
src/redux/actions/pinned_manager_actions.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import {createAction} from '@reduxjs/toolkit';
|
||||||
|
|
||||||
|
export const displayPinnedManager = createAction('pinned/displayPinnedManager');
|
||||||
|
|
||||||
@@ -13,7 +13,11 @@ import {
|
|||||||
setDismissDependencies
|
setDismissDependencies
|
||||||
} from './install_actions';
|
} from './install_actions';
|
||||||
import {unmountAll} from './mount_actions';
|
import {unmountAll} from './mount_actions';
|
||||||
import {getIPCRenderer} from '../../utils';
|
import {
|
||||||
|
checkNewReleases,
|
||||||
|
getIPCRenderer,
|
||||||
|
getNewReleases, getSelectedVersionFromState
|
||||||
|
} from '../../utils';
|
||||||
|
|
||||||
export const CLEAR_UI_UPGRADE = 'relver/clearUIUpgrade';
|
export const CLEAR_UI_UPGRADE = 'relver/clearUIUpgrade';
|
||||||
export const clearUIUpgrade = () => {
|
export const clearUIUpgrade = () => {
|
||||||
@@ -67,13 +71,13 @@ export const loadReleases = () => {
|
|||||||
const state = getState().relver;
|
const state = getState().relver;
|
||||||
let release = state.Release;
|
let release = state.Release;
|
||||||
if (release >= Constants.RELEASE_TYPES.length) {
|
if (release >= Constants.RELEASE_TYPES.length) {
|
||||||
release = state.ReleaseDefault;
|
release = Constants.DEFAULT_RELEASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
let latestVersion = versionLookup[Constants.RELEASE_TYPES[release]].length - 1;
|
let latestVersion = versionLookup[Constants.RELEASE_TYPES[release]].length - 1;
|
||||||
let version = state.Version;
|
let version = state.Version;
|
||||||
if (versionLookup[Constants.RELEASE_TYPES[release]][0] === 'unavailable') {
|
if (versionLookup[Constants.RELEASE_TYPES[release]][0] === 'unavailable') {
|
||||||
release = state.ReleaseDefault;
|
release = Constants.DEFAULT_RELEASE;
|
||||||
version = latestVersion = versionLookup[Constants.RELEASE_TYPES[release]].length - 1
|
version = latestVersion = versionLookup[Constants.RELEASE_TYPES[release]].length - 1
|
||||||
} else if ((version === -1) || !versionLookup[Constants.RELEASE_TYPES[release]][version]) {
|
} else if ((version === -1) || !versionLookup[Constants.RELEASE_TYPES[release]][version]) {
|
||||||
version = latestVersion;
|
version = latestVersion;
|
||||||
@@ -123,11 +127,26 @@ export const loadReleases = () => {
|
|||||||
...response.data.Locations[appPlatform],
|
...response.data.Locations[appPlatform],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const storedReleases = localStorage.getItem('releases');
|
||||||
|
let newReleases = [];
|
||||||
|
if (storedReleases && (storedReleases.length > 0)) {
|
||||||
|
newReleases = getNewReleases(JSON.parse(storedReleases).VersionLookup, versionLookup, getSelectedVersionFromState(getState()));
|
||||||
|
}
|
||||||
|
|
||||||
localStorage.setItem('releases', JSON.stringify({
|
localStorage.setItem('releases', JSON.stringify({
|
||||||
LocationsLookup: locationsLookup,
|
LocationsLookup: locationsLookup,
|
||||||
VersionLookup: versionLookup
|
VersionLookup: versionLookup
|
||||||
}));
|
}));
|
||||||
dispatchActions(locationsLookup, versionLookup);
|
dispatchActions(locationsLookup, versionLookup);
|
||||||
|
|
||||||
|
dispatch(setNewReleasesAvailable(newReleases));
|
||||||
|
if (getState().relver.NewReleasesAvailable.length > 0) {
|
||||||
|
dispatch(setNewReleasesAvailable2(newReleases));
|
||||||
|
localStorage.setItem('previous_releases', storedReleases);
|
||||||
|
dispatch(showWindow());
|
||||||
|
} else if ((newReleases = checkNewReleases(getSelectedVersionFromState(getState()))).length > 0) {
|
||||||
|
dispatch(setNewReleasesAvailable2(newReleases));
|
||||||
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
const releases = localStorage.getItem('releases');
|
const releases = localStorage.getItem('releases');
|
||||||
if (releases && (releases.length > 0)) {
|
if (releases && (releases.length > 0)) {
|
||||||
@@ -160,7 +179,7 @@ export const setActiveRelease = (release, version) => {
|
|||||||
const relver = getState().relver;
|
const relver = getState().relver;
|
||||||
const common = getState().common;
|
const common = getState().common;
|
||||||
if (release >= Constants.RELEASE_TYPES.length) {
|
if (release >= Constants.RELEASE_TYPES.length) {
|
||||||
release = relver.ReleaseDefault;
|
release = Constants.DEFAULT_RELEASE;
|
||||||
version = -1;
|
version = -1;
|
||||||
}
|
}
|
||||||
const versions = relver.VersionLookup[Constants.RELEASE_TYPES[release]];
|
const versions = relver.VersionLookup[Constants.RELEASE_TYPES[release]];
|
||||||
@@ -174,8 +193,11 @@ export const setActiveRelease = (release, version) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const setAllowDismissDependencies = createAction('relver/setAllowDismissDependencies');
|
export const setAllowDismissDependencies = createAction('relver/setAllowDismissDependencies');
|
||||||
|
export const setDismissNewReleasesAvailable = createAction('relver/setDismissNewReleasesAvailable');
|
||||||
export const setDismissUIUpgrade = createAction('relver/setDismissUIUpgrade');
|
export const setDismissUIUpgrade = createAction('relver/setDismissUIUpgrade');
|
||||||
export const setInstalledVersion = createAction('relver/setInstalledVersion');
|
export const setInstalledVersion = createAction('relver/setInstalledVersion');
|
||||||
|
export const setNewReleasesAvailable = createAction('relver/setNewReleasesAvailable');
|
||||||
|
export const setNewReleasesAvailable2 = createAction('relver/setNewReleasesAvailable2');
|
||||||
|
|
||||||
export const SET_RELEASE_DATA = 'relver/setReleaseData';
|
export const SET_RELEASE_DATA = 'relver/setReleaseData';
|
||||||
export const setReleaseData = (locationsLookup, versionLookup)=> {
|
export const setReleaseData = (locationsLookup, versionLookup)=> {
|
||||||
|
|||||||
4
src/redux/actions/skynet_actions.js
Normal file
4
src/redux/actions/skynet_actions.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import {createAction} from '@reduxjs/toolkit';
|
||||||
|
|
||||||
|
export const displaySkynetExport = createAction('skynet/displaySkynetExport');
|
||||||
|
export const displaySkynetImport = createAction('skynet/displaySkynetImport');
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import {createReducer} from '@reduxjs/toolkit';
|
import {createReducer} from '@reduxjs/toolkit';
|
||||||
import {
|
import {
|
||||||
DISPLAY_CONFIRM_YES_NO,
|
DISPLAY_CONFIRM_YES_NO,
|
||||||
|
NOTIFY_APPLICATION_BUSY,
|
||||||
notifyRebootRequired,
|
notifyRebootRequired,
|
||||||
setAllowMount,
|
setAllowMount,
|
||||||
setApplicationReady,
|
setApplicationReady,
|
||||||
@@ -11,6 +12,8 @@ import {
|
|||||||
export const createCommonReducer = (platformInfo, version) => {
|
export const createCommonReducer = (platformInfo, version) => {
|
||||||
return createReducer({
|
return createReducer({
|
||||||
AllowMount: false,
|
AllowMount: false,
|
||||||
|
AppBusy: false,
|
||||||
|
AppBusyTransparent: false,
|
||||||
AppPlatform: platformInfo.AppPlatform,
|
AppPlatform: platformInfo.AppPlatform,
|
||||||
AppReady: false,
|
AppReady: false,
|
||||||
DisplayConfirmYesNo: false,
|
DisplayConfirmYesNo: false,
|
||||||
@@ -51,6 +54,13 @@ export const createCommonReducer = (platformInfo, version) => {
|
|||||||
AppPlatform: action.payload,
|
AppPlatform: action.payload,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
[NOTIFY_APPLICATION_BUSY]: (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
AppBusy: action.payload.busy,
|
||||||
|
AppBusyTransparent: action.payload.busy && action.payload.transparent,
|
||||||
|
};
|
||||||
|
},
|
||||||
[notifyRebootRequired]: (state, action) => {
|
[notifyRebootRequired]: (state, action) => {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import {createReducer} from '@reduxjs/toolkit';
|
import {createReducer} from '@reduxjs/toolkit';
|
||||||
import {
|
import {
|
||||||
|
setAutoInstallRelease,
|
||||||
setDismissDependencies,
|
setDismissDependencies,
|
||||||
setInstallActive,
|
setInstallActive,
|
||||||
setInstallComplete,
|
setInstallComplete,
|
||||||
@@ -8,6 +9,7 @@ import {
|
|||||||
} from '../actions/install_actions';
|
} from '../actions/install_actions';
|
||||||
|
|
||||||
export const installReducer = createReducer({
|
export const installReducer = createReducer({
|
||||||
|
AutoInstallRelease: false,
|
||||||
DismissDependencies: false,
|
DismissDependencies: false,
|
||||||
InstallActive: false,
|
InstallActive: false,
|
||||||
InstallResult: null,
|
InstallResult: null,
|
||||||
@@ -15,6 +17,12 @@ export const installReducer = createReducer({
|
|||||||
InstallType: null,
|
InstallType: null,
|
||||||
MissingDependencies: [],
|
MissingDependencies: [],
|
||||||
}, {
|
}, {
|
||||||
|
[setAutoInstallRelease]: (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
AutoInstallRelease: action.payload,
|
||||||
|
}
|
||||||
|
},
|
||||||
[setDismissDependencies]: (state, action) => {
|
[setDismissDependencies]: (state, action) => {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
|||||||
@@ -1,24 +1,28 @@
|
|||||||
import * as Constants from '../../constants';
|
|
||||||
import {createReducer} from '@reduxjs/toolkit';
|
import {createReducer} from '@reduxjs/toolkit';
|
||||||
|
|
||||||
|
import * as Constants from '../../constants';
|
||||||
import {
|
import {
|
||||||
addRemoteMount2,
|
addRemoteMount2,
|
||||||
|
addS3Mount2,
|
||||||
DISPLAY_CONFIGURATION,
|
DISPLAY_CONFIGURATION,
|
||||||
removeRemoteMount3,
|
removeMount3,
|
||||||
RESET_MOUNTS_STATE,
|
RESET_MOUNTS_STATE,
|
||||||
SET_ALLOW_MOUNT,
|
SET_ALLOW_MOUNT,
|
||||||
SET_AUTO_MOUNT_PROCESSED,
|
SET_AUTO_MOUNT_PROCESSED,
|
||||||
setBusy,
|
|
||||||
SET_MOUNT_STATE,
|
SET_MOUNT_STATE,
|
||||||
SET_MOUNTED,
|
SET_MOUNTED,
|
||||||
SET_PROVIDER_STATE
|
SET_PROVIDER_STATE,
|
||||||
|
setBusy
|
||||||
} from '../actions/mount_actions';
|
} from '../actions/mount_actions';
|
||||||
|
|
||||||
export const createMountReducer = state => {
|
export const createMountReducer = state => {
|
||||||
let providerList = [
|
let providerList = [
|
||||||
...Constants.PROVIDER_LIST,
|
...Constants.PROVIDER_LIST,
|
||||||
...(state.RemoteMounts||[]),
|
...(state.RemoteMounts || []),
|
||||||
|
...(state.S3Mounts || []),
|
||||||
];
|
];
|
||||||
const providerState = providerList.map(provider=> {
|
const providerState = providerList
|
||||||
|
.map(provider => {
|
||||||
return {
|
return {
|
||||||
[provider]: {
|
[provider]: {
|
||||||
AutoMount: false,
|
AutoMount: false,
|
||||||
@@ -26,14 +30,13 @@ export const createMountReducer = state => {
|
|||||||
MountLocation: '',
|
MountLocation: '',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).reduce((map, obj) => {
|
})
|
||||||
return {
|
.reduce((map, obj) => {
|
||||||
...map,
|
return {...map, ...obj}
|
||||||
...obj
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const mountState = providerList.map(provider => {
|
const mountState = providerList
|
||||||
|
.map(provider => {
|
||||||
return {
|
return {
|
||||||
[provider]: {
|
[provider]: {
|
||||||
AllowMount: false,
|
AllowMount: false,
|
||||||
@@ -41,154 +44,175 @@ export const createMountReducer = state => {
|
|||||||
Mounted: false,
|
Mounted: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).reduce((map, obj) => {
|
})
|
||||||
return {
|
.reduce((map, obj) => {
|
||||||
...map,
|
return {...map, ...obj}
|
||||||
...obj
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const autoMountProcessed = providerList.map(provider => {
|
const autoMountProcessed =
|
||||||
return {
|
providerList.map(provider => {
|
||||||
[provider]: false,
|
return {[provider]: false,}
|
||||||
}
|
})
|
||||||
}).reduce((map, obj) => {
|
.reduce((map, obj) => {
|
||||||
return {
|
return {...map, ...obj}
|
||||||
...map,
|
});
|
||||||
...obj
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return createReducer({
|
return createReducer(
|
||||||
AutoMountProcessed: autoMountProcessed,
|
{
|
||||||
DisplayConfiguration: null,
|
AutoMountProcessed: autoMountProcessed,
|
||||||
DisplayRemoteConfiguration: false,
|
DisplayConfiguration: null,
|
||||||
MountsBusy: false,
|
DisplayRemoteConfiguration: false,
|
||||||
MountState: mountState,
|
DisplayS3Configuration: false,
|
||||||
ProviderState: providerState,
|
MountsBusy: false,
|
||||||
RemoteMounts: state.RemoteMounts ? state.RemoteMounts : [],
|
MountState: mountState,
|
||||||
}, {
|
ProviderState: providerState,
|
||||||
[addRemoteMount2]: (state, action) => {
|
RemoteMounts: state.RemoteMounts ? state.RemoteMounts : [],
|
||||||
let mountState = {...state.MountState};
|
S3Mounts: state.S3Mounts ? state.S3Mounts : [],
|
||||||
mountState[action.payload] = {
|
|
||||||
AllowMount: false,
|
|
||||||
DriveLetters: [],
|
|
||||||
Mounted: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let providerState = {...state.ProviderState};
|
|
||||||
providerState[action.payload] = {
|
|
||||||
AutoMount: false,
|
|
||||||
AutoRestart: false,
|
|
||||||
MountLocation: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
let autoMountProcessed = {...state.AutoMountProcessed};
|
|
||||||
autoMountProcessed[action.payload] = true;
|
|
||||||
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
AutoMountProcessed: autoMountProcessed,
|
|
||||||
MountState: mountState,
|
|
||||||
ProviderState: providerState,
|
|
||||||
RemoteMounts: [...state.RemoteMounts, action.payload],
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
[DISPLAY_CONFIGURATION]: (state, action) => {
|
{
|
||||||
return {
|
[addRemoteMount2]: (state, action) => {
|
||||||
...state,
|
let mountState = {...state.MountState};
|
||||||
DisplayConfiguration: action.payload.provider,
|
mountState[action.payload] = {
|
||||||
DisplayRemoteConfiguration: action.payload.remote,
|
AllowMount: false,
|
||||||
};
|
DriveLetters: [],
|
||||||
},
|
Mounted: false,
|
||||||
[removeRemoteMount3]: (state, action) => {
|
};
|
||||||
let mountState = {...state.MountState};
|
|
||||||
delete mountState[action.payload];
|
|
||||||
|
|
||||||
let providerState = {...state.ProviderState};
|
let providerState = {...state.ProviderState};
|
||||||
delete providerState[action.payload];
|
providerState[action.payload] = {
|
||||||
|
AutoMount: false,
|
||||||
|
AutoRestart: false,
|
||||||
|
MountLocation: '',
|
||||||
|
};
|
||||||
|
|
||||||
let autoMountProcessed = {...state.AutoMountProcessed};
|
let autoMountProcessed = {...state.AutoMountProcessed};
|
||||||
delete autoMountProcessed[action.payload];
|
autoMountProcessed[action.payload] = true;
|
||||||
|
|
||||||
const remoteMounts = state.RemoteMounts.filter(i => i !== action.payload);
|
return {
|
||||||
return {
|
...state, AutoMountProcessed: autoMountProcessed,
|
||||||
...state,
|
MountState: mountState, ProviderState: providerState,
|
||||||
AutoMountProcessed: autoMountProcessed,
|
RemoteMounts: [...state.RemoteMounts, action.payload],
|
||||||
MountState: mountState,
|
|
||||||
ProviderState: providerState,
|
|
||||||
RemoteMounts: remoteMounts,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
[RESET_MOUNTS_STATE]: (state, action) => {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
MountsBusy: false,
|
|
||||||
MountState: mountState,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[SET_AUTO_MOUNT_PROCESSED]: (state, action) => {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
AutoMountProcessed: {
|
|
||||||
...state.AutoMountProcessed,
|
|
||||||
[action.payload.provider]: action.payload.processed,
|
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
},
|
[addS3Mount2]: (state, action) => {
|
||||||
[SET_ALLOW_MOUNT]: (state, action) => {
|
let mountState = {...state.MountState};
|
||||||
return {
|
mountState[action.payload] = {
|
||||||
...state,
|
AllowMount: false,
|
||||||
MountState: {
|
DriveLetters: [],
|
||||||
...state.MountState,
|
Mounted: false,
|
||||||
[action.payload.provider]: {
|
};
|
||||||
...state.MountState[action.payload.provider],
|
|
||||||
AllowMount: action.payload.allow,
|
let providerState = {...state.ProviderState};
|
||||||
|
providerState[action.payload] = {
|
||||||
|
AutoMount: false,
|
||||||
|
AutoRestart: false,
|
||||||
|
MountLocation: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
let autoMountProcessed = {...state.AutoMountProcessed};
|
||||||
|
autoMountProcessed[action.payload] = true;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state, AutoMountProcessed: autoMountProcessed,
|
||||||
|
MountState: mountState, ProviderState: providerState,
|
||||||
|
S3Mounts: [...state.S3Mounts, action.payload],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[DISPLAY_CONFIGURATION]: (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
DisplayConfiguration: action.payload.provider,
|
||||||
|
DisplayRemoteConfiguration: action.payload.remote,
|
||||||
|
DisplayS3Configuration: action.payload.s3,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[removeMount3]: (state, action) => {
|
||||||
|
let mountState = {...state.MountState};
|
||||||
|
delete mountState[action.payload];
|
||||||
|
|
||||||
|
let providerState = {...state.ProviderState};
|
||||||
|
delete providerState[action.payload];
|
||||||
|
|
||||||
|
let autoMountProcessed = {...state.AutoMountProcessed};
|
||||||
|
delete autoMountProcessed[action.payload];
|
||||||
|
|
||||||
|
const remoteMounts =
|
||||||
|
state.RemoteMounts.filter(i => i !== action.payload);
|
||||||
|
const s3Mounts =
|
||||||
|
state.S3Mounts.filter(i => i !== action.payload);
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
AutoMountProcessed: autoMountProcessed,
|
||||||
|
MountState: mountState,
|
||||||
|
ProviderState: providerState,
|
||||||
|
RemoteMounts: remoteMounts,
|
||||||
|
S3Mounts: s3Mounts,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[RESET_MOUNTS_STATE]: (state, action) => {
|
||||||
|
return {...state, MountsBusy: false, MountState: mountState,}
|
||||||
|
},
|
||||||
|
[SET_AUTO_MOUNT_PROCESSED]: (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
AutoMountProcessed: {
|
||||||
|
...state.AutoMountProcessed,
|
||||||
|
[action.payload.provider]: action.payload.processed,
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
},
|
||||||
},
|
[SET_ALLOW_MOUNT]: (state, action) => {
|
||||||
[setBusy]: (state, action) => {
|
return {
|
||||||
return {
|
...state,
|
||||||
...state,
|
MountState: {
|
||||||
MountsBusy: action.payload
|
...state.MountState,
|
||||||
};
|
[action.payload.provider]: {
|
||||||
},
|
...state.MountState[action.payload.provider],
|
||||||
[SET_MOUNT_STATE]: (state, action) => {
|
AllowMount: action.payload.allow,
|
||||||
return {
|
}
|
||||||
...state,
|
|
||||||
MountState: {
|
|
||||||
...state.MountState,
|
|
||||||
[action.payload.provider]: {
|
|
||||||
...state.MountState[action.payload.provider],
|
|
||||||
...action.payload.state
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
[SET_MOUNTED]: (state, action) => {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
MountState: {
|
|
||||||
...state.MountState,
|
|
||||||
[action.payload.provider]: {
|
|
||||||
...state.MountState[action.payload.provider],
|
|
||||||
Mounted: action.payload.mounted,
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
},
|
||||||
},
|
[setBusy]:
|
||||||
[SET_PROVIDER_STATE]: (state, action) => {
|
(state,
|
||||||
return {
|
action) => {
|
||||||
...state,
|
return {...state, MountsBusy: action.payload};
|
||||||
ProviderState: {
|
},
|
||||||
...state.ProviderState,
|
[SET_MOUNT_STATE]: (state, action) => {
|
||||||
[action.payload.provider]: {
|
return {
|
||||||
...state.ProviderState[action.payload.provider],
|
...state,
|
||||||
...action.payload.state
|
MountState: {
|
||||||
},
|
...state.MountState,
|
||||||
}
|
[action.payload.provider]: {
|
||||||
};
|
...state.MountState[action.payload.provider],
|
||||||
}
|
...action.payload.state
|
||||||
});
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[SET_MOUNTED]: (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
MountState: {
|
||||||
|
...state.MountState,
|
||||||
|
[action.payload.provider]: {
|
||||||
|
...state.MountState[action.payload.provider],
|
||||||
|
Mounted: action.payload.mounted,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[SET_PROVIDER_STATE]: (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
ProviderState: {
|
||||||
|
...state.ProviderState,
|
||||||
|
[action.payload.provider]: {
|
||||||
|
...state.ProviderState[action.payload.provider],
|
||||||
|
...action.payload.state
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
13
src/redux/reducers/pinned_manager_reducer.js
Normal file
13
src/redux/reducers/pinned_manager_reducer.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import {createReducer} from '@reduxjs/toolkit';
|
||||||
|
import {displayPinnedManager} from '../actions/pinned_manager_actions';
|
||||||
|
|
||||||
|
export const pinnedManagerReducer = createReducer({
|
||||||
|
DisplayPinnedManager: false,
|
||||||
|
}, {
|
||||||
|
[displayPinnedManager]: (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
DisplayPinnedManager: action.payload,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -15,10 +15,12 @@ const versionLookup = Constants.RELEASE_TYPES.map(k=> {
|
|||||||
|
|
||||||
export const releaseVersionReducer = createReducer({
|
export const releaseVersionReducer = createReducer({
|
||||||
AllowDismissDependencies: false,
|
AllowDismissDependencies: false,
|
||||||
|
DismissNewReleasesAvailable: true,
|
||||||
InstalledVersion: 'none',
|
InstalledVersion: 'none',
|
||||||
LocationsLookup: {},
|
LocationsLookup: {},
|
||||||
Release: 0,
|
NewReleasesAvailable: [],
|
||||||
ReleaseDefault: 0,
|
NewReleasesAvailable2: [],
|
||||||
|
Release: Constants.DEFAULT_RELEASE,
|
||||||
ReleaseUpgradeAvailable: false,
|
ReleaseUpgradeAvailable: false,
|
||||||
UpgradeAvailable: false,
|
UpgradeAvailable: false,
|
||||||
UpgradeData: null,
|
UpgradeData: null,
|
||||||
@@ -49,6 +51,12 @@ export const releaseVersionReducer = createReducer({
|
|||||||
AllowDismissDependencies: action.payload,
|
AllowDismissDependencies: action.payload,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
[Actions.setDismissNewReleasesAvailable]: (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
DismissNewReleasesAvailable: action.payload,
|
||||||
|
};
|
||||||
|
},
|
||||||
[Actions.setDismissUIUpgrade]: (state, action) => {
|
[Actions.setDismissUIUpgrade]: (state, action) => {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
@@ -61,6 +69,19 @@ export const releaseVersionReducer = createReducer({
|
|||||||
InstalledVersion: action.payload,
|
InstalledVersion: action.payload,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
[Actions.setNewReleasesAvailable]: (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
DismissNewReleasesAvailable: false,
|
||||||
|
NewReleasesAvailable: action.payload,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[Actions.setNewReleasesAvailable2]: (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
NewReleasesAvailable2: action.payload,
|
||||||
|
};
|
||||||
|
},
|
||||||
[Actions.SET_RELEASE_DATA]: (state, action) => {
|
[Actions.SET_RELEASE_DATA]: (state, action) => {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
|||||||
20
src/redux/reducers/skynet_reducer.js
Normal file
20
src/redux/reducers/skynet_reducer.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import {createReducer} from '@reduxjs/toolkit';
|
||||||
|
import * as Actions from '../actions/skynet_actions';
|
||||||
|
|
||||||
|
export const skynetReducer = createReducer({
|
||||||
|
DisplayExport: false,
|
||||||
|
DisplayImport: false,
|
||||||
|
}, {
|
||||||
|
[Actions.displaySkynetExport]: (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
DisplayExport: action.payload,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[Actions.displaySkynetImport]: (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
DisplayImport: action.payload,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -5,6 +5,8 @@ import {errorReducer} from '../reducers/error_reducer';
|
|||||||
import {installReducer} from '../reducers/install_reducer';
|
import {installReducer} from '../reducers/install_reducer';
|
||||||
import {createMountReducer} from '../reducers/mount_reducer';
|
import {createMountReducer} from '../reducers/mount_reducer';
|
||||||
import {releaseVersionReducer} from '../reducers/release_version_reducer';
|
import {releaseVersionReducer} from '../reducers/release_version_reducer';
|
||||||
|
import {skynetReducer} from '../reducers/skynet_reducer';
|
||||||
|
import {pinnedManagerReducer} from '../reducers/pinned_manager_reducer'
|
||||||
|
|
||||||
export default function createAppStore(platformInfo, version, state) {
|
export default function createAppStore(platformInfo, version, state) {
|
||||||
const reducer = {
|
const reducer = {
|
||||||
@@ -14,6 +16,8 @@ export default function createAppStore(platformInfo, version, state) {
|
|||||||
install: installReducer,
|
install: installReducer,
|
||||||
mounts: createMountReducer(state),
|
mounts: createMountReducer(state),
|
||||||
relver: releaseVersionReducer,
|
relver: releaseVersionReducer,
|
||||||
|
skynet: skynetReducer,
|
||||||
|
pinned: pinnedManagerReducer,
|
||||||
};
|
};
|
||||||
|
|
||||||
const middleware = [...getDefaultMiddleware()];
|
const middleware = [...getDefaultMiddleware()];
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const Constants = require('../../constants');
|
const Constants = require('../../constants');
|
||||||
|
|
||||||
const addListeners = (ipcMain, closeApplication, setWindowVisibility) => {
|
const addListeners = (ipcMain, {closeApplication, setWindowVisibility}) => {
|
||||||
ipcMain.on(Constants.IPC_Shutdown, () => {
|
ipcMain.on(Constants.IPC_Shutdown, () => {
|
||||||
closeApplication();
|
closeApplication();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
const Constants = require('../../constants');
|
const Constants = require('../../constants');
|
||||||
const helpers = require('../../helpers');
|
const helpers = require('../../helpers');
|
||||||
|
|
||||||
const addListeners = (ipcMain, standardIPCReply) => {
|
const addListeners = (ipcMain, {standardIPCReply}) => {
|
||||||
ipcMain.on(Constants.IPC_Get_Config, (event, data) => {
|
ipcMain.on(Constants.IPC_Get_Config, (event, data) => {
|
||||||
helpers
|
helpers
|
||||||
.getConfig(data.Version, data.Provider, data.Remote)
|
.getConfig(data.Version, data.Provider, data.Remote, data.S3)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.Code === 0) {
|
if (data.Code === 0) {
|
||||||
standardIPCReply(event, Constants.IPC_Get_Config_Reply, {
|
standardIPCReply(event, Constants.IPC_Get_Config_Reply, {
|
||||||
@@ -21,7 +21,7 @@ const addListeners = (ipcMain, standardIPCReply) => {
|
|||||||
|
|
||||||
ipcMain.on(Constants.IPC_Get_Config_Template, (event, data) => {
|
ipcMain.on(Constants.IPC_Get_Config_Template, (event, data) => {
|
||||||
helpers
|
helpers
|
||||||
.getConfigTemplate(data.Version, data.Provider, data.Remote)
|
.getConfigTemplate(data.Version, data.Provider, data.Remote, data.S3)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
standardIPCReply(event, Constants.IPC_Get_Config_Template_Reply, {
|
standardIPCReply(event, Constants.IPC_Get_Config_Template_Reply, {
|
||||||
Template: data,
|
Template: data,
|
||||||
@@ -36,12 +36,12 @@ const addListeners = (ipcMain, standardIPCReply) => {
|
|||||||
const setConfigValue = (i) => {
|
const setConfigValue = (i) => {
|
||||||
if (i < data.Items.length) {
|
if (i < data.Items.length) {
|
||||||
helpers
|
helpers
|
||||||
.setConfigValue(data.Items[i].Name, data.Items[i].Value, data.Provider, data.Remote, data.Version)
|
.setConfigValue(data.Items[i].Name, data.Items[i].Value, data.Provider, data.Remote, data.S3, data.Version)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setConfigValue(++i);
|
setConfigValue(++i);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(error => {
|
||||||
setConfigValue(++i);
|
standardIPCReply(event, Constants.IPC_Set_Config_Values_Reply, {}, error);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
standardIPCReply(event, Constants.IPC_Set_Config_Values_Reply, {});
|
standardIPCReply(event, Constants.IPC_Set_Config_Values_Reply, {});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const Constants = require('../../constants');
|
const Constants = require('../../constants');
|
||||||
const helpers = require('../../helpers');
|
const helpers = require('../../helpers');
|
||||||
|
|
||||||
const addListeners = (ipcMain, standardIPCReply) => {
|
const addListeners = (ipcMain, {standardIPCReply}) => {
|
||||||
ipcMain.on(Constants.IPC_Check_Daemon_Version, (event, data) => {
|
ipcMain.on(Constants.IPC_Check_Daemon_Version, (event, data) => {
|
||||||
helpers
|
helpers
|
||||||
.checkDaemonVersion(data.Version, data.Provider)
|
.checkDaemonVersion(data.Version, data.Provider)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ const Constants = require('../../constants');
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const helpers = require('../../helpers');
|
const helpers = require('../../helpers');
|
||||||
|
|
||||||
const addListeners = (ipcMain, standardIPCReply) => {
|
const addListeners = (ipcMain, {standardIPCReply}) => {
|
||||||
ipcMain.on(Constants.IPC_Check_Dependency_Installed, (event, data) => {
|
ipcMain.on(Constants.IPC_Check_Dependency_Installed, (event, data) => {
|
||||||
try {
|
try {
|
||||||
const exists = fs.lstatSync(data.File).isFile();
|
const exists = fs.lstatSync(data.File).isFile();
|
||||||
@@ -72,15 +72,7 @@ const addListeners = (ipcMain, standardIPCReply) => {
|
|||||||
};
|
};
|
||||||
if (data.IsWinFSP) {
|
if (data.IsWinFSP) {
|
||||||
helpers
|
helpers
|
||||||
.performWindowsUninstall([
|
.performWindowsUninstall(Constants.WINFSP_VERSION_NAMES)
|
||||||
"WinFsp 2019.1",
|
|
||||||
"WinFsp 2019.2",
|
|
||||||
"WinFsp 2019.3 B1",
|
|
||||||
"WinFsp 2019.3 B2",
|
|
||||||
"WinFsp 2019.3 B3",
|
|
||||||
"WinFsp 2019.3 B4",
|
|
||||||
"WinFsp 2019.3 B5"
|
|
||||||
])
|
|
||||||
.then(uninstalled => {
|
.then(uninstalled => {
|
||||||
if (uninstalled) {
|
if (uninstalled) {
|
||||||
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ const Constants = require('../../constants');
|
|||||||
const helpers = require('../../helpers');
|
const helpers = require('../../helpers');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const addListeners = (ipcMain, standardIPCReply) => {
|
const addListeners = (ipcMain, {standardIPCReply}) => {
|
||||||
ipcMain.on(Constants.IPC_Download_File, (event, data) => {
|
ipcMain.on(Constants.IPC_Download_File, (event, data) => {
|
||||||
const destination = path.join(helpers.getDataDirectory(), data.Filename);
|
const destination = path.join(helpers.getDataDirectory(), data.Filename);
|
||||||
helpers.downloadFile(data.URL, destination, (progress) => {
|
helpers.downloadFile(data.URL, destination, (progress) => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const Constants = require('../../constants');
|
const Constants = require('../../constants');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
const addListeners = (ipcMain, getMainWindow, dialog) => {
|
const addListeners = (ipcMain, {getMainWindow, dialog}) => {
|
||||||
ipcMain.on(Constants.IPC_Browse_Directory + '_sync', (event, data) => {
|
ipcMain.on(Constants.IPC_Browse_Directory + '_sync', (event, data) => {
|
||||||
dialog.showOpenDialog(getMainWindow(), {
|
dialog.showOpenDialog(getMainWindow(), {
|
||||||
defaultPath: data.Location,
|
defaultPath: data.Location,
|
||||||
|
|||||||
@@ -20,29 +20,29 @@ const clearManualMountDetection = provider => {
|
|||||||
const monitorMount = (sender, provider, providerList, version, pid, location) => {
|
const monitorMount = (sender, provider, providerList, version, pid, location) => {
|
||||||
manualMountDetection[provider] = setInterval(() => {
|
manualMountDetection[provider] = setInterval(() => {
|
||||||
helpers
|
helpers
|
||||||
.detectRepertoryMounts(version, providerList)
|
.detectRepertoryMounts(version, providerList)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
if (result[provider].PID !== pid) {
|
if (result[provider].PID !== pid) {
|
||||||
if (result[provider].PID === -1) {
|
if (result[provider].PID === -1) {
|
||||||
clearManualMountDetection(provider);
|
clearManualMountDetection(provider);
|
||||||
sender.send(Constants.IPC_Unmount_Drive_Reply, {
|
sender.send(Constants.IPC_Unmount_Drive_Reply, {
|
||||||
data: {
|
data: {
|
||||||
Expected: expectedUnmount[provider],
|
Expected: expectedUnmount[provider],
|
||||||
Location: location,
|
Location: location,
|
||||||
Provider: provider,
|
Provider: provider,
|
||||||
Error: Error(provider + ' Unmounted').toString(),
|
Error: Error(provider + ' Unmounted').toString(),
|
||||||
Success: false,
|
Success: false,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
pid = result[provider].PID;
|
pid = result[provider].PID;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.catch(e => {
|
})
|
||||||
console.log(e);
|
.catch(e => {
|
||||||
});
|
console.log(e);
|
||||||
},6000);
|
});
|
||||||
|
}, 6000);
|
||||||
};
|
};
|
||||||
|
|
||||||
const unmountAllDrives = () => {
|
const unmountAllDrives = () => {
|
||||||
@@ -53,16 +53,16 @@ const unmountAllDrives = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unmount all items
|
// Unmount all items
|
||||||
for (const i in mountedLocations) {
|
for (const mountLocation of mountedLocations) {
|
||||||
const data = mountedData[mountedLocations[i]];
|
const data = mountedData[mountLocation];
|
||||||
helpers.stopMountProcessSync(data.Version, data.Provider, data.Remote);
|
helpers.stopMountProcessSync(data.Version, data.Provider, data.Remote, data.S3);
|
||||||
}
|
}
|
||||||
|
|
||||||
mountedLocations = [];
|
mountedLocations = [];
|
||||||
mountedData = {};
|
mountedData = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
const addListeners = (ipcMain, setTrayImage, standardIPCReply) => {
|
const addListeners = (ipcMain, {setTrayImage, standardIPCReply}) => {
|
||||||
ipcMain.on(Constants.IPC_Check_Mount_Location + '_sync', (event, data) => {
|
ipcMain.on(Constants.IPC_Check_Mount_Location + '_sync', (event, data) => {
|
||||||
let response = {
|
let response = {
|
||||||
Success: true,
|
Success: true,
|
||||||
@@ -93,6 +93,7 @@ const addListeners = (ipcMain, setTrayImage, standardIPCReply) => {
|
|||||||
const providerList = [
|
const providerList = [
|
||||||
...Constants.PROVIDER_LIST,
|
...Constants.PROVIDER_LIST,
|
||||||
...data.RemoteMounts,
|
...data.RemoteMounts,
|
||||||
|
...data.S3Mounts,
|
||||||
];
|
];
|
||||||
for (const provider of providerList) {
|
for (const provider of providerList) {
|
||||||
driveLetters[provider] = [];
|
driveLetters[provider] = [];
|
||||||
@@ -134,11 +135,11 @@ const addListeners = (ipcMain, setTrayImage, standardIPCReply) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const setImage = (locations) => {
|
const setImage = locations => {
|
||||||
let driveInUse;
|
let driveInUse;
|
||||||
if (Object.keys(locations).length > 0) {
|
if (Object.keys(locations).length > 0) {
|
||||||
for (const provider of providerList) {
|
for (const provider of providerList) {
|
||||||
driveInUse = locations[provider].length > 0;
|
driveInUse = locations[provider] && locations[provider].length > 0;
|
||||||
if (driveInUse)
|
if (driveInUse)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -148,52 +149,52 @@ const addListeners = (ipcMain, setTrayImage, standardIPCReply) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
helpers
|
helpers
|
||||||
.detectRepertoryMounts(data.Version, providerList)
|
.detectRepertoryMounts(data.Version, providerList)
|
||||||
.then((results) => {
|
.then((results) => {
|
||||||
let storageData = {};
|
let storageData = {};
|
||||||
let locations = {};
|
let locations = {};
|
||||||
for (const provider of providerList) {
|
for (const provider of providerList) {
|
||||||
storageData[provider] = results[provider] ? results[provider] : {
|
storageData[provider] = results[provider] ? results[provider] : {
|
||||||
Active: false,
|
Active: false,
|
||||||
Location: '',
|
Location: '',
|
||||||
PID: -1,
|
PID: -1,
|
||||||
};
|
};
|
||||||
locations[provider] = storageData[provider].Location;
|
locations[provider] = storageData[provider].Location;
|
||||||
|
|
||||||
if (storageData[provider].PID !== -1) {
|
if (storageData[provider].PID !== -1) {
|
||||||
expectedUnmount[provider] = false;
|
expectedUnmount[provider] = false;
|
||||||
if (firstMountCheck) {
|
if (firstMountCheck) {
|
||||||
monitorMount(event.sender, provider, providerList, data.Version, storageData[provider].PID, storageData[provider].Location);
|
monitorMount(event.sender, provider, providerList, data.Version, storageData[provider].PID, storageData[provider].Location);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (os.platform() === 'win32') {
|
if (os.platform() === 'win32') {
|
||||||
grabDriveLetters(locations);
|
grabDriveLetters(locations);
|
||||||
}
|
}
|
||||||
|
|
||||||
setImage(locations);
|
setImage(locations);
|
||||||
if (firstMountCheck) {
|
if (firstMountCheck) {
|
||||||
firstMountCheck = false;
|
firstMountCheck = false;
|
||||||
}
|
}
|
||||||
standardIPCReply(event, Constants.IPC_Detect_Mount_Reply, {
|
standardIPCReply(event, Constants.IPC_Detect_Mount_Reply, {
|
||||||
Active: storageData[provider].Active,
|
Active: storageData[provider].Active,
|
||||||
DriveLetters: driveLetters[provider],
|
DriveLetters: driveLetters[provider],
|
||||||
Location: locations[provider],
|
Location: locations[provider],
|
||||||
PID: storageData[provider].PID,
|
PID: storageData[provider].PID,
|
||||||
Provider: provider,
|
Provider: provider,
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
if (os.platform() === 'win32') {
|
|
||||||
grabDriveLetters({});
|
|
||||||
}
|
|
||||||
setImage({});
|
|
||||||
standardIPCReply(event, Constants.IPC_Detect_Mount_Reply, {
|
|
||||||
DriveLetters: driveLetters[provider],
|
|
||||||
Provider: provider,
|
|
||||||
}, error);
|
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
if (os.platform() === 'win32') {
|
||||||
|
grabDriveLetters({});
|
||||||
|
}
|
||||||
|
setImage({});
|
||||||
|
standardIPCReply(event, Constants.IPC_Detect_Mount_Reply, {
|
||||||
|
DriveLetters: driveLetters[provider],
|
||||||
|
Provider: provider,
|
||||||
|
}, error);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on(Constants.IPC_Mount_Drive, (event, data) => {
|
ipcMain.on(Constants.IPC_Mount_Drive, (event, data) => {
|
||||||
@@ -206,6 +207,7 @@ const addListeners = (ipcMain, setTrayImage, standardIPCReply) => {
|
|||||||
mountedData[data.Location] = {
|
mountedData[data.Location] = {
|
||||||
Provider: data.Provider,
|
Provider: data.Provider,
|
||||||
Remote: data.Remote,
|
Remote: data.Remote,
|
||||||
|
S3: data.S3,
|
||||||
Version: data.Version,
|
Version: data.Version,
|
||||||
};
|
};
|
||||||
const errorHandler = (pid, error) => {
|
const errorHandler = (pid, error) => {
|
||||||
@@ -219,16 +221,18 @@ const addListeners = (ipcMain, setTrayImage, standardIPCReply) => {
|
|||||||
Location: data.Location,
|
Location: data.Location,
|
||||||
Provider: data.Provider,
|
Provider: data.Provider,
|
||||||
Remote: data.Remote,
|
Remote: data.Remote,
|
||||||
|
S3: data.S3,
|
||||||
}, error || Error(data.Provider + ' Unmounted'));
|
}, error || Error(data.Provider + ' Unmounted'));
|
||||||
};
|
};
|
||||||
helpers
|
helpers
|
||||||
.executeMount(data.Version, data.Provider, data.Remote, data.Location, (error, pid) => {
|
.executeMount(data.Version, data.Provider, data.Remote, data.S3, data.Location, (error, pid) => {
|
||||||
errorHandler(pid, error);
|
errorHandler(pid, error);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
standardIPCReply(event, Constants.IPC_Mount_Drive_Reply, {
|
standardIPCReply(event, Constants.IPC_Mount_Drive_Reply, {
|
||||||
Provider: data.Provider,
|
Provider: data.Provider,
|
||||||
Remote: data.Remote,
|
Remote: data.Remote,
|
||||||
|
S3: data.S3,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
@@ -237,19 +241,21 @@ const addListeners = (ipcMain, setTrayImage, standardIPCReply) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on(Constants.IPC_Remove_Remote_Mount, (event, data) => {
|
ipcMain.on(Constants.IPC_Remove_Mount, (event, data) => {
|
||||||
data = data.replace(':', '_');
|
if (data.Remote) {
|
||||||
const dataDirectory = path.resolve(path.join(helpers.getDataDirectory(), '..', 'remote', data));
|
data.Name = data.Name.replace(':', '_');
|
||||||
|
}
|
||||||
|
const dataDirectory = path.resolve(path.join(helpers.getDataDirectory(), '..', data.Remote ? 'remote' : 's3', data.Name));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
helpers.removeDirectoryRecursively(dataDirectory);
|
helpers.removeDirectoryRecursively(dataDirectory);
|
||||||
standardIPCReply(event, Constants.IPC_Remove_Remote_Mount_Reply, {DataDirectory: dataDirectory});
|
standardIPCReply(event, Constants.IPC_Remove_Mount_Reply, {DataDirectory: dataDirectory});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
standardIPCReply(event, Constants.IPC_Remove_Remote_Mount_Reply, {DataDirectory: dataDirectory}, e);
|
standardIPCReply(event, Constants.IPC_Remove_Mount_Reply, {DataDirectory: dataDirectory}, e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on(Constants.IPC_Unmount_All_Drives, (event, data) => {
|
ipcMain.on(Constants.IPC_Unmount_All_Drives, event => {
|
||||||
unmountAllDrives();
|
unmountAllDrives();
|
||||||
standardIPCReply(event, Constants.IPC_Unmount_All_Drives_Reply);
|
standardIPCReply(event, Constants.IPC_Unmount_All_Drives_Reply);
|
||||||
});
|
});
|
||||||
@@ -259,13 +265,13 @@ const addListeners = (ipcMain, setTrayImage, standardIPCReply) => {
|
|||||||
|
|
||||||
expectedUnmount[data.Provider] = true;
|
expectedUnmount[data.Provider] = true;
|
||||||
helpers
|
helpers
|
||||||
.stopMountProcess(data.Version, data.Provider, data.Remote)
|
.stopMountProcess(data.Version, data.Provider, data.Remote, data.S3)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
console.log(result);
|
console.log(result);
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
49
src/renderer/ipc/PinnedIPC.js
Normal file
49
src/renderer/ipc/PinnedIPC.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
const Constants = require('../../constants');
|
||||||
|
const helpers = require('../../helpers');
|
||||||
|
|
||||||
|
const addListeners = (ipcMain, {standardIPCReply}) => {
|
||||||
|
ipcMain.on(Constants.IPC_Get_Directory_Items, (event, data) => {
|
||||||
|
helpers
|
||||||
|
.grabDirectoryItems(data.Path, data.Version, data.Provider, data.Remote, data.S3)
|
||||||
|
.then(data => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Get_Directory_Items_Reply, {
|
||||||
|
Items: data.items,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Get_Directory_Items_Reply, {}, e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on(Constants.IPC_Get_Pinned_Files, (event, data) => {
|
||||||
|
helpers
|
||||||
|
.grabDirectoryItems(data.Path, data.Version, data.Provider, data.Remote, data.S3)
|
||||||
|
.then(data => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Get_Directory_Items_Reply, {
|
||||||
|
Items: data.items,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Get_Directory_Items_Reply, {}, e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on(Constants.IPC_Get_Pinned_Files_Status, (event, data) => {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on(Constants.IPC_Set_Pinned + '_sync', (event, data) => {
|
||||||
|
helpers
|
||||||
|
.setPinned(data.Path, data.Pinned, data.Version, data.Provider, data.Remote, data.S3)
|
||||||
|
.then(success => {
|
||||||
|
event.returnValue = success;
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
event.returnValue = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
addListeners
|
||||||
|
};
|
||||||
@@ -14,7 +14,7 @@ const setPlatformOverride = platformOverride => {
|
|||||||
_platformOverride = platformOverride;
|
_platformOverride = platformOverride;
|
||||||
};
|
};
|
||||||
|
|
||||||
const addListeners = (ipcMain, detectScript, saveUiSettings) => {
|
const addListeners = (ipcMain, {detectScript, saveUiSettings}) => {
|
||||||
ipcMain.on(Constants.IPC_Get_Platform, (event) => {
|
ipcMain.on(Constants.IPC_Get_Platform, (event) => {
|
||||||
const sendResponse = (appPlatform, platform) => {
|
const sendResponse = (appPlatform, platform) => {
|
||||||
event.sender.send(Constants.IPC_Get_Platform_Reply, {
|
event.sender.send(Constants.IPC_Get_Platform_Reply, {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ const os = require('os');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const unzip = require('unzipper');
|
const unzip = require('unzipper');
|
||||||
|
|
||||||
const addListeners = (ipcMain, getCleanupReleases, standardIPCReply) => {
|
const addListeners = (ipcMain, {getCleanupReleases, standardIPCReply}) => {
|
||||||
ipcMain.on(Constants.IPC_Check_Installed, (event, data) => {
|
ipcMain.on(Constants.IPC_Check_Installed, (event, data) => {
|
||||||
const destination = path.join(helpers.getDataDirectory(), data.Version);
|
const destination = path.join(helpers.getDataDirectory(), data.Version);
|
||||||
helpers
|
helpers
|
||||||
|
|||||||
47
src/renderer/ipc/SkynetIPC.js
Normal file
47
src/renderer/ipc/SkynetIPC.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
const Constants = require('../../constants');
|
||||||
|
const helpers = require('../../helpers');
|
||||||
|
|
||||||
|
const addListeners = (ipcMain, {standardIPCReply}) => {
|
||||||
|
ipcMain.on(Constants.IPC_Export_Skylinks, (event, data) => {
|
||||||
|
helpers
|
||||||
|
.exportSkylinks(data.Version, data.Paths)
|
||||||
|
.then(result => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Export_Skylinks_Reply, {
|
||||||
|
Result: result,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Export_Skylinks_Reply, {}, error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on(Constants.IPC_Grab_Skynet_Tree, (event, data) => {
|
||||||
|
helpers
|
||||||
|
.grabSkynetFileTree(data.Version)
|
||||||
|
.then(result => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Grab_Skynet_Tree_Reply, {
|
||||||
|
Result: result,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Grab_Skynet_Tree_Reply, {}, error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on(Constants.IPC_Import_Skylinks, (event, data) => {
|
||||||
|
helpers
|
||||||
|
.importSkylinks(data.Version, data.JsonArray)
|
||||||
|
.then(result => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Import_Skylinks_Reply, {
|
||||||
|
Result: result,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Import_Skylinks_Reply, {}, error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
addListeners
|
||||||
|
};
|
||||||
@@ -3,19 +3,70 @@ const fs = require('fs');
|
|||||||
const helpers = require('../../helpers');
|
const helpers = require('../../helpers');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
|
const getDirectories = source => {
|
||||||
|
try {
|
||||||
|
return fs.readdirSync(source, {withFileTypes: true})
|
||||||
|
.filter(dirent => dirent.isDirectory())
|
||||||
|
.map(dirent => dirent.name);
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const addListeners = ipcMain => {
|
const addListeners = ipcMain => {
|
||||||
ipcMain.on(Constants.IPC_Get_State, event => {
|
ipcMain.on(Constants.IPC_Get_State, event => {
|
||||||
helpers.mkDirByPathSync(helpers.getDataDirectory());
|
helpers.mkDirByPathSync(helpers.getDataDirectory());
|
||||||
|
|
||||||
|
let data = {};
|
||||||
const configFile = path.join(helpers.getDataDirectory(), 'settings.json');
|
const configFile = path.join(helpers.getDataDirectory(), 'settings.json');
|
||||||
if (fs.existsSync(configFile)) {
|
if (fs.existsSync(configFile)) {
|
||||||
event.sender.send(Constants.IPC_Get_State_Reply, {
|
data = JSON.parse(fs.readFileSync(configFile, 'utf8'));
|
||||||
data: JSON.parse(fs.readFileSync(configFile, 'utf8')),
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
event.sender.send(Constants.IPC_Get_State_Reply, {
|
data.Release = Constants.DEFAULT_RELEASE;
|
||||||
data: null,
|
data.Version = -1;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const provider of Constants.PROVIDER_LIST) {
|
||||||
|
if (!data[provider]) {
|
||||||
|
data[provider] = {
|
||||||
|
AutoMount: false,
|
||||||
|
AutoRestart: true,
|
||||||
|
MountLocation: '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.RemoteMounts = data.RemoteMounts || [];
|
||||||
|
data.S3Mounts = data.S3Mounts || [];
|
||||||
|
|
||||||
|
const remoteItems = getDirectories(path.join(helpers.getRepertoryDirectory(), 'remote'));
|
||||||
|
for (const dir of remoteItems) {
|
||||||
|
const name = 'Remote' + dir.replace('_', ':');
|
||||||
|
if (!data.RemoteMounts || data.RemoteMounts.indexOf(name) === -1) {
|
||||||
|
data.RemoteMounts.push(name);
|
||||||
|
data[name] = {
|
||||||
|
AutoMount: false,
|
||||||
|
AutoRestart: true,
|
||||||
|
MountLocation: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const s3Items = getDirectories(path.join(helpers.getRepertoryDirectory(), 's3'));
|
||||||
|
for (const dir of s3Items) {
|
||||||
|
const name = 'S3' + dir;
|
||||||
|
if (!data.S3Mounts || data.S3Mounts.indexOf(name) === -1) {
|
||||||
|
data.S3Mounts.push(name);
|
||||||
|
data[name] = {
|
||||||
|
AutoMount: false,
|
||||||
|
AutoRestart: true,
|
||||||
|
MountLocation: '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
event.sender.send(Constants.IPC_Get_State_Reply, {
|
||||||
|
data,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on(Constants.IPC_Save_State, (event, data) => {
|
ipcMain.on(Constants.IPC_Save_State, (event, data) => {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ const Constants = require('../../constants');
|
|||||||
const os = require('os');
|
const os = require('os');
|
||||||
const helpers = require('../../helpers');
|
const helpers = require('../../helpers');
|
||||||
|
|
||||||
const addListeners = (ipcMain, closeApplication) => {
|
const addListeners = (ipcMain, {closeApplication}) => {
|
||||||
ipcMain.on(Constants.IPC_Reboot_System, () => {
|
ipcMain.on(Constants.IPC_Reboot_System, () => {
|
||||||
if (os.platform() === 'win32') {
|
if (os.platform() === 'win32') {
|
||||||
helpers.executeAsync('shutdown.exe', ['/r', '/t', '30']);
|
helpers.executeAsync('shutdown.exe', ['/r', '/t', '30']);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ const fs = require('fs');
|
|||||||
const helpers = require('../../helpers');
|
const helpers = require('../../helpers');
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
|
|
||||||
const addListeners = (ipcMain, setIsInstalling, unmountAllDrives, standardIPCReply) => {
|
const addListeners = (ipcMain, {setIsInstalling, unmountAllDrives, standardIPCReply}) => {
|
||||||
ipcMain.on(Constants.IPC_Install_Upgrade, (event, data) => {
|
ipcMain.on(Constants.IPC_Install_Upgrade, (event, data) => {
|
||||||
let allowSkipVerification = true;
|
let allowSkipVerification = true;
|
||||||
|
|
||||||
|
|||||||
82
src/utils.js
82
src/utils.js
@@ -1,13 +1,29 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import * as Constants from './constants';
|
import * as Constants from './constants';
|
||||||
import Modal from './components/UI/Modal/Modal';
|
import Modal from './components/UI/Modal/Modal';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
const ipcRenderer = (!process.versions.hasOwnProperty('electron') && window && window.require) ?
|
const ipcRenderer = (!process.versions.hasOwnProperty('electron') && window && window.require) ?
|
||||||
window.require('electron').ipcRenderer :
|
window.require('electron').ipcRenderer :
|
||||||
null;
|
null;
|
||||||
|
|
||||||
export const createModalConditionally = (condition, jsx, critical) => {
|
export const checkNewReleases = selectedVersion => {
|
||||||
const modalProps = {critical: critical};
|
let previousReleases = localStorage.getItem('previous_releases');
|
||||||
|
if (previousReleases) {
|
||||||
|
previousReleases = JSON.parse(previousReleases).VersionLookup;
|
||||||
|
|
||||||
|
let currentReleases = localStorage.getItem('releases');
|
||||||
|
if (currentReleases) {
|
||||||
|
currentReleases = JSON.parse(currentReleases).VersionLookup;
|
||||||
|
return getNewReleases(previousReleases, currentReleases, selectedVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createModalConditionally = (condition, jsx, critical, disableFocusTrap, transparent) => {
|
||||||
|
const modalProps = {critical: critical, disableFocusTrap: disableFocusTrap, transparent: transparent};
|
||||||
return condition ? (<Modal {...modalProps}>{jsx}</Modal>) : null;
|
return condition ? (<Modal {...modalProps}>{jsx}</Modal>) : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -16,10 +32,72 @@ export const extractFileNameFromURL = url => {
|
|||||||
return parts[parts.length - 1];
|
return parts[parts.length - 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const formatLinesForDisplay = lines => {
|
||||||
|
let msg = '';
|
||||||
|
for (let i = 1; i < lines.length; i++) {
|
||||||
|
if (i > 1) {
|
||||||
|
msg += '\n';
|
||||||
|
}
|
||||||
|
msg += (lines[i].replace(/(\\#)/gm, '#') + '\n');
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getChangesForRepertoryVersion = version => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const url = 'https://bitbucket.org/blockstorage/repertory/raw/' +
|
||||||
|
Constants.REPERTORY_BRANCH + '/CHANGELOG.md';
|
||||||
|
axios
|
||||||
|
.get(url, {
|
||||||
|
responseType: 'text',
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
try {
|
||||||
|
let found = false;
|
||||||
|
let ended = false;
|
||||||
|
let lines = response.data
|
||||||
|
.replace(/(\r\n)/gm, '\n')
|
||||||
|
.split('\n')
|
||||||
|
.filter(l => {
|
||||||
|
return !ended && (l.length > 0) && (found
|
||||||
|
? !(ended = l.startsWith('## '))
|
||||||
|
: (found = l.startsWith(`## ${version}`)));
|
||||||
|
});
|
||||||
|
resolve(lines);
|
||||||
|
} catch (e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const getIPCRenderer = () => {
|
export const getIPCRenderer = () => {
|
||||||
return ipcRenderer;
|
return ipcRenderer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getNewReleases = (existingLocations, newLocations, selectedVersion) => {
|
||||||
|
const ret = [];
|
||||||
|
if (existingLocations && newLocations) {
|
||||||
|
Constants.RELEASE_TYPES.forEach(release => {
|
||||||
|
newLocations[release]
|
||||||
|
.filter(version => (version !== selectedVersion) && !existingLocations[release].includes(version) && (version !== 'unavailable'))
|
||||||
|
.forEach(version => {
|
||||||
|
ret.splice(0, 0, {
|
||||||
|
Display: version,
|
||||||
|
Release: Constants.RELEASE_TYPES.indexOf(release),
|
||||||
|
Version: newLocations[release].indexOf(version),
|
||||||
|
VersionString: version,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
export const getSelectedVersionFromState = state => {
|
export const getSelectedVersionFromState = state => {
|
||||||
return (state.relver.Version === -1) ?
|
return (state.relver.Version === -1) ?
|
||||||
'unavailable' :
|
'unavailable' :
|
||||||
|
|||||||
Reference in New Issue
Block a user