fix: 공유하기 수정
This commit is contained in:
parent
bdb581459d
commit
0d3167c1a2
@ -7,6 +7,7 @@ interface ContentCardSocialActionsProps {
|
|||||||
videoId: number;
|
videoId: number;
|
||||||
storeName: string;
|
storeName: string;
|
||||||
region?: string;
|
region?: string;
|
||||||
|
title?: string | null;
|
||||||
commentCount: number;
|
commentCount: number;
|
||||||
initialLikeCount: number;
|
initialLikeCount: number;
|
||||||
initialIsLiked?: boolean;
|
initialIsLiked?: boolean;
|
||||||
@ -15,7 +16,7 @@ interface ContentCardSocialActionsProps {
|
|||||||
const ContentCardSocialActions: React.FC<ContentCardSocialActionsProps> = ({
|
const ContentCardSocialActions: React.FC<ContentCardSocialActionsProps> = ({
|
||||||
videoId,
|
videoId,
|
||||||
storeName,
|
storeName,
|
||||||
region,
|
title,
|
||||||
commentCount,
|
commentCount,
|
||||||
initialLikeCount,
|
initialLikeCount,
|
||||||
initialIsLiked = false,
|
initialIsLiked = false,
|
||||||
@ -27,15 +28,13 @@ const ContentCardSocialActions: React.FC<ContentCardSocialActionsProps> = ({
|
|||||||
const likeDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
const likeDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||||
|
|
||||||
const shareUrl = buildVideoShareUrl(API_URL, videoId);
|
const shareUrl = buildVideoShareUrl(API_URL, videoId);
|
||||||
const shareTitle = storeName || t('videoDetail.kakaoDefaultTitle');
|
const shareTitle = title || storeName || t('videoDetail.kakaoDefaultTitle');
|
||||||
const shareDescription = t('videoDetail.kakaoDescription', { region: region ?? '' });
|
|
||||||
|
|
||||||
const handleShareBtnClick = async (e: React.MouseEvent) => {
|
const handleShareBtnClick = async (e: React.MouseEvent) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
const handled = await tryNativeShare({
|
const handled = await tryNativeShare({
|
||||||
title: shareTitle,
|
title: shareTitle,
|
||||||
text: shareDescription,
|
|
||||||
url: shareUrl,
|
url: shareUrl,
|
||||||
});
|
});
|
||||||
if (handled) {
|
if (handled) {
|
||||||
|
|||||||
@ -103,26 +103,27 @@ const VideoDetailContent: React.FC<VideoDetailContentProps> = ({ videoId, isModa
|
|||||||
};
|
};
|
||||||
|
|
||||||
const shareUrl = buildVideoShareUrl(API_URL, videoId);
|
const shareUrl = buildVideoShareUrl(API_URL, videoId);
|
||||||
const shareTitle = video?.store_name ?? t('videoDetail.kakaoDefaultTitle');
|
const shareTitle = video?.title || video?.store_name || t('videoDetail.kakaoDefaultTitle');
|
||||||
const shareDescription = t('videoDetail.kakaoDescription', { region: video?.region ?? '' });
|
|
||||||
|
const handleCopyLink = async () => {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(shareUrl);
|
||||||
|
} catch {
|
||||||
|
// clipboard API 미지원 환경에서는 무시
|
||||||
|
}
|
||||||
|
setCopied(true);
|
||||||
|
setTimeout(() => setCopied(false), 2000);
|
||||||
|
};
|
||||||
|
|
||||||
const handleShareButtonClick = async () => {
|
const handleShareButtonClick = async () => {
|
||||||
const handled = await tryNativeShare({
|
const handled = await tryNativeShare({
|
||||||
title: shareTitle,
|
title: shareTitle,
|
||||||
text: shareDescription,
|
|
||||||
url: shareUrl,
|
url: shareUrl,
|
||||||
});
|
});
|
||||||
if (handled) {
|
if (handled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
await handleCopyLink();
|
||||||
try {
|
|
||||||
await navigator.clipboard.writeText(shareUrl);
|
|
||||||
setCopied(true);
|
|
||||||
setTimeout(() => setCopied(false), 2000);
|
|
||||||
} catch {
|
|
||||||
// clipboard API 미지원 환경에서는 무시
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const likeDebounceRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
|
const likeDebounceRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||||
@ -252,6 +253,7 @@ const VideoDetailContent: React.FC<VideoDetailContentProps> = ({ videoId, isModa
|
|||||||
<button
|
<button
|
||||||
className="video-detail-copy-btn"
|
className="video-detail-copy-btn"
|
||||||
onClick={handleShareButtonClick}
|
onClick={handleShareButtonClick}
|
||||||
|
title={t('videoDetail.share')}
|
||||||
>
|
>
|
||||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||||||
<circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/>
|
<circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/>
|
||||||
|
|||||||
@ -194,6 +194,7 @@ const ADO2ContentsPage: React.FC<ADO2ContentsPageProps> = () => {
|
|||||||
videoId={video.video_id}
|
videoId={video.video_id}
|
||||||
storeName={video.store_name}
|
storeName={video.store_name}
|
||||||
region={video.region}
|
region={video.region}
|
||||||
|
title={video.title}
|
||||||
commentCount={video.comment_count ?? 0}
|
commentCount={video.comment_count ?? 0}
|
||||||
initialLikeCount={video.like_count ?? 0}
|
initialLikeCount={video.like_count ?? 0}
|
||||||
initialIsLiked={video.is_liked_by_me}
|
initialIsLiked={video.is_liked_by_me}
|
||||||
|
|||||||
@ -291,6 +291,7 @@ const MyContentsPage: React.FC<MyContentsPageProps> = ({ onNavigate }) => {
|
|||||||
videoId={video.video_id}
|
videoId={video.video_id}
|
||||||
storeName={video.store_name}
|
storeName={video.store_name}
|
||||||
region={video.region}
|
region={video.region}
|
||||||
|
title={video.title}
|
||||||
commentCount={video.comment_count ?? 0}
|
commentCount={video.comment_count ?? 0}
|
||||||
initialLikeCount={video.like_count ?? 0}
|
initialLikeCount={video.like_count ?? 0}
|
||||||
initialIsLiked={video.is_liked_by_me}
|
initialIsLiked={video.is_liked_by_me}
|
||||||
|
|||||||
@ -294,6 +294,8 @@ export interface VideoDetailItem {
|
|||||||
poster_url?: string | null;
|
poster_url?: string | null;
|
||||||
store_name: string;
|
store_name: string;
|
||||||
region: string;
|
region: string;
|
||||||
|
title?: string | null;
|
||||||
|
description?: string | null;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
like_count: number;
|
like_count: number;
|
||||||
is_liked_by_me: boolean;
|
is_liked_by_me: boolean;
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
/**
|
/**
|
||||||
* 기기의 네이티브 공유 시트를 열고 요청을 처리했는지 반환합니다.
|
* 기기의 네이티브 공유 시트를 열고 요청을 처리했는지 반환합니다.
|
||||||
*
|
*
|
||||||
|
* 긴 `text`를 넣으면 카카오 등이 URL을 미리보기가 아니라 본문 텍스트로만 보냅니다.
|
||||||
|
* 제목·설명은 OG 페이지(`og:title`, `og:description`)에 두고, 여기에는 url(과 짧은 title)만 넘깁니다.
|
||||||
|
*
|
||||||
* 사용자가 공유 시트를 닫은 경우도 정상적으로 처리된 것으로 간주합니다.
|
* 사용자가 공유 시트를 닫은 경우도 정상적으로 처리된 것으로 간주합니다.
|
||||||
*/
|
*/
|
||||||
export async function tryNativeShare(data: ShareData): Promise<boolean> {
|
export async function tryNativeShare(data: ShareData): Promise<boolean> {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user