mirror of
https://github.com/ThatGuySam/doesitarm.git
synced 2026-05-18 06:44:46 -07:00
Merge branch 'feat/app-dates'
This commit is contained in:
commit
fa673232ad
7 changed files with 180 additions and 8 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -86,3 +86,4 @@ dist
|
||||||
/README-temp.md
|
/README-temp.md
|
||||||
/game-list.json
|
/game-list.json
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
/commits-data.json
|
||||||
|
|
|
||||||
24
components/relative-time.vue
Normal file
24
components/relative-time.vue
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<template>
|
||||||
|
|
||||||
|
<span>{{ relativeTime }}</span>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import parseGithubDate from '~/helpers/parse-github-date'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
timestamp: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
relativeTime () {
|
||||||
|
return parseGithubDate(this.timestamp).relative
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
@ -62,16 +62,25 @@
|
||||||
<div class="flex-shrink-0 h-12 w-12 rounded-full flex items-center justify-center bg-darker">
|
<div class="flex-shrink-0 h-12 w-12 rounded-full flex items-center justify-center bg-darker">
|
||||||
{{ app.name.charAt(0) }}
|
{{ app.name.charAt(0) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="min-w-0 flex-1 px-4 md:mr-48">
|
<div class="min-w-0 flex-1 px-4 md:mr-48 space-y-2">
|
||||||
<div class="text-sm leading-5 font-light truncate">
|
<div class="text-sm leading-5 font-light truncate">
|
||||||
<span v-if="app.endpoint.includes('/game/')">
|
<span v-if="app.endpoint.includes('/game/')">
|
||||||
🕹
|
🕹
|
||||||
</span>
|
</span>
|
||||||
{{ app.name }}
|
{{ app.name }}
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2 flex items-center text-sm leading-5 text-gray-500 overflow-hidden">
|
<div class="flex items-center text-sm leading-5 text-gray-500 overflow-hidden">
|
||||||
{{ app.text }}
|
{{ app.text }}
|
||||||
</div>
|
</div>
|
||||||
|
<!-- app.lastUpdated: {{ app.lastUpdated }} -->
|
||||||
|
<client-only
|
||||||
|
v-if="app.lastUpdated"
|
||||||
|
placeholder="Loading..."
|
||||||
|
>
|
||||||
|
<small class="text-xs opacity-50">
|
||||||
|
<RelativeTime :timestamp="app.lastUpdated.timestamp" />
|
||||||
|
</small>
|
||||||
|
</client-only>
|
||||||
</div>
|
</div>
|
||||||
<svg
|
<svg
|
||||||
class="h-5 w-5 text-gray-400"
|
class="h-5 w-5 text-gray-400"
|
||||||
|
|
@ -122,6 +131,7 @@ import scrollIntoView from 'scroll-into-view-if-needed'
|
||||||
// import appList from '~/app-list.json'
|
// import appList from '~/app-list.json'
|
||||||
|
|
||||||
import EmailSubscribe from '~/components/email-subscribe.vue'
|
import EmailSubscribe from '~/components/email-subscribe.vue'
|
||||||
|
import RelativeTime from '~/components/relative-time.vue'
|
||||||
|
|
||||||
// import overlayStore from './mixins/store'
|
// import overlayStore from './mixins/store'
|
||||||
// import modalRouter from '~/components/modals/mixins/router'
|
// import modalRouter from '~/components/modals/mixins/router'
|
||||||
|
|
@ -133,7 +143,8 @@ import EmailSubscribe from '~/components/email-subscribe.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
EmailSubscribe
|
EmailSubscribe,
|
||||||
|
RelativeTime
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
appList: {
|
appList: {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
import { promises as fs } from 'fs'
|
import { promises as fs } from 'fs'
|
||||||
import MarkdownIt from 'markdown-it'
|
import MarkdownIt from 'markdown-it'
|
||||||
import slugify from 'slugify'
|
import slugify from 'slugify'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
import parseGithubDate from './parse-github-date'
|
||||||
|
|
||||||
|
|
||||||
const md = new MarkdownIt()
|
const md = new MarkdownIt()
|
||||||
|
|
@ -14,6 +17,7 @@ export const statuses = {
|
||||||
'🚫': 'no'
|
'🚫': 'no'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const getTokenLinks = function ( childTokens ) {
|
const getTokenLinks = function ( childTokens ) {
|
||||||
|
|
||||||
const tokenList = []
|
const tokenList = []
|
||||||
|
|
@ -53,12 +57,60 @@ const getTokenLinks = function ( childTokens ) {
|
||||||
return tokenList
|
return tokenList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const lookForLastUpdated = function (app, commits) {
|
||||||
|
|
||||||
|
for (const { node: commit } of commits) {
|
||||||
|
|
||||||
|
// console.log('commit', commit)
|
||||||
|
|
||||||
|
// $$ If message body contains endpoint
|
||||||
|
if (commit.messageBody.includes(app.endpoint)) {
|
||||||
|
// console.log('Found', app.name ,commit.committedDate)
|
||||||
|
return commit.committedDate
|
||||||
|
}
|
||||||
|
|
||||||
|
// $$ If message body contains App Name
|
||||||
|
if (commit.messageBody.includes(app.name)) {
|
||||||
|
// console.log('Found', app.name ,commit.committedDate)
|
||||||
|
return commit.committedDate
|
||||||
|
}
|
||||||
|
|
||||||
|
// $$ If message headline contains App Name
|
||||||
|
if (commit.messageHeadline.includes(app.name)) {
|
||||||
|
// console.log('Found', app.name ,commit.committedDate)
|
||||||
|
return commit.committedDate
|
||||||
|
}
|
||||||
|
|
||||||
|
// $$$ If commits comments contains endpoint
|
||||||
|
for (const { node: comment } of commit.comments.edges) {
|
||||||
|
if (comment.body.includes(app.endpoint)) {
|
||||||
|
// console.log('Found', app.name ,commit.committedDate)
|
||||||
|
return commit.committedDate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export default async function () {
|
export default async function () {
|
||||||
|
|
||||||
const readmeContent = await fs.readFile('./README-temp.md', 'utf8')
|
const readmeContent = await fs.readFile('./README-temp.md', 'utf8')
|
||||||
|
|
||||||
// console.log('readmeContent', readmeContent)
|
// console.log('readmeContent', readmeContent)
|
||||||
|
|
||||||
|
// Fetch Commits
|
||||||
|
const response = await axios.get(process.env.COMMITS_SOURCE)
|
||||||
|
// Extract commit from response data
|
||||||
|
const commits = response.data.data.viewer.repository.defaultBranchRef.target.history.edges
|
||||||
|
// console.log('commits', commits)
|
||||||
|
|
||||||
|
// Save commits to file just in case
|
||||||
|
await fs.writeFile('./commits-data.json', JSON.stringify(commits))
|
||||||
|
|
||||||
|
|
||||||
// Parse markdown
|
// Parse markdown
|
||||||
const result = md.parse(readmeContent)
|
const result = md.parse(readmeContent)
|
||||||
|
|
||||||
|
|
@ -119,6 +171,8 @@ export default async function () {
|
||||||
strict: true
|
strict: true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const endpoint = `/app/${appSlug}`
|
||||||
|
|
||||||
let status = 'unknown'
|
let status = 'unknown'
|
||||||
|
|
||||||
for (const statusKey in statuses) {
|
for (const statusKey in statuses) {
|
||||||
|
|
@ -128,14 +182,22 @@ export default async function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const lastUpdatedRaw = lookForLastUpdated({ name, endpoint }, commits)
|
||||||
|
|
||||||
|
const lastUpdated = (lastUpdatedRaw) ? {
|
||||||
|
raw: lastUpdatedRaw,
|
||||||
|
timestamp: parseGithubDate(lastUpdatedRaw).timestamp,
|
||||||
|
} : null
|
||||||
|
|
||||||
|
|
||||||
appList.push({
|
appList.push({
|
||||||
name,
|
name,
|
||||||
status,
|
status,
|
||||||
|
lastUpdated,
|
||||||
url,
|
url,
|
||||||
text,
|
text,
|
||||||
slug: appSlug,
|
slug: appSlug,
|
||||||
endpoint: `/app/${appSlug}`,
|
endpoint,
|
||||||
section: {
|
section: {
|
||||||
label: sectionTitle,
|
label: sectionTitle,
|
||||||
slug: sectionSlug
|
slug: sectionSlug
|
||||||
|
|
|
||||||
33
helpers/parse-github-date.js
Normal file
33
helpers/parse-github-date.js
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
// in miliseconds
|
||||||
|
const units = {
|
||||||
|
year : 24 * 60 * 60 * 1000 * 365,
|
||||||
|
month : 24 * 60 * 60 * 1000 * 365/12,
|
||||||
|
day : 24 * 60 * 60 * 1000,
|
||||||
|
hour : 60 * 60 * 1000,
|
||||||
|
minute: 60 * 1000,
|
||||||
|
second: 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' })
|
||||||
|
|
||||||
|
const getRelativeTime = function (d1, d2 = new Date()) {
|
||||||
|
var elapsed = d1 - d2
|
||||||
|
|
||||||
|
// "Math.abs" accounts for both "past" & "future" scenarios
|
||||||
|
for (var u in units)
|
||||||
|
if (Math.abs(elapsed) > units[u] || u == 'second')
|
||||||
|
return rtf.format(Math.round(elapsed/units[u]), u)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function (rawDate) {
|
||||||
|
|
||||||
|
const date = new Date(rawDate)
|
||||||
|
|
||||||
|
return {
|
||||||
|
date,
|
||||||
|
raw: rawDate,
|
||||||
|
timestamp: date.getTime(),
|
||||||
|
relative: getRelativeTime(date)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -24,12 +24,19 @@
|
||||||
>{{ (i === 0) ? 'View' : link.label }}</LinkButton>
|
>{{ (i === 0) ? 'View' : link.label }}</LinkButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="report-links py-24 shadow-none">
|
<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/ -->
|
<!-- https://eric.blog/2016/01/08/prefilling-github-issues/ -->
|
||||||
<a
|
<a
|
||||||
:href="`https://github.com/ThatGuySam/doesitarm/issues?q=is%3Aissue+is%3Aopen+${app.name}`"
|
:href="`https://github.com/ThatGuySam/doesitarm/issues?q=is%3Aissue+is%3Aopen+${app.name}`"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="text-xs"
|
class="underline"
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
>Report Update</a>
|
>Report Update</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -38,6 +45,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import parseGithubDate from '~/helpers/parse-github-date'
|
||||||
import LinkButton from '~/components/link-button.vue'
|
import LinkButton from '~/components/link-button.vue'
|
||||||
import EmailSubscribe from '~/components/email-subscribe.vue'
|
import EmailSubscribe from '~/components/email-subscribe.vue'
|
||||||
import appList from '~/app-list.json'
|
import appList from '~/app-list.json'
|
||||||
|
|
@ -55,6 +63,18 @@ export default {
|
||||||
app: appList.find(app => (app.slug === slug))
|
app: appList.find(app => (app.slug === slug))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
lastUpdatedFriendly () {
|
||||||
|
|
||||||
|
if (this.app.lastUpdated === null) return
|
||||||
|
|
||||||
|
const options = { month: "long", day: "numeric", year: "numeric" }
|
||||||
|
const date = new Date(this.app.lastUpdated.raw)
|
||||||
|
const americanDate = new Intl.DateTimeFormat("en-US", options).format(date)
|
||||||
|
|
||||||
|
return americanDate
|
||||||
|
}
|
||||||
|
},
|
||||||
head() {
|
head() {
|
||||||
return {
|
return {
|
||||||
title: `Does ${this.app.name} work on Apple Silicon?`,
|
title: `Does ${this.app.name} work on Apple Silicon?`,
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,27 @@ import LinkButton from '~/components/link-button.vue'
|
||||||
import appList from '~/app-list.json'
|
import appList from '~/app-list.json'
|
||||||
import gameList from '~/game-list.json'
|
import gameList from '~/game-list.json'
|
||||||
|
|
||||||
|
// console.log('appList.length', appList.length)
|
||||||
|
// console.log('gameList.length', gameList.length)
|
||||||
|
|
||||||
|
function byTimeThenNull (appA, appB) {
|
||||||
|
console.log('appA.lastUpdated', appA.lastUpdated)
|
||||||
|
|
||||||
|
// equal items sort equally
|
||||||
|
if (appA.lastUpdated === appB.lastUpdated) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// nulls sort after anything else
|
||||||
|
else if (appA.lastUpdated === null) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (appB.lastUpdated === null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return appB.lastUpdated.timestamp - appA.lastUpdated.timestamp
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Search,
|
Search,
|
||||||
|
|
@ -53,7 +74,7 @@ export default {
|
||||||
computed: {
|
computed: {
|
||||||
appList() {
|
appList() {
|
||||||
return [
|
return [
|
||||||
...appList,
|
...appList.sort(byTimeThenNull),
|
||||||
...gameList
|
...gameList
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue