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:
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user