@api-client/ui 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/settings.json +1 -0
- package/build/src/core/Activity.d.ts +2 -2
- package/build/src/core/Activity.d.ts.map +1 -1
- package/build/src/core/Activity.js +2 -2
- package/build/src/core/Activity.js.map +1 -1
- package/build/src/core/ActivityManager.d.ts +29 -1
- package/build/src/core/ActivityManager.d.ts.map +1 -1
- package/build/src/core/ActivityManager.js +69 -45
- package/build/src/core/ActivityManager.js.map +1 -1
- package/build/src/core/Application.d.ts.map +1 -1
- package/build/src/core/Application.js +2 -2
- package/build/src/core/Application.js.map +1 -1
- package/build/src/core/ModalActivity.js +1 -1
- package/build/src/core/ModalActivity.js.map +1 -1
- package/eslint.config.js +3 -0
- package/package.json +1 -1
- package/src/core/Activity.ts +2 -2
- package/src/core/ActivityManager.ts +60 -36
- package/src/core/Application.ts +2 -2
- package/src/core/ModalActivity.ts +1 -1
- package/test/core/activity.spec.ts +2 -2
- package/test/core/activity_manager.spec.ts +25 -25
- package/test/core/application.spec.ts +3 -3
- package/test/core/fragment.spec.ts +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Application.js","sourceRoot":"","sources":["../../../src/core/Application.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAuB,MAAM,KAAK,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"Application.js","sourceRoot":"","sources":["../../../src/core/Application.ts"],"names":[],"mappings":"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","sourcesContent":["import { nothing, type TemplateResult } from 'lit'\nimport { ActivityManager, ActivityLifecycle } from './ActivityManager.js'\nimport type { Activity } from './Activity.js'\nimport { ApplicationRenderer } from './renderer/ApplicationRenderer.js'\nimport { ThemeManager } from './ThemeManager.js'\n\n/**\n * Allows to fine-tune the update request.\n * For example, if a `Fragment` wants to update only itself, then\n * list other types should be set to false.\n */\nexport interface UpdateRequest {\n /**\n * Whether the whole application should be updated.\n * Default to true.\n */\n app?: boolean\n /**\n * Whether the activity should be updated.\n * Default to true.\n */\n activity?: boolean\n /**\n * Whether the fragment should be updated.\n * Default to true.\n */\n fragment?: boolean\n}\n/**\n * The application represents an application screen that hosts\n * Activities. Activities are managed by the Activity manager.\n *\n * An application is a separate app within the ecosystem. For example,\n * the file browser is one application. The domain designer is another.\n *\n * Each application manages it's own lifecycle. The application is rendered\n * by the lit's library `render()` function. Activities can call application's\n * main `requestUpdate()` function to render the entire application.\n *\n * Activities have the render function that renders its UI.\n * The Activity's UI can be composed of fragments, but this is optional.\n * When an activity uses fragments, they receive control over rendering their\n * UIs. An activity implementation has to take care of passing HTMLElement\n * references to their Fragments to make that happen. Otherwise, the activity\n * has to communicate with their fragments to request to re-render the application.\n */\nexport abstract class Application extends EventTarget {\n private activityUpdateListener = this.handleActivityUpdate.bind(this)\n\n #activities: ActivityManager\n\n #theme: ThemeManager\n\n /**\n * Application's theme manager.\n */\n get theme(): ThemeManager {\n return this.#theme\n }\n\n /**\n * Returns the application's activity manager.\n */\n get manager(): ActivityManager {\n return this.#activities\n }\n\n #events: EventTarget\n\n /**\n * The application main event bus.\n * All activities and fragments use it to communicate.\n * This way, events do not leak outside the application.\n */\n get events(): EventTarget {\n return this.#events\n }\n\n #renderer: ApplicationRenderer\n\n get renderer(): ApplicationRenderer {\n return this.#renderer\n }\n\n /**\n * @type A promise resolved when the render finished.\n */\n get updateComplete(): Promise<void> | undefined {\n return this.#renderer.updateComplete\n }\n\n /**\n * @type True when the application was first rendered.\n */\n get firstRendered(): boolean {\n return this.#renderer.firstRendered\n }\n\n /**\n * @param renderRoot The element or a CSS query to the element where the application will be rendered.\n */\n constructor(renderRoot: HTMLElement | string) {\n super()\n this.#events = new EventTarget()\n this.#activities = new ActivityManager(this)\n this.#renderer = new ApplicationRenderer(this)\n this.#renderer.setRenderRoot(renderRoot)\n this.#theme = new ThemeManager()\n\n // Listen for activity updates\n this.#events.addEventListener('activity:update', this.activityUpdateListener as EventListener)\n }\n\n /**\n * @see {@link ./Renderer.js}\n */\n public setRenderRoot(renderRoot: HTMLElement | string): void {\n this.#renderer.setRenderRoot(renderRoot)\n }\n\n /**\n * Called when the application starts.\n * This is where you should start the initial Activity using\n * `ActivityManager.startActivity(...)`.\n */\n abstract onStart(): void | Promise<void>\n\n /**\n * Called when the application is stopped/closed.\n * Perform cleanup here.\n */\n onStop(): void | Promise<void> {\n //\n }\n\n /**\n * Called when the application was rendered for the first time.\n * Call `super.onFirstRender()` when overriding this method.\n */\n onFirstRender(): void {\n this.#events.dispatchEvent(new Event('app:first-render'))\n }\n\n /**\n * Called when the application was rendered.\n */\n onRendered(): void {\n //\n }\n\n /**\n * The main render method for the Application. Called whenever an activity\n * requests an update. Renders the currently active Activity's content.\n *\n * If you override this method then any activity won't be rendered.\n *\n * @returns The Lit template to render.\n */\n render(): TemplateResult | typeof nothing {\n const currentActivity = this.#activities.getCurrentActivity()\n // Only render if started or beyond\n if (currentActivity && currentActivity.lifecycle >= ActivityLifecycle.Started) {\n return currentActivity.render()\n }\n return nothing\n }\n\n /**\n * Handles activity update requests and re-renders the application.\n */\n private handleActivityUpdate(e: CustomEvent<UpdateRequest | undefined>): void {\n this.requestUpdate(e.detail || undefined)\n }\n\n /**\n * Requests an update of the application UI. This will call the `render()` method\n * and update the DOM.\n */\n requestUpdate(opts: UpdateRequest = {}): void {\n const { app = true } = opts\n if (app) {\n this.#renderer.requestUpdate()\n }\n }\n\n /**\n * Starts the application by calling onStart and performing an initial render.\n */\n public async run(): Promise<void> {\n await this.onStart()\n this.requestUpdate()\n }\n\n /**\n * Stops the application, performing cleanup if necessary.\n */\n public async stop(): Promise<void> {\n this.#events.removeEventListener('activity:update', this.activityUpdateListener as EventListener)\n // Allow subclasses to clean up\n await this.onStop()\n // ... any other application-level cleanup\n }\n\n getCurrentActivity(): Activity | undefined {\n return this.#activities.getCurrentActivity()\n }\n\n /**\n * Unifies Fragment and Application interfaces.\n * @returns `this`\n */\n getApplication() {\n return this\n }\n\n findActiveActivity(id: string): Activity | undefined {\n return this.#activities.findActiveActivity(id)\n }\n}\n"]}
|
|
@@ -49,7 +49,7 @@ let ModalActivity = (() => {
|
|
|
49
49
|
formId = __runInitializers(this, _opened_extraInitializers);
|
|
50
50
|
onResume() {
|
|
51
51
|
this.renderRoot = document.createElement('div');
|
|
52
|
-
this.renderRoot.classList.add('modal-
|
|
52
|
+
this.renderRoot.classList.add('modal-activity-container');
|
|
53
53
|
document.body.appendChild(this.renderRoot);
|
|
54
54
|
super.onResume();
|
|
55
55
|
this.requestUpdate();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ModalActivity.js","sourceRoot":"","sources":["../../../src/core/ModalActivity.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAuB,MAAM,KAAK,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAExC,OAAO,KAAK,MAAM,wBAAwB,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAEnD,OAAO,2BAA2B,CAAA;AAClC,OAAO,gCAAgC,CAAA;AAavC;;;;;;;;;GASG;IACmB,aAAa;sBAAS,QAAQ;;;;iBAA9B,aAAc,SAAQ,WAAQ;;;kCAQjD,KAAK,EAAE;YAAC,uKAAS,MAAM,6BAAN,MAAM,uFAAO;;;QAP/B;;WAEG;QACO,aAAa,GAA4B,EAAE,CAAA;QAI5C,yEAAkB,IAAI;QAE/B;;WAEG;UAJ4B;QAH/B;;WAEG;QACM,IAAS,MAAM,4CAAO;QAAtB,IAAS,MAAM,kDAAO;QAE/B;;WAEG;QACO,MAAM,sDAAS;QAEhB,QAAQ;YACf,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;YAC/C,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"ModalActivity.js","sourceRoot":"","sources":["../../../src/core/ModalActivity.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, type TemplateResult } from 'lit'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { Activity } from './Activity.js'\nimport type { UiDialogClosingReason } from '../md/dialog/internals/Dialog.js'\nimport state from '../decorators/state.js'\nimport { IntentResult } from './ActivityManager.js'\n\nimport '../md/dialog/ui-dialog.js'\nimport '../md/button/ui-text-button.js'\n\nexport interface ActionButtonInit {\n /**\n * The label to use for the button.\n */\n label?: string\n /**\n * Whether the button is disabled.\n */\n disabled?: boolean\n}\n\n/**\n * A special kind of activity that renders content in a modal dialog.\n * When a modal activity is running the underlying activities are paused.\n *\n * A modal activity uses the UiDialogElement to render its content. The dialog\n * is inserted directly into the `<body>` element of the document and rendered\n * in the top layer. Because of that, the modal activity does not support\n * regular rendering logic. It creates its own render root that is used to render\n * the template.\n */\nexport abstract class ModalActivity extends Activity {\n /**\n * The list of classes to apply to the dialog.\n */\n protected dialogClasses: Record<string, boolean> = {}\n /**\n * Controls dialog visibility without controlling the activity state.\n */\n @state() accessor opened = true\n\n /**\n * The id of the form used to render the dialog.\n */\n protected formId?: string\n\n override onResume(): void | Promise<void> {\n this.renderRoot = document.createElement('div')\n this.renderRoot.classList.add('modal-activity-container')\n document.body.appendChild(this.renderRoot)\n super.onResume()\n this.requestUpdate()\n }\n\n override async finish(): Promise<void> {\n if (this.renderRoot) {\n document.body.removeChild(this.renderRoot)\n this.renderRoot = undefined\n }\n await super.finish()\n }\n\n protected handleDialogClosed(e: CustomEvent<UiDialogClosingReason>): void {\n const { cancelled, value } = e.detail\n if (cancelled) {\n this.handleNegativeAction(value)\n } else {\n this.handlePositiveAction(value)\n }\n }\n\n /**\n * Called when the dialog is closed with a negative action.\n * Override this function to handle the negative action.\n * @param value The value passed to the dialog when it is closed.\n */\n protected handleNegativeAction(value: unknown): void {\n this.setResult(IntentResult.RESULT_CANCELED, value)\n this.finish()\n }\n\n /**\n * Called when the dialog is closed with a positive action.\n * Override this function to handle the positive action.\n * @param value The value passed to the dialog when it is closed.\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected handlePositiveAction(value: unknown): void {\n this.finish()\n }\n\n /**\n * Override this method to handle the form submission.\n * @param e The submit event.\n */\n protected handleSubmit(e: SubmitEvent): void {\n e.preventDefault()\n }\n\n /**\n * The function called by the rendered when rendering this dialog.\n * This way, the `render()` function is still used as the primary template provider.\n */\n renderDialog(): TemplateResult {\n const classes = {\n activityDialog: true,\n [this.constructor.name.toLowerCase()]: true,\n ...this.dialogClasses,\n }\n return html`<ui-dialog modal .open=\"${this.opened}\" class=\"${classMap(classes)}\" @close=\"${this.handleDialogClosed}\"\n >${this.render()}</ui-dialog\n >`\n }\n\n /**\n * Used with dialogs that render forms. Override the `handleSubmit` method\n * to handle the form submission.\n * @param content The content to render in the form.\n * @param name Optional form name\n */\n protected renderForm(content: TemplateResult, name?: string): TemplateResult {\n if (!this.formId) {\n this.formId = `form-${this.constructor.name.toLowerCase()}`\n }\n return html`<form\n id=\"${this.formId}\"\n name=\"${ifDefined(name)}\"\n class=\"dialog-content\"\n @submit=\"${this.handleSubmit}\"\n >\n ${content}\n </form>`\n }\n\n /**\n * Renders the cancel button for the dialog.\n * @param label The label to use for the cancel button.\n */\n protected renderNegativeButton(init: ActionButtonInit = {}): TemplateResult {\n const { label = 'Cancel' } = init\n return html`<ui-text-button slot=\"button\" type=\"button\" value=\"dismiss\">${label}</ui-text-button>`\n }\n\n /**\n * Renders the submit button for the dialog.\n * If the formId is set, the button will be a submit button.\n * Otherwise, it will be a regular button.\n * @param label The label to use for the submit button.\n */\n protected renderPositiveButton(init: ActionButtonInit = {}): TemplateResult {\n const { label = 'OK', disabled = false } = init\n const { formId } = this\n const type = formId ? 'submit' : 'button'\n // UI buttons have a proper support for form association.\n return html`<ui-text-button\n slot=\"button\"\n ?disabled=\"${disabled}\"\n type=\"${type}\"\n value=\"confirm\"\n form=\"${ifDefined(formId)}\"\n >${label}</ui-text-button\n >`\n }\n\n /**\n * Renders the title for the dialog.\n * @param title The title to render in the dialog.\n */\n protected renderTitle(title: string): TemplateResult {\n return html`<span slot=\"title\">${title}</span>`\n }\n}\n"]}
|
package/eslint.config.js
CHANGED
package/package.json
CHANGED
package/src/core/Activity.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
2
|
import { nothing, TemplateResult } from 'lit'
|
|
3
|
-
import {
|
|
3
|
+
import { ActivityLifecycle, IntentResult, type Intent } from './ActivityManager.js'
|
|
4
4
|
import { FragmentManager } from './FragmentManager.js'
|
|
5
5
|
import type { Fragment } from './Fragment.js'
|
|
6
6
|
import type { Application, UpdateRequest } from './Application.js'
|
|
@@ -36,7 +36,7 @@ export class Activity extends EventTarget {
|
|
|
36
36
|
*/
|
|
37
37
|
static action?: string
|
|
38
38
|
|
|
39
|
-
public
|
|
39
|
+
public lifecycle: ActivityLifecycle = ActivityLifecycle.Initialized
|
|
40
40
|
protected parent: Application
|
|
41
41
|
/**
|
|
42
42
|
* The fragment manager that manages fragments in this activity.
|
|
@@ -2,13 +2,41 @@ import type { Activity } from './Activity.js'
|
|
|
2
2
|
import type { Application } from './Application.js'
|
|
3
3
|
import { navigateScreen } from './ApplicationRoute.js'
|
|
4
4
|
|
|
5
|
-
export enum
|
|
5
|
+
export enum ActivityLifecycle {
|
|
6
|
+
/**
|
|
7
|
+
* The activity is initialized, but not yet created.
|
|
8
|
+
* This is the initial state of the activity.
|
|
9
|
+
*/
|
|
6
10
|
Initialized,
|
|
11
|
+
/**
|
|
12
|
+
* The activity is created, but not yet started.
|
|
13
|
+
* This is the state after the `onCreate()` method is called.
|
|
14
|
+
*/
|
|
7
15
|
Created,
|
|
16
|
+
/**
|
|
17
|
+
* The activity is started, but not yet resumed.
|
|
18
|
+
* This is the state after the `onStart()` method is called.
|
|
19
|
+
*/
|
|
8
20
|
Started,
|
|
21
|
+
/**
|
|
22
|
+
* The activity is resumed and visible to the user.
|
|
23
|
+
* This is the state after the `onResume()` method is called.
|
|
24
|
+
*/
|
|
9
25
|
Resumed,
|
|
26
|
+
/**
|
|
27
|
+
* The activity is paused, but still visible to the user.
|
|
28
|
+
* This is the state after the `onPause()` method is called.
|
|
29
|
+
*/
|
|
10
30
|
Paused,
|
|
31
|
+
/**
|
|
32
|
+
* The activity is stopped and no longer visible to the user.
|
|
33
|
+
* This is the state after the `onStop()` method is called.
|
|
34
|
+
*/
|
|
11
35
|
Stopped,
|
|
36
|
+
/**
|
|
37
|
+
* The activity is destroyed and no longer exists.
|
|
38
|
+
* This is the state after the `onDestroy()` method is called.
|
|
39
|
+
*/
|
|
12
40
|
Destroyed,
|
|
13
41
|
}
|
|
14
42
|
|
|
@@ -16,12 +44,10 @@ export enum IntentFlags {
|
|
|
16
44
|
/**
|
|
17
45
|
* Marks that the activity should be rendered as a modal.
|
|
18
46
|
*/
|
|
19
|
-
// eslint-disable-next-line @typescript-eslint/prefer-literal-enum-member
|
|
20
47
|
Modal = 1 << 0,
|
|
21
48
|
/**
|
|
22
49
|
* The activity is started for result.
|
|
23
50
|
*/
|
|
24
|
-
// eslint-disable-next-line @typescript-eslint/prefer-literal-enum-member
|
|
25
51
|
ForResult = 1 << 1,
|
|
26
52
|
/**
|
|
27
53
|
* When set, the intent data is passed by reference.
|
|
@@ -29,7 +55,6 @@ export enum IntentFlags {
|
|
|
29
55
|
* This is useful when the data is large and you want to avoid copying it
|
|
30
56
|
* or when you want to share the same data between activities.
|
|
31
57
|
*/
|
|
32
|
-
// eslint-disable-next-line @typescript-eslint/prefer-literal-enum-member
|
|
33
58
|
ByReference = 1 << 2,
|
|
34
59
|
}
|
|
35
60
|
|
|
@@ -178,14 +203,13 @@ export class ActivityManager {
|
|
|
178
203
|
await info.activity.onNewIntent(intent)
|
|
179
204
|
// TODO: Check if the activity is destroyed.
|
|
180
205
|
this.setupRoute(intent)
|
|
181
|
-
// this.currentActivity = info.activity
|
|
182
206
|
await this.updateCurrentActivity(info.activity, false)
|
|
183
207
|
return
|
|
184
208
|
}
|
|
185
209
|
const activity = this.buildActivity(intent)
|
|
186
210
|
if (currentActivity) {
|
|
187
211
|
await currentActivity.onPause()
|
|
188
|
-
currentActivity.
|
|
212
|
+
currentActivity.lifecycle = ActivityLifecycle.Paused
|
|
189
213
|
}
|
|
190
214
|
|
|
191
215
|
const activityId = this.generateActivityId()
|
|
@@ -204,7 +228,7 @@ export class ActivityManager {
|
|
|
204
228
|
// the activity finished and the manager already took care of this situation.
|
|
205
229
|
return
|
|
206
230
|
}
|
|
207
|
-
activity.
|
|
231
|
+
activity.lifecycle = ActivityLifecycle.Created
|
|
208
232
|
|
|
209
233
|
await this.updateCurrentActivity(activity, !!isModal)
|
|
210
234
|
if (this.isDestroyed(activity)) {
|
|
@@ -257,7 +281,7 @@ export class ActivityManager {
|
|
|
257
281
|
}
|
|
258
282
|
|
|
259
283
|
isDestroyed(activity: Activity): boolean {
|
|
260
|
-
return activity.
|
|
284
|
+
return activity.lifecycle === ActivityLifecycle.Destroyed
|
|
261
285
|
}
|
|
262
286
|
|
|
263
287
|
/**
|
|
@@ -272,23 +296,23 @@ export class ActivityManager {
|
|
|
272
296
|
const stackEntry = stack.splice(index, 1)[0]
|
|
273
297
|
|
|
274
298
|
await stackEntry.activity.onPause()
|
|
275
|
-
stackEntry.activity.
|
|
299
|
+
stackEntry.activity.lifecycle = ActivityLifecycle.Paused
|
|
276
300
|
await stackEntry.activity.onStop()
|
|
277
|
-
stackEntry.activity.
|
|
301
|
+
stackEntry.activity.lifecycle = ActivityLifecycle.Stopped
|
|
278
302
|
await stackEntry.activity.onDestroy()
|
|
279
|
-
stackEntry.activity.
|
|
303
|
+
stackEntry.activity.lifecycle = ActivityLifecycle.Destroyed
|
|
280
304
|
|
|
281
305
|
await this.manageActivityResult(stackEntry.activity, stackEntry.intent)
|
|
282
306
|
|
|
283
307
|
// Resume the previous activity
|
|
284
308
|
await this.bringLastActivityToFront()
|
|
285
309
|
} else {
|
|
286
|
-
if (activity.
|
|
310
|
+
if (activity.lifecycle === ActivityLifecycle.Created) {
|
|
287
311
|
await activity.onStop()
|
|
288
|
-
activity.
|
|
312
|
+
activity.lifecycle = ActivityLifecycle.Stopped
|
|
289
313
|
}
|
|
290
314
|
await activity.onDestroy()
|
|
291
|
-
activity.
|
|
315
|
+
activity.lifecycle = ActivityLifecycle.Destroyed
|
|
292
316
|
// This can happen when an activity finishes in one of the callback methods,
|
|
293
317
|
// before it is added to the stack. In that case, we bring the last activity back to the front.
|
|
294
318
|
await this.bringLastActivityToFront()
|
|
@@ -302,12 +326,12 @@ export class ActivityManager {
|
|
|
302
326
|
const all = [...this.activityStack, ...this.modalActivityStack]
|
|
303
327
|
const target = all.find((entry) => entry.activity.hasRequestCode(requestCode))
|
|
304
328
|
if (target) {
|
|
305
|
-
if (target.activity.
|
|
329
|
+
if (target.activity.lifecycle === ActivityLifecycle.Destroyed) {
|
|
306
330
|
return
|
|
307
331
|
}
|
|
308
|
-
if (target.activity.
|
|
332
|
+
if (target.activity.lifecycle === ActivityLifecycle.Resumed) {
|
|
309
333
|
await target.activity.onPause()
|
|
310
|
-
target.activity.
|
|
334
|
+
target.activity.lifecycle = ActivityLifecycle.Paused
|
|
311
335
|
}
|
|
312
336
|
const intentCopy = structuredClone(intent)
|
|
313
337
|
intentCopy.data = activity.getResult()
|
|
@@ -329,11 +353,11 @@ export class ActivityManager {
|
|
|
329
353
|
}
|
|
330
354
|
|
|
331
355
|
getTopActivity(): Activity | undefined {
|
|
332
|
-
const topModal = this.modalActivityStack.findLast((a) => a.activity.
|
|
356
|
+
const topModal = this.modalActivityStack.findLast((a) => a.activity.lifecycle === ActivityLifecycle.Resumed)
|
|
333
357
|
if (topModal) {
|
|
334
358
|
return topModal.activity
|
|
335
359
|
}
|
|
336
|
-
const top = this.activityStack.findLast((a) => a.activity.
|
|
360
|
+
const top = this.activityStack.findLast((a) => a.activity.lifecycle === ActivityLifecycle.Resumed)
|
|
337
361
|
return top ? top.activity : undefined
|
|
338
362
|
}
|
|
339
363
|
|
|
@@ -385,48 +409,48 @@ export class ActivityManager {
|
|
|
385
409
|
if (
|
|
386
410
|
this.currentActivity &&
|
|
387
411
|
this.currentActivity !== activity &&
|
|
388
|
-
this.currentActivity.
|
|
412
|
+
this.currentActivity.lifecycle !== ActivityLifecycle.Destroyed &&
|
|
389
413
|
// Make sure we don't pause the current activity if it's already paused.
|
|
390
|
-
this.currentActivity.
|
|
414
|
+
this.currentActivity.lifecycle !== ActivityLifecycle.Paused
|
|
391
415
|
) {
|
|
392
416
|
await this.currentActivity.onPause()
|
|
393
|
-
this.currentActivity.
|
|
417
|
+
this.currentActivity.lifecycle = ActivityLifecycle.Paused
|
|
394
418
|
}
|
|
395
|
-
if (activity.
|
|
419
|
+
if (activity.lifecycle === ActivityLifecycle.Paused) {
|
|
396
420
|
await activity.onResume()
|
|
397
421
|
if (this.isDestroyed(activity)) {
|
|
398
422
|
return
|
|
399
423
|
}
|
|
400
|
-
activity.
|
|
424
|
+
activity.lifecycle = ActivityLifecycle.Resumed
|
|
401
425
|
activity.requestUpdate()
|
|
402
|
-
} else if (activity.
|
|
426
|
+
} else if (activity.lifecycle === ActivityLifecycle.Stopped) {
|
|
403
427
|
await activity.onRestart()
|
|
404
|
-
activity.
|
|
405
|
-
} else if (activity.
|
|
428
|
+
activity.lifecycle = ActivityLifecycle.Resumed
|
|
429
|
+
} else if (activity.lifecycle === ActivityLifecycle.Destroyed) {
|
|
406
430
|
throw new Error(`Invalid state. The activity is already destroyed.`)
|
|
407
|
-
} else if (activity.
|
|
431
|
+
} else if (activity.lifecycle === ActivityLifecycle.Created) {
|
|
408
432
|
await activity.onStart()
|
|
409
433
|
if (this.isDestroyed(activity)) {
|
|
410
434
|
return
|
|
411
435
|
}
|
|
412
|
-
activity.
|
|
436
|
+
activity.lifecycle = ActivityLifecycle.Started
|
|
413
437
|
await activity.onResume()
|
|
414
438
|
if (this.isDestroyed(activity)) {
|
|
415
439
|
return
|
|
416
440
|
}
|
|
417
|
-
activity.
|
|
441
|
+
activity.lifecycle = ActivityLifecycle.Resumed
|
|
418
442
|
activity.requestUpdate()
|
|
419
|
-
} else if (activity.
|
|
443
|
+
} else if (activity.lifecycle === ActivityLifecycle.Started) {
|
|
420
444
|
await activity.onResume()
|
|
421
445
|
if (this.isDestroyed(activity)) {
|
|
422
446
|
return
|
|
423
447
|
}
|
|
424
|
-
activity.
|
|
448
|
+
activity.lifecycle = ActivityLifecycle.Resumed
|
|
425
449
|
activity.requestUpdate()
|
|
426
|
-
} else if (activity.
|
|
450
|
+
} else if (activity.lifecycle === ActivityLifecycle.Initialized) {
|
|
427
451
|
// TODO: Figure out intent passing here.
|
|
428
452
|
await activity.onCreate()
|
|
429
|
-
activity.
|
|
453
|
+
activity.lifecycle = ActivityLifecycle.Created
|
|
430
454
|
if (this.isDestroyed(activity)) {
|
|
431
455
|
// the activity finished and the manager already took care of this situation.
|
|
432
456
|
return
|
|
@@ -435,12 +459,12 @@ export class ActivityManager {
|
|
|
435
459
|
if (this.isDestroyed(activity)) {
|
|
436
460
|
return
|
|
437
461
|
}
|
|
438
|
-
activity.
|
|
462
|
+
activity.lifecycle = ActivityLifecycle.Started
|
|
439
463
|
await activity.onResume()
|
|
440
464
|
if (this.isDestroyed(activity)) {
|
|
441
465
|
return
|
|
442
466
|
}
|
|
443
|
-
activity.
|
|
467
|
+
activity.lifecycle = ActivityLifecycle.Resumed
|
|
444
468
|
activity.requestUpdate()
|
|
445
469
|
}
|
|
446
470
|
if (!isModal) {
|
package/src/core/Application.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { nothing, type TemplateResult } from 'lit'
|
|
2
|
-
import { ActivityManager,
|
|
2
|
+
import { ActivityManager, ActivityLifecycle } from './ActivityManager.js'
|
|
3
3
|
import type { Activity } from './Activity.js'
|
|
4
4
|
import { ApplicationRenderer } from './renderer/ApplicationRenderer.js'
|
|
5
5
|
import { ThemeManager } from './ThemeManager.js'
|
|
@@ -159,7 +159,7 @@ export abstract class Application extends EventTarget {
|
|
|
159
159
|
render(): TemplateResult | typeof nothing {
|
|
160
160
|
const currentActivity = this.#activities.getCurrentActivity()
|
|
161
161
|
// Only render if started or beyond
|
|
162
|
-
if (currentActivity && currentActivity.
|
|
162
|
+
if (currentActivity && currentActivity.lifecycle >= ActivityLifecycle.Started) {
|
|
163
163
|
return currentActivity.render()
|
|
164
164
|
}
|
|
165
165
|
return nothing
|
|
@@ -47,7 +47,7 @@ export abstract class ModalActivity extends Activity {
|
|
|
47
47
|
|
|
48
48
|
override onResume(): void | Promise<void> {
|
|
49
49
|
this.renderRoot = document.createElement('div')
|
|
50
|
-
this.renderRoot.classList.add('modal-
|
|
50
|
+
this.renderRoot.classList.add('modal-activity-container')
|
|
51
51
|
document.body.appendChild(this.renderRoot)
|
|
52
52
|
super.onResume()
|
|
53
53
|
this.requestUpdate()
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { assert } from '@esm-bundle/chai'
|
|
2
2
|
import { Activity } from '../../src/core/Activity.js'
|
|
3
3
|
import { Application } from '../../src/core/Application.js'
|
|
4
|
-
import { IntentResult,
|
|
4
|
+
import { IntentResult, ActivityLifecycle } from '../../src/core/ActivityManager.js'
|
|
5
5
|
import { fixture, html } from '@open-wc/testing'
|
|
6
6
|
import { EventTypes } from '../../src/events/EventTypes.js'
|
|
7
7
|
import sinon from 'sinon'
|
|
@@ -102,7 +102,7 @@ describe('Activity Lifecycle and Events', () => {
|
|
|
102
102
|
})
|
|
103
103
|
|
|
104
104
|
it('sets the default state', async () => {
|
|
105
|
-
assert.equal(activity.
|
|
105
|
+
assert.equal(activity.lifecycle, ActivityLifecycle.Initialized)
|
|
106
106
|
})
|
|
107
107
|
|
|
108
108
|
it('sets the default resultCode', async () => {
|
|
@@ -5,7 +5,7 @@ import { Activity } from '../../src/core/Activity.js'
|
|
|
5
5
|
import { Application } from '../../src/core/Application.js'
|
|
6
6
|
import {
|
|
7
7
|
ActivityManager,
|
|
8
|
-
|
|
8
|
+
ActivityLifecycle,
|
|
9
9
|
IntentFlags,
|
|
10
10
|
IntentResult,
|
|
11
11
|
type Intent,
|
|
@@ -41,7 +41,7 @@ class TestActivity extends Activity {
|
|
|
41
41
|
this.setResult.resetHistory()
|
|
42
42
|
this.getResult.resetHistory()
|
|
43
43
|
this.hasRequestCode.resetHistory()
|
|
44
|
-
this.
|
|
44
|
+
this.lifecycle = ActivityLifecycle.Initialized
|
|
45
45
|
this.pendingRequestCodes.length = 0
|
|
46
46
|
this.exitCode = IntentResult.RESULT_CANCELED
|
|
47
47
|
this.resultData = undefined
|
|
@@ -114,7 +114,7 @@ describe('ActivityManager', () => {
|
|
|
114
114
|
assert.equal(manager['activityStack'].length, 1)
|
|
115
115
|
const entry = manager['activityStack'][0]
|
|
116
116
|
assert.instanceOf(entry.activity, TestActivity)
|
|
117
|
-
assert.equal(entry.activity.
|
|
117
|
+
assert.equal(entry.activity.lifecycle, ActivityLifecycle.Initialized)
|
|
118
118
|
assert.strictEqual(entry.intent, intent)
|
|
119
119
|
assert.isUndefined(manager.getCurrentActivity())
|
|
120
120
|
})
|
|
@@ -142,7 +142,7 @@ describe('ActivityManager', () => {
|
|
|
142
142
|
assert.isTrue((entry.activity as TestActivity).onCreate.calledOnceWith(intent))
|
|
143
143
|
assert.isTrue((entry.activity as TestActivity).onStart.calledOnce)
|
|
144
144
|
assert.isTrue((entry.activity as TestActivity).onResume.calledOnce)
|
|
145
|
-
assert.equal(entry.activity.
|
|
145
|
+
assert.equal(entry.activity.lifecycle, ActivityLifecycle.Resumed)
|
|
146
146
|
// assert.isFalse(navigateScreenStub.called) // No URI in intent
|
|
147
147
|
})
|
|
148
148
|
|
|
@@ -162,12 +162,12 @@ describe('ActivityManager', () => {
|
|
|
162
162
|
await manager.startActivity(intent2)
|
|
163
163
|
const activity2 = manager.getCurrentActivity() as TestActivity
|
|
164
164
|
assert.isTrue(activity1.onPause.calledOnce, 'activity1 onPause should be called once')
|
|
165
|
-
assert.equal(activity1.
|
|
165
|
+
assert.equal(activity1.lifecycle, ActivityLifecycle.Paused, 'activity1 should be paused')
|
|
166
166
|
|
|
167
167
|
assert.isTrue(activity2.onCreate.calledOnceWith(intent2), 'activity2 onCreate should be called with intent')
|
|
168
168
|
assert.isTrue(activity2.onStart.calledOnce, 'activity2 onStart should be called once')
|
|
169
169
|
assert.isTrue(activity2.onResume.calledOnce, 'activity2 onResume should be called once')
|
|
170
|
-
assert.equal(activity2.
|
|
170
|
+
assert.equal(activity2.lifecycle, ActivityLifecycle.Resumed, 'activity2 should be resumed')
|
|
171
171
|
assert.equal(manager['activityStack'].length, 2, 'activity stack should have 2 activities')
|
|
172
172
|
})
|
|
173
173
|
|
|
@@ -182,8 +182,8 @@ describe('ActivityManager', () => {
|
|
|
182
182
|
const activity2 = manager.getCurrentActivity() as TestActivity
|
|
183
183
|
|
|
184
184
|
// activity1 is now paused, activity2 is resumed
|
|
185
|
-
assert.equal(activity1.
|
|
186
|
-
assert.equal(activity2.
|
|
185
|
+
assert.equal(activity1.lifecycle, ActivityLifecycle.Paused, 'activity1 should be paused')
|
|
186
|
+
assert.equal(activity2.lifecycle, ActivityLifecycle.Resumed, 'activity2 should be resumed')
|
|
187
187
|
|
|
188
188
|
const newIntentForActivity1: Intent = { action: TestActivity.action, data: { updated: true } }
|
|
189
189
|
await manager.startActivity(newIntentForActivity1)
|
|
@@ -191,10 +191,10 @@ describe('ActivityManager', () => {
|
|
|
191
191
|
assert.strictEqual(manager.getCurrentActivity(), activity1)
|
|
192
192
|
assert.isTrue(activity1.onNewIntent.calledOnceWith(newIntentForActivity1), 'activity1 called with new intent')
|
|
193
193
|
assert.isTrue(activity1.onResume.calledOnce, 'activity1 onResume called once') // Should be resumed
|
|
194
|
-
assert.equal(activity1.
|
|
194
|
+
assert.equal(activity1.lifecycle, ActivityLifecycle.Resumed, 'activity1 should be resumed')
|
|
195
195
|
|
|
196
196
|
assert.isTrue(activity2.onPause.calledOnce, 'activity2 paused once') // activity2 should be paused
|
|
197
|
-
assert.equal(activity2.
|
|
197
|
+
assert.equal(activity2.lifecycle, ActivityLifecycle.Paused, 'activity2 should be paused')
|
|
198
198
|
|
|
199
199
|
assert.equal(manager['activityStack'].length, 2, 'activityStack is the same') // Stack size remains the same
|
|
200
200
|
assert.strictEqual(manager['activityStack'][1].activity, activity1) // activity1 is now at the top
|
|
@@ -214,14 +214,14 @@ describe('ActivityManager', () => {
|
|
|
214
214
|
assert.strictEqual(manager['modalActivityStack'][0].activity, modalActivity)
|
|
215
215
|
|
|
216
216
|
assert.isTrue(activity1.onPause.calledOnce)
|
|
217
|
-
assert.equal(activity1.
|
|
217
|
+
assert.equal(activity1.lifecycle, ActivityLifecycle.Paused)
|
|
218
218
|
// For modal, currentActivity in manager should still be the underlying one
|
|
219
219
|
assert.strictEqual(manager.getCurrentActivity(), activity1)
|
|
220
220
|
|
|
221
221
|
assert.isTrue(modalActivity.onCreate.calledOnceWith(modalIntent))
|
|
222
222
|
assert.isTrue(modalActivity.onStart.calledOnce)
|
|
223
223
|
assert.isTrue(modalActivity.onResume.calledOnce)
|
|
224
|
-
assert.equal(modalActivity.
|
|
224
|
+
assert.equal(modalActivity.lifecycle, ActivityLifecycle.Resumed)
|
|
225
225
|
})
|
|
226
226
|
|
|
227
227
|
it('throws if activity class is not registered', async () => {
|
|
@@ -301,11 +301,11 @@ describe('ActivityManager', () => {
|
|
|
301
301
|
assert.isTrue(activity2.onPause.calledOnce, 'activity2 onPause should be called once')
|
|
302
302
|
assert.isTrue(activity2.onStop.calledOnce, 'activity2 onStop should be called once')
|
|
303
303
|
assert.isTrue(activity2.onDestroy.calledOnce, 'activity2 onDestroy should be called once')
|
|
304
|
-
assert.equal(activity2.
|
|
304
|
+
assert.equal(activity2.lifecycle, ActivityLifecycle.Destroyed, 'activity2 should be destroyed')
|
|
305
305
|
|
|
306
306
|
assert.strictEqual(manager.getCurrentActivity(), activity1)
|
|
307
307
|
assert.isTrue(activity1.onResume.calledOnce, 'activity1 onResume should be called once')
|
|
308
|
-
assert.equal(activity1.
|
|
308
|
+
assert.equal(activity1.lifecycle, ActivityLifecycle.Resumed, 'activity1 should be resumed')
|
|
309
309
|
assert.equal(manager['activityStack'].length, 1, 'activity stack should have 1 activity')
|
|
310
310
|
assert.isTrue(app.requestUpdateSpy.called, 'Application should request update after finishing activity')
|
|
311
311
|
})
|
|
@@ -325,12 +325,12 @@ describe('ActivityManager', () => {
|
|
|
325
325
|
assert.isTrue(modalActivity.onPause.calledOnce)
|
|
326
326
|
assert.isTrue(modalActivity.onStop.calledOnce)
|
|
327
327
|
assert.isTrue(modalActivity.onDestroy.calledOnce)
|
|
328
|
-
assert.equal(modalActivity.
|
|
328
|
+
assert.equal(modalActivity.lifecycle, ActivityLifecycle.Destroyed)
|
|
329
329
|
assert.equal(manager['modalActivityStack'].length, 0)
|
|
330
330
|
|
|
331
331
|
assert.strictEqual(manager.getCurrentActivity(), activity1) // Current activity should be the underlying one
|
|
332
332
|
assert.isTrue(activity1.onResume.calledOnce)
|
|
333
|
-
assert.equal(activity1.
|
|
333
|
+
assert.equal(activity1.lifecycle, ActivityLifecycle.Resumed)
|
|
334
334
|
assert.equal(manager['activityStack'].length, 1)
|
|
335
335
|
})
|
|
336
336
|
|
|
@@ -362,13 +362,13 @@ describe('ActivityManager', () => {
|
|
|
362
362
|
|
|
363
363
|
it('handles finishing an activity that was only created (not fully started)', async () => {
|
|
364
364
|
const activity = new TestActivity(app)
|
|
365
|
-
activity.
|
|
365
|
+
activity.lifecycle = ActivityLifecycle.Created // Manually set for test
|
|
366
366
|
|
|
367
367
|
await manager.finishActivity(activity)
|
|
368
368
|
|
|
369
369
|
assert.isTrue(activity.onStop.calledOnce, 'onStop should be called for created activity')
|
|
370
370
|
assert.isTrue(activity.onDestroy.calledOnce, 'onDestroy should be called')
|
|
371
|
-
assert.equal(activity.
|
|
371
|
+
assert.equal(activity.lifecycle, ActivityLifecycle.Destroyed)
|
|
372
372
|
assert.isUndefined(manager.getCurrentActivity()) // Assuming no other activities
|
|
373
373
|
})
|
|
374
374
|
|
|
@@ -380,7 +380,7 @@ describe('ActivityManager', () => {
|
|
|
380
380
|
await manager.finishActivity(activity1)
|
|
381
381
|
|
|
382
382
|
assert.isTrue(activity1.onDestroy.calledOnce)
|
|
383
|
-
assert.equal(activity1.
|
|
383
|
+
assert.equal(activity1.lifecycle, ActivityLifecycle.Destroyed)
|
|
384
384
|
assert.isUndefined(manager.getCurrentActivity())
|
|
385
385
|
assert.equal(manager['activityStack'].length, 0)
|
|
386
386
|
})
|
|
@@ -394,11 +394,11 @@ describe('ActivityManager', () => {
|
|
|
394
394
|
it('returns the top resumed regular activity', async () => {
|
|
395
395
|
await manager.startActivity({ action: TestActivity.action })
|
|
396
396
|
const activity1 = manager['activityStack'][0].activity
|
|
397
|
-
activity1.
|
|
397
|
+
activity1.lifecycle = ActivityLifecycle.Resumed // Ensure it's resumed
|
|
398
398
|
|
|
399
399
|
await manager.startActivity({ action: TestActivity2.action })
|
|
400
400
|
const activity2 = manager['activityStack'][1].activity
|
|
401
|
-
activity2.
|
|
401
|
+
activity2.lifecycle = ActivityLifecycle.Resumed // Ensure it's resumed
|
|
402
402
|
|
|
403
403
|
assert.strictEqual(manager.getTopActivity(), activity2)
|
|
404
404
|
})
|
|
@@ -406,11 +406,11 @@ describe('ActivityManager', () => {
|
|
|
406
406
|
it('returns the top resumed modal activity if present', async () => {
|
|
407
407
|
await manager.startActivity({ action: TestActivity.action }) // Regular activity
|
|
408
408
|
const regularActivity = manager['activityStack'][0].activity
|
|
409
|
-
regularActivity.
|
|
409
|
+
regularActivity.lifecycle = ActivityLifecycle.Resumed
|
|
410
410
|
|
|
411
411
|
await manager.startActivity({ action: TestActivity2.action, flags: IntentFlags.Modal })
|
|
412
412
|
const modalActivity = manager['modalActivityStack'][0].activity
|
|
413
|
-
modalActivity.
|
|
413
|
+
modalActivity.lifecycle = ActivityLifecycle.Resumed // Ensure it's resumed
|
|
414
414
|
|
|
415
415
|
assert.strictEqual(manager.getTopActivity(), modalActivity)
|
|
416
416
|
})
|
|
@@ -421,8 +421,8 @@ describe('ActivityManager', () => {
|
|
|
421
421
|
|
|
422
422
|
await manager.startActivity({ action: TestActivity2.action, flags: IntentFlags.Modal })
|
|
423
423
|
const modalActivity = manager['modalActivityStack'][0].activity
|
|
424
|
-
modalActivity.
|
|
425
|
-
regularActivity.
|
|
424
|
+
modalActivity.lifecycle = ActivityLifecycle.Paused // Not resumed
|
|
425
|
+
regularActivity.lifecycle = ActivityLifecycle.Resumed
|
|
426
426
|
assert.strictEqual(manager.getTopActivity(), regularActivity)
|
|
427
427
|
})
|
|
428
428
|
})
|
|
@@ -3,7 +3,7 @@ import sinon from 'sinon'
|
|
|
3
3
|
import { fixture, html } from '@open-wc/testing'
|
|
4
4
|
import { Application, type UpdateRequest } from '../../src/core/Application.js'
|
|
5
5
|
import { Activity } from '../../src/core/Activity.js'
|
|
6
|
-
import { ActivityManager,
|
|
6
|
+
import { ActivityManager, ActivityLifecycle } from '../../src/core/ActivityManager.js'
|
|
7
7
|
import { ApplicationRenderer } from '../../src/core/renderer/ApplicationRenderer.js'
|
|
8
8
|
import { ThemeManager } from '../../src/core/ThemeManager.js'
|
|
9
9
|
import { nothing } from 'lit'
|
|
@@ -136,12 +136,12 @@ describe('Application', () => {
|
|
|
136
136
|
await app.run() // This calls onStart which registers TestActivity
|
|
137
137
|
await app.manager.startActivity({ action: TestActivity.action })
|
|
138
138
|
const activity = app.getCurrentActivity() as TestActivity
|
|
139
|
-
activity.
|
|
139
|
+
activity.lifecycle = ActivityLifecycle.Started // Ensure state
|
|
140
140
|
|
|
141
141
|
app.render()
|
|
142
142
|
assert.isTrue(activity.renderSpy.calledOnce)
|
|
143
143
|
|
|
144
|
-
activity.
|
|
144
|
+
activity.lifecycle = ActivityLifecycle.Resumed // Ensure state
|
|
145
145
|
activity.renderSpy.resetHistory()
|
|
146
146
|
app.render()
|
|
147
147
|
assert.isTrue(activity.renderSpy.calledOnce)
|