- PlayerPanel useEffect에서 shouldShrinkTo1px 플래그로 인라인 스타일 제거 - shrinkVideoTo1px/expandVideoFrom1px 액션 추가 (배너 정보 playerState에 저장) - PlayerPanel.module.less에 .shrinkTo1px 클래스 추가 - HomePanel onScroll에서 스크롤 방향 감지하여 축소/확대 제어 - RandomUnit onBlur에서의 축소 로직은 주석 처리 (스크롤로 제어)
545 lines
17 KiB
JavaScript
545 lines
17 KiB
JavaScript
import Spotlight from '@enact/spotlight';
|
|
|
|
import { URLS } from '../api/apiConfig';
|
|
import { TAxios } from '../api/TAxios';
|
|
import { panel_names } from '../utils/Config';
|
|
import { types } from './actionTypes';
|
|
import { popPanel, pushPanel, updatePanel } from './panelActions';
|
|
|
|
//yhcho
|
|
/*
|
|
dispatch(startVideoPreview({
|
|
patnrId: randomData.patnrId,
|
|
showId: randomData.showId,
|
|
shptmBanrTpNm: randomData.shptmBanrTpNm,
|
|
lgCatCd: randomData.lgCatCd,
|
|
modal: true,
|
|
modalContainerRef: videoModalContainerRef.current, //to calc width, height, left, top
|
|
modalClassName:css.videoModal
|
|
}));
|
|
|
|
modalClassName: modal more class info and checking it's launched from preview mode
|
|
*/
|
|
let startVideoTimer = null;
|
|
//start modal mode
|
|
//start Full -> modal mode
|
|
let startVideoFocusTimer = null;
|
|
export const startVideoPlayer =
|
|
({ modal, modalContainerId, modalClassName, spotlightDisable, useNewPlayer, ...rest }) =>
|
|
(dispatch, getState) => {
|
|
const panels = getState().panels.panels;
|
|
const topPanel = panels[panels.length - 1];
|
|
let panelWorkingAction = pushPanel;
|
|
|
|
// const panelName = useNewPlayer ? panel_names.PLAYER_PANEL_NEW : panel_names.PLAYER_PANEL;
|
|
const panelName = panel_names.PLAYER_PANEL;
|
|
|
|
if (topPanel && topPanel.name === panelName) {
|
|
panelWorkingAction = updatePanel;
|
|
}
|
|
dispatch(
|
|
panelWorkingAction(
|
|
{
|
|
name: panelName,
|
|
panelInfo: {
|
|
modal,
|
|
modalContainerId,
|
|
modalClassName,
|
|
...rest,
|
|
},
|
|
},
|
|
true
|
|
)
|
|
);
|
|
if (modal && modalContainerId && !spotlightDisable) {
|
|
Spotlight.setPointerMode(false);
|
|
startVideoFocusTimer = setTimeout(() => {
|
|
Spotlight.focus(modalContainerId);
|
|
}, 0);
|
|
}
|
|
};
|
|
|
|
export const startVideoPlayerNew =
|
|
({ modal, modalContainerId, modalClassName, spotlightDisable, useNewPlayer, bannerId, ...rest }) =>
|
|
(dispatch, getState) => {
|
|
const panels = getState().panels.panels;
|
|
const topPanel = panels[panels.length - 1];
|
|
let panelWorkingAction = pushPanel;
|
|
|
|
// const panelName = useNewPlayer ? panel_names.PLAYER_PANEL_NEW : panel_names.PLAYER_PANEL;
|
|
const panelName = panel_names.PLAYER_PANEL;
|
|
|
|
if (topPanel && topPanel.name === panelName) {
|
|
panelWorkingAction = updatePanel;
|
|
}
|
|
|
|
// playerState 업데이트: 기존 playerState와 새 데이터 병합
|
|
const currentPlayerState = topPanel?.panelInfo?.playerState || {};
|
|
|
|
// 같은 배너에서 이미 비디오가 재생 중이면 return (중복 재생 방지)
|
|
if (currentPlayerState.currentBannerId === bannerId) {
|
|
return;
|
|
}
|
|
|
|
const newPlayerState = {
|
|
...currentPlayerState,
|
|
currentBannerId: bannerId,
|
|
};
|
|
|
|
dispatch(
|
|
panelWorkingAction(
|
|
{
|
|
name: panelName,
|
|
panelInfo: {
|
|
modal,
|
|
modalContainerId,
|
|
modalClassName,
|
|
playerState: newPlayerState,
|
|
...rest,
|
|
},
|
|
},
|
|
true
|
|
)
|
|
);
|
|
if (modal && modalContainerId && !spotlightDisable) {
|
|
Spotlight.setPointerMode(false);
|
|
startVideoFocusTimer = setTimeout(() => {
|
|
Spotlight.focus(modalContainerId);
|
|
}, 0);
|
|
}
|
|
};
|
|
|
|
export const finishVideoPreview = () => (dispatch, getState) => {
|
|
const panels = getState().panels.panels;
|
|
const topPanel = panels[panels.length - 1];
|
|
if (topPanel && topPanel.name === panel_names.PLAYER_PANEL && topPanel.panelInfo.modal) {
|
|
if (startVideoFocusTimer) {
|
|
clearTimeout(startVideoFocusTimer);
|
|
startVideoFocusTimer = null;
|
|
}
|
|
dispatch(popPanel());
|
|
}
|
|
};
|
|
|
|
export const finishModalVideoForce = () => (dispatch, getState) => {
|
|
const panels = getState().panels.panels;
|
|
|
|
// modal PlayerPanel이 존재하는지 확인 (스택 어디에 있든)
|
|
const hasModalPlayerPanel = panels.some(
|
|
(panel) => panel.name === panel_names.PLAYER_PANEL && panel.panelInfo?.modal
|
|
);
|
|
|
|
if (hasModalPlayerPanel) {
|
|
if (startVideoFocusTimer) {
|
|
clearTimeout(startVideoFocusTimer);
|
|
startVideoFocusTimer = null;
|
|
}
|
|
// panelName을 지정하면 스택 어디에 있든 해당 패널을 제거
|
|
dispatch(popPanel(panel_names.PLAYER_PANEL));
|
|
}
|
|
};
|
|
|
|
// 모달 비디오를 일시정지 (패널은 유지)
|
|
export const pauseModalVideo = () => (dispatch, getState) => {
|
|
const panels = getState().panels.panels;
|
|
|
|
// modal PlayerPanel 찾기
|
|
const modalPlayerPanel = panels.find(
|
|
(panel) => panel.name === panel_names.PLAYER_PANEL && panel.panelInfo?.modal
|
|
);
|
|
|
|
if (modalPlayerPanel) {
|
|
console.log('[pauseModalVideo] Pausing modal video');
|
|
dispatch(
|
|
updatePanel({
|
|
name: panel_names.PLAYER_PANEL,
|
|
panelInfo: {
|
|
...modalPlayerPanel.panelInfo,
|
|
isPaused: true, // 일시정지 플래그 추가
|
|
},
|
|
})
|
|
);
|
|
}
|
|
};
|
|
|
|
// 모달 비디오를 재생 (일시정지 해제)
|
|
export const resumeModalVideo = () => (dispatch, getState) => {
|
|
const panels = getState().panels.panels;
|
|
|
|
// modal PlayerPanel 찾기
|
|
const modalPlayerPanel = panels.find(
|
|
(panel) => panel.name === panel_names.PLAYER_PANEL && panel.panelInfo?.modal
|
|
);
|
|
|
|
if (modalPlayerPanel && modalPlayerPanel.panelInfo?.isPaused) {
|
|
console.log('[resumeModalVideo] Resuming modal video');
|
|
dispatch(
|
|
updatePanel({
|
|
name: panel_names.PLAYER_PANEL,
|
|
panelInfo: {
|
|
...modalPlayerPanel.panelInfo,
|
|
isPaused: false, // 일시정지 해제
|
|
},
|
|
})
|
|
);
|
|
}
|
|
};
|
|
|
|
// 전체화면 비디오를 일시정지 (패널은 유지)
|
|
export const pauseFullscreenVideo = () => (dispatch, getState) => {
|
|
const panels = getState().panels.panels;
|
|
|
|
// 전체화면 PlayerPanel 찾기 (modal이 false인 패널)
|
|
const fullscreenPlayerPanel = panels.find(
|
|
(panel) => panel.name === panel_names.PLAYER_PANEL && !panel.panelInfo?.modal
|
|
);
|
|
|
|
if (fullscreenPlayerPanel) {
|
|
dispatch(
|
|
updatePanel({
|
|
name: panel_names.PLAYER_PANEL,
|
|
panelInfo: {
|
|
...fullscreenPlayerPanel.panelInfo,
|
|
isPaused: true, // 일시정지 플래그 추가
|
|
},
|
|
})
|
|
);
|
|
}
|
|
};
|
|
|
|
// 전체화면 비디오를 재생 (일시정지 해제)
|
|
export const resumeFullscreenVideo = () => (dispatch, getState) => {
|
|
const panels = getState().panels.panels;
|
|
|
|
// console.log('[BgVideo] resumeFullscreenVideo called - panels:', {
|
|
// panelsCount: panels?.length,
|
|
// panels: panels?.map(p => ({ name: p.name, modal: p.panelInfo?.modal, isPaused: p.panelInfo?.isPaused }))
|
|
// });
|
|
|
|
// 전체화면 PlayerPanel 찾기 (modal이 false인 패널)
|
|
const fullscreenPlayerPanel = panels.find(
|
|
(panel) => panel.name === panel_names.PLAYER_PANEL && !panel.panelInfo?.modal
|
|
);
|
|
|
|
// console.log('[BgVideo] resumeFullscreenVideo - fullscreenPlayerPanel found:', !!fullscreenPlayerPanel);
|
|
// console.log('[BgVideo] resumeFullscreenVideo - isPaused:', fullscreenPlayerPanel?.panelInfo?.isPaused);
|
|
|
|
if (fullscreenPlayerPanel && fullscreenPlayerPanel.panelInfo?.isPaused) {
|
|
// console.log('[BgVideo] resumeFullscreenVideo - dispatching updatePanel with isPaused: false');
|
|
dispatch(
|
|
updatePanel({
|
|
name: panel_names.PLAYER_PANEL,
|
|
panelInfo: {
|
|
...fullscreenPlayerPanel.panelInfo,
|
|
isPaused: false, // 일시정지 해제
|
|
},
|
|
})
|
|
);
|
|
} else {
|
|
console.log('[BgVideo] resumeFullscreenVideo - Not resuming (not found or not paused)');
|
|
}
|
|
};
|
|
|
|
// 모달 비디오를 1px로 축소 (배너 정보 저장)
|
|
export const shrinkVideoTo1px = () => (dispatch, getState) => {
|
|
const panels = getState().panels.panels;
|
|
|
|
// modal PlayerPanel 찾기
|
|
const modalPlayerPanel = panels.find(
|
|
(panel) => panel.name === panel_names.PLAYER_PANEL && panel.panelInfo?.modal
|
|
);
|
|
|
|
if (modalPlayerPanel) {
|
|
const panelInfo = modalPlayerPanel.panelInfo;
|
|
console.log('[shrinkVideoTo1px] Shrinking modal video to 1px');
|
|
|
|
// 축소 전 배너 정보를 playerState에 저장
|
|
const updatedPlayerState = {
|
|
...(panelInfo.playerState || {}),
|
|
shrinkInfo: {
|
|
// 복구 시 필요한 정보
|
|
modalContainerId: panelInfo.modalContainerId,
|
|
modalClassName: panelInfo.modalClassName,
|
|
modalStyle: panelInfo.modalStyle,
|
|
modalScale: panelInfo.modalScale,
|
|
currentBannerId: panelInfo.playerState?.currentBannerId,
|
|
patnrId: panelInfo.patnrId,
|
|
showId: panelInfo.showId,
|
|
shptmBanrTpNm: panelInfo.shptmBanrTpNm,
|
|
lgCatCd: panelInfo.lgCatCd,
|
|
},
|
|
};
|
|
|
|
dispatch(
|
|
updatePanel({
|
|
name: panel_names.PLAYER_PANEL,
|
|
panelInfo: {
|
|
...panelInfo,
|
|
shouldShrinkTo1px: true, // 축소 플래그 설정
|
|
playerState: updatedPlayerState,
|
|
},
|
|
})
|
|
);
|
|
}
|
|
};
|
|
|
|
// 축소된 모달 비디오를 원래 크기로 복구
|
|
export const expandVideoFrom1px = () => (dispatch, getState) => {
|
|
const panels = getState().panels.panels;
|
|
|
|
// 축소된 modal PlayerPanel 찾기
|
|
const shrunkModalPlayerPanel = panels.find(
|
|
(panel) => panel.name === panel_names.PLAYER_PANEL && panel.panelInfo?.modal && panel.panelInfo?.shouldShrinkTo1px
|
|
);
|
|
|
|
if (shrunkModalPlayerPanel) {
|
|
const panelInfo = shrunkModalPlayerPanel.panelInfo;
|
|
const shrinkInfo = panelInfo.playerState?.shrinkInfo;
|
|
|
|
console.log('[expandVideoFrom1px] Expanding modal video from 1px', shrinkInfo);
|
|
|
|
dispatch(
|
|
updatePanel({
|
|
name: panel_names.PLAYER_PANEL,
|
|
panelInfo: {
|
|
...panelInfo,
|
|
shouldShrinkTo1px: false, // 축소 플래그 해제
|
|
// 저장된 정보로 복구
|
|
...(shrinkInfo && {
|
|
modalContainerId: shrinkInfo.modalContainerId,
|
|
modalClassName: shrinkInfo.modalClassName,
|
|
modalStyle: shrinkInfo.modalStyle,
|
|
modalScale: shrinkInfo.modalScale,
|
|
}),
|
|
},
|
|
})
|
|
);
|
|
}
|
|
};
|
|
|
|
// 채팅 로그 가져오기 IF-LGSP-371
|
|
export const getChatLog =
|
|
({ patnrId, showId }) =>
|
|
(dispatch, getState) => {
|
|
const onSuccess = (response) => {
|
|
console.log('getChatLog onSuccess', response.data);
|
|
|
|
dispatch({
|
|
type: types.GET_CHAT_LOG,
|
|
payload: response.data.data,
|
|
});
|
|
};
|
|
|
|
const onFail = (error) => {
|
|
console.error('getChatLog onFail', error);
|
|
};
|
|
|
|
TAxios(dispatch, getState, 'get', URLS.CHAT_LOG, { patnrId, showId }, {}, onSuccess, onFail);
|
|
};
|
|
|
|
// VOD 자막 가져오기 IF-LGSP-072
|
|
export const getSubTitle =
|
|
({ showSubtitleUrl }) =>
|
|
(dispatch, getState) => {
|
|
const onSuccess = (response) => {
|
|
console.log('getSubTitle onSuccess', response.data);
|
|
|
|
dispatch({
|
|
type: types.GET_SUBTITLE,
|
|
payload: { url: showSubtitleUrl, data: response.data.data },
|
|
});
|
|
};
|
|
|
|
const onFail = (error) => {
|
|
console.error('getSubTitle onFail', error);
|
|
dispatch({
|
|
type: types.GET_SUBTITLE,
|
|
payload: { url: showSubtitleUrl, data: 'Error' },
|
|
});
|
|
};
|
|
|
|
if (!getState().play.subTitleBlobs[showSubtitleUrl]) {
|
|
TAxios(dispatch, getState, 'get', URLS.SUBTITLE, { showSubtitleUrl }, {}, onSuccess, onFail);
|
|
} else {
|
|
console.log("playActions getSubTitle no Nothing it's exist", showSubtitleUrl);
|
|
}
|
|
};
|
|
|
|
export const CLEAR_PLAYER_INFO = () => ({
|
|
type: types.CLEAR_PLAYER_INFO,
|
|
});
|
|
|
|
/**
|
|
* 비디오 재생 상태를 Redux에 업데이트합니다.
|
|
* @param {Object} playState - 업데이트할 재생 상태
|
|
* @param {boolean} playState.isPlaying - 재생 중인지 여부
|
|
* @param {boolean} playState.isPaused - 일시정지 상태인지 여부
|
|
* @param {number} playState.currentTime - 현재 재생 시간(초)
|
|
* @param {number} playState.duration - 전체 비디오 길이(초)
|
|
* @param {number} playState.playbackRate - 재생 속도
|
|
*/
|
|
export const updateVideoPlayState = (playState) => ({
|
|
type: types.UPDATE_VIDEO_PLAY_STATE,
|
|
payload: playState,
|
|
});
|
|
|
|
/* 🔽 [추가] 새로운 '플레이 제어 매니저' 액션들 */
|
|
|
|
/**
|
|
* 비디오 재생 제어권을 요청합니다.
|
|
* 컴포넌트는 이 액션을 통해 중앙 매니저에게 재생을 '요청'합니다.
|
|
* @param {string} ownerId - 제어권을 요청하는 컴포넌트의 고유 ID (예: 'banner0_persistent')
|
|
* @param {object} videoInfo - 재생할 비디오 정보 (url, id 등)
|
|
*/
|
|
export const requestPlayControl = (ownerId, videoInfo) => (dispatch, getState) => {
|
|
const { playerControl } = getState().home;
|
|
const currentOwnerId = playerControl.ownerId;
|
|
|
|
if (currentOwnerId === ownerId) return; // 이미 제어권 소유
|
|
|
|
if (currentOwnerId) {
|
|
// 현재 제어중인 컴포넌트가 영구재생 배너이면 '일시정지'
|
|
if (currentOwnerId === 'banner0_persistent') {
|
|
dispatch(pausePlayerControl());
|
|
} else {
|
|
// 다른 미리보기라면 완전히 숨김
|
|
dispatch(releasePlayControl(currentOwnerId, true));
|
|
}
|
|
}
|
|
|
|
// 1. 매니저 상태 업데이트
|
|
dispatch({ type: types.SET_PLAYER_CONTROL, payload: { ownerId } });
|
|
|
|
// 2. 공유 PlayerPanel의 상태 업데이트
|
|
dispatch(
|
|
updatePanel({
|
|
name: panel_names.PLAYER_PANEL,
|
|
panelInfo: {
|
|
isHidden: false,
|
|
modal: true,
|
|
...videoInfo,
|
|
},
|
|
})
|
|
);
|
|
};
|
|
|
|
/**
|
|
* 비디오 재생 제어권을 해제하고, 필요시 영구재생 비디오를 복원합니다.
|
|
* @param {string} ownerId - 제어권을 해제하는 컴포넌트의 고유 ID
|
|
* @param {boolean} fromPreemption - 다른 요청에 의해 강제로 중단되었는지 여부
|
|
*/
|
|
export const releasePlayControl =
|
|
(ownerId, fromPreemption = false) =>
|
|
(dispatch, getState) => {
|
|
const { playerControl } = getState().home;
|
|
|
|
if (fromPreemption || playerControl.ownerId === ownerId) {
|
|
// 1. 공유 PlayerPanel을 다시 숨김
|
|
dispatch(
|
|
updatePanel({
|
|
name: panel_names.PLAYER_PANEL,
|
|
panelInfo: {
|
|
isHidden: true,
|
|
},
|
|
})
|
|
);
|
|
|
|
// 2. 매니저 상태 업데이트 (현재 소유주 없음)
|
|
dispatch({ type: types.CLEAR_PLAYER_CONTROL });
|
|
|
|
// 3. 만약 '일시정지'된 영구재생 비디오가 있었다면, 제어권을 되돌려주고 다시 재생
|
|
if (playerControl.isPaused && playerControl.ownerId === 'banner0_persistent') {
|
|
const persistentVideoInfo = {
|
|
/* 영구 비디오 정보를 가져오는 로직 (필요시) */
|
|
};
|
|
dispatch(requestPlayControl('banner0_persistent', persistentVideoInfo));
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 현재 재생 중인 비디오를 '일시정지' 상태로 변경하는 액션.
|
|
* 이 함수는 플레이어 패널을 닫지 않고, 단순히 비디오 재생을 멈추는 신호를 보냅니다.
|
|
*
|
|
* @param {string} ownerId - 비디오 제어권을 가진 컴포넌트의 고유 ID.
|
|
*/
|
|
// export const pausePlayerControl = (ownerId) => (dispatch, getState) => {
|
|
// const { playerControl } = getState().home;
|
|
|
|
// // 제어권을 가진 컴포넌트가 자신일 경우에만 일시정지
|
|
// if (playerControl.ownerId === ownerId) {
|
|
// dispatch({
|
|
// type: types.PAUSE_PLAYER_CONTROL,
|
|
// });
|
|
// }
|
|
// };
|
|
|
|
/**
|
|
* '일시정지' 상태의 비디오를 다시 재생하는 액션.
|
|
*
|
|
* @param {string} ownerId - 비디오 제어권을 가진 컴포넌트의 고유 ID.
|
|
*/
|
|
export const resumePlayerControl = (ownerId) => (dispatch, getState) => {
|
|
const { playerControl } = getState().home;
|
|
|
|
// 제어권을 가진 컴포넌트가 자신이고, 일시정지 상태일 때만 재개
|
|
if (playerControl.ownerId === ownerId && playerControl.isPaused) {
|
|
dispatch({
|
|
type: types.RESUME_PLAYER_CONTROL,
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 공유 PlayerPanel을 전체화면 모드로 전환합니다.
|
|
* 이 액션은 어떤 배너에서든 클릭 시 호출됩니다.
|
|
*/
|
|
export const goToFullScreen = () => (dispatch, getState) => {
|
|
// 공유 PlayerPanel의 'modal' 상태를 false로 변경하여 전체화면으로 전환
|
|
dispatch(
|
|
updatePanel({
|
|
name: panel_names.PLAYER_PANEL,
|
|
panelInfo: {
|
|
modal: false,
|
|
isHidden: false, // 혹시 숨겨져 있었다면 보이도록
|
|
},
|
|
})
|
|
);
|
|
};
|
|
|
|
/**
|
|
* 영구재생 비디오를 일시정지 상태로 만듭니다. (내부 사용)
|
|
*/
|
|
export const pausePlayerControl = () => ({
|
|
type: types.PAUSE_PLAYER_CONTROL,
|
|
});
|
|
|
|
/**
|
|
* 전체화면 플레이어에서 미리보기 상태로 복귀할 때 호출됩니다.
|
|
* 중앙 'playerControl' 상태를 확인하여 올바른 위치와 비디오로 복원합니다.
|
|
*/
|
|
export const returnToPreview = () => (dispatch, getState) => {
|
|
const { playerControl } = getState().home;
|
|
|
|
let targetOwnerId;
|
|
let targetVideoInfo;
|
|
|
|
// 만약 '일시정지'된 영구재생 비디오가 있다면, 무조건 그 비디오로 복귀하는 것이 최우선
|
|
if (playerControl.isPaused) {
|
|
targetOwnerId = 'banner0_persistent';
|
|
// targetVideoInfo = ... (0번 배너의 비디오 정보를 가져오는 로직)
|
|
} else {
|
|
// 그렇지 않다면, 전체화면으로 가기 직전의 소유주(ownerId)에게로 복귀
|
|
targetOwnerId = playerControl.ownerId;
|
|
// targetVideoInfo = ... (해당 ownerId의 비디오 정보를 가져오는 로직)
|
|
}
|
|
|
|
// 매니저에게 해당 타겟으로 재생을 다시 요청
|
|
if (targetOwnerId) {
|
|
dispatch(requestPlayControl(targetOwnerId, targetVideoInfo));
|
|
} else {
|
|
// 돌아갈 곳이 없으면 그냥 플레이어를 닫음
|
|
dispatch(finishVideoPreview());
|
|
}
|
|
};
|