import { defineStore } from 'pinia'
import { ref } from 'vue'
import prettyBytes from 'pretty-bytes'
import { useI18nStore } from './i18n.store'
function readLocal(key: string, fallback: string): string {
try { return localStorage.getItem(key) ?? fallback } catch { return fallback }
}
function readLocalBool(key: string, fallback: boolean): boolean {
try {
const v = localStorage.getItem(key)
return v === null ? fallback : v === 'true'
} catch { return fallback }
}
function readLocalNum(key: string, fallback: number): number {
try {
const v = localStorage.getItem(key)
return v === null ? fallback : Number(v)
} catch { return fallback }
}
export const useSettingsStore = defineStore('settings', () => {
// All localStorage keys match Angular settings.service.ts exactly
const redisTreeDivider = ref(readLocal('p3xr-main-treecontrol-divider', ':'))
const jsonFormat = ref(readLocalNum('p3xr-json-format', 4))
const animation = ref(readLocalNum('p3xr-animation-settings', 0) === 1)
const maxValueDisplay = ref(readLocalNum('p3xr-main-treecontrol-max-value-display', 1024))
const maxKeys = ref(readLocalNum('p3xr-max-keys', 1000))
const keysSort = ref(readLocalBool('p3xr-main-treecontrol-key-sort', true))
const searchClientSide = ref(readLocalBool('p3xr-main-treecontrol-search-client-mode', false))
const searchStartsWith = ref(readLocalBool('p3xr-main-treecontrol-search-starts-with', false))
const pageCount = ref(readLocalNum('p3xr-main-treecontrol-page-size', 250))
const keyPageCount = ref(readLocalNum('p3xr-main-key-page-size', 5))
const language = ref(readLocal('p3xr-language', 'en'))
const undoEnabled = ref(readLocalBool('p3xr-undo-enabled', true))
const showDiffBeforeSave = ref(readLocalBool('p3xr-show-diff-before-save', false))
const googleAnalytics = ref('G-8M2CK7993T')
const connectInfoStorageKey = ref('p3xr-connect-info')
const socketTimeout = ref(300000)
const maxLightKeysCount = ref(110000)
const maxValueAsBuffer = ref(1000 * 256)
// Apply animation class on init
;(() => {
const enabled = readLocalNum('p3xr-animation-settings', 0) === 1
document.body.classList.toggle('p3xr-animation', enabled)
document.body.classList.toggle('p3xr-no-animation', !enabled)
})()
function setSetting(key: string, value: any) {
try { localStorage.setItem(key, String(value)) } catch {}
const map: Record<string, any> = {
'p3xr-main-treecontrol-divider': redisTreeDivider,
'p3xr-json-format': jsonFormat,
'p3xr-animation-settings': animation,
'p3xr-main-treecontrol-max-value-display': maxValueDisplay,
'p3xr-max-keys': maxKeys,
'p3xr-main-treecontrol-key-sort': keysSort,
'p3xr-main-treecontrol-search-client-mode': searchClientSide,
'p3xr-main-treecontrol-search-starts-with': searchStartsWith,
'p3xr-main-treecontrol-page-size': pageCount,
'p3xr-main-key-page-size': keyPageCount,
'p3xr-language': language,
'p3xr-undo-enabled': undoEnabled,
'p3xr-show-diff-before-save': showDiffBeforeSave,
}
const refTarget = map[key]
if (refTarget) {
refTarget.value = value
}
if (key === 'p3xr-animation-settings') {
const enabled = String(value) === '1'
document.body.classList.toggle('p3xr-animation', enabled)
document.body.classList.toggle('p3xr-no-animation', !enabled)
}
}
function getStorageKeyCurrentDatabase(connectionId: string): string {
return `p3xr-main-current-database-${connectionId}`
}
function formatPrettyBytes(value: number): string {
let lang = language.value
if (lang === 'auto') {
const i18n = useI18nStore()
lang = i18n.currentLang || 'en'
}
return prettyBytes(value, { locale: lang })
}
function getHumanizeDurationOptions(): { language: string; languages: Record<string, any> } {
let lang = language.value
if (lang === 'auto') {
const i18n = useI18nStore()
lang = i18n.currentLang || 'en'
}
const languageMap: Record<string, string> = {
'pt-BR': 'pt', 'zn': 'zh_CN', 'zh-HK': 'zh_TW', 'zh-TW': 'zh_TW', 'pt-PT': 'pt',
}
const customLanguages: Record<string, any> = {
az: { y: () => 'il', mo: () => 'ay', w: () => 'h\u0259ft\u0259', d: () => 'g\u00fcn', h: () => 'saat', m: () => 'd\u0259qiq\u0259', s: () => 'saniy\u0259', ms: () => 'millisaniy\u0259' },
be: { y: (c: number) => c === 1 ? '\u0433\u043e\u0434' : '\u0433\u0430\u0434\u043e\u045e', mo: (c: number) => c === 1 ? '\u043c\u0435\u0441\u044f\u0446' : '\u043c\u0435\u0441\u044f\u0446\u0430\u045e', w: (c: number) => c === 1 ? '\u0442\u044b\u0434\u0437\u0435\u043d\u044c' : '\u0442\u044b\u0434\u043d\u044f\u045e', d: (c: number) => c === 1 ? '\u0434\u0437\u0435\u043d\u044c' : '\u0434\u0437\u0451\u043d', h: (c: number) => c === 1 ? '\u0433\u0430\u0434\u0437\u0456\u043d\u0430' : '\u0433\u0430\u0434\u0437\u0456\u043d', m: (c: number) => c === 1 ? '\u0445\u0432\u0456\u043b\u0456\u043d\u0430' : '\u0445\u0432\u0456\u043b\u0456\u043d', s: (c: number) => c === 1 ? '\u0441\u0435\u043a\u0443\u043d\u0434\u0430' : '\u0441\u0435\u043a\u0443\u043d\u0434', ms: (c: number) => c === 1 ? '\u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434\u0430' : '\u043c\u0456\u043b\u0456\u0441\u0435\u043a\u0443\u043d\u0434' },
bs: { y: () => 'godina', mo: () => 'mjeseci', w: () => 'sedmica', d: () => 'dana', h: () => 'sati', m: () => 'minuta', s: () => 'sekundi', ms: () => 'milisekundi' },
fil: { y: () => 'taon', mo: () => 'buwan', w: () => 'linggo', d: () => 'araw', h: () => 'oras', m: () => 'minuto', s: () => 'segundo', ms: () => 'millisegundo' },
hy: { y: () => '\u057f\u0561\u0580\u056b', mo: () => '\u0561\u0574\u056b\u057d', w: () => '\u0577\u0561\u0562\u0561\u0569', d: () => '\u0585\u0580', h: () => '\u056a\u0561\u0574', m: () => '\u0580\u0578\u057a\u0565', s: () => '\u057e\u0561\u0575\u0580\u056f\u0575\u0561\u0576', ms: () => '\u0574\u056b\u056c\u056b\u057e\u0561\u0575\u0580\u056f\u0575\u0561\u0576' },
ka: { y: () => '\u10ec\u10d4\u10da\u10d8', mo: () => '\u10d7\u10d5\u10d4', w: () => '\u10d9\u10d5\u10d8\u10e0\u10d0', d: () => '\u10d3\u10e6\u10d4', h: () => '\u10e1\u10d0\u10d0\u10d7\u10d8', m: () => '\u10ec\u10e3\u10d7\u10d8', s: () => '\u10ec\u10d0\u10db\u10d8', ms: () => '\u10db\u10d8\u10da\u10d8\u10ec\u10d0\u10db\u10d8' },
kk: { y: () => '\u0436\u044b\u043b', mo: () => '\u0430\u0439', w: () => '\u0430\u043f\u0442\u0430', d: () => '\u043a\u04af\u043d', h: () => '\u0441\u0430\u0493\u0430\u0442', m: () => '\u043c\u0438\u043d\u0443\u0442', s: () => '\u0441\u0435\u043a\u0443\u043d\u0434', ms: () => '\u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434' },
ky: { y: () => '\u0436\u044b\u043b', mo: () => '\u0430\u0439', w: () => '\u0430\u043f\u0442\u0430', d: () => '\u043a\u04af\u043d', h: () => '\u0441\u0430\u0430\u0442', m: () => '\u043c\u04af\u043d\u04e9\u0442', s: () => '\u0441\u0435\u043a\u0443\u043d\u0434', ms: () => '\u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434' },
ne: { y: () => '\u0935\u0930\u094d\u0937', mo: () => '\u092e\u0939\u093f\u0928\u093e', w: () => '\u0939\u092a\u094d\u0924\u093e', d: () => '\u0926\u093f\u0928', h: () => '\u0918\u0923\u094d\u091f\u093e', m: () => '\u092e\u093f\u0928\u0947\u091f', s: () => '\u0938\u0947\u0915\u0947\u0928\u094d\u0921', ms: () => '\u092e\u093f\u0932\u093f\u0938\u0947\u0915\u0947\u0928\u094d\u0921' },
si: { y: () => '\u0dc0\u0dc3\u0dbb', mo: () => '\u0db8\u0dcf\u0dc3', w: () => '\u0dc3\u0dad\u0dd2', d: () => '\u0daf\u0dd2\u0db1', h: () => '\u0db4\u0dd0\u0dba', m: () => '\u0db8\u0dd2\u0db1\u0dd2\u0dad\u0dca\u0dad\u0dd4', s: () => '\u0dad\u0dad\u0dca\u0db4\u0dbb', ms: () => '\u0db8\u0dd2\u0dbd\u0dd2 \u0dad\u0dad\u0dca\u0db4\u0dbb' },
tg: { y: () => '\u0441\u043e\u043b', mo: () => '\u043c\u043e\u04b3', w: () => '\u04b3\u0430\u0444\u0442\u0430', d: () => '\u0440\u04ef\u0437', h: () => '\u0441\u043e\u0430\u0442', m: () => '\u0434\u0430\u049b\u0438\u049b\u0430', s: () => '\u0441\u043e\u043d\u0438\u044f', ms: () => '\u043c\u0438\u043b\u043b\u0438\u0441\u043e\u043d\u0438\u044f' },
nb: { y: (c: number) => c === 1 ? '\u00e5r' : '\u00e5r', mo: (c: number) => c === 1 ? 'm\u00e5ned' : 'm\u00e5neder', w: (c: number) => c === 1 ? 'uke' : 'uker', d: (c: number) => c === 1 ? 'dag' : 'dager', h: (c: number) => c === 1 ? 'time' : 'timer', m: (c: number) => c === 1 ? 'minutt' : 'minutter', s: (c: number) => c === 1 ? 'sekund' : 'sekunder', ms: () => 'millisekund' },
}
return {
language: languageMap[lang] || lang || 'en',
languages: customLanguages,
}
}
function generateId(): string {
return 'P3Xid' + Array.from(crypto.getRandomValues(new Uint8Array(16)))
.map(b => b.toString(16).padStart(2, '0')).join('')
}
return {
redisTreeDivider,
jsonFormat,
animation,
maxValueDisplay,
maxKeys,
keysSort,
searchClientSide,
searchStartsWith,
pageCount,
keyPageCount,
language,
undoEnabled,
showDiffBeforeSave,
googleAnalytics,
connectInfoStorageKey,
socketTimeout,
maxLightKeysCount,
maxValueAsBuffer,
setSetting,
getStorageKeyCurrentDatabase,
prettyBytes: formatPrettyBytes,
getHumanizeDurationOptions,
generateId,
}
})