fix: 영상 상세 모달을 social-posting-modal 구조로 통일하고 video 삐져나옴 버그 수정
This commit is contained in:
parent
40ebe2cca0
commit
1c01dab748
@ -249,6 +249,7 @@ const VideoDetailContent: React.FC<VideoDetailContentProps> = ({ videoId, isModa
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="video-detail-body">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="ado2-contents-loading">
|
<div className="ado2-contents-loading">
|
||||||
<div className="loading-spinner"></div>
|
<div className="loading-spinner"></div>
|
||||||
@ -262,6 +263,7 @@ const VideoDetailContent: React.FC<VideoDetailContentProps> = ({ videoId, isModa
|
|||||||
src={video.result_movie_url}
|
src={video.result_movie_url}
|
||||||
controls
|
controls
|
||||||
autoPlay
|
autoPlay
|
||||||
|
playsInline
|
||||||
controlsList="nodownload"
|
controlsList="nodownload"
|
||||||
onContextMenu={(e) => e.preventDefault()}
|
onContextMenu={(e) => e.preventDefault()}
|
||||||
className="video-detail-player"
|
className="video-detail-player"
|
||||||
@ -477,6 +479,7 @@ const VideoDetailContent: React.FC<VideoDetailContentProps> = ({ videoId, isModa
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
</div>
|
||||||
|
|
||||||
{showLoginModal && (
|
{showLoginModal && (
|
||||||
<LoginPromptModal onClose={() => setShowLoginModal(false)} />
|
<LoginPromptModal onClose={() => setShowLoginModal(false)} />
|
||||||
|
|||||||
@ -27,29 +27,8 @@ const VideoDetailModal: React.FC<VideoDetailModalProps> = ({ videoId, onClose })
|
|||||||
const overlayCloseHandlers = useOverlayClose(onClose);
|
const overlayCloseHandlers = useOverlayClose(onClose);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className="video-detail-overlay" {...overlayCloseHandlers}>
|
||||||
style={{
|
<div className="video-detail-modal-box" onClick={(e) => e.stopPropagation()}>
|
||||||
position: 'fixed',
|
|
||||||
inset: 0,
|
|
||||||
background: 'rgba(0, 0, 0, 0.85)',
|
|
||||||
zIndex: 2000,
|
|
||||||
display: 'flex',
|
|
||||||
overflowY: 'auto',
|
|
||||||
padding: '24px 16px',
|
|
||||||
}}
|
|
||||||
{...overlayCloseHandlers}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
background: '#01282A',
|
|
||||||
borderRadius: '16px',
|
|
||||||
width: '100%',
|
|
||||||
maxWidth: '800px',
|
|
||||||
margin: 'auto',
|
|
||||||
position: 'relative',
|
|
||||||
}}
|
|
||||||
onClick={(e) => e.stopPropagation()}
|
|
||||||
>
|
|
||||||
<VideoDetailContent videoId={videoId} isModal={true} onClose={onClose} />
|
<VideoDetailContent videoId={videoId} isModal={true} onClose={onClose} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -290,6 +290,7 @@ const SsulDetailContent: React.FC<SsulDetailContentProps> = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="video-detail-body">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="ado2-contents-loading">
|
<div className="ado2-contents-loading">
|
||||||
<div className="loading-spinner"></div>
|
<div className="loading-spinner"></div>
|
||||||
@ -303,6 +304,7 @@ const SsulDetailContent: React.FC<SsulDetailContentProps> = ({
|
|||||||
src={content.video_url}
|
src={content.video_url}
|
||||||
controls
|
controls
|
||||||
autoPlay
|
autoPlay
|
||||||
|
playsInline
|
||||||
controlsList="nodownload"
|
controlsList="nodownload"
|
||||||
onContextMenu={(e) => e.preventDefault()}
|
onContextMenu={(e) => e.preventDefault()}
|
||||||
className="video-detail-player"
|
className="video-detail-player"
|
||||||
@ -513,6 +515,7 @@ const SsulDetailContent: React.FC<SsulDetailContentProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
</div>
|
||||||
|
|
||||||
{showLoginModal && (
|
{showLoginModal && (
|
||||||
<LoginPromptModal onClose={() => setShowLoginModal(false)} />
|
<LoginPromptModal onClose={() => setShowLoginModal(false)} />
|
||||||
|
|||||||
@ -39,29 +39,8 @@ const SsulViewerModal: React.FC<SsulViewerModalProps> = ({ item, onClose }) => {
|
|||||||
if (!item) return null;
|
if (!item) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className="video-detail-overlay" {...overlayCloseHandlers}>
|
||||||
style={{
|
<div className="video-detail-modal-box" onClick={(e) => e.stopPropagation()}>
|
||||||
position: 'fixed',
|
|
||||||
inset: 0,
|
|
||||||
background: 'rgba(0, 0, 0, 0.85)',
|
|
||||||
zIndex: 2000,
|
|
||||||
display: 'flex',
|
|
||||||
overflowY: 'auto',
|
|
||||||
padding: '24px 16px',
|
|
||||||
}}
|
|
||||||
{...overlayCloseHandlers}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
background: '#01282A',
|
|
||||||
borderRadius: '16px',
|
|
||||||
width: '100%',
|
|
||||||
maxWidth: '800px',
|
|
||||||
margin: 'auto',
|
|
||||||
position: 'relative',
|
|
||||||
}}
|
|
||||||
onClick={(e) => e.stopPropagation()}
|
|
||||||
>
|
|
||||||
<SsulDetailContent
|
<SsulDetailContent
|
||||||
contentId={String(item.video_id)}
|
contentId={String(item.video_id)}
|
||||||
isModal={true}
|
isModal={true}
|
||||||
|
|||||||
@ -646,10 +646,56 @@
|
|||||||
|
|
||||||
/* ── VideoDetailPage / VideoDetailModal ─────────────────────────── */
|
/* ── VideoDetailPage / VideoDetailModal ─────────────────────────── */
|
||||||
|
|
||||||
/* 모달 내부 콘텐츠 (풀페이지의 video-detail-page와 동일 스타일, 배경 제외) */
|
/* social-posting-overlay 와 동일한 구조: 배경 + 중앙 정렬 + 내부 스크롤 박스 */
|
||||||
|
.video-detail-overlay {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
text-align: left;
|
||||||
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 2000;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* social-posting-modal 과 동일한 박스 스타일: 헤더 고정 + 본문만 스크롤 */
|
||||||
|
.video-detail-modal-box {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 800px;
|
||||||
|
max-height: 90vh;
|
||||||
|
background-color: #01282A;
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 1px solid rgba(166, 255, 234, 0.1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
/* 일부 모바일 브라우저는 video 를 별도 하드웨어 컴포지팅 레이어로 그려
|
||||||
|
overflow:hidden + border-radius 클리핑을 무시하고 밖으로 삐져나온다.
|
||||||
|
contain:paint 로 이 박스 밖에는 절대 그려지지 않도록 강제한다. */
|
||||||
|
contain: paint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 모달 내부 콘텐츠 (풀페이지의 video-detail-page와 동일 스타일, 배경 제외).
|
||||||
|
헤더는 여기의 일반 흐름 자식(스크롤 없음)이고, .video-detail-body 만 스크롤된다.
|
||||||
|
과거엔 헤더에 position:sticky 를 써서 흉내냈으나, 자동재생 <video> 와 같은
|
||||||
|
스크롤 컨테이너 안에 sticky 요소가 있으면 iOS Safari 에서 video 가 별도
|
||||||
|
레이어로 떨어져나가 모달 밖으로 삐져나오는 버그가 있어 구조 자체를 분리했다. */
|
||||||
.video-detail-modal-content {
|
.video-detail-modal-content {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
padding: 24px 32px;
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* social-posting-content 에 대응하는 스크롤 영역 */
|
||||||
|
.video-detail-modal-content > .video-detail-body {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 0 32px 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-detail-page-content {
|
.video-detail-page-content {
|
||||||
@ -693,10 +739,12 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
padding: 1.25rem 1.5rem;
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-detail-modal-title {
|
.video-detail-modal-title {
|
||||||
font-size: 20px;
|
font-size: 24px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@ -737,6 +785,7 @@
|
|||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
padding: 1rem;
|
||||||
max-width: 360px;
|
max-width: 360px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
@ -752,7 +801,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
padding-top: 8px;
|
padding-top: 1rem;
|
||||||
align-self: flex-start;
|
align-self: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1183,6 +1232,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* social-posting-modal 의 Mobile Adjustments 와 동일한 기준(768px) */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.video-detail-modal-box {
|
||||||
|
max-height: 95vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-detail-modal-content > .video-detail-header {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-detail-modal-content > .video-detail-body {
|
||||||
|
padding: 0 1rem 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.pagination-info {
|
.pagination-info {
|
||||||
color: #9BCACC;
|
color: #9BCACC;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user