var cgGcfmAudioLoaded = false; var cgGcfmLoadAttempts = 0; var cgGcfmPlayAttemptInterval = null; var cgGcfmPositionTrackerInterval = null; var cgGcfmTimeWritten = false; var cgGcfmXDown = null; var cgGcfmYDown = null; var cgGcfmPlayerUrl = 'https://player.godcaster.fm'; var cgGcfmAssetsUrl = 'https://assets.godcaster.fm'; const gcfmSearchForPrograms = gcfmDebounce(() => gcfmSearchPrograms()); const gcfmFilterBodyList = gcfmDebounce(() => gcfmFilterBodyListItems()); let gcfmPlayerContainer = null; let gcfmHiddenElements = null; let gcfmAudioBar = null; const gcfmInsertSliderContainer = gcfmFindElementsByQuery("#gcfm-insert-slider"); let gcfmInsertSliderCurrentIndex = 0; /* Set sources */ if (document.currentScript.src.indexOf('lightfeed.org') !== -1) { cgGcfmPlayerUrl = 'https://player.lightfeed.org'; cgGcfmAssetsUrl = 'https://assets.lightfeed.org'; } /* Set up listeners */ document.addEventListener('click', gcfmHandlePlayerClick); document.addEventListener('change', gcfmHandlePlayerChange); document.addEventListener('keydown', gcfmHandlePlayerKeyDown); document.addEventListener('input', gcfmHandleSliderClick); document.addEventListener('error', gcfmHandlePlayerError, true); document.addEventListener('touchstart', gcfmHandleTouchStart, false); document.addEventListener('touchmove', gcfmHandleTouchMove, false); function gcfmLoadPlayer() { let lgPlayerContainer = gcfmFindElementById('gcfm-player-container'); if (!lgPlayerContainer) { console.log("GCFM: Player container not in DOM yet..."); return; } if (gcfmFindElementById('gcfm-player')) { console.log("GCFM: Player already loaded. Quitting observer."); gcfmDocumentObserver.disconnect(); return; } lgPlayerContainer.setAttribute('style', 'width:100%;height:100%;z-index:99996'); if (!lgPlayerContainer.classList.contains('gcfm-player-2b1bb1b2-iso')) { lgPlayerContainer.classList.add('class', 'gcfm-player-2b1bb1b2-iso'); } lgPlayer = document.createElement('div'); lgPlayer.setAttribute('id', 'gcfm-player'); lgPlayerContainer.appendChild(lgPlayer); gcfmIsolate(lgPlayerContainer); gcfmPlayerContainer = gcfmFindElementById('gcfm-player-container'); /* Set up listeners */ gcfmPlayerContainer.addEventListener('click', gcfmHandlePlayerClick); gcfmPlayerContainer.addEventListener('change', gcfmHandlePlayerChange); gcfmPlayerContainer.addEventListener('keydown', gcfmHandlePlayerKeyDown); gcfmPlayerContainer.addEventListener('input', gcfmHandleSliderClick); gcfmPlayerContainer.addEventListener('error', gcfmHandlePlayerError, true); gcfmPlayerContainer.addEventListener('touchstart', gcfmHandleTouchStart, false); gcfmPlayerContainer.addEventListener('touchmove', gcfmHandleTouchMove, false); gcfmPlayerInit(); } function gcfmPlayerInit() { let playerStyle = gcfmGetPlayerStyleFromUrl(); let isPwa = gcfmGetPwaStatus(); url = new URL(cgGcfmPlayerUrl + '/publicplayer/init'); url.searchParams.append('pid', gcfmGetPlayerId()); url.searchParams.append('did', gcfmGetPlayerDid()); url.searchParams.append('eid', gcfmGetEpisodeIdFromUrl()); url.searchParams.append('page', gcfmGetPageNumberFromUrl()); url.searchParams.append('fid', gcfmGetFeedIdFromUrl()); url.searchParams.append('shared', gcfmEpisodeWasShared(false)); if (playerStyle !== null) { url.searchParams.append('style', playerStyle); } if (isPwa) { url.searchParams.append('pwa', 1); } fetch(url.href) .then(response => { // When the page is loaded convert it to text return response.text() }) .then(html => { lgPlayer = gcfmFindElementById('gcfm-player'); lgPlayer.outerHTML = html; gcfmPlayerEnvironmentInit(); gcfmPlayerBodyInit(); }) .catch(error => { console.error('Failed to load the player: ', error) }) } function gcfmPlayerEnvironmentInit() { controlsPosition = gcfmGetControlsPosition(); if (controlsPosition == 2 && !gcfmFindElementsByQuery('body > #gcfm-audio-bar')) { let audioBar = gcfmFindElementById('gcfm-audio-bar'); if (audioBar) { document.body.appendChild(audioBar); gcfmAudioBar = audioBar; gcfmIsolateAudioBar(audioBar); /* Set up listeners */ gcfmAudioBar.addEventListener('click', gcfmHandlePlayerClick); gcfmAudioBar.addEventListener('change', gcfmHandlePlayerChange); gcfmAudioBar.addEventListener('keydown', gcfmHandlePlayerKeyDown); gcfmAudioBar.addEventListener('input', gcfmHandleSliderClick); gcfmAudioBar.addEventListener('error', gcfmHandlePlayerError, true); gcfmAudioBar.addEventListener('touchstart', gcfmHandleTouchStart, false); gcfmAudioBar.addEventListener('touchmove', gcfmHandleTouchMove, false); } } let hiddenElements = gcfmFindElementById('gcfm-hidden-elements'); if (hiddenElements && !gcfmFindElementsByQuery('body > #gcfm-hidden-elements')) { document.body.appendChild(hiddenElements); gcfmHiddenElements = hiddenElements; gcfmIsolateHidden(hiddenElements); /* Set up listeners */ gcfmHiddenElements.addEventListener('click', gcfmHandlePlayerClick); gcfmHiddenElements.addEventListener('change', gcfmHandlePlayerChange); gcfmHiddenElements.addEventListener('keydown', gcfmHandlePlayerKeyDown); gcfmHiddenElements.addEventListener('input', gcfmHandleSliderClick); gcfmHiddenElements.addEventListener('error', gcfmHandlePlayerError, true); gcfmHiddenElements.addEventListener('touchstart', gcfmHandleTouchStart, false); gcfmHiddenElements.addEventListener('touchmove', gcfmHandleTouchMove, false); } } function gcfmGetControlsPosition() { lgPlayer = gcfmFindElementById('gcfm-player'); controlsPosition = lgPlayer.getAttribute('data-controlsposition'); return controlsPosition; } function gcfmPlayerBodyInit() { let feedId = gcfmGetFeedIdFromUrl(); let pageNumber = gcfmGetPageNumberFromUrl(); let playerStyle = gcfmGetPlayerStyle(); let wasShared = gcfmEpisodeWasShared(); let episodeId = gcfmGetEpisodeIdFromUrl(); gcfmPlayerBodyChange( feedId, pageNumber, playerStyle, wasShared, episodeId, ); } function gcfmSetCurrentUrl(cleanUrl) { var urlString = window.location.href; if (cleanUrl) { urlString = gcfmGetCleanUrl(); } var url = new URL(urlString); let params = new URLSearchParams(url.search); url.hash = 'gcfm-player-container'; window.history.replaceState({}, '', url.toString()); } function gcfmPlayerBodyChange(feedId, page, style, shared, episodeId, collection) { if (page == 0) page = 1; var url = new URL(cgGcfmPlayerUrl + '/publicplayer/body'); url.searchParams.append('pid', gcfmGetPlayerId()); url.searchParams.append('did', gcfmGetPlayerDid()); url.searchParams.append('page', page); if (feedId) { url.searchParams.append('fid', feedId); } if (episodeId && episodeId !== "null") { url.searchParams.append('eid', episodeId); } url.searchParams.append('shared', shared); if (style !== null) { url.searchParams.append('style', style); } if (collection) { url.searchParams.append('collection', collection); } else { let coll = gcfmGetPlayerCollection(); if (coll && coll !== 'null') { url.searchParams.append('collection', coll); } } let headerPanel = gcfmFindElementById('gcfm-program-header-panel'); if (headerPanel) { headerPanel.remove(); } let hiddenBodyElements = gcfmFindElementById('gcfm-hidden-body-elements'); if (hiddenBodyElements) { hiddenBodyElements.remove(); } gcfmBodyIsLoading(true); fetch(url.href) .then(response => { // When the page is loaded convert it to text return response.text() }) .then(html => { lgPlayerBody = gcfmFindElementById('gcfm-body-wrapper'); lgPlayerBody.outerHTML = html; gcfmBodyIsLoading(false); gcfmSetPlayerStyle(style); gcfmSetPaginationStates(page); gcfmToggleProgramHeaderPanel(); }) .catch(error => { console.error('Failed to load player content: ', error) }) } function gcfmSearchPrograms() { queryText = gcfmFindElementById('gcfm-search-input').value; if (queryText.trim() == '' || queryText.trim().length < 3) { return false; } var url = new URL(cgGcfmPlayerUrl + '/publicplayer/search'); url.searchParams.append('pid', gcfmGetPlayerId()); url.searchParams.append('did', gcfmGetPlayerDid()); url.searchParams.append('query', queryText); let headerPanel = gcfmFindElementById('gcfm-program-header-panel'); if (headerPanel) { headerPanel.remove(); } let hiddenBodyElements = gcfmFindElementById('gcfm-hidden-body-elements'); if (hiddenBodyElements) { hiddenBodyElements.remove(); } gcfmBodyIsLoading(true); fetch(url.href) .then(response => { // When the page is loaded convert it to text return response.text() }) .then(html => { lgPlayerBody = gcfmFindElementById('gcfm-body-wrapper'); lgPlayerBody.outerHTML = html; gcfmBodyIsLoading(false); gcfmSetPaginationStates(0); }) .catch(error => { console.error('Failed to load player content: ', error) }) } function gcfmFilterBodyListItems() { var queryText = gcfmFindElementById('gcfm-filter-input').value.trim().toLowerCase(); let listItems = gcfmFindElementsByQuery('#gcfm-body li.gcfm-body-list-item', true); for (const item of listItems) { const text = item.textContent.toLowerCase(); if (queryText === '' || text.includes(queryText)) { item.classList.remove('hidden'); } else { item.classList.add('hidden'); } } } function gcfmToggleProgramHeaderPanel() { let programHeaderPanel = gcfmFindElementById('gcfm-program-header-panel'); if (programHeaderPanel) { if (gcfmFindElementById('gcfm-program-page-active')) { programHeaderPanel.classList.remove('hidden'); } else { programHeaderPanel.classList.add('hidden'); } } } function gcfmGetPageNumberFromUrl() { let url = new URL(window.location.href); let page = url.searchParams.get('gcfm-page'); return page || 0; } function gcfmGetPlayerStyleFromUrl() { let url = new URL(window.location.href); let style = url.searchParams.get('gcfm-style'); return style || null; } function gcfmGetPlayerStyle() { let lgPlayer = gcfmFindElementById('gcfm-player'); let elStyle = lgPlayer.querySelector('#gcfm-body-style-toggle'); if (elStyle) { return elStyle.getAttribute('data-style'); } else { return 0; } } function gcfmGetOriginalPlayerStyle() { let lgPlayer = gcfmFindElementById('gcfm-player'); if (lgPlayer) { return lgPlayer.getAttribute('data-orgplayerstyle'); } else { return gcfmGetOriginalPlayerStyle(); } } function gcfmGetPwaStatus() { let lgPlayerContainer = gcfmPlayerContainer; if (lgPlayerContainer) { let pwa = lgPlayerContainer.getAttribute('data-pwa'); if (pwa && pwa == 'true') { return true; } } return false; } function gcfmGetPlayerTitle() { let lgPlayerTitle = gcfmFindElementById('gcfm-player-title'); if (lgPlayerTitle) { return lgPlayerTitle.innerText; } else { return ''; } } function gcfmGetPlayerCollection() { let lgPlayerCollections = gcfmFindElementById('gcfm-collections'); if (lgPlayerCollections) { let collectionId = lgPlayerCollections.getAttribute('data-collectionid'); if (collectionId) { return collectionId; } } return null; } function gcfmSetPlayerCollection(collectionId) { let lgPlayerCollections = gcfmFindElementById('gcfm-collections'); if (lgPlayerCollections) { lgPlayerCollections.setAttribute('data-collectionid', collectionId); } } function gcfmGetPlatform() { let lgPlayer = gcfmFindElementById('gcfm-player'); var lgPlatform = lgPlayer.getAttribute('data-platform').trim().toLowerCase(); if (lgPlatform.indexOf('ios') < 0 && lgPlatform.indexOf('android') < 0) { lgPlatform = 'web'; } return lgPlatform; } function gcfmSetPlayerStyle(style) { let lgStyleToggle = gcfmFindElementById('gcfm-body-style-toggle'); if (!lgStyleToggle) { return false; } lgStyleToggle.setAttribute('data-style', style); let styleIcons = gcfmFindElementsByClassName('gcfm-body-style-toggle-icon') for (var i = 0; i < styleIcons.length; i++) { if (styleIcons[i].id == 'gcfm-body-style-toggle-icon-' + style) { styleIcons[i].style.display = ''; } else { styleIcons[i].style.display = 'none'; } } } function gcfmGetFeedIdFromUrl() { let url = new URL(window.location.href); let feedId = url.searchParams.get('gcfm-fid'); return feedId || 0; } function gcfmGetEpisodeIdFromUrl() { let url = new URL(window.location.href); let episodeId = url.searchParams.get('gcfm-eid'); return episodeId || 0; } function gcfmGetStartTime() { let url = new URL(window.location.href); let ts = url.searchParams.get('gcfm-ts'); return ts || 0; } function gcfmEpisodeWasShared(strip) { let url = new URL(window.location.href); let wasShared = url.searchParams.get('gcfm-shared'); if (strip) { gcfmStripSharingFromUrl(url); } return wasShared || "false"; } function gcfmStripSharingFromUrl(url) { let newUrl = new URL(url); newUrl.searchParams.delete('gcfm-shared'); newUrl.searchParams.delete('gcfm-eid'); newUrl.searchParams.delete('gcfm-ts'); window.history.replaceState(null, '', newUrl); } function gcfmGetNextPage() { let elPrevPage = gcfmFindElementById('gcfm-paginator-prev'); let elNextPage = gcfmFindElementById('gcfm-paginator-next'); if (elNextPage === null || elPrevPage === null) { return 0; } if (elPrevPage.getAttribute('data-page') == elNextPage.getAttribute('data-lastpage')) { return elNextPage.getAttribute('data-lastpage'); } return parseInt(elPrevPage.getAttribute('data-page')) + 1; } function gcfmGetPrevPage() { let elPrevPage = gcfmFindElementById('gcfm-paginator-prev'); if (elPrevPage === null || parseInt(elPrevPage.getAttribute('data-page')) <= 1) { return 1; } return parseInt(elPrevPage.getAttribute('data-page')) - 1; } function gcfmSetPaginationStates(pageRequested) { let elPrevPage = gcfmFindElementById('gcfm-paginator-prev'); let elNextPage = gcfmFindElementById('gcfm-paginator-next'); style = gcfmGetPlayerStyle(); if (style == 1 || style == '1') { gcfmShowPageNavigation(false); } else { gcfmShowPageNavigation(true); } if (elNextPage === null || elPrevPage === null) { return 0; } elPrevPage.setAttribute('data-page', pageRequested); if (pageRequested == 1) { elPrevPage.style.display = 'none'; } else { elPrevPage.style.display = ''; } if (pageRequested == parseInt(elNextPage.getAttribute('data-lastpage'))) { elNextPage.style.display = 'none'; } else { elNextPage.style.display = ''; } return 0; } function gcfmShowPageNavigation(visible) { let lgPaginatorHiddenLinks = gcfmFindElementById('gcfm-paginator-hidden-links'); let lgPaginatorLinks = gcfmFindElementById('gcfm-paginator-links'); if (lgPaginatorHiddenLinks && lgPaginatorLinks) { lgPaginatorLinks.replaceWith(lgPaginatorHiddenLinks); lgPaginatorHiddenLinks.id = 'gcfm-paginator-links'; } let lgPageNav = gcfmFindElementById('gcfm-player-page-nav'); if (!lgPageNav) { return false; } if (visible) { lgPageNav.style.display = ''; } else { lgPageNav.style.display = 'none'; } } function gcfmGetPlayerId() { let elPlayer = gcfmPlayerContainer; return elPlayer.getAttribute('data-playerid'); } function gcfmGetPlayerDid() { let elPlayer = gcfmPlayerContainer; return elPlayer.getAttribute('data-did'); } function gcfmHandleSliderClick(event) { var element = event.target; if (element.id === 'gcfm-audio-control-slider') { if (element.readOnly == true) { return false; } let lgAudioPlayer = gcfmFindElementById('gcfm-player-audio'); lgAudioPlayer.currentTime = element.value; } if (element.id === 'gcfm-fullscreen-slider') { if (element.readOnly == true) { return false; } let lgAudioPlayer = gcfmFindElementById('gcfm-player-audio'); lgAudioPlayer.currentTime = element.value; } } function gcfmHandlePlayerError(event) { var element = event.target; if (element.id === 'gcfm-player-audio-source' && element.src !== '') { let s = ""; let lgAudioPlayer = gcfmFindElementById('gcfm-player-audio'); let lgAudioPlayerSource = gcfmFindElementById('gcfm-player-audio-source'); if (lgAudioPlayer.readyState === 0 && lgAudioPlayer.networkState === 3) { gcfmDisplayErrorMessage("This media file can't be loaded because of a network issue or a publisher-side server issue."); clearInterval(cgGcfmPlayAttemptInterval); lgAudioPlayerSource.setAttribute('src', ''); gcfmHideAllEpisodeLoadingIcons(); } } } function gcfmHandlePlayerChange(event) { var element = event.target; /* Collection selector */ if (element.id === 'gcfm-collection') { gcfmPlayerBodyChange(0, 0, gcfmGetPlayerStyle(), false, 0, gcfmGetPlayerCollection()); } } function gcfmHandlePlayerKeyDown(event) { var element = event.target; if (element.id === 'gcfm-search-input' && event.key === 'Enter') { gcfmSearchForPrograms(); } if (element.id === 'gcfm-filter-input') { let showMoreButtonItem = gcfmFindElementById('gcfm-show-more-episodes-item'); if (showMoreButtonItem) { if (element.value.trim() !== '') { showMoreButtonItem.classList.add('hidden'); } } gcfmFilterBodyList(); } } function gcfmHandlePlayerClick(event) { var element = event.target; /*Episode title in episode list*/ if (element.classList.contains('gcfm-button-episode-title')) { let feedId = element.getAttribute('data-feedid'); let episodeId = element.getAttribute('data-episodeid'); gcfmPlayerBodyChange(feedId, 0, gcfmGetPlayerStyle(), false, episodeId, gcfmGetPlayerCollection()); } /* Player body style toggle */ if (element.id === 'gcfm-body-style-toggle') { var style = gcfmFindElementById('gcfm-body-style-toggle') .getAttribute('data-style'); if (style == 0 || style == 1) { gcfmPlayerBodyChange(false, 0, (1 - style), 0, 0, gcfmGetPlayerCollection()); } } /* Close full screen mode panel */ if (element.id === 'gcfm-fullscreen-exit') { gcfmFindElementById('gcfm-fullscreen-panel').classList.add('hidden'); gcfmFindElementById('gcfm-audio-bar').classList.remove('hidden'); document.body.style.overflow = ''; } /* Open full screen mode panel */ if (element.id === 'gcfm-audio-control-image') { gcfmFindElementById('gcfm-audio-bar').classList.add('hidden'); gcfmFindElementById('gcfm-fullscreen-panel').classList.remove('hidden'); document.body.style.overflow = 'hidden'; } /* Collections panel toggle button was clicked */ if (element.id === 'gcfm-collections-button') { var lgCollections = gcfmFindElementById('gcfm-collections'); let lgFooter = gcfmFindElementById('gcfm-footer'); if (lgCollections) { lgCollections.style.height = (lgFooter.offsetTop - lgCollections.offsetTop) + 'px'; if ( lgCollections.style.width === '0' || lgCollections.style.width === '0px' ) { lgCollections.style.padding = '16px'; lgCollections.style.width = '300px'; } else { lgCollections.style.padding = '0'; lgCollections.style.width = '0'; } } } /* Search icon for programs */ if (element.id === 'gcfm-search-for-program') { let searchBar = gcfmFindElementById('gcfm-search-bar-content'); let elInput = gcfmFindElementById('gcfm-search-input'); searchBar.classList.toggle('hidden'); if (searchBar.classList.contains('hidden')) { elInput.value = ''; } else { elInput.focus(); } } /* Filter list icon */ if (element.id === 'gcfm-filter-body-list') { let searchBar = gcfmFindElementById('gcfm-search-bar-content'); let elInput = gcfmFindElementById('gcfm-filter-input'); searchBar.classList.toggle('hidden'); if (searchBar.classList.contains('hidden')) { if (elInput.value.trim() !== '') { elInput.value = ''; gcfmFilterBodyListItems(); } } else { elInput.focus(); } } /* Collection link was clicked in collection panel */ if (element.classList.contains('gcfm-collection-option')) { let collectionId = element.getAttribute('data-collectionid'); gcfmSetPlayerCollection(collectionId); var lgCollectionsBtn = gcfmFindElementById('gcfm-collections-button'); if (lgCollectionsBtn) { lgCollectionsBtn.click(); } gcfmPlayerBodyChange(0, 0, gcfmGetPlayerStyle(), false, 0, gcfmGetPlayerCollection()); } /* Feed tile was clicked */ if (element.classList.contains('gcfm-program-link')) { let feedId = element.getAttribute('data-feedid'); let pageNumber = element.getAttribute('data-page'); gcfmPlayerBodyChange(feedId, pageNumber, gcfmGetPlayerStyle(), false, 0, gcfmGetPlayerCollection()); } /* Body back button was clicked */ if ( element.id === 'gcfm-back-button' || element.id === 'gcfm-back-button-div' || element.id === 'gcfm-back-button-span' || element.id === 'gcfm-back-button-icon' ) { let backButton = gcfmFindElementById('gcfm-back-button'); let pageNumber = backButton.getAttribute('data-page'); let feedId = backButton.getAttribute('data-feedid'); if (feedId) { gcfmPlayerBodyChange(feedId, pageNumber, gcfmGetPlayerStyle(), false, 0, gcfmGetPlayerCollection()); return false; } let exitTempStyle = backButton.getAttribute('data-exitstyle'); if (exitTempStyle == 'true') { gcfmSetCurrentUrl(true); gcfmPlayerBodyChange(false, pageNumber, gcfmGetPlayerStyle(), false, 0, gcfmGetPlayerCollection()); } else { gcfmPlayerBodyChange(false, pageNumber, gcfmGetPlayerStyleFromUrl(), false, 0, gcfmGetPlayerCollection()); } } if (element.id === 'gcfm-paginator-prev') { gcfmPlayerBodyChange(false, gcfmGetPrevPage(), gcfmGetPlayerStyle(), false); } if (element.id === 'gcfm-paginator-next') { gcfmPlayerBodyChange(false, gcfmGetNextPage(), gcfmGetPlayerStyle(), false); } if (element.classList.contains('gcfm-paginator-button')) { let pageNumber = element.getAttribute('data-page'); gcfmPlayerBodyChange(false, pageNumber, gcfmGetPlayerStyle(), false); } if (element.id === 'gcfm-close-video') { gcfmCloseVideo(); } /* Episode play button in the feed view */ if (element.classList.contains('gcfm-button-episode-play')) { gcfmQueueClear(); let playTriggerNode = element; gcfmPlayMedia(playTriggerNode); let isLive = playTriggerNode.getAttribute('data-live'); if (isLive && isLive == 1) { return; } /* Start playing the clicked episode and add any other episodes after it to the queue */ episodesList = gcfmFindElementsByQuery('#gcfm-body .gcfm-button-episode-play', true); var isQueueing = false; for (let episode of episodesList) { if (isQueueing) { gcfmQueueAddEpisode(episode); } if (episode.id == playTriggerNode.id) { isQueueing = true; } if (episode.getAttribute('data-live') == 1 && isQueueing) { break; } } } /* Full screen audio controls */ if (element.id === 'gcfm-fullscreen-playpause') { gcfmFindElementById('gcfm-audio-control-playpause').click(); } if (element.id === 'gcfm-fullscreen-forward') { gcfmFindElementById('gcfm-audio-control-forward').click(); } if (element.id === 'gcfm-fullscreen-back') { gcfmFindElementById('gcfm-audio-control-back').click(); } /* Audio control bar play pause toggle button */ if (element.id === 'gcfm-audio-control-playpause') { let lgAudioPlayer = gcfmFindElementById('gcfm-player-audio'); if (lgAudioPlayer.currentSrc === '') { episodesList = gcfmFindElementsByQuery('#gcfm-player-container .gcfm-button-episode-play', true); if (episodesList.length > 0) { episodesList[0].click(); } else { alert('To listen to a program, please select it from the program grid or search for it using the magnifying glass icon.'); } } else { if (lgAudioPlayer.paused) { gcfmResumeMedia(); } else { gcfmPauseMedia(); } } } /* Audio control bar jump ahead button */ if (element.id === 'gcfm-audio-control-forward') { let lgAudioPlayer = gcfmFindElementById('gcfm-player-audio'); if (lgAudioPlayer.readyState >= 4) { lgAudioPlayer.currentTime = lgAudioPlayer.currentTime + 30; } } /* Audio control bar jump backward button */ if (element.id === 'gcfm-audio-control-back') { let lgAudioPlayer = gcfmFindElementById('gcfm-player-audio'); if (lgAudioPlayer.readyState >= 4) { lgAudioPlayer.currentTime = lgAudioPlayer.currentTime - 10; } } /* Program header page show more description toggle */ if (element.id === 'gcfm-player-description-show-more') { if (element.getAttribute('data-showstate') == "less") { let description = gcfmFindElementById('gcfm-player-description-full').textContent; gcfmFindElementById('gcfm-player-description-text').textContent = description; element.textContent = 'show less'; element.setAttribute('data-showstate', 'more'); } else { let description = gcfmFindElementById('gcfm-player-description-truncated').textContent; gcfmFindElementById('gcfm-player-description-text').textContent = description; element.textContent = 'show more'; element.setAttribute('data-showstate', 'less'); } } /* Player feed view body show more episodes */ if (element.id === 'gcfm-show-more-episodes') { let episodes = gcfmFindElementsByClassName('gcfm-episode-list-item'); [].forEach.call(episodes, function (el) { el.classList.remove("hidden"); }); gcfmFindElementById('gcfm-show-more-episodes-item').remove(); } /* Close modals */ if (element.classList.contains('gcfm-modal-close')) { let modals = gcfmFindElementsByClassName('gcfm-modal'); [].forEach.call(modals, function (modal) { modal.classList.add('hidden'); }); } /* Share button in the share modal */ if (element.id === 'gcfm-share-modal-submit') { let modal = gcfmFindElementById('gcfm-share-modal'); let shareTriggerNode = gcfmFindElementById(modal.getAttribute('data-share-trigger-node-id')); /* Get the user supplied data */ let userMessage = gcfmFindElementById('gcfm-share-modal-message').value.trim(); let userName = gcfmFindElementById('gcfm-share-modal-name').value.trim(); /* Assemble the destination url that the receiver of this share will be sent to */ let shareEpisodeTitle = shareTriggerNode.getAttribute('data-episodetitle'); let shareEpisodeId = shareTriggerNode.getAttribute('data-episodeid'); var shareDestinationUrl = new URL(gcfmGetCleanUrl()); shareDestinationUrl.searchParams.append('gcfm-fid', shareTriggerNode.getAttribute('data-feedid')); let episodeId = shareTriggerNode.getAttribute('data-episodeid'); if (episodeId && episodeId !== '') { shareDestinationUrl.searchParams.append('gcfm-eid', episodeId); } shareDestinationUrl.searchParams.append('gcfm-shared', 'true'); if (gcfmFindElementById('gcfm-share-modal-timestamp').checked) { let startAt = Math.floor(gcfmFindElementById('gcfm-player-audio').currentTime); shareDestinationUrl.searchParams.append('gcfm-ts', startAt); gcfmFindElementById('gcfm-share-modal-timeshow').value = gcfmFormatCurrentSecondsAsTime(Math.floor(startAt)); } shareDestinationUrl.hash = 'gcfm-player-container'; /* Assemble the share tracking url that will then forward the receiver to the final destination */ let shareTrackUrlString = gcfmFindElementById('gcfm-share-modal').getAttribute('data-shareurl'); var shareTrackUrl = new URL(shareTrackUrlString); shareTrackUrl.searchParams.append('dest_url', shareDestinationUrl.href); shareTrackUrl.searchParams.append('did', gcfmGetPlayerDid()); shareTrackUrl.searchParams.append('pid', shareTriggerNode.getAttribute('data-playerid')); shareTrackUrl.searchParams.append('fid', shareTriggerNode.getAttribute('data-feedid')); if (shareEpisodeId && shareEpisodeId !== '') { shareTrackUrl.searchParams.append('title', shareEpisodeTitle); } else { shareTrackUrl.searchParams.append('title', 'n/a'); } if (userMessage.trim()) { shareTrackUrl.searchParams.append('message', userMessage); } if (userName.trim()) { shareTrackUrl.searchParams.append('name', userName); } if (gcfmFindElementById('gcfm-share-modal-timestamp').checked) { let startAt = Math.floor(gcfmFindElementById('gcfm-player-audio').currentTime); shareTrackUrl.searchParams.append('ts', startAt); } /* Set each share to link to be the constructed share tracking url we just made */ gcfmFindElementById('gcfm-share-modal-to-mobile').setAttribute( 'data-shareurl', shareTrackUrlString + '/' + gcfmBase64urlEncode(shareTrackUrl.href) ); gcfmFindElementById('gcfm-share-modal-to-mobile').setAttribute( 'data-sharetext', shareTrackUrlString + '/' + gcfmBase64urlEncode(shareTrackUrl.href) ); gcfmFindElementById('gcfm-share-modal-to-link').setAttribute( 'data-shareurl', shareTrackUrlString + '/' + gcfmBase64urlEncode(shareTrackUrl.href) ); gcfmFindElementById('gcfm-share-modal-to-facebook').setAttribute( 'href', 'https://www.facebook.com/sharer/sharer.php?u=' + encodeURIComponent(shareTrackUrlString + '/' + gcfmBase64urlEncode(shareTrackUrl.href)) ); gcfmFindElementById('gcfm-share-modal-to-x').setAttribute( 'href', 'https://twitter.com/intent/tweet?url=' + encodeURIComponent(shareTrackUrlString + '/' + gcfmBase64urlEncode(shareTrackUrl.href)) + '&text=' + encodeURIComponent(userMessage) + '&hashtags=godcaster' ); var emailSubject = userName + ' shared "' + shareEpisodeTitle + '"'; if (!userName.trim()) { emailSubject = 'Sharing "' + shareEpisodeTitle + '" with you...'; } var emailBody = userName + ' wrote: "' + userMessage + '"'; if (!userMessage.trim() && !userName.trim()) { emailBody = 'Someone shared "' + shareEpisodeTitle + '" with you...'; } else if (!userMessage.trim()) { emailBody = userName + ' shared "' + shareEpisodeTitle + '" with you...'; } else if (!userName.trim()) { emailBody = 'The sharer wrote: "' + userMessage + '"'; } gcfmFindElementById('gcfm-share-modal-to-email').setAttribute( 'href', 'mailto:?subject=' + encodeURIComponent(emailSubject) + '&body=' + encodeURIComponent(emailBody) + '%0D%0A%0D%0A' + encodeURIComponent(shareTrackUrlString + '/' + gcfmBase64urlEncode(shareTrackUrl.href)) ); /* Set up stage 2 of the sharing modal to show the destinations */ gcfmFindElementById('gcfm-share-modal-destinations').classList.remove('hidden'); gcfmFindElementById('gcfm-share-modal-submit').classList.add('hidden'); gcfmFindElementById('gcfm-share-modal-name-section').classList.add('hidden'); gcfmFindElementById('gcfm-share-modal-message-section').classList.add('hidden'); gcfmFindElementById('gcfm-share-modal-timestamp-section').classList.add('hidden'); } if (element.id === 'gcfm-share-modal-to-link') { gcfmCopyHrefToClipboard('gcfm-share-modal-to-link'); return false; } if (element.id === 'gcfm-share-modal-to-mobile') { let shareHref = gcfmFindElementById('gcfm-share-modal-to-mobile').getAttribute('data-shareurl'); let shareText = gcfmFindElementById('gcfm-share-modal-to-mobile').getAttribute('data-sharetext'); navigator.share( { url: shareHref, text: shareText, } ) return false; } /* Share button in the feed view */ if (element.classList.contains('gcfm-button-episode-share')) { let shareTriggerNode = element; let shareTimestamp = gcfmFindElementById('gcfm-share-modal-timestamp'); var modal = gcfmFindElementById('gcfm-share-modal'); modal.setAttribute('data-share-trigger-node-id', shareTriggerNode.id); shareTimestamp.disabled = true; if (gcfmFindElementById('gcfm-player-audio').currentTime > 0) { shareTimestamp.disabled = false; } gcfmFindElementById('gcfm-share-modal-timestamp-section').classList.remove('hidden'); modal.classList.remove('hidden'); return false; } if (element.id === 'gcfm-share-modal-close') { gcfmFindElementById('gcfm-share-modal-to-link').removeAttribute('href'); gcfmFindElementById('gcfm-share-modal-destinations').classList.add('hidden'); gcfmFindElementById('gcfm-share-modal-message').value = ''; gcfmFindElementById('gcfm-share-modal-timestamp').checked = false; gcfmFindElementById('gcfm-share-modal-timeshow').value = ''; gcfmFindElementById('gcfm-share-modal-destinations').classList.add('hidden'); gcfmFindElementById('gcfm-share-modal-submit').classList.remove('hidden'); gcfmFindElementById('gcfm-share-modal-name-section').classList.remove('hidden'); gcfmFindElementById('gcfm-share-modal-message-section').classList.remove('hidden'); gcfmFindElementById('gcfm-share-modal-timestamp-section').classList.remove('hidden'); } /* Episode link */ if (element.classList.contains('gcfm-button-episode-link')) { let feedId = element.getAttribute('data-feedid'); let episodeId = element.getAttribute('data-episodeid'); /* Assemble the destination url that to copy and attach it to the button */ var linkDestinationUrl = new URL(gcfmGetCleanUrl()); linkDestinationUrl.searchParams.append('gcfm-fid', feedId); linkDestinationUrl.searchParams.append('gcfm-eid', episodeId); linkDestinationUrl.hash = 'gcfm-player-container'; element.setAttribute('data-shareurl', linkDestinationUrl.href); gcfmCopyHrefToClipboard(element.id); return false; } /* Program page stuff */ if (element.id === 'gcfm-program-page-link-button') { let programPageActive = gcfmFindElementById('gcfm-program-page-active'); if (programPageActive) { let programId = programPageActive.getAttribute('data-programid'); /* Assemble the destination url that to copy and attach it to the button */ var linkDestinationUrl = new URL(gcfmGetCleanUrl()); linkDestinationUrl.searchParams.append('gcfm-fid', programId); linkDestinationUrl.hash = 'gcfm-player-container'; element.setAttribute('data-shareurl', linkDestinationUrl.href); gcfmCopyHrefToClipboard(element.id); } return false; } if (element.id === 'gcfm-program-page-share-button') { let shareTriggerNode = element; var modal = gcfmFindElementById('gcfm-share-modal'); modal.setAttribute('data-share-trigger-node-id', shareTriggerNode.id); gcfmFindElementById('gcfm-share-modal-timestamp-section').classList.add('hidden'); modal.classList.remove('hidden'); return false; } /* Follow button in the player */ if (element.id === 'gcfm-follow-player-feed') { fetch(gcfmGetActionUrl() + '?' + 'action=follow' + '&did=' + gcfmGetPlayerDid() + '&pid=' + gcfmGetPlayerId() ); var lgModal = gcfmFindElementById('gcfm-follow-modal'); var lgPlatform = gcfmGetPlatform(); let links = lgModal.getElementsByClassName('gcfm-follow-target'); for (let i = 0; i < links.length; i++) { if (links[i].classList.contains(lgPlatform)) { links[i].classList.remove('hidden'); } } lgModal.classList.remove('hidden'); return false; } if (element.id === 'gcfm-follow-modal-close') { gcfmFindElementById('gcfm-follow-modal').classList.add('hidden'); } } function gcfmCloseVideo() { let lgVideoPanel = gcfmFindElementById('gcfm-video-panel'); let lgVideoEmbed = gcfmFindElementById('gcfm-player-videoembed'); if (lgVideoPanel.classList.contains('hidden')) { return false; } let lgVideoPlayer = gcfmFindElementById('gcfm-player-video'); let lgVideoPlayerSource = gcfmFindElementById('gcfm-player-video-source'); lgVideoPlayer.pause(); lgVideoPlayerSource.setAttribute('src', ''); lgVideoPlayerSource.setAttribute('type', ''); lgVideoPlayer.classList.add('hidden'); lgVideoEmbed.innerHTML = ''; lgVideoPanel.classList.add('hidden'); lgVideoEmbed.classList.add('hidden'); return false; } function gcfmResumeMedia() { let lgAudioPlayer = gcfmFindElementById('gcfm-player-audio'); let playTriggerNode = gcfmFindElementById('' + lgAudioPlayer.getAttribute('episode')); var lgIsLive = 0; if (playTriggerNode) { lgIsLive = playTriggerNode.getAttribute('data-live'); } if (lgIsLive == 1) { gcfmPlayMedia(playTriggerNode, true); return true; } gcfmFindElementById('gcfm-audio-control-slider').readOnly = false; gcfmFindElementById('gcfm-fullscreen-slider').readOnly = false; if (lgAudioPlayer.readyState === 4) { lgAudioPlayer.play(); fetch(gcfmGetActionUrl() + '?' + 'action=resume' + '&did=' + gcfmGetPlayerDid() + '&pid=' + gcfmGetPlayerId() + '&fid=' + lgAudioPlayer.getAttribute('data-feedtitle') + '&eid=' + lgAudioPlayer.getAttribute('data-title') + '&ts=' + Math.floor(lgAudioPlayer.currentTime) ); let elEpisode = gcfmFindElementById(lgAudioPlayer.getAttribute('episode')); if (elEpisode) { elEpisode.getElementsByClassName('play-icon')[0].classList.add('hidden'); elEpisode.getElementsByClassName('pause-icon')[0].classList.remove('hidden'); elEpisode.getElementsByClassName('loading-icon')[0].classList.add('hidden'); } gcfmFindElementById('gcfm-audio-control-play-icon').classList.add('hidden'); gcfmFindElementById('gcfm-fullscreen-play-icon').classList.add('hidden'); gcfmFindElementById('gcfm-audio-control-pause-icon').classList.remove('hidden'); gcfmFindElementById('gcfm-fullscreen-pause-icon').classList.remove('hidden'); gcfmFindElementById('gcfm-audio-control-loading-icon').classList.add('hidden'); gcfmFindElementById('gcfm-fullscreen-loading-icon').classList.add('hidden'); } } function gcfmPlayMedia(playTriggerNode, force) { let lgAudioPlayer = gcfmFindElementById('gcfm-player-audio'); let lgAudioPlayerSource = gcfmFindElementById('gcfm-player-audio-source'); var lgAudioPlayerEpisodeId = null; lgAudioPlayerEpisodeId = lgAudioPlayer.getAttribute('episode'); let enclosureUrl = playTriggerNode.getAttribute('data-enclosureurl'); urlToLoad = gcfmBuildEnclosureUrlWithULID(enclosureUrl); urlMimeType = playTriggerNode.getAttribute('data-enclosuretype'); let lgIsLive = playTriggerNode.getAttribute('data-live'); /* YouTube video embed support */ if (urlToLoad.indexOf('youtube.com/v') > -1 && urlMimeType == 'video/youtube-embed') { let lgVideoPanel = gcfmFindElementById('gcfm-video-panel'); let lgVideoEmbed = gcfmFindElementById('gcfm-player-videoembed'); let lgVideoPlayerSource = gcfmFindElementById('gcfm-player-video-source'); let lgVideoPlayer = gcfmFindElementById('gcfm-player-video'); ytEmbedUrl = gcfmBuildEnclosureUrlYTEmbed(enclosureUrl); lgVideoEmbed.innerHTML = ''; lgVideoPlayer.pause(); lgVideoPlayer.classList.add('hidden'); lgVideoPlayerSource.setAttribute('src', ''); lgVideoPlayerSource.setAttribute('type', ''); lgVideoPanel.classList.remove('hidden'); gcfmPauseMedia(); if (gcfmGetControlsPosition() == 2) { gcfmFindElementById('gcfm-audio-bar').classList.add('hidden'); } lgVideoEmbed.classList.remove('hidden'); return false; } else { gcfmCloseVideo(); } /* Video support */ if (urlToLoad.indexOf('.mp4') > -1 && (urlMimeType.indexOf('octet') > -1 || urlMimeType.indexOf('video') > -1)) { let lgVideoPanel = gcfmFindElementById('gcfm-video-panel'); let lgVideoPlayer = gcfmFindElementById('gcfm-player-video'); let lgVideoPlayerSource = gcfmFindElementById('gcfm-player-video-source'); lgVideoPlayerSource.setAttribute('src', urlToLoad); lgVideoPlayerSource.setAttribute('type', 'video/mp4'); lgVideoPanel.classList.remove('hidden'); gcfmPauseMedia(); if (gcfmGetControlsPosition() == 2) { gcfmFindElementById('gcfm-audio-bar').classList.add('hidden'); } lgVideoPlayer.classList.remove('hidden'); lgVideoPlayer.load(); lgVideoPlayer.play(); return false; } else { gcfmCloseVideo(); } /* If this is a live stream, disable the progress slider */ if (lgIsLive == 1) { gcfmFindElementById('gcfm-audio-control-slider').readOnly = true; gcfmFindElementById('gcfm-fullscreen-slider').readOnly = true; } else { gcfmFindElementById('gcfm-audio-control-slider').readOnly = false; gcfmFindElementById('gcfm-fullscreen-slider').readOnly = false; } if (playTriggerNode.id == lgAudioPlayerEpisodeId && !force) { gcfmFindElementById('gcfm-audio-control-playpause').click(); return false; } /* If the same episode is clicked again then just treat it as a play/pause toggle */ /* Unless it's a live stream which needs to be torn down and restarted */ if (lgAudioPlayerSource.getAttribute('src') == urlToLoad && !force) { gcfmFindElementById('gcfm-audio-control-playpause').click(); return false; } /* Set the media url to load */ lgAudioPlayerSource.setAttribute('src', urlToLoad); lgAudioPlayerSource.setAttribute('type', playTriggerNode.getAttribute('data-enclosuretype')); /* Display the initial media metadata */ gcfmFindElementById('gcfm-audio-control-episode-title').innerHTML = playTriggerNode.getAttribute('data-title'); gcfmFindElementById('gcfm-fullscreen-title').innerHTML = playTriggerNode.getAttribute('data-title'); gcfmFindElementById('gcfm-fullscreen-feedtitle').innerHTML = playTriggerNode.getAttribute('data-feedtitle'); gcfmFindElementById('gcfm-audio-control-image').setAttribute('src', playTriggerNode.getAttribute('data-imageurl')); gcfmFindElementById('gcfm-fullscreen-art').setAttribute('src', playTriggerNode.getAttribute('data-imageurl')); /* UI transition */ gcfmHideAllEpisodePauseIcons(); gcfmSetEpisodeLoadingIcon(playTriggerNode); /* Load the media */ lgAudioPlayer.load(); /* Ping the mothership for stats */ fetch(gcfmGetActionUrl() + '?' + 'action=play' + '&did=' + gcfmGetPlayerDid() + '&pid=' + gcfmGetPlayerId() + '&fid=' + encodeURIComponent(playTriggerNode.getAttribute('data-feedtitle')) + '&eid=' + encodeURIComponent(playTriggerNode.getAttribute('data-title')) + '&ts=' + Math.floor(lgAudioPlayer.currentTime) ); /* Save a reference to the triggering episode element in the audio element so we can have it later */ lgAudioPlayer.setAttribute('episode', playTriggerNode.id); lgAudioPlayer.setAttribute('data-feedtitle', playTriggerNode.getAttribute('data-feedtitle')); lgAudioPlayer.setAttribute('data-title', playTriggerNode.getAttribute('data-title')); /* Set metadata for mobile device lock screens, carplay and android auto */ if ('mediaSession' in navigator) { let lgPlayerTitle = gcfmGetPlayerTitle(); var mediaTitle = playTriggerNode.getAttribute('data-title'); if (lgPlayerTitle !== '') { mediaTitle = lgPlayerTitle + ' - ' + mediaTitle; } navigator.mediaSession.metadata = new MediaMetadata({ title: 'Loading...', artist: playTriggerNode.getAttribute('data-feedtitle'), album: lgPlayerTitle, artwork: [ { src: playTriggerNode.getAttribute('data-imageurl') }, ] }); navigator.mediaSession.setActionHandler('play', function () { gcfmResumeMedia(); }); navigator.mediaSession.setActionHandler('pause', function () { gcfmPauseMedia(); }); navigator.mediaSession.setActionHandler('seekbackward', function () { gcfmFindElementById('gcfm-audio-control-back').click(); }); navigator.mediaSession.setActionHandler('seekforward', function () { gcfmFindElementById('gcfm-audio-control-forward').click(); }); navigator.mediaSession.setActionHandler('previoustrack', function () { gcfmFindElementById('gcfm-audio-control-back').click(); }); navigator.mediaSession.setActionHandler('nexttrack', function () { gcfmFindElementById('gcfm-audio-control-forward').click(); }); } /* Wait for the media to load before playing and changing state */ cgGcfmLoadAttempts = 0; cgGcfmPlayAttemptInterval = setInterval(function () { let lgAudioPlayer = gcfmFindElementById('gcfm-player-audio'); let lgAudioPlayerSource = gcfmFindElementById('gcfm-player-audio-source'); let playTriggerNode = gcfmFindElementById(lgAudioPlayer.getAttribute('episode')); if (lgAudioPlayer.readyState >= 3) { let lgIsLive = playTriggerNode.getAttribute('data-live'); let timeStartAt = playTriggerNode.getAttribute('data-startat'); let timeLastStored = localStorage.getItem(lgAudioPlayerSource.getAttribute('src')); if (timeStartAt > 0 && lgIsLive == 0) { lgAudioPlayer.currentTime = timeStartAt; } else if (timeLastStored > 0 && lgIsLive == 0) { lgAudioPlayer.currentTime = timeLastStored; } else { lgAudioPlayer.currentTime = 0; } let lgPlayerTitle = gcfmGetPlayerTitle(); var mediaTitle = playTriggerNode.getAttribute('data-title'); if (lgPlayerTitle !== '') { mediaTitle = lgPlayerTitle + ' - ' + mediaTitle; } if ('mediaSession' in navigator) { navigator.mediaSession.metadata.title = mediaTitle; } lgAudioPlayer.play(); gcfmFindElementById('gcfm-audio-control-slider').removeAttribute('disabled'); gcfmFindElementById('gcfm-fullscreen-slider').removeAttribute('disabled'); controlsPosition = gcfmGetControlsPosition(); if (controlsPosition == 2) { gcfmPlayerContainer.style.marginBottom = '60px'; } if (!gcfmIsFullScreen()) { gcfmFindElementById('gcfm-audio-bar').classList.remove('hidden'); } clearInterval(cgGcfmPlayAttemptInterval); gcfmFindElementById('gcfm-audio-control-play-icon').classList.add('hidden'); gcfmFindElementById('gcfm-fullscreen-play-icon').classList.add('hidden'); gcfmFindElementById('gcfm-audio-control-pause-icon').classList.remove('hidden'); gcfmFindElementById('gcfm-fullscreen-pause-icon').classList.remove('hidden'); gcfmFindElementById('gcfm-audio-control-loading-icon').classList.add('hidden'); gcfmFindElementById('gcfm-fullscreen-loading-icon').classList.add('hidden'); /* TODO: This will need to change later for the tailwind build pipeline */ gcfmFindElementById('gcfm-audio-bar-wrapper').classList.remove('opacity-25'); lgAudioPlayer.addEventListener('timeupdate', gcfmUpdateTrackTime); lgAudioPlayer.addEventListener('ended', gcfmAudioTrackEnded); } else if (cgGcfmLoadAttempts >= 100) { alert("Could not load the selected media to play."); clearInterval(cgGcfmPlayAttemptInterval); lgAudioPlayerSource.setAttribute('src', ''); gcfmHideAllEpisodeLoadingIcons(); } else { cgGcfmLoadAttempts = cgGcfmLoadAttempts + 1; } }, 300); } function gcfmPauseMedia() { let lgAudioPlayer = gcfmFindElementById('gcfm-player-audio'); if (!lgAudioPlayer.paused) { lgAudioPlayer.pause(); } gcfmHideAllEpisodePauseIcons(); gcfmFindElementById('gcfm-audio-control-pause-icon').classList.add('hidden'); gcfmFindElementById('gcfm-fullscreen-pause-icon').classList.add('hidden'); gcfmFindElementById('gcfm-audio-control-play-icon').classList.remove('hidden'); gcfmFindElementById('gcfm-fullscreen-play-icon').classList.remove('hidden'); gcfmFindElementById('gcfm-audio-control-loading-icon').classList.add('hidden'); gcfmFindElementById('gcfm-fullscreen-loading-icon').classList.add('hidden'); return true; } function gcfmGetActionUrl() { return gcfmFindElementById('gcfm-player-app').getAttribute('data-actionurl'); } function gcfmUpdateTrackTime(event) { let currTimeDiv = gcfmFindElementById('gcfm-audio-control-current'); let currTimeDivFs = gcfmFindElementById('gcfm-fullscreen-current'); let durationDiv = gcfmFindElementById('gcfm-audio-control-duration'); let durationDivFs = gcfmFindElementById('gcfm-fullscreen-duration'); let currTime = Math.floor(event.target.currentTime); let duration = Math.floor(event.target.duration); gcfmSetProgressBarPosition(currTime, duration); gcfmSetFullScreenProgressBarPosition(currTime, duration); currTimeDiv.innerHTML = gcfmFormatCurrentSecondsAsTime(currTime); currTimeDivFs.innerHTML = gcfmFormatCurrentSecondsAsTime(currTime); /* Write the current time to localStorage every 5 seconds */ if (currTime > 0 && currTime % 5 == 0) { if (!cgGcfmTimeWritten) { let lgAudioPlayer = gcfmFindElementById('gcfm-player-audio'); let lgAudioPlayerSource = gcfmFindElementById('gcfm-player-audio-source'); localStorage.setItem( lgAudioPlayerSource.getAttribute('src'), lgAudioPlayer.currentTime ); cgGcfmTimeWritten = true; } } else if (cgGcfmTimeWritten) { cgGcfmTimeWritten = false; } if (currTime >= duration) { gcfmHideAllEpisodePauseIcons(); gcfmFindElementById('gcfm-audio-control-pause-icon').classList.add('hidden'); gcfmFindElementById('gcfm-fullscreen-pause-icon').classList.add('hidden'); gcfmFindElementById('gcfm-audio-control-play-icon').classList.remove('hidden'); gcfmFindElementById('gcfm-fullscreen-play-icon').classList.remove('hidden'); gcfmFindElementById('gcfm-audio-control-loading-icon').classList.add('hidden'); gcfmFindElementById('gcfm-fullscreen-loading-icon').classList.add('hidden'); } gcfmUpdateEpisodeTiles(event); durationDiv.innerHTML = gcfmFormatDurationSecondsAsTime(duration); durationDivFs.innerHTML = gcfmFormatDurationSecondsAsTime(duration); } function gcfmAudioTrackEnded(event) { /* TODO: when play is first clicked, there needs to be a hidden queue of all the episodes visible so that */ /* TODO: we can pull from that list here to play the next one that was in the list at that time? */ /* TODO: live streams need this disabled, as I'm not sure how this event behaves in that context */ let lgAudioPlayer = gcfmFindElementById('gcfm-player-audio'); let lgAudioPlayerSource = gcfmFindElementById('gcfm-player-audio-source'); localStorage.removeItem(lgAudioPlayerSource.getAttribute('src')); let nextEpisode = gcfmQueuePop(); if (nextEpisode) { gcfmPlayMedia(nextEpisode, true); } } function gcfmQueueClear() { lgPlayerQueue = gcfmFindElementById('gcfm-player-queue'); lgPlayerQueue.innerHTML = ''; } function gcfmQueueIsEmpty() { lgPlayerQueue = gcfmFindElementById('gcfm-player-queue'); if (lgPlayerQueue.getElementsByTagName('li').length > 0) { return false; } return true; } function gcfmQueueAddEpisode(elEpisode) { lgPlayerQueue = gcfmFindElementById('gcfm-player-queue'); let episode = elEpisode.cloneNode(true); episode.id = 'q_' + episode.id; episode.setAttribute('data-qid', elEpisode.id); episode.className = ''; lgPlayerQueue.appendChild(episode); return true; } function gcfmQueueRemoveEpisode(episodeId) { let episode = gcfmFindElementById('gcfm-player-queue #q_' + episodeId); if (episode) { episode.remove(); } } function gcfmQueuePop() { let nowPlaying = gcfmFindElementById('gcfm-player-queue-nowplaying'); let episodes = gcfmPlayerContainer.querySelectorAll('#gcfm-player-queue > div'); if (episodes.length > 0) { let episode = episodes[0].cloneNode(true); nowPlaying.innerHTML = ''; nowPlaying.appendChild(episode); episodes[0].remove(); return episode; } return null; } function gcfmFormatDurationSecondsAsTime(secs) { if (secs == Infinity) { return 'Streaming'; } if (isNaN(secs)) { return '00:00'; } var hr = Math.floor(secs / 3600); var min = Math.floor((secs - (hr * 3600)) / 60); var sec = Math.floor(secs - (hr * 3600) - (min * 60)); if (min < 10) { min = "0" + min; } if (sec < 10) { sec = "0" + sec; } if (isNaN(hr)) { hr = 0; } if (isNaN(min)) { min = "00"; } if (isNaN(sec)) { sec = "00"; } if (hr > 0) { return hr + ':' + min + ':' + sec; } return min + ':' + sec; } function gcfmFormatCurrentSecondsAsTime(secs) { if (isNaN(secs)) { return '00:00'; } var hr = Math.floor(secs / 3600); var min = Math.floor((secs - (hr * 3600)) / 60); var sec = Math.floor(secs - (hr * 3600) - (min * 60)); if (min < 10) { min = "0" + min; } if (sec < 10) { sec = "0" + sec; } if (isNaN(hr)) { hr = 0; } if (isNaN(min)) { min = "00"; } if (isNaN(sec)) { sec = "00"; } if (hr > 0) { return hr + ':' + min + ':' + sec; } return min + ':' + sec; } function gcfmHideAllEpisodePauseIcons() { let pauseIcons = gcfmFindElementsByClassName('pause-icon'); for (i = 0; i < pauseIcons.length; i++) { pauseIcons[i].classList.add('hidden'); pauseIcons[i].parentNode.getElementsByClassName('play-icon')[0].classList.remove('hidden'); pauseIcons[i].parentNode.getElementsByClassName('loading-icon')[0].classList.add('hidden'); } } function gcfmHideAllEpisodeLoadingIcons() { let loadingIcons = gcfmFindElementsByClassName('loading-icon'); for (i = 0; i < loadingIcons.length; i++) { loadingIcons[i].classList.add('hidden'); loadingIcons[i].parentNode.getElementsByClassName('play-icon')[0].classList.remove('hidden'); loadingIcons[i].parentNode.getElementsByClassName('pause-icon')[0].classList.add('hidden'); } } function gcfmSetEpisodePlayingIcon(elEpisode) { elEpisode.getElementsByClassName('play-icon')[0].classList.add('hidden'); elEpisode.getElementsByClassName('pause-icon')[0].classList.remove('hidden'); elEpisode.getElementsByClassName('loading-icon')[0].classList.add('hidden'); } function gcfmSetEpisodeLoadingIcon(elEpisode) { elEpisode.getElementsByClassName('play-icon')[0].classList.add('hidden'); elEpisode.getElementsByClassName('pause-icon')[0].classList.add('hidden'); elEpisode.getElementsByClassName('loading-icon')[0].classList.remove('hidden'); gcfmFindElementById('gcfm-audio-control-play-icon').classList.add('hidden'); gcfmFindElementById('gcfm-fullscreen-play-icon').classList.add('hidden'); gcfmFindElementById('gcfm-audio-control-pause-icon').classList.add('hidden'); gcfmFindElementById('gcfm-fullscreen-pause-icon').classList.add('hidden'); gcfmFindElementById('gcfm-audio-control-loading-icon').classList.remove('hidden'); gcfmFindElementById('gcfm-fullscreen-loading-icon').classList.remove('hidden'); } function gcfmSetEpisodePausedIcon(elEpisode) { elEpisode.getElementsByClassName('play-icon')[0].classList.add('hidden'); elEpisode.getElementsByClassName('pause-icon')[0].classList.remove('hidden'); elEpisode.getElementsByClassName('loading-icon')[0].classList.add('hidden'); } function gcfmUpdateEpisodeTiles(event) { if (!event.target.paused) { let elementId = event.target.getAttribute('episode'); if (elementId) { let elEpisode = gcfmFindElementById(elementId); if (elEpisode) { elEpisode.getElementsByClassName('play-icon')[0].classList.add('hidden'); elEpisode.getElementsByClassName('pause-icon')[0].classList.remove('hidden'); elEpisode.getElementsByClassName('loading-icon')[0].classList.add('hidden'); let qElementId = elEpisode.getAttribute('data-qid'); if (qElementId) { let elEpisodeInQueue = gcfmFindElementById(qElementId); if (elEpisodeInQueue) { elEpisodeInQueue.getElementsByClassName('play-icon')[0].classList.add('hidden'); elEpisodeInQueue.getElementsByClassName('pause-icon')[0].classList.remove('hidden'); elEpisodeInQueue.getElementsByClassName('loading-icon')[0].classList.add('hidden'); } } } } } } function gcfmGetTouches(evt) { return evt.touches; } function gcfmHandleTouchStart(evt) { const firstTouch = gcfmGetTouches(evt)[0]; cgGcfmXDown = firstTouch.clientX; cgGcfmYDown = firstTouch.clientY; } function gcfmHandleTouchMove(evt) { if (!cgGcfmXDown || !cgGcfmYDown) { return; } var xUp = evt.touches[0].clientX; var yUp = evt.touches[0].clientY; var xDiff = cgGcfmXDown - xUp; var yDiff = cgGcfmYDown - yUp; if (Math.abs(xDiff) > Math.abs(yDiff)) {/*most significant*/ if (xDiff > 0) { /* right swipe */ /* page forward through the program listing */ let bb = gcfmFindElementById('gcfm-back-button'); let np = gcfmFindElementById('gcfm-paginator-next'); if (!bb && gcfmIsTouchInBounds(evt.target) && np) { np.click(); } } else { /* left swipe */ /* return from feed page to program listing */ let bb = gcfmFindElementById('gcfm-back-button'); if (bb && gcfmIsTouchInBounds(evt.target)) { bb.click(); } else { /* page back through the program listing */ let pp = gcfmFindElementById('gcfm-paginator-prev'); if (pp && gcfmIsTouchInBounds(evt.target)) { pp.click(); } } } } else { if (yDiff > 0) { /* down swipe */ } else { /* up swipe */ } } /* reset values */ cgGcfmXDown = null; cgGcfmYDown = null; } function gcfmSetProgressBarPosition(position, duration) { let progressBar = gcfmFindElementById('gcfm-audio-control-slider'); if (progressBar.readOnly == true) { progressBar.value = 0; return; } if (duration > 0) { progressBar.max = duration; } progressBar.value = position; } function gcfmSetFullScreenProgressBarPosition(position, duration) { let progressBar = gcfmFindElementById('gcfm-fullscreen-slider'); if (progressBar.readOnly == true) { progressBar.value = 0; return; } if (duration > 0) { progressBar.max = duration; } progressBar.value = position; } function gcfmIsFullScreen() { return !gcfmFindElementById('gcfm-fullscreen-panel').classList.contains('hidden'); } function gcfmIsTouchInBounds(targetEl) { return ( ( targetEl.className.includes('gcfm-program') || targetEl.parentNode.className.includes('gcfm-program') || targetEl.className.includes('gcfm-episode') || targetEl.parentNode.className.includes('gcfm-episode') || targetEl.className.includes('gcfm-body') || targetEl.parentNode.className.includes('gcfm-body') ) && gcfmGetPlayerStyle() == 0 ) } function gcfmBuildEnclosureUrlWithULID(enclosureUrl) { var pciStatsGuid = localStorage.getItem(enclosureUrl) if (!pciStatsGuid) { pciStatsGuid = gcfmGenerateUUIDv4(); localStorage.setItem(enclosureUrl, pciStatsGuid) } let url = new URL(enclosureUrl); url.searchParams.append('_ulid', pciStatsGuid); url.searchParams.append('_from', 'godcaster.fm'); return url.toString(); } function gcfmBuildEnclosureUrlYTEmbed(enclosureUrl) { let ytEmbedUrl = enclosureUrl.replace('youtube.com/v/', 'youtube.com/embed/'); let url = new URL(ytEmbedUrl); url.searchParams.append('autoplay', 1); return url.toString(); } function gcfmGenerateUUIDv4() { var d = new Date().getTime(); var d2 = ((typeof performance !== 'undefined') && performance.now && (performance.now() * 1000)) || 0; return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16; if (d > 0) { r = (d + r) % 16 | 0; d = Math.floor(d / 16); } else { r = (d2 + r) % 16 | 0; d2 = Math.floor(d2 / 16); } return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16); }); } function gcfmDisplayErrorMessage(message) { alert(message); } function gcfmBase64urlEncode(urlToEncode) { let lgEnc = new TextEncoder(); let buffer = lgEnc.encode(urlToEncode); return btoa(Array.from(new Uint8Array(buffer), b => String.fromCharCode(b)).join('')) .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=+$/, ''); } function gcfmGetCleanUrl() { let hostingUrl = new URL(window.location.href); let params = new URLSearchParams(hostingUrl.search); params.delete('gcfm-shared'); params.delete('gcfm-style'); params.delete('gcfm-page'); params.delete('gcfm-did'); params.delete('gcfm-pid'); params.delete('gcfm-fid'); params.delete('gcfm-eid'); params.delete('gcfm-pwa'); params.delete('pwa'); hostingUrl.hash = ''; hostingUrl.search = params.toString(); return hostingUrl.toString(); } function gcfmCopyHrefToClipboard(linkId) { let link = gcfmFindElementById(linkId); if (!link) { return false; } let href = link.getAttribute('data-shareurl'); navigator.clipboard.writeText(href).then(() => { alert('Link copied to your clipboard.'); }).catch(err => { console.error('Failed to copy: ', err); }); } function gcfmDebounce(func, timeout = 500) { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => { func.apply(this, args); }, timeout); }; } function gcfmBodyIsLoading(status) { let loadingPanel = gcfmFindElementById('gcfm-body-loading-panel'); if (status) { /* Set the loading panel height */ let lgBody = gcfmFindElementById('gcfm-body-wrapper'); loadingPanel.style.height = lgBody.offsetHeight + 'px'; loadingPanel.style.width = lgBody.offsetWidth + 'px'; loadingPanel.classList.remove('hidden'); return; } loadingPanel.classList.add('hidden'); } /* Insert Slider Advance */ const gcfmInsertSliderAdvance = (inc) => { let gcfmInsertSliderSlides = gcfmFindElementsByClassName("gcfm-insert-slider-slide"); if (gcfmInsertSliderSlides.length == 0) { return false; } for (let i = 0; i < gcfmInsertSliderSlides.length; i++) { gcfmInsertSliderSlides[i].classList.add("hidden"); } gcfmInsertSliderCurrentIndex = (gcfmInsertSliderCurrentIndex + gcfmInsertSliderSlides.length + inc) % gcfmInsertSliderSlides.length; gcfmInsertSliderSlides[gcfmInsertSliderCurrentIndex].classList.remove("hidden"); }; setInterval(function () { gcfmInsertSliderAdvance(1); }, 7000); /* Load the player */ const gcfmDocumentObserver = new MutationObserver(function () { if (gcfmFindElementById('gcfm-player-container')) { console.log("GCFM: Attempting player load from observer..."); gcfmLoadPlayer(); } }); gcfmDocumentObserver.observe(document, {subtree: true, childList: true}); function gcfmLoadGodcasterWhenDOMReady() { if (document.readyState === 'loading') { console.log('GCFM: DOM still loading... ') } else if (document.readyState === 'interactive') { console.log('GCFM: DOM almost ready... ') } else { console.log('GCFM: DOM is "' + document.readyState + '"... ') console.log('GCFM: Player loading from readystatechange...') gcfmLoadPlayer(); if (!gcfmFindElementById('gcfm-player-container')) { console.log("GCFM: Player container not mounted yet. Waiting for observer..."); } } } document.addEventListener('readystatechange', function () { gcfmLoadGodcasterWhenDOMReady(); }); function gcfmIsolate(element, isolationElement) { if (!isolationElement) { isolationElement = document.createElement('div'); isolationElement.setAttribute('id', 'gcfm-isolator') isolationElement.setAttribute('style', 'width:100%;height:100%;z-index:99996;') isolationElement.attachShadow({mode: 'open'}); } element.parentElement.insertBefore(isolationElement, element); isolationElement.shadowRoot.appendChild(element); } function gcfmIsolateHidden(element, isolationElement) { if (!isolationElement) { isolationElement = document.createElement('div'); isolationElement.setAttribute('id', 'gcfm-isolator-hidden') isolationElement.setAttribute('style', 'width:100%;height:100%;z-index:99997;') isolationElement.attachShadow({mode: 'open'}); } element.parentElement.insertBefore(isolationElement, element); isolationElement.shadowRoot.appendChild(element); } function gcfmIsolateAudioBar(element, isolationElement) { if (!isolationElement) { isolationElement = document.createElement('div'); isolationElement.setAttribute('id', 'gcfm-isolator-audiobar') isolationElement.setAttribute('style', 'width:100%;height:100%;z-index:99997;') isolationElement.attachShadow({mode: 'open'}); } element.parentElement.insertBefore(isolationElement, element); isolationElement.shadowRoot.appendChild(element); } function gcfmFindElementById(idString) { let el = document.getElementById(idString); if (el) { return el; } let isolateRoot = document.getElementById('gcfm-isolator'); if (isolateRoot) { let isolateShadowRoot = isolateRoot.shadowRoot; el = isolateShadowRoot.getElementById(idString); if (el) { return el; } } let isolateAudioBarRoot = document.getElementById('gcfm-isolator-audiobar'); if (isolateAudioBarRoot) { let isolateAudioBarShadowRoot = isolateAudioBarRoot.shadowRoot; el = isolateAudioBarShadowRoot.getElementById(idString); if (el) { return el; } } let isolateHiddenRoot = document.getElementById('gcfm-isolator-hidden'); if (isolateHiddenRoot) { let isolateHiddenShadowRoot = isolateHiddenRoot.shadowRoot; el = isolateHiddenShadowRoot.getElementById(idString); if (el) { return el; } } if (gcfmPlayerContainer) { el = gcfmPlayerContainer.querySelector('#' + idString); if (el) { return el; } } if (gcfmAudioBar) { el = gcfmAudioBar.querySelector('#' + idString); if (el) { return el; } } if (gcfmHiddenElements) { el = gcfmHiddenElements.querySelector('#' + idString); if (el) { return el; } } return null; } function gcfmFindElementsByClassName(classString) { var els = document.getElementsByClassName(classString); let empty; if (els.length > 0) { return els; } else { empty = els; } let isolateRoot = document.getElementById('gcfm-isolator'); if (isolateRoot) { let isolateShadowRoot = isolateRoot.shadowRoot; let els = isolateShadowRoot.querySelectorAll('.' + classString); if (els.length > 0) { return els; } } let isolateAudioBarRoot = document.getElementById('gcfm-isolator-audiobar'); if (isolateAudioBarRoot) { let isolateAudioBarShadowRoot = isolateAudioBarRoot.shadowRoot; let els = isolateAudioBarShadowRoot.querySelectorAll('.' + classString); if (els.length > 0) { return els; } } let isolateHiddenRoot = document.getElementById('gcfm-isolator-hidden'); if (isolateHiddenRoot) { let isolateHiddenShadowRoot = isolateHiddenRoot.shadowRoot; let els = isolateHiddenShadowRoot.querySelectorAll('.' + classString); if (els.length > 0) { return els; } } if (gcfmPlayerContainer) { els = gcfmPlayerContainer.querySelectorAll('.' + classString); if (els.length > 0) { return els; } } if (gcfmAudioBar) { els = gcfmAudioBar.querySelectorAll('.' + classString); if (els.length > 0) { return els; } } if (gcfmHiddenElements) { els = gcfmHiddenElements.querySelectorAll('.' + classString); if (els.length > 0) { return els; } } return empty; } function gcfmFindElementsByQuery(queryString, all) { if (all) { var els = document.querySelectorAll(queryString); let empty; if (els.length > 0) { return els; } else { empty = els; } let isolateRoot = document.getElementById('gcfm-isolator'); if (isolateRoot) { let isolateShadowRoot = isolateRoot.shadowRoot; let els = isolateShadowRoot.querySelectorAll(queryString); if (els.length > 0) { return els; } } let isolateAudioBarRoot = document.getElementById('gcfm-isolator-audiobar'); if (isolateAudioBarRoot) { let isolateAudioBarShadowRoot = isolateAudioBarRoot.shadowRoot; let els = isolateAudioBarShadowRoot.querySelectorAll(queryString); if (els.length > 0) { return els; } } let isolateHiddenRoot = document.getElementById('gcfm-isolator-hidden'); if (isolateHiddenRoot) { let isolateHiddenShadowRoot = isolateHiddenRoot.shadowRoot; let els = isolateHiddenShadowRoot.querySelectorAll(queryString); if (els.length > 0) { return els; } } if (gcfmPlayerContainer) { els = gcfmPlayerContainer.querySelectorAll(queryString); if (els.length > 0) { return els; } } if (gcfmAudioBar) { els = gcfmAudioBar.querySelectorAll(queryString); if (els.length > 0) { return els; } } if (gcfmHiddenElements) { els = gcfmHiddenElements.querySelectorAll(queryString); if (els.length > 0) { return els; } } return empty; } var el = document.querySelector(queryString); if (el) { return el; } let isolateRoot = document.getElementById('gcfm-isolator'); if (isolateRoot) { let isolateShadowRoot = isolateRoot.shadowRoot; let el = isolateShadowRoot.querySelector(queryString); if (el) { return el; } } let isolateAudioBarRoot = document.getElementById('gcfm-isolator-audiobar'); if (isolateAudioBarRoot) { let isolateAudioBarShadowRoot = isolateAudioBarRoot.shadowRoot; let el = isolateAudioBarShadowRoot.querySelector(queryString); if (el) { return el; } } let isolateHiddenRoot = document.getElementById('gcfm-isolator-hidden'); if (isolateHiddenRoot) { let isolateHiddenShadowRoot = isolateHiddenRoot.shadowRoot; let el = isolateHiddenShadowRoot.querySelector(queryString); if (el) { return el; } } if (gcfmPlayerContainer) { el = gcfmPlayerContainer.querySelector(queryString); if (el) { return el; } } if (gcfmAudioBar) { el = gcfmAudioBar.querySelector(queryString); if (el) { return el; } } if (gcfmHiddenElements) { el = gcfmHiddenElements.querySelector(queryString); if (el) { return el; } } return null; }