// Copyright (C) 2023 Vaughn Nugent // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program 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 // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . import { storage } from "webextension-polyfill" import { } from 'lodash' import { configureApi, debugLog } from '@vnuge/vnlib.browser' import { MaybeRefOrGetter, readonly, Ref, shallowRef, watch } from "vue"; import { JsonObject } from "type-fest"; import { Watchable } from "./types"; import { BgRuntime, FeatureApi, optionsOnly, IFeatureExport, exportForegroundApi, popupAndOptionsOnly } from './framework' import { get, set, toRefs } from "@vueuse/core"; import { waitForChangeFn, useStorage } from "./util"; import { ServerApi, useServerApi } from "./server-api"; export interface PluginConfig extends JsonObject { readonly apiUrl: string; readonly accountBasePath: string; readonly nostrEndpoint: string; readonly heartbeat: boolean; readonly maxHistory: number; readonly tagFilter: boolean, } //Default storage config const defaultConfig : PluginConfig = { apiUrl: import.meta.env.VITE_API_URL, accountBasePath: import.meta.env.VITE_ACCOUNTS_BASE_PATH, nostrEndpoint: import.meta.env.VITE_NOSTR_ENDPOINT, heartbeat: import.meta.env.VITE_HEARTBEAT_ENABLED === 'true', maxHistory: 50, tagFilter: true, }; export interface AppSettings{ saveConfig(config: PluginConfig): void; useStorageSlot(slot: string, defaultValue: MaybeRefOrGetter): Ref; useServerApi(): ServerApi, readonly currentConfig: Readonly>; } export interface SettingsApi extends FeatureApi, Watchable { getSiteConfig: () => Promise; setSiteConfig: (config: PluginConfig) => Promise; setDarkMode: (darkMode: boolean) => Promise; getDarkMode: () => Promise; } export const useAppSettings = (): AppSettings => { const _storageBackend = storage.local; const store = useStorage(_storageBackend, 'siteConfig', defaultConfig); watch(store, (config, _) => { //Configure the vnlib api configureApi({ session: { cookiesEnabled: false, browserIdSize: 32, }, user: { accountBasePath: config.accountBasePath, }, axios: { baseURL: config.apiUrl, tokenHeader: import.meta.env.VITE_WEB_TOKEN_HEADER, }, storage: localStorage }) }, { deep: true }) //Save the config and update the current config const saveConfig = (config: PluginConfig) => set(store, config); //Reactive urls for server api const { accountBasePath, nostrEndpoint } = toRefs(store) const serverApi = useServerApi(nostrEndpoint, accountBasePath) return { saveConfig, currentConfig: readonly(store), useStorageSlot: (slot: string, defaultValue: MaybeRefOrGetter) => { return useStorage(_storageBackend, slot, defaultValue) }, useServerApi: () => serverApi } } export const useSettingsApi = () : IFeatureExport =>{ return{ background: ({ state }: BgRuntime) => { const _darkMode = shallowRef(false); return { waitForChange: waitForChangeFn([state.currentConfig, _darkMode]), getSiteConfig: () => Promise.resolve(state.currentConfig.value), setSiteConfig: optionsOnly(async (config: PluginConfig): Promise => { //Save the config state.saveConfig(config); debugLog('Config settings saved!'); //Return the config return get(state.currentConfig) }), setDarkMode: popupAndOptionsOnly(async (darkMode: boolean) => { _darkMode.value = darkMode }), getDarkMode: async () => get(_darkMode), } }, foreground: exportForegroundApi([ 'getSiteConfig', 'setSiteConfig', 'setDarkMode', 'getDarkMode', 'waitForChange' ]) } }