Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audio AMA improvements #1573

Merged
merged 3 commits into from
Aug 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/AudioPlayer/Waveform.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export default function Waveform({
return (
<span
key={i}
style={{ height, minWidth: '2px' }}
style={{ height, minWidth: '2px', minHeight: '2px' }}
className="w-full bg-gray-800 rounded-md dark:bg-gray-200"
/>
)
Expand Down
33 changes: 28 additions & 5 deletions src/components/AudioPlayer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,15 @@ export default function AudioPlayer({
React.useEffect(() => {
resetProgressOverlay()

audioRef.current.addEventListener('ended', function () {
audioRef.current.currentTime = 0
resetProgressOverlay()
setIsPlaying(false)
})
audioRef.current.addEventListener('play', onAudioElementPlay)
audioRef.current.addEventListener('pause', onAudioElementPause)
audioRef.current.addEventListener('ended', onAudioElementEnded)

return function cleanupListeners() {
audioRef?.current?.removeEventListener('play', onAudioElementPlay)
audioRef?.current?.removeEventListener('pause', onAudioElementPause)
audioRef?.current?.removeEventListener('ended', onAudioElementEnded)
}
}, [])

function pause() {
Expand Down Expand Up @@ -69,7 +73,26 @@ export default function AudioPlayer({
setIsPlaying(true)
}

function onAudioElementEnded() {
audioRef.current.currentTime = 0
resetProgressOverlay()
setIsPlaying(false)
}

function onAudioElementPlay() {
setIsPlaying(true)
}

function onAudioElementPause() {
setIsPlaying(false)
}

function togglePlay() {
// pause all other audio players
const audios = document.querySelectorAll('audio')
audios.forEach((audio) => audio.pause())

// pause or play this audio player
isPlaying ? pause() : play()
}

Expand Down
4 changes: 3 additions & 1 deletion src/graphql/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@ import { baseUrl } from '~/config/seo'

export const IS_PROD = process.env.NODE_ENV === 'production'
export const CLIENT_URL = IS_PROD ? baseUrl : 'http://localhost:3000'
export const AUDIO_STORAGE_BUCKET = IS_PROD ? 'audio-ama' : 'audio-ama-dev'
export const PAGINATION_AMOUNT = 16

export const AUDIO_STORAGE_BUCKET = IS_PROD ? 'audio-ama' : 'audio-ama-dev'
export const AMA_QUESTIONS_COLLECTION = IS_PROD ? 'questions' : 'questions-dev'
35 changes: 35 additions & 0 deletions src/graphql/helpers/sanitizeAmaDocument.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { storage } from '~/graphql/services/firebase'
import { AUDIO_STORAGE_BUCKET } from '../constants'

async function fetchAudioPlaybackUrl(id) {
const bucket = storage.bucket(AUDIO_STORAGE_BUCKET)
const url = await bucket
.file(id)
.getSignedUrl({
expires: Date.now() + 60 * 60 * 1000, // one hour
action: 'read',
})
.then((r) => r[0])
.catch((e) => {
console.error({ e })
return null
})
return await Promise.resolve(url)
}

export async function sanitizeAmaDocument(document, id) {
const createdAt = document.createdAt.toDate()
const updatedAt = document.updatedAt.toDate()
const audioUrl =
document.audioWaveform?.length > 0 ? await fetchAudioPlaybackUrl(id) : null
const audioPlayCount = document.audioPlayCount || 0
const audioWaveform = document.audioWaveform || []

return {
createdAt,
updatedAt,
audioWaveform,
audioUrl,
audioPlayCount,
}
}
21 changes: 9 additions & 12 deletions src/graphql/resolvers/mutations/ama/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { baseUrl } from '~/config/seo'
import { IS_PROD } from '~/graphql/constants'
import { AMA_QUESTIONS_COLLECTION, IS_PROD } from '~/graphql/constants'
import { db } from '~/graphql/services/firebase'
import { emailMe } from '~/graphql/services/postmark'
import fetch from 'node-fetch'
Expand All @@ -9,12 +9,11 @@ import {
MutationEditAmaQuestionArgs,
MutationTranscribeAudioArgs,
} from '~/graphql/types.generated'

const COLLECTION = IS_PROD ? 'questions' : 'questions-dev'
import { sanitizeAmaDocument } from '~/graphql/helpers/sanitizeAmaDocument'

export async function editAMAQuestion(_, args: MutationEditAmaQuestionArgs) {
const { id, question, answer, status, audioWaveform } = args
const docRef = db.collection(COLLECTION).doc(id)
const docRef = db.collection(AMA_QUESTIONS_COLLECTION).doc(id)
await docRef.update({
question,
answer,
Expand All @@ -39,7 +38,7 @@ export async function addAMAQuestion(
})

return await db
.collection(COLLECTION)
.collection(AMA_QUESTIONS_COLLECTION)
.add({
question,
answer: null,
Expand All @@ -55,12 +54,12 @@ export async function deleteAMAQuestion(
_,
{ id }: MutationDeleteAmaQuestionArgs
) {
const docRef = db.collection(COLLECTION).doc(id)
const docRef = db.collection(AMA_QUESTIONS_COLLECTION).doc(id)
return await docRef.delete().then(() => true)
}

export async function addAMAReaction(_, { id }) {
const docRef = db.collection(COLLECTION).doc(id)
const docRef = db.collection(AMA_QUESTIONS_COLLECTION).doc(id)
const doc = await docRef.get().then((doc) => doc.data())

const count = doc.reactions ? doc.reactions + 1 : 1
Expand All @@ -70,15 +69,13 @@ export async function addAMAReaction(_, { id }) {
})

const res = await docRef.get().then((doc) => doc.data())
const createdAt = res.createdAt.toDate()
const updatedAt = res.updatedAt.toDate()
return { ...res, createdAt, updatedAt, id }
const sanitizedAmaDocument = await sanitizeAmaDocument(doc, id)
return { ...res, id, ...sanitizedAmaDocument }
}

export async function addAMAAudioPlay(_, { id }) {
const docRef = db.collection(COLLECTION).doc(id)
const docRef = db.collection(AMA_QUESTIONS_COLLECTION).doc(id)
const doc = await docRef.get().then((doc) => doc.data())

const count = doc.playCount ? doc.playCount + 1 : 1

await docRef.update({
Expand Down
21 changes: 7 additions & 14 deletions src/graphql/resolvers/queries/ama/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import {
QueryTranscriptionArgs,
} from '~/graphql/types.generated'
import {
AMA_QUESTIONS_COLLECTION,
AUDIO_STORAGE_BUCKET,
IS_PROD,
PAGINATION_AMOUNT,
} from '~/graphql/constants'
import { sanitizeAmaDocument } from '~/graphql/helpers/sanitizeAmaDocument'

async function fetchAudioPlaybackUrl(id) {
const bucket = storage.bucket(AUDIO_STORAGE_BUCKET)
Expand All @@ -33,15 +34,14 @@ export async function getAMAQuestions(
args: QueryAmaQuestionsArgs,
{ isMe }
) {
const COLLECTION = IS_PROD ? 'questions' : 'questions-dev'
const { skip = 0, status = 'ANSWERED' } = args

if (status === 'PENDING' && !isMe) return []

const data = []

async function processQuestions() {
let collection = db.collection(COLLECTION)
let collection = db.collection(AMA_QUESTIONS_COLLECTION)
let questionsRef = await collection
.where('status', '==', status)
.orderBy('updatedAt', 'desc')
Expand All @@ -51,20 +51,13 @@ export async function getAMAQuestions(
for (let question of questionsRef.docs) {
const d = question.data()
const id = question.id
const createdAt = d.createdAt.toDate()
const updatedAt = d.updatedAt.toDate()
const audioUrl =
d.audioWaveform?.length > 0 ? await fetchAudioPlaybackUrl(id) : null
const audioPlayCount = d.audioPlayCount || 0
const audioWaveform = d.audioWaveform || []

const sanitizedAmaDocument = await sanitizeAmaDocument(d, id)

const record = {
...d,
id,
createdAt,
updatedAt,
audioUrl,
audioPlayCount,
audioWaveform,
...sanitizedAmaDocument,
} as Ama

data.push(record)
Expand Down
5 changes: 2 additions & 3 deletions src/pages/ama.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function About() {
/>

<CenteredColumn>
<div className=" space-y-8">
<div className="space-y-8">
<Link href="/projects" passHref>
<a className="leading-snug text-tertiary hover:text-gray-1000 dark:hover:text-gray-100">
&larr; Projects
Expand All @@ -37,7 +37,7 @@ function About() {
)
}

export async function getStaticProps() {
export async function getServerSideProps() {
const client = await initApolloClient({})
await client.query({
query: GET_AMA_QUESTIONS,
Expand All @@ -55,7 +55,6 @@ export async function getStaticProps() {
*/
const apolloStaticCache = client.cache.extract()
return {
revalidate: 60 * 60,
props: {
apolloStaticCache,
},
Expand Down