308 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			308 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* eslint-env browser, jquery */
 | 
						|
/* eslint no-console: ["error", { allow: ["warn", "error", "debug"] }] */
 | 
						|
/* global serverurl, moment */
 | 
						|
 | 
						|
import store from 'store'
 | 
						|
import S from 'string'
 | 
						|
import LZString from 'lz-string'
 | 
						|
import url from 'wurl'
 | 
						|
 | 
						|
import {
 | 
						|
  checkNoteIdValid,
 | 
						|
  encodeNoteId
 | 
						|
} from './utils'
 | 
						|
 | 
						|
import {
 | 
						|
  checkIfAuth
 | 
						|
} from './lib/common/login'
 | 
						|
 | 
						|
import {
 | 
						|
  urlpath
 | 
						|
} from './lib/config'
 | 
						|
 | 
						|
window.migrateHistoryFromTempCallback = null
 | 
						|
 | 
						|
migrateHistoryFromTemp()
 | 
						|
 | 
						|
function migrateHistoryFromTemp () {
 | 
						|
  if (url('#tempid')) {
 | 
						|
    $.get(`${serverurl}/temp`, {
 | 
						|
      tempid: url('#tempid')
 | 
						|
    })
 | 
						|
      .done(data => {
 | 
						|
        if (data && data.temp) {
 | 
						|
          getStorageHistory(olddata => {
 | 
						|
            if (!olddata || olddata.length === 0) {
 | 
						|
              saveHistoryToStorage(JSON.parse(data.temp))
 | 
						|
            }
 | 
						|
          })
 | 
						|
        }
 | 
						|
      })
 | 
						|
      .always(() => {
 | 
						|
        let hash = location.hash.split('#')[1]
 | 
						|
        hash = hash.split('&')
 | 
						|
        for (let i = 0; i < hash.length; i++) {
 | 
						|
          if (hash[i].indexOf('tempid') === 0) {
 | 
						|
            hash.splice(i, 1)
 | 
						|
            i--
 | 
						|
          }
 | 
						|
        }
 | 
						|
        hash = hash.join('&')
 | 
						|
        location.hash = hash
 | 
						|
        if (window.migrateHistoryFromTempCallback) { window.migrateHistoryFromTempCallback() }
 | 
						|
      })
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
export function saveHistory (notehistory) {
 | 
						|
  checkIfAuth(
 | 
						|
    () => {
 | 
						|
      saveHistoryToServer(notehistory)
 | 
						|
    },
 | 
						|
    () => {
 | 
						|
      saveHistoryToStorage(notehistory)
 | 
						|
    }
 | 
						|
  )
 | 
						|
}
 | 
						|
 | 
						|
function saveHistoryToStorage (notehistory) {
 | 
						|
  store.set('notehistory', JSON.stringify(notehistory))
 | 
						|
}
 | 
						|
 | 
						|
function saveHistoryToServer (notehistory) {
 | 
						|
  $.post(`${serverurl}/history`, {
 | 
						|
    history: JSON.stringify(notehistory)
 | 
						|
  })
 | 
						|
}
 | 
						|
 | 
						|
export function saveStorageHistoryToServer (callback) {
 | 
						|
  const data = store.get('notehistory')
 | 
						|
  if (data) {
 | 
						|
    $.post(`${serverurl}/history`, {
 | 
						|
      history: data
 | 
						|
    })
 | 
						|
      .done(data => {
 | 
						|
        callback(data)
 | 
						|
      })
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
export function clearDuplicatedHistory (notehistory) {
 | 
						|
  const newnotehistory = []
 | 
						|
  for (let i = 0; i < notehistory.length; i++) {
 | 
						|
    let found = false
 | 
						|
    for (let j = 0; j < newnotehistory.length; j++) {
 | 
						|
      const id = notehistory[i].id.replace(/=+$/, '')
 | 
						|
      const newId = newnotehistory[j].id.replace(/=+$/, '')
 | 
						|
      if (id === newId || notehistory[i].id === newnotehistory[j].id || !notehistory[i].id || !newnotehistory[j].id) {
 | 
						|
        const time = (typeof notehistory[i].time === 'number' ? moment(notehistory[i].time) : moment(notehistory[i].time, 'MMMM Do YYYY, h:mm:ss a'))
 | 
						|
        const newTime = (typeof newnotehistory[i].time === 'number' ? moment(newnotehistory[i].time) : moment(newnotehistory[i].time, 'MMMM Do YYYY, h:mm:ss a'))
 | 
						|
        if (time >= newTime) {
 | 
						|
          newnotehistory[j] = notehistory[i]
 | 
						|
        }
 | 
						|
        found = true
 | 
						|
        break
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (!found) { newnotehistory.push(notehistory[i]) }
 | 
						|
  }
 | 
						|
  return newnotehistory
 | 
						|
}
 | 
						|
 | 
						|
function addHistory (id, text, time, tags, pinned, notehistory) {
 | 
						|
  // only add when note id exists
 | 
						|
  if (id) {
 | 
						|
    notehistory.push({
 | 
						|
      id,
 | 
						|
      text,
 | 
						|
      time,
 | 
						|
      tags,
 | 
						|
      pinned
 | 
						|
    })
 | 
						|
  }
 | 
						|
  return notehistory
 | 
						|
}
 | 
						|
 | 
						|
export function removeHistory (id, notehistory) {
 | 
						|
  for (let i = 0; i < notehistory.length; i++) {
 | 
						|
    if (notehistory[i].id === id) {
 | 
						|
      notehistory.splice(i, 1)
 | 
						|
      i -= 1
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return notehistory
 | 
						|
}
 | 
						|
 | 
						|
// used for inner
 | 
						|
export function writeHistory (title, tags) {
 | 
						|
  checkIfAuth(
 | 
						|
    () => {
 | 
						|
      // no need to do this anymore, this will count from server-side
 | 
						|
      // writeHistoryToServer(title, tags);
 | 
						|
    },
 | 
						|
    () => {
 | 
						|
      writeHistoryToStorage(title, tags)
 | 
						|
    }
 | 
						|
  )
 | 
						|
}
 | 
						|
 | 
						|
function writeHistoryToStorage (title, tags) {
 | 
						|
  const data = store.get('notehistory')
 | 
						|
  let notehistory
 | 
						|
  if (data && typeof data === 'string') {
 | 
						|
    notehistory = JSON.parse(data)
 | 
						|
  } else {
 | 
						|
    notehistory = []
 | 
						|
  }
 | 
						|
 | 
						|
  const newnotehistory = generateHistory(title, tags, notehistory)
 | 
						|
  saveHistoryToStorage(newnotehistory)
 | 
						|
}
 | 
						|
 | 
						|
if (!Array.isArray) {
 | 
						|
  Array.isArray = arg => Object.prototype.toString.call(arg) === '[object Array]'
 | 
						|
}
 | 
						|
 | 
						|
function renderHistory (title, tags) {
 | 
						|
  // console.debug(tags);
 | 
						|
  const id = urlpath ? location.pathname.slice(urlpath.length + 1, location.pathname.length).split('/')[1] : location.pathname.split('/')[1]
 | 
						|
  return {
 | 
						|
    id,
 | 
						|
    text: title,
 | 
						|
    time: moment().valueOf(),
 | 
						|
    tags
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function generateHistory (title, tags, notehistory) {
 | 
						|
  const info = renderHistory(title, tags)
 | 
						|
  // keep any pinned data
 | 
						|
  let pinned = false
 | 
						|
  for (let i = 0; i < notehistory.length; i++) {
 | 
						|
    if (notehistory[i].id === info.id && notehistory[i].pinned) {
 | 
						|
      pinned = true
 | 
						|
      break
 | 
						|
    }
 | 
						|
  }
 | 
						|
  notehistory = removeHistory(info.id, notehistory)
 | 
						|
  notehistory = addHistory(info.id, info.text, info.time, info.tags, pinned, notehistory)
 | 
						|
  notehistory = clearDuplicatedHistory(notehistory)
 | 
						|
  return notehistory
 | 
						|
}
 | 
						|
 | 
						|
// used for outer
 | 
						|
export function getHistory (callback) {
 | 
						|
  checkIfAuth(
 | 
						|
    () => {
 | 
						|
      getServerHistory(callback)
 | 
						|
    },
 | 
						|
    () => {
 | 
						|
      getStorageHistory(callback)
 | 
						|
    }
 | 
						|
  )
 | 
						|
}
 | 
						|
 | 
						|
function getServerHistory (callback) {
 | 
						|
  $.get(`${serverurl}/history`)
 | 
						|
    .done(data => {
 | 
						|
      if (data.history) {
 | 
						|
        callback(data.history)
 | 
						|
      }
 | 
						|
    })
 | 
						|
    .fail((xhr, status, error) => {
 | 
						|
      console.error(xhr.responseText)
 | 
						|
    })
 | 
						|
}
 | 
						|
 | 
						|
export function getStorageHistory (callback) {
 | 
						|
  let data = store.get('notehistory')
 | 
						|
  if (data) {
 | 
						|
    if (typeof data === 'string') { data = JSON.parse(data) }
 | 
						|
    callback(data)
 | 
						|
  }
 | 
						|
  // eslint-disable-next-line n/no-callback-literal
 | 
						|
  callback([])
 | 
						|
}
 | 
						|
 | 
						|
export function parseHistory (list, callback) {
 | 
						|
  checkIfAuth(
 | 
						|
    () => {
 | 
						|
      parseServerToHistory(list, callback)
 | 
						|
    },
 | 
						|
    () => {
 | 
						|
      parseStorageToHistory(list, callback)
 | 
						|
    }
 | 
						|
  )
 | 
						|
}
 | 
						|
 | 
						|
export function parseServerToHistory (list, callback) {
 | 
						|
  $.get(`${serverurl}/history`)
 | 
						|
    .done(data => {
 | 
						|
      if (data.history) {
 | 
						|
        parseToHistory(list, data.history, callback)
 | 
						|
      }
 | 
						|
    })
 | 
						|
    .fail((xhr, status, error) => {
 | 
						|
      console.error(xhr.responseText)
 | 
						|
    })
 | 
						|
}
 | 
						|
 | 
						|
export function parseStorageToHistory (list, callback) {
 | 
						|
  let data = store.get('notehistory')
 | 
						|
  if (data) {
 | 
						|
    if (typeof data === 'string') { data = JSON.parse(data) }
 | 
						|
    parseToHistory(list, data, callback)
 | 
						|
  }
 | 
						|
  parseToHistory(list, [], callback)
 | 
						|
}
 | 
						|
 | 
						|
function parseToHistory (list, notehistory, callback) {
 | 
						|
  if (!callback) return
 | 
						|
  else if (!list || !notehistory) callback(list, notehistory)
 | 
						|
  else if (notehistory && notehistory.length > 0) {
 | 
						|
    for (let i = 0; i < notehistory.length; i++) {
 | 
						|
      // migrate LZString encoded id to base64url encoded id
 | 
						|
      try {
 | 
						|
        const id = LZString.decompressFromBase64(notehistory[i].id)
 | 
						|
        if (id && checkNoteIdValid(id)) {
 | 
						|
          notehistory[i].id = encodeNoteId(id)
 | 
						|
        }
 | 
						|
      } catch (err) {
 | 
						|
        console.error(err)
 | 
						|
      }
 | 
						|
      // parse time to timestamp and fromNow
 | 
						|
      const timestamp = (typeof notehistory[i].time === 'number' ? moment(notehistory[i].time) : moment(notehistory[i].time, 'MMMM Do YYYY, h:mm:ss a'))
 | 
						|
      notehistory[i].timestamp = timestamp.valueOf()
 | 
						|
      notehistory[i].fromNow = timestamp.fromNow()
 | 
						|
      notehistory[i].time = timestamp.format('llll')
 | 
						|
      // prevent XSS
 | 
						|
      notehistory[i].text = S(notehistory[i].text).escapeHTML().s
 | 
						|
      notehistory[i].tags = (notehistory[i].tags && notehistory[i].tags.length > 0) ? S(notehistory[i].tags).escapeHTML().s.split(',') : []
 | 
						|
      // add to list
 | 
						|
      if (notehistory[i].id && list.get('id', notehistory[i].id).length === 0) { list.add(notehistory[i]) }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  callback(list, notehistory)
 | 
						|
}
 | 
						|
 | 
						|
export function postHistoryToServer (noteId, data, callback) {
 | 
						|
  $.post(`${serverurl}/history/${noteId}`, data)
 | 
						|
    .done(result => callback(null, result))
 | 
						|
    .fail((xhr, status, error) => {
 | 
						|
      console.error(xhr.responseText)
 | 
						|
      return callback(error, null)
 | 
						|
    })
 | 
						|
}
 | 
						|
 | 
						|
export function deleteServerHistory (noteId, callback) {
 | 
						|
  $.ajax({
 | 
						|
    url: `${serverurl}/history${noteId ? '/' + noteId : ''}`,
 | 
						|
    type: 'DELETE'
 | 
						|
  })
 | 
						|
    .done(result => callback(null, result))
 | 
						|
    .fail((xhr, status, error) => {
 | 
						|
      console.error(xhr.responseText)
 | 
						|
      return callback(error, null)
 | 
						|
    })
 | 
						|
}
 |