From d9ed7a77360393528f50b1da6e0c83cc18af8b89 Mon Sep 17 00:00:00 2001 From: Claudio Costa Date: Mon, 4 Dec 2023 17:09:00 -0600 Subject: [PATCH] Set a captions_file_id post prop to avoid indirection when fetching captions file for video preview (#581) --- server/bot_api.go | 50 ++++++++++++++++--- server/job_metadata.go | 7 +-- .../components/recordings_file_preview.tsx | 14 ++---- 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/server/bot_api.go b/server/bot_api.go index 9904b4556..b9fa0bee7 100644 --- a/server/bot_api.go +++ b/server/bot_api.go @@ -334,15 +334,49 @@ func (p *Plugin) handleBotPostTranscriptions(w http.ResponseWriter, r *http.Requ // We update the metadata with the file and post IDs for the transcription. transcriptions, ok := post.GetProp("transcriptions").(map[string]any) - if ok { - var tm jobMetadata - tm.fromMap(transcriptions[info.JobID]) - tm.FileID = info.FileIDs[0] - tm.PostID = trPost.Id - transcriptions[info.JobID] = tm.toMap() - post.AddProp("transcriptions", transcriptions) + if !ok { + res.Err = "unexpected data found in transcriptions post prop" + res.Code = http.StatusInternalServerError + p.LogError(res.Err, "trID", info.JobID) + return + } + + var tm jobMetadata + tm.fromMap(transcriptions[info.JobID]) + tm.FileID = info.FileIDs[0] + tm.PostID = trPost.Id + transcriptions[info.JobID] = tm.toMap() + post.AddProp("transcriptions", transcriptions) + + // We retrieve the related recording info (if any) so that we can save the file id + // for the VTT captions in the props of the recording post that will + // eventually render them on top of the video player. + recordings, ok := post.GetProp("recordings").(map[string]any) + if !ok { + res.Err = "unexpected data found in recordings post prop" + res.Code = http.StatusInternalServerError + p.LogError(res.Err, "trID", info.JobID) + return + } + var rm jobMetadata + rm.fromMap(recordings[tm.RecID]) + if rm.PostID != "" { + recPost, appErr := p.API.GetPost(rm.PostID) + if appErr != nil { + res.Err = "failed to get recording post: " + appErr.Error() + res.Code = http.StatusInternalServerError + p.LogError(res.Err, "trID", info.JobID) + return + } + recPost.AddProp("captions_file_id", tm.FileID) + if _, appErr := p.API.UpdatePost(recPost); appErr != nil { + res.Err = "failed to update recording post: " + appErr.Error() + res.Code = http.StatusInternalServerError + p.LogError(res.Err, "trID", info.JobID) + return + } } else { - p.LogError("unexpected data found in transcriptions post prop", "trID", info.JobID) + p.LogWarn("unexpected missing recording post ID", "trID", info.JobID) } _, appErr = p.API.UpdatePost(post) diff --git a/server/job_metadata.go b/server/job_metadata.go index ed2ad30a9..fba168285 100644 --- a/server/job_metadata.go +++ b/server/job_metadata.go @@ -12,9 +12,9 @@ type jobMetadata struct { FileID string // PostID is the Post.Id that holds the job's artifacts (e.g. recording post). PostID string - // RecID is the recording ID. + // RecID is the recording job ID. RecID string - // TrID is the transcription ID. + // TrID is the transcription job ID. TrID string } @@ -96,7 +96,8 @@ func (p *Plugin) saveRecordingMetadata(postID, recID, trID string) error { post.AddProp("recordings", recordings) // This is where we map a transcription to a recording. - // This information will be used by the client when rendering the recording preview. + // This information will be used when the transcribing job completes to populate + // the recording post props with the captions file id. if trID != "" { tm := jobMetadata{ RecID: recID, diff --git a/webapp/src/components/recordings_file_preview.tsx b/webapp/src/components/recordings_file_preview.tsx index 4ac493a1d..2fd4fe9bb 100644 --- a/webapp/src/components/recordings_file_preview.tsx +++ b/webapp/src/components/recordings_file_preview.tsx @@ -1,10 +1,7 @@ import {FileInfo} from '@mattermost/types/files'; import {Post} from '@mattermost/types/posts'; -import {GlobalState} from '@mattermost/types/store'; import {Client4} from 'mattermost-redux/client'; -import {getPost} from 'mattermost-redux/selectors/entities/posts'; import React, {useMemo} from 'react'; -import {useSelector} from 'react-redux'; import styled from 'styled-components'; type Props = { @@ -13,12 +10,7 @@ type Props = { } const RecordingsFilePreview = ({fileInfo, post}: Props) => { - const callPost = useSelector((state: GlobalState) => getPost(state, post.props?.call_post_id)); - - const recording = callPost?.props?.recordings?.[post.props?.recording_id]; - const transcription = callPost?.props?.transcriptions?.[recording?.tr_id]; - - const now = useMemo(() => Date.now(), [recording, transcription]); + const now = useMemo(() => Date.now(), [post.props.captions_file_id]); return (