Skip to content

Commit 24e2544

Browse files
committed
Url share done
1 parent a4c72a9 commit 24e2544

11 files changed

Lines changed: 291 additions & 295 deletions

File tree

browser/main/HomePage.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import _ from 'lodash'
99
import { isModalOpen, closeModal } from 'boost/modal'
1010

1111
const electron = require('electron')
12-
const BrowserWindow = electron.remote.BrowserWindow
12+
const remote = electron.remote
1313

1414
const TEXT_FILTER = 'TEXT_FILTER'
1515
const FOLDER_FILTER = 'FOLDER_FILTER'
@@ -29,10 +29,10 @@ class HomePage extends React.Component {
2929
}
3030

3131
handleKeyDown (e) {
32-
if (process.env.BOOST_ENV === 'development' && e.keyCode === 73 && e.metaKey && e.altKey) {
32+
if (e.keyCode === 73 && e.metaKey && e.altKey) {
3333
e.preventDefault()
3434
e.stopPropagation()
35-
BrowserWindow.getFocusedWindow().toggleDevTools()
35+
remote.getCurrentWebContents().openDevTools()
3636
return
3737
}
3838

@@ -106,7 +106,7 @@ class HomePage extends React.Component {
106106
list.selectNextArticle()
107107
}
108108

109-
if (e.keyCode === 65 || (e.keyCode === 13 && e.metaKey) || (e.keyCode === 78 && e.metaKey)) {
109+
if ((e.keyCode === 65 && !e.metaKey && !e.ctrlKey) || (e.keyCode === 13 && e.metaKey) || (e.keyCode === 78 && e.metaKey)) {
110110
nav.handleNewPostButtonClick()
111111
e.preventDefault()
112112
}
@@ -142,6 +142,7 @@ class HomePage extends React.Component {
142142
<ArticleDetail
143143
ref='detail'
144144
dispatch={dispatch}
145+
user={user}
145146
activeArticle={activeArticle}
146147
folders={folders}
147148
status={status}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import React, { PropTypes } from 'react'
2+
import ReactDOM from 'react-dom'
3+
import api from 'boost/api'
4+
import clientKey from 'boost/clientKey'
5+
const clipboard = require('electron').clipboard
6+
7+
function getDefault () {
8+
return {
9+
openDropdown: false,
10+
isSharing: false,
11+
// Fetched url
12+
url: null,
13+
// for tooltip Copy -> Copied!
14+
copied: false
15+
}
16+
}
17+
18+
export default class ShareButton extends React.Component {
19+
constructor (props) {
20+
super(props)
21+
this.state = getDefault()
22+
}
23+
24+
componentWillReceiveProps (nextProps) {
25+
this.setState(getDefault())
26+
}
27+
28+
componentDidMount () {
29+
this.dropdownInterceptor = e => {
30+
this.dropdownClicked = true
31+
}
32+
ReactDOM.findDOMNode(this.refs.dropdown).addEventListener('click', this.dropdownInterceptor)
33+
this.shareWithPublicURLHandler = e => {
34+
this.handleShareWithPublicURLClick(e)
35+
}
36+
}
37+
38+
componentWillUnmount () {
39+
document.removeEventListener('click', this.dropdownHandler)
40+
ReactDOM.findDOMNode(this.refs.dropdown).removeEventListener('click', this.dropdownInterceptor)
41+
}
42+
43+
handleOpenButtonClick (e) {
44+
this.openDropdown()
45+
if (this.dropdownHandler == null) {
46+
this.dropdownHandler = e => {
47+
if (!this.dropdownClicked) {
48+
this.closeDropdown()
49+
} else {
50+
this.dropdownClicked = false
51+
}
52+
}
53+
}
54+
document.removeEventListener('click', this.dropdownHandler)
55+
document.addEventListener('click', this.dropdownHandler)
56+
}
57+
58+
openDropdown () {
59+
this.setState({openDropdown: true})
60+
}
61+
62+
closeDropdown () {
63+
document.removeEventListener('click', this.dropdownHandler)
64+
this.setState({openDropdown: false})
65+
}
66+
67+
handleShareWithPublicURLClick (e) {
68+
let input = Object.assign({}, this.props.article, {clientKey: clientKey.get()})
69+
api.shareWithPublicURL(input)
70+
.then(res => {
71+
let url = res.body.url
72+
this.setState({url: url})
73+
})
74+
.catch(err => {
75+
console.log(err)
76+
})
77+
}
78+
79+
handleCopyURLClick () {
80+
clipboard.writeText(this.state.url)
81+
this.setState({copied: true})
82+
}
83+
84+
// Restore copy url tooltip
85+
handleCopyURLMouseLeave () {
86+
this.setState({copied: false})
87+
}
88+
89+
render () {
90+
let hasPublicURL = this.state.url != null
91+
return (
92+
<div className='ShareButton'>
93+
<button ref='openButton' onClick={e => this.handleOpenButtonClick(e)} className='ShareButton-open-button'>
94+
<i className='fa fa-fw fa-share-alt'/>
95+
{
96+
this.state.openDropdown ? null : (
97+
<span className='tooltip'>Share</span>
98+
)
99+
}
100+
</button>
101+
<div ref='dropdown' className={'share-dropdown' + (this.state.openDropdown ? '' : ' hide')}>
102+
{
103+
!hasPublicURL ? (
104+
<button
105+
onClick={e => this.shareWithPublicURLHandler(e)}
106+
ref='sharePublicURL'
107+
disabled={this.state.isSharing}>
108+
<i className='fa fa-fw fa-external-link'/> {!this.state.isSharing ? 'Share with public URL' : 'Sharing...'}
109+
</button>
110+
) : (
111+
<div className='ShareButton-url'>
112+
<input className='ShareButton-url-input' value={this.state.url} readOnly/>
113+
<button
114+
onClick={e => this.handleCopyURLClick(e)}
115+
className='ShareButton-url-button'
116+
onMouseLeave={e => this.handleCopyURLMouseLeave(e)}
117+
>
118+
<i className='fa fa-fw fa-clipboard'/>
119+
<div className='ShareButton-url-button-tooltip'>{this.state.copied ? 'Copied!' : 'Copy URL'}</div>
120+
</button>
121+
<div className='ShareButton-url-alert'>This url is valid for 7 days.</div>
122+
</div>
123+
)
124+
}
125+
</div>
126+
</div>
127+
)
128+
}
129+
}
130+
131+
ShareButton.propTypes = {
132+
article: PropTypes.shape({
133+
publicURL: PropTypes.string
134+
})
135+
}

browser/main/HomePage/ArticleDetail.js renamed to browser/main/HomePage/ArticleDetail/index.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import TagLink from 'boost/components/TagLink'
2424
import TagSelect from 'boost/components/TagSelect'
2525
import ModeSelect from 'boost/components/ModeSelect'
2626
import activityRecord from 'boost/activityRecord'
27+
import api from 'boost/api'
28+
import ShareButton from './ShareButton'
2729

2830
const electron = require('electron')
2931
const clipboard = electron.clipboard
@@ -106,12 +108,16 @@ export default class ArticleDetail extends React.Component {
106108
isTagChanged: false,
107109
isTitleChanged: false,
108110
isContentChanged: false,
109-
isModeChanged: false
111+
isModeChanged: false,
112+
openShareDropdown: false
110113
}
111114
}
112115

113116
componentDidMount () {
114117
this.refreshTimer = setInterval(() => this.forceUpdate(), 60 * 1000)
118+
this.shareDropdownInterceptor = e => {
119+
e.stopPropagation()
120+
}
115121
}
116122

117123
componentWillUnmount () {
@@ -234,9 +240,12 @@ export default class ArticleDetail extends React.Component {
234240
<div className='tags'><i className='fa fa-fw fa-tags'/>{tags}</div>
235241
</div>
236242
<div className='right'>
243+
<ShareButton article={activeArticle}/>
244+
237245
<button onClick={e => this.handleClipboardButtonClick(e)} className='editBtn'>
238246
<i className='fa fa-fw fa-clipboard'/><span className='tooltip'>Copy to clipboard</span>
239247
</button>
248+
240249
<button onClick={e => this.handleEditButtonClick(e)} className='editBtn'>
241250
<i className='fa fa-fw fa-edit'/><span className='tooltip'>Edit (e)</span>
242251
</button>
@@ -586,7 +595,8 @@ export default class ArticleDetail extends React.Component {
586595
ArticleDetail.propTypes = {
587596
status: PropTypes.shape(),
588597
activeArticle: PropTypes.shape(),
589-
activeUser: PropTypes.shape(),
598+
user: PropTypes.shape(),
599+
folders: PropTypes.array,
590600
dispatch: PropTypes.func
591601
}
592602
ArticleDetail.prototype.linkState = linkState

browser/main/MainPage.js

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ const electron = require('electron')
22
const ipc = electron.ipcRenderer
33
import React, { PropTypes } from 'react'
44

5-
var ContactModal = require('boost/components/modal/ContactModal')
6-
75
export default class MainContainer extends React.Component {
86
constructor (props) {
97
super(props)
@@ -20,20 +18,12 @@ export default class MainContainer extends React.Component {
2018
ipc.send('update-app', 'Deal with it.')
2119
}
2220

23-
openContactModal () {
24-
this.openModal(ContactModal)
25-
}
26-
2721
render () {
2822
return (
2923
<div className='Main'>
3024
{this.state.updateAvailable ? (
3125
<button onClick={this.updateApp} className='appUpdateButton'><i className='fa fa-cloud-download'/> Update available!</button>
3226
) : null}
33-
{/* <button onClick={this.openContactModal} className='contactButton'>
34-
<i className='fa fa-paper-plane-o'/>
35-
<div className='tooltip'>Contact us</div>
36-
</button> */}
3727
{this.props.children}
3828
</div>
3929
)

browser/styles/main/HomeContainer/components/ArticleDetail.styl

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,87 @@ iptFocusBorderColor = #369DCD
284284
color noTagsColor
285285
.right
286286
z-index 30
287-
button
287+
div.share-dropdown
288+
position absolute
289+
right 5px
290+
top 30px
291+
background-color transparentify(invBackgroundColor, 80%)
292+
padding 5px 0
293+
width 200px
294+
&.hide
295+
display none
296+
&>button
297+
width 200px
298+
text-align left
299+
display block
300+
height 33px
301+
background-color transparent
302+
color white
303+
font-size 14px
304+
padding 0 10px
305+
border none
306+
&:hover
307+
background-color transparentify(lighten(invBackgroundColor, 30%), 80%)
308+
&>.ShareButton-url
309+
clearfix()
310+
input.ShareButton-url-input
311+
width 155px
312+
margin 0 0 0 5px
313+
height 25px
314+
outline none
315+
border none
316+
border-top-left-radius 5px
317+
border-bottom-left-radius 5px
318+
float left
319+
padding 5px
320+
button.ShareButton-url-button
321+
width 35px
322+
height 25px
323+
border none
324+
margin 0 5px 0 0
325+
outline none
326+
border-top-right-radius 5px
327+
border-bottom-right-radius 5px
328+
background-color darken(white, 5%)
329+
color inactiveTextColor
330+
float right
331+
div.ShareButton-url-button-tooltip
332+
tooltip()
333+
right 10px
334+
&:hover
335+
color textColor
336+
div.ShareButton-url-button-tooltip
337+
opacity 1
338+
div.ShareButton-url-alert
339+
float left
340+
height 25px
341+
line-height 25px
342+
padding 0 15px
343+
color white
344+
345+
.ShareButton
346+
display inline-block
347+
button.ShareButton-open-button
348+
border-radius 16.5px
349+
cursor pointer
350+
height 33px
351+
width 33px
352+
border none
353+
margin-right 5px
354+
font-size 18px
355+
color inactiveTextColor
356+
background-color darken(white, 5%)
357+
padding 0
358+
.tooltip
359+
tooltip()
360+
margin-top 25px
361+
margin-left -40px
362+
&:hover
363+
color textColor
364+
.tooltip
365+
opacity 1
366+
367+
&>button
288368
border-radius 16.5px
289369
cursor pointer
290370
height 33px

lib/actions.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,23 @@ export function toggleTutorial () {
146146
type: TOGGLE_TUTORIAL
147147
}
148148
}
149+
150+
export default {
151+
updateUser,
152+
clearNewArticle,
153+
updateArticle,
154+
destroyArticle,
155+
createFolder,
156+
updateFolder,
157+
destroyFolder,
158+
replaceFolder,
159+
switchFolder,
160+
switchMode,
161+
switchArticle,
162+
setSearchFilter,
163+
setTagFilter,
164+
clearSearch,
165+
lockStatus,
166+
unlockStatus,
167+
toggleTutorial
168+
}

0 commit comments

Comments
 (0)