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