From 16b4bce136ed152fe10ff314d87c634a9921e73e Mon Sep 17 00:00:00 2001 From: ByungCheol Date: Sat, 6 Jun 2026 15:49:07 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=B0=94=ED=85=80=20=EB=82=B4=EB=B9=84?= =?UTF-8?q?=20=ED=95=98=EB=8B=A8=20=EA=B3=A0=EC=A0=95(=EC=86=8C=ED=94=84?= =?UTF-8?q?=ED=8A=B8=ED=82=A4=20=EC=9C=84)=C2=B7=EC=95=84=EC=9D=B4?= =?UTF-8?q?=EC=BD=98=ED=99=94=20+=20=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=20=EC=A0=95=EB=B3=B4=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AppBottomNav: position fixed 하단 고정(스크롤 무관 상시 노출), 아이콘 전용(28px) - MainActivity: 시스템 바 인셋만큼 웹뷰 패딩 — 에지투에지(targetSdk36)에서 소프트키 겹침 해소 - ProfileEditView: 정보변경 화면에 비밀번호 변경 섹션 흡수(현재 비밀번호 재사용) - AppHeader 비밀번호 아이콘·App.vue ChangePasswordModal 마운트 제거(진입점 일원화) Co-Authored-By: Claude Opus 4.8 --- .../kr/sblog/slimbudget/MainActivity.java | 17 ++++++ src/App.vue | 5 +- src/components/layout/AppBottomNav.vue | 50 ++++++++--------- src/components/layout/AppHeader.vue | 1 - src/views/settings/ProfileEditView.vue | 54 +++++++++++++++++-- 5 files changed, 93 insertions(+), 34 deletions(-) diff --git a/android/app/src/main/java/kr/sblog/slimbudget/MainActivity.java b/android/app/src/main/java/kr/sblog/slimbudget/MainActivity.java index 5a66b49..77742bc 100644 --- a/android/app/src/main/java/kr/sblog/slimbudget/MainActivity.java +++ b/android/app/src/main/java/kr/sblog/slimbudget/MainActivity.java @@ -1,6 +1,11 @@ package kr.sblog.slimbudget; import android.os.Bundle; +import android.view.View; + +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; import com.getcapacitor.BridgeActivity; @@ -9,5 +14,17 @@ public class MainActivity extends BridgeActivity { public void onCreate(Bundle savedInstanceState) { registerPlugin(CardNotifPlugin.class); super.onCreate(savedInstanceState); + + // targetSdk 35+ 의 에지투에지 강제 환경에서 웹뷰가 상태바/소프트키(시스템 내비) 뒤로 + // 깔리는 것을 방지한다. 시스템 바 인셋만큼 웹뷰에 패딩을 줘서 콘텐츠(하단 고정 내비 포함)가 + // 항상 안전 영역 안에 오도록 한다. (CSS env(safe-area-*) 가 기기별로 0 을 반환하는 문제 회피) + final View webView = getBridge().getWebView(); + if (webView != null) { + ViewCompat.setOnApplyWindowInsetsListener(webView, (v, insets) -> { + Insets bars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); + v.setPadding(bars.left, bars.top, bars.right, bars.bottom); + return insets; + }); + } } } diff --git a/src/App.vue b/src/App.vue index e3b9508..661ce1e 100644 --- a/src/App.vue +++ b/src/App.vue @@ -6,7 +6,6 @@ import AppSidebar from '@/components/layout/AppSidebar.vue' import AppBottomNav from '@/components/layout/AppBottomNav.vue' import LoginModal from '@/components/LoginModal.vue' import SignupModal from '@/components/SignupModal.vue' -import ChangePasswordModal from '@/components/ChangePasswordModal.vue' import WebOnlyNotice from '@/components/WebOnlyNotice.vue' import { Capacitor } from '@capacitor/core' import { useAuthStore } from '@/stores/auth' @@ -54,7 +53,6 @@ watch(() => route.fullPath, () => ui.closeSidebar()) - @@ -81,6 +79,8 @@ watch(() => route.fullPath, () => ui.closeSidebar()) .layout-body { grid-area: body; padding: 1.5rem 2rem; + /* 하단 고정 내비(56px)+소프트키 인셋만큼 비워 콘텐츠가 가리지 않게 */ + padding-bottom: calc(56px + env(safe-area-inset-bottom, 0) + 1rem); overflow: auto; } @@ -127,6 +127,7 @@ watch(() => route.fullPath, () => ui.closeSidebar()) } .layout-body { padding: 1rem; + padding-bottom: calc(56px + env(safe-area-inset-bottom, 0) + 1rem); } } diff --git a/src/components/layout/AppBottomNav.vue b/src/components/layout/AppBottomNav.vue index 7908b80..b014907 100644 --- a/src/components/layout/AppBottomNav.vue +++ b/src/components/layout/AppBottomNav.vue @@ -30,51 +30,52 @@ function goSettings() {