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
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:
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}
|
||||
|
||||
Reference in new issue
Block a user