Skip to content

Commit f11e7ee

Browse files
committed
gists #571
Lets you pull gist snippets into all notes tab from gists tab, and push snippets to github.
1 parent 78c00b1 commit f11e7ee

28 files changed

+2551
-39
lines changed

browser/components/CodeEditor.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ function translateHotkey (hotkey) {
3838
return hotkey.replace(/\s*\+\s*/g, '-').replace(/Command/g, 'Cmd').replace(/Control/g, 'Ctrl')
3939
}
4040

41-
const languageMaps = {
41+
export const languageMaps = {
4242
brainfuck: 'Brainfuck',
4343
cpp: 'C++',
4444
cs: 'C#',
@@ -747,14 +747,14 @@ export default class CodeEditor extends React.Component {
747747
}
748748

749749
incrementLines (start, linesAdded, linesRemoved, editor) {
750-
let highlightedLines = editor.options.linesHighlighted
750+
const highlightedLines = editor.options.linesHighlighted
751751

752752
const totalHighlightedLines = highlightedLines.length
753753

754-
let offset = linesAdded - linesRemoved
754+
const offset = linesAdded - linesRemoved
755755

756756
// Store new items to be added as we're changing the lines
757-
let newLines = []
757+
const newLines = []
758758

759759
let i = totalHighlightedLines
760760

browser/components/MarkdownPreview.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ export default class MarkdownPreview extends React.Component {
321321
allowCustomCSS,
322322
customCSS
323323
)
324-
let body = this.markdown.render(noteContent)
324+
const body = this.markdown.render(noteContent)
325325
const files = [this.GetCodeThemeLink(codeBlockTheme), ...CSS_FILES]
326326
files.forEach(file => {
327327
if (global.process.platform === 'win32') {

browser/components/SideNavFilter.js

+20-4
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ import i18n from 'browser/lib/i18n'
1717
*/
1818
const SideNavFilter = ({
1919
isFolded, isHomeActive, handleAllNotesButtonClick,
20-
isStarredActive, handleStarredButtonClick, isTrashedActive, handleTrashedButtonClick, counterDelNote,
21-
counterTotalNote, counterStarredNote, handleFilterButtonContextMenu
20+
isStarredActive, handleStarredButtonClick, isTrashedActive, isGistedActive, handleTrashedButtonClick, counterDelNote,
21+
counterTotalNote, counterStarredNote, counterGistsNote, handleFilterButtonContextMenu,
22+
handleGistedButtonClick
2223
}) => (
2324
<div styleName={isFolded ? 'menu--folded' : 'menu'}>
2425

@@ -50,7 +51,8 @@ const SideNavFilter = ({
5051
<span styleName='counters'>{counterStarredNote}</span>
5152
</button>
5253

53-
<button styleName={isTrashedActive ? 'menu-button-trash--active' : 'menu-button'}
54+
<button
55+
styleName={isTrashedActive ? 'menu-button-trash--active' : 'menu-button'}
5456
onClick={handleTrashedButtonClick} onContextMenu={handleFilterButtonContextMenu}
5557
>
5658
<div styleName='iconWrap'>
@@ -64,17 +66,31 @@ const SideNavFilter = ({
6466
<span styleName='counters'>{counterDelNote}</span>
6567
</button>
6668

69+
<button
70+
onClick={handleGistedButtonClick}
71+
styleName={isGistedActive ? 'menu-button-trash--active' : 'menu-button'}
72+
>
73+
<div styleName='iconWrap'>
74+
<img src='../resources/icon/icon-gist.svg' />
75+
</div>
76+
<span styleName='menu-button-label'>{i18n.__('Gists')}</span>
77+
<span styleName='counters'>{counterGistsNote}</span>
78+
</button>
79+
6780
</div>
6881
)
6982

7083
SideNavFilter.propTypes = {
7184
isFolded: PropTypes.bool,
7285
isHomeActive: PropTypes.bool.isRequired,
7386
handleAllNotesButtonClick: PropTypes.func.isRequired,
87+
counterGistsNote: PropTypes.bool.isRequired,
7488
isStarredActive: PropTypes.bool.isRequired,
7589
isTrashedActive: PropTypes.bool.isRequired,
90+
isGistedActive: PropTypes.bool.isRequired,
7691
handleStarredButtonClick: PropTypes.func.isRequired,
77-
handleTrashdButtonClick: PropTypes.func.isRequired
92+
handleTrashdButtonClick: PropTypes.func.isRequired,
93+
handleGistedButtonClick: PropTypes.func.isRequired
7894
}
7995

8096
export default CSSModules(SideNavFilter, styles)

browser/components/StorageList.styl

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
.storageList
22
absolute left right
33
bottom 37px
4-
top 180px
4+
top 200px
55
overflow-y auto
66

77
.storageList-folded

browser/lib/confirmDeleteNote.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ import i18n from 'browser/lib/i18n'
33
const { remote } = electron
44
const { dialog } = remote
55

6-
export function confirmDeleteNote (confirmDeletion, permanent) {
6+
export function confirmDeleteNote (confirmDeletion, permanent, gist = false) {
77
if (confirmDeletion || permanent) {
88
const alertConfig = {
99
ype: 'warning',
1010
message: i18n.__('Confirm note deletion'),
11-
detail: i18n.__('This will permanently remove this note.'),
11+
detail: gist ? i18n.__('This will permanently remove this gist on github.') : i18n.__('This will permanently remove this note.'),
1212
buttons: [i18n.__('Confirm'), i18n.__('Cancel')]
1313
}
1414

browser/lib/newNote.js

-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ export function createMarkdownNote (storage, folder, dispatch, location, params,
4040
export function createSnippetNote (storage, folder, dispatch, location, params, config) {
4141
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_SNIPPET')
4242
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_ALLNOTE')
43-
4443
let tags = []
4544
if (config.ui.tagNewNoteWithFilteringTags && location.pathname.match(/\/tags/)) {
4645
tags = params.tagname.split(' ')

browser/main/Detail/GistButton.js

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import PropTypes from 'prop-types'
2+
import React from 'react'
3+
import CSSModules from 'browser/lib/CSSModules'
4+
import styles from './InfoButton.styl'
5+
import i18n from 'browser/lib/i18n'
6+
// import { Icon, InlineIcon } from '@iconify/react';
7+
// import eyeIcon from '@iconify/react/octicon/eye';
8+
9+
const GistButton = ({
10+
onClick,
11+
isGisted,
12+
gistId
13+
}) => {
14+
return (
15+
<button styleName='control-infoButton'
16+
onClick={(e) => onClick(e)}
17+
>
18+
<img className='infoButton' src='../resources/icon/icon-gist.svg' />
19+
{isGisted ? 1 : 0}
20+
<span styleName='tooltip'>{isGisted ? i18n.__('Hide in All Notes') : gistId ? i18n.__('Show in All Notes') : i18n.__('Upload Gist and Show in All Notes')}</span>
21+
</button>
22+
)
23+
}
24+
25+
GistButton.propTypes = {
26+
onClick: PropTypes.func.isRequired,
27+
isGisted: PropTypes.bool,
28+
gistId: PropTypes.bool
29+
}
30+
31+
export default CSSModules(GistButton, styles)

browser/main/Detail/SnippetNoteDetail.js

+46-5
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ import context from 'browser/lib/context'
1818
import ConfigManager from 'browser/main/lib/ConfigManager'
1919
import _ from 'lodash'
2020
import {findNoteTitle} from 'browser/lib/findNoteTitle'
21-
import convertModeName from 'browser/lib/convertModeName'
2221
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
2322
import FullscreenButton from './FullscreenButton'
2423
import TrashButton from './TrashButton'
2524
import RestoreButton from './RestoreButton'
25+
import GistButton from './GistButton'
2626
import PermanentDeleteButton from './PermanentDeleteButton'
2727
import InfoButton from './InfoButton'
2828
import InfoPanel from './InfoPanel'
@@ -31,6 +31,7 @@ import { formatDate } from 'browser/lib/date-formatter'
3131
import i18n from 'browser/lib/i18n'
3232
import { confirmDeleteNote } from 'browser/lib/confirmDeleteNote'
3333
import markdownToc from 'browser/lib/markdown-toc-generator'
34+
import { getGithubApi, CREATE_SINGLE_GIST, EDIT_SINGLE_GIST, mapToGist } from 'browser/main/lib/dataApi/github-api.js'
3435

3536
const electron = require('electron')
3637
const { remote } = electron
@@ -74,6 +75,7 @@ class SnippetNoteDetail extends React.Component {
7475
componentWillReceiveProps (nextProps) {
7576
if (nextProps.note.key !== this.props.note.key && !this.state.isMovingNote) {
7677
if (this.saveQueue != null) this.saveNow()
78+
if (this.saveGithubQueue != null) this.saveGithub()
7779
const nextNote = Object.assign({
7880
description: ''
7981
}, nextProps.note, {
@@ -96,6 +98,7 @@ class SnippetNoteDetail extends React.Component {
9698

9799
componentWillUnmount () {
98100
if (this.saveQueue != null) this.saveNow()
101+
if (this.saveGithubQueue != null) this.saveGithub()
99102
ee.off('code:generate-toc', this.generateToc)
100103
}
101104

@@ -128,6 +131,11 @@ class SnippetNoteDetail extends React.Component {
128131
this.saveQueue = setTimeout(() => {
129132
this.saveNow()
130133
}, 1000)
134+
clearTimeout(this.saveGithubQueue)
135+
this.saveGithubQueue = setTimeout(() => {
136+
this.saveGithub()
137+
}, 5 * 60 * 1000
138+
)
131139
}
132140

133141
saveNow () {
@@ -146,6 +154,15 @@ class SnippetNoteDetail extends React.Component {
146154
})
147155
}
148156

157+
saveGithub () {
158+
console.log('now')
159+
160+
const { note } = this.props
161+
clearTimeout(this.saveGithubQueue)
162+
this.saveGithubQueue = null
163+
getGithubApi(EDIT_SINGLE_GIST)(mapToGist(note))
164+
}
165+
149166
handleFolderChange (e) {
150167
const { note } = this.state
151168
const value = this.refs.folder.value
@@ -198,11 +215,10 @@ class SnippetNoteDetail extends React.Component {
198215

199216
handleTrashButtonClick (e) {
200217
const { note } = this.state
201-
const { isTrashed } = note
218+
const { isTrashed, gistId } = note
202219
const { confirmDeletion } = this.props.config.ui
203-
204-
if (isTrashed) {
205-
if (confirmDeleteNote(confirmDeletion, true)) {
220+
if (isTrashed || gistId) {
221+
if (confirmDeleteNote(confirmDeletion, true, gistId)) {
206222
const {note, dispatch} = this.props
207223
dataApi
208224
.deleteNote(note.storage, note.key)
@@ -233,6 +249,26 @@ class SnippetNoteDetail extends React.Component {
233249
}
234250
}
235251

252+
handleGistedClick (e) {
253+
const { note } = this.state
254+
note.isGisted = !note.isGisted
255+
this.setState({
256+
note
257+
}, () => {
258+
this.save()
259+
})
260+
!note.gistId ? getGithubApi(CREATE_SINGLE_GIST)(mapToGist(note)).then(x => {
261+
note.gistId = x.id
262+
this.setState({
263+
note
264+
}, () => {
265+
this.save()
266+
})
267+
}).catch(x => {
268+
throw Error(x)
269+
}) : null
270+
}
271+
236272
handleUndoButtonClick (e) {
237273
const { note } = this.state
238274

@@ -759,9 +795,12 @@ class SnippetNoteDetail extends React.Component {
759795
</div>
760796
<div styleName='info-right'>
761797
<PermanentDeleteButton onClick={(e) => this.handleTrashButtonClick(e)} />
798+
799+
<GistButton onClick={(e) => this.handleGistedClick(e)} gistId={note.gistId} isGisted={note.isGisted} />
762800
<InfoButton
763801
onClick={(e) => this.handleInfoButtonClick(e)}
764802
/>
803+
765804
<InfoPanelTrashed
766805
storageName={currentOption.storage.name}
767806
folderName={currentOption.folder.name}
@@ -805,6 +844,8 @@ class SnippetNoteDetail extends React.Component {
805844

806845
<TrashButton onClick={(e) => this.handleTrashButtonClick(e)} />
807846

847+
<GistButton onClick={(e) => this.handleGistedClick(e)} gistId={note.gistId} isGisted={note.isGisted} />
848+
808849
<InfoButton
809850
onClick={(e) => this.handleInfoButtonClick(e)}
810851
/>

browser/main/Main.js

+37-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ import store from 'browser/main/store'
1717
import i18n from 'browser/lib/i18n'
1818
import { getLocales } from 'browser/lib/Languages'
1919
import applyShortcuts from 'browser/main/lib/shortcutManager'
20+
import {
21+
getGithubApi,
22+
GET_ALL_GISTS,
23+
mapToNote
24+
} from 'browser/main/lib/dataApi/github-api'
2025
const path = require('path')
2126
const electron = require('electron')
2227
const { remote } = electron
@@ -141,7 +146,7 @@ class Main extends React.Component {
141146

142147
componentDidMount () {
143148
const { dispatch, config } = this.props
144-
149+
console.log(1)
145150
const supportedThemes = ['dark', 'white', 'solarized-dark', 'monokai', 'dracula']
146151

147152
if (supportedThemes.indexOf(config.ui.theme) !== -1) {
@@ -156,6 +161,7 @@ class Main extends React.Component {
156161
i18n.setLocale('en')
157162
}
158163
applyShortcuts()
164+
159165
// Reload all data
160166
dataApi.init().then(data => {
161167
dispatch({
@@ -167,6 +173,36 @@ class Main extends React.Component {
167173
if (data.storages.length < 1) {
168174
this.init()
169175
}
176+
return data
177+
}).then(data => {
178+
function makeUpdate (note) {
179+
store.dispatch({
180+
type: 'UPDATE_NOTE',
181+
note: note
182+
})
183+
}
184+
function add (note, older) {
185+
if (older) {
186+
dataApi.updateNote(note.storage, note.key, note)
187+
.then(makeUpdate)
188+
} else {
189+
dataApi
190+
.createNote(data.storages[0].key, note)
191+
.then(makeUpdate)
192+
}
193+
}
194+
getGithubApi(GET_ALL_GISTS)().then((items) => {
195+
var loadedGists = new Map(data.notes.filter(x => x.gistId).map(x => [x.gistId, x]))
196+
items.forEach(x => {
197+
const gistId = x.id
198+
const older = loadedGists.get(gistId)
199+
const note = Object.assign({ }, mapToNote(x), older, { gistId }, { folder: data.storages[0].folders[0].key })
200+
add(note, older)
201+
})
202+
}).catch(x => {
203+
throw Error(x)
204+
})
205+
return data
170206
})
171207

172208
delete CodeMirror.keyMap.emacs['Ctrl-V']

0 commit comments

Comments
 (0)