aboutsummaryrefslogtreecommitdiff
path: root/extension/src/entries/options/components
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2023-11-19 14:50:46 -0500
committerLibravatar vnugent <public@vaughnnugent.com>2023-11-19 14:50:46 -0500
commitbc7b86a242673d7831f6105d000995d9f4d63e09 (patch)
tree8da5c92047e92174b80ff6f460f8c3148e1e00ca /extension/src/entries/options/components
parent0b609c17199e937518c42365b360288acfa872be (diff)
hasty not working update to get my workspace clean
Diffstat (limited to 'extension/src/entries/options/components')
-rw-r--r--extension/src/entries/options/components/Identities.vue56
-rw-r--r--extension/src/entries/options/components/Privacy.vue61
-rw-r--r--extension/src/entries/options/components/SiteSettings.vue118
3 files changed, 140 insertions, 95 deletions
diff --git a/extension/src/entries/options/components/Identities.vue b/extension/src/entries/options/components/Identities.vue
index d7fd75d..e3af74e 100644
--- a/extension/src/entries/options/components/Identities.vue
+++ b/extension/src/entries/options/components/Identities.vue
@@ -39,7 +39,7 @@
</Popover>
</div>
</div>
- <div v-for="key in allKeys" :key="key" class="mt-2 mb-3">
+ <div v-for="key in allKeys" :key="key.Id" class="mt-2 mb-3">
<div class="" :class="{'selected': isSelected(key)}" @click.self="selectKey(key)">
<div class="mb-8">
@@ -83,7 +83,7 @@
<script setup lang="ts">
import { isEqual, map } from 'lodash'
-import { ref, toRefs } from "vue";
+import { ref } from "vue";
import {
Popover,
PopoverButton,
@@ -91,30 +91,26 @@ import {
PopoverOverlay
} from '@headlessui/vue'
import { apiCall, configureNotifier } from '@vnuge/vnlib.browser';
-import { useManagment, useStatus } from '~/bg-api/options.ts';
+import { NostrPubKey } from '../../../features';
import { notify } from "@kyvg/vue3-notification";
-import { useClipboard } from '@vueuse/core';
-import { NostrIdentiy } from '~/bg-api/bg-api';
-import { NostrPubKey } from '../../background/types';
+import { get, useClipboard } from '@vueuse/core';
+import { useStore } from '../../store';
+import { storeToRefs } from 'pinia';
-const emit = defineEmits(['edit-key', 'update-all'])
-const props = defineProps<{
- allKeys:NostrIdentiy[]
-}>()
-
-const { allKeys } = toRefs(props)
+const emit = defineEmits(['edit-key'])
//Configre the notifier to use the toaster
configureNotifier({ notify, close: notify.close })
const downloadAnchor = ref<HTMLAnchorElement>()
-const { selectedKey } = useStatus()
-const { selectKey, createIdentity, deleteIdentity, getAllKeys } = useManagment()
+const store = useStore()
+const { selectedKey, allKeys } = storeToRefs(store)
const { copy } = useClipboard()
-const isSelected = (me : NostrIdentiy) => isEqual(me, selectedKey.value)
-const editKey = (key : NostrIdentiy) => emit('edit-key', key);
+const isSelected = (me : NostrPubKey) => isEqual(me, selectedKey.value)
+const editKey = (key : NostrPubKey) => emit('edit-key', key);
+const selectKey = (key: NostrPubKey) => store.selectKey(key)
const onCreate = async (e: Event, onClose : () => void) => {
@@ -123,35 +119,39 @@ const onCreate = async (e: Event, onClose : () => void) => {
//try to get existing key field
const ExistingKey = e.target['key']?.value as string
- //Create new identity
- await createIdentity({ UserName, ExistingKey })
- //Update keys
- emit('update-all');
+ await apiCall(async () => {
+ //Create new identity
+ await store.createIdentity({ UserName, ExistingKey })
+ })
+
onClose()
}
-const prettyPrintDate = (key : NostrIdentiy) => {
+const prettyPrintDate = (key : NostrPubKey) => {
const d = new Date(key.LastModified)
return `${d.toLocaleDateString()} ${d.toLocaleTimeString()}`
}
-const onDeleteKey = async (key : NostrIdentiy) => {
+const onDeleteKey = async (key : NostrPubKey) => {
if(!confirm(`Are you sure you want to delete ${key.UserName}?`)){
return;
}
- //Delete identity
- await deleteIdentity(key)
-
- //Update keys
- emit('update-all');
+ apiCall(async ({ toaster }) => {
+ //Delete identity
+ await store.deleteIdentity(key)
+ toaster.general.success({
+ 'title': 'Success',
+ 'text': `${key.UserName} has been deleted`
+ })
+ })
}
const onNip05Download = () => {
apiCall(async () => {
//Get all public keys from the server
- const keys = await getAllKeys() as NostrPubKey[]
+ const keys = get(allKeys)
const nip05 = {}
//Map the keys to the NIP-05 format
map(keys, k => nip05[k.UserName] = k.PublicKey)
diff --git a/extension/src/entries/options/components/Privacy.vue b/extension/src/entries/options/components/Privacy.vue
index 7d2ce4d..d54f679 100644
--- a/extension/src/entries/options/components/Privacy.vue
+++ b/extension/src/entries/options/components/Privacy.vue
@@ -1,9 +1,68 @@
<template>
<div class="flex flex-col w-full mt-4 sm:px-2">
-
+ <div class="flex flex-row gap-1">
+ <div class="text-2xl">
+ Tracking protection
+ </div>
+ <div class="mt-auto" :class="[isOriginProtectionOn ? 'text-primary-600' : 'text-red-500']">
+ {{ isOriginProtectionOn ? 'active' : 'inactive' }}
+ </div>
+ </div>
+ <div class="">
+ <div class="p-2">
+ <div class="my-1">
+ <form @submit.prevent="allowOrigin()">
+ <input class="w-full max-w-xs input primary" type="text" v-model="newOrigin" placeholder="Add new origin"/>
+ <button type="submit" class="ml-1 btn xs" >
+ <fa-icon icon="plus" />
+ </button>
+ </form>
+ </div>
+ <label class="font-semibold">Whitelist:</label>
+ <ul class="pl-1 list-disc list-inside">
+ <li v-for="origin in allowedOrigins" :key="origin" class="my-1 text-sm">
+ <span class="">
+ {{ origin }}
+ </span>
+ <span>
+ <button class="ml-1 text-xs text-red-500" @click="store.dissallowOrigin(origin)">
+ remove
+ </button>
+ </span>
+ </li>
+ </ul>
+ </div>
+ </div>
</div>
</template>
<script setup lang="ts">
+import { storeToRefs } from 'pinia';
+import { useStore } from '../../store';
+import { useFormToaster } from '@vnuge/vnlib.browser';
+import { ref } from 'vue';
+
+const store = useStore()
+const { isOriginProtectionOn, allowedOrigins } = storeToRefs(store)
+const newOrigin = ref('')
+const { error, info } = useFormToaster()
+
+const allowOrigin = async () =>{
+ try {
+ await store.allowOrigin(newOrigin.value)
+ }
+ catch (err: any) {
+ error({
+ title: 'Failed to allow origin',
+ text: err.message
+ })
+ return;
+ }
+ info({
+ title: 'Origin allowed',
+ text: `Origin ${newOrigin.value} has been allowed`
+ })
+ newOrigin.value = ''
+}
</script> \ No newline at end of file
diff --git a/extension/src/entries/options/components/SiteSettings.vue b/extension/src/entries/options/components/SiteSettings.vue
index 2b32a93..c0c2e93 100644
--- a/extension/src/entries/options/components/SiteSettings.vue
+++ b/extension/src/entries/options/components/SiteSettings.vue
@@ -7,23 +7,23 @@
Extension settings
</h3>
<div class="my-6">
- <fieldset :disabled="waiting">
+ <fieldset :disabled="waiting.value">
<div class="">
<div class="w-full">
<div class="flex flex-row w-full">
<Switch
- v-model="buffer.autoInject"
- :class="buffer.autoInject ? 'bg-black dark:bg-gray-50' : 'bg-gray-200 dark:bg-dark-600'"
+ v-model="originProtection"
+ :class="originProtection ? 'bg-black dark:bg-gray-50' : 'bg-gray-200 dark:bg-dark-600'"
class="relative inline-flex items-center h-5 rounded-full w-11"
>
- <span class="sr-only">NIP-07</span>
+ <span class="sr-only">Origin protection</span>
<span
- :class="buffer.autoInject ? 'translate-x-6' : 'translate-x-1'"
+ :class="originProtection ? 'translate-x-6' : 'translate-x-1'"
class="inline-block w-4 h-4 transition transform bg-white rounded-full dark:bg-dark-900"
/>
</Switch>
<div class="my-auto ml-2 text-sm dark:text-gray-200">
- Always on NIP-07
+ Tracking protection
</div>
</div>
</div>
@@ -69,27 +69,42 @@
</a>
</div>
</div>
- <fieldset :disabled="waiting || !editMode">
+ <fieldset>
<div class="pl-1 mt-2">
</div>
<div class="mt-2">
<label class="pl-1">BaseUrl</label>
- <input class="w-full input" v-model="v$.apiUrl.$model" :class="{'error': v$.apiUrl.$invalid }" />
+ <input
+ class="w-full input"
+ :class="{'error': v$.apiUrl.$invalid }"
+ v-model="v$.apiUrl.$model"
+ :readonly="!editMode"
+ />
<p class="pl-1 mt-1 text-xs text-gray-600 dark:text-gray-400">
* The http path to the vault server (must start with http:// or https://)
</p>
</div>
<div class="mt-2">
<label class="pl-1">Account endpoint</label>
- <input class="w-full input" v-model="v$.accountBasePath.$model" :class="{ 'error': v$.accountBasePath.$invalid }" />
+ <input
+ class="w-full input"
+ v-model="v$.accountBasePath.$model"
+ :class="{ 'error': v$.accountBasePath.$invalid }"
+ :readonly="!editMode"
+ />
<p class="pl-1 mt-1 text-xs text-gray-600 dark:text-gray-400">
* This is the path to the account server endpoint (must start with /)
</p>
</div>
<div class="mt-2">
<label class="pl-1">Nostr endpoint</label>
- <input class="w-full input" v-model="v$.nostrEndpoint.$model" :class="{ 'error': v$.nostrEndpoint.$invalid }" />
+ <input
+ class="w-full input"
+ v-model="v$.nostrEndpoint.$model"
+ :class="{ 'error': v$.nostrEndpoint.$invalid }"
+ :readonly="!editMode"
+ />
<p class="pl-1 mt-1 text-xs text-gray-600 dark:text-gray-400">
* This is the path to the Nostr plugin endpoint path (must start with /)
</p>
@@ -104,25 +119,31 @@
</template>
<script setup lang="ts">
-import { apiCall, useDataBuffer, useFormToaster, useVuelidateWrapper, useWait } from '@vnuge/vnlib.browser';
-import { computed, ref, watch } from 'vue';
-import { useManagment } from '~/bg-api/options.ts';
+import { apiCall, useDataBuffer, useVuelidateWrapper, useWait } from '@vnuge/vnlib.browser';
+import { computed, watch } from 'vue';
import { useToggle, watchDebounced } from '@vueuse/core';
import { maxLength, helpers, required } from '@vuelidate/validators'
-import { clone, isNil } from 'lodash';
-import{ Switch } from '@headlessui/vue'
+import { Switch } from '@headlessui/vue'
+import { useStore } from '../../store';
+import { storeToRefs } from 'pinia';
import useVuelidate from '@vuelidate/core'
const { waiting } = useWait();
-const { info } = useFormToaster();
-const { getSiteConfig, saveSiteConfig } = useManagment();
-
-const { apply, data, buffer, modified } = useDataBuffer({
- apiUrl: '',
- accountBasePath: '',
- nostrEndpoint:'',
- heartbeat:false,
- autoInject:true,
+const store = useStore()
+const { settings, isOriginProtectionOn } = storeToRefs(store)
+
+const { apply, data, buffer, modified, update } = useDataBuffer(settings.value, async sb =>{
+ const newConfig = await store.saveSiteConfig(sb.buffer)
+ apply(newConfig)
+ return newConfig;
+})
+
+//Watch for store settings changes and apply them
+watch(settings, v => apply(v.value))
+
+const originProtection = computed({
+ get: () => isOriginProtectionOn.value,
+ set: v => store.setOriginProtection(v)
})
const url = (val : string) => /^https?:\/\/[a-zA-Z0-9\.\:\/-]+$/.test(val);
@@ -145,15 +166,13 @@ const vRules = {
alphaNum: helpers.withMessage('Nostr path is not a valid endpoint path that begins with /', path)
},
heartbeat: {},
- darkMode:{}
}
//Configure validator and validate function
const v$ = useVuelidate(vRules, buffer)
-const { validate } = useVuelidateWrapper(v$);
+const { validate } = useVuelidateWrapper(v$ as any);
-const editMode = ref(false);
-const toggleEdit = useToggle(editMode);
+const [ editMode, toggleEdit ] = useToggle(false);
const autoInject = computed(() => buffer.autoInject)
const heartbeat = computed(() => buffer.heartbeat)
@@ -171,24 +190,12 @@ const onSave = async () => {
return;
}
- info({
- title: 'Reloading in 4 seconds',
- text: 'Your configuration will be saved and the extension will reload in 4 seconds'
- })
-
- await new Promise(r => setTimeout(r, 4000));
-
- publishConfig();
+ await update();
//disable dit
toggleEdit();
}
-const publishConfig = async () =>{
- const c = clone(buffer);
- await saveSiteConfig(c);
- await loadConfig();
-}
const testConnection = async () =>{
return await apiCall(async ({axios, toaster}) =>{
@@ -201,38 +208,17 @@ const testConnection = async () =>{
return true;
}
catch(e){
- if(isNil(e.response?.status)){
- toaster.form.error({
- title: 'Network error',
- text: `Please verify your vault server address`
- });
- }
-
toaster.form.error({
title: 'Warning',
- text: `Failed to connect to the vault server. Status code: ${e.response.status}`
+ text: `Failed to connect to the vault server. Status code: ${(e as any).response?.status}`
});
}
})
}
-const loadConfig = async () => {
- const config = await getSiteConfig();
- apply(config);
-}
-
-const init = async () => {
- await loadConfig();
-
- //Watch for changes to autoinject value and publish changes when it does
- watchDebounced(autoInject, publishConfig, { debounce: 500, immediate: false })
- watchDebounced(heartbeat, publishConfig, { debounce: 500, immediate: false })
-}
-
-//If edit mode is toggled off, reload config
-watch(editMode, v => v ? null : loadConfig());
-
-init();
+//Watch for changes to autoinject value and publish changes when it does
+watchDebounced(autoInject, update, { debounce: 500, immediate: false })
+watchDebounced(heartbeat, update, { debounce: 500, immediate: false })
</script>