From 751f51d889f4f46ffe797d4ff52f030a54286baa Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Tue, 27 Aug 2019 18:25:53 -0500 Subject: [PATCH 01/22] Updated version --- CHANGELOG.md | 2 + README.md | 6 +- package.json | 2 +- releases.json | 208 +++++++++++++++++++------------------------------- 4 files changed, 86 insertions(+), 132 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e782deb..eae74d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +## 1.0.8 + ## 1.0.7 * \#31: New installation displays 'Mount location is not set' on Windows * \#33: Add 'Microsoft Visual C++ Redistributable' as dependency installation on Windows diff --git a/README.md b/README.md index d2bc48f..ba8f3be 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,10 @@ Repertory allows you to mount Sia and/or SiaPrime blockchain storage solutions v * SiaPrime >=1.4.0 ## Downloads -* **Repertory UI v1.0.7 Linux 64-bit** [](https://pixeldrain.com/u/thkU0RHP) [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_linux_x86_64.AppImage) +* **Repertory UI v1.0.8 Linux 64-bit** []() [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage) * NOTE: Linux distributions require `fuse` and `libfuse` to be installed. -* **Repertory UI v1.0.7 OS X 64-bit** [](https://pixeldrain.com/u/gBW5TSR0) [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_mac.dmg) -* **Repertory UI v1.0.7 Windows 64-bit** [](https://pixeldrain.com/u/AcsttDQ_) [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_win.exe) +* **Repertory UI v1.0.8 OS X 64-bit** []() [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_mac.dmg) +* **Repertory UI v1.0.8 Windows 64-bit** []() [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_win.exe) * NOTE: Windows systems require [Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019](https://aka.ms/vs/16/release/vc_redist.x64.exe) ## Supported Platforms diff --git a/package.json b/package.json index 939aac5..7cadff8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "repertory-ui", - "version": "1.0.7", + "version": "1.0.8", "private": true, "author": "scott.e.graves@protonmail.com", "description": "GUI for Repertory - Repertory allows you to mount Sia and/or SiaPrime blockchain storage solutions via FUSE on Linux/OS X or via WinFSP on Windows.", diff --git a/releases.json b/releases.json index f783752..863694c 100644 --- a/releases.json +++ b/releases.json @@ -1,220 +1,172 @@ { "Locations": { "arch": { - "1.0.7": { - "sha256": "dac898185beb12bd6e0eaf0164f2cdcd517223981678ee18e8ec99983921ecbf", - "sig": "A/jHXV4OFVc4jjczUlB+CzHZbmaCWIygzshHVS3wjpPYBuQjZRbqn0Lj7yIV7PBoaT3xBAykI0Nd6BAxFHdWwwt10d/Snz8jbW94U7LpQMYjhbmy/7FxlbVOcLJSGs1AeoZUIMsYZpyu74IFD0eHn7x37z5Sg62HBE03uggiwVdwKi5g5qfvgzpBkQnzlSAYRQFOb3wELjLu5GRupJQiKdYsUaSkh8xLeloxhsb3UD8VKB427lfyDG7Da+ZMUFROJN9e+1afkGshlJmLu+/6G+Wiyik7gnjVvNEIQyZOoUMfZNZfhO2oL+5YH1a5Sc7vXcPo1CqHxC9ZT9d5L2QLi/9isAk72FemdiRYhPcMHMJ52Zkp4s5WP/2HxCGunAMLx+qC+Zp4NIihkC99fGJcsJfJ4MX7W9ENdxtBA9al4E+Au2CftrxFWXuARhyCy3X6+b1JlQ1jeMWBqixEqthcsAHvWgVTJUOJKCcEJb4BzpQQt2iEIAqNg2nxIKcSeal86GSvz27Z7Cf7CaNXCxrc0CAJ8XeIm8ZzB17Fg/GnKfEDRzaxweL3yyMIrzpIZnGECc8xHBVa1cLpOpuL3s5DxsLRB4XvcNEQ9ywcyuK0ZiEDRHJMW7lWeKEHgvxhMZNTKFnBp72Fgla9Sb7r+ZGXkwJjSn2chwPkKyFr4HlQgMLU386C2fieL8aqaScbb9VpZnPC9gfXDE/ZaFnLug1ORQYwE45DFXoUSnLNVrFUAMne3ISDaXJ946dMQm/6lrAQm1PglS7WKk+1V+GYmrszx9YeHi+Mqz8Dmlww7PCOPbCYsDFHqeruxxcfisq7SoFoHEOzmlq1FNqT3h0hNatpGIKJ2/FM4tQnEuDIGb6gQZMUZrLrLiVYW4ZmeNBe/GoqOt6c8REbtbt4Hpo9UgueKhZtCZOppZZBXu6i59eJXOIgBtNqX+6Kg8R9iM8vhTNbpec5hC0Q9yyELdkoRZkbUDmKWObKZQSr6h82LlsDSggHFYKRtZ4mOqJNxR7U8T8XEr7xqSaC0jmCl9bbxNND1Ir1x6PREfOuSNABxCYHRvZBAqp3PI+T41OsN/2Gcbz5FKc1ShfRcEZKH6npg/mPeYB6KNtuTtgpTJefAAgEra6t3mrV84sjEPig0IfQhfp8VeZItB09OXV02aOOXHKOBU2VilXWF7+Lapjk51I6+BnWRulBkZg6k70YZP/6icOaR+Z60PS8kTqplELfsk4r41nsGlo7iQPHONd5jOa4vhRdmAws7Fan2o5x6wfCJyn1nljNTysLktSm9y8PzJFUVq/kscXac5Q7Rfl4F8JIqbVvmUT740/tJv1zTB4YLfgYJI5cnwVbFuTzTXeDOR/KPCk=", - "urls": [ - "https://pixeldrain.com/api/file/thkU0RHP", - "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_linux_x86_64.AppImage" - ] + "1.0.8": { + "sha256": "", + "sig": "", + "urls": [] } }, "centos7": { - "1.0.7": { - "sha256": "dac898185beb12bd6e0eaf0164f2cdcd517223981678ee18e8ec99983921ecbf", - "sig": "A/jHXV4OFVc4jjczUlB+CzHZbmaCWIygzshHVS3wjpPYBuQjZRbqn0Lj7yIV7PBoaT3xBAykI0Nd6BAxFHdWwwt10d/Snz8jbW94U7LpQMYjhbmy/7FxlbVOcLJSGs1AeoZUIMsYZpyu74IFD0eHn7x37z5Sg62HBE03uggiwVdwKi5g5qfvgzpBkQnzlSAYRQFOb3wELjLu5GRupJQiKdYsUaSkh8xLeloxhsb3UD8VKB427lfyDG7Da+ZMUFROJN9e+1afkGshlJmLu+/6G+Wiyik7gnjVvNEIQyZOoUMfZNZfhO2oL+5YH1a5Sc7vXcPo1CqHxC9ZT9d5L2QLi/9isAk72FemdiRYhPcMHMJ52Zkp4s5WP/2HxCGunAMLx+qC+Zp4NIihkC99fGJcsJfJ4MX7W9ENdxtBA9al4E+Au2CftrxFWXuARhyCy3X6+b1JlQ1jeMWBqixEqthcsAHvWgVTJUOJKCcEJb4BzpQQt2iEIAqNg2nxIKcSeal86GSvz27Z7Cf7CaNXCxrc0CAJ8XeIm8ZzB17Fg/GnKfEDRzaxweL3yyMIrzpIZnGECc8xHBVa1cLpOpuL3s5DxsLRB4XvcNEQ9ywcyuK0ZiEDRHJMW7lWeKEHgvxhMZNTKFnBp72Fgla9Sb7r+ZGXkwJjSn2chwPkKyFr4HlQgMLU386C2fieL8aqaScbb9VpZnPC9gfXDE/ZaFnLug1ORQYwE45DFXoUSnLNVrFUAMne3ISDaXJ946dMQm/6lrAQm1PglS7WKk+1V+GYmrszx9YeHi+Mqz8Dmlww7PCOPbCYsDFHqeruxxcfisq7SoFoHEOzmlq1FNqT3h0hNatpGIKJ2/FM4tQnEuDIGb6gQZMUZrLrLiVYW4ZmeNBe/GoqOt6c8REbtbt4Hpo9UgueKhZtCZOppZZBXu6i59eJXOIgBtNqX+6Kg8R9iM8vhTNbpec5hC0Q9yyELdkoRZkbUDmKWObKZQSr6h82LlsDSggHFYKRtZ4mOqJNxR7U8T8XEr7xqSaC0jmCl9bbxNND1Ir1x6PREfOuSNABxCYHRvZBAqp3PI+T41OsN/2Gcbz5FKc1ShfRcEZKH6npg/mPeYB6KNtuTtgpTJefAAgEra6t3mrV84sjEPig0IfQhfp8VeZItB09OXV02aOOXHKOBU2VilXWF7+Lapjk51I6+BnWRulBkZg6k70YZP/6icOaR+Z60PS8kTqplELfsk4r41nsGlo7iQPHONd5jOa4vhRdmAws7Fan2o5x6wfCJyn1nljNTysLktSm9y8PzJFUVq/kscXac5Q7Rfl4F8JIqbVvmUT740/tJv1zTB4YLfgYJI5cnwVbFuTzTXeDOR/KPCk=", - "urls": [ - "https://pixeldrain.com/api/file/thkU0RHP", - "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_linux_x86_64.AppImage" - ] + "1.0.8": { + "sha256": "", + "sig": "", + "urls": [] } }, "darwin": { - "1.0.7": { - "sha256": "e4f5cf9765224d4c25472310089e0996f59772573dc59c1baa065810a16c19ba", - "sig": "A11yvEkveuPo2yyJaDhw9xt/+/xw7/4T3D2Kd/Px1LwCREio25gCr5BWPSIef5yALCS1nDHIzG8CIaDS+OHc4w87YAqIqVOcQaDi2E2t1El7B1noW8yXs+Ew/Ro3AwqN0lnJrtr8fZWVFKqxUTvxLLOJmh5jiud9vdrFzlaI2MNEvC0dY62T0hS1o4uij5/NIXHrZJuz43sa8WftL1RSD/z0lQELF43MaFYCfcDeyCZn2N/htyyvlOEi0bVbjZg1N2cyWAhKbAZu47t5Z5uyoV+VYcIPJT0IsGK2Vr/Js6ziSr3IqdpWl44ztXRLGp4Es17MMnjne30AbhOt+qIOPIcwyRQ7ENEu6MEgT3nA35y5fd1YK7Nz3IkJMxMe1XwyjLE82MgXg9tywb46zKeEJ9zzWk4No71Z6CPwo7kGEl7kzKLw61GYL+1AY+o2dmiDrO+l+DmTzHqGJ3GqBuCnG+5yKM+6klEKU+zmtuaQsPHamY5YLa302G59ecnH90+XIP9veB8jj0ipID8UoGZqJNZgUvkNN3CFoV3TMqA01M5VH7xqWTGPib+aoxCwFsaYiaKTbZBYjw9PQ/ECGXakfX3YpkR1YniNq+Y6UHpfnQNznqZBC+lrud67R2SmRN5JO6wIKiqaKwUT5B5k1ze3Ltdfb1i8bkhk1yNJZBmnr3MA4n5w7wvS/Fw4Uq1zkeUb+No4lP3nH1TcAwU+shesB44MUaLiTlnWUii1AGivEsTtqNp1YoSKVdX1c5GOia0F3iJBqyO1T++bgRpm433AkwaFLqvOr66CirCRtelhZaZtZPStBXATzSBlXEn1J2NbEA6rS185Twco4Cp92+otMFfACm59Ew94E0I8/NSXWEtGkaF7OadMdjS9WPf/5jHWoMnqA8dpYZZXXnZN3xU1eUaVxlu7bdoQxwjllkVMElLp30nOE7Gg2sHuV9xTZ5L2zaueDhZToiItZqce1mlG7zqN0fPlJ8SY0V5nGkm91L90rVi7/9YLKa3jE63Kkv6rMd/o1MAqaFIu1KOgcEbVzexIh1f3ikphIfgxT0PdEuhYa5OGhXwHI/7oaNT8I9XebFRVXCIRHoaYz+zxqCIDQVqDWnW62aTKBwdmGBAp0b9RsCNekCheR2SHfiJi2qAvMWbQR1c3MZpC9A5xAIJZ+FJpTqpagR5U09RIkMjfewpCrfXQYdIWXDJ7CDm2pYGxVn2IIrxvc5kpbsh7VpvNh8bA/TaHyxEKqRWFbua9JZcGP17jliBx3R2ZLt45BYET63Z7z6C8A/Js4bfEspXDd8KfF+rmu83crc1txaJx4WRpbVx8KTLlU/b9o+B5PaoV+BTt/CV3Jgf6uLLXKLB/EXU=", - "urls": [ - "https://pixeldrain.com/api/file/gBW5TSR0", - "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_mac.dmg" - ] + "1.0.8": { + "sha256": "", + "sig": "", + "urls": [] } }, "debian9": { - "1.0.7": { - "sha256": "dac898185beb12bd6e0eaf0164f2cdcd517223981678ee18e8ec99983921ecbf", - "sig": "A/jHXV4OFVc4jjczUlB+CzHZbmaCWIygzshHVS3wjpPYBuQjZRbqn0Lj7yIV7PBoaT3xBAykI0Nd6BAxFHdWwwt10d/Snz8jbW94U7LpQMYjhbmy/7FxlbVOcLJSGs1AeoZUIMsYZpyu74IFD0eHn7x37z5Sg62HBE03uggiwVdwKi5g5qfvgzpBkQnzlSAYRQFOb3wELjLu5GRupJQiKdYsUaSkh8xLeloxhsb3UD8VKB427lfyDG7Da+ZMUFROJN9e+1afkGshlJmLu+/6G+Wiyik7gnjVvNEIQyZOoUMfZNZfhO2oL+5YH1a5Sc7vXcPo1CqHxC9ZT9d5L2QLi/9isAk72FemdiRYhPcMHMJ52Zkp4s5WP/2HxCGunAMLx+qC+Zp4NIihkC99fGJcsJfJ4MX7W9ENdxtBA9al4E+Au2CftrxFWXuARhyCy3X6+b1JlQ1jeMWBqixEqthcsAHvWgVTJUOJKCcEJb4BzpQQt2iEIAqNg2nxIKcSeal86GSvz27Z7Cf7CaNXCxrc0CAJ8XeIm8ZzB17Fg/GnKfEDRzaxweL3yyMIrzpIZnGECc8xHBVa1cLpOpuL3s5DxsLRB4XvcNEQ9ywcyuK0ZiEDRHJMW7lWeKEHgvxhMZNTKFnBp72Fgla9Sb7r+ZGXkwJjSn2chwPkKyFr4HlQgMLU386C2fieL8aqaScbb9VpZnPC9gfXDE/ZaFnLug1ORQYwE45DFXoUSnLNVrFUAMne3ISDaXJ946dMQm/6lrAQm1PglS7WKk+1V+GYmrszx9YeHi+Mqz8Dmlww7PCOPbCYsDFHqeruxxcfisq7SoFoHEOzmlq1FNqT3h0hNatpGIKJ2/FM4tQnEuDIGb6gQZMUZrLrLiVYW4ZmeNBe/GoqOt6c8REbtbt4Hpo9UgueKhZtCZOppZZBXu6i59eJXOIgBtNqX+6Kg8R9iM8vhTNbpec5hC0Q9yyELdkoRZkbUDmKWObKZQSr6h82LlsDSggHFYKRtZ4mOqJNxR7U8T8XEr7xqSaC0jmCl9bbxNND1Ir1x6PREfOuSNABxCYHRvZBAqp3PI+T41OsN/2Gcbz5FKc1ShfRcEZKH6npg/mPeYB6KNtuTtgpTJefAAgEra6t3mrV84sjEPig0IfQhfp8VeZItB09OXV02aOOXHKOBU2VilXWF7+Lapjk51I6+BnWRulBkZg6k70YZP/6icOaR+Z60PS8kTqplELfsk4r41nsGlo7iQPHONd5jOa4vhRdmAws7Fan2o5x6wfCJyn1nljNTysLktSm9y8PzJFUVq/kscXac5Q7Rfl4F8JIqbVvmUT740/tJv1zTB4YLfgYJI5cnwVbFuTzTXeDOR/KPCk=", - "urls": [ - "https://pixeldrain.com/api/file/thkU0RHP", - "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_linux_x86_64.AppImage" - ] + "1.0.8": { + "sha256": "", + "sig": "", + "urls": [] } }, "debian10": { - "1.0.7": { - "sha256": "dac898185beb12bd6e0eaf0164f2cdcd517223981678ee18e8ec99983921ecbf", - "sig": "A/jHXV4OFVc4jjczUlB+CzHZbmaCWIygzshHVS3wjpPYBuQjZRbqn0Lj7yIV7PBoaT3xBAykI0Nd6BAxFHdWwwt10d/Snz8jbW94U7LpQMYjhbmy/7FxlbVOcLJSGs1AeoZUIMsYZpyu74IFD0eHn7x37z5Sg62HBE03uggiwVdwKi5g5qfvgzpBkQnzlSAYRQFOb3wELjLu5GRupJQiKdYsUaSkh8xLeloxhsb3UD8VKB427lfyDG7Da+ZMUFROJN9e+1afkGshlJmLu+/6G+Wiyik7gnjVvNEIQyZOoUMfZNZfhO2oL+5YH1a5Sc7vXcPo1CqHxC9ZT9d5L2QLi/9isAk72FemdiRYhPcMHMJ52Zkp4s5WP/2HxCGunAMLx+qC+Zp4NIihkC99fGJcsJfJ4MX7W9ENdxtBA9al4E+Au2CftrxFWXuARhyCy3X6+b1JlQ1jeMWBqixEqthcsAHvWgVTJUOJKCcEJb4BzpQQt2iEIAqNg2nxIKcSeal86GSvz27Z7Cf7CaNXCxrc0CAJ8XeIm8ZzB17Fg/GnKfEDRzaxweL3yyMIrzpIZnGECc8xHBVa1cLpOpuL3s5DxsLRB4XvcNEQ9ywcyuK0ZiEDRHJMW7lWeKEHgvxhMZNTKFnBp72Fgla9Sb7r+ZGXkwJjSn2chwPkKyFr4HlQgMLU386C2fieL8aqaScbb9VpZnPC9gfXDE/ZaFnLug1ORQYwE45DFXoUSnLNVrFUAMne3ISDaXJ946dMQm/6lrAQm1PglS7WKk+1V+GYmrszx9YeHi+Mqz8Dmlww7PCOPbCYsDFHqeruxxcfisq7SoFoHEOzmlq1FNqT3h0hNatpGIKJ2/FM4tQnEuDIGb6gQZMUZrLrLiVYW4ZmeNBe/GoqOt6c8REbtbt4Hpo9UgueKhZtCZOppZZBXu6i59eJXOIgBtNqX+6Kg8R9iM8vhTNbpec5hC0Q9yyELdkoRZkbUDmKWObKZQSr6h82LlsDSggHFYKRtZ4mOqJNxR7U8T8XEr7xqSaC0jmCl9bbxNND1Ir1x6PREfOuSNABxCYHRvZBAqp3PI+T41OsN/2Gcbz5FKc1ShfRcEZKH6npg/mPeYB6KNtuTtgpTJefAAgEra6t3mrV84sjEPig0IfQhfp8VeZItB09OXV02aOOXHKOBU2VilXWF7+Lapjk51I6+BnWRulBkZg6k70YZP/6icOaR+Z60PS8kTqplELfsk4r41nsGlo7iQPHONd5jOa4vhRdmAws7Fan2o5x6wfCJyn1nljNTysLktSm9y8PzJFUVq/kscXac5Q7Rfl4F8JIqbVvmUT740/tJv1zTB4YLfgYJI5cnwVbFuTzTXeDOR/KPCk=", - "urls": [ - "https://pixeldrain.com/api/file/thkU0RHP", - "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_linux_x86_64.AppImage" - ] + "1.0.8": { + "sha256": "", + "sig": "", + "urls": [] } }, "fedora28": { - "1.0.7": { - "sha256": "dac898185beb12bd6e0eaf0164f2cdcd517223981678ee18e8ec99983921ecbf", - "sig": "A/jHXV4OFVc4jjczUlB+CzHZbmaCWIygzshHVS3wjpPYBuQjZRbqn0Lj7yIV7PBoaT3xBAykI0Nd6BAxFHdWwwt10d/Snz8jbW94U7LpQMYjhbmy/7FxlbVOcLJSGs1AeoZUIMsYZpyu74IFD0eHn7x37z5Sg62HBE03uggiwVdwKi5g5qfvgzpBkQnzlSAYRQFOb3wELjLu5GRupJQiKdYsUaSkh8xLeloxhsb3UD8VKB427lfyDG7Da+ZMUFROJN9e+1afkGshlJmLu+/6G+Wiyik7gnjVvNEIQyZOoUMfZNZfhO2oL+5YH1a5Sc7vXcPo1CqHxC9ZT9d5L2QLi/9isAk72FemdiRYhPcMHMJ52Zkp4s5WP/2HxCGunAMLx+qC+Zp4NIihkC99fGJcsJfJ4MX7W9ENdxtBA9al4E+Au2CftrxFWXuARhyCy3X6+b1JlQ1jeMWBqixEqthcsAHvWgVTJUOJKCcEJb4BzpQQt2iEIAqNg2nxIKcSeal86GSvz27Z7Cf7CaNXCxrc0CAJ8XeIm8ZzB17Fg/GnKfEDRzaxweL3yyMIrzpIZnGECc8xHBVa1cLpOpuL3s5DxsLRB4XvcNEQ9ywcyuK0ZiEDRHJMW7lWeKEHgvxhMZNTKFnBp72Fgla9Sb7r+ZGXkwJjSn2chwPkKyFr4HlQgMLU386C2fieL8aqaScbb9VpZnPC9gfXDE/ZaFnLug1ORQYwE45DFXoUSnLNVrFUAMne3ISDaXJ946dMQm/6lrAQm1PglS7WKk+1V+GYmrszx9YeHi+Mqz8Dmlww7PCOPbCYsDFHqeruxxcfisq7SoFoHEOzmlq1FNqT3h0hNatpGIKJ2/FM4tQnEuDIGb6gQZMUZrLrLiVYW4ZmeNBe/GoqOt6c8REbtbt4Hpo9UgueKhZtCZOppZZBXu6i59eJXOIgBtNqX+6Kg8R9iM8vhTNbpec5hC0Q9yyELdkoRZkbUDmKWObKZQSr6h82LlsDSggHFYKRtZ4mOqJNxR7U8T8XEr7xqSaC0jmCl9bbxNND1Ir1x6PREfOuSNABxCYHRvZBAqp3PI+T41OsN/2Gcbz5FKc1ShfRcEZKH6npg/mPeYB6KNtuTtgpTJefAAgEra6t3mrV84sjEPig0IfQhfp8VeZItB09OXV02aOOXHKOBU2VilXWF7+Lapjk51I6+BnWRulBkZg6k70YZP/6icOaR+Z60PS8kTqplELfsk4r41nsGlo7iQPHONd5jOa4vhRdmAws7Fan2o5x6wfCJyn1nljNTysLktSm9y8PzJFUVq/kscXac5Q7Rfl4F8JIqbVvmUT740/tJv1zTB4YLfgYJI5cnwVbFuTzTXeDOR/KPCk=", - "urls": [ - "https://pixeldrain.com/api/file/thkU0RHP", - "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_linux_x86_64.AppImage" - ] + "1.0.8": { + "sha256": "", + "sig": "", + "urls": [] } }, "fedora29": { - "1.0.7": { - "sha256": "dac898185beb12bd6e0eaf0164f2cdcd517223981678ee18e8ec99983921ecbf", - "sig": "A/jHXV4OFVc4jjczUlB+CzHZbmaCWIygzshHVS3wjpPYBuQjZRbqn0Lj7yIV7PBoaT3xBAykI0Nd6BAxFHdWwwt10d/Snz8jbW94U7LpQMYjhbmy/7FxlbVOcLJSGs1AeoZUIMsYZpyu74IFD0eHn7x37z5Sg62HBE03uggiwVdwKi5g5qfvgzpBkQnzlSAYRQFOb3wELjLu5GRupJQiKdYsUaSkh8xLeloxhsb3UD8VKB427lfyDG7Da+ZMUFROJN9e+1afkGshlJmLu+/6G+Wiyik7gnjVvNEIQyZOoUMfZNZfhO2oL+5YH1a5Sc7vXcPo1CqHxC9ZT9d5L2QLi/9isAk72FemdiRYhPcMHMJ52Zkp4s5WP/2HxCGunAMLx+qC+Zp4NIihkC99fGJcsJfJ4MX7W9ENdxtBA9al4E+Au2CftrxFWXuARhyCy3X6+b1JlQ1jeMWBqixEqthcsAHvWgVTJUOJKCcEJb4BzpQQt2iEIAqNg2nxIKcSeal86GSvz27Z7Cf7CaNXCxrc0CAJ8XeIm8ZzB17Fg/GnKfEDRzaxweL3yyMIrzpIZnGECc8xHBVa1cLpOpuL3s5DxsLRB4XvcNEQ9ywcyuK0ZiEDRHJMW7lWeKEHgvxhMZNTKFnBp72Fgla9Sb7r+ZGXkwJjSn2chwPkKyFr4HlQgMLU386C2fieL8aqaScbb9VpZnPC9gfXDE/ZaFnLug1ORQYwE45DFXoUSnLNVrFUAMne3ISDaXJ946dMQm/6lrAQm1PglS7WKk+1V+GYmrszx9YeHi+Mqz8Dmlww7PCOPbCYsDFHqeruxxcfisq7SoFoHEOzmlq1FNqT3h0hNatpGIKJ2/FM4tQnEuDIGb6gQZMUZrLrLiVYW4ZmeNBe/GoqOt6c8REbtbt4Hpo9UgueKhZtCZOppZZBXu6i59eJXOIgBtNqX+6Kg8R9iM8vhTNbpec5hC0Q9yyELdkoRZkbUDmKWObKZQSr6h82LlsDSggHFYKRtZ4mOqJNxR7U8T8XEr7xqSaC0jmCl9bbxNND1Ir1x6PREfOuSNABxCYHRvZBAqp3PI+T41OsN/2Gcbz5FKc1ShfRcEZKH6npg/mPeYB6KNtuTtgpTJefAAgEra6t3mrV84sjEPig0IfQhfp8VeZItB09OXV02aOOXHKOBU2VilXWF7+Lapjk51I6+BnWRulBkZg6k70YZP/6icOaR+Z60PS8kTqplELfsk4r41nsGlo7iQPHONd5jOa4vhRdmAws7Fan2o5x6wfCJyn1nljNTysLktSm9y8PzJFUVq/kscXac5Q7Rfl4F8JIqbVvmUT740/tJv1zTB4YLfgYJI5cnwVbFuTzTXeDOR/KPCk=", - "urls": [ - "https://pixeldrain.com/api/file/thkU0RHP", - "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_linux_x86_64.AppImage" - ] + "1.0.8": { + "sha256": "", + "sig": "", + "urls": [] } }, "fedora30": { - "1.0.7": { - "sha256": "dac898185beb12bd6e0eaf0164f2cdcd517223981678ee18e8ec99983921ecbf", - "sig": "A/jHXV4OFVc4jjczUlB+CzHZbmaCWIygzshHVS3wjpPYBuQjZRbqn0Lj7yIV7PBoaT3xBAykI0Nd6BAxFHdWwwt10d/Snz8jbW94U7LpQMYjhbmy/7FxlbVOcLJSGs1AeoZUIMsYZpyu74IFD0eHn7x37z5Sg62HBE03uggiwVdwKi5g5qfvgzpBkQnzlSAYRQFOb3wELjLu5GRupJQiKdYsUaSkh8xLeloxhsb3UD8VKB427lfyDG7Da+ZMUFROJN9e+1afkGshlJmLu+/6G+Wiyik7gnjVvNEIQyZOoUMfZNZfhO2oL+5YH1a5Sc7vXcPo1CqHxC9ZT9d5L2QLi/9isAk72FemdiRYhPcMHMJ52Zkp4s5WP/2HxCGunAMLx+qC+Zp4NIihkC99fGJcsJfJ4MX7W9ENdxtBA9al4E+Au2CftrxFWXuARhyCy3X6+b1JlQ1jeMWBqixEqthcsAHvWgVTJUOJKCcEJb4BzpQQt2iEIAqNg2nxIKcSeal86GSvz27Z7Cf7CaNXCxrc0CAJ8XeIm8ZzB17Fg/GnKfEDRzaxweL3yyMIrzpIZnGECc8xHBVa1cLpOpuL3s5DxsLRB4XvcNEQ9ywcyuK0ZiEDRHJMW7lWeKEHgvxhMZNTKFnBp72Fgla9Sb7r+ZGXkwJjSn2chwPkKyFr4HlQgMLU386C2fieL8aqaScbb9VpZnPC9gfXDE/ZaFnLug1ORQYwE45DFXoUSnLNVrFUAMne3ISDaXJ946dMQm/6lrAQm1PglS7WKk+1V+GYmrszx9YeHi+Mqz8Dmlww7PCOPbCYsDFHqeruxxcfisq7SoFoHEOzmlq1FNqT3h0hNatpGIKJ2/FM4tQnEuDIGb6gQZMUZrLrLiVYW4ZmeNBe/GoqOt6c8REbtbt4Hpo9UgueKhZtCZOppZZBXu6i59eJXOIgBtNqX+6Kg8R9iM8vhTNbpec5hC0Q9yyELdkoRZkbUDmKWObKZQSr6h82LlsDSggHFYKRtZ4mOqJNxR7U8T8XEr7xqSaC0jmCl9bbxNND1Ir1x6PREfOuSNABxCYHRvZBAqp3PI+T41OsN/2Gcbz5FKc1ShfRcEZKH6npg/mPeYB6KNtuTtgpTJefAAgEra6t3mrV84sjEPig0IfQhfp8VeZItB09OXV02aOOXHKOBU2VilXWF7+Lapjk51I6+BnWRulBkZg6k70YZP/6icOaR+Z60PS8kTqplELfsk4r41nsGlo7iQPHONd5jOa4vhRdmAws7Fan2o5x6wfCJyn1nljNTysLktSm9y8PzJFUVq/kscXac5Q7Rfl4F8JIqbVvmUT740/tJv1zTB4YLfgYJI5cnwVbFuTzTXeDOR/KPCk=", - "urls": [ - "https://pixeldrain.com/api/file/thkU0RHP", - "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_linux_x86_64.AppImage" - ] + "1.0.8": { + "sha256": "", + "sig": "", + "urls": [] } }, "opensuse15": { - "1.0.7": { - "sha256": "dac898185beb12bd6e0eaf0164f2cdcd517223981678ee18e8ec99983921ecbf", - "sig": "A/jHXV4OFVc4jjczUlB+CzHZbmaCWIygzshHVS3wjpPYBuQjZRbqn0Lj7yIV7PBoaT3xBAykI0Nd6BAxFHdWwwt10d/Snz8jbW94U7LpQMYjhbmy/7FxlbVOcLJSGs1AeoZUIMsYZpyu74IFD0eHn7x37z5Sg62HBE03uggiwVdwKi5g5qfvgzpBkQnzlSAYRQFOb3wELjLu5GRupJQiKdYsUaSkh8xLeloxhsb3UD8VKB427lfyDG7Da+ZMUFROJN9e+1afkGshlJmLu+/6G+Wiyik7gnjVvNEIQyZOoUMfZNZfhO2oL+5YH1a5Sc7vXcPo1CqHxC9ZT9d5L2QLi/9isAk72FemdiRYhPcMHMJ52Zkp4s5WP/2HxCGunAMLx+qC+Zp4NIihkC99fGJcsJfJ4MX7W9ENdxtBA9al4E+Au2CftrxFWXuARhyCy3X6+b1JlQ1jeMWBqixEqthcsAHvWgVTJUOJKCcEJb4BzpQQt2iEIAqNg2nxIKcSeal86GSvz27Z7Cf7CaNXCxrc0CAJ8XeIm8ZzB17Fg/GnKfEDRzaxweL3yyMIrzpIZnGECc8xHBVa1cLpOpuL3s5DxsLRB4XvcNEQ9ywcyuK0ZiEDRHJMW7lWeKEHgvxhMZNTKFnBp72Fgla9Sb7r+ZGXkwJjSn2chwPkKyFr4HlQgMLU386C2fieL8aqaScbb9VpZnPC9gfXDE/ZaFnLug1ORQYwE45DFXoUSnLNVrFUAMne3ISDaXJ946dMQm/6lrAQm1PglS7WKk+1V+GYmrszx9YeHi+Mqz8Dmlww7PCOPbCYsDFHqeruxxcfisq7SoFoHEOzmlq1FNqT3h0hNatpGIKJ2/FM4tQnEuDIGb6gQZMUZrLrLiVYW4ZmeNBe/GoqOt6c8REbtbt4Hpo9UgueKhZtCZOppZZBXu6i59eJXOIgBtNqX+6Kg8R9iM8vhTNbpec5hC0Q9yyELdkoRZkbUDmKWObKZQSr6h82LlsDSggHFYKRtZ4mOqJNxR7U8T8XEr7xqSaC0jmCl9bbxNND1Ir1x6PREfOuSNABxCYHRvZBAqp3PI+T41OsN/2Gcbz5FKc1ShfRcEZKH6npg/mPeYB6KNtuTtgpTJefAAgEra6t3mrV84sjEPig0IfQhfp8VeZItB09OXV02aOOXHKOBU2VilXWF7+Lapjk51I6+BnWRulBkZg6k70YZP/6icOaR+Z60PS8kTqplELfsk4r41nsGlo7iQPHONd5jOa4vhRdmAws7Fan2o5x6wfCJyn1nljNTysLktSm9y8PzJFUVq/kscXac5Q7Rfl4F8JIqbVvmUT740/tJv1zTB4YLfgYJI5cnwVbFuTzTXeDOR/KPCk=", - "urls": [ - "https://pixeldrain.com/api/file/thkU0RHP", - "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_linux_x86_64.AppImage" - ] + "1.0.8": { + "sha256": "", + "sig": "", + "urls": [] } }, "opensuse15.1": { - "1.0.7": { - "sha256": "dac898185beb12bd6e0eaf0164f2cdcd517223981678ee18e8ec99983921ecbf", - "sig": "A/jHXV4OFVc4jjczUlB+CzHZbmaCWIygzshHVS3wjpPYBuQjZRbqn0Lj7yIV7PBoaT3xBAykI0Nd6BAxFHdWwwt10d/Snz8jbW94U7LpQMYjhbmy/7FxlbVOcLJSGs1AeoZUIMsYZpyu74IFD0eHn7x37z5Sg62HBE03uggiwVdwKi5g5qfvgzpBkQnzlSAYRQFOb3wELjLu5GRupJQiKdYsUaSkh8xLeloxhsb3UD8VKB427lfyDG7Da+ZMUFROJN9e+1afkGshlJmLu+/6G+Wiyik7gnjVvNEIQyZOoUMfZNZfhO2oL+5YH1a5Sc7vXcPo1CqHxC9ZT9d5L2QLi/9isAk72FemdiRYhPcMHMJ52Zkp4s5WP/2HxCGunAMLx+qC+Zp4NIihkC99fGJcsJfJ4MX7W9ENdxtBA9al4E+Au2CftrxFWXuARhyCy3X6+b1JlQ1jeMWBqixEqthcsAHvWgVTJUOJKCcEJb4BzpQQt2iEIAqNg2nxIKcSeal86GSvz27Z7Cf7CaNXCxrc0CAJ8XeIm8ZzB17Fg/GnKfEDRzaxweL3yyMIrzpIZnGECc8xHBVa1cLpOpuL3s5DxsLRB4XvcNEQ9ywcyuK0ZiEDRHJMW7lWeKEHgvxhMZNTKFnBp72Fgla9Sb7r+ZGXkwJjSn2chwPkKyFr4HlQgMLU386C2fieL8aqaScbb9VpZnPC9gfXDE/ZaFnLug1ORQYwE45DFXoUSnLNVrFUAMne3ISDaXJ946dMQm/6lrAQm1PglS7WKk+1V+GYmrszx9YeHi+Mqz8Dmlww7PCOPbCYsDFHqeruxxcfisq7SoFoHEOzmlq1FNqT3h0hNatpGIKJ2/FM4tQnEuDIGb6gQZMUZrLrLiVYW4ZmeNBe/GoqOt6c8REbtbt4Hpo9UgueKhZtCZOppZZBXu6i59eJXOIgBtNqX+6Kg8R9iM8vhTNbpec5hC0Q9yyELdkoRZkbUDmKWObKZQSr6h82LlsDSggHFYKRtZ4mOqJNxR7U8T8XEr7xqSaC0jmCl9bbxNND1Ir1x6PREfOuSNABxCYHRvZBAqp3PI+T41OsN/2Gcbz5FKc1ShfRcEZKH6npg/mPeYB6KNtuTtgpTJefAAgEra6t3mrV84sjEPig0IfQhfp8VeZItB09OXV02aOOXHKOBU2VilXWF7+Lapjk51I6+BnWRulBkZg6k70YZP/6icOaR+Z60PS8kTqplELfsk4r41nsGlo7iQPHONd5jOa4vhRdmAws7Fan2o5x6wfCJyn1nljNTysLktSm9y8PzJFUVq/kscXac5Q7Rfl4F8JIqbVvmUT740/tJv1zTB4YLfgYJI5cnwVbFuTzTXeDOR/KPCk=", - "urls": [ - "https://pixeldrain.com/api/file/thkU0RHP", - "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_linux_x86_64.AppImage" - ] + "1.0.8": { + "sha256": "", + "sig": "", + "urls": [] } }, "solus": { - "1.0.7": { - "sha256": "dac898185beb12bd6e0eaf0164f2cdcd517223981678ee18e8ec99983921ecbf", - "sig": "A/jHXV4OFVc4jjczUlB+CzHZbmaCWIygzshHVS3wjpPYBuQjZRbqn0Lj7yIV7PBoaT3xBAykI0Nd6BAxFHdWwwt10d/Snz8jbW94U7LpQMYjhbmy/7FxlbVOcLJSGs1AeoZUIMsYZpyu74IFD0eHn7x37z5Sg62HBE03uggiwVdwKi5g5qfvgzpBkQnzlSAYRQFOb3wELjLu5GRupJQiKdYsUaSkh8xLeloxhsb3UD8VKB427lfyDG7Da+ZMUFROJN9e+1afkGshlJmLu+/6G+Wiyik7gnjVvNEIQyZOoUMfZNZfhO2oL+5YH1a5Sc7vXcPo1CqHxC9ZT9d5L2QLi/9isAk72FemdiRYhPcMHMJ52Zkp4s5WP/2HxCGunAMLx+qC+Zp4NIihkC99fGJcsJfJ4MX7W9ENdxtBA9al4E+Au2CftrxFWXuARhyCy3X6+b1JlQ1jeMWBqixEqthcsAHvWgVTJUOJKCcEJb4BzpQQt2iEIAqNg2nxIKcSeal86GSvz27Z7Cf7CaNXCxrc0CAJ8XeIm8ZzB17Fg/GnKfEDRzaxweL3yyMIrzpIZnGECc8xHBVa1cLpOpuL3s5DxsLRB4XvcNEQ9ywcyuK0ZiEDRHJMW7lWeKEHgvxhMZNTKFnBp72Fgla9Sb7r+ZGXkwJjSn2chwPkKyFr4HlQgMLU386C2fieL8aqaScbb9VpZnPC9gfXDE/ZaFnLug1ORQYwE45DFXoUSnLNVrFUAMne3ISDaXJ946dMQm/6lrAQm1PglS7WKk+1V+GYmrszx9YeHi+Mqz8Dmlww7PCOPbCYsDFHqeruxxcfisq7SoFoHEOzmlq1FNqT3h0hNatpGIKJ2/FM4tQnEuDIGb6gQZMUZrLrLiVYW4ZmeNBe/GoqOt6c8REbtbt4Hpo9UgueKhZtCZOppZZBXu6i59eJXOIgBtNqX+6Kg8R9iM8vhTNbpec5hC0Q9yyELdkoRZkbUDmKWObKZQSr6h82LlsDSggHFYKRtZ4mOqJNxR7U8T8XEr7xqSaC0jmCl9bbxNND1Ir1x6PREfOuSNABxCYHRvZBAqp3PI+T41OsN/2Gcbz5FKc1ShfRcEZKH6npg/mPeYB6KNtuTtgpTJefAAgEra6t3mrV84sjEPig0IfQhfp8VeZItB09OXV02aOOXHKOBU2VilXWF7+Lapjk51I6+BnWRulBkZg6k70YZP/6icOaR+Z60PS8kTqplELfsk4r41nsGlo7iQPHONd5jOa4vhRdmAws7Fan2o5x6wfCJyn1nljNTysLktSm9y8PzJFUVq/kscXac5Q7Rfl4F8JIqbVvmUT740/tJv1zTB4YLfgYJI5cnwVbFuTzTXeDOR/KPCk=", - "urls": [ - "https://pixeldrain.com/api/file/thkU0RHP", - "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_linux_x86_64.AppImage" - ] + "1.0.8": { + "sha256": "", + "sig": "", + "urls": [] } }, "tumbleweed": { - "1.0.7": { - "sha256": "dac898185beb12bd6e0eaf0164f2cdcd517223981678ee18e8ec99983921ecbf", - "sig": "A/jHXV4OFVc4jjczUlB+CzHZbmaCWIygzshHVS3wjpPYBuQjZRbqn0Lj7yIV7PBoaT3xBAykI0Nd6BAxFHdWwwt10d/Snz8jbW94U7LpQMYjhbmy/7FxlbVOcLJSGs1AeoZUIMsYZpyu74IFD0eHn7x37z5Sg62HBE03uggiwVdwKi5g5qfvgzpBkQnzlSAYRQFOb3wELjLu5GRupJQiKdYsUaSkh8xLeloxhsb3UD8VKB427lfyDG7Da+ZMUFROJN9e+1afkGshlJmLu+/6G+Wiyik7gnjVvNEIQyZOoUMfZNZfhO2oL+5YH1a5Sc7vXcPo1CqHxC9ZT9d5L2QLi/9isAk72FemdiRYhPcMHMJ52Zkp4s5WP/2HxCGunAMLx+qC+Zp4NIihkC99fGJcsJfJ4MX7W9ENdxtBA9al4E+Au2CftrxFWXuARhyCy3X6+b1JlQ1jeMWBqixEqthcsAHvWgVTJUOJKCcEJb4BzpQQt2iEIAqNg2nxIKcSeal86GSvz27Z7Cf7CaNXCxrc0CAJ8XeIm8ZzB17Fg/GnKfEDRzaxweL3yyMIrzpIZnGECc8xHBVa1cLpOpuL3s5DxsLRB4XvcNEQ9ywcyuK0ZiEDRHJMW7lWeKEHgvxhMZNTKFnBp72Fgla9Sb7r+ZGXkwJjSn2chwPkKyFr4HlQgMLU386C2fieL8aqaScbb9VpZnPC9gfXDE/ZaFnLug1ORQYwE45DFXoUSnLNVrFUAMne3ISDaXJ946dMQm/6lrAQm1PglS7WKk+1V+GYmrszx9YeHi+Mqz8Dmlww7PCOPbCYsDFHqeruxxcfisq7SoFoHEOzmlq1FNqT3h0hNatpGIKJ2/FM4tQnEuDIGb6gQZMUZrLrLiVYW4ZmeNBe/GoqOt6c8REbtbt4Hpo9UgueKhZtCZOppZZBXu6i59eJXOIgBtNqX+6Kg8R9iM8vhTNbpec5hC0Q9yyELdkoRZkbUDmKWObKZQSr6h82LlsDSggHFYKRtZ4mOqJNxR7U8T8XEr7xqSaC0jmCl9bbxNND1Ir1x6PREfOuSNABxCYHRvZBAqp3PI+T41OsN/2Gcbz5FKc1ShfRcEZKH6npg/mPeYB6KNtuTtgpTJefAAgEra6t3mrV84sjEPig0IfQhfp8VeZItB09OXV02aOOXHKOBU2VilXWF7+Lapjk51I6+BnWRulBkZg6k70YZP/6icOaR+Z60PS8kTqplELfsk4r41nsGlo7iQPHONd5jOa4vhRdmAws7Fan2o5x6wfCJyn1nljNTysLktSm9y8PzJFUVq/kscXac5Q7Rfl4F8JIqbVvmUT740/tJv1zTB4YLfgYJI5cnwVbFuTzTXeDOR/KPCk=", - "urls": [ - "https://pixeldrain.com/api/file/thkU0RHP", - "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_linux_x86_64.AppImage" - ] + "1.0.8": { + "sha256": "", + "sig": "", + "urls": [] } }, "ubuntu18.04": { - "1.0.7": { - "sha256": "dac898185beb12bd6e0eaf0164f2cdcd517223981678ee18e8ec99983921ecbf", - "sig": "A/jHXV4OFVc4jjczUlB+CzHZbmaCWIygzshHVS3wjpPYBuQjZRbqn0Lj7yIV7PBoaT3xBAykI0Nd6BAxFHdWwwt10d/Snz8jbW94U7LpQMYjhbmy/7FxlbVOcLJSGs1AeoZUIMsYZpyu74IFD0eHn7x37z5Sg62HBE03uggiwVdwKi5g5qfvgzpBkQnzlSAYRQFOb3wELjLu5GRupJQiKdYsUaSkh8xLeloxhsb3UD8VKB427lfyDG7Da+ZMUFROJN9e+1afkGshlJmLu+/6G+Wiyik7gnjVvNEIQyZOoUMfZNZfhO2oL+5YH1a5Sc7vXcPo1CqHxC9ZT9d5L2QLi/9isAk72FemdiRYhPcMHMJ52Zkp4s5WP/2HxCGunAMLx+qC+Zp4NIihkC99fGJcsJfJ4MX7W9ENdxtBA9al4E+Au2CftrxFWXuARhyCy3X6+b1JlQ1jeMWBqixEqthcsAHvWgVTJUOJKCcEJb4BzpQQt2iEIAqNg2nxIKcSeal86GSvz27Z7Cf7CaNXCxrc0CAJ8XeIm8ZzB17Fg/GnKfEDRzaxweL3yyMIrzpIZnGECc8xHBVa1cLpOpuL3s5DxsLRB4XvcNEQ9ywcyuK0ZiEDRHJMW7lWeKEHgvxhMZNTKFnBp72Fgla9Sb7r+ZGXkwJjSn2chwPkKyFr4HlQgMLU386C2fieL8aqaScbb9VpZnPC9gfXDE/ZaFnLug1ORQYwE45DFXoUSnLNVrFUAMne3ISDaXJ946dMQm/6lrAQm1PglS7WKk+1V+GYmrszx9YeHi+Mqz8Dmlww7PCOPbCYsDFHqeruxxcfisq7SoFoHEOzmlq1FNqT3h0hNatpGIKJ2/FM4tQnEuDIGb6gQZMUZrLrLiVYW4ZmeNBe/GoqOt6c8REbtbt4Hpo9UgueKhZtCZOppZZBXu6i59eJXOIgBtNqX+6Kg8R9iM8vhTNbpec5hC0Q9yyELdkoRZkbUDmKWObKZQSr6h82LlsDSggHFYKRtZ4mOqJNxR7U8T8XEr7xqSaC0jmCl9bbxNND1Ir1x6PREfOuSNABxCYHRvZBAqp3PI+T41OsN/2Gcbz5FKc1ShfRcEZKH6npg/mPeYB6KNtuTtgpTJefAAgEra6t3mrV84sjEPig0IfQhfp8VeZItB09OXV02aOOXHKOBU2VilXWF7+Lapjk51I6+BnWRulBkZg6k70YZP/6icOaR+Z60PS8kTqplELfsk4r41nsGlo7iQPHONd5jOa4vhRdmAws7Fan2o5x6wfCJyn1nljNTysLktSm9y8PzJFUVq/kscXac5Q7Rfl4F8JIqbVvmUT740/tJv1zTB4YLfgYJI5cnwVbFuTzTXeDOR/KPCk=", - "urls": [ - "https://pixeldrain.com/api/file/thkU0RHP", - "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_linux_x86_64.AppImage" - ] + "1.0.8": { + "sha256": "", + "sig": "", + "urls": [] } }, "ubuntu18.10": { - "1.0.7": { - "sha256": "dac898185beb12bd6e0eaf0164f2cdcd517223981678ee18e8ec99983921ecbf", - "sig": "A/jHXV4OFVc4jjczUlB+CzHZbmaCWIygzshHVS3wjpPYBuQjZRbqn0Lj7yIV7PBoaT3xBAykI0Nd6BAxFHdWwwt10d/Snz8jbW94U7LpQMYjhbmy/7FxlbVOcLJSGs1AeoZUIMsYZpyu74IFD0eHn7x37z5Sg62HBE03uggiwVdwKi5g5qfvgzpBkQnzlSAYRQFOb3wELjLu5GRupJQiKdYsUaSkh8xLeloxhsb3UD8VKB427lfyDG7Da+ZMUFROJN9e+1afkGshlJmLu+/6G+Wiyik7gnjVvNEIQyZOoUMfZNZfhO2oL+5YH1a5Sc7vXcPo1CqHxC9ZT9d5L2QLi/9isAk72FemdiRYhPcMHMJ52Zkp4s5WP/2HxCGunAMLx+qC+Zp4NIihkC99fGJcsJfJ4MX7W9ENdxtBA9al4E+Au2CftrxFWXuARhyCy3X6+b1JlQ1jeMWBqixEqthcsAHvWgVTJUOJKCcEJb4BzpQQt2iEIAqNg2nxIKcSeal86GSvz27Z7Cf7CaNXCxrc0CAJ8XeIm8ZzB17Fg/GnKfEDRzaxweL3yyMIrzpIZnGECc8xHBVa1cLpOpuL3s5DxsLRB4XvcNEQ9ywcyuK0ZiEDRHJMW7lWeKEHgvxhMZNTKFnBp72Fgla9Sb7r+ZGXkwJjSn2chwPkKyFr4HlQgMLU386C2fieL8aqaScbb9VpZnPC9gfXDE/ZaFnLug1ORQYwE45DFXoUSnLNVrFUAMne3ISDaXJ946dMQm/6lrAQm1PglS7WKk+1V+GYmrszx9YeHi+Mqz8Dmlww7PCOPbCYsDFHqeruxxcfisq7SoFoHEOzmlq1FNqT3h0hNatpGIKJ2/FM4tQnEuDIGb6gQZMUZrLrLiVYW4ZmeNBe/GoqOt6c8REbtbt4Hpo9UgueKhZtCZOppZZBXu6i59eJXOIgBtNqX+6Kg8R9iM8vhTNbpec5hC0Q9yyELdkoRZkbUDmKWObKZQSr6h82LlsDSggHFYKRtZ4mOqJNxR7U8T8XEr7xqSaC0jmCl9bbxNND1Ir1x6PREfOuSNABxCYHRvZBAqp3PI+T41OsN/2Gcbz5FKc1ShfRcEZKH6npg/mPeYB6KNtuTtgpTJefAAgEra6t3mrV84sjEPig0IfQhfp8VeZItB09OXV02aOOXHKOBU2VilXWF7+Lapjk51I6+BnWRulBkZg6k70YZP/6icOaR+Z60PS8kTqplELfsk4r41nsGlo7iQPHONd5jOa4vhRdmAws7Fan2o5x6wfCJyn1nljNTysLktSm9y8PzJFUVq/kscXac5Q7Rfl4F8JIqbVvmUT740/tJv1zTB4YLfgYJI5cnwVbFuTzTXeDOR/KPCk=", - "urls": [ - "https://pixeldrain.com/api/file/thkU0RHP", - "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_linux_x86_64.AppImage" - ] + "1.0.8": { + "sha256": "", + "sig": "", + "urls": [] } }, "ubuntu19.04": { - "1.0.7": { - "sha256": "dac898185beb12bd6e0eaf0164f2cdcd517223981678ee18e8ec99983921ecbf", - "sig": "A/jHXV4OFVc4jjczUlB+CzHZbmaCWIygzshHVS3wjpPYBuQjZRbqn0Lj7yIV7PBoaT3xBAykI0Nd6BAxFHdWwwt10d/Snz8jbW94U7LpQMYjhbmy/7FxlbVOcLJSGs1AeoZUIMsYZpyu74IFD0eHn7x37z5Sg62HBE03uggiwVdwKi5g5qfvgzpBkQnzlSAYRQFOb3wELjLu5GRupJQiKdYsUaSkh8xLeloxhsb3UD8VKB427lfyDG7Da+ZMUFROJN9e+1afkGshlJmLu+/6G+Wiyik7gnjVvNEIQyZOoUMfZNZfhO2oL+5YH1a5Sc7vXcPo1CqHxC9ZT9d5L2QLi/9isAk72FemdiRYhPcMHMJ52Zkp4s5WP/2HxCGunAMLx+qC+Zp4NIihkC99fGJcsJfJ4MX7W9ENdxtBA9al4E+Au2CftrxFWXuARhyCy3X6+b1JlQ1jeMWBqixEqthcsAHvWgVTJUOJKCcEJb4BzpQQt2iEIAqNg2nxIKcSeal86GSvz27Z7Cf7CaNXCxrc0CAJ8XeIm8ZzB17Fg/GnKfEDRzaxweL3yyMIrzpIZnGECc8xHBVa1cLpOpuL3s5DxsLRB4XvcNEQ9ywcyuK0ZiEDRHJMW7lWeKEHgvxhMZNTKFnBp72Fgla9Sb7r+ZGXkwJjSn2chwPkKyFr4HlQgMLU386C2fieL8aqaScbb9VpZnPC9gfXDE/ZaFnLug1ORQYwE45DFXoUSnLNVrFUAMne3ISDaXJ946dMQm/6lrAQm1PglS7WKk+1V+GYmrszx9YeHi+Mqz8Dmlww7PCOPbCYsDFHqeruxxcfisq7SoFoHEOzmlq1FNqT3h0hNatpGIKJ2/FM4tQnEuDIGb6gQZMUZrLrLiVYW4ZmeNBe/GoqOt6c8REbtbt4Hpo9UgueKhZtCZOppZZBXu6i59eJXOIgBtNqX+6Kg8R9iM8vhTNbpec5hC0Q9yyELdkoRZkbUDmKWObKZQSr6h82LlsDSggHFYKRtZ4mOqJNxR7U8T8XEr7xqSaC0jmCl9bbxNND1Ir1x6PREfOuSNABxCYHRvZBAqp3PI+T41OsN/2Gcbz5FKc1ShfRcEZKH6npg/mPeYB6KNtuTtgpTJefAAgEra6t3mrV84sjEPig0IfQhfp8VeZItB09OXV02aOOXHKOBU2VilXWF7+Lapjk51I6+BnWRulBkZg6k70YZP/6icOaR+Z60PS8kTqplELfsk4r41nsGlo7iQPHONd5jOa4vhRdmAws7Fan2o5x6wfCJyn1nljNTysLktSm9y8PzJFUVq/kscXac5Q7Rfl4F8JIqbVvmUT740/tJv1zTB4YLfgYJI5cnwVbFuTzTXeDOR/KPCk=", - "urls": [ - "https://pixeldrain.com/api/file/thkU0RHP", - "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_linux_x86_64.AppImage" - ] + "1.0.8": { + "sha256": "", + "sig": "", + "urls": [] } }, "win32": { - "1.0.7": { - "sha256": "fbf7611bca712413bd6e6900bcbd49bd3a1545b4d4e70afb2ee9bd59f74b8f97", - "sig": "B3URP0wqwJcxuisX/qkoLg19Tm1tUu0rQbkBrCtpscaSa5PhUS/p+6ID/eApKMy91SWqCeqw0C071OvTVfTmWRoB/v+9Kkftqs9IISIMDBZgJEAcwf5h0CYqRp/cLyl5XfZLnZoMDR6x7cIVejBaDu1EWtWtACTxfDy3SvtbHkXTfo5ojKk5DScTSNAeDVSL1dY7BBsGuy5WDR0GYpB+519//V4uNCeLSxmHMekEQdyMmjpaO4iKDOkqccwYNSrw3LpL6TQ6YpTX8g2I1tD1ucTKob5Z44LANceL/PMjk7XYRCplufZBIiAnK6mBQFjFFMm4dDTSWqFQKn+pJboTE1E20Gvs/1MFwO1S30mwOIuYebZ4Xfa/D26rFjjxsA8a62Xrxw5YenKczRWs1iNRK+BZUUNw3pbm0KtEwvJZX/XhaVBBuHwT4CDTLIK0tvVsVF6cMNXLdgJEBmItkSw8LdDta81SwHVco0oMxwExqFbwhXqZf7hQBx4NaytBft0QeXNGF0T1B7GTi+D2qr9F5YcIALzYPh5b6RC8yTuTuVgIW+f3LSY8yPTvJaFS3idjTMbzebWAC2aR0BNW1dPyEEoLzsQEfBDbXqSN4m7j+Nt2l5HGfpy370uOaVeKhIFgASJTvhp6FJ0+3FdJfv5E6E0h6EXCXsGCXmh51kcz5kPpmeLXa3OaoF8G5277hICztyUfqskmgz6cu5udRglW57ZwVM8nWRYo9yO5oiLn9ygq4ALOhUfQhbaCpICsDO5nG1R3rAj0t4a2yzQg+CqN9GXzf0+xlbuO0wdg92s2Tgs1O2F5U8yPvgp7fJIil8/GYmmJHj9zqj+kWjFm+ZPdreXns5m+jr58/hepaVyu7KVV/I/o5Q2dse5Xf+jvt7B8u2TC+JWmitzBJkDGRM0Rml+3QIb2F1lKMfPSs34aI7HJHjrfvExAcFiXDVsFXudVZqayjKWreA4gsgZ07GUi1lZ6qX00K7trxWz0BmlZqtXGofrDUQGgsiZ5FoGW5tFSs9t7DqUnpQAZCiVfPki8bphbPMeRsPXBMXsHKTK6TzbU8nukq8urMJWURetWQP5N4/dSI5zrgByBVI7n1TQvdE2bzMQrJP/xTLWGZUCRXfi2J7FmW7fbUtcAStVC2TPWPuzEC9Lvb3ybg0wepgEbMn1kGfb7mohJ5jeLHqhGzY9mx9fO191cduH9zI+yV5wrnYqWd5wN9J4NY66ULxeGxt03rzjMd2hv2tRRVRsT+/4ACUZcIV8JwUZgK51s5DuUWUsl2e5DBPAND/RVpThXJVFyAtBo/vDqoY3lg/pc4RaQZ6gNMoFeHbXwD/yu6TDDTWq5u00ZwNCbR0PaBTwDabs=", - "urls": [ - "https://pixeldrain.com/api/file/AcsttDQ_", - "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.7_win.exe" - ] + "1.0.8": { + "sha256": "", + "sig": "", + "urls": [] } } }, "Versions": { "arch": [ - "1.0.7" + "1.0.8" ], "centos7": [ - "1.0.7" + "1.0.8" ], "darwin": [ - "1.0.7" + "1.0.8" ], "debian9": [ - "1.0.7" + "1.0.8" ], "debian10": [ - "1.0.7" + "1.0.8" ], "fedora28": [ - "1.0.7" + "1.0.8" ], "fedora29": [ - "1.0.7" + "1.0.8" ], "fedora30": [ - "1.0.7" + "1.0.8" ], "linux": [ "unavailable" ], "opensuse15": [ - "1.0.7" + "1.0.8" ], "opensuse15.1": [ - "1.0.7" + "1.0.8" ], "solus": [ - "1.0.7" + "1.0.8" ], "tumbleweed": [ - "1.0.7" + "1.0.8" ], "ubuntu18.04": [ - "1.0.7" + "1.0.8" ], "ubuntu18.10": [ - "1.0.7" + "1.0.8" ], "ubuntu19.04": [ - "1.0.7" + "1.0.8" ], "unknown": [ "unavailable" ], "win32": [ - "1.0.7" + "1.0.8" ] } } From f84550b16c90be002c5e7bd70ec11f56c60c5363 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Tue, 27 Aug 2019 18:29:53 -0500 Subject: [PATCH 02/22] Update to testing branches --- src/constants.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/constants.js b/src/constants.js index 9ffe2b8..913a7ae 100644 --- a/src/constants.js +++ b/src/constants.js @@ -28,8 +28,8 @@ exports.DEV_PUBLIC_KEY = '-----BEGIN PUBLIC KEY-----\n' + '-----END PUBLIC KEY-----'; -const REPERTORY_BRANCH = 'master'; -const REPERTORY_UI_BRANCH = 'master'; +const REPERTORY_BRANCH = '1.1.0-release_branch'; +const REPERTORY_UI_BRANCH = '1.0.8_branch'; exports.RELEASES_URL = 'https://bitbucket.org/blockstorage/repertory/raw/' + REPERTORY_BRANCH + '/releases.json'; exports.UI_RELEASES_URL = 'https://bitbucket.org/blockstorage/repertory-ui/raw/' + REPERTORY_UI_BRANCH + '/releases.json'; From 2df4068e2ed52735502829ba4be41cd5f894054b Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Tue, 27 Aug 2019 20:06:54 -0500 Subject: [PATCH 03/22] Update packages --- package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 7cadff8..0d497b1 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "author": "scott.e.graves@protonmail.com", "description": "GUI for Repertory - Repertory allows you to mount Sia and/or SiaPrime blockchain storage solutions via FUSE on Linux/OS X or via WinFSP on Windows.", "dependencies": { - "@fortawesome/fontawesome-svg-core": "^1.2.19", - "@fortawesome/free-solid-svg-icons": "^5.9.0", + "@fortawesome/fontawesome-svg-core": "^1.2.22", + "@fortawesome/free-solid-svg-icons": "^5.10.2", "@fortawesome/react-fontawesome": "^0.1.4", "auto-launch": "^5.0.5", "axios": "^0.18.1", @@ -14,10 +14,10 @@ "font-awesome": "^4.7.0", "node-schedule": "^1.3.2", "randomstring": "^1.1.5", - "react": "^16.8.6", - "react-dom": "^16.8.6", + "react": "^16.9.0", + "react-dom": "^16.9.0", "react-loader-spinner": "^2.3.0", - "react-redux": "^7.1.0", + "react-redux": "^7.1.1", "react-scripts": "2.1.8", "react-tooltip": "^3.10.0", "redux": "^4.0.4", @@ -28,7 +28,7 @@ }, "devDependencies": { "cross-env": "^5.2.0", - "electron": "^4.2.8", + "electron": "^4.2.9", "electron-builder": "^20.44.4", "extract-text-webpack-plugin": "^3.0.2", "typescript": "^3.5.3", From 82000992d92f0d0b766e925a60e6ad94aed47833 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Wed, 28 Aug 2019 09:50:17 -0500 Subject: [PATCH 04/22] Additional WinFSP display names --- public/electron.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/electron.js b/public/electron.js index dd4ab76..6772291 100644 --- a/public/electron.js +++ b/public/electron.js @@ -744,7 +744,7 @@ ipcMain.on(Constants.IPC_Install_Dependency, (event, data) => { }; if (data.IsWinFSP) { helpers - .performWindowsUninstall(["WinFsp 2019.3 B1", "WinFsp 2019.3 B2"]) + .performWindowsUninstall(["WinFsp 2019.1", "WinFsp 2019.2", "WinFsp 2019.3 B1", "WinFsp 2019.3 B2"]) .then(uninstalled => { if (uninstalled) { standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, { From 3dd395584601d9fb7db93ff2916ec29b63f677fc Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Wed, 28 Aug 2019 09:50:59 -0500 Subject: [PATCH 05/22] Updated CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index eae74d1..fb75554 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## 1.0.8 +* Added additional WinFsp uninstall strings ## 1.0.7 * \#31: New installation displays 'Mount location is not set' on Windows From 0671a3980926687514657d90fb77ef311ee6ecc9 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Wed, 28 Aug 2019 13:34:11 -0500 Subject: [PATCH 06/22] #36: Add ability to select Linux distribution type if OS is unsupported - partial --- CHANGELOG.md | 1 + public/electron.js | 30 +++++++++++-------- src/App.js | 23 ++++++++++---- .../SelectAppPlatform/SelectAppPlatform.css | 11 +++++++ .../SelectAppPlatform/SelectAppPlatform.js | 27 +++++++++++++++++ src/constants.js | 6 ++++ src/redux/actions/common_actions.js | 1 + src/redux/reducers/common_reducer.js | 8 +++++ 8 files changed, 90 insertions(+), 17 deletions(-) create mode 100644 src/components/SelectAppPlatform/SelectAppPlatform.css create mode 100644 src/components/SelectAppPlatform/SelectAppPlatform.js diff --git a/CHANGELOG.md b/CHANGELOG.md index fb75554..e89cfac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## 1.0.8 +* \#36: Add ability to select Linux distribution type if OS is unsupported * Added additional WinFsp uninstall strings ## 1.0.7 diff --git a/public/electron.js b/public/electron.js index 6772291..769822f 100644 --- a/public/electron.js +++ b/public/electron.js @@ -28,6 +28,7 @@ let expectedUnmount = {}; let launchHidden = false; let firstMountCheck = true; let manualMountDetection = {}; +let platformOverride; let isShutdown = false; let isQuiting = false; @@ -244,6 +245,7 @@ const loadUiSettings = () => { if (fs.statSync(settingFile).isFile()) { const settings = JSON.parse(fs.readFileSync(settingFile, 'utf8')); launchHidden = settings.launch_hidden; + platformOverride = settings.platform_override; } } catch (e) { } @@ -659,13 +661,16 @@ ipcMain.on(Constants.IPC_Get_Platform, (event) => { const platform = os.platform(); if (platform === 'linux') { - const scriptFile = path.join(os.tmpdir(), 'repertory_detect_linux.sh'); - fs.writeFileSync(scriptFile, detectScript); + if (platformOverride && (platformOverride.trim().length > 0)) { + sendResponse(platformOverride, 'linux'); + } else { + const scriptFile = path.join(os.tmpdir(), 'repertory_detect_linux.sh'); + fs.writeFileSync(scriptFile, detectScript); - helpers + helpers .executeScript(scriptFile) .then(data => { - let appPlatform = data.replace(/(\r\n|\n|\r)/gm,""); + let appPlatform = data.replace(/(\r\n|\n|\r)/gm, ""); if (appPlatform === 'unknown') { helpers .downloadFile(Constants.LINUX_DETECT_SCRIPT_URL, scriptFile, null, err => { @@ -673,14 +678,14 @@ ipcMain.on(Constants.IPC_Get_Platform, (event) => { sendResponse(appPlatform, platform); } else { helpers - .executeScript(scriptFile) - .then(data => { - appPlatform = data.replace(/(\r\n|\n|\r)/gm, ""); - sendResponse(appPlatform, platform); - }) - .catch(() => { - sendResponse(appPlatform, platform); - }); + .executeScript(scriptFile) + .then(data => { + appPlatform = data.replace(/(\r\n|\n|\r)/gm, ""); + sendResponse(appPlatform, platform); + }) + .catch(() => { + sendResponse(appPlatform, platform); + }); } }); } else { @@ -690,6 +695,7 @@ ipcMain.on(Constants.IPC_Get_Platform, (event) => { .catch(() => { sendResponse(platform, platform); }); + } } else { sendResponse(platform, platform); } diff --git a/src/App.js b/src/App.js index b0ae7f8..c36adc6 100644 --- a/src/App.js +++ b/src/App.js @@ -14,7 +14,11 @@ import MountItems from './containers/MountItems/MountItems'; import {notifyError} from './redux/actions/error_actions'; import Reboot from './components/Reboot/Reboot'; import ReleaseVersionDisplay from './components/ReleaseVersionDisplay/ReleaseVersionDisplay'; -import {saveState} from './redux/actions/common_actions'; +import { + displaySelectAppPlatform, + saveState +} from './redux/actions/common_actions'; +import SelectAppPlatform from './components/SelectAppPlatform/SelectAppPlatform'; import Text from './components/UI/Text/Text'; import UpgradeIcon from './components/UpgradeIcon/UpgradeIcon'; import UpgradeUI from './components/UpgradeUI/UpgradeUI'; @@ -30,7 +34,11 @@ class App extends IPCContainer { componentDidMount() { const detectUpgrades = () => { if (this.props.AppPlatform === 'unknown') { - this.props.notifyError('Operating system is not supported.', true); + if (this.props.Platform === 'linux') { + this.props.displaySelectAppPlatform(true); + } else { + this.props.notifyError('Operating system is not supported.', true); + } } else { this.props.loadReleases(); } @@ -119,9 +127,12 @@ class App extends IPCContainer { const downloadDisplay = this.createModalConditionally(this.props.DownloadActive, ); const errorDisplay = this.createModalConditionally(this.props.DisplayError, , true); const upgradeDisplay = this.createModalConditionally(showUpgrade, ); + const selectAppPlatformDisplay = this.createModalConditionally(this.props.DisplaySelectAppPlatform, ); let mainContent = []; - if (this.props.AppReady) { + if (this.props.DisplaySelectAppPlatform || !this.props.AppReady) { + mainContent = + } else { let key = 0; mainContent.push((
)); } - } else { - mainContent = } return (
+ {selectAppPlatformDisplay} {errorDisplay} {dependencyDisplay} {upgradeDisplay} @@ -193,12 +203,14 @@ const mapStateToProps = state => { DismissDependencies: state.install.DismissDependencies, DisplayConfiguration: state.mounts.DisplayConfiguration, DisplayError: state.error.DisplayError, + DisplaySelectAppPlatform: state.common.DisplaySelectAppPlatform, DownloadActive: state.download.DownloadActive, InstallActive: state.install.InstallActive, InstalledVersion: state.relver.InstalledVersion, LocationsLookup: state.relver.LocationsLookup, MissingDependencies: state.install.MissingDependencies, MountsBusy: state.mounts.MountsBusy, + Platform: state.common.Platform, ProviderState: state.mounts.ProviderState, RebootRequired: state.common.RebootRequired, Release: state.relver.Release, @@ -212,6 +224,7 @@ const mapStateToProps = state => { const mapDispatchToProps = dispatch => { return { + displaySelectAppPlatform: ()=> dispatch(displaySelectAppPlatform()), loadReleases: ()=> dispatch(loadReleases()), notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)), saveState: () => dispatch(saveState()), diff --git a/src/components/SelectAppPlatform/SelectAppPlatform.css b/src/components/SelectAppPlatform/SelectAppPlatform.css new file mode 100644 index 0000000..6f13ee9 --- /dev/null +++ b/src/components/SelectAppPlatform/SelectAppPlatform.css @@ -0,0 +1,11 @@ +.SAPHeading { + color: var(--text_color_error); + text-align: center; + margin-bottom: 4px; +} + +.SAPContent { + max-height: 60vh; + overflow-y: auto; + margin-bottom: 8px; +} \ No newline at end of file diff --git a/src/components/SelectAppPlatform/SelectAppPlatform.js b/src/components/SelectAppPlatform/SelectAppPlatform.js new file mode 100644 index 0000000..6da459d --- /dev/null +++ b/src/components/SelectAppPlatform/SelectAppPlatform.js @@ -0,0 +1,27 @@ +import React from 'react'; +import './SelectAppPlatform.css'; +import * as Constants from '../../constants'; +import {connect} from 'react-redux'; +import Box from '../UI/Box/Box'; +import Button from '../UI/Button/Button'; +import DropDown from '../UI/DropDown/DropDown'; +import {rebootSystem} from '../../redux/actions/common_actions'; + +const mapDispatchToProps = dispatch => { + return { + rebootSystem: () => dispatch(rebootSystem()), + }; +}; + +export default connect(null, mapDispatchToProps)(props => { + return ( + +

Select Linux Platform

+
+

Repertory was unable to detect your Linux distribution. Please select one of the following and click 'Test' to continue:

+
+ + +
+ ); +}); \ No newline at end of file diff --git a/src/constants.js b/src/constants.js index 913a7ae..e8909cb 100644 --- a/src/constants.js +++ b/src/constants.js @@ -36,6 +36,12 @@ exports.UI_RELEASES_URL = 'https://bitbucket.org/blockstorage/repertory-ui/raw/' exports.LINUX_DETECT_SCRIPT_URL = 'https://bitbucket.org/blockstorage/repertory/raw/' + REPERTORY_BRANCH + '/detect_linux.sh'; +exports.LINUX_SELECTABLE_PLATFORMS = [ + 'ubuntu18.04', + 'ubuntu18.10', + 'ubuntu19.04' +]; + exports.DATA_LOCATIONS = { linux: '~/.local/repertory/ui', darwin: '~/Library/Application Support/repertory/ui', diff --git a/src/redux/actions/common_actions.js b/src/redux/actions/common_actions.js index 72854fb..18a3bce 100644 --- a/src/redux/actions/common_actions.js +++ b/src/redux/actions/common_actions.js @@ -4,6 +4,7 @@ import {getIPCRenderer} from '../../utils'; const ipcRenderer = getIPCRenderer(); +export const displaySelectAppPlatform = createAction('common/displaySelectAppPlatform'); export const notifyRebootRequired = createAction('common/notifyRebootRequired'); export const setAllowMount = createAction('common/setAllowMount'); diff --git a/src/redux/reducers/common_reducer.js b/src/redux/reducers/common_reducer.js index a2599bc..d1b2799 100644 --- a/src/redux/reducers/common_reducer.js +++ b/src/redux/reducers/common_reducer.js @@ -1,5 +1,6 @@ import {createReducer} from 'redux-starter-kit'; import { + displaySelectAppPlatform, notifyRebootRequired, setAllowMount, setApplicationReady, @@ -10,10 +11,17 @@ export const createCommonReducer = (platform, appPlatform, version) => { AllowMount: false, AppPlatform: appPlatform, AppReady: false, + DisplaySelectAppPlatform: false, Platform: platform, RebootRequired: false, Version: version, }, { + [displaySelectAppPlatform]: (state, action) => { + return { + ...state, + DisplaySelectAppPlatform: action.payload, + } + }, [setAllowMount]: (state, action) => { return { ...state, From 0105602a4477fc661dfb9b82f226d9b124d83ea3 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Wed, 28 Aug 2019 18:58:43 -0500 Subject: [PATCH 07/22] #36: Add ability to select Linux distribution type if OS is unsupported - partial --- public/electron.js | 9 +- src/App.js | 6 +- .../SelectAppPlatform/SelectAppPlatform.js | 27 ------ src/constants.js | 9 +- .../SelectAppPlatform/SelectAppPlatform.css | 9 +- .../SelectAppPlatform/SelectAppPlatform.js | 83 +++++++++++++++++++ src/redux/actions/common_actions.js | 24 +++++- src/redux/actions/download_actions.js | 6 +- src/redux/actions/install_actions.js | 40 +++++++++ src/redux/reducers/common_reducer.js | 11 ++- src/redux/reducers/install_reducer.js | 8 ++ 11 files changed, 194 insertions(+), 38 deletions(-) delete mode 100644 src/components/SelectAppPlatform/SelectAppPlatform.js rename src/{components => containers}/SelectAppPlatform/SelectAppPlatform.css (64%) create mode 100644 src/containers/SelectAppPlatform/SelectAppPlatform.js diff --git a/public/electron.js b/public/electron.js index 769822f..7f17196 100644 --- a/public/electron.js +++ b/public/electron.js @@ -284,6 +284,7 @@ const saveUiSettings = () => { try { fs.writeFileSync(settingFile, JSON.stringify({ launch_hidden: launchHidden, + platform_override: platformOverride, }), 'utf-8'); } catch (e) { } @@ -662,7 +663,7 @@ ipcMain.on(Constants.IPC_Get_Platform, (event) => { const platform = os.platform(); if (platform === 'linux') { if (platformOverride && (platformOverride.trim().length > 0)) { - sendResponse(platformOverride, 'linux'); + sendResponse(platformOverride.trim(), 'linux'); } else { const scriptFile = path.join(os.tmpdir(), 'repertory_detect_linux.sh'); fs.writeFileSync(scriptFile, detectScript); @@ -948,6 +949,12 @@ ipcMain.on(Constants.IPC_Set_Config_Values, (event, data) => { setConfigValue(0); }); +ipcMain.on(Constants.IPC_Set_Linux_AppPlatform, (event, data) => { + platformOverride = data.AppPlatform; + saveUiSettings(); + event.returnValue = true; +}); + ipcMain.on(Constants.IPC_Shutdown, () => { closeApplication(); }); diff --git a/src/App.js b/src/App.js index c36adc6..6f15cbe 100644 --- a/src/App.js +++ b/src/App.js @@ -18,7 +18,7 @@ import { displaySelectAppPlatform, saveState } from './redux/actions/common_actions'; -import SelectAppPlatform from './components/SelectAppPlatform/SelectAppPlatform'; +import SelectAppPlatform from './containers/SelectAppPlatform/SelectAppPlatform'; import Text from './components/UI/Text/Text'; import UpgradeIcon from './components/UpgradeIcon/UpgradeIcon'; import UpgradeUI from './components/UpgradeUI/UpgradeUI'; @@ -43,8 +43,8 @@ class App extends IPCContainer { this.props.loadReleases(); } }; - this.scheduledUpdateJob = Scheduler.scheduleJob('23 11 * * *', detectUpgrades); detectUpgrades(); + this.scheduledUpdateJob = Scheduler.scheduleJob('23 11 * * *', detectUpgrades); } componentDidUpdate(prevProps) { @@ -224,7 +224,7 @@ const mapStateToProps = state => { const mapDispatchToProps = dispatch => { return { - displaySelectAppPlatform: ()=> dispatch(displaySelectAppPlatform()), + displaySelectAppPlatform: display => dispatch(displaySelectAppPlatform(display)), loadReleases: ()=> dispatch(loadReleases()), notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)), saveState: () => dispatch(saveState()), diff --git a/src/components/SelectAppPlatform/SelectAppPlatform.js b/src/components/SelectAppPlatform/SelectAppPlatform.js deleted file mode 100644 index 6da459d..0000000 --- a/src/components/SelectAppPlatform/SelectAppPlatform.js +++ /dev/null @@ -1,27 +0,0 @@ -import React from 'react'; -import './SelectAppPlatform.css'; -import * as Constants from '../../constants'; -import {connect} from 'react-redux'; -import Box from '../UI/Box/Box'; -import Button from '../UI/Button/Button'; -import DropDown from '../UI/DropDown/DropDown'; -import {rebootSystem} from '../../redux/actions/common_actions'; - -const mapDispatchToProps = dispatch => { - return { - rebootSystem: () => dispatch(rebootSystem()), - }; -}; - -export default connect(null, mapDispatchToProps)(props => { - return ( - -

Select Linux Platform

-
-

Repertory was unable to detect your Linux distribution. Please select one of the following and click 'Test' to continue:

-
- - -
- ); -}); \ No newline at end of file diff --git a/src/constants.js b/src/constants.js index e8909cb..ddb1916 100644 --- a/src/constants.js +++ b/src/constants.js @@ -28,7 +28,8 @@ exports.DEV_PUBLIC_KEY = '-----BEGIN PUBLIC KEY-----\n' + '-----END PUBLIC KEY-----'; -const REPERTORY_BRANCH = '1.1.0-release_branch'; +//const REPERTORY_BRANCH = '1.1.0-release_branch'; +const REPERTORY_BRANCH = 'master'; const REPERTORY_UI_BRANCH = '1.0.8_branch'; exports.RELEASES_URL = 'https://bitbucket.org/blockstorage/repertory/raw/' + REPERTORY_BRANCH + '/releases.json'; @@ -68,6 +69,7 @@ exports.RELEASE_TYPES = [ exports.INSTALL_TYPES = { Dependency: 'dependency', Release: 'release', + TestRelease: 'test_release', Upgrade: 'upgrade', }; @@ -126,8 +128,13 @@ exports.IPC_Show_Window = 'show_window'; exports.IPC_Set_Config_Values = 'set_config_values'; exports.IPC_Set_Config_Values_Reply = 'set_config_values_reply'; +exports.IPC_Set_Linux_AppPlatform = 'IPC_Set_Linux_AppPlatform'; + exports.IPC_Shutdown = 'shutdown'; +exports.IPC_Test_Release = 'test_release'; +exports.IPC_Test_Release_Reply = 'test_release_reply'; + exports.IPC_Unmount_All_Drives = 'unmount_all'; exports.IPC_Unmount_All_Drives_Reply = 'unmount_all_reply'; diff --git a/src/components/SelectAppPlatform/SelectAppPlatform.css b/src/containers/SelectAppPlatform/SelectAppPlatform.css similarity index 64% rename from src/components/SelectAppPlatform/SelectAppPlatform.css rename to src/containers/SelectAppPlatform/SelectAppPlatform.css index 6f13ee9..723c7f6 100644 --- a/src/components/SelectAppPlatform/SelectAppPlatform.css +++ b/src/containers/SelectAppPlatform/SelectAppPlatform.css @@ -6,6 +6,13 @@ .SAPContent { max-height: 60vh; + width: 255px; overflow-y: auto; margin-bottom: 8px; -} \ No newline at end of file +} + +.SAPActions { + margin-top: 4px; + display: flex; + flex-direction: row; +} diff --git a/src/containers/SelectAppPlatform/SelectAppPlatform.js b/src/containers/SelectAppPlatform/SelectAppPlatform.js new file mode 100644 index 0000000..10f4f2e --- /dev/null +++ b/src/containers/SelectAppPlatform/SelectAppPlatform.js @@ -0,0 +1,83 @@ +import React from 'react'; +import IPCContainer from '../IPCContainer/IPCContainer'; +import './SelectAppPlatform.css'; +import * as Constants from '../../constants'; +import {connect} from 'react-redux'; +import Box from '../../components/UI/Box/Box'; +import Button from '../../components/UI/Button/Button'; +import {downloadItem} from '../../redux/actions/download_actions'; +import DropDown from '../../components/UI/DropDown/DropDown'; +import axios from 'axios'; +import {notifyError} from '../../redux/actions/error_actions'; +import {setInstallTestActive} from '../../redux/actions/install_actions'; + +class SelectAppPlatform extends IPCContainer { + state = { + Selected: 0, + }; + + grabLatestRelease = appPlatform => { + const errorHandler = error => { + this.props.notifyError(error); + this.props.setInstallTestActive(false); + }; + axios + .get(Constants.RELEASES_URL) + .then(response => { + try { + const releases = response.data.Versions.Release[appPlatform]; + const latestVersion = releases[releases.length - 1]; + const release = response.data.Locations[appPlatform][latestVersion]; + this.props.downloadItem(latestVersion + '.zip', Constants.INSTALL_TYPES.TestRelease, release.urls, false, latestVersion, appPlatform); + } catch (error) { + errorHandler(error); + } + }) + .catch(error => { + errorHandler(error); + }); + }; + + handleTestClicked = () => { + this.props.setInstallTestActive(true); + this.grabLatestRelease(Constants.LINUX_SELECTABLE_PLATFORMS[this.state.Selected]) + }; + + render() { + return ( + +

Select Linux Platform

+
+

Repertory was unable to detect your Linux distribution. Please select one of the following and click Test to continue:

+
+
+ this.setState({ + ...this.state, + Selected: e.target.value + })} + disabled={this.props.InstallTestActive} + items={Constants.LINUX_SELECTABLE_PLATFORMS} + selected={this.state.Selected}/> + +
+
+ ); + } +} + +const mapStateToProps = state => { + return { + InstallTestActive: state.install.InstallTestActive, + } +}; + +const mapDispatchToProps = dispatch => { + return { + downloadItem: (name, type, urls, isWinFSP, testVersion, appPlatform) => dispatch(downloadItem(name, type, urls, isWinFSP, testVersion, appPlatform)), + notifyError: msg => dispatch(notifyError(msg)), + setInstallTestActive: active => dispatch(setInstallTestActive(active)), + }; +}; + +export default connect(mapStateToProps, mapDispatchToProps)(SelectAppPlatform); \ No newline at end of file diff --git a/src/redux/actions/common_actions.js b/src/redux/actions/common_actions.js index 18a3bce..ca9ce7a 100644 --- a/src/redux/actions/common_actions.js +++ b/src/redux/actions/common_actions.js @@ -4,9 +4,17 @@ import {getIPCRenderer} from '../../utils'; const ipcRenderer = getIPCRenderer(); -export const displaySelectAppPlatform = createAction('common/displaySelectAppPlatform'); +export const displaySelectAppPlatform = display => { + return dispatch => { + if (display) { + dispatch(showWindow()); + } + + dispatch(setDisplaySelectAppPlatform(display)); + }; +}; + export const notifyRebootRequired = createAction('common/notifyRebootRequired'); -export const setAllowMount = createAction('common/setAllowMount'); export const rebootSystem = () => { return dispatch => { @@ -17,7 +25,19 @@ export const rebootSystem = () => { } }; +export const setAllowMount = createAction('common/setAllowMount'); export const setApplicationReady = createAction('common/setApplicationReady'); + +export const SET_DISPLAY_SELECT_APPPLATFORM = 'common/displaySelectAppPlatform'; +export const setDisplaySelectAppPlatform = display => { + return { + type: SET_DISPLAY_SELECT_APPPLATFORM, + payload: display, + }; +}; + +export const setLinuxAppPlatform = createAction('common/setLinuxAppPlatform'); + export const setRebootRequired = () => { return dispatch => { dispatch(showWindow()); diff --git a/src/redux/actions/download_actions.js b/src/redux/actions/download_actions.js index 2f8367e..5002fbc 100644 --- a/src/redux/actions/download_actions.js +++ b/src/redux/actions/download_actions.js @@ -3,6 +3,7 @@ import {createAction} from 'redux-starter-kit'; import {getIPCRenderer} from '../../utils'; import {notifyError} from './error_actions'; import { + installAndTestRelease, installDependency, installRelease, installUpgrade @@ -25,7 +26,7 @@ export const setDownloadBegin = (name, type, url) => { export const setDownloadEnd = createAction('download/setDownloadEnd'); export const setDownloadProgress = createAction('download/setDownloadProgress'); -export const downloadItem = (name, type, urls, isWinFSP) => { +export const downloadItem = (name, type, urls, isWinFSP, testVersion, appPlatform) => { return (dispatch, getState) => { if (!Array.isArray(urls)) { urls = [urls]; @@ -40,6 +41,9 @@ export const downloadItem = (name, type, urls, isWinFSP) => { case Constants.INSTALL_TYPES.Release: dispatch(installRelease(result.Destination)); break; + case Constants.INSTALL_TYPES.TestRelease: + dispatch(installAndTestRelease(result.Destination, testVersion, appPlatform)); + break; case Constants.INSTALL_TYPES.Upgrade: //const info = this.props.LocationsLookup[this.props.AppPlatform][this.props.VersionLookup[this.props.AppPlatform][0]]; const sha256 = null;//info.sha256; diff --git a/src/redux/actions/install_actions.js b/src/redux/actions/install_actions.js index 4c11816..1550869 100644 --- a/src/redux/actions/install_actions.js +++ b/src/redux/actions/install_actions.js @@ -7,13 +7,16 @@ import { import {notifyError} from './error_actions'; import {setAllowDownload} from './download_actions'; import { + loadReleases, setActiveRelease, setInstalledVersion, setReleaseUpgradeAvailable } from './release_version_actions'; import { + displaySelectAppPlatform, setAllowMount, setApplicationReady, + setLinuxAppPlatform, setRebootRequired, showWindow, shutdownApplication @@ -134,6 +137,42 @@ export const installDependency = (source, url, isWinFSP) => { }; }; +export const installAndTestRelease = (source, version, appPlatform) => { + return (dispatch, getState) => { + if (ipcRenderer && !getState().install.InstallTestActive) { + const extractReleaseComplete = (event, arg) => { + ipcRenderer.send(Constants.IPC_Delete_File, { + FilePath: source, + }); + + ipcRenderer.once(Constants.IPC_Test_Release_Reply, (event, arg) => { + if (arg.data.Success) { + ipcRenderer.sendSync(Constants.IPC_Set_Linux_AppPlatform, { + AppPlatform: appPlatform, + }); + dispatch(setLinuxAppPlatform(appPlatform)); + dispatch(setInstallTestActive(false)); + dispatch(displaySelectAppPlatform(false)); + dispatch(loadReleases()); + } else { + dispatch(notifyError(arg.data.Error)); + dispatch(setInstallTestActive(false)); + } + }); + ipcRenderer.send(Constants.IPC_Test_Release, { + Version: version, + }) + }; + + ipcRenderer.once(Constants.IPC_Extract_Release_Complete, extractReleaseComplete); + ipcRenderer.send(Constants.IPC_Extract_Release, { + Source: source, + Version: version, + }); + } + }; +}; + export const installRelease = source => { return (dispatch, getState) => { if (ipcRenderer && !getState().install.InstallActive) { @@ -193,5 +232,6 @@ export const installUpgrade = (source, sha256, signature, skipVerification) => { export const setDismissDependencies = createAction('install/setDismissDependencies'); export const setInstallActive = createAction('install/setInstallActive'); +export const setInstallTestActive = createAction('install/setInstallTestActive'); export const setInstallComplete = createAction('install/setInstallComplete'); export const setMissingDependencies = createAction('install/setMissingDependencies'); diff --git a/src/redux/reducers/common_reducer.js b/src/redux/reducers/common_reducer.js index d1b2799..1502396 100644 --- a/src/redux/reducers/common_reducer.js +++ b/src/redux/reducers/common_reducer.js @@ -1,9 +1,10 @@ import {createReducer} from 'redux-starter-kit'; import { - displaySelectAppPlatform, notifyRebootRequired, setAllowMount, setApplicationReady, + setLinuxAppPlatform, + SET_DISPLAY_SELECT_APPPLATFORM } from '../actions/common_actions'; export const createCommonReducer = (platform, appPlatform, version) => { @@ -16,7 +17,7 @@ export const createCommonReducer = (platform, appPlatform, version) => { RebootRequired: false, Version: version, }, { - [displaySelectAppPlatform]: (state, action) => { + [SET_DISPLAY_SELECT_APPPLATFORM]: (state, action) => { return { ...state, DisplaySelectAppPlatform: action.payload, @@ -34,6 +35,12 @@ export const createCommonReducer = (platform, appPlatform, version) => { AppReady: action.payload, }; }, + [setLinuxAppPlatform]: (state, action) => { + return { + ...state, + AppPlatform: action.payload, + } + }, [notifyRebootRequired]: (state, action) => { return { ...state, diff --git a/src/redux/reducers/install_reducer.js b/src/redux/reducers/install_reducer.js index 9237040..78c7b95 100644 --- a/src/redux/reducers/install_reducer.js +++ b/src/redux/reducers/install_reducer.js @@ -3,6 +3,7 @@ import { setDismissDependencies, setInstallActive, setInstallComplete, + setInstallTestActive, setMissingDependencies } from '../actions/install_actions'; @@ -10,6 +11,7 @@ export const installReducer = createReducer({ DismissDependencies: false, InstallActive: false, InstallResult: null, + InstallTestActive: false, InstallType: null, MissingDependencies: [], }, { @@ -35,6 +37,12 @@ export const installReducer = createReducer({ InstallType: null, } }, + [setInstallTestActive]: (state, action) => { + return { + ...state, + InstallTestActive: action.payload, + } + }, [setMissingDependencies]: (state, action) => { return { ...state, From 083b2192d7d47d96ba84dba491a0e9530d990ede Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Wed, 28 Aug 2019 21:20:30 -0500 Subject: [PATCH 08/22] #36: Add ability to select Linux distribution type if OS is unsupported --- public/electron.js | 12 ++++++++++++ .../SelectAppPlatform/SelectAppPlatform.js | 14 ++++++++++---- src/helpers.js | 17 +++++++++++++++++ src/redux/actions/download_actions.js | 3 +++ src/redux/actions/install_actions.js | 3 ++- 5 files changed, 44 insertions(+), 5 deletions(-) diff --git a/public/electron.js b/public/electron.js index 7f17196..358b646 100644 --- a/public/electron.js +++ b/public/electron.js @@ -584,6 +584,7 @@ ipcMain.on(Constants.IPC_Download_File, (event, data) => { ipcMain.on(Constants.IPC_Extract_Release, (event, data) => { const destination = path.join(helpers.getDataDirectory(), data.Version); + helpers.removeDirectoryRecursively(destination); helpers.mkDirByPathSync(destination); const stream = fs.createReadStream(data.Source); @@ -968,6 +969,17 @@ ipcMain.on(Constants.IPC_Show_Window + '_sync', event => { event.returnValue = true; }); +ipcMain.on(Constants.IPC_Test_Release, (event, data) => { + helpers + .testRepertoryBinary(data.Version) + .then(() => { + standardIPCReply(event, Constants.IPC_Test_Release_Reply, {}); + }) + .catch(error => { + standardIPCReply(event, Constants.IPC_Test_Release_Reply, {}, error); + }); +}); + ipcMain.on(Constants.IPC_Unmount_All_Drives, (event, data) => { unmountAllDrives(); standardIPCReply(event, Constants.IPC_Unmount_All_Drives_Reply); diff --git a/src/containers/SelectAppPlatform/SelectAppPlatform.js b/src/containers/SelectAppPlatform/SelectAppPlatform.js index 10f4f2e..c24e200 100644 --- a/src/containers/SelectAppPlatform/SelectAppPlatform.js +++ b/src/containers/SelectAppPlatform/SelectAppPlatform.js @@ -1,13 +1,16 @@ import React from 'react'; -import IPCContainer from '../IPCContainer/IPCContainer'; import './SelectAppPlatform.css'; -import * as Constants from '../../constants'; +import axios from 'axios'; import {connect} from 'react-redux'; +import * as Constants from '../../constants'; import Box from '../../components/UI/Box/Box'; import Button from '../../components/UI/Button/Button'; -import {downloadItem} from '../../redux/actions/download_actions'; +import { + downloadItem, + setAllowDownload +} from '../../redux/actions/download_actions'; import DropDown from '../../components/UI/DropDown/DropDown'; -import axios from 'axios'; +import IPCContainer from '../IPCContainer/IPCContainer'; import {notifyError} from '../../redux/actions/error_actions'; import {setInstallTestActive} from '../../redux/actions/install_actions'; @@ -20,6 +23,7 @@ class SelectAppPlatform extends IPCContainer { const errorHandler = error => { this.props.notifyError(error); this.props.setInstallTestActive(false); + this.props.setAllowDownload(false); }; axios .get(Constants.RELEASES_URL) @@ -40,6 +44,7 @@ class SelectAppPlatform extends IPCContainer { handleTestClicked = () => { this.props.setInstallTestActive(true); + this.props.setAllowDownload(true); this.grabLatestRelease(Constants.LINUX_SELECTABLE_PLATFORMS[this.state.Selected]) }; @@ -76,6 +81,7 @@ const mapDispatchToProps = dispatch => { return { downloadItem: (name, type, urls, isWinFSP, testVersion, appPlatform) => dispatch(downloadItem(name, type, urls, isWinFSP, testVersion, appPlatform)), notifyError: msg => dispatch(notifyError(msg)), + setAllowDownload: allow => dispatch(setAllowDownload(allow)), setInstallTestActive: active => dispatch(setInstallTestActive(active)), }; }; diff --git a/src/helpers.js b/src/helpers.js index dfb955a..c11e5c1 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -705,6 +705,23 @@ module.exports.stopMountProcessSync = (version, provider) => { process.unref(); }; +module.exports.testRepertoryBinary = version => { + return new Promise((resolve, reject) => { + const command = path.join(_getDataDirectory(), version, (os.platform() === 'win32') ? 'repertory.exe' : 'repertory'); + _executeProcess(command, ['-dc']) + .then(code => { + if (code === 0) { + resolve(); + } else { + reject(Error('Invalid exit code: ' + code)); + } + }) + .catch(error => { + reject(error); + }); + }); +}; + module.exports.verifyHash = (file, hash) => { return new Promise((resolve, reject) => { const platform = os.platform(); diff --git a/src/redux/actions/download_actions.js b/src/redux/actions/download_actions.js index 5002fbc..8d35fc8 100644 --- a/src/redux/actions/download_actions.js +++ b/src/redux/actions/download_actions.js @@ -55,6 +55,9 @@ export const downloadItem = (name, type, urls, isWinFSP, testVersion, appPlatfor break; } } else { + if (type === Constants.INSTALL_TYPES.TestRelease) { + this.props.setAllowDownload(false); + } dispatch(notifyError(result.Error)); } }; diff --git a/src/redux/actions/install_actions.js b/src/redux/actions/install_actions.js index 1550869..ae44dec 100644 --- a/src/redux/actions/install_actions.js +++ b/src/redux/actions/install_actions.js @@ -139,7 +139,7 @@ export const installDependency = (source, url, isWinFSP) => { export const installAndTestRelease = (source, version, appPlatform) => { return (dispatch, getState) => { - if (ipcRenderer && !getState().install.InstallTestActive) { + if (ipcRenderer && getState().install.InstallTestActive) { const extractReleaseComplete = (event, arg) => { ipcRenderer.send(Constants.IPC_Delete_File, { FilePath: source, @@ -153,6 +153,7 @@ export const installAndTestRelease = (source, version, appPlatform) => { dispatch(setLinuxAppPlatform(appPlatform)); dispatch(setInstallTestActive(false)); dispatch(displaySelectAppPlatform(false)); + dispatch(setAllowDownload(false)); dispatch(loadReleases()); } else { dispatch(notifyError(arg.data.Error)); From f8ec89413a35625c446f99dea35ace501c5b00de Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Thu, 29 Aug 2019 16:24:05 -0500 Subject: [PATCH 09/22] Refactoring Electron IPC --- package.json | 1 + public/electron.js | 963 ++++-------------------------- src/constants.js | 3 +- src/renderer/ipc/AppIPC.js | 20 + src/renderer/ipc/ConfigIPC.js | 56 ++ src/renderer/ipc/DaemonIPC.js | 47 ++ src/renderer/ipc/DependencyIPC.js | 102 ++++ src/renderer/ipc/DownloadIPC.js | 24 + src/renderer/ipc/FilesystemIPC.js | 31 + src/renderer/ipc/MountsIPC.js | 249 ++++++++ src/renderer/ipc/PlatformIPC.js | 79 +++ src/renderer/ipc/ReleaseIPC.js | 87 +++ src/renderer/ipc/StateIPC.js | 30 + src/renderer/ipc/SystemIPC.js | 16 + src/renderer/ipc/UpgradeIPC.js | 116 ++++ 15 files changed, 988 insertions(+), 836 deletions(-) create mode 100644 src/renderer/ipc/AppIPC.js create mode 100644 src/renderer/ipc/ConfigIPC.js create mode 100644 src/renderer/ipc/DaemonIPC.js create mode 100644 src/renderer/ipc/DependencyIPC.js create mode 100644 src/renderer/ipc/DownloadIPC.js create mode 100644 src/renderer/ipc/FilesystemIPC.js create mode 100644 src/renderer/ipc/MountsIPC.js create mode 100644 src/renderer/ipc/PlatformIPC.js create mode 100644 src/renderer/ipc/ReleaseIPC.js create mode 100644 src/renderer/ipc/StateIPC.js create mode 100644 src/renderer/ipc/SystemIPC.js create mode 100644 src/renderer/ipc/UpgradeIPC.js diff --git a/package.json b/package.json index 0d497b1..eff71cd 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "build/**/*", "node_modules/**/*", "src/helpers.js", + "src/renderer/**/*", "public/detect_linux.sh", "public/install_linux.sh" ], diff --git a/public/electron.js b/public/electron.js index 358b646..a4741d6 100644 --- a/public/electron.js +++ b/public/electron.js @@ -1,44 +1,48 @@ -// Modules to control application life and create native browser window - -const {app, BrowserWindow, Tray, nativeImage, Menu, dialog} = require('electron'); -const {ipcMain} = require('electron'); +const { + app, + BrowserWindow, + dialog, + ipcMain, + Menu, + nativeImage, + Tray +} = require('electron'); +const AutoLaunch = require('auto-launch'); const Constants = require('../src/constants'); +const fs = require('fs'); +const helpers = require('../src/helpers'); +const os = require('os'); const path = require('path'); const url = require('url'); require('electron-debug/index')(); -const os = require('os'); -const helpers = require('../src/helpers'); -const fs = require('fs'); -const unzip = require('unzipper'); -const AutoLaunch = require('auto-launch'); require.extensions['.sh'] = function (module, filename) { module.exports = fs.readFileSync(filename, 'utf8'); }; const detectScript = require('./detect_linux.sh'); -// Keep a global reference of the window object, if you don't, the window will -// be closed automatically when the JavaScript object is garbage collected. -let trayContextMenu; -let mainWindow; -let mainWindowTray; -let mountedData = {}; -let mountedLocations = []; -let expectedUnmount = {}; -let launchHidden = false; -let firstMountCheck = true; -let manualMountDetection = {}; -let platformOverride; +const AppIPC = require('../src/renderer/ipc/AppIPC'); +const ConfigIPC = require('../src/renderer/ipc/ConfigIPC'); +const DaemonIPC = require('../src/renderer/ipc/DaemonIPC'); +const DependencyIPC = require('../src/renderer/ipc/DependencyIPC'); +const DownloadIPC = require('../src/renderer/ipc/DownloadIPC'); +const FilesystemIPC = require('../src/renderer/ipc/FilesystemIPC'); +const MountsIPC = require('../src/renderer/ipc/MountsIPC'); +const PlatformIPC = require('../src/renderer/ipc/PlatformIPC'); +const ReleaseIPC = require('../src/renderer/ipc/ReleaseIPC'); +const StateIPC = require('../src/renderer/ipc/StateIPC'); +const SystemIPC = require('../src/renderer/ipc/SystemIPC'); +const UpgradeIPC = require('../src/renderer/ipc/UpgradeIPC'); let isShutdown = false; let isQuiting = false; let isInstalling = false; +let launchHidden = false; +let mainWindow; +let mainWindowTray; +let trayContextMenu; -app.on('before-quit', function () { - isQuiting = true; -}); - -function closeApplication() { +const closeApplication = () => { if (!isShutdown) { isShutdown = true; if (mainWindowTray) { @@ -46,52 +50,25 @@ function closeApplication() { } app.quit(); } -} - -function setWindowVisibility(show) { - if (show) { - mainWindow.show(); - if (os.platform() === 'darwin') { - app.dock.show(); - } - - if (mainWindow.isMinimized()) { - mainWindow.restore(); - } - mainWindow.focus(); - } else { - mainWindow.hide(); - if (os.platform() === 'darwin') { - app.dock.hide(); - } - } - - if (trayContextMenu && mainWindowTray) { - trayContextMenu.items[0].checked = show; - mainWindowTray.setContextMenu(trayContextMenu) - } -} - -const unmountAllDrives = () => { - // Reset mount states - for (const provider of Constants.PROVIDER_LIST) { - clearManualMountDetection(provider); - expectedUnmount[provider] = true; - } - - // Unmount all items - for (const i in mountedLocations) { - const data = mountedData[mountedLocations[i]]; - helpers.stopMountProcessSync(data.Version, data.Provider); - } - - mountedLocations = []; - mountedData = {}; }; -function createWindow() { +const configurePrimaryApp = () => { + app.on('second-instance', () => { + if (!isInstalling && mainWindow) { + setWindowVisibility(true); + } + }); + + app.on('ready', createWindow); + + app.on('window-all-closed', () => { + closeApplication(); + }); +}; + +const createWindow = () => { loadUiSettings(); - + let extra = {}; if (os.platform() === 'linux') { extra = { @@ -141,12 +118,12 @@ function createWindow() { // when you should delete the corresponding element. mainWindow = null; - unmountAllDrives(); + MountsIPC.unmountAllDrives(); }); const appPath = (os.platform() === 'win32') ? path.resolve(path.join(app.getAppPath(), '..\\..\\repertory-ui.exe')) : (os.platform() === 'darwin') ? path.resolve(path.join(path.dirname(app.getAppPath()), '../MacOS/repertory-ui')) : - process.env.APPIMAGE; + process.env.APPIMAGE; const autoLauncher = new AutoLaunch({ name: 'Repertory UI', @@ -193,50 +170,21 @@ function createWindow() { mainWindowTray = new Tray(image); autoLauncher - .isEnabled() - .then((enabled) => { - trayContextMenu.items[1].checked = enabled; - mainWindowTray.setToolTip('Repertory UI'); - mainWindowTray.setContextMenu(trayContextMenu) - }) - .catch(() => { - closeApplication(); - }); - - mainWindow.loadURL(startUrl); -} - -let instanceLock = app.requestSingleInstanceLock(); -const configurePrimaryApp = () => { - app.on('second-instance', () => { - if (!isInstalling && mainWindow) { - setWindowVisibility(true); - } - }); - - app.on('ready', createWindow); - - app.on('window-all-closed', () => { + .isEnabled() + .then((enabled) => { + trayContextMenu.items[1].checked = enabled; + mainWindowTray.setToolTip('Repertory UI'); + mainWindowTray.setContextMenu(trayContextMenu) + }) + .catch(() => { closeApplication(); }); -}; -if (!instanceLock) { - setTimeout(() => { - if ((instanceLock = app.requestSingleInstanceLock())) { - configurePrimaryApp(); - } else { - closeApplication(); - } - }, 3000); -} else { - configurePrimaryApp(); -} -const clearManualMountDetection = (provider) => { - if (manualMountDetection[provider]) { - clearInterval(manualMountDetection[provider]); - delete manualMountDetection[provider]; - } + mainWindow.loadURL(startUrl); +}; + +const getMainWindow = () => { + return mainWindow; }; const loadUiSettings = () => { @@ -245,51 +193,61 @@ const loadUiSettings = () => { if (fs.statSync(settingFile).isFile()) { const settings = JSON.parse(fs.readFileSync(settingFile, 'utf8')); launchHidden = settings.launch_hidden; - platformOverride = settings.platform_override; + PlatformIPC.setPlatformOverride(settings.platform_override); } } catch (e) { } }; -const monitorMount = (sender, provider, version, pid, location) => { - manualMountDetection[provider] = setInterval(() => { - helpers - .detectRepertoryMounts(version) - .then(result => { - if (result[provider].PID !== pid) { - if (result[provider].PID === -1) { - clearManualMountDetection(provider); - sender.send(Constants.IPC_Unmount_Drive_Reply, { - data: { - Expected: expectedUnmount[provider], - Location: location, - Provider: provider, - Error: Error(provider + ' Unmounted').toString(), - Success: false, - } - }); - } else { - pid = result[provider].PID; - } - } - }) - .catch(e => { - console.log(e); - }); - },6000); -}; - const saveUiSettings = () => { const settingFile = path.join(helpers.getDataDirectory(), 'ui.json'); try { fs.writeFileSync(settingFile, JSON.stringify({ launch_hidden: launchHidden, - platform_override: platformOverride, + platform_override: PlatformIPC.getPlatformOverride(), }), 'utf-8'); } catch (e) { } }; +const setIsInstalling = installing => { + isInstalling = installing; +}; + +const setTrayImage = driveInUse => { + let image; + if (driveInUse) { + image = nativeImage.createFromPath(path.join(__dirname, os.platform() === 'darwin' ? '../build/logo_both_mac.png' : '../build/logo_both.png')); + } else { + image = nativeImage.createFromPath(path.join(__dirname, os.platform() === 'darwin' ? '../build/logo_mac.png' : '../build/logo.png')); + } + mainWindowTray.setImage(image); +}; + +const setWindowVisibility = show => { + if (show) { + mainWindow.show(); + if (os.platform() === 'darwin') { + app.dock.show(); + } + + if (mainWindow.isMinimized()) { + mainWindow.restore(); + } + mainWindow.focus(); + } else { + mainWindow.hide(); + if (os.platform() === 'darwin') { + app.dock.hide(); + } + } + + if (trayContextMenu && mainWindowTray) { + trayContextMenu.items[0].checked = show; + mainWindowTray.setContextMenu(trayContextMenu) + } +}; + const standardIPCReply = (event, channel, data, error) => { if (mainWindow) { event.sender.send(channel, { @@ -302,699 +260,36 @@ const standardIPCReply = (event, channel, data, error) => { } }; -ipcMain.on(Constants.IPC_Browse_Directory + '_sync', (event, data) => { - dialog.showOpenDialog(mainWindow, { - defaultPath: data.Location, - properties: ['openDirectory'], - title: data.Title, - }, (filePaths) => { - if (filePaths && (filePaths.length > 0)) { - event.returnValue = filePaths[0]; + + + +app.on('before-quit', function () { + isQuiting = true; +}); + +let instanceLock = app.requestSingleInstanceLock(); +if (!instanceLock) { + setTimeout(() => { + if ((instanceLock = app.requestSingleInstanceLock())) { + configurePrimaryApp(); } else { - event.returnValue = ''; + closeApplication(); } - }); -}); + }, 3000); +} else { + configurePrimaryApp(); +} -ipcMain.on(Constants.IPC_Check_Daemon_Version, (event, data) => { - helpers - .checkDaemonVersion(data.Version, data.Provider) - .then(code => { - standardIPCReply(event, Constants.IPC_Check_Daemon_Version_Reply, { - Valid: (code === 0), - Code: code, - }); - }) - .catch(e => { - standardIPCReply(event, Constants.IPC_Check_Daemon_Version_Reply, { - Valid: false, - }, e); - }); -}); -ipcMain.on(Constants.IPC_Check_Daemon_Version + '_sync', (event, data) => { - helpers - .checkDaemonVersion(data.Version, data.Provider) - .then(code => { - event.returnValue = { - data: { - Success: true, - Valid: (code === 0), - Code: code, - }, - }; - }) - .catch(e => { - event.returnValue = { - data: { - Error: e.toString(), - Success: false, - Valid: false - }, - }; - }); -}); - -ipcMain.on(Constants.IPC_Check_Dependency_Installed, (event, data) => { - try { - const exists = fs.lstatSync(data.File).isFile(); - standardIPCReply(event, Constants.IPC_Check_Dependency_Installed_Reply, { - data: { - Exists: exists, - }, - }); - } catch (e) { - standardIPCReply(event, Constants.IPC_Check_Dependency_Installed_Reply, { - data : { - Exists: false, - }, - }); - } -}); - -ipcMain.on(Constants.IPC_Check_Dependency_Installed + '_sync', (event, data) => { - try { - const ls = fs.lstatSync(data.File); - event.returnValue = { - data: { - Exists: ls.isFile() || ls.isSymbolicLink(), - }, - }; - } catch (e) { - event.returnValue = { - data: { - Exists: false - }, - }; - } -}); - -ipcMain.on(Constants.IPC_Check_Installed, (event, data) => { - const destination = path.join(helpers.getDataDirectory(), data.Version); - helpers - .getMissingDependencies(data.Dependencies) - .then((dependencies) => { - let exists = false; - try { - exists = fs.existsSync(destination) && fs.lstatSync(destination).isDirectory(); - } catch (e) { - } - standardIPCReply(event, Constants.IPC_Check_Installed_Reply, { - Dependencies: dependencies, - Exists: exists, - Version: data.Version, - }); - }).catch(error => { - standardIPCReply(event, Constants.IPC_Check_Installed_Reply, { - Dependencies: [], - Version: data.Version, - }, error); - }); -}); - -ipcMain.on(Constants.IPC_Check_Mount_Location + '_sync', (event, data) => { - let response = { - Success: true, - Error: '' - }; - - try { - if (fs.existsSync(data.Location) && fs.statSync(data.Location).isDirectory()) { - if (fs.readdirSync(data.Location).length !== 0) { - response.Success = false; - response.Error = 'Directory not empty: ' + data.Location; - } - } else { - response.Success = false; - response.Error = 'Directory not found: ' + data.Location; - } - } catch (e) { - response.Success = false; - response.Error = e.toString(); - } - event.returnValue = response; -}); - -ipcMain.on(Constants.IPC_Delete_File, (event, data) => { - try { - if (fs.existsSync(data.FilePath)) { - fs.unlinkSync(data.FilePath); - } - } catch (e) { - } -}); - -ipcMain.on(Constants.IPC_Delete_File + '_sync', (event, data) => { - try { - if (fs.existsSync(data.FilePath)) { - fs.unlinkSync(data.FilePath); - } - event.returnValue = { - data: true, - }; - } catch (e) { - event.returnValue = { - data: false, - }; - } -}); - -ipcMain.on(Constants.IPC_Detect_Mounts, (event, data) => { - let driveLetters = {}; - for (const provider of Constants.PROVIDER_LIST) { - driveLetters[provider] = []; - } - - const grabDriveLetters = (locations) => { - for (let i = 'c'.charCodeAt(0); i <= 'z'.charCodeAt(0); i++) { - const drive = (String.fromCharCode(i) + ':').toUpperCase(); - let driveInUse; - if (Object.keys(locations).length > 0) { - for (const provider of Constants.PROVIDER_LIST) { - driveInUse = locations[provider].startsWith(drive); - if (driveInUse) - break; - } - } - if (!driveInUse) { - try { - if (!fs.existsSync(drive)) { - for (const provider of Constants.PROVIDER_LIST) { - driveLetters[provider].push(drive); - } - } - } catch (e) { - } - } - } - - if (Object.keys(locations).length > 0) { - for (const provider of Constants.PROVIDER_LIST) { - if (locations[provider].length > 0) { - if (!driveLetters[provider].find((driveLetter) => { - return driveLetter === locations[provider]; - })) { - driveLetters[provider].push(locations[provider]); - } - } - } - } - }; - - const setImage = (locations) => { - let driveInUse; - if (Object.keys(locations).length > 0) { - for (const provider of Constants.PROVIDER_LIST) { - driveInUse = locations[provider].length > 0; - if (driveInUse) - break; - } - } - - let image; - if (driveInUse) { - image = nativeImage.createFromPath(path.join(__dirname, os.platform() === 'darwin' ? '../build/logo_both_mac.png' : '../build/logo_both.png')); - } else { - image = nativeImage.createFromPath(path.join(__dirname, os.platform() === 'darwin' ? '../build/logo_mac.png' : '../build/logo.png')); - } - - mainWindowTray.setImage(image); - }; - - helpers - .detectRepertoryMounts(data.Version) - .then((results) => { - let storageData = {}; - let locations = {}; - for (const provider of Constants.PROVIDER_LIST) { - storageData[provider] = results[provider] ? results[provider] : { - Active: false, - Location: '', - PID: -1, - }; - locations[provider] = storageData[provider].Location; - - if (storageData[provider].PID !== -1) { - expectedUnmount[provider] = false; - if (firstMountCheck) { - monitorMount(event.sender, provider, data.Version, storageData[provider].PID, storageData[provider].Location); - } - } - } - - if (os.platform() === 'win32') { - grabDriveLetters(locations); - } - - setImage(locations); - if (firstMountCheck) { - firstMountCheck = false; - } - standardIPCReply(event, Constants.IPC_Detect_Mounts_Reply, { - DriveLetters: driveLetters, - Locations: locations, - }); - }) - .catch(error => { - if (os.platform() === 'win32') { - grabDriveLetters({}); - } - setImage({}); - standardIPCReply(event, Constants.IPC_Detect_Mounts_Reply, { - DriveLetters: driveLetters, - }, error); - }); -}); - -ipcMain.on(Constants.IPC_Download_File, (event, data) => { - const destination = path.join(helpers.getDataDirectory(), data.Filename); - helpers.downloadFile(data.URL, destination, (progress) => { - standardIPCReply(event, Constants.IPC_Download_File_Progress, { - Destination: destination, - Progress: progress, - URL: data.URL, - }); - }, error => { - standardIPCReply(event, Constants.IPC_Download_File_Complete, { - Destination: destination, - URL: data.URL, - }, error); - }); -}); - -ipcMain.on(Constants.IPC_Extract_Release, (event, data) => { - const destination = path.join(helpers.getDataDirectory(), data.Version); - helpers.removeDirectoryRecursively(destination); - helpers.mkDirByPathSync(destination); - - const stream = fs.createReadStream(data.Source); - stream - .pipe(unzip.Extract({ path: destination })) - .on('error', error => { - try { - helpers.removeDirectoryRecursively(destination); - } catch (e) { - } - stream.close(); - standardIPCReply(event, Constants.IPC_Extract_Release_Complete, { - Source: data.Source, - }, error); - }) - .on('finish', () => { - stream.close(); - if (os.platform() !== 'win32') { - helpers - .executeAndWait("chmod +x \"" + path.join(destination, 'repertory') + "\"") - .then(() => { - standardIPCReply(event, Constants.IPC_Extract_Release_Complete, { - Source: data.Source, - }); - }) - .catch(error => { - standardIPCReply(event, Constants.IPC_Extract_Release_Complete, { - Source: data.Source, - }, error); - }) - } else { - standardIPCReply(event, Constants.IPC_Extract_Release_Complete, { - Source: data.Source, - }); - } - }); -}); - -ipcMain.on(Constants.IPC_Get_Config, (event, data) => { - helpers - .getConfig(data.Version, data.Provider) - .then((data) => { - if (data.Code === 0) { - standardIPCReply(event, Constants.IPC_Get_Config_Reply, { - Config: data.Data, - }); - } else { - standardIPCReply(event, Constants.IPC_Get_Config_Reply, {}, data.Code); - } - }) - .catch(error => { - standardIPCReply(event, Constants.IPC_Get_Config_Reply, {}, error); - }); -}); - -ipcMain.on(Constants.IPC_Get_Config_Template, (event, data) => { - helpers - .getConfigTemplate(data.Version, data.Provider) - .then((data) => { - standardIPCReply(event, Constants.IPC_Get_Config_Template_Reply, { - Template: data, - }); - }) - .catch(error => { - standardIPCReply(event, Constants.IPC_Get_Config_Template_Reply, {}, error); - }); -}); - -ipcMain.on(Constants.IPC_Get_Platform, (event) => { - const sendResponse = (appPlatform, platform) => { - event.sender.send(Constants.IPC_Get_Platform_Reply, { - AppPlatform: appPlatform, - Platform: platform, - }); - }; - - const platform = os.platform(); - if (platform === 'linux') { - if (platformOverride && (platformOverride.trim().length > 0)) { - sendResponse(platformOverride.trim(), 'linux'); - } else { - const scriptFile = path.join(os.tmpdir(), 'repertory_detect_linux.sh'); - fs.writeFileSync(scriptFile, detectScript); - - helpers - .executeScript(scriptFile) - .then(data => { - let appPlatform = data.replace(/(\r\n|\n|\r)/gm, ""); - if (appPlatform === 'unknown') { - helpers - .downloadFile(Constants.LINUX_DETECT_SCRIPT_URL, scriptFile, null, err => { - if (err) { - sendResponse(appPlatform, platform); - } else { - helpers - .executeScript(scriptFile) - .then(data => { - appPlatform = data.replace(/(\r\n|\n|\r)/gm, ""); - sendResponse(appPlatform, platform); - }) - .catch(() => { - sendResponse(appPlatform, platform); - }); - } - }); - } else { - sendResponse(appPlatform, platform); - } - }) - .catch(() => { - sendResponse(platform, platform); - }); - } - } else { - sendResponse(platform, platform); - } -}); - -ipcMain.on(Constants.IPC_Get_State, event => { - helpers.mkDirByPathSync(helpers.getDataDirectory()); - const configFile = path.join(helpers.getDataDirectory(), 'settings.json'); - if (fs.existsSync(configFile)) { - event.sender.send(Constants.IPC_Get_State_Reply, { - data: JSON.parse(fs.readFileSync(configFile, 'utf8')), - }); - } else { - event.sender.send(Constants.IPC_Get_State_Reply, { - data: null, - }); - } -}); - -ipcMain.on(Constants.IPC_Install_Dependency, (event, data) => { - if (data.Source.toLowerCase().endsWith('.dmg')) { - helpers - .executeAsync('open', ['-a', 'Finder', '-W', data.Source]) - .then(() => { - standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, { - Source: data.Source, - URL: data.URL, - }); - }) - .catch(error=> { - standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, { - Source: data.Source, - URL: data.URL, - }, error); - }); - } else { - const execInstall = () => { - helpers - .executeAndWait(data.Source) - .then(() => { - standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, { - Source: data.Source, - URL: data.URL, - }); - }) - .catch(error => { - standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, { - Source: data.Source, - URL: data.URL, - }, error); - }); - }; - if (data.IsWinFSP) { - helpers - .performWindowsUninstall(["WinFsp 2019.1", "WinFsp 2019.2", "WinFsp 2019.3 B1", "WinFsp 2019.3 B2"]) - .then(uninstalled => { - if (uninstalled) { - standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, { - RebootRequired: true, - Source: data.Source, - URL: data.URL, - }); - } else { - execInstall(); - } - }) - .catch(error => { - standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, { - Source: data.Source, - URL: data.URL, - }, error); - }); - } else { - execInstall(); - } - } -}); - -ipcMain.on(Constants.IPC_Install_Upgrade, (event, data) => { - let allowSkipVerification = true; - - unmountAllDrives(); - - let tempSig; - let tempPub; - const cleanupFiles = () => { - try { - if (tempSig) { - fs.unlinkSync(tempSig); - } - if (tempPub) { - fs.unlinkSync(tempPub); - } - } catch (e) { - } - }; - - const errorHandler = err => { - cleanupFiles(); - standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, { - AllowSkipVerification: allowSkipVerification, - Source: data.Source, - }, err); - }; - - // TODO Enable verification in 1.0.4 - const hasSignature = false;//!data.SkipVerification && data.Signature && (data.Signature.length > 0); - const hasHash = false;//!data.SkipVerification && data.Sha256 && (data.Sha256.length > 0); - if (hasSignature) { - try { - const files = helpers.createSignatureFiles(data.Signature, Constants.DEV_PUBLIC_KEY); - tempPub = files.PublicKeyFile; - tempSig = files.SignatureFile; - } catch (e) { - errorHandler(e); - return; - } - } - - let command; - let args; - const platform = os.platform(); - if (platform === 'win32') { - command = data.Source; - } else if (platform === 'darwin') { - command = 'open'; - args = ['-a', 'Finder', data.Source]; - } else if (platform === 'linux') { - try { - command = data.Source; - fs.chmodSync(command, '750'); - } catch (e) { - errorHandler(e); - } - } else { - errorHandler(Error('Platform not supported: ' + os.platform())); - } - - if (command) { - const executeInstall = () => { - isInstalling = true; - helpers - .executeAsync(command, args) - .then(() => { - cleanupFiles(); - standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply) - }) - .catch(error => { - isInstalling = false; - errorHandler(error); - }); - }; - - if (hasSignature) { - helpers - .verifySignature(data.Source, tempSig, tempPub) - .then(() => { - executeInstall(); - }) - .catch(() => { - errorHandler(Error('Failed to verify installation package signature')); - }); - } else if (hasHash) { - helpers - .verifyHash(data.Source, data.Sha256) - .then(()=> { - executeInstall(); - }) - .catch(() => { - errorHandler(Error('Failed to verify installation package hash')); - }); - } else { - if (platform === 'darwin') { - setTimeout(executeInstall, 3000); - } else { - executeInstall(); - } - } - } else { - errorHandler(Error('Unsupported upgrade: ' + data.Source)); - } -}); - -ipcMain.on(Constants.IPC_Mount_Drive, (event, data) => { - expectedUnmount[data.Provider] = false; - - if (mountedLocations.indexOf(data.Location) !== -1) { - console.log(data.Provider + ' already mounted: ' + data.Location); - } else { - mountedLocations.push(data.Location); - mountedData[data.Location] = { - Version: data.Version, - Provider: data.Provider, - }; - const errorHandler = (pid, error) => { - if (mountedLocations.indexOf(data.Location) !== -1) { - mountedLocations.splice(mountedLocations.indexOf(data.Location), 1); - delete mountedData[data.Location]; - } - - standardIPCReply(event, Constants.IPC_Unmount_Drive_Reply, { - Expected: expectedUnmount[data.Provider], - Location: data.Location, - Provider: data.Provider, - }, error || Error(data.Provider + ' Unmounted')); - }; - helpers - .executeMount(data.Version, data.Provider, data.Location, data.NoConsoleSupported, (error, pid) => { - errorHandler(pid, error); - }) - .then(() => { - standardIPCReply(event, Constants.IPC_Mount_Drive_Reply, { - Provider: data.Provider, - }); - }) - .catch(error => { - errorHandler(-1, error); - }); - } -}); - -ipcMain.on(Constants.IPC_Reboot_System, () => { - if (os.platform() === 'win32') { - helpers.executeAsync('shutdown.exe', ['/r', '/t', '30']); - } - closeApplication(); -}); - -ipcMain.on(Constants.IPC_Save_State, (event, data) => { - helpers.mkDirByPathSync(helpers.getDataDirectory()); - const configFile = path.join(helpers.getDataDirectory(), 'settings.json'); - fs.writeFileSync(configFile, JSON.stringify(data.State), 'utf8'); -}); - -ipcMain.on(Constants.IPC_Set_Config_Values, (event, data) => { - const setConfigValue = (i) => { - if (i < data.Items.length) { - helpers - .setConfigValue(data.Items[i].Name, data.Items[i].Value, data.Provider, data.Version) - .then(() => { - setConfigValue(++i); - }) - .catch(() => { - setConfigValue(++i); - }); - } else { - standardIPCReply(event, Constants.IPC_Set_Config_Values_Reply, {}); - } - }; - setConfigValue(0); -}); - -ipcMain.on(Constants.IPC_Set_Linux_AppPlatform, (event, data) => { - platformOverride = data.AppPlatform; - saveUiSettings(); - event.returnValue = true; -}); - -ipcMain.on(Constants.IPC_Shutdown, () => { - closeApplication(); -}); - -ipcMain.on(Constants.IPC_Show_Window, () => { - setWindowVisibility(true); -}); - -ipcMain.on(Constants.IPC_Show_Window + '_sync', event => { - setWindowVisibility(true); - event.returnValue = true; -}); - -ipcMain.on(Constants.IPC_Test_Release, (event, data) => { - helpers - .testRepertoryBinary(data.Version) - .then(() => { - standardIPCReply(event, Constants.IPC_Test_Release_Reply, {}); - }) - .catch(error => { - standardIPCReply(event, Constants.IPC_Test_Release_Reply, {}, error); - }); -}); - -ipcMain.on(Constants.IPC_Unmount_All_Drives, (event, data) => { - unmountAllDrives(); - standardIPCReply(event, Constants.IPC_Unmount_All_Drives_Reply); -}); - -ipcMain.on(Constants.IPC_Unmount_Drive, (event, data) => { - clearManualMountDetection(data.Provider); - - expectedUnmount[data.Provider] = true; - helpers - .stopMountProcess(data.Version, data.Provider) - .then(result => { - console.log(result); - }) - .catch(e => { - console.log(e); - }); -}); +AppIPC.addListeners(ipcMain, closeApplication, setWindowVisibility); +ConfigIPC.addListeners(ipcMain, standardIPCReply); +DaemonIPC.addListeners(ipcMain, standardIPCReply); +DependencyIPC.addListeners(ipcMain, standardIPCReply); +DownloadIPC.addListeners(ipcMain, standardIPCReply); +FilesystemIPC.addListeners(ipcMain, getMainWindow, dialog); +MountsIPC.addListeners(ipcMain, setTrayImage, standardIPCReply); +PlatformIPC.addListeners(ipcMain, detectScript, saveUiSettings); +ReleaseIPC.addListeners(ipcMain, standardIPCReply); +StateIPC.addListeners(ipcMain); +SystemIPC.addListeners(ipcMain, closeApplication); +UpgradeIPC.addListeners(ipcMain, setIsInstalling, MountsIPC.unmountAllDrives, standardIPCReply); \ No newline at end of file diff --git a/src/constants.js b/src/constants.js index ddb1916..a74beef 100644 --- a/src/constants.js +++ b/src/constants.js @@ -28,8 +28,7 @@ exports.DEV_PUBLIC_KEY = '-----BEGIN PUBLIC KEY-----\n' + '-----END PUBLIC KEY-----'; -//const REPERTORY_BRANCH = '1.1.0-release_branch'; -const REPERTORY_BRANCH = 'master'; +const REPERTORY_BRANCH = '1.1.0-release_branch'; const REPERTORY_UI_BRANCH = '1.0.8_branch'; exports.RELEASES_URL = 'https://bitbucket.org/blockstorage/repertory/raw/' + REPERTORY_BRANCH + '/releases.json'; diff --git a/src/renderer/ipc/AppIPC.js b/src/renderer/ipc/AppIPC.js new file mode 100644 index 0000000..4fdd3da --- /dev/null +++ b/src/renderer/ipc/AppIPC.js @@ -0,0 +1,20 @@ +const Constants = require('../../constants'); + +const addListeners = (ipcMain, closeApplication, setWindowVisibility) => { + ipcMain.on(Constants.IPC_Shutdown, () => { + closeApplication(); + }); + + ipcMain.on(Constants.IPC_Show_Window, () => { + setWindowVisibility(true); + }); + + ipcMain.on(Constants.IPC_Show_Window + '_sync', event => { + setWindowVisibility(true); + event.returnValue = true; + }); +}; + +module.exports = { + addListeners +}; \ No newline at end of file diff --git a/src/renderer/ipc/ConfigIPC.js b/src/renderer/ipc/ConfigIPC.js new file mode 100644 index 0000000..6f15ba0 --- /dev/null +++ b/src/renderer/ipc/ConfigIPC.js @@ -0,0 +1,56 @@ +const Constants = require('../../constants'); +const helpers = require('../../helpers'); + +const addListeners = (ipcMain, standardIPCReply) => { + ipcMain.on(Constants.IPC_Get_Config, (event, data) => { + helpers + .getConfig(data.Version, data.Provider) + .then((data) => { + if (data.Code === 0) { + standardIPCReply(event, Constants.IPC_Get_Config_Reply, { + Config: data.Data, + }); + } else { + standardIPCReply(event, Constants.IPC_Get_Config_Reply, {}, data.Code); + } + }) + .catch(error => { + standardIPCReply(event, Constants.IPC_Get_Config_Reply, {}, error); + }); + }); + + ipcMain.on(Constants.IPC_Get_Config_Template, (event, data) => { + helpers + .getConfigTemplate(data.Version, data.Provider) + .then((data) => { + standardIPCReply(event, Constants.IPC_Get_Config_Template_Reply, { + Template: data, + }); + }) + .catch(error => { + standardIPCReply(event, Constants.IPC_Get_Config_Template_Reply, {}, error); + }); + }); + + ipcMain.on(Constants.IPC_Set_Config_Values, (event, data) => { + const setConfigValue = (i) => { + if (i < data.Items.length) { + helpers + .setConfigValue(data.Items[i].Name, data.Items[i].Value, data.Provider, data.Version) + .then(() => { + setConfigValue(++i); + }) + .catch(() => { + setConfigValue(++i); + }); + } else { + standardIPCReply(event, Constants.IPC_Set_Config_Values_Reply, {}); + } + }; + setConfigValue(0); + }); +}; + +module.exports = { + addListeners +}; \ No newline at end of file diff --git a/src/renderer/ipc/DaemonIPC.js b/src/renderer/ipc/DaemonIPC.js new file mode 100644 index 0000000..c563c1c --- /dev/null +++ b/src/renderer/ipc/DaemonIPC.js @@ -0,0 +1,47 @@ +const Constants = require('../../constants'); +const helpers = require('../../helpers'); + +const addListeners = (ipcMain, standardIPCReply) => { + ipcMain.on(Constants.IPC_Check_Daemon_Version, (event, data) => { + helpers + .checkDaemonVersion(data.Version, data.Provider) + .then(code => { + standardIPCReply(event, Constants.IPC_Check_Daemon_Version_Reply, { + Valid: (code === 0), + Code: code, + }); + }) + .catch(e => { + standardIPCReply(event, Constants.IPC_Check_Daemon_Version_Reply, { + Valid: false, + }, e); + }); + }); + + ipcMain.on(Constants.IPC_Check_Daemon_Version + '_sync', (event, data) => { + helpers + .checkDaemonVersion(data.Version, data.Provider) + .then(code => { + event.returnValue = { + data: { + Success: true, + Valid: (code === 0), + Code: code, + }, + }; + }) + .catch(e => { + event.returnValue = { + data: { + Error: e.toString(), + Success: false, + Valid: false + }, + }; + }); + }); +}; + +module.exports = { + addListeners +}; \ No newline at end of file diff --git a/src/renderer/ipc/DependencyIPC.js b/src/renderer/ipc/DependencyIPC.js new file mode 100644 index 0000000..6e884f7 --- /dev/null +++ b/src/renderer/ipc/DependencyIPC.js @@ -0,0 +1,102 @@ +const Constants = require('../../constants'); +const fs = require('fs'); +const helpers = require('../../helpers'); + +const addListeners = (ipcMain, standardIPCReply) => { + ipcMain.on(Constants.IPC_Check_Dependency_Installed, (event, data) => { + try { + const exists = fs.lstatSync(data.File).isFile(); + standardIPCReply(event, Constants.IPC_Check_Dependency_Installed_Reply, { + data: { + Exists: exists, + }, + }); + } catch (e) { + standardIPCReply(event, Constants.IPC_Check_Dependency_Installed_Reply, { + data : { + Exists: false, + }, + }); + } + }); + + ipcMain.on(Constants.IPC_Check_Dependency_Installed + '_sync', (event, data) => { + try { + const ls = fs.lstatSync(data.File); + event.returnValue = { + data: { + Exists: ls.isFile() || ls.isSymbolicLink(), + }, + }; + } catch (e) { + event.returnValue = { + data: { + Exists: false + }, + }; + } + }); + + ipcMain.on(Constants.IPC_Install_Dependency, (event, data) => { + if (data.Source.toLowerCase().endsWith('.dmg')) { + helpers + .executeAsync('open', ['-a', 'Finder', '-W', data.Source]) + .then(() => { + standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, { + Source: data.Source, + URL: data.URL, + }); + }) + .catch(error=> { + standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, { + Source: data.Source, + URL: data.URL, + }, error); + }); + } else { + const execInstall = () => { + helpers + .executeAndWait(data.Source) + .then(() => { + standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, { + Source: data.Source, + URL: data.URL, + }); + }) + .catch(error => { + standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, { + Source: data.Source, + URL: data.URL, + }, error); + }); + }; + if (data.IsWinFSP) { + helpers + .performWindowsUninstall(["WinFsp 2019.1", "WinFsp 2019.2", "WinFsp 2019.3 B1", "WinFsp 2019.3 B2"]) + .then(uninstalled => { + if (uninstalled) { + standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, { + RebootRequired: true, + Source: data.Source, + URL: data.URL, + }); + } else { + execInstall(); + } + }) + .catch(error => { + standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, { + Source: data.Source, + URL: data.URL, + }, error); + }); + } else { + execInstall(); + } + } + }); +}; + +module.exports = { + addListeners +}; \ No newline at end of file diff --git a/src/renderer/ipc/DownloadIPC.js b/src/renderer/ipc/DownloadIPC.js new file mode 100644 index 0000000..30b407e --- /dev/null +++ b/src/renderer/ipc/DownloadIPC.js @@ -0,0 +1,24 @@ +const Constants = require('../../constants'); +const helpers = require('../../helpers'); + +const addListeners = (ipcMain, standardIPCReply) => { + ipcMain.on(Constants.IPC_Download_File, (event, data) => { + const destination = path.join(helpers.getDataDirectory(), data.Filename); + helpers.downloadFile(data.URL, destination, (progress) => { + standardIPCReply(event, Constants.IPC_Download_File_Progress, { + Destination: destination, + Progress: progress, + URL: data.URL, + }); + }, error => { + standardIPCReply(event, Constants.IPC_Download_File_Complete, { + Destination: destination, + URL: data.URL, + }, error); + }); + }); +}; + +module.exports = { + addListeners +}; \ No newline at end of file diff --git a/src/renderer/ipc/FilesystemIPC.js b/src/renderer/ipc/FilesystemIPC.js new file mode 100644 index 0000000..1294e76 --- /dev/null +++ b/src/renderer/ipc/FilesystemIPC.js @@ -0,0 +1,31 @@ +const Constants = require('../../constants'); +const fs = require('fs'); + +const addListeners = (ipcMain, getMainWindow, dialog) => { + ipcMain.on(Constants.IPC_Browse_Directory + '_sync', (event, data) => { + dialog.showOpenDialog(getMainWindow(), { + defaultPath: data.Location, + properties: ['openDirectory'], + title: data.Title, + }, (filePaths) => { + if (filePaths && (filePaths.length > 0)) { + event.returnValue = filePaths[0]; + } else { + event.returnValue = ''; + } + }); + }); + + ipcMain.on(Constants.IPC_Delete_File, (event, data) => { + try { + if (fs.existsSync(data.FilePath)) { + fs.unlinkSync(data.FilePath); + } + } catch (e) { + } + }); +}; + +module.exports = { + addListeners +}; \ No newline at end of file diff --git a/src/renderer/ipc/MountsIPC.js b/src/renderer/ipc/MountsIPC.js new file mode 100644 index 0000000..28add62 --- /dev/null +++ b/src/renderer/ipc/MountsIPC.js @@ -0,0 +1,249 @@ +const Constants = require('../../constants'); +const fs = require('fs'); +const helpers = require('../../helpers'); +const os = require('os'); + +let expectedUnmount = {}; +let firstMountCheck = true; +let manualMountDetection = {}; +let mountedData = {}; +let mountedLocations = []; + +const clearManualMountDetection = provider => { + if (manualMountDetection[provider]) { + clearInterval(manualMountDetection[provider]); + delete manualMountDetection[provider]; + } +}; + +const monitorMount = (sender, provider, version, pid, location) => { + manualMountDetection[provider] = setInterval(() => { + helpers + .detectRepertoryMounts(version) + .then(result => { + if (result[provider].PID !== pid) { + if (result[provider].PID === -1) { + clearManualMountDetection(provider); + sender.send(Constants.IPC_Unmount_Drive_Reply, { + data: { + Expected: expectedUnmount[provider], + Location: location, + Provider: provider, + Error: Error(provider + ' Unmounted').toString(), + Success: false, + } + }); + } else { + pid = result[provider].PID; + } + } + }) + .catch(e => { + console.log(e); + }); + },6000); +}; + +const unmountAllDrives = () => { + // Reset mount states + for (const provider of Constants.PROVIDER_LIST) { + clearManualMountDetection(provider); + expectedUnmount[provider] = true; + } + + // Unmount all items + for (const i in mountedLocations) { + const data = mountedData[mountedLocations[i]]; + helpers.stopMountProcessSync(data.Version, data.Provider); + } + + mountedLocations = []; + mountedData = {}; +}; + +const addListeners = (ipcMain, setTrayImage, standardIPCReply) => { + ipcMain.on(Constants.IPC_Check_Mount_Location + '_sync', (event, data) => { + let response = { + Success: true, + Error: '' + }; + + try { + if (fs.existsSync(data.Location) && fs.statSync(data.Location).isDirectory()) { + if (fs.readdirSync(data.Location).length !== 0) { + response.Success = false; + response.Error = 'Directory not empty: ' + data.Location; + } + } else { + response.Success = false; + response.Error = 'Directory not found: ' + data.Location; + } + } catch (e) { + response.Success = false; + response.Error = e.toString(); + } + event.returnValue = response; + }); + + ipcMain.on(Constants.IPC_Detect_Mounts, (event, data) => { + let driveLetters = {}; + for (const provider of Constants.PROVIDER_LIST) { + driveLetters[provider] = []; + } + + const grabDriveLetters = (locations) => { + for (let i = 'c'.charCodeAt(0); i <= 'z'.charCodeAt(0); i++) { + const drive = (String.fromCharCode(i) + ':').toUpperCase(); + let driveInUse; + if (Object.keys(locations).length > 0) { + for (const provider of Constants.PROVIDER_LIST) { + driveInUse = locations[provider].startsWith(drive); + if (driveInUse) + break; + } + } + if (!driveInUse) { + try { + if (!fs.existsSync(drive)) { + for (const provider of Constants.PROVIDER_LIST) { + driveLetters[provider].push(drive); + } + } + } catch (e) { + } + } + } + + if (Object.keys(locations).length > 0) { + for (const provider of Constants.PROVIDER_LIST) { + if (locations[provider].length > 0) { + if (!driveLetters[provider].find((driveLetter) => { + return driveLetter === locations[provider]; + })) { + driveLetters[provider].push(locations[provider]); + } + } + } + } + }; + + const setImage = (locations) => { + let driveInUse; + if (Object.keys(locations).length > 0) { + for (const provider of Constants.PROVIDER_LIST) { + driveInUse = locations[provider].length > 0; + if (driveInUse) + break; + } + } + + setTrayImage(driveInUse) + }; + + helpers + .detectRepertoryMounts(data.Version) + .then((results) => { + let storageData = {}; + let locations = {}; + for (const provider of Constants.PROVIDER_LIST) { + storageData[provider] = results[provider] ? results[provider] : { + Active: false, + Location: '', + PID: -1, + }; + locations[provider] = storageData[provider].Location; + + if (storageData[provider].PID !== -1) { + expectedUnmount[provider] = false; + if (firstMountCheck) { + monitorMount(event.sender, provider, data.Version, storageData[provider].PID, storageData[provider].Location); + } + } + } + + if (os.platform() === 'win32') { + grabDriveLetters(locations); + } + + setImage(locations); + if (firstMountCheck) { + firstMountCheck = false; + } + standardIPCReply(event, Constants.IPC_Detect_Mounts_Reply, { + DriveLetters: driveLetters, + Locations: locations, + }); + }) + .catch(error => { + if (os.platform() === 'win32') { + grabDriveLetters({}); + } + setImage({}); + standardIPCReply(event, Constants.IPC_Detect_Mounts_Reply, { + DriveLetters: driveLetters, + }, error); + }); + }); + + ipcMain.on(Constants.IPC_Mount_Drive, (event, data) => { + expectedUnmount[data.Provider] = false; + + if (mountedLocations.indexOf(data.Location) !== -1) { + console.log(data.Provider + ' already mounted: ' + data.Location); + } else { + mountedLocations.push(data.Location); + mountedData[data.Location] = { + Version: data.Version, + Provider: data.Provider, + }; + const errorHandler = (pid, error) => { + if (mountedLocations.indexOf(data.Location) !== -1) { + mountedLocations.splice(mountedLocations.indexOf(data.Location), 1); + delete mountedData[data.Location]; + } + + standardIPCReply(event, Constants.IPC_Unmount_Drive_Reply, { + Expected: expectedUnmount[data.Provider], + Location: data.Location, + Provider: data.Provider, + }, error || Error(data.Provider + ' Unmounted')); + }; + helpers + .executeMount(data.Version, data.Provider, data.Location, data.NoConsoleSupported, (error, pid) => { + errorHandler(pid, error); + }) + .then(() => { + standardIPCReply(event, Constants.IPC_Mount_Drive_Reply, { + Provider: data.Provider, + }); + }) + .catch(error => { + errorHandler(-1, error); + }); + } + }); + + ipcMain.on(Constants.IPC_Unmount_All_Drives, (event, data) => { + unmountAllDrives(); + standardIPCReply(event, Constants.IPC_Unmount_All_Drives_Reply); + }); + + ipcMain.on(Constants.IPC_Unmount_Drive, (event, data) => { + clearManualMountDetection(data.Provider); + + expectedUnmount[data.Provider] = true; + helpers + .stopMountProcess(data.Version, data.Provider) + .then(result => { + console.log(result); + }) + .catch(e => { + console.log(e); + }); + }); +}; + +module.exports = { + addListeners, + unmountAllDrives +}; \ No newline at end of file diff --git a/src/renderer/ipc/PlatformIPC.js b/src/renderer/ipc/PlatformIPC.js new file mode 100644 index 0000000..f55a35c --- /dev/null +++ b/src/renderer/ipc/PlatformIPC.js @@ -0,0 +1,79 @@ +const Constants = require('../../constants'); +const fs = require('fs'); +const helpers = require('../../helpers'); +const os = require('os'); +const path = require('path'); + +let _platformOverride; + +const getPlatformOverride = () => { + return _platformOverride; +}; + +const setPlatformOverride = platformOverride => { + _platformOverride = platformOverride; +}; + +const addListeners = (ipcMain, detectScript, saveUiSettings) => { + ipcMain.on(Constants.IPC_Get_Platform, (event) => { + const sendResponse = (appPlatform, platform) => { + event.sender.send(Constants.IPC_Get_Platform_Reply, { + AppPlatform: appPlatform, + Platform: platform, + }); + }; + + const platform = os.platform(); + if (platform === 'linux') { + if (_platformOverride && (_platformOverride.length > 0)) { + sendResponse(_platformOverride, 'linux'); + } else { + const scriptFile = path.join(os.tmpdir(), 'repertory_detect_linux.sh'); + fs.writeFileSync(scriptFile, detectScript); + + helpers + .executeScript(scriptFile) + .then(data => { + let appPlatform = data.replace(/(\r\n|\n|\r)/gm, ""); + if (appPlatform === 'unknown') { + helpers + .downloadFile(Constants.LINUX_DETECT_SCRIPT_URL, scriptFile, null, err => { + if (err) { + sendResponse(appPlatform, platform); + } else { + helpers + .executeScript(scriptFile) + .then(data => { + appPlatform = data.replace(/(\r\n|\n|\r)/gm, ""); + sendResponse(appPlatform, platform); + }) + .catch(() => { + sendResponse(appPlatform, platform); + }); + } + }); + } else { + sendResponse(appPlatform, platform); + } + }) + .catch(() => { + sendResponse(platform, platform); + }); + } + } else { + sendResponse(platform, platform); + } + }); + + ipcMain.on(Constants.IPC_Set_Linux_AppPlatform, (event, data) => { + setPlatformOverride(data.AppPlatform); + saveUiSettings(); + event.returnValue = true; + }); +}; + +module.exports = { + getPlatformOverride, + setPlatformOverride, + addListeners +}; \ No newline at end of file diff --git a/src/renderer/ipc/ReleaseIPC.js b/src/renderer/ipc/ReleaseIPC.js new file mode 100644 index 0000000..5d1eb66 --- /dev/null +++ b/src/renderer/ipc/ReleaseIPC.js @@ -0,0 +1,87 @@ +const Constants = require('../../constants'); +const fs = require('fs'); +const helpers = require('../../helpers'); +const os = require('os'); +const path = require('path'); +const unzip = require('unzipper'); + +const addListeners = (ipcMain, standardIPCReply) => { + ipcMain.on(Constants.IPC_Check_Installed, (event, data) => { + const destination = path.join(helpers.getDataDirectory(), data.Version); + helpers + .getMissingDependencies(data.Dependencies) + .then((dependencies) => { + let exists = false; + try { + exists = fs.existsSync(destination) && fs.lstatSync(destination).isDirectory(); + } catch (e) { + } + standardIPCReply(event, Constants.IPC_Check_Installed_Reply, { + Dependencies: dependencies, + Exists: exists, + Version: data.Version, + }); + }).catch(error => { + standardIPCReply(event, Constants.IPC_Check_Installed_Reply, { + Dependencies: [], + Version: data.Version, + }, error); + }); + }); + + ipcMain.on(Constants.IPC_Extract_Release, (event, data) => { + const destination = path.join(helpers.getDataDirectory(), data.Version); + helpers.removeDirectoryRecursively(destination); + helpers.mkDirByPathSync(destination); + + const stream = fs.createReadStream(data.Source); + stream + .pipe(unzip.Extract({ path: destination })) + .on('error', error => { + try { + helpers.removeDirectoryRecursively(destination); + } catch (e) { + } + stream.close(); + standardIPCReply(event, Constants.IPC_Extract_Release_Complete, { + Source: data.Source, + }, error); + }) + .on('finish', () => { + stream.close(); + if (os.platform() !== 'win32') { + helpers + .executeAndWait("chmod +x \"" + path.join(destination, 'repertory') + "\"") + .then(() => { + standardIPCReply(event, Constants.IPC_Extract_Release_Complete, { + Source: data.Source, + }); + }) + .catch(error => { + standardIPCReply(event, Constants.IPC_Extract_Release_Complete, { + Source: data.Source, + }, error); + }) + } else { + standardIPCReply(event, Constants.IPC_Extract_Release_Complete, { + Source: data.Source, + }); + } + }); + }); + + ipcMain.on(Constants.IPC_Test_Release, (event, data) => { + helpers + .testRepertoryBinary(data.Version) + .then(() => { + standardIPCReply(event, Constants.IPC_Test_Release_Reply, {}); + }) + .catch(error => { + standardIPCReply(event, Constants.IPC_Test_Release_Reply, {}, error); + }); + }); +}; + +module.exports = { + addListeners +}; \ No newline at end of file diff --git a/src/renderer/ipc/StateIPC.js b/src/renderer/ipc/StateIPC.js new file mode 100644 index 0000000..f6f1a7c --- /dev/null +++ b/src/renderer/ipc/StateIPC.js @@ -0,0 +1,30 @@ +const Constants = require('../../constants'); +const fs = require('fs'); +const helpers = require('../../helpers'); +const path = require('path'); + +const addListeners = ipcMain => { + ipcMain.on(Constants.IPC_Get_State, event => { + helpers.mkDirByPathSync(helpers.getDataDirectory()); + const configFile = path.join(helpers.getDataDirectory(), 'settings.json'); + if (fs.existsSync(configFile)) { + event.sender.send(Constants.IPC_Get_State_Reply, { + data: JSON.parse(fs.readFileSync(configFile, 'utf8')), + }); + } else { + event.sender.send(Constants.IPC_Get_State_Reply, { + data: null, + }); + } + }); + + ipcMain.on(Constants.IPC_Save_State, (event, data) => { + helpers.mkDirByPathSync(helpers.getDataDirectory()); + const configFile = path.join(helpers.getDataDirectory(), 'settings.json'); + fs.writeFileSync(configFile, JSON.stringify(data.State), 'utf8'); + }); +}; + +module.exports = { + addListeners +}; \ No newline at end of file diff --git a/src/renderer/ipc/SystemIPC.js b/src/renderer/ipc/SystemIPC.js new file mode 100644 index 0000000..52ebb2f --- /dev/null +++ b/src/renderer/ipc/SystemIPC.js @@ -0,0 +1,16 @@ +const Constants = require('../../constants'); +const os = require('os'); +const helpers = require('../../helpers'); + +const addListeners = (ipcMain, closeApplication) => { + ipcMain.on(Constants.IPC_Reboot_System, () => { + if (os.platform() === 'win32') { + helpers.executeAsync('shutdown.exe', ['/r', '/t', '30']); + } + closeApplication(); + }); +}; + +module.exports = { + addListeners +}; \ No newline at end of file diff --git a/src/renderer/ipc/UpgradeIPC.js b/src/renderer/ipc/UpgradeIPC.js new file mode 100644 index 0000000..7bdc24c --- /dev/null +++ b/src/renderer/ipc/UpgradeIPC.js @@ -0,0 +1,116 @@ +const Constants = require('../../constants'); +const fs = require('fs'); +const helpers = require('../../helpers'); +const os = require('os'); + +const addListeners = (ipcMain, setIsInstalling, unmountAllDrives, standardIPCReply) => { + ipcMain.on(Constants.IPC_Install_Upgrade, (event, data) => { + let allowSkipVerification = true; + + unmountAllDrives(); + + let tempSig; + let tempPub; + const cleanupFiles = () => { + try { + if (tempSig) { + fs.unlinkSync(tempSig); + } + if (tempPub) { + fs.unlinkSync(tempPub); + } + } catch (e) { + } + }; + + const errorHandler = err => { + cleanupFiles(); + setIsInstalling(false); + standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, { + AllowSkipVerification: allowSkipVerification, + Source: data.Source, + }, err); + }; + + // TODO Enable verification in 1.0.4 + const hasSignature = false;//!data.SkipVerification && data.Signature && (data.Signature.length > 0); + const hasHash = false;//!data.SkipVerification && data.Sha256 && (data.Sha256.length > 0); + if (hasSignature) { + try { + const files = helpers.createSignatureFiles(data.Signature, Constants.DEV_PUBLIC_KEY); + tempPub = files.PublicKeyFile; + tempSig = files.SignatureFile; + } catch (e) { + errorHandler(e); + return; + } + } + + let command; + let args; + const platform = os.platform(); + if (platform === 'win32') { + command = data.Source; + } else if (platform === 'darwin') { + command = 'open'; + args = ['-a', 'Finder', data.Source]; + } else if (platform === 'linux') { + try { + command = data.Source; + fs.chmodSync(command, '750'); + } catch (e) { + errorHandler(e); + } + } else { + errorHandler(Error('Platform not supported: ' + os.platform())); + } + + if (command) { + const executeInstall = () => { + setIsInstalling(true); + helpers + .executeAsync(command, args) + .then(() => { + cleanupFiles(); + standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply) + }) + .catch(error => { + setIsInstalling(false); + errorHandler(error); + }); + }; + + if (hasSignature) { + helpers + .verifySignature(data.Source, tempSig, tempPub) + .then(() => { + executeInstall(); + }) + .catch(() => { + errorHandler(Error('Failed to verify installation package signature')); + }); + } else if (hasHash) { + helpers + .verifyHash(data.Source, data.Sha256) + .then(()=> { + executeInstall(); + }) + .catch(() => { + errorHandler(Error('Failed to verify installation package hash')); + }); + } else { + if (platform === 'darwin') { + setTimeout(executeInstall, 3000); + } else { + executeInstall(); + } + } + } else { + errorHandler(Error('Unsupported upgrade: ' + data.Source)); + } + }); +}; + +module.exports = { + addListeners +}; \ No newline at end of file From cbc61742a272082e9e88f2acc2088c8213a8e485 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Thu, 29 Aug 2019 21:05:10 -0500 Subject: [PATCH 10/22] Fix missing import --- src/renderer/ipc/DownloadIPC.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/renderer/ipc/DownloadIPC.js b/src/renderer/ipc/DownloadIPC.js index 30b407e..1492ea9 100644 --- a/src/renderer/ipc/DownloadIPC.js +++ b/src/renderer/ipc/DownloadIPC.js @@ -1,5 +1,6 @@ const Constants = require('../../constants'); const helpers = require('../../helpers'); +const path = require('path'); const addListeners = (ipcMain, standardIPCReply) => { ipcMain.on(Constants.IPC_Download_File, (event, data) => { From adcc060d138496d7531a14fd9fb1891da13fe2bd Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Fri, 30 Aug 2019 12:32:08 -0500 Subject: [PATCH 11/22] #37: Version check fails with incorrect message when VC runtime is missing --- CHANGELOG.md | 1 + src/containers/MountItems/MountItems.js | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e89cfac..cafbf8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## 1.0.8 * \#36: Add ability to select Linux distribution type if OS is unsupported +* \#37: Version check fails with incorrect message when VC runtime is missing * Added additional WinFsp uninstall strings ## 1.0.7 diff --git a/src/containers/MountItems/MountItems.js b/src/containers/MountItems/MountItems.js index 58a84ce..209502c 100644 --- a/src/containers/MountItems/MountItems.js +++ b/src/containers/MountItems/MountItems.js @@ -171,7 +171,11 @@ class MountItems extends IPCContainer { } } else { allowAction = false; - this.displayRetryMount(provider, location, 'Version check failed: ' + result.Error); + 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.'); + } else { + this.displayRetryMount(provider, location, 'Version check failed: ' + result.Error); + } } } From 297d7af060b354901aaae3a789b5fb40706471f6 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Fri, 30 Aug 2019 15:12:28 -0500 Subject: [PATCH 12/22] #8: Add tooltips to settings [partial] --- src/assets/settings.json | 25 +++++++++++++++++++ .../ConfigurationItem/ConfigurationItem.css | 4 +++ .../ConfigurationItem/ConfigurationItem.js | 19 +++++++++++++- .../DependencyList/Dependency/Dependency.js | 3 +-- src/containers/Configuration/Configuration.js | 2 ++ 5 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 src/assets/settings.json diff --git a/src/assets/settings.json b/src/assets/settings.json new file mode 100644 index 0000000..bd52d46 --- /dev/null +++ b/src/assets/settings.json @@ -0,0 +1,25 @@ +{ + "HostConfig": { + + }, + "Settings": { + "ApiAuth": "Password used to connect to Repertory API. Auto-generated by default.", + "ApiPort": "Repertory API port to use for JSON-RPC requests.", + "ApiUser": "Username used to connect to Repertory API. Default is 'repertory'.", + "ChunkDownloaderTimeoutSeconds": "Files that are not cached locally will download data in ChunkSize chunks when a read or write operation occurs. This timeout value specifies the amount of time chunks should continue downloading after the last file handle has been closed.", + "ChunkSize": "This is the minimum data size (converted to KiB - value of 8 means 8KiB) used for downloads. This value cannot be less than 8 and should also be a multiple of 8. Default is 2048.", + "EnableChunkDownloaderTimeout": "This setting applies to full allocation downloads. When set to true, downloads will timeout after ChunkDownloaderTimeoutSeconds if the file has no more open handles. If set to false, the entire file will always download.", + "EnableDriveEvents": "When set to true, additional logging for FUSE on UNIX or WinFSP on Windows will occur. It's best to leave this value set to 'false' unless troubleshooting an issue as enabling it may have an adverse affect on performance.", + "EnableMaxCacheSize": "If set to true, files will begin to be removed from the local cache as soon as MaxCacheSizeBytes and MinimumRedundancy have been met. This does not mean further attempts to write will fail when MaxCacheSizeBytes is reached. Writes will continue as long as there is enough local drive space to accommodate the operation.\n\nIf set to false, files will begin to be removed from the local cache as soon as MinimumRedundancy has been met.\n\nIn both cases, files that do not have any open handles will be chosen by oldest modification date for removal.", + "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.", + "EvictionDelayMinutes": "Number of minutes to wait after all file handles are closed before allowing file to be evicted from cache.", + "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 to take affect.", + "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/SiaPrime 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.", + "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/SiaPrime.\n\nDirect mode utilizes no disk space. All data is read directly from Sia/SiaPrime.\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/SiaPrime.", + "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.", + "RingBufferFileSize": "The size of the ring buffer file in MiB. Default is 512. Valid values are: 64, 128, 256, 512, 1024." + } +} \ No newline at end of file diff --git a/src/components/ConfigurationItem/ConfigurationItem.css b/src/components/ConfigurationItem/ConfigurationItem.css index c6a6e77..328ae2c 100644 --- a/src/components/ConfigurationItem/ConfigurationItem.css +++ b/src/components/ConfigurationItem/ConfigurationItem.css @@ -33,4 +33,8 @@ input.ConfigurationItemInput { background: rgba(10, 10, 15, 0.8); border-color: rgba(10, 10, 20, 0.9); color: var(--text_color); +} + +.ConfigurationInfo { + cursor: pointer; } \ No newline at end of file diff --git a/src/components/ConfigurationItem/ConfigurationItem.js b/src/components/ConfigurationItem/ConfigurationItem.js index d2dc240..13b4e24 100644 --- a/src/components/ConfigurationItem/ConfigurationItem.js +++ b/src/components/ConfigurationItem/ConfigurationItem.js @@ -1,5 +1,8 @@ import React from 'react'; import './ConfigurationItem.css'; +import settings from '../../assets/settings'; +import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; +import {faInfoCircle} from '@fortawesome/free-solid-svg-icons'; export default props => { const handleChanged = (e) => { @@ -9,6 +12,18 @@ export default props => { } props.changed(target); }; + + let infoDisplay; + if (settings[props.grouping] && settings[props.grouping][props.label]) { + const displayInfo = () => { + const description = settings[props.grouping][props.label]; + alert(description); + }; + + infoDisplay = {displayInfo(); return false;}}>; + } let data; switch (props.template.type) { @@ -96,7 +111,9 @@ export default props => { width='100%'> - {props.label} + {infoDisplay ? + {infoDisplay} {props.label} : + {props.label}} {data} diff --git a/src/components/DependencyList/Dependency/Dependency.js b/src/components/DependencyList/Dependency/Dependency.js index e979f10..f869874 100644 --- a/src/components/DependencyList/Dependency/Dependency.js +++ b/src/components/DependencyList/Dependency/Dependency.js @@ -22,8 +22,7 @@ export default connect(mapStateToProps)(props => { {props.AllowDownload ? - {props.onDownload(); return false;}}>Install : 'Installing...'} diff --git a/src/containers/Configuration/Configuration.js b/src/containers/Configuration/Configuration.js index 46ac070..f62cefd 100644 --- a/src/containers/Configuration/Configuration.js +++ b/src/containers/Configuration/Configuration.js @@ -231,6 +231,7 @@ class Configuration extends IPCContainer { ((this.state.ShowAdvanced && k.advanced) || !k.advanced) ? this.handleItemChanged(e, i)} + grouping={'Settings'} items={this.state.Template[k.label].items} key={i} label={k.label} @@ -251,6 +252,7 @@ class Configuration extends IPCContainer { ((this.state.ShowAdvanced && k.advanced) || !k.advanced) ? this.handleObjectItemChanged(e, key, i)} + grouping={key} items={this.state.Template[key].template[k.label].items} key={i} label={k.label} From 42515a08c39e3e692944ba3ac3dae35eee4e84da Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Fri, 30 Aug 2019 15:14:29 -0500 Subject: [PATCH 13/22] Updated CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cafbf8b..f133fa9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## 1.0.8 +* \#8: Add tooltips to settings * \#36: Add ability to select Linux distribution type if OS is unsupported * \#37: Version check fails with incorrect message when VC runtime is missing * Added additional WinFsp uninstall strings From 7e6e3cbc4901e112d5ffc2eb848b2f620fb81ce5 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Fri, 30 Aug 2019 16:51:49 -0500 Subject: [PATCH 14/22] #8: Add tooltips to settings [partial] --- src/App.js | 8 +++-- .../ConfigurationItem/ConfigurationItem.js | 14 ++++++-- src/components/InfoDetails/InfoDetails.css | 11 ++++++ src/components/InfoDetails/InfoDetails.js | 30 ++++++++++++++++ src/redux/actions/error_actions.js | 34 +++++++++++++++++++ src/redux/reducers/error_reducer.js | 25 +++++++++++++- 6 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 src/components/InfoDetails/InfoDetails.css create mode 100644 src/components/InfoDetails/InfoDetails.js diff --git a/src/App.js b/src/App.js index 6f15cbe..780b5e5 100644 --- a/src/App.js +++ b/src/App.js @@ -7,6 +7,7 @@ import DependencyList from './components/DependencyList/DependencyList'; import DownloadProgress from './components/DownloadProgress/DownloadProgress'; import ErrorDetails from './components/ErrorDetails/ErrorDetails'; import Grid from './components/UI/Grid/Grid'; +import InfoDetails from './components/InfoDetails/InfoDetails'; import IPCContainer from './containers/IPCContainer/IPCContainer'; import Loading from './components/UI/Loading/Loading'; import Modal from './components/UI/Modal/Modal'; @@ -121,6 +122,7 @@ class App extends IPCContainer { !this.props.DismissDependencies && this.props.AllowMount; + const infoDisplay = this.createModalConditionally(this.props.DisplayInfo, , true); const rebootDisplay = this.createModalConditionally(this.props.RebootRequired, ); const configDisplay = this.createModalConditionally(showConfig, ); const dependencyDisplay = this.createModalConditionally(showDependencies, ); @@ -156,12 +158,13 @@ class App extends IPCContainer { return (
{selectAppPlatformDisplay} - {errorDisplay} {dependencyDisplay} {upgradeDisplay} - {downloadDisplay} {configDisplay} + {infoDisplay} + {downloadDisplay} {rebootDisplay} + {errorDisplay}
@@ -203,6 +206,7 @@ const mapStateToProps = state => { DismissDependencies: state.install.DismissDependencies, DisplayConfiguration: state.mounts.DisplayConfiguration, DisplayError: state.error.DisplayError, + DisplayInfo: state.error.DisplayInfo, DisplaySelectAppPlatform: state.common.DisplaySelectAppPlatform, DownloadActive: state.download.DownloadActive, InstallActive: state.install.InstallActive, diff --git a/src/components/ConfigurationItem/ConfigurationItem.js b/src/components/ConfigurationItem/ConfigurationItem.js index 13b4e24..f143839 100644 --- a/src/components/ConfigurationItem/ConfigurationItem.js +++ b/src/components/ConfigurationItem/ConfigurationItem.js @@ -3,8 +3,16 @@ import './ConfigurationItem.css'; import settings from '../../assets/settings'; import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; import {faInfoCircle} from '@fortawesome/free-solid-svg-icons'; +import {connect} from 'react-redux'; +import {notifyInfo} from '../../redux/actions/error_actions'; -export default props => { +const mapDispatchToProps = dispatch => { + return { + notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)) + } +}; + +export default connect(null, mapDispatchToProps)(props => { const handleChanged = (e) => { const target = e.target; if (target.type === 'checkbox') { @@ -17,7 +25,7 @@ export default props => { if (settings[props.grouping] && settings[props.grouping][props.label]) { const displayInfo = () => { const description = settings[props.grouping][props.label]; - alert(description); + props.notifyInfo(props.label, description); }; infoDisplay = {
); -}; \ No newline at end of file +}); \ No newline at end of file diff --git a/src/components/InfoDetails/InfoDetails.css b/src/components/InfoDetails/InfoDetails.css new file mode 100644 index 0000000..28fe9d2 --- /dev/null +++ b/src/components/InfoDetails/InfoDetails.css @@ -0,0 +1,11 @@ +.InfoDetailsHeading { + text-align: center; + margin-bottom: 4px; +} + +.InfoDetailsContent { + max-height: 70vh; + min-width: 80vw; + overflow-y: auto; + margin-bottom: 8px; +} \ No newline at end of file diff --git a/src/components/InfoDetails/InfoDetails.js b/src/components/InfoDetails/InfoDetails.js new file mode 100644 index 0000000..37d6d0c --- /dev/null +++ b/src/components/InfoDetails/InfoDetails.js @@ -0,0 +1,30 @@ +import React from 'react'; +import {dismissInfo} from '../../redux/actions/error_actions'; +import {connect} from 'react-redux'; +import Box from '../UI/Box/Box'; +import Button from '../UI/Button/Button'; +import './InfoDetails.css'; + +const mapStateToProps = state => { + return { + InfoMessage: state.error.InfoStack.length > 0 ? state.error.InfoStack[0] : '', + }; +}; + +const mapDispatchToProps = dispatch => { + return { + dismissInfo: () => dispatch(dismissInfo()), + }; +}; + +export default connect(mapStateToProps, mapDispatchToProps)(props => { + return ( + +

{props.InfoMessage.title}

+
+

{props.InfoMessage.message}

+
+ +
+ ); +}); \ No newline at end of file diff --git a/src/redux/actions/error_actions.js b/src/redux/actions/error_actions.js index f46c8cc..0fdcf4c 100644 --- a/src/redux/actions/error_actions.js +++ b/src/redux/actions/error_actions.js @@ -13,6 +13,14 @@ export const clearError = () => { }; }; +export const CLEAR_INFO = 'error/clearInfo'; +export const clearInfo = () => { + return { + type: CLEAR_INFO, + payload: null, + }; +}; + export const dismissError = () => { return (dispatch, getState) => { dispatch(clearError()); @@ -27,6 +35,12 @@ export const dismissError = () => { }; }; +export const dismissInfo = () => { + return dispatch => { + dispatch(clearInfo()); + }; +}; + export const notifyError = (msg, critical, callback) => { return dispatch => { ErrorActions = [callback, ...ErrorActions]; @@ -36,6 +50,14 @@ export const notifyError = (msg, critical, callback) => { }; }; +export const notifyInfo = (title, msg) => { + return dispatch => { + title = title ? title.toString() : 'Information'; + msg = msg ? msg.toString() : ''; + dispatch(setInfo(title, msg)); + }; +}; + export const SET_ERROR_INFO = 'error/setErrorInfo'; export const setErrorInfo = (msg, critical) => { return { @@ -45,4 +67,16 @@ export const setErrorInfo = (msg, critical) => { critical } } +}; + + +export const SET_INFO = 'error/setInfo'; +export const setInfo = (title, msg) => { + return { + type: SET_INFO, + payload: { + title, + msg + } + } }; \ No newline at end of file diff --git a/src/redux/reducers/error_reducer.js b/src/redux/reducers/error_reducer.js index 8a25120..0bb20d2 100644 --- a/src/redux/reducers/error_reducer.js +++ b/src/redux/reducers/error_reducer.js @@ -1,13 +1,17 @@ import {createReducer} from 'redux-starter-kit'; import { CLEAR_ERROR, - SET_ERROR_INFO + CLEAR_INFO, + SET_ERROR_INFO, + SET_INFO } from '../actions/error_actions'; export const errorReducer = createReducer({ DisplayError: false, + DisplayInfo: false, ErrorCritical: false, ErrorStack: [], + InfoStack: [], }, { [CLEAR_ERROR]: state => { const errorStack = (state.ErrorStack.length > 0) ? state.ErrorStack.slice(1) : []; @@ -17,6 +21,14 @@ export const errorReducer = createReducer({ ErrorStack: errorStack, } }, + [CLEAR_INFO]: state => { + const infoStack = (state.InfoStack.length > 0) ? state.InfoStack.slice(1) : []; + return { + ...state, + DisplayInfo: (infoStack.length > 0), + InfoStack: infoStack, + } + }, [SET_ERROR_INFO]: (state, action) => { const errorStack = [action.payload.msg, ...state.ErrorStack]; return { @@ -25,5 +37,16 @@ export const errorReducer = createReducer({ ErrorCritical: state.ErrorCritical || action.payload.critical, ErrorStack: errorStack, } + }, + [SET_INFO]: (state, action) => { + const infoStack = [{ + title: action.payload.title, + message: action.payload.msg + }, ...state.InfoStack]; + return { + ...state, + DisplayInfo: true, + InfoStack: infoStack, + } } }); \ No newline at end of file From 83b5a6b1579c349df6f7b67c5691643f6e413260 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Fri, 30 Aug 2019 16:58:16 -0500 Subject: [PATCH 15/22] Fix description --- src/assets/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/settings.json b/src/assets/settings.json index bd52d46..158799a 100644 --- a/src/assets/settings.json +++ b/src/assets/settings.json @@ -14,7 +14,7 @@ "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.", "EvictionDelayMinutes": "Number of minutes to wait after all file handles are closed before allowing file to be evicted from cache.", - "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 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.", "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/SiaPrime 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.", From ee69bc7fe3c40505db718bd42ed10919c2cace84 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Fri, 30 Aug 2019 17:04:23 -0500 Subject: [PATCH 16/22] Update max height --- src/components/InfoDetails/InfoDetails.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/InfoDetails/InfoDetails.css b/src/components/InfoDetails/InfoDetails.css index 28fe9d2..ae9a3ae 100644 --- a/src/components/InfoDetails/InfoDetails.css +++ b/src/components/InfoDetails/InfoDetails.css @@ -4,7 +4,7 @@ } .InfoDetailsContent { - max-height: 70vh; + max-height: 60vh; min-width: 80vw; overflow-y: auto; margin-bottom: 8px; From 9df466643848cc75372f1af52cd91011ac7c8e9e Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Fri, 30 Aug 2019 17:18:02 -0500 Subject: [PATCH 17/22] Text formatting --- src/assets/settings.json | 4 ++-- src/components/InfoDetails/InfoDetails.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/assets/settings.json b/src/assets/settings.json index 158799a..893ff9c 100644 --- a/src/assets/settings.json +++ b/src/assets/settings.json @@ -5,9 +5,9 @@ "Settings": { "ApiAuth": "Password used to connect to Repertory API. Auto-generated by default.", "ApiPort": "Repertory API port to use for JSON-RPC requests.", - "ApiUser": "Username used to connect to Repertory API. Default is 'repertory'.", + "ApiUser": "Username used to connect to Repertory API.", "ChunkDownloaderTimeoutSeconds": "Files that are not cached locally will download data in ChunkSize chunks when a read or write operation occurs. This timeout value specifies the amount of time chunks should continue downloading after the last file handle has been closed.", - "ChunkSize": "This is the minimum data size (converted to KiB - value of 8 means 8KiB) used for downloads. This value cannot be less than 8 and should also be a multiple of 8. Default is 2048.", + "ChunkSize": "This is the minimum data size (converted to KiB - value of 8 means 8KiB) used for downloads. This value cannot be less than 8 and should also be a multiple of 8.", "EnableChunkDownloaderTimeout": "This setting applies to full allocation downloads. When set to true, downloads will timeout after ChunkDownloaderTimeoutSeconds if the file has no more open handles. If set to false, the entire file will always download.", "EnableDriveEvents": "When set to true, additional logging for FUSE on UNIX or WinFSP on Windows will occur. It's best to leave this value set to 'false' unless troubleshooting an issue as enabling it may have an adverse affect on performance.", "EnableMaxCacheSize": "If set to true, files will begin to be removed from the local cache as soon as MaxCacheSizeBytes and MinimumRedundancy have been met. This does not mean further attempts to write will fail when MaxCacheSizeBytes is reached. Writes will continue as long as there is enough local drive space to accommodate the operation.\n\nIf set to false, files will begin to be removed from the local cache as soon as MinimumRedundancy has been met.\n\nIn both cases, files that do not have any open handles will be chosen by oldest modification date for removal.", diff --git a/src/components/InfoDetails/InfoDetails.js b/src/components/InfoDetails/InfoDetails.js index 37d6d0c..2bbcc7e 100644 --- a/src/components/InfoDetails/InfoDetails.js +++ b/src/components/InfoDetails/InfoDetails.js @@ -22,7 +22,7 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {

{props.InfoMessage.title}

-

{props.InfoMessage.message}

+

{props.InfoMessage.message}

From d58ba1411ea62fff8152fd507b3edfb8319a07a6 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Fri, 30 Aug 2019 21:37:11 -0500 Subject: [PATCH 18/22] #8: Add tooltips to settings --- package.json | 2 +- src/assets/settings.json | 10 +++++++--- src/constants.js | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index eff71cd..373cb7e 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "test": "react-scripts test", "eject": "react-scripts eject", "electron-dev": "cross-env ELECTRON_START_URL=http://localhost:3000 electron .", - "electron-dev-unix": "cross-env ELECTRON_START_URL=http://localhost:3000 electron $NODE_DEBUG_OPTION .", + "electron-dev-unix": "cross-env ELECTRON_START_URL=http://localhost:3000 electron .", "pack": "npm run build && electron-builder --dir --x64", "dist": "npm run build && electron-builder --x64", "dist-all": "npm run build && electron-builder --x64 --win --linux --mac", diff --git a/src/assets/settings.json b/src/assets/settings.json index 893ff9c..2642db6 100644 --- a/src/assets/settings.json +++ b/src/assets/settings.json @@ -1,11 +1,15 @@ { "HostConfig": { - + "AgentString": "'User-Agent' used when communicating with Sia/SiaPrime's API.", + "ApiPassword": "Password used when communicating with Sia/SiaPrime's API.\n\nThis is not the same as your wallet's password, so please do not enter it here. Sia/SiaPrime typically auto-generate this value. It is exclusively used for API authentication purposes.", + "ApiPort": "API port used to connect to Sia/SiaPrime's daemon.", + "HostNameOrIp": "IP address or host name of Sia/SiaPrime daemon.", + "TimeoutMs": "Number of milliseconds to wait for Sia/SiaPrime API responses before timing out." }, "Settings": { - "ApiAuth": "Password used to connect to Repertory API. Auto-generated by default.", + "ApiAuth": "Password used to communicate with Repertory's API. Auto-generated by default.", "ApiPort": "Repertory API port to use for JSON-RPC requests.", - "ApiUser": "Username used to connect to Repertory API.", + "ApiUser": "Username used to communicate with Repertory's API.", "ChunkDownloaderTimeoutSeconds": "Files that are not cached locally will download data in ChunkSize chunks when a read or write operation occurs. This timeout value specifies the amount of time chunks should continue downloading after the last file handle has been closed.", "ChunkSize": "This is the minimum data size (converted to KiB - value of 8 means 8KiB) used for downloads. This value cannot be less than 8 and should also be a multiple of 8.", "EnableChunkDownloaderTimeout": "This setting applies to full allocation downloads. When set to true, downloads will timeout after ChunkDownloaderTimeoutSeconds if the file has no more open handles. If set to false, the entire file will always download.", diff --git a/src/constants.js b/src/constants.js index a74beef..7582f13 100644 --- a/src/constants.js +++ b/src/constants.js @@ -28,8 +28,8 @@ exports.DEV_PUBLIC_KEY = '-----BEGIN PUBLIC KEY-----\n' + '-----END PUBLIC KEY-----'; -const REPERTORY_BRANCH = '1.1.0-release_branch'; -const REPERTORY_UI_BRANCH = '1.0.8_branch'; +const REPERTORY_BRANCH = 'master'; +const REPERTORY_UI_BRANCH = 'master'; exports.RELEASES_URL = 'https://bitbucket.org/blockstorage/repertory/raw/' + REPERTORY_BRANCH + '/releases.json'; exports.UI_RELEASES_URL = 'https://bitbucket.org/blockstorage/repertory-ui/raw/' + REPERTORY_UI_BRANCH + '/releases.json'; From 5f6d9a3e88db9a3cf40f5f47cc2377d0d0f28aac Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Sat, 31 Aug 2019 00:22:11 -0500 Subject: [PATCH 19/22] Linux release --- README.md | 2 +- releases.json | 126 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 85 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index ba8f3be..b9145f1 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Repertory allows you to mount Sia and/or SiaPrime blockchain storage solutions v * SiaPrime >=1.4.0 ## Downloads -* **Repertory UI v1.0.8 Linux 64-bit** []() [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage) +* **Repertory UI v1.0.8 Linux 64-bit** [](https://pixeldrain.com/api/file/a1H78Dc_) [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage) * NOTE: Linux distributions require `fuse` and `libfuse` to be installed. * **Repertory UI v1.0.8 OS X 64-bit** []() [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_mac.dmg) * **Repertory UI v1.0.8 Windows 64-bit** []() [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_win.exe) diff --git a/releases.json b/releases.json index 863694c..f121041 100644 --- a/releases.json +++ b/releases.json @@ -2,16 +2,22 @@ "Locations": { "arch": { "1.0.8": { - "sha256": "", - "sig": "", - "urls": [] + "sha256": "6bbbb94934d12aa125400a4565d645387515ed4eebd4e54e3e2319423966ec66", + "sig": "AgRclnw5BALJpZFKkvqkXsu8nt5gzYU62xLrPwa5CEsQVjv55LnFiPjQp8pDHi7rH+r2fh+PludH59muiYvmG1WXc52CYZih0rH3I3+Zv169bq+HoooCOuzCOgDkuGlVT7KCc0lCV5UfaWu4tme7NOiOBecEdBAG6ppyq432PjjNPdupe/MGwT4IAYfHAsoR2lPH9nyNKtzTnbMGX1EXEUPOjnsFxyVKKbfer3QKUst7aF5xh30vSzDvq5OpXseA0sCKroWIndaDHW6dLnywnaUqOEW/IyuMNuksAw9LTMFovbULRrxhF4S9VTMZ1wp8X99JlM4MBtTcN2homtqP3Mr7MEmChQR4XyqwF9lrLcq8nbGK5ni6ZpV7AfMLqTB+K+jH5rdNY2H812TYjAJA14ntGBKTRJSgPn/mzKLbBVQtpAMMZ/G/280QKkDH1E6ULEJPdBxDGRDNvDCE7Goe5L4tG9VKn8ncFLPGJIttP3qJreRyx3lBVnSbp0Ya+IUs1YrXctbbUsiM7dubql2H+rLnhzsX33PgkpPcOyR01P1pymI8LLNBLotCDJjwCNIF+hOB+a34txJFiOWIX7Uw8U4h5HWO6XAZFy8/UNG5Miljv+Y6xFIVv1HQxeivKGNBWHlh/m2nvg9sSf2FEydk78zHoBaeB/XFZNgQmhfolQSnywyugPZMxxAmYqI64pvgrNpo+tLp5XFy0vmCvKJNEdrjkKfYNYks66+aBHsNd76jKocaFNu/nc24X5nqpTpBowJXLG7jAGeo7+yqj6V8mK5yNMhGT5HbcyhB+5DSkeTTHcVD+x2Hdimy0VNNXI6qjAaE3R5SlUnv5a/lt+t5HM248LwAbYSzk//Jjk1rR+AnNuBJ5HSxuVdLKqUIkwZ+k0EjFebATmHx+89ieliOv0VAuoMlFr06tjoIyvn2QojOICaB/gHdeOMM6NYoTEl3K4xPbM/Ve1n2ZdYq/PapM8IEJ33H9l3zVjb5oC5lW1B02qiD+qu4BK39RV2nYrCXZbr9Xs7F4M+YifeYVA7oMSa+qDJvNGBj5XGPnBidEDp+jWWIsRoykdjpt0vJA1PoX659UuW/cr1vB9wkI8IxgXEya8mOxEQ7QrPW5RKlha1oi1GVhdzM7tJPzehSyhe+y9zSyVELmhfcJRjC0sy39WYaaDQuCoVhz1gztR6innjUkKFBuEYRQYOsdraBitRkQC48gMPrKe/XmsvJM1o6Uo06GIq9Xiv/VEQrN7uKd7Xqy+nKkdKzy/BtkxsnXrUjc+tAuM89z33trkGYdRDdbAefYz7nVQ2HZ6SPEhT6LGhW8uBa1RU9bIryFBQHStbvbrGvdwDBZvt8z8qfyKUYzhQ=", + "urls": [ + "https://pixeldrain.com/api/file/a1H78Dc_", + "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage" + ] } }, "centos7": { "1.0.8": { - "sha256": "", - "sig": "", - "urls": [] + "sha256": "6bbbb94934d12aa125400a4565d645387515ed4eebd4e54e3e2319423966ec66", + "sig": "AgRclnw5BALJpZFKkvqkXsu8nt5gzYU62xLrPwa5CEsQVjv55LnFiPjQp8pDHi7rH+r2fh+PludH59muiYvmG1WXc52CYZih0rH3I3+Zv169bq+HoooCOuzCOgDkuGlVT7KCc0lCV5UfaWu4tme7NOiOBecEdBAG6ppyq432PjjNPdupe/MGwT4IAYfHAsoR2lPH9nyNKtzTnbMGX1EXEUPOjnsFxyVKKbfer3QKUst7aF5xh30vSzDvq5OpXseA0sCKroWIndaDHW6dLnywnaUqOEW/IyuMNuksAw9LTMFovbULRrxhF4S9VTMZ1wp8X99JlM4MBtTcN2homtqP3Mr7MEmChQR4XyqwF9lrLcq8nbGK5ni6ZpV7AfMLqTB+K+jH5rdNY2H812TYjAJA14ntGBKTRJSgPn/mzKLbBVQtpAMMZ/G/280QKkDH1E6ULEJPdBxDGRDNvDCE7Goe5L4tG9VKn8ncFLPGJIttP3qJreRyx3lBVnSbp0Ya+IUs1YrXctbbUsiM7dubql2H+rLnhzsX33PgkpPcOyR01P1pymI8LLNBLotCDJjwCNIF+hOB+a34txJFiOWIX7Uw8U4h5HWO6XAZFy8/UNG5Miljv+Y6xFIVv1HQxeivKGNBWHlh/m2nvg9sSf2FEydk78zHoBaeB/XFZNgQmhfolQSnywyugPZMxxAmYqI64pvgrNpo+tLp5XFy0vmCvKJNEdrjkKfYNYks66+aBHsNd76jKocaFNu/nc24X5nqpTpBowJXLG7jAGeo7+yqj6V8mK5yNMhGT5HbcyhB+5DSkeTTHcVD+x2Hdimy0VNNXI6qjAaE3R5SlUnv5a/lt+t5HM248LwAbYSzk//Jjk1rR+AnNuBJ5HSxuVdLKqUIkwZ+k0EjFebATmHx+89ieliOv0VAuoMlFr06tjoIyvn2QojOICaB/gHdeOMM6NYoTEl3K4xPbM/Ve1n2ZdYq/PapM8IEJ33H9l3zVjb5oC5lW1B02qiD+qu4BK39RV2nYrCXZbr9Xs7F4M+YifeYVA7oMSa+qDJvNGBj5XGPnBidEDp+jWWIsRoykdjpt0vJA1PoX659UuW/cr1vB9wkI8IxgXEya8mOxEQ7QrPW5RKlha1oi1GVhdzM7tJPzehSyhe+y9zSyVELmhfcJRjC0sy39WYaaDQuCoVhz1gztR6innjUkKFBuEYRQYOsdraBitRkQC48gMPrKe/XmsvJM1o6Uo06GIq9Xiv/VEQrN7uKd7Xqy+nKkdKzy/BtkxsnXrUjc+tAuM89z33trkGYdRDdbAefYz7nVQ2HZ6SPEhT6LGhW8uBa1RU9bIryFBQHStbvbrGvdwDBZvt8z8qfyKUYzhQ=", + "urls": [ + "https://pixeldrain.com/api/file/a1H78Dc_", + "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage" + ] } }, "darwin": { @@ -23,86 +29,122 @@ }, "debian9": { "1.0.8": { - "sha256": "", - "sig": "", - "urls": [] + "sha256": "6bbbb94934d12aa125400a4565d645387515ed4eebd4e54e3e2319423966ec66", + "sig": "AgRclnw5BALJpZFKkvqkXsu8nt5gzYU62xLrPwa5CEsQVjv55LnFiPjQp8pDHi7rH+r2fh+PludH59muiYvmG1WXc52CYZih0rH3I3+Zv169bq+HoooCOuzCOgDkuGlVT7KCc0lCV5UfaWu4tme7NOiOBecEdBAG6ppyq432PjjNPdupe/MGwT4IAYfHAsoR2lPH9nyNKtzTnbMGX1EXEUPOjnsFxyVKKbfer3QKUst7aF5xh30vSzDvq5OpXseA0sCKroWIndaDHW6dLnywnaUqOEW/IyuMNuksAw9LTMFovbULRrxhF4S9VTMZ1wp8X99JlM4MBtTcN2homtqP3Mr7MEmChQR4XyqwF9lrLcq8nbGK5ni6ZpV7AfMLqTB+K+jH5rdNY2H812TYjAJA14ntGBKTRJSgPn/mzKLbBVQtpAMMZ/G/280QKkDH1E6ULEJPdBxDGRDNvDCE7Goe5L4tG9VKn8ncFLPGJIttP3qJreRyx3lBVnSbp0Ya+IUs1YrXctbbUsiM7dubql2H+rLnhzsX33PgkpPcOyR01P1pymI8LLNBLotCDJjwCNIF+hOB+a34txJFiOWIX7Uw8U4h5HWO6XAZFy8/UNG5Miljv+Y6xFIVv1HQxeivKGNBWHlh/m2nvg9sSf2FEydk78zHoBaeB/XFZNgQmhfolQSnywyugPZMxxAmYqI64pvgrNpo+tLp5XFy0vmCvKJNEdrjkKfYNYks66+aBHsNd76jKocaFNu/nc24X5nqpTpBowJXLG7jAGeo7+yqj6V8mK5yNMhGT5HbcyhB+5DSkeTTHcVD+x2Hdimy0VNNXI6qjAaE3R5SlUnv5a/lt+t5HM248LwAbYSzk//Jjk1rR+AnNuBJ5HSxuVdLKqUIkwZ+k0EjFebATmHx+89ieliOv0VAuoMlFr06tjoIyvn2QojOICaB/gHdeOMM6NYoTEl3K4xPbM/Ve1n2ZdYq/PapM8IEJ33H9l3zVjb5oC5lW1B02qiD+qu4BK39RV2nYrCXZbr9Xs7F4M+YifeYVA7oMSa+qDJvNGBj5XGPnBidEDp+jWWIsRoykdjpt0vJA1PoX659UuW/cr1vB9wkI8IxgXEya8mOxEQ7QrPW5RKlha1oi1GVhdzM7tJPzehSyhe+y9zSyVELmhfcJRjC0sy39WYaaDQuCoVhz1gztR6innjUkKFBuEYRQYOsdraBitRkQC48gMPrKe/XmsvJM1o6Uo06GIq9Xiv/VEQrN7uKd7Xqy+nKkdKzy/BtkxsnXrUjc+tAuM89z33trkGYdRDdbAefYz7nVQ2HZ6SPEhT6LGhW8uBa1RU9bIryFBQHStbvbrGvdwDBZvt8z8qfyKUYzhQ=", + "urls": [ + "https://pixeldrain.com/api/file/a1H78Dc_", + "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage" + ] } }, "debian10": { "1.0.8": { - "sha256": "", - "sig": "", - "urls": [] + "sha256": "6bbbb94934d12aa125400a4565d645387515ed4eebd4e54e3e2319423966ec66", + "sig": "AgRclnw5BALJpZFKkvqkXsu8nt5gzYU62xLrPwa5CEsQVjv55LnFiPjQp8pDHi7rH+r2fh+PludH59muiYvmG1WXc52CYZih0rH3I3+Zv169bq+HoooCOuzCOgDkuGlVT7KCc0lCV5UfaWu4tme7NOiOBecEdBAG6ppyq432PjjNPdupe/MGwT4IAYfHAsoR2lPH9nyNKtzTnbMGX1EXEUPOjnsFxyVKKbfer3QKUst7aF5xh30vSzDvq5OpXseA0sCKroWIndaDHW6dLnywnaUqOEW/IyuMNuksAw9LTMFovbULRrxhF4S9VTMZ1wp8X99JlM4MBtTcN2homtqP3Mr7MEmChQR4XyqwF9lrLcq8nbGK5ni6ZpV7AfMLqTB+K+jH5rdNY2H812TYjAJA14ntGBKTRJSgPn/mzKLbBVQtpAMMZ/G/280QKkDH1E6ULEJPdBxDGRDNvDCE7Goe5L4tG9VKn8ncFLPGJIttP3qJreRyx3lBVnSbp0Ya+IUs1YrXctbbUsiM7dubql2H+rLnhzsX33PgkpPcOyR01P1pymI8LLNBLotCDJjwCNIF+hOB+a34txJFiOWIX7Uw8U4h5HWO6XAZFy8/UNG5Miljv+Y6xFIVv1HQxeivKGNBWHlh/m2nvg9sSf2FEydk78zHoBaeB/XFZNgQmhfolQSnywyugPZMxxAmYqI64pvgrNpo+tLp5XFy0vmCvKJNEdrjkKfYNYks66+aBHsNd76jKocaFNu/nc24X5nqpTpBowJXLG7jAGeo7+yqj6V8mK5yNMhGT5HbcyhB+5DSkeTTHcVD+x2Hdimy0VNNXI6qjAaE3R5SlUnv5a/lt+t5HM248LwAbYSzk//Jjk1rR+AnNuBJ5HSxuVdLKqUIkwZ+k0EjFebATmHx+89ieliOv0VAuoMlFr06tjoIyvn2QojOICaB/gHdeOMM6NYoTEl3K4xPbM/Ve1n2ZdYq/PapM8IEJ33H9l3zVjb5oC5lW1B02qiD+qu4BK39RV2nYrCXZbr9Xs7F4M+YifeYVA7oMSa+qDJvNGBj5XGPnBidEDp+jWWIsRoykdjpt0vJA1PoX659UuW/cr1vB9wkI8IxgXEya8mOxEQ7QrPW5RKlha1oi1GVhdzM7tJPzehSyhe+y9zSyVELmhfcJRjC0sy39WYaaDQuCoVhz1gztR6innjUkKFBuEYRQYOsdraBitRkQC48gMPrKe/XmsvJM1o6Uo06GIq9Xiv/VEQrN7uKd7Xqy+nKkdKzy/BtkxsnXrUjc+tAuM89z33trkGYdRDdbAefYz7nVQ2HZ6SPEhT6LGhW8uBa1RU9bIryFBQHStbvbrGvdwDBZvt8z8qfyKUYzhQ=", + "urls": [ + "https://pixeldrain.com/api/file/a1H78Dc_", + "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage" + ] } }, "fedora28": { "1.0.8": { - "sha256": "", - "sig": "", - "urls": [] + "sha256": "6bbbb94934d12aa125400a4565d645387515ed4eebd4e54e3e2319423966ec66", + "sig": "AgRclnw5BALJpZFKkvqkXsu8nt5gzYU62xLrPwa5CEsQVjv55LnFiPjQp8pDHi7rH+r2fh+PludH59muiYvmG1WXc52CYZih0rH3I3+Zv169bq+HoooCOuzCOgDkuGlVT7KCc0lCV5UfaWu4tme7NOiOBecEdBAG6ppyq432PjjNPdupe/MGwT4IAYfHAsoR2lPH9nyNKtzTnbMGX1EXEUPOjnsFxyVKKbfer3QKUst7aF5xh30vSzDvq5OpXseA0sCKroWIndaDHW6dLnywnaUqOEW/IyuMNuksAw9LTMFovbULRrxhF4S9VTMZ1wp8X99JlM4MBtTcN2homtqP3Mr7MEmChQR4XyqwF9lrLcq8nbGK5ni6ZpV7AfMLqTB+K+jH5rdNY2H812TYjAJA14ntGBKTRJSgPn/mzKLbBVQtpAMMZ/G/280QKkDH1E6ULEJPdBxDGRDNvDCE7Goe5L4tG9VKn8ncFLPGJIttP3qJreRyx3lBVnSbp0Ya+IUs1YrXctbbUsiM7dubql2H+rLnhzsX33PgkpPcOyR01P1pymI8LLNBLotCDJjwCNIF+hOB+a34txJFiOWIX7Uw8U4h5HWO6XAZFy8/UNG5Miljv+Y6xFIVv1HQxeivKGNBWHlh/m2nvg9sSf2FEydk78zHoBaeB/XFZNgQmhfolQSnywyugPZMxxAmYqI64pvgrNpo+tLp5XFy0vmCvKJNEdrjkKfYNYks66+aBHsNd76jKocaFNu/nc24X5nqpTpBowJXLG7jAGeo7+yqj6V8mK5yNMhGT5HbcyhB+5DSkeTTHcVD+x2Hdimy0VNNXI6qjAaE3R5SlUnv5a/lt+t5HM248LwAbYSzk//Jjk1rR+AnNuBJ5HSxuVdLKqUIkwZ+k0EjFebATmHx+89ieliOv0VAuoMlFr06tjoIyvn2QojOICaB/gHdeOMM6NYoTEl3K4xPbM/Ve1n2ZdYq/PapM8IEJ33H9l3zVjb5oC5lW1B02qiD+qu4BK39RV2nYrCXZbr9Xs7F4M+YifeYVA7oMSa+qDJvNGBj5XGPnBidEDp+jWWIsRoykdjpt0vJA1PoX659UuW/cr1vB9wkI8IxgXEya8mOxEQ7QrPW5RKlha1oi1GVhdzM7tJPzehSyhe+y9zSyVELmhfcJRjC0sy39WYaaDQuCoVhz1gztR6innjUkKFBuEYRQYOsdraBitRkQC48gMPrKe/XmsvJM1o6Uo06GIq9Xiv/VEQrN7uKd7Xqy+nKkdKzy/BtkxsnXrUjc+tAuM89z33trkGYdRDdbAefYz7nVQ2HZ6SPEhT6LGhW8uBa1RU9bIryFBQHStbvbrGvdwDBZvt8z8qfyKUYzhQ=", + "urls": [ + "https://pixeldrain.com/api/file/a1H78Dc_", + "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage" + ] } }, "fedora29": { "1.0.8": { - "sha256": "", - "sig": "", - "urls": [] + "sha256": "6bbbb94934d12aa125400a4565d645387515ed4eebd4e54e3e2319423966ec66", + "sig": "AgRclnw5BALJpZFKkvqkXsu8nt5gzYU62xLrPwa5CEsQVjv55LnFiPjQp8pDHi7rH+r2fh+PludH59muiYvmG1WXc52CYZih0rH3I3+Zv169bq+HoooCOuzCOgDkuGlVT7KCc0lCV5UfaWu4tme7NOiOBecEdBAG6ppyq432PjjNPdupe/MGwT4IAYfHAsoR2lPH9nyNKtzTnbMGX1EXEUPOjnsFxyVKKbfer3QKUst7aF5xh30vSzDvq5OpXseA0sCKroWIndaDHW6dLnywnaUqOEW/IyuMNuksAw9LTMFovbULRrxhF4S9VTMZ1wp8X99JlM4MBtTcN2homtqP3Mr7MEmChQR4XyqwF9lrLcq8nbGK5ni6ZpV7AfMLqTB+K+jH5rdNY2H812TYjAJA14ntGBKTRJSgPn/mzKLbBVQtpAMMZ/G/280QKkDH1E6ULEJPdBxDGRDNvDCE7Goe5L4tG9VKn8ncFLPGJIttP3qJreRyx3lBVnSbp0Ya+IUs1YrXctbbUsiM7dubql2H+rLnhzsX33PgkpPcOyR01P1pymI8LLNBLotCDJjwCNIF+hOB+a34txJFiOWIX7Uw8U4h5HWO6XAZFy8/UNG5Miljv+Y6xFIVv1HQxeivKGNBWHlh/m2nvg9sSf2FEydk78zHoBaeB/XFZNgQmhfolQSnywyugPZMxxAmYqI64pvgrNpo+tLp5XFy0vmCvKJNEdrjkKfYNYks66+aBHsNd76jKocaFNu/nc24X5nqpTpBowJXLG7jAGeo7+yqj6V8mK5yNMhGT5HbcyhB+5DSkeTTHcVD+x2Hdimy0VNNXI6qjAaE3R5SlUnv5a/lt+t5HM248LwAbYSzk//Jjk1rR+AnNuBJ5HSxuVdLKqUIkwZ+k0EjFebATmHx+89ieliOv0VAuoMlFr06tjoIyvn2QojOICaB/gHdeOMM6NYoTEl3K4xPbM/Ve1n2ZdYq/PapM8IEJ33H9l3zVjb5oC5lW1B02qiD+qu4BK39RV2nYrCXZbr9Xs7F4M+YifeYVA7oMSa+qDJvNGBj5XGPnBidEDp+jWWIsRoykdjpt0vJA1PoX659UuW/cr1vB9wkI8IxgXEya8mOxEQ7QrPW5RKlha1oi1GVhdzM7tJPzehSyhe+y9zSyVELmhfcJRjC0sy39WYaaDQuCoVhz1gztR6innjUkKFBuEYRQYOsdraBitRkQC48gMPrKe/XmsvJM1o6Uo06GIq9Xiv/VEQrN7uKd7Xqy+nKkdKzy/BtkxsnXrUjc+tAuM89z33trkGYdRDdbAefYz7nVQ2HZ6SPEhT6LGhW8uBa1RU9bIryFBQHStbvbrGvdwDBZvt8z8qfyKUYzhQ=", + "urls": [ + "https://pixeldrain.com/api/file/a1H78Dc_", + "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage" + ] } }, "fedora30": { "1.0.8": { - "sha256": "", - "sig": "", - "urls": [] + "sha256": "6bbbb94934d12aa125400a4565d645387515ed4eebd4e54e3e2319423966ec66", + "sig": "AgRclnw5BALJpZFKkvqkXsu8nt5gzYU62xLrPwa5CEsQVjv55LnFiPjQp8pDHi7rH+r2fh+PludH59muiYvmG1WXc52CYZih0rH3I3+Zv169bq+HoooCOuzCOgDkuGlVT7KCc0lCV5UfaWu4tme7NOiOBecEdBAG6ppyq432PjjNPdupe/MGwT4IAYfHAsoR2lPH9nyNKtzTnbMGX1EXEUPOjnsFxyVKKbfer3QKUst7aF5xh30vSzDvq5OpXseA0sCKroWIndaDHW6dLnywnaUqOEW/IyuMNuksAw9LTMFovbULRrxhF4S9VTMZ1wp8X99JlM4MBtTcN2homtqP3Mr7MEmChQR4XyqwF9lrLcq8nbGK5ni6ZpV7AfMLqTB+K+jH5rdNY2H812TYjAJA14ntGBKTRJSgPn/mzKLbBVQtpAMMZ/G/280QKkDH1E6ULEJPdBxDGRDNvDCE7Goe5L4tG9VKn8ncFLPGJIttP3qJreRyx3lBVnSbp0Ya+IUs1YrXctbbUsiM7dubql2H+rLnhzsX33PgkpPcOyR01P1pymI8LLNBLotCDJjwCNIF+hOB+a34txJFiOWIX7Uw8U4h5HWO6XAZFy8/UNG5Miljv+Y6xFIVv1HQxeivKGNBWHlh/m2nvg9sSf2FEydk78zHoBaeB/XFZNgQmhfolQSnywyugPZMxxAmYqI64pvgrNpo+tLp5XFy0vmCvKJNEdrjkKfYNYks66+aBHsNd76jKocaFNu/nc24X5nqpTpBowJXLG7jAGeo7+yqj6V8mK5yNMhGT5HbcyhB+5DSkeTTHcVD+x2Hdimy0VNNXI6qjAaE3R5SlUnv5a/lt+t5HM248LwAbYSzk//Jjk1rR+AnNuBJ5HSxuVdLKqUIkwZ+k0EjFebATmHx+89ieliOv0VAuoMlFr06tjoIyvn2QojOICaB/gHdeOMM6NYoTEl3K4xPbM/Ve1n2ZdYq/PapM8IEJ33H9l3zVjb5oC5lW1B02qiD+qu4BK39RV2nYrCXZbr9Xs7F4M+YifeYVA7oMSa+qDJvNGBj5XGPnBidEDp+jWWIsRoykdjpt0vJA1PoX659UuW/cr1vB9wkI8IxgXEya8mOxEQ7QrPW5RKlha1oi1GVhdzM7tJPzehSyhe+y9zSyVELmhfcJRjC0sy39WYaaDQuCoVhz1gztR6innjUkKFBuEYRQYOsdraBitRkQC48gMPrKe/XmsvJM1o6Uo06GIq9Xiv/VEQrN7uKd7Xqy+nKkdKzy/BtkxsnXrUjc+tAuM89z33trkGYdRDdbAefYz7nVQ2HZ6SPEhT6LGhW8uBa1RU9bIryFBQHStbvbrGvdwDBZvt8z8qfyKUYzhQ=", + "urls": [ + "https://pixeldrain.com/api/file/a1H78Dc_", + "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage" + ] } }, "opensuse15": { "1.0.8": { - "sha256": "", - "sig": "", - "urls": [] + "sha256": "6bbbb94934d12aa125400a4565d645387515ed4eebd4e54e3e2319423966ec66", + "sig": "AgRclnw5BALJpZFKkvqkXsu8nt5gzYU62xLrPwa5CEsQVjv55LnFiPjQp8pDHi7rH+r2fh+PludH59muiYvmG1WXc52CYZih0rH3I3+Zv169bq+HoooCOuzCOgDkuGlVT7KCc0lCV5UfaWu4tme7NOiOBecEdBAG6ppyq432PjjNPdupe/MGwT4IAYfHAsoR2lPH9nyNKtzTnbMGX1EXEUPOjnsFxyVKKbfer3QKUst7aF5xh30vSzDvq5OpXseA0sCKroWIndaDHW6dLnywnaUqOEW/IyuMNuksAw9LTMFovbULRrxhF4S9VTMZ1wp8X99JlM4MBtTcN2homtqP3Mr7MEmChQR4XyqwF9lrLcq8nbGK5ni6ZpV7AfMLqTB+K+jH5rdNY2H812TYjAJA14ntGBKTRJSgPn/mzKLbBVQtpAMMZ/G/280QKkDH1E6ULEJPdBxDGRDNvDCE7Goe5L4tG9VKn8ncFLPGJIttP3qJreRyx3lBVnSbp0Ya+IUs1YrXctbbUsiM7dubql2H+rLnhzsX33PgkpPcOyR01P1pymI8LLNBLotCDJjwCNIF+hOB+a34txJFiOWIX7Uw8U4h5HWO6XAZFy8/UNG5Miljv+Y6xFIVv1HQxeivKGNBWHlh/m2nvg9sSf2FEydk78zHoBaeB/XFZNgQmhfolQSnywyugPZMxxAmYqI64pvgrNpo+tLp5XFy0vmCvKJNEdrjkKfYNYks66+aBHsNd76jKocaFNu/nc24X5nqpTpBowJXLG7jAGeo7+yqj6V8mK5yNMhGT5HbcyhB+5DSkeTTHcVD+x2Hdimy0VNNXI6qjAaE3R5SlUnv5a/lt+t5HM248LwAbYSzk//Jjk1rR+AnNuBJ5HSxuVdLKqUIkwZ+k0EjFebATmHx+89ieliOv0VAuoMlFr06tjoIyvn2QojOICaB/gHdeOMM6NYoTEl3K4xPbM/Ve1n2ZdYq/PapM8IEJ33H9l3zVjb5oC5lW1B02qiD+qu4BK39RV2nYrCXZbr9Xs7F4M+YifeYVA7oMSa+qDJvNGBj5XGPnBidEDp+jWWIsRoykdjpt0vJA1PoX659UuW/cr1vB9wkI8IxgXEya8mOxEQ7QrPW5RKlha1oi1GVhdzM7tJPzehSyhe+y9zSyVELmhfcJRjC0sy39WYaaDQuCoVhz1gztR6innjUkKFBuEYRQYOsdraBitRkQC48gMPrKe/XmsvJM1o6Uo06GIq9Xiv/VEQrN7uKd7Xqy+nKkdKzy/BtkxsnXrUjc+tAuM89z33trkGYdRDdbAefYz7nVQ2HZ6SPEhT6LGhW8uBa1RU9bIryFBQHStbvbrGvdwDBZvt8z8qfyKUYzhQ=", + "urls": [ + "https://pixeldrain.com/api/file/a1H78Dc_", + "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage" + ] } }, "opensuse15.1": { "1.0.8": { - "sha256": "", - "sig": "", - "urls": [] + "sha256": "6bbbb94934d12aa125400a4565d645387515ed4eebd4e54e3e2319423966ec66", + "sig": "AgRclnw5BALJpZFKkvqkXsu8nt5gzYU62xLrPwa5CEsQVjv55LnFiPjQp8pDHi7rH+r2fh+PludH59muiYvmG1WXc52CYZih0rH3I3+Zv169bq+HoooCOuzCOgDkuGlVT7KCc0lCV5UfaWu4tme7NOiOBecEdBAG6ppyq432PjjNPdupe/MGwT4IAYfHAsoR2lPH9nyNKtzTnbMGX1EXEUPOjnsFxyVKKbfer3QKUst7aF5xh30vSzDvq5OpXseA0sCKroWIndaDHW6dLnywnaUqOEW/IyuMNuksAw9LTMFovbULRrxhF4S9VTMZ1wp8X99JlM4MBtTcN2homtqP3Mr7MEmChQR4XyqwF9lrLcq8nbGK5ni6ZpV7AfMLqTB+K+jH5rdNY2H812TYjAJA14ntGBKTRJSgPn/mzKLbBVQtpAMMZ/G/280QKkDH1E6ULEJPdBxDGRDNvDCE7Goe5L4tG9VKn8ncFLPGJIttP3qJreRyx3lBVnSbp0Ya+IUs1YrXctbbUsiM7dubql2H+rLnhzsX33PgkpPcOyR01P1pymI8LLNBLotCDJjwCNIF+hOB+a34txJFiOWIX7Uw8U4h5HWO6XAZFy8/UNG5Miljv+Y6xFIVv1HQxeivKGNBWHlh/m2nvg9sSf2FEydk78zHoBaeB/XFZNgQmhfolQSnywyugPZMxxAmYqI64pvgrNpo+tLp5XFy0vmCvKJNEdrjkKfYNYks66+aBHsNd76jKocaFNu/nc24X5nqpTpBowJXLG7jAGeo7+yqj6V8mK5yNMhGT5HbcyhB+5DSkeTTHcVD+x2Hdimy0VNNXI6qjAaE3R5SlUnv5a/lt+t5HM248LwAbYSzk//Jjk1rR+AnNuBJ5HSxuVdLKqUIkwZ+k0EjFebATmHx+89ieliOv0VAuoMlFr06tjoIyvn2QojOICaB/gHdeOMM6NYoTEl3K4xPbM/Ve1n2ZdYq/PapM8IEJ33H9l3zVjb5oC5lW1B02qiD+qu4BK39RV2nYrCXZbr9Xs7F4M+YifeYVA7oMSa+qDJvNGBj5XGPnBidEDp+jWWIsRoykdjpt0vJA1PoX659UuW/cr1vB9wkI8IxgXEya8mOxEQ7QrPW5RKlha1oi1GVhdzM7tJPzehSyhe+y9zSyVELmhfcJRjC0sy39WYaaDQuCoVhz1gztR6innjUkKFBuEYRQYOsdraBitRkQC48gMPrKe/XmsvJM1o6Uo06GIq9Xiv/VEQrN7uKd7Xqy+nKkdKzy/BtkxsnXrUjc+tAuM89z33trkGYdRDdbAefYz7nVQ2HZ6SPEhT6LGhW8uBa1RU9bIryFBQHStbvbrGvdwDBZvt8z8qfyKUYzhQ=", + "urls": [ + "https://pixeldrain.com/api/file/a1H78Dc_", + "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage" + ] } }, "solus": { "1.0.8": { - "sha256": "", - "sig": "", - "urls": [] + "sha256": "6bbbb94934d12aa125400a4565d645387515ed4eebd4e54e3e2319423966ec66", + "sig": "AgRclnw5BALJpZFKkvqkXsu8nt5gzYU62xLrPwa5CEsQVjv55LnFiPjQp8pDHi7rH+r2fh+PludH59muiYvmG1WXc52CYZih0rH3I3+Zv169bq+HoooCOuzCOgDkuGlVT7KCc0lCV5UfaWu4tme7NOiOBecEdBAG6ppyq432PjjNPdupe/MGwT4IAYfHAsoR2lPH9nyNKtzTnbMGX1EXEUPOjnsFxyVKKbfer3QKUst7aF5xh30vSzDvq5OpXseA0sCKroWIndaDHW6dLnywnaUqOEW/IyuMNuksAw9LTMFovbULRrxhF4S9VTMZ1wp8X99JlM4MBtTcN2homtqP3Mr7MEmChQR4XyqwF9lrLcq8nbGK5ni6ZpV7AfMLqTB+K+jH5rdNY2H812TYjAJA14ntGBKTRJSgPn/mzKLbBVQtpAMMZ/G/280QKkDH1E6ULEJPdBxDGRDNvDCE7Goe5L4tG9VKn8ncFLPGJIttP3qJreRyx3lBVnSbp0Ya+IUs1YrXctbbUsiM7dubql2H+rLnhzsX33PgkpPcOyR01P1pymI8LLNBLotCDJjwCNIF+hOB+a34txJFiOWIX7Uw8U4h5HWO6XAZFy8/UNG5Miljv+Y6xFIVv1HQxeivKGNBWHlh/m2nvg9sSf2FEydk78zHoBaeB/XFZNgQmhfolQSnywyugPZMxxAmYqI64pvgrNpo+tLp5XFy0vmCvKJNEdrjkKfYNYks66+aBHsNd76jKocaFNu/nc24X5nqpTpBowJXLG7jAGeo7+yqj6V8mK5yNMhGT5HbcyhB+5DSkeTTHcVD+x2Hdimy0VNNXI6qjAaE3R5SlUnv5a/lt+t5HM248LwAbYSzk//Jjk1rR+AnNuBJ5HSxuVdLKqUIkwZ+k0EjFebATmHx+89ieliOv0VAuoMlFr06tjoIyvn2QojOICaB/gHdeOMM6NYoTEl3K4xPbM/Ve1n2ZdYq/PapM8IEJ33H9l3zVjb5oC5lW1B02qiD+qu4BK39RV2nYrCXZbr9Xs7F4M+YifeYVA7oMSa+qDJvNGBj5XGPnBidEDp+jWWIsRoykdjpt0vJA1PoX659UuW/cr1vB9wkI8IxgXEya8mOxEQ7QrPW5RKlha1oi1GVhdzM7tJPzehSyhe+y9zSyVELmhfcJRjC0sy39WYaaDQuCoVhz1gztR6innjUkKFBuEYRQYOsdraBitRkQC48gMPrKe/XmsvJM1o6Uo06GIq9Xiv/VEQrN7uKd7Xqy+nKkdKzy/BtkxsnXrUjc+tAuM89z33trkGYdRDdbAefYz7nVQ2HZ6SPEhT6LGhW8uBa1RU9bIryFBQHStbvbrGvdwDBZvt8z8qfyKUYzhQ=", + "urls": [ + "https://pixeldrain.com/api/file/a1H78Dc_", + "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage" + ] } }, "tumbleweed": { "1.0.8": { - "sha256": "", - "sig": "", - "urls": [] + "sha256": "6bbbb94934d12aa125400a4565d645387515ed4eebd4e54e3e2319423966ec66", + "sig": "AgRclnw5BALJpZFKkvqkXsu8nt5gzYU62xLrPwa5CEsQVjv55LnFiPjQp8pDHi7rH+r2fh+PludH59muiYvmG1WXc52CYZih0rH3I3+Zv169bq+HoooCOuzCOgDkuGlVT7KCc0lCV5UfaWu4tme7NOiOBecEdBAG6ppyq432PjjNPdupe/MGwT4IAYfHAsoR2lPH9nyNKtzTnbMGX1EXEUPOjnsFxyVKKbfer3QKUst7aF5xh30vSzDvq5OpXseA0sCKroWIndaDHW6dLnywnaUqOEW/IyuMNuksAw9LTMFovbULRrxhF4S9VTMZ1wp8X99JlM4MBtTcN2homtqP3Mr7MEmChQR4XyqwF9lrLcq8nbGK5ni6ZpV7AfMLqTB+K+jH5rdNY2H812TYjAJA14ntGBKTRJSgPn/mzKLbBVQtpAMMZ/G/280QKkDH1E6ULEJPdBxDGRDNvDCE7Goe5L4tG9VKn8ncFLPGJIttP3qJreRyx3lBVnSbp0Ya+IUs1YrXctbbUsiM7dubql2H+rLnhzsX33PgkpPcOyR01P1pymI8LLNBLotCDJjwCNIF+hOB+a34txJFiOWIX7Uw8U4h5HWO6XAZFy8/UNG5Miljv+Y6xFIVv1HQxeivKGNBWHlh/m2nvg9sSf2FEydk78zHoBaeB/XFZNgQmhfolQSnywyugPZMxxAmYqI64pvgrNpo+tLp5XFy0vmCvKJNEdrjkKfYNYks66+aBHsNd76jKocaFNu/nc24X5nqpTpBowJXLG7jAGeo7+yqj6V8mK5yNMhGT5HbcyhB+5DSkeTTHcVD+x2Hdimy0VNNXI6qjAaE3R5SlUnv5a/lt+t5HM248LwAbYSzk//Jjk1rR+AnNuBJ5HSxuVdLKqUIkwZ+k0EjFebATmHx+89ieliOv0VAuoMlFr06tjoIyvn2QojOICaB/gHdeOMM6NYoTEl3K4xPbM/Ve1n2ZdYq/PapM8IEJ33H9l3zVjb5oC5lW1B02qiD+qu4BK39RV2nYrCXZbr9Xs7F4M+YifeYVA7oMSa+qDJvNGBj5XGPnBidEDp+jWWIsRoykdjpt0vJA1PoX659UuW/cr1vB9wkI8IxgXEya8mOxEQ7QrPW5RKlha1oi1GVhdzM7tJPzehSyhe+y9zSyVELmhfcJRjC0sy39WYaaDQuCoVhz1gztR6innjUkKFBuEYRQYOsdraBitRkQC48gMPrKe/XmsvJM1o6Uo06GIq9Xiv/VEQrN7uKd7Xqy+nKkdKzy/BtkxsnXrUjc+tAuM89z33trkGYdRDdbAefYz7nVQ2HZ6SPEhT6LGhW8uBa1RU9bIryFBQHStbvbrGvdwDBZvt8z8qfyKUYzhQ=", + "urls": [ + "https://pixeldrain.com/api/file/a1H78Dc_", + "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage" + ] } }, "ubuntu18.04": { "1.0.8": { - "sha256": "", - "sig": "", - "urls": [] + "sha256": "6bbbb94934d12aa125400a4565d645387515ed4eebd4e54e3e2319423966ec66", + "sig": "AgRclnw5BALJpZFKkvqkXsu8nt5gzYU62xLrPwa5CEsQVjv55LnFiPjQp8pDHi7rH+r2fh+PludH59muiYvmG1WXc52CYZih0rH3I3+Zv169bq+HoooCOuzCOgDkuGlVT7KCc0lCV5UfaWu4tme7NOiOBecEdBAG6ppyq432PjjNPdupe/MGwT4IAYfHAsoR2lPH9nyNKtzTnbMGX1EXEUPOjnsFxyVKKbfer3QKUst7aF5xh30vSzDvq5OpXseA0sCKroWIndaDHW6dLnywnaUqOEW/IyuMNuksAw9LTMFovbULRrxhF4S9VTMZ1wp8X99JlM4MBtTcN2homtqP3Mr7MEmChQR4XyqwF9lrLcq8nbGK5ni6ZpV7AfMLqTB+K+jH5rdNY2H812TYjAJA14ntGBKTRJSgPn/mzKLbBVQtpAMMZ/G/280QKkDH1E6ULEJPdBxDGRDNvDCE7Goe5L4tG9VKn8ncFLPGJIttP3qJreRyx3lBVnSbp0Ya+IUs1YrXctbbUsiM7dubql2H+rLnhzsX33PgkpPcOyR01P1pymI8LLNBLotCDJjwCNIF+hOB+a34txJFiOWIX7Uw8U4h5HWO6XAZFy8/UNG5Miljv+Y6xFIVv1HQxeivKGNBWHlh/m2nvg9sSf2FEydk78zHoBaeB/XFZNgQmhfolQSnywyugPZMxxAmYqI64pvgrNpo+tLp5XFy0vmCvKJNEdrjkKfYNYks66+aBHsNd76jKocaFNu/nc24X5nqpTpBowJXLG7jAGeo7+yqj6V8mK5yNMhGT5HbcyhB+5DSkeTTHcVD+x2Hdimy0VNNXI6qjAaE3R5SlUnv5a/lt+t5HM248LwAbYSzk//Jjk1rR+AnNuBJ5HSxuVdLKqUIkwZ+k0EjFebATmHx+89ieliOv0VAuoMlFr06tjoIyvn2QojOICaB/gHdeOMM6NYoTEl3K4xPbM/Ve1n2ZdYq/PapM8IEJ33H9l3zVjb5oC5lW1B02qiD+qu4BK39RV2nYrCXZbr9Xs7F4M+YifeYVA7oMSa+qDJvNGBj5XGPnBidEDp+jWWIsRoykdjpt0vJA1PoX659UuW/cr1vB9wkI8IxgXEya8mOxEQ7QrPW5RKlha1oi1GVhdzM7tJPzehSyhe+y9zSyVELmhfcJRjC0sy39WYaaDQuCoVhz1gztR6innjUkKFBuEYRQYOsdraBitRkQC48gMPrKe/XmsvJM1o6Uo06GIq9Xiv/VEQrN7uKd7Xqy+nKkdKzy/BtkxsnXrUjc+tAuM89z33trkGYdRDdbAefYz7nVQ2HZ6SPEhT6LGhW8uBa1RU9bIryFBQHStbvbrGvdwDBZvt8z8qfyKUYzhQ=", + "urls": [ + "https://pixeldrain.com/api/file/a1H78Dc_", + "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage" + ] } }, "ubuntu18.10": { "1.0.8": { - "sha256": "", - "sig": "", - "urls": [] + "sha256": "6bbbb94934d12aa125400a4565d645387515ed4eebd4e54e3e2319423966ec66", + "sig": "AgRclnw5BALJpZFKkvqkXsu8nt5gzYU62xLrPwa5CEsQVjv55LnFiPjQp8pDHi7rH+r2fh+PludH59muiYvmG1WXc52CYZih0rH3I3+Zv169bq+HoooCOuzCOgDkuGlVT7KCc0lCV5UfaWu4tme7NOiOBecEdBAG6ppyq432PjjNPdupe/MGwT4IAYfHAsoR2lPH9nyNKtzTnbMGX1EXEUPOjnsFxyVKKbfer3QKUst7aF5xh30vSzDvq5OpXseA0sCKroWIndaDHW6dLnywnaUqOEW/IyuMNuksAw9LTMFovbULRrxhF4S9VTMZ1wp8X99JlM4MBtTcN2homtqP3Mr7MEmChQR4XyqwF9lrLcq8nbGK5ni6ZpV7AfMLqTB+K+jH5rdNY2H812TYjAJA14ntGBKTRJSgPn/mzKLbBVQtpAMMZ/G/280QKkDH1E6ULEJPdBxDGRDNvDCE7Goe5L4tG9VKn8ncFLPGJIttP3qJreRyx3lBVnSbp0Ya+IUs1YrXctbbUsiM7dubql2H+rLnhzsX33PgkpPcOyR01P1pymI8LLNBLotCDJjwCNIF+hOB+a34txJFiOWIX7Uw8U4h5HWO6XAZFy8/UNG5Miljv+Y6xFIVv1HQxeivKGNBWHlh/m2nvg9sSf2FEydk78zHoBaeB/XFZNgQmhfolQSnywyugPZMxxAmYqI64pvgrNpo+tLp5XFy0vmCvKJNEdrjkKfYNYks66+aBHsNd76jKocaFNu/nc24X5nqpTpBowJXLG7jAGeo7+yqj6V8mK5yNMhGT5HbcyhB+5DSkeTTHcVD+x2Hdimy0VNNXI6qjAaE3R5SlUnv5a/lt+t5HM248LwAbYSzk//Jjk1rR+AnNuBJ5HSxuVdLKqUIkwZ+k0EjFebATmHx+89ieliOv0VAuoMlFr06tjoIyvn2QojOICaB/gHdeOMM6NYoTEl3K4xPbM/Ve1n2ZdYq/PapM8IEJ33H9l3zVjb5oC5lW1B02qiD+qu4BK39RV2nYrCXZbr9Xs7F4M+YifeYVA7oMSa+qDJvNGBj5XGPnBidEDp+jWWIsRoykdjpt0vJA1PoX659UuW/cr1vB9wkI8IxgXEya8mOxEQ7QrPW5RKlha1oi1GVhdzM7tJPzehSyhe+y9zSyVELmhfcJRjC0sy39WYaaDQuCoVhz1gztR6innjUkKFBuEYRQYOsdraBitRkQC48gMPrKe/XmsvJM1o6Uo06GIq9Xiv/VEQrN7uKd7Xqy+nKkdKzy/BtkxsnXrUjc+tAuM89z33trkGYdRDdbAefYz7nVQ2HZ6SPEhT6LGhW8uBa1RU9bIryFBQHStbvbrGvdwDBZvt8z8qfyKUYzhQ=", + "urls": [ + "https://pixeldrain.com/api/file/a1H78Dc_", + "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage" + ] } }, "ubuntu19.04": { "1.0.8": { - "sha256": "", - "sig": "", - "urls": [] + "sha256": "6bbbb94934d12aa125400a4565d645387515ed4eebd4e54e3e2319423966ec66", + "sig": "AgRclnw5BALJpZFKkvqkXsu8nt5gzYU62xLrPwa5CEsQVjv55LnFiPjQp8pDHi7rH+r2fh+PludH59muiYvmG1WXc52CYZih0rH3I3+Zv169bq+HoooCOuzCOgDkuGlVT7KCc0lCV5UfaWu4tme7NOiOBecEdBAG6ppyq432PjjNPdupe/MGwT4IAYfHAsoR2lPH9nyNKtzTnbMGX1EXEUPOjnsFxyVKKbfer3QKUst7aF5xh30vSzDvq5OpXseA0sCKroWIndaDHW6dLnywnaUqOEW/IyuMNuksAw9LTMFovbULRrxhF4S9VTMZ1wp8X99JlM4MBtTcN2homtqP3Mr7MEmChQR4XyqwF9lrLcq8nbGK5ni6ZpV7AfMLqTB+K+jH5rdNY2H812TYjAJA14ntGBKTRJSgPn/mzKLbBVQtpAMMZ/G/280QKkDH1E6ULEJPdBxDGRDNvDCE7Goe5L4tG9VKn8ncFLPGJIttP3qJreRyx3lBVnSbp0Ya+IUs1YrXctbbUsiM7dubql2H+rLnhzsX33PgkpPcOyR01P1pymI8LLNBLotCDJjwCNIF+hOB+a34txJFiOWIX7Uw8U4h5HWO6XAZFy8/UNG5Miljv+Y6xFIVv1HQxeivKGNBWHlh/m2nvg9sSf2FEydk78zHoBaeB/XFZNgQmhfolQSnywyugPZMxxAmYqI64pvgrNpo+tLp5XFy0vmCvKJNEdrjkKfYNYks66+aBHsNd76jKocaFNu/nc24X5nqpTpBowJXLG7jAGeo7+yqj6V8mK5yNMhGT5HbcyhB+5DSkeTTHcVD+x2Hdimy0VNNXI6qjAaE3R5SlUnv5a/lt+t5HM248LwAbYSzk//Jjk1rR+AnNuBJ5HSxuVdLKqUIkwZ+k0EjFebATmHx+89ieliOv0VAuoMlFr06tjoIyvn2QojOICaB/gHdeOMM6NYoTEl3K4xPbM/Ve1n2ZdYq/PapM8IEJ33H9l3zVjb5oC5lW1B02qiD+qu4BK39RV2nYrCXZbr9Xs7F4M+YifeYVA7oMSa+qDJvNGBj5XGPnBidEDp+jWWIsRoykdjpt0vJA1PoX659UuW/cr1vB9wkI8IxgXEya8mOxEQ7QrPW5RKlha1oi1GVhdzM7tJPzehSyhe+y9zSyVELmhfcJRjC0sy39WYaaDQuCoVhz1gztR6innjUkKFBuEYRQYOsdraBitRkQC48gMPrKe/XmsvJM1o6Uo06GIq9Xiv/VEQrN7uKd7Xqy+nKkdKzy/BtkxsnXrUjc+tAuM89z33trkGYdRDdbAefYz7nVQ2HZ6SPEhT6LGhW8uBa1RU9bIryFBQHStbvbrGvdwDBZvt8z8qfyKUYzhQ=", + "urls": [ + "https://pixeldrain.com/api/file/a1H78Dc_", + "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage" + ] } }, "win32": { From 9c290be5bc3e6673e3c734293060ef4c4b96d033 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Sat, 31 Aug 2019 00:48:07 -0500 Subject: [PATCH 20/22] Windows release --- README.md | 4 ++-- releases.json | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b9145f1..3b7563e 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,10 @@ Repertory allows you to mount Sia and/or SiaPrime blockchain storage solutions v * SiaPrime >=1.4.0 ## Downloads -* **Repertory UI v1.0.8 Linux 64-bit** [](https://pixeldrain.com/api/file/a1H78Dc_) [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage) +* **Repertory UI v1.0.8 Linux 64-bit** [](https://pixeldrain.com/u/a1H78Dc_) [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage) * NOTE: Linux distributions require `fuse` and `libfuse` to be installed. * **Repertory UI v1.0.8 OS X 64-bit** []() [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_mac.dmg) -* **Repertory UI v1.0.8 Windows 64-bit** []() [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_win.exe) +* **Repertory UI v1.0.8 Windows 64-bit** [](https://pixeldrain.com/u/u_pP3IAk) [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_win.exe) * NOTE: Windows systems require [Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019](https://aka.ms/vs/16/release/vc_redist.x64.exe) ## Supported Platforms diff --git a/releases.json b/releases.json index f121041..730aac8 100644 --- a/releases.json +++ b/releases.json @@ -149,9 +149,12 @@ }, "win32": { "1.0.8": { - "sha256": "", - "sig": "", - "urls": [] + "sha256": "1dcf2ca95ee9ce1893166e7966e4aaa465735d00476d99414c57d18e7232212f", + "sig": "AzXf0WkuGx4lXoGPgxsj2LDCAHwotKnvZHBFZv1f2A77sNtJaDQAgS3b4Hjg0AiWCRL9HzjJNprBv5lEUwc7AeRLXuj+4AI6Z7PeRaVs2NBgEHlIqldPwjime8bE2NBrkKfdDDdiAzhm3AqxgRzwhZ4sxkb3vNDdKIj4WnH79LsVCEcBgtuWalNvt3Q0i5ppBvu6+Iy/gZuGa7z+Jv2WU+Ijm7WjkmmmTdpcvP1UQTBL2UkriYOxVMIfrjHM0b2ch6RGBKUxS2h26h0xmJ7SzFoZ6lHcHDIxi8fsi7DIO/QDpottJPVgZLRuufSTyXLCbehLRI3dd1IWhQns0OTU11MBAUTRczJTaZ8nrjMesKdwbWqDDGMWOHyl39EuGIaGm3Mbi4iQWI3gz4RmX9kIWf0OSaT73okPvfjWA2Onn8IOs57TDw5fIyKKFjMkxqAPy0O+WonjJ5bd4Q/8HUpVx9M9NoClbztMQUhom2hVPkPiD3jQ8I9YcrmD9phZYkMf5As1G6RBsITsbpRA0bu9426y6K+nNJLPAM0TrW33oOziYV2z5HD1/Z+TsUMcusAPTbatjPLyLZ9kWIUqybPga8iPZW9iqszei2ywKl3EgAP/rZx2fn3qko9PvdpsoV6VBp9FxT2mguoRnkIo3lPGYXssBlfVBz0treGyjDoqcOrtciVLJbal54FTPU5o+Acuffi0Ft2F4qW7d3VglhEeA2i4zzPH2l8R0CuStei8ePMhOpebtByTPrclkvlbcOCg5adF+3/zTH9H261+P/IyrPct1ucvVpa6FlpcKfErWttRmxc9QhqiepyPUonLkHgB4Ur/ft6PzlE/+wD6arA7avSKdZqzeSksFSdnX/41fD8gL5CHfsCdbeqPvPd97CliiMCeGjVngQ5qFbC1+5DHuDopvs0yWcmDAO+nFrcQt3K01VjDYT+5plb263Ba3HKHqkT9N2gH8yWK/DdfT4Y8WAABomcgPeRSg6lAtNFv5RtWbSq9Q4dLFuhGM55EtXPG15zYAZqePCcyWYieP0wNuszcSsVNDScU8gqilwtn1oKO0ISZSYZUbdzI3fDc6SbaJNLwYdT/AlELZy0fAKILmJJN8MUXvcC7we6zyPOqwEf1ESLOb84Zw3+gPtH+Ao9dWHKdHOlyNyRzPvTYrcqSn2Uf3iHOLeoazqEEJ5Bh7jbDgVBkB4XEwijb+BvFV3cBcLdSg1Id3zZF02jkpaN4SMbEmqPbUv393CKRNs47p6ffFKKS5oUEpF6GpZq/wtjmKkdMSIzGVurbHPIaZI8JfLrEu/GAxAMGM7G3O5AiKOf0AH0wexhP5Vh6iE3MLNMA7n8SEQL5i/YUIL6b0tDL/wc=", + "urls": [ + "https://pixeldrain.com/api/file/u_pP3IAk", + "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_win.exe" + ] } } }, From 3549c5d6f42dcd8af5c2a2a7ceb5aaf6a36e18f3 Mon Sep 17 00:00:00 2001 From: Scott Graves Date: Sat, 31 Aug 2019 05:55:43 +0000 Subject: [PATCH 21/22] README.md edited online with Bitbucket --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 3b7563e..aeb9268 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,6 @@ Repertory allows you to mount Sia and/or SiaPrime blockchain storage solutions v * NOTE: Linux distributions require `fuse` and `libfuse` to be installed. * **Repertory UI v1.0.8 OS X 64-bit** []() [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_mac.dmg) * **Repertory UI v1.0.8 Windows 64-bit** [](https://pixeldrain.com/u/u_pP3IAk) [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_win.exe) - * NOTE: Windows systems require [Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019](https://aka.ms/vs/16/release/vc_redist.x64.exe) ## Supported Platforms * OS X 64-bit From d40b9089cdb51f864375832172c9c91e54e15698 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Sat, 31 Aug 2019 01:53:32 -0500 Subject: [PATCH 22/22] macOS release --- README.md | 2 +- releases.json | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index aeb9268..13f1962 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Repertory allows you to mount Sia and/or SiaPrime blockchain storage solutions v ## Downloads * **Repertory UI v1.0.8 Linux 64-bit** [](https://pixeldrain.com/u/a1H78Dc_) [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_linux_x86_64.AppImage) * NOTE: Linux distributions require `fuse` and `libfuse` to be installed. -* **Repertory UI v1.0.8 OS X 64-bit** []() [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_mac.dmg) +* **Repertory UI v1.0.8 OS X 64-bit** [](https://pixeldrain.com/u/6NjT6uEl) [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_mac.dmg) * **Repertory UI v1.0.8 Windows 64-bit** [](https://pixeldrain.com/u/u_pP3IAk) [](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_win.exe) ## Supported Platforms diff --git a/releases.json b/releases.json index 730aac8..6b8adbf 100644 --- a/releases.json +++ b/releases.json @@ -22,9 +22,12 @@ }, "darwin": { "1.0.8": { - "sha256": "", - "sig": "", - "urls": [] + "sha256": "fa978eeb6f5456c1fcea902cafb039eeda6d13f93770150564a0253341cb3d63", + "sig": "CfzV0Jl/Saq6Yqtwz21Qm5F7C/geGtmotifZrUcSFpGTaniYbtWtwJSap1tAep1EzL43l4wtxmpDM9EJ3qkquD6JMQjKK89twYotzMoWneZyyEB7obhpi/M3mfih8fYrPCgxaUkVm4DZ4DNbZn2GwjMmdCV698OnUfg2PKhVH4LnjqekqOEsU02B/cvlym2zPLLoEhjJoL8+s2ICIV3WBVDHpcF4ZF3lnI8HgfjjpvhQ+V8LQCk+LQTzIwwBDj6C1sH5V9om7ZUyZZEQk8ALcvo6EJHhhOoQ6extou5NIfBSkDir9IJW8hnTVykgYwoFXSUSAf7tvLn/fx+xpvp27hh+MQqA7KPhVyUD0I2qobm87KV9RBUuW0eqC/ijkcfacyhBnTEikSrHbew3cy69KtBTs4xaicIErQogJXcRfn0bQsVYxk1H3lRyoZnnaFliLwBw/8NQnrvjZqMiqlVXijZj6w0gWZjfrJ/s7UZ0K+yofVAyp3Qzf8JsdlUeCS+lqsv65ANWOBrUeF2Tz2neIWWISnVADmBMeacp/Xuz/bwuGLc4FnMWyhIBjBGwYLBTiaq0nk0oC6wn7a+LZoib8WtU9CAJ4v82k0e8YgiwBDPZPfU03wWWVJoRC2yUu89/6x8AQaClwNh364XWmF7bgbCyjThjC70iz2Feu0ORkj4D0vjClYnP1Kz5HOAvzCRlJTtwVnB9xrEBtV45ONaw6wRwVPkADLg/624FTHzwpi7BTTV2xCAn3kx2JvSH7n9ISySu8ZG6Z2pZ5IBs7+7jWQKmtbC8b6wB0VpYwoCcLjGIduaYtx2YKv0FvjMxOeMmrfu3X33Ab9KL/T4meu5LhqcW01JDP2MlzZ8UYebykd+0KI2mts+hGHNhCT3/d7fEh/ccmaJQ1sNl8VoKos1DlwUL+U8t7PVUNj6e4SXZK+Na9pPLI3pMPKvaoPZimbXRKShF+mYUGlLEcQLcjFTTmOnFSkIP39pa98K7mtTwy50dgcqroTm9rAoBGLcicjdlOi76XcSikYrYrBupx2LtAiWUuXrD0Zm9lQ/Lfwp3smUaC6aFNmnyxPmDJ1XscbQr3m/5oxfNopBNliZCvlGLUc/HGUpy0XcEZymPA77AZog4cHcjgAi9tsdnPHfxMmFTniThDD/SgVjTolzSu4Sm/RY2K2hCJ8qFeSuvbhmgPPWOBbNMOfsv9Nswa4Rd57uEqxxSrpAo1dzxdJPklrDsCxeexVz1/6xW3Qj+I12abMacCCa8oX+PLfpdT6hDqBSlzT3KbVz6ApWNRheM/z8kwpDCDHKGIKPZ5OjRm0SRn/SlogRCUHZ93TSOClIPRr37TDYDpvzeoSjAxnwQ2jTxuIs=", + "urls": [ + "https://pixeldrain.com/api/file/6NjT6uEl", + "https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.0.8_mac.dmg" + ] } }, "debian9": {