Skip to content

Commit

Permalink
feat(preview): add resource preview to flat-web. (#812)
Browse files Browse the repository at this point in the history
  • Loading branch information
Cheerego7 authored Jul 26, 2021
1 parent 2becc27 commit 19a3fbb
Show file tree
Hide file tree
Showing 15 changed files with 400 additions and 5 deletions.
2 changes: 1 addition & 1 deletion web/flat-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"react-virtualized": "^9.22.3",
"uuid": "^8.3.2",
"video.js": "7.10.2",
"white-web-sdk": "2.13.11"
"white-web-sdk": "2.13.12"
},
"scripts": {
"postinstall": "esbuild-dev ./scripts/post-install.ts",
Expand Down
4 changes: 4 additions & 0 deletions web/flat-web/src/AppRoutes/route-pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,8 @@ export const routePages: RoutePages = {
title: "JoinPage",
component: () => import("../pages/JoinPage"),
},
[RouteNameType.ResourcePreviewPage]: {
title: "ResourcePreviewPage",
component: () => import("../pages/ResourcePreviewPage"),
},
};
18 changes: 14 additions & 4 deletions web/flat-web/src/pages/CloudStoragePage/store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
renameFile,
} from "../../apiMiddleware/flatServer/storage";
import { errorTips } from "../../components/Tips/ErrorTips";
import { INVITE_BASEURL } from "../../constants/Process";
import { getUploadTaskManager } from "../../utils/UploadTaskManager";
import { UploadStatusType, UploadTask } from "../../utils/UploadTaskManager/UploadTask";

Expand Down Expand Up @@ -357,6 +358,18 @@ export class CloudStorageStore extends CloudStorageStoreBase {
}

private previewCourseware(file: CloudStorageFile): void {
const { fileURL, taskToken, taskUUID } = file;

const convertFileTypeList = [".pptx", ".ppt", ".pdf", ".doc", ".docx"];

const isConvertFileType = convertFileTypeList.some(type => fileURL.includes(type));

const encodeFileURL = encodeURIComponent(fileURL);

const resourcePreviewURL = isConvertFileType
? `${INVITE_BASEURL}/preview/${encodeFileURL}/${taskToken}/${taskUUID}/`
: `${INVITE_BASEURL}/preview/${encodeFileURL}/`;

switch (file.convert) {
case "converting": {
Modal.info({ content: this.i18n.t("please-wait-while-the-lesson-is-transcoded") });
Expand All @@ -367,10 +380,7 @@ export class CloudStorageStore extends CloudStorageStoreBase {
return;
}
default: {
// @TODO preview courseware
Modal.info({
content: this.i18n.t("please-go-to-the-room-to-view-the-courseware"),
});
window.open(resourcePreviewURL, "_blank");
}
}
}
Expand Down
40 changes: 40 additions & 0 deletions web/flat-web/src/pages/ResourcePreviewPage/DynamicPreview.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.dynamic-preview-container {
background-color: #eee;
}

.ppt-preview-container {
.ppt-preview-main-container {
padding-top: 25px;
border: none;
}
}

.ppt-preview-controls {
display: none;
}

.dynamic-preview-pagination-previous {
cursor: pointer;
}

.dynamic-preview-pagination-next {
cursor: pointer;
}

.dynamic-preview-pagination-container {
position: absolute;
bottom: 24px;
z-index: 2;
left: 48%;
width: 140px;
height: 44px;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.5);
border-radius: 8px;
}

.dynamic-preview-pagination-middle {
color: #fff;
}
94 changes: 94 additions & 0 deletions web/flat-web/src/pages/ResourcePreviewPage/DynamicPreview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import "./DynamicPreview.less";
import previousStepSVG from "./image/previous-step.svg";
import nextStepSVG from "./image/next-step.svg";

import { observer } from "mobx-react-lite";
import React, { useEffect, useRef, useState } from "react";
import { ConversionResponse, previewPPT } from "white-web-sdk";
import { queryConvertingTaskStatus } from "../../apiMiddleware/courseware-converting";
import { useSafePromise } from "../../utils/hooks/lifecycle";
import { EventEmitter } from "eventemitter3";

export interface DynamicPreviewProps {
taskUUID: string;
taskToken: string;
}

export const DynamicPreview = observer<DynamicPreviewProps>(function PPTPreview({
taskUUID,
taskToken,
}) {
const DynamicPreviewRef = useRef<HTMLDivElement>(null);
const sp = useSafePromise();

const [currentPage, setCurrentPage] = useState(1);
const [totalPage, setTotalPage] = useState(0);
const [eventEmit] = useState(() => new EventEmitter());

useEffect(() => {
async function getDynamicResource(): Promise<void> {
const convertState = await sp(
queryConvertingTaskStatus({
taskUUID,
taskToken,
dynamic: true,
}),
);

if (DynamicPreviewRef.current) {
previewPPT(
convertState as ConversionResponse,
DynamicPreviewRef.current,
{},
true,
{},
undefined,
undefined,
eventEmit,
);
}
}

getDynamicResource().catch(console.warn);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useEffect(() => {
eventEmit.on("update", data => {
setCurrentPage(data.index);
});
eventEmit.once("update", data => {
setTotalPage(data.total);
});
return () => {
eventEmit.removeAllListeners();
};
}, [eventEmit]);

return (
<div className="dynamic-preview-container">
<div ref={DynamicPreviewRef} className="dynamic-preview-inner" />
<div className="dynamic-preview-pagination-container">
<div
className="dynamic-preview-pagination-previous"
onClick={() => {
eventEmit.emit("preStep");
}}
>
<img src={previousStepSVG} alt="previous step" />
</div>
<div className="dynamic-preview-pagination-middle">
{currentPage} / {totalPage}
</div>
<div
className="dynamic-preview-pagination-next"
onClick={() => {
eventEmit.emit("nextStep");
}}
>
<img src={nextStepSVG} alt="next step" />
</div>
</div>
</div>
);
});
23 changes: 23 additions & 0 deletions web/flat-web/src/pages/ResourcePreviewPage/MediaPreview.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.media-preview-container {
height: 100vh;
background-color: #000000;

video {
width: 100%;
height: 100%;
object-fit: contain;
}
}

.audio-container {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}

.img-container {
height: 100%;
display: flex;
justify-content: center;
}
42 changes: 42 additions & 0 deletions web/flat-web/src/pages/ResourcePreviewPage/MediaPreview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import "./MediaPreview.less";

import React from "react";
import { observer } from "mobx-react-lite";
import { getFileSuffix } from "./utils";

export interface MediaPreviewProps {
fileURL: string;
}

export const MediaPreview = observer<MediaPreviewProps>(function PPTPreview({ fileURL }) {
const mediaFileURL = decodeURIComponent(fileURL);

const mediaFileSuffix = getFileSuffix(mediaFileURL);

return <div className="media-preview-container">{renderMediaPreview()}</div>;

function renderMediaPreview(): React.ReactElement {
switch (mediaFileSuffix) {
case ".mp3": {
return (
<div className="audio-container">
<audio controls src={mediaFileURL} />
</div>
);
}
case ".jpg":
case ".jpeg":
case ".png": {
return (
<div className="img-container">
<img src={mediaFileURL} alt="img resource" />
</div>
);
}

default: {
return <video controls src={mediaFileURL} />;
}
}
}
});
11 changes: 11 additions & 0 deletions web/flat-web/src/pages/ResourcePreviewPage/StaticPreview.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.static-preview-container {
display: flex;
flex-direction: column;
align-items: center;
}

.static-preview-item {
display: block;
border-bottom: 2px #f3f3f3 dashed;
padding-bottom: 10px;
}
61 changes: 61 additions & 0 deletions web/flat-web/src/pages/ResourcePreviewPage/StaticPreview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import "./StaticPreview.less";

import { observer } from "mobx-react-lite";
import React, { useEffect, useState } from "react";
import { queryConvertingTaskStatus } from "../../apiMiddleware/courseware-converting";
import { useSafePromise } from "../../utils/hooks/lifecycle";

export interface StaticPreviewProps {
taskUUID: string;
taskToken: string;
}

type ConvertedFileList =
| {
width: number;
height: number;
conversionFileUrl: string;
preview?: string | undefined;
}[]
| undefined;

export const StaticPreview = observer<StaticPreviewProps>(function DocumentPreview({
taskUUID,
taskToken,
}) {
const [convertList, setConvertList] = useState<ConvertedFileList>([]);
const sp = useSafePromise();

useEffect(() => {
async function getStaticResource(): Promise<void> {
const convertResult = await sp(
queryConvertingTaskStatus({
taskUUID,
taskToken,
dynamic: false,
}),
);

setConvertList(convertResult.progress?.convertedFileList);
}

getStaticResource().catch(console.warn);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return (
<div className="static-preview-container fancy-scrollbar">
<div className="static-preview-list">
{convertList?.map(file => {
return (
<img
className="static-preview-item"
src={file.conversionFileUrl}
key={file.conversionFileUrl}
></img>
);
})}
</div>
</div>
);
});
13 changes: 13 additions & 0 deletions web/flat-web/src/pages/ResourcePreviewPage/image/next-step.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions web/flat-web/src/pages/ResourcePreviewPage/image/previous-step.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 19a3fbb

Please sign in to comment.