Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions README.de.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ Blitztext registriert globale Hotkeys via `evdev`. Mit diesen Kombinationen hast
Die KI-Workflows helfen bei Formulierung, Ton und Emojis. Die passenden Einstellungen findest du unter **Einstellungen → KI-Workflows**:

<div align="center">
<img src="docs/screenshots/linux/en/settings-ai-workflows.png" alt="KI-Workflow-Einstellungen" width="480">
<img src="docs/screenshots/linux/settings-ai-workflows-en.png" alt="KI-Workflow-Einstellungen" width="480">
<br><br>
</div>

Expand Down Expand Up @@ -195,6 +195,12 @@ Für den Workflow **Blitztext+** (Text-Verbesserer) gibt es vorgefertigte Schrei

Das **Compose-Fenster** (`✍ Compose…` im Tray-Kontextmenü) ermöglicht das Umschreiben beliebiger Texte mit der KI — ganz ohne Sprachaufnahme. Es eignet sich ideal zum Überarbeiten fertiger Entwürfe, E-Mails oder Notizen.

<div align="center">
<br>
<img src="docs/screenshots/linux/compose-en.png" alt="Compose-Fenster" width="480">
<br><br>
</div>

**Öffnen:** Klick auf das Tray-Icon → **✍ Compose…**

**Was du im Compose-Fenster tun kannst:**
Expand Down Expand Up @@ -251,7 +257,7 @@ Das Tray-Kontextmenü gibt dir schnellen Zugriff auf alle Workflows, das Compose

<div align="center">
<br>
<img src="docs/screenshots/linux/en/tray-menu.png" alt="Tray-Kontextmenü" width="280">
<img src="docs/screenshots/linux/tray-menu-en.png" alt="Tray-Kontextmenü" width="280">
<br><br>
</div>

Expand All @@ -266,11 +272,12 @@ Das Hauptfenster ist dein grafisches Kontrollzentrum — nützlich, wenn Hotkeys

<div align="center">
<br>
<img src="docs/screenshots/linux/en/blitztext-ready.png" alt="Hauptfenster" width="300">
<img src="docs/screenshots/linux/main-window-en.png" alt="Hauptfenster" width="300">
<br><br>
</div>

- **Workflow-Dropdown:** Alle 5 Aufnahmemodi zur Auswahl.
- **Schreibstil-Vorlage:** Sichtbar wenn **Blitztext+** gewählt ist — Preset direkt im Hauptfenster wählen. Änderungen werden sofort mit dem Tray synchronisiert.
- **Start/Stopp-Button:** Klick zum Starten oder Beenden einer Aufnahme.
- **Abbruch:** Bricht die aktuelle Aufnahme ohne Transkription ab.
- **Diktat / Verlauf:** Schnellzugriff auf den Diktat-Modus und den Transkript-Verlauf.
Expand All @@ -286,8 +293,8 @@ Zusätzlich zu den Workflows bietet das Tool drei Komfort-Funktionen:

<div align="center">
<br>
<img src="docs/screenshots/linux/history.png" alt="Verlauf" width="340">
<img src="docs/screenshots/linux/en/read-aloud.png" alt="Vorlesen" width="340">
<img src="docs/screenshots/linux/history-en.png" alt="Verlauf" width="340">
<img src="docs/screenshots/linux/tts-en.png" alt="Vorlesen" width="340">
<br><br>
</div>

Expand Down Expand Up @@ -320,11 +327,11 @@ Alles wird lokal und sicher unter `~/.config/blitztext-linux/config.json` gespei
Der Einstellungs-Dialog hat drei Tabs:

<div align="center">
<img src="docs/screenshots/linux/en/settings-speech-recognition.png" alt="Einstellungen: Spracherkennung" width="480">
<img src="docs/screenshots/linux/settings-speech-en.png" alt="Einstellungen: Spracherkennung" width="480">
<br><i>Spracherkennung — Whisper-Modell, Backend, Sprache, Hotkey-Modus und Aufnahmetaste.</i><br><br>
<img src="docs/screenshots/linux/en/settings-ai-workflows.png" alt="Einstellungen: KI-Workflows" width="480">
<img src="docs/screenshots/linux/settings-ai-workflows-en.png" alt="Einstellungen: KI-Workflows" width="480">
<br><i>KI-Workflows — LLM-Anbieter, API-Key, Base-URL, Modell, Tonfall und Schreibstil-Vorlage.</i><br><br>
<img src="docs/screenshots/linux/en/settings-general.png" alt="Einstellungen: Allgemein" width="480">
<img src="docs/screenshots/linux/settings-general-en.png" alt="Einstellungen: Allgemein" width="480">
<br><i>Allgemein — Auto-Paste, Diktat-Ordner, Verlaufsgröße, Sprache der Oberfläche und Signatur.</i><br><br>
</div>

Expand Down
23 changes: 15 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ Blitztext registers global hotkeys via `evdev`. With these combinations you have
The AI workflows help with phrasing, tone, and emojis. You'll find the relevant settings under **Settings → AI Workflows**:

<div align="center">
<img src="docs/screenshots/linux/en/settings-ai-workflows.png" alt="AI workflow settings" width="480">
<img src="docs/screenshots/linux/settings-ai-workflows-en.png" alt="AI workflow settings" width="480">
<br><br>
</div>

Expand Down Expand Up @@ -197,6 +197,12 @@ For the **Blitztext+** workflow (text improver) there are ready-made writing-sty

The **Compose window** (`✍ Compose…` in the tray menu) lets you rewrite any text using the AI — without recording your voice. It is ideal for editing existing drafts, emails, or notes.

<div align="center">
<br>
<img src="docs/screenshots/linux/compose-en.png" alt="Compose window" width="480">
<br><br>
</div>

**How to open:** Click the tray icon → **✍ Compose…**

**What you can do in the Compose window:**
Expand Down Expand Up @@ -253,7 +259,7 @@ The tray context menu gives you quick access to all workflows, the compose windo

<div align="center">
<br>
<img src="docs/screenshots/linux/en/tray-menu.png" alt="Tray context menu" width="280">
<img src="docs/screenshots/linux/tray-menu-en.png" alt="Tray context menu" width="280">
<br><br>
</div>

Expand All @@ -268,11 +274,12 @@ The main window is your graphical control center — useful when hotkeys are blo

<div align="center">
<br>
<img src="docs/screenshots/linux/en/blitztext-ready.png" alt="Main window" width="300">
<img src="docs/screenshots/linux/main-window-en.png" alt="Main window" width="300">
<br><br>
</div>

- **Workflow dropdown:** Select from all 5 recording modes.
- **Writing-style preset:** Visible when **Blitztext+** is selected — pick your preset directly in the main window. Changes sync to the tray instantly.
- **Start/Stop button:** Click to begin or end a recording.
- **Discard:** Cancels the current recording without transcription.
- **Dictation / History:** Quick access to dictation mode and the transcript history.
Expand All @@ -288,8 +295,8 @@ In addition to the workflows, the tool offers three convenience functions:

<div align="center">
<br>
<img src="docs/screenshots/linux/history.png" alt="History" width="340">
<img src="docs/screenshots/linux/en/read-aloud.png" alt="Read aloud" width="340">
<img src="docs/screenshots/linux/history-en.png" alt="History" width="340">
<img src="docs/screenshots/linux/tts-en.png" alt="Read aloud" width="340">
<br><br>
</div>

Expand Down Expand Up @@ -323,11 +330,11 @@ Everything is stored locally and securely under `~/.config/blitztext-linux/confi
The settings dialog has three tabs:

<div align="center">
<img src="docs/screenshots/linux/en/settings-speech-recognition.png" alt="Settings: Speech Recognition" width="480">
<img src="docs/screenshots/linux/settings-speech-en.png" alt="Settings: Speech Recognition" width="480">
<br><i>Speech Recognition — Whisper model, backend, language, hotkey mode, and recording key.</i><br><br>
<img src="docs/screenshots/linux/en/settings-ai-workflows.png" alt="Settings: AI Workflows" width="480">
<img src="docs/screenshots/linux/settings-ai-workflows-en.png" alt="Settings: AI Workflows" width="480">
<br><i>AI Workflows — LLM provider, API key, base URL, model, tone, and writing-style preset.</i><br><br>
<img src="docs/screenshots/linux/en/settings-general.png" alt="Settings: General" width="480">
<img src="docs/screenshots/linux/settings-general-en.png" alt="Settings: General" width="480">
<br><i>General — Auto-Paste, dictation folder, history size, interface language, and signature.</i><br><br>
</div>

Expand Down
Binary file added docs/screenshots/linux/Banner-de.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/linux/Banner-en.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/linux/compose-de.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/linux/compose-en.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/linux/history-de.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/linux/history-en.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/linux/main-window-de.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/linux/main-window-en.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/linux/settings-general-de.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/linux/settings-general-en.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/linux/settings-speech-de.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/linux/settings-speech-en.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/linux/tray-menu-de.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/linux/tray-menu-en.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/linux/tts-de.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/linux/tts-en.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
82 changes: 67 additions & 15 deletions scripts/_make_screenshots.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QApplication

from app.blitztext_linux import BlitztextApp, Config, SettingsDialog
from app.compose_window import ComposeWindow
from app.config import BlitztextConfig
from app.history_panel import HistoryPanel
from app.i18n import set_language, t
from app.llm_service import LLMService, WorkflowType
from app.main_window import MainWindow
from app.paste_service import PasteService
from app.tts_window import TtsWindow
from app.blitztext_linux import BlitztextApp, Config, SettingsDialog

SCREENSHOT_DIR = Path("docs/screenshots/linux")
CANVAS_SIZE = (1280, 640)
Expand All @@ -47,20 +50,22 @@
"hero": "Your local AI voice assistant for KDE Plasma & Wayland",
"sub": "Record speech, transcribe locally or online, optionally rewrite it with AI, and paste it directly into the active app.",
"flow": "Record • Transcribe • Rewrite • Paste",
"feature_title": "What is new in v0.4.0",
"feature_title": "What is new in v0.8.0",
"tag_new": "NEW",
"chips": [
("Multilingual UI", "Switch the whole app between English and German."),
("Writing-style presets", "Ready-made Blitztext+ presets for common writing tasks."),
("Offline-ready", "Local Whisper and privacy-friendly workflows stay available."),
("Global hotkeys", "Capture dictation from anywhere in KDE Plasma."),
("Compose window", "Draft, refine and compare AI-rewritten text before pasting it anywhere."),
("Preset in main window", "Pick your writing style in the main window — changes sync to the tray instantly."),
("Tone & template control", "Choose tone and writing template directly inside the Compose window."),
("Prompt transparency", "Inspect and edit the AI system prompt before running a rewrite."),
],
"labels": {
"main": "Main window",
"general": "Settings → General",
"compose": "Compose window",
"workflows": "Settings → AI Workflows",
"tray": "Tray presets",
},
"compose_input": "Please help me write a concise follow-up email for our product meeting earlier today.",
"compose_output": "Hi team,\n\nThank you for the productive discussion today. Here are the key action items we agreed on:\n\n• Finalise the API contract by Friday\n• Schedule a follow-up review for next Tuesday\n• Share the updated roadmap with stakeholders\n\nLet me know if I missed anything.\n\nBest,",
"history_entries": [
("Please move tomorrow's team sync to 10:00.", False),
("Could you send me the updated rollout plan afterwards?", True),
Expand All @@ -74,20 +79,22 @@
"hero": "Dein lokaler KI-Sprachassistent für KDE Plasma & Wayland",
"sub": "Sprache aufnehmen, lokal oder online transkribieren, optional mit KI umformulieren und direkt in die aktive Anwendung einfügen.",
"flow": "Aufnehmen • Transkribieren • Umformulieren • Direkt einfügen",
"feature_title": "Neu im Stand v0.4.0",
"feature_title": "Neu in v0.8.0",
"tag_new": "NEU",
"chips": [
("Mehrsprachige Oberfläche", "Die komplette App lässt sich zwischen Deutsch und Englisch umschalten."),
("Schreibstil-Vorlagen", "Vorgefertigte Blitztext+-Presets für typische Schreibaufgaben."),
("Offline-fähig", "Lokale Whisper-Workflows bleiben für datensparsame Nutzung verfügbar."),
("Globale Hotkeys", "Diktat direkt aus jeder Anwendung unter KDE Plasma starten."),
("Entwurfsfenster", "Text entwerfen, verfeinern und KI-Varianten vergleichen, bevor du einfügst."),
("Preset im Hauptfenster", "Schreibstil direkt im Hauptfenster wählen – Änderungen bleiben mit dem Tray synchron."),
("Tonfall & Vorlage", "Tonfall und Schreibvorlage direkt im Entwurfsfenster steuern."),
("Prompt-Transparenz", "KI-Systemprompt vor der Ausführung einsehen und anpassen."),
],
"labels": {
"main": "Hauptfenster",
"general": "Einstellungen → Allgemein",
"compose": "Entwurfsfenster",
"workflows": "Einstellungen → KI-Workflows",
"tray": "Tray-Presets",
},
"compose_input": "Bitte hilf mir, eine knappe Nachfass-E-Mail zu unserem heutigen Produktmeeting zu schreiben.",
"compose_output": "Hallo zusammen,\n\nvielen Dank für die produktive Diskussion heute. Hier die vereinbarten Aufgaben:\n\n• API-Vertrag bis Freitag finalisieren\n• Review-Termin für nächsten Dienstag eintragen\n• Aktualisierte Roadmap an Stakeholder verteilen\n\nBitte meldet euch, falls ich etwas vergessen habe.\n\nViele Grüße,",
"history_entries": [
("Bitte verschiebe das Team-Meeting morgen auf 10 Uhr.", False),
("Kannst du mir danach den aktualisierten Rollout-Plan schicken?", True),
Expand Down Expand Up @@ -277,14 +284,14 @@ def _make_banner(lang: str, out_dir: Path) -> None:

screenshots = {
"main": out_dir / f"main-window-{lang}.png",
"general": out_dir / f"settings-general-{lang}.png",
"compose": out_dir / f"compose-{lang}.png",
"workflows": out_dir / f"settings-ai-workflows-{lang}.png",
"tray": out_dir / f"tray-menu-{lang}.png",
}

placements = [
(screenshots["main"], (824, 74), (220, 260), copy["labels"]["main"]),
(screenshots["general"], (1046, 74), (194, 260), copy["labels"]["general"]),
(screenshots["compose"], (1046, 74), (194, 260), copy["labels"]["compose"]),
(screenshots["workflows"], (790, 350), (250, 236), copy["labels"]["workflows"]),
(screenshots["tray"], (1054, 332), (186, 254), copy["labels"]["tray"]),
]
Expand All @@ -307,6 +314,36 @@ def _make_banner(lang: str, out_dir: Path) -> None:
print(f" ✓ {social_path.name}")


class _FakeLLMService(LLMService):
"""Minimal LLMService stub for offscreen rendering — never calls any API."""

def __init__(self) -> None:
self.api_key = "SCREENSHOT_DUMMY_TOKEN"
self.writing_preset = "standard"

def is_configured(self) -> bool:
return True

def rewrite_text(self, *args, **kwargs) -> str: # type: ignore[override]
return ""

def build_system_prompt(self, *args, **kwargs) -> str: # type: ignore[override]
return ""

def rewrite_raw(self, *args, **kwargs) -> str: # type: ignore[override]
return ""


class _FakePasteService(PasteService):
"""Minimal PasteService stub — suppresses all clipboard / xdotool calls."""

def __init__(self) -> None:
pass

def paste(self, text: str, force_autopaste=None) -> None:
pass


def _tab_index(tabs, key: str) -> int:
"""Resolve a settings tab by its i18n key, independent of tab order or language."""
target = t(key)
Expand Down Expand Up @@ -336,9 +373,16 @@ def _render_language_set(out_dir: Path, lang: str) -> None:
show_history_panel=lambda *a, **k: None,
show_settings_dialog=lambda *a, **k: None,
show_tts_window=lambda *a, **k: None,
main_window_preset_changed=lambda *a, **k: None,
)

main_window = MainWindow(controller)
# Switch to TEXT_IMPROVER so the writing-style preset combo is visible
for i in range(main_window._workflow_combo.count()):
if main_window._workflow_combo.itemData(i) == WorkflowType.TEXT_IMPROVER:
main_window._workflow_combo.setCurrentIndex(i)
_process_events()
break
_grab(main_window, out_dir / f"main-window-{lang}.png")
main_window.update_state("RECORDING", None, None)
_grab(main_window, out_dir / f"main-window-recording-{lang}.png")
Expand All @@ -347,6 +391,8 @@ def _render_language_set(out_dir: Path, lang: str) -> None:
settings = SettingsDialog(config)
settings.tabs.setCurrentIndex(_tab_index(settings.tabs, "settings.tab.general"))
_grab(settings, out_dir / f"settings-general-{lang}.png")
settings.tabs.setCurrentIndex(_tab_index(settings.tabs, "settings.tab.speech"))
_grab(settings, out_dir / f"settings-speech-{lang}.png")
settings.tabs.setCurrentIndex(_tab_index(settings.tabs, "settings.tab.workflows"))
_grab(settings, out_dir / f"settings-ai-workflows-{lang}.png")
settings.close()
Expand All @@ -366,6 +412,12 @@ def _render_language_set(out_dir: Path, lang: str) -> None:
_grab(tts, out_dir / f"tts-{lang}.png")
tts.close()

compose = ComposeWindow(_FakeLLMService(), _FakePasteService(), config)
compose.set_input_text(copy["compose_input"])
compose.txtOutput.setPlainText(copy["compose_output"])
_grab(compose, out_dir / f"compose-{lang}.png")
compose.close()

_capture_tray_menu(config, lang, out_dir / f"tray-menu-{lang}.png")
_make_banner(lang, out_dir)

Expand Down