[251013] feat:Video관련 action 추가
🕐 커밋 시간: 2025. 10. 13. 12:37:46 📊 변경 통계: • 총 파일: 7개 • 추가: +95줄 • 삭제: -168줄 📁 추가된 파일: + com.twin.app.shoptime/[251013]_RollingUnit_리렌더링_분석_및_해결방법.md 📝 수정된 파일: ~ com.twin.app.shoptime/src/actions/actionTypes.js ~ com.twin.app.shoptime/src/actions/playActions.js ~ com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.js ~ com.twin.app.shoptime/src/reducers/playReducer.js ~ com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx 🔧 함수 변경 내용: 📄 com.twin.app.shoptime/src/actions/playActions.js (javascript): 🔄 Modified: pauseModalVideo() 📄 com.twin.app.shoptime/src/views/HomePanel/HomeBanner/HomeBanner.jsx (javascript): 🔄 Modified: SpotlightContainerDecorator() 🔧 주요 변경 내용: • 타입 시스템 안정성 강화 • 핵심 비즈니스 로직 개선 • UI 컴포넌트 아키텍처 개선 • 개발 문서 및 가이드 개선 Performance: 코드 최적화로 성능 개선 기대
This commit is contained in:
416
com.twin.app.shoptime/[251013]_RollingUnit_리렌더링_분석_및_해결방법.md
Normal file
416
com.twin.app.shoptime/[251013]_RollingUnit_리렌더링_분석_및_해결방법.md
Normal file
@@ -0,0 +1,416 @@
|
|||||||
|
# [251013] RollingUnit 리렌더링 분석 및 해결방법
|
||||||
|
|
||||||
|
## 📋 문제 요약
|
||||||
|
- **증상**: HomeBanner의 RollingUnit 컴포넌트가 계속 리렌더링됨
|
||||||
|
- **특이사항**:
|
||||||
|
- RandomUnit은 정상 작동
|
||||||
|
- JustForYou 배너 관련 위치에서 특히 심함
|
||||||
|
- RollingUnit의 자동 순환(10초 롤링)이 제대로 작동하지 않음
|
||||||
|
- **원인**: OptionalTerms(선택약관) 관련 코드 추가 후 발생
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 근본 원인 분석
|
||||||
|
|
||||||
|
### 1. 불안정한 Props Chain (HomePanel → HomeBanner → RollingUnit)
|
||||||
|
|
||||||
|
**문제 흐름:**
|
||||||
|
```
|
||||||
|
HomePanel.jsx
|
||||||
|
↓ nowShelf 상태 변경
|
||||||
|
↓ doSendLogGNB 재생성 (의존성: nowShelf, panelInfo.nowShelf, pageSpotIds)
|
||||||
|
↓ handleItemFocus 재생성 (의존성: doSendLogGNB)
|
||||||
|
↓ handleItemFocus(el.shptmApphmDspyOptCd) 호출 → 매번 새 함수 생성
|
||||||
|
HomeBanner.jsx
|
||||||
|
↓ _handleItemFocus 재생성 (의존성: handleItemFocus)
|
||||||
|
↓ renderItem 재생성 (의존성: _handleItemFocus, _handleShelfFocus, bannerDataList)
|
||||||
|
RollingUnit.jsx
|
||||||
|
↓ 새로운 props 수신
|
||||||
|
↓ 리렌더링 발생!
|
||||||
|
```
|
||||||
|
|
||||||
|
**코드 위치:**
|
||||||
|
- `HomePanel.jsx` 라인 220-270
|
||||||
|
- `HomeBanner.jsx` 라인 81-85, 348-352, 497-542
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. OptionalTerms 상태와 조건부 렌더링 문제 ⚠️ **핵심 원인**
|
||||||
|
|
||||||
|
**문제 코드:** `HomeBanner.jsx` 라인 628-680
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const renderLayout = useCallback(() => {
|
||||||
|
switch (selectTemplate) {
|
||||||
|
case 'DSP00201': {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ContainerBasic className={css.smallBox}>
|
||||||
|
{renderItem(0, true, true)}
|
||||||
|
{renderItem(1, true, true)}
|
||||||
|
</ContainerBasic>
|
||||||
|
{renderItem(2, false, false)}
|
||||||
|
|
||||||
|
{/* ⚠️ 문제 부분: introTermsAgree 상태에 의존 */}
|
||||||
|
{introTermsAgree === 'Y' ? (
|
||||||
|
<div className={css.imgBox}>
|
||||||
|
<JustForSwitchBanner
|
||||||
|
renderItem={renderItem}
|
||||||
|
handleShelfFocus={_handleShelfFocus}
|
||||||
|
handleItemFocus={_handleItemFocus}
|
||||||
|
isHorizontal={false}
|
||||||
|
spotlightId={'banner3'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
renderItem(3, false, false)
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}, [selectTemplate, renderItem, renderSimpleVideoContainer]);
|
||||||
|
// ❌ 문제: introTermsAgree가 의존성 배열에 없음!
|
||||||
|
```
|
||||||
|
|
||||||
|
**문제점:**
|
||||||
|
1. `introTermsAgree`가 JSX 내부에서 참조되지만 의존성 배열에 없음
|
||||||
|
2. `introTermsAgree` 변경 시 React가 최적화를 제대로 하지 못함
|
||||||
|
3. 클로저 문제로 인해 예상치 못한 리렌더링 발생
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. JustForSwitchBanner의 구조적 문제
|
||||||
|
|
||||||
|
**문제 코드:** `JustForYouBanner.jsx` 라인 154-230
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
export default function JustForSwitchBanner({
|
||||||
|
renderItem, // ← HomeBanner에서 받은 renderItem
|
||||||
|
handleShelfFocus, // ← 계속 변하는 함수
|
||||||
|
handleItemFocus, // ← 계속 변하는 함수
|
||||||
|
isHorizontal,
|
||||||
|
spotlightId,
|
||||||
|
}) {
|
||||||
|
const [currentIndex, setCurrentIndex] = useState(0);
|
||||||
|
|
||||||
|
const onFocus = useCallback(() => {
|
||||||
|
if (handleItemFocus) {
|
||||||
|
handleItemFocus(); // ⚠️ 매번 새로운 함수 참조!
|
||||||
|
}
|
||||||
|
}, [handleItemFocus]); // ← 의존성: 계속 변경됨
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<SpottableComponent onClick={handlePrev} />
|
||||||
|
|
||||||
|
{currentIndex === 0 ? (
|
||||||
|
<JustForYouBanner
|
||||||
|
onFocus={onFocus} // ← 계속 변하는 콜백!
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
renderItem(3, false) // ⚠️ RollingUnit 렌더링!
|
||||||
|
)}
|
||||||
|
|
||||||
|
<SpottableComponent onClick={handleNext} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**문제의 연쇄 반응:**
|
||||||
|
```
|
||||||
|
handleItemFocus 변경
|
||||||
|
→ JustForSwitchBanner의 onFocus 재생성
|
||||||
|
→ JustForYouBanner 리렌더링
|
||||||
|
→ currentIndex === 1일 때 renderItem(3) 호출
|
||||||
|
→ RollingUnit 리렌더링!
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. RollingUnit 자동 롤링이 작동하지 않는 이유
|
||||||
|
|
||||||
|
**코드 위치:** `RollingUnit.jsx` 라인 463-487
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 10초 롤링
|
||||||
|
useEffect(() => {
|
||||||
|
lastIndexRef.current = rollingDataLength - 1;
|
||||||
|
previousTimeRef.current = undefined; // ⚠️ 타이머 리셋!
|
||||||
|
|
||||||
|
if (rollingDataLength <= 1 || unitHasFocus) {
|
||||||
|
doRollingRef.current = false;
|
||||||
|
window.cancelAnimationFrame(requestRef.current);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
doRollingRef.current = true;
|
||||||
|
requestRef.current = window.requestAnimationFrame(animate);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
doRollingRef.current = false;
|
||||||
|
window.cancelAnimationFrame(requestRef.current);
|
||||||
|
};
|
||||||
|
}, [rollingDataLength, unitHasFocus]);
|
||||||
|
```
|
||||||
|
|
||||||
|
**문제:**
|
||||||
|
- RollingUnit이 계속 리렌더링되면 이 `useEffect`가 계속 실행됨
|
||||||
|
- `previousTimeRef.current = undefined`로 타이머가 계속 리셋됨
|
||||||
|
- `requestAnimationFrame`이 취소되고 다시 시작됨
|
||||||
|
- **결과: 10초 타이머가 초기화되어 자동 롤링이 작동하지 않음**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5. RandomUnit은 왜 괜찮은가?
|
||||||
|
|
||||||
|
**RandomUnit의 경우:**
|
||||||
|
```javascript
|
||||||
|
// HomeBanner.jsx - renderLayout (DSP00201)
|
||||||
|
<ContainerBasic className={css.smallBox}>
|
||||||
|
{renderItem(0, true, true)} // ← Rolling 또는 Random
|
||||||
|
{renderItem(1, true, true)} // ← 주로 Random (고정 위치)
|
||||||
|
</ContainerBasic>
|
||||||
|
```
|
||||||
|
|
||||||
|
**RandomUnit은:**
|
||||||
|
- ✅ 고정된 위치(index 0, 1)에서 렌더링
|
||||||
|
- ✅ 조건부 렌더링 없음
|
||||||
|
- ✅ `introTermsAgree` 상태와 무관
|
||||||
|
- ✅ JustForSwitchBanner를 통하지 않음
|
||||||
|
- ✅ 안정적인 props만 받음
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💡 해결방법
|
||||||
|
|
||||||
|
### ✅ 해결방법 1: renderLayout 의존성 배열에 introTermsAgree 추가 (적용됨)
|
||||||
|
|
||||||
|
**파일:** `HomeBanner.jsx` 라인 514
|
||||||
|
|
||||||
|
**변경 전:**
|
||||||
|
```javascript
|
||||||
|
}, [selectTemplate, renderItem, renderSimpleVideoContainer]);
|
||||||
|
```
|
||||||
|
|
||||||
|
**변경 후:**
|
||||||
|
```javascript
|
||||||
|
}, [selectTemplate, renderItem, renderSimpleVideoContainer, introTermsAgree]);
|
||||||
|
```
|
||||||
|
|
||||||
|
**효과:**
|
||||||
|
- `introTermsAgree` 변경 시 `renderLayout`이 명시적으로 재생성됨
|
||||||
|
- React가 변경사항을 정확히 추적할 수 있음
|
||||||
|
- 클로저 문제 해결
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🔧 추가 권장 해결방법
|
||||||
|
|
||||||
|
#### 해결방법 2: HomePanel의 handleItemFocus 최적화
|
||||||
|
|
||||||
|
**파일:** `HomePanel.jsx` 라인 265-270
|
||||||
|
|
||||||
|
**현재 문제:**
|
||||||
|
```javascript
|
||||||
|
const handleItemFocus = useCallback(
|
||||||
|
(containerId, location, title) => () => {
|
||||||
|
doSendLogGNB(containerId, location, title);
|
||||||
|
},
|
||||||
|
[doSendLogGNB]
|
||||||
|
);
|
||||||
|
|
||||||
|
// 렌더링 시 매번 새 함수 생성
|
||||||
|
<HomeBanner
|
||||||
|
handleItemFocus={handleItemFocus(el.shptmApphmDspyOptCd)}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
**해결방법:**
|
||||||
|
```javascript
|
||||||
|
// 1. 함수를 직접 전달하지 말고 파라미터를 전달
|
||||||
|
<HomeBanner
|
||||||
|
containerId={el.shptmApphmDspyOptCd}
|
||||||
|
location={el.expsOrd}
|
||||||
|
title={el.shptmApphmDspyOptNm}
|
||||||
|
onItemFocus={handleItemFocus} // 안정적인 함수 참조
|
||||||
|
/>
|
||||||
|
|
||||||
|
// 2. HomeBanner에서 필요할 때 호출
|
||||||
|
const _handleItemFocus = useCallback(() => {
|
||||||
|
if (onItemFocus) {
|
||||||
|
onItemFocus(containerId, location, title);
|
||||||
|
}
|
||||||
|
}, [onItemFocus, containerId, location, title]);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 해결방법 3: JustForSwitchBanner 최적화
|
||||||
|
|
||||||
|
**파일:** `JustForYouBanner.jsx` 라인 189-195
|
||||||
|
|
||||||
|
**현재 문제:**
|
||||||
|
```javascript
|
||||||
|
const onFocus = useCallback(() => {
|
||||||
|
if (handleItemFocus) {
|
||||||
|
handleItemFocus();
|
||||||
|
}
|
||||||
|
}, [handleItemFocus]); // ← 계속 변경됨
|
||||||
|
```
|
||||||
|
|
||||||
|
**해결방법 A: useRef 사용**
|
||||||
|
```javascript
|
||||||
|
const handleItemFocusRef = useRef(handleItemFocus);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleItemFocusRef.current = handleItemFocus;
|
||||||
|
}, [handleItemFocus]);
|
||||||
|
|
||||||
|
const onFocus = useCallback(() => {
|
||||||
|
if (handleItemFocusRef.current) {
|
||||||
|
handleItemFocusRef.current();
|
||||||
|
}
|
||||||
|
}, []); // ← 의존성 없음, 안정적
|
||||||
|
```
|
||||||
|
|
||||||
|
**해결방법 B: React.memo로 JustForYouBanner 감싸기**
|
||||||
|
```javascript
|
||||||
|
const JustForYouBanner = React.memo(function JustForYouBanner({
|
||||||
|
onClick,
|
||||||
|
spotlightId,
|
||||||
|
onFocus,
|
||||||
|
isHorizontal,
|
||||||
|
popupVisible,
|
||||||
|
activePopup,
|
||||||
|
}) {
|
||||||
|
// ... 기존 코드
|
||||||
|
}, (prevProps, nextProps) => {
|
||||||
|
// onFocus가 변경되어도 리렌더링하지 않음
|
||||||
|
return (
|
||||||
|
prevProps.spotlightId === nextProps.spotlightId &&
|
||||||
|
prevProps.isHorizontal === nextProps.isHorizontal &&
|
||||||
|
prevProps.popupVisible === nextProps.popupVisible &&
|
||||||
|
prevProps.activePopup === nextProps.activePopup
|
||||||
|
);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 해결방법 4: doSendLogGNB 의존성 최적화
|
||||||
|
|
||||||
|
**파일:** `HomePanel.jsx` 라인 220-263
|
||||||
|
|
||||||
|
**현재 문제:**
|
||||||
|
```javascript
|
||||||
|
const doSendLogGNB = useCallback(
|
||||||
|
(containerId, location = null, title = null) => {
|
||||||
|
// ... 로직
|
||||||
|
},
|
||||||
|
[pageSpotIds, nowShelf, panelInfo.nowShelf] // ← 자주 변경됨
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
**해결방법: useRef 사용**
|
||||||
|
```javascript
|
||||||
|
const nowShelfRef = useRef(nowShelf);
|
||||||
|
const panelInfoRef = useRef(panelInfo.nowShelf);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
nowShelfRef.current = nowShelf;
|
||||||
|
panelInfoRef.current = panelInfo.nowShelf;
|
||||||
|
}, [nowShelf, panelInfo.nowShelf]);
|
||||||
|
|
||||||
|
const doSendLogGNB = useCallback(
|
||||||
|
(containerId, location = null, title = null) => {
|
||||||
|
// nowShelfRef.current 사용
|
||||||
|
if (containerId !== nowShelfRef.current && location && title) {
|
||||||
|
// ... 로직
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[pageSpotIds] // ← 의존성 감소
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 해결방법 5: RollingUnit을 React.memo로 감싸기
|
||||||
|
|
||||||
|
**파일:** `RollingUnit.jsx` 마지막 줄
|
||||||
|
|
||||||
|
**현재:**
|
||||||
|
```javascript
|
||||||
|
export default function RollingUnit({ ... }) {
|
||||||
|
// ... 코드
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**해결방법:**
|
||||||
|
```javascript
|
||||||
|
function RollingUnit({ ... }) {
|
||||||
|
// ... 기존 코드
|
||||||
|
}
|
||||||
|
|
||||||
|
export default React.memo(RollingUnit, (prevProps, nextProps) => {
|
||||||
|
// props가 실제로 변경되었을 때만 리렌더링
|
||||||
|
return (
|
||||||
|
prevProps.bannerData === nextProps.bannerData &&
|
||||||
|
prevProps.spotlightId === nextProps.spotlightId &&
|
||||||
|
prevProps.isHorizontal === nextProps.isHorizontal &&
|
||||||
|
prevProps.videoPlayerable === nextProps.videoPlayerable
|
||||||
|
// handleItemFocus, handleShelfFocus는 비교하지 않음
|
||||||
|
);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 우선순위별 적용 순서
|
||||||
|
|
||||||
|
### 1단계 (필수) ✅ 완료
|
||||||
|
- [x] `renderLayout` 의존성 배열에 `introTermsAgree` 추가
|
||||||
|
|
||||||
|
### 2단계 (권장)
|
||||||
|
- [ ] `doSendLogGNB` 의존성 최적화 (useRef 사용)
|
||||||
|
- [ ] `handleItemFocus` 구조 개선 (파라미터 전달 방식)
|
||||||
|
|
||||||
|
### 3단계 (선택)
|
||||||
|
- [ ] `JustForSwitchBanner` 최적화 (useRef 또는 React.memo)
|
||||||
|
- [ ] `RollingUnit`을 React.memo로 감싸기
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 예상 효과
|
||||||
|
|
||||||
|
### 1단계 적용 후:
|
||||||
|
- ✅ `introTermsAgree` 변경 시 명시적 리렌더링
|
||||||
|
- ✅ 클로저 문제 해결
|
||||||
|
- ⚠️ 여전히 props chain으로 인한 불필요한 리렌더링 가능
|
||||||
|
|
||||||
|
### 2-3단계 적용 후:
|
||||||
|
- ✅ 불필요한 리렌더링 대폭 감소
|
||||||
|
- ✅ RollingUnit 자동 롤링 정상 작동
|
||||||
|
- ✅ 성능 개선
|
||||||
|
- ✅ 안정적인 컴포넌트 동작
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 테스트 체크리스트
|
||||||
|
|
||||||
|
- [ ] RollingUnit이 불필요하게 리렌더링되지 않는지 확인
|
||||||
|
- [ ] RollingUnit의 10초 자동 롤링이 정상 작동하는지 확인
|
||||||
|
- [ ] OptionalTerms 동의 전/후 배너 전환이 정상적인지 확인
|
||||||
|
- [ ] JustForYou 배너와 RollingUnit 간 전환이 부드러운지 확인
|
||||||
|
- [ ] RandomUnit이 여전히 정상 작동하는지 확인
|
||||||
|
- [ ] 포커스 이동 시 로그가 정상적으로 전송되는지 확인
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📅 작성 정보
|
||||||
|
- **날짜**: 2025-10-13
|
||||||
|
- **분석 대상**: RollingUnit 리렌더링 문제
|
||||||
|
- **주요 원인**: OptionalTerms 상태 + JustForSwitchBanner 조건부 렌더링
|
||||||
|
- **적용된 해결방법**: renderLayout 의존성 배열에 introTermsAgree 추가
|
||||||
@@ -2,218 +2,219 @@
|
|||||||
|
|
||||||
export const types = {
|
export const types = {
|
||||||
// panel actions
|
// panel actions
|
||||||
PUSH_PANEL: "PUSH_PANEL",
|
PUSH_PANEL: 'PUSH_PANEL',
|
||||||
POP_PANEL: "POP_PANEL",
|
POP_PANEL: 'POP_PANEL',
|
||||||
UPDATE_PANEL: "UPDATE_PANEL",
|
UPDATE_PANEL: 'UPDATE_PANEL',
|
||||||
RESET_PANELS: "RESET_PANELS",
|
RESET_PANELS: 'RESET_PANELS',
|
||||||
|
|
||||||
// device actions
|
// device actions
|
||||||
GET_AUTHENTICATION_CODE: "GET_AUTHENTICATION_CODE",
|
GET_AUTHENTICATION_CODE: 'GET_AUTHENTICATION_CODE',
|
||||||
REGISTER_DEVICE: "REGISTER_DEVICE",
|
REGISTER_DEVICE: 'REGISTER_DEVICE',
|
||||||
REGISTER_DEVICE_INFO: "REGISTER_DEVICE_INFO",
|
REGISTER_DEVICE_INFO: 'REGISTER_DEVICE_INFO',
|
||||||
GET_DEVICE_INFO: "GET_DEVICE_INFO",
|
GET_DEVICE_INFO: 'GET_DEVICE_INFO',
|
||||||
CLEAR_REGISTER_DEVICE_INFO: "CLEAR_REGISTER_DEVICE_INFO",
|
CLEAR_REGISTER_DEVICE_INFO: 'CLEAR_REGISTER_DEVICE_INFO',
|
||||||
REGISTER_DEVICE_RESET: "REGISTER_DEVICE_RESET",
|
REGISTER_DEVICE_RESET: 'REGISTER_DEVICE_RESET',
|
||||||
|
|
||||||
// common actions
|
// common actions
|
||||||
GET_HTTP_HEADER: "GET_HTTP_HEADER",
|
GET_HTTP_HEADER: 'GET_HTTP_HEADER',
|
||||||
CHANGE_APP_STATUS: "CHANGE_APP_STATUS",
|
CHANGE_APP_STATUS: 'CHANGE_APP_STATUS',
|
||||||
SEND_BROADCAST: "SEND_BROADCAST",
|
SEND_BROADCAST: 'SEND_BROADCAST',
|
||||||
CHANGE_LOCAL_SETTINGS: "CHANGE_LOCAL_SETTINGS",
|
CHANGE_LOCAL_SETTINGS: 'CHANGE_LOCAL_SETTINGS',
|
||||||
GNB_OPENED: "GNB_OPENED",
|
GNB_OPENED: 'GNB_OPENED',
|
||||||
SET_SHOW_POPUP: "SET_SHOW_POPUP",
|
SET_SHOW_POPUP: 'SET_SHOW_POPUP',
|
||||||
SET_SHOW_SECONDARY_POPUP: "SET_SHOW_SECONDARY_POPUP",
|
SET_SHOW_SECONDARY_POPUP: 'SET_SHOW_SECONDARY_POPUP',
|
||||||
SET_HIDE_POPUP: "SET_HIDE_POPUP",
|
SET_HIDE_POPUP: 'SET_HIDE_POPUP',
|
||||||
SET_HIDE_SECONDARY_POPUP: "SET_HIDE_SECONDARY_POPUP",
|
SET_HIDE_SECONDARY_POPUP: 'SET_HIDE_SECONDARY_POPUP',
|
||||||
SHOW_OPTIONAL_TERMS_CONFIRM_POPUP: "SHOW_OPTIONAL_TERMS_CONFIRM_POPUP",
|
SHOW_OPTIONAL_TERMS_CONFIRM_POPUP: 'SHOW_OPTIONAL_TERMS_CONFIRM_POPUP',
|
||||||
HIDE_OPTIONAL_TERMS_CONFIRM_POPUP: "HIDE_OPTIONAL_TERMS_CONFIRM_POPUP",
|
HIDE_OPTIONAL_TERMS_CONFIRM_POPUP: 'HIDE_OPTIONAL_TERMS_CONFIRM_POPUP',
|
||||||
TOGGLE_OPTIONAL_TERMS_CONFIRM: "TOGGLE_OPTIONAL_TERMS_CONFIRM",
|
TOGGLE_OPTIONAL_TERMS_CONFIRM: 'TOGGLE_OPTIONAL_TERMS_CONFIRM',
|
||||||
// 선택약관 팝업 상태 관리
|
// 선택약관 팝업 상태 관리
|
||||||
SET_OPTIONAL_TERMS_POPUP_SHOWN: "SET_OPTIONAL_TERMS_POPUP_SHOWN",
|
SET_OPTIONAL_TERMS_POPUP_SHOWN: 'SET_OPTIONAL_TERMS_POPUP_SHOWN',
|
||||||
SET_OPTIONAL_TERMS_USER_DECISION: "SET_OPTIONAL_TERMS_USER_DECISION",
|
SET_OPTIONAL_TERMS_USER_DECISION: 'SET_OPTIONAL_TERMS_USER_DECISION',
|
||||||
RESET_OPTIONAL_TERMS_SESSION: "RESET_OPTIONAL_TERMS_SESSION",
|
RESET_OPTIONAL_TERMS_SESSION: 'RESET_OPTIONAL_TERMS_SESSION',
|
||||||
// 선택약관 직접 상태 업데이트 (API 호출 없이)
|
// 선택약관 직접 상태 업데이트 (API 호출 없이)
|
||||||
UPDATE_OPTIONAL_TERMS_AGREE_DIRECT: "UPDATE_OPTIONAL_TERMS_AGREE_DIRECT",
|
UPDATE_OPTIONAL_TERMS_AGREE_DIRECT: 'UPDATE_OPTIONAL_TERMS_AGREE_DIRECT',
|
||||||
UPDATE_TERMS_AGREEMENT_STATUS_DIRECT: "UPDATE_TERMS_AGREEMENT_STATUS_DIRECT",
|
UPDATE_TERMS_AGREEMENT_STATUS_DIRECT: 'UPDATE_TERMS_AGREEMENT_STATUS_DIRECT',
|
||||||
SET_EXIT_APP: "SET_EXIT_APP",
|
SET_EXIT_APP: 'SET_EXIT_APP',
|
||||||
GET_LOGIN_USER_DATA: "GET_LOGIN_USER_DATA",
|
GET_LOGIN_USER_DATA: 'GET_LOGIN_USER_DATA',
|
||||||
GET_TERMS_AGREE_YN: "GET_TERMS_AGREE_YN",
|
GET_TERMS_AGREE_YN: 'GET_TERMS_AGREE_YN',
|
||||||
LAUNCH_MEMBERSHIP_APP: "LAUNCH_MEMBERSHIP_APP",
|
LAUNCH_MEMBERSHIP_APP: 'LAUNCH_MEMBERSHIP_APP',
|
||||||
SET_FOCUS: "SET_FOCUS",
|
SET_FOCUS: 'SET_FOCUS',
|
||||||
SET_GNB_MENU: "SET_GNB_MENU",
|
SET_GNB_MENU: 'SET_GNB_MENU',
|
||||||
SET_SYSTEM_NOTICE: "SET_SYSTEM_NOTICE",
|
SET_SYSTEM_NOTICE: 'SET_SYSTEM_NOTICE',
|
||||||
SET_SYSTEM_TERMINATION: "SET_SYSTEM_TERMINATION",
|
SET_SYSTEM_TERMINATION: 'SET_SYSTEM_TERMINATION',
|
||||||
SET_DEEP_LINK: "SET_DEEP_LINK",
|
SET_DEEP_LINK: 'SET_DEEP_LINK',
|
||||||
SET_SECOND_LAYER_INFO: "SET_SECOND_LAYER_INFO",
|
SET_SECOND_LAYER_INFO: 'SET_SECOND_LAYER_INFO',
|
||||||
SET_ERROR_MESSAGE: "SET_ERROR_MESSAGE",
|
SET_ERROR_MESSAGE: 'SET_ERROR_MESSAGE',
|
||||||
CLEAR_ERROR_MESSAGE: "CLEAR_ERROR_MESSAGE",
|
CLEAR_ERROR_MESSAGE: 'CLEAR_ERROR_MESSAGE',
|
||||||
GET_DEVICE_MACADDRESS: "GET_DEVICE_MACADDRESS",
|
GET_DEVICE_MACADDRESS: 'GET_DEVICE_MACADDRESS',
|
||||||
SET_DEVICE_REGISTERED: "SET_DEVICE_REGISTERED",
|
SET_DEVICE_REGISTERED: 'SET_DEVICE_REGISTERED',
|
||||||
|
|
||||||
// billing actions
|
// billing actions
|
||||||
GET_MY_INFO_BILLING_SEARCH: "GET_MY_INFO_BILLING_SEARCH",
|
GET_MY_INFO_BILLING_SEARCH: 'GET_MY_INFO_BILLING_SEARCH',
|
||||||
|
|
||||||
// card actions
|
// card actions
|
||||||
GET_MY_INFO_CARD_SEARCH: "GET_MY_INFO_CARD_SEARCH",
|
GET_MY_INFO_CARD_SEARCH: 'GET_MY_INFO_CARD_SEARCH',
|
||||||
|
|
||||||
// shipping actions
|
// shipping actions
|
||||||
GET_MY_INFO_SHIPPING_SEARCH: "GET_MY_INFO_SHIPPING_SEARCH",
|
GET_MY_INFO_SHIPPING_SEARCH: 'GET_MY_INFO_SHIPPING_SEARCH',
|
||||||
|
|
||||||
// cart actions
|
// cart actions
|
||||||
GET_MY_INFO_CART_SEARCH: "GET_MY_INFO_CART_SEARCH",
|
GET_MY_INFO_CART_SEARCH: 'GET_MY_INFO_CART_SEARCH',
|
||||||
ADD_TO_CART: "ADD_TO_CART",
|
ADD_TO_CART: 'ADD_TO_CART',
|
||||||
REMOVE_FROM_CART: "REMOVE_FROM_CART",
|
REMOVE_FROM_CART: 'REMOVE_FROM_CART',
|
||||||
UPDATE_CART_ITEM: "UPDATE_CART_ITEM",
|
UPDATE_CART_ITEM: 'UPDATE_CART_ITEM',
|
||||||
CLEAR_CART: "CLEAR_CART",
|
CLEAR_CART: 'CLEAR_CART',
|
||||||
|
|
||||||
// appData actions
|
// appData actions
|
||||||
ADD_MAIN_INDEX: "ADD_MAIN_INDEX",
|
ADD_MAIN_INDEX: 'ADD_MAIN_INDEX',
|
||||||
SEND_SMS: "SEND_SMS",
|
SEND_SMS: 'SEND_SMS',
|
||||||
CLEAR_SMS: "CLEAR_SMS",
|
CLEAR_SMS: 'CLEAR_SMS',
|
||||||
|
|
||||||
// home actions
|
// home actions
|
||||||
GET_HOME_TERMS: "GET_HOME_TERMS",
|
GET_HOME_TERMS: 'GET_HOME_TERMS',
|
||||||
SET_TERMS_ID_MAP: "SET_TERMS_ID_MAP",
|
SET_TERMS_ID_MAP: 'SET_TERMS_ID_MAP',
|
||||||
SET_OPTIONAL_TERMS_AVAILABILITY: "SET_OPTIONAL_TERMS_AVAILABILITY",
|
SET_OPTIONAL_TERMS_AVAILABILITY: 'SET_OPTIONAL_TERMS_AVAILABILITY',
|
||||||
GET_HOME_MENU: "GET_HOME_MENU",
|
GET_HOME_MENU: 'GET_HOME_MENU',
|
||||||
GET_HOME_LAYOUT: "GET_HOME_LAYOUT",
|
GET_HOME_LAYOUT: 'GET_HOME_LAYOUT',
|
||||||
GET_HOME_MAIN_CONTENTS: "GET_HOME_MAIN_CONTENTS",
|
GET_HOME_MAIN_CONTENTS: 'GET_HOME_MAIN_CONTENTS',
|
||||||
GET_HOME_FULL_VIDEO_INFO: "GET_HOME_FULL_VIDEO_INFO",
|
GET_HOME_FULL_VIDEO_INFO: 'GET_HOME_FULL_VIDEO_INFO',
|
||||||
GET_THEME_CURATION_INFO: "GET_THEME_CURATION_INFO",
|
GET_THEME_CURATION_INFO: 'GET_THEME_CURATION_INFO',
|
||||||
GET_THEME_CURATION_DETAIL_INFO: "GET_THEME_CURATION_DETAIL_INFO",
|
GET_THEME_CURATION_DETAIL_INFO: 'GET_THEME_CURATION_DETAIL_INFO',
|
||||||
GET_THEME_HOTEL_DETAIL_INFO: "GET_THEME_HOTEL_DETAIL_INFO",
|
GET_THEME_HOTEL_DETAIL_INFO: 'GET_THEME_HOTEL_DETAIL_INFO',
|
||||||
GET_THEME_MENU_SHELF_INFO: "GET_THEME_MENU_SHELF_INFO",
|
GET_THEME_MENU_SHELF_INFO: 'GET_THEME_MENU_SHELF_INFO',
|
||||||
CLEAR_THEME_MENU_SHELF_INFO: "CLEAR_THEME_MENU_SHELF_INFO",
|
CLEAR_THEME_MENU_SHELF_INFO: 'CLEAR_THEME_MENU_SHELF_INFO',
|
||||||
CLEAR_THEME_DETAIL: "CLEAR_THEME_DETAIL",
|
CLEAR_THEME_DETAIL: 'CLEAR_THEME_DETAIL',
|
||||||
CHECK_ENTER_THROUGH_GNB: "CHECK_ENTER_THROUGH_GNB",
|
CHECK_ENTER_THROUGH_GNB: 'CHECK_ENTER_THROUGH_GNB',
|
||||||
SET_DEFAULT_FOCUS: "SET_DEFAULT_FOCUS",
|
SET_DEFAULT_FOCUS: 'SET_DEFAULT_FOCUS',
|
||||||
SET_BANNER_INDEX: "SET_BANNER_INDEX",
|
SET_BANNER_INDEX: 'SET_BANNER_INDEX',
|
||||||
RESET_HOME_INFO: "RESET_HOME_INFO",
|
RESET_HOME_INFO: 'RESET_HOME_INFO',
|
||||||
UPDATE_HOME_INFO: "UPDATE_HOME_INFO",
|
UPDATE_HOME_INFO: 'UPDATE_HOME_INFO',
|
||||||
|
|
||||||
// brand actions
|
// brand actions
|
||||||
GET_BRAND_LIST: "GET_BRAND_LIST",
|
GET_BRAND_LIST: 'GET_BRAND_LIST',
|
||||||
GET_BRAND_LAYOUT_INFO: "GET_BRAND_LAYOUT_INFO",
|
GET_BRAND_LAYOUT_INFO: 'GET_BRAND_LAYOUT_INFO',
|
||||||
GET_BRAND_LIVE_CHANNEL_INFO: "GET_BRAND_LIVE_CHANNEL_INFO",
|
GET_BRAND_LIVE_CHANNEL_INFO: 'GET_BRAND_LIVE_CHANNEL_INFO',
|
||||||
GET_BRAND_CHAN_INFO: "GET_BRAND_CHAN_INFO",
|
GET_BRAND_CHAN_INFO: 'GET_BRAND_CHAN_INFO',
|
||||||
GET_BRAND_TSV_INFO: "GET_BRAND_TSV_INFO",
|
GET_BRAND_TSV_INFO: 'GET_BRAND_TSV_INFO',
|
||||||
GET_BRAND_RECOMMENDED_SHOW_INFO: "GET_BRAND_RECOMMENDED_SHOW_INFO",
|
GET_BRAND_RECOMMENDED_SHOW_INFO: 'GET_BRAND_RECOMMENDED_SHOW_INFO',
|
||||||
GET_BRAND_SERIES_INFO: "GET_BRAND_SERIES_INFO",
|
GET_BRAND_SERIES_INFO: 'GET_BRAND_SERIES_INFO',
|
||||||
GET_BRAND_CATEGORY_INFO: "GET_BRAND_CATEGORY_INFO",
|
GET_BRAND_CATEGORY_INFO: 'GET_BRAND_CATEGORY_INFO',
|
||||||
GET_BRAND_CATEGORY_PRODUCT_INFO: "GET_BRAND_CATEGORY_PRODUCT_INFO",
|
GET_BRAND_CATEGORY_PRODUCT_INFO: 'GET_BRAND_CATEGORY_PRODUCT_INFO',
|
||||||
GET_BRAND_BEST_SELLER: "GET_BRAND_BEST_SELLER",
|
GET_BRAND_BEST_SELLER: 'GET_BRAND_BEST_SELLER',
|
||||||
GET_BRAND_CREATORS_INFO: "GET_BRAND_CREATORS_INFO",
|
GET_BRAND_CREATORS_INFO: 'GET_BRAND_CREATORS_INFO',
|
||||||
GET_BRAND_SHOWROOM: "GET_BRAND_SHOWROOM",
|
GET_BRAND_SHOWROOM: 'GET_BRAND_SHOWROOM',
|
||||||
GET_BRAND_RECENTLY_AIRED: "GET_BRAND_RECENTLY_AIRED",
|
GET_BRAND_RECENTLY_AIRED: 'GET_BRAND_RECENTLY_AIRED',
|
||||||
SET_BRAND_LIVE_CHANNEL_UPCOMING: "SET_BRAND_LIVE_CHANNEL_UPCOMING",
|
SET_BRAND_LIVE_CHANNEL_UPCOMING: 'SET_BRAND_LIVE_CHANNEL_UPCOMING',
|
||||||
SET_BRAND_CHAN_INFO: "SET_BRAND_CHAN_INFO",
|
SET_BRAND_CHAN_INFO: 'SET_BRAND_CHAN_INFO',
|
||||||
RESET_BRAND_STATE: "RESET_BRAND_STATE",
|
RESET_BRAND_STATE: 'RESET_BRAND_STATE',
|
||||||
RESET_BRAND_STATE_EXCEPT_BRAND_INFO: "RESET_BRAND_STATE_EXCEPT_BRAND_INFO",
|
RESET_BRAND_STATE_EXCEPT_BRAND_INFO: 'RESET_BRAND_STATE_EXCEPT_BRAND_INFO',
|
||||||
RESET_BRAND_LAYOUT_INFO: "RESET_BRAND_LAYOUT_INFO",
|
RESET_BRAND_LAYOUT_INFO: 'RESET_BRAND_LAYOUT_INFO',
|
||||||
|
|
||||||
// main actions
|
// main actions
|
||||||
GET_SUB_CATEGORY: "GET_SUB_CATEGORY",
|
GET_SUB_CATEGORY: 'GET_SUB_CATEGORY',
|
||||||
APPEND_SUB_CATEGORY: "APPEND_SUB_CATEGORY",
|
APPEND_SUB_CATEGORY: 'APPEND_SUB_CATEGORY',
|
||||||
GET_TOP_20_SHOW: "GET_TOP_20_SHOW",
|
GET_TOP_20_SHOW: 'GET_TOP_20_SHOW',
|
||||||
GET_PRODUCT_DETAIL: "GET_PRODUCT_DETAIL",
|
GET_PRODUCT_DETAIL: 'GET_PRODUCT_DETAIL',
|
||||||
GET_YOUMAYLIKE: "GET_YOUMAYLIKE",
|
GET_YOUMAYLIKE: 'GET_YOUMAYLIKE',
|
||||||
SET_MAIN_LIKE_CATEGORY: "SET_MAIN_LIKE_CATEGORY",
|
SET_MAIN_LIKE_CATEGORY: 'SET_MAIN_LIKE_CATEGORY',
|
||||||
SET_MAIN_LIVE_UPCOMING_ALARM: "SET_MAIN_LIVE_UPCOMING_ALARM",
|
SET_MAIN_LIVE_UPCOMING_ALARM: 'SET_MAIN_LIVE_UPCOMING_ALARM',
|
||||||
GET_MAIN_LIVE_SHOW_NOW_PRODUCT: "GET_MAIN_LIVE_SHOW_NOW_PRODUCT",
|
GET_MAIN_LIVE_SHOW_NOW_PRODUCT: 'GET_MAIN_LIVE_SHOW_NOW_PRODUCT',
|
||||||
GET_MAIN_LIVE_SHOW: "GET_MAIN_LIVE_SHOW",
|
GET_MAIN_LIVE_SHOW: 'GET_MAIN_LIVE_SHOW',
|
||||||
GET_MAIN_CATEGORY_SHOW_DETAIL: "GET_MAIN_CATEGORY_SHOW_DETAIL",
|
GET_MAIN_CATEGORY_SHOW_DETAIL: 'GET_MAIN_CATEGORY_SHOW_DETAIL',
|
||||||
CLEAR_PRODUCT_DETAIL: "CLEAR_PRODUCT_DETAIL",
|
CLEAR_PRODUCT_DETAIL: 'CLEAR_PRODUCT_DETAIL',
|
||||||
CLEAR_SUB_CATEGORY: "CLEAR_SUB_CATEGORY",
|
CLEAR_SUB_CATEGORY: 'CLEAR_SUB_CATEGORY',
|
||||||
CLEAR_SHOPNOW_INFO: "CLEAR_SHOPNOW_INFO",
|
CLEAR_SHOPNOW_INFO: 'CLEAR_SHOPNOW_INFO',
|
||||||
|
|
||||||
// myPage actions
|
// myPage actions
|
||||||
GET_MY_RECOMMANDED_KEYWORD: "GET_MY_RECOMMANDED_KEYWORD",
|
GET_MY_RECOMMANDED_KEYWORD: 'GET_MY_RECOMMANDED_KEYWORD',
|
||||||
GET_MY_FAQ_INFO: "GET_MY_FAQ_INFO",
|
GET_MY_FAQ_INFO: 'GET_MY_FAQ_INFO',
|
||||||
GET_NOTICE: "GET_NOTICE",
|
GET_NOTICE: 'GET_NOTICE',
|
||||||
GET_MY_CUSTOMERS: "GET_MY_CUSTOMERS",
|
GET_MY_CUSTOMERS: 'GET_MY_CUSTOMERS',
|
||||||
GET_MY_FAVORITE: "GET_MY_FAVORITE",
|
GET_MY_FAVORITE: 'GET_MY_FAVORITE',
|
||||||
DELETE_MY_FAVORITE: "DELETE_MY_FAVORITE",
|
DELETE_MY_FAVORITE: 'DELETE_MY_FAVORITE',
|
||||||
GET_MY_FAVORITE_FLAG: "GET_MY_FAVORITE_FLAG",
|
GET_MY_FAVORITE_FLAG: 'GET_MY_FAVORITE_FLAG',
|
||||||
SET_MY_TERMS_WITHDRAW: "SET_MY_TERMS_WITHDRAW",
|
SET_MY_TERMS_WITHDRAW: 'SET_MY_TERMS_WITHDRAW',
|
||||||
GET_MY_UPCOMING_CHANGE_INFO: "GET_MY_UPCOMING_CHANGE_INFO",
|
GET_MY_UPCOMING_CHANGE_INFO: 'GET_MY_UPCOMING_CHANGE_INFO',
|
||||||
GET_MY_UPCOMING_ALERT_SHOW: "GET_MY_UPCOMING_ALERT_SHOW",
|
GET_MY_UPCOMING_ALERT_SHOW: 'GET_MY_UPCOMING_ALERT_SHOW',
|
||||||
DELETE_MY_UPCOMING_ALERT_SHOW: "DELETE_MY_UPCOMING_ALERT_SHOW",
|
DELETE_MY_UPCOMING_ALERT_SHOW: 'DELETE_MY_UPCOMING_ALERT_SHOW',
|
||||||
GET_MY_UPCOMING_ALERT_SHOW_KEYS: "GET_MY_UPCOMING_ALERT_SHOW_KEYS",
|
GET_MY_UPCOMING_ALERT_SHOW_KEYS: 'GET_MY_UPCOMING_ALERT_SHOW_KEYS',
|
||||||
SET_MY_UPCOMING_USE_ALERT: "SET_MY_UPCOMING_USE_ALERT",
|
SET_MY_UPCOMING_USE_ALERT: 'SET_MY_UPCOMING_USE_ALERT',
|
||||||
GET_UPCOMING_ALERT_SHOW_CHANGE_INFO: "GET_UPCOMING_ALERT_SHOW_CHANGE_INFO",
|
GET_UPCOMING_ALERT_SHOW_CHANGE_INFO: 'GET_UPCOMING_ALERT_SHOW_CHANGE_INFO',
|
||||||
GET_MY_RECENTLY_VIEWED_INFO: "GET_MY_RECENTLY_VIEWED_INFO",
|
GET_MY_RECENTLY_VIEWED_INFO: 'GET_MY_RECENTLY_VIEWED_INFO',
|
||||||
CLEAR_RECENTLY_VIEWED_INFO: "CLEAR_RECENTLY_VIEWED_INFO",
|
CLEAR_RECENTLY_VIEWED_INFO: 'CLEAR_RECENTLY_VIEWED_INFO',
|
||||||
CLEAR_FAVORITES: "CLEAR_FAVORITES",
|
CLEAR_FAVORITES: 'CLEAR_FAVORITES',
|
||||||
SET_MYPAGE_TERMS_AGREE: "SET_MYPAGE_TERMS_AGREE",
|
SET_MYPAGE_TERMS_AGREE: 'SET_MYPAGE_TERMS_AGREE',
|
||||||
SET_MYPAGE_TERMS_AGREE_SUCCESS: "SET_MYPAGE_TERMS_AGREE_SUCCESS",
|
SET_MYPAGE_TERMS_AGREE_SUCCESS: 'SET_MYPAGE_TERMS_AGREE_SUCCESS',
|
||||||
SET_MYPAGE_TERMS_AGREE_FAIL: "SET_MYPAGE_TERMS_AGREE_FAIL",
|
SET_MYPAGE_TERMS_AGREE_FAIL: 'SET_MYPAGE_TERMS_AGREE_FAIL',
|
||||||
|
|
||||||
// onSale actions
|
// onSale actions
|
||||||
GET_HOME_ON_SALE_INFO: "GET_HOME_ON_SALE_INFO",
|
GET_HOME_ON_SALE_INFO: 'GET_HOME_ON_SALE_INFO',
|
||||||
GET_ON_SALE_INFO: "GET_ON_SALE_INFO",
|
GET_ON_SALE_INFO: 'GET_ON_SALE_INFO',
|
||||||
COPY_CATEGORY_INFO: "COPY_CATEGORY_INFO",
|
COPY_CATEGORY_INFO: 'COPY_CATEGORY_INFO',
|
||||||
RESET_ON_SALE_STATE: "RESET_ON_SALE_STATE",
|
RESET_ON_SALE_STATE: 'RESET_ON_SALE_STATE',
|
||||||
|
|
||||||
// product actions
|
// product actions
|
||||||
GET_BEST_SELLER: "GET_BEST_SELLER",
|
GET_BEST_SELLER: 'GET_BEST_SELLER',
|
||||||
GET_PRODUCT_GROUP: "GET_PRODUCT_GROUP",
|
GET_PRODUCT_GROUP: 'GET_PRODUCT_GROUP',
|
||||||
GET_PRODUCT_OPTION: "GET_PRODUCT_OPTION",
|
GET_PRODUCT_OPTION: 'GET_PRODUCT_OPTION',
|
||||||
GET_PRODUCT_IMAGE_LENGTH: "GET_PRODUCT_IMAGE_LENGTH",
|
GET_PRODUCT_IMAGE_LENGTH: 'GET_PRODUCT_IMAGE_LENGTH',
|
||||||
GET_VIDEO_INDECATOR_FOCUS: "GET_VIDEO_INDECATOR_FOCUS",
|
GET_VIDEO_INDECATOR_FOCUS: 'GET_VIDEO_INDECATOR_FOCUS',
|
||||||
GET_PRODUCT_OPTION_ID: "GET_PRODUCT_OPTION_ID",
|
GET_PRODUCT_OPTION_ID: 'GET_PRODUCT_OPTION_ID',
|
||||||
CLEAR_PRODUCT_OPTIONS: "CLEAR_PRODUCT_OPTIONS",
|
CLEAR_PRODUCT_OPTIONS: 'CLEAR_PRODUCT_OPTIONS',
|
||||||
GET_USER_REVIEW: "GET_USER_REVIEW",
|
GET_USER_REVIEW: 'GET_USER_REVIEW',
|
||||||
TOGGLE_SHOW_ALL_REVIEWS: "TOGGLE_SHOW_ALL_REVIEWS",
|
TOGGLE_SHOW_ALL_REVIEWS: 'TOGGLE_SHOW_ALL_REVIEWS',
|
||||||
RESET_SHOW_ALL_REVIEWS: "RESET_SHOW_ALL_REVIEWS",
|
RESET_SHOW_ALL_REVIEWS: 'RESET_SHOW_ALL_REVIEWS',
|
||||||
|
|
||||||
// search actions
|
// search actions
|
||||||
GET_SEARCH: "GET_SEARCH",
|
GET_SEARCH: 'GET_SEARCH',
|
||||||
RESET_SEARCH: "RESET_SEARCH",
|
RESET_SEARCH: 'RESET_SEARCH',
|
||||||
GET_SEARCH_PROCESSED: "GET_SEARCH_PROCESSED",
|
GET_SEARCH_PROCESSED: 'GET_SEARCH_PROCESSED',
|
||||||
SET_SEARCH_INIT_PERFORMED: "SET_SEARCH_INIT_PERFORMED",
|
SET_SEARCH_INIT_PERFORMED: 'SET_SEARCH_INIT_PERFORMED',
|
||||||
UPDATE_SEARCH_TIMESTAMP: "UPDATE_SEARCH_TIMESTAMP",
|
UPDATE_SEARCH_TIMESTAMP: 'UPDATE_SEARCH_TIMESTAMP',
|
||||||
|
|
||||||
// event actions
|
// event actions
|
||||||
GET_WELCOME_EVENT_INFO: "GET_WELCOME_EVENT_INFO",
|
GET_WELCOME_EVENT_INFO: 'GET_WELCOME_EVENT_INFO',
|
||||||
GET_EVENT_ISSUED_STATUS: "GET_EVENT_ISSUED_STATUS",
|
GET_EVENT_ISSUED_STATUS: 'GET_EVENT_ISSUED_STATUS',
|
||||||
SET_EVENT_ISSUE_REQ: "SET_EVENT_ISSUE_REQ",
|
SET_EVENT_ISSUE_REQ: 'SET_EVENT_ISSUE_REQ',
|
||||||
SET_EVENT_POP_CLICK_INFO: "SET_EVENT_POP_CLICK_INFO",
|
SET_EVENT_POP_CLICK_INFO: 'SET_EVENT_POP_CLICK_INFO',
|
||||||
CLEAR_EVENT_INFO: "CLEAR_EVENT_INFO",
|
CLEAR_EVENT_INFO: 'CLEAR_EVENT_INFO',
|
||||||
SKIP_CLICK_INFO: "SKIP_CLICK_INFO",
|
SKIP_CLICK_INFO: 'SKIP_CLICK_INFO',
|
||||||
CLEAR_CURATION_COUPON: "CLEAR_CURATION_COUPON",
|
CLEAR_CURATION_COUPON: 'CLEAR_CURATION_COUPON',
|
||||||
CLEAR_EVENT_ISSUED_STATUS_SUCCEESS: "CLEAR_EVENT_ISSUED_STATUS_SUCCEESS",
|
CLEAR_EVENT_ISSUED_STATUS_SUCCEESS: 'CLEAR_EVENT_ISSUED_STATUS_SUCCEESS',
|
||||||
|
|
||||||
// coupon actions
|
// coupon actions
|
||||||
GET_PRODUCT_COUPON_INFO: "GET_PRODUCT_COUPON_INFO",
|
GET_PRODUCT_COUPON_INFO: 'GET_PRODUCT_COUPON_INFO',
|
||||||
GET_PRODUCT_COUPON_SEARCH: "GET_PRODUCT_COUPON_SEARCH",
|
GET_PRODUCT_COUPON_SEARCH: 'GET_PRODUCT_COUPON_SEARCH',
|
||||||
GET_PRODUCT_COUPON_DOWNLOAD: "GET_PRODUCT_COUPON_DOWNLOAD",
|
GET_PRODUCT_COUPON_DOWNLOAD: 'GET_PRODUCT_COUPON_DOWNLOAD',
|
||||||
GET_PRODUCT_COUPON_TOTDOWNLOAD: "GET_PRODUCT_COUPON_TOTDOWNLOAD",
|
GET_PRODUCT_COUPON_TOTDOWNLOAD: 'GET_PRODUCT_COUPON_TOTDOWNLOAD',
|
||||||
CLEAR_COUPON_INFO: "CLEAR_COUPON_INFO",
|
CLEAR_COUPON_INFO: 'CLEAR_COUPON_INFO',
|
||||||
CLEAR_GET_PRODUCT_COUPON_DOWNLOAD: "CLEAR_GET_PRODUCT_COUPON_DOWNLOAD",
|
CLEAR_GET_PRODUCT_COUPON_DOWNLOAD: 'CLEAR_GET_PRODUCT_COUPON_DOWNLOAD',
|
||||||
|
|
||||||
// checkout actions
|
// checkout actions
|
||||||
GET_CHECKOUT_INFO: "GET_CHECKOUT_INFO",
|
GET_CHECKOUT_INFO: 'GET_CHECKOUT_INFO',
|
||||||
INSERT_MY_INFO_CHECKOUT_ORDER: "INSERT_MY_INFO_CHECKOUT_ORDER",
|
INSERT_MY_INFO_CHECKOUT_ORDER: 'INSERT_MY_INFO_CHECKOUT_ORDER',
|
||||||
GET_TAX_INFOS: "GET_TAX_INFOS",
|
GET_TAX_INFOS: 'GET_TAX_INFOS',
|
||||||
UPDATE_SELECTED_SHIPPING_ADDR: "UPDATE_SELECTED_SHIPPING_ADDR",
|
UPDATE_SELECTED_SHIPPING_ADDR: 'UPDATE_SELECTED_SHIPPING_ADDR',
|
||||||
UPDATE_SELECTED_BILLING_ADDR: "UPDATE_SELECTED_BILLING_ADDR",
|
UPDATE_SELECTED_BILLING_ADDR: 'UPDATE_SELECTED_BILLING_ADDR',
|
||||||
UPDATE_SELECTED_COUPON: "UPDATE_SELECTED_COUPON",
|
UPDATE_SELECTED_COUPON: 'UPDATE_SELECTED_COUPON',
|
||||||
GET_CHECKOUT_TOTAL_AMT: "GET_CHECKOUT_TOTAL_AMT",
|
GET_CHECKOUT_TOTAL_AMT: 'GET_CHECKOUT_TOTAL_AMT',
|
||||||
CHECKOUT_DATA_RESET: "CHECKOUT_DATA_RESET",
|
CHECKOUT_DATA_RESET: 'CHECKOUT_DATA_RESET',
|
||||||
|
|
||||||
// order actions
|
// order actions
|
||||||
SET_PURCHASE_TERMS_AGREE: "SET_PURCHASE_TERMS_AGREE",
|
SET_PURCHASE_TERMS_AGREE: 'SET_PURCHASE_TERMS_AGREE',
|
||||||
SET_PURCHASE_TERMS_WITHDRAW: "SET_PURCHASE_TERMS_WITHDRAW",
|
SET_PURCHASE_TERMS_WITHDRAW: 'SET_PURCHASE_TERMS_WITHDRAW',
|
||||||
GET_MY_INFO_ORDER_SEARCH: "GET_MY_INFO_ORDER_SEARCH",
|
GET_MY_INFO_ORDER_SEARCH: 'GET_MY_INFO_ORDER_SEARCH',
|
||||||
GET_MY_INFO_ORDER_SEARCH_CANCEL: "GET_MY_INFO_ORDER_SEARCH_CANCEL",
|
GET_MY_INFO_ORDER_SEARCH_CANCEL: 'GET_MY_INFO_ORDER_SEARCH_CANCEL',
|
||||||
GET_MY_INFO_ORDER_DETAIL_SEARCH: "GET_MY_INFO_ORDER_DETAIL_SEARCH",
|
GET_MY_INFO_ORDER_DETAIL_SEARCH: 'GET_MY_INFO_ORDER_DETAIL_SEARCH',
|
||||||
GET_MY_INFO_ORDER_SHIPPING_SEARCH: "GET_MY_INFO_ORDER_SHIPPING_SEARCH",
|
GET_MY_INFO_ORDER_SHIPPING_SEARCH: 'GET_MY_INFO_ORDER_SHIPPING_SEARCH',
|
||||||
CLEAR_MY_INFO_ORDER_SEARCH: "CLEAR_MY_INFO_ORDER_SEARCH",
|
CLEAR_MY_INFO_ORDER_SEARCH: 'CLEAR_MY_INFO_ORDER_SEARCH',
|
||||||
|
|
||||||
// play controller
|
// play controller
|
||||||
GET_CHAT_LOG: "GET_CHAT_LOG",
|
GET_CHAT_LOG: 'GET_CHAT_LOG',
|
||||||
GET_SUBTITLE: "GET_SUBTITLE",
|
GET_SUBTITLE: 'GET_SUBTITLE',
|
||||||
CLEAR_PLAYER_INFO: "CLEAR_PLAYER_INFO",
|
CLEAR_PLAYER_INFO: 'CLEAR_PLAYER_INFO',
|
||||||
|
UPDATE_VIDEO_PLAY_STATE: 'UPDATE_VIDEO_PLAY_STATE',
|
||||||
|
|
||||||
// 🔽 [추가] 플레이 제어 매니저 액션 타입
|
// 🔽 [추가] 플레이 제어 매니저 액션 타입
|
||||||
/**
|
/**
|
||||||
@@ -224,58 +225,57 @@ export const types = {
|
|||||||
* SET_PLAYER_CONTROL: 특정 컴포넌트에게 비디오 재생 제어권을 부여합니다.
|
* SET_PLAYER_CONTROL: 특정 컴포넌트에게 비디오 재생 제어권을 부여합니다.
|
||||||
* CLEAR_PLAYER_CONTROL: 컴포넌트로부터 비디오 재생 제어권을 회수합니다.
|
* CLEAR_PLAYER_CONTROL: 컴포넌트로부터 비디오 재생 제어권을 회수합니다.
|
||||||
*/
|
*/
|
||||||
SET_PLAYER_CONTROL: "SET_PLAYER_CONTROL",
|
SET_PLAYER_CONTROL: 'SET_PLAYER_CONTROL',
|
||||||
CLEAR_PLAYER_CONTROL: "CLEAR_PLAYER_CONTROL",
|
CLEAR_PLAYER_CONTROL: 'CLEAR_PLAYER_CONTROL',
|
||||||
|
|
||||||
// reset action
|
// reset action
|
||||||
RESET_REDUX_STATE: "RESET_REDUX_STATE",
|
RESET_REDUX_STATE: 'RESET_REDUX_STATE',
|
||||||
|
|
||||||
// cancel actions
|
// cancel actions
|
||||||
GET_MY_INFO_ORDER_CANCEL_SEARCH: "GET_MY_INFO_ORDER_CANCEL_SEARCH",
|
GET_MY_INFO_ORDER_CANCEL_SEARCH: 'GET_MY_INFO_ORDER_CANCEL_SEARCH',
|
||||||
GET_MY_INFO_ORDER_CANCEL_COLUMNS_SEARCH:
|
GET_MY_INFO_ORDER_CANCEL_COLUMNS_SEARCH: 'GET_MY_INFO_ORDER_CANCEL_COLUMNS_SEARCH',
|
||||||
"GET_MY_INFO_ORDER_CANCEL_COLUMNS_SEARCH",
|
UPDATE_ORDER_PARTIAL_CANCEL: 'UPDATE_ORDER_PARTIAL_CANCEL',
|
||||||
UPDATE_ORDER_PARTIAL_CANCEL: "UPDATE_ORDER_PARTIAL_CANCEL",
|
PAYMENT_TOTAL_CANCEL: 'PAYMENT_TOTAL_CANCEL',
|
||||||
PAYMENT_TOTAL_CANCEL: "PAYMENT_TOTAL_CANCEL",
|
|
||||||
|
|
||||||
// emp actions
|
// emp actions
|
||||||
GET_SHOPTIME_TERMS: "GET_SHOPTIME_TERMS",
|
GET_SHOPTIME_TERMS: 'GET_SHOPTIME_TERMS',
|
||||||
|
|
||||||
// pinCode actions
|
// pinCode actions
|
||||||
GET_MY_INFO_CARD_PINCODE_CHECK: "GET_MY_INFO_CARD_PINCODE_CHECK",
|
GET_MY_INFO_CARD_PINCODE_CHECK: 'GET_MY_INFO_CARD_PINCODE_CHECK',
|
||||||
|
|
||||||
// new actions
|
// new actions
|
||||||
CANCEL_FOCUS_ELEMENT: "CANCEL_FOCUS_ELEMENT",
|
CANCEL_FOCUS_ELEMENT: 'CANCEL_FOCUS_ELEMENT',
|
||||||
|
|
||||||
// 약관동의 여부 확인 상태
|
// 약관동의 여부 확인 상태
|
||||||
GET_TERMS_AGREE_YN_START: "GET_TERMS_AGREE_YN_START",
|
GET_TERMS_AGREE_YN_START: 'GET_TERMS_AGREE_YN_START',
|
||||||
GET_TERMS_AGREE_YN_SUCCESS: "GET_TERMS_AGREE_YN_SUCCESS",
|
GET_TERMS_AGREE_YN_SUCCESS: 'GET_TERMS_AGREE_YN_SUCCESS',
|
||||||
GET_TERMS_AGREE_YN_FAILURE: "GET_TERMS_AGREE_YN_FAILURE",
|
GET_TERMS_AGREE_YN_FAILURE: 'GET_TERMS_AGREE_YN_FAILURE',
|
||||||
|
|
||||||
// device
|
// device
|
||||||
REQ_REG_DEVICE_INFO: "REQ_REG_DEVICE_INFO",
|
REQ_REG_DEVICE_INFO: 'REQ_REG_DEVICE_INFO',
|
||||||
|
|
||||||
// 🔽 [추가] 영구재생 비디오 정보 저장
|
// 🔽 [추가] 영구재생 비디오 정보 저장
|
||||||
SET_PERSISTENT_VIDEO_INFO: "SET_PERSISTENT_VIDEO_INFO",
|
SET_PERSISTENT_VIDEO_INFO: 'SET_PERSISTENT_VIDEO_INFO',
|
||||||
|
|
||||||
// 🔽 [추가] 배너 비디오 제어 액션 타입
|
// 🔽 [추가] 배너 비디오 제어 액션 타입
|
||||||
/**
|
/**
|
||||||
* HomeBanner의 배너 간 비디오 재생 제어를 위한 액션 타입들.
|
* HomeBanner의 배너 간 비디오 재생 제어를 위한 액션 타입들.
|
||||||
* 첫 번째 배너 상시 재생과 두 번째 배너 포커스 재생을 관리합니다.
|
* 첫 번째 배너 상시 재생과 두 번째 배너 포커스 재생을 관리합니다.
|
||||||
*/
|
*/
|
||||||
SET_BANNER_STATE: "SET_BANNER_STATE",
|
SET_BANNER_STATE: 'SET_BANNER_STATE',
|
||||||
SET_BANNER_FOCUS: "SET_BANNER_FOCUS",
|
SET_BANNER_FOCUS: 'SET_BANNER_FOCUS',
|
||||||
SET_BANNER_AVAILABILITY: "SET_BANNER_AVAILABILITY",
|
SET_BANNER_AVAILABILITY: 'SET_BANNER_AVAILABILITY',
|
||||||
SET_BANNER_TRANSITION: "SET_BANNER_TRANSITION",
|
SET_BANNER_TRANSITION: 'SET_BANNER_TRANSITION',
|
||||||
PAUSE_PLAYER_CONTROL: "PAUSE_PLAYER_CONTROL",
|
PAUSE_PLAYER_CONTROL: 'PAUSE_PLAYER_CONTROL',
|
||||||
RESUME_PLAYER_CONTROL: "RESUME_PLAYER_CONTROL",
|
RESUME_PLAYER_CONTROL: 'RESUME_PLAYER_CONTROL',
|
||||||
// 🔽 [추가] HomeBanner 동영상 포커스 정책 관리
|
// 🔽 [추가] HomeBanner 동영상 포커스 정책 관리
|
||||||
SET_CURRENT_FOCUS_BANNER: "SET_CURRENT_FOCUS_BANNER",
|
SET_CURRENT_FOCUS_BANNER: 'SET_CURRENT_FOCUS_BANNER',
|
||||||
UPDATE_VIDEO_POLICY: "UPDATE_VIDEO_POLICY",
|
UPDATE_VIDEO_POLICY: 'UPDATE_VIDEO_POLICY',
|
||||||
SET_MODAL_BORDER: "SET_MODAL_BORDER",
|
SET_MODAL_BORDER: 'SET_MODAL_BORDER',
|
||||||
SET_BANNER_VISIBILITY: "SET_BANNER_VISIBILITY",
|
SET_BANNER_VISIBILITY: 'SET_BANNER_VISIBILITY',
|
||||||
|
|
||||||
// 🔽 [추가] JustForYou 상품 관리 부분
|
// 🔽 [추가] JustForYou 상품 관리 부분
|
||||||
GET_RECENTLY_SAW_ITEM: "GET_RECENTLY_SAW_ITEM",
|
GET_RECENTLY_SAW_ITEM: 'GET_RECENTLY_SAW_ITEM',
|
||||||
GET_LIKE_BRAND_PRODUCT: "GET_LIKE_BRAND_PRODUCT",
|
GET_LIKE_BRAND_PRODUCT: 'GET_LIKE_BRAND_PRODUCT',
|
||||||
GET_MORE_TO_CONCIDER_AT_THIS_PRICE: "GET_MORE_TO_CONCIDER_AT_THIS_PRICE",
|
GET_MORE_TO_CONCIDER_AT_THIS_PRICE: 'GET_MORE_TO_CONCIDER_AT_THIS_PRICE',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -135,6 +135,52 @@ export const resumeModalVideo = () => (dispatch, getState) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 전체화면 비디오를 일시정지 (패널은 유지)
|
||||||
|
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) {
|
||||||
|
console.log('[pauseFullscreenVideo] Pausing fullscreen video');
|
||||||
|
dispatch(
|
||||||
|
updatePanel({
|
||||||
|
name: panel_names.PLAYER_PANEL,
|
||||||
|
panelInfo: {
|
||||||
|
...fullscreenPlayerPanel.panelInfo,
|
||||||
|
isPaused: true, // 일시정지 플래그 추가
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 전체화면 비디오를 재생 (일시정지 해제)
|
||||||
|
export const resumeFullscreenVideo = () => (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 && fullscreenPlayerPanel.panelInfo?.isPaused) {
|
||||||
|
console.log('[resumeFullscreenVideo] Resuming fullscreen video');
|
||||||
|
dispatch(
|
||||||
|
updatePanel({
|
||||||
|
name: panel_names.PLAYER_PANEL,
|
||||||
|
panelInfo: {
|
||||||
|
...fullscreenPlayerPanel.panelInfo,
|
||||||
|
isPaused: false, // 일시정지 해제
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 채팅 로그 가져오기 IF-LGSP-371
|
// 채팅 로그 가져오기 IF-LGSP-371
|
||||||
export const getChatLog =
|
export const getChatLog =
|
||||||
({ patnrId, showId }) =>
|
({ patnrId, showId }) =>
|
||||||
@@ -187,6 +233,20 @@ export const CLEAR_PLAYER_INFO = () => ({
|
|||||||
type: types.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,
|
||||||
|
});
|
||||||
|
|
||||||
/* 🔽 [추가] 새로운 '플레이 제어 매니저' 액션들 */
|
/* 🔽 [추가] 새로운 '플레이 제어 매니저' 액션들 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ import Overlay from './Overlay';
|
|||||||
import TReactPlayer from './TReactPlayer';
|
import TReactPlayer from './TReactPlayer';
|
||||||
import Video from './Video';
|
import Video from './Video';
|
||||||
import css from './VideoPlayer.module.less';
|
import css from './VideoPlayer.module.less';
|
||||||
|
import { updateVideoPlayState } from '../../actions/playActions';
|
||||||
|
|
||||||
const isEnter = is('enter');
|
const isEnter = is('enter');
|
||||||
const isLeft = is('left');
|
const isLeft = is('left');
|
||||||
@@ -714,6 +715,7 @@ const VideoPlayerBase = class extends React.Component {
|
|||||||
belowContentsVisible: PropTypes.bool,
|
belowContentsVisible: PropTypes.bool,
|
||||||
tabContainerVersion: PropTypes.number,
|
tabContainerVersion: PropTypes.number,
|
||||||
tabIndexV2: PropTypes.number,
|
tabIndexV2: PropTypes.number,
|
||||||
|
dispatch: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
static contextType = FloatingLayerContext;
|
static contextType = FloatingLayerContext;
|
||||||
@@ -1507,6 +1509,19 @@ const VideoPlayerBase = class extends React.Component {
|
|||||||
updatedState.thumbnailUrl = null;
|
updatedState.thumbnailUrl = null;
|
||||||
}
|
}
|
||||||
this.setState(updatedState);
|
this.setState(updatedState);
|
||||||
|
|
||||||
|
// Redux에 비디오 재생 상태 업데이트
|
||||||
|
if (this.props.dispatch) {
|
||||||
|
this.props.dispatch(
|
||||||
|
updateVideoPlayState({
|
||||||
|
isPlaying: !updatedState.paused,
|
||||||
|
isPaused: updatedState.paused,
|
||||||
|
currentTime: updatedState.currentTime,
|
||||||
|
duration: updatedState.duration,
|
||||||
|
playbackRate: updatedState.playbackRate,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
renderBottomControl = new Job(() => {
|
renderBottomControl = new Job(() => {
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
import { types } from "../actions/actionTypes";
|
import { types } from '../actions/actionTypes';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
subTitleBlobs: {},
|
subTitleBlobs: {},
|
||||||
chatData: null,
|
chatData: null,
|
||||||
|
videoPlayState: {
|
||||||
|
isPlaying: false,
|
||||||
|
isPaused: true,
|
||||||
|
currentTime: 0,
|
||||||
|
duration: 0,
|
||||||
|
playbackRate: 1,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const playReducer = (state = initialState, action) => {
|
export const playReducer = (state = initialState, action) => {
|
||||||
@@ -19,14 +26,13 @@ export const playReducer = (state = initialState, action) => {
|
|||||||
...state,
|
...state,
|
||||||
subTitleBlobs: {
|
subTitleBlobs: {
|
||||||
...state.subTitleBlobs,
|
...state.subTitleBlobs,
|
||||||
[action.payload.url]: "Error",
|
[action.payload.url]: 'Error',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
var srtRegex =
|
var srtRegex = /(.*\n)?(\d\d:\d\d:\d\d),(\d\d\d --> \d\d:\d\d:\d\d),(\d\d\d)/g;
|
||||||
/(.*\n)?(\d\d:\d\d:\d\d),(\d\d\d --> \d\d:\d\d:\d\d),(\d\d\d)/g;
|
var vttText = 'WEBVTT\n\n' + srtText.replace(srtRegex, '$1$2.$3.$4');
|
||||||
var vttText = "WEBVTT\n\n" + srtText.replace(srtRegex, "$1$2.$3.$4");
|
var vttBlob = new Blob([vttText], { type: 'text/vtt' });
|
||||||
var vttBlob = new Blob([vttText], { type: "text/vtt" });
|
|
||||||
let blobUrl = URL.createObjectURL(vttBlob);
|
let blobUrl = URL.createObjectURL(vttBlob);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -43,6 +49,15 @@ export const playReducer = (state = initialState, action) => {
|
|||||||
chatData: {},
|
chatData: {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
case types.UPDATE_VIDEO_PLAY_STATE: {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
videoPlayState: {
|
||||||
|
...state.videoPlayState,
|
||||||
|
...action.payload,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
|
|||||||
@@ -84,82 +84,6 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha
|
|||||||
}
|
}
|
||||||
}, [handleItemFocus]);
|
}, [handleItemFocus]);
|
||||||
|
|
||||||
// 🔽 [추가] 0번째 배너에 대한 영구 비디오 재생을 처리하는 useEffect
|
|
||||||
// useEffect(() => {
|
|
||||||
// if (
|
|
||||||
// bannerDataList &&
|
|
||||||
// bannerDataList.length > 0 &&
|
|
||||||
// selectTemplate === "DSP00201"
|
|
||||||
// ) {
|
|
||||||
// const banner0Data = bannerDataList[0]?.bannerDetailInfos?.[0];
|
|
||||||
|
|
||||||
// if (banner0Data && banner0Data.showUrl) {
|
|
||||||
// // DOM 요소가 존재하는지 확인 후 실행
|
|
||||||
// console.log("[HomeBanner] banner0Data", banner0Data);
|
|
||||||
// const checkAndPlay = () => {
|
|
||||||
// const targetElement = document.querySelector(
|
|
||||||
// '[data-spotlight-id="banner0"]',
|
|
||||||
// );
|
|
||||||
// console.log("[HomeBanner] targetElement", targetElement);
|
|
||||||
// if (targetElement) {
|
|
||||||
// console.log("[HomeBanner] targetElement 존재");
|
|
||||||
// dispatch(
|
|
||||||
// startVideoPlayer({
|
|
||||||
// showUrl: banner0Data.showUrl,
|
|
||||||
// patnrId: banner0Data.patnrId,
|
|
||||||
// showId: banner0Data.showId,
|
|
||||||
// shptmBanrTpNm: "MEDIA",
|
|
||||||
// modal: true,
|
|
||||||
// modalContainerId: "banner0",
|
|
||||||
// spotlightDisable: true,
|
|
||||||
// }),
|
|
||||||
// );
|
|
||||||
// console.log("[HomeBanner] startVideoPlayer 호출");
|
|
||||||
// } else {
|
|
||||||
// // 요소가 없으면 잠시 후 재시도
|
|
||||||
// console.log("[HomeBanner] targetElement 없음");
|
|
||||||
// setTimeout(checkAndPlay, 100);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// // 다음 tick에서 실행하여 렌더링 완료 보장
|
|
||||||
// setTimeout(checkAndPlay, 0);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }, [dispatch, bannerDataList, selectTemplate]);
|
|
||||||
|
|
||||||
// 🔽 [수정] 새로운 1번 배너 포커스/블러 핸들러
|
|
||||||
const handleSecondBannerFocus = useCallback(() => {
|
|
||||||
const secondBannerData = bannerDataList?.[1];
|
|
||||||
if (secondBannerData) {
|
|
||||||
const randomData = secondBannerData.bannerDetailInfos[secondBannerData.randomIndex];
|
|
||||||
const videoInfo = {
|
|
||||||
showUrl: randomData.showUrl,
|
|
||||||
patnrId: randomData.patnrId,
|
|
||||||
showId: randomData.showId,
|
|
||||||
shptmBanrTpNm: randomData.showId ? randomData.shptmBanrTpNm : 'MEDIA',
|
|
||||||
lgCatCd: randomData.lgCatCd,
|
|
||||||
chanId: randomData.brdcChnlId,
|
|
||||||
modal: true,
|
|
||||||
modalContainerId: 'banner1',
|
|
||||||
modalClassName: css.videoModal,
|
|
||||||
isVerticalModal: true, // Assuming second banner is horizontal, so modal is vertical
|
|
||||||
};
|
|
||||||
|
|
||||||
// 중앙 제어 시스템에 '미리보기' 재생을 요청
|
|
||||||
dispatch(requestPlayControl('banner1_preview', videoInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handleItemFocus) {
|
|
||||||
handleItemFocus();
|
|
||||||
}
|
|
||||||
}, [dispatch, bannerDataList, handleItemFocus]);
|
|
||||||
|
|
||||||
const handleSecondBannerBlur = useCallback(() => {
|
|
||||||
// 중앙 제어 시스템에 '미리보기' 제어권 해제를 요청
|
|
||||||
dispatch(releasePlayControl('banner1_preview'));
|
|
||||||
}, [dispatch]);
|
|
||||||
|
|
||||||
const termsData = useSelector((state) => state.home.termsData);
|
const termsData = useSelector((state) => state.home.termsData);
|
||||||
const termsIdMap = useSelector((state) => state.home.termsIdMap);
|
const termsIdMap = useSelector((state) => state.home.termsIdMap);
|
||||||
const optionalTermsAvailable = useSelector((state) => state.home.optionalTermsAvailable);
|
const optionalTermsAvailable = useSelector((state) => state.home.optionalTermsAvailable);
|
||||||
@@ -379,27 +303,6 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha
|
|||||||
return null;
|
return null;
|
||||||
}, [bannerDataList]);
|
}, [bannerDataList]);
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// if (firstSpot && defaultFocus && popupVisible === false) {
|
|
||||||
// setTimeout(() => {
|
|
||||||
// Spotlight.focus(defaultFocus);
|
|
||||||
// }, 0);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (defaultFocus) {
|
|
||||||
// dispatch(setDefaultFocus(defaultFocus));
|
|
||||||
// }
|
|
||||||
// }, [defaultFocus, dispatch, popupVisible]);
|
|
||||||
|
|
||||||
// 테스트용 팝업 표시
|
|
||||||
// useEffect(() => {
|
|
||||||
// setTimeout(() => {
|
|
||||||
// console.log("App.js optionalTermsTest 팝업 표시");
|
|
||||||
// setIsOptionalConfirmVisible(true);
|
|
||||||
// // setIsOptionalTermsVisible(true);
|
|
||||||
// }, 1000);
|
|
||||||
// }, []);
|
|
||||||
|
|
||||||
// 약관 동의 및 선택 약관 팝업 처리 (TV 환경 최적화)
|
// 약관 동의 및 선택 약관 팝업 처리 (TV 환경 최적화)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (termsLoading) {
|
if (termsLoading) {
|
||||||
@@ -423,77 +326,6 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha
|
|||||||
}
|
}
|
||||||
}, [shouldShowOptionalTermsPopup, termsLoading, isOptionalConfirmVisible, dispatch]);
|
}, [shouldShowOptionalTermsPopup, termsLoading, isOptionalConfirmVisible, dispatch]);
|
||||||
|
|
||||||
// const renderItem = useCallback(
|
|
||||||
// (index, isHorizontal) => {
|
|
||||||
// const data = bannerDataList?.[index] ?? {};
|
|
||||||
|
|
||||||
// if (index === 1) {
|
|
||||||
// return (
|
|
||||||
// <div className={!isHorizontal ? css.imgBox : undefined}>
|
|
||||||
// <RandomUnitNew
|
|
||||||
// bannerData={data}
|
|
||||||
// isHorizontal={isHorizontal}
|
|
||||||
// key={"banner" + index}
|
|
||||||
// spotlightId={"banner" + index}
|
|
||||||
// handleShelfFocus={_handleShelfFocus}
|
|
||||||
// onFocus={handleSecondBannerFocus}
|
|
||||||
// onBlur={handleSecondBannerBlur}
|
|
||||||
// randomNumber={data.randomIndex}
|
|
||||||
// />
|
|
||||||
// </div>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return (
|
|
||||||
// <div className={!isHorizontal ? css.imgBox : undefined}>
|
|
||||||
// {data.shptmDspyTpNm === "Rolling" ? (
|
|
||||||
// <Rolling
|
|
||||||
// bannerData={data}
|
|
||||||
// isHorizontal={isHorizontal}
|
|
||||||
// key={"banner" + index}
|
|
||||||
// spotlightId={"banner" + index}
|
|
||||||
// handleShelfFocus={_handleShelfFocus}
|
|
||||||
// handleItemFocus={_handleItemFocus}
|
|
||||||
// />
|
|
||||||
// ) : data.shptmDspyTpNm === "Random" ? (
|
|
||||||
// <Random
|
|
||||||
// bannerData={data}
|
|
||||||
// isHorizontal={isHorizontal}
|
|
||||||
// key={"banner" + index}
|
|
||||||
// spotlightId={"banner" + index}
|
|
||||||
// handleShelfFocus={_handleShelfFocus}
|
|
||||||
// handleItemFocus={_handleItemFocus}
|
|
||||||
// randomNumber={data.randomIndex}
|
|
||||||
// />
|
|
||||||
// ) : (
|
|
||||||
// <SpottableComponent spotlightId={"banner" + index}>
|
|
||||||
// <CustomImage
|
|
||||||
// delay={0}
|
|
||||||
// src={
|
|
||||||
// isHorizontal
|
|
||||||
// ? homeTopDisplayInfo.wdthtpImgPath1
|
|
||||||
// : homeTopDisplayInfo.vtctpImgPath1
|
|
||||||
// }
|
|
||||||
// aria-label={
|
|
||||||
// isHorizontal
|
|
||||||
// ? homeTopDisplayInfo.wdthtpImgNm1
|
|
||||||
// : homeTopDisplayInfo.vtctpImgNm1
|
|
||||||
// }
|
|
||||||
// />
|
|
||||||
// </SpottableComponent>
|
|
||||||
// )}
|
|
||||||
// </div>
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
// [
|
|
||||||
// bannerDataList,
|
|
||||||
// _handleItemFocus,
|
|
||||||
// _handleShelfFocus,
|
|
||||||
// handleSecondBannerFocus,
|
|
||||||
// handleSecondBannerBlur,
|
|
||||||
// ],
|
|
||||||
// );
|
|
||||||
|
|
||||||
const renderItem = useCallback(
|
const renderItem = useCallback(
|
||||||
(index, isHorizontal, videoPlayerable = false) => {
|
(index, isHorizontal, videoPlayerable = false) => {
|
||||||
const data = bannerDataList?.[index] ?? {};
|
const data = bannerDataList?.[index] ?? {};
|
||||||
@@ -678,7 +510,7 @@ export default function HomeBanner({ firstSpot, spotlightId, handleItemFocus, ha
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}, [selectTemplate, renderItem, renderSimpleVideoContainer]);
|
}, [selectTemplate, renderItem, renderSimpleVideoContainer, introTermsAgree]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -254,6 +254,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
const liveShowInfos = USE_SELECTOR('liveShowInfos', (state) => state.main.liveShowInfos);
|
const liveShowInfos = USE_SELECTOR('liveShowInfos', (state) => state.main.liveShowInfos);
|
||||||
const vodSubtitleData = USE_SELECTOR('vodSubtitleData', (state) => state.play.subTitleBlobs);
|
const vodSubtitleData = USE_SELECTOR('vodSubtitleData', (state) => state.play.subTitleBlobs);
|
||||||
const broadcast = USE_SELECTOR('broadcast', (state) => state.common.broadcast);
|
const broadcast = USE_SELECTOR('broadcast', (state) => state.common.broadcast);
|
||||||
|
const videoPlayState = USE_SELECTOR('videoPlayState', (state) => state.play.videoPlayState);
|
||||||
|
|
||||||
const lastPanelAction = USE_SELECTOR('lastPanelAction', (state) => state.panels.lastPanelAction);
|
const lastPanelAction = USE_SELECTOR('lastPanelAction', (state) => state.panels.lastPanelAction);
|
||||||
const nowMenu = USE_SELECTOR('nowMenu', (state) => state.common.menu.nowMenu);
|
const nowMenu = USE_SELECTOR('nowMenu', (state) => state.common.menu.nowMenu);
|
||||||
@@ -2215,6 +2216,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props
|
|||||||
broadcast={broadcast}
|
broadcast={broadcast}
|
||||||
tabContainerVersion={tabContainerVersion}
|
tabContainerVersion={tabContainerVersion}
|
||||||
tabIndexV2={tabIndexV2}
|
tabIndexV2={tabIndexV2}
|
||||||
|
dispatch={dispatch}
|
||||||
>
|
>
|
||||||
{typeof window === 'object' && window.PalmSystem && (
|
{typeof window === 'object' && window.PalmSystem && (
|
||||||
<source src={currentPlayingUrl} type={videoType} />
|
<source src={currentPlayingUrl} type={videoType} />
|
||||||
|
|||||||
Reference in New Issue
Block a user