1.0.4 • Published 3 months ago

react-filerobot-media-annotator v1.0.4

Weekly downloads
-
License
-
Repository
-
Last release
3 months ago

React Filerobot Media Annotator

An emendable web-based plugin that is used in annotating the media files (images & videos) with consideration of your media player's design/controls.

Demo

TBD.....

Features

  • ⏳ History management (Undo/Redo).
  • 🎨 Image/Video Annotating & Drawing.
  • 🧊 A variety of annotating shapes.
  • 🏗️ Easy, Focused & Simple UI for better UX.
  • ➕ Ability to customize.
  • 🤹🏼 And more to discover by yourself...

Contents

Prerequisites

You have to install the following packages (if you haven't them installed in your project) as they are required as peer dependencies,

  • react, react-dom >= v17.0.1
  • styled-components >= 5.2.3",
  • @scaleflex/ui >= 2.0.0-beta.40
  • @scaleflex/icons >= 2.0.0-beta.36
  • reactjs-eventemitter >= 1.0.6
  • react, react-dom: npm install --save react react-dom.
  • styled-components: npm install --save styled-components.
  • scaleflex/ui, @scaleflex/icons: npm install --save @scaleflex/ui @scaleflex/icons.
  • reactjs-eventemitter: npm install --save reactjs-eventemitter.

Installation

NPM

npm install --save react-filerobot-media-annotator

Usage/Examples

React Example

import React, { useRef } from 'react';

import {
  Canvas,
  AnnotatingField,
	Comments
} from 'react-filerobot-media-annotator';
import translations from './translations';
import {
  createCommentRequest, deleteCommentsRequest, dislikeCommentRequest, editCommentTextRequest,
  fetchCommentsRequest, likeCommentRequest, subscribeToCommentRequest,
  unsubscribeToCommentRequest,
} from './services';

const Annotator = ({ config }) => {
  const mediaRef = useRef(null);
  const rootContainerRef = useRef(null);

//First of all we need to map the fetched comment to the plugin comments format!
	const getFormattedComment = (fetchedComment) => ({
		id: fetchedComment.id,
		shapes: fetchedComment.shapes || [],
		user: {
      id: fetchedComment.user.id,
			name: fetchedComment.user.userName,
			photo_uri: fetchedComment.user.photo,
		},
		createdAt: fetchedComment.createdAt,
		body: fetchedComment.body,
		meta: {
		  likers: fetchedComment.meta.likers || [],
			subscribers: fetchedComment.meta.subscribers || [],
			resolved: fetchedComment.meta.resolved || false,
			canvasDimensions: fetchedComment.meta.canvasDimensions,
			displayTimeStamp: fetchedComment.meta.displayTimeStamp || null,
	}})

//Then fetch the backend comments and get our mapped comments!
  const getComments = () => (
		//do not forget to import your fetchCommentRequest function!
    fetchCommentsRequest().then(({ comments: fetchedComments = [] }) => {
      const updatedComments = fetchedComments.map((fetchedComment) => {
        return getFormattedComment(fetchedComment)
      });

      return updatedComments;
    })
  );

//We need a way to handle our various updates! here we used actions object
//you can handle the updateComment function they way you prefer ⚡
//do not forget to import your commentRequests or equivalent logic functions!
  const ACTIONS = {
    [ACTIONS_IDS.TOGGLE_LIKE || 'toggleLike']: {
      action: (updatedComment, updates) => {
        const newLikers = updates;
        if (newLikers.includes(config.currentUserId)) {
          return likeCommentRequest(updatedComment.id).then((res) => (res));
        }
        return dislikeCommentRequest(updatedComment.id).then((res) => (res));
      },
    },
    [ACTIONS_IDS.TOGGLE_SUBSCRIBE || 'toggleSubscribe']: {
      action: (updatedComment, updates) => {
        const newSubscribers = updates;
        if (newSubscribers.includes(config.currentUserId)) {
          return subscribeToCommentRequest(updatedComment.id).then((res) => (res));
        }
        return unsubscribeToCommentRequest(updatedComment.id).then((res) => (res));
      },
    },
    [ACTIONS_IDS.UPDATE_COMMENT_PROPS || 'updateCommentProps']: {
      action: (updatedComment, updates) => {
        const newResolve = updates;
        return editCommentTextRequest(updatedComment.id, {resolved: newResolve});
      },
    },
    [ACTIONS_IDS.UPDATE_COMMENT_TEXT || 'updateCommentText']: {
      action: (updatedComment, updates) => {
        const newText = updates;
        return editCommentTextRequest(updatedComment.id, { text: newText });
      },
    },
  };

	const updateComment = ({ actionId, updatedComment, updates }) => (
    ACTIONS?.[actionId]?.action(updatedComment, updates)
  );

//We need a function to handle submitting of new comment then returning new, mapped comment
// do not forget to import your createCommentRequest function!
  const onSubmitComment = (newCommentProps) => createCommentRequest(newCommentProps)
    .then((newComment) => {
			return getFormattedComment(newComment)
    });

//Also a function to handle replying to comment then returning new, mapped comment
// do not forget to import your createReplyRequest function!
  const createReply = (newCommentProps) => createReplyRequest(newCommentProps)
    .then((newComment) => {
			return getFormattedComment(newComment)
    });

//Finally, we need a function to handle delete comment and then return the new Comments!
// do not forget to import your deleteCommentsRequest function!
  const deleteComment = (commentId) => (
    deleteCommentsRequest([commentId]).then(() => (
      getComments().then((newComments) => (newComments))
    ))
  );

  return (
    <div ref={rootContainerRef}>
      <video
        ref={mediaRef}
        muted
      >
        <track src={'http://www.w3schools.com/html/mov_bbb.mp4'} />
        <source src={'captions_en.vtt'} />
      </video>
      <Canvas
        isVideoShapesAutoStreamed={true}
        mediaRef={mediaRef}
        shapeStreamingDuration={1000}
      />
      <AnnotatingField
			  annotatingTools={['Color', 'Brush', 'Circle', 'Square', 'Line', 'Arrow']}
        translations={translations}
        onSubmit={onSubmitComment}
      />
      <Comments
        isVideoAutoPlayed
        translations={translations}
        getComments={getComments}
        createReply={createReply}
        updateComment={updateComment}
        deleteComment={deleteComment}
        currentUserId={currentUserId}
      />
  </div>
  );
};

export default Annotator;

Config

NOTE: The plugin respects the container/wrapper HTML element through CSS by having both width & height set 100% so you could change the width/height of the plugin through adding/changing width/height of the wrapper HTML element.

Properties

theme

Type: object

Supported version: +v0.1.0

Default: {}.

Defines the theme used in the plugin, utilized by @scaleflex/ui library, u'll find the theme object form here.

currentUserId

Type: string

Supported version: +v0.1.0

Default: undefined.

The id of the current user using the plugin.

annotatingTools

Type: array

Supported version: +v0.1.0

The tools and shapes used to annotate shapes on media, available tools are Color, Brush, Circle, Square, Line, Arrow, if not supported all of them will be used

shapeStreamingDuration

Type: number

Supported version: +v0.1.0

Default: 1000.

The duration in milliseconds which the shape will be streamed until and then removed.

isVideoAutoPlayed

Type: boolean

Supported version: +v0.1.4

Default: true.

The flag to stream the play the loaded video automatically after comments loads.

isVideoShapesAutoStreamed

Type: boolean

Supported version: +v0.1.0

Default: true.

The flag to stream the shapes automatically on video play or just by clicking on comment.

translations

Type: object

Supported version: +v0.1.0

Default: undefined.

Translations keys and equivalent string supported to the plugin, if not supported the plugin will use the default keys as displayed in the following table see available translations

getComments

Type: async function

Supported version: +v0.1.0

Backend request function to get comments mapped to our comment object.

createReply

Type: async function

Supported version: +v0.1.0

Backend request function to reply to comment and get the new comments mapped to our comment object.

updateComment

Type: async function

Supported version: +v0.1.0

Backend request function to update comment.

deleteComment

Type: async function

Supported version: +v0.1.0

Backend request function to delete comment.

Development

To run in development mode, follow the next steps:

  1. Clone the repository.
  2. Open the repository's folder & run yarn to install the project's dependencies.
  3. Run yarn dev to start the project in development.
  4. Happy coding🕺🏽!

Used By

This project is used by the following companies:

Fork the repoistory, append your company's name with the URL in above format inside the README.md file and make a PR! or create a GitHub issue mentioning (Site's name & domain).

Feedback

Create an issue on github repo. and mention the details there.

Contributing

All contributions are super welcomed!

License

Filerobot Image Editor is provided under MIT License