Zoom App Images not Rendering on Zoom but shows on browser

Zoom Apps Configuration
Node js, ejs template

Description
This is my first time building a zoom app so pardon my ignorance please and point me in the right direction because I am currently stuck with these issues

  • I have a countdown timer which I implemented with javascript setInterval. It works well if I open the page on a browser but when I do the same on zoom app it doesn’t work. The initial value of the HTML element remains the same. The javascript setInterval that’s meant to change it to the count down value doesn’t do anything.

  • Secondly I can’t redirect user to the browser to say view a particular content on our website instead of the app because its more detailed on the website. Tried using window.open(page_link) and res.redirect(page_link). It does nothing on the app. But works well on browser

  • Lastly I cloned this repo to start GitHub - zoom/zoomapps-sample-js: A Hello World Zoom App built with Vanilla JS to start this project but images from an external src don’t work. only local image asserts gets displayed. I tried modifying the contentSecurityPolicy directives object like so

imgSrc: ['*', 'data:', "'self'", `https://${redirectHost}`, 'blob:', 'https://res.cloudinary.com']

But as always. It works fine on a browser but on zoom it just doesn’t load the images

Error?
I don’t get any error message from zoom

How To Reproduce

  • Clone the GitHub repo from the link above
  • Then try loading any image with an external source say from cloudunary, unsplash or whatever you like,
  • Create a button and try to redirect user to a website on click
  • Lastly create a simple countdown with setInterval say countdown from 60 to 0

I tested this out on my end with the Basic Sample App but I didn’t see the same issue. The interval seemed to fire when placed in the public/index.js file.

Can you share a code snippet of your implementation?

You can use the openUrl() function from the JS SDK for this.

Make sure that you’re also adding that external URL to the Domain Allow List and re-authorizing your app. Here’s an example of how I would set up img-src in the CSP:

I hope that helps! Let me know if you have any questions.

1 Like

Firstly thank you so much for responding to my questions. Much appreciated

I tested this out on my end with the Basic Sample App but I didn’t see the same issue. The interval seemed to fire when placed in the public/index.js file.

Can you share a code snippet of your implementation?

Yes the interval fires in the browser. Did you try it on zoom?

My code snippet

const { DateTime } = luxon

const leadingZeros = (value, numberOfLeadingZero = 2) => {
  return String(Math.ceil(value)).padStart(numberOfLeadingZero, '0')
}

const stageTimer = document.querySelector('.stage-timer-count-down')
const stageTimerTopDescription = document.querySelector('.stage-count-down p:first-child')
const stageTimerBottomDescription = document.querySelector('.stage-count-down p:last-child')
const startAt = stageTimer.dataset.startat
const endAt = stageTimer.dataset.endat

class StageTimer {
  constructor(stageTimer, startAt, endAt) {
    this.stageTimer = stageTimer
    this.startAt = startAt
    this.endAt = endAt
    this.timer = null
  }

  start() {
    this.timer = setInterval(() => {
      const start = DateTime.fromISO(this.startAt)
      const end = DateTime.fromISO(this.endAt)
      const diffStartMillis = start.toMillis() - DateTime.now().toMillis()
      const diffStartObject = start
        .diffNow(['hours', 'minutes', 'seconds', 'milliseconds'])
        .toObject()
      const diffEnd = end.toMillis() - DateTime.now().toMillis()
      const diffEndObject = end.diffNow(['hours', 'minutes', 'seconds', 'milliseconds']).toObject()

      if (diffStartMillis > 0) {
        stageTimerTopDescription.textContent = 'Starts in'
        this.stageTimer.innerHTML = `${leadingZeros(diffStartObject.hours)}:${leadingZeros(
          diffStartObject.minutes
        )}:${leadingZeros(diffStartObject.seconds)}`
        stageTimerBottomDescription.textContent = ''
      } else if (diffEnd > 0) {
        this.stageTimer.innerHTML = `${leadingZeros(diffEndObject.hours)}:${leadingZeros(
          diffEndObject.minutes
        )}:${leadingZeros(diffEndObject.seconds)}`
      } else {
        stageTimerTopDescription.textContent = 'Ended'
        this.stageTimer.innerHTML = `${leadingZeros(Math.abs(diffEndObject.hours))}:${leadingZeros(
          Math.abs(diffEndObject.minutes)
        )}:${leadingZeros(Math.abs(diffEndObject.seconds))}`
        stageTimerBottomDescription.textContent = 'ago'
        this.end()
      }
    }, 1000)
  }

  end() {
    clearInterval(this.timer)
  }
}

const stageTime = new StageTimer(stageTimer, startAt, endAt)
stageTime.start()

You can use the openUrl() function from the JS SDK for this.

Sorry this is definitely on me as I don’t understand what I am doing wrong. If you can give me pointers that would be great

My code. I can’t see the console on zoom so I just used one of my 2 buttons to show me the error message. The join innerHTML is just to let me know the eventlistener is being called

const btnArea = document.querySelector('.btn-area')
const btn = document.querySelector('.btn-area button')
const btnEdit = document.querySelector('.btn-area button:last-child')

async function configureApp() {
  try {
    const configResponse = await zoomSdk.config({
      version: '0.16',
      popoutSize: { width: 480, height: 360 },
      capabilities: ['shareApp'],
    })
    btnEdit.innerHTML = configResponse.clientVersion
  } catch (error) {
    console.log(error.message)
    btnEdit.innerHTML = error.message
  }
}

configureApp()

btn.addEventListener('click', async () => {
  // window.open(btnArea.dataset.kirlink, '_blank');
  btn.innerHTML = 'Join'
  await zoomSdk.openUrl({ url: 'https://awesome-zoom-app.com/login' })
  // window.location.href = `/redirect?link=${btnArea.dataset.kirlink}`;
})

Error I got on browser read zoom app SDK is not supported by this browser. I am using google chrome by the way

Error on Zoom read Zoom SDK not defined. Why do I get not supported on browser if it is undefined, I don’t get it? I added this script tag to my HTML page

<script src="https://appssdk.zoom.us/sdk.js"></script>

Make sure that you’re also adding that external URL to the Domain Allow List and re-authorizing your app. Here’s an example of how I would set up img-src in the CSP:

The images loads on browser but when I open them on zoom, they don’t load. I added the img-src to CSP. So I thought maybe its my implementation that has issues so I tested it on the Basic Sample App

Heres what I added

 directives: {
            'default-src': 'self',
            styleSrc: ["'self'"],
            scriptSrc: ["'self'", 'https://appssdk.zoom.us/sdk.min.js'],
            imgSrc: ["'self'", `https://${redirectHost}`, 'https://res.cloudinary.com'],
            'connect-src': 'self',
            'base-uri': 'self',
            'form-action': 'self',
        },

added this in view/index.pug

img(src="https://res.cloudinary.com/emmsdan-com/image/upload/v1665687967/simple-line-icons_event_qejnww.svg", alt="dsds")

The icon shows on browser but it doesn’t show on zoom.

I took a lot of screenshots but it seems I am not allowed to post them as a new user. If you can send an email, I would be happy to forward them to you

Yes, I was able to see the timer firing within zoom. Does a simple interval implementation work? Here’s the code I used:

import zoomSdk from '@zoom/appssdk';

(async () => {
    const interval = setInterval(()  => {
        console.log('test!')
    }, 1000)

    try {
        const configResponse = await zoomSdk.config({
            size: { width: 480, height: 360 },
            capabilities: [
                /* Add Capabilities Here */
                'shareApp',
            ],
        });

        console.debug('Zoom JS SDK Configuration', configResponse);
    } catch (e) {
        console.error(e);
        clearInterval(interval)
    }
})();

If you’re importing the SDK on the page you’ll see this warning and the zoomSdk object will be undefined. This shouldn’t prevent you from using the openUrl() function from within the Zoom client though.

You should be able to post images now. What errors are you seeing when attempting to load that image? There may be another header that needs to be adjusted.

You should be able to post images now. What errors are you seeing when attempting to load that image? There may be another header that needs to be adjusted.

Yeah, I don’t really get any error it just doesn’t load the image. It shows the regular HTML tag no image icon and the alt text next to it. But when I open it on a browser it loads the image.

I wasn’t able to get the set interval working. How do you view the console on zoom though? Cause you were logging text from your snippet but I couldn’t verify if it works

Finally, I was able to get the OpenURL working, If I can just get the image to load that would be great. We can do without the setInterval for now

Please see this link to enable the developer logs. After following these steps you can right click and inspect an element on your page:

https://marketplace.zoom.us/docs/zoom-apps/create-zoom-app/#enabling--developer-tools

After that, I expect there will be an error related to the missing image in the console. Let me know if there is.