Move nuxt pages to pages-nuxt/

This commit is contained in:
Sam Carlton 2021-09-11 12:25:13 -05:00
parent 1cd19177f3
commit 321c2ee468
19 changed files with 5 additions and 0 deletions

View file

@ -1,6 +0,0 @@
# PAGES
This directory contains your Application Views and Routes.
The framework reads all the `*.vue` files inside this directory and create the router of your application.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing).

View file

@ -1,268 +0,0 @@
<template>
<section class="container pb-16">
<div class="flex flex-col items-center text-center space-y-8">
<template
v-if="video"
>
<VideoPlayer
:video="video"
class="pt-16"
/>
<ChannelCredit
:video="video"
class="flex w-full justify-start md:px-10"
/>
</template>
<template v-else>
<div
:style="{
'left': '50%',
'right': '50%',
'margin-left': '-50vw',
'margin-right': '-50vw'
}"
class="video-canvas w-screen flex justify-center bg-black pt-16"
>
<div class="ratio-wrapper w-full max-w-4xl">
<div class="relative overflow-hidden w-full pb-16/9">
<div class="absolute h-full w-full flex justify-center items-center">
<div class="message text-4xl md:text-6xl font-hairline leading-tight text-center">No videos yet</div>
</div>
</div>
</div>
</div>
</template>
<!-- <h1 class="title text-sm md:text-3xl font-bold">
{{ video.name }}
</h1> -->
<div class="related-videos w-full max-w-4xl">
<h2 class="subtitle text-xl md:text-2xl font-bold mb-3">
Benchmark Videos
</h2>
<!-- <pre class="text-left">{{ benchmarkVideos }}</pre> -->
<VideoRow
:videos="benchmarkVideos"
:active-video-id="activeVideoId"
/>
</div>
<div
v-if="performanceVideos.length !== 0"
class="performance-videos w-full max-w-4xl"
>
<h2 class="subtitle text-xl md:text-2xl font-bold mb-3">
Performance Videos
</h2>
<!-- <pre class="text-left">{{ performanceVideos }}</pre> -->
<VideoRow
:videos="performanceVideos"
:active-video-id="activeVideoId"
/>
</div>
<div
v-if="moreVideos.length !== 0"
class="related-videos w-full max-w-4xl"
>
<h2 class="subtitle text-xl md:text-2xl font-bold mb-3">
More Videos
</h2>
<!-- <pre class="text-left">{{ relatedVideos }}</pre> -->
<VideoRow
:videos="moreVideos"
:active-video-id="activeVideoId"
/>
</div>
<!-- video: {{ video }} -->
<!-- <div class="links space-y-6 sm:space-x-6 mb-8">
<LinkButton
v-for="(link, i) in app.relatedLinks"
:key="i"
:href="link.href"
target="_blank"
class=""
>{{ (i === 0) ? 'View' : link.label }}</LinkButton>
</div> -->
</div>
</section>
</template>
<script>
import LinkButton from '~/components/link-button.vue'
import EmailSubscribe from '~/components/email-subscribe.vue'
import VideoRow from '~/components/video/row.vue'
import VideoPlayer from '~/components/video/player.vue'
import ChannelCredit from '~/components/video/channel-credit.vue'
export default {
components: {
LinkButton,
EmailSubscribe,
VideoRow,
VideoPlayer,
ChannelCredit
},
async asyncData ( data ) {
const {
params: { slug },
route
} = data
let {
payload
} = data
// Manually get payload as fallback
// Uncomment for dev
// if ( payload === undefined ) {
// // Read back the JSON we just wrote to ensure it exists
// const { default: savedList } = await import('~/static/nuxt-endpoints.json')
// const endpoint = savedList.find( resource => {
// return resource.route === route.path
// } )
// payload = endpoint.payload
// }
return {
app: payload.app,
allVideos: payload.allVideos,
submitVideoCard: payload.submitVideoCard
}
},
data: function () {
return {
activeVideoIndex: 0,
benchmarkVideos: [],
performanceVideos: [],
moreVideos: [],
}
},
computed: {
video () {
return this.allVideos[this.activeVideoIndex]
},
title () {
return `${this.app.name} Benchmarks for Apple Silicon - Does It ARM`
},
description () {
return `Apple Silicon benchmark, performance, and support videos for ${this.app.name}`
},
activeVideoId () {
return (this.video === Object(this.video)) ? this.video.id : null
}
},
created () {
const nonBenchmarkVideos = []
// console.log('benchmarkVideos.length', this.benchmarkVideos.length)
// console.log('performanceVideos.length', this.performanceVideos.length)
// console.log('moreVideos.length', this.moreVideos.length)
// Move benchmark videos out of related videos
this.allVideos.forEach((video, index) => {
// console.log('video.name', video.name)
// console.log('video.tags', video.tags)
if (!video.tags.includes('benchmark')) {
nonBenchmarkVideos.push(video)
return
}
// Add to benchmark videos
this.benchmarkVideos.push(video)
})
// console.log('Added benchmark videos')
// console.log('benchmarkVideos.length', this.benchmarkVideos.length)
// console.log('performanceVideos.length', this.performanceVideos.length)
// console.log('moreVideos.length', this.moreVideos.length)
// Move performance videos out of related videos
nonBenchmarkVideos.forEach((video, index) => {
if (!video.tags.includes('performance')) {
this.moreVideos.push(video)
return
}
// Add to benchmark videos
this.performanceVideos.push(video)
})
// Append submit card to end
this.benchmarkVideos.push(this.submitVideoCard)
// console.log('Added performance videos')
// console.log('benchmarkVideos.length', this.benchmarkVideos.length)
// console.log('performanceVideos.length', this.performanceVideos.length)
// console.log('moreVideos.length', this.moreVideos.length)
},
mounted () {
window.onhashchange = this.loadVideoFromHash
if (location.hash.length !== 0) this.loadVideoFromHash()
},
methods: {
loadVideoFromHash () {
// console.log('location.hash', location.hash)
// Separate the video id from our window hash
const hashId = location.hash.split('#')[1]
// Find the index of the video with the matching hash
const newVideoIndex = this.allVideos.findIndex(video => {
return video.id === hashId
})
console.log('newVideoIndex', newVideoIndex)
// Load in the index to load out video
this.activeVideoIndex = newVideoIndex
window.scroll({ top: 0, behavior: 'smooth' })
}
},
head() {
return {
title: this.title,
meta: [
// hid is used as unique identifier. Do not use `vmid` for it as it will not work
{
'hid': 'description',
'name': 'description',
'content': this.description
},
// Twitter Card
{
'hid': 'twitter:title',
'property': 'twitter:title',
'content': this.title
},
{
'hid': 'twitter:description',
'property': 'twitter:description',
'content': this.description
},
{
'property': 'twitter:url',
'content': `${process.env.URL}${this.$nuxt.$route.path}`
},
]
}
}
}
</script>

View file

@ -1,141 +0,0 @@
<template>
<section class="container py-32">
<div class="flex flex-col items-center text-center space-y-8">
<div class="hero-heading space-y-6">
<h1 class="title text-sm md:text-2xl font-bold">
Does {{ app.name }} work on Apple Silicon?
</h1>
<h2 class="subtitle text-2xl md:text-5xl font-bold">
{{ app.text }}
</h2>
</div>
<div class="subscribe">
<AllUpdatesSubscribe
:app-name="app.name"
/>
</div>
<div class="links space-y-6 sm:space-x-6">
<LinkButton
v-for="(link, i) in app.relatedLinks"
:key="i"
:href="link.href"
target="_blank"
class=""
>{{ (i === 0) ? 'View' : link.label }}</LinkButton>
</div>
<div
v-if="relatedVideos.length !== 0"
class="related-videos w-full"
>
<h2 class="subtitle text-xl md:text-2xl font-bold mb-3">
Related Videos
</h2>
<VideoRow
:videos="relatedVideos"
/>
</div>
<div class="report-links py-24 text-xs shadow-none">
<div v-if="app.lastUpdated">
<time
:datetime="app.lastUpdated.raw"
>
Last Updated {{ lastUpdatedFriendly }}
</time>
</div>
<!-- https://eric.blog/2016/01/08/prefilling-github-issues/ -->
<a
:href="`https://github.com/ThatGuySam/doesitarm/issues?q=is%3Aissue+is%3Aopen+${app.name}`"
target="_blank"
class="underline"
rel="noopener"
>Report Update</a>
</div>
</div>
</section>
</template>
<script>
import { makeLastUpdatedFriendly } from '~/helpers/parse-date'
import { getAppEndpoint } from '~/helpers/app-derived.js'
import LinkButton from '~/components/link-button.vue'
import AllUpdatesSubscribe from '~/components/all-updates-subscribe.vue'
import VideoRow from '~/components/video/row.vue'
import appList from '~/static/app-list.json'
// import buildAppList from '~/helpers/build-app-list'
export default {
components: {
LinkButton,
AllUpdatesSubscribe,
VideoRow
},
async asyncData ({ params: { slug } }) {
const { default: videoList } = await import('~/static/video-list.json')
const { videosRelatedToApp } = await import('~/helpers/related.js')
const app = appList.find(app => (app.slug === slug))
const relatedVideos = videosRelatedToApp( app, (new Set(videoList)) )
// Find other videos that also feature this video's app
// for (const video of videoList) {
// if (!video.apps.includes(app.slug)) continue
// relatedVideos.push(video)
// }
return {
slug,
app,
relatedVideos: relatedVideos.map(video => {
// console.log('video', video)
return {
...video,
endpoint: `${getAppEndpoint(app)}/benchmarks#${video.id}`
}
})
}
},
computed: {
lastUpdatedFriendly () {
return makeLastUpdatedFriendly( this.app.lastUpdated )
}
},
head() {
return {
title: `Does ${this.app.name} work on Apple Silicon?`,
meta: [
// hid is used as unique identifier. Do not use `vmid` for it as it will not work
{
'hid': 'description',
'name': 'description',
'content': `Check the the latest reported support status of ${this.app.name} on Apple Silicon and Apple M1 Processors`
},
// Twitter Card
{
'hid': 'twitter:title',
'property': 'twitter:title',
'content': `Does ${this.app.name} work on Apple Silicon?`
},
{
'hid': 'twitter:description',
'property': 'twitter:description',
'content': `Check the the latest reported support status of ${this.app.name} on Apple Silicon and Apple M1 Processors`
},
{
'property': 'twitter:url',
'content': `${process.env.URL}${this.$nuxt.$route.path}`
},
]
}
}
}
</script>

View file

@ -1,361 +0,0 @@
<template>
<section class="container py-24">
<div class="flex flex-col items-center space-y-24">
<header class="flex flex-col items-center space-y-6 md:px-12">
<div class="title-container relative">
<h1 class="title text-3xl md:text-5xl font-hairline leading-tight text-center">
Apple Silicon App Test
</h1>
<div
class="beta-pill absolute h-5 text-xs bg-white-2 flex justify-center items-center outline-0 rounded-full ease px-2"
style="top: -1em; right: 0;"
>
Beta
</div>
</div>
<h2 class="subtitle md:text-xl text-center">
Check for Apple Silicon compatibility for your apps before you buy an M1 Mac.
</h2>
</header>
<div class="app-tester w-full space-y-4 pb-64">
<div
class="relative w-full flex flex-col justify-center items-center space-y-4 pb-8"
>
<button
:class="[
'rounded-xl text-3xl font-semibold scale-150 bg-darkest neumorphic-shadow focus:outline-none py-4 px-6',
isLoadingFiles ? 'shimmer' : ''
]"
@click="triggerFilepicker"
>{{ isLoadingFiles ? 'Loading Files' : 'Select Apps' }}</button>
<template v-if="isLoadingFiles">
<div>Loading usually takes about a minute per 500mb</div>
<button
class="underline"
@click="isLoadingFiles = false"
>Cancel</button>
</template>
<div>
<small>
<span>Supports: Mac Apps, Zip files. Extract DMGs and PKGs first. Bigger files take longer. </span>
<a
href="https://www.youtube.com/watch?v=icq9wJx7wbg"
class="underline"
rel="noopener"
>How it works</a>
</small>
</div>
<input
ref="file-selector"
type="file"
accept="application/**"
multiple
hidden
@change="fileInputChanged"
>
<!-- Directories only: webkitdirectory directory -->
</div>
<div
v-if="foundFiles.length !== 0"
class="w-full text-center"
>
Total Files: {{ foundFiles.length }}
</div>
<div
v-if="foundFiles.length !== 0"
class="app-scans-container relative divide-y divide-gray-700 w-full rounded-lg border border-gray-700 bg-gradient-to-br from-darker to-dark spac-y-3 my-4 px-5"
>
<ul
class="results-container divide-y divide-gray-700"
>
<li
v-for="( appScan, index ) in foundFiles"
:key="`${appScan.name}-${index}`"
:ref="`${appScan.name}-row`"
class="relative"
>
<!-- app.endpoint: {{ app.endpoint }} -->
<div
:class="[
'flex flex-col justify-center inset-x-0 hover:bg-darkest border-2 border-white border-opacity-0 hover:border-opacity-50 focus:outline-none focus:bg-gray-50 duration-300 ease-in-out rounded-lg space-y-3 -mx-5 pl-5 md:pl-20 pr-6 md:pr-64 py-5',
(appScan.status !== 'finished') ? 'shimmer' : ''
]"
style="transition-property: border;"
>
<div class="absolute hidden left-0 h-12 w-12 rounded-full md:flex items-center justify-center bg-darker">
{{ appScan.name.charAt(0) }}
</div>
{{ appScan.displayName || appScan.name }}
{{ appScan.appVersion ? `- v${appScan.appVersion}` : '' }}
{{ appScan.displayAppSize ? `- App ${appScan.displayAppSize}` : '' }}
{{ appScan.displayBinarySize ? `- Binary ${appScan.displayBinarySize}` : '' }}
<div class="text-sm leading-5 font-bold">
{{ appScan.statusMessage }}
</div>
<!-- appScan.binarySize: {{ appScan.binarySize }} -->
<div
v-if="appScan.binarySize && appScan.binarySize < (10 ^ 6)"
class="text-sm leading-5 font-bold"
>
Large Binary - This scan may take a while an/or have issues
</div>
<details class="w-full pt-6">
<summary class="cursor-pointer mb-3">Details</summary>
<div>
<div v-if="appScan.details.length === 0">No details available</div>
<ul v-else>
<li
v-for="( detail ) in appScan.details"
:key="`${appScan.name}-detail-${detail.label}`"
><strong>{{ detail.label }}</strong> <span v-html="detail.value" /></li>
</ul>
</div>
</details>
<div class="flex flex-col md:flex-row space-x-0 space-y-4 md:space-y-0 md:space-x-4">
<a
:href="`https://github.com/ThatGuySam/doesitarm/issues?q=is%3Aissue+${appScan.displayName || appScan.name}`"
class="underline"
>Request a Review</a>
</div>
</div>
</li>
</ul>
</div>
</div>
<div class="w-full max-w-2xl">
<details
v-for="([ question, answer ], index) in faqs"
:key="`question-${index}`"
class="w-full"
>
<summary class="cursor-pointer">{{ question }}</summary>
<div class="p-4">
<p>{{ answer }}</p>
</div>
</details>
</div>
</div>
<!-- <client-only>
<FullScreenFileDrop @drop="onDrop" />
</client-only> -->
</section>
</template>
<script>
// import axios from 'axios'
// import AppFilesScanner from '~/helpers/app-files-scanner.js'
import LinkButton from '~/components/link-button.vue'
import AllUpdatesSubscribe from '~/components/all-updates-subscribe.vue'
export default {
// async asyncData () {
// return {
// allAppSearchLinks,
// customSummaryNumbers: getListSummaryNumbers(allList)
// }
// },
components: {
// FullScreenFileDrop: () => process.client ? import('~/components/fullscreen-file-drop.vue') : null,
LinkButton,
AllUpdatesSubscribe
},
data: function () {
return {
query: '',
isLoadingFiles: false,
appsBeingScanned: []
}
},
computed: {
foundFiles () {
return this.appsBeingScanned.filter( appScan => {
return !appScan.statusMessage.includes('⏭')
})
},
faqs () {
return [
[
'Non-native Apps (🔶)',
`
When an App scan is reported and Non-native (as indicated by an 🔶), that means the app file provided does not have native compatibility with Apple Silicon, and we have not had any reports of native versions of the app yet.
This doesn't necessarily mean the app won't work, it just means it hasn't been updated for Apple Silicon specifically and can't say for certain that it will definitely work.
Most apps reported as Non-native will usually still work under Rosetta 2 Translation with similar performance to the app's experience under an Intel-based Mac.
You can try getting the latest version from the developer\'s the download page scan that.
You can also request a manual review to determine the current status of the app on Rosetta 2.
`
],
[
'App Decompression Error (❔)',
`
This means we weren't able to extract an App Binary from the file provided.
If your app is contained within a PKG or a DMG file, you can extract the Mac App file from that Package/Archive and scan it directly.
If you are scanning from Windows, an EXE file is not scannable; however, you can download the Mac version of the app and extract it onto your Windows system, and that Mac App file can be scanned from your Windows computer.
This also applies when scanning apps from Linux-based Systems, ChromeOS, iOS, and, in theory, any system capable of running modern Javascript in a browser and extracting compressed files.
Currently, the supported formats are Mac Apps, Zip files containing Mac Apps, and specific rare DMG files. Bigger files take longer to scan.
`
],
[
'What if the scan never ends?',
`
Currently, some random apps will cause the scan to hang indefinitely.
If this happens, you can try scanning a few apps at a time or one at a time until it hangs again and skip scanning that app for now.
`
],
[
'Why can\'t it tell me if an app will work on Rosetta 2? ',
`
Currently, Rosetta 2 is a proprietary Apple software that is only available on macOS on Apple Silicon devices.
This means there isn't any way to test Rosetta 2 compatibility with an app without a physical Apple Silicon device, and so you definitely can't test that with just a website alone... for now...
Feel free to signup for email updates.
`
],
[
'Don\'t all previous Mac Apps work via Rosetta 2 translation? ',
`
Most apps will work with Rosetta 2 translation well, but it's not a perfect technology.
Some apps will have various small issues and graphical bugs but will work well enough, a few apps will fail to launch entirely, and some apps will run with virtually no problems and perform even faster than on an equivalent Intel-based Mac.
For now, the best way to determine how well an app will run under Rosetta 2 is by human review.
`
]
]
},
title () {
return `Apple Silicon Compatibility Test Online`
},
description () {
return `Check for Apple Silicon compatibility for any of your apps instantly before you buy an M1 Mac. `
}
},
mounted () {
this.scanner = null
},
methods: {
log ( thing ) {
console.log( thing )
},
triggerFilepicker () {
this.isLoadingFiles = true
// this.watchFileInput()
this.$refs['file-selector'].dispatchEvent(new MouseEvent('click'))
},
async fileInputChanged () {
this.isLoadingFiles = false
// console.log('file-selector', this.$refs['file-selector'])
// Get FileList from input
const fileList = this.$refs['file-selector'].files
// If the scanner instance is not set up yet
// then create and initialize it
if ( this.scanner === null ) {
console.log('Initializing scanner instance')
// Bring in code
const { default: AppFilesScanner} = await import('~/helpers/app-files-scanner.js')
// Initialize instance
this.scanner = new AppFilesScanner({
observableFilesArray: this.appsBeingScanned,
testResultStore: this.$config.testResultStore
})
}
// console.log('fileInputChanged files', fileList)
this.scanner.scan( fileList )
},
// async onDrop ( formData, fileList ) {
// console.log('Off to the races')
// // await new Promise(r => setTimeout(r, 2000))
// const formValues = formData.values()
// for ( const value of formValues ) {
// console.log( 'value', value )
// }
// // console.log( 'formData', formData.values() ) // Can be posted to server
// // console.log( 'fileList', fileList ) // Can get access to things like file name and size
// this.scanner.scan( fileList )
// }
// async onQueryUpdate ( $event ) {
// // console.log('$event', $event)
// this.query = $event
// return
// }
},
head() {
return {
title: this.title,
meta: [
// hid is used as unique identifier. Do not use `vmid` for it as it will not work
{
'hid': 'description',
'name': 'description',
'content': this.description
},
// Twitter Card
{
'hid': 'twitter:title',
'property': 'twitter:title',
'content': this.title
},
{
'hid': 'twitter:description',
'property': 'twitter:description',
'content': this.description
},
{
'property': 'twitter:url',
'content': `${process.env.URL}${this.$nuxt.$route.path}`
},
]
}
}
}
</script>

View file

@ -1,253 +0,0 @@
<template>
<section class="container relative md:static overflow-hidden md:overflow-visible pb-16">
<div class="flex flex-col items-center text-center space-y-12">
<BgPlayer
:video="video"
class="absolute overflow-hidden w-2x-screen md:w-full pointer-events-none"
/>
<div class="page-heading flex justify-start w-full">
<h1 class="title text-2xl leading-tight mt-12 mb-6">
Benchmarks
</h1>
</div>
<div class="line-separator border-white border-t-2 mb-12" />
<a
:href="video.endpoint"
>
<div
class="relative flex flex-col w-full justify-center items-center space-y-8 py-16 md:pt-0 md:pb-12 md:px-10"
>
<div
class="play-circle w-16 h-16 bg-white-2 bg-blur flex justify-center items-center outline-0 rounded-full ease"
>
<svg
viewBox="0 0 18 18"
style="width:24px;height:24px;margin-left:3px"
>
<path
fill="currentColor"
d="M15.562 8.1L3.87.225c-.818-.562-1.87 0-1.87.9v15.75c0 .9 1.052 1.462 1.87.9L15.563 9.9c.584-.45.584-1.35 0-1.8z"
/>
</svg>
</div>
<h2 class="title text-lg md:text-2xl font-bold">
{{ video.name }}
</h2>
</div>
</a>
<div
class="features-apps w-full"
>
<hr class="w-full" >
<div class="featured-apps overflow-x-auto overflow-y-visible whitespace-no-wrap py-2 space-x-2">
<LinkButton
v-for="app in featuredApps"
:key="app.slug"
:href="app.endpoint"
:class="[
'inline-block text-xs rounded-lg py-1 px-2',
]"
:class-groups="{
shadow: 'neumorphic-shadow-inner'
}"
>{{ app.name }}</LinkButton>
</div>
</div>
<div
v-for="(row, key) in videoRows"
:key="key"
:class="`${key}-videos w-full max-w-4xl`"
>
<h2 class="subtitle text-xl md:text-2xl font-bold mb-3">
{{ row.heading }}
</h2>
<!-- <pre class="text-left">{{ benchmarkVideos }}</pre> -->
<VideoRow
:videos="row.videos"
/>
</div>
</div>
</section>
</template>
<script>
import { getVideoEndpoint, getAppEndpoint } from '~/helpers/app-derived.js'
import LinkButton from '~/components/link-button.vue'
import EmailSubscribe from '~/components/email-subscribe.vue'
import VideoRow from '~/components/video/row.vue'
import BgPlayer from '~/components/video/bg-player.vue'
import ChannelCredit from '~/components/video/channel-credit.vue'
export default {
components: {
LinkButton,
EmailSubscribe,
VideoRow,
BgPlayer,
ChannelCredit
},
async asyncData ({ params: { slug } }) {
const { appsRelatedToVideo } = await import('~/helpers/related.js')
const { default: videoList } = await import('~/static/video-list.json')
const { allVideoAppsList } = await import('~/helpers/get-list.js')
// Get featured apps
const featuredAppsSet = new Set()
videoList.slice(0, 24).forEach( video => {
appsRelatedToVideo(video, allVideoAppsList).forEach( app => {
featuredAppsSet.add(app)
})
})
return {
video: videoList[0],
featuredApps: Array.from(featuredAppsSet).map( app => {
return {
...app,
endpoint: getAppEndpoint(app) + '/benchmarks'
}
}),
allVideos: videoList.map( video => {
return {
...video,
endpoint: getVideoEndpoint(video)
}
})
}
},
data: function () {
return {
videoRows: {
'video-benchmarks': {
heading: 'Video Editing Benchmarks',
matchesCondition: video => {
return video.tags.includes('benchmark') && video.tags.includes('video-and-motion-tools')
},
videos: []
},
'music-and-audio-tools': {
heading: 'Music and DAW Performance',
matchesCondition: video => {
return video.tags.includes('music-and-audio-tools')
},
videos: []
},
// 'science-and-research-software': {
// heading: 'Science and Research',
// matchesCondition: video => {
// return video.tags.includes('science-and-research-software')
// },
// videos: []
// },
'photo-and-graphic-tools': {
heading: 'Photography and Design Compatibility',
matchesCondition: video => {
return video.tags.includes('photo-and-graphic-tools')
},
videos: []
},
'games': {
heading: 'Gaming Benchmarks',
matchesCondition: video => {
return video.tags.includes('benchmark') && video.tags.includes('games')
},
videos: []
},
'benchmarks': {
heading: 'Other Benchmark Videos',
matchesCondition: video => video.tags.includes('benchmark'),
videos: []
},
'performance': {
heading: 'Performance Videos',
matchesCondition: video => video.tags.includes('performance'),
videos: []
},
'other': {
heading: 'More Videos',
// Always true
matchesCondition: () => true,
videos: []
}
}
}
},
computed: {
title () {
return `Benchmarks for Apple M1 and Apple Silicon - Does It ARM`
},
description () {
// const featuredAppsString = this.featuredApps.slice(0, 5).map(app => app.name).join(', ')
return `Apple Silicon benchmark, performance, and compatibility videos`
},
activeVideoId () {
return this.video.id
}
},
created () {
// Move videos to relevant categories
this.allVideos.forEach((video, index) => {
// console.log('video.name', video.name)
// console.log('video.tags', video.tags)
// Look through row conditions to see if video matches
for (const row in this.videoRows) {
if( this.videoRows[row].matchesCondition(video) ) {
// Add the matching video
this.videoRows[row].videos.push(video)
return
}
}
})
// console.log('lengths', Object.values(this.videoRows).map(row => [row.heading, row.videos.length]))
},
head() {
return {
title: this.title,
meta: [
// hid is used as unique identifier. Do not use `vmid` for it as it will not work
{
'hid': 'description',
'name': 'description',
'content': this.description
},
// Twitter Card
{
'hid': 'twitter:title',
'property': 'twitter:title',
'content': this.title
},
{
'hid': 'twitter:description',
'property': 'twitter:description',
'content': this.description
},
{
'property': 'twitter:url',
'content': `${process.env.URL}${this.$nuxt.$route.path}`
},
]
}
}
}
</script>

View file

@ -1,126 +0,0 @@
<template>
<section class="container py-24">
<div class="flex flex-col">
<h1 class="title text-2xl leading-tight mb-6">
Categories
</h1>
<div class="line-separator border-white border-t-2 mb-12" />
<!-- categoryList: {{ categoryList }} -->
<ul class="categories-list space-y-3">
<li
v-for="(category, i) in categoryList"
:key="`${category.slug}-${i}`"
:ref="`${category.slug}-row`"
class="relative"
>
<!-- category.endpoint: {{ category.endpoint }} -->
<a
:href="`/kind/${category.slug}`"
class="flex justify-start items-center inset-x-0 text-3xl md:text-4xl hover:bg-darkest border-2 border-white border-opacity-0 hover:border-opacity-50 focus:outline-none focus:bg-gray-50 duration-300 ease-in-out rounded-lg space-x-3 -mx-5 px-5 md:pr-64 py-3"
style="transition-property: border;"
>
<div class="font-hairline">
<div>{{ category.label }}</div>
<div class="text-xs opacity-75 mb-3">{{ category.appNames }}</div>
</div>
<div></div>
</a>
</li>
</ul>
</div>
</section>
</template>
<script>
import Search from '~/components/search.vue'
import LinkButton from '~/components/link-button.vue'
// import appList from '~/static/app-list.json'
// import gamelist from '~/static/game-list.json'
export default {
async asyncData () {
// const { default: appList } = await import('~/static/app-list.json')
// const { default: gamelist } = await import('~/static/game-list.json')
const { allList } = await import('~/helpers/get-list.js')
const { categories } = await import('~/helpers/categories.js')
// Map Categories into category list
const categoryList = Object.fromEntries(Object.entries(categories).map( ( entry ) => {
entry[1].appNamesList = []
return entry
} ))
// Delete no-category
delete categoryList['no-category']
allList.forEach( app => {
// Find and store all categories
// console.log('app.category.slug', app.category.slug)
if (categoryList.hasOwnProperty(app.category.slug)) {
categoryList[app.category.slug].appNamesList.push(app.name)
return
}
categoryList[app.category.slug] = {
// Merg in category data from app
...app.category,
// Merge in category data from category file
...categories[app.category.slug],
appNamesList: [ app.name ]
}
})
// Add App Names Text into categoryList
Object.keys(categoryList).map(function(key, index) {
const category = categoryList[key]
categoryList[key] = {
...category,
appNames: category.appNamesList.slice(0, 25).join(', ') + ', etc...'
}
})
// console.log('categoryList', categoryList)
return {
categoryList
}
},
components: {
Search,
LinkButton
},
data: function () {
return {}
},
// computed: {
// categoryList () {
// return categoryList
// }
// },
head() {
return {
title: `Categories of App Support for Apple Silicon - Does It ARM`,
// meta: [
// // hid is used as unique identifier. Do not use `vmid` for it as it will not work
// {
// hid: 'description',
// name: 'description',
// content: 'My custom description'
// }
// ]
}
}
}
</script>

View file

@ -1,225 +0,0 @@
<template>
<section class="container py-24">
<div class="flex flex-col items-center space-y-12">
<div class="summary space-y-6 max-w-2xl">
<h1 class="title text-3xl md:text-5xl font-hairline leading-tight text-center">
{{ device.name }}
</h1>
<div
v-if="device.description"
class="md:text-md text-center"
>
{{ device.description }}
</div>
<div
v-if="supportedAppList.length !== 0"
class="md:text-md text-center"
>
Supported apps include {{ supportedAppList.join(', ') }}.
</div>
<div class="flex justify-center py-3">
<LinkButton
v-if="device.amazonUrl"
:href="device.amazonUrl"
target="_blank"
>
Check Pricing
</LinkButton>
</div>
</div>
<div class="search-apps w-full flex flex-col items-center space-y-4">
<h2
class="subtitle md:text-lg font-bold text-center"
>
Search app support for {{ device.name }}
</h2>
<Search
:app-list="deviceAppList"
:quick-buttons="quickButtons"
:autofocus="false"
:initial-limit="50"
@update:query="query = $event"
>
<template v-slot:before-search>
<div class="empty-div" />
</template>
</Search>
</div>
<div class="flex flex-col md:flex-row space-x-0 space-y-4 md:space-y-0 md:space-x-4">
<LinkButton
:href="`https://github.com/ThatGuySam/doesitarm/issues?q=is%3Aissue+${query}`"
class="text-xs"
>
Request an App with Github
</LinkButton>
<LinkButton
:href="`https://twitter.com/DoesItARM/status/1330027384041508865`"
class="text-xs"
>
Request an App with Twitter
</LinkButton>
<LinkButton
:href="`/apple-silicon-app-test/`"
class="text-xs"
>
Scan Your Own App
</LinkButton>
</div>
</div>
</section>
</template>
<script>
import Search from '~/components/search.vue'
import LinkButton from '~/components/link-button.vue'
// import { categories } from '~/helpers/categories.js'
import { deviceSupportsApp } from '~/helpers/devices.js'
export default {
async asyncData ({ params: { slug } }) {
const { default: Chance } = await import('chance')
const { allList } = await import('~/helpers/get-list.js')
const { default: deviceList } = await import('~/static/device-list.json')
const charCode = slug.charCodeAt( slug.length-2 )
const shuffler = new Chance( charCode )
const device = deviceList.find( device => {
return device.slug === slug
})
// console.log( 'device', device )
const deviceAppList = allList.map( app => {
const appIsSupported = deviceSupportsApp( device, app )
return {
name: app.name,
status: app.status,
slug: app.slug,
// endpoint: app.endpoint,
text: appIsSupported ? `✅ Supported on ${device.name}` : `🚫 Not yet reported working on ${device.name}`,
lastUpdated: app.lastUpdated,
category: app.category,
// searchLinks: makeAppSearchLinks( app, (new Set(videoList)) )
}
})
const supportedApps = deviceAppList.filter( app => {
const supported = app.text.startsWith('✅')
const hasNotAllowedCategory = ([
'no-category',
'homebrew',
'games',
]).some( categorySlug => (app.category.slug === categorySlug) )
// console.log('hasNonStandardCategory', app.category.slug, hasNonStandardCategory)
return supported && !hasNotAllowedCategory
})
const featuredApps = shuffler.shuffle( supportedApps ).slice(0, 12)
// console.log('featuredApps', featuredApps[0])
return {
slug,
device,
featuredApps,
deviceAppList
}
},
components: {
Search,
LinkButton
},
data: function () {
return {
query: '',
quickButtons: []
}
},
computed: {
supportedAppList () {
return this.featuredApps.map(app => app.name)
},
title () {
return `App support list for ${this.device.name}`
},
description () {
return `Check the the latest reported support status of apps and software on ${this.device.name}.`
},
structuredData () {
return {
"@context": "https://schema.org",
// https://developers.google.com/search/docs/data-types/faqpage
// https://schema.org/FAQPage
"@type": "FAQPage",
"mainEntity": this.deviceAppList.map( app => {
return {
// https://schema.org/Question
"@type": "Question",
"name": `Does ${app.name} work on ${ this.device.name }?`,
"acceptedAnswer": {
// https://schema.org/Answer
"@type": "Answer",
"text": app.text
}
}
})
}
}
},
head() {
return {
title: this.title,
meta: [
// hid is used as unique identifier. Do not use `vmid` for it as it will not work
{
'hid': 'description',
'name': 'description',
'content': this.description
},
// Twitter Card
{
'hid': 'twitter:title',
'property': 'twitter:title',
'content': this.title
},
{
'hid': 'twitter:description',
'property': 'twitter:description',
'content': this.description
},
{
'property': 'twitter:url',
'content': `${process.env.URL}${this.$nuxt.$route.path}`
},
],
__dangerouslyDisableSanitizers: ['script'],
script: [{ innerHTML: JSON.stringify(this.structuredData), type: 'application/ld+json' }]
}
}
}
</script>

View file

@ -1,76 +0,0 @@
<template>
<section class="container py-24">
<div class="flex flex-col">
<h1 class="title text-2xl leading-tight mb-6">
Devices
</h1>
<div class="line-separator border-white border-t-2 mb-12" />
<!-- deviceList: {{ deviceList }} -->
<ul class="device-list space-y-3">
<li
v-for="(device, i) in deviceList"
:key="`${device.slug}-${i}`"
:ref="`${device.slug}-row`"
class="relative"
>
<!-- device.endpoint: {{ device.endpoint }} -->
<a
:href="device.endpoint"
class="flex justify-start items-center inset-x-0 text-3xl md:text-4xl hover:bg-darkest border-2 border-white border-opacity-0 hover:border-opacity-50 focus:outline-none focus:bg-gray-50 duration-300 ease-in-out rounded-lg space-x-3 -mx-5 px-5 md:pr-64 py-3"
style="transition-property: border;"
>
<div class="font-hairline">
<div>{{ device.name }}</div>
<!-- <div class="text-xs opacity-75 mb-3">{{ device.appNames }}</div> -->
</div>
<div></div>
</a>
</li>
</ul>
</div>
</section>
</template>
<script>
import LinkButton from '~/components/link-button.vue'
export default {
async asyncData () {
const { default: deviceList } = await import('~/static/device-list.json')
return {
deviceList
}
},
components: {
LinkButton
},
data: function () {
return {}
},
// computed: {
// deviceList () {
// return deviceList
// }
// },
head() {
return {
title: `Categories of App Support for Apple Silicon - Does It ARM`,
// meta: [
// // hid is used as unique identifier. Do not use `vmid` for it as it will not work
// {
// hid: 'description',
// name: 'description',
// content: 'My custom description'
// }
// ]
}
}
}
</script>

View file

@ -1,36 +0,0 @@
<template>
<AllUpdatesSubscribe
class="w-100 h-100 absolute inset-0 flex justify-center items-center"
/>
</template>
<script>
import AllUpdatesSubscribe from '~/components/all-updates-subscribe.vue'
export default {
layout: 'embed',
components: {
AllUpdatesSubscribe
},
data: function () {
return {}
},
head() {
return {
title: 'Subscribe',
// meta: [
// // hid is used as unique identifier. Do not use `vmid` for it as it will not work
// {
// hid: 'description',
// name: 'description',
// content: 'My custom description'
// }
// ]
}
}
}
</script>

View file

@ -1,80 +0,0 @@
<template>
<VideoPlayer
v-if="youtubeId !== null"
:video="video"
class="w-100 h-100 absolute inset-0 flex justify-center items-center"
>
<template v-slot:cover-bottom>
<div class="page-heading h-full flex items-end md:p-4">
<h1 class="title text-xs text-left md:text-2xl font-bold">
{{ video.name }}
</h1>
</div>
</template>
</VideoPlayer>
</template>
<script>
import VideoPlayer from '~/components/video/player.vue'
export default {
layout: 'embed',
components: {
VideoPlayer
},
data: function () {
return {
youtubeId: null,
name: ''
}
},
computed: {
video () {
return {
name: this.name,
id: this.youtubeId,
timestamps: [],
thumbnail: {
sizes: '(max-width: 640px) 100vw, 640px',
srcset: `https://i.ytimg.com/vi/${this.youtubeId}/default.jpg 120w, https://i.ytimg.com/vi/${this.youtubeId}/mqdefault.jpg 320w, https://i.ytimg.com/vi/${this.youtubeId}/hqdefault.jpg 480w, https://i.ytimg.com/vi/${this.youtubeId}/sddefault.jpg 640w`,
src: `https://i.ytimg.com/vi/${this.youtubeId}/default.jpg`
},
}
}
},
head() {
return {
title: 'Video - Does It ARM',
// meta: [
// // hid is used as unique identifier. Do not use `vmid` for it as it will not work
// {
// hid: 'description',
// name: 'description',
// content: 'My custom description'
// }
// ]
}
},
mounted () {
// this.youtubeId = 'NDwmqJYJq9s'
// console.log('window', window)
if ( process.client ) {
const urlParams = new URLSearchParams(window.location.search)
this.youtubeId = urlParams.get('youtube-id')
this.name = urlParams.get('name')
}
// console.log('this.youtubeId', this.youtubeId)
}
}
</script>

View file

@ -1,84 +0,0 @@
<template>
<section class="container py-32">
<div class="flex flex-col items-center text-center">
<h1 class="title text-sm md:text-2xl font-bold">
Does <code>{{ app.name }}</code> work on Apple Silicon when installed via Homebrew?
</h1>
<h2 class="subtitle text-2xl md:text-5xl font-bold py-6">
{{ app.text }}
</h2>
<small class="data-credit text-sm opacity-75 text-center mb-4">
<span>According to Github</span>
</small>
<div
class="comments text-sm mb-8"
v-html="app.content"
/>
<div class="links space-y-6 sm:space-x-6 mb-8">
<LinkButton
v-for="(link, i) in app.relatedLinks"
:key="i"
:href="link.href"
target="_blank"
class=""
>{{ (i === 0) ? 'View' : link.label }}</LinkButton>
</div>
</div>
</section>
</template>
<script>
import LinkButton from '~/components/link-button.vue'
// import EmailSubscribe from '~/components/email-subscribe.vue'
// import homebrewList from '~/static/homebrew-list.json'
export default {
components: {
LinkButton,
// EmailSubscribe
},
async asyncData ({ params: { slug }, payload: { app } }) {
return {
slug,
app//: homebrewList.find(app => (app.slug === slug))
}
},
head() {
return {
title: `Does ${this.app.name} work on Apple Silicon?`,
meta: [
// hid is used as unique identifier. Do not use `vmid` for it as it will not work
{
'hid': 'description',
'name': 'description',
'content': `Check the the latest reported support status of ${this.app.name} on Apple Silicon and Apple M1 Processors when installed via Homebrew. `
},
// Twitter Card
{
'hid': 'twitter:title',
'property': 'twitter:title',
'content': `Does ${this.app.name} work on Apple Silicon?`
},
{
'hid': 'twitter:description',
'property': 'twitter:description',
'content': `Check the the latest reported support status of ${this.app.name} on Apple Silicon and Apple M1 Processors when installed via Homebrew. `
},
{
'property': 'twitter:url',
'content': `${process.env.URL}${this.$nuxt.$route.path}`
},
]
}
}
}
</script>

View file

@ -1,226 +0,0 @@
<template>
<section class="container pb-16">
<div class="flex flex-col items-center text-center space-y-8">
<template
v-if="video"
>
<VideoPlayer
:video="video"
class="pt-16"
/>
<ChannelCredit
:video="video"
class="flex w-full justify-start md:px-10"
/>
</template>
<template v-else>
<div
:style="{
'left': '50%',
'right': '50%',
'margin-left': '-50vw',
'margin-right': '-50vw'
}"
class="video-canvas w-screen flex justify-center bg-black pt-16"
>
<div class="ratio-wrapper w-full max-w-4xl">
<div class="relative overflow-hidden w-full pb-16/9">
<div class="absolute h-full w-full flex justify-center items-center">
<div class="message text-4xl md:text-6xl font-hairline leading-tight text-center">No videos yet</div>
</div>
</div>
</div>
</div>
</template>
<div
v-for="(row, key) in videoRows"
:key="key"
class="w-full max-w-4xl"
>
<div
v-if="row.videos.length !== 0"
:class="`${key}-videos w-full`"
>
<h2 class="subtitle text-xl md:text-2xl font-bold mb-3">
{{ row.heading }}
</h2>
<!-- <pre class="text-left">{{ benchmarkVideos }}</pre> -->
<VideoRow
:videos="row.videos"
:active-video-id="activeVideoId"
/>
</div>
</div>
</div>
</section>
</template>
<script>
import LinkButton from '~/components/link-button.vue'
import EmailSubscribe from '~/components/email-subscribe.vue'
import VideoRow from '~/components/video/row.vue'
import VideoPlayer from '~/components/video/player.vue'
import ChannelCredit from '~/components/video/channel-credit.vue'
export default {
components: {
LinkButton,
EmailSubscribe,
VideoRow,
VideoPlayer,
ChannelCredit
},
asyncData ({ params: { slug }, payload: { app, allVideos } }) {
// const { allVideoAppsList } = await import('~/helpers/get-list.js')
// const { default: videoList } = await import('~/static/video-list.json')
// const { videosRelatedToApp } = await import('~/helpers/related.js')
// const app = allVideoAppsList.find(app => (app.slug === slug))
// // const submitVideoCard = {
// // endpoint: `https://docs.google.com/forms/d/e/1FAIpQLSeEVGM9vE7VcfLMy6fJkfU70X2VZ60rHDyhDQLtnAN4nso0WA/viewform?usp=pp_url&entry.1018125313=${app.name}`
// // }
// // const featuredApps = []
// const relatedVideos = videosRelatedToApp( app, videoList ).map(video => {
// // console.log('video', video)
// return {
// ...video,
// // endpoint: `#${video.id}`
// }
// })
// console.log({
// app,
// allVideos,
// // submitVideoCard
// })
return {
app,
allVideos,
// submitVideoCard
}
},
data: function () {
return {
activeVideoIndex: 0,
videoRows: {
'benchmarks': {
heading: 'Benchmark Videos',
matchesCondition: video => video.tags.includes('benchmark'),
videos: []
},
'performance': {
heading: 'Performance Videos',
matchesCondition: video => video.tags.includes('performance'),
videos: []
},
'other': {
heading: 'More Videos',
// Always true
matchesCondition: () => true,
videos: []
}
}
}
},
computed: {
video () {
return this.allVideos[this.activeVideoIndex]
},
title () {
return `${this.app.name} Benchmarks for Apple Silicon - Does It ARM`
},
description () {
return `Apple Silicon gaming benchmark, performance, and support videos for ${this.app.name}`
},
activeVideoId () {
return (this.video === Object(this.video)) ? this.video.id : null
}
},
created () {
// Move videos to relevant categories
this.allVideos.forEach((video, index) => {
// console.log('video.name', video.name)
// console.log('video.tags', video.tags)
// Look through row conditions to see if video matches
for (const row in this.videoRows) {
if( this.videoRows[row].matchesCondition(video) ) {
// Add the matching video
this.videoRows[row].videos.push(video)
return
}
}
})
// console.log('lengths', Object.values(this.videoRows).map(row => [row.heading, row.videos.length]))
},
mounted () {
window.onhashchange = this.loadVideoFromHash
if (location.hash.length !== 0) this.loadVideoFromHash()
},
methods: {
loadVideoFromHash () {
// console.log('location.hash', location.hash)
// Separate the video id from our window hash
const hashId = location.hash.split('#')[1]
// Find the index of the video with the matching hash
const newVideoIndex = this.allVideos.findIndex(video => {
return video.id === hashId
})
console.log('newVideoIndex', newVideoIndex)
// Load in the index to load out video
this.activeVideoIndex = newVideoIndex
window.scroll({ top: 0, behavior: 'smooth' })
}
},
head() {
return {
title: this.title,
meta: [
// hid is used as unique identifier. Do not use `vmid` for it as it will not work
{
'hid': 'description',
'name': 'description',
'content': this.description
},
// Twitter Card
{
'hid': 'twitter:title',
'property': 'twitter:title',
'content': this.title
},
{
'hid': 'twitter:description',
'property': 'twitter:description',
'content': this.description
},
{
'property': 'twitter:url',
'content': `${process.env.URL}${this.$nuxt.$route.path}`
},
]
}
}
}
</script>

View file

@ -1,178 +0,0 @@
<template>
<section class="container py-32">
<div class="flex flex-col items-center text-center">
<div class="intro-content flex flex-col items-center text-center min-h-3/4-screen md:min-h-0">
<h1 class="title text-sm md:text-2xl font-bold">
Does {{ app.name }} work on Apple Silicon?
</h1>
<h2 class="subtitle text-2xl md:text-5xl font-bold py-6">
{{ app.text }}
</h2>
<ThomasCredit />
</div>
<div
v-if="relatedVideos.length !== 0"
class="related-videos w-full"
>
<h2 class="subtitle text-xl md:text-2xl font-bold mb-3">
Related Videos
</h2>
<VideoRow
:videos="relatedVideos"
/>
</div>
<h2 class="subtitle text-xl md:text-2xl font-bold py-6">
Reports
</h2>
<ul class="flex flex-col md:flex-row space-x-0 space-y-4 md:space-y-0 md:space-x-4 mb-4">
<li
v-for="(report, i) in app.reports"
:key="`${app.slug}-${i}`"
class="col-span-1 rounded-lg border w-full md:w-64"
>
<div class="w-full flex items-center justify-between p-6">
<div class="flex-1">
<div class="space-x-3">
<h3 class="text-sm leading-5 font-bold">{{ report['Specs'] }}</h3>
<span class="flex-shrink-0 inline-block px-2 py-0.5 text-teal-800 text-xs leading-4 font-bold bg-teal-100 rounded-full">{{ report['FPS'] }}</span>
</div>
<p class="mt-1 text-sm leading-5">{{ report['Notes'] }}</p>
<p
v-if="report['Resolution'].length !== 0"
class="mt-1 text-sm leading-5"
>
🖥 {{ report['Resolution'] }}
</p>
<p
v-if="report['Settings'].length !== 0"
class="mt-1 text-sm leading-5"
>
{{ report['Settings'] }}
</p>
</div>
</div>
<div
v-if="report['Source'].includes('https://')"
class="border-t border-gray-200"
>
<div class="-mt-px flex">
<div class="w-0 flex-1 flex border-r border-gray-200">
<a
:href="report['Source']"
class="relative -mr-px w-0 flex-1 inline-flex items-center justify-center py-4 text-sm leading-5 font-bold border border-transparent rounded-bl-lg hover:text-gray-500 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 transition ease-in-out duration-150"
>
<!-- Heroicon name: mail -->
<svg
class="w-5 h-5"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
>
<path d="M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z" />
<path d="M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z" />
</svg>
<span class="ml-3 opacity-75">Source</span>
</a>
</div>
</div>
</div>
</li>
</ul>
<div class="report-links py-24 shadow-none">
<!-- https://eric.blog/2016/01/08/prefilling-github-issues/ -->
<a
:href="`https://forms.gle/29GWt85i1G1L7Ttj8`"
target="_blank"
class="text-xs"
rel="noopener"
>Report Update</a>
</div>
</div>
</section>
</template>
<script>
import { getAppEndpoint } from '~/helpers/app-derived.js'
import VideoRow from '~/components/video/row.vue'
import LinkButton from '~/components/link-button.vue'
import ThomasCredit from '~/components/thomas-credit.vue'
export default {
components: {
VideoRow,
LinkButton,
ThomasCredit
},
async asyncData ({ params: { slug } }) {
const { default: gameList } = await import('~/static/game-list.json')
const { default: videoList } = await import('~/static/video-list.json')
const { videosRelatedToApp } = await import('~/helpers/related.js')
const app = gameList.find(app => (app.slug === slug))
const relatedVideos = videosRelatedToApp( app, (new Set(videoList)) )
// Find other videos that also feature this video's app
// for (const video of videoList) {
// if (!video.apps.includes(app.slug)) continue
// relatedVideos.push(video)
// }
return {
slug,
app,
relatedVideos: relatedVideos.map(video => {
// console.log('video', video)
return {
...video,
endpoint: `${getAppEndpoint(app)}/benchmarks#${video.id}`
}
})
}
},
head() {
return {
title: `Does ${this.app.name} work on Apple Silicon?`,
meta: [
// hid is used as unique identifier. Do not use `vmid` for it as it will not work
{
'hid': 'description',
'name': 'description',
'content': `Check the the latest reported support status of ${this.app.name} on Apple Silicon and Apple M1 Processors for gaming. `
},
// Twitter Card
{
'hid': 'twitter:title',
'property': 'twitter:title',
'content': `Does ${this.app.name} work on Apple Silicon?`
},
{
'hid': 'twitter:description',
'property': 'twitter:description',
'content': `Check the the latest reported support status of ${this.app.name} on Apple Silicon and Apple M1 Processors for gaming. `
},
{
'property': 'twitter:url',
'content': `${process.env.URL}${this.$nuxt.$route.path}`
},
]
}
}
}
</script>

View file

@ -1,102 +0,0 @@
<template>
<section class="container py-24">
<div class="flex flex-col items-center">
<h1 class="title text-4xl md:text-6xl font-hairline leading-tight text-center">
Does It ARM?
</h1>
<h2 class="subtitle md:text-xl text-center">
Games that are reported to support Apple Silicon
</h2>
<ThomasCredit />
<Search
:app-list="gameList"
:quick-buttons="quickButtons"
no-email-subscribe
@update:query="query = $event"
/>
<LinkButton
:href="`https://forms.gle/29GWt85i1G1L7Ttj8`"
>
Report a Game
</LinkButton>
</div>
</section>
</template>
<script>
import Search from '~/components/search.vue'
import LinkButton from '~/components/link-button.vue'
import ThomasCredit from '~/components/thomas-credit.vue'
import gameList from '~/static/game-list.json'
export default {
async asyncData () {
const { sortedAppList, allList, allVideoAppsList, makeAppSearchLinks } = await import('~/helpers/get-list.js')
const { default: gameList } = await import('~/static/game-list.json')
const { default: videoList } = await import('~/static/video-list.json')
return {
// Map game list
gameList: gameList.map( app => {
return {
name: app.name,
status: app.status,
slug: app.slug,
// endpoint: app.endpoint,
text: app.text,
lastUpdated: app.lastUpdated,
category: app.category,
searchLinks: makeAppSearchLinks( app, (new Set(videoList)) )
}
})
}
},
components: {
Search,
LinkButton,
ThomasCredit
},
data: function () {
return {
query: '',
quickButtons: [
{
label: '✅ Full Native Support',
query: 'status:native'
},
{
label: '✳️ Rosetta',
query: 'status:rosetta'
},
{
label: '🚫 Unsupported',
query: 'status:no'
}
]
}
},
computed: {
// gameList() {
// return gameList
// }
},
head() {
return {
title: `Games supported on Apple Silicon - Does It ARM`,
// meta: [
// // hid is used as unique identifier. Do not use `vmid` for it as it will not work
// {
// hid: 'description',
// name: 'description',
// content: 'My custom description'
// }
// ]
}
}
}
</script>

View file

@ -1,263 +0,0 @@
<template>
<section class="container py-24">
<div class="flex flex-col items-center">
<h1 class="title text-4xl md:text-6xl font-hairline leading-tight text-center">
Does It ARM?
</h1>
<h2 class="subtitle md:text-xl text-center">
Apps that are reported to support Apple Silicon
</h2>
<Search
:app-list="allList"
:quick-buttons="quickButtons"
:initial-limit="100"
@update:query="onQueryUpdate"
>
<template v-slot:before-search>
<div class="list-summary-wrapper flex justify-center text-center text-sm my-4">
<ListSummary
:custom-numbers="customSummaryNumbers"
class="max-w-4xl"
/>
</div>
</template>
</Search>
<div class="flex flex-col md:flex-row space-x-0 space-y-4 md:space-y-0 md:space-x-4">
<LinkButton
:href="`https://github.com/ThatGuySam/doesitarm/issues?q=is%3Aissue+${query}`"
class="text-xs"
>
Request an App with Github
</LinkButton>
<LinkButton
:href="`https://twitter.com/DoesItARM/status/1330027384041508865`"
class="text-xs"
>
Request an App with Twitter
</LinkButton>
<LinkButton
:href="`/apple-silicon-app-test/`"
class="text-xs"
>
Scan Your Own App
</LinkButton>
</div>
<AllUpdatesSubscribe
:input-class-groups="{
shadow: 'hover:neumorphic-shadow',
bg: '',
focus: 'bg-transparent neumorphic-shadow pl-8',
blur: 'placeholder-white text-center border border-transparent bg-transparent opacity-50 hover:opacity-100 px-3',
}"
class="my-12"
/>
</div>
</section>
</template>
<script>
import axios from 'axios'
import getListSummaryNumbers from '~/helpers/get-list-summary-numbers.js'
import Search from '~/components/search.vue'
import LinkButton from '~/components/link-button.vue'
import AllUpdatesSubscribe from '~/components/all-updates-subscribe.vue'
import ListSummary from '~/components/list-summary.vue'
export default {
async asyncData () {
// const { default: appList } = await import('~/static/app-list.json')
// const { default: gamelist } = await import('~/static/game-list.json')
const { sortedAppList, allList, allVideoAppsList, makeAppSearchLinks } = await import('~/helpers/get-list.js')
const { default: videoList } = await import('~/static/video-list.json')
const allAppSearchLinks = {}
// console.log('allVideoAppsList', allVideoAppsList)
allVideoAppsList.forEach( app => {
// Make the search links
const searchLinks = makeAppSearchLinks( app, (new Set(videoList)) )
// If there are more than zero
// add them to our list
if (searchLinks.length > 0) {
allAppSearchLinks[app.slug] = searchLinks
}
})
return {
// Filter app list to leave out data not needed for search
initialAppList: sortedAppList.map( app => {
const searchLinks = allAppSearchLinks?.[app.slug] || []
// if (typeof allAppSearchLinks[app.slug] !== 'undefined') {
// searchLinks = allAppSearchLinks[app.slug]
// }
return {
name: app.name,
status: app.status,
slug: app.slug,
// endpoint: app.endpoint,
text: app.text,
lastUpdated: app.lastUpdated,
category: app.category,
searchLinks
}
}),
allAppSearchLinks,
customSummaryNumbers: getListSummaryNumbers(allList)
}
},
components: {
Search,
LinkButton,
AllUpdatesSubscribe,
ListSummary
},
data: function () {
return {
query: '',
fetchedAppList: [],
quickButtons: [
{
label: '✅ Full Native Support',
query: 'status:native'
},
{
label: '✳️ Rosetta',
query: 'status:rosetta'
},
{
label: '🚫 Unsupported',
query: 'status:no'
},
{
label: '🎮 Games',
query: 'Games'
},
{
label: '🍺 Homebrew Formulae',
query: 'Homebrew'
},
{
label: 'Music Tools',
query: 'Music'
},
{
label: 'Developer Tools',
query: 'Developer'
},
{
label: 'Photo Tools',
query: 'Photo'
},
{
label: 'Video Tools',
query: 'Video'
},
{
label: 'Productivity Tools',
query: 'Productivity'
},
]
}
},
computed: {
title () {
return `Apple Silicon and Apple M1 app and game compatibility list`
},
description () {
return `List of compatibility apps and games for Apple Silicon and the Apple M1 including performance reports and benchmarks`
},
allList () {
return [
...this.initialAppList,
...this.fetchedAppList
]
}
},
methods: {
async onQueryUpdate ( $event ) {
// console.log('$event', $event)
this.query = $event
// If fetched lists have already been loaded in
// OR if there's no query
// then stop
if (this.fetchedAppList.length !== 0 || this.query.trim().length === 0) return
// console.log('this.allAppSearchLinks', this.allAppSearchLinks)
const fetchedListUrls = [
'/game-list.json',
'/homebrew-list.json'
]
const fetchedLists = await Promise.all(fetchedListUrls.map( async listUrl => {
// Fetch List
const response = await axios.get(listUrl)
// Extract apps from response data
const fetchedApps = response.data
return fetchedApps
}))
// console.log('fetchedLists', fetchedLists)
this.fetchedAppList = fetchedLists.flat(1).map( app => {
const searchLinks = this.allAppSearchLinks?.[app.slug] || []
return {
...app,
searchLinks
}
})
return
}
},
head() {
return {
title: this.title,
meta: [
// hid is used as unique identifier. Do not use `vmid` for it as it will not work
{
'hid': 'description',
'name': 'description',
'content': this.description
},
// Twitter Card
{
'hid': 'twitter:title',
'property': 'twitter:title',
'content': this.title
},
{
'hid': 'twitter:description',
'property': 'twitter:description',
'content': this.description
},
{
'property': 'twitter:url',
'content': `${process.env.URL}${this.$nuxt.$route.path}`
},
]
}
}
}
</script>

View file

@ -1,202 +0,0 @@
<template>
<section class="container py-24">
<div class="flex flex-col items-center">
<h1 class="title text-3xl md:text-5xl font-hairline leading-tight text-center pb-4">
{{ pluralLabel }} that are reported to support Apple Silicon
</h1>
<h2
v-if="supportedAppList.length !== 0"
class="subtitle md:text-xl text-center"
>
Supported apps include {{ supportedAppList.join(', ') }}.
</h2>
<Search
:app-list="categoryAppList"
:quick-buttons="quickButtons"
@update:query="query = $event"
/>
<div class="flex flex-col md:flex-row space-x-0 space-y-4 md:space-y-0 md:space-x-4">
<template v-if="category.requestLinks">
<LinkButton
v-for="link in category.requestLinks"
:key="link.label"
:href="link.href"
class="text-xs"
>
{{ link.label }}
</LinkButton>
</template>
<template v-else>
<LinkButton
:href="`https://github.com/ThatGuySam/doesitarm/issues?q=is%3Aissue+${query}`"
class="text-xs"
>
Request an App with Github
</LinkButton>
<LinkButton
:href="`https://twitter.com/DoesItARM/status/1330027384041508865`"
class="text-xs"
>
Request an App with Twitter
</LinkButton>
<LinkButton
:href="`/apple-silicon-app-test/`"
class="text-xs"
>
Scan Your Own App
</LinkButton>
</template>
</div>
</div>
</section>
</template>
<script>
import Search from '~/components/search.vue'
import LinkButton from '~/components/link-button.vue'
import { categories, getAppCategory } from '~/helpers/categories.js'
export default {
async asyncData ({ params: { slug } }) {
const { sortedAppList, allList, allVideoAppsList, makeAppSearchLinks } = await import('~/helpers/get-list.js')
const { default: gameList } = await import('~/static/game-list.json')
const { default: videoList } = await import('~/static/video-list.json')
const filteredList = allList.filter(app => {
return app.category.slug === slug
})
return {
slug,
categoryAppList: filteredList.map( app => {
return {
name: app.name,
status: app.status,
slug: app.slug,
// endpoint: app.endpoint,
text: app.text,
lastUpdated: app.lastUpdated,
category: app.category,
searchLinks: makeAppSearchLinks( app, (new Set(videoList)) )
}
})
}
},
components: {
Search,
LinkButton
},
data: function () {
return {
query: '',
quickButtons: [
{
label: '✅ Full Native Support',
query: 'status:native'
},
{
label: '✳️ Rosetta',
query: 'status:rosetta'
},
{
label: '🚫 Unsupported',
query: 'status:no'
},
]
}
},
computed: {
category () {
if ( categories.hasOwnProperty( this.slug ) ) {
return categories[this.slug]
}
// Try to find the category info within the passed apps
const appWithCategory = this.categoryAppList.find( app => {
return app.category.slug === this.slug
})
// console.log('appWithCategory', appWithCategory)
return appWithCategory.category
},
pluralLabel () {
if ( this.category.hasOwnProperty('pluralLabel') ) {
return this.category.pluralLabel
}
return this.category.label
},
supportedAppList () {
return this.categoryAppList.filter(app => {
return app.status.includes('yes')
}).map(app => app.name)
},
title () {
return `List of ${this.pluralLabel || this.category.label} that work on Apple Silicon?`
},
description () {
return `Check the the latest reported support status of ${this.pluralLabel || this.category.label} on Apple Silicon and Apple M1 Processors. `
},
structuredData () {
return {
"@context": "https://schema.org",
// https://developers.google.com/search/docs/data-types/faqpage
// https://schema.org/FAQPage
"@type": "FAQPage",
"mainEntity": this.categoryAppList.map( app => {
return {
// https://schema.org/Question
"@type": "Question",
"name": `Does ${app.name} work on Apple Silicon and Apple M1 Macs?`,
"acceptedAnswer": {
// https://schema.org/Answer
"@type": "Answer",
"text": app.text
}
}
})
}
}
},
head() {
return {
title: this.title,
meta: [
// hid is used as unique identifier. Do not use `vmid` for it as it will not work
{
'hid': 'description',
'name': 'description',
'content': this.description
},
// Twitter Card
{
'hid': 'twitter:title',
'property': 'twitter:title',
'content': this.title
},
{
'hid': 'twitter:description',
'property': 'twitter:description',
'content': this.description
},
{
'property': 'twitter:url',
'content': `${process.env.URL}${this.$nuxt.$route.path}`
},
],
__dangerouslyDisableSanitizers: ['script'],
script: [{ innerHTML: JSON.stringify(this.structuredData), type: 'application/ld+json' }]
}
}
}
</script>

View file

@ -1,32 +0,0 @@
<template>
<section class="container py-24">
<!-- __template -->
</section>
</template>
<script>
export default {
data: function () {
return {}
},
// computed: {
// categoryList () {
// return categoryList
// }
// },
head() {
return {
title: '__template',
// meta: [
// // hid is used as unique identifier. Do not use `vmid` for it as it will not work
// {
// hid: 'description',
// name: 'description',
// content: 'My custom description'
// }
// ]
}
}
}
</script>

View file

@ -1,189 +0,0 @@
<template>
<section class="container pb-16">
<div class="flex flex-col items-center text-center space-y-6">
<VideoPlayer
:video="video"
class="pt-16"
>
<template v-slot:cover-bottom>
<div class="page-heading h-full flex items-end md:p-4">
<h1 class="title text-xs text-left md:text-2xl font-bold">
{{ video.name }}
</h1>
</div>
</template>
</VideoPlayer>
<div
class="md:flex w-full justify-between space-y-4 md:space-y-0 md:px-10"
>
<!-- <h1 class="title text-lg md:text-2xl font-bold">
{{ video.name }}
</h1> -->
<ChannelCredit
:video="video"
/>
</div>
<hr class="w-full" >
<div
v-if="featuredApps.length !== 0"
class="related-apps w-full"
>
<h2 class="subtitle text-xl md:text-2xl font-bold mb-3">
Related Apps
</h2>
<div class="featured-apps overflow-x-auto overflow-y-visible whitespace-no-wrap py-2 space-x-2">
<LinkButton
v-for="app in featuredApps"
:key="app.slug"
:href="getAppEndpoint(app)"
:class="[
'inline-block text-xs rounded-lg py-1 px-2',
]"
:class-groups="{
shadow: 'neumorphic-shadow-inner'
}"
>{{ app.name }}</LinkButton>
</div>
</div>
<div class="related-videos w-full">
<h2 class="subtitle text-xl md:text-2xl font-bold mb-3">
Related Videos
</h2>
<VideoRow
:videos="relatedVideos"
/>
</div>
<!-- video: {{ video }} -->
<!-- <div class="links space-y-6 sm:space-x-6 mb-8">
<LinkButton
v-for="(link, i) in app.relatedLinks"
:key="i"
:href="link.href"
target="_blank"
class=""
>{{ (i === 0) ? 'View' : link.label }}</LinkButton>
</div> -->
</div>
</section>
</template>
<script>
import { getAppEndpoint } from '~/helpers/app-derived.js'
import { buildVideoStructuredData } from '~/helpers/structured-data.js'
import LinkButton from '~/components/link-button.vue'
import EmailSubscribe from '~/components/email-subscribe.vue'
import VideoRow from '~/components/video/row.vue'
import VideoPlayer from '~/components/video/player.vue'
import ChannelCredit from '~/components/video/channel-credit.vue'
function makeFeaturedAppsString ( featuredApps ) {
return featuredApps.slice(0, 5).map(app => app.name).join(', ')
}
export default {
components: {
LinkButton,
EmailSubscribe,
VideoRow,
VideoPlayer,
ChannelCredit
},
async asyncData ( data ) {
const {
params: { slug },
route
} = data
let {
payload
} = data
// Manually get payload as fallback
// Uncomment for dev
// if ( payload === undefined ) {
// // Read back the JSON we just wrote to ensure it exists
// const { default: savedList } = await import('~/static/nuxt-endpoints.json')
// const endpoint = savedList.find( resource => {
// return resource.route === route.path
// } )
// payload = endpoint.payload
// }
return {
video: payload.video,
featuredApps: payload.featuredApps,
relatedVideos: payload.relatedVideos
}
},
computed: {
title () {
return `${this.video.name} - Does It ARM`
},
description () {
const featuredAppsString = makeFeaturedAppsString( this.featuredApps )
return `Apple Silicon performance and support videos for ${featuredAppsString}`
},
},
methods: {
getAppEndpoint
},
head() {
const structuredData = buildVideoStructuredData( this.video, this.featuredApps, {
siteUrl: this.$config.siteUrl
} )
return {
title: this.title,
meta: [
// hid is used as unique identifier. Do not use `vmid` for it as it will not work
{
'hid': 'description',
'name': 'description',
'content': this.description
},
// Twitter Card
{
'hid': 'twitter:title',
'property': 'twitter:title',
'content': this.title
},
{
'hid': 'twitter:description',
'property': 'twitter:description',
'content': this.description
},
{
'property': 'twitter:url',
'content': `${process.env.URL}${this.$nuxt.$route.path}`
},
],
__dangerouslyDisableSanitizers: ['script'],
script: [{ innerHTML: JSON.stringify( structuredData ), type: 'application/ld+json' }]
}
}
}
</script>