@react-native-ohos/ting 1.3.0-rc.1 → 1.3.0-rc.3

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.
@@ -1,5 +1,5 @@
1
1
  export default class BuildProfile {
2
- static readonly HAR_VERSION = '1.3.0-rc.1';
2
+ static readonly HAR_VERSION = '1.3.0-rc.3';
3
3
  static readonly BUILD_MODE_NAME = 'debug';
4
4
  static readonly DEBUG = true;
5
5
  static readonly TARGET_NAME = 'default';
@@ -1,11 +1,11 @@
1
1
  {
2
2
  license: 'MIT',
3
3
  types: '',
4
- name: '@react-native-oh-tpl/ting',
4
+ name: '@react-native-ohos/ting',
5
5
  description: '',
6
6
  main: 'index.ets',
7
7
  type: 'module',
8
- version: '1.3.0-rc.1',
8
+ version: '1.3.0-rc.3',
9
9
  dependencies: {
10
10
  "@rnoh/react-native-openharmony": "file:../../node_modules/@react-native-oh/react-native-harmony/harmony/react_native_openharmony.har"
11
11
  },
@@ -23,24 +23,24 @@
23
23
  */
24
24
 
25
25
  import { TurboModule } from '@rnoh/react-native-openharmony/ts';
26
- import { TM } from "../ets/generated/ts";
27
- import { ComponentContent, PromptAction, promptAction, window } from '@kit.ArkUI';
28
- import { ToastOptions, AlertOptions, Options, AlertBuilderData } from './Type';
26
+ import { TM } from '../ets/generated/ts';
27
+ import { ComponentContent, promptAction, window } from '@kit.ArkUI';
28
+ import { AlertBuilderData, AlertOptions, Options, ToastBuilderData, ToastOptions , ToastQueueItem, AlertQueueItem} from './Type';
29
29
  import { vibrator } from '@kit.SensorServiceKit';
30
30
  import { common2D, drawing } from '@kit.ArkGraphics2D';
31
31
 
32
32
  @Builder
33
- function buildToast(toastOptions: ToastOptions) {
33
+ function buildToast(toastBuilderData: ToastBuilderData) {
34
34
  Row() {
35
- if (!toastOptions.icon?.uri) {
36
- if (toastOptions.preset === 'spinner') {
35
+ if (!toastBuilderData.toastOptions.icon?.uri) {
36
+ if (toastBuilderData.toastOptions.preset === 'spinner') {
37
37
  Progress({ value: 0, total: 100, type: ProgressType.Ring })
38
38
  .width('100px')
39
39
  .height('100px')
40
- .color(toastOptions.progressColor || '#008080')
40
+ .color(toastBuilderData.toastOptions.progressColor || '#008080')
41
41
  .style({ strokeWidth: 5, status: ProgressStatus.LOADING })
42
42
  .margin({ left: 7 })
43
- } else if (toastOptions.preset === 'error') {
43
+ } else if (toastBuilderData.toastOptions.preset === 'error') {
44
44
  Path()
45
45
  .commands('M52.5 44.17 L81.67 15 L90 23.33 L60.83 52.5 L90 81.67 L81.67 90 L52.5 60.83 L23.33 90 ' +
46
46
  'L15 81.67 L44.17 52.5 L15 23.33 L23.33 15 L52.5 44.17 Z')
@@ -49,7 +49,7 @@ function buildToast(toastOptions: ToastOptions) {
49
49
  .fill(Color.Red)
50
50
  .stroke(Color.Red)
51
51
  .margin({ left: 7 })
52
- } else if (toastOptions.preset === 'done') {
52
+ } else if (toastBuilderData.toastOptions.preset === 'done') {
53
53
  Polyline()
54
54
  .width('100px')
55
55
  .height('100px')
@@ -57,7 +57,7 @@ function buildToast(toastOptions: ToastOptions) {
57
57
  .fillOpacity(0)
58
58
  .stroke(Color.Green)
59
59
  .strokeWidth(4)
60
- } else if (toastOptions.preset === 'none') {
60
+ } else if (toastBuilderData.toastOptions.preset === 'none') {
61
61
  // there is no component.
62
62
  } else {
63
63
  Polyline()
@@ -69,22 +69,22 @@ function buildToast(toastOptions: ToastOptions) {
69
69
  .strokeWidth(4)
70
70
  }
71
71
  } else {
72
- if (typeof toastOptions.icon?.uri === 'string') {
73
- if (!toastOptions.icon?.tintColor) {
74
- Image(toastOptions.icon.uri as string)
72
+ if (typeof toastBuilderData.toastOptions.icon?.uri === 'string') {
73
+ if (!toastBuilderData.toastOptions.icon?.tintColor) {
74
+ Image(toastBuilderData.toastOptions.icon.uri as string)
75
75
  .objectFit(ImageFit.Contain)
76
76
  .autoResize(true)
77
- .width(toastOptions.icon.size || '100px')
78
- .height(toastOptions.icon.size || '100px')
77
+ .width(toastBuilderData.toastOptions.icon.size || '100px')
78
+ .height(toastBuilderData.toastOptions.icon.size || '100px')
79
79
  .borderRadius(17.5)
80
80
  .margin({ left: 7 })
81
81
  } else {
82
- Image(toastOptions.icon?.uri as string)
82
+ Image(toastBuilderData.toastOptions.icon?.uri as string)
83
83
  .objectFit(ImageFit.Contain)
84
84
  .autoResize(true)
85
- .width(toastOptions.icon.size || '100px')
86
- .height(toastOptions.icon.size || '100px')
87
- .colorFilter(drawing.ColorFilter.createBlendModeColorFilter(toastOptions.icon.tintColor as common2D.Color
85
+ .width(toastBuilderData.toastOptions.icon.size || '100px')
86
+ .height(toastBuilderData.toastOptions.icon.size || '100px')
87
+ .colorFilter(drawing.ColorFilter.createBlendModeColorFilter(toastBuilderData.toastOptions.icon.tintColor as common2D.Color
88
88
  , drawing.BlendMode.SRC_IN))
89
89
  .borderRadius(17.5)
90
90
  .margin({ left: 7 })
@@ -93,17 +93,17 @@ function buildToast(toastOptions: ToastOptions) {
93
93
  }
94
94
 
95
95
  Column() {
96
- Text(toastOptions.title || '')
96
+ Text(toastBuilderData.toastOptions.title || '')
97
97
  .fontSize(13)
98
- .fontColor(toastOptions.titleColor || '#000000')
98
+ .fontColor(toastBuilderData.toastOptions.titleColor || '#000000')
99
99
  .alignSelf(ItemAlign.Center)
100
100
  .maxLines(1)
101
101
  .textOverflow({ overflow: TextOverflow.Ellipsis })
102
102
  .margin({ bottom: 5 })
103
103
 
104
- Text(toastOptions.message || '')
104
+ Text(toastBuilderData.toastOptions.message || '')
105
105
  .fontSize(12)
106
- .fontColor(toastOptions.messageColor || '#BEBEBE')
106
+ .fontColor(toastBuilderData.toastOptions.messageColor || '#BEBEBE')
107
107
  .alignSelf(ItemAlign.Center)
108
108
  .maxLines(1)
109
109
  .textOverflow({ overflow: TextOverflow.Ellipsis })
@@ -119,13 +119,27 @@ function buildToast(toastOptions: ToastOptions) {
119
119
  .height('auto')
120
120
  .width('auto')
121
121
  .borderRadius('50%')
122
- .backgroundColor(toastOptions.backgroundColor || '#FFFFFF')
122
+ .backgroundColor(toastBuilderData.toastOptions.backgroundColor || '#FFFFFF')
123
123
  .padding(5)
124
+ .gesture(
125
+ PanGesture({
126
+ distance: 5,
127
+ fingers: 1,
128
+ direction: PanDirection.All
129
+ })
130
+ .onActionUpdate((event: GestureEvent) => {
131
+ // 处理滑动数据
132
+ if (toastBuilderData.toastOptions.shouldDismissByDrag && toastBuilderData.onDismiss) {
133
+ toastBuilderData.onDismiss();
134
+ }
135
+ })
136
+ )
124
137
  }
125
138
 
126
139
  @Builder
127
140
  function buildAlert(alertBuilderData: AlertBuilderData) {
128
141
  Column() {
142
+ // 图标部分
129
143
  if (!alertBuilderData.alertOptions.icon?.uri) {
130
144
  if (alertBuilderData.alertOptions.preset === 'spinner') {
131
145
  Progress({ value: 0, total: 100, type: ProgressType.Ring })
@@ -189,6 +203,7 @@ function buildAlert(alertBuilderData: AlertBuilderData) {
189
203
  }
190
204
  }
191
205
 
206
+ // 文本部分
192
207
  Column() {
193
208
  Text(alertBuilderData.alertOptions.title || '')
194
209
  .fontSize(16)
@@ -230,14 +245,12 @@ function buildAlert(alertBuilderData: AlertBuilderData) {
230
245
  }
231
246
 
232
247
  export class TingTurboModule extends TurboModule implements TM.Ting.Spec {
233
- private alertPromptAction: PromptAction | null = null;
234
- private alertComponentContent: ComponentContent<object> | null = null;
235
- private timeoutId: number | null = null;
236
- private isCancelled: boolean = false;
237
248
  private toastOptionInit: ToastOptions | undefined = undefined;
238
249
  private alertOptionInit: AlertOptions | undefined = undefined;
239
250
  private PREFIX = "asset://";
240
251
  private RAWFILE_PREFIX = "resource://RAWFILE/assets/";
252
+ private toastQueue: Array<ToastQueueItem> = [];
253
+ private alertQueue: Array<AlertQueueItem> = [];
241
254
 
242
255
  async showToast(toastOptions: ToastOptions) {
243
256
  if (this.toastOptionInit) {
@@ -250,51 +263,97 @@ export class TingTurboModule extends TurboModule implements TM.Ting.Spec {
250
263
 
251
264
  let option: promptAction.BaseDialogOptions = {
252
265
  alignment: DialogAlignment.Top,
253
- autoCancel: true,
266
+ autoCancel: false,
254
267
  offset: { dx: 0, dy: 50 },
255
- isModal: true,
256
- maskColor: '#00FF0000',
257
- transition: TransitionEffect.asymmetric(TransitionEffect.move(TransitionEdge.TOP)
258
- .animation({ curve: Curve.Sharp }),
259
- TransitionEffect.move(TransitionEdge.TOP).animation({ curve: Curve.Sharp })),
268
+ isModal: false,
269
+ transition: TransitionEffect.asymmetric(
270
+ TransitionEffect.move(TransitionEdge.TOP).animation({ curve: Curve.Sharp }),
271
+ TransitionEffect.move(TransitionEdge.TOP).animation({ curve: Curve.Sharp })
272
+ ),
260
273
  };
261
274
 
262
275
  if (toastOptions.position === "bottom") {
263
276
  option.alignment = DialogAlignment.Bottom;
264
277
  option.offset = { dx: 0, dy: -50 };
265
- option.transition = TransitionEffect.asymmetric(TransitionEffect.move(TransitionEdge.BOTTOM)
266
- .animation({ curve: Curve.Sharp }),
267
- TransitionEffect.move(TransitionEdge.BOTTOM).animation({ curve: Curve.Sharp }));
278
+ option.transition = TransitionEffect.asymmetric(
279
+ TransitionEffect.move(TransitionEdge.BOTTOM).animation({ curve: Curve.Sharp }),
280
+ TransitionEffect.move(TransitionEdge.BOTTOM).animation({ curve: Curve.Sharp })
281
+ );
268
282
  }
269
283
 
270
- if (toastOptions.shouldDismissByDrag === false) {
271
- option.autoCancel = false;
272
- }
273
-
274
- if (toastOptions.duration && toastOptions.duration !== 3000) {
275
- toastOptions.duration = toastOptions.duration * 1000;
276
- if (toastOptions.duration > 0 && toastOptions.duration <= 1000) {
277
- toastOptions.duration += 500;
284
+ if(toastOptions.duration){
285
+ if (toastOptions.duration > 0 && toastOptions.duration <= 1) {
286
+ toastOptions.duration += 0.5;
278
287
  }
279
288
  }
289
+ const duration = toastOptions.duration ? toastOptions.duration * 1000 : 3000;
280
290
 
281
- if (toastOptions.haptic) {
282
- option.onDidAppear = () => this.vibrator(toastOptions.haptic as string);
283
- }
291
+ // 创建关闭函数
292
+ const dismissToast = () => {
293
+ this.clearAllToasts();
294
+ };
295
+
296
+ const toastBuilderData: ToastBuilderData = {
297
+ toastOptions: toastOptions,
298
+ onDismiss: dismissToast
299
+ };
284
300
 
285
- const contentNode = new ComponentContent(uiContext!, wrapBuilder(buildToast), toastOptions);
301
+ const componentContent = new ComponentContent(uiContext!, wrapBuilder(buildToast), toastBuilderData);
286
302
 
287
303
  try {
288
- promptAction?.openCustomDialog(contentNode, option);
304
+ // 显示前先清理之前的Toast
305
+ this.clearAllToasts();
306
+
307
+ // 显示新Toast
308
+ promptAction?.openCustomDialog(componentContent, option);
309
+
310
+ // 添加到队列
311
+ const timeoutId = setTimeout(() => {
312
+ promptAction?.closeCustomDialog(componentContent);
313
+ this.removeToastFromQueue(componentContent);
314
+ }, duration);
315
+
316
+ this.toastQueue.push({
317
+ componentContent,
318
+ promptAction,
319
+ timeoutId
320
+ });
289
321
 
290
- setTimeout(() => {
291
- promptAction?.closeCustomDialog(contentNode);
292
- }, toastOptions.duration || 3000);
293
322
  } catch (error) {
294
323
  throw new Error('Can\'t open CustomDialog: ' + error);
295
324
  }
296
325
  }
297
326
 
327
+ private clearAllToasts() {
328
+ // 清理所有正在显示的Toast
329
+ this.toastQueue.forEach(item => {
330
+ if (item.timeoutId) {
331
+ clearTimeout(item.timeoutId);
332
+ }
333
+ try {
334
+ item.promptAction.closeCustomDialog(item.componentContent);
335
+ } catch (e) {
336
+ // 忽略关闭错误
337
+ }
338
+ });
339
+ this.toastQueue = [];
340
+ }
341
+
342
+ private removeToastFromQueue(componentContent: ComponentContent<object>) {
343
+ const index = this.toastQueue.findIndex(item => item.componentContent === componentContent);
344
+ if (index !== -1) {
345
+ const item = this.toastQueue[index];
346
+ if (item.timeoutId) {
347
+ clearTimeout(item.timeoutId);
348
+ }
349
+ this.toastQueue.splice(index, 1);
350
+ }
351
+ }
352
+
353
+ dismissToast(): void {
354
+ this.clearAllToasts();
355
+ }
356
+
298
357
  async showAlert(alertOptions: AlertOptions) {
299
358
  if (this.alertOptionInit) {
300
359
  alertOptions = this.mergeAlertOptions(this.alertOptionInit, alertOptions);
@@ -302,33 +361,20 @@ export class TingTurboModule extends TurboModule implements TM.Ting.Spec {
302
361
 
303
362
  const windowValue = await window.getLastWindow(this.ctx.uiAbilityContext);
304
363
  const uiContext = windowValue?.getUIContext();
305
- this.alertPromptAction = uiContext?.getPromptAction();
364
+ const promptAction = uiContext?.getPromptAction();
306
365
 
307
366
  let option: promptAction.BaseDialogOptions = {
308
367
  alignment: DialogAlignment.Center,
309
- autoCancel: true,
310
- isModal: true,
368
+ autoCancel: false,
369
+ isModal: false,
311
370
  maskColor: '#00FF0000'
312
371
  };
313
372
 
314
- if (alertOptions.shouldDismissByTap === false) {
315
- option.autoCancel = false;
316
- }
317
-
318
373
  if (alertOptions.backdropOpacity && alertOptions.backdropOpacity >= 1) {
319
374
  option.maskColor = '#000000';
320
375
  }
321
376
 
322
- if (alertOptions.duration && alertOptions.duration !== 3000) {
323
- alertOptions.duration = alertOptions.duration * 1000;
324
- }
325
-
326
- if (this.timeoutId) {
327
- clearTimeout(this.timeoutId);
328
- this.isCancelled = true; // 标记为取消状态
329
- }
330
-
331
- this.isCancelled = false;
377
+ const duration = alertOptions.duration ? alertOptions.duration * 1000 : 3000;
332
378
 
333
379
  if (alertOptions.haptic) {
334
380
  option.onDidAppear = () => this.vibrator(alertOptions.haptic as string);
@@ -336,7 +382,7 @@ export class TingTurboModule extends TurboModule implements TM.Ting.Spec {
336
382
 
337
383
  // 创建关闭函数
338
384
  const dismissAlert = () => {
339
- this.dismissAlert();
385
+ this.clearAllAlerts();
340
386
  };
341
387
 
342
388
  const alertBuilderData: AlertBuilderData = {
@@ -344,21 +390,62 @@ export class TingTurboModule extends TurboModule implements TM.Ting.Spec {
344
390
  onDismiss: dismissAlert
345
391
  };
346
392
 
347
-
348
- this.alertComponentContent = new ComponentContent(uiContext!, wrapBuilder(buildAlert), alertBuilderData);
393
+ const componentContent = new ComponentContent(uiContext!, wrapBuilder(buildAlert), alertBuilderData);
349
394
 
350
395
  try {
351
- this.alertPromptAction?.openCustomDialog(this.alertComponentContent, option);
396
+ // 显示前先清理之前的Alert
397
+ this.clearAllAlerts();
398
+
399
+ // 显示新Alert
400
+ promptAction?.openCustomDialog(componentContent, option);
401
+
402
+ // 添加到队列
403
+ const timeoutId = setTimeout(() => {
404
+ promptAction?.closeCustomDialog(componentContent);
405
+ this.removeAlertFromQueue(componentContent);
406
+ }, duration);
352
407
 
353
- this.timeoutId = setTimeout(async () => {
354
- await this.alertPromptAction?.closeCustomDialog(this.alertComponentContent);
355
- }, alertOptions.duration || 3000);
408
+ this.alertQueue.push({
409
+ componentContent,
410
+ promptAction,
411
+ timeoutId
412
+ });
356
413
 
357
414
  } catch (error) {
358
415
  throw new Error('Can\'t open CustomDialog: ' + error);
359
416
  }
360
417
  }
361
418
 
419
+ private clearAllAlerts() {
420
+ // 清理所有正在显示的Alert
421
+ this.alertQueue.forEach(item => {
422
+ if (item.timeoutId) {
423
+ clearTimeout(item.timeoutId);
424
+ }
425
+ try {
426
+ item.promptAction.closeCustomDialog(item.componentContent);
427
+ } catch (e) {
428
+ // 忽略关闭错误
429
+ }
430
+ });
431
+ this.alertQueue = [];
432
+ }
433
+
434
+ private removeAlertFromQueue(componentContent: ComponentContent<object>) {
435
+ const index = this.alertQueue.findIndex(item => item.componentContent === componentContent);
436
+ if (index !== -1) {
437
+ const item = this.alertQueue[index];
438
+ if (item.timeoutId) {
439
+ clearTimeout(item.timeoutId);
440
+ }
441
+ this.alertQueue.splice(index, 1);
442
+ }
443
+ }
444
+
445
+ dismissAlert(): void {
446
+ this.clearAllAlerts();
447
+ }
448
+
362
449
  toast(options: Object): void {
363
450
  if (options && typeof options === 'object') {
364
451
  const toastOptions = options as ToastOptions;
@@ -391,18 +478,6 @@ export class TingTurboModule extends TurboModule implements TM.Ting.Spec {
391
478
  }
392
479
  }
393
480
 
394
- dismissAlert(): void {
395
- if (this.timeoutId) {
396
- clearTimeout(this.timeoutId);
397
- this.timeoutId = null;
398
- this.isCancelled = true;
399
-
400
- if (this.alertPromptAction && this.alertComponentContent) {
401
- this.alertPromptAction.closeCustomDialog(this.alertComponentContent);
402
- }
403
- }
404
- }
405
-
406
481
  setup(options: Object): void {
407
482
  const opts = options as Options;
408
483
  this.alertOptionInit = opts.alert;
@@ -528,4 +603,4 @@ export class TingTurboModule extends TurboModule implements TM.Ting.Spec {
528
603
  }
529
604
  return path;
530
605
  }
531
- }
606
+ }
@@ -23,12 +23,29 @@
23
23
  */
24
24
 
25
25
  import { common2D } from '@kit.ArkGraphics2D';
26
+ import { ComponentContent,PromptAction } from '@kit.ArkUI';
27
+ export interface ToastQueueItem {
28
+ componentContent: ComponentContent<object>;
29
+ promptAction: PromptAction;
30
+ timeoutId: number;
31
+ }
32
+
33
+ export interface AlertQueueItem {
34
+ componentContent: ComponentContent<object>;
35
+ promptAction: PromptAction;
36
+ timeoutId: number;
37
+ }
26
38
 
27
39
  export interface AlertBuilderData {
28
40
  alertOptions: AlertOptions;
29
41
  onDismiss: () => void;
30
42
  }
31
43
 
44
+ export interface ToastBuilderData {
45
+ toastOptions: ToastOptions;
46
+ onDismiss: () => void;
47
+ }
48
+
32
49
  export interface Icon {
33
50
  size?: number;
34
51
  uri?: string | number;
package/harmony/ting.har CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-native-ohos/ting",
3
- "version": "1.3.0-rc.1",
3
+ "version": "1.3.0-rc.3",
4
4
  "description": "test",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",