From 2997714e2cba9f49c810b97e272df58d8acdb4ee Mon Sep 17 00:00:00 2001 From: Yu Sung Date: Thu, 8 Oct 2026 20:34:54 +0900 Subject: [PATCH] =?UTF-8?q?fix(gift):=20=EC=83=81=EC=84=B8=20=EB=AC=B8?= =?UTF-8?q?=EC=9D=98=EB=A5=BC=20TALK=EC=97=90=20=EC=97=B0=EA=B2=B0?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ServiceCenter/ServiceCenterView.swift | 8 +++- .../V2/Gift/Constants/GiftConstants.swift | 1 - .../Components/GiftCancelCompleteView.swift | 2 +- .../Components/GiftDetailActionBar.swift | 2 +- .../ReceivedGiftDetailContentView.swift | 2 +- work/tests/check-gift-detail-talk-inquiry.sh | 39 +++++++++++++++++++ work/tests/check-received-gift-detail.sh | 2 +- 7 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 work/tests/check-gift-detail-talk-inquiry.sh diff --git a/SodaLive/Sources/MyPage/ServiceCenter/ServiceCenterView.swift b/SodaLive/Sources/MyPage/ServiceCenter/ServiceCenterView.swift index 43580121..25a9f9c6 100644 --- a/SodaLive/Sources/MyPage/ServiceCenter/ServiceCenterView.swift +++ b/SodaLive/Sources/MyPage/ServiceCenter/ServiceCenterView.swift @@ -7,6 +7,12 @@ import SwiftUI +enum ServiceCenterInquiry { + static func openTalk() { + UIApplication.shared.open(URL(string: "http://pf.kakao.com/_lkxgxhG/chat")!) + } +} + struct ServiceCenterView: View { @ObservedObject var viewModel = ServiceCenterViewModel() @@ -45,7 +51,7 @@ struct ServiceCenterView: View { .padding(.horizontal, 13.3) .padding(.top, 20) .onTapGesture { - UIApplication.shared.open(URL(string: "http://pf.kakao.com/_lkxgxhG/chat")!) + ServiceCenterInquiry.openTalk() } Rectangle() diff --git a/SodaLive/Sources/V2/Gift/Constants/GiftConstants.swift b/SodaLive/Sources/V2/Gift/Constants/GiftConstants.swift index c541a4bf..cd2fe06b 100644 --- a/SodaLive/Sources/V2/Gift/Constants/GiftConstants.swift +++ b/SodaLive/Sources/V2/Gift/Constants/GiftConstants.swift @@ -4,7 +4,6 @@ enum GiftConstants { static let termsURL = URL(string: "https://app.notion.com/p/3eb27b359673802b937ae741ab7b4ad3") static let damagePolicyURL = URL(string: "https://app.notion.com/p/3f227b3596738018ba5dea2e5205293b") static let addressSearchAvailable = false - static let inquiryStep: AppStep = .serviceCenter static let feedbackStep: AppStep = .serviceCenter static let unavailableActionMessage = "준비 중입니다." static let courierCompanyNames = [ diff --git a/SodaLive/Sources/V2/Gift/Detail/Components/GiftCancelCompleteView.swift b/SodaLive/Sources/V2/Gift/Detail/Components/GiftCancelCompleteView.swift index 2837d0d7..439c395c 100644 --- a/SodaLive/Sources/V2/Gift/Detail/Components/GiftCancelCompleteView.swift +++ b/SodaLive/Sources/V2/Gift/Detail/Components/GiftCancelCompleteView.swift @@ -59,7 +59,7 @@ struct GiftCancelCompleteView: View { Button { guard !isNavigating else { return } isNavigating = true - AppState.shared.setAppStep(step: GiftConstants.inquiryStep) + ServiceCenterInquiry.openTalk() } label: { Text("문의하기") .appFont(.body2) diff --git a/SodaLive/Sources/V2/Gift/Detail/Components/GiftDetailActionBar.swift b/SodaLive/Sources/V2/Gift/Detail/Components/GiftDetailActionBar.swift index 046be189..5f18326a 100644 --- a/SodaLive/Sources/V2/Gift/Detail/Components/GiftDetailActionBar.swift +++ b/SodaLive/Sources/V2/Gift/Detail/Components/GiftDetailActionBar.swift @@ -44,7 +44,7 @@ struct GiftDetailActionBar: View { Button { guard !isNavigating else { return } isNavigating = true - AppState.shared.setAppStep(step: GiftConstants.inquiryStep) + ServiceCenterInquiry.openTalk() } label: { secondaryLabel("문의하기", isEnabled: !isNavigating) } diff --git a/SodaLive/Sources/V2/Gift/Detail/Components/ReceivedGiftDetailContentView.swift b/SodaLive/Sources/V2/Gift/Detail/Components/ReceivedGiftDetailContentView.swift index eb4326b2..ae1363d5 100644 --- a/SodaLive/Sources/V2/Gift/Detail/Components/ReceivedGiftDetailContentView.swift +++ b/SodaLive/Sources/V2/Gift/Detail/Components/ReceivedGiftDetailContentView.swift @@ -119,7 +119,7 @@ struct ReceivedGiftDetailActionBar: View { Button { guard !isNavigating else { return } isNavigating = true - AppState.shared.setAppStep(step: GiftConstants.inquiryStep) + ServiceCenterInquiry.openTalk() } label: { secondaryLabel("문의하기", isEnabled: !isNavigating) } diff --git a/work/tests/check-gift-detail-talk-inquiry.sh b/work/tests/check-gift-detail-talk-inquiry.sh new file mode 100644 index 00000000..43d0eebf --- /dev/null +++ b/work/tests/check-gift-detail-talk-inquiry.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +set -euo pipefail + +root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +ruby - "$root" <<'RUBY' +root = ARGV.fetch(0) +source_root = File.join(root, 'SodaLive/Sources') + +read = lambda do |path| + File.read(File.join(source_root, path)) + .gsub(%r{"(?:\\.|[^"\\])*"|//[^\n]*|/\*.*?\*/}m) { |token| token.start_with?('"') ? token : '' } + .gsub(/\s+/, ' ').gsub(/\s*([(),:])\s*/, '\1').strip +end + +check = lambda do |condition, message| + abort "RED gift-detail TALK inquiry: #{message}" unless condition +end + +service = read.call('MyPage/ServiceCenter/ServiceCenterView.swift') +gift_sources = [ + 'V2/Gift/Detail/Components/GiftDetailActionBar.swift', + 'V2/Gift/Detail/Components/ReceivedGiftDetailContentView.swift', + 'V2/Gift/Detail/Components/GiftCancelCompleteView.swift' +].map { |path| [path, read.call(path)] } + +helper = 'enum ServiceCenterInquiry { static func openTalk(){ UIApplication.shared.open(URL(string:"http://pf.kakao.com/_lkxgxhG/chat")!)} }' +check.call(service.include?(helper), 'ServiceCenterInquiry.openTalk must own the existing Kakao TALK action') +check.call(service.scan('ServiceCenterInquiry.openTalk()').length == 1, 'ServiceCenter TALK button must call the shared action once') +check.call(service.scan('http://pf.kakao.com/_lkxgxhG/chat').length == 1, 'Kakao TALK URL must have one source of truth') + +gift_sources.each do |path, source| + check.call(source.scan('ServiceCenterInquiry.openTalk()').length == 1, "#{path} must call the shared action once") + check.call(!source.include?('GiftConstants.inquiryStep'), "#{path} must not navigate to the in-app service center") + check.call(!source.include?('.serviceCenter'), "#{path} must not navigate directly to the in-app service center") + check.call(!source.include?('http://pf.kakao.com/_lkxgxhG/chat'), "#{path} must not duplicate the TALK URL") +end + +puts 'PASS gift-detail TALK inquiry: ServiceCenter and all three Gift actions share one TALK action' +RUBY diff --git a/work/tests/check-received-gift-detail.sh b/work/tests/check-received-gift-detail.sh index c3b18a44..ffbe8123 100644 --- a/work/tests/check-received-gift-detail.sh +++ b/work/tests/check-received-gift-detail.sh @@ -218,7 +218,7 @@ for probe in ('GiftInfoSectionView(title: "받는 주소")', 'GiftInfoRow(title: require(not re.search(r"model\.(senderInfo|mailbox|applicationNo|paidCan|tracking)\b", component), "privacy-safe component") actions, _ = block(component, "struct ReceivedGiftDetailActionBar: View") require("guard !isNavigating else { return }" in actions and "isNavigating = true" in actions and ".disabled(isNavigating)" in actions, "inquiry repeat guard") -require("AppState.shared.setAppStep(step: GiftConstants.inquiryStep)" in actions and '"문의하기"' in actions, "existing inquiry route") +require("ServiceCenterInquiry.openTalk()" in actions and '"문의하기"' in actions, "shared TALK inquiry action") appear, _ = block(actions, ".onAppear") require("isNavigating = false" in appear, "navigation guard resets") require("let onPolicy: () -> Void" in actions and "onPolicy()" in actions and '"선물 정책 확인"' in actions, "policy callback")