feat(mobile): list items and new notes via a sheet opened by "+"
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m34s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
sandrodachandClaude Opus 5.5 committed 2026-10-31 15:41:44 +01:00
1 parent 19f98ae92f
commit c43c99dc0c
6 files changed
+201 -99

No files matched your search

@@ -562,14 +562,14 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
}, [currentUser, reloadTrash]);
const handleCreateDocument = useCallback(
async (folderPath = '') => {
async (folderPath = '', title = 'Neue Notiz', icon = '📝') => {
if (isCreatingRef.current) return;
isCreatingRef.current = true;
triggerHaptic(10);
try {
const created = await api.createDocument({
title: 'Neue Notiz',
icon: '📝',
title: title.trim() || 'Neue Notiz',
icon: icon.trim() || '📝',
folderPath,
blocks: [
{
@@ -602,6 +602,24 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
[onStatsChange]
);
// Phones: "+" asks for name and emoji first, so a stray tap does not leave an empty note behind.
// The desktop keeps creating at once.
const [newNoteSheet, setNewNoteSheet] = useState<{ folderPath: string } | null>(null);
const [newNoteTitle, setNewNoteTitle] = useState('');
const [newNoteIcon, setNewNoteIcon] = useState('📝');
const openNewNote = useCallback(
(folderPath = '') => {
if (window.innerWidth >= 640) {
void handleCreateDocument(folderPath);
return;
}
setNewNoteTitle('');
setNewNoteIcon('📝');
setNewNoteSheet({ folderPath });
},
[handleCreateDocument]
);
const handleJumpToDocBlock = useCallback((docId: string, blockId?: string) => {
setSelectedDocId(docId);
setTargetBlockId(blockId || null);
@@ -1142,7 +1160,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
// Register mobile FAB actions and the menu at the top; on phones the menu also switches between
// notes, to-dos and hashtags (like the lists in Tasks and Shopping lists), the tab row is hidden there
useEffect(() => {
setPrimaryAction(() => handleCreateDocument(''));
setPrimaryAction(() => openNewNote(''));
setGroups([
{
id: 'workspace-views',
@@ -1191,7 +1209,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
label: 'Neue Notiz',
icon: <FilePlus className="w-4 h-4" />,
variant: 'accent',
onClick: () => handleCreateDocument(''),
onClick: () => openNewNote(''),
},
{
id: 'new-folder',
@@ -1213,7 +1231,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
setGroups([]);
setPrimaryAction(undefined);
};
}, [handleCreateDocument, setGroups, setPrimaryAction, trash.length, openTrash, subView, totalOpenTodos, tagsSummary.length]);
}, [handleCreateDocument, openNewNote, setGroups, setPrimaryAction, trash.length, openTrash, subView, totalOpenTodos, tagsSummary.length]);
// Real-time matched blocks and all nested children for the selected hashtag
const activeTagGroups = useMemo(() => {
@@ -2735,7 +2753,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
)}
<button
type="button"
onClick={() => handleCreateDocument('')}
onClick={() => openNewNote('')}
className="btn-primary inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-semibold"
>
<Plus className="w-3.5 h-3.5" />
@@ -2766,6 +2784,40 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
</FormSheet>
)}
{/* Phones: name and emoji of a new note before it is created */}
{newNoteSheet && (
<FormSheet
title="Neue Notiz"
icon={<FilePlus className="w-4 h-4 text-accent" />}
onClose={() => setNewNoteSheet(null)}
onSubmit={(e) => {
e.preventDefault();
const { folderPath } = newNoteSheet;
setNewNoteSheet(null);
void handleCreateDocument(folderPath, newNoteTitle, newNoteIcon);
}}
>
<div className="flex items-center gap-1.5">
<input
type="text"
value={newNoteIcon}
onChange={(e) => setNewNoteIcon(e.target.value)}
aria-label="Emoji"
title="Icon (Emoji)"
className="w-12 sm:w-10 h-11 sm:h-8 text-center input-field text-base sm:text-sm"
/>
<input
type="text"
autoFocus
value={newNoteTitle}
onChange={(e) => setNewNoteTitle(e.target.value)}
placeholder="Name der Notiz"
className="input-field flex-1 min-w-0 h-11 sm:h-8 px-2.5 text-base sm:text-xs"
/>
</div>
</FormSheet>
)}
{mergeDialog && (
<MergeDialog
docs={docs}