diff --git a/CHANGELOG.md b/CHANGELOG.md index 7220df3..d370d29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,13 @@ Das Format folgt [Keep a Changelog](https://keepachangelog.com/de/1.1.0/), die V ## [Unreleased] +## [0.26.1] - 2026-10-31 + +### Fixed +- Notizen am Handy: Ein Tipp rechts neben einen Punkt löste die unsichtbaren Knöpfe aus (In eigene Notiz umwandeln, Fokus, Löschen …). Die Knöpfe reagieren jetzt nur noch, wenn sie zu sehen sind, also beim Bearbeiten des Punkts. +- Notizen: Ein Punkt, der schon in eine eigene Notiz umgewandelt wurde (nur noch der Link, ggf. mit Hashtags), lässt sich nicht noch einmal umwandeln; der Knopf und `/extract` fehlen dort. Bisher entstand dabei eine zweite Notiz, die nur den Link enthielt. +- Hinweis nach dem Umwandeln am Handy („Öffnen“, „Rückgängig“): sitzt jetzt über der unteren Leiste statt am Bildschirmrand, Text oben (höchstens zwei Zeilen), Knöpfe darunter. + ## [0.26.0] - 2026-10-31 ### Added @@ -527,7 +534,8 @@ Das Format folgt [Keep a Changelog](https://keepachangelog.com/de/1.1.0/), die V - Geteilte Listen (Einkaufs-, Pack- und Checklisten) mit `#Kategorie`-Gruppierung, Mengenangaben und Echtzeit-Abhaken. - Benutzer-, Gruppen- und Admin-Verwaltung (Ersteinrichtungs-Assistent, Einladungscodes, Profilbilder, persönliche API-Keys & Webhook-Ingest `/api/v1/webhooks/ingest`, JSON-Datenexport) sowie CSS-Theme-Engine mit 4 Themes (`Dark`, `Light`, `High Contrast`, `Soft`) und PWA-Unterstützung. -[Unreleased]: https://git.dsit.me/sandrodach/MindSift/compare/v0.26.0...dev +[Unreleased]: https://git.dsit.me/sandrodach/MindSift/compare/v0.26.1...dev +[0.26.1]: https://git.dsit.me/sandrodach/MindSift/compare/v0.26.0...v0.26.1 [0.26.0]: https://git.dsit.me/sandrodach/MindSift/compare/v0.25.1...v0.26.0 [0.25.1]: https://git.dsit.me/sandrodach/MindSift/compare/v0.25.0...v0.25.1 [0.25.0]: https://git.dsit.me/sandrodach/MindSift/compare/v0.24.2...v0.25.0 diff --git a/Doku/api/rest.md b/Doku/api/rest.md index 6b1f75e..2a3c2b2 100644 --- a/Doku/api/rest.md +++ b/Doku/api/rest.md @@ -127,7 +127,7 @@ Schreibzugriffe von Lesern auf Listen oder deren Aufgaben liefern `403` („Kein | POST | `/documents/{id}/blocks/{blockId}/enhanced-task` | Aus einem Block eine verknüpfte Aufgabe machen (`content`, `checked`) | | GET/POST | `/documents/{id}/shares` | Notiz-Freigaben (`userId`/`email`/`teamId`, `permission`: `read`/`write`) | | DELETE | `/documents/{id}/shares/{userId}` | Notiz-Freigabe entfernen | -| POST | `/documents/{id}/extract` | `{blockId, clientId}`: legt aus den Unterpunkten des Punkts eine eigene Notiz an (Titel = Text ohne Hashtags, gleicher Ordner, Freigaben übernommen, fremder Besitzer bekommt Schreibrecht) → `{document, link}`. Die Ursprungsnotiz ändert der Server nicht; der Editor ersetzt den Ast selbst durch `link` (normale eigene Änderung, Strg+Z möglich). Schreibrecht nötig; `409`, wenn jemand anderes im Ast schreibt | +| POST | `/documents/{id}/extract` | `{blockId, clientId}`: legt aus den Unterpunkten des Punkts eine eigene Notiz an (Titel = Text ohne Hashtags, gleicher Ordner, Freigaben übernommen, fremder Besitzer bekommt Schreibrecht) → `{document, link}`. Die Ursprungsnotiz ändert der Server nicht; der Editor ersetzt den Ast selbst durch `link` (normale eigene Änderung, Strg+Z möglich). Schreibrecht nötig; `409`, wenn jemand anderes im Ast schreibt; `400`, wenn der Punkt nur noch ein Link auf eine Notiz ist (ggf. mit Hashtags) | | GET | `/push/key` | `{enabled, publicKey}` – öffentlicher VAPID-Schlüssel für `pushManager.subscribe` (in der Demo `enabled: false`) | | GET | `/push/devices` | Eigene Geräte mit Push → `{devices: [{id, endpoint, device, createdAt}]}` | | POST | `/push/subscribe` | `{endpoint, keys: {p256dh, auth}, device}` – Gerät anmelden (nur `https`-Endpunkte) | diff --git a/README.md b/README.md index 8398b63..1a814d4 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Self-Hosted](https://img.shields.io/badge/100%25-Self--Hosted-2563eb?style=flat-square)](#) [![Docker](https://img.shields.io/badge/Deployment-Single%20Container-2496ed?style=flat-square&logo=docker&logoColor=white)](#-schnellstart) [![SQLite](https://img.shields.io/badge/Daten-SQLite-003b57?style=flat-square&logo=sqlite&logoColor=white)](#-deine-daten-gehören-dir) -[![Version](https://img.shields.io/badge/Version-v0.26.0-16a34a?style=flat-square)](CHANGELOG.md) +[![Version](https://img.shields.io/badge/Version-v0.26.1-16a34a?style=flat-square)](CHANGELOG.md) **MindSift** ist eine selbst gehostete Schaltstelle für spontane Gedanken, Aufgaben mit Kanban-Board, hierarchische Outliner-Notizen, die mehrere Personen gleichzeitig bearbeiten können, und gemeinsame Listen. Alles läuft als ein einzelner Container mit eingebetteter SQLite-Datenbank, auf deinem eigenen Server. diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c238685..91765fc 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "mindsift-frontend", - "version": "0.26.0", + "version": "0.26.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mindsift-frontend", - "version": "0.26.0", + "version": "0.26.1", "license": "Unlicense", "dependencies": { "@fontsource-variable/inter": "5.3.0", diff --git a/frontend/package.json b/frontend/package.json index 68cfb16..4d68e39 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "mindsift-frontend", "private": true, - "version": "0.26.0", + "version": "0.26.1", "license": "Unlicense", "type": "module", "scripts": { diff --git a/frontend/src/features/workspace/DocumentEditor.tsx b/frontend/src/features/workspace/DocumentEditor.tsx index 3bcb118..a3c1e16 100644 --- a/frontend/src/features/workspace/DocumentEditor.tsx +++ b/frontend/src/features/workspace/DocumentEditor.tsx @@ -1372,23 +1372,28 @@ export const DocumentEditor: React.FC = ({ {notice && (
- {notice} - {noticeActions.map((a) => ( - - ))} + {/* Phones: text on top (two lines at most), buttons below; desktop: one line */} + {notice} + {noticeActions.length > 0 && ( + + {noticeActions.map((a) => ( + + ))} + + )}
)} diff --git a/frontend/src/features/workspace/OutlinerBlock.tsx b/frontend/src/features/workspace/OutlinerBlock.tsx index 56f801e..e8e3fa4 100644 --- a/frontend/src/features/workspace/OutlinerBlock.tsx +++ b/frontend/src/features/workspace/OutlinerBlock.tsx @@ -42,6 +42,7 @@ import { mediaContent, parseMediaContent } from '../../lib/media'; import { renderInlineMarkdown } from '../../lib/markdown'; import { api } from '../../lib/api'; import { safeHref } from '../../lib/safeUrl'; +import { isNoteLinkOnly } from '../../lib/wikiLink'; export interface SlashCommand { type: BlockType | 'link' | 'dictation' | 'extract'; @@ -459,7 +460,7 @@ export const OutlinerBlock: React.FC = ({ // /extract only when note has content and is at start/end if (c.type === 'extract') { - return !isRestEmpty && isAtStartOrEnd && !!onExtractBlock; + return !isRestEmpty && isAtStartOrEnd && !!onExtractBlock && !isNoteLinkOnly(restOfBlock); } // /h1, /h2, /h3, /todo, /callout, /text (type 'bullet') at start or at end @@ -1579,7 +1580,8 @@ export const OutlinerBlock: React.FC = ({ className={`absolute right-1 sm:right-2 top-0.5 sm:top-1 z-20 bg-panel/90 backdrop-blur-sm border border-border shadow-xs rounded-pill px-1 sm:px-1.5 py-0.5 flex items-center gap-0.5 sm:gap-1 transition-opacity ${ activeFocus ? 'opacity-100 pointer-events-auto' - : 'opacity-0 group-hover:opacity-100 focus-within:opacity-100 pointer-events-none group-hover:pointer-events-auto focus-within:pointer-events-auto' + : // Hover only with a real pointer: a tap on a phone would make the invisible buttons clickable + 'opacity-0 [@media(hover:hover)]:group-hover:opacity-100 focus-within:opacity-100 pointer-events-none [@media(hover:hover)]:group-hover:pointer-events-auto focus-within:pointer-events-auto' }`} > {/* Convert back to bullet for headings, callouts, dividers, code and numbered items */} @@ -1702,7 +1704,7 @@ export const OutlinerBlock: React.FC = ({ )} {/* Branch into its own note */} - {canEdit && onExtractBlock && localContent.trim() !== '' && !mediaPicker && ( + {canEdit && onExtractBlock && localContent.trim() !== '' && !isNoteLinkOnly(localContent) && !mediaPicker && (