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

feat(classroom): add presets #1526

Merged
merged 1 commit into from
May 17, 2022
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
1 change: 1 addition & 0 deletions desktop/renderer-app/src/assets/image/tool-presets.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions desktop/renderer-app/src/components/Whiteboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import React, { useCallback, useContext, useEffect, useState } from "react";
import { Fastboard, Language } from "@netless/fastboard-react";
import {
DarkModeContext,
PresetsModal,
RaiseHand,
SaveAnnotationModal,
SaveAnnotationModalProps,
Expand All @@ -20,6 +21,7 @@ import { isSupportedFileExt } from "../utils/drag-and-drop";
import { isSupportedImageType, onDropImage } from "../utils/drag-and-drop/image";
import { ClassRoomStore } from "../stores/class-room-store";
import { refreshApps } from "../utils/toolbar-apps";
import { PRESETS } from "../constants/presets";

export interface WhiteboardProps {
whiteboardStore: WhiteboardStore;
Expand All @@ -46,6 +48,7 @@ export const Whiteboard = observer<WhiteboardProps>(function Whiteboard({
const [saveAnnotationImages, setSaveAnnotationImages] = useState<
SaveAnnotationModalProps["images"]
>([]);
const [presetsVisible, showPresets] = useState(false);

const isReconnecting = phase === RoomPhase.Reconnecting;

Expand Down Expand Up @@ -135,6 +138,9 @@ export const Whiteboard = observer<WhiteboardProps>(function Whiteboard({
onSaveAnnotation: () => {
showSaveAnnotation(true);
},
onPresets: () => {
showPresets(true);
},
});
}, [t]);

Expand All @@ -156,6 +162,14 @@ export const Whiteboard = observer<WhiteboardProps>(function Whiteboard({
}
}, []);

const insertPresetImage = useCallback(
(fileURL: string) => {
whiteboardStore.insertImage({ fileURL });
showPresets(false);
},
[whiteboardStore],
);

const onDragOver = useCallback(
(event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
Expand Down Expand Up @@ -219,6 +233,12 @@ export const Whiteboard = observer<WhiteboardProps>(function Whiteboard({
visible={saveAnnotationVisible}
onClose={() => showSaveAnnotation(false)}
/>
<PresetsModal
images={PRESETS}
visible={presetsVisible}
onClick={insertPresetImage}
onClose={() => showPresets(false)}
/>
</>
);
});
16 changes: 16 additions & 0 deletions desktop/renderer-app/src/constants/presets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { PresetImage } from "flat-components";

export const PRESETS: PresetImage[] = [
{
src: "https://flat-storage.oss-cn-hangzhou.aliyuncs.com/flat-resources/presets/math_1.png",
i18nKey: "presets.math_1",
},
{
src: "https://flat-storage.oss-cn-hangzhou.aliyuncs.com/flat-resources/presets/english_1.jpeg",
i18nKey: "presets.english_1",
},
{
src: "https://flat-storage.oss-cn-hangzhou.aliyuncs.com/flat-resources/presets/chinese_1.png",
i18nKey: "presets.chinese_1",
},
];
2 changes: 1 addition & 1 deletion desktop/renderer-app/src/stores/whiteboard-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ export class WhiteboardStore {
}
};

public insertImage = async (file: CloudStorageFile): Promise<void> => {
public insertImage = async (file: Pick<CloudStorageFile, "fileURL">): Promise<void> => {
const room = this.room;
if (!room) {
return;
Expand Down
10 changes: 9 additions & 1 deletion desktop/renderer-app/src/utils/toolbar-apps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import monacoSVG from "../assets/image/tool-monaco.svg";
import geogebraSVG from "../assets/image/tool-geogebra.svg";
import countdownSVG from "../assets/image/tool-countdown.svg";
import saveSVG from "../assets/image/tool-save.svg";
import presetsSVG from "../assets/image/tool-presets.svg";

import { TFunction } from "react-i18next";
import { apps, FastboardApp } from "@netless/fastboard-react";
Expand All @@ -11,9 +12,10 @@ import { i18n } from "./i18n";
export interface RefreshAppsParams {
t: TFunction;
onSaveAnnotation?: (app: FastboardApp) => void;
onPresets?: (app: FastboardApp) => void;
}

export const refreshApps = ({ t, onSaveAnnotation }: RefreshAppsParams): void => {
export const refreshApps = ({ t, onSaveAnnotation, onPresets }: RefreshAppsParams): void => {
apps.clear();
apps.push(
{
Expand All @@ -40,6 +42,12 @@ export const refreshApps = ({ t, onSaveAnnotation }: RefreshAppsParams): void =>
label: t("tool.save"),
onClick: onSaveAnnotation || noop,
},
{
kind: "Presets",
icon: presetsSVG,
label: t("tool.presets"),
onClick: onPresets || noop,
},
);
};

Expand Down
58 changes: 58 additions & 0 deletions packages/flat-components/src/components/PresetsModal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import "./style.less";

import React from "react";
import { Modal } from "antd";
import { useTranslation } from "react-i18next";

import { SVGPlus } from "../FlatIcons";

export interface PresetImage {
src: string;
i18nKey: string;
}

export interface PresetsModalProps {
visible: boolean;
images: PresetImage[];
onClick: (image: string) => void;
onClose: () => void;
}

export const PresetsModal: React.FC<PresetsModalProps> = ({
visible,
images,
onClick,
onClose,
}) => {
const { t } = useTranslation();

return (
<Modal
closable
destroyOnClose
footer={null}
title={t("presets.title")}
visible={visible}
width={640}
wrapClassName="presets-modal-container"
onCancel={onClose}
>
{images.map(({ src, i18nKey }) => (
<div className="presets-modal-item">
<button
key={i18nKey}
className="presets-modal-btn"
title={t(i18nKey)}
onClick={() => onClick(src)}
>
<img alt={i18nKey} src={src} title={t(i18nKey)} />
<div className="presets-modal-mask">
<SVGPlus />
</div>
</button>
<div className="presets-modal-text">{t(i18nKey)}</div>
</div>
))}
</Modal>
);
};
99 changes: 99 additions & 0 deletions packages/flat-components/src/components/PresetsModal/style.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
.presets-modal-container {
.ant-modal-title {
text-align: center;
}
.ant-modal-body {
display: grid;
grid-template-columns: repeat(3, 1fr);
justify-items: center;
gap: 54px 48px;
padding: 16px 54px 48px;
height: 480px - 54px;
overflow-y: auto;
}
}

.presets-modal-item {
text-align: center;
width: 140px;
}

.presets-modal-btn {
appearance: none;
background-color: transparent;
padding: 0;
position: relative;
width: 100%;
height: 100px;
border: 1px solid var(--grey-3);
border-radius: 4px;
overflow: hidden;
transition: border 0.1s linear;
cursor: pointer;
user-select: none;
-webkit-user-select: none;

img {
width: 100%;
height: 100%;
object-fit: cover;
}
}

.presets-modal-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: var(--grey-12);
transition: opacity 0.2s ease;
opacity: 0;
z-index: 9;
display: flex;
align-items: center;
justify-content: center;

svg {
width: 48px;
height: 48px;
}
}

.presets-modal-text {
color: var(--text);
font-size: 14px;
line-height: 1.75;
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

.flat-color-scheme-dark {
.presets-modal-btn {
border-color: var(--grey-8);
}
.presets-modal-mask {
background-color: rgba(0, 0, 0, 0.8);
}
}

.presets-modal-btn:hover {
border-color: var(--primary);
.presets-modal-mask {
opacity: 0.5;
}
}

.presets-modal-btn:active {
border-color: var(--primary-strong);
.presets-modal-mask {
opacity: 0.6;
transition: none;
}
.presets-modal-text {
opacity: 1;
transition: none;
}
}
1 change: 1 addition & 0 deletions packages/flat-components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export * from "./components/PeriodicRoomPage";
export * from "./components/RemoveHistoryRoomModal";
export * from "./components/RemoveRoomModal";
export * from "./components/SaveAnnotationModal";
export * from "./components/PresetsModal";
export * from "./components/RoomDetailPage";
export * from "./components/RoomStatusElement";
export * from "./containers/CloudStorageContainer";
Expand Down
9 changes: 8 additions & 1 deletion packages/flat-i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -441,10 +441,17 @@
"monaco": "Code Editor",
"geogebra": "GeoGebra",
"countdown": "Countdown",
"save": "Save Annotation"
"save": "Save Annotation",
"presets": "Presets"
},
"annotation": {
"save-action": "Save Annotation",
"save-failed": "Save annotation failed"
},
"presets": {
"title": "Presets",
"math_1": "Coordinate Axis",
"english_1": "Four Lines and Three Grids",
"chinese_1": "Tin Word Format"
}
}
9 changes: 8 additions & 1 deletion packages/flat-i18n/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -441,10 +441,17 @@
"monaco": "编辑器",
"geogebra": "几何代数",
"countdown": "计时器",
"save": "保存板书"
"save": "保存板书",
"presets": "素材库"
},
"annotation": {
"save-action": "保存板书",
"save-failed": "板书保存失败"
},
"presets": {
"title": "资源素材库",
"math_1": "坐标系",
"english_1": "四线三格",
"chinese_1": "田字格"
}
}
1 change: 1 addition & 0 deletions web/flat-web/src/assets/image/tool-presets.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions web/flat-web/src/components/Whiteboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Fastboard, Language } from "@netless/fastboard-react";
import { RoomPhase } from "white-web-sdk";
import {
DarkModeContext,
PresetsModal,
RaiseHand,
SaveAnnotationModal,
SaveAnnotationModalProps,
Expand All @@ -20,6 +21,7 @@ import { isSupportedFileExt } from "../utils/drag-and-drop";
import { isSupportedImageType, onDropImage } from "../utils/drag-and-drop/image";
import { ClassRoomStore } from "../stores/class-room-store";
import { refreshApps } from "../utils/toolbar-apps";
import { PRESETS } from "../constants/presets";

export interface WhiteboardProps {
whiteboardStore: WhiteboardStore;
Expand All @@ -46,6 +48,7 @@ export const Whiteboard = observer<WhiteboardProps>(function Whiteboard({
const [saveAnnotationImages, setSaveAnnotationImages] = useState<
SaveAnnotationModalProps["images"]
>([]);
const [presetsVisible, showPresets] = useState(false);

const isReconnecting = phase === RoomPhase.Reconnecting;

Expand Down Expand Up @@ -76,6 +79,9 @@ export const Whiteboard = observer<WhiteboardProps>(function Whiteboard({
onSaveAnnotation: () => {
showSaveAnnotation(true);
},
onPresets: () => {
showPresets(true);
},
});
}, [t]);

Expand All @@ -102,6 +108,14 @@ export const Whiteboard = observer<WhiteboardProps>(function Whiteboard({
}
}, []);

const insertPresetImage = useCallback(
(fileURL: string) => {
whiteboardStore.insertImage({ fileURL });
showPresets(false);
},
[whiteboardStore],
);

const onDragOver = useCallback(
(event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
Expand Down Expand Up @@ -220,6 +234,12 @@ export const Whiteboard = observer<WhiteboardProps>(function Whiteboard({
visible={saveAnnotationVisible}
onClose={() => showSaveAnnotation(false)}
/>
<PresetsModal
images={PRESETS}
visible={presetsVisible}
onClick={insertPresetImage}
onClose={() => showPresets(false)}
/>
</>
);
});
Loading