Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Commit

Permalink
Fix fetching related media both on the server and on the client
Browse files Browse the repository at this point in the history
  • Loading branch information
obulat committed Apr 30, 2022
1 parent cbabec5 commit b908dc6
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 118 deletions.
60 changes: 33 additions & 27 deletions src/pages/audio/_id.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
</main>
</template>

<script>
import { computed } from '@nuxtjs/composition-api'
<script lang="ts">
import { computed, defineComponent } from '@nuxtjs/composition-api'
import { AUDIO } from '~/constants/media'
import type { AudioDetail } from '~/models/media'
import { useRelatedMediaStore } from '~/stores/media/related-media'
import { useSingleResultStore } from '~/stores/media/single-result'
Expand All @@ -32,7 +32,9 @@ import VBackToSearchResultsLink from '~/components/VBackToSearchResultsLink.vue'
import VRelatedAudio from '~/components/VAudioDetails/VRelatedAudio.vue'
import VMediaReuse from '~/components/VMediaInfo/VMediaReuse.vue'
const AudioDetailPage = {
import type { NuxtApp } from '@nuxt/types/app'
export default defineComponent({
name: 'AudioDetailPage',
components: {
VAudioDetails,
Expand All @@ -41,30 +43,41 @@ const AudioDetailPage = {
VMediaReuse,
VRelatedAudio,
},
data() {
return {
showBackToSearchLink: false,
}
beforeRouteEnter(to, from, nextPage) {
nextPage((_this) => {
if (
from.name ===
(_this as NuxtApp).localeRoute({ path: '/search/' }).name ||
from.name ===
(_this as NuxtApp).localeRoute({ path: '/search/audio' }).name
) {
// I don't know how to type `this` here
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
_this.showBackToSearchLink = true
}
})
},
setup() {
const singleResultStore = useSingleResultStore()
const relatedMediaStore = useRelatedMediaStore()
const audio = computed(() =>
singleResultStore.mediaType === AUDIO
? (singleResultStore.mediaItem as AudioDetail)
: null
)
const relatedMedia = computed(() => relatedMediaStore.media)
const relatedFetchState = computed(() => relatedMediaStore.fetchState)
return { relatedMedia, relatedFetchState }
return { audio, relatedMedia, relatedFetchState }
},
async asyncData({ route, error, app, $pinia }) {
const audioId = route.params.id
const singleResultStore = useSingleResultStore($pinia)
try {
await singleResultStore.fetchMediaItem(AUDIO, audioId)
const audio = singleResultStore.mediaItem
return {
audio,
}
await singleResultStore.fetch(AUDIO, audioId)
} catch (err) {
error({
statusCode: 404,
Expand All @@ -75,15 +88,10 @@ const AudioDetailPage = {
})
}
},
beforeRouteEnter(to, from, nextPage) {
nextPage((_this) => {
if (
from.name === _this.localeRoute({ path: '/search/' }).name ||
from.name === _this.localeRoute({ path: '/search/audio' }).name
) {
_this.showBackToSearchLink = true
}
})
data() {
return {
showBackToSearchLink: false,
}
},
head() {
const title = this.audio.title
Expand All @@ -98,9 +106,7 @@ const AudioDetailPage = {
],
}
},
}
export default AudioDetailPage
})
</script>
<style>
.audio-page {
Expand Down
151 changes: 86 additions & 65 deletions src/pages/image/_id.vue
Original file line number Diff line number Diff line change
Expand Up @@ -73,115 +73,138 @@
</div>
</template>

<script>
<script lang="ts">
import axios from 'axios'
import { computed } from '@nuxtjs/composition-api'
import { computed, defineComponent, ref } from '@nuxtjs/composition-api'
import { IMAGE } from '~/constants/media'
import { useSingleResultStore } from '~/stores/media/single-result'
import { useRelatedMediaStore } from '~/stores/media/related-media'
import VButton from '~/components/VButton.vue'
import VIcon from '~/components/VIcon/VIcon.vue'
import VLink from '~/components/VLink.vue'
import VImageDetails from '~/components/VImageDetails/VImageDetails.vue'
import VMediaReuse from '~/components/VMediaInfo/VMediaReuse.vue'
import VRelatedImages from '~/components/VImageDetails/VRelatedImages.vue'
import SketchFabViewer from '~/components/SketchFabViewer.vue'
import VBackToSearchResultsLink from '~/components/VBackToSearchResultsLink.vue'
const VImageDetailsPage = {
import { ImageDetail } from '../../models/media'
export default defineComponent({
name: 'VImageDetailsPage',
components: {
VButton,
VIcon,
VLink,
VImageDetails,
VMediaReuse,
VRelatedImages,
SketchFabViewer,
VBackToSearchResultsLink,
},
data() {
return {
imageWidth: 0,
imageHeight: 0,
imageType: 'Unknown',
isLoadingFullImage: true,
showBackToSearchLink: false,
sketchFabfailure: false,
}
beforeRouteEnter(_to, from, nextPage) {
nextPage((_this) => {
// I don't know how to type `this` here
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
if (
from.name === _this.localeRoute({ path: '/search/' })?.name ||
from.name === _this.localeRoute({ path: '/search/image' })?.name
) {
// I don't know how to type `this` here
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
_this.showBackToSearchLink = true
}
})
},
setup() {
const singleResultStore = useSingleResultStore()
const relatedMediaStore = useRelatedMediaStore()
const image = computed(() =>
singleResultStore.mediaType === IMAGE
? (singleResultStore.mediaItem as ImageDetail)
: null
)
const relatedMedia = computed(() => relatedMediaStore.media)
const relatedFetchState = computed(() => relatedMediaStore.fetchState)
return { relatedMedia, relatedFetchState }
},
computed: {
sketchFabUid() {
if (this.image?.source !== 'sketchfab' || this.sketchFabfailure) {
const imageWidth = ref(0)
const imageHeight = ref(0)
const imageType = ref('Unknown')
const isLoadingFullImage = ref(true)
const sketchFabfailure = ref(false)
const sketchFabUid = computed(() => {
if (image.value?.source !== 'sketchfab' || sketchFabfailure.value) {
return null
}
return this.image.url
return image.value.url
.split('https://media.sketchfab.com/models/')[1]
.split('/')[0]
},
})
const onImageLoaded = (event: Event) => {
if (!(event.target instanceof HTMLImageElement)) {
return
}
imageWidth.value = image.value?.width || event.target.naturalWidth
imageHeight.value = image.value?.height || event.target.naturalHeight
if (image.value?.filetype) {
imageType.value = image.value.filetype
} else {
if (event.target) {
axios
.head(event.target.src)
.then((res) => {
imageType.value = res.headers['content-type']
})
.catch(() => {
/**
* Do nothing. This avoid the console warning "Uncaught (in promise) Error:
* Network Error" in Firefox in development mode.
*/
})
}
}
isLoadingFullImage.value = false
}
return {
image,
relatedMedia,
relatedFetchState,
imageWidth,
imageHeight,
imageType,
isLoadingFullImage,
sketchFabfailure,
sketchFabUid,
onImageLoaded,
}
},
async asyncData({ app, error, route, $pinia }) {
const imageId = route.params.id
const singleResultStore = useSingleResultStore($pinia)
try {
await singleResultStore.fetchMediaItem(IMAGE, imageId)
const image = singleResultStore.mediaItem
return {
image,
}
await singleResultStore.fetch(IMAGE, imageId)
} catch (err) {
const errorMessage = app.i18n.t('error.image-not-found', {
id: imageId,
})
error({
const errorMessage = app.i18n
.t('error.image-not-found', {
id: imageId,
})
.toString()
return error({
statusCode: 404,
message: errorMessage,
})
}
},
beforeRouteEnter(to, from, nextPage) {
nextPage((_this) => {
if (
from.name === _this.localeRoute({ path: '/search/' }).name ||
from.name === _this.localeRoute({ path: '/search/image' }).name
) {
_this.showBackToSearchLink = true
}
})
},
methods: {
onImageLoaded(event) {
this.imageWidth = this.image.width || event.target.naturalWidth
this.imageHeight = this.image.height || event.target.naturalHeight
if (this.image.filetype) {
this.imageType = this.image.filetype
} else {
axios
.head(event.target.src)
.then((res) => {
this.imageType = res.headers['content-type']
})
.catch(() => {
/**
* Do nothing. This avoid the console warning "Uncaught (in promise) Error:
* Network Error" in Firefox in development mode.
*/
})
}
this.isLoadingFullImage = false
},
},
data: () => ({
showBackToSearchLink: false,
}),
head() {
const title = `${this.image.title} | Openverse`
Expand All @@ -206,9 +229,7 @@ const VImageDetailsPage = {
],
}
},
}
export default VImageDetailsPage
})
</script>

<style scoped>
Expand Down
Loading

0 comments on commit b908dc6

Please sign in to comment.