Skip to content

๐Ÿ”€ :: (#956) AI ์ฑ—๋ด‡ ์ฑ„ํŒ… ํ™”๋ฉด ์‚ฌ์šฉ์„ฑ ๊ฐœ์„ #957

Merged
ashxom merged 20 commits into
developfrom
bug/956-ai-์ฑ—๋ด‡-์ฑ„ํŒ…-ํ™”๋ฉด-์‚ฌ์šฉ์„ฑ-๊ฐœ์„ 
Jul 7, 2026

Hidden character warning

The head ref may contain hidden characters: "bug/956-ai-\ucc57\ubd07-\ucc44\ud305-\ud654\uba74-\uc0ac\uc6a9\uc131-\uac1c\uc120"
Merged

๐Ÿ”€ :: (#956) AI ์ฑ—๋ด‡ ์ฑ„ํŒ… ํ™”๋ฉด ์‚ฌ์šฉ์„ฑ ๊ฐœ์„ #957
ashxom merged 20 commits into
developfrom
bug/956-ai-์ฑ—๋ด‡-์ฑ„ํŒ…-ํ™”๋ฉด-์‚ฌ์šฉ์„ฑ-๊ฐœ์„ 

Conversation

@ashxom

@ashxom ashxom commented Jul 6, 2026

Copy link
Copy Markdown
Member

๊ฐœ์š”

  • ํ‚ค๋ณด๋“œ ํ‘œ์‹œ ์‹œ Bottom Navigation์ด ์‚ฌ๋ผ์ง€๋Š” ๋ฌธ์ œ ์ˆ˜์ •
  • AI ์‘๋‹ต Markdown ๋ Œ๋”๋ง ์ง€์›
  • ํ‚ค๋ณด๋“œ ํ‘œ์‹œ ์‹œ ์ฑ„ํŒ… ํ•˜๋‹จ ์ฝ˜ํ…์ธ ๊ฐ€ ์ž˜๋ฆฌ๊ณ  ์Šคํฌ๋กค๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ ์ˆ˜์ •

์ž‘์—…์‚ฌํ•ญ

์ถ”๊ฐ€ ๋กœ ํ•  ๋ง

Summary by CodeRabbit

  • New Features

    • Chatbot messages now render richer formatting, including bold text and cleaner bullet lists.
    • The chatbot typing indicator now uses an animated dot sequence for clearer activity feedback.
  • Bug Fixes

    • Bottom navigation visibility now tracks the active screen more reliably.
    • The chatbot input and message spacing were improved, adjusting smoothly with the on-screen keyboard and providing better readability while the assistant is typing.

@ashxom ashxom self-assigned this Jul 6, 2026
@ashxom ashxom added the ๐Ÿ‘พbug ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ label Jul 6, 2026
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ashxom, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 53 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
โš™๏ธ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e98f1ba9-0af0-4a1c-b6dc-62b30e87c0d4

๐Ÿ“ฅ Commits

Reviewing files that changed from the base of the PR and between 34fc989 and a8cb58b.

๐Ÿ“’ Files selected for processing (1)
  • feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/component/ChatBotTypingIndicator.kt
๐Ÿ“ Walkthrough

Walkthrough

DmsApp now derives bottom-bar visibility from the navigation back stack, ChatBotScreen uses IME-driven layout spacing, ChatBotMessageBubble renders markdown-styled text, and ChatBotTypingIndicator now animates three dots.

Changes

Chatbot and navigation updates

Layer / File(s) Summary
Route-based bottom bar visibility in DmsApp
app/src/main/kotlin/team/aliens/dms/android/app/ui/DmsApp.kt
currentScreen is derived from the back stack, and shouldShowBottomBar is set by membership in a fixed route list, replacing focus-dependent logic; onInputFocusChange callback wiring is removed. Imports and several route entries are reformatted.
Keyboard-driven chatbot layout
feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/ChatBotScreen.kt
IME insets drive animated input padding and message bottom spacing, a bottom background area is added, and the input bar uses computed padding instead of imePadding().
Markdown chat message rendering
feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/component/ChatBotMessageBubble.kt
User messages render as AnnotatedString, and non-user messages are converted from markdown bullets and bold spans into styled annotated text.
Animated typing indicator
feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/component/ChatBotTypingIndicator.kt
The typing indicator now renders three staggered animated dots with infinite transitions, offset motion, and opacity animation.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related issues

  • team-aliens/DMS-Android#956: Matches the chatbot UX changes across bottom navigation visibility, IME-driven layout, and markdown rendering.

Possibly related PRs

  • team-aliens/DMS-Android#955: Touches the same chatbot navigation wiring and UI components, including the focus-related flow removed here.

Suggested labels: feat

๐Ÿšฅ Pre-merge checks | โœ… 5
โœ… Passed checks (5 passed)
Check name Status Explanation
Description Check โœ… Passed Check skipped - CodeRabbitโ€™s high-level summary is enabled.
Title check โœ… Passed The title clearly matches the main change: improving the AI chatbot chat screen usability.
Docstring Coverage โœ… Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check โœ… Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check โœ… Passed Check skipped because no linked issues were found for this pull request.
โœจ Finishing Touches
๐Ÿงช Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bug/956-ai-์ฑ—๋ด‡-์ฑ„ํŒ…-ํ™”๋ฉด-์‚ฌ์šฉ์„ฑ-๊ฐœ์„ 

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

โค๏ธ Share

Comment @coderabbitai help to get the list of available commands.

PointHistoryRoute(
pointType = it.pointType,
onBackClick = { backStack.remove(PointHistoryScreenNav(it.pointType)) }
onBackClick = { backStack.remove(PointHistoryScreenNav(it.pointType)) },

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and canโ€™t be posted inline due to platform limitations.

โš ๏ธ Outside diff range comments (1)
feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/ChatBotScreen.kt (1)

100-155: ๐Ÿฉบ Stability & Availability | ๐ŸŸก Minor | โšก Quick win

Handle IME insets for the persistent bottom bar
ChatBotInputBar only applies imePadding(), while DmsApp keeps the bottom bar visible with no bottom-window insets, so the chat input can be obscured or collide with the keyboard on edge-to-edge screens. Add bottom/IME inset handling at the scaffold or bottom-bar level.

๐Ÿค– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/ChatBotScreen.kt`
around lines 100 - 155, ChatBotInputBar currently only relies on imePadding(),
so the persistent bottom bar can still overlap the keyboard on edge-to-edge
screens. Update the chat screen layout around ChatBotScreen and ChatBotInputBar
to apply proper bottom/IME window inset handling at the scaffold or bottom-bar
level, ensuring the input bar stays above the keyboard and respects system
bottom insets when isInputFocused changes.
๐Ÿงน Nitpick comments (4)
app/src/main/kotlin/team/aliens/dms/android/app/ui/DmsApp.kt (1)

101-141: ๐Ÿ“ Maintainability & Code Quality | ๐Ÿ”ต Trivial | โšก Quick win

Bottom-tab route set is duplicated in two different forms.

The route membership check at Lines 102-107 (currentScreen in listOf(...)) and the removal filter at Lines 135-138 (it is HomeScreenNav || ...) encode the same "bottom-tab routes" concept twice, using different comparison styles (equality vs. is). If a new bottom-tab destination is added later, it's easy to update one list and forget the other, silently breaking bottom bar visibility or back-stack cleanup.

โ™ป๏ธ Suggested consolidation
+    val bottomTabRoutes = remember {
+        setOf(HomeScreenNav, ApplicationScreenNav, ChatBotScreenNav, MyPageScreenNav)
+    }
     val currentScreen = backStack.lastOrNull()
-    val shouldShowBottomBar = currentScreen in listOf(
-        HomeScreenNav,
-        ApplicationScreenNav,
-        ChatBotScreenNav,
-        MyPageScreenNav,
-    )
+    val shouldShowBottomBar = currentScreen in bottomTabRoutes
                             if (currentScreen != destination) {
-                                backStack.removeAll {
-                                    it is HomeScreenNav ||
-                                            it is ApplicationScreenNav ||
-                                            it is ChatBotScreenNav ||
-                                            it is MyPageScreenNav
-                                }
+                                backStack.removeAll { it in bottomTabRoutes }
                                 backStack.add(destination)
                             }
๐Ÿค– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/kotlin/team/aliens/dms/android/app/ui/DmsApp.kt` around lines
101 - 141, The bottom-tab route set is duplicated in DmsApp between the
`shouldShowBottomBar` membership check and the `onNavigate` back-stack cleanup
in `BottomNavigationBar`. Consolidate this shared concept into a single reusable
bottom-tab route helper or collection and use it both for the visibility check
and the removal predicate so new routes only need to be added in one place.
feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/component/ChatBotMessageBubble.kt (2)

34-39: ๐Ÿš€ Performance & Scalability | ๐Ÿ”ต Trivial | โšก Quick win

Markdown conversion is recomputed on every recomposition.

text.toChatBotMarkdownText() runs its regex passes and rebuilds the AnnotatedString on every recomposition of ChatBotMessageBubble, even though text for a given message is static once appended. Wrap it in remember(text) to avoid redundant regex work, especially since this bubble is re-created as items scroll in/out of a LazyColumn.

โ™ป๏ธ Proposed fix
         Text(
             modifier = Modifier.padding(horizontal = 18.dp, vertical = 14.dp),
             text = if (isUser) {
                 AnnotatedString(text)
             } else {
-                text.toChatBotMarkdownText()
+                remember(text) { text.toChatBotMarkdownText() }
             },
๐Ÿค– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/component/ChatBotMessageBubble.kt`
around lines 34 - 39, The markdown parsing in ChatBotMessageBubble is recomputed
on every recomposition because text.toChatBotMarkdownText() is called directly
in the text assignment. Cache the converted AnnotatedString with remember(text)
inside ChatBotMessageBubble so the conversion only reruns when the message text
changes, while still keeping the existing isUser branch unchanged.

63-86: ๐ŸŽฏ Functional Correctness | ๐Ÿ”ต Trivial | ๐Ÿ’ค Low value

Bullet conversion only recognizes * prefixes, not - or numbered lists.

LLM-generated markdown commonly uses - for bullets and 1. for ordered lists; those will render as raw literal characters instead of styled list markers. Given the feature is explicitly scoped to "bullets and bold," this is acceptable for now, but consider extending the regex to also match -\s+ if answers commonly use dash bullets.

๐Ÿค– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/component/ChatBotMessageBubble.kt`
around lines 63 - 86, The bullet conversion in toChatBotMarkdownText only
handles "*" prefixes, so dash bullets still render as raw text; update the regex
in String.toChatBotMarkdownText to also match "-" bullet prefixes (while keeping
the current bold handling in AnnotatedString) so common LLM bullet formats are
normalized consistently.
feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/ChatBotScreen.kt (1)

105-112: ๐Ÿ“ Maintainability & Code Quality | ๐Ÿ”ต Trivial | โšก Quick win

Hardcoded bottom padding values are brittle given the new "always-visible" bottom bar behavior.

The 180.dp/220.dp bottom padding is a magic-number guess meant to clear the input bar and (per the sibling layer) the now-always-visible outer bottom navigation bar plus keyboard. If the actual heights of the input bar, bottom nav bar, or IME differ across devices/font scales, content will again be clipped or over-padded โ€” the exact bug this PR is fixing. Consider deriving this padding from measured component heights (onSizeChanged/onGloballyPositioned) or from WindowInsets.ime/WindowInsets.navigationBars instead of fixed constants.

๐Ÿค– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/ChatBotScreen.kt`
around lines 105 - 112, The bottom content padding in ChatBotScreen is using
brittle magic numbers, so replace the fixed 180.dp/220.dp values with padding
derived from actual UI measurements or insets. Update the contentPadding logic
in ChatBotScreen to account for the input bar and always-visible bottom
navigation bar using measured component heights (for example via onSizeChanged
or onGloballyPositioned) and/or WindowInsets.ime plus
WindowInsets.navigationBars, so the spacing stays correct across devices, font
scales, and keyboard states.
๐Ÿค– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/ChatBotScreen.kt`:
- Around line 100-155: ChatBotInputBar currently only relies on imePadding(), so
the persistent bottom bar can still overlap the keyboard on edge-to-edge
screens. Update the chat screen layout around ChatBotScreen and ChatBotInputBar
to apply proper bottom/IME window inset handling at the scaffold or bottom-bar
level, ensuring the input bar stays above the keyboard and respects system
bottom insets when isInputFocused changes.

---

Nitpick comments:
In `@app/src/main/kotlin/team/aliens/dms/android/app/ui/DmsApp.kt`:
- Around line 101-141: The bottom-tab route set is duplicated in DmsApp between
the `shouldShowBottomBar` membership check and the `onNavigate` back-stack
cleanup in `BottomNavigationBar`. Consolidate this shared concept into a single
reusable bottom-tab route helper or collection and use it both for the
visibility check and the removal predicate so new routes only need to be added
in one place.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/ChatBotScreen.kt`:
- Around line 105-112: The bottom content padding in ChatBotScreen is using
brittle magic numbers, so replace the fixed 180.dp/220.dp values with padding
derived from actual UI measurements or insets. Update the contentPadding logic
in ChatBotScreen to account for the input bar and always-visible bottom
navigation bar using measured component heights (for example via onSizeChanged
or onGloballyPositioned) and/or WindowInsets.ime plus
WindowInsets.navigationBars, so the spacing stays correct across devices, font
scales, and keyboard states.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/component/ChatBotMessageBubble.kt`:
- Around line 34-39: The markdown parsing in ChatBotMessageBubble is recomputed
on every recomposition because text.toChatBotMarkdownText() is called directly
in the text assignment. Cache the converted AnnotatedString with remember(text)
inside ChatBotMessageBubble so the conversion only reruns when the message text
changes, while still keeping the existing isUser branch unchanged.
- Around line 63-86: The bullet conversion in toChatBotMarkdownText only handles
"*" prefixes, so dash bullets still render as raw text; update the regex in
String.toChatBotMarkdownText to also match "-" bullet prefixes (while keeping
the current bold handling in AnnotatedString) so common LLM bullet formats are
normalized consistently.

โ„น๏ธ Review info
โš™๏ธ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 695814b8-de69-462b-8090-edf480c7d229

๐Ÿ“ฅ Commits

Reviewing files that changed from the base of the PR and between e5652b5 and 5239d4f.

๐Ÿ“’ Files selected for processing (3)
  • app/src/main/kotlin/team/aliens/dms/android/app/ui/DmsApp.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/ChatBotScreen.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/component/ChatBotMessageBubble.kt

ashxom added 16 commits July 6, 2026 22:34

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๐Ÿงน Nitpick comments (2)
feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/component/ChatBotTypingIndicator.kt (2)

26-91: ๐Ÿ“ Maintainability & Code Quality | ๐Ÿ”ต Trivial | โšก Quick win

Consider a text alternative for screen readers.

The typing indicator conveys "AI is responding" purely visually via animated dots, with no contentDescription/semantics for assistive technology.

๐Ÿค– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/component/ChatBotTypingIndicator.kt`
around lines 26 - 91, The ChatBotTypingIndicator UI is purely visual and needs a
screen-reader alternative. Add appropriate Compose semantics in
ChatBotTypingIndicator and/or ChatBotTypingDot so assistive tech can announce
that the AI is responding, using the existing ChatBotTypingIndicator and
ChatBotTypingDot components as the place to attach the text alternative without
changing the animation behavior.

42-76: ๐Ÿ“ Maintainability & Code Quality | ๐Ÿ”ต Trivial | โšก Quick win

Prefer initialStartOffset instead of embedding delay into keyframe timestamps.

The staggering is implemented by baking delayMillis into each keyframe's timestamp, duplicated across the offsetY and alpha specs. Compose provides initialStartOffset on infiniteRepeatable specifically for this staggered-start use case, which avoids the timestamp arithmetic and keeps each dot's keyframes block identical.

โ™ป๏ธ Simplify using initialStartOffset
     val offsetY by infiniteTransition.animateFloat(
         initialValue = 0f,
         targetValue = -4f,
         animationSpec = infiniteRepeatable(
             animation = keyframes {
                 durationMillis = 720
-                0f at delayMillis
-                -4f at delayMillis + 180
-                0f at delayMillis + 360
-                0f at 720
+                0f at 0
+                -4f at 180
+                0f at 360
+                0f at 720
             },
             repeatMode = RepeatMode.Restart,
+            initialStartOffset = StartOffset(delayMillis, StartOffsetType.Delay),
         ),
         label = "ChatBotTypingDotOffset",
     )

Verify this behaves as expected across API levels (initialStartOffset requires Compose animation-core โ‰ฅ1.1.0).

๐Ÿค– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/component/ChatBotTypingIndicator.kt`
around lines 42 - 76, The staggered animation in ChatBotTypingIndicatorโ€™s
rememberInfiniteTransition setup is hardcoded by adding delayMillis into each
keyframe timestamp, and this duplicated arithmetic should be replaced with
initialStartOffset on infiniteRepeatable. Update the offsetY and alpha
animationSpec blocks so their keyframes stay identical and the per-dot delay is
applied via initialStartOffset instead of timestamp offsets, keeping the
animation behavior the same while simplifying the code. Ensure the change still
works with the Compose animation-core version used by this module.
๐Ÿค– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/component/ChatBotTypingIndicator.kt`:
- Around line 26-91: The ChatBotTypingIndicator UI is purely visual and needs a
screen-reader alternative. Add appropriate Compose semantics in
ChatBotTypingIndicator and/or ChatBotTypingDot so assistive tech can announce
that the AI is responding, using the existing ChatBotTypingIndicator and
ChatBotTypingDot components as the place to attach the text alternative without
changing the animation behavior.
- Around line 42-76: The staggered animation in ChatBotTypingIndicatorโ€™s
rememberInfiniteTransition setup is hardcoded by adding delayMillis into each
keyframe timestamp, and this duplicated arithmetic should be replaced with
initialStartOffset on infiniteRepeatable. Update the offsetY and alpha
animationSpec blocks so their keyframes stay identical and the per-dot delay is
applied via initialStartOffset instead of timestamp offsets, keeping the
animation behavior the same while simplifying the code. Ensure the change still
works with the Compose animation-core version used by this module.

โ„น๏ธ Review info
โš™๏ธ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b4787d30-0c90-4f4e-8f90-b5af20891fe4

๐Ÿ“ฅ Commits

Reviewing files that changed from the base of the PR and between 5239d4f and 34fc989.

๐Ÿ“’ Files selected for processing (3)
  • app/src/main/kotlin/team/aliens/dms/android/app/ui/DmsApp.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/ChatBotScreen.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/component/ChatBotTypingIndicator.kt
๐Ÿ’ค Files with no reviewable changes (1)
  • app/src/main/kotlin/team/aliens/dms/android/app/ui/DmsApp.kt

@ashxom
ashxom merged commit bf2f89c into develop Jul 7, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

๐Ÿ‘พbug ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AI ์ฑ—๋ด‡ ์ฑ„ํŒ… ํ™”๋ฉด ์‚ฌ์šฉ์„ฑ ๊ฐœ์„ 

2 participants