diff --git a/.github/workflows/flatpak-bundle.yml b/.github/workflows/flatpak-bundle.yml deleted file mode 100644 index fb4d1b3b..00000000 --- a/.github/workflows/flatpak-bundle.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: Flatpak -on: workflow_dispatch - -jobs: - prepare-repo: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: 'recursive' - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: cache of container - id: cache-container - uses: actions/cache@v3 - with: - path: prepare-dist - key: ${{ runner.os }}-container-${{ hashFiles('prepare-dist') }} - - name: Run latest-tag - id: latest-tag - uses: oprypin/find-latest-tag@v1 - with: - repository: - lumehq/lume - #FIXME: lumehq after merged fix, now it just won't find tags - # repository: ${{ github.repository }} - - - name: Build container - # if: steps.cache-container.outputs.cache-hit != 'true' - run: | - docker buildx build -t flatpak-prepare-lume --build-arg=${{steps.latest-tag.outputs.tag}} --rm --output=. --target=final -f flatpak/Containerfile . - - name: Copy flatpak files content - run: | - cp -r flatpak/*.xml flatpak/*.desktop flatpak/*.yml prepare-dist - - uses: actions/upload-artifact@v4 - with: - name: repo-dist - path: prepare-dist - flatpak: - name: flatpak-bundle - needs: prepare-repo - runs-on: ubuntu-latest - container: - image: bilelmoussaoui/flatpak-github-actions:gnome-45 - options: --privileged - steps: - - uses: actions/download-artifact@v4 - with: - name: repo-dist - - uses: actions/checkout@v4 - with: - repository: flathub/shared-modules - path: shared-modules - - uses: flatpak/flatpak-github-actions/flatpak-builder@v6 - with: - bundle: lume.flatpak - manifest-path: nu.lume.Lume.yml - restore-cache: false - # cache-key: flatpak-builder-${{ github.sha }} - - name: Release - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') - with: - append_body: true - files: lume.flatpak - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - uses: geekyeggo/delete-artifact@v4 - with: - name: repo-dist - token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 770e13a9..cd5f28a2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,12 +16,12 @@ jobs: args: "--target aarch64-apple-darwin" - platform: "macos-latest" # for Intel based macs. args: "--target x86_64-apple-darwin" - - platform: "macos-latest" # for Intel based macs. + - platform: "macos-latest" # for Intel & Arm based macs. args: "--target universal-apple-darwin" - - platform: 'ubuntu-22.04' - args: '' - - platform: 'windows-latest' - args: '--target x86_64-pc-windows-msvc' + #- platform: 'ubuntu-22.04' + # args: '' + #- platform: 'windows-latest' + # args: '--target x86_64-pc-windows-msvc' runs-on: ${{ matrix.platform }} steps: - uses: actions/checkout@v4 diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index d1c268b1..2148b957 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1236,30 +1236,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" -[[package]] -name = "dbus" -version = "0.9.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" -dependencies = [ - "libc", - "libdbus-sys", - "winapi", -] - -[[package]] -name = "dbus-secret-service" -version = "4.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1caa0c241c01ad8d99a78d553567d38f873dd3ac16eca33a5370d650ab25584e" -dependencies = [ - "dbus", - "futures-util", - "num", - "once_cell", - "rand 0.8.5", -] - [[package]] name = "deranged" version = "0.3.11" @@ -2762,7 +2738,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b9af47ded4df3067484d7d45758ca2b36bd083bf6d024c2952bbd8af1cdaa4" dependencies = [ "byteorder", - "dbus-secret-service", "security-framework", "windows-sys 0.59.0", ] @@ -2837,15 +2812,6 @@ version = "0.2.157" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "374af5f94e54fa97cf75e945cce8a6b201e88a1a07e688b47dfd2a59c66dbd86" -[[package]] -name = "libdbus-sys" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" -dependencies = [ - "pkg-config", -] - [[package]] name = "libloading" version = "0.7.4" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 5dea4ff9..53f9db93 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -44,11 +44,7 @@ url = "2.5.0" futures = "0.3.30" linkify = "0.10.0" regex = "1.10.4" -keyring = { version = "3", features = [ - "apple-native", - "windows-native", - "sync-secret-service", -] } +keyring = { version = "3", features = ["apple-native", "windows-native"] } keyring-search = "1.2.0" [target.'cfg(target_os = "macos")'.dependencies] diff --git a/src-tauri/src/commands/window.rs b/src-tauri/src/commands/window.rs index a70647f2..b4dde532 100644 --- a/src-tauri/src/commands/window.rs +++ b/src-tauri/src/commands/window.rs @@ -1,25 +1,15 @@ use std::path::PathBuf; -use std::str::FromStr; #[cfg(target_os = "macos")] use border::WebviewWindowExt as BorderWebviewWindowExt; -#[cfg(target_os = "macos")] -use cocoa::{appkit::NSApp, base::nil, foundation::NSString}; use serde::{Deserialize, Serialize}; use specta::Type; -#[cfg(not(target_os = "linux"))] use tauri::utils::config::WindowEffectsConfig; -#[cfg(not(target_os = "linux"))] use tauri::window::Effect; #[cfg(target_os = "macos")] use tauri::TitleBarStyle; use tauri::WebviewWindowBuilder; -use tauri::{LogicalPosition, LogicalSize, Manager, State, WebviewUrl}; -#[cfg(not(target_os = "linux"))] -use tauri_plugin_decorum::WebviewWindowExt; -use url::Url; - -use crate::Nostr; +use tauri::{LogicalPosition, LogicalSize, Manager, WebviewUrl}; #[derive(Serialize, Deserialize, Type)] pub struct Window { @@ -43,44 +33,28 @@ pub struct Column { height: f32, } -#[tauri::command] +#[tauri::command(async)] #[specta::specta] -pub fn create_column( - column: Column, - app_handle: tauri::AppHandle, - state: State<'_, Nostr>, -) -> Result { - let settings = state.settings.lock().unwrap().clone(); - +pub fn create_column(column: Column, app_handle: tauri::AppHandle) -> Result { match app_handle.get_window("main") { Some(main_window) => match app_handle.get_webview(&column.label) { Some(_) => Ok(column.label), None => { let path = PathBuf::from(column.url); let webview_url = WebviewUrl::App(path); - let builder = match settings.proxy { - Some(url) => { - let proxy = Url::from_str(&url).unwrap(); - tauri::webview::WebviewBuilder::new(column.label, webview_url) - .user_agent("Lume/4.0") - .zoom_hotkeys_enabled(true) - .enable_clipboard_access() - .transparent(true) - .proxy_url(proxy) - } - None => tauri::webview::WebviewBuilder::new(column.label, webview_url) - .user_agent("Lume/4.0") - .zoom_hotkeys_enabled(true) - .enable_clipboard_access() - .transparent(true), - }; - match main_window.add_child( + + let builder = tauri::webview::WebviewBuilder::new(column.label, webview_url) + .incognito(true) + .transparent(true); + + if let Ok(webview) = main_window.add_child( builder, LogicalPosition::new(column.x, column.y), LogicalSize::new(column.width, column.height), ) { - Ok(webview) => Ok(webview.label().into()), - Err(_) => Err("Create webview failed".into()), + Ok(webview.label().into()) + } else { + Err("Create webview failed".into()) } } }, @@ -88,10 +62,10 @@ pub fn create_column( } } -#[tauri::command] +#[tauri::command(async)] #[specta::specta] -pub fn close_column(label: &str, app_handle: tauri::AppHandle) -> Result { - match app_handle.get_webview(label) { +pub fn close_column(label: String, app_handle: tauri::AppHandle) -> Result { + match app_handle.get_webview(&label) { Some(webview) => { if webview.close().is_ok() { Ok(true) @@ -103,15 +77,15 @@ pub fn close_column(label: &str, app_handle: tauri::AppHandle) -> Result Result<(), String> { - match app_handle.get_webview(label) { + match app_handle.get_webview(&label) { Some(webview) => { if webview.set_position(LogicalPosition::new(x, y)).is_ok() { Ok(()) @@ -123,15 +97,15 @@ pub fn reposition_column( } } -#[tauri::command] +#[tauri::command(async)] #[specta::specta] pub fn resize_column( - label: &str, + label: String, width: f32, height: f32, app_handle: tauri::AppHandle, ) -> Result<(), String> { - match app_handle.get_webview(label) { + match app_handle.get_webview(&label) { Some(webview) => { if webview.set_size(LogicalSize::new(width, height)).is_ok() { Ok(()) @@ -143,10 +117,10 @@ pub fn resize_column( } } -#[tauri::command] +#[tauri::command(async)] #[specta::specta] -pub fn reload_column(label: &str, app_handle: tauri::AppHandle) -> Result<(), String> { - match app_handle.get_webview(label) { +pub fn reload_column(label: String, app_handle: tauri::AppHandle) -> Result<(), String> { + match app_handle.get_webview(&label) { Some(webview) => { if webview.eval("window.location.reload()").is_ok() { Ok(()) @@ -203,6 +177,7 @@ pub fn open_window(window: Window, app_handle: tauri::AppHandle) -> Result<(), S .inner_size(window.width, window.height) .minimizable(window.minimizable) .maximizable(window.maximizable) + .transparent(true) .effects(WindowEffectsConfig { state: None, effects: vec![Effect::Mica], @@ -212,22 +187,8 @@ pub fn open_window(window: Window, app_handle: tauri::AppHandle) -> Result<(), S .build() .unwrap(); - #[cfg(target_os = "linux")] - let window = WebviewWindowBuilder::new( - &app_handle, - &window.label, - WebviewUrl::App(PathBuf::from(window.url)), - ) - .title(&window.title) - .min_inner_size(window.width, window.height) - .inner_size(window.width, window.height) - .minimizable(window.minimizable) - .maximizable(window.maximizable) - .build() - .unwrap(); - // Set decoration - #[cfg(not(target_os = "linux"))] + #[cfg(target_os = "windows")] window.create_overlay_titlebar().unwrap(); // Restore native border @@ -266,18 +227,3 @@ pub fn open_main_window(app: tauri::AppHandle) { pub fn force_quit() { std::process::exit(0) } - -#[tauri::command] -#[specta::specta] -pub fn set_badge(count: i32) { - #[cfg(target_os = "macos")] - unsafe { - let label = if count == 0 { - nil - } else { - NSString::alloc(nil).init_str(&format!("{}", count)) - }; - let dock_tile: cocoa::base::id = msg_send![NSApp(), dockTile]; - let _: cocoa::base::id = msg_send![dock_tile, setBadgeLabel: label]; - } -} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index c17261f9..cf709e3b 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -5,9 +5,6 @@ #[cfg(target_os = "macos")] extern crate cocoa; -#[cfg(target_os = "macos")] -#[macro_use] -extern crate objc; #[cfg(target_os = "macos")] use border::WebviewWindowExt as BorderWebviewWindowExt; @@ -24,7 +21,6 @@ use std::{ time::Duration, }; use tauri::{path::BaseDirectory, Manager}; -#[cfg(not(target_os = "linux"))] use tauri_plugin_decorum::WebviewWindowExt; use tauri_specta::{collect_commands, Builder}; @@ -132,8 +128,7 @@ fn main() { reload_column, open_window, open_main_window, - force_quit, - set_badge + force_quit ]); builder @@ -156,7 +151,7 @@ fn main() { #[cfg(target_os = "macos")] app.handle().plugin(tauri_nspanel::init()).unwrap(); - #[cfg(not(target_os = "linux"))] + let handle = app.handle(); let main_window = app.get_webview_window("main").unwrap(); // Set custom decoration for Windows @@ -188,9 +183,11 @@ fn main() { let home_dir = app.path().home_dir().unwrap(); let _ = fs::create_dir_all(home_dir.join("Lume/")); - tauri::async_runtime::block_on(async move { + let client = tauri::async_runtime::block_on(async move { // Setup database - let database = SQLiteDatabase::open(home_dir.join("Lume/lume.db")).await; + let database = SQLiteDatabase::open(home_dir.join("Lume/lume.db")) + .await + .expect("Error."); // Config let opts = Options::new() @@ -199,13 +196,13 @@ fn main() { .timeout(Duration::from_secs(30)); // Setup nostr client - let client = match database { - Ok(db) => ClientBuilder::default().database(db).opts(opts).build(), - Err(_) => ClientBuilder::default().opts(opts).build(), - }; + let client = ClientBuilder::default() + .database(database) + .opts(opts) + .build(); // Get bootstrap relays - if let Ok(path) = app + if let Ok(path) = handle .path() .resolve("resources/relays.txt", BaseDirectory::Resource) { @@ -240,12 +237,14 @@ fn main() { // Connect client.connect().await; - // Update global state - app.handle().manage(Nostr { - client, - contact_list: Mutex::new(vec![]), - settings: Mutex::new(Settings::default()), - }) + client + }); + + // Create global state + app.manage(Nostr { + client, + contact_list: Mutex::new(vec![]), + settings: Mutex::new(Settings::default()), }); Ok(()) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c8c6f64a..c91f0c37 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -51,37 +51,16 @@ "icons/icon.icns", "icons/icon.ico" ], - "linux": { - "appimage": { - "bundleMediaFramework": true, - "files": {} - }, - "deb": { - "files": {} - }, - "rpm": { - "epoch": 0, - "files": {}, - "release": "1" + "windows": { + "allowDowngrades": true, + "webviewInstallMode": { + "silent": true, + "type": "downloadBootstrapper" } }, "macOS": { "minimumSystemVersion": "10.15" }, - "windows": { - "allowDowngrades": true, - "certificateThumbprint": null, - "digestAlgorithm": "sha256", - "nsis": null, - "timestampUrl": null, - "tsp": false, - "webviewFixedRuntimePath": null, - "webviewInstallMode": { - "silent": true, - "type": "downloadBootstrapper" - }, - "wix": null - }, "fileAssociations": [ { "name": "bech32", diff --git a/src-tauri/tauri.linux.conf.json b/src-tauri/tauri.linux.conf.json deleted file mode 100644 index 8cf8fa90..00000000 --- a/src-tauri/tauri.linux.conf.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "../node_modules/@tauri-apps/cli/schema.json", - "app": { - "windows": [ - { - "title": "Lume", - "label": "main", - "width": 1045, - "height": 800, - "minWidth": 480, - "minHeight": 760 - } - ] - } -} diff --git a/src-tauri/tauri.macos.conf.json b/src-tauri/tauri.macos.conf.json index 4e8b1588..02745c0a 100644 --- a/src-tauri/tauri.macos.conf.json +++ b/src-tauri/tauri.macos.conf.json @@ -1,30 +1,23 @@ { - "$schema": "../node_modules/@tauri-apps/cli/schema.json", - "app": { - "trayIcon": { - "id": "main", - "iconPath": "./icons/tray.png", - "iconAsTemplate": true, - "menuOnLeftClick": false - }, - "windows": [ - { - "title": "Lume", - "label": "main", - "titleBarStyle": "Overlay", - "width": 1045, - "height": 800, - "minWidth": 480, - "minHeight": 760, - "hiddenTitle": true, - "transparent": true, - "windowEffects": { - "state": "followsWindowActiveState", - "effects": [ - "underWindowBackground" - ] - } - } - ] - } + "$schema": "../node_modules/@tauri-apps/cli/schema.json", + "app": { + "windows": [ + { + "title": "Lume", + "label": "main", + "titleBarStyle": "Overlay", + "width": 900, + "height": 700, + "minWidth": 480, + "minHeight": 700, + "hiddenTitle": true, + "transparent": true, + "windowEffects": { + "effects": [ + "underWindowBackground" + ] + } + } + ] + } } diff --git a/src-tauri/tauri.windows.conf.json b/src-tauri/tauri.windows.conf.json index f91f8f40..9a97189d 100644 --- a/src-tauri/tauri.windows.conf.json +++ b/src-tauri/tauri.windows.conf.json @@ -1,21 +1,22 @@ { - "$schema": "../node_modules/@tauri-apps/cli/schema.json", - "app": { - "windows": [ - { - "title": "Lume", - "label": "main", - "width": 1045, - "height": 800, - "minWidth": 480, - "minHeight": 760, - "transparent": true, - "windowEffects": { - "effects": [ - "mica" - ] - } - } - ] - } + "$schema": "../node_modules/@tauri-apps/cli/schema.json", + "app": { + "windows": [ + { + "title": "Lume", + "label": "main", + "width": 900, + "height": 700, + "minWidth": 480, + "minHeight": 700, + "transparent": true, + "decorations": false, + "windowEffects": { + "effects": [ + "mica" + ] + } + } + ] + } } diff --git a/src/commands.gen.ts b/src/commands.gen.ts index 860c43a1..d007bb45 100644 --- a/src/commands.gen.ts +++ b/src/commands.gen.ts @@ -429,9 +429,6 @@ async openMainWindow() : Promise { }, async forceQuit() : Promise { await TAURI_INVOKE("force_quit"); -}, -async setBadge(count: number) : Promise { - await TAURI_INVOKE("set_badge", { count }); } } diff --git a/src/components/column.tsx b/src/components/column.tsx index 76ac6aee..f21e00fb 100644 --- a/src/components/column.tsx +++ b/src/components/column.tsx @@ -1,5 +1,5 @@ -import type { LumeColumn } from "@/types"; import { CheckIcon, HorizontalDotsIcon } from "@/components"; +import type { LumeColumn } from "@/types"; import { invoke } from "@tauri-apps/api/core"; import { listen } from "@tauri-apps/api/event"; import { Menu, MenuItem, PredefinedMenuItem } from "@tauri-apps/api/menu"; @@ -84,7 +84,7 @@ export const Column = memo(function Column({ }, [account]); return ( -
+
rootRoute, -} as any) +} as any).lazy(() => + import('./routes/bootstrap-relays.lazy').then((d) => d.Route), +) const AccountRoute = AccountImport.update({ path: '/$account', diff --git a/src/routes/$account/home.lazy.tsx b/src/routes/$account/home.lazy.tsx index c6334d52..3df35ea8 100644 --- a/src/routes/$account/home.lazy.tsx +++ b/src/routes/$account/home.lazy.tsx @@ -170,7 +170,7 @@ function Screen() { account={account} /> ))} -
+
+
+
+ {relays.map((relay) => ( +
+
{relay}
+
+ +
+
+ ))} +
+ +
+ + + Lume will relaunch after saving. + +
+
+
+
+ ); +} diff --git a/src/routes/bootstrap-relays.tsx b/src/routes/bootstrap-relays.tsx index 48878ac7..92560aba 100644 --- a/src/routes/bootstrap-relays.tsx +++ b/src/routes/bootstrap-relays.tsx @@ -1,150 +1,14 @@ -import { Spinner } from "@/components"; -import { CancelIcon, PlusIcon } from "@/components"; -import { NostrQuery } from "@/system"; -import type { Relay } from "@/types"; +import { commands } from "@/commands.gen"; import { createFileRoute } from "@tanstack/react-router"; -import { message } from "@tauri-apps/plugin-dialog"; -import { useEffect, useState } from "react"; -import { useForm } from "react-hook-form"; export const Route = createFileRoute("/bootstrap-relays")({ loader: async () => { - const bootstrapRelays = await NostrQuery.getBootstrapRelays(); - return bootstrapRelays; + const res = await commands.getBootstrapRelays(); + + if (res.status === "ok") { + return res.data.map((item) => item.replace(",", "")); + } else { + throw new Error(res.error); + } }, - component: Screen, }); - -function Screen() { - const bootstrapRelays = Route.useLoaderData(); - const { register, reset, handleSubmit } = useForm(); - - const [relays, setRelays] = useState([]); - const [isLoading, setIsLoading] = useState(false); - - const removeRelay = (url: string) => { - setRelays((prev) => prev.filter((relay) => relay.url !== url)); - }; - - const onSubmit = async (data: { url: string; purpose: string }) => { - try { - if (!data.url.startsWith("wss://") || !data.url.startsWith("ws://")) { - return await message("Relay must be starts with wss:// or ws://", { - title: "Bootstrap Relays", - kind: "info", - }); - } - - const relay: Relay = { url: data.url, purpose: data.purpose }; - setRelays((prev) => [...prev, relay]); - reset(); - } catch (e) { - await message(String(e), { title: "Bootstrap Relays", kind: "error" }); - } - }; - - const save = async () => { - try { - setIsLoading(true); - await NostrQuery.saveBootstrapRelays(relays); - } catch (e) { - await message(String(e), { title: "Bootstrap Relays", kind: "error" }); - } - }; - - useEffect(() => { - setRelays(bootstrapRelays); - }, [bootstrapRelays]); - - return ( -
-
-
-
-

Customize Bootstrap Relays

-
-
-
-
- {relays.map((relay) => ( -
-
- {relay.url} -
-
- {relay.purpose?.length ? ( - - ) : null} - -
-
- ))} -
-
-
- - -
- -
-
-
-
- -
-
-
-
- ); -} diff --git a/src/system/query.ts b/src/system/query.ts index e58be7f0..4c5bdc82 100644 --- a/src/system/query.ts +++ b/src/system/query.ts @@ -381,7 +381,7 @@ export const NostrQuery = { return []; } }, - saveBootstrapRelays: async (relays: Relay[]) => { + saveBootstrapRelays: async (relays: string[]) => { const text = relays .map((relay) => Object.values(relay).join(",")) .join("\n");