mirror of
https://github.com/luminous-devs/lume.git
synced 2024-09-19 19:46:34 +00:00
wip: convert tauri sql to prisma
This commit is contained in:
parent
9b8a96c651
commit
39e7c9bf34
3
src-tauri/.gitignore
vendored
3
src-tauri/.gitignore
vendored
@ -3,4 +3,5 @@
|
|||||||
/target/
|
/target/
|
||||||
|
|
||||||
# prisma
|
# prisma
|
||||||
src/prisma.rs
|
src/db.rs
|
||||||
|
lume.db
|
||||||
|
1
src-tauri/Cargo.lock
generated
1
src-tauri/Cargo.lock
generated
@ -2193,6 +2193,7 @@ dependencies = [
|
|||||||
"tauri",
|
"tauri",
|
||||||
"tauri-build",
|
"tauri-build",
|
||||||
"tauri-specta",
|
"tauri-specta",
|
||||||
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -21,6 +21,7 @@ prisma-client-rust = { git = "https://github.com/Brendonovich/prisma-client-rust
|
|||||||
prisma-client-rust-cli = { git = "https://github.com/Brendonovich/prisma-client-rust", tag = "0.6.7", default-features = false, features = ["sqlite", "migrations", "mocking", "specta"] }
|
prisma-client-rust-cli = { git = "https://github.com/Brendonovich/prisma-client-rust", tag = "0.6.7", default-features = false, features = ["sqlite", "migrations", "mocking", "specta"] }
|
||||||
specta = "1.0.0"
|
specta = "1.0.0"
|
||||||
tauri-specta = { version = "1.0.0", features = ["typescript"] }
|
tauri-specta = { version = "1.0.0", features = ["typescript"] }
|
||||||
|
tokio = { version = "1.26.0", features = ["macros"] }
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
objc = "0.2.7"
|
objc = "0.2.7"
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
-- Add migration script here
|
|
||||||
-- create relays
|
|
||||||
CREATE TABLE
|
|
||||||
relays (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
relay_url TEXT NOT NULL,
|
|
||||||
relay_status INTEGER NOT NULL DEFAULT 1,
|
|
||||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
||||||
);
|
|
||||||
|
|
||||||
-- add default relays
|
|
||||||
-- relay status:
|
|
||||||
-- 0: off
|
|
||||||
-- 1: on
|
|
||||||
INSERT INTO
|
|
||||||
relays (relay_url, relay_status)
|
|
||||||
VALUES
|
|
||||||
("wss://relay.damus.io", "1"),
|
|
||||||
("wss://eden.nostr.land", "0"),
|
|
||||||
("wss://nostr-pub.wellorder.net", "1"),
|
|
||||||
("wss://nostr.bongbong.com", "1"),
|
|
||||||
("wss://nostr.zebedee.cloud", "1"),
|
|
||||||
("wss://nostr.fmt.wiz.biz", "1"),
|
|
||||||
("wss://nostr.walletofsatoshi.com", "0"),
|
|
||||||
("wss://relay.snort.social", "1"),
|
|
||||||
("wss://offchain.pub", "1"),
|
|
||||||
("wss://brb.io", "0"),
|
|
||||||
("wss://relay.current.fyi", "1"),
|
|
||||||
("wss://nostr.relayer.se", "0"),
|
|
||||||
("wss://nostr.bitcoiner.social", "1"),
|
|
||||||
("wss://relay.nostr.info", "1"),
|
|
||||||
("wss://relay.zeh.app", "0"),
|
|
||||||
("wss://nostr-01.dorafactory.org", "1"),
|
|
||||||
("wss://nostr.zhongwen.world", "1"),
|
|
||||||
("wss://nostro.cc", "1"),
|
|
||||||
("wss://relay.nostr.net.in", "1"),
|
|
||||||
("wss://nos.lol", "1");
|
|
||||||
|
|
||||||
-- create accounts
|
|
||||||
-- is_active (part of multi-account feature):
|
|
||||||
-- 0: false
|
|
||||||
-- 1: true
|
|
||||||
CREATE TABLE
|
|
||||||
accounts (
|
|
||||||
id TEXT PRIMARY KEY,
|
|
||||||
privkey TEXT NOT NULL,
|
|
||||||
npub TEXT NOT NULL,
|
|
||||||
nsec TEXT NOT NULL,
|
|
||||||
is_active INTEGER NOT NULL DEFAULT 0,
|
|
||||||
metadata TEXT
|
|
||||||
);
|
|
||||||
|
|
||||||
-- create follows
|
|
||||||
-- kind (part of multi-newsfeed feature):
|
|
||||||
-- 0: direct
|
|
||||||
-- 1: follow of follow
|
|
||||||
CREATE TABLE
|
|
||||||
follows (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
pubkey TEXT NOT NULL,
|
|
||||||
account TEXT NOT NULL,
|
|
||||||
kind INTEGER NOT NULL DEFAULT 0,
|
|
||||||
metadata TEXT
|
|
||||||
);
|
|
||||||
|
|
||||||
-- create index for pubkey in follows
|
|
||||||
CREATE UNIQUE INDEX index_pubkey_on_follows ON follows (pubkey);
|
|
||||||
|
|
||||||
-- create cache profiles
|
|
||||||
CREATE TABLE
|
|
||||||
cache_profiles (
|
|
||||||
id TEXT PRIMARY KEY,
|
|
||||||
metadata TEXT,
|
|
||||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
||||||
);
|
|
||||||
|
|
||||||
-- create cache notes
|
|
||||||
CREATE TABLE
|
|
||||||
cache_notes (
|
|
||||||
id TEXT PRIMARY KEY,
|
|
||||||
pubkey TEXT NOT NULL,
|
|
||||||
created_at TEXT,
|
|
||||||
kind INTEGER NOT NULL DEFAULT 1,
|
|
||||||
tags TEXT NOT NULL,
|
|
||||||
content TEXT NOT NULL,
|
|
||||||
parent_id TEXT,
|
|
||||||
parent_comment_id TEXT
|
|
||||||
);
|
|
||||||
|
|
||||||
-- create settings
|
|
||||||
CREATE TABLE
|
|
||||||
settings (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
setting_key TEXT NOT NULL,
|
|
||||||
setting_value TEXT NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
-- add default setting
|
|
||||||
INSERT INTO
|
|
||||||
settings (setting_key, setting_value)
|
|
||||||
VALUES
|
|
||||||
("last_login", "0");
|
|
@ -1,11 +1,75 @@
|
|||||||
datasource db {
|
datasource db {
|
||||||
provider = "sqlite"
|
provider = "sqlite"
|
||||||
url = "file:lume.db"
|
url = "file:../lume.db"
|
||||||
}
|
}
|
||||||
|
|
||||||
generator client {
|
generator client {
|
||||||
// Corresponds to the cargo alias created earlier
|
|
||||||
provider = "cargo prisma"
|
provider = "cargo prisma"
|
||||||
// The location to generate the client. Is relative to the position of the schema
|
// The location to generate the client. Is relative to the position of the schema
|
||||||
output = "../src/prisma.rs"
|
output = "../src/db.rs"
|
||||||
|
module_path = "db"
|
||||||
|
}
|
||||||
|
|
||||||
|
model Account {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
pubkey String
|
||||||
|
privkey String @unique
|
||||||
|
active Boolean @default(false)
|
||||||
|
metadata String
|
||||||
|
|
||||||
|
// related
|
||||||
|
follows Follow[]
|
||||||
|
messages Message[]
|
||||||
|
notes Note[]
|
||||||
|
|
||||||
|
@@index([pubkey])
|
||||||
|
}
|
||||||
|
|
||||||
|
model Follow {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
pubkey String
|
||||||
|
kind Int
|
||||||
|
metadata String
|
||||||
|
|
||||||
|
Account Account @relation(fields: [accountId], references: [id])
|
||||||
|
accountId Int
|
||||||
|
}
|
||||||
|
|
||||||
|
model Note {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
pubkey String
|
||||||
|
kind Int
|
||||||
|
tags String
|
||||||
|
content String
|
||||||
|
parent_id String
|
||||||
|
parent_comment_id String
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
Account Account @relation(fields: [accountId], references: [id])
|
||||||
|
accountId Int
|
||||||
|
}
|
||||||
|
|
||||||
|
model Message {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
pubkey String
|
||||||
|
content String
|
||||||
|
tags String
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
Account Account @relation(fields: [accountId], references: [id])
|
||||||
|
accountId Int
|
||||||
|
|
||||||
|
@@index([pubkey])
|
||||||
|
}
|
||||||
|
|
||||||
|
model Relay {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
url String
|
||||||
|
active Boolean @default(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
model Setting {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
key String
|
||||||
|
value String
|
||||||
}
|
}
|
||||||
|
@ -8,13 +8,87 @@
|
|||||||
extern crate objc;
|
extern crate objc;
|
||||||
|
|
||||||
use tauri::{Manager, WindowEvent};
|
use tauri::{Manager, WindowEvent};
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
use window_ext::WindowExt;
|
use window_ext::WindowExt;
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
mod window_ext;
|
mod window_ext;
|
||||||
|
|
||||||
fn main() {
|
mod db;
|
||||||
|
|
||||||
|
use db::*;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use specta::{collect_types, Type};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tauri::State;
|
||||||
|
use tauri_specta::ts;
|
||||||
|
|
||||||
|
type DbState<'a> = State<'a, Arc<PrismaClient>>;
|
||||||
|
|
||||||
|
#[derive(Deserialize, Type)]
|
||||||
|
struct CreateAccountData {
|
||||||
|
pubkey: String,
|
||||||
|
privkey: String,
|
||||||
|
metadata: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Type)]
|
||||||
|
struct CreateFollowData {
|
||||||
|
pubkey: String,
|
||||||
|
kind: i32,
|
||||||
|
metadata: String,
|
||||||
|
account_id: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
#[specta::specta]
|
||||||
|
async fn get_account(db: DbState<'_>) -> Result<Vec<account::Data>, ()> {
|
||||||
|
db.account()
|
||||||
|
.find_many(vec![account::active::equals(true)])
|
||||||
|
.exec()
|
||||||
|
.await
|
||||||
|
.map_err(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
#[specta::specta]
|
||||||
|
async fn create_account(db: DbState<'_>, data: CreateAccountData) -> Result<account::Data, ()> {
|
||||||
|
db.account()
|
||||||
|
.create(data.pubkey, data.privkey, data.metadata, vec![])
|
||||||
|
.exec()
|
||||||
|
.await
|
||||||
|
.map_err(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
#[specta::specta]
|
||||||
|
async fn create_follow(db: DbState<'_>, data: CreateFollowData) -> Result<follow::Data, ()> {
|
||||||
|
db.follow()
|
||||||
|
.create(
|
||||||
|
data.pubkey,
|
||||||
|
data.kind,
|
||||||
|
data.metadata,
|
||||||
|
account::id::equals(data.account_id),
|
||||||
|
vec![],
|
||||||
|
)
|
||||||
|
.exec()
|
||||||
|
.await
|
||||||
|
.map_err(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
let db = PrismaClient::_builder().build().await.unwrap();
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
ts::export(
|
||||||
|
collect_types![get_account, create_account, create_follow],
|
||||||
|
"../src/utils/bindings.ts",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
db._db_push().await.unwrap();
|
||||||
|
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
let main_window = app.get_window("main").unwrap();
|
let main_window = app.get_window("main").unwrap();
|
||||||
@ -38,6 +112,12 @@ fn main() {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.invoke_handler(tauri::generate_handler![
|
||||||
|
get_account,
|
||||||
|
create_account,
|
||||||
|
create_follow
|
||||||
|
])
|
||||||
|
.manage(Arc::new(db))
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
}
|
}
|
||||||
|
@ -2,24 +2,27 @@ import BaseLayout from '@layouts/base';
|
|||||||
|
|
||||||
import { activeAccountAtom } from '@stores/account';
|
import { activeAccountAtom } from '@stores/account';
|
||||||
|
|
||||||
import { getActiveAccount } from '@utils/storage';
|
|
||||||
|
|
||||||
import LumeSymbol from '@assets/icons/Lume';
|
import LumeSymbol from '@assets/icons/Lume';
|
||||||
|
|
||||||
import { useSetAtom } from 'jotai';
|
import { useSetAtom } from 'jotai';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useEffect } from 'react';
|
import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useCallback, useEffect } from 'react';
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const setActiveAccount = useSetAtom(activeAccountAtom);
|
const setActiveAccount = useSetAtom(activeAccountAtom);
|
||||||
|
|
||||||
|
const fetchActiveAccount = useCallback(async () => {
|
||||||
|
const { getAccount } = await import('@utils/bindings');
|
||||||
|
return await getAccount();
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getActiveAccount()
|
fetchActiveAccount()
|
||||||
.then((res: any) => {
|
.then((res: any) => {
|
||||||
if (res) {
|
if (res.length > 0) {
|
||||||
// update local storage
|
// update local storage
|
||||||
setActiveAccount(res);
|
setActiveAccount(res[0]);
|
||||||
// redirect
|
// redirect
|
||||||
router.replace('/init');
|
router.replace('/init');
|
||||||
} else {
|
} else {
|
||||||
@ -27,7 +30,7 @@ export default function Page() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(console.error);
|
.catch(console.error);
|
||||||
}, [router, setActiveAccount]);
|
}, [fetchActiveAccount, setActiveAccount, router]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative h-full overflow-hidden">
|
<div className="relative h-full overflow-hidden">
|
||||||
|
@ -2,13 +2,20 @@ import BaseLayout from '@layouts/base';
|
|||||||
|
|
||||||
import { RelayContext } from '@components/relaysProvider';
|
import { RelayContext } from '@components/relaysProvider';
|
||||||
|
|
||||||
import { createAccount } from '@utils/storage';
|
|
||||||
|
|
||||||
import { ArrowLeftIcon, EyeClosedIcon, EyeOpenIcon } from '@radix-ui/react-icons';
|
import { ArrowLeftIcon, EyeClosedIcon, EyeOpenIcon } from '@radix-ui/react-icons';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { generatePrivateKey, getEventHash, getPublicKey, nip19, signEvent } from 'nostr-tools';
|
import { generatePrivateKey, getEventHash, getPublicKey, nip19, signEvent } from 'nostr-tools';
|
||||||
import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useContext, useMemo, useState } from 'react';
|
import {
|
||||||
|
JSXElementConstructor,
|
||||||
|
ReactElement,
|
||||||
|
ReactFragment,
|
||||||
|
ReactPortal,
|
||||||
|
useCallback,
|
||||||
|
useContext,
|
||||||
|
useMemo,
|
||||||
|
useState,
|
||||||
|
} from 'react';
|
||||||
import { Config, names, uniqueNamesGenerator } from 'unique-names-generator';
|
import { Config, names, uniqueNamesGenerator } from 'unique-names-generator';
|
||||||
|
|
||||||
const config: Config = {
|
const config: Config = {
|
||||||
@ -39,23 +46,11 @@ export default function Page() {
|
|||||||
display_name: name,
|
display_name: name,
|
||||||
name: name,
|
name: name,
|
||||||
username: name.toLowerCase(),
|
username: name.toLowerCase(),
|
||||||
picture: 'https://void.cat/d/KmypFh2fBdYCEvyJrPiN89',
|
picture: 'https://void.cat/d/KmypFh2fBdYCEvyJrPiN89.webp',
|
||||||
}),
|
}),
|
||||||
[name]
|
[name]
|
||||||
);
|
);
|
||||||
|
|
||||||
// build profile
|
|
||||||
const data = useMemo(
|
|
||||||
() => ({
|
|
||||||
pubkey: pubKey,
|
|
||||||
privkey: privKey,
|
|
||||||
npub: npub,
|
|
||||||
nsec: nsec,
|
|
||||||
metadata: metadata,
|
|
||||||
}),
|
|
||||||
[metadata, npub, nsec, privKey, pubKey]
|
|
||||||
);
|
|
||||||
|
|
||||||
// toggle privatek key
|
// toggle privatek key
|
||||||
const showPrivateKey = () => {
|
const showPrivateKey = () => {
|
||||||
if (type === 'password') {
|
if (type === 'password') {
|
||||||
@ -66,7 +61,8 @@ export default function Page() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// create account and broadcast to all relays
|
// create account and broadcast to all relays
|
||||||
const submit = () => {
|
const submit = useCallback(async () => {
|
||||||
|
const { createAccount } = await import('@utils/bindings');
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
// build event
|
// build event
|
||||||
@ -81,16 +77,16 @@ export default function Page() {
|
|||||||
event.sig = signEvent(event, privKey);
|
event.sig = signEvent(event, privKey);
|
||||||
|
|
||||||
// insert to database then broadcast
|
// insert to database then broadcast
|
||||||
createAccount(data)
|
createAccount({ pubkey: pubKey, privkey: privKey, metadata: JSON.stringify(metadata) })
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
pool.publish(event, relays);
|
pool.publish(event, relays);
|
||||||
router.push({
|
router.push({
|
||||||
pathname: '/onboarding/create/step-2',
|
pathname: '/onboarding/create/step-2',
|
||||||
query: { id: pubKey, privkey: privKey },
|
query: { id: res.id, privkey: res.privkey },
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(console.error);
|
.catch(console.error);
|
||||||
};
|
}, [pool, pubKey, privKey, metadata, relays, router]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid h-full w-full grid-rows-5">
|
<div className="grid h-full w-full grid-rows-5">
|
||||||
|
@ -3,7 +3,7 @@ import BaseLayout from '@layouts/base';
|
|||||||
import { RelayContext } from '@components/relaysProvider';
|
import { RelayContext } from '@components/relaysProvider';
|
||||||
import { UserBase } from '@components/user/base';
|
import { UserBase } from '@components/user/base';
|
||||||
|
|
||||||
import { createFollows } from '@utils/storage';
|
import { followsTag } from '@utils/transform';
|
||||||
|
|
||||||
import { CheckCircledIcon } from '@radix-ui/react-icons';
|
import { CheckCircledIcon } from '@radix-ui/react-icons';
|
||||||
import { createClient } from '@supabase/supabase-js';
|
import { createClient } from '@supabase/supabase-js';
|
||||||
@ -15,6 +15,7 @@ import {
|
|||||||
ReactElement,
|
ReactElement,
|
||||||
ReactFragment,
|
ReactFragment,
|
||||||
ReactPortal,
|
ReactPortal,
|
||||||
|
useCallback,
|
||||||
useContext,
|
useContext,
|
||||||
useEffect,
|
useEffect,
|
||||||
useState,
|
useState,
|
||||||
@ -76,18 +77,9 @@ export default function Page() {
|
|||||||
setFollows(arr);
|
setFollows(arr);
|
||||||
};
|
};
|
||||||
|
|
||||||
// build event tags
|
|
||||||
const tags = () => {
|
|
||||||
const arr = [];
|
|
||||||
// push item to tags
|
|
||||||
follows.forEach((item) => {
|
|
||||||
arr.push(['p', item]);
|
|
||||||
});
|
|
||||||
return arr;
|
|
||||||
};
|
|
||||||
|
|
||||||
// save follows to database then broadcast
|
// save follows to database then broadcast
|
||||||
const submit = () => {
|
const submit = useCallback(async () => {
|
||||||
|
const { createFollow } = await import('@utils/bindings');
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
// build event
|
// build event
|
||||||
@ -96,21 +88,18 @@ export default function Page() {
|
|||||||
created_at: Math.floor(Date.now() / 1000),
|
created_at: Math.floor(Date.now() / 1000),
|
||||||
kind: 3,
|
kind: 3,
|
||||||
pubkey: id,
|
pubkey: id,
|
||||||
tags: tags(),
|
tags: followsTag(follows),
|
||||||
};
|
};
|
||||||
event.id = getEventHash(event);
|
event.id = getEventHash(event);
|
||||||
event.sig = signEvent(event, privkey);
|
event.sig = signEvent(event, privkey);
|
||||||
|
|
||||||
createFollows(follows, id, 0)
|
follows.forEach((item) => {
|
||||||
.then((res) => {
|
createFollow({ pubkey: item, kind: 0, metadata: JSON.stringify({}), account_id: id });
|
||||||
if (res === 'ok') {
|
});
|
||||||
// publish to relays
|
|
||||||
pool.publish(event, relays);
|
pool.publish(event, relays);
|
||||||
router.replace('/');
|
router.replace('/');
|
||||||
}
|
}, [follows, id, pool, privkey, relays, router]);
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
|
26
src/utils/bindings.ts
Normal file
26
src/utils/bindings.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// This file was generated by [tauri-specta](https://github.com/oscartbeaumont/tauri-specta). Do not edit this file manually.
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
__TAURI_INVOKE__<T>(cmd: string, args?: Record<string, unknown>): Promise<T>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const invoke = window.__TAURI_INVOKE__;
|
||||||
|
|
||||||
|
export function getAccount() {
|
||||||
|
return invoke<Account[]>('get_account');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createAccount(data: CreateAccountData) {
|
||||||
|
return invoke<Account>('create_account', { data });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createFollow(data: CreateFollowData) {
|
||||||
|
return invoke<Follow>('create_follow', { data });
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Account = { id: number; pubkey: string; privkey: string; active: boolean; metadata: string };
|
||||||
|
export type Follow = { id: number; pubkey: string; kind: number; metadata: string; accountId: number };
|
||||||
|
export type CreateFollowData = { pubkey: string; kind: number; metadata: string; account_id: number };
|
||||||
|
export type CreateAccountData = { pubkey: string; privkey: string; metadata: string };
|
@ -9,6 +9,15 @@ export const tagsToArray = (arr) => {
|
|||||||
return newarr;
|
return newarr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const followsTag = (arr) => {
|
||||||
|
const newarr = [];
|
||||||
|
// push item to tags
|
||||||
|
arr.forEach((item) => {
|
||||||
|
arr.push(['p', item]);
|
||||||
|
});
|
||||||
|
return newarr;
|
||||||
|
};
|
||||||
|
|
||||||
export const pubkeyArray = (arr) => {
|
export const pubkeyArray = (arr) => {
|
||||||
const newarr = [];
|
const newarr = [];
|
||||||
// push item to newarr
|
// push item to newarr
|
||||||
|
Loading…
Reference in New Issue
Block a user