feat(notedeck): add cross-platform URI opener

This commit is contained in:
Fernando López Guevara
2025-07-28 19:53:54 -03:00
committed by William Casarin
parent ba76b20ad2
commit f282363748
9 changed files with 116 additions and 48 deletions

4
.gitignore vendored
View File

@@ -20,4 +20,6 @@ queries/damus-notifs.json
scripts/macos_build_secrets.sh scripts/macos_build_secrets.sh
/tags /tags
.zed .zed
.lsp .lsp
.idea
local.properties

120
Cargo.lock generated
View File

@@ -765,6 +765,25 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "block-sys"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae85a0696e7ea3b835a453750bf002770776609115e6d25c6d2ff28a8200f7e7"
dependencies = [
"objc-sys",
]
[[package]]
name = "block2"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e58aa60e59d8dbfcc36138f5f18be5f24394d33b38b24f7fd0b1caa33095f22f"
dependencies = [
"block-sys",
"objc2 0.5.2",
]
[[package]] [[package]]
name = "block2" name = "block2"
version = "0.5.1" version = "0.5.1"
@@ -2508,6 +2527,16 @@ dependencies = [
"cc", "cc",
] ]
[[package]]
name = "icrate"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb69199826926eb864697bddd27f73d9fddcffc004f5733131e15b465e30642"
dependencies = [
"block2 0.4.0",
"objc2 0.5.2",
]
[[package]] [[package]]
name = "icu_collections" name = "icu_collections"
version = "2.0.0" version = "2.0.0"
@@ -2745,25 +2774,6 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "is-docker"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3"
dependencies = [
"once_cell",
]
[[package]]
name = "is-wsl"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5"
dependencies = [
"is-docker",
"once_cell",
]
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.10.5" version = "0.10.5"
@@ -3522,7 +3532,6 @@ dependencies = [
"notedeck", "notedeck",
"notedeck_ui", "notedeck_ui",
"oot_bitset", "oot_bitset",
"open",
"opener", "opener",
"poll-promise", "poll-promise",
"pretty_assertions", "pretty_assertions",
@@ -3531,6 +3540,7 @@ dependencies = [
"puffin_egui", "puffin_egui",
"rfd", "rfd",
"rmpv", "rmpv",
"robius-open",
"security-framework 2.11.1", "security-framework 2.11.1",
"serde", "serde",
"serde_derive", "serde_derive",
@@ -4014,17 +4024,6 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "open"
version = "5.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2483562e62ea94312f3576a7aca397306df7990b8d89033e18766744377ef95"
dependencies = [
"is-wsl",
"libc",
"pathdiff",
]
[[package]] [[package]]
name = "opener" name = "opener"
version = "0.8.2" version = "0.8.2"
@@ -4137,12 +4136,6 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pathdiff"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
[[package]] [[package]]
name = "pbkdf2" name = "pbkdf2"
version = "0.12.2" version = "0.12.2"
@@ -4950,6 +4943,30 @@ dependencies = [
"rmp", "rmp",
] ]
[[package]]
name = "robius-android-env"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "087fcb3061ccc432658a605cb868edd44e0efb08e7a159b486f02804a7616bef"
dependencies = [
"jni 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ndk-context",
]
[[package]]
name = "robius-open"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "243e2abbc8c1ca8ddc283056d4675b67e452fd527c3741c5318642da37840ff3"
dependencies = [
"cfg-if",
"icrate",
"jni 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
"objc2 0.5.2",
"robius-android-env",
"windows 0.54.0",
]
[[package]] [[package]]
name = "roxmltree" name = "roxmltree"
version = "0.19.0" version = "0.19.0"
@@ -6792,6 +6809,16 @@ dependencies = [
"windows-targets 0.52.6", "windows-targets 0.52.6",
] ]
[[package]]
name = "windows"
version = "0.54.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49"
dependencies = [
"windows-core 0.54.0",
"windows-targets 0.52.6",
]
[[package]] [[package]]
name = "windows" name = "windows"
version = "0.58.0" version = "0.58.0"
@@ -6811,6 +6838,16 @@ dependencies = [
"windows-targets 0.52.6", "windows-targets 0.52.6",
] ]
[[package]]
name = "windows-core"
version = "0.54.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65"
dependencies = [
"windows-result 0.1.2",
"windows-targets 0.52.6",
]
[[package]] [[package]]
name = "windows-core" name = "windows-core"
version = "0.58.0" version = "0.58.0"
@@ -6887,6 +6924,15 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
[[package]]
name = "windows-result"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
dependencies = [
"windows-targets 0.52.6",
]
[[package]] [[package]]
name = "windows-result" name = "windows-result"
version = "0.2.0" version = "0.2.0"

View File

@@ -51,7 +51,7 @@ notedeck_dave = { path = "crates/notedeck_dave" }
notedeck_ui = { path = "crates/notedeck_ui" } notedeck_ui = { path = "crates/notedeck_ui" }
tokenator = { path = "crates/tokenator" } tokenator = { path = "crates/tokenator" }
once_cell = "1.19.0" once_cell = "1.19.0"
open = "5.3.0" robius-open = "0.1"
poll-promise = { version = "0.3.0", features = ["tokio"] } poll-promise = { version = "0.3.0", features = ["tokio"] }
puffin = { git = "https://github.com/jb55/puffin", package = "puffin", rev = "c6a6242adaf90b6292c0f462d2acd34d96d224d2" } puffin = { git = "https://github.com/jb55/puffin", package = "puffin", rev = "c6a6242adaf90b6292c0f462d2acd34d96d224d2" }
puffin_egui = { git = "https://github.com/jb55/puffin", package = "puffin_egui", rev = "c6a6242adaf90b6292c0f462d2acd34d96d224d2" } puffin_egui = { git = "https://github.com/jb55/puffin", package = "puffin_egui", rev = "c6a6242adaf90b6292c0f462d2acd34d96d224d2" }

View File

@@ -63,6 +63,12 @@ short_description = "The nostr browser"
identifier = "com.damus.notedeck" identifier = "com.damus.notedeck"
icon = ["assets/app_icon.icns"] icon = ["assets/app_icon.icns"]
[package.metadata.android.manifest.queries]
intent = [
{ action = ["android.intent.action.MAIN"] },
]
[package.metadata.android] [package.metadata.android]
package = "com.damus.app" package = "com.damus.app"
apk_name = "Notedeck" apk_name = "Notedeck"

View File

@@ -23,11 +23,18 @@
</activity> </activity>
</application> </application>
<queries>
<intent>
<action android:name="android.intent.action.MAIN" />
</intent>
</queries>
<uses-feature android:name="android.hardware.vulkan.level" <uses-feature android:name="android.hardware.vulkan.level"
android:required="true" android:required="true"
android:version="1" /> android:version="1" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest> </manifest>

View File

@@ -32,7 +32,7 @@ image = { workspace = true }
indexmap = { workspace = true } indexmap = { workspace = true }
nostrdb = { workspace = true } nostrdb = { workspace = true }
notedeck_ui = { workspace = true } notedeck_ui = { workspace = true }
open = { workspace = true } robius-open = { workspace = true }
poll-promise = { workspace = true } poll-promise = { workspace = true }
puffin = { workspace = true, optional = true } puffin = { workspace = true, optional = true }
puffin_egui = { workspace = true, optional = true } puffin_egui = { workspace = true, optional = true }

View File

@@ -28,7 +28,7 @@ impl Support {
} }
static MAX_LOG_LINES: usize = 500; static MAX_LOG_LINES: usize = 500;
static SUPPORT_EMAIL: &str = "support@damus.io"; pub static SUPPORT_EMAIL: &str = "support+notedeck@damus.io";
static EMAIL_TEMPLATE: &str = concat!("version ", env!("CARGO_PKG_VERSION"), "\nCommit hash: ", env!("GIT_COMMIT_HASH"), "\n\nDescribe the bug you have encountered:\n<-- your statement here -->\n\n===== Paste your log below =====\n\n"); static EMAIL_TEMPLATE: &str = concat!("version ", env!("CARGO_PKG_VERSION"), "\nCommit hash: ", env!("GIT_COMMIT_HASH"), "\n\nDescribe the bug you have encountered:\n<-- your statement here -->\n\n===== Paste your log below =====\n\n");
impl Support { impl Support {

View File

@@ -6,6 +6,7 @@ use enostr::Pubkey;
use nostrdb::{ProfileRecord, Transaction}; use nostrdb::{ProfileRecord, Transaction};
use notedeck::{tr, Localization}; use notedeck::{tr, Localization};
use notedeck_ui::profile::follow_button; use notedeck_ui::profile::follow_button;
use robius_open::Uri;
use tracing::error; use tracing::error;
use crate::{ use crate::{
@@ -285,8 +286,8 @@ fn handle_link(ui: &mut egui::Ui, website_url: &str) {
.interact(Sense::click()) .interact(Sense::click())
.clicked() .clicked()
{ {
if let Err(e) = open::that(website_url) { if let Err(e) = Uri::new(website_url).open() {
error!("Failed to open URL {} because: {}", website_url, e); error!("Failed to open URL {} because: {:?}", website_url, e);
}; };
} }
} }

View File

@@ -1,10 +1,10 @@
use crate::support::{Support, SUPPORT_EMAIL};
use egui::{vec2, Button, Label, Layout, RichText}; use egui::{vec2, Button, Label, Layout, RichText};
use notedeck::{tr, Localization, NamedFontFamily, NotedeckTextStyle}; use notedeck::{tr, Localization, NamedFontFamily, NotedeckTextStyle};
use notedeck_ui::{colors::PINK, padding}; use notedeck_ui::{colors::PINK, padding};
use robius_open::Uri;
use tracing::error; use tracing::error;
use crate::support::Support;
pub struct SupportView<'a> { pub struct SupportView<'a> {
support: &'a mut Support, support: &'a mut Support,
i18n: &'a mut Localization, i18n: &'a mut Localization,
@@ -44,15 +44,21 @@ impl<'a> SupportView<'a> {
"Open your default email client to get help from the Damus team", "Open your default email client to get help from the Damus team",
"Instruction to open email client" "Instruction to open email client"
)); ));
ui.horizontal_wrapped(|ui| {
ui.label(tr!(self.i18n, "Support email:", "Support email address",));
ui.label(RichText::new(SUPPORT_EMAIL).color(PINK))
});
let size = vec2(120.0, 40.0); let size = vec2(120.0, 40.0);
ui.allocate_ui_with_layout(size, Layout::top_down(egui::Align::Center), |ui| { ui.allocate_ui_with_layout(size, Layout::top_down(egui::Align::Center), |ui| {
let font_size = let font_size =
notedeck::fonts::get_font_size(ui.ctx(), &NotedeckTextStyle::Body); notedeck::fonts::get_font_size(ui.ctx(), &NotedeckTextStyle::Body);
let button_resp = ui.add(open_email_button(self.i18n, font_size, size)); let button_resp = ui.add(open_email_button(self.i18n, font_size, size));
if button_resp.clicked() { if button_resp.clicked() {
if let Err(e) = open::that(self.support.get_mailto_url()) { if let Err(e) = Uri::new(self.support.get_mailto_url()).open() {
error!( error!(
"Failed to open URL {} because: {}", "Failed to open URL {} because: {:?}",
self.support.get_mailto_url(), self.support.get_mailto_url(),
e e
); );