| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- import { BaseSession } from './sessions'
-
- /**
- * # Session Manager
- *
- * Sessions are instances that manage data mutations for activities such as
- * dragging, transforming, drawing, etc. The session manager singleton provides
- * an API with which the state's actions can begin a session and interact it.
- *
- * A session has a lifecycle:
- *
- * - it `begin`s when the session instance is created
- * - it receives `update`s during the session
- * - it ends either when it is `complete`d or `cancel`led
- *
- * Each session may produce different effects during these life cycles, according
- * to its implementation. Most sessions call a command when completed.
- *
- * It's intended that only a single session occurs at once. This pattern helps
- * ensure that we don't accidentally begin a new session before the current one
- * is cancelled or completes.
- */
-
- class SessionManager {
- #current?: BaseSession
-
- /**
- * Begin a new session.
- * @param session A Session instance.
- * @example
- * ```ts
- * session.begin(new Sessions.EditSession(data))
- * ```
- */
- begin(session: BaseSession) {
- if (this.#current) {
- throw Error(
- 'Cannot begin a session until the current session is complete. This error indicates a problem with the state chart.'
- )
- }
-
- this.#current = session
- return this
- }
-
- /**
- * Update the current session. Include the session type as a generic in order to properly type the arguments.
- * @param args The arguments of the current session's `update` method.
- * @example
- * ```ts
- * session.update<Sessions.EditSession>(data, payload.change)
- * ```
- */
- update<T extends BaseSession>(...args: Parameters<T['update']>) {
- const session = this.#current
-
- if (session === undefined) {
- throw Error('No current session.')
- }
-
- session.update.call(this.#current, ...args)
- return this
- }
-
- /**
- * Complete the current session. Include the session type as a generic in order to properly type the arguments.
- * @param args The arguments of the current session's `complete` method.
- * @example
- * ```ts
- * session.update<Sessions.EditSession>(data, payload.change)
- * ```
- */
- complete<T extends BaseSession>(...args: Parameters<T['complete']>) {
- const session = this.#current
-
- if (session === undefined) return this
-
- session.complete.call(this.#current, ...args)
- this.#current = undefined
- return this
- }
-
- /**
- * Cancel the current session.
- * @param args The arguments of the current session's `cancel` method.
- * @example
- * ```ts
- * session.cancel(data)
- * ```
- */
- cancel<T extends BaseSession>(...args: Parameters<T['cancel']>) {
- this.#current.cancel.call(this.#current, ...args)
- this.#current = undefined
- return this
- }
- }
-
- const session = new SessionManager()
-
- export default session
|