Browse Source
* Add relay.nostr.scot Add relay.nostr.scot * Add rsslay.nostr.moe (#210) A custom fork of the rss-bridge relay of fiatjaf [piraces/rsslay](https://github.com/piraces/rsslay) Co-authored-by: Sandwich <299465+dskvr@users.noreply.github.com> * remove e.e. * kind3 editing, ssl, various improvements * working relay list editor * remove debugging * move buttons * show/hide button for logged in/out * bugfix * fix column issue * remove debugging * reduce wait time * disable edit button while relays are refreshing * add some gates * resets after save Co-authored-by: Paul Rollo <kingrollo@gmail.com> Co-authored-by: Raul Piraces Alastuey <raul.piraces@gmail.com> Co-authored-by: dskvr <dskvr@users.noreply.github.com>develop
Sandwich
2 years ago
committed by
GitHub
25 changed files with 698 additions and 204 deletions
@ -0,0 +1,191 @@ |
|||
<template> |
|||
<div class="inline" v-if="store.user.getPublicKey.length"> |
|||
<div class="inline text-left"> |
|||
|
|||
<span v-if="savedSuccess" class="inline-block mr-3"> |
|||
<svg class="h-4 w-4 inline-block" fill="none" stroke="#32CD32" stroke-width="1.5" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> |
|||
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path> |
|||
</svg> |
|||
Saved to <span>{{ savedSuccess }}</span> |
|||
</span> |
|||
|
|||
<button |
|||
:title="this.store.tasks.getActiveSlug === 'relays/check' ? 'disabled while relays are checking' : ''" |
|||
ref="btnRef" |
|||
type="button" |
|||
v-on:click="this.store.tasks.getActiveSlug === 'relays/check' ? false : toggleEditor()" |
|||
:class="{ |
|||
'cursor-not-allowed opacity-40': this.store.tasks.getActiveSlug === 'relays/check', |
|||
'cursor-pointer': this.store.tasks.getActiveSlug === 'user/relay/list' |
|||
}" |
|||
class="mr-3 inline-flex items-center justify-center rounded-md border border-transparent bg-white/20 px-4 py-2 text-m font-medium text-white shadow-sm hover:bg-white/40 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 sm:w-auto"> |
|||
<span v-if="this.store.layout.editorExpanded"> |
|||
Cancel |
|||
</span> |
|||
|
|||
<span v-if="!this.store.layout.editorExpanded"> |
|||
Edit Relay List |
|||
</span> |
|||
</button> |
|||
|
|||
<button |
|||
:title="!changed ? 'nothing to save' : ''" |
|||
ref="btnRef" |
|||
type="button" |
|||
v-on:click="changed ? persistChanges() : false" |
|||
v-if="this.store.layout.editorExpanded && store.tasks.getActiveSlug !== 'user/relay/list'" |
|||
:class="{ |
|||
'cursor-not-allowed opacity-40': !changed, |
|||
'cursor-pointer': changed |
|||
}" |
|||
class="mr-3 inline-flex items-center justify-center rounded-md border border-transparent bg-white/20 px-4 py-2 text-m font-medium text-white shadow-sm hover:bg-white/40 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 sm:w-auto"> |
|||
Save |
|||
</button> |
|||
|
|||
|
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
// import { createPopper } from "@popperjs/core"; |
|||
import { defineComponent, toRefs } from 'vue' |
|||
import { setupStore } from '@/store/' |
|||
import safeStringify from 'fast-safe-stringify' |
|||
import { getEventHash, validateEvent, verifySignature } from 'nostr-tools' |
|||
import RelaysLib from '@/shared/relays-lib' |
|||
import { RelayPool } from 'nostr' |
|||
import objHash from 'object-hash' |
|||
|
|||
export default defineComponent({ |
|||
name: "NostrSyncPopoverNag", |
|||
setup(props){ |
|||
const {editorProp: editor} = toRefs(props) |
|||
return { |
|||
store : setupStore(), |
|||
editor: editor |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
changed: false, |
|||
hashCache: null, |
|||
hashOG: null, |
|||
savedTo: [], |
|||
savedSuccess: null, |
|||
interval: null, |
|||
// editor: false, |
|||
// popoverShow: false |
|||
} |
|||
}, |
|||
mounted(){ |
|||
this.hashOG = objHash(structuredClone(this.store.user.getKind3)) |
|||
this.hashCache = structuredClone(this.hashOG) |
|||
this.store.layout.editorOff() |
|||
this.interval = setInterval( () => { |
|||
if(this.savedTo.length) |
|||
this.savedSuccess = this.savedTo.shift() |
|||
else |
|||
this.savedSuccess = null |
|||
|
|||
const hashCurrent = objHash(this.store.user.getKind3), |
|||
hashCache = this.hashCache, |
|||
hashOG = this.hashOG |
|||
|
|||
if(hashCache === hashCurrent) |
|||
return |
|||
|
|||
if(hashOG === hashCurrent ) |
|||
return this.changed = false |
|||
|
|||
console.log('input cache did not match', hashCache) |
|||
|
|||
console.log( |
|||
'changed?', |
|||
this.changed, |
|||
'ok..', |
|||
hashCache, |
|||
objHash(this.store.user.getKind3), |
|||
hashCache == objHash(this.store.user.getKind3) |
|||
) |
|||
|
|||
this.hashCache = objHash(structuredClone(this.store.user.getKind3)) |
|||
this.changed = true |
|||
|
|||
}, 500) |
|||
}, |
|||
unmounted(){ |
|||
clearInterval(this.interval) |
|||
this.store.layout.editorOff() |
|||
}, |
|||
methods: Object.assign(RelaysLib, { |
|||
toggleEditor: async function(){ |
|||
this.store.layout.toggleEditor() |
|||
if(this.store.layout.editorExpanded) |
|||
this.queueJob( |
|||
'user/relay/list', |
|||
async () => { |
|||
await this.store.user.setKind3() |
|||
.then( () => { |
|||
Object.keys(this.store.user.kind3).forEach( key => { |
|||
this.store.relays.setFavorite(key) |
|||
}) |
|||
this.store.tasks.completeJob() |
|||
}) |
|||
.catch( err => { |
|||
console.error('error!', err) |
|||
this.store.tasks.completeJob() |
|||
}) |
|||
}, |
|||
true |
|||
) |
|||
}, |
|||
persistChanges: async function(){ |
|||
const event = { |
|||
created_at: Math.floor(Date.now()/1000), |
|||
kind: 3, |
|||
content: safeStringify(this.store.user.kind3), |
|||
tags: [...this.store.user.kind3Event.tags], |
|||
pubkey: this.store.user.getPublicKey, |
|||
} |
|||
event.id = getEventHash(event) |
|||
|
|||
console.log('kind3 event', event) |
|||
|
|||
console.log(window.nostr, typeof window.nostr.signEvent) |
|||
|
|||
const signedEvent = await window.nostr.signEvent(structuredClone(event)) |
|||
|
|||
let ok = validateEvent(signedEvent) |
|||
let veryOk = verifySignature(signedEvent) |
|||
|
|||
if(!ok || !veryOk) |
|||
return |
|||
|
|||
console.log('valid event?', ok, veryOk) |
|||
|
|||
const pool = new RelayPool( Object.keys(this.store.user.kind3) ) |
|||
|
|||
pool.on('open', relay=>{ |
|||
relay.send(['EVENT', signedEvent]) |
|||
}) |
|||
pool.on('ok', relay => { |
|||
this.savedTo.push(relay.url) |
|||
}) |
|||
|
|||
this.hashOG = objHash(JSON.parse(event.content)) |
|||
this.hashCache = this.hashOG |
|||
this.changed = false |
|||
}, |
|||
togglePopover: function(){ |
|||
// if(this.popoverShow){ |
|||
// this.popoverShow = false; |
|||
// } else { |
|||
// this.popoverShow = true; |
|||
// createPopper(this.$refs.btnRef, this.$refs.popoverRef, { |
|||
// placement: "left" |
|||
// }); |
|||
// } |
|||
}, |
|||
}) |
|||
}) |
|||
</script> |
@ -1,53 +0,0 @@ |
|||
<template> |
|||
<div class="inline"> |
|||
<div class="inline text-left"> |
|||
<button |
|||
ref="btnRef" |
|||
type="button" |
|||
v-on:click="togglePopover()" |
|||
class="items-start cursor-not-allowed inline-flex items-center rounded border border-gray-300 bg-white px-2.5 py-1.5 text-xs font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"> |
|||
Sync Favs with Nostr |
|||
</button> |
|||
<div ref="popoverRef" |
|||
v-bind:class="{'hidden': !popoverShow, 'block': popoverShow}" |
|||
class="bg-pink-600 border-0 mr-3 z-50 font-normal leading-normal text-sm max-w-xs text-left no-underline break-words rounded-lg |
|||
"> |
|||
<div> |
|||
<div class="bg-pink-600 text-white opacity-75 font-semibold p-3 mb-0 border-b border-solid border-slate-100 uppercase rounded-t-lg"> |
|||
Coming soon |
|||
</div> |
|||
<div class="text-white p-3"> |
|||
This feature depends on the finalization of |
|||
<a href="https://github.com/nostr-protocol/nips/pull/32" target="_blank">NIP-23 [link]</a>, |
|||
if you actively develop a nostr client, please provide input on the NIP to help make the |
|||
implementation of user relay lists easier for everyone. |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
import { createPopper } from "@popperjs/core"; |
|||
|
|||
export default { |
|||
name: "NostrSyncPopoverNag", |
|||
data() { |
|||
return { |
|||
popoverShow: false |
|||
} |
|||
}, |
|||
methods: { |
|||
togglePopover: function(){ |
|||
if(this.popoverShow){ |
|||
this.popoverShow = false; |
|||
} else { |
|||
this.popoverShow = true; |
|||
createPopper(this.$refs.btnRef, this.$refs.popoverRef, { |
|||
placement: "left" |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
@ -0,0 +1,125 @@ |
|||
<template> |
|||
<span |
|||
v-if="this.store.tasks.getActiveSlug === taskSlug && isLoggedIn" |
|||
class="text-white lg:text-sm mr-10 ml-2 mt-1.5 text-xs"> |
|||
<span>Retrieving Relays List...</span> |
|||
</span> |
|||
</template> |
|||
|
|||
<style scoped> |
|||
|
|||
</style> |
|||
|
|||
<script> |
|||
import crypto from 'crypto' |
|||
// import { RelayPool } from 'nostr' |
|||
|
|||
import { defineComponent, toRefs } from 'vue' |
|||
|
|||
import { setupStore } from '@/store' |
|||
|
|||
import SharedMethods from '@/shared/relays-lib.js' |
|||
import UserMethods from '@/shared/user-lib.js' |
|||
import SharedComputed from '@/shared/computed.js' |
|||
|
|||
import { relays } from '../../../../relays.yaml' |
|||
|
|||
const localMethods = new Object() |
|||
|
|||
localMethods.invalidate = function(force){ |
|||
if( !this.isExpired(this.taskSlug) && !force ) |
|||
return |
|||
|
|||
if( !this.isLoggedIn ) |
|||
return |
|||
|
|||
if( !this.store.prefs.useKind3 ) |
|||
return |
|||
|
|||
console.log('wtf?', this.taskSlug, !this.isExpired(this.taskSlug) && !force) |
|||
|
|||
this.queueKind3(this.taskSlug) |
|||
} |
|||
|
|||
localMethods.timeUntilRefresh = function(){ |
|||
return this.timeSince(Date.now()-(this.store.tasks.getLastUpdate(this.taskSlug)+this.store.prefs.duration-Date.now())) |
|||
} |
|||
|
|||
localMethods.timeSinceRefresh = function(){ |
|||
return this.timeSince(this.store.tasks.getLastUpdate(this.taskSlug)) || Date.now() |
|||
} |
|||
|
|||
localMethods.hash = function(relay){ |
|||
return crypto.createHash('md5').update(relay).digest('hex'); |
|||
} |
|||
|
|||
export default defineComponent({ |
|||
name: 'TemplateTask', |
|||
components: {}, |
|||
data() { |
|||
return { |
|||
taskSlug: 'user/relay/list', |
|||
kind3Remote: new Object(), |
|||
kind3Local: {} |
|||
} |
|||
}, |
|||
setup(props){ |
|||
const {resultsProp: results} = toRefs(props) |
|||
const {forceProp: force} = toRefs(props) |
|||
return { |
|||
store : setupStore(), |
|||
results: results, |
|||
force: force |
|||
} |
|||
}, |
|||
created(){ |
|||
clearInterval(this.interval) |
|||
}, |
|||
unmounted(){ |
|||
clearInterval(this.interval) |
|||
}, |
|||
beforeMount(){ |
|||
this.lastUpdate = this.store.tasks.getLastUpdate(this.taskSlug) |
|||
this.untilNext = this.timeUntilRefresh() |
|||
this.sinceLast = this.timeSinceRefresh() |
|||
|
|||
this.relays = Array.from(new Set(relays)) |
|||
}, |
|||
mounted(){ |
|||
console.log('task', this.taskSlug, 'is processing:', this.store.tasks.isProcessing(this.taskSlug)) |
|||
if(this.store.tasks.isProcessing(this.taskSlug)) |
|||
this.invalidate(true) |
|||
else |
|||
this.invalidate(this.force) |
|||
}, |
|||
updated(){}, |
|||
computed: Object.assign(SharedComputed, { |
|||
getDynamicTimeout: function(){ |
|||
return this.averageLatency*this.relays.length |
|||
}, |
|||
}), |
|||
methods: Object.assign(localMethods, UserMethods, SharedMethods), |
|||
props: { |
|||
resultsProp: { |
|||
type: Object, |
|||
default(){ |
|||
return {} |
|||
} |
|||
}, |
|||
forceProp: { |
|||
type: Boolean, |
|||
default(){ |
|||
return false |
|||
} |
|||
}, |
|||
}, |
|||
}) |
|||
</script> |
|||
|
|||
<style scoped> |
|||
#refresh { font-size: 12pt; color:#666; margin-bottom:15px } |
|||
#refresh button { cursor: pointer; border-radius: 3px; border: 1px solid #a0a0a0; color:#333 } |
|||
#refresh button:hover {color:#000;} |
|||
#refresh button[disabled] {color:#999 !important; border-color:#e0e0e0} |
|||
</style> |
|||
|
Loading…
Reference in new issue