iT邦幫忙

2022 iThome 鐵人賽

DAY 24
0
Modern Web

新手進化日記,從React至Redux Saga系列 第 24

Day 24 - 影片標記頁面完整雛形

  • 分享至 

  • xImage
  •  
tags: iThome 鐵人賽 30天

這次markdown editor決定採用@uiw/react-md-editor,不過畢竟我也沒用過,就當作試用來用看看囉!

Markdown Editor

先來安裝套件:

npm i @uiw/react-md-editor

因為這套件裡面就有內建Markdown的渲染了,所以來替代昨天用的ReactMarkdown吧~

修改MarkView.jsx並增加onDoubleClick事件來幫助觸發編輯:

import React from 'react'
import { Button, Box } from '@mui/material'
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import MDEditor from '@uiw/react-md-editor'

export default function MarkView(props) {
    const { sec, content, onDoubleClick } = props

    return (
        <Box sx={{ p: 1 }}>
            <Button size="small" variant="outlined">{parseInt(sec / 60)}:{(((sec - parseInt(sec / 60) * 60) / 100).toFixed(2)).split('.')[1]}</Button>
            <Box
                sx={{ border: "1px solid #000", p: 1, margin: "5px 0", borderRadius: "10px", backgroundColor: "#fff" }}
                component="div"
            >
                <article onDoubleClick={e => onDoubleClick(e)}>
                    <MDEditor.Markdown source={content} linkTarget="_blank" style={{ padding: 10 }} />
                </article>
            </Box>
        </Box>
    )
}

目前畫面:

測試的onDoubleClick也是正常的:

Markdown編輯器編輯標記

那再來就是雙擊後觸發編輯畫面了!我的打算是把整個右半邊的標記部分全部都變為編輯器,這樣範圍比較大編輯起來也比較舒服~

另外我把右邊的標記畫面也分開成另一個component,放在/src/components/Main/MarkPage.jsx之中,所以目前WatchPage長這個樣子:

export default function WatchPage(props) {
    const { } = props
    const [player, setPlayer] = useState(null)

    return (
        <Box sx={{ display: "flex", height: '100%', overflow: "auto" }} >
            <Box sx={{ width: "70%" }} className="watch_wrapper">
                <div className='video_wrapper'>
                    <div className='video_container'>
                        <div id="player" width="100%"></div>
                    </div>
                </div>
                <YouTubeIframe
                    v={"Ga22mpTDS6A"}
                    t={0}
                    playerid="player"
                    player={player}
                    setPlayer={pl => setPlayer(pl)}
                />
            </Box>
            <Box sx={{ width: "30%", position: "relative" }} className="mark_container">
                <MarkPage />
            </Box>
        </Box>
    )
}

製作編輯畫面一樣使用套件即可,並且設定按下esc就離開編輯畫面。

/src/components/Main/MarkPage.jsx

import React, { useState, useEffect, useRef } from 'react'
import MarkView from '../elements/MarkView'
import MDEditor from '@uiw/react-md-editor'

export default function MarkPage(props) {

    const [isEdit, setEdit] = useState(false)
    const [mdInfo, setMdInfo] = useState({ content: null, id: null, sec: null })

    const content = ``

    // 當按下esc離開編輯器
    const handleKeydown = (e) => {
        if (e.keyCode == 27) {
            setEdit(false)
        }
    }

    useEventListener('keydown', handleKeydown)

    return (
        <>
            {!!isEdit &&
                <MDEditor
                    value={mdInfo.content}
                    onChange={value => setMdInfo({ ...mdInfo, content: value })}
                    style={{ position: "absolute", zIndex: "1" }}
                    height="100%"
                    width="100%"
                    className='md_editor'
                />
            }
            <MarkView
                sec={33}
                content={content}
                onDoubleClick={e => setEdit(!isEdit)}
            />
        </>
    )
}


function useEventListener(eventName, handler, element = window) {
    const savedHandler = useRef();

    useEffect(() => {
        savedHandler.current = handler;
    }, [handler]);
    useEffect(() => {
        const isSupported = element && element.addEventListener;
        if (!isSupported) return;
        const eventListener = (event) => savedHandler.current(event);
        element.addEventListener(eventName, eventListener);
        return () => {
            element.removeEventListener(eventName, eventListener);
        };
    }, [eventName, element]);
}

這裡會用isEdit來控制編輯器的出現,並且在按下esc (keyCode: 27) 鍵來把isEdit變為false。然後按下編輯時,會把要編輯的原始內容跟編號放到mdInfo之中,編輯的畫面就會從中取得資料去做編輯,並由onChange即時更新mdInfo內的content

底下的useEventListener就看看就好,因為時間不多所以不多做深入的介紹了,反正由於hook的關係,使用原本的lisener方式會導致一些小問題,所以才要把listener另外獨立出來變成另一個component。


點兩下之後的編輯畫面


後記

今天完工後就只剩下API的製作與介接和Redux Saga的介紹與應用啦!API應該會在明天先把基本的功能都實作出來,但是為了簡單就不用使用到資料庫了,先單純以JSON檔案來控制標記。

附上專案:2022-iThomeIronman

對資安或Mapbox有興趣的話也可以觀看我們團隊的鐵人發文喔~


上一篇
Day 23 - 影片標記頁面初步刻畫
下一篇
Day 25 - 建立專屬於影片標記系統的API
系列文
新手進化日記,從React至Redux Saga30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言