Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0c5cf173a6 | |||
| c0eca40382 | |||
| bd563c4785 | |||
| 9c29a99731 | |||
| 0f4fc07416 | |||
| 989b3af4c1 | |||
| d11952525e | |||
| 6dbadf1e74 | |||
| 08c28830b0 | |||
| f9db7deed1 | |||
| 2ddc8b9091 | |||
| 5b10e60102 | |||
| 7b39e2c243 | |||
| c9c6477133 | |||
| b310d54a43 | |||
| 9014fe3023 | |||
| 01e9fb4256 | |||
| f74ebb45e1 | |||
| 13a2e52f9d |
66
.github/workflows/main.yaml
vendored
Normal file
66
.github/workflows/main.yaml
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
---
|
||||
name: Main workflow
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Lint code & build
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
container: alpine:3.19
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
apk update
|
||||
apk add \
|
||||
build-base \
|
||||
git \
|
||||
glib-dev \
|
||||
gtk+3.0-dev \
|
||||
nodejs \
|
||||
webkit2gtk-4.1-dev
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup toolchain
|
||||
uses: actions/rs-toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Get Cargo.lock hash
|
||||
id: hash
|
||||
run: |
|
||||
hash="$(sha256sum Cargo.lock | awk '{print $1}')"
|
||||
echo "hash=$hash" >>"$GITHUB_OUTPUT"
|
||||
|
||||
- name: Setup cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
target/
|
||||
key: cargo-${{ steps.hash.outputs.hash }}
|
||||
|
||||
- name: Run fmt
|
||||
run: cargo fmt --all --check
|
||||
|
||||
- name: Run check
|
||||
run: cargo check
|
||||
|
||||
- name: Run clippy
|
||||
run: cargo clippy -- -D warnings
|
||||
|
||||
- name: Build
|
||||
run: cargo build
|
||||
env:
|
||||
# Disable static linking; rustup's toolchain enables by default for musl
|
||||
RUSTFLAGS: -C target-feature=-crt-static
|
||||
11
.renovaterc.json5
Normal file
11
.renovaterc.json5
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"dependencyDashboard": true,
|
||||
"extends": [
|
||||
":enableVulnerabilityAlerts",
|
||||
"group:allNonMajor",
|
||||
"schedule:weekly",
|
||||
"security:openssf-scorecard",
|
||||
],
|
||||
"enabledManagers": ["cargo"],
|
||||
}
|
||||
1129
Cargo.lock
generated
1129
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
10
Cargo.toml
10
Cargo.toml
@@ -5,10 +5,10 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
confy = "0.6.0"
|
||||
confy = "0.6.1"
|
||||
dirs = "5.0.1"
|
||||
eyre = "0.6.12"
|
||||
serde = { version = "1.0.196", features = ["derive"] }
|
||||
serde_json = "1.0.113"
|
||||
tao = "0.25.0"
|
||||
wry = "0.36.0"
|
||||
serde = { version = "1.0.199", features = ["derive"] }
|
||||
serde_json = "1.0.116"
|
||||
tao = "0.29.0"
|
||||
wry = "0.42.0"
|
||||
|
||||
56
html/index.html
Normal file
56
html/index.html
Normal file
@@ -0,0 +1,56 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>SilverBullet</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
main {
|
||||
display: flex;
|
||||
margin: 0 auto;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 100vh;
|
||||
max-width: 768px;
|
||||
}
|
||||
|
||||
input, button {
|
||||
padding: 10px;
|
||||
margin: 5px 0;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<form id="set_url" target="#">
|
||||
<label for="url"><b>Set your SilverBullet instance</b></label>
|
||||
<input type="url" id="url" name="url" required autofocus />
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
</main>
|
||||
<script>
|
||||
const form = document.getElementById('set_url');
|
||||
form.addEventListener('submit', async (e) => {
|
||||
try {
|
||||
// Test that the URL is a valid URL.
|
||||
const url = new URL(form.elements['url'].value);
|
||||
// Test that the URL resolves to an actual website.
|
||||
await fetch(url.href, { method: 'HEAD', mode: 'no-cors' });
|
||||
window.ipc.postMessage(JSON.stringify({ command: 'set_url', url }));
|
||||
window.location.assign(url);
|
||||
} catch(e) {
|
||||
if (e instanceof TypeError) {
|
||||
// Fetch failed due to network error (dns, etc.)
|
||||
alert('Failed to connect to SilverBullet due to a network error.\nPlease check that the URL is correct and you are connected.');
|
||||
} else {
|
||||
alert('The SilverBullet URL doesn\'t seem to be valid.\nPlease check that the URL is correct.');
|
||||
}
|
||||
}
|
||||
e.preventDefault();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -11,7 +11,7 @@ window.addEventListener('load', () => {
|
||||
if (target.href !== null) {
|
||||
if (target.host !== window.location.host) {
|
||||
window.ipc.postMessage(JSON.stringify({
|
||||
command: "open",
|
||||
command: 'open',
|
||||
uri: target.href,
|
||||
}));
|
||||
e.preventDefault();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use eyre::eyre;
|
||||
use confy::ConfyError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub const APP_NAME: &str = env!("CARGO_PKG_NAME");
|
||||
@@ -10,11 +10,11 @@ pub struct Config {
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn load() -> eyre::Result<Self> {
|
||||
let cfg: Config = confy::load(APP_NAME, "config")?;
|
||||
if cfg.base_url.is_empty() {
|
||||
return Err(eyre!("base_url must not be empty"));
|
||||
}
|
||||
Ok(cfg)
|
||||
pub fn load() -> Result<Self, ConfyError> {
|
||||
confy::load(APP_NAME, "config")
|
||||
}
|
||||
|
||||
pub fn store(&self) -> Result<(), ConfyError> {
|
||||
confy::store(APP_NAME, "config", self)
|
||||
}
|
||||
}
|
||||
|
||||
11
src/ipc.rs
11
src/ipc.rs
@@ -2,10 +2,13 @@ use std::process;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::config::Config;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(tag = "command", rename_all = "lowercase")]
|
||||
#[serde(tag = "command", rename_all = "snake_case")]
|
||||
pub enum Command {
|
||||
Open { uri: String },
|
||||
SetUrl { url: String },
|
||||
}
|
||||
|
||||
impl Command {
|
||||
@@ -15,6 +18,12 @@ impl Command {
|
||||
process::Command::new("xdg-open").arg(uri).output()?;
|
||||
Ok(())
|
||||
}
|
||||
Command::SetUrl { url } => {
|
||||
let cfg = Config {
|
||||
base_url: url.to_string(),
|
||||
};
|
||||
Ok(cfg.store()?)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,27 +15,34 @@ pub fn run(cfg: Config) -> eyre::Result<()> {
|
||||
.with_title("SilverBullet")
|
||||
.build(&event_loop)?;
|
||||
|
||||
let builder = WebViewBuilder::new_gtk(
|
||||
window
|
||||
.default_vbox()
|
||||
.ok_or_else(|| eyre!("failed to get vbox"))?,
|
||||
);
|
||||
let data_dir = dirs::state_dir()
|
||||
.ok_or_else(|| eyre!("failed to find state dir"))?
|
||||
.join(APP_NAME);
|
||||
let mut context = WebContext::new(Some(data_dir));
|
||||
|
||||
let webview = builder
|
||||
.with_initialization_script(include_str!("../js/init.js"))
|
||||
.with_ipc_handler(|msg| match serde_json::from_str::<Command>(&msg) {
|
||||
Ok(cmd) => cmd
|
||||
.handle()
|
||||
.unwrap_or_else(|err| eprintln!("failed to handle command: {err}")),
|
||||
Err(err) => eprintln!("invalid ipc command {msg}: {err}"),
|
||||
})
|
||||
.with_web_context(&mut context)
|
||||
.with_url(&cfg.base_url)?
|
||||
.build()?;
|
||||
let mut builder = WebViewBuilder::new_gtk(
|
||||
window
|
||||
.default_vbox()
|
||||
.ok_or_else(|| eyre!("failed to get vbox"))?,
|
||||
)
|
||||
.with_initialization_script(include_str!("../js/init.js"))
|
||||
.with_ipc_handler(|req| match serde_json::from_str::<Command>(req.body()) {
|
||||
Ok(cmd) => cmd
|
||||
.handle()
|
||||
.unwrap_or_else(|err| eprintln!("failed to handle command: {err}")),
|
||||
Err(err) => eprintln!("invalid ipc command {}: {err}", req.body()),
|
||||
})
|
||||
.with_web_context(&mut context);
|
||||
if cfg.base_url.is_empty() {
|
||||
builder = builder.with_html(include_str!("../html/index.html"));
|
||||
} else {
|
||||
let mut base_url = cfg.base_url;
|
||||
if !(base_url.starts_with("http://") || base_url.starts_with("https://")) {
|
||||
base_url.insert_str(0, "https://");
|
||||
}
|
||||
builder = builder.with_url(&base_url);
|
||||
}
|
||||
let webview = builder.build()?;
|
||||
|
||||
let mut modifiers = ModifiersState::default();
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
|
||||
Reference in New Issue
Block a user