Add postsack-web target for wasm

This includes everything required to build a wasm target.
It also separates the egui initialization into the separate
postsack target for native
pull/8/head
Benedikt Terhechte 2 years ago
parent 8ee485f7a7
commit 047552a20a

22
Cargo.lock generated

@ -202,10 +202,12 @@ version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
dependencies = [
"js-sys",
"libc",
"num-integer",
"num-traits",
"time 0.1.44",
"wasm-bindgen",
"winapi",
]
@ -256,6 +258,16 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "console_error_panic_hook"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen",
]
[[package]]
name = "copypasta"
version = "0.7.1"
@ -1562,6 +1574,16 @@ dependencies = [
"ps-importer",
]
[[package]]
name = "postsack-web"
version = "0.2.0"
dependencies = [
"console_error_panic_hook",
"ps-core",
"ps-gui",
"wasm-bindgen",
]
[[package]]
name = "ppv-lite86"
version = "0.2.15"

@ -5,6 +5,7 @@ members = [
"ps-importer",
"ps-gui",
"postsack",
"postsack-web",
]
[profile.dev]

@ -0,0 +1,3 @@
/target
target
.DS_Store

2633
postsack-web/Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,16 @@
[package]
name = "postsack-web"
version = "0.2.0"
edition = "2021"
description = "Provides a high level visual overview of swaths of email"
[lib]
crate-type = ["cdylib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
ps-gui = { path = "../ps-gui" }
ps-core = { path = "../ps-core" }
wasm-bindgen = "*"
console_error_panic_hook = "0.1.7"

@ -16,12 +16,16 @@ export RUSTFLAGS=--cfg=web_sys_unstable_apis
rm -f web_demo/${CRATE_NAME_SNAKE_CASE}_bg.wasm
echo "Building rust…"
BUILD=release
cargo build --release -p ${CRATE_NAME} --lib --target wasm32-unknown-unknown
BUILD=debug
if [[ "$BUILD" == "debug" ]]; then
cargo build -p ${CRATE_NAME} --lib --target wasm32-unknown-unknown
else
cargo build --${BUILD} -p ${CRATE_NAME} --lib --target wasm32-unknown-unknown
fi
echo "Generating JS bindings for wasm…"
TARGET_NAME="${CRATE_NAME_SNAKE_CASE}.wasm"
wasm-bindgen "target/wasm32-unknown-unknown/${BUILD}/${TARGET_NAME}" \
wasm-bindgen "../target/wasm32-unknown-unknown/${BUILD}/${TARGET_NAME}" \
--out-dir web_demo --no-modules --no-typescript
# to get wasm-opt: apt/brew/dnf install binaryen

@ -0,0 +1,60 @@
use std::path::Path;
use std::thread::JoinHandle;
use ps_core::{
crossbeam_channel::Sender,
eyre::{bail, Result},
Config, DBMessage, DatabaseLike, DatabaseQuery, Field, Query, QueryResult, ValueField,
};
pub struct FakeDatabase {}
impl FakeDatabase {
pub fn total_item_count() -> usize {
33
}
}
impl Clone for FakeDatabase {
fn clone(&self) -> Self {
FakeDatabase {}
}
}
impl DatabaseQuery for FakeDatabase {
fn query(&self, query: &Query) -> Result<Vec<QueryResult>> {
Ok((0..50)
.map(|e| QueryResult::Grouped {
count: e as usize + 30,
value: ValueField::usize(&Field::Month, e as usize),
})
.collect())
}
}
impl DatabaseLike for FakeDatabase {
fn new(path: impl AsRef<Path>) -> Result<Self>
where
Self: Sized,
{
Ok(FakeDatabase {})
}
fn config(path: impl AsRef<Path>) -> Result<Config>
where
Self: Sized,
{
bail!("Na")
}
fn total_mails(&self) -> Result<usize> {
Ok(0)
}
fn import(self) -> (Sender<DBMessage>, JoinHandle<Result<usize>>) {
panic!()
}
fn save_config(&self, config: Config) -> Result<()> {
Ok(())
}
}

@ -0,0 +1,28 @@
#[cfg(target_arch = "wasm32")]
use ps_core::{Config, FormatType};
#[cfg(target_arch = "wasm32")]
use ps_gui::{eframe, PostsackApp};
mod database;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*;
#[cfg(target_arch = "wasm32")]
use console_error_panic_hook;
/// Call this once from the HTML.
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
pub fn start(canvas_id: &str) -> Result<(), eframe::wasm_bindgen::JsValue> {
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
use database::FakeDatabase;
let format = FormatType::AppleMail;
let config = Config::new(None, "", vec!["test@gmail.com".to_owned()], format).unwrap();
let app = PostsackApp::<database::FakeDatabase>::new(config, FakeDatabase::total_item_count());
eframe::start_web(canvas_id, Box::new(app))
}

@ -0,0 +1,89 @@
<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- Disable zooming: -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<head>
<title>egui An experimental immediate mode GUI written in Rust</title>
<style>
html {
/* Remove touch delay: */
touch-action: manipulation;
}
body {
/* Light mode background color for what is not covered by the egui canvas,
or where the egui canvas is translucent. */
background: #909090;
}
@media (prefers-color-scheme: dark) {
body {
/* Dark mode background color for what is not covered by the egui canvas,
or where the egui canvas is translucent. */
background: #404040;
}
}
/* Allow canvas to fill entire web page: */
html,
body {
overflow: hidden;
margin: 0 !important;
padding: 0 !important;
}
/* Position canvas in center-top: */
canvas {
margin-right: auto;
margin-left: auto;
display: block;
position: absolute;
top: 0%;
left: 50%;
transform: translate(-50%, 0%);
}
</style>
</head>
<body>
<!-- The WASM code will resize this dynamically -->
<canvas id="the_canvas_id"></canvas>
<script>
// The `--no-modules`-generated JS from `wasm-bindgen` attempts to use
// `WebAssembly.instantiateStreaming` to instantiate the wasm module,
// but this doesn't work with `file://` urls. This example is frequently
// viewed by simply opening `index.html` in a browser (with a `file://`
// url), so it would fail if we were to call this function!
//
// Work around this for now by deleting the function to ensure that the
// `no_modules.js` script doesn't have access to it. You won't need this
// hack when deploying over HTTP.
delete WebAssembly.instantiateStreaming;
</script>
<!-- this is the JS generated by the `wasm-bindgen` CLI tool -->
<script src="postsack_web.js"></script>
<script>
// We'll defer our execution until the wasm is ready to go.
// Here we tell bindgen the path to the wasm file so it can start
// initialization and return to us a promise when it's done.
wasm_bindgen("./postsack_web_bg.wasm")
.then(on_wasm_loaded)
.catch(console.error);
function on_wasm_loaded() {
// This call installs a bunch of callbacks and then returns.
console.log("loaded wasm, starting egui app");
wasm_bindgen.start("the_canvas_id");
}
</script>
</body>
</html>
<!-- Powered by egui: https://github.com/emilk/egui/ -->

@ -1,8 +1,10 @@
use ps_database::Database;
use ps_gui::{eframe, PostsackApp};
fn main() {
#[cfg(debug_assertions)]
ps_core::setup_tracing();
ps_gui::run_ui::<Database>();
let options = eframe::NativeOptions::default();
eframe::run_native(Box::new(PostsackApp::<Database>::new()), options);
}

@ -1,29 +0,0 @@
#!/bin/sh
set -e
rm -rf target/release/bundle/osx/Postsack.app
# Build for x86 and ARM
cargo build --release --target=aarch64-apple-darwin
cargo build --release --target=x86_64-apple-darwin
# Combine into a fat binary
lipo -create target/aarch64-apple-darwin/release/postsack target/x86_64-apple-darwin/release/postsack -output postsack
# Perform Cargo bundle to create a macOS Bundle
cargo bundle --release
# Override bundle binary with the fat one
# Also: We want to have `Postsack` capitalized on macOS, so we rename
rm target/release/bundle/osx/Postsack.app/Contents/MacOS/postsack
mv ./postsack target/release/bundle/osx/Postsack.app/Contents/MacOS/
# Tell the Info.plist or binary is capitalized
/usr/libexec/PlistBuddy -c "Set :CFBundleExecutable Postsack" "target/release/bundle/osx/Postsack.app/Contents/Info.plist"

@ -7,9 +7,5 @@ mod segmentation_bar;
mod textures;
pub(crate) mod widgets;
use ps_core::DatabaseLike;
pub fn run_ui<Database: DatabaseLike>() {
let options = eframe::NativeOptions::default();
eframe::run_native(Box::new(app::PostsackApp::<Database>::new()), options);
}
pub use app::PostsackApp;
pub use eframe;

Loading…
Cancel
Save