mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-25 23:51:51 +00:00
add Finder & update main.js & cleanup some old files
This commit is contained in:
43
browser/finder/Components/FinderDetail.jsx
Normal file
43
browser/finder/Components/FinderDetail.jsx
Normal file
@@ -0,0 +1,43 @@
|
||||
var React = require('react/addons')
|
||||
|
||||
var CodeViewer = require('../../main/Components/CodeViewer')
|
||||
|
||||
var Markdown = require('../../main/Mixins/Markdown')
|
||||
|
||||
module.exports = React.createClass({
|
||||
mixins: [Markdown],
|
||||
propTypes: {
|
||||
currentArticle: React.PropTypes.object
|
||||
},
|
||||
render: function () {
|
||||
var article = this.props.currentArticle
|
||||
|
||||
if (article != null) {
|
||||
if (article.type === 'snippet') {
|
||||
return (
|
||||
<div className='FinderDetail'>
|
||||
<div className='header'>{article.callSign}</div>
|
||||
<div className='content'>
|
||||
<CodeViewer code={article.content} mode={article.mode}/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
} else if (article.type === 'blueprint') {
|
||||
|
||||
return (
|
||||
<div className='FinderDetail'>
|
||||
<div className='header'>{article.title}</div>
|
||||
<div className='content'>
|
||||
<div className='marked' dangerouslySetInnerHTML={{__html: ' ' + this.markdown(article.content)}}></div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div className='FinderDetail'>
|
||||
<div className='nothing'>Nothing selected</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
15
browser/finder/Components/FinderInput.jsx
Normal file
15
browser/finder/Components/FinderInput.jsx
Normal file
@@ -0,0 +1,15 @@
|
||||
var React = require('react/addons')
|
||||
|
||||
module.exports = React.createClass({
|
||||
propTypes: {
|
||||
onChange: React.PropTypes.func,
|
||||
search: React.PropTypes.string
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<div className='FinderInput'>
|
||||
<input value={this.props.search} onChange={this.props.onChange} type='text'/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
69
browser/finder/Components/FinderList.jsx
Normal file
69
browser/finder/Components/FinderList.jsx
Normal file
@@ -0,0 +1,69 @@
|
||||
var React = require('react/addons')
|
||||
|
||||
module.exports = React.createClass({
|
||||
propTypes: {
|
||||
articles: React.PropTypes.arrayOf,
|
||||
currentArticle: React.PropTypes.shape({
|
||||
id: React.PropTypes.number,
|
||||
type: React.PropTypes.string
|
||||
})
|
||||
},
|
||||
componentDidUpdate: function () {
|
||||
var index = this.props.articles.indexOf(this.props.currentArticle)
|
||||
var el = React.findDOMNode(this)
|
||||
var li = el.querySelectorAll('li')[index]
|
||||
|
||||
var overflowBelow = el.clientHeight + el.scrollTop < li.offsetTop + li.clientHeight
|
||||
if (overflowBelow) {
|
||||
el.scrollTop = li.offsetTop + li.clientHeight - el.clientHeight
|
||||
}
|
||||
var overflowAbove = el.scrollTop > li.offsetTop
|
||||
if (overflowAbove) {
|
||||
el.scrollTop = li.offsetTop
|
||||
}
|
||||
},
|
||||
render: function () {
|
||||
var list = this.props.articles.map(function (article) {
|
||||
if (article == null) {
|
||||
return (
|
||||
<li className={isActive ? 'active' : ''}>
|
||||
<div className='articleItem'>Undefined</div>
|
||||
<div className='divider'/>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
var isActive = this.props.currentArticle != null && (article.type === this.props.currentArticle.type && article.id === this.props.currentArticle.id)
|
||||
if (article.type === 'snippet') {
|
||||
return (
|
||||
<li className={isActive ? 'active' : ''}>
|
||||
<div className='articleItem'><i className='fa fa-code fa-fw'/> {article.callSign} / {article.description.substring(0, 10)}</div>
|
||||
<div className='divider'/>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
if (article.type === 'blueprint') {
|
||||
return (
|
||||
<li className={isActive ? 'active' : ''}>
|
||||
<div className='articleItem'><i className='fa fa-file-text-o fa-fw'/> {article.title}</div>
|
||||
<div className='divider'/>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<li className={isActive ? 'active' : ''}>
|
||||
<div className='articleItem'>Undefined</div>
|
||||
<div className='divider'/>
|
||||
</li>
|
||||
)
|
||||
}.bind(this))
|
||||
|
||||
return (
|
||||
<div className='FinderList'>
|
||||
<ul>
|
||||
{list}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
53
browser/finder/index.electron.html
Normal file
53
browser/finder/index.electron.html
Normal file
@@ -0,0 +1,53 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CodeXen Popup</title>
|
||||
|
||||
<link rel="stylesheet" href="../vendor/fontawesome/css/font-awesome.min.css" media="screen" title="no title" charset="utf-8">
|
||||
<link rel="shortcut icon" href="favicon.ico">
|
||||
<script>
|
||||
if (!Object.assign) {
|
||||
Object.defineProperty(Object, 'assign', {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: function(target) {
|
||||
'use strict';
|
||||
if (target === undefined || target === null) {
|
||||
throw new TypeError('Cannot convert first argument to object');
|
||||
}
|
||||
|
||||
var to = Object(target);
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
var nextSource = arguments[i];
|
||||
if (nextSource === undefined || nextSource === null) {
|
||||
continue;
|
||||
}
|
||||
nextSource = Object(nextSource);
|
||||
|
||||
var keysArray = Object.keys(Object(nextSource));
|
||||
for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
|
||||
var nextKey = keysArray[nextIndex];
|
||||
var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
|
||||
if (desc !== undefined && desc.enumerable) {
|
||||
to[nextKey] = nextSource[nextKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
return to;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
require('electron-stylus')(__dirname + '/../styles/finder/index.styl')
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content"></div>
|
||||
<script src="../ace/src-min/ace.js"></script>
|
||||
<script>
|
||||
require('node-jsx').install({ harmony: true, extension: '.jsx' })
|
||||
require('./index.jsx')
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
0
browser/finder/index.html
Normal file
0
browser/finder/index.html
Normal file
188
browser/finder/index.jsx
Normal file
188
browser/finder/index.jsx
Normal file
@@ -0,0 +1,188 @@
|
||||
/* global localStorage */
|
||||
var remote = require('remote')
|
||||
var hideFinder = remote.getGlobal('hideFinder')
|
||||
var clipboard = require('clipboard')
|
||||
|
||||
var React = require('react/addons')
|
||||
|
||||
var FinderInput = require('./Components/FinderInput')
|
||||
var FinderList = require('./Components/FinderList')
|
||||
var FinderDetail = require('./Components/FinderDetail')
|
||||
|
||||
// filter start
|
||||
function basicFilter (keyword, articles) {
|
||||
if (keyword === '' || keyword == null) return articles
|
||||
var firstFiltered = articles.filter(function (article) {
|
||||
|
||||
var first = article.type === 'snippet' ? article.callSign : article.title
|
||||
if (first.match(new RegExp(keyword, 'i'))) return true
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
var secondFiltered = articles.filter(function (article) {
|
||||
var second = article.type === 'snippet' ? article.description : article.content
|
||||
if (second.match(new RegExp(keyword, 'i'))) return true
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
var thirdFiltered = articles.filter(function (article) {
|
||||
if (article.type === 'snippet') {
|
||||
if (article.content.match(new RegExp(keyword, 'i'))) return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
return firstFiltered.concat(secondFiltered, thirdFiltered).filter(function (value, index, self) {
|
||||
return self.indexOf(value) === index
|
||||
})
|
||||
}
|
||||
|
||||
function snippetFilter (articles) {
|
||||
return articles.filter(function (article) {
|
||||
return article.type === 'snippet'
|
||||
})
|
||||
}
|
||||
|
||||
function blueprintFilter (articles) {
|
||||
return articles.filter(function (article) {
|
||||
return article.type === 'blueprint'
|
||||
})
|
||||
}
|
||||
|
||||
function tagFilter (keyword, articles) {
|
||||
return articles.filter(function (article) {
|
||||
return article.Tags.some(function (tag) {
|
||||
return tag.name.match(new RegExp('^' + keyword, 'i'))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function searchArticle (search, articles) {
|
||||
var keywords = search.split(' ')
|
||||
|
||||
for (var keyword of keywords) {
|
||||
if (keyword.match(/^\$s/, 'i')) {
|
||||
articles = snippetFilter(articles)
|
||||
continue
|
||||
} else if (keyword.match(/^\$b/, 'i')) {
|
||||
articles = blueprintFilter(articles)
|
||||
continue
|
||||
} else if (keyword.match(/^#[A-Za-z0-9]+/)) {
|
||||
articles = tagFilter(keyword.substring(1, keyword.length), articles)
|
||||
continue
|
||||
}
|
||||
articles = basicFilter(keyword, articles)
|
||||
}
|
||||
|
||||
return articles
|
||||
}
|
||||
// Filter end
|
||||
|
||||
function fetchArticles () {
|
||||
var user = JSON.parse(localStorage.getItem('user'))
|
||||
if (user == null) {
|
||||
console.log('need to login')
|
||||
return []
|
||||
}
|
||||
|
||||
var articles = []
|
||||
user.Planets.forEach(function (planet) {
|
||||
var _planet = JSON.parse(localStorage.getItem('planet-' + planet.id))
|
||||
articles = articles.concat(_planet.Snippets, _planet.Blueprints)
|
||||
})
|
||||
console.log(articles.length + ' articles')
|
||||
|
||||
return articles
|
||||
}
|
||||
|
||||
var Finder = React.createClass({
|
||||
getInitialState: function () {
|
||||
var articles = fetchArticles()
|
||||
return {
|
||||
articles: articles,
|
||||
currentArticle: articles[0],
|
||||
search: ''
|
||||
}
|
||||
},
|
||||
componentDidMount: function () {
|
||||
document.addEventListener('keydown', this.handleKeyDown)
|
||||
document.addEventListener('click', this.handleClick)
|
||||
window.addEventListener('focus', this.handleFinderFocus)
|
||||
},
|
||||
componentWillUnmount: function () {
|
||||
document.removeEventListener('keydown', this.handleKeyDown)
|
||||
document.removeEventListener('click', this.handleClick)
|
||||
window.removeEventListener('focus', this.handleFinderFocus)
|
||||
},
|
||||
handleFinderFocus: function () {
|
||||
console.log('focusseeddddd')
|
||||
this.focusInput()
|
||||
var articles = fetchArticles()
|
||||
this.setState({
|
||||
articles: articles,
|
||||
currentArticle: articles[0],
|
||||
search: ''
|
||||
})
|
||||
},
|
||||
handleKeyDown: function (e) {
|
||||
if (e.keyCode === 38) {
|
||||
this.selectPrevious()
|
||||
e.preventDefault()
|
||||
}
|
||||
|
||||
if (e.keyCode === 40) {
|
||||
this.selectNext()
|
||||
e.preventDefault()
|
||||
}
|
||||
|
||||
if (e.keyCode === 13) {
|
||||
var article = this.state.currentArticle
|
||||
if (article.type === 'snippet') {
|
||||
clipboard.writeText(article.content)
|
||||
hideFinder()
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
if (e.keyCode === 27) {
|
||||
hideFinder()
|
||||
e.preventDefault()
|
||||
}
|
||||
},
|
||||
focusInput: function () {
|
||||
React.findDOMNode(this.refs.finderInput).querySelector('input').focus()
|
||||
},
|
||||
handleClick: function () {
|
||||
this.focusInput()
|
||||
},
|
||||
selectPrevious: function () {
|
||||
var index = this.refs.finderList.props.articles.indexOf(this.state.currentArticle)
|
||||
if (index > 0) {
|
||||
this.setState({currentArticle: this.refs.finderList.props.articles[index - 1]})
|
||||
}
|
||||
},
|
||||
selectNext: function () {
|
||||
var index = this.refs.finderList.props.articles.indexOf(this.state.currentArticle)
|
||||
if (index > -1 && index < this.refs.finderList.props.articles.length - 1) {
|
||||
this.setState({currentArticle: this.refs.finderList.props.articles[index + 1]})
|
||||
}
|
||||
},
|
||||
handleChange: function (e) {
|
||||
this.setState({search: e.target.value}, function () {
|
||||
this.setState({currentArticle: this.refs.finderList.props.articles[0]})
|
||||
})
|
||||
},
|
||||
render: function () {
|
||||
var articles = searchArticle(this.state.search, this.state.articles)
|
||||
return (
|
||||
<div className='Finder'>
|
||||
<FinderInput ref='finderInput' onChange={this.handleChange} search={this.state.search}/>
|
||||
<FinderList ref='finderList' currentArticle={this.state.currentArticle} articles={articles}/>
|
||||
<FinderDetail currentArticle={this.state.currentArticle}/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
React.render(<Finder/>, document.getElementById('content'))
|
||||
Reference in New Issue
Block a user