Skip to content

Commit

Permalink
Iframes and Image Caching (#29)
Browse files Browse the repository at this point in the history
* Force browser to cache images

* Iframe and 12-hour media refresh added

* Remove hiring poster
  • Loading branch information
s-egge authored Oct 14, 2024
1 parent a50043b commit 55d5349
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 32 deletions.
76 changes: 56 additions & 20 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<el-container class="app">
<el-header class="header"> </el-header>
<el-main class="main" ref="main">
<router-view />
<router-view @iframeChanged="iframe = $event" />
</el-main>
</el-container>
</template>
Expand All @@ -31,10 +31,12 @@ export default {
modifiedDateUnix: 0,
timeDiffUnix: 0,
refreshInterval: 600, // 10 minutes refresh interval. Time in seconds (lower for debug)
mediaCheckTimer: null,
mediaCheckInterval: 43200000, // 12 hours. Time in ms
inactivityTimeout: 30000, // 30 seconds of inactivity. Time in milliseconds
inactivityTimeoutDefault: 30000, // 30 seconds of inactivity. Time in milliseconds
inactivityTimer: null,
mediaList: ['images/Fall_Hiring_Poster_24.png']
iframe: null,
mediaList: []
}
},
methods: {
Expand All @@ -57,29 +59,47 @@ export default {
},
// fetch media from AWS bucket
async fetchMedia () {
const bucketURL = 'https://osu-kiosk-media.s3.us-west-2.amazonaws.com'
const listUrl = 'https://osu-kiosk-media.s3.us-west-2.amazonaws.com'
const imgUrlPrefix = 'https://d3aici5r99iqap.cloudfront.net'
// fetch media list from S3 bucket
try {
const response = await axios.get(bucketURL)
const response = await axios.get(listUrl)
const parser = new DOMParser()
const xmlDoc = parser.parseFromString(response.data, 'text/xml')
const keys = xmlDoc.getElementsByTagName('Key')
this.mediaList = Array.from(keys).map(
(key) => `${bucketURL}/${key.textContent}`
this.fetchedMediaList = Array.from(keys).map(
(key) => `${imgUrlPrefix}/${key.textContent}`
)
// remove any old images
for (const imgUrl of this.mediaList) {
if (!this.fetchedMediaList.includes(imgUrl)) {
this.mediaList = this.mediaList.filter((media) => media !== imgUrl)
}
}
// add new images and force browser to cache them
for (const imgUrl of this.fetchedMediaList) {
if (!this.mediaList.includes(imgUrl)) {
const img = new Image()
img.src = imgUrl
img.onload = () => {
this.mediaList.push(imgUrl)
}
img.onerror = (error) => {
console.error('Error loading image:', error)
}
}
}
} catch (error) {
console.error('Error fetching media:', error)
}
console.log('Media list:', this.mediaList)
},
// creates a timer that routes to the Carousel page after time is up
createInactivityTimer () {
// refresh media
// this.fetchMedia()
this.inactivityTimer = setTimeout(() => {
this.$router.push({
name: 'Carousel',
Expand All @@ -98,9 +118,11 @@ export default {
}
// set a new timer for navigating to image carousel
this.createInactivityTimer()
if (!this.iframe) this.createInactivityTimer()
this.$router.push('/')
if (!this.iframe && this.$route.path === '/carousel') {
this.$router.push('/')
}
}
},
async created () {
Expand All @@ -114,11 +136,16 @@ export default {
this.fetchLastModified,
this.refreshInterval * 1000
) // setInterval expects milliseconds
// check for new media
this.mediaCheckTimer = setInterval(
this.fetchMedia,
this.mediaCheckInterval
)
}
// get media for rotation
// await this.fetchMedia()
console.log('Media list:', this.mediaList)
await this.fetchMedia()
// create a timer for media rotation
this.createInactivityTimer()
Expand All @@ -128,6 +155,7 @@ export default {
},
beforeDestroy () {
clearInterval(this.timer)
clearInterval(this.mediaCheckTimer)
if (this.inactivityTimer) {
clearTimeout(this.inactivityTimer)
Expand All @@ -151,17 +179,25 @@ export default {
}
},
mediaList: function (newList, oldList) {
console.log('Media length: ', newList.length)
if (newList.length === 0) {
this.inactivityTimeout = this.refreshInterval * 1000
} else {
this.inactivityTimeout = this.inactivityTimeoutDefault
clearInterval(this.inactivityTimer)
} else if (oldList.length === 0) {
this.createInactivityTimer()
}
},
$route (to, from) {
if (from.path === '/carousel' && to.path !== '/carousel') {
this.createInactivityTimer()
}
},
// clear the carousel timer when the iframe is active,
// reset it when the iframe is closed
iframe: function (newUrl, oldUrl) {
if (newUrl) {
clearTimeout(this.inactivityTimer)
} else {
this.createInactivityTimer()
}
}
}
}
Expand Down
Binary file removed src/assets/Fall_Hiring_Poster_24.png
Binary file not shown.
5 changes: 1 addition & 4 deletions src/components/carousel.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
<template>
<el-row class="img-container" type="flex" justify="center" align="middle">
<img
src="@/assets/Fall_Hiring_Poster_24.png"
alt="Fall hiring poster with QR codes"
/>
<img :src="currentImage" alt="Hiring or Event posting" />
<div v-if="touchScreenIndicator">
<h1 class="text-content">
Tap to learn more about the Sustainability Office
Expand Down
133 changes: 125 additions & 8 deletions src/components/main.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,100 @@
<el-col> </el-col>
<el-col> </el-col>
<el-col>
<a href="https://fa.oregonstate.edu/sustainability"
><el-button id="myBtn">Sustainability Website</el-button></a
<el-button
id="myBtn"
@click="setIframe('https://fa.oregonstate.edu/sustainability')"
>Sustainability Website</el-button
>
</el-col>
<el-col>
<a
href="https://osu-sustainability-office.github.io/sustainability_jeopardy/"
><el-button id="myBtn">Sustainability Jeopardy</el-button></a
<el-button
id="myBtn"
@click="
setIframe(
'https://osu-sustainability-office.github.io/sustainability_jeopardy/'
)
"
>Sustainability Jeopardy</el-button
>
</el-col>
<el-col>
<a href="https://myco2.sustainability.oregonstate.edu/"
><el-button id="myBtn">Carbon Footprint Calculator</el-button></a
<el-button
id="myBtn"
@click="setIframe('https://myco2.sustainability.oregonstate.edu/')"
>Carbon Footprint Calculator</el-button
>
</el-col>
<el-col> </el-col>
<el-col> </el-col>
</el-row>
<div v-if="iframe" id="iframe-container">
<div id="iframe-inactivity-test" @click="resetIframeActivityTester()">
<p id="stay-on-page-text">Tap to stay on this page</p>
</div>
<iframe
:src="iframe"
width="100%"
height="100%"
frameborder="0"
allowfullscreen
></iframe>
<el-button
id="home-btn"
size="large"
icon="el-icon-s-home"
circle
@click="setIframe(null)"
></el-button>
</div>
</el-col>
</el-row>
</template>

<script>
export default {}
export default {
data () {
return {
iframe: null,
iframeTimer: null,
iframeTimeout: 300000, // 5 minutes
iframeActivityTestTimeout: 240000 // 4 minutes
}
},
methods: {
setIframe (url) {
this.iframe = url
this.resetIframeTimer()
this.$emit('iframeChanged', url)
},
resetIframeTimer () {
// set click tester timer to reset pointer-event to auto
setTimeout(() => {
this.toggleIframeActivityTester('visible')
}, this.iframeActivityTestTimeout)
clearTimeout(this.iframeTimer)
this.iframeTimer = setTimeout(() => {
this.iframe = null
this.$emit('iframeChanged', null)
}, this.iframeTimeout)
},
resetIframeActivityTester () {
this.toggleIframeActivityTester('hidden')
this.resetIframeTimer()
},
toggleIframeActivityTester (visibility) {
const iframeActivityDiv = document.getElementById(
'iframe-inactivity-test'
)
iframeActivityDiv.style.visibility =
visibility === 'hidden' ? 'hidden' : 'visible'
}
},
beforeDestroy () {
clearTimeout(this.iframeTimer)
}
}
</script>

<style scoped lang="scss">
Expand Down Expand Up @@ -124,4 +194,51 @@ video {
background: $--color-white;
color: $--color-black;
}
/* iframe styling */
#iframe-container {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 100;
background: white;
}
#iframe-inactivity-test {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 101;
background: rgba(0, 0, 0, 0.5);
visibility: hidden;
}
#stay-on-page-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 2em;
color: rgba(255, 255, 255, 0.8);
text-align: center;
width: fit-content;
padding: 10px;
border-radius: 10px;
z-index: 102;
background: rgba(0, 0, 0, 0.5);
}
#home-btn {
position: fixed;
background-color: #ff4e00;
border: none;
color: black;
bottom: 10px;
left: 10px;
z-index: 105;
}
</style>

0 comments on commit 55d5349

Please sign in to comment.