// src/actions/commonActions.js import { Job } from '@enact/core/util'; import Spotlight from '@enact/spotlight'; // <<<<<<< HEAD import appinfo from '../../webos-meta/appinfo.json'; import appinfo35 from '../../webos-meta/appinfo35.json'; import appinfo79 from '../../webos-meta/appinfo79.json'; import * as lunaSend from '../lunaSend'; import * as Config from '../utils/Config'; import * as HelperMethods from '../utils/helperMethods'; import { types } from './actionTypes'; import { createDebugHelpers } from '../utils/debug'; // 디버그 헬퍼 설정 const DEBUG_MODE = false; const { dlog, derror } = createDebugHelpers(DEBUG_MODE); // ======= // import appinfo from "../../webos-meta/appinfo.json"; // import appinfo35 from "../../webos-meta/appinfo35.json"; // import appinfo79 from "../../webos-meta/appinfo79.json"; // import { handleBypassLink } from "../App/bypassLinkHandler"; // import * as lunaSend from "../lunaSend"; // import { initialLocalSettings } from "../reducers/localSettingsReducer"; // import * as Config from "../utils/Config"; // import * as HelperMethods from "../utils/helperMethods"; // import { types } from "./actionTypes"; // >>>>>>> gitlab/develop export const changeAppStatus = (status) => ({ type: types.CHANGE_APP_STATUS, payload: status, }); export const changeBroadcastEvent = (status) => ({ type: types.SEND_BROADCAST, payload: status, }); export const changeLocalSettings = (status) => ({ type: types.CHANGE_LOCAL_SETTINGS, payload: status, }); export const gnbOpened = (status) => ({ type: types.GNB_OPENED, payload: status, }); // <<<<<<< HEAD export const setShowPopup = (config, addPayload = {}) => { let payload; if (typeof config === 'string') { payload = { activePopup: config, ...addPayload }; } else { payload = config; } // ======= // export const setShowPopup = (config) => { // const payload = typeof config === "string" ? { activePopup: config } : config; // >>>>>>> gitlab/develop return { type: types.SET_SHOW_POPUP, payload, }; }; export const setShowSecondaryPopup = (popupType, payload = {}) => ({ type: types.SET_SHOW_SECONDARY_POPUP, payload: { activePopup: popupType, ...payload }, }); export const setHidePopup = () => ({ type: types.SET_HIDE_POPUP, }); export const setHideSecondaryPopup = () => ({ type: types.SET_HIDE_SECONDARY_POPUP, }); export const showOptionalTermsConfirmPopup = () => ({ type: types.SHOW_OPTIONAL_TERMS_CONFIRM_POPUP, }); export const hideOptionalTermsConfirmPopup = () => ({ type: types.HIDE_OPTIONAL_TERMS_CONFIRM_POPUP, }); export const toggleOptionalTermsConfirm = (selected) => ({ type: types.TOGGLE_OPTIONAL_TERMS_CONFIRM, payload: selected, }); export const setExitApp = () => (dispatch) => { dispatch({ type: types.SET_EXIT_APP }); dlog('Exiting App...'); if (typeof window === 'object') { window.close(); } else { window.location.reload(); } }; export const getLoginUserData = (userData) => ({ type: types.GET_LOGIN_USER_DATA, payload: userData, }); export const loadingComplete = (status) => ({ type: 'loadingComplete', payload: status, }); export const alertToast = (payload) => (dispatch) => { if (typeof window === 'object' && !window.PalmSystem) { dispatch(changeAppStatus({ toast: true, toastText: payload })); } else { lunaSend.createToast(payload); } }; export const getSystemSettings = () => (dispatch) => { dlog('getSystemSettings '); lunaSend.getSystemSettings( { category: 'caption', keys: ['captionEnable'] }, { onSuccess: () => {}, onFailure: () => {}, onComplete: (res) => { dlog('getSystemSettings onComplete', res); if (res && res.settings) { if (typeof res.settings.captionEnable !== 'undefined') { dispatch( changeAppStatus({ captionEnable: res.settings.captionEnable === 'on' || res.settings.captionEnable === true, }) ); } } }, } ); }; export const getHttpHeaderForServiceRequest = () => (dispatch, getState) => { dlog('getHttpHeaderForServiceRequest '); const { serverType, ricCodeSetting, languageSetting } = getState().localSettings; lunaSend.getHttpHeaderForServiceRequest({ onSuccess: (res) => { const version = res['X-Device-Netcast-Platform-Version'] || ''; const webOSVersion = Number(version.substring(0, version.lastIndexOf('.'))); // 4버전 미만인 경우 다른 처리 없이 버전 정보만 저장 if (webOSVersion < 4) { dispatch( changeAppStatus({ webOSVersion, showLoadingPanel: { show: false }, }) ); return; } // 4버전 이상인 경우 기존 로직 수행 dlog('getHttpHeaderForServiceRequest', res); const convertedRes = { Authorization: res['Authorization'], 'X-Authentication': res['X-Authentication'], 'X-Device-ID': res['X-Device-ID'], 'X-Device-Product': res['X-Device-Product'], 'X-Device-Platform': res['X-Device-Platform'], 'X-Device-Model': res['X-Device-Model'], 'X-Device-Eco-Info': res['X-Device-Eco-Info'], 'X-Device-Country': res['X-Device-Country'], 'X-Device-Language': res['X-Device-Language'], 'X-Device-Netcast-Platform-Version': res['X-Device-Netcast-Platform-Version'], 'X-Device-Publish-Flag': res['X-Device-Publish-Flag'], 'X-Device-Fck': res['X-Device-Fck'], 'X-Device-Eula': res['X-Device-Eula'], 'X-Device-SDK-VERSION': res['X-Device-SDK-VERSION'], }; convertedRes['X-Device-Personalization'] = 'Y'; if ( typeof window === 'object' && window.PalmSystem && window.PalmSystem.identifier && process.env.REACT_APP_MODE !== 'DEBUG' ) { convertedRes['app_id'] = window.PalmSystem.identifier ?? appinfo.id; } else { if (ricCodeSetting === 'aic') { convertedRes['app_id'] = appinfo.id; } else if (ricCodeSetting === 'eic') { convertedRes['app_id'] = appinfo35.id; } else if (ricCodeSetting === 'ruc') { convertedRes['app_id'] = appinfo79.id; } else { convertedRes['app_id'] = appinfo.id; } } convertedRes['app_ver'] = '1.0.0'; convertedRes['cntry_cd'] = res['X-Device-Country']; convertedRes['prod_cd'] = res['X-Device-Product']; convertedRes['plat_cd'] = res['X-Device-Platform']; convertedRes['lang_cd'] = res['X-Device-Language']; convertedRes['sdk_ver'] = res['X-Device-SDK-VERSION']; convertedRes['publish_flag'] = res['X-Device-Publish-Flag']; convertedRes['os_ver'] = version; convertedRes['dvc_auth'] = res['X-Authentication']; if (serverType !== 'system') { if (ricCodeSetting === 'eic') { if (languageSetting === 'GB') { convertedRes['cntry_cd'] = 'GB'; convertedRes['X-Device-Country'] = 'GB'; res['HOST'] = 'GB.nextlgsdp.com'; } if (languageSetting === 'DE') { convertedRes['cntry_cd'] = 'DE'; convertedRes['X-Device-Country'] = 'DE'; res['HOST'] = 'DE.nextlgsdp.com'; } } if (ricCodeSetting === 'aic') { convertedRes['cntry_cd'] = 'US'; convertedRes['X-Device-Country'] = 'US'; res['HOST'] = 'US.nextlgsdp.com'; } if (ricCodeSetting === 'ruc') { convertedRes['cntry_cd'] = 'RU'; convertedRes['X-Device-Country'] = 'RU'; res['HOST'] = 'RU.nextlgsdp.com'; } } if (convertedRes['cntry_cd'] === 'US') { convertedRes['lang_cd'] = 'en-US'; } if (convertedRes['cntry_cd'] === 'DE') { convertedRes['lang_cd'] = 'de-DE'; } if (convertedRes['cntry_cd'] === 'GB') { convertedRes['lang_cd'] = 'en-GB'; } if (convertedRes['cntry_cd'] === 'RU') { convertedRes['lang_cd'] = 'ru-RU'; } dispatch({ type: types.GET_HTTP_HEADER, payload: convertedRes }); dispatch( changeAppStatus({ webOSVersion, serverHOST: res['HOST'], mbr_no: res['X-User-Number'], }) ); const parameters = { serviceName: 'LGE' }; const mbrNo = res['X-User-Number']; lunaSend.getLoginUserData(parameters, { onSuccess: (loginRes) => { const userId = loginRes.id ?? ''; const profileNick = loginRes.profileNick || userId.split('@')[0]; dispatch( getLoginUserData({ userId, userNumber: mbrNo, profileNick, }) ); }, onFailure: (err) => derror('LoginData fetch failed ', err), }); }, onFailure: (err) => { dlog('getHttpHeaderForServiceRequest fail', err); }, }); }; export const getDeviceId = (onComplete) => (dispatch) => { lunaSend.getDeviceId( { idType: ['LGUDID'] }, { onSuccess: (res) => { dlog('getDeviceId ', res); if (res.returnValue) { const deviceId = res.idList[0].idValue; dispatch(changeAppStatus({ deviceId: deviceId })); } }, onFailure: (err) => { dlog(err); }, onComplete: () => { dlog('getDeviceId done'); if (onComplete) onComplete(); }, } ); }; export const getTermsAgreeYn = () => (dispatch, getState) => { dispatch({ type: types.GET_TERMS_AGREE_YN_START }); try { const { terms } = getState().home.termsData.data; dlog( 'getTermsAgreeYn', terms.map((term) => ({ trmsId: term.trmsId, trmsTpCd: term.trmsTpCd, trmsAgrFlag: term.trmsAgrFlag, trmsPopFlag: term.trmsPopFlag, })) ); // MST00405 선택약관 정보만 따로 출력 const optionalTerm = terms.find((term) => term.trmsTpCd === 'MST00405'); if (optionalTerm) { dlog('getTermsAgreeYn MST00405 선택약관:', { trmsId: optionalTerm.trmsId, trmsTpCd: optionalTerm.trmsTpCd, trmsAgrFlag: optionalTerm.trmsAgrFlag, trmsPopFlag: optionalTerm.trmsPopFlag, }); } else { dlog('getTermsAgreeYn MST00405 선택약관을 찾을 수 없습니다.'); } const termsAgreeFlag = terms.reduce((acc, term) => { switch (term.trmsTpCd) { case 'MST00401': acc.privacyTerms = term.trmsAgrFlag; break; case 'MST00402': acc.serviceTerms = term.trmsAgrFlag; break; case 'MST00403': acc.purchaseTerms = term.trmsAgrFlag; break; case 'MST00404': acc.paymentTerms = term.trmsAgrFlag; break; case 'MST00405': acc.optionalTerms = term.trmsAgrFlag; break; default: break; } return acc; }, {}); dispatch({ type: types.GET_TERMS_AGREE_YN_SUCCESS, payload: termsAgreeFlag, }); } catch (error) { derror('getTermsAgreeYn error:', error); dispatch({ type: types.GET_TERMS_AGREE_YN_FAILURE }); } }; // export const getTermsAgreeYn = () => (dispatch, getState) => { // const { terms } = getState().home.termsData.data; // // dlog("getTermsAgreeYn", terms); // dlog("getTermsAgreeYn", terms.map(term => ({ // trmsId: term.trmsId, // trmsTpCd: term.trmsTpCd, // trmsAgrFlag: term.trmsAgrFlag, // trmsPopFlag: term.trmsPopFlag, // }))); // const termsAgreeFlag = terms.reduce((acc, term) => { // switch (term.trmsTpCd) { // case "MST00401": // acc.privacyTerms = term.trmsAgrFlag; // break; // case "MST00402": // acc.serviceTerms = term.trmsAgrFlag; // break; // case "MST00403": // acc.purchaseTerms = term.trmsAgrFlag; // break; // case "MST00404": // acc.paymentTerms = term.trmsAgrFlag; // break; // case "MST00405": // acc.optionalTerms = term.trmsAgrFlag; // break; // default: // break; // } // return acc; // }, {}); // dispatch({ // type: types.GET_TERMS_AGREE_YN, // payload: termsAgreeFlag, // }); // }; export const launchMembershipApp = () => (dispatch, getState) => { const state = getState(); const panels = state.panels.panels; const currentPanel = panels[panels.length - 1]; const returnPath = JSON.stringify({ name: currentPanel.name, panelInfo: currentPanel.panelInfo || {}, }); if (typeof window === 'object' && !window.PalmSystem) { // const testBypass = { // name: Config.panel_names.CATEGORY_PANEL, // panelInfo: { // COUNT: 31, // currentSpot: null, // dropDownTab: 0, // expsOrd: 1, // focusedContainerId: null, // lgCatCd: "1017", // lgCatNm: "LG Electronics", // tab: 0, // }, // }; dlog('returnPath', returnPath); // setTimeout(() => { // dispatch(handleBypassLink(JSON.stringify(testBypass))); // }, 1000); return; } lunaSend.launchMembershipApp(returnPath, { onSuccess: (res) => { dlog('membership launch success: ', res); }, onFailure: (err) => { dlog('membership launch failed:', err); }, }); }; let rafId = null; export const setFocus = (spotlightId) => ({ type: types.SET_FOCUS, payload: spotlightId, }); export const focusElement = (spotlightId) => (dispatch) => { dispatch(setFocus(spotlightId)); if (typeof window === 'object') { rafId = window.requestAnimationFrame(() => { Spotlight.focus(spotlightId); }); } }; export const cancelFocusElement = () => () => { if (rafId !== null) { if (typeof window === 'object') { window.cancelAnimationFrame(rafId); rafId = null; } } }; let broadcastTimer = null; export const sendBroadCast = ({ type, moreInfo }) => (dispatch) => { clearTimeout(broadcastTimer); dispatch(changeBroadcastEvent({ type, moreInfo })); broadcastTimer = setTimeout(() => { //clear after 500ms dispatch(changeBroadcastEvent({})); }, 5000); }; export const requestLiveSubtitle = ({ mediaId, enable }) => (dispatch, getState) => { const webOSVersion = getState().common.appStatus.webOSVersion; if (Number(webOSVersion) <= 4.5) { lunaSend.setSubtitleEnable(mediaId, enable, { onSuccess: (res) => { dlog(res); }, onFailure: (err) => { dlog(err); }, }); return; } else { lunaSend.setSubtitleEnableOver5(mediaId, enable, { onSuccess: (res) => { dlog(res); }, onFailure: (err) => { dlog(err); }, }); } }; export const addReservation = (data) => (dispatch) => { lunaSend.addReservation(data, { onSuccess: (res) => { dlog('addReservation success:', res); // Optionally show success toast if (res && res.returnValue) { dispatch(alertToast('Reminder set successfully')); } }, onFailure: (err) => { derror('addReservation failed:', err); // Use the helper function for better error handling const errorMessage = HelperMethods.getReservationErrorMessage(err); dispatch(alertToast(errorMessage)); }, onComplete: () => { dlog('addReservation completed'); }, }); }; export const deleteReservationCallback = (scheduleIdList) => () => { lunaSend.deleteReservationCallback(scheduleIdList, { onSuccess: (res) => { // dispatch(alertToast("success" + JSON.stringify(res))); }, onFailure: (err) => { // dispatch(alertToast("failed" + JSON.stringify(err))); }, }); }; export const deleteReservation = (showId) => (dispatch) => { lunaSend.deleteReservation({ onSuccess: (res) => { let items = []; res.results.forEach((item) => { let obj = JSON.parse(item.information.information); items.push({ _id: item._id, showId: obj.showId, }); }); let index = items.findIndex((item) => item.showId === showId); let deletedIdList = []; if (index !== -1) { deletedIdList.push(items[index]._id); dispatch(deleteReservationCallback(deletedIdList)); } }, onFailure: (err) => { dlog(err); }, }); }; export const setSystemNotice = () => ({ type: types.SET_SYSTEM_NOTICE, }); export const setSystemTermination = (isinitialLoad) => ({ type: types.SET_SYSTEM_TERMINATION, payload: { isinitialLoad }, }); export const setDeepLink = (deepLinkInfo) => ({ type: types.SET_DEEP_LINK, payload: deepLinkInfo, }); export const setSecondLayerInfo = (secondLayerInfo) => ({ type: types.SET_SECOND_LAYER_INFO, payload: secondLayerInfo, }); export const setGNBMenu = (gnbMenu) => ({ type: types.SET_GNB_MENU, payload: gnbMenu, }); export const setDeviceRegistered = (isRegistered) => ({ type: types.SET_DEVICE_REGISTERED, payload: isRegistered, }); export const clearErrorMessage = () => ({ type: types.CLEAR_ERROR_MESSAGE, }); export const showError = (errorCode, errorMsg, shouldPopPanel = false, retDetailCode = null, returnBindStrings = null) => (dispatch) => { dispatch( setShowPopup(Config.ACTIVE_POPUP.errorPopup, { data: { errorCode, errorMsg, retDetailCode, shouldPopPanel, returnBindStrings, }, }) ); }; //luna-send -f -n 1 luna://com.webos.service.db/delKind '{"id": "com.lgshop.app:5"}' -a "com.lgshop.app" export const deleteOldDb8Datas = () => (dispatch) => { for (let i = 1; i < 10; i++) { lunaSend.deleteOldDb8(i, { onSuccess: () => {}, onFailure: () => {}, }); } dispatch(changeLocalSettings({ oldDb8Deleted: true })); }; export const checkFirstLaunch = () => (dispatch) => { lunaSend.checkFirstLaunch({ onSuccess: (res) => { if (!res.returnValue) { derror('Failed to check first launch status'); return; } if (res.results.length === 0) { dlog('First launch detected - initializing localStorage'); if (typeof window === 'object') { dispatch(changeLocalSettings({ phoneNumbers: {}, recentItems: [] })); } lunaSend.saveFirstLaunchInfo({ onSuccess: (saveRes) => { dlog('First launch info saved to DB8:', saveRes); dispatch(changeAppStatus({ isFirstLaunch: true })); }, onFailure: (err) => { derror('Failed to save first launch info:', err); }, }); } else { dlog('Not first launch - keeping existing settings'); dispatch(changeAppStatus({ isFirstLaunch: false })); } }, onFailure: (err) => { derror('Failed to check first launch:', err); }, }); }; let updateNetworkStateJob = new Job((dispatch, connected) => { dispatch(changeAppStatus({ isInternetConnected: connected })); }); export const getConnectionStatus = () => (dispatch) => { lunaSend.getConnectionStatus({ onSuccess: (res) => { dlog('lunasend getConnectionStatus', res); if (res.returnValue) { const isInternet = (res.wifi && res.wifi.onInternet === 'yes') || (res.wired && res.wired.onInternet === 'yes'); const isInternetConnected = (res.wifi && res.wifi.state === 'connected') || (res.wired && res.wired.state === 'connected'); dlog('internetconnected.............', isInternet, isInternetConnected, res); const connected = isInternet && isInternetConnected; updateNetworkStateJob.startAfter(connected ? 100 : 3000, dispatch, connected); } }, onFailure: (err) => { dlog(err); }, onComplete: (res) => { dlog('getConnectionStatus done', res); }, }); }; // macAddress export const getConnectionInfo = () => (dispatch) => { lunaSend.getConnectionInfo({ onSuccess: (res) => { dlog('lunasend getConnectionStatus', res); if (res && res.returnValue) { const macAddress = res?.wiredInfo?.macAddress; dlog('macAddress...........', macAddress, res); } }, onFailure: (err) => { dlog('getConnentionInfo', err); }, onComplete: (res) => { dlog('getConnentionInfo done', res); dispatch({ type: types.GET_DEVICE_MACADDRESS, payload: res, }); }, }); }; export const disableNotification = () => { lunaSend.disableNotification({ onSuccess: (res) => { dlog('lunasend disable notification success', res); }, onFailure: (err) => { dlog('lunasend disable notification failure', err); }, onComplete: (res) => { dlog('lunasend disable notification complete', res); }, }); }; export const enableNotification = () => { lunaSend.enableNotification({ onSuccess: (res) => { dlog('lunasend enable notification success', res); }, onFailure: (err) => { dlog('lunasend enable notification failure', err); }, onComplete: (res) => { dlog('lunasend enable notification complete', res); }, }); }; // 선택약관 팝업 상태 관리 액션 생성자들 (TV 환경 최적화) export const setOptionalTermsPopupShown = (shown = true) => ({ type: types.SET_OPTIONAL_TERMS_POPUP_SHOWN, payload: shown, }); export const setOptionalTermsUserDecision = (decision) => ({ type: types.SET_OPTIONAL_TERMS_USER_DECISION, payload: decision, // 'agreed' | 'declined' | null }); export const resetOptionalTermsSession = () => ({ type: types.RESET_OPTIONAL_TERMS_SESSION, }); // 선택약관 동의 처리를 위한 헬퍼 함수 export const handleOptionalTermsAgree = () => (dispatch) => { dlog('[CommonActions] 선택약관 동의 처리'); dispatch(setOptionalTermsUserDecision('agreed')); dispatch(setOptionalTermsPopupShown(true)); }; // 선택약관 거절 처리를 위한 헬퍼 함수 export const handleOptionalTermsDecline = () => (dispatch) => { dlog('[CommonActions] 선택약관 거절 처리'); dispatch(setOptionalTermsUserDecision('declined')); dispatch(setOptionalTermsPopupShown(true)); }; // 선택약관 상태 통합 업데이트 (TV 환경 최적화 - API 호출 없이 즉시 반영) export const updateOptionalTermsAgreement = (agreed = true) => (dispatch) => { dlog(`[CommonActions] 선택약관 통합 상태 업데이트: ${agreed}`); // 1. optionalTermsPopupFlow 업데이트 (TV 환경용) dispatch(setOptionalTermsUserDecision(agreed ? 'agreed' : 'declined')); dispatch(setOptionalTermsPopupShown(true)); // 2. 기본 optionalTermsAgree 상태 직접 업데이트 (API 호출 없이) dispatch({ type: types.UPDATE_OPTIONAL_TERMS_AGREE_DIRECT, payload: agreed, }); // 3. termsAgreementStatus도 동기화 dispatch({ type: types.UPDATE_TERMS_AGREEMENT_STATUS_DIRECT, payload: { MST00405: agreed }, }); };