feat: Flatpak-Paket (Vorbereitung für Flathub)
- packaging/flatpak/eu.pansi.ink-notes.yml: Runtime freedesktop 26.08, Rust aus rust-stable, Abhängigkeiten offline aus cargo-sources.json. Rechte: Wayland/X11, GPU, Lesen von Bildern/Downloads/Schreibtisch, Schreiben in den Dokumente-Ordner (kein Zugriff auf den ganzen Home-Ordner). - Im Flatpak sucht und installiert ink-notes keine Updates selbst (Vorgabe von Flathub); der Update-Dialog verweist auf die Software-Verwaltung. - Export-Ordner aus user-dirs.dirs (z. B. ~/Dokumente) statt fest ~/Documents; nur dieser Ordner ist im Flatpak beschreibbar. - Metainfo und Desktop-Datei auf Englisch mit deutscher Übersetzung, Release-Einträge, unterstützte Eingabegeräte. - Test: cargo-sources.json deckt Cargo.lock ab. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -74,6 +74,7 @@ Die Oberfläche gibt es auf Deutsch und Englisch; ink-notes folgt der Systemspra
|
|||||||
|
|
||||||
### Updates
|
### Updates
|
||||||
- Die App prüft auf neue Versionen auf Gitea und installiert sie auf Wunsch. Installiert wird nur, wenn die Minisign-Signatur und die SHA-256-Prüfsumme stimmen (Details unten).
|
- Die App prüft auf neue Versionen auf Gitea und installiert sie auf Wunsch. Installiert wird nur, wenn die Minisign-Signatur und die SHA-256-Prüfsumme stimmen (Details unten).
|
||||||
|
- Als Flatpak sucht ink-notes nicht selbst nach Updates; die kommen dann über die Software-Verwaltung (`flatpak update`).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -190,6 +191,17 @@ Mehr dazu in [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md), das Speicherformat
|
|||||||
|
|
||||||
Veröffentlicht wird über Gitea Actions ([`.gitea/workflows/release.yaml`](.gitea/workflows/release.yaml)), sobald ein Tag `vX.Y.Z` gepusht wird: Tests, Pakete bauen, signieren, Release anlegen. Manuell geht es mit `GITEA_TOKEN=… ./scripts/publish-gitea-release.sh`.
|
Veröffentlicht wird über Gitea Actions ([`.gitea/workflows/release.yaml`](.gitea/workflows/release.yaml)), sobald ein Tag `vX.Y.Z` gepusht wird: Tests, Pakete bauen, signieren, Release anlegen. Manuell geht es mit `GITEA_TOKEN=… ./scripts/publish-gitea-release.sh`.
|
||||||
|
|
||||||
|
### Flatpak
|
||||||
|
|
||||||
|
Das Manifest liegt in [`packaging/flatpak/`](packaging/flatpak/) (Runtime `org.freedesktop.Platform` 26.08, Rust aus der SDK-Erweiterung `rust-stable`). Lokal bauen und installieren:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
flatpak-builder --user --install --force-clean target/flatpak-build packaging/flatpak/eu.pansi.ink-notes.yml
|
||||||
|
flatpak run eu.pansi.ink-notes
|
||||||
|
```
|
||||||
|
|
||||||
|
Nach jeder Änderung an `Cargo.lock` muss `packaging/flatpak/cargo-sources.json` mit dem [flatpak-cargo-generator](https://github.com/flatpak/flatpak-builder-tools/tree/master/cargo) neu erzeugt werden (`python3 flatpak-cargo-generator.py Cargo.lock -o packaging/flatpak/cargo-sources.json`). In der Sandbox darf ink-notes Bilder, Downloads und Schreibtisch lesen und in den Dokumente-Ordner exportieren; die Notizbücher liegen unter `~/.var/app/eu.pansi.ink-notes/`.
|
||||||
|
|
||||||
### Release-Signatur einrichten (einmalig)
|
### Release-Signatur einrichten (einmalig)
|
||||||
|
|
||||||
Updates werden in der App nur mit gültiger Minisign-Signatur installiert. Signiert wird mit [rsign2](https://crates.io/crates/rsign2) (`cargo install rsign2 --locked`). Schlüsselpaar ohne Passwort erzeugen (es wird nur als CI-Secret verwendet):
|
Updates werden in der App nur mit gültiger Minisign-Signatur installiert. Signiert wird mit [rsign2](https://crates.io/crates/rsign2) (`cargo install rsign2 --locked`). Schlüsselpaar ohne Passwort erzeugen (es wird nur als CI-Secret verwendet):
|
||||||
|
|||||||
@@ -1,18 +1,22 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Version=1.0
|
Version=1.0
|
||||||
Name=ink-notes
|
Name=ink-notes
|
||||||
GenericName=Notizbuch- & Inking-App
|
GenericName=Note-Taking & Inking App
|
||||||
Comment=Handschriftliche Notizen mit Stift, Touch und Maus; PDFs beschriften
|
GenericName[de]=Notizbuch- & Inking-App
|
||||||
|
Comment=Handwritten notes with pen, touch and mouse; annotate PDFs
|
||||||
|
Comment[de]=Handschriftliche Notizen mit Stift, Touch und Maus; PDFs beschriften
|
||||||
Exec=ink-notes %F
|
Exec=ink-notes %F
|
||||||
Icon=eu.pansi.ink-notes
|
Icon=eu.pansi.ink-notes
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Type=Application
|
Type=Application
|
||||||
Categories=Office;Graphics;Utility;
|
Categories=Office;Graphics;
|
||||||
Keywords=Note;Notiz;Pen;Stift;Ink;Inking;Stylus;Drawing;Zeichnen;PDF;Vector;Text;Annotation;
|
Keywords=Note;Pen;Ink;Inking;Stylus;Drawing;PDF;Vector;Text;Annotation;
|
||||||
|
Keywords[de]=Notiz;Stift;Ink;Inking;Stylus;Zeichnen;PDF;Vektor;Text;Annotation;
|
||||||
StartupWMClass=eu.pansi.ink-notes
|
StartupWMClass=eu.pansi.ink-notes
|
||||||
MimeType=application/x-inknotes;
|
MimeType=application/x-inknotes;
|
||||||
Actions=NewWindow;
|
Actions=NewWindow;
|
||||||
|
|
||||||
[Desktop Action NewWindow]
|
[Desktop Action NewWindow]
|
||||||
Name=Neues Fenster
|
Name=New Window
|
||||||
|
Name[de]=Neues Fenster
|
||||||
Exec=ink-notes
|
Exec=ink-notes
|
||||||
|
|||||||
@@ -4,22 +4,34 @@
|
|||||||
<metadata_license>CC0-1.0</metadata_license>
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
<project_license>MIT</project_license>
|
<project_license>MIT</project_license>
|
||||||
<name>ink-notes</name>
|
<name>ink-notes</name>
|
||||||
<summary>Notizbuch-App für Stift, Touch und Maus</summary>
|
<summary>Handwritten notes with pen, touch and mouse</summary>
|
||||||
|
<summary xml:lang="de">Notizbuch-App für Stift, Touch und Maus</summary>
|
||||||
<description>
|
<description>
|
||||||
<p>
|
<p>
|
||||||
ink-notes ist eine Notizbuch-App für Linux, geschrieben in Rust mit wgpu. Handschrift wird als
|
ink-notes is a notebook app for Linux tablets and convertibles. Handwriting is stored as
|
||||||
|
vectors; write with a pen, your finger, a touchpad or a mouse.
|
||||||
|
</p>
|
||||||
|
<p xml:lang="de">
|
||||||
|
ink-notes ist eine Notizbuch-App für Linux-Tablets und Convertibles. Handschrift wird als
|
||||||
Vektoren gespeichert; geschrieben wird mit Stift, Finger, Touchpad oder Maus.
|
Vektoren gespeichert; geschrieben wird mit Stift, Finger, Touchpad oder Maus.
|
||||||
</p>
|
</p>
|
||||||
<p>Funktionen:</p>
|
<p>Features:</p>
|
||||||
|
<p xml:lang="de">Funktionen:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Stift und Textmarker mit Druckstärke, Glättung beim Schreiben und Ecken-Erhaltung</li>
|
<li>Pens and highlighter with pressure, smoothing while writing and sharp corners</li>
|
||||||
<li>Radierer für ganze Striche, Teilstriche oder nur Textmarker; virtuelles Lineal</li>
|
<li xml:lang="de">Stifte und Textmarker mit Druckstärke, Glättung beim Schreiben und Ecken-Erhaltung</li>
|
||||||
<li>Formerkennung (Linien, Pfeile, Kreise, Ellipsen, Rechtecke, Dreiecke, Rauten, Koordinatensysteme)</li>
|
<li>Shape recognition: hold at the end of a stroke to get clean lines, arrows, circles, rectangles, triangles and coordinate systems</li>
|
||||||
<li>Auswählen, Verschieben, Drehen, Skalieren und Umfärben; Rückgängig für alle Änderungen</li>
|
<li xml:lang="de">Formerkennung: am Strichende halten für saubere Linien, Pfeile, Kreise, Rechtecke, Dreiecke und Koordinatensysteme</li>
|
||||||
<li>Textfelder, Bilder und PDF-Import zum Beschriften (Querformat-Folien bekommen Querformat-Seiten)</li>
|
<li>Eraser for whole strokes, partial strokes or highlighter only; virtual ruler</li>
|
||||||
<li>Durchgehendes Scrollen, Zoom von 25 bis 1000 Prozent, Papier- und Musterfarben</li>
|
<li xml:lang="de">Radierer für ganze Striche, Teilstriche oder nur Textmarker; virtuelles Lineal</li>
|
||||||
<li>Mehrere Notizbücher, automatisches Speichern im Hintergrund</li>
|
<li>Select, move, rotate, scale and recolor; undo for every change</li>
|
||||||
<li>Export als PDF (mit durchsuchbarem Text), PNG oder SVG</li>
|
<li xml:lang="de">Auswählen, Verschieben, Drehen, Skalieren und Umfärben; Rückgängig für alle Änderungen</li>
|
||||||
|
<li>Text boxes, images and PDF import to annotate lecture slides and worksheets</li>
|
||||||
|
<li xml:lang="de">Textfelder, Bilder und PDF-Import zum Beschriften von Vorlesungsfolien und Übungsblättern</li>
|
||||||
|
<li>Notebooks in folders, continuous scrolling, automatic saving in the background</li>
|
||||||
|
<li xml:lang="de">Notizbücher in Ordnern, durchgehendes Scrollen, automatisches Speichern im Hintergrund</li>
|
||||||
|
<li>Export as PDF (with searchable text), PNG or SVG</li>
|
||||||
|
<li xml:lang="de">Export als PDF (mit durchsuchbarem Text), PNG oder SVG</li>
|
||||||
</ul>
|
</ul>
|
||||||
</description>
|
</description>
|
||||||
<launchable type="desktop-id">eu.pansi.ink-notes.desktop</launchable>
|
<launchable type="desktop-id">eu.pansi.ink-notes.desktop</launchable>
|
||||||
@@ -29,12 +41,46 @@
|
|||||||
<categories>
|
<categories>
|
||||||
<category>Office</category>
|
<category>Office</category>
|
||||||
<category>Graphics</category>
|
<category>Graphics</category>
|
||||||
<category>Utility</category>
|
|
||||||
</categories>
|
</categories>
|
||||||
|
<keywords>
|
||||||
|
<keyword>notes</keyword>
|
||||||
|
<keyword>handwriting</keyword>
|
||||||
|
<keyword>stylus</keyword>
|
||||||
|
<keyword>pen</keyword>
|
||||||
|
<keyword>PDF</keyword>
|
||||||
|
<keyword>annotate</keyword>
|
||||||
|
</keywords>
|
||||||
|
<supports>
|
||||||
|
<control>pointing</control>
|
||||||
|
<control>touch</control>
|
||||||
|
<control>tablet</control>
|
||||||
|
</supports>
|
||||||
<developer id="eu.pansi">
|
<developer id="eu.pansi">
|
||||||
<name>Harald</name>
|
<name>Harald Pansi</name>
|
||||||
</developer>
|
</developer>
|
||||||
<url type="homepage">https://gitea.pansi.eu/harald/ink-notes</url>
|
<url type="homepage">https://gitea.pansi.eu/harald/ink-notes</url>
|
||||||
<url type="bugtracker">https://gitea.pansi.eu/harald/ink-notes/issues</url>
|
<url type="bugtracker">https://gitea.pansi.eu/harald/ink-notes/issues</url>
|
||||||
|
<url type="vcs-browser">https://gitea.pansi.eu/harald/ink-notes</url>
|
||||||
|
<branding>
|
||||||
|
<color type="primary" scheme_preference="light">#a8c8f0</color>
|
||||||
|
<color type="primary" scheme_preference="dark">#1f3a5f</color>
|
||||||
|
</branding>
|
||||||
<content_rating type="oars-1.1" />
|
<content_rating type="oars-1.1" />
|
||||||
|
<releases>
|
||||||
|
<release version="0.25.0" date="2026-10-09">
|
||||||
|
<description>
|
||||||
|
<p>English user interface; the language follows the system and can be changed in the menu. Holding to snap a shape tolerates a slightly trembling pen.</p>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
|
<release version="0.24.0" date="2026-10-09">
|
||||||
|
<description>
|
||||||
|
<p>Axis cross from two crossing strokes.</p>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
|
<release version="0.23.0" date="2026-10-09">
|
||||||
|
<description>
|
||||||
|
<p>The on-screen keyboard of GNOME appears when tapping a text field.</p>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
|
</releases>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,55 @@
|
|||||||
|
# Flatpak-Manifest für ink-notes (Flathub).
|
||||||
|
#
|
||||||
|
# Lokal bauen und installieren (aus dem Repository-Wurzelverzeichnis):
|
||||||
|
# flatpak-builder --user --install --force-clean target/flatpak-build \
|
||||||
|
# packaging/flatpak/eu.pansi.ink-notes.yml
|
||||||
|
#
|
||||||
|
# cargo-sources.json nach jeder Änderung an Cargo.lock neu erzeugen:
|
||||||
|
# python3 flatpak-cargo-generator.py Cargo.lock -o packaging/flatpak/cargo-sources.json
|
||||||
|
# (flatpak-builder-tools, https://github.com/flatpak/flatpak-builder-tools/tree/master/cargo)
|
||||||
|
#
|
||||||
|
# Für die Einreichung bei Flathub die Quelle `type: dir` durch das Release-Tag ersetzen
|
||||||
|
# (type: git, url, tag, commit).
|
||||||
|
id: eu.pansi.ink-notes
|
||||||
|
runtime: org.freedesktop.Platform
|
||||||
|
runtime-version: '26.08'
|
||||||
|
sdk: org.freedesktop.Sdk
|
||||||
|
sdk-extensions:
|
||||||
|
- org.freedesktop.Sdk.Extension.rust-stable
|
||||||
|
command: ink-notes
|
||||||
|
finish-args:
|
||||||
|
- --socket=wayland
|
||||||
|
- --socket=fallback-x11
|
||||||
|
- --share=ipc
|
||||||
|
- --device=dri
|
||||||
|
# Die eingebaute Dateiauswahl (Bilder und PDFs einfügen) arbeitet ohne Desktop-Portal und
|
||||||
|
# bietet Bilder, Downloads und Schreibtisch an; Export (PDF, PNG, SVG) in den Dokumente-Ordner.
|
||||||
|
# Ziehen aus dem Dateimanager geht über das Dokumenten-Portal auch aus anderen Ordnern.
|
||||||
|
- --filesystem=xdg-pictures:ro
|
||||||
|
- --filesystem=xdg-download:ro
|
||||||
|
- --filesystem=xdg-desktop:ro
|
||||||
|
- --filesystem=xdg-documents
|
||||||
|
build-options:
|
||||||
|
append-path: /usr/lib/sdk/rust-stable/bin
|
||||||
|
env:
|
||||||
|
CARGO_HOME: /run/build/ink-notes/cargo
|
||||||
|
modules:
|
||||||
|
- name: ink-notes
|
||||||
|
buildsystem: simple
|
||||||
|
build-commands:
|
||||||
|
- cargo --offline build --release --locked
|
||||||
|
- install -Dm755 target/release/ink-notes /app/bin/ink-notes
|
||||||
|
- install -Dm644 packaging/eu.pansi.ink-notes.desktop /app/share/applications/eu.pansi.ink-notes.desktop
|
||||||
|
- install -Dm644 packaging/eu.pansi.ink-notes.metainfo.xml /app/share/metainfo/eu.pansi.ink-notes.metainfo.xml
|
||||||
|
- install -Dm644 assets/ink-notes.svg /app/share/icons/hicolor/scalable/apps/eu.pansi.ink-notes.svg
|
||||||
|
- install -Dm644 assets/ink-notes.png /app/share/icons/hicolor/256x256/apps/eu.pansi.ink-notes.png
|
||||||
|
sources:
|
||||||
|
- type: dir
|
||||||
|
path: ../..
|
||||||
|
skip:
|
||||||
|
- target
|
||||||
|
- .git
|
||||||
|
- .flatpak-builder
|
||||||
|
- ideas.txt
|
||||||
|
- issue.txt
|
||||||
|
- cargo-sources.json
|
||||||
@@ -1,18 +1,22 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Version=1.0
|
Version=1.0
|
||||||
Name=ink-notes
|
Name=ink-notes
|
||||||
GenericName=Notizbuch- & Inking-App
|
GenericName=Note-Taking & Inking App
|
||||||
Comment=Handschriftliche Notizen mit Stift, Touch und Maus; PDFs beschriften
|
GenericName[de]=Notizbuch- & Inking-App
|
||||||
|
Comment=Handwritten notes with pen, touch and mouse; annotate PDFs
|
||||||
|
Comment[de]=Handschriftliche Notizen mit Stift, Touch und Maus; PDFs beschriften
|
||||||
Exec=ink-notes %F
|
Exec=ink-notes %F
|
||||||
Icon=eu.pansi.ink-notes
|
Icon=eu.pansi.ink-notes
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Type=Application
|
Type=Application
|
||||||
Categories=Office;Graphics;Utility;
|
Categories=Office;Graphics;
|
||||||
Keywords=Note;Notiz;Pen;Stift;Ink;Inking;Stylus;Drawing;Zeichnen;PDF;Vector;Text;Annotation;
|
Keywords=Note;Pen;Ink;Inking;Stylus;Drawing;PDF;Vector;Text;Annotation;
|
||||||
|
Keywords[de]=Notiz;Stift;Ink;Inking;Stylus;Zeichnen;PDF;Vektor;Text;Annotation;
|
||||||
StartupWMClass=eu.pansi.ink-notes
|
StartupWMClass=eu.pansi.ink-notes
|
||||||
MimeType=application/x-inknotes;
|
MimeType=application/x-inknotes;
|
||||||
Actions=NewWindow;
|
Actions=NewWindow;
|
||||||
|
|
||||||
[Desktop Action NewWindow]
|
[Desktop Action NewWindow]
|
||||||
Name=Neues Fenster
|
Name=New Window
|
||||||
|
Name[de]=Neues Fenster
|
||||||
Exec=ink-notes
|
Exec=ink-notes
|
||||||
|
|||||||
@@ -4,22 +4,34 @@
|
|||||||
<metadata_license>CC0-1.0</metadata_license>
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
<project_license>MIT</project_license>
|
<project_license>MIT</project_license>
|
||||||
<name>ink-notes</name>
|
<name>ink-notes</name>
|
||||||
<summary>Notizbuch-App für Stift, Touch und Maus</summary>
|
<summary>Handwritten notes with pen, touch and mouse</summary>
|
||||||
|
<summary xml:lang="de">Notizbuch-App für Stift, Touch und Maus</summary>
|
||||||
<description>
|
<description>
|
||||||
<p>
|
<p>
|
||||||
ink-notes ist eine Notizbuch-App für Linux, geschrieben in Rust mit wgpu. Handschrift wird als
|
ink-notes is a notebook app for Linux tablets and convertibles. Handwriting is stored as
|
||||||
|
vectors; write with a pen, your finger, a touchpad or a mouse.
|
||||||
|
</p>
|
||||||
|
<p xml:lang="de">
|
||||||
|
ink-notes ist eine Notizbuch-App für Linux-Tablets und Convertibles. Handschrift wird als
|
||||||
Vektoren gespeichert; geschrieben wird mit Stift, Finger, Touchpad oder Maus.
|
Vektoren gespeichert; geschrieben wird mit Stift, Finger, Touchpad oder Maus.
|
||||||
</p>
|
</p>
|
||||||
<p>Funktionen:</p>
|
<p>Features:</p>
|
||||||
|
<p xml:lang="de">Funktionen:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Stift und Textmarker mit Druckstärke, Glättung beim Schreiben und Ecken-Erhaltung</li>
|
<li>Pens and highlighter with pressure, smoothing while writing and sharp corners</li>
|
||||||
<li>Radierer für ganze Striche, Teilstriche oder nur Textmarker; virtuelles Lineal</li>
|
<li xml:lang="de">Stifte und Textmarker mit Druckstärke, Glättung beim Schreiben und Ecken-Erhaltung</li>
|
||||||
<li>Formerkennung (Linien, Pfeile, Kreise, Ellipsen, Rechtecke, Dreiecke, Rauten, Koordinatensysteme)</li>
|
<li>Shape recognition: hold at the end of a stroke to get clean lines, arrows, circles, rectangles, triangles and coordinate systems</li>
|
||||||
<li>Auswählen, Verschieben, Drehen, Skalieren und Umfärben; Rückgängig für alle Änderungen</li>
|
<li xml:lang="de">Formerkennung: am Strichende halten für saubere Linien, Pfeile, Kreise, Rechtecke, Dreiecke und Koordinatensysteme</li>
|
||||||
<li>Textfelder, Bilder und PDF-Import zum Beschriften (Querformat-Folien bekommen Querformat-Seiten)</li>
|
<li>Eraser for whole strokes, partial strokes or highlighter only; virtual ruler</li>
|
||||||
<li>Durchgehendes Scrollen, Zoom von 25 bis 1000 Prozent, Papier- und Musterfarben</li>
|
<li xml:lang="de">Radierer für ganze Striche, Teilstriche oder nur Textmarker; virtuelles Lineal</li>
|
||||||
<li>Mehrere Notizbücher, automatisches Speichern im Hintergrund</li>
|
<li>Select, move, rotate, scale and recolor; undo for every change</li>
|
||||||
<li>Export als PDF (mit durchsuchbarem Text), PNG oder SVG</li>
|
<li xml:lang="de">Auswählen, Verschieben, Drehen, Skalieren und Umfärben; Rückgängig für alle Änderungen</li>
|
||||||
|
<li>Text boxes, images and PDF import to annotate lecture slides and worksheets</li>
|
||||||
|
<li xml:lang="de">Textfelder, Bilder und PDF-Import zum Beschriften von Vorlesungsfolien und Übungsblättern</li>
|
||||||
|
<li>Notebooks in folders, continuous scrolling, automatic saving in the background</li>
|
||||||
|
<li xml:lang="de">Notizbücher in Ordnern, durchgehendes Scrollen, automatisches Speichern im Hintergrund</li>
|
||||||
|
<li>Export as PDF (with searchable text), PNG or SVG</li>
|
||||||
|
<li xml:lang="de">Export als PDF (mit durchsuchbarem Text), PNG oder SVG</li>
|
||||||
</ul>
|
</ul>
|
||||||
</description>
|
</description>
|
||||||
<launchable type="desktop-id">eu.pansi.ink-notes.desktop</launchable>
|
<launchable type="desktop-id">eu.pansi.ink-notes.desktop</launchable>
|
||||||
@@ -29,12 +41,46 @@
|
|||||||
<categories>
|
<categories>
|
||||||
<category>Office</category>
|
<category>Office</category>
|
||||||
<category>Graphics</category>
|
<category>Graphics</category>
|
||||||
<category>Utility</category>
|
|
||||||
</categories>
|
</categories>
|
||||||
|
<keywords>
|
||||||
|
<keyword>notes</keyword>
|
||||||
|
<keyword>handwriting</keyword>
|
||||||
|
<keyword>stylus</keyword>
|
||||||
|
<keyword>pen</keyword>
|
||||||
|
<keyword>PDF</keyword>
|
||||||
|
<keyword>annotate</keyword>
|
||||||
|
</keywords>
|
||||||
|
<supports>
|
||||||
|
<control>pointing</control>
|
||||||
|
<control>touch</control>
|
||||||
|
<control>tablet</control>
|
||||||
|
</supports>
|
||||||
<developer id="eu.pansi">
|
<developer id="eu.pansi">
|
||||||
<name>Harald</name>
|
<name>Harald Pansi</name>
|
||||||
</developer>
|
</developer>
|
||||||
<url type="homepage">https://gitea.pansi.eu/harald/ink-notes</url>
|
<url type="homepage">https://gitea.pansi.eu/harald/ink-notes</url>
|
||||||
<url type="bugtracker">https://gitea.pansi.eu/harald/ink-notes/issues</url>
|
<url type="bugtracker">https://gitea.pansi.eu/harald/ink-notes/issues</url>
|
||||||
|
<url type="vcs-browser">https://gitea.pansi.eu/harald/ink-notes</url>
|
||||||
|
<branding>
|
||||||
|
<color type="primary" scheme_preference="light">#a8c8f0</color>
|
||||||
|
<color type="primary" scheme_preference="dark">#1f3a5f</color>
|
||||||
|
</branding>
|
||||||
<content_rating type="oars-1.1" />
|
<content_rating type="oars-1.1" />
|
||||||
|
<releases>
|
||||||
|
<release version="0.25.0" date="2026-10-09">
|
||||||
|
<description>
|
||||||
|
<p>English user interface; the language follows the system and can be changed in the menu. Holding to snap a shape tolerates a slightly trembling pen.</p>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
|
<release version="0.24.0" date="2026-10-09">
|
||||||
|
<description>
|
||||||
|
<p>Axis cross from two crossing strokes.</p>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
|
<release version="0.23.0" date="2026-10-09">
|
||||||
|
<description>
|
||||||
|
<p>The on-screen keyboard of GNOME appears when tapping a text field.</p>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
|
</releases>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
+13
-2
@@ -46,7 +46,9 @@ pub fn sanitize_filename_component(title: &str) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ermittelt das Standard-Dokumentenverzeichnis ($XDG_DOCUMENTS_DIR mit Fallback ~/Documents).
|
/// Ermittelt das Standard-Dokumentenverzeichnis: `$XDG_DOCUMENTS_DIR`, sonst der Eintrag in
|
||||||
|
/// `~/.config/user-dirs.dirs` (z. B. „Dokumente“), sonst `~/Documents`. Im Flatpak ist nur
|
||||||
|
/// dieser Ordner beschreibbar, der Fallback allein träfe bei deutschen Systemen daneben.
|
||||||
pub fn default_documents_dir() -> PathBuf {
|
pub fn default_documents_dir() -> PathBuf {
|
||||||
if let Ok(dir) = std::env::var("XDG_DOCUMENTS_DIR") {
|
if let Ok(dir) = std::env::var("XDG_DOCUMENTS_DIR") {
|
||||||
if !dir.trim().is_empty() {
|
if !dir.trim().is_empty() {
|
||||||
@@ -56,7 +58,16 @@ pub fn default_documents_dir() -> PathBuf {
|
|||||||
|
|
||||||
if let Ok(home) = std::env::var("HOME") {
|
if let Ok(home) = std::env::var("HOME") {
|
||||||
if !home.trim().is_empty() {
|
if !home.trim().is_empty() {
|
||||||
return PathBuf::from(home).join("Documents");
|
let home = PathBuf::from(home);
|
||||||
|
let user_dirs =
|
||||||
|
std::fs::read_to_string(home.join(".config/user-dirs.dirs")).unwrap_or_default();
|
||||||
|
if let Some(dir) =
|
||||||
|
crate::file_picker::parse_user_dir(&user_dirs, "XDG_DOCUMENTS_DIR", &home)
|
||||||
|
.filter(|dir| *dir != home)
|
||||||
|
{
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
return home.join("Documents");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,9 +66,11 @@ pub const EN: &[(&str, &str)] = &[
|
|||||||
("Die beschädigte Originaldatei wurde in Quarantäne gesichert:", "The damaged original file was saved to quarantine:"),
|
("Die beschädigte Originaldatei wurde in Quarantäne gesichert:", "The damaged original file was saved to quarantine:"),
|
||||||
("Die Datei ist kein lesbares PDF", "The file is not a readable PDF"),
|
("Die Datei ist kein lesbares PDF", "The file is not a readable PDF"),
|
||||||
("Die einzige Seite eines Notizbuchs kann nicht gelöscht werden", "The only page of a notebook cannot be deleted"),
|
("Die einzige Seite eines Notizbuchs kann nicht gelöscht werden", "The only page of a notebook cannot be deleted"),
|
||||||
|
("Die Flatpak-Version wird über die Software-Verwaltung aktualisiert.", "The Flatpak version is updated through the software manager."),
|
||||||
("Die heruntergeladene Datei existiert nicht mehr.", "The downloaded file no longer exists."),
|
("Die heruntergeladene Datei existiert nicht mehr.", "The downloaded file no longer exists."),
|
||||||
("die oberste Ebene", "the top level"),
|
("die oberste Ebene", "the top level"),
|
||||||
("Die Zwischenablage ist leer", "The clipboard is empty"),
|
("Die Zwischenablage ist leer", "The clipboard is empty"),
|
||||||
|
("Diese Version wird über die Software-Verwaltung aktualisiert (z. B. GNOME Software oder „flatpak update“).", "This version is updated through the software manager (e.g. GNOME Software or “flatpak update”)."),
|
||||||
("Dieser Ordner ist leer.", "This folder is empty."),
|
("Dieser Ordner ist leer.", "This folder is empty."),
|
||||||
("Dokument '{title}' erstellt", "Document '{title}' created"),
|
("Dokument '{title}' erstellt", "Document '{title}' created"),
|
||||||
("Dokument '{title}' geöffnet", "Document '{title}' opened"),
|
("Dokument '{title}' geöffnet", "Document '{title}' opened"),
|
||||||
|
|||||||
@@ -4281,6 +4281,18 @@ pub fn render_ui(
|
|||||||
ui.label(egui::RichText::new(format!("({})", runtime_name)).color(egui::Color32::from_gray(150)));
|
ui.label(egui::RichText::new(format!("({})", runtime_name)).color(egui::Color32::from_gray(150)));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if !updater.runtime().self_update_allowed() {
|
||||||
|
ui.add_space(8.0);
|
||||||
|
ui.label(
|
||||||
|
egui::RichText::new(t!(
|
||||||
|
"Diese Version wird über die Software-Verwaltung aktualisiert \
|
||||||
|
(z. B. GNOME Software oder „flatpak update“)."
|
||||||
|
))
|
||||||
|
.color(egui::Color32::from_gray(210)),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.label(egui::RichText::new(t!("Server:")).color(egui::Color32::from_gray(180)));
|
ui.label(egui::RichText::new(t!("Server:")).color(egui::Color32::from_gray(180)));
|
||||||
ui.label(egui::RichText::new(format!("{}/{}/{}", updater.config().server_url, updater.config().repo_owner, updater.config().repo_name)).color(egui::Color32::from_gray(210)));
|
ui.label(egui::RichText::new(format!("{}/{}/{}", updater.config().server_url, updater.config().repo_owner, updater.config().repo_name)).color(egui::Color32::from_gray(210)));
|
||||||
@@ -4446,7 +4458,8 @@ pub fn render_ui(
|
|||||||
let action_label = match updater.runtime() {
|
let action_label = match updater.runtime() {
|
||||||
crate::updater::RuntimeEnvironment::AppImage { .. } => t!("🚀 AppImage aktualisieren & ausführen"),
|
crate::updater::RuntimeEnvironment::AppImage { .. } => t!("🚀 AppImage aktualisieren & ausführen"),
|
||||||
crate::updater::RuntimeEnvironment::DebPackage { .. } => t!("📦 Paket mit Software-Center öffnen / installieren"),
|
crate::updater::RuntimeEnvironment::DebPackage { .. } => t!("📦 Paket mit Software-Center öffnen / installieren"),
|
||||||
crate::updater::RuntimeEnvironment::PortableOrDev { .. } => t!("📂 Im Dateimanager anzeigen"),
|
crate::updater::RuntimeEnvironment::PortableOrDev { .. }
|
||||||
|
| crate::updater::RuntimeEnvironment::Flatpak => t!("📂 Im Dateimanager anzeigen"),
|
||||||
};
|
};
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
|
|||||||
@@ -118,11 +118,20 @@ pub enum RuntimeEnvironment {
|
|||||||
DebPackage { binary_path: PathBuf },
|
DebPackage { binary_path: PathBuf },
|
||||||
/// Aus Quellcode / Entwicklungs-Binary (z.B. target/debug oder target/release)
|
/// Aus Quellcode / Entwicklungs-Binary (z.B. target/debug oder target/release)
|
||||||
PortableOrDev { binary_path: PathBuf },
|
PortableOrDev { binary_path: PathBuf },
|
||||||
|
/// Als Flatpak installiert: Updates kommen über die Software-Verwaltung, ink-notes lädt
|
||||||
|
/// selbst nichts herunter (Vorgabe von Flathub)
|
||||||
|
Flatpak,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RuntimeEnvironment {
|
impl RuntimeEnvironment {
|
||||||
/// Erkennt die aktuelle Laufzeitumgebung anhand der Umgebung und des Binärpfads.
|
/// Erkennt die aktuelle Laufzeitumgebung anhand der Umgebung und des Binärpfads.
|
||||||
pub fn detect() -> Self {
|
pub fn detect() -> Self {
|
||||||
|
if is_flatpak(
|
||||||
|
std::env::var("FLATPAK_ID").ok().as_deref(),
|
||||||
|
Path::new("/.flatpak-info").exists(),
|
||||||
|
) {
|
||||||
|
return RuntimeEnvironment::Flatpak;
|
||||||
|
}
|
||||||
let appimage_var = std::env::var("APPIMAGE").ok();
|
let appimage_var = std::env::var("APPIMAGE").ok();
|
||||||
let current_exe = std::env::current_exe().unwrap_or_else(|_| PathBuf::from("ink-notes"));
|
let current_exe = std::env::current_exe().unwrap_or_else(|_| PathBuf::from("ink-notes"));
|
||||||
Self::detect_from(appimage_var.as_deref(), ¤t_exe)
|
Self::detect_from(appimage_var.as_deref(), ¤t_exe)
|
||||||
@@ -156,8 +165,20 @@ impl RuntimeEnvironment {
|
|||||||
RuntimeEnvironment::AppImage { .. } => t!("AppImage (Portabel)"),
|
RuntimeEnvironment::AppImage { .. } => t!("AppImage (Portabel)"),
|
||||||
RuntimeEnvironment::DebPackage { .. } => t!("System-Paket (.deb)"),
|
RuntimeEnvironment::DebPackage { .. } => t!("System-Paket (.deb)"),
|
||||||
RuntimeEnvironment::PortableOrDev { .. } => t!("Entwicklung / Lokal"),
|
RuntimeEnvironment::PortableOrDev { .. } => t!("Entwicklung / Lokal"),
|
||||||
|
RuntimeEnvironment::Flatpak => "Flatpak",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ob ink-notes selbst nach Updates suchen und sie installieren darf
|
||||||
|
pub fn self_update_allowed(&self) -> bool {
|
||||||
|
!matches!(self, RuntimeEnvironment::Flatpak)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Läuft ink-notes in einer Flatpak-Sandbox (`FLATPAK_ID` gesetzt oder `/.flatpak-info`
|
||||||
|
/// vorhanden)?
|
||||||
|
pub fn is_flatpak(flatpak_id: Option<&str>, info_file_exists: bool) -> bool {
|
||||||
|
flatpak_id.is_some_and(|id| !id.trim().is_empty()) || info_file_exists
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bereinigt und validiert einen Asset-Dateinamen gegen Path Traversal Angriffe.
|
/// Bereinigt und validiert einen Asset-Dateinamen gegen Path Traversal Angriffe.
|
||||||
@@ -578,6 +599,9 @@ impl UpdaterController {
|
|||||||
|
|
||||||
/// Fragt im Hintergrund die Gitea-API ab.
|
/// Fragt im Hintergrund die Gitea-API ab.
|
||||||
pub fn check_for_updates(&mut self) {
|
pub fn check_for_updates(&mut self) {
|
||||||
|
if !self.runtime.self_update_allowed() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if matches!(
|
if matches!(
|
||||||
self.status,
|
self.status,
|
||||||
UpdaterStatus::Checking | UpdaterStatus::Downloading { .. }
|
UpdaterStatus::Checking | UpdaterStatus::Downloading { .. }
|
||||||
@@ -887,6 +911,10 @@ impl UpdaterController {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
RuntimeEnvironment::Flatpak => Err(t!(
|
||||||
|
"Die Flatpak-Version wird über die Software-Verwaltung aktualisiert."
|
||||||
|
)
|
||||||
|
.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1074,6 +1102,19 @@ dcdeb7ac87d9e6cb8022e5a71bc7f2c56d779b4fce4efdd5bae5be3b0214884a ink-notes_0.1.
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_flatpak_detection_disables_self_update() {
|
||||||
|
assert!(is_flatpak(Some("eu.pansi.ink-notes"), false));
|
||||||
|
assert!(is_flatpak(None, true));
|
||||||
|
assert!(!is_flatpak(Some(" "), false));
|
||||||
|
assert!(!is_flatpak(None, false));
|
||||||
|
assert!(!RuntimeEnvironment::Flatpak.self_update_allowed());
|
||||||
|
assert!(
|
||||||
|
RuntimeEnvironment::detect_from(None, Path::new("/usr/bin/ink-notes"))
|
||||||
|
.self_update_allowed()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_https_enforcement() {
|
fn test_https_enforcement() {
|
||||||
let config = UpdaterConfig {
|
let config = UpdaterConfig {
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
//! Das Flatpak baut ohne Netz aus `packaging/flatpak/cargo-sources.json`; jede Abhängigkeit
|
||||||
|
//! aus `Cargo.lock` muss dort stehen, sonst schlägt der Flatpak-Build fehl.
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cargo_sources_cover_cargo_lock() {
|
||||||
|
let lock = include_str!("../Cargo.lock");
|
||||||
|
let sources = include_str!("../packaging/flatpak/cargo-sources.json");
|
||||||
|
let mut missing = Vec::new();
|
||||||
|
for package in lock.split("[[package]]").skip(1) {
|
||||||
|
let field = |key: &str| {
|
||||||
|
package.lines().find_map(|line| {
|
||||||
|
line.strip_prefix(key)
|
||||||
|
.map(|rest| rest.trim().trim_matches('"').to_string())
|
||||||
|
})
|
||||||
|
};
|
||||||
|
// Nur Pakete aus crates.io (das eigene Paket hat keine Quelle)
|
||||||
|
if field("source = ").is_none() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let (Some(name), Some(version)) = (field("name = "), field("version = ")) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let crate_file = format!("/{name}-{version}.crate\"");
|
||||||
|
if !sources.contains(&crate_file) {
|
||||||
|
missing.push(format!("{name} {version}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert!(
|
||||||
|
missing.is_empty(),
|
||||||
|
"cargo-sources.json ist veraltet (flatpak-cargo-generator neu ausführen), es fehlen: {}",
|
||||||
|
missing.join(", ")
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user