feat: parse hashtags from content instead of dedicated tag input

Tags are now automatically extracted from #hashtags in content text.
Removed TagInput from entry editing, keeping it only in FilterBar.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Thomas Richter
2026-02-01 21:59:04 +01:00
parent 21a11bbb22
commit ce07d79652
5 changed files with 54 additions and 34 deletions

View File

@@ -5,8 +5,8 @@
import { slide } from 'svelte/transition';
import ImageGallery from './ImageGallery.svelte';
import ImageUpload from './ImageUpload.svelte';
import TagInput from './TagInput.svelte';
import { highlightText } from '$lib/utils/highlightText';
import { highlightHashtags } from '$lib/utils/parseHashtags';
interface EntryWithData extends Entry {
images: Image[];
@@ -15,11 +15,10 @@
interface Props {
entry: EntryWithData;
availableTags: Tag[];
searchQuery?: string;
}
let { entry, availableTags, searchQuery = '' }: Props = $props();
let { entry, searchQuery = '' }: Props = $props();
// Expand/collapse state
let expanded = $state(false);
@@ -33,7 +32,6 @@
let editContent = $state(entry.content);
let editType = $state(entry.type);
let editDueDate = $state(entry.dueDate || '');
let editTags = $state<Tag[]>(entry.tags || []);
// Sync edit state when entry changes (after invalidateAll)
$effect(() => {
@@ -42,7 +40,6 @@
editContent = entry.content;
editType = entry.type;
editDueDate = entry.dueDate || '';
editTags = entry.tags || [];
}
});
@@ -192,22 +189,6 @@
await invalidateAll();
}
async function handleTagsChange(newTags: Tag[]) {
editTags = newTags;
// Save immediately (no debounce for tags)
const formData = new FormData();
formData.append('id', entry.id);
formData.append('tags', JSON.stringify(newTags.map((t) => t.name)));
await fetch('?/updateTags', {
method: 'POST',
body: formData
});
await invalidateAll();
}
async function handleCameraInput(e: Event) {
const input = e.target as HTMLInputElement;
const file = input.files?.[0];
@@ -317,7 +298,7 @@
{#if searchQuery}
{@html highlightText(entry.content, searchQuery)}
{:else}
{entry.content}
{@html highlightHashtags(entry.content)}
{/if}
</p>
{#if entry.tags?.length > 0}
@@ -510,12 +491,6 @@
</div>
</div>
<!-- Tags section -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Tags</label>
<TagInput {availableTags} selectedTags={editTags} onchange={handleTagsChange} />
</div>
<div class="flex items-center justify-between">
<div>
<label for="edit-type-{entry.id}" class="block text-sm font-medium text-gray-700 mb-1"