Refactor task components, add mobile-friendly enhancements, and improve settings management

- Introduced `TodoItemTouch`, a responsive task item optimized for mobile interaction with swipe actions.
- Added `MobileActions` for streamlined task creation and settings access on smaller screens.
- Refactored `App.vue` to adapt layouts dynamically for mobile and desktop users.
- Implemented collapsible, categorized task lists with improved handling in `TodoList` and `TodoListTouch`.
- Improved task swipe actions with `useSwipe` for smoother UI interactions.
- Updated styling with DaisyUI theme customization and multi-theme support.
- Enhanced `useSettings` with a `todayShown` toggle for quick agenda visibility.
This commit is contained in:
2026-03-04 10:41:23 +01:00
parent 2fea267ce9
commit 353bbea093
20 changed files with 500 additions and 241 deletions

View File

@@ -15,11 +15,13 @@ import {
tagRenameCommand,
} from '../utils/actions.ts'
import { parseCommand } from '../utils/parser.ts'
import { useSettings } from './useSettings.ts'
import { useTasks } from './useTasks.ts'
export default function useActions() {
const { tasks: tasksOriginal, createTask, updateTask } = useTasks()
const run = (value: string) => {
const { settings } = useSettings()
const run = async (value: string) => {
const cmd = parseCommand(value)
let tasksToUpdate: Task[] = []
let taskToCreate: Pick<Task, 'tag' | 'title' | 'dueDate'> | null = null
@@ -81,10 +83,9 @@ export default function useActions() {
case 'tagrename':
tasksToUpdate = tagRenameCommand(cmd, tasks)
break
/* Visibility */
// case 'hide':
// updateCandidate = hideCommand(updateCandidate, cmd)
// break
case 'today':
settings.value.todayShown = !settings.value.todayShown
break
// case 'show':
// updateCandidate = showCommand(updateCandidate, cmd)
// break
@@ -97,12 +98,11 @@ export default function useActions() {
// break
}
}
// console.log(tasksToUpdate, taskToCreate)
if (tasksToUpdate) {
updateTask(tasksToUpdate)
await updateTask(tasksToUpdate)
}
if (taskToCreate) {
createTask(taskToCreate)
await createTask(taskToCreate)
}
}
return { run }

View File

@@ -1,14 +1,13 @@
import { computed, onMounted, ref } from 'vue'
import { useStore } from './useStore.ts'
const store = ref<string[]>([])
const historyIndex = ref(0)
export default function useHistory() {
const { getValue, setValue } = useStore()
const store = ref<string[]>([])
const history = computed<string[]>(() => store.value)
const historyIndex = ref(0)
const resetHistoryIndex = () => {
historyIndex.value = store.value.length - 1
}

View File

@@ -1,63 +1,67 @@
import { ref, watch } from 'vue';
import { useStore } from './useStore.ts';
import { useCrypto } from './useCrypto.ts';
import { ref, watch } from 'vue'
import { useCrypto } from './useCrypto.ts'
import { useStore } from './useStore.ts'
export type Settings = {
username: string,
password: string,
export interface Settings {
username: string
password: string
todayShown: boolean
}
const settingsDefault: Settings = {
username: '',
password: '',
};
todayShown: false,
}
const settings = ref<Settings>({ ...settingsDefault })
export function useSettings() {
const { setValue, getValue } = useStore();
const { encrypt, decrypt } = useCrypto();
const settings = ref<Settings>({ ...settingsDefault });
const { setValue, getValue } = useStore()
const { encrypt, decrypt } = useCrypto()
const loadSettings = async () => {
const readSettings = await getValue<Settings>('settings');
const readSettings = await getValue<Settings>('settings')
if (!readSettings) {
settings.value = { ...settingsDefault };
return;
settings.value = { ...settingsDefault }
return
}
let password = readSettings.password ?? '';
let password = readSettings.password ?? ''
if (password) {
try {
password = decrypt(password) as string;
} catch (error) {
console.warn('Failed to decrypt stored password:', error);
password = decrypt(password) as string
}
catch (error) {
console.warn('Failed to decrypt stored password:', error)
}
}
settings.value = {
username: readSettings.username ?? '',
...settingsDefault,
...readSettings,
password,
};
};
}
}
const saveSettings = async () => {
const encryptedPassword = settings.value.password
? encrypt(settings.value.password) as string
: '';
: ''
await setValue<Settings>('settings', {
username: settings.value.username,
...settings.value,
password: encryptedPassword,
});
};
})
}
watch(settings, () => {
void saveSettings();
}, { deep: true });
void saveSettings()
}, { deep: true })
void loadSettings();
void loadSettings()
return {
settings,
loadSettings,
};
}
}

View File

@@ -10,7 +10,6 @@ const error = ref<string | null>(null)
export function useTasks() {
const api = useApi()
const fetchTasks = async (force = false) => {
if (tasks.value.length > 0 && !force)
return