Skip to content

SCRUM-270 SCRUM-271 feat: add terms webview#43

Merged
gdaegeun539 merged 14 commits into
project-lyrics:developfrom
gdaegeun539:feature/SCRUM-270-SCRUM-271
May 5, 2026
Merged

SCRUM-270 SCRUM-271 feat: add terms webview#43
gdaegeun539 merged 14 commits into
project-lyrics:developfrom
gdaegeun539:feature/SCRUM-270-SCRUM-271

Conversation

@gdaegeun539
Copy link
Copy Markdown
Member

@gdaegeun539 gdaegeun539 commented May 5, 2026

Please check if the PR fulfills these requirements

  • The commit message follows our guidelines

What kind of change does this PR introduce?

  • Add feature
  • Implement design

What is the current behavior?

약관, 개인정보처리방침 등의 외부 링크가 연결되지 않은 상태입니다.

What is the new behavior (if this is a feature change)?

  • 약관, 개인정보처리방침 등의 외부 링크를 연결합니다.
    • 기존 iOS 앱의 구현과 맞게 노션 링크(약관, 개인정보처리방침)는 내부 웹뷰로, 서비스 문의 Google docs 링크는 외부 브라우저로 표시합니다.
  • 구현 중 소요가 발생해 설정 화면에서는 FAQ를 같이 표시합니다.
    • 노션 링크여서 약관과 같이 내부 웹뷰로 표시합니다.

Does this PR introduce a breaking change? (What changes might users need to make in their application due to this PR?)

No breaking changes.

ScreenShots

회원가입 온보딩

Screen_Recording_20260505_112940_Feelin.mp4

설정화면

Screen_Recording_20260505_113005_Feelin.mp4

Screenshot_20260505_133453_Feelin Screenshot_20260505_133838_Feelin

외부 브라우저를 통해 링크를 표시하는데, 브라우저가 없는 경우

Screenshot_Feelin_20260505_233830

Other information:

노션 웹뷰를 다크모드에 대응하기 위해서는 View 시스템 테마를 다크모드에 대응하도록 수정해야 하더라고요. 해당 부분은 이 브랜치의 구현을 넘는 것 같아 이슈로 등록하고 수정하겠습니다.

Summary by CodeRabbit

  • New Features
    • View terms, privacy policy, FAQs and support pages inside the app via an internal WebView
    • Option to open some links in the external browser
    • Dark mode applied to web content
    • Refresh control with a refresh icon for WebView pages
    • Settings reorganized with quick access to service/info links and navigation to web content
    • Shows a toast if no external browser is available

gdaegeun539 and others added 9 commits May 3, 2026 18:30
Patch Notion's collapsed scroll container so legal pages remain visible inside the Android internal WebView.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Use public Notion URLs for WebView display while preserving the original agreement URLs sent in signup payloads.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Add AndroidX WebKit and apply runtime darkening settings so

interoperated WebView content can react to dark mode changes.
@gdaegeun539 gdaegeun539 requested a review from hyunjung-choi May 5, 2026 05:26
@gdaegeun539 gdaegeun539 self-assigned this May 5, 2026
@gdaegeun539 gdaegeun539 added feat 새로운 기능 design 디자인 관련 수정 labels May 5, 2026
@gdaegeun539 gdaegeun539 marked this pull request as ready for review May 5, 2026 05:26
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

📝 Walkthrough

Walkthrough

Adds an internal WebView flow: new composable screen hosting an Android WebView with dark-mode support and refresh/close actions, navigation route and URL encoding, settings-driven link definitions that choose internal vs external opening, a refresh drawable/icon, an external browser launcher, and the androidx-webkit dependency; SignUpTerm gains a separate display URL field.

Changes

Internal WebView Feature

Layer / File(s) Summary
Data Shape / Models
app/src/main/java/com/lyrics/feelin/core/domain/model/SignUpTerm.kt, app/src/main/java/com/lyrics/feelin/presentation/view/mypage/setting/SettingInfoLink.kt
SignUpTerm constructor adds webViewUrl: String = agreement; SERVICE_USAGE and PERSONAL_INFO set explicit webViewUrl. New SettingInfoLink enum defines title, url, and opensInternally entries.
Dependencies & Resources
gradle/libs.versions.toml, app/build.gradle.kts, app/src/main/res/drawable/refresh.xml, app/src/main/java/com/lyrics/feelin/core/designsystem/icon/Icons.kt
Adds webkit = "1.15.0" and androidx-webkit library alias; adds refresh.xml vector drawable and exposes it as RefreshIcon; includes dependency in module dependencies.
Navigation Surface
app/src/main/java/com/lyrics/feelin/navigation/FeelinDestination.kt, app/src/main/java/com/lyrics/feelin/navigation/FeelinNavHost.kt
Adds FeelinDestination.InternalWebView route with url argument and createRoute(url) that URL-encodes values. Registers internalWebViewScreen on the NavHost; onboarding and settings now navigate to the internal webview route; introduces myPageNavGraph and wiring for internal/external link handlers.
UI / Composables & Platform Integration
app/src/main/java/com/lyrics/feelin/presentation/view/webview/InternalWebViewScreen.kt, app/src/main/java/com/lyrics/feelin/presentation/view/mypage/setting/SettingScreen.kt, app/src/main/java/com/lyrics/feelin/presentation/util/ExternalBrowserLauncher.kt
Adds InternalWebViewScreen(url, onCloseClick) using AndroidView to create/configure a WebView (JS, DOM storage enabled; mixed content/file access disabled), applies dark-mode via WebViewFeature checks, supports refresh and safe disposal. SettingScreen signature updated to accept onInternalWebViewClick and onExternalBrowserClick and iterates SettingInfoLink to route clicks. Adds Context.openExternalBrowser(url) to launch external browser intents with error handling.

Sequence Diagrams

sequenceDiagram
    actor User
    participant Settings as SettingScreen
    participant Nav as Navigation
    participant Web as InternalWebView
    participant Sys as System Browser

    User->>Settings: Tap link
    Settings->>Nav: request open(link.url)
    alt opensInternally
        Nav->>Nav: encode url
        Nav->>Web: navigate(encoded url)
        Web->>Web: decode, apply dark mode, load content
        Web->>User: render page
    else opens externally
        Nav->>Sys: launch ACTION_VIEW(url)
        Sys->>User: open in external browser
    end
Loading
sequenceDiagram
    actor User
    participant Onboarding as OnboardingTermsScreen
    participant Nav as Navigation
    participant Web as InternalWebView

    User->>Onboarding: Tap term detail
    Onboarding->>Nav: createRoute(term.webViewUrl)
    Nav->>Nav: encode url
    Nav->>Web: navigate(encoded url)
    Web->>Web: apply dark mode, load
    User->>Web: tap refresh or close
    Web->>Web: reload
    Web->>Nav: popBackStack on close
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A tiny hop, an encoded trail,
In a cozy WebView, night or pale;
Refresh to sparkle, close to roam,
Links decide to stay or go home—
The rabbit claps, "Safe journey, sail!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding a WebView feature for displaying terms and related content, which is the core focus of all changes across multiple files.
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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Comment thread app/src/main/java/com/lyrics/feelin/navigation/FeelinNavHost.kt Outdated
WebView(context).apply {
webView = this
// Notion의 full-height 레이아웃이 Android WebView에서 0px로 접히지 않도록 명시한다.
layoutParams = ViewGroup.LayoutParams(
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

웹뷰가 표시되는 뷰시스템의 크기를 잡지 않고 링크를 표시하면 노션 페이지의 레이아웃이 망가져서 표시되더라고요.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 04f4d64dfc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@@ -0,0 +1,28 @@
package com.lyrics.feelin.presentation.view.mypage.setting

enum class SettingInfoLink(
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

도메인 요소로 보기는 뭐하고, 화면에 표시하는 요소는 맞아서 같은 디렉토리에 프레젠테이션 모델로 외부 링크 데이터를 두었어요.

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: 3

🧹 Nitpick comments (1)
app/src/main/java/com/lyrics/feelin/presentation/view/mypage/setting/SettingInfoLink.kt (1)

8-27: ⚡ Quick win

Consolidate legal-link URLs into one source of truth.

SERVICE_USAGE / PERSONAL_INFO URLs are duplicated here and in SignUpTerm, which can drift and show different legal documents across onboarding vs settings. Consider centralizing shared legal links in one model/constants source.

🤖 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/lyrics/feelin/presentation/view/mypage/setting/SettingInfoLink.kt`
around lines 8 - 27, SERVICE_USAGE and PERSONAL_INFO duplicate legal URLs here
and in SignUpTerm causing drift; create a single source of truth (e.g., a
LegalLinks object or enum) that exposes constants/properties for
SERVICE_USAGE_URL and PERSONAL_INFO_URL, move the URLs into that new LegalLinks,
and update SettingInfoLink (entries SERVICE_USAGE, PERSONAL_INFO) and SignUpTerm
to reference LegalLinks.SERVICE_USAGE_URL and LegalLinks.PERSONAL_INFO_URL
respectively so both consumers use the same centralized constants.
🤖 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/lyrics/feelin/navigation/FeelinNavHost.kt`:
- Around line 275-284: In the onExternalBrowserClick lambda in FeelinNavHost
(the block that calls context.startActivity(Intent(Intent.ACTION_VIEW,
url.toUri()))), keep the existing Log.w for ActivityNotFoundException but also
show a user-facing Toast (e.g., Toast.makeText(context, "No browser found to
open link", Toast.LENGTH_SHORT).show()) inside the onFailure branch when
throwable is ActivityNotFoundException; do not rethrow in that branch so the
Toast is the visible feedback and preserve current behavior for other
exceptions.

In
`@app/src/main/java/com/lyrics/feelin/presentation/view/webview/InternalWebViewScreen.kt`:
- Around line 68-69: The contentDescription for the refresh control in
InternalWebViewScreen is hardcoded; replace the literal "Refresh" used in the
contentDescription property with a localized string resource (use
stringResource(R.string.refresh) inside InternalWebViewScreen) and add a
corresponding entry named "refresh" to your strings.xml (and translated Korean
strings.xml) so the accessibility text is localized across locales.
- Around line 83-97: The WebView is created inside the WebView(context).apply
block in InternalWebViewScreen but no WebViewClient is set, so navigations open
the system browser; set webView.webViewClient (inside the same
WebView(context).apply block) to a WebViewClient implementation that keeps
navigation in-app — e.g., override shouldOverrideUrlLoading to load the request
in the current WebView (or return false to let the WebView handle it) and handle
redirects/errors as needed; ensure this assignment occurs before calling
loadUrl(url) so applyDarkTheme, webView variable, and loadUrl(url) continue to
work correctly.

---

Nitpick comments:
In
`@app/src/main/java/com/lyrics/feelin/presentation/view/mypage/setting/SettingInfoLink.kt`:
- Around line 8-27: SERVICE_USAGE and PERSONAL_INFO duplicate legal URLs here
and in SignUpTerm causing drift; create a single source of truth (e.g., a
LegalLinks object or enum) that exposes constants/properties for
SERVICE_USAGE_URL and PERSONAL_INFO_URL, move the URLs into that new LegalLinks,
and update SettingInfoLink (entries SERVICE_USAGE, PERSONAL_INFO) and SignUpTerm
to reference LegalLinks.SERVICE_USAGE_URL and LegalLinks.PERSONAL_INFO_URL
respectively so both consumers use the same centralized constants.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fdc8b2b7-9a93-4e80-9af9-50d489441ea9

📥 Commits

Reviewing files that changed from the base of the PR and between a5aa164 and baacca4.

📒 Files selected for processing (10)
  • app/build.gradle.kts
  • app/src/main/java/com/lyrics/feelin/core/designsystem/icon/Icons.kt
  • app/src/main/java/com/lyrics/feelin/core/domain/model/SignUpTerm.kt
  • app/src/main/java/com/lyrics/feelin/navigation/FeelinDestination.kt
  • app/src/main/java/com/lyrics/feelin/navigation/FeelinNavHost.kt
  • app/src/main/java/com/lyrics/feelin/presentation/view/mypage/setting/SettingInfoLink.kt
  • app/src/main/java/com/lyrics/feelin/presentation/view/mypage/setting/SettingScreen.kt
  • app/src/main/java/com/lyrics/feelin/presentation/view/webview/InternalWebViewScreen.kt
  • app/src/main/res/drawable/refresh.xml
  • gradle/libs.versions.toml

Comment thread app/src/main/java/com/lyrics/feelin/navigation/FeelinNavHost.kt Outdated
gdaegeun539 and others added 3 commits May 5, 2026 22:46
Assign a WebViewClient so policy page redirects and link navigation stay inside the internal WebView instead of falling back to the system browser.
Move external browser launch handling out of FeelinNavHost so the navigation graph only wires link actions to presentation utilities.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@gdaegeun539
Copy link
Copy Markdown
Member Author

@codex

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e9db31a1ae

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread app/src/main/java/com/lyrics/feelin/navigation/FeelinNavHost.kt Outdated
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

🤖 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/lyrics/feelin/navigation/FeelinNavHost.kt`:
- Around line 291-299: The navArgument currently sets defaultValue = "" which
masks missing URLs; change the argument to be nullable (remove the empty default
and set nullable = true on the navArgument for
FeelinDestination.InternalWebView.UrlArgument) so
backStackEntry.arguments?.getString(FeelinDestination.InternalWebView.UrlArgument)
can return null, then add an explicit guard at the call site in FeelinNavHost
(where you read backStackEntry.arguments?.getString(...).orEmpty()) to check for
null/blank (e.g., if (url.isNullOrBlank()) { show error UI / navigateUp / log
and return }) instead of silently loading an empty WebView.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 776bd6c8-860a-4daf-a3e6-d906c9ce5f72

📥 Commits

Reviewing files that changed from the base of the PR and between 8ef07ab and e5c54e1.

📒 Files selected for processing (3)
  • app/src/main/java/com/lyrics/feelin/navigation/FeelinNavHost.kt
  • app/src/main/java/com/lyrics/feelin/presentation/util/ExternalBrowserLauncher.kt
  • app/src/main/java/com/lyrics/feelin/presentation/view/webview/InternalWebViewScreen.kt
✅ Files skipped from review due to trivial changes (2)
  • app/src/main/java/com/lyrics/feelin/presentation/util/ExternalBrowserLauncher.kt
  • app/src/main/java/com/lyrics/feelin/presentation/view/webview/InternalWebViewScreen.kt

Comment on lines +291 to +299
navArgument(FeelinDestination.InternalWebView.UrlArgument) {
type = NavType.StringType
defaultValue = ""
}
),
) { backStackEntry ->
val url = backStackEntry.arguments
?.getString(FeelinDestination.InternalWebView.UrlArgument)
.orEmpty()
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 | 🟡 Minor | ⚡ Quick win

Empty-URL fallback will silently load a blank WebView.

defaultValue = "" means any navigation to this destination without the URL argument (e.g., malformed deep link) gives InternalWebViewScreen an empty string, resulting in a blank, error-free WebView. Prefer explicit null handling so the screen can bail out early or show an error.

🛡️ Proposed fix
 navArgument(FeelinDestination.InternalWebView.UrlArgument) {
     type = NavType.StringType
-    defaultValue = ""
+    nullable = true
+    defaultValue = null
 }

Then guard at the call site:

-val url = backStackEntry.arguments
-    ?.getString(FeelinDestination.InternalWebView.UrlArgument)
-    .orEmpty()
-
-InternalWebViewScreen(
-    url = url,
-    onCloseClick = { navController.popBackStack() },
-)
+val url = backStackEntry.arguments
+    ?.getString(FeelinDestination.InternalWebView.UrlArgument)
+
+if (url.isNullOrBlank()) {
+    navController.popBackStack()
+} else {
+    InternalWebViewScreen(
+        url = url,
+        onCloseClick = { navController.popBackStack() },
+    )
+}
🤖 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/lyrics/feelin/navigation/FeelinNavHost.kt` around lines
291 - 299, The navArgument currently sets defaultValue = "" which masks missing
URLs; change the argument to be nullable (remove the empty default and set
nullable = true on the navArgument for
FeelinDestination.InternalWebView.UrlArgument) so
backStackEntry.arguments?.getString(FeelinDestination.InternalWebView.UrlArgument)
can return null, then add an explicit guard at the call site in FeelinNavHost
(where you read backStackEntry.arguments?.getString(...).orEmpty()) to check for
null/blank (e.g., if (url.isNullOrBlank()) { show error UI / navigateUp / log
and return }) instead of silently loading an empty WebView.

@gdaegeun539
Copy link
Copy Markdown
Member Author

빈 웹뷰 minor issue는 실제 문제 발생시 수정하고 우선 병합하겠습니다.

@gdaegeun539 gdaegeun539 merged commit f2268a2 into project-lyrics:develop May 5, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

design 디자인 관련 수정 feat 새로운 기능

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant