Compare commits

...

20 commits
v0.1.0 ... main

Author SHA1 Message Date
Breadway
df42aba1d3 CI: use /tmp for ecosystem clone, avoid permissions conflict
All checks were successful
Mirror to GitHub / mirror (push) Successful in 2s
2026-06-19 08:38:40 +08:00
Breadway
e0b55e1713 Bump bread-theme to v0.2.8 (live-reload fix)
Some checks failed
Mirror to GitHub / mirror (push) Successful in 2s
Build and publish package / package (push) Failing after 4m47s
2026-06-17 12:55:57 +08:00
Breadway
c30aa2497e Fix illegible text on light pywal palettes + hot-reload
Use bread-theme 0.2.7's luminance-picked ink (@on-*): type chips on @overlay and
selected sidebar rows / confirm buttons on @blue kept @fg or @bg, which vanished
when those slots came out light/dark. They now use @on-overlay / @on-accent.

Add breadpad_shared::theme::apply_live (wraps bread_theme::gtk::apply_app_css) so
breadpad and breadman recolour live on `bread-theme reload` and re-read the user's
style.css — replacing the build-once provider. bread-theme bumped to v0.2.7
(gtk feature).
2026-06-17 12:42:12 +08:00
Breadway
dfe19708ba Release 0.3.4: shared bread-theme stylesheet (overlay=color7)
Some checks failed
Mirror to GitHub / mirror (push) Successful in 2s
Build and publish package / package (push) Failing after 4m33s
2026-06-16 18:35:33 +08:00
Breadway
08d8956eac docs: add CalDAV calendar-sync walkthrough
The [calendar] config keys existed without explanation. Document enabling
CalDAV sync end to end: finding the collection URL, creating an app password,
the config block, and the best-effort sync behaviour.
2026-06-16 17:07:06 +08:00
Breadway
49f6966d9c theme: build on the shared bread-theme stylesheet
build_css() now starts from bread_theme::stylesheet(palette) and appends only
breadpad/breadman-specific components. This unifies fonts, palette, and generic
widgets with the rest of the ecosystem and fixes the colour mapping (overlay is
now color7, matching every other app, not color0). Bump bread-theme to v0.2.6.
2026-06-16 16:57:16 +08:00
Breadway
eab3775de1 Disable debug package so the main package publishes correctly
Some checks failed
Mirror to GitHub / mirror (push) Successful in 2s
Build and publish package / package (push) Failing after 3m53s
makepkg's debug split produced a -debug pkg; the upload's head -1 could
grab it instead of the main package. !debug yields a single package.
2026-06-13 23:00:52 +08:00
Breadway
9ae815caa2 Use REGISTRY_TOKEN (scoped write:package) for registry publish
Some checks failed
Mirror to GitHub / mirror (push) Successful in 2s
Build and publish package / package (push) Failing after 6m16s
2026-06-13 22:55:43 +08:00
Breadway
d4ae2dfed4 Disable LTO in PKGBUILD (vendored ring/mlua static libs vs makepkg -flto) 2026-06-13 17:06:56 +08:00
Breadway
d1aef21998 Clone from public URL, not GITHUB_SERVER_URL (resolves to localhost in runner)
The Forgejo runner injects GITHUB_SERVER_URL as http://localhost:3002, which
is unreachable from inside the job container. Use the public URL instead.
2026-06-13 16:14:15 +08:00
Breadway
ca95ac0693 Rename mirror secret to MIRROR_TOKEN (GITHUB_ prefix is reserved)
Forgejo/gitea rejects user secret names starting with GITHUB_.
2026-06-13 16:10:51 +08:00
Breadway
ce0b7740d6 Fix Forgejo workflows for the actual server capabilities
- package.yml: correct Arch registry upload (octet-stream + binary body),
  drop --privileged, manual shell clone (archlinux image has no Node),
  built-in Actions token, --nocheck
- mirror.yml: clone --mirror + explicit refs push with --prune
2026-06-13 16:02:30 +08:00
Breadway
659e3da5ed Add packaging/arch PKGBUILD and Forgejo Actions workflows
- packaging/arch/PKGBUILD: builds and publishes breadpad to [breadway] repo
- .forgejo/workflows/mirror.yml: mirrors every push/tag to GitHub
- .forgejo/workflows/package.yml: builds on tag, publishes to Forgejo registry

Requires FORGEJO_TOKEN and GITHUB_MIRROR_TOKEN secrets in Forgejo.
2026-06-13 12:12:43 +08:00
Breadway
596ae90455 fix: enable load-dynamic ORT feature for breadpad-test
Some checks failed
release / build (push) Failing after 2s
ort::init_from requires the load-dynamic feature; breadpad-test calls
it to load libonnxruntime.so from a runtime path.
2026-06-11 14:53:23 +08:00
Breadway
e21c5c4ad3 chore: update Cargo.lock for v0.3.1 2026-06-11 14:28:11 +08:00
Breadway
bf4586e608 chore: bump version to 0.3.1 2026-06-11 14:21:50 +08:00
Breadway
d7d8828477 fix: remove non-existent rocm-runtime dep, add optional_system_deps
rocm-runtime is not a real Arch package name. ORT links ONNX Runtime
statically and falls back to CPU — ROCm should not block install.
Required: gtk4, gtk4-layer-shell only.
Optional: rocm-hip-runtime (GPU inference), ollama (AI fallback), hyprland.
2026-06-11 13:38:35 +08:00
Breadway
8dbeacb46d feat: enable ROCm EP for GPU inference, add rocm-runtime system dep
Some checks failed
release / build (push) Failing after 5s
Switches ort from load-dynamic to rocm feature so the ROCm execution
provider is compiled in. Adds rocm-runtime to bakery system_deps so
bakery doctor/install can verify it's present.
2026-06-07 15:59:02 +08:00
Breadway
478d06a5d5 fix: skip ROCm EP registration when not available in ORT build
Some checks failed
release / build (push) Failing after 3s
Eliminates the spurious ERROR log from ORT when ROCm isn't compiled in.
Checks is_available() before attempting registration so the session
correctly falls back to CPU without noise.
2026-06-07 15:53:06 +08:00
Breadway
708eb8f3b4 fix: use relative symlink for latest to work inside Docker containers 2026-06-07 09:02:38 +08:00
13 changed files with 212 additions and 134 deletions

View file

@ -0,0 +1,21 @@
name: Mirror to GitHub
on:
push:
branches: ['**']
tags: ['**']
jobs:
mirror:
runs-on: [self-hosted, hestia]
steps:
- name: Mirror to GitHub
run: |
set -euo pipefail
git clone --mirror "https://git.breadway.dev/${GITHUB_REPOSITORY}.git" repo.git
cd repo.git
# Mirror only branches and tags (not refs/pull/*, which GitHub rejects);
# --prune deletes GitHub refs that no longer exist on Forgejo.
git push --prune \
"https://x-access-token:${{ secrets.MIRROR_TOKEN }}@github.com/Breadway/breadpad.git" \
'+refs/heads/*:refs/heads/*' '+refs/tags/*:refs/tags/*'

View file

@ -0,0 +1,40 @@
name: Build and publish package
on:
push:
tags: ['v*']
jobs:
package:
runs-on: [self-hosted, hestia]
container:
image: archlinux:latest
steps:
# Note: no actions/checkout — the archlinux image has no Node, which JS
# actions require. Everything runs as shell steps and clones manually.
- name: Build and publish
env:
PUBLISH_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: |
set -euo pipefail
VERSION="${GITHUB_REF_NAME#v}"
pacman -Syu --noconfirm base-devel git rust cargo gtk4 gtk4-layer-shell
useradd -m builder
git config --global --add safe.directory '*'
git clone --branch "${GITHUB_REF_NAME}" --depth 1 \
"https://git.breadway.dev/${GITHUB_REPOSITORY}.git" /home/builder/src
cd /home/builder/src
git archive --format=tar.gz --prefix="breadpad-${VERSION}/" HEAD \
> packaging/arch/breadpad-${VERSION}.tar.gz
SHA=$(sha256sum packaging/arch/breadpad-${VERSION}.tar.gz | awk '{print $1}')
sed -i "s/^pkgver=.*/pkgver=${VERSION}/" packaging/arch/PKGBUILD
sed -i "s/^sha256sums=.*/sha256sums=('${SHA}')/" packaging/arch/PKGBUILD
chown -R builder:builder /home/builder/src
# --nocheck: packaging builds the artifact; tests belong in a CI job.
su builder -c "cd /home/builder/src/packaging/arch && makepkg -f --noconfirm --nocheck"
PKG=$(find /home/builder/src/packaging/arch -name '*.pkg.tar.zst' | head -1)
curl -fsS -X PUT \
-H "Authorization: token ${PUBLISH_TOKEN}" \
-H "Content-Type: application/octet-stream" \
--data-binary "@${PKG}" \
"https://git.breadway.dev/api/packages/Breadway/arch/os"

View file

@ -9,7 +9,7 @@ permissions:
env: env:
DL_DIR: /srv/breadway-dl DL_DIR: /srv/breadway-dl
ECOSYSTEM_DIR: /home/breadway/Projects/bread-ecosystem ECOSYSTEM_DIR: /tmp/bread-ecosystem-ci
jobs: jobs:
build: build:
@ -36,16 +36,12 @@ jobs:
done done
cp breadpad.example.toml "${PKG_DIR}/" cp breadpad.example.toml "${PKG_DIR}/"
cp bakery.toml "${PKG_DIR}/bakery.toml" cp bakery.toml "${PKG_DIR}/bakery.toml"
ln -sfn "${PKG_DIR}" "${DL_DIR}/breadpad/latest" ln -sfn "${VERSION}" "${DL_DIR}/breadpad/latest"
- name: ensure bread-ecosystem - name: ensure bread-ecosystem
run: | run: |
if [[ -d "${ECOSYSTEM_DIR}/.git" ]]; then rm -rf "${ECOSYSTEM_DIR}"
git -C "${ECOSYSTEM_DIR}" pull --ff-only git clone https://github.com/Breadway/bread-ecosystem.git "${ECOSYSTEM_DIR}"
else
mkdir -p "$(dirname "${ECOSYSTEM_DIR}")"
git clone https://github.com/Breadway/bread-ecosystem.git "${ECOSYSTEM_DIR}"
fi
- name: regenerate index.json - name: regenerate index.json
run: bash "${ECOSYSTEM_DIR}/scripts/gen-index.sh" run: bash "${ECOSYSTEM_DIR}/scripts/gen-index.sh"

13
Cargo.lock generated
View file

@ -304,17 +304,18 @@ dependencies = [
[[package]] [[package]]
name = "bread-theme" name = "bread-theme"
version = "0.1.0" version = "0.2.3"
source = "git+https://github.com/Breadway/bread-ecosystem?tag=v0.1.0#6b5f4f475f66a645b08cb865e6dda8228d23679b" source = "git+https://github.com/Breadway/bread-ecosystem?tag=v0.2.8#77417d552130281ff787e07d52541eb25e9d533b"
dependencies = [ dependencies = [
"dirs 5.0.1", "dirs 5.0.1",
"gtk4",
"serde", "serde",
"serde_json", "serde_json",
] ]
[[package]] [[package]]
name = "breadman" name = "breadman"
version = "0.1.0" version = "0.3.4"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"breadpad-shared", "breadpad-shared",
@ -331,7 +332,7 @@ dependencies = [
[[package]] [[package]]
name = "breadpad" name = "breadpad"
version = "0.1.0" version = "0.3.4"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"breadpad-shared", "breadpad-shared",
@ -350,7 +351,7 @@ dependencies = [
[[package]] [[package]]
name = "breadpad-shared" name = "breadpad-shared"
version = "0.1.0" version = "0.3.4"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bread-theme", "bread-theme",
@ -376,7 +377,7 @@ dependencies = [
[[package]] [[package]]
name = "breadpad-test" name = "breadpad-test"
version = "0.1.0" version = "0.3.4"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"breadpad-shared", "breadpad-shared",

View file

@ -8,7 +8,7 @@ members = [
resolver = "2" resolver = "2"
[workspace.package] [workspace.package]
version = "0.1.0" version = "0.3.4"
edition = "2021" edition = "2021"
license = "MIT" license = "MIT"
authors = ["Breadway"] authors = ["Breadway"]
@ -24,7 +24,7 @@ chrono = { version = "0.4", features = ["serde"] }
rrule = "0.12" rrule = "0.12"
tokio = { version = "1", features = ["full"] } tokio = { version = "1", features = ["full"] }
zbus = { version = "4", default-features = false, features = ["tokio"] } zbus = { version = "4", default-features = false, features = ["tokio"] }
ort = { version = "2.0.0-rc.12", default-features = false, features = ["std", "ndarray", "tracing", "api-24", "load-dynamic"] } ort = { version = "2.0.0-rc.12", default-features = false, features = ["std", "ndarray", "tracing", "api-24", "rocm", "load-dynamic"] }
ndarray = "0.16" ndarray = "0.16"
tokenizers = { version = "0.21", default-features = false, features = ["http", "fancy-regex"] } tokenizers = { version = "0.21", default-features = false, features = ["http", "fancy-regex"] }
gtk4 = { version = "0.11", features = ["v4_12"] } gtk4 = { version = "0.11", features = ["v4_12"] }

View file

@ -190,8 +190,41 @@ enabled = true # set false to never call Ollama
[reminders] [reminders]
default_morning = "08:00" # what "tomorrow morning" resolves to default_morning = "08:00" # what "tomorrow morning" resolves to
missed_grace_minutes = 60 # how long after boot to still fire a missed reminder missed_grace_minutes = 60 # how long after boot to still fire a missed reminder
[calendar]
enabled = false # turn on CalDAV sync (see below)
url = "" # CalDAV calendar collection URL
username = ""
password = "" # app password / token recommended
``` ```
### Calendar sync (CalDAV)
When `[calendar].enabled = true`, reminders and dated notes are pushed to a
CalDAV calendar as events (tracked by `caldav_uid` on each note), so they show
up alongside the rest of your calendar.
1. Find your calendar's **collection URL**. It's the per-calendar CalDAV path,
not the server root — e.g. Nextcloud:
`https://host/remote.php/dav/calendars/<user>/<calendar-id>/`.
2. Create an **app password** for breadpad (don't use your main password):
Nextcloud → Settings → Security → *Devices & sessions* → "Create new app
password". Most CalDAV servers have an equivalent.
3. Fill in `breadpad.toml` (or BOS Settings → breadpad → Calendar):
```toml
[calendar]
enabled = true
url = "https://host/remote.php/dav/calendars/me/breadpad/"
username = "me"
password = "xxxx-xxxx-xxxx-xxxx"
```
4. Restart breadpad. New dated/reminder notes sync up; the `caldav_uid` field
links each note to its event so updates and deletes stay in step.
If the server is unreachable, breadpad logs a warning and keeps the note
locally — sync is best-effort and never blocks capture.
--- ---
## Usage ## Usage

View file

@ -2,6 +2,7 @@ name = "breadpad"
description = "Quick-capture scratchpad and note viewer with AI classification" description = "Quick-capture scratchpad and note viewer with AI classification"
binaries = ["breadpad", "breadman"] binaries = ["breadpad", "breadman"]
system_deps = ["gtk4", "gtk4-layer-shell"] system_deps = ["gtk4", "gtk4-layer-shell"]
optional_system_deps = ["rocm-hip-runtime", "ollama", "hyprland"]
bread_deps = [] bread_deps = []
[config] [config]

View file

@ -4,7 +4,6 @@ use breadpad_shared::{
parser::parse_rule_based, parser::parse_rule_based,
scheduler::Scheduler, scheduler::Scheduler,
store::Store, store::Store,
theme::{build_css, load_palette},
types::{Note, NoteType, RecurrenceRule}, types::{Note, NoteType, RecurrenceRule},
}; };
use chrono::Local; use chrono::Local;
@ -924,19 +923,7 @@ fn show_add_note_window(parent: &gtk4::ApplicationWindow, state: AppState) {
// ── CSS ─────────────────────────────────────────────────────────────────────── // ── CSS ───────────────────────────────────────────────────────────────────────
fn apply_css(_cfg: &Config) { fn apply_css(_cfg: &Config) {
let palette = load_palette(); // Hot-reloads on `bread-theme reload` (recolours to the new pywal palette
let user_css = std::fs::read_to_string(breadpad_shared::config::style_css_path()).ok(); // and re-reads the user's style.css). See breadpad_shared::theme::apply_live.
let css = build_css(&palette, user_css.as_deref()); breadpad_shared::theme::apply_live();
let provider = gtk4::CssProvider::new();
provider.load_from_string(&css);
let Some(display) = gtk4::gdk::Display::default() else {
tracing::warn!("no default display; skipping CSS provider");
return;
};
gtk4::style_context_add_provider_for_display(
&display,
&provider,
gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION,
);
} }

View file

@ -7,7 +7,7 @@ authors.workspace = true
[dependencies] [dependencies]
bread-theme = { git = "https://github.com/Breadway/bread-ecosystem", tag = "v0.1.0" } bread-theme = { git = "https://github.com/Breadway/bread-ecosystem", tag = "v0.2.8", features = ["gtk"] }
anyhow.workspace = true anyhow.workspace = true
tracing.workspace = true tracing.workspace = true
serde.workspace = true serde.workspace = true

View file

@ -247,12 +247,18 @@ fn try_load_session(
path: &std::path::Path, path: &std::path::Path,
) -> (Option<ort::session::Session>, ExecutionProvider) { ) -> (Option<ort::session::Session>, ExecutionProvider) {
// Try ROCm (iGPU) first, fall back to CPU. // Try ROCm (iGPU) first, fall back to CPU.
match build_onnx_session(path, ort::ep::ROCm::default().build()) { let rocm_available = {
Ok(s) => { use ort::execution_providers::ExecutionProvider as _;
tracing::info!("ONNX session loaded (ROCm iGPU)"); ort::ep::ROCm::default().is_available().unwrap_or(false)
return (Some(s), ExecutionProvider::Gpu); };
if rocm_available {
match build_onnx_session(path, ort::ep::ROCm::default().build()) {
Ok(s) => {
tracing::info!("ONNX session loaded (ROCm iGPU)");
return (Some(s), ExecutionProvider::Gpu);
}
Err(e) => tracing::debug!("ROCm EP unavailable: {}; trying CPU", e),
} }
Err(e) => tracing::debug!("ROCm EP unavailable: {}; trying CPU", e),
} }
match build_onnx_session(path, ort::ep::CPU::default().build()) { match build_onnx_session(path, ort::ep::CPU::default().build()) {
Ok(s) => { Ok(s) => {

View file

@ -1,31 +1,34 @@
pub use bread_theme::{load_palette, Palette}; pub use bread_theme::{load_palette, Palette};
/// Generate the full breadpad CSS string. The base colour variables come from /// Apply breadpad/breadman's stylesheet and keep it live across palette changes.
/// `bread-theme`; the widget rules below are breadpad-specific. /// [`build_css`] bundles the shared component sheet with the app's own rules from
/// the current pywal palette; `bread_theme::gtk::apply_app_css` re-runs this
/// whenever `bread-theme reload` rewrites the shared theme file, so the UI
/// recolours in place (and re-reads the user's `style.css` override too).
pub fn apply_live() {
bread_theme::gtk::apply_app_css(|| {
let palette = load_palette();
let user_css = std::fs::read_to_string(crate::config::style_css_path()).ok();
build_css(&palette, user_css.as_deref())
});
}
/// Generate the full breadpad/breadman CSS string. The base — `@define-color`
/// palette, fonts, and generic widget styling — comes from the shared
/// `bread_theme::stylesheet`, so breadpad and breadman look identical to the
/// rest of the ecosystem. Only breadpad-specific component rules are appended.
pub fn build_css(palette: &Palette, user_css: Option<&str>) -> String { pub fn build_css(palette: &Palette, user_css: Option<&str>) -> String {
let mut css = format!( // Shared ecosystem base (define-colors incl. accent, font, buttons, entries,
// switches, lists, cards, scrollbars). `overlay` here is color7 — consistent
// with every other bread app (breadpad previously mapped it to color0).
let mut css = bread_theme::stylesheet(palette);
css.push_str(
r#" r#"
@define-color bg {bg}; /* breadpad/breadman-specific components */
@define-color fg {fg}; window { border-radius: 8px; }
@define-color red {c1};
@define-color green {c2};
@define-color yellow {c3};
@define-color blue {c4};
@define-color pink {c5};
@define-color teal {c6};
@define-color overlay {c0};
* {{ .popup-entry {
font-family: 'Varela Round', sans-serif;
}}
window {{
background-color: @bg;
color: @fg;
border-radius: 8px;
}}
.popup-entry {{
background: @bg; background: @bg;
color: @fg; color: @fg;
border: 2px solid @blue; border: 2px solid @blue;
@ -33,80 +36,59 @@ window {{
padding: 12px 16px; padding: 12px 16px;
font-size: 14px; font-size: 14px;
caret-color: @fg; caret-color: @fg;
}} }
.popup-entry:focus {{ .popup-entry:focus {
outline: none; outline: none;
border-color: @teal; border-color: @teal;
}} }
.type-chip {{ .type-chip {
background: @overlay; background: @overlay;
color: @fg; color: @on-overlay;
border-radius: 999px; border-radius: 999px;
padding: 4px 12px; padding: 4px 12px;
font-size: 12px; font-size: 12px;
margin: 4px; margin: 4px;
}} }
.type-chip.active {{ .type-chip.active {
background: @blue; background: @blue;
color: @bg; color: @on-accent;
}} }
.confirm-button {{ .confirm-button {
background: @blue; background: @blue;
color: @bg; color: @on-accent;
border: none; border: none;
border-radius: 8px; border-radius: 8px;
padding: 8px 16px; padding: 8px 16px;
font-weight: bold; font-weight: bold;
}} }
.note-card {{ .note-card {
background: shade(@bg, 1.1); background: shade(@bg, 1.1);
border-radius: 8px; border-radius: 8px;
padding: 12px; padding: 12px;
margin: 8px; margin: 8px;
border-left: 3px solid @blue; border-left: 3px solid @blue;
}} }
.note-card:hover {{ .note-card:hover {
background: shade(@bg, 1.2); background: shade(@bg, 1.2);
}} }
.search-entry {{ .search-entry {
background: shade(@bg, 1.1); background: shade(@bg, 1.1);
color: @fg; color: @fg;
border: 1px solid @overlay; border: 1px solid @overlay;
border-radius: 6px; border-radius: 6px;
padding: 8px 12px; padding: 8px 12px;
}}
.search-entry:focus {{
border-color: @blue;
outline: none;
}}
"#,
bg = palette.background,
fg = palette.foreground,
c0 = palette.color0,
c1 = palette.color1,
c2 = palette.color2,
c3 = palette.color3,
c4 = palette.color4,
c5 = palette.color5,
c6 = palette.color6,
);
css.push_str(r#"
.dim-label {
color: alpha(@fg, 0.5);
font-size: 12px;
} }
.sidebar { .search-entry:focus {
background: shade(@bg, 0.93); border-color: @blue;
outline: none;
} }
.sidebar-row { .sidebar-row {
@ -121,7 +103,7 @@ window {{
.sidebar-row:selected { .sidebar-row:selected {
background: @blue; background: @blue;
color: @bg; color: @on-accent;
font-weight: 500; font-weight: 500;
} }
@ -217,20 +199,6 @@ window {{
} }
.snooze-option:hover { background: shade(@bg, 1.2); } .snooze-option:hover { background: shade(@bg, 1.2); }
entry {
background: shade(@bg, 1.1);
color: @fg;
border: 1px solid @overlay;
border-radius: 6px;
caret-color: @fg;
padding: 5px 10px;
}
entry:focus {
border-color: @blue;
outline: none;
}
"#); "#);
if let Some(extra) = user_css { if let Some(extra) = user_css {

View file

@ -2,10 +2,9 @@ use anyhow::Result;
use breadpad_shared::{ use breadpad_shared::{
calendar::CalDavClient, calendar::CalDavClient,
classifier::Classifier, classifier::Classifier,
config::{style_css_path, Config}, config::Config,
scheduler::Scheduler, scheduler::Scheduler,
store::Store, store::Store,
theme::{build_css, load_palette},
types::{Note, NoteType}, types::{Note, NoteType},
}; };
use gtk4::{glib, prelude::*}; use gtk4::{glib, prelude::*};
@ -765,19 +764,7 @@ fn save_note_classified(
} }
fn apply_css(_cfg: &Config) { fn apply_css(_cfg: &Config) {
let palette = load_palette(); // Hot-reloads on `bread-theme reload` (recolours to the new pywal palette
let user_css = std::fs::read_to_string(style_css_path()).ok(); // and re-reads the user's style.css). See breadpad_shared::theme::apply_live.
let css = build_css(&palette, user_css.as_deref()); breadpad_shared::theme::apply_live();
let provider = gtk4::CssProvider::new();
provider.load_from_string(&css);
let Some(display) = gtk4::gdk::Display::default() else {
tracing::warn!("no default display; skipping CSS provider");
return;
};
gtk4::style_context_add_provider_for_display(
&display,
&provider,
gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION,
);
} }

38
packaging/arch/PKGBUILD Normal file
View file

@ -0,0 +1,38 @@
# Maintainer: Breadway <rileyhorsham@gmail.com>
pkgname=breadpad
pkgver=0.3.1
pkgrel=1
pkgdesc="Quick-capture scratchpad and note viewer with AI classification"
arch=('x86_64')
url="https://github.com/Breadway/breadpad"
license=('MIT')
# Some Rust deps (ring/mlua) build vendored C/asm into static archives; makepkg's
# default -flto=auto emits GCC LTO bitcode the Rust (lld) link cannot read,
# causing undefined-symbol errors. Disable LTO.
options=(!lto !debug)
depends=('gtk4' 'gtk4-layer-shell')
optdepends=(
'ollama: local AI note classification'
'hyprland: scratchpad window integration'
)
makedepends=('rust' 'cargo')
source=("${pkgname}-${pkgver}.tar.gz")
sha256sums=('SKIP')
build() {
cd "${srcdir}/${pkgname}-${pkgver}"
cargo build --release --locked
}
check() {
cd "${srcdir}/${pkgname}-${pkgver}"
cargo test --release --locked --workspace
}
package() {
cd "${srcdir}/${pkgname}-${pkgver}"
install -Dm755 target/release/breadpad "${pkgdir}/usr/bin/breadpad"
install -Dm755 target/release/breadman "${pkgdir}/usr/bin/breadman"
install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
}