mirror of
https://github.com/believethehype/nostrdvm.git
synced 2025-11-18 12:08:00 +01:00
restructure test/gui to ui/
This commit is contained in:
@@ -1,29 +0,0 @@
|
||||
# vue
|
||||
|
||||
This template should help get you started developing with Vue 3 in Vite.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
||||
|
||||
## Customize configuration
|
||||
|
||||
See [Vite Configuration Reference](https://vitejs.dev/config/).
|
||||
|
||||
## Project Setup
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compile and Hot-Reload for Development
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Compile and Minify for Production
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
@@ -1,13 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Nooooooooogle</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
{
|
||||
"name": "vue",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@rust-nostr/nostr-sdk": "^0.9.0",
|
||||
"bootstrap": "^5.3.2",
|
||||
"daisyui": "^4.6.0",
|
||||
"mini-toastr": "^0.8.1",
|
||||
"vue": "^3.4.15",
|
||||
"vue-notifications": "^1.0.2",
|
||||
"vue3-easy-data-table": "^1.5.47",
|
||||
"vuex": "^4.1.0",
|
||||
"webln": "^0.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^4.5.2",
|
||||
"autoprefixer": "^10.4.17",
|
||||
"postcss": "^8.4.33",
|
||||
"sass": "^1.70.0",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"vite": "^5.0.10",
|
||||
"vue-router": "^4.2.5"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-linux-x64-gnu": "4.6.1"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 263 KiB |
@@ -1,45 +0,0 @@
|
||||
<script setup>
|
||||
import Home from './components/Home.vue'
|
||||
import ThreeColumnLayout from "./layouts/ThreeColumnLayout.vue";
|
||||
import Nip07 from "@/components/Nip07.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
|
||||
<main>
|
||||
<ThreeColumnLayout>
|
||||
<template #aside>
|
||||
|
||||
</template>
|
||||
</ThreeColumnLayout>
|
||||
|
||||
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
header {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@media (min-width: 768px) {
|
||||
header {
|
||||
display: flex;
|
||||
place-items: center;
|
||||
|
||||
}
|
||||
|
||||
.logo {
|
||||
margin: 0 2rem 0 0;
|
||||
}
|
||||
|
||||
header .wrapper {
|
||||
display: flex;
|
||||
place-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,38 +0,0 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #242424;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
}
|
||||
a,
|
||||
.green {
|
||||
text-decoration: none;
|
||||
color: hsla(160, 100%, 37%, 1);
|
||||
transition: 0.4s;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.purple {
|
||||
@apply text-nostr;
|
||||
text-decoration: none;
|
||||
transition: 0.4s;
|
||||
padding: 3px;
|
||||
}
|
||||
.menu {
|
||||
color: white;
|
||||
@apply btn bg-transparent border-transparent tracking-wide;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/* color palette from <https://github.com/vuejs/theme> */
|
||||
:root {
|
||||
--vt-c-white: #ffffff;
|
||||
--vt-c-white-soft: #f8f8f8;
|
||||
--vt-c-white-mute: #f2f2f2;
|
||||
|
||||
--vt-c-black: #181818;
|
||||
--vt-c-black-soft: #222222;
|
||||
--vt-c-black-mute: #282828;
|
||||
|
||||
--vt-c-indigo: #2c3e50;
|
||||
|
||||
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
|
||||
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
|
||||
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
|
||||
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
|
||||
|
||||
--vt-c-text-light-1: var(--vt-c-indigo);
|
||||
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
|
||||
--vt-c-text-dark-1: var(--vt-c-white);
|
||||
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
|
||||
}
|
||||
|
||||
/* semantic color variables for this project */
|
||||
:root {
|
||||
--color-background: var(--vt-c-white);
|
||||
--color-background-soft: var(--vt-c-white-soft);
|
||||
--color-background-mute: var(--vt-c-white-mute);
|
||||
|
||||
--color-border: var(--vt-c-divider-light-2);
|
||||
--color-border-hover: var(--vt-c-divider-light-1);
|
||||
|
||||
--color-heading: var(--vt-c-text-light-1);
|
||||
--color-text: var(--vt-c-text-light-1);
|
||||
|
||||
--section-gap: 160px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--color-background: var(--vt-c-black);
|
||||
--color-background-soft: var(--vt-c-black-soft);
|
||||
--color-background-mute: var(--vt-c-black-mute);
|
||||
|
||||
--color-border: var(--vt-c-divider-dark-2);
|
||||
--color-border-hover: var(--vt-c-divider-dark-1);
|
||||
|
||||
--color-heading: var(--vt-c-text-dark-1);
|
||||
--color-text: var(--vt-c-text-dark-2);
|
||||
}
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
color: var(--color-text);
|
||||
background: var(--color-background);
|
||||
transition:
|
||||
color 0.5s,
|
||||
background-color 0.5s;
|
||||
line-height: 1.6;
|
||||
font-family:
|
||||
Inter,
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
'Segoe UI',
|
||||
Roboto,
|
||||
Oxygen,
|
||||
Ubuntu,
|
||||
Cantarell,
|
||||
'Fira Sans',
|
||||
'Droid Sans',
|
||||
'Helvetica Neue',
|
||||
sans-serif;
|
||||
font-size: 15px;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 211 B |
Binary file not shown.
|
Before Width: | Height: | Size: 545 B |
Binary file not shown.
|
Before Width: | Height: | Size: 819 KiB |
@@ -1,35 +0,0 @@
|
||||
@import './base.css';
|
||||
|
||||
#app {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
a,
|
||||
.green {
|
||||
text-decoration: none;
|
||||
color: hsla(160, 100%, 37%, 1);
|
||||
transition: 0.4s;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
a:hover {
|
||||
background-color: hsla(160, 100%, 37%, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
body {
|
||||
display: flex;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
#app {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
padding: 0 2rem;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<svg width="225" height="224" viewBox="0 0 225 224" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="224.047" height="224" rx="64" fill="url(#paint0_radial_855_5166)"/>
|
||||
<path d="M162.441 135.941V88.0593C170.359 85.1674 176 77.5348 176 68.6696C176 57.2919 166.708 48 155.33 48C143.953 48 134.661 57.2444 134.661 68.6696C134.661 77.5822 140.302 85.1674 148.219 88.0593V135.941C147.698 136.13 147.176 136.367 146.655 136.604L87.3956 77.3452C88.6282 74.6904 89.2919 71.7511 89.2919 68.6696C89.2919 57.2444 80.0474 48 68.6696 48C57.2919 48 48 57.2444 48 68.6696C48 77.5822 53.6415 85.1674 61.5585 88.0593V135.941C53.6415 138.833 48 146.465 48 155.33C48 166.708 57.2444 176 68.6696 176C80.0948 176 89.3393 166.708 89.3393 155.33C89.3393 146.418 83.6978 138.833 75.7807 135.941V88.0593C76.3022 87.8696 76.8237 87.6326 77.3452 87.3956L136.604 146.655C135.372 149.31 134.708 152.249 134.708 155.33C134.708 166.708 143.953 176 155.378 176C166.803 176 176.047 166.708 176.047 155.33C176.047 146.418 170.406 138.833 162.489 135.941H162.441Z" fill="white"/>
|
||||
<defs>
|
||||
<radialGradient id="paint0_radial_855_5166" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(224.047 224) rotate(-135.006) scale(316.817 473.813)">
|
||||
<stop stop-color="#6951FA"/>
|
||||
<stop offset="1" stop-color="#9151FA"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 7.8 KiB |
@@ -1,154 +0,0 @@
|
||||
<template>
|
||||
<div class="max-w-5xl mx-auto flex flex-col gap-8">
|
||||
<div class="flex flex-row gap-6 items-center">
|
||||
<Logo />
|
||||
<div class="flex flex-col gap-2">
|
||||
<h1 class="text-7xl font-black tracking-wide">About</h1>
|
||||
<!-- <div class="text-lg text-nostr">
|
||||
There are many things that make using and working with DVMs a bit of a magical experience.
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<br><br>
|
||||
<!-- <div class="grid grid-cols-2 gap-6">
|
||||
<div class="card card-compact rounded-box bg-black">
|
||||
<div class="card-body !text-base">
|
||||
<div class="card-title text-base-100-content font-bold">
|
||||
Global improvements
|
||||
</div>
|
||||
|
||||
<p>Once a Nostr app supports DVMs that means that they get immediate access to all features,
|
||||
algorithms, and crazy inventions all DVMs support.</p>
|
||||
|
||||
<p>
|
||||
Don't like your client's default <em>Trending</em> algorithm? Pick from hundreds of different
|
||||
algorithms. Your Highlighter client doesn't work well when trying to read an obscure PDF?
|
||||
Use a DVM that has better support for it.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You say the spam filtering in your client is too aggressive? or not aggressive enough? Just choose
|
||||
from a different spam-filtering DVM!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card card-compact rounded-box bg-black">
|
||||
<div class="card-body !text-base">
|
||||
<div class="card-title text-base-100-content font-bold">
|
||||
Long-tail
|
||||
</div>
|
||||
|
||||
<p>Because discoverability of these algorithms is solved by the very use of Nostr, we can easily imagine
|
||||
a future where there are thousands of very specific, very niche and abundantly weird DVMs providing all
|
||||
kinds of obscure functionalities.</p>
|
||||
|
||||
<p>
|
||||
Even if a DVM only had a handful of users, it would still be worth it for its users and for the DVM.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card card-compact rounded-box bg-black">
|
||||
<div class="card-body !text-base">
|
||||
<div class="card-title text-base-100-content font-bold">
|
||||
Reusable results
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Every time a Nostr client autotranslates a note, it pings a specific API endpoint to get the
|
||||
result translated.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Over, and over. The same text being translated by each user.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Since Data Vending Machine results are public by default, once a note has been translated,
|
||||
all clients can choose to reuse the same translation.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>-->
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div className="chat chat-start">
|
||||
<div className="chat-image avatar">
|
||||
<div className="w-10 rounded-full">
|
||||
<img alt="Tailwind CSS chat bubble component" src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="chat-bubble">NIP 90 Data Vending Machines can perform multiple tasks leveraging the Nostr Protocol.</div>
|
||||
</div>
|
||||
<div className="chat chat-start">
|
||||
<div className="chat-image avatar">
|
||||
<div className="w-10 rounded-full">
|
||||
<img alt="Tailwind CSS chat bubble component" src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="chat-bubble">This Demo Application uses a Kind 5302 event to ask DVMs to search for content on the Nostr.</div>
|
||||
</div>
|
||||
|
||||
<div className="chat chat-start">
|
||||
<div className="chat-image avatar">
|
||||
<div className="w-10 rounded-full">
|
||||
<img alt="Tailwind CSS chat bubble component" src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="chat-bubble">You can add from:npub.... to your search to filter content for a specific user.</div>
|
||||
</div>
|
||||
<div className="chat chat-start">
|
||||
<div className="chat-image avatar">
|
||||
<div className="w-10 rounded-full">
|
||||
<img alt="Tailwind CSS chat bubble component" src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="chat-bubble">When you're logged in you can add from:me to search content from yourself</div>
|
||||
</div>
|
||||
<div className="chat chat-start">
|
||||
<div className="chat-image avatar">
|
||||
<div className="w-10 rounded-full">
|
||||
<img alt="Tailwind CSS chat bubble component" src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="chat-bubble">This page then combines all the results from available search dvms.</div>
|
||||
</div>
|
||||
<div className="chat chat-start">
|
||||
<div className="chat-image avatar">
|
||||
<div className="w-10 rounded-full">
|
||||
<img alt="Tailwind CSS chat bubble component" src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="chat-bubble">This way we will be able to decentralize the most centralized thing on the internet. Search.</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'dailyUIdemo',
|
||||
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
h3 {
|
||||
margin: 40px 0 0;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
||||
@@ -1,132 +0,0 @@
|
||||
<script>
|
||||
import { requestProvider } from "webln";
|
||||
import miniToastr from "mini-toastr";
|
||||
import VueNotifications from "vue-notifications";
|
||||
import {PublicKey, ZapDetails, ZapEntity, ZapType} from "@rust-nostr/nostr-sdk";
|
||||
import store from "@/store.js";
|
||||
import {data} from "autoprefixer";
|
||||
|
||||
|
||||
export default {
|
||||
|
||||
data() {
|
||||
return {
|
||||
dvmlnaddress: "hype@bitcoinfixesthis.org",
|
||||
dvmpaymentaddr: "",
|
||||
dvminvoice: "",
|
||||
nostrsdklnaddress: "yuki@getalby.com",
|
||||
nostrsdkpaymentaddr: "",
|
||||
nostrsdkinvoice: "",
|
||||
amount: 1000
|
||||
}},
|
||||
|
||||
methods: {
|
||||
async handleZap(){
|
||||
try {
|
||||
let pk = PublicKey.fromBech32("npub1nxa4tywfz9nqp7z9zp7nr7d4nchhclsf58lcqt5y782rmf2hefjquaa6q8");
|
||||
let entity = ZapEntity.publicKey(pk);
|
||||
let details = new ZapDetails(ZapType.Private).message("Zap for Rust Nostr!");
|
||||
await store.state.client.zap(entity, 1000, details);
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
},
|
||||
|
||||
async copyinvoice(invoice){
|
||||
await navigator.clipboard.writeText(invoice)
|
||||
window.open("lightning:" + invoice,"_blank")
|
||||
miniToastr.showMessage("", "Copied Invoice to clipboard", VueNotifications.types.info)
|
||||
},
|
||||
|
||||
async zap(lnaddress, amount) {
|
||||
let webln;
|
||||
let invoice = await this.createBolt11Lud16(lnaddress, amount)
|
||||
if (lnaddress === this.nostrsdklnaddress){
|
||||
this.nostrsdkpaymentaddr = `https://chart.googleapis.com/chart?cht=qr&chl=${invoice}&chs=250x250&chld=M|0`;
|
||||
this.nostrsdkinvoice = invoice
|
||||
}
|
||||
else{
|
||||
this.dvmpaymentaddr = `https://chart.googleapis.com/chart?cht=qr&chl=${invoice}&chs=250x250&chld=M|0`;
|
||||
this.dvminvoice = invoice
|
||||
}
|
||||
|
||||
try {
|
||||
webln = await requestProvider();
|
||||
} catch (err) {
|
||||
await this.copyinvoice(invoice)
|
||||
}
|
||||
|
||||
if (webln) {
|
||||
console.log(invoice)
|
||||
let response = await webln.sendPayment(invoice)
|
||||
console.log(response)
|
||||
}
|
||||
},
|
||||
|
||||
async createBolt11Lud16(lud16, amount) {
|
||||
let url;
|
||||
if (lud16.includes('@')) { // LNaddress
|
||||
const parts = lud16.split('@');
|
||||
url = `https://${parts[1]}/.well-known/lnurlp/${parts[0]}`;
|
||||
} else { // No lud16 set or format invalid
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
console.log(url);
|
||||
const response = await fetch(url);
|
||||
const ob = await response.json();
|
||||
const callback = ob.callback;
|
||||
const amountInSats = parseInt(amount) * 1000;
|
||||
const callbackResponse = await fetch(`${callback}?amount=${amountInSats}`);
|
||||
const obCallback = await callbackResponse.json();
|
||||
return obCallback.pr;
|
||||
}
|
||||
catch (e) {
|
||||
console.log(`LUD16: ${e}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div className="dropdown dropdown-top">
|
||||
<div tabIndex={0} role="button" class="v-Button"><svg class="relative w-5 h-5 mr-2 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M13 10V3L4 14h7v7l9-11h-7z"></path></svg>Donate</div>
|
||||
<div tabIndex={0} className="dropdown-content z-[1] -start-20 card card-compact w-64 p-2 shadow bg-primary text-primary-content">
|
||||
<div className="card-body">
|
||||
<div>
|
||||
<p>Sats:</p><input class="c-Input" v-model="amount" placeholder="1000">
|
||||
</div>
|
||||
|
||||
<h3 className="card-title">Donate to Noogle</h3>
|
||||
<button class="v-Button2" @click="zap(this.dvmlnaddress, amount)"><svg class="relative w-5 h-5 mr-2 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M13 10V3L4 14h7v7l9-11h-7z"></path></svg>Donate</button>
|
||||
<img v-if="this.dvmpaymentaddr" alt="Invoice" width="250" :src=this.dvmpaymentaddr @click="this.copyinvoice(this.dvminvoice)" />
|
||||
|
||||
<h3 className="card-title">Donate to NostrSDK</h3>
|
||||
<button class="v-Button2" @click="zap(this.nostrsdklnaddress, amount)"><svg class="relative w-5 h-5 mr-2 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M13 10V3L4 14h7v7l9-11h-7z"></path></svg>Donate</button>
|
||||
<img v-if="this.nostrsdkpaymentaddr" alt="Invoice" width="250" :src=this.nostrsdkpaymentaddr @click="this.copyinvoice(this.nostrsdkinvoice)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.v-Button {
|
||||
@apply tracking-wide bg-black hover:bg-amber-400 focus:ring-white mb-2 inline-flex flex-none items-center rounded-lg border border-transparent px-3 py-1.5 text-sm leading-4 text-white transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-white dark:focus:ring-offset-gray-900;
|
||||
height: 24px;
|
||||
}
|
||||
.v-Button2 {
|
||||
@apply tracking-wide bg-black hover:bg-amber-400 focus:ring-white mb-2 inline-flex flex-none items-center rounded-lg border border-transparent px-3 py-1.5 text-sm leading-4 text-white transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-white dark:focus:ring-offset-gray-900;
|
||||
}
|
||||
|
||||
.c-Input {
|
||||
@apply bg-black hover:bg-gray-900 focus:ring-white mb-2 inline-flex flex-none items-center rounded-lg border border-transparent px-3 py-1.5 text-sm leading-4 text-white transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-white dark:focus:ring-offset-gray-900;
|
||||
color: white;
|
||||
background: black;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,29 +0,0 @@
|
||||
<script>
|
||||
import Search from "@/components/Search.vue";
|
||||
import ResultsTable from "@/components/SearchResultTable.vue";
|
||||
import Nip07 from "@/components/Nip07.vue";
|
||||
import Donate from "@/components/Donate.vue";
|
||||
|
||||
export default {
|
||||
name: "Home",
|
||||
components: {Donate, Nip07, ResultsTable, Search}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="center">
|
||||
<br>
|
||||
<Search/>
|
||||
<br>
|
||||
<ResultsTable/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,28 +0,0 @@
|
||||
<script>
|
||||
import ImageGeneration from "@/components/ImageGeneration.vue";
|
||||
import ResultsTable from "@/components/ImageResultTable.vue";
|
||||
import Nip07 from "@/components/Nip07.vue";
|
||||
import Donate from "@/components/Donate.vue";
|
||||
|
||||
export default {
|
||||
name: "Home",
|
||||
components: {Donate, Nip07, ResultsTable, ImageGeneration}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="center">
|
||||
<br>
|
||||
<ImageGeneration/>
|
||||
<br>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,394 +0,0 @@
|
||||
<script setup>
|
||||
|
||||
|
||||
|
||||
|
||||
import {
|
||||
Client,
|
||||
Filter,
|
||||
Timestamp,
|
||||
Event,
|
||||
Metadata,
|
||||
PublicKey,
|
||||
EventBuilder,
|
||||
Tag,
|
||||
EventId,
|
||||
Nip19Event, Alphabet
|
||||
} from "@rust-nostr/nostr-sdk";
|
||||
import store from '../store';
|
||||
import miniToastr from "mini-toastr";
|
||||
import VueNotifications from "vue-notifications";
|
||||
import searchdvms from './data/searchdvms.json'
|
||||
import {computed, watch} from "vue";
|
||||
import countries from "@/components/data/countries.json";
|
||||
import deadnip89s from "@/components/data/deadnip89s.json";
|
||||
import {data} from "autoprefixer";
|
||||
import {requestProvider} from "webln";
|
||||
|
||||
let dvms =[]
|
||||
let searching = false
|
||||
|
||||
let listener = false
|
||||
|
||||
|
||||
|
||||
|
||||
async function generate_image(message) {
|
||||
|
||||
try {
|
||||
if (message === undefined){
|
||||
message = "A purple Ostrich"
|
||||
}
|
||||
|
||||
if(store.state.pubkey === undefined){
|
||||
miniToastr.showMessage("Please login first", "No pubkey set", VueNotifications.types.warn)
|
||||
return
|
||||
}
|
||||
|
||||
dvms = []
|
||||
store.commit('set_imagedvm_results', dvms)
|
||||
let client = store.state.client
|
||||
let tags = []
|
||||
console.log(message)
|
||||
tags.push(Tag.parse(["i", message, "text"]))
|
||||
|
||||
let evt = new EventBuilder(5100, "NIP 90 Image Generation request", tags)
|
||||
let res = await client.sendEventBuilder(evt)
|
||||
store.commit('set_current_request_id_image', res.toHex())
|
||||
console.log("IMAGE EVENT SENT: " + res.toHex())
|
||||
|
||||
//miniToastr.showMessage("Sent Request to DVMs", "Awaiting results", VueNotifications.types.warn)
|
||||
searching = true
|
||||
if (!store.state.imagehasEventListener){
|
||||
listen()
|
||||
store.commit('set_imagehasEventListener', true)
|
||||
}
|
||||
else{
|
||||
console.log("Already has event listener")
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function listen() {
|
||||
listener = true
|
||||
|
||||
let client = store.state.client
|
||||
let pubkey = store.state.pubkey
|
||||
|
||||
const filter = new Filter().kinds([7000, 6100]).pubkey(pubkey).since(Timestamp.now());
|
||||
await client.subscribe([filter]);
|
||||
|
||||
const handle = {
|
||||
// Handle event
|
||||
handleEvent: async (relayUrl, event) => {
|
||||
if (store.state.imagehasEventListener === false){
|
||||
return true
|
||||
}
|
||||
//const dvmname = getNamefromId(event.author.toHex())
|
||||
console.log("Received new event from", relayUrl);
|
||||
let resonsetorequest = false
|
||||
for (let tag in event.tags) {
|
||||
if (event.tags[tag].asVec()[0] === "e") {
|
||||
console.log("IMAGE ETAG: " + event.tags[tag].asVec()[1])
|
||||
console.log("IMAGE LISTEN TO : " + store.state.requestidImage)
|
||||
if (event.tags[tag].asVec()[1] === store.state.requestidImage) {
|
||||
resonsetorequest = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (resonsetorequest === true) {
|
||||
|
||||
|
||||
|
||||
if (event.kind === 7000) {
|
||||
|
||||
|
||||
|
||||
try {
|
||||
console.log("7000: ", event.content);
|
||||
console.log("DVM: " + event.author.toHex())
|
||||
searching = false
|
||||
//miniToastr.showMessage("DVM: " + dvmname, event.content, VueNotifications.types.info)
|
||||
|
||||
let status = "unknown"
|
||||
let jsonentry = {
|
||||
id: event.author.toHex(),
|
||||
kind: "",
|
||||
status: status,
|
||||
result: "",
|
||||
name: event.author.toBech32(),
|
||||
about: "",
|
||||
image: "",
|
||||
amount: 0,
|
||||
bolt11: ""
|
||||
}
|
||||
|
||||
for (const tag in event.tags) {
|
||||
if (event.tags[tag].asVec()[0] === "status") {
|
||||
status = event.tags[tag].asVec()[1]
|
||||
}
|
||||
|
||||
if (event.tags[tag].asVec()[0] === "amount") {
|
||||
jsonentry.amount = event.tags[tag].asVec()[1]
|
||||
if (event.tags[tag].asVec().length > 2) {
|
||||
jsonentry.bolt11 = event.tags[tag].asVec()[2]
|
||||
}
|
||||
// TODO else request invoice
|
||||
}
|
||||
}
|
||||
|
||||
//let dvm = store.state.nip89dvms.find(x => JSON.parse(x.event).pubkey === event.author.toHex())
|
||||
for (const el of store.state.nip89dvms) {
|
||||
if (JSON.parse(el.event).pubkey === event.author.toHex().toString()) {
|
||||
jsonentry.name = el.name
|
||||
jsonentry.about = el.about
|
||||
jsonentry.image = el.image
|
||||
|
||||
console.log(jsonentry)
|
||||
|
||||
}
|
||||
}
|
||||
if (dvms.filter(i => i.id === jsonentry.id).length === 0) {
|
||||
dvms.push(jsonentry)
|
||||
}
|
||||
|
||||
|
||||
dvms.find(i => i.id === jsonentry.id).status = status
|
||||
|
||||
store.commit('set_imagedvm_results', dvms)
|
||||
|
||||
|
||||
} catch (error) {
|
||||
console.log("Error: ", error);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
else if(event.kind === 6100) {
|
||||
let entries = []
|
||||
console.log("6100:", event.content);
|
||||
|
||||
//miniToastr.showMessage("DVM: " + dvmname, "Received Results", VueNotifications.types.success)
|
||||
dvms.find(i => i.id === event.author.toHex()).result = event.content
|
||||
dvms.find(i => i.id === event.author.toHex()).status = "finished"
|
||||
store.commit('set_imagedvm_results', dvms)
|
||||
}
|
||||
}
|
||||
},
|
||||
// Handle relay message
|
||||
handleMsg: async (relayUrl, message) => {
|
||||
//console.log("Received message from", relayUrl, message.asJson());
|
||||
}
|
||||
};
|
||||
|
||||
client.handleNotifications(handle);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function nextInput(e) {
|
||||
const next = e.currentTarget.nextElementSibling;
|
||||
if (next) {
|
||||
next.focus();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function copyinvoice(invoice){
|
||||
await navigator.clipboard.writeText(invoice)
|
||||
window.open("lightning:" + invoice,"_blank")
|
||||
miniToastr.showMessage("", "Copied Invoice to clipboard", VueNotifications.types.info)
|
||||
}
|
||||
|
||||
async function copyurl(url){
|
||||
await navigator.clipboard.writeText(url)
|
||||
miniToastr.showMessage("", "Copied link to clipboard", VueNotifications.types.info)
|
||||
}
|
||||
|
||||
|
||||
async function zap(invoice) {
|
||||
let webln;
|
||||
|
||||
//this.dvmpaymentaddr = `https://chart.googleapis.com/chart?cht=qr&chl=${invoice}&chs=250x250&chld=M|0`;
|
||||
//this.dvminvoice = invoice
|
||||
|
||||
|
||||
try {
|
||||
webln = await requestProvider();
|
||||
} catch (err) {
|
||||
await copyinvoice(invoice)
|
||||
}
|
||||
|
||||
if (webln) {
|
||||
|
||||
let response = await webln.sendPayment(invoice)
|
||||
//console.log(response)
|
||||
//for (const dvm of dvms){
|
||||
// console.log(dvm.bolt11 + " " + invoice)
|
||||
//}
|
||||
|
||||
dvms.find(i => i.bolt11 === invoice).status = "paid"
|
||||
store.commit('set_imagedvm_results', dvms)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
async function createBolt11Lud16(lud16, amount) {
|
||||
let url;
|
||||
if (lud16.includes('@')) { // LNaddress
|
||||
const parts = lud16.split('@');
|
||||
url = `https://${parts[1]}/.well-known/lnurlp/${parts[0]}`;
|
||||
} else { // No lud16 set or format invalid
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
console.log(url);
|
||||
const response = await fetch(url);
|
||||
const ob = await response.json();
|
||||
const callback = ob.callback;
|
||||
const amountInSats = parseInt(amount) * 1000;
|
||||
const callbackResponse = await fetch(`${callback}?amount=${amountInSats}`);
|
||||
const obCallback = await callbackResponse.json();
|
||||
return obCallback.pr;
|
||||
}
|
||||
catch (e) {
|
||||
console.log(`LUD16: ${e}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
defineProps({
|
||||
msg: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<template>
|
||||
|
||||
<div class="greetings">
|
||||
<br>
|
||||
<br>
|
||||
<h1 class="text-7xl font-black tracking-wide">Noogle</h1>
|
||||
<h1 class="text-7xl font-black tracking-wide">Image Generation</h1>
|
||||
<h2 class="text-base-200-content text-center tracking-wide text-2xl font-thin">
|
||||
Generate Images, the decentralized way</h2>
|
||||
<h3>
|
||||
<br>
|
||||
<input class="c-Input" autofocus placeholder="A purple ostrich..." v-model="message" @keyup.enter="generate_image(message)" @keydown.enter="nextInput">
|
||||
<button class="v-Button" @click="generate_image(message)">Generate Image</button>
|
||||
</h3>
|
||||
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div class="max-w-5xl relative space-y-3">
|
||||
<div class="grid grid-cols-2 gap-6">
|
||||
<div className="card w-70 bg-base-100 shadow-xl flex flex-col" v-for="dvm in store.state.imagedvmreplies"
|
||||
:key="dvm.id">
|
||||
|
||||
<figure class="w-full">
|
||||
<img v-if="dvm.result" :src="dvm.result" height="200" alt="DVM Picture" @click="copyurl(dvm.result)"/>
|
||||
<img v-if="!dvm.result" :src="dvm.image" height="200" alt="DVM Picture" />
|
||||
</figure>
|
||||
|
||||
|
||||
<div className="card-body">
|
||||
<h2 className="card-title">{{ dvm.name }}</h2>
|
||||
<h3 class="fa-cut" >{{ dvm.about }}</h3>
|
||||
|
||||
|
||||
|
||||
<div className="card-actions justify-end mt-auto" >
|
||||
|
||||
<div className="tooltip mt-auto" :data-tip="dvm.card ">
|
||||
|
||||
|
||||
<button v-if="dvm.status === 'processing'" className="btn">Processing</button>
|
||||
<button v-if="dvm.status === 'finished'" className="btn">Done</button>
|
||||
<button v-if="dvm.status === 'paid'" className="btn">Paid, waiting for DVM..</button>
|
||||
<button v-if="dvm.status === 'error'" className="btn">Error</button>
|
||||
<button v-if="dvm.status === 'payment-required'" className="zap-Button" @click="zap(dvm.bolt11);">{{ dvm.amount/1000 }} Sats</button>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.zap-Button{
|
||||
@apply btn hover:bg-amber-400;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.v-Button {
|
||||
@apply bg-nostr hover:bg-nostr2 focus:ring-white mb-2 inline-flex flex-none items-center rounded-lg border border-black px-3 py-1.5 text-sm leading-4 text-white transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-white dark:focus:ring-offset-gray-900;
|
||||
height: 48px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.c-Input {
|
||||
@apply bg-black hover:bg-gray-900 focus:ring-white mb-2 inline-flex flex-none items-center rounded-lg border border-transparent px-3 py-1.5 text-sm leading-4 text-white transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-white dark:focus:ring-offset-gray-900;
|
||||
|
||||
width: 350px;
|
||||
height: 48px;
|
||||
color: white;
|
||||
background: black;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
width:100%;
|
||||
height:125px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.0rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.greetings h1,
|
||||
.greetings h3 {
|
||||
text-align: left;
|
||||
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
|
||||
.greetings h1,
|
||||
.greetings h3 {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,144 +0,0 @@
|
||||
<template>
|
||||
<EasyDataTable class="customize-table" header-text-direction="left" v-if="store.state.results.length != 0" table-class-name="customize-table"
|
||||
:headers="headers"
|
||||
:items="store.state.results" :sort-by="sortBy"
|
||||
:sort-type="sortType">
|
||||
<template #item-content="{ content, author, authorurl, avatar, indicator, links}">
|
||||
<div class="playeauthor-wrapper">
|
||||
|
||||
<img class="avatar" v-if="avatar" :src="avatar" alt="Avatar" />
|
||||
<img class="avatar" v-else src="@/assets/nostr-purple.svg" />
|
||||
|
||||
<a class="purple" :href="authorurl" target="_blank">{{ author }}</a>
|
||||
<div class="time" :data-tip="indicator.time">
|
||||
{{indicator.time.split("T")[1].split("Z")[0].trim()}}
|
||||
{{indicator.time.split("T")[0].split("-")[2].trim()}}.{{indicator.time.split("T")[0].split("-")[1].trim()}}.{{indicator.time.split("T")[0].split("-")[0].trim().slice(2)}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>{{content.substr(0, 320) + "\u2026"}}</p>
|
||||
<div style="padding: 2px; text-align: left;" >
|
||||
<a class="menusmall" :href="links.uri" target="_blank">Nostr Client</a>
|
||||
<a class="menusmall" :href="links.njump" target="_blank">NJump</a>
|
||||
<a class="menusmall" :href="links.highlighter" target="_blank">Highlighter</a>
|
||||
<!-- <a class="menusmall":href="links.nostrudel" target="_blank">Nostrudel</a> -->
|
||||
</div>
|
||||
<!-- <p>{{content}}</p> -->
|
||||
</template>
|
||||
<!--<template #expand="item">
|
||||
<div style="padding: 15px; text-align: left;" >
|
||||
<a class="menu" :href="item.links.uri" target="_blank">Nostr Client</a>
|
||||
<a class="menu" :href="item.links.njump" target="_blank">NJump</a>
|
||||
<a class="menu" :href="item.links.highlighter" target="_blank">Highlighter</a>
|
||||
<a class="menu":href="item.links.nostrudel" target="_blank">Nostrudel</a>
|
||||
</div>
|
||||
</template> -->
|
||||
|
||||
|
||||
</EasyDataTable>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
|
||||
import type {Header, Item, SortType} from "vue3-easy-data-table";
|
||||
import store from '../store';
|
||||
|
||||
const sortBy = "indicator.time";
|
||||
const sortType: SortType = "desc";
|
||||
|
||||
const headers: Header[] = [
|
||||
{ text: "Results:", value: "content", fixed:true},
|
||||
// { text: "Time", value: "indicator.time", sortable: true, },
|
||||
];
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.operation-wrapper .operation-icon {
|
||||
width: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.playeauthor-wrapper {
|
||||
padding: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
}
|
||||
|
||||
.menusmall {
|
||||
@apply btn text-gray-600 bg-transparent border-transparent tracking-wide;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.vue3-easy-data-table__footer.previous-page__click-button{
|
||||
height:100px
|
||||
}
|
||||
|
||||
.time {
|
||||
padding: 6px;
|
||||
display: flex;
|
||||
font-size: 1em;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
}
|
||||
.avatar {
|
||||
margin-right: 10px;
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
box-shadow: inset 0 4px 4px 0 rgb(0 0 0 / 10%);
|
||||
}
|
||||
.customize-table {
|
||||
|
||||
--easy-table-border: 1px solid #000000;
|
||||
--easy-table-row-border: 1px solid #000000;
|
||||
|
||||
--easy-table-header-font-size: 14px;
|
||||
--easy-table-header-height: 50px;
|
||||
--easy-table-header-font-color: #c1cad4;
|
||||
--easy-table-header-background-color: #242424;
|
||||
|
||||
--easy-table-header-item-padding: 10px 15px;
|
||||
|
||||
--easy-table-body-even-row-font-color: #fff;
|
||||
--easy-table-body-even-row-background-color: #242424;
|
||||
|
||||
--easy-table-body-row-font-color: #c0c7d2;
|
||||
--easy-table-body-row-background-color: #242424;
|
||||
--easy-table-body-row-height: 50px;
|
||||
--easy-table-body-row-font-size: 14px;
|
||||
|
||||
--easy-table-body-row-hover-font-color: #FFFFFF;
|
||||
--easy-table-body-row-hover-background-color: #242424;
|
||||
|
||||
--easy-table-body-item-padding: 10px 15px;
|
||||
|
||||
--easy-table-footer-background-color: #242424;
|
||||
--easy-table-footer-font-color: #c0c7d2;
|
||||
--easy-table-footer-font-size: 14px;
|
||||
--easy-table-footer-padding: 0px 10px;
|
||||
--easy-table-footer-height: 50px;
|
||||
|
||||
--easy-table-rows-per-page-selector-width: 70px;
|
||||
--easy-table-rows-per-page-selector-option-padding: 10px;
|
||||
--easy-table-rows-per-page-selector-z-index: 1;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--easy-table-scrollbar-track-color: #2d3a4f;
|
||||
--easy-table-scrollbar-color: #2d3a4f;
|
||||
--easy-table-scrollbar-thumb-color: #4c5d7a;;
|
||||
--easy-table-scrollbar-corner-color: #2d3a4f;
|
||||
|
||||
--easy-table-loading-mask-background-color: #2d3a4f;
|
||||
}
|
||||
</style>
|
||||
@@ -1,285 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="playeauthor-wrapper" v-if="current_user">
|
||||
<img class="avatar" @click="sign_out()" :src="this.avatar" alt="" />
|
||||
<p>{{ this.current_user }}</p>
|
||||
</div>
|
||||
|
||||
<template v-if="!current_user">
|
||||
<div className="dropdown">
|
||||
<div tabIndex={0} role="button" class="v-Button" >Sign in</div>
|
||||
<div tabIndex={0} className="dropdown-content -start-44 z-[1] horizontal card card-compact w-64 p-2 shadow bg-primary text-primary-content">
|
||||
<div className="card-body">
|
||||
<h3 className="card-title">Nip07 Login</h3>
|
||||
<p>Use a Browser Nip07 Extension like getalby or nos2x to login</p>
|
||||
<button className="btn" @click="sign_in_nip07()">Nip07 Sign in</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Nip89></Nip89>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
loadWasmAsync,
|
||||
Client,
|
||||
ClientSigner,
|
||||
Nip07Signer,
|
||||
Filter,
|
||||
initLogger,
|
||||
LogLevel,
|
||||
Timestamp, Keys, NostrDatabase, ClientBuilder, ClientZapper, Alphabet
|
||||
} from "@rust-nostr/nostr-sdk";
|
||||
import VueNotifications from "vue-notifications";
|
||||
import store from '../store';
|
||||
import Nip89 from "@/components/Nip89.vue";
|
||||
import miniToastr from "mini-toastr";
|
||||
import deadnip89s from "@/components/data/deadnip89s.json";
|
||||
let nip89dvms = []
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
current_user: "",
|
||||
avatar: "",
|
||||
signer: "",
|
||||
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
try{
|
||||
if (localStorage.getItem('nostr-key-method') === 'nip07')
|
||||
{
|
||||
await this.sign_in_nip07()
|
||||
}
|
||||
else {
|
||||
await this.sign_in_anon()
|
||||
}
|
||||
|
||||
await this.getnip89s()
|
||||
}
|
||||
catch (error){
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
async sign_in_anon() {
|
||||
try {
|
||||
await loadWasmAsync();
|
||||
/*try {
|
||||
initLogger(LogLevel.debug());
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}*/
|
||||
|
||||
let keys = Keys.fromSkStr("ece3c0aa759c3e895ecb3c13ab3813c0f98430c6d4bd22160b9c2219efc9cf0e")
|
||||
this.signer = ClientSigner.keys(keys) //TODO store keys
|
||||
let client = new ClientBuilder().signer(this.signer).build()
|
||||
|
||||
for (const relay of store.state.relays){
|
||||
await client.addRelay(relay);
|
||||
}
|
||||
|
||||
const pubkey = keys.publicKey
|
||||
await client.connect();
|
||||
|
||||
/*
|
||||
const filter = new Filter().kind(6302).limit(20)
|
||||
await client.reconcile(filter);
|
||||
const filterl = new Filter().author(pubkey)
|
||||
let test = await client.database.query([filterl])
|
||||
for (let ev of test){
|
||||
console.log(ev.asJson())
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
|
||||
store.commit('set_client', client)
|
||||
store.commit('set_pubkey', pubkey)
|
||||
store.commit('set_hasEventListener', false)
|
||||
localStorage.setItem('nostr-key-method', "anon")
|
||||
localStorage.setItem('nostr-key', "")
|
||||
console.log("Client connected")
|
||||
|
||||
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
async sign_in_nip07() {
|
||||
|
||||
try {
|
||||
|
||||
await loadWasmAsync();
|
||||
|
||||
/* try {
|
||||
initLogger(LogLevel.debug());
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} */
|
||||
|
||||
let nip07_signer = new Nip07Signer();
|
||||
try{
|
||||
this.signer = ClientSigner.nip07(nip07_signer);
|
||||
console.log("SIGNER: " + this.signer)
|
||||
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
this.signer = ClientSigner.keys(Keys.generate())
|
||||
}
|
||||
|
||||
let zapper = ClientZapper.webln()
|
||||
let client = new ClientBuilder().signer(this.signer).zapper(zapper).build();
|
||||
|
||||
for (const relay of store.state.relays){
|
||||
await client.addRelay(relay);
|
||||
}
|
||||
|
||||
const pubkey = await nip07_signer.getPublicKey();
|
||||
await client.connect();
|
||||
|
||||
/*
|
||||
const filter = new Filter().kind(6302).limit(20)
|
||||
await client.reconcile(filter);
|
||||
const filterl = new Filter().author(pubkey)
|
||||
let test = await client.database.query([filterl])
|
||||
for (let ev of test){
|
||||
console.log(ev.asJson())
|
||||
}*/
|
||||
|
||||
store.commit('set_client', client)
|
||||
store.commit('set_pubkey', pubkey)
|
||||
store.commit('set_hasEventListener', false)
|
||||
localStorage.setItem('nostr-key-method', "nip07")
|
||||
localStorage.setItem('nostr-key', "")
|
||||
console.log("Client connected")
|
||||
await this.get_user_info(pubkey)
|
||||
//miniToastr.showMessage("Login successful!", "Logged in as " + this.current_user, VueNotifications.types.success)
|
||||
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
async getnip89s(){
|
||||
|
||||
//let keys = Keys.generate()
|
||||
let keys = Keys.fromSkStr("ece3c0aa759c3e895ecb3c13ab3813c0f98430c6d4bd22160b9c2219efc9cf0e")
|
||||
|
||||
let signer = ClientSigner.keys(keys) //TODO store keys
|
||||
let client = new ClientBuilder().signer(signer).build()
|
||||
for (const relay of store.state.relays){
|
||||
await client.addRelay(relay);
|
||||
}
|
||||
await client.connect();
|
||||
|
||||
let dvmkinds = []
|
||||
for (let i = 5000; i < 6000; i++) {
|
||||
dvmkinds.push((i.toString()))
|
||||
}
|
||||
console.log(dvmkinds)
|
||||
|
||||
const filter = new Filter().kind(31990).customTag(Alphabet.K, dvmkinds)
|
||||
//await client.reconcile(filter);
|
||||
//const filterl = new Filter().kind(31990)
|
||||
//let evts = await client.database.query([filterl])
|
||||
let evts = await client.getEventsOf([filter], 3)
|
||||
for (const entry of evts){
|
||||
for (const tag in entry.tags){
|
||||
if (entry.tags[tag].asVec()[0] === "k")
|
||||
if(entry.tags[tag].asVec()[1] >= 5000 && entry.tags[tag].asVec()[1] <= 5999 && deadnip89s.filter(i => i.id === entry.id.toHex() ).length === 0) { // blocklist.indexOf(entry.id.toHex()) < 0){
|
||||
|
||||
// console.log(entry.tags[tag].asVec()[1])
|
||||
|
||||
try {
|
||||
|
||||
let jsonentry = JSON.parse(entry.content)
|
||||
if (jsonentry.picture){
|
||||
jsonentry.image = jsonentry.picture
|
||||
}
|
||||
jsonentry.event = entry.asJson()
|
||||
jsonentry.kind = entry.tags[tag].asVec()[1]
|
||||
nip89dvms.push(jsonentry);
|
||||
}
|
||||
catch (error){
|
||||
//console.log(error)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
store.commit('set_nip89dvms', nip89dvms)
|
||||
|
||||
return nip89dvms
|
||||
|
||||
|
||||
},
|
||||
|
||||
|
||||
|
||||
async get_user_info(pubkey){
|
||||
let client = store.state.client
|
||||
const profile_filter = new Filter().kind(0).author(pubkey).limit(1)
|
||||
let evts = await client.getEventsOf([profile_filter], 10)
|
||||
console.log("PROFILES:" + evts.length)
|
||||
if (evts.length > 0){
|
||||
let latest_entry = evts[0]
|
||||
let latest_time = 0
|
||||
|
||||
for (const entry of evts){
|
||||
if (entry.createdAt.asSecs() > latest_time){
|
||||
latest_time = entry.createdAt.asSecs();
|
||||
latest_entry = entry
|
||||
}
|
||||
}
|
||||
|
||||
let profile = JSON.parse(latest_entry.content);
|
||||
this.current_user = profile["name"]
|
||||
this.avatar = profile["picture"]
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
async sign_out(){
|
||||
this.current_user = ""
|
||||
await this.state.client.shutdown();
|
||||
localStorage.setItem('nostr-key-method', "")
|
||||
localStorage.setItem('nostr-key', "")
|
||||
await this.sign_in_anon()
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.operation-wrapper .operation-icon {
|
||||
width: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.playeauthor-wrapper {
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
}
|
||||
.avatar {
|
||||
margin-right: 10px;
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
box-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 10%);
|
||||
}
|
||||
|
||||
.v-Button {
|
||||
@apply bg-black text-center hover:bg-nostr focus:ring-nostr mb-2 inline-flex flex-none items-center rounded-lg border border-nostr px-3 py-1.5 text-sm leading-4 text-white transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-white dark:focus:ring-offset-gray-900;
|
||||
margin-right: 14px;
|
||||
height: 44px;
|
||||
width: 70px
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,95 +0,0 @@
|
||||
<template>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
ClientSigner,
|
||||
Filter,
|
||||
Keys, ClientBuilder, Alphabet
|
||||
} from "@rust-nostr/nostr-sdk";
|
||||
import store from '../store';
|
||||
import miniToastr from "mini-toastr";
|
||||
import deadnip89s from "@/components/data/deadnip89s.json";
|
||||
let nip89dvms = []
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
current_user: "",
|
||||
avatar: "",
|
||||
signer: "",
|
||||
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
try{
|
||||
await this.getnip89s()
|
||||
}
|
||||
catch (error){
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
async getnip89s(){
|
||||
|
||||
//let keys = Keys.generate()
|
||||
let keys = Keys.fromSkStr("ece3c0aa759c3e895ecb3c13ab3813c0f98430c6d4bd22160b9c2219efc9cf0e")
|
||||
|
||||
let signer = ClientSigner.keys(keys) //TODO store keys
|
||||
let client = new ClientBuilder().signer(signer).build()
|
||||
//await client.addRelay("wss://nos.lol");
|
||||
await client.addRelay("wss://relay.f7z.io")
|
||||
await client.addRelay("wss://pablof7z.nostr1.com")
|
||||
//await client.addRelay("wss://relay.nostr.net")
|
||||
await client.addRelay("wss://relay.nostr.band");
|
||||
//await client.addRelay("wss://nostr-pub.wellorder.net")
|
||||
await client.connect();
|
||||
|
||||
let dvmkinds = []
|
||||
for (let i = 5000; i < 6000; i++) {
|
||||
dvmkinds.push((i.toString()))
|
||||
}
|
||||
|
||||
|
||||
const filter = new Filter().kind(31990).customTag(Alphabet.K, dvmkinds)
|
||||
//await client.reconcile(filter);
|
||||
//const filterl = new Filter().kind(31990)
|
||||
//let evts = await client.database.query([filterl])
|
||||
let evts = await client.getEventsOf([filter], 3)
|
||||
for (const entry of evts){
|
||||
for (const tag in entry.tags){
|
||||
if (entry.tags[tag].asVec()[0] === "k")
|
||||
|
||||
if(entry.tags[tag].asVec()[1] >= 5000 && entry.tags[tag].asVec()[1] <= 5999 && deadnip89s.filter(i => i.id === entry.id.toHex() ).length === 0) { // blocklist.indexOf(entry.id.toHex()) < 0){
|
||||
try {
|
||||
let jsonentry = JSON.parse(entry.content)
|
||||
if (jsonentry.picture){
|
||||
jsonentry.image = jsonentry.picture
|
||||
}
|
||||
jsonentry.event = entry.asJson()
|
||||
jsonentry.createdAt = entry.createdAt.asSecs()
|
||||
jsonentry.kind = entry.tags[tag].asVec()[1]
|
||||
nip89dvms.push(jsonentry);
|
||||
}
|
||||
catch (error){
|
||||
console.log(error)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
store.commit('set_nip89dvms', nip89dvms)
|
||||
|
||||
return nip89dvms
|
||||
|
||||
|
||||
},
|
||||
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,66 +0,0 @@
|
||||
<template>
|
||||
|
||||
<div class="max-w-5xl relative space-y-3">
|
||||
<div v-if="store.state.nip89dvms.length === 0">
|
||||
<p>Loading Nip89s.. </p>
|
||||
<span className="loading loading-dots loading-lg" ></span>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-6">
|
||||
<div className="card w-70 bg-base-100 shadow-xl" v-for="dvm in store.state.nip89dvms"
|
||||
:key="dvm.name">
|
||||
<figure><img :src="dvm.image" alt="DVM Picture" /></figure>
|
||||
<div className="card-body">
|
||||
<h2 className="card-title">{{ dvm.name }}</h2>
|
||||
<p> {{ dvm.about }}</p>
|
||||
<p>Kind: {{ dvm.kind }}</p>
|
||||
<div className="card-actions justify-end">
|
||||
<div className="tooltip" :data-tip="dvm.event">
|
||||
<button className="btn" @click="copyDoiToClipboard(dvm.event);">Copy Event</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import '../app.css'
|
||||
import store from "@/store.js";
|
||||
import {Alphabet, ClientBuilder, ClientSigner, Filter, Keys, NostrDatabase, Tag} from "@rust-nostr/nostr-sdk";
|
||||
import miniToastr from "mini-toastr";
|
||||
import VueNotifications from "vue-notifications";
|
||||
|
||||
import deadnip89s from './data/deadnip89s.json'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
store() {
|
||||
return store
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
copyDoiToClipboard (doi) {
|
||||
navigator.clipboard.writeText(doi)
|
||||
miniToastr.showMessage("", "Copied Nip89 Event to clipboard", VueNotifications.types.info)
|
||||
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
async mounted(){
|
||||
|
||||
},
|
||||
|
||||
setup() {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,294 +0,0 @@
|
||||
<script setup>
|
||||
import {
|
||||
Client,
|
||||
Filter,
|
||||
Timestamp,
|
||||
Event,
|
||||
Metadata,
|
||||
PublicKey,
|
||||
EventBuilder,
|
||||
Tag,
|
||||
EventId,
|
||||
Nip19Event
|
||||
} from "@rust-nostr/nostr-sdk";
|
||||
import store from '../store';
|
||||
import miniToastr from "mini-toastr";
|
||||
import VueNotifications from "vue-notifications";
|
||||
import searchdvms from './data/searchdvms.json'
|
||||
import {computed} from "vue";
|
||||
import countries from "@/components/data/countries.json";
|
||||
import deadnip89s from "@/components/data/deadnip89s.json";
|
||||
|
||||
let items = []
|
||||
|
||||
let listener = false
|
||||
|
||||
|
||||
|
||||
|
||||
async function send_search_request(message) {
|
||||
try {
|
||||
if (message === undefined){
|
||||
message = "Nostr"
|
||||
}
|
||||
|
||||
if(store.state.pubkey === undefined){
|
||||
miniToastr.showMessage("Please login first", "No pubkey set", VueNotifications.types.warn)
|
||||
return
|
||||
}
|
||||
items = []
|
||||
store.commit('set_search_results', items)
|
||||
let client = store.state.client
|
||||
let tags = []
|
||||
let users = [];
|
||||
|
||||
const taggedUsersFrom = message.split(' ')
|
||||
.filter(word => word.startsWith('from:'))
|
||||
.map(word => word.replace('from:', ''));
|
||||
|
||||
// search
|
||||
let search = message;
|
||||
|
||||
// tags
|
||||
|
||||
for (let word of taggedUsersFrom) {
|
||||
search = search.replace(word, "");
|
||||
if(word === "me"){
|
||||
word = store.state.pubkey.toBech32()
|
||||
}
|
||||
const userPubkey = PublicKey.fromBech32(word.replace("@", "")).toHex()
|
||||
const pTag = Tag.parse(["p", userPubkey]);
|
||||
users.push(pTag.asVec());
|
||||
}
|
||||
|
||||
message = search.replace(/from:|to:|@/g, '').trim();
|
||||
console.log(search);
|
||||
|
||||
tags.push(Tag.parse(["i", message, "text"]))
|
||||
tags.push(Tag.parse(["param", "max_results", "150"]))
|
||||
tags.push(Tag.parse(['param', 'users', JSON.stringify(users)]))
|
||||
|
||||
let evt = new EventBuilder(5302, "NIP 90 Search request", tags)
|
||||
let res = await client.sendEventBuilder(evt)
|
||||
store.commit('set_current_request_id_search', res.toHex())
|
||||
console.log("SEARCH EVENT SENT: " + res.toHex())
|
||||
miniToastr.showMessage("Sent Request to DVMs", "Awaiting results", VueNotifications.types.warn)
|
||||
if (!store.state.hasEventListener){
|
||||
listen()
|
||||
store.commit('set_hasEventListener', true)
|
||||
}
|
||||
else{
|
||||
console.log("Already has event listener")
|
||||
}
|
||||
|
||||
console.log(res)
|
||||
|
||||
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function getEvents(eventids) {
|
||||
const event_filter = new Filter().ids(eventids)
|
||||
let client = store.state.client
|
||||
return await client.getEventsOf([event_filter], 5)
|
||||
}
|
||||
|
||||
async function get_user_infos(pubkeys){
|
||||
let profiles = []
|
||||
let client = store.state.client
|
||||
const profile_filter = new Filter().kind(0).authors(pubkeys)
|
||||
let evts = await client.getEventsOf([profile_filter], 10)
|
||||
console.log("PROFILES:" + evts.length)
|
||||
for (const entry of evts){
|
||||
try{
|
||||
let contentjson = JSON.parse(entry.content)
|
||||
profiles.push({profile: contentjson, author: entry.author.toHex(), createdAt: entry.createdAt});
|
||||
}
|
||||
catch(error){
|
||||
console.log("error")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return profiles
|
||||
|
||||
}
|
||||
|
||||
async function listen() {
|
||||
listener = true
|
||||
let client = store.state.client
|
||||
let pubkey = store.state.pubkey
|
||||
|
||||
const filter = new Filter().kinds([7000, 6302]).pubkey(pubkey).since(Timestamp.now());
|
||||
await client.subscribe([filter]);
|
||||
|
||||
const handle = {
|
||||
// Handle event
|
||||
handleEvent: async (relayUrl, event) => {
|
||||
if (store.state.hasEventListener === false){
|
||||
return true
|
||||
}
|
||||
const dvmname = getNamefromId(event.author.toHex())
|
||||
console.log("Received new event from", relayUrl);
|
||||
let resonsetorequest = false
|
||||
for (let tag in event.tags) {
|
||||
if (event.tags[tag].asVec()[0] === "e") {
|
||||
//console.log("SEARCH ETAG: " + event.tags[tag].asVec()[1])
|
||||
// console.log("SEARCH LISTEN TO : " + store.state.requestidSearch)
|
||||
if (event.tags[tag].asVec()[1] === store.state.requestidSearch) {
|
||||
resonsetorequest = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if(resonsetorequest){
|
||||
|
||||
if (event.kind === 7000) {
|
||||
try {
|
||||
console.log("7000: ", event.content);
|
||||
console.log("DVM: " + event.author.toHex())
|
||||
miniToastr.showMessage("DVM: " + dvmname, event.content, VueNotifications.types.info)
|
||||
} catch (error) {
|
||||
console.log("Error: ", error);
|
||||
}
|
||||
}
|
||||
else if(event.kind === 6302) {
|
||||
let entries = []
|
||||
console.log("6302:", event.content);
|
||||
|
||||
miniToastr.showMessage("DVM: " + dvmname, "Received Results", VueNotifications.types.success)
|
||||
let event_etags = JSON.parse(event.content)
|
||||
for (let etag of event_etags){
|
||||
const eventid = EventId.fromHex(etag[1])
|
||||
entries.push(eventid)
|
||||
}
|
||||
const events = await getEvents(entries)
|
||||
let authors = []
|
||||
for (const evt of events){
|
||||
authors.push(evt.author)
|
||||
}
|
||||
let profiles = await get_user_infos(authors)
|
||||
|
||||
|
||||
for (const evt of events){
|
||||
let p = profiles.find( record => record.author === evt.author.toHex())
|
||||
let bech32id = evt.id.toBech32()
|
||||
let nip19 = new Nip19Event(event.id, event.author, store.state.relays)
|
||||
let nip19bech32 = nip19.toBech32()
|
||||
let picture = p === undefined ? "../assets/nostr-purple.svg" : p["profile"]["picture"]
|
||||
let name = p === undefined ? bech32id : p["profile"]["name"]
|
||||
let highlighterurl = "https://highlighter.com/a/" + bech32id
|
||||
let njumpurl = "https://njump.me/" + bech32id
|
||||
let nostrudelurl = "https://nostrudel.ninja/#/n/" + bech32id
|
||||
let uri = "nostr:" + bech32id // nip19.toNostrUri()
|
||||
|
||||
if (items.find(e => e.id.toHex() === evt.id.toHex()) === undefined) {
|
||||
items.push({id:evt.id, content: evt.content, author: name, authorurl: "https://njump.me/" + evt.author.toBech32(), links: {"uri": uri, "highlighter": highlighterurl, "njump": njumpurl, "nostrudel": nostrudelurl} , avatar: picture, indicator: {"time": evt.createdAt.toHumanDatetime()}})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
console.log("Events from" + event.author.toHex())
|
||||
console.log(items)
|
||||
store.commit('set_search_results', items)
|
||||
}
|
||||
}
|
||||
},
|
||||
// Handle relay message
|
||||
handleMsg: async (relayUrl, message) => {
|
||||
//console.log("Received message from", relayUrl, message.asJson());
|
||||
}
|
||||
};
|
||||
|
||||
client.handleNotifications(handle);
|
||||
}
|
||||
|
||||
|
||||
function getNamefromId(id){
|
||||
let elements = searchdvms.filter(i => i.id === id)
|
||||
if (elements.length === 0){
|
||||
return id
|
||||
}
|
||||
else return elements[0].name
|
||||
}
|
||||
|
||||
function nextInput(e) {
|
||||
const next = e.currentTarget.nextElementSibling;
|
||||
if (next) {
|
||||
next.focus();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
defineProps({
|
||||
msg: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
|
||||
<div class="greetings">
|
||||
<img alt="Nostr logo" class="logo" src="../assets/nostr-purple.svg" />
|
||||
<br>
|
||||
<h1 class="text-7xl font-black tracking-wide">Noogle</h1>
|
||||
<h2 class="text-base-200-content text-center tracking-wide text-2xl font-thin">
|
||||
Search the Nostr with Data Vending Machines</h2>
|
||||
<h3>
|
||||
<br>
|
||||
<input class="c-Input" autofocus placeholder="Search..." v-model="message" @keyup.enter="send_search_request(message)" @keydown.enter="nextInput">
|
||||
<button class="v-Button" @click="send_search_request(message)">Search the Nostr</button>
|
||||
</h3>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.v-Button {
|
||||
@apply bg-nostr hover:bg-nostr2 focus:ring-white mb-2 inline-flex flex-none items-center rounded-lg border border-black px-3 py-1.5 text-sm leading-4 text-white transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-white dark:focus:ring-offset-gray-900;
|
||||
height: 48px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.c-Input {
|
||||
@apply bg-black hover:bg-gray-900 focus:ring-white mb-2 inline-flex flex-none items-center rounded-lg border border-transparent px-3 py-1.5 text-sm leading-4 text-white transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-white dark:focus:ring-offset-gray-900;
|
||||
|
||||
width: 350px;
|
||||
height: 48px;
|
||||
color: white;
|
||||
background: black;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
width:100%;
|
||||
height:125px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.greetings h1,
|
||||
.greetings h3 {
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
|
||||
.greetings h1,
|
||||
.greetings h3 {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,144 +0,0 @@
|
||||
<template>
|
||||
<EasyDataTable class="customize-table" header-text-direction="left" v-if="store.state.results.length != 0" table-class-name="customize-table"
|
||||
:headers="headers"
|
||||
:items="store.state.results" :sort-by="sortBy"
|
||||
:sort-type="sortType">
|
||||
<template #item-content="{ content, author, authorurl, avatar, indicator, links}">
|
||||
<div class="playeauthor-wrapper">
|
||||
|
||||
<img class="avatar" v-if="avatar" :src="avatar" alt="Avatar" />
|
||||
<img class="avatar" v-else src="@/assets/nostr-purple.svg" />
|
||||
|
||||
<a class="purple" :href="authorurl" target="_blank">{{ author }}</a>
|
||||
<div class="time" :data-tip="indicator.time">
|
||||
{{indicator.time.split("T")[1].split("Z")[0].trim()}}
|
||||
{{indicator.time.split("T")[0].split("-")[2].trim()}}.{{indicator.time.split("T")[0].split("-")[1].trim()}}.{{indicator.time.split("T")[0].split("-")[0].trim().slice(2)}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>{{content.substr(0, 320) + "\u2026"}}</p>
|
||||
<div style="padding: 2px; text-align: left;" >
|
||||
<a class="menusmall" :href="links.uri" target="_blank">Nostr Client</a>
|
||||
<a class="menusmall" :href="links.njump" target="_blank">NJump</a>
|
||||
<a class="menusmall" :href="links.highlighter" target="_blank">Highlighter</a>
|
||||
<!-- <a class="menusmall":href="links.nostrudel" target="_blank">Nostrudel</a> -->
|
||||
</div>
|
||||
<!-- <p>{{content}}</p> -->
|
||||
</template>
|
||||
<!--<template #expand="item">
|
||||
<div style="padding: 15px; text-align: left;" >
|
||||
<a class="menu" :href="item.links.uri" target="_blank">Nostr Client</a>
|
||||
<a class="menu" :href="item.links.njump" target="_blank">NJump</a>
|
||||
<a class="menu" :href="item.links.highlighter" target="_blank">Highlighter</a>
|
||||
<a class="menu":href="item.links.nostrudel" target="_blank">Nostrudel</a>
|
||||
</div>
|
||||
</template> -->
|
||||
|
||||
|
||||
</EasyDataTable>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
|
||||
import type {Header, Item, SortType} from "vue3-easy-data-table";
|
||||
import store from '../store';
|
||||
|
||||
const sortBy = "indicator.time";
|
||||
const sortType: SortType = "desc";
|
||||
|
||||
const headers: Header[] = [
|
||||
{ text: "Results:", value: "content", fixed:true},
|
||||
// { text: "Time", value: "indicator.time", sortable: true, },
|
||||
];
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.operation-wrapper .operation-icon {
|
||||
width: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.playeauthor-wrapper {
|
||||
padding: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
}
|
||||
|
||||
.menusmall {
|
||||
@apply btn text-gray-600 bg-transparent border-transparent tracking-wide;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.vue3-easy-data-table__footer.previous-page__click-button{
|
||||
height:100px
|
||||
}
|
||||
|
||||
.time {
|
||||
padding: 6px;
|
||||
display: flex;
|
||||
font-size: 1em;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
}
|
||||
.avatar {
|
||||
margin-right: 10px;
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
box-shadow: inset 0 4px 4px 0 rgb(0 0 0 / 10%);
|
||||
}
|
||||
.customize-table {
|
||||
|
||||
--easy-table-border: 1px solid #000000;
|
||||
--easy-table-row-border: 1px solid #000000;
|
||||
|
||||
--easy-table-header-font-size: 14px;
|
||||
--easy-table-header-height: 50px;
|
||||
--easy-table-header-font-color: #c1cad4;
|
||||
--easy-table-header-background-color: #242424;
|
||||
|
||||
--easy-table-header-item-padding: 10px 15px;
|
||||
|
||||
--easy-table-body-even-row-font-color: #fff;
|
||||
--easy-table-body-even-row-background-color: #242424;
|
||||
|
||||
--easy-table-body-row-font-color: #c0c7d2;
|
||||
--easy-table-body-row-background-color: #242424;
|
||||
--easy-table-body-row-height: 50px;
|
||||
--easy-table-body-row-font-size: 14px;
|
||||
|
||||
--easy-table-body-row-hover-font-color: #FFFFFF;
|
||||
--easy-table-body-row-hover-background-color: #242424;
|
||||
|
||||
--easy-table-body-item-padding: 10px 15px;
|
||||
|
||||
--easy-table-footer-background-color: #242424;
|
||||
--easy-table-footer-font-color: #c0c7d2;
|
||||
--easy-table-footer-font-size: 14px;
|
||||
--easy-table-footer-padding: 0px 10px;
|
||||
--easy-table-footer-height: 50px;
|
||||
|
||||
--easy-table-rows-per-page-selector-width: 70px;
|
||||
--easy-table-rows-per-page-selector-option-padding: 10px;
|
||||
--easy-table-rows-per-page-selector-z-index: 1;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--easy-table-scrollbar-track-color: #2d3a4f;
|
||||
--easy-table-scrollbar-color: #2d3a4f;
|
||||
--easy-table-scrollbar-thumb-color: #4c5d7a;;
|
||||
--easy-table-scrollbar-corner-color: #2d3a4f;
|
||||
|
||||
--easy-table-loading-mask-background-color: #2d3a4f;
|
||||
}
|
||||
</style>
|
||||
@@ -1,72 +0,0 @@
|
||||
[
|
||||
{"id": "766809b054c9b772652377ef968625509a7e92c56669e302940ac08c8c3d0f96"},
|
||||
{"id": "7fb49260fbd9148e08672b8339bca6c5a866cf7aaa03051898ed02f6d85109b2"},
|
||||
{"id": "edd11ae518e4f59a25472d5ef869f114c8e5399723fd7bed32389eef37a6ec0c"},
|
||||
{"id": "b6e93a7185036b69b04a55665409957ba4d9fb2a944e43c690e6f4d64678c43f"},
|
||||
{"id": "be40dfce56ff47bce6cfa2073dd6c6d88e53d44d7e1178cc30ebb4ca991de4e4"},
|
||||
{"id": "72d86d5428049c74f94ac335cd662772f580fa27497398dd06b443653a16b4ad"},
|
||||
{"id": "0e2b90ea31426f03f9ccfff6093aacde0322a2c026d3fedf47fa35e722970fdf"},
|
||||
{"id": "ad281d17781cdcbdfce38cf13188f56b9dbb16977ca029823a3d6e0fa502e73a"},
|
||||
{"id": "c0361dd4bbae4cc32be424cf564f547b29496b3bd7bbbf3ede0cb0b8d8930b5c"},
|
||||
{"id": "349fdcad3da119f09bde6861806ae3ff461b1eb3b3708067f0abb0e669c54841"},
|
||||
{"id": "d9a016283161f262b2764e6a5710f9c2dc1aca19a42d19cca5af7cc20ff2955e"},
|
||||
{"id": "365aa211f1e873988dacb4ff1a10fe3b7221a940c3d155b8f4d33a25ca42fa52"},
|
||||
{"id": "2b07103533f747c0899f00f575c79cdea960ac62b33d06780e284eb020215c0b"},
|
||||
{"id": "5f7ce70135b7172358ee41b0f1f0ff9110af7294eef7ca7878882e129e6104db"},
|
||||
{"id": "b570d7d7d68130750c4b84aa3808fd209ed767300246365a5deaaedffcfb6d0b"},
|
||||
{"id": "3468c0769e9a8c10cc74e9bdbf11a00df1b35480b65059f71357c7f1a9e35d68"},
|
||||
{"id": "1f0cf47de297037e91450631552b3ff7ce6567b73eac57e94bbbe2d6ca99e744"},
|
||||
{"id": "02650e51270e0a734505fb2876adbef89f26bbe660ca4e8fadea0ecf1ea1b1d0"},
|
||||
{"id": "764b2ac58c23310f2caeecd155eff294f190e433438d3df5a244b5af979d3a81"},
|
||||
{"id": "c788b8a0ce4e9d795dd1895e87c0e3dd019766ebbfcd4f99112d523b8374e9de"},
|
||||
{"id": "e9ec70f0f0c1e8134efacb9941647d451f4c6d3acccb40b878598ade9308599a"},
|
||||
{"id": "4f3e5fbbb27392ce4b4ef46ee0d5bc42e5112bde6cb72644a34d89bc7505b9d5"},
|
||||
{"id": "5e4e3c95215be93be3bc5bac242f6b332c1265140d179f31af858e8f172c8d6a"},
|
||||
{"id": "bdbcfb112b0f7d55e2bcc231ec06335ea5051d49edcbed8170f717f8ecf1a965"},
|
||||
{"id": "294303fbde21251093bb86683701023bd1d7e310a64e0b1068f6160696f3c6a4"},
|
||||
{"id": "00ef6f71fcaa72742493178b8409c32bb68d92c9f67af717f92bef35272a74d4"},
|
||||
{"id": "4fff1259602cf46619d379ee8c790a1acc310a53cb617fa46d522978d6b4876b"},
|
||||
{"id": "aab06b1602f0380e6c2f442c7992c82259968d8abbba1da69d774a32d747c3b4"},
|
||||
{"id": "4bbee7e48d393b692f80e5a5357fcb435adbd46172b38f367a43c3aeb45b2fb3"},
|
||||
{"id": "97a7fa0776225a5eb644da81db9a73eacebf046d7fe745f567345c1cec0a9e32"},
|
||||
{"id": "aad1de5bb5dc4ce80de3d55a6ce7037ddb46aadb4e44c3742781d1422cf79765"},
|
||||
{"id": "2dcd9ea8b4959c7b986bfda2bdc8175ed156a474457d38be42f54f027a1dff5a"},
|
||||
{"id": "747215ea31506d60af14bae6914fd1107de0893f99c0f2e178216bea79de4677"},
|
||||
{"id": "d69a3d1b7d635ba12be30ebb9473ad4a973138e54ef1aaa2f6cce060a82937b4"},
|
||||
{"id": "c4ba426af0bb7be9de06b774aec33b7733cb952c5e1bc723c9bf021b3e2be1ea"},
|
||||
{"id": "0f7dac8f31a9aac4d4479373153489fc57889c964e82dd619bed2f60f0af27ee"},
|
||||
{"id": "561420baa35477e27b85e62ecfded0b76cab0c0acaedc9b3ab6ac7d88be42165"},
|
||||
{"id": "d68d8eab7bad9c263f5af0eb46db168d2d82ad19acc5fb19c606fcb18de7994b"},
|
||||
{"id": "86f7e9f6d98831e0ad19a575512f3d969d3af6921260809cc7a33b3b918d87f1"},
|
||||
{"id": "f9287d47f86cc0af606026fe5e017fd479230b6cd2dcc82db915603658312d82"},
|
||||
{"id": "cb83acb45cd810d8fd0df5f1f40d5bfd5406b74e37c9cda54c77114c5dcd357a"},
|
||||
{"id": "5457c08086b3e78887c8eeb39cdd8dcb6559ceea13f32cc4a6f8a84513bfacf1"},
|
||||
{"id": "1c86e2d22620ec6c94aac12fad7ed304bdf439020e74bbc0f0fc096bd5335891"},
|
||||
{"id": "6ad22ca994d0b5952b26cb0b4cae939d474f57729e18509574ace9882a635641"},
|
||||
{"id": "e15e167f70fb7d3ab740248e993096ecd7819de7ad5640f05e5c302b34737f33"},
|
||||
{"id": "a391df97b5fdf380f78091d18da0626afbf9ca2f9517935f3dee766cd0ac72fe"},
|
||||
{"id": "7b4185b0d115b5a12ba57f6804703789c68fb52d1587487161e96011a6a72223"},
|
||||
{"id": "dbd86fc945e0748b2f263abad2338ff212ae02a895f38b0a2c262a0da518ebd2"},
|
||||
{"id": "91591d5dd56657a1acbcc04116f17b2264dd369b9ad361bf15033e6ca326f5ac"},
|
||||
{"id": "eb382df17d822d81d85097f28a49f86dc69ba8a05285dff39e2d877ea31e21cc"},
|
||||
{"id": "b4a85c1e7e4c13281ae58538c57529cc6035ee465a2f69e40b41a6711a2eeb18"},
|
||||
{"id": "0ea69892da43e1b4de82bde7bb599c3f15a71120f9f506fd210c2712ba7026a3"},
|
||||
{"id": "b424c79388a2ea8b04e72f7ea32c0648db15ca5f25705bcd4231d0b658156af1"},
|
||||
{"id": "db11596a64f76082991df4d1d1e8764f4d8da926f81ddbe09333d2ca1335ecd6"},
|
||||
{"id": "f6e4c5cba1dc008f9b9611515ba163ccd1489105265dc8b2809eb846c1b94209"},
|
||||
{"id": "cd4c4f1e65bd1f351dabf8c04fe2903b043ce98ce5613808c027c6609a0556d5"},
|
||||
{"id": "9b0172004b25ee43e517ed6dd969bceb3fef4db3a577f91d8a3dc9cb6fe4e1d1"},
|
||||
{"id": "ca0ee728c85f4df5ffab3561f55fdd2295291a86cd409839c59b92903d041025"},
|
||||
{"id": "c589506d090796e304763dc269731029be08dee1706c1e87413fb376a2e84a97"},
|
||||
{"id": "99ea6a5a7701c255661fc2bea32cb615ca0d4674c45fe6633e58e7eeb5f92873"},
|
||||
{"id": "8e55f6ec8de9e8b4f75e3a771c601c1583855b5d113124ac9fb997b8589117fc"},
|
||||
{"id": "11803eb1505d5014bc13c48621638a94f0b852587f0b5adbcb3ee471d9488ec3"},
|
||||
{"id": "488cf9801acccc925b75d6828287ecaaff8b2bee9b58ce26fa0a2abdd61bd155"},
|
||||
{"id": "0e9bc4a5989a39d4fc7ba73876c88822928b1cc965ed158b431759378363c182"},
|
||||
{"id": "386b2cd47df9260f5b313b151ae988d0710e83e615dfd2abc948f1fa93eb76d6"},
|
||||
{"id": "a451833e4856194aa5f56508eb34c298a5718539b9d320a2b7b30f32a107cc37"},
|
||||
{"id": "91c0639025aba28c5af2178f49d653757bcc68e88d7cc461c86edc1ac2a61942"},
|
||||
{"id": "aaf0b0846e265dec3dcf7b943ea2fc0331daf29a6114ac2eb971c10988e73f6d"},
|
||||
{"id": "d26a9c5d89b9ce197e03bf91e2768df571cf04df796b5ae08742aea97be1c8c5"},
|
||||
{"id": "490debe9303abe3c72fae49c62f8be15556a78c77c4d74e82305c5ce5723986a"}
|
||||
]
|
||||
@@ -1,4 +0,0 @@
|
||||
[
|
||||
{"id": "1c986b929f61d7a696719c9f92d41e2163e82c0fcdf30779a09f9b70886ad59c", "name": "Noogle: Latest" },
|
||||
{"id": "d70aea7efa004887514b0c6b53d0448029303989c6fc33ba37f2315ca77a4170", "name": "Noogle: One year ago"}
|
||||
]
|
||||
@@ -1,7 +0,0 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -1,7 +0,0 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
|
||||
<path
|
||||
d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -1,7 +0,0 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -1,7 +0,0 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
|
||||
<path
|
||||
d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -1,19 +0,0 @@
|
||||
<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
|
||||
<template>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
class="iconify iconify--mdi"
|
||||
width="24"
|
||||
height="24"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -1,43 +0,0 @@
|
||||
<script>
|
||||
import store from "@/store.js";
|
||||
|
||||
export default {
|
||||
name: "modaltest",
|
||||
computed: {
|
||||
store() {
|
||||
return store
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
users: [],
|
||||
isModalVisible: false,
|
||||
userModal: {},
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
openModal(user) {
|
||||
this.userModal = user;
|
||||
this.isModalVisible = true;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-for="user in store.state.nip89dvms" :key="user.id">
|
||||
<button @click="openModal(user)">open modal</button>
|
||||
</div>
|
||||
|
||||
<Modal v-show="isModalVisible" @close="closeModal">
|
||||
<p>TEST</p>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,107 +0,0 @@
|
||||
<script setup>
|
||||
import Nip07 from "@/components/Nip07.vue";
|
||||
import Donate from "@/components/Donate.vue"
|
||||
import {isVisible} from "bootstrap/js/src/util/index.js";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
<div className="navbar bg-base-100">
|
||||
<div className="flex-none">
|
||||
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<router-link class="menu" to="/">Noogle</router-link>
|
||||
<router-link class="menu" to="/image">ImageGen</router-link>
|
||||
<router-link class="menu" to="/about">About</router-link>
|
||||
<router-link class="menu" to="/nip89">DVMs</router-link>
|
||||
|
||||
|
||||
</div>
|
||||
<Nip07/>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="three-column-layout">
|
||||
<header>
|
||||
|
||||
<!-- <AppLogo />-->
|
||||
|
||||
</header>
|
||||
|
||||
<main >
|
||||
<router-view />
|
||||
<slot/>
|
||||
</main>
|
||||
|
||||
<aside>
|
||||
<slot name="aside" />
|
||||
|
||||
</aside>
|
||||
<footer>
|
||||
<Donate style="margin-top: 4px"/>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.three-column-layout {
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
"header"
|
||||
"main"
|
||||
"aside"
|
||||
"footer";
|
||||
|
||||
header {
|
||||
grid-area: header;
|
||||
margin-top: 30px;
|
||||
}
|
||||
main {
|
||||
|
||||
grid-area: main;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 100px;
|
||||
padding: 20px;
|
||||
|
||||
}
|
||||
footer{
|
||||
|
||||
position: fixed;
|
||||
bottom:0;
|
||||
background: rgba(0, 0, 0, 0.5);;
|
||||
grid-area: footer;
|
||||
width: 100vw;
|
||||
height: 32px;
|
||||
|
||||
z-index: 10;
|
||||
text-align: center;
|
||||
}
|
||||
aside {
|
||||
grid-area: aside;
|
||||
margin-top: 10px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
|
||||
.router-link-exact-active{
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
}
|
||||
|
||||
|
||||
.v-Button {
|
||||
@apply bg-black hover:bg-nostr focus:ring-nostr mb-2 inline-flex flex-none items-center rounded-lg border border-nostr px-3 py-1.5 text-sm leading-4 text-white transition-colors duration-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-white dark:focus:ring-offset-gray-900;
|
||||
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@media (min-width: 768px) {
|
||||
grid-template-columns: 1fr 3fr 1fr;
|
||||
grid-template-areas: "header main aside footer";
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,44 +0,0 @@
|
||||
//import './assets/main.css'
|
||||
import { createApp } from 'vue'
|
||||
|
||||
import App from './App.vue'
|
||||
import store from './store';
|
||||
import "./app.css"
|
||||
|
||||
import 'vue3-easy-data-table/dist/style.css';
|
||||
import router from './router'
|
||||
import Vue3EasyDataTable from 'vue3-easy-data-table';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//This is all for notifications
|
||||
import VueNotifications from "vue-notifications";
|
||||
import miniToastr from 'mini-toastr'
|
||||
|
||||
miniToastr.init()
|
||||
|
||||
|
||||
function toast ({title, message, type, timeout, cb}) {
|
||||
return miniToastr[type](message, title, timeout, cb)
|
||||
}
|
||||
|
||||
const options = {
|
||||
success: toast,
|
||||
error: toast,
|
||||
info: toast,
|
||||
warn: toast
|
||||
}
|
||||
//This is all for notifications end
|
||||
|
||||
|
||||
|
||||
|
||||
createApp(App)
|
||||
.use(VueNotifications, options)
|
||||
.use(store)
|
||||
.use(router)
|
||||
|
||||
.component('EasyDataTable', Vue3EasyDataTable)
|
||||
.mount('#app')
|
||||
@@ -1,20 +0,0 @@
|
||||
import { createWebHistory, createRouter } from "vue-router";
|
||||
|
||||
|
||||
|
||||
const routes = [
|
||||
{ path: "/", component: () => import("@/components/Home.vue") },
|
||||
{ path: "/about", component: () => import("@/components/AboutPage.vue") },
|
||||
{ path: "/donate", component: () => import("@/components/Donate.vue") },
|
||||
{ path: "/nip89", component: () => import("@/components/Nip89view.vue") },
|
||||
{ path: "/image", component: () => import("@/components/Image.vue") },
|
||||
{ path: "/article/:id", component: () => import("@/components/Home.vue") },
|
||||
{ path: '/:pathMatch(.*)*', component: () => import("@/components/Home.vue") },
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes,
|
||||
});
|
||||
|
||||
export default router;
|
||||
@@ -1,59 +0,0 @@
|
||||
import {createStore} from "vuex";
|
||||
import {Client, ClientSigner, PublicKey} from "@rust-nostr/nostr-sdk";
|
||||
|
||||
const store = createStore({
|
||||
state () {
|
||||
return {
|
||||
count: 0,
|
||||
test: "hello",
|
||||
client: Client,
|
||||
pubkey: PublicKey,
|
||||
requestidSearch: String,
|
||||
requestidImage: String,
|
||||
hasEventListener: false,
|
||||
imagehasEventListener: false,
|
||||
imagedvmreplies: [],
|
||||
nip89dvms: [],
|
||||
results: [],
|
||||
relays: ["wss://relay.damus.io", "wss://nos.lol", "wss://pablof7z.nostr1.com", "wss://relay.nostr.net", "wss://relay.nostr.net", "wss://relay.nostr.band", "wss://nostr-pub.wellorder.net"],
|
||||
}
|
||||
},
|
||||
mutations: {
|
||||
increment (state) {
|
||||
state.count++
|
||||
},
|
||||
set_client (state, client) {
|
||||
state.client = client
|
||||
},
|
||||
set_pubkey(state, pubkey) {
|
||||
state.pubkey = pubkey
|
||||
},
|
||||
set_hasEventListener(state, hasEventListener) {
|
||||
state.hasEventListener = hasEventListener
|
||||
},
|
||||
set_imagehasEventListener(state, imagehasEventListener) {
|
||||
state.imagehasEventListener = imagehasEventListener
|
||||
},
|
||||
set_nip89dvms(state, nip89dvms) {
|
||||
state.nip89dvms.length = 0
|
||||
state.nip89dvms.push.apply(state.nip89dvms, nip89dvms)
|
||||
},
|
||||
set_current_request_id_search(state, requestid){
|
||||
state.requestidSearch = requestid
|
||||
},
|
||||
set_current_request_id_image(state, requestid){
|
||||
state.requestidImage = requestid
|
||||
},
|
||||
set_search_results(state, results){
|
||||
state.results.length = 0
|
||||
state.results.push.apply(state.results, results)
|
||||
},
|
||||
set_imagedvm_results(state, results){
|
||||
state.imagedvmreplies.length = 0
|
||||
state.imagedvmreplies.push.apply(state.imagedvmreplies, results)
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
export default store;
|
||||
@@ -1,21 +0,0 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: [
|
||||
"./index.html",
|
||||
"./src/**/*.{vue,js,ts,jsx,tsx}",
|
||||
|
||||
],
|
||||
theme: {
|
||||
|
||||
extend: {
|
||||
colors:{
|
||||
'nostr': '#6d52f1',
|
||||
'nostr2': '#8453f1',
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
plugins: [require("daisyui")],
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import { fileURLToPath, URL } from 'node:url'
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user