Skip to content

Commit 142d6c5

Browse files
committed
适配capi
1 parent 72bcccd commit 142d6c5

24 files changed

+292
-114
lines changed

harmony/maps/BuildProfile.ets

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export default class BuildProfile {
2-
static readonly HAR_VERSION = '1.0.0';
2+
static readonly HAR_VERSION = '1.10.3-0.0.4';
33
static readonly BUILD_MODE_NAME = 'debug';
44
static readonly DEBUG = true;
5+
static readonly TARGET_NAME = 'default';
56
}

harmony/maps/oh-package.json5

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
2-
"name": "maps",
3-
"version": "1.0.0",
4-
"description": "Please describe the basic information.",
2+
"name": "@react-native-oh-tpl/react-native-maps",
3+
"version": "1.10.3-0.0.4",
4+
"description": "Map for React Native",
55
"main": "Index.ets",
66
"author": "",
77
"license": "Apache-2.0",
88
"dependencies": {
9-
"rnoh": "file:../rnoh"
9+
"@rnoh/react-native-openharmony": "file:../react_native_openharmony"
1010
}
1111
}

harmony/maps/src/main/cpp/MapsPackage.h

-15
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#include "ComponentDescriptors.h"
22
#include "RNOH/Package.h"
33
#include "MapsJSIBinder.h"
4-
#include "MapsNapiBinder.h"
54
#include "MapsEventEmitRequestHandler.h"
65
#include "AIRMapManagerTurboModule.h"
76

@@ -55,20 +54,6 @@ namespace rnoh {
5554
facebook::react::AIRMapOverlayComponentDescriptor>()};
5655
};
5756

58-
ComponentNapiBinderByString createComponentNapiBinderByName() override {
59-
return {{"AIRMap", std::make_shared<AIRMapNapiBinder>()},
60-
{"AIRMapMarker", std::make_shared<AIRMapMarkerNapiBinder>()},
61-
{"AIRMapPolyline", std::make_shared<AIRMapPolylineNapiBinder>()},
62-
{"AIRMapPolygon", std::make_shared<AIRMapPolygonNapiBinder>()},
63-
{"AIRMapCircle", std::make_shared<AIRMapCircleNapiBinder>()},
64-
{"AIRMapCallout", std::make_shared<AIRMapCalloutNapiBinder>()},
65-
{"AIRMapCalloutSubview", std::make_shared<AIRMapCalloutSubviewNapiBinder>()},
66-
{"Geojson", std::make_shared<GeojsonNapiBinder>()},
67-
{"AIRMapUrlTile", std::make_shared<AIRMapUrlTileNapiBinder>()},
68-
{"AIRMapWMSTile", std::make_shared<AIRMapWMSTileNapiBinder>()},
69-
{"AIRMapOverlay", std::make_shared<AIRMapOverlayNapiBinder>()}};
70-
};
71-
7257
ComponentJSIBinderByString createComponentJSIBinderByName() override {
7358
return {{"AIRMap", std::make_shared<AIRMapJSIBinder>()},
7459
{"AIRMapMarker", std::make_shared<AIRMapMarkerJSIBinder>()},

harmony/maps/src/main/cpp/ShadowNodes.h

+12-14
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@
1111
#pragma once
1212

1313
#include "EventEmitters.h"
14-
#include "Props.h"
15-
#include "States.h"
1614
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
15+
#include <react/renderer/components/view/ViewShadowNode.h>
1716
#include <jsi/jsi.h>
1817

1918
namespace facebook {
@@ -44,28 +43,27 @@ JSI_EXPORT extern const char AIRMapOverlayComponentName[];
4443
/*
4544
* `ShadowNode` for <AIRMap> component.
4645
*/
47-
using AIRMapShadowNode = ConcreteViewShadowNode<AIRMapComponentName, AIRMapProps, AIRMapEventEmitter, AIRMapState>;
46+
using AIRMapShadowNode = ConcreteViewShadowNode<AIRMapComponentName, ViewProps, AIRMapEventEmitter>;
4847

49-
using AIRMapMarkerShadowNode = ConcreteViewShadowNode<AIRMapMarkerComponentName, AIRMapMarkerProps, AIRMapMarkerEventEmitter, AIRMapMarkerState>;
48+
using AIRMapMarkerShadowNode = ConcreteViewShadowNode<AIRMapMarkerComponentName, ViewProps, AIRMapMarkerEventEmitter>;
5049

51-
using AIRMapPolylineShadowNode = ConcreteViewShadowNode<AIRMapPolylineComponentName, AIRMapPolylineProps, AIRMapPolylineEventEmitter, AIRMapPolylineState>;
50+
using AIRMapPolylineShadowNode = ConcreteViewShadowNode<AIRMapPolylineComponentName, ViewProps, AIRMapPolylineEventEmitter>;
5251

53-
using AIRMapPolygonShadowNode = ConcreteViewShadowNode<AIRMapPolygonComponentName, AIRMapPolygonProps, AIRMapPolygonEventEmitter, AIRMapPolygonState>;
52+
using AIRMapPolygonShadowNode = ConcreteViewShadowNode<AIRMapPolygonComponentName, ViewProps, AIRMapPolygonEventEmitter>;
5453

55-
using AIRMapCircleShadowNode = ConcreteViewShadowNode<AIRMapCircleComponentName, AIRMapCircleProps, AIRMapCircleEventEmitter, AIRMapCircleState>;
54+
using AIRMapCircleShadowNode = ConcreteViewShadowNode<AIRMapCircleComponentName, ViewProps, AIRMapCircleEventEmitter>;
5655

57-
using AIRMapCalloutShadowNode = ConcreteViewShadowNode<AIRMapCalloutComponentName, AIRMapCalloutProps, AIRMapCalloutEventEmitter, AIRMapCalloutState>;
56+
using AIRMapCalloutShadowNode = ConcreteViewShadowNode<AIRMapCalloutComponentName, ViewProps, AIRMapCalloutEventEmitter>;
5857

59-
using AIRMapCalloutSubviewShadowNode = ConcreteViewShadowNode<AIRMapCalloutSubviewComponentName, AIRMapCalloutSubviewProps,
60-
AIRMapCalloutSubviewEventEmitter, AIRMapCalloutSubviewState>;
58+
using AIRMapCalloutSubviewShadowNode = ConcreteViewShadowNode<AIRMapCalloutSubviewComponentName, ViewProps, AIRMapCalloutSubviewEventEmitter>;
6159

62-
using GeojsonShadowNode =ConcreteViewShadowNode<GeojsonComponentName, GeojsonProps, GeojsonEventEmitter, GeojsonState>;
60+
using GeojsonShadowNode =ConcreteViewShadowNode<GeojsonComponentName, ViewProps, GeojsonEventEmitter>;
6361

64-
using AIRMapUrlTileShadowNode = ConcreteViewShadowNode<AIRMapUrlTileComponentName, AIRMapUrlTileProps, AIRMapUrlTileEventEmitter, AIRMapUrlTileState>;
62+
using AIRMapUrlTileShadowNode = ConcreteViewShadowNode<AIRMapUrlTileComponentName, ViewProps, AIRMapUrlTileEventEmitter>;
6563

66-
using AIRMapWMSTileShadowNode = ConcreteViewShadowNode<AIRMapWMSTileComponentName, AIRMapWMSTileProps, AIRMapWMSTileEventEmitter, AIRMapWMSTileState>;
64+
using AIRMapWMSTileShadowNode = ConcreteViewShadowNode<AIRMapWMSTileComponentName, ViewProps, AIRMapWMSTileEventEmitter>;
6765

68-
using AIRMapOverlayShadowNode = ConcreteViewShadowNode<AIRMapOverlayComponentName, AIRMapOverlayProps, AIRMapOverlayEventEmitter, AIRMapOverlayState>;
66+
using AIRMapOverlayShadowNode = ConcreteViewShadowNode<AIRMapOverlayComponentName, ViewProps, AIRMapOverlayEventEmitter>;
6967

7068
} // namespace react
7169
} // namespace facebook

harmony/maps/src/main/ets/AIRMaps/AIRMap.ets

+8-5
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@
2020
* SOFTWARE.
2121
*/
2222

23-
import { RNOHContext, RNViewBase, ComponentBuilderContext, Tag, rnComponentFactoryBuilder, } from 'rnoh';
23+
import { RNViewBase, Tag, RNComponentContext, ComponentBuilderContext} from '@rnoh/react-native-openharmony';
2424

2525
import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';
2626
import common from '@ohos.app.ability.common';
2727
import {map, mapCommon, MapComponent} from '@kit.MapKit'
2828
import { AsyncCallback, BusinessError } from '@kit.BasicServicesKit';
2929
import { bundleManager } from '@kit.AbilityKit';
3030

31+
import { mapsComponentFactoryBuilder } from '../MapsComponentFactory'
3132
import { Camera, DEFAULT_ZOOM, EdgePadding, LatLng, Region, TAG } from '../sharedTypes';
3233
import { MapsManager } from '../MapsManager';
3334
import { AIRMapDescriptor } from './AIRMapDescriptorTypes';
@@ -41,12 +42,10 @@ const permissions: Array<Permissions> = ['ohos.permission.INTERNET', 'ohos.permi
4142

4243
@Component
4344
export struct AIRMap {
44-
ctx!: RNOHContext
45+
ctx!: RNComponentContext
4546
tag: number = 0
4647
@BuilderParam public renderChildren: () => void
47-
@BuilderParam buildCustomComponent: (componentBuilderContext: ComponentBuilderContext) => void
4848
@State descriptor: AIRMapDescriptor = {} as AIRMapDescriptor
49-
5049
protected cleanUpCallbacks: (() => void)[] = []
5150
private callback?: AsyncCallback<map.MapComponentController>;
5251
private mapController?: map.MapComponentController = undefined;
@@ -326,7 +325,11 @@ export struct AIRMap {
326325
// 调用MapComponent组件初始化地图
327326
MapComponent({ mapOptions: this.mapOptions, mapCallback: this.callback }).width('100%').height('100%');
328327
ForEach(this.descriptor.childrenTags, (tag: Tag) => {
329-
rnComponentFactoryBuilder(this.ctx, tag, this.ctx.rnInstance.getComponentNameFromDescriptorType(this.ctx.descriptorRegistry.getDescriptor(tag)?.type))
328+
// this.ctx.wrappedRNChildrenBuilder.builder(this.ctx, tag)
329+
mapsComponentFactoryBuilder(
330+
this.ctx,
331+
tag,
332+
this.ctx.rnInstance.getComponentNameFromDescriptorType(this.ctx.descriptorRegistry.getDescriptor(tag)?.type))
330333
}, (tag: Tag) => tag.toString())
331334
}
332335
}

harmony/maps/src/main/ets/AIRMaps/AIRMapCallout.ets

+3-8
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,7 @@
2020
* SOFTWARE.
2121
*/
2222

23-
import { Descriptor, ComponentBuilderContext, ViewBaseProps, ViewRawProps, RNViewBase,
24-
rnComponentFactoryBuilder,
25-
Tag
26-
} from 'rnoh';
27-
import { RNOHContext } from 'rnoh'
23+
import { RNViewBase, Tag, RNComponentContext } from '@rnoh/react-native-openharmony';
2824
import { AIRMapCalloutDescriptor } from './AIRMapDescriptorTypes';
2925
import { MapsManager } from '../MapsManager';
3026
import { LWLog } from '../LWLog';
@@ -35,9 +31,8 @@ export const AIR_MAP_CALLOUT_TYPE: string = "AIRMapCallout"
3531

3632
@Component
3733
export struct AIRMapCallout {
38-
ctx!: RNOHContext
34+
ctx!: RNComponentContext
3935
tag: number = 0
40-
@BuilderParam buildCustomComponent: (componentBuilderContext: ComponentBuilderContext) => void
4136
@State descriptor: AIRMapCalloutDescriptor = {} as AIRMapCalloutDescriptor
4237
private unregisterDescriptorChangesListener?: () => void = undefined
4338

@@ -66,7 +61,7 @@ export struct AIRMapCallout {
6661
RNViewBase({ ctx: this.ctx, tag: this.tag }) {
6762
Stack(){
6863
ForEach(this.descriptor.childrenTags, (tag: Tag) => {
69-
rnComponentFactoryBuilder(this.ctx, tag, this.ctx.rnInstance.getComponentNameFromDescriptorType(this.ctx.descriptorRegistry.getDescriptor(tag)?.type))
64+
7065
}, (tag: Tag) => tag.toString())
7166
}
7267
}

harmony/maps/src/main/ets/AIRMaps/AIRMapCalloutSubview.ets

+3-6
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,7 @@
2020
* SOFTWARE.
2121
*/
2222

23-
import { Descriptor, ComponentBuilderContext, ViewBaseProps, ViewRawProps, RNViewBase, Tag,
24-
rnComponentFactoryBuilder } from 'rnoh';
25-
import { RNOHContext } from 'rnoh'
26-
import { LatLng, Region, TAG } from '../sharedTypes';
23+
import { ComponentBuilderContext, RNComponentContext, RNViewBase, Tag } from '@rnoh/react-native-openharmony';
2724
import { MapsManager } from '../MapsManager';
2825
import { AIRMapCalloutSubviewDescriptor } from './AIRMapDescriptorTypes';
2926
import { LWLog } from '../LWLog';
@@ -33,7 +30,7 @@ export const AIR_MAP_CALLOUT_SUBVIEW_TYPE: string = "AIRMapCalloutSubview"
3330
//todo 不支持自定义view显示
3431
@Component
3532
export struct AIRMapCalloutSubview {
36-
ctx!: RNOHContext
33+
ctx!: RNComponentContext
3734
tag: number = 0
3835
@BuilderParam buildCustomComponent: (componentBuilderContext: ComponentBuilderContext) => void
3936
@State descriptor: AIRMapCalloutSubviewDescriptor = {} as AIRMapCalloutSubviewDescriptor
@@ -61,7 +58,7 @@ export struct AIRMapCalloutSubview {
6158
RNViewBase({ ctx: this.ctx, tag: this.tag }) {
6259
Stack(){
6360
ForEach(this.descriptor.childrenTags, (tag: Tag) => {
64-
rnComponentFactoryBuilder(this.ctx, tag, this.ctx.rnInstance.getComponentNameFromDescriptorType(this.ctx.descriptorRegistry.getDescriptor(tag)?.type))
61+
6562
}, (tag: Tag) => tag.toString())
6663
}
6764
}

harmony/maps/src/main/ets/AIRMaps/AIRMapCircle.ets

+2-4
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@
2020
* SOFTWARE.
2121
*/
2222

23-
import { Descriptor, ComponentBuilderContext, ViewBaseProps, ViewRawProps } from 'rnoh';
24-
import { RNOHContext } from 'rnoh'
25-
import { LatLng, Region, TAG } from '../sharedTypes';
23+
import { ComponentBuilderContext, RNComponentContext } from '@rnoh/react-native-openharmony';
2624
import { AIRMapCircleDescriptor } from './AIRMapDescriptorTypes';
2725
import { MapsManager } from '../MapsManager';
2826
import { LWLog } from '../LWLog';
@@ -33,7 +31,7 @@ export const AIR_MAP_CIRCLE_TYPE: string = "AIRMapCircle"
3331

3432
@Component
3533
export struct AIRMapCircle {
36-
ctx!: RNOHContext
34+
ctx!: RNComponentContext
3735
tag: number = 0
3836
@BuilderParam buildCustomComponent: (componentBuilderContext: ComponentBuilderContext) => void
3937
@State descriptor: AIRMapCircleDescriptor = {} as AIRMapCircleDescriptor

harmony/maps/src/main/ets/AIRMaps/AIRMapDescriptorTypes.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020
* SOFTWARE.
2121
*/
2222

23-
import { Descriptor, ViewBaseProps, ViewRawProps } from 'rnoh/ts';
23+
import { Descriptor, ViewBaseProps, ViewRawProps } from '@rnoh/react-native-openharmony/ts';
2424
import { Camera, EdgePadding, LatLng, MapStyleElement, MapType, Region, Point, GeoJSON } from '../sharedTypes';
2525

2626
export interface AIRMapState {}
27-
export interface AIRMapProps extends ViewRawProps {
27+
export interface AIRMapRawProps extends ViewRawProps {
2828
cacheEnabled?: boolean;
2929
camera?: Camera;
3030
customMapStyle?: MapStyleElement[];
@@ -59,8 +59,7 @@ export interface AIRMapProps extends ViewRawProps {
5959
provider: string;
6060
userLocationAnnotationTitle: string;
6161
}
62-
// export type AIRMapDescriptor = Descriptor<"AIRMap", AIRMapProps>
63-
export type AIRMapDescriptor = Descriptor<"AIRMap", ViewBaseProps, AIRMapState, AIRMapProps>
62+
export type AIRMapDescriptor = Descriptor<"AIRMap", ViewBaseProps, AIRMapState, AIRMapRawProps>
6463

6564
export interface AIRMapMarkerState {}
6665
export interface AIRMapMarkerRawProps extends ViewRawProps {

harmony/maps/src/main/ets/AIRMaps/AIRMapManager.ts

+18-1
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,27 @@
2020
* SOFTWARE.
2121
*/
2222

23-
import { TurboModule, RNOHError } from 'rnoh/ts';
23+
import { TurboModule, RNOHError, RNOHContext } from '@rnoh/react-native-openharmony/ts';
2424
import { MapsTurboManager } from '../MapsTurboManager';
2525
import { Camera, EdgePadding, LatLng, Point, Region, SnapshotOptions, TAG } from '../sharedTypes';
2626

2727
export class AIRMapManager extends TurboModule {
28+
// constructor(ctx: RNOHContext) {
29+
// super(ctx);
30+
// MapsTurboManager.getInstance().
31+
// ctx.descriptorRegistry.subscribeToDescriptorChanges(this.tag,
32+
// (newDescriptor) => {
33+
//
34+
// this.descriptor = (newDescriptor as AIRMapDescriptor)
35+
// LWLog('AIRMap.subscribeToDescriptorChanges=' + JSON.stringify(newDescriptor))
36+
// }
37+
// )
38+
// }
39+
40+
public __onDestroy__(): void {
41+
}
42+
43+
2844

2945
/**
3046
* Like animateCamera, but sets the new view instantly, without an animation.
@@ -108,6 +124,7 @@ export class AIRMapManager extends TurboModule {
108124
*/
109125
public getMarkersFrames(onlyVisible: Boolean){
110126
//todo 华为地图不支持
127+
MapsTurboManager.getInstance().getMarkersFrames(onlyVisible);
111128
}
112129

113130
public animateToRegion(region: Region, duration: number) {

harmony/maps/src/main/ets/AIRMaps/AIRMapMarker.ets

+9-7
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,7 @@
2020
* SOFTWARE.
2121
*/
2222

23-
import { Descriptor, ComponentBuilderContext, ViewBaseProps, ViewRawProps, rnComponentFactoryBuilder, Tag,
24-
RNViewManager } from 'rnoh';
25-
import { RNOHContext, RNViewBase } from 'rnoh'
26-
import { ImageURISource, Region, TAG } from '../sharedTypes';
23+
import { RNViewBase, ComponentBuilderContext, Tag, RNComponentContext } from '@rnoh/react-native-openharmony';
2724
import { MapsManager } from '../MapsManager';
2825
import { mapCommon, map } from '@kit.MapKit';
2926
import { AIRMapMarkerDescriptor } from './AIRMapDescriptorTypes';
@@ -33,7 +30,7 @@ export const AIR_MAP_MARKER_TYPE: string = "AIRMapMarker"
3330

3431
@Component
3532
export struct AIRMapMarker {
36-
ctx!: RNOHContext
33+
ctx!: RNComponentContext
3734
tag: number = 0
3835
@BuilderParam buildCustomComponent: (componentBuilderContext: ComponentBuilderContext) => void
3936
@State descriptor: AIRMapMarkerDescriptor = {} as AIRMapMarkerDescriptor
@@ -75,7 +72,12 @@ export struct AIRMapMarker {
7572
} else if (command === 'redrawCallout') {
7673
//todo 华为地图不支持 当infoWindow为自定义view的时候,调用此方法更新infoWindow里的内容
7774
} else if (command === 'animateMarkerToCoordinate') {
78-
//todo 华为地图不支持
75+
let animation = new map.TranslateAnimation(args[0]);
76+
if (args.length > 1) {
77+
animation.setDuration(args[1]);
78+
}
79+
this.marker?.setAnimation(animation);
80+
this.marker?.startAnimation();
7981
} else if (command === 'redraw') {
8082
this.marker?.remove();
8183
MapsManager.getInstance().addMarker(this, false);
@@ -105,7 +107,7 @@ export struct AIRMapMarker {
105107
RNViewBase({ ctx: this.ctx, tag: this.tag }) {
106108
Stack(){
107109
ForEach(this.descriptor.childrenTags, (tag: Tag) => {
108-
rnComponentFactoryBuilder(this.ctx, tag, this.ctx.rnInstance.getComponentNameFromDescriptorType(this.ctx.descriptorRegistry.getDescriptor(tag)?.type))
110+
109111
}, (tag: Tag) => tag.toString())
110112
}
111113
}

harmony/maps/src/main/ets/AIRMaps/AIRMapMarkerManager.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
* SOFTWARE.
2121
*/
2222

23-
import { TurboModule, RNOHError } from 'rnoh/ts';
23+
import { TurboModule, RNOHError } from '@rnoh/react-native-openharmony/ts';
2424
import { MapsTurboManager } from '../MapsTurboManager';
2525
import { Camera, LatLng, Point, Region, TAG } from '../sharedTypes';
2626

@@ -51,7 +51,7 @@ export class AIRMapMarkerManager extends TurboModule {
5151
* Animates marker movement. Note: Android only
5252
*/
5353
public animateMarkerToCoordinate(coordinate: LatLng, duration: number){
54-
//todo 华为地图不支持
54+
//todo 在Marker中实现
5555
}
5656

5757
/**

harmony/maps/src/main/ets/AIRMaps/AIRMapOverlay.ets

+3-8
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,7 @@
2020
* SOFTWARE.
2121
*/
2222

23-
import { Descriptor, ComponentBuilderContext, ViewBaseProps, ViewRawProps, RNViewBase,
24-
rnComponentFactoryBuilder,
25-
Tag
26-
} from 'rnoh';
27-
import { RNOHContext } from 'rnoh'
28-
import { LatLng, Region, TAG } from '../sharedTypes';
23+
import { ComponentBuilderContext, RNViewBase, Tag, RNComponentContext } from '@rnoh/react-native-openharmony';
2924
import { AIRMapOverlayDescriptor } from './AIRMapDescriptorTypes';
3025
import { MapsManager } from '../MapsManager';
3126
import { LWLog } from '../LWLog';
@@ -34,7 +29,7 @@ export const AIR_OVERLAY_TYPE: string = "AIRMapOverlay"
3429

3530
@Component
3631
export struct AIRMapOverlay {
37-
ctx!: RNOHContext
32+
ctx!: RNComponentContext
3833
tag: number = 0
3934
@BuilderParam buildCustomComponent: (componentBuilderContext: ComponentBuilderContext) => void
4035
@State descriptor: AIRMapOverlayDescriptor = {} as AIRMapOverlayDescriptor
@@ -66,7 +61,7 @@ export struct AIRMapOverlay {
6661
RNViewBase({ ctx: this.ctx, tag: this.tag }) {
6762
Stack(){
6863
ForEach(this.descriptor.childrenTags, (tag: Tag) => {
69-
rnComponentFactoryBuilder(this.ctx, tag, this.ctx.rnInstance.getComponentNameFromDescriptorType(this.ctx.descriptorRegistry.getDescriptor(tag)?.type))
64+
7065
}, (tag: Tag) => tag.toString())
7166
}
7267
}

0 commit comments

Comments
 (0)