diff --git a/plugin/src/api/index.ts b/plugin/src/api/index.ts index 32c9ac4..ad0d6fc 100644 --- a/plugin/src/api/index.ts +++ b/plugin/src/api/index.ts @@ -30,12 +30,57 @@ export class TodoistApiClient { } } - public async createTask(content: string, options?: CreateTaskParams): Promise { - const body = snakify({ - content: content, - ...(options ?? {}), + public async createTask(content: string, options?: CreateTaskParams, useQuickAddEndpoint?: boolean): Promise { + if (useQuickAddEndpoint) { + // Quick add endpoint expects a different payload + const body = new URLSearchParams({ + text: content, + ...((options?.description ? { description: options.description } : {})), + ...((options?.projectId ? { project_id: options.projectId } : {})), + ...((options?.sectionId ? { section_id: options.sectionId } : {})), + ...((options?.dueDate ? { due_date: options.dueDate } : {})), + ...((options?.dueDatetime ? { due_datetime: options.dueDatetime } : {})), + ...((options?.labels ? { labels: options.labels.join(",") } : {})), + ...((options?.priority ? { priority: String(options.priority) } : {})), + }); + await this.doQuickAdd("https://api.todoist.com/sync/v9/quick/add", body); + } else { + const body = snakify({ + content: content, + ...(options ?? {}), + }); + await this.do("/tasks", "POST", body); + } + } + + private async doQuickAdd(url: string, body: URLSearchParams): Promise { + const params: RequestParams = { + url, + method: "POST", + headers: { + Authorization: `Bearer ${this.token}`, + "Content-Type": "application/x-www-form-urlencoded", + }, + body: body.toString(), + }; + + debug({ + msg: "Sending Todoist Quick Add API request", + context: params, }); - await this.do("/tasks", "POST", body); + + const response = await this.fetcher.fetch(params); + + debug({ + msg: "Received Todoist Quick Add API response", + context: response, + }); + + if (response.statusCode >= 400) { + throw new TodoistApiError(params, response); + } + + return response; } public async closeTask(id: TaskId): Promise { diff --git a/plugin/src/data/index.ts b/plugin/src/data/index.ts index aa2ad20..7ca2c8a 100644 --- a/plugin/src/data/index.ts +++ b/plugin/src/data/index.ts @@ -7,6 +7,7 @@ import { Repository, type RepositoryReader } from "@/data/repository"; import { SubscriptionManager, type UnsubscribeCallback } from "@/data/subscriptions"; import type { Task } from "@/data/task"; import { Maybe } from "@/utils/maybe"; +import { useSettingsStore } from "@/settings"; export enum QueryErrorKind { BadRequest = 0, @@ -38,8 +39,10 @@ class LabelsRepository extends Repository { export class TodoistAdapter { public actions = { closeTask: async (id: TaskId) => await this.closeTask(id), - createTask: async (content: string, params: CreateTaskParams) => - await this.api.withInner((api) => api.createTask(content, params)), + createTask: async (content: string, params: CreateTaskParams) => { + const { useQuickAddEndpoint } = useSettingsStore.getState(); + await this.api.withInner((api) => api.createTask(content, params, useQuickAddEndpoint)); + }, }; private readonly api: Maybe = Maybe.Empty(); diff --git a/plugin/src/i18n/langs/nl.ts b/plugin/src/i18n/langs/nl.ts index 16cd9b0..28d06c8 100644 --- a/plugin/src/i18n/langs/nl.ts +++ b/plugin/src/i18n/langs/nl.ts @@ -71,7 +71,7 @@ export const nl: DeepPartial = { label: "Debug-logboek inschakelen", description: "Of debug-logboeken moeten worden ingeschakeld", }, - }, + }, deprecation: { warningMessage: "Deze instelling is verouderd en wordt in een toekomstige release verwijderd.", diff --git a/plugin/src/settings.ts b/plugin/src/settings.ts index 3db1e5e..7c9f1dc 100644 --- a/plugin/src/settings.ts +++ b/plugin/src/settings.ts @@ -27,6 +27,8 @@ const defaultSettings: Settings = { taskCreationDefaultProject: null, debugLogging: false, + + useQuickAddEndpoint: false, }; export type Settings = { @@ -48,6 +50,8 @@ export type Settings = { taskCreationDefaultProject: ProjectDefaultSetting; debugLogging: boolean; + + useQuickAddEndpoint: boolean; }; export const useSettingsStore = create(() => ({ diff --git a/plugin/src/ui/createTaskModal/index.tsx b/plugin/src/ui/createTaskModal/index.tsx index 4198d61..635ec78 100644 --- a/plugin/src/ui/createTaskModal/index.tsx +++ b/plugin/src/ui/createTaskModal/index.tsx @@ -25,6 +25,7 @@ import "./styles.scss"; import type { Translations } from "@/i18n/translation"; import { OptionsSelector } from "@/ui/createTaskModal/OptionsSelector"; +import { Setting } from "@/ui/settings/SettingItem"; export type LinkDestination = "content" | "description"; @@ -138,6 +139,7 @@ const CreateTaskModalContent: React.FC = ({ ); const [options, setOptions] = useState(initialOptions); + const [useQuickAdd, setUseQuickAdd] = useState(settings.useQuickAddEndpoint); const isSubmitButtonDisabled = content === "" && options.appendLinkTo !== "content"; @@ -186,6 +188,10 @@ const CreateTaskModalContent: React.FC = ({ } try { + // Persist the last used preference so user choice is remembered + if (useQuickAdd !== settings.useQuickAddEndpoint) { + await plugin.writeOptions({ useQuickAddEndpoint: useQuickAdd }); + } await plugin.services.todoist.actions.createTask( buildWithLink(content, options.appendLinkTo === "content"), params, @@ -228,6 +234,16 @@ const CreateTaskModalContent: React.FC = ({
    {linkDestinationMessage &&
  • {linkDestinationMessage}
  • }
+
+ +