From 94b39a44bd316457bdec2be7e4e8300e303eb8bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=84=B1=EA=B2=BD?= Date: Mon, 24 Aug 2026 13:45:16 +0900 Subject: [PATCH] =?UTF-8?q?feat(ssulbox):=20=EC=8D=B0=EB=B0=95=EC=8A=A4=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=EC=97=90=20=EA=B3=B5=EC=8B=9D=20=EB=A7=81?= =?UTF-8?q?=ED=81=AC=20=EC=98=A4=EB=B2=84=EB=A0=88=EC=9D=B4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/VideoDetailContent.tsx | 11 +---- src/pages/Ssulbox/SsulDetailContent.tsx | 57 +++++++++++++++++++------ src/styles/contents-social.css | 2 +- src/utils/api.ts | 2 + src/utils/url.ts | 15 +++++++ 5 files changed, 63 insertions(+), 24 deletions(-) create mode 100644 src/utils/url.ts diff --git a/src/components/VideoDetailContent.tsx b/src/components/VideoDetailContent.tsx index 10fa4d6..ced9e7b 100644 --- a/src/components/VideoDetailContent.tsx +++ b/src/components/VideoDetailContent.tsx @@ -13,16 +13,7 @@ import { import { VideoDetailItem, CommentItem, UserMeResponse } from '../types/api'; import { buildVideoShareUrl, tryNativeShare } from '../utils/nativeShare'; import LoginPromptModal from './LoginPromptModal'; - -const isSafeHttpUrl = (url?: string | null): boolean => { - if (!url) return false; - try { - const parsed = new URL(url); - return parsed.protocol === 'http:' || parsed.protocol === 'https:'; - } catch { - return false; - } -}; +import { isSafeHttpUrl } from '../utils/url'; interface VideoDetailContentProps { videoId: string; diff --git a/src/pages/Ssulbox/SsulDetailContent.tsx b/src/pages/Ssulbox/SsulDetailContent.tsx index 2b60897..f3dc331 100644 --- a/src/pages/Ssulbox/SsulDetailContent.tsx +++ b/src/pages/Ssulbox/SsulDetailContent.tsx @@ -14,6 +14,7 @@ import type { SsulDetailItem } from '../../utils/api'; import { CommentItem, UserMeResponse } from '../../types/api'; import { buildContentShareUrl, tryNativeShare } from '../../utils/nativeShare'; import LoginPromptModal from '../../components/LoginPromptModal'; +import { isSafeHttpUrl } from '../../utils/url'; interface SsulDetailContentProps { contentId: string; @@ -48,6 +49,7 @@ const SsulDetailContent: React.FC = ({ const [copied, setCopied] = useState(false); const [isLandscape, setIsLandscape] = useState(false); + const [showSiteOverlay, setShowSiteOverlay] = useState(false); const [showLoginModal, setShowLoginModal] = useState(false); const [comments, setComments] = useState([]); @@ -86,6 +88,7 @@ const SsulDetailContent: React.FC = ({ const fetchContent = async () => { setLoading(true); setError(null); + setShowSiteOverlay(false); try { const data = await getSsulContentById(contentId); setContent(data); @@ -265,19 +268,47 @@ const SsulDetailContent: React.FC = ({

{error}

) : content ? (
-