dea62cf310
Signed-off-by: Sheogorath <sheogorath@shivering-isles.com>
304 lines
8 KiB
JavaScript
304 lines
8 KiB
JavaScript
/* eslint-env browser, jquery */
|
|
/* global serverurl, moment */
|
|
|
|
import store from 'store'
|
|
import S from 'string'
|
|
import LZString from 'lz-string'
|
|
|
|
import {
|
|
checkNoteIdValid,
|
|
encodeNoteId
|
|
} from './utils'
|
|
|
|
import {
|
|
checkIfAuth
|
|
} from './lib/common/login'
|
|
|
|
import {
|
|
urlpath
|
|
} from './lib/config'
|
|
|
|
window.migrateHistoryFromTempCallback = null
|
|
|
|
migrateHistoryFromTemp()
|
|
|
|
function migrateHistoryFromTemp () {
|
|
if (window.url('#tempid')) {
|
|
$.get(`${serverurl}/temp`, {
|
|
tempid: window.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) {
|
|
let 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)
|
|
}
|
|
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 {
|
|
let 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)
|
|
})
|
|
}
|