1
0
Fork 1
mirror of https://github.com/maunium/stickerpicker synced 2024-09-18 00:20:52 +00:00

Frequently used in sync with packs & way to clear Frequently used

This commit is contained in:
Kévin Cocchi 2023-05-27 18:21:25 +02:00
parent 5c8c72e341
commit 70b90b5738
No known key found for this signature in database
GPG key ID: E3F3FFBE2818518D
2 changed files with 106 additions and 29 deletions

View file

@ -13,22 +13,80 @@
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
const FREQUENTLY_USED = JSON.parse(window.localStorage.mauFrequentlyUsedStickerIDs || "{}")
const FREQUENTLY_USED_STORAGE_KEY = 'mauFrequentlyUsedStickerIDs'
const FREQUENTLY_USED_STORAGE_CACHE_KEY = 'mauFrequentlyUsedStickerCache'
let FREQUENTLY_USED = JSON.parse(window.localStorage[FREQUENTLY_USED_STORAGE_KEY] ?? '{}')
let FREQUENTLY_USED_SORTED = null
export const add = id => {
const [count] = FREQUENTLY_USED[id] || [0]
FREQUENTLY_USED[id] = [count + 1, Date.now()]
window.localStorage.mauFrequentlyUsedStickerIDs = JSON.stringify(FREQUENTLY_USED)
const sortFrequentlyUsedEntries = (entry1, entry2) => {
const [, [count1, date1]] = entry1
const [, [count2, date2]] = entry2
return count2 === count1 ? date2 - date1 : count2 - count1
}
export const setFrequentlyUsedStorage = (frequentlyUsed) => {
FREQUENTLY_USED = frequentlyUsed ?? {}
window.localStorage[FREQUENTLY_USED_STORAGE_KEY] = JSON.stringify(FREQUENTLY_USED)
FREQUENTLY_USED_SORTED = null
}
export const setFrequentlyUsedCacheStorage = (stickers) => {
const toPutInCache = stickers.map(sticker => [sticker.id, sticker])
window.localStorage[FREQUENTLY_USED_STORAGE_CACHE_KEY] = JSON.stringify(toPutInCache)
}
export const add = (id) => {
let FREQUENTLY_USED_COPY = { ...FREQUENTLY_USED }
const [count] = FREQUENTLY_USED_COPY[id] || [0]
FREQUENTLY_USED_COPY[id] = [count + 1, Date.now()]
setFrequentlyUsedStorage(FREQUENTLY_USED_COPY)
}
export const get = (limit = 16) => {
if (FREQUENTLY_USED_SORTED === null) {
FREQUENTLY_USED_SORTED = Object.entries(FREQUENTLY_USED)
.sort(([, [count1, date1]], [, [count2, date2]]) =>
count2 === count1 ? date2 - date1 : count2 - count1)
FREQUENTLY_USED_SORTED = Object.entries(FREQUENTLY_USED || {})
.sort(sortFrequentlyUsedEntries)
.map(([emoji]) => emoji)
}
return FREQUENTLY_USED_SORTED.slice(0, limit)
}
export const getFromCache = () => {
return Object.values(JSON.parse(localStorage[FREQUENTLY_USED_STORAGE_CACHE_KEY] ?? '[]'))
}
export const remove = (id) => {
let FREQUENTLY_USED_COPY = { ...FREQUENTLY_USED }
if (FREQUENTLY_USED_COPY[id]) {
delete FREQUENTLY_USED_COPY[id]
setFrequentlyUsedStorage(FREQUENTLY_USED_COPY)
}
}
export const removeMultiple = (ids) => {
let FREQUENTLY_USED_COPY = { ...FREQUENTLY_USED }
ids.forEach((id) => {
delete FREQUENTLY_USED_COPY[id]
})
setFrequentlyUsedStorage(FREQUENTLY_USED_COPY)
}
export const removeAll = setFrequentlyUsedStorage
const compareStorageWith = (packs) => {
const stickersIDsFromPacks = packs.map((pack) => pack.stickers).flat().map((sticker) => sticker.id)
const stickersIDsFromFrequentlyUsedStorage = get()
const notFound = stickersIDsFromFrequentlyUsedStorage.filter((id) => !stickersIDsFromPacks.includes(id))
const found = stickersIDsFromFrequentlyUsedStorage.filter((id) => !notFound.includes(id))
return { found, notFound }
}
export const removeNotFoundFromStorage = (packs) => {
const { found, notFound } = compareStorageWith(packs)
removeMultiple(notFound)
return found
}

View file

@ -47,6 +47,13 @@ const defaultState = {
},
}
const makeFrequentlyUsedState = ({ stickerIDs, stickers } = {}) => ({
id: "frequently-used",
title: "Frequently used",
stickerIDs: stickerIDs ?? [],
stickers: stickers ?? [],
})
class App extends Component {
constructor(props) {
super(props)
@ -57,29 +64,26 @@ class App extends Component {
error: null,
stickersPerRow: parseInt(localStorage.mauStickersPerRow || "4"),
theme: localStorage.mauStickerThemeOverride || this.defaultTheme,
frequentlyUsed: {
id: "frequently-used",
title: "Frequently used",
stickerIDs: frequent.get(),
stickers: [],
},
frequentlyUsed: makeFrequentlyUsedState(),
filtering: defaultState.filtering,
}
if (!supportedThemes.includes(this.state.theme)) {
this.state.theme = "light"
}
if (!supportedThemes.includes(this.defaultTheme)) {
this.defaultTheme = "light"
}
this.stickersByID = new Map(JSON.parse(localStorage.mauFrequentlyUsedStickerCache || "[]"))
this.state.frequentlyUsed.stickers = this._getStickersByID(this.state.frequentlyUsed.stickerIDs)
this.imageObserver = null
this.packListRef = null
this.navRef = null
this.searchStickers = this.searchStickers.bind(this)
this.sendSticker = this.sendSticker.bind(this)
this.navScroll = this.navScroll.bind(this)
this.reloadPacks = this.reloadPacks.bind(this)
this.clearFrequentlyUsed = this.clearFrequentlyUsed.bind(this)
this.observeSectionIntersections = this.observeSectionIntersections.bind(this)
this.observeImageIntersections = this.observeImageIntersections.bind(this)
}
@ -88,17 +92,26 @@ class App extends Component {
return ids.map(id => this.stickersByID.get(id)).filter(sticker => !!sticker)
}
_setFrequentlyUsed(stickerIDs = []) {
const stickers = this._getStickersByID(stickerIDs)
const frequentlyUsed = makeFrequentlyUsedState({ stickerIDs, stickers })
this.setState({ frequentlyUsed })
frequent.setFrequentlyUsedCacheStorage(stickers)
}
updateFrequentlyUsed() {
const stickerIDs = frequent.get()
const stickers = this._getStickersByID(stickerIDs)
this.setState({
frequentlyUsed: {
...this.state.frequentlyUsed,
stickerIDs,
stickers,
},
})
localStorage.mauFrequentlyUsedStickerCache = JSON.stringify(stickers.map(sticker => [sticker.id, sticker]))
this._setFrequentlyUsed(stickerIDs)
}
refreshFrequentlyUsed(packs) {
const stickerIDs = frequent.removeNotFoundFromStorage(packs)
this._setFrequentlyUsed(stickerIDs)
}
clearFrequentlyUsed() {
frequent.removeAll()
this._setFrequentlyUsed()
}
searchStickers(e) {
@ -152,6 +165,10 @@ class App extends Component {
this._loadPacks(true)
}
_initializeStickersByID(ids) {
this.stickersByID = new Map(ids ?? [])
}
async populateStickersByID(allPacks) {
const allStickers = allPacks.map(({ stickers }) => stickers).flat()
allStickers.forEach((sticker) => {
@ -187,17 +204,18 @@ class App extends Component {
loading: false,
})
this.populateStickersByID(fetchedPacks)
this.updateFrequentlyUsed()
this.refreshFrequentlyUsed(fetchedPacks)
return fetchedPacks
}, error => this.setState({ loading: false, error }))
}
componentDidMount() {
document.documentElement.style.setProperty("--stickers-per-row", this.state.stickersPerRow.toString())
this._loadPacks()
this.imageObserver = new IntersectionObserver(this.observeImageIntersections, {
rootMargin: "100px",
})
this._initializeStickersByID(frequent.getFromCache())
this.imageObserver = new IntersectionObserver(this.observeImageIntersections, { rootMargin: "100px" })
this.sectionObserver = new IntersectionObserver(this.observeSectionIntersections)
}
@ -309,6 +327,7 @@ const Settings = ({ app }) => html`
<h1>Settings</h1>
<div class="settings-list">
<button onClick=${app.reloadPacks}>Reload</button>
<button onClick=${app.clearFrequentlyUsed}>Clear frequently used</button>
<div>
<label for="stickers-per-row">Stickers per row: ${app.state.stickersPerRow}</label>
<input type="range" min=2 max=10 id="stickers-per-row" id="stickers-per-row"