Skip to content
11 changes: 6 additions & 5 deletions browser/lib/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ import _ from 'lodash'

export default function searchFromNotes (notes, search) {
if (search.trim().length === 0) return []
let searchBlocks = search.split(' ')
const searchBlocks = search.split(' ').filter(block => { return block !== '' })

let foundNotes = findByWord(notes, searchBlocks[0])
searchBlocks.forEach((block) => {
foundNotes = findByWord(foundNotes, block)
if (block.match(/^#.+/)) {
notes = findByTag(notes, block)
} else {
notes = findByWord(notes, block)
foundNotes = foundNotes.concat(findByTag(notes, block))
}
})
return notes
return foundNotes
}

function findByTag (notes, block) {
Expand Down
57 changes: 31 additions & 26 deletions browser/main/NoteList/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class NoteList extends React.Component {

this.state = {
}

this.contextNotes = []
}

componentDidMount () {
Expand Down Expand Up @@ -90,6 +92,7 @@ class NoteList extends React.Component {

if (this.notes.length > 0 && location.query.key == null) {
let { router } = this.context
if (!location.pathname.match(/\/searched/)) this.contextNotes = this.getContextNotes()
router.replace({
pathname: location.pathname,
query: {
Expand Down Expand Up @@ -234,48 +237,50 @@ class NoteList extends React.Component {
let { router } = this.context

if (location.pathname.match(/\/home/)) {
return data.noteMap.map((note) => note)
const allNotes = data.noteMap.map((note) => note)
this.contextNotes = allNotes
return allNotes
}

if (location.pathname.match(/\/starred/)) {
return data.starredSet.toJS()
.map((uniqueKey) => data.noteMap.get(uniqueKey))
const starredNotes = data.starredSet.toJS().map((uniqueKey) => data.noteMap.get(uniqueKey))
this.contextNotes = starredNotes
return starredNotes
}

if (location.pathname.match(/\/searched/)) {
const searchInputText = document.getElementsByClassName('searchInput')[0].value
if (searchInputText === '') {
router.push('/home')
return this.contextNotes
}
return searchFromNotes(this.notes, searchInputText)
return searchFromNotes(this.contextNotes, searchInputText)
}

if (location.pathname.match(/\/trashed/)) {
return data.trashedSet.toJS()
.map((uniqueKey) => data.noteMap.get(uniqueKey))
const trashedNotes = data.trashedSet.toJS().map((uniqueKey) => data.noteMap.get(uniqueKey))
this.contextNotes = trashedNotes
return trashedNotes
}

let storageKey = params.storageKey
let folderKey = params.folderKey
let storage = data.storageMap.get(storageKey)
if (storage == null) return []

let folder = _.find(storage.folders, {key: folderKey})
if (folder == null) {
let storageNoteSet = data.storageNoteMap
.get(storage.key)
if (storageNoteSet == null) storageNoteSet = []
return storageNoteSet
.map((uniqueKey) => data.noteMap.get(uniqueKey))
}
return this.getContextNotes()
}

let folderNoteKeyList = data.folderNoteMap
.get(storage.key + '-' + folder.key)
// get notes in the current folder
getContextNotes () {
const { data, params } = this.props
const storageKey = params.storageKey
const folderKey = params.folderKey
const storage = data.storageMap.get(storageKey)
if (storage === undefined) return []

const folder = _.find(storage.folders, {key: folderKey})
if (folder === undefined) {
const storageNoteSet = data.storageNoteMap.get(storage.key) || []
return storageNoteSet.map((uniqueKey) => data.noteMap.get(uniqueKey))
}

return folderNoteKeyList != null
? folderNoteKeyList
.map((uniqueKey) => data.noteMap.get(uniqueKey))
: []
const folderNoteKeyList = data.folderNoteMap.get(`${storage.key}-${folder.key}`) || []
return folderNoteKeyList.map((uniqueKey) => data.noteMap.get(uniqueKey))
}

handleNoteClick (e, uniqueKey) {
Expand Down
54 changes: 51 additions & 3 deletions browser/main/TopBar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ class TopBar extends React.Component {
this.state = {
search: '',
searchOptions: [],
isSearching: false
isSearching: false,
isAlphabet: false,
isIME: false,
isConfirmTranslation: false
}

this.focusSearchHandler = () => {
Expand All @@ -34,9 +37,52 @@ class TopBar extends React.Component {
ee.off('top:focus-search', this.focusSearchHandler)
}

handleKeyDown (e) {
// reset states
this.setState({
isAlphabet: false,
isIME: false
})

// When the key is an alphabet, del, enter or ctr
if (e.keyCode <= 90 || e.keyCode >= 186 && e.keyCode <= 222) {
this.setState({
isAlphabet: true
})
// When the key is an IME input (Japanese, Chinese)
} else if (e.keyCode === 229) {
this.setState({
isIME: true
})
}
}

handleKeyUp (e) {
const { router } = this.context
// reset states
this.setState({
isConfirmTranslation: false
})

// When the key is translation confirmation (Enter, Space)
if (this.state.isIME && (e.keyCode === 32 || e.keyCode === 13)) {
this.setState({
isConfirmTranslation: true
})
router.push('/searched')
this.setState({
search: this.refs.searchInput.value
})
}
}

handleSearchChange (e) {
let { router } = this.context
router.push('/searched')
const { router } = this.context
if (this.state.isAlphabet || this.state.isConfirmTranslation) {
router.push('/searched')
} else {
e.preventDefault()
}
this.setState({
search: this.refs.searchInput.value
})
Expand Down Expand Up @@ -93,6 +139,8 @@ class TopBar extends React.Component {
ref='searchInput'
value={this.state.search}
onChange={(e) => this.handleSearchChange(e)}
onKeyDown={(e) => this.handleKeyDown(e)}
onKeyUp={(e) => this.handleKeyUp(e)}
placeholder='Search'
type='text'
className='searchInput'
Expand Down
12 changes: 8 additions & 4 deletions tests/lib/search-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,30 @@ import _ from 'lodash'
const pickContents = (notes) => notes.map((note) => { return note.content })

let notes = []
let note1, note2
let note1, note2, note3

test.before(t => {
const data1 = { type: 'MARKDOWN_NOTE', content: 'content1', tags: ['tag1'] }
const data2 = { type: 'MARKDOWN_NOTE', content: 'content1\ncontent2', tags: ['tag1', 'tag2'] }
const data3 = { type: 'MARKDOWN_NOTE', content: '#content4', tags: ['tag1'] }

note1 = dummyNote(data1)
note2 = dummyNote(data2)
note3 = dummyNote(data3)

notes = [note1, note2]
notes = [note1, note2, note3]
})

test('it can find notes by tags or words', t => {
// [input, expected content (Array)]
const testCases = [
['#tag1', [note1.content, note2.content]],
['#tag1', [note1.content, note2.content, note3.content]],
['#tag1 #tag2', [note2.content]],
['#tag1 #tag2 #tag3', []],
['content1', [note1.content, note2.content]],
['content1 content2', [note2.content]],
['content1 content2 content3', []]
['content1 content2 content3', []],
['#content4', [note3.content]]
]

testCases.forEach((testCase) => {
Expand Down