chore: setup tauri
This commit is contained in:
1656
src-tauri/Cargo.lock
generated
1656
src-tauri/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -11,8 +11,35 @@ edition = "2021"
|
||||
tauri-build = { version = "2.0.0-beta", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "2.0.0-beta", features = [] }
|
||||
nostr-sdk = { version = "0.33", features = ["sqlite"] }
|
||||
tauri = { version = "2.0.0-beta", features = [
|
||||
"tray-icon",
|
||||
"macos-private-api",
|
||||
"protocol-asset",
|
||||
] }
|
||||
tauri-plugin-shell = "2.0.0-beta"
|
||||
tauri-plugin-decorum = "0.1.5"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
keyring = { version = "3", features = [
|
||||
"apple-native",
|
||||
"windows-native",
|
||||
"linux-native",
|
||||
] }
|
||||
keyring-search = "1.2.0"
|
||||
itertools = "0.13.0"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
border = { git = "https://github.com/ahkohd/tauri-toolkit", branch = "v2" }
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
lto = true
|
||||
panic = "abort"
|
||||
incremental = false
|
||||
opt-level = "z"
|
||||
strip = true
|
||||
rpath = false
|
||||
debug = false
|
||||
debug-assertions = false
|
||||
overflow-checks = false
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "Capability for the main window",
|
||||
"windows": ["main"],
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"permissions": [
|
||||
"path:default",
|
||||
"event:default",
|
||||
@@ -12,6 +14,14 @@
|
||||
"resources:default",
|
||||
"menu:default",
|
||||
"tray:default",
|
||||
"shell:allow-open"
|
||||
"shell:allow-open",
|
||||
"window:allow-close",
|
||||
"window:allow-center",
|
||||
"window:allow-minimize",
|
||||
"window:allow-maximize",
|
||||
"window:allow-set-size",
|
||||
"window:allow-set-focus",
|
||||
"window:allow-start-dragging",
|
||||
"decorum:allow-show-snap-overlay"
|
||||
]
|
||||
}
|
||||
|
||||
100
src-tauri/src/commands/account.rs
Normal file
100
src-tauri/src/commands/account.rs
Normal file
@@ -0,0 +1,100 @@
|
||||
use itertools::Itertools;
|
||||
use keyring::Entry;
|
||||
use keyring_search::{Limit, List, Search};
|
||||
use nostr_sdk::prelude::*;
|
||||
use std::{collections::HashSet, str::FromStr};
|
||||
use tauri::State;
|
||||
|
||||
use crate::Nostr;
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_accounts() -> Vec<String> {
|
||||
let search = Search::new().expect("Unexpected.");
|
||||
let results = search.by_user("nostr_secret");
|
||||
let list = List::list_credentials(&results, Limit::All);
|
||||
let accounts: HashSet<String> =
|
||||
list.split_whitespace().filter(|v| v.starts_with("npub1")).map(String::from).collect();
|
||||
|
||||
accounts.into_iter().collect()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_profile(id: String, state: State<'_, Nostr>) -> Result<String, ()> {
|
||||
let client = &state.client;
|
||||
let public_key = PublicKey::from_str(&id).unwrap();
|
||||
let filter = Filter::new().author(public_key).kind(Kind::Metadata).limit(1);
|
||||
|
||||
let events = client.get_events_of(vec![filter], None).await.unwrap();
|
||||
|
||||
if let Some(event) = events.first() {
|
||||
Ok(Metadata::from_json(&event.content).unwrap().as_json())
|
||||
} else {
|
||||
Ok(Metadata::new().as_json())
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn login(id: String, state: State<'_, Nostr>) -> Result<(), String> {
|
||||
let client = &state.client;
|
||||
let keyring = Entry::new(&id, "nostr_secret").expect("Unexpected.");
|
||||
|
||||
let password = match keyring.get_password() {
|
||||
Ok(pw) => pw,
|
||||
Err(_) => return Err("Cancelled".into()),
|
||||
};
|
||||
|
||||
let keys = Keys::parse(password).expect("Secret Key is modified, please check again.");
|
||||
let signer = NostrSigner::Keys(keys);
|
||||
|
||||
// Set signer
|
||||
client.set_signer(Some(signer)).await;
|
||||
|
||||
let public_key = PublicKey::from_str(&id).unwrap();
|
||||
let incoming = Filter::new().kind(Kind::GiftWrap).pubkey(public_key);
|
||||
let inbox = Filter::new().kind(Kind::Custom(10050)).author(public_key).limit(1);
|
||||
|
||||
if let Ok(events) = client.get_events_of(vec![inbox], None).await {
|
||||
if let Some(event) = events.into_iter().next() {
|
||||
for tag in &event.tags {
|
||||
if let Some(TagStandard::Relay(url)) = tag.as_standardized() {
|
||||
let relay = url.to_string();
|
||||
let _ = client.add_relay(&relay).await;
|
||||
let _ = client.connect_relay(&relay).await;
|
||||
|
||||
println!("Connecting to {} ...", relay);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(report) = client.reconcile(incoming.clone(), NegentropyOptions::default()).await {
|
||||
let receives = report.received.clone();
|
||||
let ids = receives.into_iter().collect::<Vec<_>>();
|
||||
|
||||
if let Ok(events) = client.database().query(vec![Filter::new().ids(ids)], Order::Desc).await
|
||||
{
|
||||
let pubkeys = events
|
||||
.into_iter()
|
||||
.unique_by(|ev| ev.pubkey)
|
||||
.map(|ev| ev.pubkey)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if client
|
||||
.reconcile(
|
||||
Filter::new().kind(Kind::GiftWrap).pubkeys(pubkeys),
|
||||
NegentropyOptions::default(),
|
||||
)
|
||||
.await
|
||||
.is_ok()
|
||||
{
|
||||
println!("Sync done.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if client.subscribe(vec![incoming.limit(0)], None).await.is_ok() {
|
||||
println!("Waiting for new message...")
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
1
src-tauri/src/commands/mod.rs
Normal file
1
src-tauri/src/commands/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod account;
|
||||
@@ -1,16 +1,66 @@
|
||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
|
||||
#[tauri::command]
|
||||
fn greet(name: &str) -> String {
|
||||
format!("Hello, {}! You've been greeted from Rust!", name)
|
||||
use border::WebviewWindowExt as WebviewWindowExtAlt;
|
||||
use commands::account::{get_accounts, get_profile, login};
|
||||
use nostr_sdk::prelude::*;
|
||||
use serde::Serialize;
|
||||
use std::{fs, sync::Mutex};
|
||||
use tauri::Manager;
|
||||
use tauri_plugin_decorum::WebviewWindowExt;
|
||||
|
||||
mod commands;
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct Nostr {
|
||||
#[serde(skip_serializing)]
|
||||
client: Client,
|
||||
contact_list: Mutex<Vec<Contact>>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
let main_window = app.get_webview_window("main").unwrap();
|
||||
|
||||
// Set custom decoration
|
||||
main_window.create_overlay_titlebar().unwrap();
|
||||
|
||||
// Restore native border
|
||||
#[cfg(target_os = "macos")]
|
||||
main_window.add_border(None);
|
||||
|
||||
tauri::async_runtime::block_on(async move {
|
||||
// Create data folder if not exist
|
||||
let dir = app.path().config_dir().expect("Config Directory not found.");
|
||||
let _ = fs::create_dir_all(dir.join("Coop/"));
|
||||
|
||||
// Setup database
|
||||
let database = SQLiteDatabase::open(dir.join("Coop/coop.db")).await;
|
||||
|
||||
// Setup nostr client
|
||||
let client = match database {
|
||||
Ok(db) => ClientBuilder::default().database(db).build(),
|
||||
Err(_) => ClientBuilder::default().build(),
|
||||
};
|
||||
|
||||
// Add bootstrap relay
|
||||
let _ = client.add_relay("wss://relay.damus.io/").await;
|
||||
let _ = client.add_relay("wss://relay.nostr.net/").await;
|
||||
|
||||
// Connect
|
||||
client.connect().await;
|
||||
|
||||
// Create global state
|
||||
app.handle().manage(Nostr { client, contact_list: Mutex::new(vec![]) })
|
||||
});
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.plugin(tauri_plugin_decorum::init())
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.invoke_handler(tauri::generate_handler![greet])
|
||||
.invoke_handler(tauri::generate_handler![login, get_accounts, get_profile])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"productName": "coop",
|
||||
"productName": "Coop",
|
||||
"version": "0.0.0",
|
||||
"identifier": "com.tauri.dev",
|
||||
"build": {
|
||||
@@ -9,15 +9,27 @@
|
||||
"frontendDist": "../dist"
|
||||
},
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "coop",
|
||||
"width": 800,
|
||||
"height": 600
|
||||
}
|
||||
],
|
||||
"macOSPrivateApi": true,
|
||||
"withGlobalTauri": true,
|
||||
"security": {
|
||||
"csp": null
|
||||
"csp": null,
|
||||
"assetProtocol": {
|
||||
"enable": true,
|
||||
"scope": [
|
||||
"$APPDATA/*",
|
||||
"$DATA/*",
|
||||
"$LOCALDATA/*",
|
||||
"$DESKTOP/*",
|
||||
"$DOCUMENT/*",
|
||||
"$DOWNLOAD/*",
|
||||
"$HOME/*",
|
||||
"$PICTURE/*",
|
||||
"$PUBLIC/*",
|
||||
"$VIDEO/*",
|
||||
"$APPCONFIG/*",
|
||||
"$RESOURCE/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
|
||||
14
src-tauri/tauri.linux.conf.json
Normal file
14
src-tauri/tauri.linux.conf.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "Coop",
|
||||
"label": "main",
|
||||
"width": 860,
|
||||
"height": 650,
|
||||
"minWidth": 860,
|
||||
"minHeight": 650
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
23
src-tauri/tauri.macos.conf.json
Normal file
23
src-tauri/tauri.macos.conf.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "Coop",
|
||||
"label": "main",
|
||||
"width": 860,
|
||||
"height": 650,
|
||||
"minWidth": 860,
|
||||
"minHeight": 650,
|
||||
"titleBarStyle": "Overlay",
|
||||
"hiddenTitle": true,
|
||||
"transparent": true,
|
||||
"windowEffects": {
|
||||
"state": "followsWindowActiveState",
|
||||
"effects": [
|
||||
"underWindowBackground"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
20
src-tauri/tauri.windows.conf.json
Normal file
20
src-tauri/tauri.windows.conf.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "Coop",
|
||||
"label": "main",
|
||||
"width": 860,
|
||||
"height": 650,
|
||||
"minWidth": 860,
|
||||
"minHeight": 650,
|
||||
"transparent": true,
|
||||
"windowEffects": {
|
||||
"effects": [
|
||||
"mica"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user