Skip to content

feat: 햅틱 적용#878

Open
Sadturtleman wants to merge 1 commit into
developfrom
feat/877
Open

feat: 햅틱 적용#878
Sadturtleman wants to merge 1 commit into
developfrom
feat/877

Conversation

@Sadturtleman
Copy link
Copy Markdown
Contributor

@Sadturtleman Sadturtleman commented May 14, 2026

📌𝘐𝘴𝘴𝘶𝘦𝘴

📎𝘞𝘰𝘳𝘬 𝘋𝘦𝘴𝘤𝘳𝘪𝘱𝘵𝘪𝘰𝘯

📷𝘚𝘤𝘳𝘦𝘦𝘯𝘴𝘩𝘰𝘵

💬𝘛𝘰 𝘙𝘦𝘷𝘪𝘦𝘸𝘦𝘳𝘴

별점 슬라이더에 햅틱 추가했습니다. 딱히 강도에 대한 이야기는 없어서 가장 대중적으로 사용되는 거 같은 햅틱으로 넣었습니다.

Summary by CodeRabbit

  • 신규 기능
    • 평가 범위 슬라이더에 햅틱 피드백 기능 추가: 사용자가 슬라이더를 드래그할 때 촉각적 반응을 통해 상호작용 경험 강화
    • 지능형 피드백 시스템: 슬라이더 값이 실제로 변경되는 시점에서만 피드백이 발생하여 자연스럽고 반응성 있는 인터페이스 경험 제공

Review Change Stack

@Sadturtleman Sadturtleman added 🍯 [FEAT] 새로운 기능을 개발합니다. 🧙마법사 하루 labels May 14, 2026
@github-actions github-actions Bot requested review from devfeijoa, m6z1 and s9hn May 14, 2026 00:47
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 14, 2026

둘러보기

RatingRangeSlider 컴포넌트에 드래그 제스처 중 햅틱 피드백을 추가했습니다. LocalView를 통해 뷰에 접근하고, 각 엄지손가락의 마지막 스냅 값을 추적한 후, 스냅 값이 변경될 때만 CLOCK_TICK 피드백을 트리거합니다.

변경 사항

별점 슬라이더 햅틱 피드백

계층 / 파일 설명
햅틱 피드백 임포트 및 상태 초기화
app/src/main/java/com/into/websoso/ui/detailExplore/component/RatingRangeSlider.kt
HapticFeedbackConstants와 LocalView 임포트를 추가하고, 최소 및 최대 엄지손가락의 마지막 스냅 값을 추적하기 위한 상태를 도입합니다.
드래그 업데이트 중 조건부 햅틱 피드백 트리거
app/src/main/java/com/into/websoso/ui/detailExplore/component/RatingRangeSlider.kt
드래그 중 활성 엄지손가락의 스냅 값을 계산하여 마지막 스냅 상태와 비교하고, 값이 변경되면 CLOCK_TICK 햅틱 피드백을 트리거한 후 상태를 갱신합니다.

🎯 2 (Simple) | ⏱️ ~10 minutes

🐰 별점 슬라이더에 진동이 흐르네요,
사용자의 손가락이 맞춰질 때마다,
톡톡톡, 부드러운 햅틱의 축제!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive 풀 리퀘스트 설명은 리포지토리 템플릿 구조를 따르고 있으나, '작업 설명' 섹션이 비어있고 '스크린샷' 섹션도 제공되지 않아 기술 리뷰어를 위한 구체적인 정보가 부족합니다. 작업 설명 섹션에 구현 세부사항(예: 햅틱 피드백 종류, CLOCK_TICK 사용 이유)과 변경사항을 추가하고, 가능하면 스크린샷이나 동작 영상을 포함하기를 권장합니다.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed 풀 리퀘스트 제목 '햅틱 적용'은 변경 사항의 핵심 내용을 명확하게 요약하고 있으며, RatingRangeSlider 컴포넌트에 햅틱 피드백이 추가된 주요 변경사항과 완벽하게 일치합니다.
Linked Issues check ✅ Passed 풀 리퀘스트 변경사항은 #877에 명시된 '별점 슬라이더에 햅틱 추가' 요구사항을 충족하고 있으며, 설명에서 언급한 일반적인 햅틱 강도 적용이 코드에 반영되어 있습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항은 RatingRangeSlider 컴포넌트의 햅틱 피드백 추가에만 집중하고 있으며, #877 이슈의 범위를 벗어난 변경사항이 없습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/877

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
app/src/main/java/com/into/websoso/ui/detailExplore/component/RatingRangeSlider.kt (1)

111-116: 💤 Low value

중복 계산 제거를 고려하세요.

스냅된 값이 두 번 계산됩니다(햅틱 체크용, onValueChange 호출용). 변수에 저장하여 재사용하면 코드가 더 명확해집니다.

♻️ 리팩토링 제안
 onDrag = { change, _ ->
     change.consume()
     val newValue = valueAtX(change.position.x)
     if (activeThumb == 1) {
         val snapped = newValue.coerceAtMost(latestMax)
         if (snapped != lastMinSnapped) {
             view.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK)
             lastMinSnapped = snapped
         }
-        onValueChange(newValue.coerceAtMost(latestMax), latestMax)
+        onValueChange(snapped, latestMax)
     } else {
         val snapped = newValue.coerceAtLeast(latestMin)
         if (snapped != lastMaxSnapped) {
             view.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK)
             lastMaxSnapped = snapped
         }
-        onValueChange(latestMin, newValue.coerceAtLeast(latestMin))
+        onValueChange(latestMin, snapped)
     }
 },

Also applies to: 118-123

🤖 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/java/com/into/websoso/ui/detailExplore/component/RatingRangeSlider.kt`
around lines 111 - 116, Avoid computing the snapped value twice: compute snapped
= newValue.coerceAtMost(latestMax) once, reuse that variable for the haptic
check (compare with lastMinSnapped and call view.performHapticFeedback) and pass
the same snapped to onValueChange instead of recomputing; update lastMinSnapped
when needed. Apply the same change to the analogous block that references
lastMaxSnapped/onValueChange for lines 118-123.
🤖 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.

Inline comments:
In
`@app/src/main/java/com/into/websoso/ui/detailExplore/component/RatingRangeSlider.kt`:
- Around line 68-70: The haptic false-positive occurs because
lastMinSnapped/lastMaxSnapped retain previous values across external prop
updates; update onDragStart in RatingRangeSlider to reset lastMinSnapped = min
and lastMaxSnapped = max (use the current min/max props) so the first onDrag
compares against the current positions and only triggers haptics when a real
snap crossing occurs.

---

Nitpick comments:
In
`@app/src/main/java/com/into/websoso/ui/detailExplore/component/RatingRangeSlider.kt`:
- Around line 111-116: Avoid computing the snapped value twice: compute snapped
= newValue.coerceAtMost(latestMax) once, reuse that variable for the haptic
check (compare with lastMinSnapped and call view.performHapticFeedback) and pass
the same snapped to onValueChange instead of recomputing; update lastMinSnapped
when needed. Apply the same change to the analogous block that references
lastMaxSnapped/onValueChange for lines 118-123.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c26e2b85-42d1-45f7-999b-4be9bfdfdb5c

📥 Commits

Reviewing files that changed from the base of the PR and between 2dffd30 and 8172584.

📒 Files selected for processing (1)
  • app/src/main/java/com/into/websoso/ui/detailExplore/component/RatingRangeSlider.kt

Comment on lines +68 to +70
val view = LocalView.current
var lastMinSnapped by remember { mutableFloatStateOf(min) }
var lastMaxSnapped by remember { mutableFloatStateOf(max) }
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚖️ Poor tradeoff

onDragStart에서 마지막 스냅 상태를 초기화해야 합니다.

드래그 시작 시 lastMinSnapped/lastMaxSnapped를 초기화하지 않아 다음 시나리오에서 잘못된 햅틱이 트리거됩니다:

  1. 사용자가 min thumb을 3.0으로 드래그 후 릴리스 (lastMinSnapped = 3.0)
  2. 외부 상태 변경으로 min prop이 1.0으로 업데이트 (lastMinSnapped는 여전히 3.0)
  3. 사용자가 1.0 위치에서 새 드래그 시작
  4. 첫 번째 onDrag 이벤트에서 snapped = 1.0이고 1.0 != 3.0이므로 햅틱 트리거
  5. 문제: 실제로 스냅 포인트를 넘지 않았는데도 햅틱이 발생

햅틱은 드래그 중 스냅 포인트를 실제로 넘을 때만 트리거되어야 합니다.

🔧 수정 제안

onDragStart에서 현재 위치로 상태를 초기화하세요:

 onDragStart = { offset ->
     val touchX = offset.x
     activeThumb =
         if ((touchX - latestStartCenter).absoluteValue <=
             (touchX - latestEndCenter).absoluteValue
         ) {
             1
         } else {
             2
         }
     val newValue = valueAtX(touchX)
     if (activeThumb == 1) {
-        onValueChange(newValue.coerceAtMost(latestMax), latestMax)
+        val snapped = newValue.coerceAtMost(latestMax)
+        lastMinSnapped = snapped
+        onValueChange(snapped, latestMax)
     } else {
-        onValueChange(latestMin, newValue.coerceAtLeast(latestMin))
+        val snapped = newValue.coerceAtLeast(latestMin)
+        lastMaxSnapped = snapped
+        onValueChange(latestMin, snapped)
     }
 },
🤖 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/java/com/into/websoso/ui/detailExplore/component/RatingRangeSlider.kt`
around lines 68 - 70, The haptic false-positive occurs because
lastMinSnapped/lastMaxSnapped retain previous values across external prop
updates; update onDragStart in RatingRangeSlider to reset lastMinSnapped = min
and lastMaxSnapped = max (use the current min/max props) so the first onDrag
compares against the current positions and only triggers haptics when a real
snap crossing occurs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🍯 [FEAT] 새로운 기능을 개발합니다. 🧙마법사 하루

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 별점 슬라이더 햅틱 추가

1 participant