Skip to content

Commit a162e93

Browse files
committed
Merge branches 'feat/multipath-overlay' and 'main' of github.com:mym0404/react-native-naver-map
2 parents b34fb75 + f6d8e79 commit a162e93

File tree

15 files changed

+798
-7
lines changed

15 files changed

+798
-7
lines changed

CLAUDE.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,9 @@ abstract class RNCNaverMapViewManagerSpec<T : ViewGroup> :
220220
override fun getDelegate(): ViewManagerDelegate<T>? = mDelegate
221221
}
222222
223+
ViewGroupManager or SimpleViewManager can be used based on the component type.
224+
Don't generate overriding functions by yourself. It is included in generated spec interface by codegen
225+
223226
// android/src/main/java/.../RNCNaverMapViewManager.kt
224227
class RNCNaverMapViewManager : RNCNaverMapViewManagerSpec<RNCNaverMapViewWrapper>() {
225228
@@ -320,3 +323,58 @@ To test the library, you need to configure API keys:
320323
- Documentation is auto-generated with TypeDoc from JSDoc comments
321324
- All native code changes require both iOS and Android implementations
322325
- Codegen runs automatically on build - regenerate with `yarn codegen` if specs change
326+
327+
# JSDoc & TypeDoc Documentation
328+
329+
JSDoc 형식으로 TypeDoc 호환 문서 작성:
330+
331+
```typescript
332+
/**
333+
* 네이티브 렌더링을 사용하는 네이버 지도 컴포넌트입니다.
334+
*/
335+
export const NaverMapView: React.FC<NaverMapViewProps> = (props) => {};
336+
337+
/**
338+
* 화면 좌표를 지리 좌표로 변환합니다.
339+
* @param x 화면 X 좌표
340+
* @param y 화면 Y 좌표
341+
* @returns LatLng를 반환하는 Promise
342+
*/
343+
screenToCoordinate(x: number, y: number): Promise<LatLng>;
344+
```
345+
346+
주요 태그: `@param`, `@returns`, `@example`, `@default`, `@internal`, `@platform`
347+
348+
# Package Scripts
349+
350+
## Development Scripts
351+
- `yarn dev` - Start development server for example app
352+
- `yarn ios` - Run example app on iOS simulator
353+
- `yarn android` - Run example app on Android emulator
354+
- `yarn studio` - Open Android Studio for the example project
355+
- `yarn xcode` - Open Xcode workspace for the example project
356+
357+
## Code Quality & Testing
358+
- `yarn typecheck` - Run TypeScript type checking without emitting files
359+
- `yarn lint` / `yarn t` - Run all linting checks (uses Lefthook)
360+
- `yarn format` - Format code using configured formatters (Biome)
361+
362+
## Build & Release
363+
- `yarn prepack` - Full build process: Expo plugin + docs + library build
364+
- `yarn build:expo-config-plugin` - Build Expo configuration plugin
365+
- `yarn build:docs` - Generate TypeDoc documentation
366+
- `yarn clean` - Clean all build directories
367+
- `yarn release` - Execute release script
368+
369+
## Native Development
370+
- `yarn codegen` - Generate native codegen artifacts for both platforms
371+
- `yarn codegen:android` - Generate Android codegen artifacts only
372+
- `yarn codegen:ios` - Generate iOS codegen artifacts only
373+
- `yarn pod` - Install iOS dependencies via CocoaPods
374+
- `yarn pod:update` - Update iOS dependencies via CocoaPods
375+
376+
## CI/CD Scripts
377+
- `yarn ci:ios` - Build iOS project for CI (xcodebuild)
378+
- `yarn ci:android` - Build Android project for CI (gradlew assembleDebug)
379+
- `yarn turbo:android` - Run Android CI with Turbo caching
380+
- `yarn turbo:ios` - Run iOS CI with Turbo caching

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,8 +656,8 @@ iOS에선 단순히 `UIView`를 `UIImage`로 캔버스에 그려 표시해줍니
656656
- [x] Implement Clustering (23.04.24)
657657
- [x] Implement ArrowheadPath Overlay (23.05.01)
658658
- [x] Implement Ground Overlay (23.05.01)
659+
- [x] Implement MutlPath Overlay (25.08.25)
659660
- [ ] Implement Location Overlay Commands <- 🔥
660-
- [ ] Implement MutlPath Overlay <- 🔥
661661

662662
## Contributing
663663

android/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ android {
7777
}
7878

7979
compileOptions {
80-
sourceCompatibility JavaVersion.VERSION_1_8
81-
targetCompatibility JavaVersion.VERSION_1_8
80+
sourceCompatibility JavaVersion.VERSION_17
81+
targetCompatibility JavaVersion.VERSION_17
8282
}
8383

8484
sourceSets {

android/src/main/java/com/mjstudio/reactnativenavermap/RNCNaverMapPackage.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import com.mjstudio.reactnativenavermap.overlay.arrowheadpath.RNCNaverMapArrowhe
99
import com.mjstudio.reactnativenavermap.overlay.circle.RNCNaverMapCircleManager
1010
import com.mjstudio.reactnativenavermap.overlay.ground.RNCNaverMapGroundManager
1111
import com.mjstudio.reactnativenavermap.overlay.marker.RNCNaverMapMarkerManager
12+
import com.mjstudio.reactnativenavermap.overlay.multipath.RNCNaverMapMultiPathManager
1213
import com.mjstudio.reactnativenavermap.overlay.path.RNCNaverMapPathManager
1314
import com.mjstudio.reactnativenavermap.overlay.polygon.RNCNaverMapPolygonManager
1415
import com.mjstudio.reactnativenavermap.overlay.polyline.RNCNaverMapPolylineManager
@@ -22,6 +23,7 @@ class RNCNaverMapPackage : ReactPackage {
2223
add(RNCNaverMapPolygonManager())
2324
add(RNCNaverMapPolylineManager())
2425
add(RNCNaverMapPathManager())
26+
add(RNCNaverMapMultiPathManager())
2527
add(RNCNaverMapArrowheadPathManager())
2628
add(RNCNaverMapGroundManager())
2729
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.mjstudio.reactnativenavermap.overlay.multipath
2+
3+
import android.annotation.SuppressLint
4+
import com.facebook.react.uimanager.ThemedReactContext
5+
import com.mjstudio.reactnativenavermap.event.NaverMapOverlayTapEvent
6+
import com.mjstudio.reactnativenavermap.util.emitEvent
7+
import com.mjstudio.reactnativenavermap.util.image.RNCNaverMapImageRenderableOverlay
8+
import com.naver.maps.geometry.LatLng
9+
import com.naver.maps.map.NaverMap
10+
import com.naver.maps.map.overlay.MultipartPathOverlay
11+
import com.naver.maps.map.overlay.OverlayImage
12+
13+
@SuppressLint("ViewConstructor")
14+
class RNCNaverMapMultiPath(
15+
val reactContext: ThemedReactContext,
16+
) : RNCNaverMapImageRenderableOverlay<MultipartPathOverlay>(reactContext) {
17+
override val overlay: MultipartPathOverlay by lazy {
18+
MultipartPathOverlay().apply {
19+
setOnClickListener {
20+
reactContext.emitEvent(id) { surfaceId, reactTag ->
21+
NaverMapOverlayTapEvent(
22+
surfaceId,
23+
reactTag,
24+
)
25+
}
26+
true
27+
}
28+
}
29+
}
30+
31+
fun setCoordParts(coordParts: List<List<LatLng>>) {
32+
overlay.coordParts = coordParts
33+
}
34+
35+
fun setColorParts(colorParts: List<MultipartPathOverlay.ColorPart>) {
36+
overlay.colorParts = colorParts
37+
}
38+
39+
override fun addToMap(map: NaverMap) {
40+
overlay.map = map
41+
}
42+
43+
override fun removeFromMap(map: NaverMap) {
44+
overlay.map = null
45+
}
46+
47+
override fun onDropViewInstance() {
48+
overlay.map = null
49+
overlay.onClickListener = null
50+
super.onDropViewInstance()
51+
}
52+
53+
override fun setOverlayAlpha(alpha: Float) {
54+
// MultipartPathOverlay doesn't support alpha directly
55+
}
56+
57+
override fun setOverlayImage(image: OverlayImage?) {
58+
overlay.patternImage = image
59+
}
60+
}
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
package com.mjstudio.reactnativenavermap.overlay.multipath
2+
3+
import com.facebook.react.bridge.ReadableArray
4+
import com.facebook.react.bridge.ReadableMap
5+
import com.facebook.react.uimanager.ThemedReactContext
6+
import com.facebook.react.uimanager.annotations.ReactProp
7+
import com.mjstudio.reactnativenavermap.RNCNaverMapMultiPathManagerSpec
8+
import com.mjstudio.reactnativenavermap.event.NaverMapOverlayTapEvent
9+
import com.mjstudio.reactnativenavermap.util.getLatLng
10+
import com.mjstudio.reactnativenavermap.util.isValidNumber
11+
import com.mjstudio.reactnativenavermap.util.px
12+
import com.mjstudio.reactnativenavermap.util.registerDirectEvent
13+
import com.naver.maps.map.overlay.MultipartPathOverlay
14+
15+
class RNCNaverMapMultiPathManager : RNCNaverMapMultiPathManagerSpec<RNCNaverMapMultiPath>() {
16+
override fun getName(): String = NAME
17+
18+
override fun createViewInstance(context: ThemedReactContext): RNCNaverMapMultiPath = RNCNaverMapMultiPath(context)
19+
20+
override fun onDropViewInstance(view: RNCNaverMapMultiPath) {
21+
super.onDropViewInstance(view)
22+
view.onDropViewInstance()
23+
}
24+
25+
override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> =
26+
(super.getExportedCustomDirectEventTypeConstants() ?: mutableMapOf()).apply {
27+
registerDirectEvent(this, NaverMapOverlayTapEvent.EVENT_NAME)
28+
}
29+
30+
private fun RNCNaverMapMultiPath?.withOverlay(fn: (MultipartPathOverlay) -> Unit) {
31+
this?.overlay?.run(fn)
32+
}
33+
34+
@ReactProp(name = "zIndexValue")
35+
override fun setZIndexValue(
36+
view: RNCNaverMapMultiPath?,
37+
value: Int,
38+
) = view.withOverlay {
39+
it.zIndex = value
40+
}
41+
42+
@ReactProp(name = "globalZIndexValue")
43+
override fun setGlobalZIndexValue(
44+
view: RNCNaverMapMultiPath?,
45+
value: Int,
46+
) = view.withOverlay {
47+
if (isValidNumber(value)) {
48+
it.globalZIndex = value
49+
}
50+
}
51+
52+
@ReactProp(name = "isHidden")
53+
override fun setIsHidden(
54+
view: RNCNaverMapMultiPath?,
55+
value: Boolean,
56+
) = view.withOverlay {
57+
it.isVisible = !value
58+
}
59+
60+
@ReactProp(name = "minZoom")
61+
override fun setMinZoom(
62+
view: RNCNaverMapMultiPath?,
63+
value: Double,
64+
) = view.withOverlay {
65+
it.minZoom = value
66+
}
67+
68+
@ReactProp(name = "maxZoom")
69+
override fun setMaxZoom(
70+
view: RNCNaverMapMultiPath?,
71+
value: Double,
72+
) = view.withOverlay {
73+
it.maxZoom = value
74+
}
75+
76+
@ReactProp(name = "isMinZoomInclusive")
77+
override fun setIsMinZoomInclusive(
78+
view: RNCNaverMapMultiPath?,
79+
value: Boolean,
80+
) = view.withOverlay {
81+
it.isMinZoomInclusive = value
82+
}
83+
84+
@ReactProp(name = "isMaxZoomInclusive")
85+
override fun setIsMaxZoomInclusive(
86+
view: RNCNaverMapMultiPath?,
87+
value: Boolean,
88+
) = view.withOverlay {
89+
it.isMaxZoomInclusive = value
90+
}
91+
92+
@Suppress("UNCHECKED_CAST")
93+
@ReactProp(name = "coordParts")
94+
override fun setCoordParts(
95+
view: RNCNaverMapMultiPath?,
96+
value: ReadableArray?,
97+
) {
98+
val coordParts =
99+
value?.toArrayList()?.map { coordPart ->
100+
(coordPart as? ArrayList<*>)?.map { coord ->
101+
(coord as Map<String, *>).getLatLng()
102+
} ?: listOf()
103+
} ?: listOf()
104+
view?.setCoordParts(coordParts)
105+
}
106+
107+
@Suppress("UNCHECKED_CAST")
108+
@ReactProp(name = "colorParts")
109+
override fun setColorParts(
110+
view: RNCNaverMapMultiPath?,
111+
value: ReadableArray?,
112+
) {
113+
val colorParts =
114+
value?.toArrayList()?.map { colorPart ->
115+
val colorMap = colorPart as Map<String, *>
116+
MultipartPathOverlay.ColorPart(
117+
colorMap["color"] as? Int ?: android.graphics.Color.BLACK,
118+
colorMap["passedColor"] as? Int ?: android.graphics.Color.BLACK,
119+
colorMap["outlineColor"] as? Int ?: android.graphics.Color.BLACK,
120+
colorMap["passedOutlineColor"] as? Int ?: android.graphics.Color.BLACK,
121+
)
122+
} ?: listOf()
123+
view?.setColorParts(colorParts)
124+
}
125+
126+
@ReactProp(name = "width")
127+
override fun setWidth(
128+
view: RNCNaverMapMultiPath?,
129+
value: Double,
130+
) = view.withOverlay {
131+
it.width = value.px
132+
}
133+
134+
@ReactProp(name = "outlineWidth")
135+
override fun setOutlineWidth(
136+
view: RNCNaverMapMultiPath?,
137+
value: Double,
138+
) = view.withOverlay {
139+
it.outlineWidth = value.px
140+
}
141+
142+
@ReactProp(name = "patternImage")
143+
override fun setPatternImage(
144+
view: RNCNaverMapMultiPath?,
145+
value: ReadableMap?,
146+
) {
147+
view?.setImage(value)
148+
}
149+
150+
@ReactProp(name = "patternInterval")
151+
override fun setPatternInterval(
152+
view: RNCNaverMapMultiPath?,
153+
value: Int,
154+
) = view.withOverlay {
155+
it.patternInterval = value
156+
}
157+
158+
@ReactProp(name = "isHideCollidedSymbols")
159+
override fun setIsHideCollidedSymbols(
160+
view: RNCNaverMapMultiPath?,
161+
value: Boolean,
162+
) = view.withOverlay {
163+
it.isHideCollidedSymbols = value
164+
}
165+
166+
@ReactProp(name = "isHideCollidedMarkers")
167+
override fun setIsHideCollidedMarkers(
168+
view: RNCNaverMapMultiPath?,
169+
value: Boolean,
170+
) = view.withOverlay {
171+
it.isHideCollidedMarkers = value
172+
}
173+
174+
@ReactProp(name = "isHideCollidedCaptions")
175+
override fun setIsHideCollidedCaptions(
176+
view: RNCNaverMapMultiPath?,
177+
value: Boolean,
178+
) = view.withOverlay {
179+
it.isHideCollidedCaptions = value
180+
}
181+
182+
companion object {
183+
const val NAME = "RNCNaverMapMultiPath"
184+
}
185+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.mjstudio.reactnativenavermap
2+
3+
import android.view.ViewGroup
4+
import com.facebook.react.uimanager.SimpleViewManager
5+
import com.facebook.react.uimanager.ViewManagerDelegate
6+
import com.facebook.react.viewmanagers.RNCNaverMapMultiPathManagerDelegate
7+
import com.facebook.react.viewmanagers.RNCNaverMapMultiPathManagerInterface
8+
9+
abstract class RNCNaverMapMultiPathManagerSpec<T : ViewGroup> :
10+
SimpleViewManager<T>(),
11+
RNCNaverMapMultiPathManagerInterface<T> {
12+
private val mDelegate: ViewManagerDelegate<T> = RNCNaverMapMultiPathManagerDelegate(this)
13+
14+
override fun getDelegate(): ViewManagerDelegate<T>? = mDelegate
15+
}

0 commit comments

Comments
 (0)