mirror of
https://github.com/LBRYFoundation/lbry-desktop.git
synced 2025-08-29 16:31:33 +00:00
Merge branch 'master' into wallet-encryption
This commit is contained in:
commit
097a523b39
29 changed files with 787 additions and 157 deletions
|
@ -1,7 +1,7 @@
|
||||||
[main]
|
[main]
|
||||||
host = https://www.transifex.com
|
host = https://www.transifex.com
|
||||||
|
|
||||||
[lbry-app.app-strings]
|
[lbry-deskop.app-strings]
|
||||||
file_filter = dist/locales/<lang>.json
|
file_filter = dist/locales/<lang>.json
|
||||||
source_file = dist/locales/en.json
|
source_file = dist/locales/en.json
|
||||||
source_lang = en
|
source_lang = en
|
||||||
|
|
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -7,10 +7,20 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
* Edit option missing from certain published claims ([#175](https://github.com/lbryio/lbry-desktop/issues/1756))
|
||||||
|
|
||||||
### Added
|
### 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
|
### 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
|
## [0.22.2] - 2018-07-09
|
||||||
|
@ -33,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))
|
* 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))
|
* 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))
|
* 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
|
### Changed
|
||||||
* Show claim name, instead of URI, when loading a channel([#1711](https://github.com/lbryio/lbry-desktop/pull/1711))
|
* Show claim name, instead of URI, when loading a channel([#1711](https://github.com/lbryio/lbry-desktop/pull/1711))
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
[](https://www.codacy.com/app/LBRY/lbry-desktop?utm_source=github.com&utm_medium=referral&utm_content=lbryio/lbry-desktop&utm_campaign=Badge_Grade)
|
[](https://www.codacy.com/app/LBRY/lbry-desktop?utm_source=github.com&utm_medium=referral&utm_content=lbryio/lbry-desktop&utm_campaign=Badge_Grade)
|
||||||
[](https://chat.lbry.io)
|
[](https://chat.lbry.io)
|
||||||
|
|
||||||
|
[](https://forthebadge.com)
|
||||||
|
|
||||||
The LBRY app is a graphical browser for the decentralized content marketplace provided by the
|
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](https://lbry.io) protocol. It is essentially the
|
||||||
[lbry daemon](https://github.com/lbryio/lbry) bundled with an UI using
|
[lbry daemon](https://github.com/lbryio/lbry) bundled with an UI using
|
||||||
|
|
|
@ -42,13 +42,13 @@
|
||||||
"electron-is-dev": "^0.3.0",
|
"electron-is-dev": "^0.3.0",
|
||||||
"electron-log": "^2.2.12",
|
"electron-log": "^2.2.12",
|
||||||
"electron-publisher-s3": "^20.8.1",
|
"electron-publisher-s3": "^20.8.1",
|
||||||
"electron-updater": "^2.21.10",
|
"electron-updater": "^2.23.3",
|
||||||
"electron-window-state": "^4.1.1",
|
"electron-window-state": "^4.1.1",
|
||||||
"find-process": "^1.1.0",
|
"find-process": "^1.1.0",
|
||||||
"formik": "^0.10.4",
|
"formik": "^0.10.4",
|
||||||
"hast-util-sanitize": "^1.1.2",
|
"hast-util-sanitize": "^1.1.2",
|
||||||
"keytar": "^4.2.1",
|
"keytar": "^4.2.1",
|
||||||
"lbry-redux": "lbryio/lbry-redux#177ef2c1916f9672e713267500e447d671ae1bc3",
|
"lbry-redux": "lbryio/lbry-redux#e0909b08647a790d155f3189b9f9bf0b3e55bd17",
|
||||||
"localforage": "^1.7.1",
|
"localforage": "^1.7.1",
|
||||||
"mime": "^2.3.1",
|
"mime": "^2.3.1",
|
||||||
"mixpanel-browser": "^2.17.1",
|
"mixpanel-browser": "^2.17.1",
|
||||||
|
@ -78,6 +78,7 @@
|
||||||
"shapeshift.io": "^1.3.1",
|
"shapeshift.io": "^1.3.1",
|
||||||
"source-map-support": "^0.5.4",
|
"source-map-support": "^0.5.4",
|
||||||
"stream-to-blob-url": "^2.1.1",
|
"stream-to-blob-url": "^2.1.1",
|
||||||
|
"three": "^0.93.0",
|
||||||
"tree-kill": "^1.1.0",
|
"tree-kill": "^1.1.0",
|
||||||
"y18n": "^4.0.0"
|
"y18n": "^4.0.0"
|
||||||
},
|
},
|
||||||
|
@ -93,7 +94,7 @@
|
||||||
"del": "^3.0.0",
|
"del": "^3.0.0",
|
||||||
"devtron": "^1.4.0",
|
"devtron": "^1.4.0",
|
||||||
"electron": "^1.8.4",
|
"electron": "^1.8.4",
|
||||||
"electron-builder": "^20.13.3",
|
"electron-builder": "^20.22.0",
|
||||||
"electron-devtools-installer": "^2.2.3",
|
"electron-devtools-installer": "^2.2.3",
|
||||||
"electron-webpack": "^1.13.0",
|
"electron-webpack": "^1.13.0",
|
||||||
"eslint": "^4.19.0",
|
"eslint": "^4.19.0",
|
||||||
|
@ -126,7 +127,7 @@
|
||||||
"yarn": "^1.3"
|
"yarn": "^1.3"
|
||||||
},
|
},
|
||||||
"lbrySettings": {
|
"lbrySettings": {
|
||||||
"lbrynetDaemonVersion": "0.20.3",
|
"lbrynetDaemonVersion": "0.20.4",
|
||||||
"lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-daemon-vDAEMONVER-OSNAME.zip",
|
"lbrynetDaemonUrlTemplate": "https://github.com/lbryio/lbry/releases/download/vDAEMONVER/lbrynet-daemon-vDAEMONVER-OSNAME.zip",
|
||||||
"lbrynetDaemonDir": "static/daemon",
|
"lbrynetDaemonDir": "static/daemon",
|
||||||
"lbrynetDaemonFileName": "lbrynet-daemon"
|
"lbrynetDaemonFileName": "lbrynet-daemon"
|
||||||
|
|
|
@ -53,6 +53,13 @@ app.setAsDefaultProtocolClient('lbry');
|
||||||
app.setName('LBRY');
|
app.setName('LBRY');
|
||||||
app.setAppUserModelId('io.lbry.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 () => {
|
app.on('ready', async () => {
|
||||||
const processList = await findProcess('name', 'lbrynet-daemon');
|
const processList = await findProcess('name', 'lbrynet-daemon');
|
||||||
const isDaemonRunning = processList.length > 0;
|
const isDaemonRunning = processList.length > 0;
|
||||||
|
|
|
@ -9,7 +9,7 @@ type Props = {
|
||||||
type: string,
|
type: string,
|
||||||
currentPath: ?string,
|
currentPath: ?string,
|
||||||
onFileChosen: (string, string) => void,
|
onFileChosen: (string, string) => void,
|
||||||
fileLabel: ?string,
|
fileLabel?: string,
|
||||||
directoryLabel?: string,
|
directoryLabel?: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ class FileSelector extends React.PureComponent<Props> {
|
||||||
type === 'file' ? fileLabel || __('Choose File') : directoryLabel || __('Choose Directory');
|
type === 'file' ? fileLabel || __('Choose File') : directoryLabel || __('Choose Directory');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormRow verticallyCentered padded>
|
<FormRow verticallyCentered>
|
||||||
<Button button="primary" onClick={() => this.handleButtonClick()} label={label} />
|
<Button button="primary" onClick={() => this.handleButtonClick()} label={label} />
|
||||||
<input
|
<input
|
||||||
webkitdirectory="true"
|
webkitdirectory="true"
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import LoadingScreen from 'component/common/loading-screen';
|
import LoadingScreen from 'component/common/loading-screen';
|
||||||
import PdfViewer from 'component/viewers/pdfViewer';
|
import PdfViewer from 'component/viewers/pdfViewer';
|
||||||
|
import ThreeViewer from 'component/viewers/threeViewer';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
mediaType: string,
|
mediaType: string,
|
||||||
|
@ -20,7 +21,7 @@ class FileRender extends React.PureComponent<Props> {
|
||||||
|
|
||||||
// Supported mediaTypes
|
// Supported mediaTypes
|
||||||
const mediaTypes = {
|
const mediaTypes = {
|
||||||
// '3D-file': <ThreeViewer {...viewerProps}/>,
|
'3D-file': <ThreeViewer {...viewerProps} />,
|
||||||
// Add routes to viewer...
|
// Add routes to viewer...
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {
|
||||||
import { makeSelectClientSetting, selectShowNsfw } from 'redux/selectors/settings';
|
import { makeSelectClientSetting, selectShowNsfw } from 'redux/selectors/settings';
|
||||||
import { selectMediaPaused, makeSelectMediaPositionForUri } from 'redux/selectors/media';
|
import { selectMediaPaused, makeSelectMediaPositionForUri } from 'redux/selectors/media';
|
||||||
import { selectPlayingUri } from 'redux/selectors/content';
|
import { selectPlayingUri } from 'redux/selectors/content';
|
||||||
|
import { selectFileInfoErrors } from 'redux/selectors/file_info';
|
||||||
import FileViewer from './view';
|
import FileViewer from './view';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => ({
|
||||||
|
@ -34,6 +35,7 @@ const select = (state, props) => ({
|
||||||
mediaPosition: makeSelectMediaPositionForUri(props.uri)(state),
|
mediaPosition: makeSelectMediaPositionForUri(props.uri)(state),
|
||||||
autoplay: makeSelectClientSetting(settings.AUTOPLAY)(state),
|
autoplay: makeSelectClientSetting(settings.AUTOPLAY)(state),
|
||||||
searchBarFocused: selectSearchBarFocused(state),
|
searchBarFocused: selectSearchBarFocused(state),
|
||||||
|
fileInfoErrors: selectFileInfoErrors(state)
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
|
|
@ -17,6 +17,9 @@ type Props = {
|
||||||
download_path: string,
|
download_path: string,
|
||||||
completed: boolean,
|
completed: boolean,
|
||||||
},
|
},
|
||||||
|
fileInfoErrors: ?{
|
||||||
|
[string]: boolean,
|
||||||
|
},
|
||||||
metadata: ?{
|
metadata: ?{
|
||||||
nsfw: boolean,
|
nsfw: boolean,
|
||||||
thumbnail: string,
|
thumbnail: string,
|
||||||
|
@ -55,14 +58,17 @@ class FileViewer extends React.PureComponent<Props> {
|
||||||
window.addEventListener('keydown', this.handleKeyDown);
|
window.addEventListener('keydown', this.handleKeyDown);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps: Props) {
|
componentDidUpdate(prev: Props) {
|
||||||
if (
|
if (
|
||||||
this.props.autoplay !== nextProps.autoplay ||
|
this.props.autoplay !== prev.autoplay ||
|
||||||
this.props.fileInfo !== nextProps.fileInfo ||
|
this.props.fileInfo !== prev.fileInfo ||
|
||||||
this.props.isDownloading !== nextProps.isDownloading ||
|
this.props.isDownloading !== prev.isDownloading ||
|
||||||
this.props.playingUri !== nextProps.playingUri
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,8 +73,8 @@ class PublishForm extends React.PureComponent<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
const { isStillEditing, thumbnail } = this.props;
|
const { thumbnail } = this.props;
|
||||||
if (!isStillEditing || !thumbnail) {
|
if (!thumbnail) {
|
||||||
this.props.resetThumbnailStatus();
|
this.props.resetThumbnailStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -356,14 +356,17 @@ class PublishForm extends React.PureComponent<Props> {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<FileSelector currentPath={filePath} onFileChosen={this.handleFileChange} />
|
<div className="card__content">
|
||||||
{!!isStillEditing && (
|
<FileSelector currentPath={filePath} onFileChosen={this.handleFileChange} />
|
||||||
<p className="card__content card__subtitle">
|
{!!isStillEditing &&
|
||||||
{__("If you don't choose a file, the file from your existing claim")}
|
name && (
|
||||||
{` "${name}" `}
|
<p className="card__content card__subtitle">
|
||||||
{__('will be used.')}
|
{__("If you don't choose a file, the file from your existing claim")}
|
||||||
</p>
|
{` "${name}" `}
|
||||||
)}
|
{__('will be used.')}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<div className={classnames({ 'card--disabled': formDisabled })}>
|
<div className={classnames({ 'card--disabled': formDisabled })}>
|
||||||
<section className="card card--section">
|
<section className="card card--section">
|
||||||
|
@ -400,10 +403,9 @@ class PublishForm extends React.PureComponent<Props> {
|
||||||
__('Enter a URL for your thumbnail.')
|
__('Enter a URL for your thumbnail.')
|
||||||
) : (
|
) : (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{__(
|
{__('Upload your thumbnail (.png/.jpg/.jpeg/.gif) to')}{' '}
|
||||||
'Upload your thumbnail (.png/.jpg/.jpeg/.gif) to spee.ch, or enter the URL manually. Learn more about spee.ch '
|
<Button button="link" label={__('spee.ch')} href="https://spee.ch/about" />.{' '}
|
||||||
)}
|
{__('Recommended size: 800x450 (16:9)')}
|
||||||
<Button button="link" label={__('here')} href="https://spee.ch/about" />.
|
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
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';
|
import RewardSummary from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
unclaimedRewardAmount: selectUnclaimedRewardValue(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);
|
||||||
|
|
|
@ -2,47 +2,60 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import CreditAmount from 'component/common/credit-amount';
|
import CreditAmount from 'component/common/credit-amount';
|
||||||
|
import BusyIndicator from 'component/common/busy-indicator';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
unclaimedRewardAmount: number,
|
unclaimedRewardAmount: number,
|
||||||
|
fetching: boolean,
|
||||||
|
fetchRewards: () => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
const RewardSummary = (props: Props) => {
|
class RewardSummary extends React.Component<Props> {
|
||||||
const { unclaimedRewardAmount } = props;
|
componentDidMount() {
|
||||||
const hasRewards = unclaimedRewardAmount > 0;
|
this.props.fetchRewards();
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
render() {
|
||||||
<section className="card card--section">
|
const { unclaimedRewardAmount, fetching } = this.props;
|
||||||
<div className="card__title">{__('Rewards')}</div>
|
const hasRewards = unclaimedRewardAmount > 0;
|
||||||
<p className="card__subtitle">
|
|
||||||
{hasRewards ? (
|
return (
|
||||||
<React.Fragment>
|
<section className="card card--section">
|
||||||
{__('You have')}
|
<div className="card__title">
|
||||||
|
{__('Rewards')}
|
||||||
<CreditAmount noStyle amount={unclaimedRewardAmount} precision={8} />
|
{fetching && <BusyIndicator />}
|
||||||
|
</div>
|
||||||
{__('in unclaimed rewards')}.
|
<p className="card__subtitle">
|
||||||
</React.Fragment>
|
{!fetching &&
|
||||||
) : (
|
(hasRewards ? (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{__('There are no rewards available at this time, please check back later')}.
|
{__('You have')}
|
||||||
</React.Fragment>
|
|
||||||
)}
|
<CreditAmount noStyle amount={unclaimedRewardAmount} precision={8} />
|
||||||
</p>
|
|
||||||
<div className="card__actions">
|
{__('in unclaimed rewards')}.
|
||||||
<Button
|
</React.Fragment>
|
||||||
button="primary"
|
) : (
|
||||||
navigate="/rewards"
|
<React.Fragment>
|
||||||
label={hasRewards ? __('Claim Rewards') : __('View Rewards')}
|
{__('There are no rewards available at this time, please check back later')}.
|
||||||
/>
|
</React.Fragment>
|
||||||
</div>
|
))}
|
||||||
<p className="help help--padded">
|
</p>
|
||||||
{__('Read our')}{' '}
|
<div className="card__actions">
|
||||||
<Button button="link" label={__('FAQ')} href="https://lbry.io/faq/rewards" />{' '}
|
<Button
|
||||||
{__('to learn more about LBRY Rewards')}.
|
button="primary"
|
||||||
</p>
|
navigate="/rewards"
|
||||||
</section>
|
label={hasRewards ? __('Claim Rewards') : __('View Rewards')}
|
||||||
);
|
/>
|
||||||
};
|
</div>
|
||||||
|
<p className="help help--padded">
|
||||||
|
{__('Read our')}{' '}
|
||||||
|
<Button button="link" label={__('FAQ')} href="https://lbry.io/faq/rewards" />{' '}
|
||||||
|
{__('to learn more about LBRY Rewards')}.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default RewardSummary;
|
export default RewardSummary;
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { THUMBNAIL_STATUSES, MODALS } from 'lbry-redux';
|
import { THUMBNAIL_STATUSES, MODALS } from 'lbry-redux';
|
||||||
import React from 'react';
|
import * as React from 'react';
|
||||||
import { FormField, FormRow } from 'component/common/form';
|
import { FormField } from 'component/common/form';
|
||||||
import FileSelector from 'component/common/file-selector';
|
import FileSelector from 'component/common/file-selector';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
import Native from 'native';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
thumbnail: ?string,
|
thumbnail: ?string,
|
||||||
|
@ -15,7 +16,29 @@ type Props = {
|
||||||
resetThumbnailStatus: () => void,
|
resetThumbnailStatus: () => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
class SelectThumbnail extends React.PureComponent<Props> {
|
type State = {
|
||||||
|
thumbnailError: boolean,
|
||||||
|
};
|
||||||
|
|
||||||
|
class SelectThumbnail extends React.PureComponent<Props, State> {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
thumbnailError: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
(this: any).handleThumbnailChange = this.handleThumbnailChange.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleThumbnailChange(e: SyntheticInputEvent<*>) {
|
||||||
|
const { updatePublishForm } = this.props;
|
||||||
|
const newThumbnail = e.target.value.replace(' ', '');
|
||||||
|
|
||||||
|
updatePublishForm({ thumbnail: newThumbnail });
|
||||||
|
this.setState({ thumbnailError: false });
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
thumbnail,
|
thumbnail,
|
||||||
|
@ -26,25 +49,47 @@ class SelectThumbnail extends React.PureComponent<Props> {
|
||||||
thumbnailPath,
|
thumbnailPath,
|
||||||
resetThumbnailStatus,
|
resetThumbnailStatus,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
const { thumbnailError } = this.state;
|
||||||
|
const thumbnailSrc =
|
||||||
|
!thumbnail || thumbnailError ? Native.imagePath('no-thumbnail.png') : thumbnail;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="card__content">
|
||||||
{status === THUMBNAIL_STATUSES.API_DOWN || status === THUMBNAIL_STATUSES.MANUAL ? (
|
{status === THUMBNAIL_STATUSES.API_DOWN || status === THUMBNAIL_STATUSES.MANUAL ? (
|
||||||
<FormRow padded>
|
<div className="column">
|
||||||
<FormField
|
<img
|
||||||
stretch
|
src={thumbnailSrc}
|
||||||
type="text"
|
className="column__item thumbnail-preview"
|
||||||
name="content_thumbnail"
|
alt={__('Thumbnail Preview')}
|
||||||
label={__('URL')}
|
onError={() => {
|
||||||
placeholder="http://spee.ch/mylogo"
|
this.setState({ thumbnailError: true });
|
||||||
value={thumbnail}
|
}}
|
||||||
disabled={formDisabled}
|
|
||||||
onChange={e => updatePublishForm({ thumbnail: e.target.value })}
|
|
||||||
/>
|
/>
|
||||||
</FormRow>
|
<div className="column__item">
|
||||||
|
<FormField
|
||||||
|
className="input--thumbnail"
|
||||||
|
type="text"
|
||||||
|
name="content_thumbnail"
|
||||||
|
label="URL"
|
||||||
|
placeholder="http://spee.ch/mylogo"
|
||||||
|
value={thumbnail}
|
||||||
|
disabled={formDisabled}
|
||||||
|
onChange={this.handleThumbnailChange}
|
||||||
|
/>
|
||||||
|
<div className="card__actions">
|
||||||
|
<Button
|
||||||
|
button="link"
|
||||||
|
label={__('Use thumbnail upload tool')}
|
||||||
|
onClick={() =>
|
||||||
|
updatePublishForm({ uploadThumbnailStatus: THUMBNAIL_STATUSES.READY })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="form-row--padded">
|
<React.Fragment>
|
||||||
{(status === THUMBNAIL_STATUSES.READY || status === THUMBNAIL_STATUSES.COMPLETE) && (
|
{status === THUMBNAIL_STATUSES.READY && (
|
||||||
<FileSelector
|
<FileSelector
|
||||||
currentPath={thumbnailPath}
|
currentPath={thumbnailPath}
|
||||||
fileLabel={__('Choose Thumbnail')}
|
fileLabel={__('Choose Thumbnail')}
|
||||||
|
@ -52,18 +97,31 @@ class SelectThumbnail extends React.PureComponent<Props> {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{status === THUMBNAIL_STATUSES.COMPLETE && (
|
{status === THUMBNAIL_STATUSES.COMPLETE && (
|
||||||
<div>
|
<div className="column column--space-between">
|
||||||
<p>
|
<img
|
||||||
Upload complete. View it{' '}
|
className="column__item thumbnail-preview"
|
||||||
<Button button="link" href={thumbnail} label={__('here')} />.
|
src={thumbnail}
|
||||||
</p>
|
alt={__('Thumbnail Preview')}
|
||||||
<Button button="link" label={__('New thumbnail')} onClick={resetThumbnailStatus} />
|
/>
|
||||||
|
<div className="column__item">
|
||||||
|
<p>
|
||||||
|
Upload complete.{' '}
|
||||||
|
<Button button="link" href={thumbnail} label={__('View it on spee.ch')} />.
|
||||||
|
</p>
|
||||||
|
<div className="card__actions">
|
||||||
|
<Button
|
||||||
|
button="link"
|
||||||
|
label={__('New thumbnail')}
|
||||||
|
onClick={resetThumbnailStatus}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
<div className="card__actions">
|
{status === THUMBNAIL_STATUSES.READY && (
|
||||||
{status === THUMBNAIL_STATUSES.READY && (
|
<div className="card__actions">
|
||||||
<Button
|
<Button
|
||||||
button="link"
|
button="link"
|
||||||
label={__('Or enter a URL manually')}
|
label={__('Or enter a URL manually')}
|
||||||
|
@ -71,15 +129,8 @@ class SelectThumbnail extends React.PureComponent<Props> {
|
||||||
updatePublishForm({ uploadThumbnailStatus: THUMBNAIL_STATUSES.MANUAL })
|
updatePublishForm({ uploadThumbnailStatus: THUMBNAIL_STATUSES.MANUAL })
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
</div>
|
||||||
{status === THUMBNAIL_STATUSES.MANUAL && (
|
)}
|
||||||
<Button
|
|
||||||
button="link"
|
|
||||||
label={__('Use thumbnail upload tool')}
|
|
||||||
onClick={() => updatePublishForm({ uploadThumbnailStatus: THUMBNAIL_STATUSES.READY })}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{status === THUMBNAIL_STATUSES.IN_PROGRESS && <p>{__('Uploading thumbnail')}...</p>}
|
{status === THUMBNAIL_STATUSES.IN_PROGRESS && <p>{__('Uploading thumbnail')}...</p>}
|
||||||
</div>
|
</div>
|
||||||
|
|
281
src/renderer/component/viewers/threeViewer/index.jsx
Normal file
281
src/renderer/component/viewers/threeViewer/index.jsx
Normal file
|
@ -0,0 +1,281 @@
|
||||||
|
// @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<Props> {
|
||||||
|
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 (
|
||||||
|
<React.Fragment>
|
||||||
|
{error && <LoadingScreen status={error} spinner={false} />}
|
||||||
|
{showLoading && <LoadingScreen status={loadingMessage} spinner />}
|
||||||
|
<div
|
||||||
|
style={{ opacity: showViewer ? 1 : 0 }}
|
||||||
|
className="three-viewer file-render__viewer"
|
||||||
|
ref={this.viewer}
|
||||||
|
/>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ThreeViewer;
|
|
@ -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;
|
|
@ -0,0 +1,33 @@
|
||||||
|
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;
|
|
@ -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;
|
57
src/renderer/component/viewers/threeViewer/internal/scene.js
Normal file
57
src/renderer/component/viewers/threeViewer/internal/scene.js
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
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;
|
10
src/renderer/component/viewers/threeViewer/internal/three.js
Normal file
10
src/renderer/component/viewers/threeViewer/internal/three.js
Normal file
|
@ -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;
|
|
@ -10,7 +10,6 @@ import type { Reward } from 'types/reward';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
doAuth: () => void,
|
doAuth: () => void,
|
||||||
fetchRewards: () => void,
|
|
||||||
navigate: string => void,
|
navigate: string => void,
|
||||||
fetching: boolean,
|
fetching: boolean,
|
||||||
rewards: Array<Reward>,
|
rewards: Array<Reward>,
|
||||||
|
@ -27,10 +26,6 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
class RewardsPage extends React.PureComponent<Props> {
|
class RewardsPage extends React.PureComponent<Props> {
|
||||||
componentDidMount() {
|
|
||||||
this.props.fetchRewards();
|
|
||||||
}
|
|
||||||
|
|
||||||
renderPageHeader() {
|
renderPageHeader() {
|
||||||
const { doAuth, navigate, user, daemonSettings } = this.props;
|
const { doAuth, navigate, user, daemonSettings } = this.props;
|
||||||
|
|
||||||
|
|
|
@ -171,7 +171,7 @@ export function doUpdateLoadStatus(uri, outpoint) {
|
||||||
} else {
|
} else {
|
||||||
// ready to play
|
// ready to play
|
||||||
const { total_bytes: totalBytes, written_bytes: writtenBytes } = fileInfo;
|
const { total_bytes: totalBytes, written_bytes: writtenBytes } = fileInfo;
|
||||||
const progress = writtenBytes / totalBytes * 100;
|
const progress = (writtenBytes / totalBytes) * 100;
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ACTIONS.DOWNLOADING_PROGRESSED,
|
type: ACTIONS.DOWNLOADING_PROGRESSED,
|
||||||
|
@ -259,29 +259,37 @@ export function doLoadVideo(uri) {
|
||||||
streamInfo === null || typeof streamInfo !== 'object' || streamInfo.error === 'Timeout';
|
streamInfo === null || typeof streamInfo !== 'object' || streamInfo.error === 'Timeout';
|
||||||
|
|
||||||
if (timeout) {
|
if (timeout) {
|
||||||
dispatch(doSetPlayingUri(null));
|
dispatch(handleLoadVideoError(uri, 'timeout'));
|
||||||
dispatch({
|
|
||||||
type: ACTIONS.LOADING_VIDEO_FAILED,
|
|
||||||
data: { uri },
|
|
||||||
});
|
|
||||||
|
|
||||||
dispatch(doNotify({ id: MODALS.FILE_TIMEOUT }, { uri }));
|
|
||||||
} else {
|
} else {
|
||||||
dispatch(doDownloadFile(uri, streamInfo));
|
dispatch(doDownloadFile(uri, streamInfo));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
dispatch(doSetPlayingUri(null));
|
dispatch(handleLoadVideoError(uri));
|
||||||
dispatch({
|
});
|
||||||
type: ACTIONS.LOADING_VIDEO_FAILED,
|
};
|
||||||
data: { 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(
|
dispatch(
|
||||||
doAlertError(
|
doAlertError(
|
||||||
`Failed to download ${uri}, please try again. If this problem persists, visit https://lbry.io/faq/support for support.`
|
`Failed to download ${uri}, please try again. If this problem persists, visit https://lbry.io/faq/support for support.`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ export function doClaimRewardType(rewardType, options) {
|
||||||
});
|
});
|
||||||
|
|
||||||
const success = successReward => {
|
const success = successReward => {
|
||||||
|
dispatch(doRewardList());
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ACTIONS.CLAIM_REWARD_SUCCESS,
|
type: ACTIONS.CLAIM_REWARD_SUCCESS,
|
||||||
data: {
|
data: {
|
||||||
|
|
|
@ -3,9 +3,9 @@ import {
|
||||||
selectIsFetchingClaimListMine,
|
selectIsFetchingClaimListMine,
|
||||||
selectMyClaims,
|
selectMyClaims,
|
||||||
selectClaimsById,
|
selectClaimsById,
|
||||||
} from 'redux/selectors/claims';
|
buildURI,
|
||||||
|
} from 'lbry-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { buildURI } from 'lbryURI';
|
|
||||||
|
|
||||||
export const selectState = state => state.fileInfo || {};
|
export const selectState = state => state.fileInfo || {};
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ export const selectTotalDownloadProgress = createSelector(selectDownloadingFileI
|
||||||
const progress = [];
|
const progress = [];
|
||||||
|
|
||||||
fileInfos.forEach(fileInfo => {
|
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);
|
const totalProgress = progress.reduce((a, b) => a + b, 0);
|
||||||
|
@ -195,3 +195,5 @@ export const selectSearchDownloadUris = query =>
|
||||||
})
|
})
|
||||||
: null;
|
: null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const selectFileInfoErrors = createSelector(selectState, state => state.errors || {});
|
||||||
|
|
|
@ -153,7 +153,6 @@ dd {
|
||||||
|
|
||||||
p {
|
p {
|
||||||
font-family: 'metropolis-medium';
|
font-family: 'metropolis-medium';
|
||||||
padding: $spacing-vertical * 1/3 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.page {
|
.page {
|
||||||
|
@ -302,6 +301,14 @@ p {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.column {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.column__item:not(:first-child) {
|
||||||
|
padding-left: $spacing-width * 2/3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.truncated-text {
|
.truncated-text {
|
||||||
//display: inline-block;
|
//display: inline-block;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
|
@ -365,3 +372,9 @@ p {
|
||||||
.error-text {
|
.error-text {
|
||||||
color: var(--color-error);
|
color: var(--color-error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.thumbnail-preview {
|
||||||
|
height: var(--thumbnail-preview-height);
|
||||||
|
width: var(--thumbnail-preview-width);
|
||||||
|
border: var(--thumbnail-preview-border);
|
||||||
|
}
|
||||||
|
|
|
@ -179,4 +179,10 @@ $large-breakpoint: 1921px;
|
||||||
// /* Animation :) */
|
// /* Animation :) */
|
||||||
--animation-duration: 0.3s;
|
--animation-duration: 0.3s;
|
||||||
--animation-style: cubic-bezier(0.55, 0, 0.1, 1);
|
--animation-style: cubic-bezier(0.55, 0, 0.1, 1);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -255,6 +255,12 @@
|
||||||
right: $spacing-vertical;
|
right: $spacing-vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card__actions-bottom-corner {
|
||||||
|
position: absolute;
|
||||||
|
bottom: $spacing-vertical;
|
||||||
|
right: $spacing-vertical;
|
||||||
|
}
|
||||||
|
|
||||||
.card__actions--end {
|
.card__actions--end {
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,8 +67,8 @@
|
||||||
width: 35px;
|
width: 35px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input.paginate-channel {
|
input.input--thumbnail {
|
||||||
width: 35px;
|
width: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.form-field--auto-height {
|
&.form-field--auto-height {
|
||||||
|
|
BIN
static/img/no-thumbnail.png
Normal file
BIN
static/img/no-thumbnail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
148
yarn.lock
148
yarn.lock
|
@ -279,6 +279,14 @@ app-builder-bin@1.11.1:
|
||||||
version "1.11.1"
|
version "1.11.1"
|
||||||
resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-1.11.1.tgz#33741167f2873cf76805c9557b62caac8ede017b"
|
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-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:
|
app-root-path@^2.0.1:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.1.0.tgz#98bf6599327ecea199309866e8140368fd2e646a"
|
resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.1.0.tgz#98bf6599327ecea199309866e8140368fd2e646a"
|
||||||
|
@ -1479,7 +1487,16 @@ buffers@~0.1.1:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb"
|
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"
|
version "4.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-4.4.0.tgz#1f486819df12a04abfa128fe082e7c54edda0ef7"
|
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-4.4.0.tgz#1f486819df12a04abfa128fe082e7c54edda0ef7"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -1488,7 +1505,45 @@ builder-util-runtime@4.4.0, builder-util-runtime@^4.4.0, builder-util-runtime@~4
|
||||||
fs-extra-p "^4.6.1"
|
fs-extra-p "^4.6.1"
|
||||||
sax "^1.2.4"
|
sax "^1.2.4"
|
||||||
|
|
||||||
builder-util@5.16.0, builder-util@^5.13.0, builder-util@^5.14.0, builder-util@~5.16.0:
|
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.2"
|
||||||
|
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.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.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"
|
version "5.16.0"
|
||||||
resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-5.16.0.tgz#8b9aabe15a1a5c4ffa8ebc511049248918f717df"
|
resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-5.16.0.tgz#8b9aabe15a1a5c4ffa8ebc511049248918f717df"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -2504,13 +2559,13 @@ diffie-hellman@^5.0.0:
|
||||||
miller-rabin "^4.0.0"
|
miller-rabin "^4.0.0"
|
||||||
randombytes "^2.0.0"
|
randombytes "^2.0.0"
|
||||||
|
|
||||||
dmg-builder@4.14.0:
|
dmg-builder@4.14.1:
|
||||||
version "4.14.0"
|
version "4.14.1"
|
||||||
resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-4.14.0.tgz#6d19922a82cee78cc13557ab0cbc16047864002a"
|
resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-4.14.1.tgz#af1e2c7b40407291555f72df9bfee2ed7d0ebf68"
|
||||||
dependencies:
|
dependencies:
|
||||||
bluebird-lst "^1.0.5"
|
bluebird-lst "^1.0.5"
|
||||||
builder-util "~5.16.0"
|
builder-util "~5.16.2"
|
||||||
electron-builder-lib "~20.20.4"
|
electron-builder-lib "~20.22.0"
|
||||||
fs-extra-p "^4.6.1"
|
fs-extra-p "^4.6.1"
|
||||||
iconv-lite "^0.4.23"
|
iconv-lite "^0.4.23"
|
||||||
js-yaml "^3.12.0"
|
js-yaml "^3.12.0"
|
||||||
|
@ -2650,21 +2705,21 @@ ejs@^2.6.1:
|
||||||
version "2.6.1"
|
version "2.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0"
|
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.22.0:
|
||||||
version "20.20.4"
|
version "20.22.0"
|
||||||
resolved "https://registry.yarnpkg.com/electron-builder-lib/-/electron-builder-lib-20.20.4.tgz#fd129ae85c5514f16f4f392218141ebe3dc8411d"
|
resolved "https://registry.yarnpkg.com/electron-builder-lib/-/electron-builder-lib-20.22.0.tgz#594077a3ffdb0ccfb18e79959ca7a5fc8662912c"
|
||||||
dependencies:
|
dependencies:
|
||||||
"7zip-bin" "~4.0.2"
|
"7zip-bin" "~4.0.2"
|
||||||
app-builder-bin "1.11.1"
|
app-builder-bin "1.11.2"
|
||||||
async-exit-hook "^2.0.1"
|
async-exit-hook "^2.0.1"
|
||||||
bluebird-lst "^1.0.5"
|
bluebird-lst "^1.0.5"
|
||||||
builder-util "5.16.0"
|
builder-util "5.16.2"
|
||||||
builder-util-runtime "4.4.0"
|
builder-util-runtime "4.4.1"
|
||||||
chromium-pickle-js "^0.2.0"
|
chromium-pickle-js "^0.2.0"
|
||||||
debug "^3.1.0"
|
debug "^3.1.0"
|
||||||
ejs "^2.6.1"
|
ejs "^2.6.1"
|
||||||
electron-osx-sign "0.4.10"
|
electron-osx-sign "0.4.10"
|
||||||
electron-publish "20.22.0"
|
electron-publish "20.22.2"
|
||||||
env-paths "^1.0.0"
|
env-paths "^1.0.0"
|
||||||
fs-extra-p "^4.6.1"
|
fs-extra-p "^4.6.1"
|
||||||
hosted-git-info "^2.7.1"
|
hosted-git-info "^2.7.1"
|
||||||
|
@ -2681,16 +2736,47 @@ electron-builder-lib@20.20.4, electron-builder-lib@~20.20.4:
|
||||||
sumchecker "^2.0.2"
|
sumchecker "^2.0.2"
|
||||||
temp-file "^3.1.3"
|
temp-file "^3.1.3"
|
||||||
|
|
||||||
electron-builder@^20.13.3:
|
electron-builder-lib@~20.22.0:
|
||||||
version "20.20.4"
|
version "20.22.1"
|
||||||
resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-20.20.4.tgz#09d879c6551df801444a153dc7b159a304e1d55d"
|
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.3"
|
||||||
|
async-exit-hook "^2.0.1"
|
||||||
|
bluebird-lst "^1.0.5"
|
||||||
|
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.2"
|
||||||
|
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@^20.22.0:
|
||||||
|
version "20.22.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-20.22.0.tgz#90760c2335e0673d1c2d24af7a2f8e33646e9303"
|
||||||
dependencies:
|
dependencies:
|
||||||
bluebird-lst "^1.0.5"
|
bluebird-lst "^1.0.5"
|
||||||
builder-util "5.16.0"
|
builder-util "5.16.2"
|
||||||
builder-util-runtime "4.4.0"
|
builder-util-runtime "4.4.1"
|
||||||
chalk "^2.4.1"
|
chalk "^2.4.1"
|
||||||
dmg-builder "4.14.0"
|
dmg-builder "4.14.1"
|
||||||
electron-builder-lib "20.20.4"
|
electron-builder-lib "20.22.0"
|
||||||
fs-extra-p "^4.6.1"
|
fs-extra-p "^4.6.1"
|
||||||
is-ci "^1.1.0"
|
is-ci "^1.1.0"
|
||||||
lazy-val "^1.0.3"
|
lazy-val "^1.0.3"
|
||||||
|
@ -2749,13 +2835,13 @@ electron-osx-sign@0.4.10:
|
||||||
minimist "^1.2.0"
|
minimist "^1.2.0"
|
||||||
plist "^2.1.0"
|
plist "^2.1.0"
|
||||||
|
|
||||||
electron-publish@20.22.0:
|
electron-publish@20.22.2:
|
||||||
version "20.22.0"
|
version "20.22.2"
|
||||||
resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-20.22.0.tgz#352f04fc4821176e0c40a16d64b1c94026e2441f"
|
resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-20.22.2.tgz#4a680de581b0d7339aff113fd8a505a0976a0d58"
|
||||||
dependencies:
|
dependencies:
|
||||||
bluebird-lst "^1.0.5"
|
bluebird-lst "^1.0.5"
|
||||||
builder-util "^5.14.0"
|
builder-util "~5.16.2"
|
||||||
builder-util-runtime "^4.4.0"
|
builder-util-runtime "^4.4.1"
|
||||||
chalk "^2.4.1"
|
chalk "^2.4.1"
|
||||||
fs-extra-p "^4.6.1"
|
fs-extra-p "^4.6.1"
|
||||||
lazy-val "^1.0.3"
|
lazy-val "^1.0.3"
|
||||||
|
@ -2788,7 +2874,7 @@ electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.47:
|
||||||
version "1.3.52"
|
version "1.3.52"
|
||||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.52.tgz#d2d9f1270ba4a3b967b831c40ef71fb4d9ab5ce0"
|
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"
|
version "2.23.3"
|
||||||
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-2.23.3.tgz#7bf054075f0cef2cd832cb533cf21adcdd5780b8"
|
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-2.23.3.tgz#7bf054075f0cef2cd832cb533cf21adcdd5780b8"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -5135,9 +5221,9 @@ lazy-val@^1.0.3:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.3.tgz#bb97b200ef00801d94c317e29dc6ed39e31c5edc"
|
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"
|
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:
|
dependencies:
|
||||||
proxy-polyfill "0.1.6"
|
proxy-polyfill "0.1.6"
|
||||||
reselect "^3.0.0"
|
reselect "^3.0.0"
|
||||||
|
@ -8411,6 +8497,10 @@ text-table@~0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
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:
|
throttleit@0.0.2:
|
||||||
version "0.0.2"
|
version "0.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf"
|
resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf"
|
||||||
|
|
Loading…
Add table
Reference in a new issue