From 89aa0491d7e595646787bda4da0177cc30396aa2 Mon Sep 17 00:00:00 2001 From: seongwon seo Date: Thu, 22 Jan 2026 15:02:12 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=8F=99=EC=95=84=EB=A6=AC=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=9B=B9=EB=B7=B0=20=EB=84=A4=EC=9D=B4=ED=8B=B0?= =?UTF-8?q?=EB=B8=8C=20=EA=B3=B5=EC=9C=A0=ED=95=98=EA=B8=B0=20=ED=95=B8?= =?UTF-8?q?=EB=93=A4=EB=9F=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 웹뷰에서 전달받은 'SHARE' 메시지를 처리하여 네이티브 공유하기(Share.share) 기능을 실행하는 로직 추가 - WebView 컴포넌트에 onMessage 핸들러 연결 --- ui/club-detail/club-detail-screen.tsx | 92 +++++++++++++++++---------- 1 file changed, 57 insertions(+), 35 deletions(-) diff --git a/ui/club-detail/club-detail-screen.tsx b/ui/club-detail/club-detail-screen.tsx index fe06a9c..da48b5e 100644 --- a/ui/club-detail/club-detail-screen.tsx +++ b/ui/club-detail/club-detail-screen.tsx @@ -1,18 +1,23 @@ -import { MoaImage } from '@/components/moa-image'; -import { MoaText } from '@/components/moa-text'; -import { PermissionDialog } from '@/components/permission-dialog'; -import { USER_EVENT } from '@/constants/eventname'; -import { useMixpanelContext } from '@/contexts'; -import { useSubscribedClubsContext } from '@/contexts/subscribed-clubs-context'; -import { useMixpanelTrack } from '@/hooks'; -import { Ionicons } from '@expo/vector-icons'; -import Constants from 'expo-constants'; -import { useLocalSearchParams, useRouter } from 'expo-router'; -import { useMemo, useState } from 'react'; -import { ActivityIndicator, Platform, TouchableOpacity } from 'react-native'; -import { SafeAreaView } from 'react-native-safe-area-context'; -import { WebView } from 'react-native-webview'; -import styled from 'styled-components/native'; +import { MoaImage } from "@/components/moa-image"; +import { MoaText } from "@/components/moa-text"; +import { PermissionDialog } from "@/components/permission-dialog"; +import { USER_EVENT } from "@/constants/eventname"; +import { useMixpanelContext } from "@/contexts"; +import { useSubscribedClubsContext } from "@/contexts/subscribed-clubs-context"; +import { useMixpanelTrack } from "@/hooks"; +import { Ionicons } from "@expo/vector-icons"; +import Constants from "expo-constants"; +import { useLocalSearchParams, useRouter } from "expo-router"; +import { useMemo, useState } from "react"; +import { + ActivityIndicator, + Platform, + Share, + TouchableOpacity, +} from "react-native"; +import { SafeAreaView } from "react-native-safe-area-context"; +import { WebView, WebViewMessageEvent } from "react-native-webview"; +import styled from "styled-components/native"; export default function ClubWebViewScreen() { const router = useRouter(); @@ -26,13 +31,13 @@ export default function ClubWebViewScreen() { const webviewUrl = process.env.EXPO_PUBLIC_WEBVIEW_URL; const uri = useMemo(() => { - if (!id || typeof id !== 'string') { + if (!id || typeof id !== "string") { return `${webviewUrl}/club`; } - const cleanUrl = webviewUrl?.replace(/\/$/, '') || ''; + const cleanUrl = webviewUrl?.replace(/\/$/, "") || ""; const baseUrl = `${cleanUrl}/club/${id}`; - + if (sessionId) { return `${baseUrl}?session_id=${encodeURIComponent(sessionId)}`; } @@ -45,8 +50,8 @@ export default function ClubWebViewScreen() { // UserAgent 생성 const userAgent = useMemo(() => { - const appVersion = Constants.expoConfig?.version || '1.0.0'; - const platform = Platform.OS === 'ios' ? 'iOS' : 'Android'; + const appVersion = Constants.expoConfig?.version || "1.0.0"; + const platform = Platform.OS === "ios" ? "iOS" : "Android"; return `MoadongApp/${appVersion} (${platform})`; }, []); @@ -59,29 +64,29 @@ export default function ClubWebViewScreen() { const handleBack = () => { trackEvent(USER_EVENT.BACK_BUTTON_CLICKED, { - from: 'club_detail', + from: "club_detail", clubName: name, - url: 'app://moadong/club', + url: "app://moadong/club", }); - + if (router.canGoBack()) { router.back(); } else { - router.push('/(tabs)'); + router.push("/(tabs)"); } }; const handleSubscribeToggle = async () => { - if (id && typeof id === 'string') { + if (id && typeof id === "string") { const wasSubscribed = isSubscribed(id); - + trackEvent(USER_EVENT.SUBSCRIBE_BUTTON_CLICKED, { clubName: name, subscribed: !wasSubscribed, - from: 'club_detail', - url: 'app://moadong/club', + from: "club_detail", + url: "app://moadong/club", }); - + const result = await toggleSubscribe(id); if (result.needsPermission) { setShowPermissionDialog(true); @@ -89,8 +94,24 @@ export default function ClubWebViewScreen() { } }; + const handleMessage = async (event: WebViewMessageEvent) => { + try { + const data = JSON.parse(event.nativeEvent.data); + if (data.type === "SHARE") { + const { title, text, url } = data.payload; + await Share.share({ + title, + message: text, + url, + }); + } + } catch (e) { + // Ignore errors + } + }; + return ( - +
@@ -100,8 +121,8 @@ export default function ClubWebViewScreen() { )} - + {/* 알림 권한 다이얼로그 */}