Files
logseq/libs/src/modules/LSPlugin.Request.ts
Charlie 6d6da2046c Enhance/shortcuts (#9803)
* refactor(shortcuts): simplify to build handler category map

* fix(shortcuts): redundant re-mount for the pdf shortcuts

* refactor(shortcuts): simplify names

* refactor(shortcuts): simplify user keynames

* fix(shortcuts): persist inited state for dev mode

* refactor(shortcuts): simplify handlers installation

* refactor(shortcuts): optimize shortcuts mixin

* fix: incorrect function ref

* refactor(shortcuts): shortcuts mixin

* fix(shortcuts): incorrect initialization for the pdf shortcut handler

* refactor(shortcuts): optimize binding keys map

* refactor(shortcuts): optimize shortcuts conflicts detection

* refactor(shortcuts): optimize binding ids map

* refactor(shortcuts): WIP the new keymap page

* refactor(shortcuts): WIP the new keymap related components

* feat(shortcuts): WIP fuzzy search for the shortcuts

* refactor(shortcuts): WIP the new keymap related components

* feat(shortcuts): WIP the new shorcuts record component

* feat(shortcuts): WIP the new shorcuts record component

* feat(shortcuts): WIP check shortcut conflicts component

* feat(shortcuts): WIP the new shorcuts record component

* refactor(shortcuts): WIP persist user shortcuts

* fix(shortcuts): detection for the conflicts

* feat(shortcuts): WIP detection for the conflicts

* feat(shortcuts): WIP persist user shortcuts

* refactor(shortcuts): add unit tests

* enhance(ux): search pane for the shortcuts

* feat(shortcuts): remove the existent shortcut item

* feat(shortcuts): fold/unfold categories

* feat(shortcuts): add shortcuts filters

* enhance(shortcuts): resove binding map description

* enhance(shortcuts): reactive category shortcuts

* enhance(shortcuts): register api for plugins

* feat(shortcuts): add keyboard shortcuts filters

* feat(shortcuts): impl keyboard shortcuts filters

* enhance(shortcuts): leader keys for the shortcut conflicts detection

* enhance(tests): leader keys conflicts for the shortucts

* enhance(shortcuts): parse conflicts from current binding list

* enhance(ui): polish the component of the restore shortcut action

* enhance(shortcuts): get conflicts with specific handler id

* enhance(shortcuts): polish the confilts component

* enhance(shortcuts): polish keymap conflicts component

* enhance(shortcuts): ux for handling shorcuts conflicts

* enhance(ui): polish notifications cp

* fix(shortcuts): remove reduplicate shortcuts for category

* enhance(shortcuts): polish ux for handling shorcuts conflicts

* chore(plugin): build libs core

* enhance(plugin): support shortcut command lifecycle hooks

* enhance(plugin): support shortcut command lifecycle hooks

* chore(plugin): build libs core

* enhance(shortcuts): support shortcuts saved to global config

* enhance(shortcuts): support shortcuts be saved to global config

* feat(shortcuts): support keymap manager to global settings

* enhance(shortcuts): shortcut to open keymap settings

* fix(units): tests

* fix: lints

* enhance(shortcuts): unlisten all shortcuts

* fix: lints

* fix: lints

* fix(units): tests

* fix(units): tests

* fix(units): tests

* enhance(shortcuts): unlisten/listen all shortcuts

* enhance(shortcuts): polish conflicts component

* fix(ui): modal size

* fix(ui): modal panel container

* enhance(shortcuts): i18n

* enhance(ui): layout of the shortcuts recorder component

* fix(lint): i18n

* enhance(ui): keyboard icon for the keymap settings tab

* fix(shortcuts): incorrect filters for the collaspsed shortcuts

* enhance(ui): polish details for the keymap settings

* enhance(ui): polish details for the keymap settings

* fix(shortcuts): get shortcut description error when the associated handler-id not exist

* fix(ui): the shortcut disabled label overlaps with section headers.

* refactor(shortcuts): names

* enhance(ui): filter icons
2023-08-29 19:33:48 +08:00

144 lines
3.1 KiB
TypeScript

import { LSPluginUser, WithOptional } from '../LSPlugin.user'
import { EventEmitter } from 'eventemitter3'
export type IRequestOptions<R = any> = {
url: string
abortable: boolean
headers: Record<string, string>
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
data: Object | ArrayBuffer
timeout: number
returnType: 'json' | 'text' | 'base64' | 'arraybuffer'
success: (result: R) => void
fail: (err: any) => void
final: () => void
}
export type RequestTaskID = string | number
const CLIENT_MSG_CALLBACK = '#lsp#request#callback'
const genTaskCallbackType = (id: RequestTaskID) => `task_callback_${id}`
/**
* Request task
*/
export class LSPluginRequestTask<R = any> {
private readonly _promise: Promise<R>
private _aborted: boolean = false
constructor(
private _client: LSPluginRequest,
private _requestId: RequestTaskID,
private _requestOptions: Partial<IRequestOptions> = {}
) {
this._promise = new Promise<any>((resolve, reject) => {
if (!this._requestId) {
return reject(null)
}
// task result listener
this._client.once(genTaskCallbackType(this._requestId), (e) => {
if (e && e instanceof Error) {
reject(e)
} else {
resolve(e)
}
})
})
const { success, fail, final } = this._requestOptions
this._promise
.then((res) => {
success?.(res)
})
.catch((e) => {
fail?.(e)
})
.finally(() => {
final?.()
})
}
abort() {
if (!this._requestOptions.abortable || this._aborted) return
this._client.ctx._execCallableAPI('http_request_abort', this._requestId)
this._aborted = true
}
get promise(): Promise<R> {
return this._promise
}
get client(): LSPluginRequest {
return this._client
}
get requestId(): RequestTaskID {
return this._requestId
}
}
/**
* A simple request client
*/
export class LSPluginRequest extends EventEmitter {
constructor(private _ctx: LSPluginUser) {
super()
// request callback listener
this.ctx.caller.on(CLIENT_MSG_CALLBACK, (e: any) => {
const reqId = e?.requestId
if (!reqId) return
this.emit(genTaskCallbackType(reqId), e?.payload)
})
}
static createRequestTask(
client: LSPluginRequest,
requestID: RequestTaskID,
requestOptions: Partial<IRequestOptions>
) {
return new LSPluginRequestTask(client, requestID, requestOptions)
}
async _request<
R extends {},
T extends WithOptional<
IRequestOptions<R>,
keyof Omit<IRequestOptions, 'url'>
>
>(
options: T
): Promise<
T extends Pick<IRequestOptions, 'abortable'> ? LSPluginRequestTask<R> : R
> {
const pid = this.ctx.baseInfo.id
const { success, fail, final, ...requestOptions } = options
const reqID = this.ctx.Experiments.invokeExperMethod(
'request',
pid,
requestOptions
)
const task = LSPluginRequest.createRequestTask(
this.ctx.Request,
reqID,
options
)
if (!requestOptions.abortable) {
return task.promise
}
return task as any
}
get ctx(): LSPluginUser {
return this._ctx
}
}