Skip to content

Commit

Permalink
Add warning in the Quick Start guides about Safari breaking Copy to C…
Browse files Browse the repository at this point in the history
…lipboard (#3898)

### What

For security reason, Safari doesn't let use copy text from our Web
viewer, see:
- emilk/egui#3480

This PR detects if we are running on Safari and adds a warning to the
top of the Quick Start guides.

<img width="1112" alt="image"
src="https://github.com/rerun-io/rerun/assets/49431240/a8bf5a1c-5c64-42ef-942e-344bc100015a">


### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested [demo.rerun.io](https://demo.rerun.io/pr/3898) (if
applicable)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG

- [PR Build Summary](https://build.rerun.io/pr/3898)
- [Docs
preview](https://rerun.io/preview/063e12defa92f5249e22c771c4fe0454231420cc/docs)
<!--DOCS-PREVIEW-->
- [Examples
preview](https://rerun.io/preview/063e12defa92f5249e22c771c4fe0454231420cc/examples)
<!--EXAMPLES-PREVIEW-->
- [Recent benchmark results](https://ref.rerun.io/dev/bench/)
- [Wasm size tracking](https://ref.rerun.io/dev/sizes/)

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
  • Loading branch information
abey79 and emilk committed Oct 17, 2023
1 parent a364405 commit 8826c1d
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 25 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion crates/re_viewer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ wgpu.workspace = true
# web dependencies:
[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen-futures.workspace = true
web-sys = { workspace = true, features = ["Window"] }

[build-dependencies]
re_build_tools.workspace = true
Expand Down
4 changes: 4 additions & 0 deletions crates/re_viewer/data/quick_start_guides/python_native.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## Python Quick Start

${SAFARI_WARNING}

### Installing the Rerun SDK

The Rerun SDK is available on [PyPI](https://pypi.org/) under the
Expand Down Expand Up @@ -31,3 +33,5 @@ Instead of a pre-packaged demo, you can log your own data. Copy and paste the fo
```python
${EXAMPLE_CODE}
```

${HOW_DOES_IT_WORK}
4 changes: 4 additions & 0 deletions crates/re_viewer/data/quick_start_guides/rust_native.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## Rust Quick Start

${SAFARI_WARNING}

### Installing Rerun

To use the Rerun SDK in your project, you need the [rerun crate](https://crates.io/crates/rerun) which you can add with `cargo add rerun`.
Expand Down Expand Up @@ -29,3 +31,5 @@ cargo run
Once everything finishes compiling, you will see the points in this viewer:

![Demo recording](https://static.rerun.io/intro_rust_result/cc780eb9bf014d8b1a68fac174b654931f92e14f/768w.png)

${HOW_DOES_IT_WORK}
100 changes: 77 additions & 23 deletions crates/re_viewer/src/ui/welcome_screen/welcome_page.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
use super::{large_text_button, status_strings, url_large_text_button, WelcomeScreenResponse};
use egui::{NumExt, Ui};
use itertools::Itertools;
use re_data_store::StoreDb;
use re_log_types::{
DataRow, EntityPath, LogMsg, RowId, StoreId, StoreInfo, StoreKind, StoreSource, Time, TimePoint,
};
use re_smart_channel::ReceiveSet;
use re_ui::UICommandSender;
use re_viewer_context::{SystemCommand, SystemCommandSender};
use std::collections::HashMap;

const SPACE_VIEWS_HELP: &str = "https://www.rerun.io/docs/getting-started/viewer-walkthrough";

const HOW_DOES_IT_WORK: &str = include_str!("../../../data/quick_start_guides/how_does_it_work.md");

/// Show the welcome page.
///
/// Return `true` if the user wants to switch to the example page.
Expand Down Expand Up @@ -66,15 +68,18 @@ fn onboarding_content_ui(
if large_text_button(ui, "C++").clicked() {
open_quick_start(
command_sender,
include_str!("../../../data/quick_start_guides/cpp_native.md"),
[
include_str!("../../../data/quick_start_guides/cpp_native.md"),
include_str!(
"../../../data/quick_start_guides/how_does_it_work.md"
(
"EXAMPLE_CODE",
include_str!(
"../../../data/quick_start_guides/quick_start_connect.cpp"
),
),
],
include_str!(
"../../../data/quick_start_guides/quick_start_connect.cpp"
),
("HOW_DOES_IT_WORK", HOW_DOES_IT_WORK),
("SAFARI_WARNING", safari_warning()),
]
.into(),
"C++ Quick Start",
"cpp_quick_start",
);
Expand All @@ -83,23 +88,37 @@ fn onboarding_content_ui(
if large_text_button(ui, "Python").clicked() {
open_quick_start(
command_sender,
include_str!("../../../data/quick_start_guides/python_native.md"),
[
include_str!("../../../data/quick_start_guides/python_native.md"),
include_str!("../../../data/quick_start_guides/how_does_it_work.md"),
],
include_str!("../../../data/quick_start_guides/quick_start_connect.py"),
(
"EXAMPLE_CODE",
include_str!(
"../../../data/quick_start_guides/quick_start_connect.py"
),
),
("HOW_DOES_IT_WORK", HOW_DOES_IT_WORK),
("SAFARI_WARNING", safari_warning()),
]
.into(),
"Python Quick Start",
"python_quick_start",
);
}
if large_text_button(ui, "Rust").clicked() {
open_quick_start(
command_sender,
include_str!("../../../data/quick_start_guides/rust_native.md"),
[
include_str!("../../../data/quick_start_guides/rust_native.md"),
include_str!("../../../data/quick_start_guides/how_does_it_work.md"),
],
include_str!("../../../data/quick_start_guides/quick_start_connect.rs"),
(
"EXAMPLE_CODE",
include_str!(
"../../../data/quick_start_guides/quick_start_connect.rs"
),
),
("HOW_DOES_IT_WORK", HOW_DOES_IT_WORK),
("SAFARI_WARNING", safari_warning()),
]
.into(),
"Rust Quick Start",
"rust_quick_start",
);
Expand Down Expand Up @@ -276,17 +295,20 @@ fn image_banner(ui: &mut egui::Ui, icon: &re_ui::Icon, column_width: f32, max_im

/// Open a Quick Start recording
///
/// The `parts` are joined with newlines to form the markdown, and the spacial tag
/// `"${EXAMPLE_CODE}"` is replaced with the content of th `example_code` variable.
fn open_quick_start<'a>(
/// The markdown content may contain placeholders in the form of `${NAME}`. These will be replaced
/// with the corresponding value from the `placeholder_content` hash map.
fn open_quick_start(
command_sender: &re_viewer_context::CommandSender,
parts: impl IntoIterator<Item = &'a str>,
example_code: &str,
markdown: &str,
placeholder_content: HashMap<&'static str, &'static str>,
app_id: &str,
entity_path: &str,
) {
let mut markdown = parts.into_iter().join("\n");
markdown = markdown.replace("${EXAMPLE_CODE}", example_code);
let mut markdown = markdown.to_owned();

for (key, value) in placeholder_content {
markdown = markdown.replace(format!("${{{key}}}").as_str(), value);
}

let res = open_markdown_recording(command_sender, markdown.as_str(), app_id, entity_path);
if let Err(err) = res {
Expand Down Expand Up @@ -324,3 +346,35 @@ fn open_markdown_recording(

Ok(())
}

/// The User-Agent of the user's browser.
fn user_agent() -> Option<String> {
#[cfg(target_arch = "wasm32")]
return eframe::web::user_agent();

#[cfg(not(target_arch = "wasm32"))]
None
}

/// Are we running on Safari?
fn safari_warning() -> &'static str {
// Note that this implementation is very naive and might return false positives. This is ok for
// the purpose of displaying a "can't copy" warning in the Quick Start guide, but this detection
// is likely not suitable for pretty much anything else.
//
// See this page for more information on User Agent sniffing (and why/how to avoid it):
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent

let is_safari = user_agent().is_some_and(|user_agent| {
user_agent.contains("Safari")
&& !user_agent.contains("Chrome")
&& !user_agent.contains("Chromium")
});

if is_safari {
"**Note**: This browser appears to be Safari. If you are unable to copy the code, please \
try a different browser (see [this issue](https://github.com/emilk/egui/issues/3480))."
} else {
""
}
}

0 comments on commit 8826c1d

Please sign in to comment.