Skip to content

Commit

Permalink
Merge pull request #2095 from lbryio/comments
Browse files Browse the repository at this point in the history
Comments support button
  • Loading branch information
Sean Yesmunt authored Nov 14, 2018
2 parents f4d1a4e + 39fa8e7 commit a8b8e02
Show file tree
Hide file tree
Showing 16 changed files with 261 additions and 71 deletions.
7 changes: 7 additions & 0 deletions src/renderer/component/expandable/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { connect } from 'react-redux';
import Expandable from './view';

export default connect(
null,
null
)(Expandable);
57 changes: 57 additions & 0 deletions src/renderer/component/expandable/view.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// @flow
import React, { PureComponent, Node } from 'react';
import classnames from 'classnames';
import Button from 'component/button';

// Note:
// When we use this in other parts of the app, we will probably need to
// add props for collapsed height

type Props = {
children: Node | Array<Node>,
};

type State = {
expanded: boolean,
};

export default class Expandable extends PureComponent<Props, State> {
constructor() {
super();

this.state = {
expanded: false,
};

(this: any).handleClick = this.handleClick.bind(this);
}

handleClick() {
this.setState({
expanded: !this.state.expanded,
});
}

render() {
const { children } = this.props;
const { expanded } = this.state;

return (
<div className="expandable">
<div
className={classnames({
'expandable--open': expanded,
'expandable--closed': !expanded,
})}
>
{children}
</div>
<Button
button="link"
label={expanded ? __('Less') : __('More')}
onClick={this.handleClick}
/>
</div>
);
}
}
8 changes: 8 additions & 0 deletions src/renderer/component/fileDetails/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,27 @@ import {
makeSelectContentTypeForUri,
makeSelectMetadataForUri,
makeSelectFileInfoForUri,
doNotify,
} from 'lbry-redux';
import { selectUser } from 'lbryinc';
import { doOpenFileInFolder } from 'redux/actions/file';
import { selectHasClickedComment } from 'redux/selectors/app';
import { doClickCommentButton } from 'redux/actions/app';
import FileDetails from './view';

const select = (state, props) => ({
claim: makeSelectClaimForUri(props.uri)(state),
contentType: makeSelectContentTypeForUri(props.uri)(state),
fileInfo: makeSelectFileInfoForUri(props.uri)(state),
metadata: makeSelectMetadataForUri(props.uri)(state),
hasClickedComment: selectHasClickedComment(state),
user: selectUser(state),
});

const perform = dispatch => ({
openFolder: path => dispatch(doOpenFileInFolder(path)),
showSnackBar: message => dispatch(doNotify({ message, displayType: ['snackbar'] })),
clickCommentButton: () => dispatch(doClickCommentButton()),
});

export default connect(
Expand Down
163 changes: 107 additions & 56 deletions src/renderer/component/fileDetails/view.jsx
Original file line number Diff line number Diff line change
@@ -1,77 +1,128 @@
// @flow
import * as React from 'react';
import type { Claim, Metadata } from 'types/claim';
import type { FileInfo } from 'types/file_info';
import React, { Fragment, PureComponent } from 'react';
import { Lbryio } from 'lbryinc';
import MarkdownPreview from 'component/common/markdown-preview';
import Button from 'component/button';
import path from 'path';
import type { Claim } from 'types/claim';
import Expandable from 'component/expandable';

type Props = {
claim: Claim,
fileInfo: {
download_path: string,
},
metadata: {
description: string,
language: string,
license: string,
},
fileInfo: FileInfo,
metadata: Metadata,
openFolder: string => void,
contentType: string,
clickCommentButton: () => void,
showSnackBar: string => void,
hasClickedComment: boolean,
user: ?any,
};

const FileDetails = (props: Props) => {
const { claim, contentType, fileInfo, metadata, openFolder } = props;
class FileDetails extends PureComponent<Props> {
constructor() {
super();
(this: any).handleCommentClick = this.handleCommentClick.bind(this);
}

if (!claim || !metadata) {
return (
<div className="card__content">
<span className="empty">{__('Empty claim or metadata info.')}</span>
</div>
);
handleCommentClick() {
const { clickCommentButton, showSnackBar } = this.props;

clickCommentButton();
Lbryio.call('user_tag', 'edit', { add: 'comments-waitlist' });
showSnackBar(__('Thanks! Comments are coming soon(ish).'));
}

const { description, language, license } = metadata;
render() {
const {
claim,
contentType,
fileInfo,
metadata,
openFolder,
hasClickedComment,
user,
} = this.props;

const mediaType = contentType || 'unknown';
const downloadPath = fileInfo ? path.normalize(fileInfo.download_path) : null;
if (!claim || !metadata) {
return (
<div className="card__content">
<span className="empty">{__('Empty claim or metadata info.')}</span>
</div>
);
}

const { description, language, license } = metadata;

return (
<React.Fragment>
{description && (
<React.Fragment>
<div className="card__subtext-title">About</div>
const mediaType = contentType || 'unknown';
const downloadPath = fileInfo ? path.normalize(fileInfo.download_path) : null;

return (
<Fragment>
<Expandable>
{description && (
<Fragment>
<div className="card__subtext-title">About</div>
<div className="card__subtext">
<MarkdownPreview content={description} promptLinks />
</div>
</Fragment>
)}
<div className="card__subtext-title">Info</div>
<div className="card__subtext">
<MarkdownPreview content={description} promptLinks={true} />
<div>
{__('Content-Type')}
{': '}
{mediaType}
</div>
<div>
{__('Language')}
{': '}
{language}
</div>
<div>
{__('License')}
{': '}
{license}
</div>
{downloadPath && (
<div>
{__('Downloaded to')}
{': '}
<Button
button="link"
onClick={() => openFolder(downloadPath)}
label={downloadPath}
/>
</div>
)}
</div>
</React.Fragment>
)}
<div className="card__subtext-title">Info</div>
<div className="card__subtext">
<div>
{__('Content-Type')}
{': '}
{mediaType}
</div>
<div>
{__('Language')}
{': '}
{language}
</div>
<div>
{__('License')}
{': '}
{license}
</div>
{downloadPath && (
<div>
{__('Downloaded to')}
{': '}
<Button button="link" onClick={() => openFolder(downloadPath)} label={downloadPath} />
</Expandable>
<div className="card__content">
<div className="card__subtext-title">Comments</div>
<div className="card__actions card__actions--center">
<Button
data-id="add-comment"
disabled={hasClickedComment}
button="primary"
label={__('Want to comment?')}
onClick={this.handleCommentClick}
/>
</div>
)}
</div>
</React.Fragment>
);
};
{hasClickedComment && (
<p className="main--for-content">
{user
? __(
'Your support has been added. You will be notified when comments are available.'
)
: __('Your support has been added. Comments are coming soon.')}
</p>
)}
</div>
</Fragment>
);
}
}

export default FileDetails;
2 changes: 2 additions & 0 deletions src/renderer/constants/action_types.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const DAEMON_READY = 'DAEMON_READY';
export const DAEMON_VERSION_MATCH = 'DAEMON_VERSION_MATCH';
export const DAEMON_VERSION_MISMATCH = 'DAEMON_VERSION_MISMATCH';
export const VOLUME_CHANGED = 'VOLUME_CHANGED';
export const ADD_COMMENT = 'ADD_COMMENT';

// Navigation
export const CHANGE_AFTER_AUTH_PATH = 'CHANGE_AFTER_AUTH_PATH';
Expand All @@ -36,6 +37,7 @@ export const SKIP_UPGRADE = 'SKIP_UPGRADE';
export const START_UPGRADE = 'START_UPGRADE';
export const AUTO_UPDATE_DECLINED = 'AUTO_UPDATE_DECLINED';
export const AUTO_UPDATE_DOWNLOADED = 'AUTO_UPDATE_DOWNLOADED';
export const CLEAR_UPGRADE_TIMER = 'CLEAR_UPGRADE_TIMER';

// Wallet
export const GET_NEW_ADDRESS_STARTED = 'GET_NEW_ADDRESS_STARTED';
Expand Down
7 changes: 6 additions & 1 deletion src/renderer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,16 @@ document.addEventListener('drop', event => {
});
document.addEventListener('click', event => {
let { target } = event;

while (target && target !== document) {
if (target.matches('a') || target.matches('button')) {
// TODO: Look into using accessiblity labels (this would also make the app more accessible)
const hrefParts = window.location.href.split('#');
const element = target.title || (target.textContent && target.textContent.trim());

// Buttons that we want to track should use `data-id`
// This prevents multiple buttons being grouped together if they have the same text
const element =
target.dataset.id || target.title || (target.textContent && target.textContent.trim());
if (element) {
analytics.track('CLICK', {
target: element,
Expand Down
8 changes: 7 additions & 1 deletion src/renderer/redux/actions/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { execSync } from 'child_process';
import isDev from 'electron-is-dev';
import path from 'path';
import { ipcRenderer, remote } from 'electron';
import * as ACTIONS from 'constants/action_types';
import {
ACTIONS,
Lbry,
doBalanceSubscribe,
doFetchFileInfosAndPublishedClaims,
Expand Down Expand Up @@ -387,6 +387,12 @@ export function doChangeVolume(volume) {
};
}

export function doClickCommentButton() {
return {
type: ACTIONS.ADD_COMMENT,
};
}

export function doConditionalAuthNavigate(newSession) {
return (dispatch, getState) => {
const state = getState();
Expand Down
10 changes: 7 additions & 3 deletions src/renderer/redux/reducers/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export type AppState = {
checkUpgradeTimer: ?number,
isUpgradeAvailable: ?boolean,
isUpgradeSkipped: ?boolean,
snackBar: ?SnackBar,
hasClickedComment: boolean,
};

const defaultState: AppState = {
Expand All @@ -50,14 +50,13 @@ const defaultState: AppState = {
autoUpdateDownloaded: false,
autoUpdateDeclined: false,
modalsAllowed: true,

hasClickedComment: false,
downloadProgress: undefined,
upgradeDownloading: undefined,
upgradeDownloadComplete: undefined,
checkUpgradeTimer: undefined,
isUpgradeAvailable: undefined,
isUpgradeSkipped: undefined,
snackBar: undefined,
};

reducers[ACTIONS.DAEMON_READY] = state =>
Expand Down Expand Up @@ -189,6 +188,11 @@ reducers[ACTIONS.CLEAR_UPGRADE_TIMER] = state =>
checkUpgradeTimer: undefined,
});

reducers[ACTIONS.ADD_COMMENT] = state =>
Object.assign({}, state, {
hasClickedComment: true,
});

export default function reducer(state: AppState = defaultState, action: any) {
const handler = reducers[action.type];
if (handler) return handler(state, action);
Expand Down
5 changes: 5 additions & 0 deletions src/renderer/redux/selectors/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ export const selectUpdateUrl = createSelector(selectPlatform, platform => {
}
});

export const selectHasClickedComment = createSelector(
selectState,
state => state.hasClickedComment
);

export const selectRemoteVersion = createSelector(selectState, state => state.remoteVersion);

export const selectIsUpgradeAvailable = createSelector(
Expand Down
Loading

0 comments on commit a8b8e02

Please sign in to comment.