@react-native-ohos/ting 1.3.0-rc.2 → 1.3.0-rc.4

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.2';
2
+ static readonly HAR_VERSION = '1.3.0-rc.4';
3
3
  static readonly BUILD_MODE_NAME = 'debug';
4
4
  static readonly DEBUG = true;
5
5
  static readonly TARGET_NAME = 'default';
@@ -5,7 +5,7 @@
5
5
  description: '',
6
6
  main: 'index.ets',
7
7
  type: 'module',
8
- version: '1.3.0-rc.2',
8
+ version: '1.3.0-rc.4',
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,99 @@ 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
  }
280
-
289
+ const duration = toastOptions.duration ? toastOptions.duration * 1000 : 3000;
281
290
  if (toastOptions.haptic) {
282
291
  option.onDidAppear = () => this.vibrator(toastOptions.haptic as string);
283
292
  }
293
+ // 创建关闭函数
294
+ const dismissToast = () => {
295
+ this.clearAllToasts();
296
+ };
297
+
298
+ const toastBuilderData: ToastBuilderData = {
299
+ toastOptions: toastOptions,
300
+ onDismiss: dismissToast
301
+ };
284
302
 
285
- const contentNode = new ComponentContent(uiContext!, wrapBuilder(buildToast), toastOptions);
303
+ const componentContent = new ComponentContent(uiContext!, wrapBuilder(buildToast), toastBuilderData);
286
304
 
287
305
  try {
288
- promptAction?.openCustomDialog(contentNode, option);
306
+ // 显示前先清理之前的Toast
307
+ this.clearAllToasts();
308
+
309
+ // 显示新Toast
310
+ promptAction?.openCustomDialog(componentContent, option);
311
+
312
+ // 添加到队列
313
+ const timeoutId = setTimeout(() => {
314
+ promptAction?.closeCustomDialog(componentContent);
315
+ this.removeToastFromQueue(componentContent);
316
+ }, duration);
317
+
318
+ this.toastQueue.push({
319
+ componentContent,
320
+ promptAction,
321
+ timeoutId
322
+ });
289
323
 
290
- setTimeout(() => {
291
- promptAction?.closeCustomDialog(contentNode);
292
- }, toastOptions.duration || 3000);
293
324
  } catch (error) {
294
325
  throw new Error('Can\'t open CustomDialog: ' + error);
295
326
  }
296
327
  }
297
328
 
329
+ private clearAllToasts() {
330
+ // 清理所有正在显示的Toast
331
+ this.toastQueue.forEach(item => {
332
+ if (item.timeoutId) {
333
+ clearTimeout(item.timeoutId);
334
+ }
335
+ try {
336
+ item.promptAction.closeCustomDialog(item.componentContent);
337
+ } catch (e) {
338
+ // 忽略关闭错误
339
+ }
340
+ });
341
+ this.toastQueue = [];
342
+ }
343
+
344
+ private removeToastFromQueue(componentContent: ComponentContent<object>) {
345
+ const index = this.toastQueue.findIndex(item => item.componentContent === componentContent);
346
+ if (index !== -1) {
347
+ const item = this.toastQueue[index];
348
+ if (item.timeoutId) {
349
+ clearTimeout(item.timeoutId);
350
+ }
351
+ this.toastQueue.splice(index, 1);
352
+ }
353
+ }
354
+
355
+ dismissToast(): void {
356
+ this.clearAllToasts();
357
+ }
358
+
298
359
  async showAlert(alertOptions: AlertOptions) {
299
360
  if (this.alertOptionInit) {
300
361
  alertOptions = this.mergeAlertOptions(this.alertOptionInit, alertOptions);
@@ -302,33 +363,22 @@ export class TingTurboModule extends TurboModule implements TM.Ting.Spec {
302
363
 
303
364
  const windowValue = await window.getLastWindow(this.ctx.uiAbilityContext);
304
365
  const uiContext = windowValue?.getUIContext();
305
- this.alertPromptAction = uiContext?.getPromptAction();
366
+ const promptAction = uiContext?.getPromptAction();
306
367
 
307
368
  let option: promptAction.BaseDialogOptions = {
308
369
  alignment: DialogAlignment.Center,
309
- autoCancel: true,
310
- isModal: true,
370
+ autoCancel: false,
371
+ isModal: false,
311
372
  maskColor: '#00FF0000'
312
373
  };
313
374
 
314
- if (alertOptions.shouldDismissByTap === false) {
315
- option.autoCancel = false;
316
- }
317
-
318
375
  if (alertOptions.backdropOpacity && alertOptions.backdropOpacity >= 1) {
319
376
  option.maskColor = '#000000';
377
+ let baseOption = alertOptions as promptAction.BaseDialogOptions;
378
+ option.isModal = baseOption?.isModal;
320
379
  }
321
380
 
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;
381
+ const duration = alertOptions.duration ? alertOptions.duration * 1000 : 3000;
332
382
 
333
383
  if (alertOptions.haptic) {
334
384
  option.onDidAppear = () => this.vibrator(alertOptions.haptic as string);
@@ -336,7 +386,7 @@ export class TingTurboModule extends TurboModule implements TM.Ting.Spec {
336
386
 
337
387
  // 创建关闭函数
338
388
  const dismissAlert = () => {
339
- this.dismissAlert();
389
+ this.clearAllAlerts();
340
390
  };
341
391
 
342
392
  const alertBuilderData: AlertBuilderData = {
@@ -344,21 +394,62 @@ export class TingTurboModule extends TurboModule implements TM.Ting.Spec {
344
394
  onDismiss: dismissAlert
345
395
  };
346
396
 
347
-
348
- this.alertComponentContent = new ComponentContent(uiContext!, wrapBuilder(buildAlert), alertBuilderData);
397
+ const componentContent = new ComponentContent(uiContext!, wrapBuilder(buildAlert), alertBuilderData);
349
398
 
350
399
  try {
351
- this.alertPromptAction?.openCustomDialog(this.alertComponentContent, option);
400
+ // 显示前先清理之前的Alert
401
+ this.clearAllAlerts();
402
+
403
+ // 显示新Alert
404
+ promptAction?.openCustomDialog(componentContent, option);
405
+
406
+ // 添加到队列
407
+ const timeoutId = setTimeout(() => {
408
+ promptAction?.closeCustomDialog(componentContent);
409
+ this.removeAlertFromQueue(componentContent);
410
+ }, duration);
352
411
 
353
- this.timeoutId = setTimeout(async () => {
354
- await this.alertPromptAction?.closeCustomDialog(this.alertComponentContent);
355
- }, alertOptions.duration || 3000);
412
+ this.alertQueue.push({
413
+ componentContent,
414
+ promptAction,
415
+ timeoutId
416
+ });
356
417
 
357
418
  } catch (error) {
358
419
  throw new Error('Can\'t open CustomDialog: ' + error);
359
420
  }
360
421
  }
361
422
 
423
+ private clearAllAlerts() {
424
+ // 清理所有正在显示的Alert
425
+ this.alertQueue.forEach(item => {
426
+ if (item.timeoutId) {
427
+ clearTimeout(item.timeoutId);
428
+ }
429
+ try {
430
+ item.promptAction.closeCustomDialog(item.componentContent);
431
+ } catch (e) {
432
+ // 忽略关闭错误
433
+ }
434
+ });
435
+ this.alertQueue = [];
436
+ }
437
+
438
+ private removeAlertFromQueue(componentContent: ComponentContent<object>) {
439
+ const index = this.alertQueue.findIndex(item => item.componentContent === componentContent);
440
+ if (index !== -1) {
441
+ const item = this.alertQueue[index];
442
+ if (item.timeoutId) {
443
+ clearTimeout(item.timeoutId);
444
+ }
445
+ this.alertQueue.splice(index, 1);
446
+ }
447
+ }
448
+
449
+ dismissAlert(): void {
450
+ this.clearAllAlerts();
451
+ }
452
+
362
453
  toast(options: Object): void {
363
454
  if (options && typeof options === 'object') {
364
455
  const toastOptions = options as ToastOptions;
@@ -391,18 +482,6 @@ export class TingTurboModule extends TurboModule implements TM.Ting.Spec {
391
482
  }
392
483
  }
393
484
 
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
485
  setup(options: Object): void {
407
486
  const opts = options as Options;
408
487
  this.alertOptionInit = opts.alert;
@@ -528,4 +607,4 @@ export class TingTurboModule extends TurboModule implements TM.Ting.Spec {
528
607
  }
529
608
  return path;
530
609
  }
531
- }
610
+ }
@@ -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.2",
3
+ "version": "1.3.0-rc.4",
4
4
  "description": "test",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -42,7 +42,6 @@
42
42
  "registry": "https://registry.npmjs.org/"
43
43
  },
44
44
  "devDependencies": {
45
- "@evilmartians/lefthook": "^1.2.2",
46
45
  "@commitlint/config-conventional": "^17.0.2",
47
46
  "@evilmartians/lefthook": "^1.5.0",
48
47
  "@react-native/eslint-config": "^0.73.1",
@@ -58,9 +57,9 @@
58
57
  "jest": "^29.7.0",
59
58
  "pod-install": "^0.1.0",
60
59
  "prettier": "^3.0.3",
61
- "react": "18.3.1",
62
- "react-native": "0.77.1",
63
- "react-native-builder-bob": "^0.20.0",
60
+ "react": "18.3.1",
61
+ "react-native": "0.77.1",
62
+ "react-native-builder-bob": "^0.20.4",
64
63
  "release-it": "^15.0.0",
65
64
  "turbo": "^1.10.7",
66
65
  "typescript": "^5.2.2"