From 754044e5adbe149c060b0368f478c6e181aff0cf Mon Sep 17 00:00:00 2001 From: Thomas Zarebczan Date: Mon, 16 Jul 2018 00:47:50 -0400 Subject: [PATCH 01/28] chore: bump electron builder + updater Test build, exe built locally is much smaller and startup fails --- package.json | 4 +-- yarn.lock | 80 +++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index cfcc220bd..5a090f6d9 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "electron-is-dev": "^0.3.0", "electron-log": "^2.2.12", "electron-publisher-s3": "^20.8.1", - "electron-updater": "^2.21.10", + "electron-updater": "^2.23.3", "electron-window-state": "^4.1.1", "find-process": "^1.1.0", "formik": "^0.10.4", @@ -96,7 +96,7 @@ "del": "^3.0.0", "devtron": "^1.4.0", "electron": "^1.8.4", - "electron-builder": "^20.13.3", + "electron-builder": "20.21.2", "electron-devtools-installer": "^2.2.3", "electron-webpack": "^1.13.0", "eslint": "^4.19.0", diff --git a/yarn.lock b/yarn.lock index b25d9d41d..af7065c25 100644 --- a/yarn.lock +++ b/yarn.lock @@ -293,6 +293,10 @@ app-builder-bin@1.11.1: version "1.11.1" resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-1.11.1.tgz#33741167f2873cf76805c9557b62caac8ede017b" +app-builder-bin@1.11.2: + version "1.11.2" + resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-1.11.2.tgz#3cfb28cb8731253072e402513d82dcda97bb4d24" + app-root-path@^2.0.1: version "2.1.0" resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.1.0.tgz#98bf6599327ecea199309866e8140368fd2e646a" @@ -1554,6 +1558,25 @@ builder-util@5.16.0, builder-util@^5.13.0, builder-util@^5.14.0, builder-util@~5 stat-mode "^0.2.2" temp-file "^3.1.3" +builder-util@5.16.1: + version "5.16.1" + resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-5.16.1.tgz#3ac21c90ef040ff02fc8d0ee4fd5ec46929c767b" + dependencies: + "7zip-bin" "~4.0.2" + app-builder-bin "1.11.2" + bluebird-lst "^1.0.5" + builder-util-runtime "^4.4.0" + chalk "^2.4.1" + debug "^3.1.0" + fs-extra-p "^4.6.1" + is-ci "^1.1.0" + js-yaml "^3.12.0" + lazy-val "^1.0.3" + semver "^5.5.0" + source-map-support "^0.5.6" + stat-mode "^0.2.2" + temp-file "^3.1.3" + builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" @@ -2831,7 +2854,38 @@ ejs@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" -electron-builder-lib@20.20.4, electron-builder-lib@~20.20.4: +electron-builder-lib@20.21.2: + version "20.21.2" + resolved "https://registry.yarnpkg.com/electron-builder-lib/-/electron-builder-lib-20.21.2.tgz#761fb2147a62ba9e40a837f01efa73c7a3ff6fd3" + dependencies: + "7zip-bin" "~4.0.2" + app-builder-bin "1.11.2" + async-exit-hook "^2.0.1" + bluebird-lst "^1.0.5" + builder-util "5.16.1" + builder-util-runtime "4.4.0" + chromium-pickle-js "^0.2.0" + debug "^3.1.0" + ejs "^2.6.1" + electron-osx-sign "0.4.10" + electron-publish "20.22.1" + env-paths "^1.0.0" + fs-extra-p "^4.6.1" + hosted-git-info "^2.7.1" + is-ci "^1.1.0" + isbinaryfile "^3.0.2" + js-yaml "^3.12.0" + lazy-val "^1.0.3" + minimatch "^3.0.4" + normalize-package-data "^2.4.0" + plist "^3.0.1" + read-config-file "3.1.0" + sanitize-filename "^1.6.1" + semver "^5.5.0" + sumchecker "^2.0.2" + temp-file "^3.1.3" + +electron-builder-lib@~20.20.4: version "20.20.4" resolved "https://registry.yarnpkg.com/electron-builder-lib/-/electron-builder-lib-20.20.4.tgz#fd129ae85c5514f16f4f392218141ebe3dc8411d" dependencies: @@ -2862,16 +2916,16 @@ electron-builder-lib@20.20.4, electron-builder-lib@~20.20.4: sumchecker "^2.0.2" temp-file "^3.1.3" -electron-builder@^20.13.3: - version "20.20.4" - resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-20.20.4.tgz#09d879c6551df801444a153dc7b159a304e1d55d" +electron-builder@20.21.2: + version "20.21.2" + resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-20.21.2.tgz#56889c622bae3c70d3aa6fb2118c1bef22113043" dependencies: bluebird-lst "^1.0.5" - builder-util "5.16.0" + builder-util "5.16.1" builder-util-runtime "4.4.0" chalk "^2.4.1" dmg-builder "4.14.0" - electron-builder-lib "20.20.4" + electron-builder-lib "20.21.2" fs-extra-p "^4.6.1" is-ci "^1.1.0" lazy-val "^1.0.3" @@ -2942,6 +2996,18 @@ electron-publish@20.22.0: lazy-val "^1.0.3" mime "^2.3.1" +electron-publish@20.22.1: + version "20.22.1" + resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-20.22.1.tgz#c4f1c90376829bcbecef9e286166f360ec1b5bb1" + dependencies: + bluebird-lst "^1.0.5" + builder-util "~5.16.0" + builder-util-runtime "^4.4.0" + chalk "^2.4.1" + fs-extra-p "^4.6.1" + lazy-val "^1.0.3" + mime "^2.3.1" + electron-publish@~20.17.2: version "20.17.2" resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-20.17.2.tgz#b44bb4ec51497a56e9a91fdaec63f61713ee9011" @@ -2969,7 +3035,7 @@ electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.47: version "1.3.52" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.52.tgz#d2d9f1270ba4a3b967b831c40ef71fb4d9ab5ce0" -electron-updater@^2.21.10: +electron-updater@^2.23.3: version "2.23.3" resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-2.23.3.tgz#7bf054075f0cef2cd832cb533cf21adcdd5780b8" dependencies: From 31ec889565d0425ce10ff1bb8bea126ed7ad276f Mon Sep 17 00:00:00 2001 From: btzr-io Date: Wed, 6 Jun 2018 00:06:03 -0600 Subject: [PATCH 02/28] add threeViewer component --- package.json | 1 + .../component/common/loading-screen.jsx | 5 +- src/renderer/component/threeViewer/index.jsx | 269 ++++++++++++++++++ .../threeViewer/internal/detector.js | 10 + .../component/threeViewer/internal/loader.js | 35 +++ .../threeViewer/internal/renderer.js | 15 + .../component/threeViewer/internal/scene.js | 57 ++++ .../component/threeViewer/internal/three.js | 10 + yarn.lock | 4 + 9 files changed, 404 insertions(+), 2 deletions(-) create mode 100644 src/renderer/component/threeViewer/index.jsx create mode 100644 src/renderer/component/threeViewer/internal/detector.js create mode 100644 src/renderer/component/threeViewer/internal/loader.js create mode 100644 src/renderer/component/threeViewer/internal/renderer.js create mode 100644 src/renderer/component/threeViewer/internal/scene.js create mode 100644 src/renderer/component/threeViewer/internal/three.js diff --git a/package.json b/package.json index cfcc220bd..117d9114b 100644 --- a/package.json +++ b/package.json @@ -78,6 +78,7 @@ "shapeshift.io": "^1.3.1", "source-map-support": "^0.5.4", "stream-to-blob-url": "^2.1.1", + "three": "^0.93.0", "tree-kill": "^1.1.0", "y18n": "^4.0.0" }, diff --git a/src/renderer/component/common/loading-screen.jsx b/src/renderer/component/common/loading-screen.jsx index c8eb3f3fb..f313b412d 100644 --- a/src/renderer/component/common/loading-screen.jsx +++ b/src/renderer/component/common/loading-screen.jsx @@ -3,8 +3,8 @@ import React from 'react'; import Spinner from 'component/spinner'; type Props = { - status: string, spinner: boolean, + status: string, }; class LoadingScreen extends React.PureComponent { @@ -17,7 +17,8 @@ class LoadingScreen extends React.PureComponent { return (
{spinner && } - {status && {status}} + + {status}
); } diff --git a/src/renderer/component/threeViewer/index.jsx b/src/renderer/component/threeViewer/index.jsx new file mode 100644 index 000000000..28afb5c86 --- /dev/null +++ b/src/renderer/component/threeViewer/index.jsx @@ -0,0 +1,269 @@ +// @flow +import * as React from 'react'; +import * as THREE from './internal/three.js'; +import detectWebGL from './internal/detector.js'; +import ThreeScene from './internal/scene.js'; +import ThreeLoader from './internal/loader.js'; +import ThreeRenderer from './internal/renderer.js'; +import LoadingScreen from 'component/common/loading-screen'; + +type Props = { + theme: string, + autoRotate: boolean, + source: { + fileType: string, + filePath: string, + }, +}; + +class ThreeViewer extends React.PureComponent { + constructor(props: Props) { + super(props); + //Main container + this.viewer = React.createRef(); + // Object colors + this.materialColors = { + red: '#e74c3c', + blue: '#3498db', + green: '#44b098', + orange: '#f39c12', + }; + + this.state = { + error: null, + isReady: false, + isLoading: false, + }; + + this.themes = { + dark: { + gridColor: '#414e5c', + groundColor: '#13233C', + backgroundColor: '#13233C', + centerLineColor: '#7f8c8d', + }, + light: { + gridColor: '#7f8c8d', + groundColor: '#DDD', + backgroundColor: '#EEE', + centerLineColor: '#2F2F2F', + }, + }; + + const { theme } = this.props; + this.theme = this.themes[theme] || this.themes.light; + } + + createOrbitControls(camera, canvas) { + const { autoRotate } = this.props; + const controls = new THREE.OrbitControls(camera, canvas); + // Controls configuration + controls.enableDamping = true; + controls.dampingFactor = 0.75; + controls.enableZoom = true; + controls.minDistance = 1; + controls.maxDistance = 50; + controls.autoRotate = autoRotate; + return controls; + } + + createGeometry(data) { + const geometry = new THREE.Geometry(); + geometry.fromBufferGeometry(data); + geometry.computeBoundingBox(); + geometry.computeVertexNormals(); + geometry.center(); + geometry.rotateX(-Math.PI / 2); + geometry.lookAt(new THREE.Vector3(0, 0, 1)); + return geometry; + } + + createWireFrame(group) { + const wireframe = new THREE.WireframeGeometry(group.geometry); + this.wireframe = new THREE.LineSegments(wireframe); + this.wireframe.material.depthTest = false; + this.wireframe.material.opacity = 0; + this.wireframe.transparent = true; + group.add(this.wireframe); + } + + createMesh(geometry) { + const material = new THREE.MeshPhongMaterial({ + opacity: 1, + transparent: true, + depthWrite: true, + vertexColors: THREE.FaceColors, + // Positive value pushes polygon further away + polygonOffsetFactor: 1, + polygonOffsetUnits: 1, + }); + + // Set material color + material.color.set(this.materialColors.green); + + const mesh = new THREE.Mesh(geometry, material); + mesh.name = 'objectGroup'; + this.scene.add(mesh); + this.fitMeshToCamera(mesh); + this.setControlsTarget(mesh.position); + return mesh; + } + + toggleWireFrame(show = false) { + this.wireframe.opacity = show ? 1 : 0; + this.mesh.material.opacity = show ? 0 : 1; + //this.mesh.material.shading(THREE.FlatShading); + } + + fitMeshToCamera(group) { + let max = { x: 0, y: 0, z: 0 }; + let min = { x: 0, y: 0, z: 0 }; + + group.traverse(child => { + if (child instanceof THREE.Mesh) { + const box = new THREE.Box3().setFromObject(group); + // Max + max.x = box.max.x > max.x ? box.max.x : max.x; + max.y = box.max.y > max.y ? box.max.y : max.y; + max.z = box.max.z > max.z ? box.max.z : max.z; + // Min + min.x = box.min.x < min.x ? box.min.x : min.x; + min.y = box.min.y < min.y ? box.min.y : min.y; + min.z = box.min.z < min.z ? box.min.z : min.z; + } + }); + + const meshY = Math.abs(max.y - min.y); + const meshX = Math.abs(max.x - min.x); + const meshZ = Math.abs(max.z - min.z); + const scaleFactor = 10 / Math.max(meshX, meshY); + + group.scale.set(scaleFactor, scaleFactor, scaleFactor); + group.position.y = meshY / 2 * scaleFactor; + group.position.multiplyScalar(-1); + group.position.y += meshY * scaleFactor; + this.createWireFrame(group); + } + + setControlsTarget(point) { + this.controls.target.fromArray([point.x, point.y, point.z]); + this.controls.update(); + } + + startLoader() { + const { source } = this.props; + source && + ThreeLoader(source, this.renderModel.bind(this), { + onStart: this.handleStart(this), + onLoad: this.handleReady.bind(this), + onError: this.handleError.bind(this), + onProgress: this.handleProgress.bind(this), + }); + } + + handleStart() { + this.setState({ isLoading: true }); + } + + handleReady() { + // Handle load ready + this.setState({ isReady: true, isLoading: false }); + this.toggleWireFrame(); + } + + handleResize = () => { + const { offsetWidth: width, offsetHeight: height } = this.viewer.current; + this.camera.aspect = width / height; + this.camera.updateProjectionMatrix(); + this.controls.update(); + this.renderer.setSize(width, height); + }; + + handleError(url) { + this.setState({ error: "Sorry, looks like we can't load this file" }); + } + + handleProgress(url, currentItem, totalItems) { + /// Handle progress + } + + handleColorChange(color) { + if (!this.mesh) return; + const pickColor = this.materialColors[color] || this.materialColors.green; + this.mesh.material.color.set(pickColor); + this.wireframe.material.color.set(pickColor); + } + + renderModel(fileType, data) { + const geometry = this.createGeometry(data); + this.mesh = this.createMesh(geometry); + } + + renderScene() { + this.renderer = ThreeRenderer({ + antialias: true, + shadowMap: true, + }); + + this.scene = ThreeScene({ + showFog: true, + showGrid: true, + ...this.theme, + }); + + const viewer = this.viewer.current; + const canvas = this.renderer.domElement; + const { offsetWidth: width, offsetHeight: height } = viewer; + // Camera + this.camera = new THREE.PerspectiveCamera(80, width / height, 0.1, 1000); + this.camera.position.set(-9.5, 14, 11); + // Controls + this.controls = this.createOrbitControls(this.camera, canvas); + // Set viewer size + this.renderer.setSize(width, height); + // Load file and render mesh + this.startLoader(); + + const updateScene = () => { + requestAnimationFrame(updateScene); + this.controls.update(); + this.renderer.render(this.scene, this.camera); + }; + + updateScene(); + // Append canvas + viewer.appendChild(canvas); + } + + componentDidMount() { + if (detectWebGL()) { + this.renderScene(); + // Update render on resize window + window.addEventListener('resize', this.handleResize, false); + } else { + // No webgl support, handle Error... + this.state({ error: 'No webgl support!' }); + } + } + + componentWillUnmount() { + window.removeEventListener('resize', this.handleResize, false); + } + + render() { + const { isReady, isLoading, error } = this.state; + const loadingMessage = 'Rendering model.'; + const showViewer = isReady && !error; + const showLoading = isLoading && !error; + + return ( + + {error && } + {showLoading && } +
+ + ); + } +} + +export default ThreeViewer; diff --git a/src/renderer/component/threeViewer/internal/detector.js b/src/renderer/component/threeViewer/internal/detector.js new file mode 100644 index 000000000..f75d46c3f --- /dev/null +++ b/src/renderer/component/threeViewer/internal/detector.js @@ -0,0 +1,10 @@ +const detectWebGL = () => { + // Create canvas element. + const canvas = document.createElement('canvas'); + // Get WebGLRenderingContext from canvas element. + const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); + // Return the result. + return gl && gl instanceof WebGLRenderingContext; +}; + +export default detectWebGL; diff --git a/src/renderer/component/threeViewer/internal/loader.js b/src/renderer/component/threeViewer/internal/loader.js new file mode 100644 index 000000000..2ba2dc83e --- /dev/null +++ b/src/renderer/component/threeViewer/internal/loader.js @@ -0,0 +1,35 @@ +import { LoadingManager, STLLoader, OBJLoader } from './three.js'; + +const Manager = ({ onLoad, onStart, onProgress, onError }) => { + const manager = new THREE.LoadingManager(); + manager.onLoad = onLoad; + manager.onStart = onStart; + //manager.onProgress = onProgress; + manager.onError = onError; + + return manager; +}; + +const Loader = (fileType, manager) => { + const fileTypes = { + stl: () => new STLLoader(manager), + obj: () => new OBJLoader(manager), + }; + return fileTypes[fileType] ? fileTypes[fileType]() : null; +}; + +const ThreeLoader = ({ fileType, filePath }, renderModel, managerEvents) => { + if (!fileType) return; + + const manager = Manager(managerEvents); + const loader = Loader(fileType, manager); + + // Unsuported loader + if (!loader) return false; + + loader.load(filePath, data => { + renderModel(fileType, data); + }); +}; + +export default ThreeLoader; diff --git a/src/renderer/component/threeViewer/internal/renderer.js b/src/renderer/component/threeViewer/internal/renderer.js new file mode 100644 index 000000000..11b6c0545 --- /dev/null +++ b/src/renderer/component/threeViewer/internal/renderer.js @@ -0,0 +1,15 @@ +import { WebGLRenderer } from './three'; + +const ThreeRenderer = ({ antialias, shadowMap }) => { + const renderer = new WebGLRenderer({ + antialias, + }); + // Renderer configuration + renderer.setPixelRatio(window.devicePixelRatio); + renderer.gammaInput = true; + renderer.gammaOutput = true; + renderer.shadowMap.enabled = shadowMap; + return renderer; +}; + +export default ThreeRenderer; diff --git a/src/renderer/component/threeViewer/internal/scene.js b/src/renderer/component/threeViewer/internal/scene.js new file mode 100644 index 000000000..c6e79c731 --- /dev/null +++ b/src/renderer/component/threeViewer/internal/scene.js @@ -0,0 +1,57 @@ +import * as THREE from './three.js'; + +const addGrid = (scene, { gridColor, centerLineColor, size }) => { + const divisions = size / 2; + const grid = new THREE.GridHelper( + size, + divisions, + new THREE.Color(centerLineColor), + new THREE.Color(gridColor) + ); + grid.material.opacity = 0.4; + grid.material.transparent = true; + scene.add(grid); +}; + +const addLights = (scene, color, groundColor) => { + // Light color + const lightColor = new THREE.Color(color); + // Main light + const light = new THREE.HemisphereLight(lightColor, groundColor, 0.4); + // Shadow light + const shadowLight = new THREE.DirectionalLight(lightColor, 0.4); + shadowLight.position.set(100, 50, 100); + // Back light + const backLight = new THREE.DirectionalLight(lightColor, 0.6); + backLight.position.set(-100, 200, 50); + // Add lights to scene + scene.add(backLight); + scene.add(light); + scene.add(shadowLight); +}; + +const Scene = ({ backgroundColor, groundColor, showFog, showGrid, gridColor, centerLineColor }) => { + // Convert colors + backgroundColor = new THREE.Color(backgroundColor); + groundColor = new THREE.Color(groundColor); + // New scene + const scene = new THREE.Scene(); + // Background color + scene.background = backgroundColor; + // Fog effect + scene.fog = showFog === true ? new THREE.Fog(backgroundColor, 1, 95) : null; + + showGrid && + addGrid(scene, { + size: 100, + gridColor, + centerLineColor, + }); + + // Add basic lights + addLights(scene, '#FFFFFF', groundColor); + // Return new three scene + return scene; +}; + +export default Scene; diff --git a/src/renderer/component/threeViewer/internal/three.js b/src/renderer/component/threeViewer/internal/three.js new file mode 100644 index 000000000..6cb0051d0 --- /dev/null +++ b/src/renderer/component/threeViewer/internal/three.js @@ -0,0 +1,10 @@ +import * as THREE from 'three'; + +// Currently it's not possible to import the files within the "examples/js" directory. +// Fix: https://github.com/mrdoob/three.js/issues/9562#issuecomment-383390251 +global.THREE = THREE; +require('three/examples/js/controls/OrbitControls'); +require('three/examples/js/loaders/OBJLoader'); +require('three/examples/js/loaders/STLLoader'); + +module.exports = global.THREE; diff --git a/yarn.lock b/yarn.lock index b25d9d41d..160424789 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8940,6 +8940,10 @@ text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" +three@^0.93.0: + version "0.93.0" + resolved "https://registry.yarnpkg.com/three/-/three-0.93.0.tgz#3fd6c367ef4554abbb6e16ad69936283e895c123" + throttleit@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf" From 87ffac9a52c8d9ba2d71c4308a982e6b0f03f879 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sat, 9 Jun 2018 14:33:31 -0600 Subject: [PATCH 03/28] minor fixes --- src/renderer/component/threeViewer/index.jsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/renderer/component/threeViewer/index.jsx b/src/renderer/component/threeViewer/index.jsx index 28afb5c86..1c3c202f5 100644 --- a/src/renderer/component/threeViewer/index.jsx +++ b/src/renderer/component/threeViewer/index.jsx @@ -50,6 +50,7 @@ class ThreeViewer extends React.PureComponent { }, }; + // Select current theme const { theme } = this.props; this.theme = this.themes[theme] || this.themes.light; } @@ -102,9 +103,13 @@ class ThreeViewer extends React.PureComponent { material.color.set(this.materialColors.green); const mesh = new THREE.Mesh(geometry, material); + + // Assign name mesh.name = 'objectGroup'; + this.scene.add(mesh); this.fitMeshToCamera(mesh); + this.createWireFrame(mesh); this.setControlsTarget(mesh.position); return mesh; } @@ -112,7 +117,6 @@ class ThreeViewer extends React.PureComponent { toggleWireFrame(show = false) { this.wireframe.opacity = show ? 1 : 0; this.mesh.material.opacity = show ? 0 : 1; - //this.mesh.material.shading(THREE.FlatShading); } fitMeshToCamera(group) { @@ -142,7 +146,6 @@ class ThreeViewer extends React.PureComponent { group.position.y = meshY / 2 * scaleFactor; group.position.multiplyScalar(-1); group.position.y += meshY * scaleFactor; - this.createWireFrame(group); } setControlsTarget(point) { @@ -168,7 +171,6 @@ class ThreeViewer extends React.PureComponent { handleReady() { // Handle load ready this.setState({ isReady: true, isLoading: false }); - this.toggleWireFrame(); } handleResize = () => { @@ -184,7 +186,8 @@ class ThreeViewer extends React.PureComponent { } handleProgress(url, currentItem, totalItems) { - /// Handle progress + // Handle progress + // TODO: Show progressbar... } handleColorChange(color) { @@ -242,6 +245,7 @@ class ThreeViewer extends React.PureComponent { window.addEventListener('resize', this.handleResize, false); } else { // No webgl support, handle Error... + // TODO: Use a better error message this.state({ error: 'No webgl support!' }); } } From e1c10964581bb07512d497d5a90c75e67d085591 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Sun, 10 Jun 2018 21:51:39 -0600 Subject: [PATCH 04/28] add progress-bar --- .../component/common/loading-screen.jsx | 8 +++-- .../component/common/progress-bar.jsx | 23 +++++++++++++++ src/renderer/component/threeViewer/index.jsx | 29 +++++++++++-------- .../scss/component/_progress-bar.scss | 16 ++++++++++ 4 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 src/renderer/component/common/progress-bar.jsx create mode 100644 src/renderer/scss/component/_progress-bar.scss diff --git a/src/renderer/component/common/loading-screen.jsx b/src/renderer/component/common/loading-screen.jsx index f313b412d..24bc33f2e 100644 --- a/src/renderer/component/common/loading-screen.jsx +++ b/src/renderer/component/common/loading-screen.jsx @@ -1,10 +1,12 @@ // @flow import React from 'react'; import Spinner from 'component/spinner'; +import ProgressBar from 'component/common/progress-bar'; type Props = { - spinner: boolean, status: string, + spinner: boolean, + progress?: number, }; class LoadingScreen extends React.PureComponent { @@ -17,8 +19,8 @@ class LoadingScreen extends React.PureComponent { return (
{spinner && } - - {status} + {progress && } + {status && {status}}
); } diff --git a/src/renderer/component/common/progress-bar.jsx b/src/renderer/component/common/progress-bar.jsx new file mode 100644 index 000000000..8b63206ba --- /dev/null +++ b/src/renderer/component/common/progress-bar.jsx @@ -0,0 +1,23 @@ +// @flow +import React from 'react'; + +type Props = { + progress: number, +}; + +class progressBar extends React.PureComponent { + static defaultProps = { + progress: 0, + }; + + render() { + const { progress } = this.props; + return ( +
+
+
+ ); + } +} + +export default LoadingScreen; diff --git a/src/renderer/component/threeViewer/index.jsx b/src/renderer/component/threeViewer/index.jsx index 1c3c202f5..0db371092 100644 --- a/src/renderer/component/threeViewer/index.jsx +++ b/src/renderer/component/threeViewer/index.jsx @@ -19,8 +19,12 @@ type Props = { class ThreeViewer extends React.PureComponent { constructor(props: Props) { super(props); + + const { theme } = this.props; + //Main container this.viewer = React.createRef(); + // Object colors this.materialColors = { red: '#e74c3c', @@ -29,12 +33,7 @@ class ThreeViewer extends React.PureComponent { orange: '#f39c12', }; - this.state = { - error: null, - isReady: false, - isLoading: false, - }; - + // Viewer themes this.themes = { dark: { gridColor: '#414e5c', @@ -51,8 +50,14 @@ class ThreeViewer extends React.PureComponent { }; // Select current theme - const { theme } = this.props; this.theme = this.themes[theme] || this.themes.light; + + // State + this.state = { + error: null, + isReady: false, + isLoading: false, + }; } createOrbitControls(camera, canvas) { @@ -186,8 +191,8 @@ class ThreeViewer extends React.PureComponent { } handleProgress(url, currentItem, totalItems) { - // Handle progress - // TODO: Show progressbar... + const progress = (currentItem / totalItems) * 100; + this.setState({progress}); } handleColorChange(color) { @@ -255,15 +260,15 @@ class ThreeViewer extends React.PureComponent { } render() { - const { isReady, isLoading, error } = this.state; + const { error, progress, isReady, isLoading } = this.state; const loadingMessage = 'Rendering model.'; const showViewer = isReady && !error; const showLoading = isLoading && !error; return ( - {error && } - {showLoading && } + {error && } + {showLoading && }
); diff --git a/src/renderer/scss/component/_progress-bar.scss b/src/renderer/scss/component/_progress-bar.scss new file mode 100644 index 000000000..4ee4b8dbe --- /dev/null +++ b/src/renderer/scss/component/_progress-bar.scss @@ -0,0 +1,16 @@ +.progress-bar { + width: 75%; + height: 5px; + display: block; + background: rgba(255, 255, 255, 0.25); + border-radius: 3px; + overflow: hidden; +} + +.progress-bar__progress { + width: 20px; + height: 5px; + background: var(--color-primary); + border-radius: 3px; + transition: width 0.3s ease; +} From 064e28a02eebad69dab6fb29e9d9fc230d9031e4 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Tue, 12 Jun 2018 16:40:55 -0600 Subject: [PATCH 05/28] more fixes --- .../component/common/loading-screen.jsx | 3 - .../component/common/progress-bar.jsx | 23 ---- src/renderer/component/threeViewer/index.jsx | 106 ++++++++++-------- .../component/threeViewer/internal/loader.js | 25 ++--- .../component/threeViewer/internal/scene.js | 18 +-- .../scss/component/_progress-bar.scss | 16 --- 6 files changed, 79 insertions(+), 112 deletions(-) delete mode 100644 src/renderer/component/common/progress-bar.jsx delete mode 100644 src/renderer/scss/component/_progress-bar.scss diff --git a/src/renderer/component/common/loading-screen.jsx b/src/renderer/component/common/loading-screen.jsx index 24bc33f2e..c8eb3f3fb 100644 --- a/src/renderer/component/common/loading-screen.jsx +++ b/src/renderer/component/common/loading-screen.jsx @@ -1,12 +1,10 @@ // @flow import React from 'react'; import Spinner from 'component/spinner'; -import ProgressBar from 'component/common/progress-bar'; type Props = { status: string, spinner: boolean, - progress?: number, }; class LoadingScreen extends React.PureComponent { @@ -19,7 +17,6 @@ class LoadingScreen extends React.PureComponent { return (
{spinner && } - {progress && } {status && {status}}
); diff --git a/src/renderer/component/common/progress-bar.jsx b/src/renderer/component/common/progress-bar.jsx deleted file mode 100644 index 8b63206ba..000000000 --- a/src/renderer/component/common/progress-bar.jsx +++ /dev/null @@ -1,23 +0,0 @@ -// @flow -import React from 'react'; - -type Props = { - progress: number, -}; - -class progressBar extends React.PureComponent { - static defaultProps = { - progress: 0, - }; - - render() { - const { progress } = this.props; - return ( -
-
-
- ); - } -} - -export default LoadingScreen; diff --git a/src/renderer/component/threeViewer/index.jsx b/src/renderer/component/threeViewer/index.jsx index 0db371092..8c74efa10 100644 --- a/src/renderer/component/threeViewer/index.jsx +++ b/src/renderer/component/threeViewer/index.jsx @@ -1,11 +1,12 @@ // @flow import * as React from 'react'; -import * as THREE from './internal/three.js'; -import detectWebGL from './internal/detector.js'; -import ThreeScene from './internal/scene.js'; -import ThreeLoader from './internal/loader.js'; -import ThreeRenderer from './internal/renderer.js'; import LoadingScreen from 'component/common/loading-screen'; +// ThreeJS +import * as THREE from './internal/three'; +import detectWebGL from './internal/detector'; +import ThreeScene from './internal/scene'; +import ThreeLoader from './internal/loader'; +import ThreeRenderer from './internal/renderer'; type Props = { theme: string, @@ -22,7 +23,7 @@ class ThreeViewer extends React.PureComponent { const { theme } = this.props; - //Main container + // Main container this.viewer = React.createRef(); // Object colors @@ -60,6 +61,22 @@ class ThreeViewer extends React.PureComponent { }; } + componentDidMount() { + if (detectWebGL()) { + this.renderScene(); + // Update render on resize window + window.addEventListener('resize', this.handleResize, false); + } else { + // No webgl support, handle Error... + // TODO: Use a better error message + this.state({ error: "Sorry, your computer doesn't support WebGL." }); + } + } + + componentWillUnmount() { + window.removeEventListener('resize', this.handleResize, false); + } + createOrbitControls(camera, canvas) { const { autoRotate } = this.props; const controls = new THREE.OrbitControls(camera, canvas); @@ -85,11 +102,15 @@ class ThreeViewer extends React.PureComponent { } createWireFrame(group) { - const wireframe = new THREE.WireframeGeometry(group.geometry); - this.wireframe = new THREE.LineSegments(wireframe); - this.wireframe.material.depthTest = false; - this.wireframe.material.opacity = 0; - this.wireframe.transparent = true; + const wireframeGeometry = new THREE.WireframeGeometry(group.geometry); + const wireframeMaterial = new THREE.LineBasicMaterial({ + opacity: 0, + transparent: true, + linewidth: 1, + }); + // Set material color + wireframeMaterial.color.set(this.materialColors.green); + this.wireframe = new THREE.LineSegments(wireframeGeometry, wireframeMaterial); group.add(this.wireframe); } @@ -115,7 +136,7 @@ class ThreeViewer extends React.PureComponent { this.scene.add(mesh); this.fitMeshToCamera(mesh); this.createWireFrame(mesh); - this.setControlsTarget(mesh.position); + this.updateControlsTarget(mesh.position); return mesh; } @@ -125,8 +146,8 @@ class ThreeViewer extends React.PureComponent { } fitMeshToCamera(group) { - let max = { x: 0, y: 0, z: 0 }; - let min = { x: 0, y: 0, z: 0 }; + const max = { x: 0, y: 0, z: 0 }; + const min = { x: 0, y: 0, z: 0 }; group.traverse(child => { if (child instanceof THREE.Mesh) { @@ -144,29 +165,25 @@ class ThreeViewer extends React.PureComponent { const meshY = Math.abs(max.y - min.y); const meshX = Math.abs(max.x - min.x); - const meshZ = Math.abs(max.z - min.z); - const scaleFactor = 10 / Math.max(meshX, meshY); + const scaleFactor = 15 / Math.max(meshX, meshY); group.scale.set(scaleFactor, scaleFactor, scaleFactor); - group.position.y = meshY / 2 * scaleFactor; + group.position.setY((meshY / 2) * scaleFactor); group.position.multiplyScalar(-1); - group.position.y += meshY * scaleFactor; - } - - setControlsTarget(point) { - this.controls.target.fromArray([point.x, point.y, point.z]); - this.controls.update(); + group.position.setY(meshY * scaleFactor); } startLoader() { const { source } = this.props; - source && + + if (source) { ThreeLoader(source, this.renderModel.bind(this), { onStart: this.handleStart(this), onLoad: this.handleReady.bind(this), onError: this.handleError.bind(this), onProgress: this.handleProgress.bind(this), }); + } } handleStart() { @@ -186,13 +203,13 @@ class ThreeViewer extends React.PureComponent { this.renderer.setSize(width, height); }; - handleError(url) { + handleError() { this.setState({ error: "Sorry, looks like we can't load this file" }); } - handleProgress(url, currentItem, totalItems) { - const progress = (currentItem / totalItems) * 100; - this.setState({progress}); + handleProgress() { + // const progress = (currentItem / totalItems) * 100; + // console.info(currentItem, totalItems, progress); } handleColorChange(color) { @@ -202,6 +219,11 @@ class ThreeViewer extends React.PureComponent { this.wireframe.material.color.set(pickColor); } + updateControlsTarget(point) { + this.controls.target.fromArray([point.x, point.y, point.z]); + this.controls.update(); + } + renderModel(fileType, data) { const geometry = this.createGeometry(data); this.mesh = this.createMesh(geometry); @@ -243,33 +265,21 @@ class ThreeViewer extends React.PureComponent { viewer.appendChild(canvas); } - componentDidMount() { - if (detectWebGL()) { - this.renderScene(); - // Update render on resize window - window.addEventListener('resize', this.handleResize, false); - } else { - // No webgl support, handle Error... - // TODO: Use a better error message - this.state({ error: 'No webgl support!' }); - } - } - - componentWillUnmount() { - window.removeEventListener('resize', this.handleResize, false); - } - render() { - const { error, progress, isReady, isLoading } = this.state; - const loadingMessage = 'Rendering model.'; + const { error, isReady, isLoading } = this.state; + const loadingMessage = 'Loading 3D model.'; const showViewer = isReady && !error; const showLoading = isLoading && !error; return ( {error && } - {showLoading && } -
+ {showLoading && } +
); } diff --git a/src/renderer/component/threeViewer/internal/loader.js b/src/renderer/component/threeViewer/internal/loader.js index 2ba2dc83e..96bdf26b6 100644 --- a/src/renderer/component/threeViewer/internal/loader.js +++ b/src/renderer/component/threeViewer/internal/loader.js @@ -1,10 +1,10 @@ -import { LoadingManager, STLLoader, OBJLoader } from './three.js'; +import { LoadingManager, STLLoader, OBJLoader } from './three'; const Manager = ({ onLoad, onStart, onProgress, onError }) => { - const manager = new THREE.LoadingManager(); + const manager = new LoadingManager(); manager.onLoad = onLoad; manager.onStart = onStart; - //manager.onProgress = onProgress; + manager.onProgress = onProgress; manager.onError = onError; return manager; @@ -19,17 +19,16 @@ const Loader = (fileType, manager) => { }; const ThreeLoader = ({ fileType, filePath }, renderModel, managerEvents) => { - if (!fileType) return; + if (fileType) { + const manager = Manager(managerEvents); + const loader = Loader(fileType, manager); - const manager = Manager(managerEvents); - const loader = Loader(fileType, manager); - - // Unsuported loader - if (!loader) return false; - - loader.load(filePath, data => { - renderModel(fileType, data); - }); + if (loader) { + loader.load(filePath, data => { + renderModel(fileType, data); + }); + } + } }; export default ThreeLoader; diff --git a/src/renderer/component/threeViewer/internal/scene.js b/src/renderer/component/threeViewer/internal/scene.js index c6e79c731..f858c8832 100644 --- a/src/renderer/component/threeViewer/internal/scene.js +++ b/src/renderer/component/threeViewer/internal/scene.js @@ -1,4 +1,4 @@ -import * as THREE from './three.js'; +import * as THREE from './three'; const addGrid = (scene, { gridColor, centerLineColor, size }) => { const divisions = size / 2; @@ -31,25 +31,25 @@ const addLights = (scene, color, groundColor) => { }; const Scene = ({ backgroundColor, groundColor, showFog, showGrid, gridColor, centerLineColor }) => { - // Convert colors - backgroundColor = new THREE.Color(backgroundColor); - groundColor = new THREE.Color(groundColor); + // Convert color + const bgColor = new THREE.Color(backgroundColor); // New scene const scene = new THREE.Scene(); // Background color - scene.background = backgroundColor; + scene.background = bgColor; // Fog effect - scene.fog = showFog === true ? new THREE.Fog(backgroundColor, 1, 95) : null; - - showGrid && + scene.fog = showFog === true ? new THREE.Fog(bgColor, 1, 95) : null; + // Add grid + if (showGrid) { addGrid(scene, { size: 100, gridColor, centerLineColor, }); - + } // Add basic lights addLights(scene, '#FFFFFF', groundColor); + // Return new three scene return scene; }; diff --git a/src/renderer/scss/component/_progress-bar.scss b/src/renderer/scss/component/_progress-bar.scss deleted file mode 100644 index 4ee4b8dbe..000000000 --- a/src/renderer/scss/component/_progress-bar.scss +++ /dev/null @@ -1,16 +0,0 @@ -.progress-bar { - width: 75%; - height: 5px; - display: block; - background: rgba(255, 255, 255, 0.25); - border-radius: 3px; - overflow: hidden; -} - -.progress-bar__progress { - width: 20px; - height: 5px; - background: var(--color-primary); - border-radius: 3px; - transition: width 0.3s ease; -} From 34ba2cf3ebad8383e045d606ff8b5c27921e53a7 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Tue, 12 Jun 2018 17:18:00 -0600 Subject: [PATCH 06/28] fix object position --- src/renderer/component/threeViewer/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/component/threeViewer/index.jsx b/src/renderer/component/threeViewer/index.jsx index 8c74efa10..475630421 100644 --- a/src/renderer/component/threeViewer/index.jsx +++ b/src/renderer/component/threeViewer/index.jsx @@ -170,7 +170,7 @@ class ThreeViewer extends React.PureComponent { group.scale.set(scaleFactor, scaleFactor, scaleFactor); group.position.setY((meshY / 2) * scaleFactor); group.position.multiplyScalar(-1); - group.position.setY(meshY * scaleFactor); + group.position.setY((meshY * scaleFactor) / 2); } startLoader() { From ac89a3d91cefbb876324f8045ce2773ab1d4a178 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Mon, 16 Jul 2018 10:38:46 -0400 Subject: [PATCH 07/28] re-add 3d-file viewer --- src/renderer/component/fileRender/view.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/renderer/component/fileRender/view.jsx b/src/renderer/component/fileRender/view.jsx index 5ce35c6b7..dba8ecbb2 100644 --- a/src/renderer/component/fileRender/view.jsx +++ b/src/renderer/component/fileRender/view.jsx @@ -2,6 +2,7 @@ import React from 'react'; import LoadingScreen from 'component/common/loading-screen'; import PdfViewer from 'component/viewers/pdfViewer'; +import ThreeViewer from 'component/threeViewer'; type Props = { mediaType: string, @@ -20,7 +21,7 @@ class FileRender extends React.PureComponent { // Supported mediaTypes const mediaTypes = { - // '3D-file': , + '3D-file': , // Add routes to viewer... }; From d43dd7882192f0481df8126016181eedcd0aa946 Mon Sep 17 00:00:00 2001 From: Travis Eden Date: Thu, 12 Jul 2018 15:37:01 -0400 Subject: [PATCH 08/28] suppress load video error; disable autoplay per-video after download failure --- src/renderer/component/fileViewer/index.js | 2 ++ src/renderer/component/fileViewer/view.jsx | 16 ++++++++-- src/renderer/redux/actions/content.js | 36 +++++++++++++--------- src/renderer/redux/selectors/file_info.js | 8 +++-- 4 files changed, 43 insertions(+), 19 deletions(-) diff --git a/src/renderer/component/fileViewer/index.js b/src/renderer/component/fileViewer/index.js index 00ef7c3c0..2e77b38d4 100644 --- a/src/renderer/component/fileViewer/index.js +++ b/src/renderer/component/fileViewer/index.js @@ -17,6 +17,7 @@ import { import { makeSelectClientSetting, selectShowNsfw } from 'redux/selectors/settings'; import { selectMediaPaused, makeSelectMediaPositionForUri } from 'redux/selectors/media'; import { selectPlayingUri } from 'redux/selectors/content'; +import { selectFileInfoErrors } from 'redux/selectors/file_info'; import FileViewer from './view'; const select = (state, props) => ({ @@ -34,6 +35,7 @@ const select = (state, props) => ({ mediaPosition: makeSelectMediaPositionForUri(props.uri)(state), autoplay: makeSelectClientSetting(settings.AUTOPLAY)(state), searchBarFocused: selectSearchBarFocused(state), + fileInfoErrors: selectFileInfoErrors(state) }); const perform = dispatch => ({ diff --git a/src/renderer/component/fileViewer/view.jsx b/src/renderer/component/fileViewer/view.jsx index 2a0d9f53d..0a16d9f92 100644 --- a/src/renderer/component/fileViewer/view.jsx +++ b/src/renderer/component/fileViewer/view.jsx @@ -79,10 +79,22 @@ class FileViewer extends React.PureComponent { } } + // do not play when state.content.errors[uri] handleAutoplay = (props: Props) => { - const { autoplay, playingUri, fileInfo, costInfo, isDownloading, uri, play, metadata } = props; + const { + autoplay, + playingUri, + fileInfo, + costInfo, + isDownloading, + uri, + play, + metadata, + fileInfoErrors, + } = props; - const playable = autoplay && playingUri !== uri && metadata && !metadata.nsfw; + const playable = + autoplay && playingUri !== uri && metadata && !metadata.nsfw && !(uri in fileInfoErrors); if (playable && costInfo && costInfo.cost === 0 && !fileInfo && !isDownloading) { play(uri); diff --git a/src/renderer/redux/actions/content.js b/src/renderer/redux/actions/content.js index f16d89f6f..c50bff457 100644 --- a/src/renderer/redux/actions/content.js +++ b/src/renderer/redux/actions/content.js @@ -171,7 +171,7 @@ export function doUpdateLoadStatus(uri, outpoint) { } else { // ready to play const { total_bytes: totalBytes, written_bytes: writtenBytes } = fileInfo; - const progress = writtenBytes / totalBytes * 100; + const progress = (writtenBytes / totalBytes) * 100; dispatch({ type: ACTIONS.DOWNLOADING_PROGRESSED, @@ -259,29 +259,37 @@ export function doLoadVideo(uri) { streamInfo === null || typeof streamInfo !== 'object' || streamInfo.error === 'Timeout'; if (timeout) { - dispatch(doSetPlayingUri(null)); - dispatch({ - type: ACTIONS.LOADING_VIDEO_FAILED, - data: { uri }, - }); - - dispatch(doNotify({ id: MODALS.FILE_TIMEOUT }, { uri })); + dispatch(handleLoadVideoError(uri, 'timeout')); } else { dispatch(doDownloadFile(uri, streamInfo)); } }) .catch(() => { - dispatch(doSetPlayingUri(null)); - dispatch({ - type: ACTIONS.LOADING_VIDEO_FAILED, - data: { uri }, - }); + dispatch(handleLoadVideoError(uri)); + }); + }; +} + +function handleLoadVideoError(uri, errorType = '') { + return (dispatch, getState) => { + // suppress error when another media is playing + const { playingUri } = getState().content; + if (!playingUri || playingUri === uri) { + dispatch({ + type: ACTIONS.LOADING_VIDEO_FAILED, + data: { uri }, + }); + dispatch(doSetPlayingUri(null)); + if (errorType === 'timeout') { + doNotify({ id: MODALS.FILE_TIMEOUT }, { uri }); + } else { dispatch( doAlertError( `Failed to download ${uri}, please try again. If this problem persists, visit https://lbry.io/faq/support for support.` ) ); - }); + } + } }; } diff --git a/src/renderer/redux/selectors/file_info.js b/src/renderer/redux/selectors/file_info.js index 801ced0b4..d49f2e9a2 100644 --- a/src/renderer/redux/selectors/file_info.js +++ b/src/renderer/redux/selectors/file_info.js @@ -3,9 +3,9 @@ import { selectIsFetchingClaimListMine, selectMyClaims, selectClaimsById, -} from 'redux/selectors/claims'; + buildURI, +} from 'lbry-redux'; import { createSelector } from 'reselect'; -import { buildURI } from 'lbryURI'; export const selectState = state => state.fileInfo || {}; @@ -97,7 +97,7 @@ export const selectTotalDownloadProgress = createSelector(selectDownloadingFileI const progress = []; fileInfos.forEach(fileInfo => { - progress.push(fileInfo.written_bytes / fileInfo.total_bytes * 100); + progress.push((fileInfo.written_bytes / fileInfo.total_bytes) * 100); }); const totalProgress = progress.reduce((a, b) => a + b, 0); @@ -195,3 +195,5 @@ export const selectSearchDownloadUris = query => }) : null; }); + +export const selectFileInfoErrors = createSelector(selectState, state => state.errors || {}); From 17ca490db40156dac7ee5f3e98497a7349f36137 Mon Sep 17 00:00:00 2001 From: Travis Eden Date: Wed, 18 Jul 2018 10:29:43 -0400 Subject: [PATCH 09/28] display download error only when that uri is playing --- src/renderer/redux/actions/content.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/redux/actions/content.js b/src/renderer/redux/actions/content.js index c50bff457..04808b6e1 100644 --- a/src/renderer/redux/actions/content.js +++ b/src/renderer/redux/actions/content.js @@ -274,7 +274,7 @@ function handleLoadVideoError(uri, errorType = '') { return (dispatch, getState) => { // suppress error when another media is playing const { playingUri } = getState().content; - if (!playingUri || playingUri === uri) { + if (playingUri && playingUri === uri) { dispatch({ type: ACTIONS.LOADING_VIDEO_FAILED, data: { uri }, From bc68b75012d0e7eab061238f7c83d88f50550ef3 Mon Sep 17 00:00:00 2001 From: Travis Eden Date: Wed, 18 Jul 2018 10:41:14 -0400 Subject: [PATCH 10/28] prevent handleAutoplay in componentDidUpdate --- src/renderer/component/fileViewer/view.jsx | 34 +++++++++------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/src/renderer/component/fileViewer/view.jsx b/src/renderer/component/fileViewer/view.jsx index 0a16d9f92..406c25186 100644 --- a/src/renderer/component/fileViewer/view.jsx +++ b/src/renderer/component/fileViewer/view.jsx @@ -17,6 +17,9 @@ type Props = { download_path: string, completed: boolean, }, + fileInfoErrors: ?{ + [string]: boolean, + }, metadata: ?{ nsfw: boolean, thumbnail: string, @@ -55,14 +58,17 @@ class FileViewer extends React.PureComponent { window.addEventListener('keydown', this.handleKeyDown); } - componentWillReceiveProps(nextProps: Props) { + componentDidUpdate(prev: Props) { if ( - this.props.autoplay !== nextProps.autoplay || - this.props.fileInfo !== nextProps.fileInfo || - this.props.isDownloading !== nextProps.isDownloading || - this.props.playingUri !== nextProps.playingUri + this.props.autoplay !== prev.autoplay || + this.props.fileInfo !== prev.fileInfo || + this.props.isDownloading !== prev.isDownloading || + this.props.playingUri !== prev.playingUri ) { - this.handleAutoplay(nextProps); + // suppress autoplay after download error + if (!(this.props.uri in this.props.fileInfoErrors)) { + this.handleAutoplay(this.props); + } } } @@ -79,22 +85,10 @@ class FileViewer extends React.PureComponent { } } - // do not play when state.content.errors[uri] handleAutoplay = (props: Props) => { - const { - autoplay, - playingUri, - fileInfo, - costInfo, - isDownloading, - uri, - play, - metadata, - fileInfoErrors, - } = props; + const { autoplay, playingUri, fileInfo, costInfo, isDownloading, uri, play, metadata } = props; - const playable = - autoplay && playingUri !== uri && metadata && !metadata.nsfw && !(uri in fileInfoErrors); + const playable = autoplay && playingUri !== uri && metadata && !metadata.nsfw; if (playable && costInfo && costInfo.cost === 0 && !fileInfo && !isDownloading) { play(uri); From 0038ff06ed2e0f325ced6286c4ae5a8cd3affa38 Mon Sep 17 00:00:00 2001 From: Thomas Zarebczan Date: Wed, 18 Jul 2018 12:28:44 -0400 Subject: [PATCH 11/28] chore: bump electron-builder To version 20.22.0 which was tested on Mac/Windows for the autoupgrade process. --- package.json | 2 +- yarn.lock | 124 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 73 insertions(+), 53 deletions(-) diff --git a/package.json b/package.json index 5a090f6d9..134bec72c 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,7 @@ "del": "^3.0.0", "devtron": "^1.4.0", "electron": "^1.8.4", - "electron-builder": "20.21.2", + "electron-builder": "^20.22.0", "electron-devtools-installer": "^2.2.3", "electron-webpack": "^1.13.0", "eslint": "^4.19.0", diff --git a/yarn.lock b/yarn.lock index af7065c25..b2da2f0bf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -297,6 +297,10 @@ app-builder-bin@1.11.2: version "1.11.2" resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-1.11.2.tgz#3cfb28cb8731253072e402513d82dcda97bb4d24" +app-builder-bin@1.11.3: + version "1.11.3" + resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-1.11.3.tgz#cc936e0b87e1fbe0cd797d7fba3fd8081f36f0cf" + app-root-path@^2.0.1: version "2.1.0" resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.1.0.tgz#98bf6599327ecea199309866e8140368fd2e646a" @@ -1530,7 +1534,16 @@ buffers@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" -builder-util-runtime@4.4.0, builder-util-runtime@^4.4.0, builder-util-runtime@~4.4.0: +builder-util-runtime@4.4.1, builder-util-runtime@^4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-4.4.1.tgz#2770d03241e51fde46acacc7ed3ed8a9f45f02cb" + dependencies: + bluebird-lst "^1.0.5" + debug "^3.1.0" + fs-extra-p "^4.6.1" + sax "^1.2.4" + +builder-util-runtime@^4.4.0, builder-util-runtime@~4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-4.4.0.tgz#1f486819df12a04abfa128fe082e7c54edda0ef7" dependencies: @@ -1539,14 +1552,14 @@ builder-util-runtime@4.4.0, builder-util-runtime@^4.4.0, builder-util-runtime@~4 fs-extra-p "^4.6.1" sax "^1.2.4" -builder-util@5.16.0, builder-util@^5.13.0, builder-util@^5.14.0, builder-util@~5.16.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-5.16.0.tgz#8b9aabe15a1a5c4ffa8ebc511049248918f717df" +builder-util@5.16.2: + version "5.16.2" + resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-5.16.2.tgz#21b705cd9ea6a6940e3abf541f3e6ee8b8be6e14" dependencies: "7zip-bin" "~4.0.2" - app-builder-bin "1.11.1" + app-builder-bin "1.11.2" bluebird-lst "^1.0.5" - builder-util-runtime "^4.4.0" + builder-util-runtime "^4.4.1" chalk "^2.4.1" debug "^3.1.0" fs-extra-p "^4.6.1" @@ -1558,12 +1571,31 @@ builder-util@5.16.0, builder-util@^5.13.0, builder-util@^5.14.0, builder-util@~5 stat-mode "^0.2.2" temp-file "^3.1.3" -builder-util@5.16.1: - version "5.16.1" - resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-5.16.1.tgz#3ac21c90ef040ff02fc8d0ee4fd5ec46929c767b" +builder-util@5.16.3, builder-util@~5.16.2: + version "5.16.3" + resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-5.16.3.tgz#05b61688bef3f9f28e53152604e339d515d1ece6" dependencies: "7zip-bin" "~4.0.2" - app-builder-bin "1.11.2" + app-builder-bin "1.11.3" + bluebird-lst "^1.0.5" + builder-util-runtime "^4.4.1" + chalk "^2.4.1" + debug "^3.1.0" + fs-extra-p "^4.6.1" + is-ci "^1.1.0" + js-yaml "^3.12.0" + lazy-val "^1.0.3" + semver "^5.5.0" + source-map-support "^0.5.6" + stat-mode "^0.2.2" + temp-file "^3.1.3" + +builder-util@^5.13.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-5.16.0.tgz#8b9aabe15a1a5c4ffa8ebc511049248918f717df" + dependencies: + "7zip-bin" "~4.0.2" + app-builder-bin "1.11.1" bluebird-lst "^1.0.5" builder-util-runtime "^4.4.0" chalk "^2.4.1" @@ -2683,13 +2715,13 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" -dmg-builder@4.14.0: - version "4.14.0" - resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-4.14.0.tgz#6d19922a82cee78cc13557ab0cbc16047864002a" +dmg-builder@4.14.1: + version "4.14.1" + resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-4.14.1.tgz#af1e2c7b40407291555f72df9bfee2ed7d0ebf68" dependencies: bluebird-lst "^1.0.5" - builder-util "~5.16.0" - electron-builder-lib "~20.20.4" + builder-util "~5.16.2" + electron-builder-lib "~20.22.0" fs-extra-p "^4.6.1" iconv-lite "^0.4.23" js-yaml "^3.12.0" @@ -2854,21 +2886,21 @@ ejs@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" -electron-builder-lib@20.21.2: - version "20.21.2" - resolved "https://registry.yarnpkg.com/electron-builder-lib/-/electron-builder-lib-20.21.2.tgz#761fb2147a62ba9e40a837f01efa73c7a3ff6fd3" +electron-builder-lib@20.22.0: + version "20.22.0" + resolved "https://registry.yarnpkg.com/electron-builder-lib/-/electron-builder-lib-20.22.0.tgz#594077a3ffdb0ccfb18e79959ca7a5fc8662912c" dependencies: "7zip-bin" "~4.0.2" app-builder-bin "1.11.2" async-exit-hook "^2.0.1" bluebird-lst "^1.0.5" - builder-util "5.16.1" - builder-util-runtime "4.4.0" + builder-util "5.16.2" + builder-util-runtime "4.4.1" chromium-pickle-js "^0.2.0" debug "^3.1.0" ejs "^2.6.1" electron-osx-sign "0.4.10" - electron-publish "20.22.1" + electron-publish "20.22.2" env-paths "^1.0.0" fs-extra-p "^4.6.1" hosted-git-info "^2.7.1" @@ -2885,21 +2917,21 @@ electron-builder-lib@20.21.2: sumchecker "^2.0.2" temp-file "^3.1.3" -electron-builder-lib@~20.20.4: - version "20.20.4" - resolved "https://registry.yarnpkg.com/electron-builder-lib/-/electron-builder-lib-20.20.4.tgz#fd129ae85c5514f16f4f392218141ebe3dc8411d" +electron-builder-lib@~20.22.0: + version "20.22.1" + resolved "https://registry.yarnpkg.com/electron-builder-lib/-/electron-builder-lib-20.22.1.tgz#d6d4cfd4ccc6efb747d15868f2361cefbbc9716f" dependencies: "7zip-bin" "~4.0.2" - app-builder-bin "1.11.1" + app-builder-bin "1.11.3" async-exit-hook "^2.0.1" bluebird-lst "^1.0.5" - builder-util "5.16.0" - builder-util-runtime "4.4.0" + builder-util "5.16.3" + builder-util-runtime "4.4.1" chromium-pickle-js "^0.2.0" debug "^3.1.0" ejs "^2.6.1" electron-osx-sign "0.4.10" - electron-publish "20.22.0" + electron-publish "20.22.2" env-paths "^1.0.0" fs-extra-p "^4.6.1" hosted-git-info "^2.7.1" @@ -2916,16 +2948,16 @@ electron-builder-lib@~20.20.4: sumchecker "^2.0.2" temp-file "^3.1.3" -electron-builder@20.21.2: - version "20.21.2" - resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-20.21.2.tgz#56889c622bae3c70d3aa6fb2118c1bef22113043" +electron-builder@^20.22.0: + version "20.22.0" + resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-20.22.0.tgz#90760c2335e0673d1c2d24af7a2f8e33646e9303" dependencies: bluebird-lst "^1.0.5" - builder-util "5.16.1" - builder-util-runtime "4.4.0" + builder-util "5.16.2" + builder-util-runtime "4.4.1" chalk "^2.4.1" - dmg-builder "4.14.0" - electron-builder-lib "20.21.2" + dmg-builder "4.14.1" + electron-builder-lib "20.22.0" fs-extra-p "^4.6.1" is-ci "^1.1.0" lazy-val "^1.0.3" @@ -2984,25 +3016,13 @@ electron-osx-sign@0.4.10: minimist "^1.2.0" plist "^2.1.0" -electron-publish@20.22.0: - version "20.22.0" - resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-20.22.0.tgz#352f04fc4821176e0c40a16d64b1c94026e2441f" +electron-publish@20.22.2: + version "20.22.2" + resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-20.22.2.tgz#4a680de581b0d7339aff113fd8a505a0976a0d58" dependencies: bluebird-lst "^1.0.5" - builder-util "^5.14.0" - builder-util-runtime "^4.4.0" - chalk "^2.4.1" - fs-extra-p "^4.6.1" - lazy-val "^1.0.3" - mime "^2.3.1" - -electron-publish@20.22.1: - version "20.22.1" - resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-20.22.1.tgz#c4f1c90376829bcbecef9e286166f360ec1b5bb1" - dependencies: - bluebird-lst "^1.0.5" - builder-util "~5.16.0" - builder-util-runtime "^4.4.0" + builder-util "~5.16.2" + builder-util-runtime "^4.4.1" chalk "^2.4.1" fs-extra-p "^4.6.1" lazy-val "^1.0.3" From 7db1782c5730a758a0e0f9287c311707b67a0bc3 Mon Sep 17 00:00:00 2001 From: btzr-io Date: Thu, 19 Jul 2018 00:45:32 -0600 Subject: [PATCH 12/28] more minor fixes --- src/main/index.js | 7 +++++ src/renderer/component/fileRender/view.jsx | 2 +- .../{ => viewers}/threeViewer/index.jsx | 31 +++++++------------ .../threeViewer/internal/detector.js | 0 .../threeViewer/internal/loader.js | 3 +- .../threeViewer/internal/renderer.js | 0 .../threeViewer/internal/scene.js | 0 .../threeViewer/internal/three.js | 0 8 files changed, 21 insertions(+), 22 deletions(-) rename src/renderer/component/{ => viewers}/threeViewer/index.jsx (93%) rename src/renderer/component/{ => viewers}/threeViewer/internal/detector.js (100%) rename src/renderer/component/{ => viewers}/threeViewer/internal/loader.js (88%) rename src/renderer/component/{ => viewers}/threeViewer/internal/renderer.js (100%) rename src/renderer/component/{ => viewers}/threeViewer/internal/scene.js (100%) rename src/renderer/component/{ => viewers}/threeViewer/internal/three.js (100%) diff --git a/src/main/index.js b/src/main/index.js index 807ca08e4..1c81d6217 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -53,6 +53,13 @@ app.setAsDefaultProtocolClient('lbry'); app.setName('LBRY'); app.setAppUserModelId('io.lbry.LBRY'); +if (isDev) { + // Enable WEBGL + app.commandLine.appendSwitch('ignore-gpu-blacklist'); + app.commandLine.appendSwitch('--disable-gpu-process-crash-limit'); + app.disableDomainBlockingFor3DAPIs(); +} + app.on('ready', async () => { const processList = await findProcess('name', 'lbrynet-daemon'); const isDaemonRunning = processList.length > 0; diff --git a/src/renderer/component/fileRender/view.jsx b/src/renderer/component/fileRender/view.jsx index dba8ecbb2..79aca834a 100644 --- a/src/renderer/component/fileRender/view.jsx +++ b/src/renderer/component/fileRender/view.jsx @@ -2,7 +2,7 @@ import React from 'react'; import LoadingScreen from 'component/common/loading-screen'; import PdfViewer from 'component/viewers/pdfViewer'; -import ThreeViewer from 'component/threeViewer'; +import ThreeViewer from 'component/viewers/threeViewer'; type Props = { mediaType: string, diff --git a/src/renderer/component/threeViewer/index.jsx b/src/renderer/component/viewers/threeViewer/index.jsx similarity index 93% rename from src/renderer/component/threeViewer/index.jsx rename to src/renderer/component/viewers/threeViewer/index.jsx index 475630421..63dc38622 100644 --- a/src/renderer/component/threeViewer/index.jsx +++ b/src/renderer/component/viewers/threeViewer/index.jsx @@ -69,7 +69,7 @@ class ThreeViewer extends React.PureComponent { } else { // No webgl support, handle Error... // TODO: Use a better error message - this.state({ error: "Sorry, your computer doesn't support WebGL." }); + this.setState({ error: "Sorry, your computer doesn't support WebGL." }); } } @@ -178,22 +178,24 @@ class ThreeViewer extends React.PureComponent { if (source) { ThreeLoader(source, this.renderModel.bind(this), { - onStart: this.handleStart(this), - onLoad: this.handleReady.bind(this), - onError: this.handleError.bind(this), - onProgress: this.handleProgress.bind(this), + onStart: this.handleStart, + onLoad: this.handleReady, + onError: this.handleError, }); } } - handleStart() { + handleStart = () => { this.setState({ isLoading: true }); - } + }; - handleReady() { - // Handle load ready + handleReady = () => { this.setState({ isReady: true, isLoading: false }); - } + }; + + handleError = () => { + this.setState({ error: "Sorry, looks like we can't load this file" }); + }; handleResize = () => { const { offsetWidth: width, offsetHeight: height } = this.viewer.current; @@ -203,15 +205,6 @@ class ThreeViewer extends React.PureComponent { this.renderer.setSize(width, height); }; - handleError() { - this.setState({ error: "Sorry, looks like we can't load this file" }); - } - - handleProgress() { - // const progress = (currentItem / totalItems) * 100; - // console.info(currentItem, totalItems, progress); - } - handleColorChange(color) { if (!this.mesh) return; const pickColor = this.materialColors[color] || this.materialColors.green; diff --git a/src/renderer/component/threeViewer/internal/detector.js b/src/renderer/component/viewers/threeViewer/internal/detector.js similarity index 100% rename from src/renderer/component/threeViewer/internal/detector.js rename to src/renderer/component/viewers/threeViewer/internal/detector.js diff --git a/src/renderer/component/threeViewer/internal/loader.js b/src/renderer/component/viewers/threeViewer/internal/loader.js similarity index 88% rename from src/renderer/component/threeViewer/internal/loader.js rename to src/renderer/component/viewers/threeViewer/internal/loader.js index 96bdf26b6..dc4ce7482 100644 --- a/src/renderer/component/threeViewer/internal/loader.js +++ b/src/renderer/component/viewers/threeViewer/internal/loader.js @@ -1,10 +1,9 @@ import { LoadingManager, STLLoader, OBJLoader } from './three'; -const Manager = ({ onLoad, onStart, onProgress, onError }) => { +const Manager = ({ onLoad, onStart, onError }) => { const manager = new LoadingManager(); manager.onLoad = onLoad; manager.onStart = onStart; - manager.onProgress = onProgress; manager.onError = onError; return manager; diff --git a/src/renderer/component/threeViewer/internal/renderer.js b/src/renderer/component/viewers/threeViewer/internal/renderer.js similarity index 100% rename from src/renderer/component/threeViewer/internal/renderer.js rename to src/renderer/component/viewers/threeViewer/internal/renderer.js diff --git a/src/renderer/component/threeViewer/internal/scene.js b/src/renderer/component/viewers/threeViewer/internal/scene.js similarity index 100% rename from src/renderer/component/threeViewer/internal/scene.js rename to src/renderer/component/viewers/threeViewer/internal/scene.js diff --git a/src/renderer/component/threeViewer/internal/three.js b/src/renderer/component/viewers/threeViewer/internal/three.js similarity index 100% rename from src/renderer/component/threeViewer/internal/three.js rename to src/renderer/component/viewers/threeViewer/internal/three.js From 61dc4cb73c9d5b4326df75b5f95fb51706dfa6e5 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Thu, 19 Jul 2018 09:55:33 -0400 Subject: [PATCH 13/28] update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26713a24b..44c9f58f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). ### Added + * Added 3D file viewer for OBJ & STL file types ([#1558](https://github.com/lbryio/lbry-desktop/pull/1558)) + + ### Changed From 09a637d5725eee2b5d0ff31e82ad9b9e4604c129 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Thu, 19 Jul 2018 09:59:05 -0400 Subject: [PATCH 14/28] update lbry-redux --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cfcc220bd..303331a47 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "formik": "^0.10.4", "hast-util-sanitize": "^1.1.2", "keytar": "^4.2.1", - "lbry-redux": "lbryio/lbry-redux#177ef2c1916f9672e713267500e447d671ae1bc3", + "lbry-redux": "lbryio/lbry-redux#e0909b08647a790d155f3189b9f9bf0b3e55bd17", "localforage": "^1.7.1", "mime": "^2.3.1", "mixpanel-browser": "^2.17.1", From 3b1167c45afef697e24bbcfc533ab33ced78cd50 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Thu, 19 Jul 2018 10:01:25 -0400 Subject: [PATCH 15/28] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26713a24b..0fcdf0a91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). ### Changed +* Only show video error modal if you are on the video page & don't retry to play failed videos ([#1768](https://github.com/lbryio/lbry-desktop/pull/1768)) ## [0.22.2] - 2018-07-09 From c518e39e5fc686d2d839417b471ea92fa7972802 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Thu, 19 Jul 2018 10:05:33 -0400 Subject: [PATCH 16/28] update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26713a24b..044878ade 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). ### Changed + * Actually hide NSFW files if a user chooses to hide NSFW content via the settings page ([#1748](https://github.com/lbryio/lbry-desktop/pull/1748)) + * Hide the "Community top bids" section if user chooses to hide NSFW content ([#1760](https://github.com/lbryio/lbry-desktop/pull/1760)) + ## [0.22.2] - 2018-07-09 From cbcdfb187a99f7b8d2f4700654054069cddcbb76 Mon Sep 17 00:00:00 2001 From: Travis Eden Date: Tue, 17 Jul 2018 19:14:29 -0400 Subject: [PATCH 17/28] fetch rewards after successfully claiming reward --- src/renderer/redux/actions/rewards.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/renderer/redux/actions/rewards.js b/src/renderer/redux/actions/rewards.js index a20bfcb48..d98d4a9b6 100644 --- a/src/renderer/redux/actions/rewards.js +++ b/src/renderer/redux/actions/rewards.js @@ -55,6 +55,7 @@ export function doClaimRewardType(rewardType, options) { }); const success = successReward => { + dispatch(doRewardList()); dispatch({ type: ACTIONS.CLAIM_REWARD_SUCCESS, data: { From 0d642b2be1e74ffe6ffda3001e9e0bbb6355bd43 Mon Sep 17 00:00:00 2001 From: Travis Eden Date: Tue, 17 Jul 2018 19:26:03 -0400 Subject: [PATCH 18/28] move reward fetching from rewards page to reward summary component on wallet overview page --- src/renderer/component/rewardSummary/index.js | 14 ++- src/renderer/component/rewardSummary/view.jsx | 85 +++++++++++-------- src/renderer/page/rewards/view.jsx | 5 -- 3 files changed, 60 insertions(+), 44 deletions(-) diff --git a/src/renderer/component/rewardSummary/index.js b/src/renderer/component/rewardSummary/index.js index 54124dfda..3ac4d29e9 100644 --- a/src/renderer/component/rewardSummary/index.js +++ b/src/renderer/component/rewardSummary/index.js @@ -1,10 +1,18 @@ -import React from 'react'; import { connect } from 'react-redux'; -import { selectUnclaimedRewardValue } from 'redux/selectors/rewards'; +import { selectUnclaimedRewardValue, selectFetchingRewards } from 'redux/selectors/rewards'; +import { doRewardList } from 'redux/actions/rewards'; import RewardSummary from './view'; const select = state => ({ unclaimedRewardAmount: selectUnclaimedRewardValue(state), + fetching: selectFetchingRewards(state), }); -export default connect(select, null)(RewardSummary); +const perform = dispatch => ({ + fetchRewards: () => dispatch(doRewardList()), +}); + +export default connect( + select, + perform +)(RewardSummary); diff --git a/src/renderer/component/rewardSummary/view.jsx b/src/renderer/component/rewardSummary/view.jsx index 5436897d6..0a74fdfb6 100644 --- a/src/renderer/component/rewardSummary/view.jsx +++ b/src/renderer/component/rewardSummary/view.jsx @@ -2,47 +2,60 @@ import * as React from 'react'; import Button from 'component/button'; import CreditAmount from 'component/common/credit-amount'; +import BusyIndicator from 'component/common/busy-indicator'; type Props = { unclaimedRewardAmount: number, + fetching: boolean, + fetchRewards: () => void, }; -const RewardSummary = (props: Props) => { - const { unclaimedRewardAmount } = props; - const hasRewards = unclaimedRewardAmount > 0; +class RewardSummary extends React.Component { + componentDidMount() { + this.props.fetchRewards(); + } - return ( -
-
{__('Rewards')}
-

- {hasRewards ? ( - - {__('You have')} -   - -   - {__('in unclaimed rewards')}. - - ) : ( - - {__('There are no rewards available at this time, please check back later')}. - - )} -

-
-
-

- {__('Read our')}{' '} -

- ); -}; + render() { + const { unclaimedRewardAmount, fetching } = this.props; + const hasRewards = unclaimedRewardAmount > 0; + + return ( +
+
+ {__('Rewards')} + {fetching && } +
+

+ {!fetching && + (hasRewards ? ( + + {__('You have')} +   + +   + {__('in unclaimed rewards')}. + + ) : ( + + {__('There are no rewards available at this time, please check back later')}. + + ))} +

+
+
+

+ {__('Read our')}{' '} +

+ ); + } +} export default RewardSummary; diff --git a/src/renderer/page/rewards/view.jsx b/src/renderer/page/rewards/view.jsx index d9e577c60..7f98b50e8 100644 --- a/src/renderer/page/rewards/view.jsx +++ b/src/renderer/page/rewards/view.jsx @@ -10,7 +10,6 @@ import type { Reward } from 'types/reward'; type Props = { doAuth: () => void, - fetchRewards: () => void, navigate: string => void, fetching: boolean, rewards: Array, @@ -27,10 +26,6 @@ type Props = { }; class RewardsPage extends React.PureComponent { - componentDidMount() { - this.props.fetchRewards(); - } - renderPageHeader() { const { doAuth, navigate, user, daemonSettings } = this.props; From 45de83fdf3807cc0c210d943375656558086db11 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Tue, 17 Jul 2018 13:43:43 -0400 Subject: [PATCH 19/28] thumbnail preview on publish page --- src/renderer/component/publishForm/view.jsx | 2 +- .../component/selectThumbnail/view.jsx | 99 +++++++++++++----- src/renderer/scss/_gui.scss | 14 ++- src/renderer/scss/component/_card.scss | 6 ++ static/img/thumbnail.png | Bin 0 -> 6994 bytes 5 files changed, 90 insertions(+), 31 deletions(-) create mode 100644 static/img/thumbnail.png diff --git a/src/renderer/component/publishForm/view.jsx b/src/renderer/component/publishForm/view.jsx index 2b3739d93..7c572ced3 100644 --- a/src/renderer/component/publishForm/view.jsx +++ b/src/renderer/component/publishForm/view.jsx @@ -74,7 +74,7 @@ class PublishForm extends React.PureComponent { componentWillMount() { const { isStillEditing, thumbnail } = this.props; - if (!isStillEditing || !thumbnail) { + if (!thumbnail) { this.props.resetThumbnailStatus(); } } diff --git a/src/renderer/component/selectThumbnail/view.jsx b/src/renderer/component/selectThumbnail/view.jsx index e93b6327a..d34d90289 100644 --- a/src/renderer/component/selectThumbnail/view.jsx +++ b/src/renderer/component/selectThumbnail/view.jsx @@ -4,6 +4,7 @@ import React from 'react'; import { FormField, FormRow } from 'component/common/form'; import FileSelector from 'component/common/file-selector'; import Button from 'component/button'; +import Native from 'native'; type Props = { thumbnail: ?string, @@ -15,7 +16,29 @@ type Props = { resetThumbnailStatus: () => void, }; -class SelectThumbnail extends React.PureComponent { +type State = { + thumbnailValid: boolean, +} + +class SelectThumbnail extends React.PureComponent { + constructor() { + super(); + + this.state = { + thumbnailValid: false, + }; + + (this: any).handleThumbnailChange = this.handleThumbnailChange.bind(this); + } + + handleThumbnailChange(e) { + const { updatePublishForm } = this.props; + const newThumbnail = e.target.value.replace(' ', ''); + + updatePublishForm({ thumbnail: newThumbnail }); + this.setState({ thumbnailValid: true }) + } + render() { const { thumbnail, @@ -26,25 +49,44 @@ class SelectThumbnail extends React.PureComponent { thumbnailPath, resetThumbnailStatus, } = this.props; - + + const { thumbnailValid } = this.state; + return ( -
+
{status === THUMBNAIL_STATUSES.API_DOWN || status === THUMBNAIL_STATUSES.MANUAL ? ( - - updatePublishForm({ thumbnail: e.target.value })} +
+
+ +
+
+
+ Thumbnail Preview { + this.setState({ thumbnailValid: false }) + }} /> - +
) : (
- {(status === THUMBNAIL_STATUSES.READY || status === THUMBNAIL_STATUSES.COMPLETE) && ( + {status === THUMBNAIL_STATUSES.READY && ( { /> )} {status === THUMBNAIL_STATUSES.COMPLETE && ( -
-

- Upload complete. View it{' '} -

+
+ +
+

+ Upload complete.{' '} +

+
)}
)} @@ -72,13 +120,6 @@ class SelectThumbnail extends React.PureComponent { } /> )} - {status === THUMBNAIL_STATUSES.MANUAL && ( -
{status === THUMBNAIL_STATUSES.IN_PROGRESS &&

{__('Uploading thumbnail')}...

} diff --git a/src/renderer/scss/_gui.scss b/src/renderer/scss/_gui.scss index c240197da..439a05c33 100644 --- a/src/renderer/scss/_gui.scss +++ b/src/renderer/scss/_gui.scss @@ -153,7 +153,6 @@ dd { p { font-family: 'metropolis-medium'; - padding: $spacing-vertical * 1/3 0; } .page { @@ -302,6 +301,14 @@ p { opacity: 0.5; } +.column { + display: flex; + + .column__item:not(:first-child) { + padding-left: $spacing-width * 2/3; + } +} + .truncated-text { //display: inline-block; display: -webkit-box; @@ -361,3 +368,8 @@ p { margin-top: $spacing-vertical * 2/3; } } + +.thumbnail-preview { + height: 100px; + width: 177px; +} diff --git a/src/renderer/scss/component/_card.scss b/src/renderer/scss/component/_card.scss index 50cdc4478..f44a60d91 100644 --- a/src/renderer/scss/component/_card.scss +++ b/src/renderer/scss/component/_card.scss @@ -255,6 +255,12 @@ right: $spacing-vertical; } +.card__actions-bottom-corner { + position: absolute; + bottom: $spacing-vertical; + right: $spacing-vertical; +} + .card__actions--end { justify-content: flex-end; } diff --git a/static/img/thumbnail.png b/static/img/thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..05d7e2b4406436c525391be715d50fed5ab89d4a GIT binary patch literal 6994 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 EKRCdd)c^nh literal 0 HcmV?d00001 From 6df4032c9060bc91aa26abc310f0fb4f3dd5c72d Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Wed, 18 Jul 2018 11:46:21 -0400 Subject: [PATCH 20/28] improve thumbnail preview styling --- .../component/common/file-selector.jsx | 4 +- src/renderer/component/publishForm/view.jsx | 28 ++++--- .../component/selectThumbnail/view.jsx | 80 ++++++++++--------- src/renderer/scss/component/_form-field.scss | 4 +- 4 files changed, 63 insertions(+), 53 deletions(-) diff --git a/src/renderer/component/common/file-selector.jsx b/src/renderer/component/common/file-selector.jsx index ec19394e1..3729202d0 100644 --- a/src/renderer/component/common/file-selector.jsx +++ b/src/renderer/component/common/file-selector.jsx @@ -9,7 +9,7 @@ type Props = { type: string, currentPath: ?string, onFileChosen: (string, string) => void, - fileLabel: ?string, + fileLabel?: string, directoryLabel?: string, }; @@ -56,7 +56,7 @@ class FileSelector extends React.PureComponent { type === 'file' ? fileLabel || __('Choose File') : directoryLabel || __('Choose Directory'); return ( - +
)} - - {!!isStillEditing && ( -

- {__("If you don't choose a file, the file from your existing claim")} - {` "${name}" `} - {__('will be used.')} -

- )} +
+ + {!!isStillEditing && + name && ( +

+ {__("If you don't choose a file, the file from your existing claim")} + {` "${name}" `} + {__('will be used.')} +

+ )} +
@@ -400,10 +403,9 @@ class PublishForm extends React.PureComponent { __('Enter a URL for your thumbnail.') ) : ( - {__( - 'Upload your thumbnail (.png/.jpg/.jpeg/.gif) to spee.ch, or enter the URL manually. Learn more about spee.ch ' - )} -
diff --git a/src/renderer/component/selectThumbnail/view.jsx b/src/renderer/component/selectThumbnail/view.jsx index d34d90289..0c8f6b813 100644 --- a/src/renderer/component/selectThumbnail/view.jsx +++ b/src/renderer/component/selectThumbnail/view.jsx @@ -1,7 +1,7 @@ // @flow import { THUMBNAIL_STATUSES, MODALS } from 'lbry-redux'; -import React from 'react'; -import { FormField, FormRow } from 'component/common/form'; +import * as React from 'react'; +import { FormField } from 'component/common/form'; import FileSelector from 'component/common/file-selector'; import Button from 'component/button'; import Native from 'native'; @@ -17,28 +17,28 @@ type Props = { }; type State = { - thumbnailValid: boolean, -} + thumbnailError: boolean, +}; class SelectThumbnail extends React.PureComponent { constructor() { super(); - + this.state = { - thumbnailValid: false, + thumbnailError: false, }; - + (this: any).handleThumbnailChange = this.handleThumbnailChange.bind(this); } - - handleThumbnailChange(e) { + + handleThumbnailChange(e: SyntheticInputEvent<*>) { const { updatePublishForm } = this.props; const newThumbnail = e.target.value.replace(' ', ''); - + updatePublishForm({ thumbnail: newThumbnail }); - this.setState({ thumbnailValid: true }) + this.setState({ thumbnailError: false }); } - + render() { const { thumbnail, @@ -49,43 +49,46 @@ class SelectThumbnail extends React.PureComponent { thumbnailPath, resetThumbnailStatus, } = this.props; - - const { thumbnailValid } = this.state; - + const { thumbnailError } = this.state; + const thumbnailSrc = + !thumbnail || thumbnailError ? Native.imagePath('thumbnail.png') : thumbnail; + return (
{status === THUMBNAIL_STATUSES.API_DOWN || status === THUMBNAIL_STATUSES.MANUAL ? (
+ {__('Thumbnail { + this.setState({ thumbnailError: true }); + }} + />
+ />
- Thumbnail Preview { - this.setState({ thumbnailValid: false }) - }} - />
) : ( -
+ {status === THUMBNAIL_STATUSES.READY && ( { + alt={__('Thumbnail Preview')} + />

Upload complete.{' '}

-
+
)} -
+ )} -
- {status === THUMBNAIL_STATUSES.READY && ( + {status === THUMBNAIL_STATUSES.READY && ( +
+
+ )} {status === THUMBNAIL_STATUSES.IN_PROGRESS &&

{__('Uploading thumbnail')}...

}
diff --git a/src/renderer/scss/component/_form-field.scss b/src/renderer/scss/component/_form-field.scss index e46223982..0b5ad5f4a 100644 --- a/src/renderer/scss/component/_form-field.scss +++ b/src/renderer/scss/component/_form-field.scss @@ -67,8 +67,8 @@ width: 35px; } - input.paginate-channel { - width: 35px; + input.input--thumbnail { + width: 370px; } &.form-field--auto-height { From a68f276fb09d17f526cb8d32ef712e1303149b26 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Wed, 18 Jul 2018 11:55:17 -0400 Subject: [PATCH 21/28] use variables for thumbnail size --- src/renderer/scss/_gui.scss | 6 +++--- src/renderer/scss/_vars.scss | 4 ++++ src/renderer/scss/component/_form-field.scss | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/renderer/scss/_gui.scss b/src/renderer/scss/_gui.scss index 439a05c33..bf711e78a 100644 --- a/src/renderer/scss/_gui.scss +++ b/src/renderer/scss/_gui.scss @@ -303,7 +303,7 @@ p { .column { display: flex; - + .column__item:not(:first-child) { padding-left: $spacing-width * 2/3; } @@ -370,6 +370,6 @@ p { } .thumbnail-preview { - height: 100px; - width: 177px; + height: var(--thumbnail-preview-height); + width: var(--thumbnail-preview-width); } diff --git a/src/renderer/scss/_vars.scss b/src/renderer/scss/_vars.scss index bc0ec1428..d2bba62e2 100644 --- a/src/renderer/scss/_vars.scss +++ b/src/renderer/scss/_vars.scss @@ -179,4 +179,8 @@ $large-breakpoint: 1921px; // /* Animation :) */ --animation-duration: 0.3s; --animation-style: cubic-bezier(0.55, 0, 0.1, 1); + + /* Image */ + --thumbnail-preview-height: 100px; + --thumbnail-preview-width: 177px; } diff --git a/src/renderer/scss/component/_form-field.scss b/src/renderer/scss/component/_form-field.scss index 0b5ad5f4a..1c8db8db9 100644 --- a/src/renderer/scss/component/_form-field.scss +++ b/src/renderer/scss/component/_form-field.scss @@ -68,7 +68,7 @@ } input.input--thumbnail { - width: 370px; + width: 400px; } &.form-field--auto-height { From 0179357e7cf37fa15190b36ef89e05b5a5fcefc6 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Wed, 18 Jul 2018 12:01:28 -0400 Subject: [PATCH 22/28] fix spacing --- src/renderer/component/selectThumbnail/view.jsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/renderer/component/selectThumbnail/view.jsx b/src/renderer/component/selectThumbnail/view.jsx index 0c8f6b813..975356f15 100644 --- a/src/renderer/component/selectThumbnail/view.jsx +++ b/src/renderer/component/selectThumbnail/view.jsx @@ -106,13 +106,15 @@ class SelectThumbnail extends React.PureComponent {

Upload complete.{' '} -

)} From 8ed40be8a4101304013975798f9375c1fe92994b Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Thu, 19 Jul 2018 10:51:03 -0400 Subject: [PATCH 23/28] better thumbnail placeholder --- src/renderer/component/selectThumbnail/view.jsx | 2 +- src/renderer/scss/_gui.scss | 1 + src/renderer/scss/_vars.scss | 2 ++ static/img/no-thumbnail.png | Bin 0 -> 2791 bytes static/img/thumbnail.png | Bin 6994 -> 0 bytes yarn.lock | 4 ++-- 6 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 static/img/no-thumbnail.png delete mode 100644 static/img/thumbnail.png diff --git a/src/renderer/component/selectThumbnail/view.jsx b/src/renderer/component/selectThumbnail/view.jsx index 975356f15..1fcd59cb6 100644 --- a/src/renderer/component/selectThumbnail/view.jsx +++ b/src/renderer/component/selectThumbnail/view.jsx @@ -51,7 +51,7 @@ class SelectThumbnail extends React.PureComponent { } = this.props; const { thumbnailError } = this.state; const thumbnailSrc = - !thumbnail || thumbnailError ? Native.imagePath('thumbnail.png') : thumbnail; + !thumbnail || thumbnailError ? Native.imagePath('no-thumbnail.png') : thumbnail; return (
diff --git a/src/renderer/scss/_gui.scss b/src/renderer/scss/_gui.scss index bf711e78a..582448d59 100644 --- a/src/renderer/scss/_gui.scss +++ b/src/renderer/scss/_gui.scss @@ -372,4 +372,5 @@ p { .thumbnail-preview { height: var(--thumbnail-preview-height); width: var(--thumbnail-preview-width); + border: var(--thumbnail-preview-border); } diff --git a/src/renderer/scss/_vars.scss b/src/renderer/scss/_vars.scss index d2bba62e2..517f33fdd 100644 --- a/src/renderer/scss/_vars.scss +++ b/src/renderer/scss/_vars.scss @@ -183,4 +183,6 @@ $large-breakpoint: 1921px; /* Image */ --thumbnail-preview-height: 100px; --thumbnail-preview-width: 177px; + // This will awlways white, it looks fine on light mode + --thumbnail-preview-border: 1px solid var(--color-white); } diff --git a/static/img/no-thumbnail.png b/static/img/no-thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..af89f26919afc2cbefaf77596e24f1c4712e8a8a GIT binary patch literal 2791 zcmd^Bdr(tX8b9~uLM{P9R;k66)LW^e?H17mtvrOwOR5-P1$-2VbY0z6(PY&?Se0DK zwzbRRvJXYT5)?76I)qxMREZ=)x3Coi6$Yph(-CAN580F$c_i8IV5jZO&g^t&`(N|V zJ?Hzr-{bpoa&q5KNlNe*{8WGt@?P_L+YL|#RmrmyId}- z)w+4}W|n1JTU$Af>+S6=EiJut>C(W!fJ7qMv15n9VA!{BUv+hLQBje>Uebb)K(;0> zI!!4ZHoiz;YR08oallB;h4qj4qx!aYwzsZH9A6sfRh3R3p&vQ6j)eZ>jB5NKFQ?GA zQ987sqV}uxBRzv2OTu2NY)ig%Hh}zW+IL&ng39*fTiO89 z>QkKKEn*3ZNc-EK9UES9{Ec zq6>)!9CNtT@D0sA48uJLbllh-u^;?j9PJJn_-*JOSnAjH%Pvp?rufE6A4}<}s4N`Q z&OaBF;0ciQ^8B-_Hef`OMVoXC&EaKt8b&-9bL^j-BMqFzjYAc;AKw$s0m);tUy1{$xY6L6R9S}%)~ZkJ`qFa!lZf;91CmN)l3x(nw0)mhc^6%CpI^9u!v@g)#oRV z;GQ4Vyxg^WKAy@3t?s?tQ#_g)xxbMJ;ERs*8iHc`5g9#YAMjtvvBS>lL^C2koGK|Z z64Wp4x*C!%qWcV;@h?Pk9ggsU7J`bg>jW?rSEIYA!%$05<3ZVoaCpL(hePz;D1vHy zl8g@5I%cy>wu|~fLmdVioTIF+5Xay+Xlz-lN_4$;GO8MnHRh&b^1&|-tp>@K?P-e1 z^;;uPLp=M#bzTnsOm$p&!_fJ*sYNi`Q;DkjqZxM0VO;2F>X2dIYlX((T=@iiBPnuJ zQLny%^Rswkmrvcl2u!|y+^-c~tD&#T9u%SCmps-WGTz;s7i)+I(ZwOCedxRur~io# zhWe!D%KwF__M-g$lR>sl@s>|8i9aV({oZy$uP($>(pT(RAo)wKJoOUJ&Etk5Ri%2h z?9dgA%tn!eLExzGxgk*cySv#ir7XLu_Ot;oh9@s~J&4TXKW~BDc6ala8n<2AQS+>4 z`qOngtU{>)lg{PZ^BP;l`W)u)I=s9YB4o)R|g-~7> z>+uv9uRuYcs5fH%YIn0+?pPS+?m+r}VT0~AMtK_xN6o1p#o*##6m(5}_t6Nhd5R)* zS0#PdACCg|9lm+6Y^YN_ZNfbrMEN!4SJn5w0Q~1Z#&%oXc&il>wOxR@Qe%Sf$Md*B zh3#`7%4#B%QdLGBw2>W#+IQ9L!ZR!4oAWZSNwMfs6x4Bl1D=kXyE(pWXf0MZB7Mrn zX9m5DiMG1sxUIv4^2)2*3W{ zi8(hB9gaL1Q4X5JGQ$Wii5_Cp|5>P1pqif%_d<;*A{qXn+AZ~o!WdY{EagiQUWEH( zHct*dNacBIsZeCZrV5bhGd=(x?V#c>w*_dy*BqdC1em`k?tc=&#jHkiIyr&*!^F#d^Y+Ft$kb>c_3;=c1X aRY?kut$qEAwvSKZL9B^SimQpqD)=`6pH_ST literal 0 HcmV?d00001 diff --git a/static/img/thumbnail.png b/static/img/thumbnail.png deleted file mode 100644 index 05d7e2b4406436c525391be715d50fed5ab89d4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6994 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 EKRCdd)c^nh diff --git a/yarn.lock b/yarn.lock index 789b4c997..e4c5512dc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5221,9 +5221,9 @@ lazy-val@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.3.tgz#bb97b200ef00801d94c317e29dc6ed39e31c5edc" -lbry-redux@lbryio/lbry-redux#177ef2c1916f9672e713267500e447d671ae1bc3: +lbry-redux@lbryio/lbry-redux#e0909b08647a790d155f3189b9f9bf0b3e55bd17: version "0.0.1" - resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/177ef2c1916f9672e713267500e447d671ae1bc3" + resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/e0909b08647a790d155f3189b9f9bf0b3e55bd17" dependencies: proxy-polyfill "0.1.6" reselect "^3.0.0" From b3c7738668b8fb7efd81d30df074ab50f72ae6c1 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Thu, 19 Jul 2018 10:53:12 -0400 Subject: [PATCH 24/28] update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 502730a1d..aa56f8542 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). ### Added * Added 3D file viewer for OBJ & STL file types ([#1558](https://github.com/lbryio/lbry-desktop/pull/1558)) - + * Added thumbnail preview on publish page ([#1755](https://github.com/lbryio/lbry-desktop/pull/1755)) ### Changed From 8a15eb8c27f9aff119e3b44e6a2a4caf02fe76bc Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Thu, 19 Jul 2018 10:58:45 -0400 Subject: [PATCH 25/28] update changelog --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 502730a1d..aa408c6db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). ### Fixed + * Edit option missing from certain published claims ([#175](https://github.com/lbryio/lbry-desktop/issues/1756)) + ### Added * Added 3D file viewer for OBJ & STL file types ([#1558](https://github.com/lbryio/lbry-desktop/pull/1558)) @@ -14,9 +16,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). ### Changed + * Rename the Github repo to lbry-desktop ([#1765](https://github.com/lbryio/lbry-desktop/pull/1765)) * Only show video error modal if you are on the video page & don't retry to play failed videos ([#1768](https://github.com/lbryio/lbry-desktop/pull/1768)) * Actually hide NSFW files if a user chooses to hide NSFW content via the settings page ([#1748](https://github.com/lbryio/lbry-desktop/pull/1748)) * Hide the "Community top bids" section if user chooses to hide NSFW content ([#1760](https://github.com/lbryio/lbry-desktop/pull/1760)) + * Add a more descriptive error message when Shapeshift is unavailable ([#1771](https://github.com/lbryio/lbry-desktop/pull/1771)) ## [0.22.2] - 2018-07-09 @@ -39,7 +43,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). * Console errors when multiple downloads for same claim exist ([#1724](https://github.com/lbryio/lbry-desktop/pull/1724)) * App version in dev mode ([#1722](https://github.com/lbryio/lbry-desktop/pull/1722)) * Long URI name displays in transaction list/Help ([#1694](https://github.com/lbryio/lbry-desktop/pull/1694))/([#1692](https://github.com/lbryio/lbry-desktop/pull/1692)) - * Edit option missing from certain published claims ([#175](https://github.com/lbryio/lbry-desktop/issues/1756)) + ### Changed * Show claim name, instead of URI, when loading a channel([#1711](https://github.com/lbryio/lbry-desktop/pull/1711)) From 0d71ed7c5836554f4e916be46d7095c2a95b93f8 Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Thu, 19 Jul 2018 11:27:25 -0400 Subject: [PATCH 26/28] update daemon to 0.20.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index da2241252..786ebab43 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,7 @@ "yarn": "^1.3" }, "lbrySettings": { - "lbrynetDaemonVersion": "0.20.3", + "lbrynetDaemonVersion": "0.20.4", "lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-daemon-vDAEMONVER-OSNAME.zip", "lbrynetDaemonDir": "static/daemon", "lbrynetDaemonFileName": "lbrynet-daemon" From f0e364243e4bd4e2d75a667ae95ea8430384ba3c Mon Sep 17 00:00:00 2001 From: Sean Yesmunt Date: Thu, 19 Jul 2018 11:56:05 -0400 Subject: [PATCH 27/28] add badge to readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8c0c5e55d..04616e269 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ [![Codacy Badge](https://api.codacy.com/project/badge/Grade/78b627d4f5524792adc48719835e1523)](https://www.codacy.com/app/LBRY/lbry-desktop?utm_source=github.com&utm_medium=referral&utm_content=lbryio/lbry-desktop&utm_campaign=Badge_Grade) [![chat on Discord](https://img.shields.io/discord/362322208485277697.svg?logo=discord)](https://chat.lbry.io) +[![forthebadge](https://forthebadge.com/images/badges/certified-steve-bruhle.svg)](https://forthebadge.com) + The LBRY app is a graphical browser for the decentralized content marketplace provided by the [LBRY](https://lbry.io) protocol. It is essentially the [lbry daemon](https://github.com/lbryio/lbry) bundled with an UI using From ccd49cd6b9f4b7ce527bc9a4d80675622a6066a2 Mon Sep 17 00:00:00 2001 From: Thomas Zarebczan Date: Thu, 19 Jul 2018 23:45:28 -0400 Subject: [PATCH 28/28] Update config --- .tx/config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.tx/config b/.tx/config index d4677541c..3868bf506 100644 --- a/.tx/config +++ b/.tx/config @@ -1,7 +1,7 @@ [main] host = https://www.transifex.com -[lbry-app.app-strings] +[lbry-deskop.app-strings] file_filter = dist/locales/.json source_file = dist/locales/en.json source_lang = en