diff --git a/app/assets/javascripts/initializers/initializePodcastPlayback.js b/app/assets/javascripts/initializers/initializePodcastPlayback.js index e548cee71..3a046a889 100644 --- a/app/assets/javascripts/initializers/initializePodcastPlayback.js +++ b/app/assets/javascripts/initializers/initializePodcastPlayback.js @@ -473,19 +473,9 @@ function initializePodcastPlayback() { } } - function handlePodcastMessages(mutation) { - if (mutation.type !== 'attributes') { - return; - } - - var message = {}; - try { - var messageData = getById('audiocontent').dataset.podcast; - message = JSON.parse(messageData); - } catch (e) { - console.log(e); // eslint-disable-line no-console - return; - } + function handlePodcastMessages(event) { + const message = JSON.parse(event.detail); + if (message.namespace !== 'podcast') { return } var currentState = currentAudioState(); switch (message.action) { @@ -499,41 +489,24 @@ function initializePodcastPlayback() { updateProgress(currentState.currentTime, currentState.duration, 100); break; default: - console.log('Unrecognized podcast message: ', message); // eslint-disable-line no-console + console.log('Unrecognized message: ', message); // eslint-disable-line no-console } saveMediaState(currentState); } - function addMutationObserver() { - var mutationObserver = new MutationObserver(function (mutations) { - mutations.forEach(function (mutation) { - handlePodcastMessages(mutation); - }); - }); - mutationObserver.observe(getById('audiocontent'), { attributes: true }); - } - // When Runtime.podcastMessage is undefined we need to execute web logic function initRuntime() { if (Runtime.isNativeIOS('podcast')) { deviceType = 'iOS'; - Runtime.podcastMessage = function (message) { - try { - window.webkit.messageHandlers.podcast.postMessage(message); - } catch (err) { - console.log(err.message); // eslint-disable-line no-console - } - }; } else if (Runtime.isNativeAndroid('podcastMessage')) { deviceType = 'Android'; - Runtime.podcastMessage = function (message) { - try { - AndroidBridge.podcastMessage(JSON.stringify(message)); - } catch (err) { - console.log(err.message); // eslint-disable-line no-console - } - }; + } + + if (deviceType !== 'web') { + Runtime.podcastMessage = (msg) => { + window.ForemMobile.injectNativeMessage('podcast', msg); + } } } @@ -560,7 +533,7 @@ function initializePodcastPlayback() { updateProgressListener(audio), false, ); - addMutationObserver(); + document.addEventListener('ForemMobile', handlePodcastMessages); }, 500); applyOnclickToPodcastBar(audio); } diff --git a/app/assets/javascripts/initializers/initializeVideoPlayback.js b/app/assets/javascripts/initializers/initializeVideoPlayback.js index d827cdca6..15b34a95b 100644 --- a/app/assets/javascripts/initializers/initializeVideoPlayback.js +++ b/app/assets/javascripts/initializers/initializeVideoPlayback.js @@ -122,17 +122,9 @@ function initializeVideoPlayback() { videoPlayerEvent(true); } - function handleVideoMessages(mutation) { - if (mutation.type !== 'attributes') { - return; - } - - var message = {}; - try { - var messageData = getById('video-player-source').dataset.message; - message = JSON.parse(messageData); - } catch (e) { - console.log(e); // eslint-disable-line no-console + function handleVideoMessages(event) { + const message = JSON.parse(event.detail); + if (message.namespace !== 'video') { return; } @@ -151,7 +143,7 @@ function initializeVideoPlayback() { currentTime = message.currentTime; break; default: - console.log('Unrecognized video message: ', message); // eslint-disable-line no-console + console.log('Unrecognized message: ', message); // eslint-disable-line no-console } } @@ -161,40 +153,25 @@ function initializeVideoPlayback() { if (Runtime.isNativeIOS('video')) { deviceType = 'iOS'; - Runtime.videoMessage = function (message) { - try { - window.webkit.messageHandlers.video.postMessage(message); - } catch (err) { - console.log(err.message); // eslint-disable-line no-console - } - }; } else if (Runtime.isNativeAndroid('videoMessage')) { deviceType = 'Android'; - Runtime.videoMessage = function (message) { - try { - AndroidBridge.videoMessage(JSON.stringify(message)); - } catch (err) { - console.log(err.message); // eslint-disable-line no-console - } - }; } else { // jwplayer is initialized and no further interaction is needed initWebPlayer(seconds, metadata); return; } + Runtime.videoMessage = (msg) => { + window.ForemMobile.injectNativeMessage('video', msg); + }; + var playerElement = getById(`video-player-${metadata.id}`); playerElement.addEventListener('click', requestFocus); playerElement.classList.add('native'); getById('play-butt').classList.add('active'); - var mutationObserver = new MutationObserver(function (mutations) { - mutations.forEach(function (mutation) { - handleVideoMessages(mutation); - }); - }); - mutationObserver.observe(videoSource, { attributes: true }); + document.addEventListener('ForemMobile', handleVideoMessages); currentTime = `${seconds}`; } diff --git a/app/controllers/devices_controller.rb b/app/controllers/devices_controller.rb index 8d0034eb7..72859ec62 100644 --- a/app/controllers/devices_controller.rb +++ b/app/controllers/devices_controller.rb @@ -42,7 +42,7 @@ class DevicesController < ApplicationController user: current_user, token: params[:token], platform: params[:platform], - consumer_app: ConsumerApp.find_by(app_bundle: params[:app_bundle]) + consumer_app: consumer_app } end @@ -57,7 +57,11 @@ class DevicesController < ApplicationController user_id: params[:id], token: params[:token], platform: params[:platform], - consumer_app: ConsumerApp.find_by(app_bundle: params[:app_bundle]) + consumer_app: consumer_app } end + + def consumer_app + ConsumerApp.find_by(app_bundle: params[:app_bundle], platform: params[:platform]) + end end diff --git a/app/javascript/article-form/components/ArticleCoverImage.jsx b/app/javascript/article-form/components/ArticleCoverImage.jsx index 2e0ceb404..9fdc54dab 100644 --- a/app/javascript/article-form/components/ArticleCoverImage.jsx +++ b/app/javascript/article-form/components/ArticleCoverImage.jsx @@ -14,7 +14,6 @@ const NativeIosImageUpload = ({ extraProps, uploadLabel, isUploadingImage, - handleNativeMessage, }) => ( {isUploadingImage ? null : ( @@ -26,12 +25,6 @@ const NativeIosImageUpload = ({ {uploadLabel} )} - ); @@ -98,20 +91,27 @@ export class ArticleCoverImage extends Component { }; useNativeUpload = () => { - return Runtime.isNativeIOS('imageUpload'); + // This namespace is not implemented in the native side. This allows us to + // deploy our refactor and wait until our iOS app is approved by AppStore + // review. The old web implementation will be the fallback until then. + return Runtime.isNativeIOS('imageUpload_disabled'); }; initNativeImagePicker = (e) => { e.preventDefault(); - window.webkit.messageHandlers.imageUpload.postMessage({ - id: 'native-cover-image-upload-message', + window.ForemMobile?.injectNativeMessage('coverUpload', { + action: 'coverImageUpload', ratio: `${100.0 / 42.0}`, }); }; handleNativeMessage = (e) => { - const message = JSON.parse(e.target.value); + const message = JSON.parse(e.detail); + if (message.namespace !== 'coverUpload') { + return; + } + /* eslint-disable no-case-declarations */ switch (message.action) { case 'uploading': this.setState({ uploadingImage: true }); @@ -125,10 +125,14 @@ export class ArticleCoverImage extends Component { }); break; case 'success': - this.props.onMainImageUrlChange({ links: [message.link] }); + const { onMainImageUrlChange } = this.props; + onMainImageUrlChange({ + links: [message.link], + }); this.setState({ uploadingImage: false }); break; } + /* eslint-enable no-case-declarations */ }; triggerMainImageRemoval = (e) => { @@ -169,6 +173,9 @@ export class ArticleCoverImage extends Component { } : {}; + // Native Bridge messages come through ForemMobile events + document.addEventListener('ForemMobile', this.handleNativeMessage); + return ( ) : ( ( +const NativeIosImageUpload = ({ uploadingImage, extraProps }) => ( {!uploadingImage && (