* Copyright (c) 2022 - present TinyVue Authors.
* Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
export class Memorize {
constructor(value, options = {}) {
if (value && typeof value === 'object') {
options = value
} else {
value = []
}
if (typeof options.key !== 'string' || !options.key) {
throw new Error('Memorize Initialization error.')
}
this._prefix = 'tiny_memorize_'
this._customField1 = 'frequency'
this._customField2 = 'time'
this._sortBy = (options.sortBy || 'frequency').toUpperCase()
this._sort = (options.sort || 'desc').toUpperCase()
this._dataKey = options.dataKey || 'value'
this._highlightClass = options.highlightClass || 'memorize-highlight'
this._highlightNum = options.highlightNum || Infinity
this._cacheNum = options.cacheNum || Infinity
this._serialize = options.serialize || JSON.stringify
this._deserialize = options.deserialize || JSON.parse
this.setKey(options.key)
this.assemble(value)
}
setKey(storeKey) {
this._storeKey = this._prefix + (storeKey || Number(new Date()))
}
getValue(isSort = true) {
const storeVlue = window.localStorage[this._storeKey] || ''
if (storeVlue) {
try {
const list = this._deserialize(storeVlue)
return isSort ? this.sort(list) : list
} catch (e) {
return []
}
}
return []
}
setValue(value) {
try {
window.localStorage.setItem(this._storeKey, this._serialize(value))
} catch (e) {
throw new Error('Memorize set localStorage error.')
}
}
clear() {
window.localStorage.removeItem(this._storeKey)
}
add(dataKey) {
const list = this.getValue(false)
const newData = {
key: dataKey
}
newData[this._customField1] = 1
newData[this._customField2] = Number(new Date())
if (list.length < this._cacheNum) {
list.push(newData)
this.setValue(list)
}
}
updateByKey(dataKey) {
let isChanged = false
const list = this.getValue(false)
list.some((item) => {
if (item.key === dataKey) {
item[this._customField1] = (item[this._customField1] || 0) + 1
item[this._customField2] = Number(new Date())
isChanged = true
return true
}
return false
})
isChanged ? this.setValue(list) : this.add(dataKey)
}
sort(list) {
if (Array.isArray(list)) {
return list.sort((x, y) => {
const isDesc = this._sort === 'DESC'
const compare = isDesc ? [-1, 1] : [1, -1]
const sortField = this._sortBy === 'FREQUENCY' ? this._customField1 : this._customField2
const xField = x[sortField]
const yField = y[sortField]
if (isNaN(xField)) {
return isDesc ? -1 : 1
} else if (isNaN(yField)) {
return -1
}
return xField > yField ? compare[0] : compare[1]
})
} else {
return list
}
}
assemble(list) {
const storeValue = this.getValue(true)
if (!(Array.isArray(list) && list.length) || !storeValue.length) {
return list
}
let matchCount = 0
const handler = (storeItem) => (listItem, index) => {
if (listItem[this._dataKey] === storeItem.key) {
matchCount++
list.splice(index, 1)
if (matchCount <= this._highlightNum) {
listItem._highlightClass = this._highlightClass
}
list.unshift(listItem)
return true
}
return false
}
for (let i = storeValue.length - 1; i > -1; i--) {
const storeItem = storeValue[i]
list.some(handler(storeItem))
}
return list
}
}