@api-client/ui 0.6.4 → 0.6.6
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/build/src/core/Activity.d.ts +21 -34
- package/build/src/core/Activity.d.ts.map +1 -1
- package/build/src/core/Activity.js +20 -56
- package/build/src/core/Activity.js.map +1 -1
- package/build/src/core/ActivityManager.d.ts +42 -7
- package/build/src/core/ActivityManager.d.ts.map +1 -1
- package/build/src/core/ActivityManager.js +56 -48
- package/build/src/core/ActivityManager.js.map +1 -1
- package/build/src/core/Fragment.d.ts +13 -28
- package/build/src/core/Fragment.d.ts.map +1 -1
- package/build/src/core/Fragment.js +15 -56
- package/build/src/core/Fragment.js.map +1 -1
- package/build/src/core/FragmentManager.d.ts +0 -6
- package/build/src/core/FragmentManager.d.ts.map +1 -1
- package/build/src/core/FragmentManager.js +0 -13
- package/build/src/core/FragmentManager.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/core/Activity.ts +30 -65
- package/src/core/ActivityManager.ts +84 -49
- package/src/core/Fragment.ts +17 -66
- package/src/core/FragmentManager.ts +0 -14
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 { ActivityLifecycle, IntentResult, type Intent } from './ActivityManager.js'
|
|
3
|
+
import { ActivityLifecycle, IntentResult, type Intent, type ResolvedIntent } 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'
|
|
@@ -8,6 +8,13 @@ import { bound } from '../decorators/bound.js'
|
|
|
8
8
|
import type { ActivityDetail, ActivityWithResultDetail } from '../events/IntentEvents.js'
|
|
9
9
|
import { EventTypes } from '../events/EventTypes.js'
|
|
10
10
|
|
|
11
|
+
export interface ActivityResult {
|
|
12
|
+
requestCode: number
|
|
13
|
+
resultCode: IntentResult
|
|
14
|
+
data?: unknown
|
|
15
|
+
intent: Intent
|
|
16
|
+
}
|
|
17
|
+
|
|
11
18
|
/**
|
|
12
19
|
* ## Activity
|
|
13
20
|
*
|
|
@@ -84,9 +91,6 @@ export class Activity extends EventTarget {
|
|
|
84
91
|
return this.exitCode
|
|
85
92
|
}
|
|
86
93
|
|
|
87
|
-
/** Tracks pending request codes for activities started for result. */
|
|
88
|
-
protected pendingRequestCodes: number[] = []
|
|
89
|
-
|
|
90
94
|
/**
|
|
91
95
|
* Constructs a new Activity.
|
|
92
96
|
* @param parent The parent application instance.
|
|
@@ -97,6 +101,14 @@ export class Activity extends EventTarget {
|
|
|
97
101
|
this.manager = new FragmentManager(this)
|
|
98
102
|
}
|
|
99
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Returns the current activity instance.
|
|
106
|
+
* @returns This activity.
|
|
107
|
+
*/
|
|
108
|
+
getActivity(): Activity {
|
|
109
|
+
return this
|
|
110
|
+
}
|
|
111
|
+
|
|
100
112
|
/**
|
|
101
113
|
* Checks if the activity is in the `Destroyed` state.
|
|
102
114
|
* @returns `true` if destroyed, `false` otherwise.
|
|
@@ -282,25 +294,28 @@ export class Activity extends EventTarget {
|
|
|
282
294
|
* await this.startActivity({ action: 'login' });
|
|
283
295
|
* ```
|
|
284
296
|
*/
|
|
285
|
-
startActivity(intent: Intent): Promise<
|
|
286
|
-
|
|
297
|
+
async startActivity(intent: Intent): Promise<Activity> {
|
|
298
|
+
const { manager } = this.getApplication()
|
|
299
|
+
return manager.startActivity(intent)
|
|
287
300
|
}
|
|
288
301
|
|
|
289
302
|
/**
|
|
290
303
|
* Starts a new activity for a result.
|
|
304
|
+
* @template T The type of the result data expected.
|
|
291
305
|
* @param intent The intent to start.
|
|
292
|
-
* @returns
|
|
306
|
+
* @returns A promise that resolves when the started activity finishes, returning the result Intent with
|
|
307
|
+
* data of type T.
|
|
293
308
|
* @example
|
|
294
309
|
* ```typescript
|
|
295
|
-
* const
|
|
310
|
+
* const resultIntent = await this.startActivityForResult<{ userId: string }>({ action: 'pickUser' });
|
|
311
|
+
* if (resultIntent.resultCode === IntentResult.RESULT_OK) {
|
|
312
|
+
* console.log(resultIntent.data?.userId);
|
|
313
|
+
* }
|
|
296
314
|
* ```
|
|
297
315
|
*/
|
|
298
|
-
async startActivityForResult(intent: Intent): Promise<
|
|
316
|
+
async startActivityForResult<T>(intent: Intent): Promise<ResolvedIntent<T | undefined>> {
|
|
299
317
|
const { manager } = this.getApplication()
|
|
300
|
-
|
|
301
|
-
this.pendingRequestCodes.push(code)
|
|
302
|
-
await manager.startActivityForResult(intent, code)
|
|
303
|
-
return code
|
|
318
|
+
return manager.startActivityForResult(intent)
|
|
304
319
|
}
|
|
305
320
|
|
|
306
321
|
/**
|
|
@@ -317,57 +332,6 @@ export class Activity extends EventTarget {
|
|
|
317
332
|
this.resultData = data
|
|
318
333
|
}
|
|
319
334
|
|
|
320
|
-
/**
|
|
321
|
-
* Called when an activity you launched exits, giving you the request code, result code, and intent.
|
|
322
|
-
* Override to handle results from started activities.
|
|
323
|
-
* @param requestCode The request code.
|
|
324
|
-
* @param resultCode The result code.
|
|
325
|
-
* @param intent The intent that was used to start the activity.
|
|
326
|
-
* @example
|
|
327
|
-
* ```typescript
|
|
328
|
-
* async onActivityResult(requestCode, resultCode, intent) {
|
|
329
|
-
* if (resultCode === IntentResult.RESULT_OK) {
|
|
330
|
-
* // handle result
|
|
331
|
-
* }
|
|
332
|
-
* }
|
|
333
|
-
* ```
|
|
334
|
-
*/
|
|
335
|
-
async onActivityResult(requestCode: number, resultCode: IntentResult, intent: Intent): Promise<void> {
|
|
336
|
-
const index = this.pendingRequestCodes.indexOf(requestCode)
|
|
337
|
-
if (index !== -1) {
|
|
338
|
-
this.pendingRequestCodes.splice(index, 1)
|
|
339
|
-
}
|
|
340
|
-
// First we check whether any of the fragments has the code.
|
|
341
|
-
const fragment = this.manager.findByRequestCode(requestCode)
|
|
342
|
-
if (fragment) {
|
|
343
|
-
return fragment.onActivityResult(requestCode, resultCode, intent)
|
|
344
|
-
}
|
|
345
|
-
if (this.constructor === Activity) {
|
|
346
|
-
// eslint-disable-next-line no-console
|
|
347
|
-
console.info(
|
|
348
|
-
`Activity#onActivityResult not implemented. Request code: ${requestCode}, result code: ${resultCode}`,
|
|
349
|
-
intent
|
|
350
|
-
)
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
* Returns the current activity instance.
|
|
356
|
-
* @returns This activity.
|
|
357
|
-
*/
|
|
358
|
-
getActivity(): Activity {
|
|
359
|
-
return this
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* Checks if this activity initiated the activity for result with the given code.
|
|
364
|
-
* @param code The request code.
|
|
365
|
-
* @returns `true` if the code is pending, `false` otherwise.
|
|
366
|
-
*/
|
|
367
|
-
hasRequestCode(code: number): boolean {
|
|
368
|
-
return this.pendingRequestCodes.includes(code)
|
|
369
|
-
}
|
|
370
|
-
|
|
371
335
|
/**
|
|
372
336
|
* Gets the result data set by `setResult`.
|
|
373
337
|
* @returns The result data or `undefined`.
|
|
@@ -392,7 +356,8 @@ export class Activity extends EventTarget {
|
|
|
392
356
|
async handleIntentEvent(event: CustomEvent<ActivityDetail | ActivityWithResultDetail>): Promise<void> {
|
|
393
357
|
if (event.type === EventTypes.Intent.startActivityForResult) {
|
|
394
358
|
const info = event.detail as ActivityWithResultDetail
|
|
395
|
-
await this.startActivityForResult(info.intent)
|
|
359
|
+
const result = await this.startActivityForResult(info.intent)
|
|
360
|
+
info.onResult(result.result, result)
|
|
396
361
|
} else if (event.type === EventTypes.Intent.startActivity) {
|
|
397
362
|
await this.startActivity(event.detail.intent)
|
|
398
363
|
} else {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Activity } from './Activity.js'
|
|
2
2
|
import type { Application } from './Application.js'
|
|
3
|
-
import { navigateScreen } from './ApplicationRoute.js'
|
|
3
|
+
// import { navigateScreen } from './ApplicationRoute.js'
|
|
4
4
|
|
|
5
5
|
export enum ActivityLifecycle {
|
|
6
6
|
/**
|
|
@@ -59,9 +59,22 @@ export enum IntentFlags {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
export interface Intent<T = unknown> {
|
|
62
|
+
/**
|
|
63
|
+
* The action name the activity is registered for.
|
|
64
|
+
*/
|
|
62
65
|
action: string
|
|
66
|
+
/**
|
|
67
|
+
* The data passed to the activity.
|
|
68
|
+
*/
|
|
63
69
|
data?: T
|
|
70
|
+
/**
|
|
71
|
+
* The category of the activity.
|
|
72
|
+
* Optional and currently not used.
|
|
73
|
+
*/
|
|
64
74
|
category?: string[]
|
|
75
|
+
/**
|
|
76
|
+
* The flags that control the behavior of the activity.
|
|
77
|
+
*/
|
|
65
78
|
flags?: number
|
|
66
79
|
/**
|
|
67
80
|
* The request code used to distinguish between different activities.
|
|
@@ -69,6 +82,17 @@ export interface Intent<T = unknown> {
|
|
|
69
82
|
requestCode?: number
|
|
70
83
|
}
|
|
71
84
|
|
|
85
|
+
/**
|
|
86
|
+
* An intent returned by an activity after the activity result is ready.
|
|
87
|
+
* This object is only created when the activity is started with the `ForResult` flag.
|
|
88
|
+
*/
|
|
89
|
+
export interface ResolvedIntent<T = unknown> extends Intent<T> {
|
|
90
|
+
/**
|
|
91
|
+
* The result code returned by the activity.
|
|
92
|
+
*/
|
|
93
|
+
result: IntentResult
|
|
94
|
+
}
|
|
95
|
+
|
|
72
96
|
export enum IntentResult {
|
|
73
97
|
RESULT_CANCELED,
|
|
74
98
|
RESULT_OK,
|
|
@@ -134,6 +158,11 @@ export class ActivityManager {
|
|
|
134
158
|
*/
|
|
135
159
|
private activityClasses = new Map<string, typeof Activity>()
|
|
136
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Stores the resolvers for activities started for result.
|
|
163
|
+
*/
|
|
164
|
+
private resultResolvers = new Map<Intent, (intent: ResolvedIntent) => void>()
|
|
165
|
+
|
|
137
166
|
/**
|
|
138
167
|
* Represents the activity stack. It is used to manage
|
|
139
168
|
* the UI state after calling the back action.
|
|
@@ -184,15 +213,6 @@ export class ActivityManager {
|
|
|
184
213
|
this.activityClasses.set(action, activityClass as typeof Activity)
|
|
185
214
|
}
|
|
186
215
|
|
|
187
|
-
// protected reflectEvent<T extends Event>(event: T): T {
|
|
188
|
-
// const copy = Reflect.construct(event.constructor, [event.type, event])
|
|
189
|
-
// const dispatched = this.#parent.events.dispatchEvent(copy)
|
|
190
|
-
// if (!dispatched) {
|
|
191
|
-
// event.preventDefault()
|
|
192
|
-
// }
|
|
193
|
-
// return copy
|
|
194
|
-
// }
|
|
195
|
-
|
|
196
216
|
/**
|
|
197
217
|
* Creates an activity and pushes it into the stack, but it does not initialize any of the lifecycle methods.
|
|
198
218
|
* It is a way to put an activity at some place of the stack,
|
|
@@ -210,21 +230,21 @@ export class ActivityManager {
|
|
|
210
230
|
this.activityStack.push(stackEntry)
|
|
211
231
|
}
|
|
212
232
|
|
|
213
|
-
setupRoute(intent: Intent): void {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
}
|
|
233
|
+
// setupRoute(intent: Intent): void {
|
|
234
|
+
// if (intent.data) {
|
|
235
|
+
// const typed = intent.data as { uri?: string }
|
|
236
|
+
// if (typed.uri) {
|
|
237
|
+
// navigateScreen(typed.uri)
|
|
238
|
+
// }
|
|
239
|
+
// }
|
|
240
|
+
// }
|
|
221
241
|
|
|
222
242
|
/**
|
|
223
243
|
* Starts a new activity and brings it to the foreground.
|
|
224
244
|
*
|
|
225
245
|
* @param intent The intent that created this activity.
|
|
226
246
|
*/
|
|
227
|
-
async startActivity(intent: Intent): Promise<
|
|
247
|
+
async startActivity(intent: Intent): Promise<Activity> {
|
|
228
248
|
const { currentActivity, activityStack } = this
|
|
229
249
|
const lastIndex = activityStack.findLastIndex((entry) => entry.action === intent.action)
|
|
230
250
|
// if the activity is in the history list, we bring it up and update intent.
|
|
@@ -239,9 +259,9 @@ export class ActivityManager {
|
|
|
239
259
|
})
|
|
240
260
|
await info.activity.onNewIntent(intent)
|
|
241
261
|
// TODO: Check if the activity is destroyed.
|
|
242
|
-
this.setupRoute(intent)
|
|
262
|
+
// this.setupRoute(intent)
|
|
243
263
|
await this.updateCurrentActivity(info.activity, false)
|
|
244
|
-
return
|
|
264
|
+
return info.activity
|
|
245
265
|
}
|
|
246
266
|
const activity = this.buildActivity(intent)
|
|
247
267
|
if (currentActivity) {
|
|
@@ -263,16 +283,17 @@ export class ActivityManager {
|
|
|
263
283
|
await activity.onCreate(intent)
|
|
264
284
|
if (this.isDestroyed(activity)) {
|
|
265
285
|
// the activity finished and the manager already took care of this situation.
|
|
266
|
-
return
|
|
286
|
+
return activity
|
|
267
287
|
}
|
|
268
288
|
activity.lifecycle = ActivityLifecycle.Created
|
|
269
289
|
|
|
270
290
|
await this.updateCurrentActivity(activity, !!isModal)
|
|
271
291
|
if (this.isDestroyed(activity)) {
|
|
272
292
|
// the activity finished and the manager already took care of this situation.
|
|
273
|
-
return
|
|
293
|
+
return activity
|
|
274
294
|
}
|
|
275
|
-
this.setupRoute(intent)
|
|
295
|
+
// this.setupRoute(intent)
|
|
296
|
+
return activity
|
|
276
297
|
}
|
|
277
298
|
|
|
278
299
|
private buildActivity(intent: Intent): Activity {
|
|
@@ -293,12 +314,20 @@ export class ActivityManager {
|
|
|
293
314
|
|
|
294
315
|
/**
|
|
295
316
|
* Starts an activity that should return a result to the calling activity.
|
|
296
|
-
*
|
|
317
|
+
*
|
|
318
|
+
* @template T The type of the result data expected.
|
|
297
319
|
* @param intent The intent to start the activity.
|
|
298
|
-
* @
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
320
|
+
* @returns A promise that resolves when the started activity finishes, returning the result Intent with
|
|
321
|
+
* data of type T.
|
|
322
|
+
* @example
|
|
323
|
+
* ```typescript
|
|
324
|
+
* const resultIntent = await mgr.startActivityForResult<{ userId: string }>({ action: 'pickUser' });
|
|
325
|
+
* if (resultIntent.resultCode === IntentResult.RESULT_OK) {
|
|
326
|
+
* console.log(resultIntent.data?.userId);
|
|
327
|
+
* }
|
|
328
|
+
* ```
|
|
329
|
+
*/
|
|
330
|
+
async startActivityForResult<T>(intent: Intent): Promise<ResolvedIntent<T | undefined>> {
|
|
302
331
|
const byReference = (intent.flags ?? 0) & IntentFlags.ByReference
|
|
303
332
|
const shallowCopy = { ...intent }
|
|
304
333
|
const data = shallowCopy.data
|
|
@@ -314,7 +343,14 @@ export class ActivityManager {
|
|
|
314
343
|
} else {
|
|
315
344
|
deepCopy.flags = IntentFlags.ForResult
|
|
316
345
|
}
|
|
317
|
-
|
|
346
|
+
|
|
347
|
+
return new Promise<ResolvedIntent<T>>((resolve, reject) => {
|
|
348
|
+
this.resultResolvers.set(deepCopy, resolve as (intent: ResolvedIntent<unknown>) => void)
|
|
349
|
+
this.startActivity(deepCopy).catch((e) => {
|
|
350
|
+
this.resultResolvers.delete(deepCopy)
|
|
351
|
+
reject(e)
|
|
352
|
+
})
|
|
353
|
+
})
|
|
318
354
|
}
|
|
319
355
|
|
|
320
356
|
isDestroyed(activity: Activity): boolean {
|
|
@@ -342,7 +378,7 @@ export class ActivityManager {
|
|
|
342
378
|
// Clean up resources to prevent memory leaks
|
|
343
379
|
this.cleanupActivity(stackEntry.activity)
|
|
344
380
|
|
|
345
|
-
|
|
381
|
+
this.resolveActivityResult(stackEntry.activity, stackEntry.intent)
|
|
346
382
|
|
|
347
383
|
// Resume the previous activity
|
|
348
384
|
await this.bringLastActivityToFront()
|
|
@@ -353,6 +389,9 @@ export class ActivityManager {
|
|
|
353
389
|
}
|
|
354
390
|
await activity.onDestroy()
|
|
355
391
|
activity.lifecycle = ActivityLifecycle.Destroyed
|
|
392
|
+
|
|
393
|
+
this.resolveActivityResult(activity, { action: '' })
|
|
394
|
+
|
|
356
395
|
// This can happen when an activity finishes in one of the callback methods,
|
|
357
396
|
// before it is added to the stack. In that case, we bring the last activity back to the front.
|
|
358
397
|
await this.bringLastActivityToFront()
|
|
@@ -360,25 +399,21 @@ export class ActivityManager {
|
|
|
360
399
|
this.#parent.requestUpdate()
|
|
361
400
|
}
|
|
362
401
|
|
|
363
|
-
private
|
|
364
|
-
const
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
// Let's create a shallow copy of the intent. We can disregard the ByReference flag here,
|
|
377
|
-
// as we override the data with the result data.
|
|
378
|
-
const intentCopy = { ...intent }
|
|
379
|
-
intentCopy.data = activity.getResult()
|
|
380
|
-
await target.activity.onActivityResult(requestCode, activity.resultCode, intentCopy)
|
|
402
|
+
private resolveActivityResult(activity: Activity, originalIntent: Intent): void {
|
|
403
|
+
const resolver = this.resultResolvers.get(originalIntent)
|
|
404
|
+
// The activity might have not been started with startActivityForResult.
|
|
405
|
+
// A thing to consider for the future is whether we should throw an error in a case where
|
|
406
|
+
// the activity was started for result but the resolver was not found.
|
|
407
|
+
if (resolver) {
|
|
408
|
+
this.resultResolvers.delete(originalIntent)
|
|
409
|
+
// We construct the result intent.
|
|
410
|
+
// Ideally we would like to preserve the original intent structure but with new data.
|
|
411
|
+
const resultIntent: ResolvedIntent = {
|
|
412
|
+
...originalIntent,
|
|
413
|
+
data: activity.getResult(),
|
|
414
|
+
result: activity.resultCode,
|
|
381
415
|
}
|
|
416
|
+
resolver(resultIntent)
|
|
382
417
|
}
|
|
383
418
|
}
|
|
384
419
|
|
package/src/core/Fragment.ts
CHANGED
|
@@ -3,16 +3,12 @@ import { Activity } from './Activity.js'
|
|
|
3
3
|
import { FragmentState, type FragmentOptions, FragmentManager } from './FragmentManager.js'
|
|
4
4
|
import type { Application, UpdateRequest } from './Application.js'
|
|
5
5
|
import { FragmentRenderer } from './renderer/FragmentRenderer.js'
|
|
6
|
-
import { Intent,
|
|
6
|
+
import { Intent, ResolvedIntent } from './ActivityManager.js'
|
|
7
7
|
import { bound } from '../decorators/bound.js'
|
|
8
8
|
import type { ActivityDetail, ActivityWithResultDetail } from '../events/IntentEvents.js'
|
|
9
9
|
import { EventTypes } from '../events/EventTypes.js'
|
|
10
10
|
import { type RefOrCallback } from 'lit/directives/ref.js'
|
|
11
11
|
|
|
12
|
-
export interface PendingActivityResult {
|
|
13
|
-
onResult(result: IntentResult, intent: Intent): void
|
|
14
|
-
}
|
|
15
|
-
|
|
16
12
|
/**
|
|
17
13
|
* Similar to Activity, with lifecycle methods (onCreate, onAttach, onDetach, etc.).
|
|
18
14
|
* The crucial difference is that a Fragment is always hosted by an `Activity` or
|
|
@@ -31,20 +27,6 @@ export class Fragment extends EventTarget {
|
|
|
31
27
|
protected children = new Map<string, Fragment>()
|
|
32
28
|
protected fragmentManager: FragmentManager
|
|
33
29
|
|
|
34
|
-
/**
|
|
35
|
-
* The request code used to start an activity for a result.
|
|
36
|
-
*/
|
|
37
|
-
requestCode = -1
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* A list of pending activity results that were requested by the components
|
|
41
|
-
* hosted in this fragment.
|
|
42
|
-
* The key is the request code and the value contains the callback
|
|
43
|
-
* that will be called when the activity result is received.
|
|
44
|
-
* The callback is called with the result code and the resulting intent.
|
|
45
|
-
*/
|
|
46
|
-
pendingActivityResult: Map<number, PendingActivityResult> = new Map<number, PendingActivityResult>()
|
|
47
|
-
|
|
48
30
|
#renderer: FragmentRenderer
|
|
49
31
|
|
|
50
32
|
get renderer(): FragmentRenderer {
|
|
@@ -230,7 +212,7 @@ export class Fragment extends EventTarget {
|
|
|
230
212
|
*
|
|
231
213
|
* @example
|
|
232
214
|
* // In your parent fragment's render method:
|
|
233
|
-
* html`<div ${ref(this.createFragmentRef('my-child-fragment'))}></div>`
|
|
215
|
+
* // html`<div ${ref(this.createFragmentRef('my-child-fragment'))}></div>`
|
|
234
216
|
*/
|
|
235
217
|
createFragmentRef(key: string): RefOrCallback<Element> {
|
|
236
218
|
return (element?: Element) => {
|
|
@@ -268,14 +250,24 @@ export class Fragment extends EventTarget {
|
|
|
268
250
|
|
|
269
251
|
/**
|
|
270
252
|
* Starts an activity for result.
|
|
253
|
+
* @template T The type of the result data expected.
|
|
271
254
|
* @param intent The intent to start.
|
|
255
|
+
* @returns A promise that resolves when the started activity finishes, returning the result Intent with
|
|
256
|
+
* data of type T.
|
|
257
|
+
* @example
|
|
258
|
+
* ```typescript
|
|
259
|
+
* const resultIntent = await this.startActivityForResult<{ userId: string }>({ action: 'pickUser' });
|
|
260
|
+
* if (resultIntent.resultCode === IntentResult.RESULT_OK) {
|
|
261
|
+
* console.log(resultIntent.data?.userId);
|
|
262
|
+
* }
|
|
263
|
+
* ```
|
|
272
264
|
*/
|
|
273
|
-
async startActivityForResult(intent: Intent): Promise<
|
|
265
|
+
async startActivityForResult<T>(intent: Intent): Promise<ResolvedIntent<T | undefined>> {
|
|
274
266
|
const activity = this.getActivity()
|
|
275
267
|
if (!activity) {
|
|
276
|
-
throw new Error(
|
|
268
|
+
throw new Error('Fragment is not attached to an activity')
|
|
277
269
|
}
|
|
278
|
-
|
|
270
|
+
return activity.startActivityForResult<T>(intent)
|
|
279
271
|
}
|
|
280
272
|
|
|
281
273
|
/**
|
|
@@ -290,44 +282,6 @@ export class Fragment extends EventTarget {
|
|
|
290
282
|
await activity.startActivity(intent)
|
|
291
283
|
}
|
|
292
284
|
|
|
293
|
-
/**
|
|
294
|
-
* The callback method that is triggered when another activity that was
|
|
295
|
-
* started for result finishes.
|
|
296
|
-
*
|
|
297
|
-
* @param requestCode The request code that was used to start the activity.
|
|
298
|
-
* @param data The data that was passed back.
|
|
299
|
-
* @param intent The intent that was used to start the activity.
|
|
300
|
-
*/
|
|
301
|
-
async onActivityResult(requestCode: number, resultCode: IntentResult, intent: Intent): Promise<void> {
|
|
302
|
-
const { pendingActivityResult, children } = this
|
|
303
|
-
if (pendingActivityResult.has(requestCode)) {
|
|
304
|
-
const { onResult } = pendingActivityResult.get(requestCode) as PendingActivityResult
|
|
305
|
-
pendingActivityResult.delete(requestCode)
|
|
306
|
-
onResult(resultCode, intent)
|
|
307
|
-
return
|
|
308
|
-
}
|
|
309
|
-
for (const fragment of children.values()) {
|
|
310
|
-
if (fragment.hasRequestCode(requestCode)) {
|
|
311
|
-
fragment.onActivityResult(requestCode, resultCode, intent)
|
|
312
|
-
return
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
this.requestCode = -1
|
|
316
|
-
if (this.constructor === Fragment) {
|
|
317
|
-
// eslint-disable-next-line no-console
|
|
318
|
-
console.info('Fragment#onActivityResult() not implemented', requestCode, resultCode, intent)
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
hasRequestCode(requestCode: number): boolean {
|
|
323
|
-
for (const fragment of this.children.values()) {
|
|
324
|
-
if (fragment.hasRequestCode(requestCode)) {
|
|
325
|
-
return true
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
return this.requestCode === requestCode
|
|
329
|
-
}
|
|
330
|
-
|
|
331
285
|
/**
|
|
332
286
|
* A handler for the intent event dispatched by web components hosted by this fragment.
|
|
333
287
|
*
|
|
@@ -351,11 +305,8 @@ export class Fragment extends EventTarget {
|
|
|
351
305
|
}
|
|
352
306
|
if (event.type === EventTypes.Intent.startActivityForResult) {
|
|
353
307
|
const info = event.detail as ActivityWithResultDetail
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
this.pendingActivityResult.set(code, {
|
|
357
|
-
onResult: info.onResult,
|
|
358
|
-
})
|
|
308
|
+
const result = await this.startActivityForResult(info.intent)
|
|
309
|
+
info.onResult(result.result, result)
|
|
359
310
|
} else if (event.type === EventTypes.Intent.startActivity) {
|
|
360
311
|
await activity.startActivity(event.detail.intent)
|
|
361
312
|
} else {
|
|
@@ -210,18 +210,4 @@ export class FragmentManager {
|
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
212
|
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Finds a fragment by activity request code.
|
|
216
|
-
* @param requestCode The request code to find the fragment by.
|
|
217
|
-
* @returns The corresponding fragment or `null`.
|
|
218
|
-
*/
|
|
219
|
-
findByRequestCode(requestCode: number): Fragment | null {
|
|
220
|
-
for (const [, fragment] of this.fragments) {
|
|
221
|
-
if (fragment.hasRequestCode(requestCode)) {
|
|
222
|
-
return fragment
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
return null
|
|
226
|
-
}
|
|
227
213
|
}
|