mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2025-07-29 07:04:31 +02:00
625 lines
No EOL
17 KiB
JavaScript
625 lines
No EOL
17 KiB
JavaScript
import { Capacitor } from '@capacitor/core';
|
|
import { CapacitorDataStorageSqlite } from 'capacitor-data-storage-sqlite';
|
|
import { Storage } from '@capacitor/storage'
|
|
|
|
class StoreService {
|
|
store
|
|
isService = false
|
|
platform
|
|
isOpen = false
|
|
tableName = 'downloads'
|
|
|
|
constructor() {
|
|
this.init()
|
|
}
|
|
|
|
/**
|
|
* Plugin Initialization
|
|
*/
|
|
init() {
|
|
this.platform = Capacitor.getPlatform()
|
|
this.store = CapacitorDataStorageSqlite
|
|
this.isService = true
|
|
console.log('in init ', this.platform, this.isService)
|
|
}
|
|
|
|
/**
|
|
* Open a Store
|
|
* @param _dbName string optional
|
|
* @param _table string optional
|
|
* @param _encrypted boolean optional
|
|
* @param _mode string optional
|
|
*/
|
|
async openStore(_dbName, _table, _encrypted, _mode) {
|
|
if (this.isService && this.store != null) {
|
|
const database = _dbName ? _dbName : "storage"
|
|
const table = _table ? _table : "storage_table"
|
|
const encrypted = _encrypted ? _encrypted : false
|
|
const mode = _mode ? _mode : "no-encryption"
|
|
|
|
this.isOpen = false
|
|
try {
|
|
await this.store.openStore({ database, table, encrypted, mode })
|
|
// return Promise.resolve()
|
|
this.isOpen = true
|
|
return true
|
|
} catch (err) {
|
|
// return Promise.reject(err)
|
|
return false
|
|
}
|
|
} else {
|
|
// return Promise.reject(new Error("openStore: Store not opened"))
|
|
return false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Close a store
|
|
* @param dbName
|
|
* @returns
|
|
*/
|
|
async closeStore(dbName) {
|
|
if (this.isService && this.store != null) {
|
|
try {
|
|
await this.store.closeStore({ database: dbName })
|
|
return Promise.resolve()
|
|
} catch (err) {
|
|
return Promise.reject(err)
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("close: Store not opened"))
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if a store is opened
|
|
* @param dbName
|
|
* @returns
|
|
*/
|
|
async isStoreOpen(dbName) {
|
|
if (this.isService && this.store != null) {
|
|
try {
|
|
const ret = await this.store.isStoreOpen({ database: dbName })
|
|
return Promise.resolve(ret)
|
|
} catch (err) {
|
|
return Promise.reject(err)
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("isStoreOpen: Store not opened"))
|
|
}
|
|
}
|
|
/**
|
|
* Check if a store already exists
|
|
* @param dbName
|
|
* @returns
|
|
*/
|
|
async isStoreExists(dbName) {
|
|
if (this.isService && this.store != null) {
|
|
try {
|
|
const ret = await this.store.isStoreExists({ database: dbName })
|
|
return Promise.resolve(ret)
|
|
} catch (err) {
|
|
return Promise.reject(err)
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("isStoreExists: Store not opened"))
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create/Set a Table
|
|
* @param table string
|
|
*/
|
|
async setTable(table) {
|
|
if (this.isService && this.store != null) {
|
|
try {
|
|
await this.store.setTable({ table })
|
|
return Promise.resolve()
|
|
} catch (err) {
|
|
return Promise.reject(err)
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("setTable: Store not opened"))
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set of Key
|
|
* @param key string
|
|
* @param value string
|
|
*/
|
|
async setItem(key, value) {
|
|
if (this.isService && this.store != null) {
|
|
if (key.length > 0) {
|
|
try {
|
|
await this.store.set({ key, value });
|
|
return Promise.resolve();
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("setItem: Must give a key"));
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("setItem: Store not opened"));
|
|
}
|
|
}
|
|
/**
|
|
* Get the Value for a given Key
|
|
* @param key string
|
|
*/
|
|
async getItem(key) {
|
|
if (this.isService && this.store != null) {
|
|
if (key.length > 0) {
|
|
try {
|
|
const { value } = await this.store.get({ key });
|
|
console.log("in getItem value ", value)
|
|
return Promise.resolve(value);
|
|
} catch (err) {
|
|
console.error(`in getItem key: ${key} err: ${JSON.stringify(err)}`)
|
|
return Promise.reject(err);
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("getItem: Must give a key"));
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("getItem: Store not opened"));
|
|
}
|
|
|
|
}
|
|
async isKey(key) {
|
|
if (this.isService && this.store != null) {
|
|
if (key.length > 0) {
|
|
try {
|
|
const { result } = await this.store.iskey({ key });
|
|
return Promise.resolve(result);
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("isKey: Must give a key"));
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("isKey: Store not opened"));
|
|
}
|
|
|
|
}
|
|
|
|
async getAllKeys() {
|
|
if (this.isService && this.store != null) {
|
|
try {
|
|
const { keys } = await this.store.keys();
|
|
return Promise.resolve(keys);
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("getAllKeys: Store not opened"));
|
|
}
|
|
}
|
|
async getAllValues() {
|
|
if (this.isService && this.store != null) {
|
|
try {
|
|
const { values } = await this.store.values();
|
|
return Promise.resolve(values);
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("getAllValues: Store not opened"));
|
|
}
|
|
}
|
|
async getFilterValues(filter) {
|
|
if (this.isService && this.store != null) {
|
|
try {
|
|
const { values } = await this.store.filtervalues({ filter });
|
|
return Promise.resolve(values);
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("getFilterValues: Store not opened"));
|
|
}
|
|
}
|
|
async getAllKeysValues() {
|
|
if (this.isService && this.store != null) {
|
|
try {
|
|
const { keysvalues } = await this.store.keysvalues();
|
|
return Promise.resolve(keysvalues);
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("getAllKeysValues: Store not opened"));
|
|
}
|
|
}
|
|
|
|
async removeItem(key) {
|
|
if (this.isService && this.store != null) {
|
|
if (key.length > 0) {
|
|
try {
|
|
await this.store.remove({ key });
|
|
return Promise.resolve();
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("removeItem: Must give a key"));
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("removeItem: Store not opened"));
|
|
}
|
|
}
|
|
|
|
async clear() {
|
|
if (this.isService && this.store != null) {
|
|
try {
|
|
await this.store.clear();
|
|
return Promise.resolve();
|
|
} catch (err) {
|
|
return Promise.reject(err.message);
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("clear: Store not opened"));
|
|
}
|
|
}
|
|
|
|
async deleteStore(_dbName) {
|
|
const database = _dbName ? _dbName : "storage"
|
|
|
|
if (this.isService && this.store != null) {
|
|
try {
|
|
await this.store.deleteStore({ database })
|
|
return Promise.resolve();
|
|
} catch (err) {
|
|
return Promise.reject(err.message)
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("deleteStore: Store not opened"));
|
|
}
|
|
}
|
|
async isTable(table) {
|
|
if (this.isService && this.store != null) {
|
|
if (table.length > 0) {
|
|
try {
|
|
const { result } = await this.store.isTable({ table });
|
|
return Promise.resolve(result);
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("isTable: Must give a table"));
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("isTable: Store not opened"));
|
|
}
|
|
}
|
|
async getAllTables() {
|
|
if (this.isService && this.store != null) {
|
|
try {
|
|
const { tables } = await this.store.tables();
|
|
return Promise.resolve(tables);
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("getAllTables: Store not opened"));
|
|
}
|
|
}
|
|
async deleteTable(table) {
|
|
if (this.isService && this.store != null) {
|
|
if (table.length > 0) {
|
|
try {
|
|
await this.store.deleteTable({ table });
|
|
return Promise.resolve();
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("deleteTable: Must give a table"));
|
|
}
|
|
} else {
|
|
return Promise.reject(new Error("deleteTable: Store not opened"));
|
|
}
|
|
}
|
|
|
|
async getDownload(id) {
|
|
if (!this.isOpen) {
|
|
var success = await this.openStore('storage', this.tableName)
|
|
if (!success) {
|
|
console.error('Store failed to open')
|
|
return null
|
|
}
|
|
}
|
|
try {
|
|
var value = await this.getItem(id)
|
|
return JSON.parse(value)
|
|
} catch (error) {
|
|
console.error('Failed to get download from store', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
async setDownload(download) {
|
|
if (!this.isOpen) {
|
|
var success = await this.openStore('storage', this.tableName)
|
|
if (!success) {
|
|
console.error('Store failed to open')
|
|
return false
|
|
}
|
|
}
|
|
|
|
try {
|
|
await this.setItem(download.id, JSON.stringify(download))
|
|
console.log(`[STORE] Set Download ${download.id}`)
|
|
return true
|
|
} catch (error) {
|
|
console.error('Failed to set download in store', error)
|
|
return false
|
|
}
|
|
}
|
|
|
|
async removeDownload(id) {
|
|
if (!this.isOpen) {
|
|
var success = await this.openStore('storage', this.tableName)
|
|
if (!success) {
|
|
console.error('Store failed to open')
|
|
return false
|
|
}
|
|
}
|
|
|
|
try {
|
|
await this.removeItem(id)
|
|
console.log(`[STORE] Removed download ${id}`)
|
|
return true
|
|
} catch (error) {
|
|
console.error('Failed to remove download in store', error)
|
|
return false
|
|
}
|
|
}
|
|
|
|
async getAllDownloads() {
|
|
if (!this.isOpen) {
|
|
var success = await this.openStore('storage', this.tableName)
|
|
if (!success) {
|
|
console.error('Store failed to open')
|
|
return []
|
|
}
|
|
}
|
|
var keysvalues = await this.getAllKeysValues()
|
|
var downloads = []
|
|
|
|
for (let i = 0; i < keysvalues.length; i++) {
|
|
try {
|
|
var download = JSON.parse(keysvalues[i].value)
|
|
downloads.push(download)
|
|
} catch (error) {
|
|
console.error('Failed to parse download', error)
|
|
await this.removeItem(keysvalues[i].key)
|
|
}
|
|
}
|
|
|
|
return downloads
|
|
}
|
|
}
|
|
|
|
class LocalStorage {
|
|
constructor(vuexStore) {
|
|
this.vuexStore = vuexStore
|
|
|
|
this.userAudiobooksLoaded = false
|
|
this.downloadFolder = null
|
|
this.userAudiobooks = {}
|
|
}
|
|
|
|
async getMostRecentUserAudiobook(audiobookId) {
|
|
if (!this.userAudiobooksLoaded) {
|
|
await this.loadUserAudiobooks()
|
|
}
|
|
var local = this.getUserAudiobook(audiobookId)
|
|
var server = this.vuexStore.getters['user/getUserAudiobook'](audiobookId)
|
|
|
|
if (local && server) {
|
|
if (local.lastUpdate > server.lastUpdate) {
|
|
console.log('[LocalStorage] Most recent user audiobook is from LOCAL')
|
|
return local
|
|
}
|
|
console.log('[LocalStorage] Most recent user audiobook is from SERVER')
|
|
return server
|
|
} else if (local) {
|
|
console.log('[LocalStorage] Most recent user audiobook is from LOCAL')
|
|
return local
|
|
} else if (server) {
|
|
console.log('[LocalStorage] Most recent user audiobook is from SERVER')
|
|
return server
|
|
}
|
|
return null
|
|
}
|
|
|
|
async loadUserAudiobooks() {
|
|
try {
|
|
var val = (await Storage.get({ key: 'userAudiobooks' }) || {}).value || null
|
|
this.userAudiobooks = val ? JSON.parse(val) : {}
|
|
this.userAudiobooksLoaded = true
|
|
this.vuexStore.commit('user/setLocalUserAudiobooks', this.userAudiobooks)
|
|
} catch (error) {
|
|
console.error('[LocalStorage] Failed to load user audiobooks', error)
|
|
}
|
|
}
|
|
|
|
async saveUserAudiobooks() {
|
|
try {
|
|
await Storage.set({ key: 'userAudiobooks', value: JSON.stringify(this.userAudiobooks) })
|
|
} catch (error) {
|
|
console.error('[LocalStorage] Failed to set user audiobooks', error)
|
|
}
|
|
}
|
|
|
|
async setAllAudiobookProgress(progresses) {
|
|
this.userAudiobooks = progresses
|
|
await this.saveUserAudiobooks()
|
|
this.vuexStore.commit('user/setLocalUserAudiobooks', this.userAudiobooks)
|
|
}
|
|
|
|
async updateUserAudiobookProgress(progressPayload) {
|
|
this.userAudiobooks[progressPayload.audiobookId] = {
|
|
...progressPayload
|
|
}
|
|
console.log('[LocalStorage] Updated User Audiobook Progress ' + progressPayload.audiobookId)
|
|
await this.saveUserAudiobooks()
|
|
this.vuexStore.commit('user/setLocalUserAudiobooks', this.userAudiobooks)
|
|
}
|
|
|
|
async removeAudiobookProgress(audiobookId) {
|
|
if (!this.userAudiobooks[audiobookId]) return
|
|
delete this.userAudiobooks[audiobookId]
|
|
await this.saveUserAudiobooks()
|
|
this.vuexStore.commit('user/setLocalUserAudiobooks', this.userAudiobooks)
|
|
}
|
|
|
|
getUserAudiobook(audiobookId) {
|
|
return this.userAudiobooks[audiobookId] || null
|
|
}
|
|
|
|
async setToken(token) {
|
|
try {
|
|
if (token) {
|
|
await Storage.set({ key: 'token', value: token })
|
|
} else {
|
|
await Storage.remove({ key: 'token' })
|
|
}
|
|
} catch (error) {
|
|
console.error('[LocalStorage] Failed to set token', error)
|
|
}
|
|
}
|
|
|
|
async getToken() {
|
|
try {
|
|
return (await Storage.get({ key: 'token' }) || {}).value || null
|
|
} catch (error) {
|
|
console.error('[LocalStorage] Failed to get token', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
async setCurrentLibrary(library) {
|
|
try {
|
|
if (library) {
|
|
await Storage.set({ key: 'library', value: JSON.stringify(library) })
|
|
} else {
|
|
await Storage.remove({ key: 'library' })
|
|
}
|
|
} catch (error) {
|
|
console.error('[LocalStorage] Failed to set library', error)
|
|
}
|
|
}
|
|
|
|
async getCurrentLibrary() {
|
|
try {
|
|
var _value = (await Storage.get({ key: 'library' }) || {}).value || null
|
|
if (!_value) return null
|
|
return JSON.parse(_value)
|
|
} catch (error) {
|
|
console.error('[LocalStorage] Failed to get current library', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
async setDownloadFolder(folderObj) {
|
|
try {
|
|
if (folderObj) {
|
|
await Storage.set({ key: 'downloadFolder', value: JSON.stringify(folderObj) })
|
|
this.downloadFolder = folderObj
|
|
} else {
|
|
await Storage.remove({ key: 'downloadFolder' })
|
|
this.downloadFolder = null
|
|
}
|
|
} catch (error) {
|
|
console.error('[LocalStorage] Failed to set download folder', error)
|
|
}
|
|
}
|
|
|
|
async getDownloadFolder() {
|
|
try {
|
|
var _value = (await Storage.get({ key: 'downloadFolder' }) || {}).value || null
|
|
if (!_value) return null
|
|
this.downloadFolder = JSON.parse(_value)
|
|
return this.downloadFolder
|
|
} catch (error) {
|
|
console.error('[LocalStorage] Failed to get download folder', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
async getServerUrl() {
|
|
try {
|
|
return (await Storage.get({ key: 'serverUrl' }) || {}).value || null
|
|
} catch (error) {
|
|
console.error('[LocalStorage] Failed to get serverUrl', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
async setUserSettings(settings) {
|
|
try {
|
|
await Storage.set({ key: 'userSettings', value: JSON.stringify(settings) })
|
|
} catch (error) {
|
|
console.error('[LocalStorage] Failed to update user settings', error)
|
|
}
|
|
}
|
|
|
|
async getUserSettings() {
|
|
try {
|
|
var settingsObj = await Storage.get({ key: 'userSettings' }) || {}
|
|
return settingsObj.value ? JSON.parse(settingsObj.value) : null
|
|
} catch (error) {
|
|
console.error('[LocalStorage] Failed to get user settings', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
async setCurrent(current) {
|
|
try {
|
|
if (current) {
|
|
await Storage.set({ key: 'current', value: JSON.stringify(current) })
|
|
} else {
|
|
await Storage.remove({ key: 'current' })
|
|
}
|
|
} catch (error) {
|
|
console.error('[LocalStorage] Failed to set current', error)
|
|
}
|
|
}
|
|
|
|
async getCurrent() {
|
|
try {
|
|
var currentObj = await Storage.get({ key: 'current' }) || {}
|
|
return currentObj.value ? JSON.parse(currentObj.value) : null
|
|
} catch (error) {
|
|
console.error('[LocalStorage] Failed to get current', error)
|
|
return null
|
|
}
|
|
}
|
|
|
|
async setBookshelfView(view) {
|
|
try {
|
|
await Storage.set({ key: 'bookshelfView', value: view })
|
|
} catch (error) {
|
|
console.error('[LocalStorage] Failed to set bookshelf view', error)
|
|
}
|
|
}
|
|
|
|
async getBookshelfView() {
|
|
try {
|
|
var view = await Storage.get({ key: 'bookshelfView' }) || {}
|
|
return view.value || null
|
|
} catch (error) {
|
|
console.error('[LocalStorage] Failed to get bookshelf view', error)
|
|
return null
|
|
}
|
|
}
|
|
}
|
|
|
|
export default ({ app, store }, inject) => {
|
|
inject('sqlStore', new StoreService())
|
|
inject('localStore', new LocalStorage(store))
|
|
} |