mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-20 20:29:06 +00:00
refactor: improve transcript list performance (#480)
* refactor: improve transcript list performance * fix: sync openapi * fix: frontend types * fix: remove drop table _alembic_tmp_meeting * fix: remove create table too * fix: remove uq_recording_object_key
This commit is contained in:
@@ -44,7 +44,7 @@ import {
|
||||
import useTranscriptList from "../transcripts/useTranscriptList";
|
||||
import useSessionUser from "../../lib/useSessionUser";
|
||||
import NextLink from "next/link";
|
||||
import { Room, GetTranscript } from "../../api";
|
||||
import { Room, GetTranscriptMinimal } from "../../api";
|
||||
import Pagination from "./pagination";
|
||||
import { formatTimeMs } from "../../lib/time";
|
||||
import useApi from "../../lib/useApi";
|
||||
@@ -328,7 +328,7 @@ export default function TranscriptBrowser() {
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{response?.items?.map((item: GetTranscript) => (
|
||||
{response?.items?.map((item: GetTranscriptMinimal) => (
|
||||
<Tr key={item.id}>
|
||||
<Td>
|
||||
<Flex alignItems="start">
|
||||
@@ -416,7 +416,7 @@ export default function TranscriptBrowser() {
|
||||
</Box>
|
||||
<Box display={{ base: "block", md: "none" }}>
|
||||
<Stack spacing={2}>
|
||||
{response?.items?.map((item: GetTranscript) => (
|
||||
{response?.items?.map((item: GetTranscriptMinimal) => (
|
||||
<Box key={item.id} borderWidth={1} p={4} borderRadius="md">
|
||||
<Flex justify="space-between" alignItems="flex-start" gap="2">
|
||||
<Box>
|
||||
|
||||
@@ -193,7 +193,7 @@ export default function RoomsList() {
|
||||
(err.body as any).detail == "Room name is not unique"
|
||||
) {
|
||||
setNameError(
|
||||
"This room name is already taken. Please choose a different name."
|
||||
"This room name is already taken. Please choose a different name.",
|
||||
);
|
||||
} else {
|
||||
setNameError("An error occurred. Please try again.");
|
||||
@@ -316,7 +316,7 @@ export default function RoomsList() {
|
||||
options={roomModeOptions}
|
||||
value={{
|
||||
label: roomModeOptions.find(
|
||||
(rm) => rm.value === room.roomMode
|
||||
(rm) => rm.value === room.roomMode,
|
||||
)?.label,
|
||||
value: room.roomMode,
|
||||
}}
|
||||
@@ -335,7 +335,7 @@ export default function RoomsList() {
|
||||
options={recordingTypeOptions}
|
||||
value={{
|
||||
label: recordingTypeOptions.find(
|
||||
(rt) => rt.value === room.recordingType
|
||||
(rt) => rt.value === room.recordingType,
|
||||
)?.label,
|
||||
value: room.recordingType,
|
||||
}}
|
||||
@@ -358,7 +358,7 @@ export default function RoomsList() {
|
||||
options={recordingTriggerOptions}
|
||||
value={{
|
||||
label: recordingTriggerOptions.find(
|
||||
(rt) => rt.value === room.recordingTrigger
|
||||
(rt) => rt.value === room.recordingTrigger,
|
||||
)?.label,
|
||||
value: room.recordingTrigger,
|
||||
}}
|
||||
|
||||
@@ -183,17 +183,21 @@ const TopicPlayer = ({
|
||||
setIsPlaying(false);
|
||||
};
|
||||
|
||||
const isLoaded = !mp3.loading && !!topicTime
|
||||
const isLoaded = !mp3.loading && !!topicTime;
|
||||
const error = mp3.error;
|
||||
if (error !== null) {
|
||||
return <Text fontSize="sm" pt="1" pl="2">
|
||||
Loading error: {error}
|
||||
</Text>
|
||||
return (
|
||||
<Text fontSize="sm" pt="1" pl="2">
|
||||
Loading error: {error}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
if (mp3.audioDeleted) {
|
||||
return <Text fontSize="sm" pt="1" pl="2">
|
||||
This topic file has been deleted.
|
||||
</Text>
|
||||
return (
|
||||
<Text fontSize="sm" pt="1" pl="2">
|
||||
This topic file has been deleted.
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Skeleton
|
||||
|
||||
@@ -67,8 +67,6 @@ export default function TranscriptDetails(details: TranscriptDetails) {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<Grid
|
||||
@@ -78,7 +76,10 @@ export default function TranscriptDetails(details: TranscriptDetails) {
|
||||
mt={4}
|
||||
mb={4}
|
||||
>
|
||||
{waveform.waveform && mp3.media && !mp3.audioDeleted && topics.topics ? (
|
||||
{waveform.waveform &&
|
||||
mp3.media &&
|
||||
!mp3.audioDeleted &&
|
||||
topics.topics ? (
|
||||
<Player
|
||||
topics={topics?.topics}
|
||||
useActiveTopic={useActiveTopic}
|
||||
|
||||
@@ -43,8 +43,7 @@ import {
|
||||
Input,
|
||||
} from "@chakra-ui/react";
|
||||
const TranscriptCreate = () => {
|
||||
|
||||
const isClient = typeof window !== 'undefined';
|
||||
const isClient = typeof window !== "undefined";
|
||||
const router = useRouter();
|
||||
const { isLoading, isAuthenticated } = useSessionStatus();
|
||||
const requireLogin = featureEnabled("requireLogin");
|
||||
@@ -186,9 +185,9 @@ const TranscriptCreate = () => {
|
||||
<Spacer />
|
||||
) : permissionDenied ? (
|
||||
<Text className="">
|
||||
Permission to use your microphone was denied, please change
|
||||
the permission setting in your browser and refresh this
|
||||
page.
|
||||
Permission to use your microphone was denied, please
|
||||
change the permission setting in your browser and refresh
|
||||
this page.
|
||||
</Text>
|
||||
) : (
|
||||
<Button
|
||||
|
||||
@@ -124,7 +124,7 @@ const useAudioDevice = () => {
|
||||
permissionDenied,
|
||||
audioDevices,
|
||||
getAudioStream,
|
||||
requestPermission
|
||||
requestPermission,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -14,9 +14,13 @@ const useMp3 = (transcriptId: string, waiting?: boolean): Mp3Response => {
|
||||
const [media, setMedia] = useState<HTMLMediaElement | null>(null);
|
||||
const [later, setLater] = useState(waiting);
|
||||
const [audioLoading, setAudioLoading] = useState<boolean>(true);
|
||||
const [audioLoadingError, setAudioLoadingError] = useState<null | string>(null);
|
||||
const [transcriptMetadataLoading, setTranscriptMetadataLoading] = useState<boolean>(true);
|
||||
const [transcriptMetadataLoadingError, setTranscriptMetadataLoadingError] = useState<string | null>(null);
|
||||
const [audioLoadingError, setAudioLoadingError] = useState<null | string>(
|
||||
null,
|
||||
);
|
||||
const [transcriptMetadataLoading, setTranscriptMetadataLoading] =
|
||||
useState<boolean>(true);
|
||||
const [transcriptMetadataLoadingError, setTranscriptMetadataLoadingError] =
|
||||
useState<string | null>(null);
|
||||
const [audioDeleted, setAudioDeleted] = useState<boolean | null>(null);
|
||||
const api = getApi();
|
||||
const { api_url } = useContext(DomainContext);
|
||||
@@ -47,28 +51,29 @@ const useMp3 = (transcriptId: string, waiting?: boolean): Mp3Response => {
|
||||
});
|
||||
}, [navigator.serviceWorker, !serviceWorker, accessTokenInfo]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (!transcriptId || !api || later) return;
|
||||
|
||||
let deleted: boolean | null = null;
|
||||
|
||||
setTranscriptMetadataLoading(true);
|
||||
|
||||
|
||||
const audioElement = document.createElement("audio");
|
||||
audioElement.src = `${api_url}/v1/transcripts/${transcriptId}/audio/mp3`;
|
||||
audioElement.crossOrigin = "anonymous";
|
||||
audioElement.preload = "auto";
|
||||
|
||||
|
||||
const handleCanPlay = () => {
|
||||
if (deleted) {
|
||||
console.error('Illegal state: audio supposed to be deleted, but was loaded');
|
||||
console.error(
|
||||
"Illegal state: audio supposed to be deleted, but was loaded",
|
||||
);
|
||||
return;
|
||||
}
|
||||
setAudioLoading(false);
|
||||
setAudioLoadingError(null);
|
||||
};
|
||||
|
||||
|
||||
const handleError = () => {
|
||||
setAudioLoading(false);
|
||||
if (deleted) {
|
||||
@@ -77,18 +82,18 @@ const useMp3 = (transcriptId: string, waiting?: boolean): Mp3Response => {
|
||||
}
|
||||
setAudioLoadingError("Failed to load audio");
|
||||
};
|
||||
|
||||
audioElement.addEventListener('canplay', handleCanPlay);
|
||||
audioElement.addEventListener('error', handleError);
|
||||
|
||||
setMedia(audioElement);
|
||||
|
||||
audioElement.addEventListener("canplay", handleCanPlay);
|
||||
audioElement.addEventListener("error", handleError);
|
||||
|
||||
setMedia(audioElement);
|
||||
|
||||
setAudioLoading(true);
|
||||
|
||||
let stopped = false;
|
||||
// Fetch transcript info in parallel
|
||||
api.v1TranscriptGet({ transcriptId })
|
||||
api
|
||||
.v1TranscriptGet({ transcriptId })
|
||||
.then((transcript) => {
|
||||
if (stopped) return;
|
||||
deleted = transcript.audio_deleted || false;
|
||||
@@ -109,12 +114,12 @@ const useMp3 = (transcriptId: string, waiting?: boolean): Mp3Response => {
|
||||
.finally(() => {
|
||||
if (stopped) return;
|
||||
setTranscriptMetadataLoading(false);
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
return () => {
|
||||
stopped = true;
|
||||
audioElement.removeEventListener('canplay', handleCanPlay);
|
||||
audioElement.removeEventListener('error', handleError);
|
||||
audioElement.removeEventListener("canplay", handleCanPlay);
|
||||
audioElement.removeEventListener("error", handleError);
|
||||
};
|
||||
}, [transcriptId, !api, later, api_url]);
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useError } from "../../(errors)/errorContext";
|
||||
import useApi from "../../lib/useApi";
|
||||
import { Page_GetTranscript_, SourceKind } from "../../api";
|
||||
import { Page_GetTranscriptMinimal_, SourceKind } from "../../api";
|
||||
|
||||
type TranscriptList = {
|
||||
response: Page_GetTranscript_ | null;
|
||||
response: Page_GetTranscriptMinimal_ | null;
|
||||
loading: boolean;
|
||||
error: Error | null;
|
||||
refetch: () => void;
|
||||
@@ -16,7 +16,9 @@ const useTranscriptList = (
|
||||
roomId: string | null,
|
||||
searchTerm: string | null,
|
||||
): TranscriptList => {
|
||||
const [response, setResponse] = useState<Page_GetTranscript_ | null>(null);
|
||||
const [response, setResponse] = useState<Page_GetTranscriptMinimal_ | null>(
|
||||
null,
|
||||
);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [error, setErrorState] = useState<Error | null>(null);
|
||||
const { setError } = useError();
|
||||
|
||||
Reference in New Issue
Block a user