diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a7b323c4..044878ade 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,6 @@ 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 * 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)) diff --git a/package.json b/package.json index 0300cf5d0..fb8de69c9 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,6 @@ "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/main/index.js b/src/main/index.js index 1c81d6217..807ca08e4 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -53,13 +53,6 @@ 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 79aca834a..5ce35c6b7 100644 --- a/src/renderer/component/fileRender/view.jsx +++ b/src/renderer/component/fileRender/view.jsx @@ -2,7 +2,6 @@ import React from 'react'; import LoadingScreen from 'component/common/loading-screen'; import PdfViewer from 'component/viewers/pdfViewer'; -import ThreeViewer from 'component/viewers/threeViewer'; type Props = { mediaType: string, @@ -21,7 +20,7 @@ class FileRender extends React.PureComponent { // Supported mediaTypes const mediaTypes = { - '3D-file': , + // '3D-file': , // Add routes to viewer... }; 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/component/viewers/threeViewer/index.jsx b/src/renderer/component/viewers/threeViewer/index.jsx deleted file mode 100644 index 63dc38622..000000000 --- a/src/renderer/component/viewers/threeViewer/index.jsx +++ /dev/null @@ -1,281 +0,0 @@ -// @flow -import * as React from 'react'; -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, - autoRotate: boolean, - source: { - fileType: string, - filePath: string, - }, -}; - -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', - blue: '#3498db', - green: '#44b098', - orange: '#f39c12', - }; - - // Viewer themes - this.themes = { - dark: { - gridColor: '#414e5c', - groundColor: '#13233C', - backgroundColor: '#13233C', - centerLineColor: '#7f8c8d', - }, - light: { - gridColor: '#7f8c8d', - groundColor: '#DDD', - backgroundColor: '#EEE', - centerLineColor: '#2F2F2F', - }, - }; - - // Select current theme - this.theme = this.themes[theme] || this.themes.light; - - // State - this.state = { - error: null, - isReady: false, - isLoading: false, - }; - } - - 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.setState({ 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); - // 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 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); - } - - 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); - - // Assign name - mesh.name = 'objectGroup'; - - this.scene.add(mesh); - this.fitMeshToCamera(mesh); - this.createWireFrame(mesh); - this.updateControlsTarget(mesh.position); - return mesh; - } - - toggleWireFrame(show = false) { - this.wireframe.opacity = show ? 1 : 0; - this.mesh.material.opacity = show ? 0 : 1; - } - - fitMeshToCamera(group) { - const max = { x: 0, y: 0, z: 0 }; - const 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 scaleFactor = 15 / Math.max(meshX, meshY); - - group.scale.set(scaleFactor, scaleFactor, scaleFactor); - group.position.setY((meshY / 2) * scaleFactor); - group.position.multiplyScalar(-1); - group.position.setY((meshY * scaleFactor) / 2); - } - - startLoader() { - const { source } = this.props; - - if (source) { - ThreeLoader(source, this.renderModel.bind(this), { - onStart: this.handleStart, - onLoad: this.handleReady, - onError: this.handleError, - }); - } - } - - handleStart = () => { - this.setState({ isLoading: true }); - }; - - 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; - this.camera.aspect = width / height; - this.camera.updateProjectionMatrix(); - this.controls.update(); - this.renderer.setSize(width, height); - }; - - 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); - } - - 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); - } - - 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); - } - - render() { - const { error, isReady, isLoading } = this.state; - const loadingMessage = 'Loading 3D model.'; - const showViewer = isReady && !error; - const showLoading = isLoading && !error; - - return ( - - {error && } - {showLoading && } -
- - ); - } -} - -export default ThreeViewer; diff --git a/src/renderer/component/viewers/threeViewer/internal/detector.js b/src/renderer/component/viewers/threeViewer/internal/detector.js deleted file mode 100644 index f75d46c3f..000000000 --- a/src/renderer/component/viewers/threeViewer/internal/detector.js +++ /dev/null @@ -1,10 +0,0 @@ -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/viewers/threeViewer/internal/loader.js b/src/renderer/component/viewers/threeViewer/internal/loader.js deleted file mode 100644 index dc4ce7482..000000000 --- a/src/renderer/component/viewers/threeViewer/internal/loader.js +++ /dev/null @@ -1,33 +0,0 @@ -import { LoadingManager, STLLoader, OBJLoader } from './three'; - -const Manager = ({ onLoad, onStart, onError }) => { - const manager = new LoadingManager(); - manager.onLoad = onLoad; - manager.onStart = onStart; - 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) { - const manager = Manager(managerEvents); - const loader = Loader(fileType, manager); - - if (loader) { - loader.load(filePath, data => { - renderModel(fileType, data); - }); - } - } -}; - -export default ThreeLoader; diff --git a/src/renderer/component/viewers/threeViewer/internal/renderer.js b/src/renderer/component/viewers/threeViewer/internal/renderer.js deleted file mode 100644 index 11b6c0545..000000000 --- a/src/renderer/component/viewers/threeViewer/internal/renderer.js +++ /dev/null @@ -1,15 +0,0 @@ -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/viewers/threeViewer/internal/scene.js b/src/renderer/component/viewers/threeViewer/internal/scene.js deleted file mode 100644 index f858c8832..000000000 --- a/src/renderer/component/viewers/threeViewer/internal/scene.js +++ /dev/null @@ -1,57 +0,0 @@ -import * as THREE from './three'; - -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 color - const bgColor = new THREE.Color(backgroundColor); - // New scene - const scene = new THREE.Scene(); - // Background color - scene.background = bgColor; - // Fog effect - 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; -}; - -export default Scene; diff --git a/src/renderer/component/viewers/threeViewer/internal/three.js b/src/renderer/component/viewers/threeViewer/internal/three.js deleted file mode 100644 index 6cb0051d0..000000000 --- a/src/renderer/component/viewers/threeViewer/internal/three.js +++ /dev/null @@ -1,10 +0,0 @@ -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/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; 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: { diff --git a/yarn.lock b/yarn.lock index 789b4c997..24b98e124 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8497,10 +8497,6 @@ 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"