[251010] feat: HomeBanner 비디오 상시재생

🕐 커밋 시간: 2025. 10. 10. 13:38:25

📊 변경 통계:
  • 총 파일: 6개
  • 추가: +150줄
  • 삭제: -16줄

📝 수정된 파일:
  ~ com.twin.app.shoptime/src/actions/playActions.js
  ~ com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx
  ~ com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.jsx
  ~ com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RandomUnit.module.less
  ~ com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RollingUnit.jsx
  ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx

🔧 함수 변경 내용:
  📄 com.twin.app.shoptime/src/actions/playActions.js (javascript):
     Deleted: CLEAR_PLAYER_INFO(), resumePlayerControl()
  📄 com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx (javascript):
    🔄 Modified: SpotlightContainerDecorator()
  📄 com.twin.app.shoptime/src/views/HomePanel/HomeBanner/RollingUnit.jsx (javascript):
     Added: createPanelInfo()

🔧 주요 변경 내용:
  • 핵심 비즈니스 로직 개선
This commit is contained in:
2025-10-10 13:38:27 +09:00
parent a00856c461
commit 10d96f4d8a
6 changed files with 434 additions and 447 deletions

View File

@@ -1,10 +1,10 @@
import Spotlight from "@enact/spotlight";
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";
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
/*
@@ -30,7 +30,7 @@ export const startVideoPlayer =
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;
if (topPanel && topPanel.name === panelName) {
@@ -57,6 +57,7 @@ export const startVideoPlayer =
}, 0);
}
};
export const finishVideoPreview = () => (dispatch, getState) => {
const panels = getState().panels.panels;
const topPanel = panels[panels.length - 1];
@@ -68,12 +69,77 @@ export const finishVideoPreview = () => (dispatch, getState) => {
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, // 일시정지 해제
},
})
);
}
};
// 채팅 로그 가져오기 IF-LGSP-371
export const getChatLog =
({ patnrId, showId }) =>
(dispatch, getState) => {
const onSuccess = (response) => {
console.log("getChatLog onSuccess", response.data);
console.log('getChatLog onSuccess', response.data);
dispatch({
type: types.GET_CHAT_LOG,
@@ -82,10 +148,10 @@ export const getChatLog =
};
const onFail = (error) => {
console.error("getChatLog onFail", error);
console.error('getChatLog onFail', error);
};
TAxios(dispatch, getState, "get", URLS.CHAT_LOG, { patnrId, showId }, {}, onSuccess, onFail);
TAxios(dispatch, getState, 'get', URLS.CHAT_LOG, { patnrId, showId }, {}, onSuccess, onFail);
};
// VOD 자막 가져오기 IF-LGSP-072
@@ -93,7 +159,7 @@ export const getSubTitle =
({ showSubtitleUrl }) =>
(dispatch, getState) => {
const onSuccess = (response) => {
console.log("getSubTitle onSuccess", response.data);
console.log('getSubTitle onSuccess', response.data);
dispatch({
type: types.GET_SUBTITLE,
@@ -102,15 +168,15 @@ export const getSubTitle =
};
const onFail = (error) => {
console.error("getSubTitle onFail", error);
console.error('getSubTitle onFail', error);
dispatch({
type: types.GET_SUBTITLE,
payload: { url: showSubtitleUrl, data: "Error" },
payload: { url: showSubtitleUrl, data: 'Error' },
});
};
if (!getState().play.subTitleBlobs[showSubtitleUrl]) {
TAxios(dispatch, getState, "get", URLS.SUBTITLE, { showSubtitleUrl }, {}, onSuccess, onFail);
TAxios(dispatch, getState, 'get', URLS.SUBTITLE, { showSubtitleUrl }, {}, onSuccess, onFail);
} else {
console.log("playActions getSubTitle no Nothing it's exist", showSubtitleUrl);
}
@@ -129,33 +195,35 @@ export const CLEAR_PLAYER_INFO = () => ({
* @param {object} videoInfo - 재생할 비디오 정보 (url, id 등)
*/
export const requestPlayControl = (ownerId, videoInfo) => (dispatch, getState) => {
const { playerControl } = getState().home;
const currentOwnerId = playerControl.ownerId;
const { playerControl } = getState().home;
const currentOwnerId = playerControl.ownerId;
if (currentOwnerId === ownerId) return; // 이미 제어권 소유
if (currentOwnerId === ownerId) return; // 이미 제어권 소유
if (currentOwnerId) {
// 현재 제어중인 컴포넌트가 영구재생 배너이면 '일시정지'
if (currentOwnerId === 'banner0_persistent') {
dispatch(pausePlayerControl());
} else {
// 다른 미리보기라면 완전히 숨김
dispatch(releasePlayControl(currentOwnerId, true));
}
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
}
}));
}
// 1. 매니저 상태 업데이트
dispatch({ type: types.SET_PLAYER_CONTROL, payload: { ownerId } });
// 2. 공유 PlayerPanel의 상태 업데이트
dispatch(
updatePanel({
name: panel_names.PLAYER_PANEL,
panelInfo: {
isHidden: false,
modal: true,
...videoInfo,
},
})
);
};
/**
@@ -163,28 +231,34 @@ export const requestPlayControl = (ownerId, videoInfo) => (dispatch, getState) =
* @param {string} ownerId - 제어권을 해제하는 컴포넌트의 고유 ID
* @param {boolean} fromPreemption - 다른 요청에 의해 강제로 중단되었는지 여부
*/
export const releasePlayControl = (ownerId, fromPreemption = false) => (dispatch, getState) => {
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,
}
}));
// 1. 공유 PlayerPanel을 다시 숨김
dispatch(
updatePanel({
name: panel_names.PLAYER_PANEL,
panelInfo: {
isHidden: true,
},
})
);
// 2. 매니저 상태 업데이트 (현재 소유주 없음)
dispatch({ type: types.CLEAR_PLAYER_CONTROL });
// 2. 매니저 상태 업데이트 (현재 소유주 없음)
dispatch({ type: types.CLEAR_PLAYER_CONTROL });
// 3. 만약 '일시정지'된 영구재생 비디오가 있었다면, 제어권을 되돌려주고 다시 재생
if (playerControl.isPaused && playerControl.ownerId === 'banner0_persistent') {
const persistentVideoInfo = { /* 영구 비디오 정보를 가져오는 로직 (필요시) */ };
dispatch(requestPlayControl('banner0_persistent', persistentVideoInfo));
}
// 3. 만약 '일시정지'된 영구재생 비디오가 있었다면, 제어권을 되돌려주고 다시 재생
if (playerControl.isPaused && playerControl.ownerId === 'banner0_persistent') {
const persistentVideoInfo = {
/* 영구 비디오 정보를 가져오는 로직 (필요시) */
};
dispatch(requestPlayControl('banner0_persistent', persistentVideoInfo));
}
}
};
};
/**
* 현재 재생 중인 비디오를 '일시정지' 상태로 변경하는 액션.
@@ -224,25 +298,25 @@ export const resumePlayerControl = (ownerId) => (dispatch, getState) => {
* 이 액션은 어떤 배너에서든 클릭 시 호출됩니다.
*/
export const goToFullScreen = () => (dispatch, getState) => {
// 공유 PlayerPanel의 'modal' 상태를 false로 변경하여 전체화면으로 전환
dispatch(updatePanel({
name: panel_names.PLAYER_PANEL,
panelInfo: {
modal: false,
isHidden: false, // 혹시 숨겨져 있었다면 보이도록
}
}));
// 공유 PlayerPanel의 'modal' 상태를 false로 변경하여 전체화면으로 전환
dispatch(
updatePanel({
name: panel_names.PLAYER_PANEL,
panelInfo: {
modal: false,
isHidden: false, // 혹시 숨겨져 있었다면 보이도록
},
})
);
};
/**
* 영구재생 비디오를 일시정지 상태로 만듭니다. (내부 사용)
*/
export const pausePlayerControl = () => ({
type: types.PAUSE_PLAYER_CONTROL
type: types.PAUSE_PLAYER_CONTROL,
});
/**
* 전체화면 플레이어에서 미리보기 상태로 복귀할 때 호출됩니다.
* 중앙 'playerControl' 상태를 확인하여 올바른 위치와 비디오로 복원합니다.
@@ -270,4 +344,4 @@ export const returnToPreview = () => (dispatch, getState) => {
// 돌아갈 곳이 없으면 그냥 플레이어를 닫음
dispatch(finishVideoPreview());
}
};
};