Skip to content
This repository has been archived by the owner on Jan 15, 2025. It is now read-only.

Commit

Permalink
Merge pull request #1432 from ecency/improve-3speak-video-upload
Browse files Browse the repository at this point in the history
Improve 3speak video upload
  • Loading branch information
feruzm authored Aug 8, 2023
2 parents 27a93dd + 7fc844e commit 09a7232
Show file tree
Hide file tree
Showing 21 changed files with 329 additions and 149 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"start:prod": "NODE_ENV=production node build/server.js"
},
"dependencies": {
"@ecency/render-helper": "^2.2.24",
"@ecency/render-helper": "^2.2.25",
"@ecency/render-helper-amp": "^1.1.0",
"@firebase/analytics": "^0.8.0",
"@firebase/app": "^0.7.28",
Expand Down
1 change: 1 addition & 0 deletions src/common/api/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export interface MetaData {
export interface BeneficiaryRoute {
account: string;
weight: number;
src?: string;
}

export interface CommentOptions {
Expand Down
18 changes: 10 additions & 8 deletions src/common/api/threespeak/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useState } from "react";
import { uploadFile, uploadVideoInfo } from "./api";
import { QueryIdentifiers } from "../../core";
import { ThreeSpeakVideo } from "./types";
import { useThreeSpeakVideo } from "./queries";

export function useThreeSpeakVideoUpload() {
const [completedByType, setCompletedByType] = useState<Record<string, number>>({});
Expand All @@ -28,6 +28,7 @@ export function useThreeSpeakVideoUpload() {

export function useUploadVideoInfo() {
const queryClient = useQueryClient();
const { data, refetch } = useThreeSpeakVideo("all");

return useMutation(
["threeSpeakVideoUploadInfo"],
Expand Down Expand Up @@ -55,14 +56,15 @@ export function useUploadVideoInfo() {
},

{
onSuccess: (response) => {
onSuccess: async (response) => {
if (response) {
const next = [
response,
...(queryClient.getQueryData<ThreeSpeakVideo[]>([
QueryIdentifiers.THREE_SPEAK_VIDEO_LIST
]) ?? [])
];
let current = data;
if (current.length === 0) {
const response = await refetch();
current = response.data ?? [];
}

const next = [response, ...current];
queryClient.setQueryData([QueryIdentifiers.THREE_SPEAK_VIDEO_LIST], next);
queryClient.setQueryData([QueryIdentifiers.THREE_SPEAK_VIDEO_LIST_FILTERED, "all"], next);
}
Expand Down
2 changes: 1 addition & 1 deletion src/common/api/threespeak/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export function useThreeSpeakVideo(
const queryClient = useQueryClient();

const apiQuery = useQuery(
[QueryIdentifiers.THREE_SPEAK_VIDEO_LIST],
[QueryIdentifiers.THREE_SPEAK_VIDEO_LIST, activeUser?.username ?? ""],
async () => {
try {
return await getAllVideoStatuses(activeUser!.username);
Expand Down
1 change: 1 addition & 0 deletions src/common/components/beneficiary-editor/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import BeneficiaryEditorDialog, { DialogBody } from "./index";
import TestRenderer from "react-test-renderer";

const defProps = {
body: "",
list: [
{
account: "foo",
Expand Down
32 changes: 20 additions & 12 deletions src/common/components/beneficiary-editor/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { Component } from "react";

import { Button, Modal, Form, InputGroup, FormControl } from "react-bootstrap";
import { Button, Form, FormControl, InputGroup, Modal } from "react-bootstrap";

import BaseComponent from "../base";
import { error } from "../feedback";
Expand All @@ -11,11 +11,14 @@ import { getAccount } from "../../api/hive";

import { _t } from "../../i18n";

import { plusSvg, deleteForeverSvg, accountMultipleSvg } from "../../img/svg";
import { accountMultipleSvg, deleteForeverSvg, plusSvg } from "../../img/svg";
import { handleInvalid, handleOnInput } from "../../util/input-util";
import "./_index.scss";

const THREE_SPEAK_VIDEO_PATTERN = /\[!\[]\(https:\/\/ipfs-3speak.*\)\]\(https:\/\/3speak\.tv.*\)/g;

interface Props {
body: string;
author?: string;
list: BeneficiaryRoute[];
onAdd: (item: BeneficiaryRoute) => void;
Expand Down Expand Up @@ -162,16 +165,21 @@ export class DialogBody extends BaseComponent<Props, DialogBodyState> {
<td>{`@${x.account}`}</td>
<td>{`${x.weight / 100}%`}</td>
<td>
<Button
onClick={() => {
const { onDelete } = this.props;
onDelete(x.account);
}}
variant="danger"
size="sm"
>
{deleteForeverSvg}
</Button>
{!!this.props.body.match(THREE_SPEAK_VIDEO_PATTERN) &&
x.src === "ENCODER_PAY" ? (
<></>
) : (
<Button
onClick={() => {
const { onDelete } = this.props;
onDelete(x.account);
}}
variant="danger"
size="sm"
>
{deleteForeverSvg}
</Button>
)}
</td>
</tr>
);
Expand Down
46 changes: 44 additions & 2 deletions src/common/components/decks/deck-threads-form/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@
}
}

&:not(.inline) {
.deck-toolbar-threads-form-content {
overflow-x: hidden;
overflow-y: auto;
}
}

&::-webkit-scrollbar {
display: none;
}
Expand Down Expand Up @@ -192,6 +199,27 @@
background-color: rgba($primary, 0.15);
}
}

&-video-picker {
position: relative;

&::before {
content: '';
position: absolute;
top: 0.5rem;
right: 1rem;
width: 0.25rem;
height: 0.25rem;
opacity: 0;
background-color: $danger;
border-radius: 50%;
transition: 0.3s;
}

&:hover::before {
opacity: 1;
}
}
}

.deck-threads-form-selected-image {
Expand All @@ -206,8 +234,8 @@

.remove {
position: absolute;
top: 0;
right: 0;
top: 0.5rem;
right: 0.5rem;
background-color: $white;
display: flex;
align-items: center;
Expand All @@ -223,6 +251,20 @@
height: 1rem;
}
}

.type {
position: absolute;
background-color: $dark-sky-blue;
color: $white;
rotate: -45deg;
padding: 0.125rem;
text-align: center;
width: 100px;
top: 0.75rem;
left: -1.75rem;
font-size: 0.675rem;
text-transform: uppercase;
}
}

.dropdown {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import { closeSvg } from "../../../img/svg";
interface Props {
text: string;
setText: (v: string) => void;
video: string | null;
selectedImage: string | null;
setSelectedImage: (url: string | null) => void;
onAddImage: (url: string, name: string) => void;
onAddVideo: (value: string | null) => void;
placeholder?: string;
onTextareaFocus: () => void;
}
Expand All @@ -21,7 +23,9 @@ export const DeckThreadsFormControl = ({
selectedImage,
setSelectedImage,
placeholder,
onTextareaFocus
onTextareaFocus,
onAddVideo,
video
}: Props) => {
return (
<>
Expand All @@ -37,16 +41,34 @@ export const DeckThreadsFormControl = ({
<div className="length-prompt">{text.length}/255</div>
</div>
{selectedImage && (
<div className="deck-threads-form-selected-image">
<div className="deck-threads-form-selected-image border mb-3">
<div className="type">image</div>
<img src={selectedImage} alt="" />
<div className="remove" onClick={() => setSelectedImage(null)}>
{closeSvg}
</div>
</div>
)}
{video && (
<div className="deck-threads-form-selected-image border mb-3">
<div className="type">video</div>
<img
src={video
.matchAll(/<center>\[!\[](.*)].*<\/center>/g)
.next()
.value[1].replace("(", "")
.replace(")", "")}
alt=""
/>
<div className="remove" onClick={() => onAddVideo(null)}>
{closeSvg}
</div>
</div>
)}
<DeckThreadsFormToolbar
onAddImage={onAddImage}
onEmojiPick={(v) => setText(`${text}${v}`)}
onAddVideo={onAddVideo}
/>
</div>
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Tooltip from "../../tooltip";
import { _t } from "../../../i18n";
import { PopperDropdown } from "../../popper-dropdown";
import { videoSvg } from "../../../img/svg";
import React, { useState } from "react";
import { useMappedStore } from "../../../store/use-mapped-store";
import { VideoUpload } from "../../video-upload-threespeak";
import VideoGallery from "../../video-gallery";

interface Props {
onSelect: (video: string) => void;
}

export function DeckThreadsFormToolbarVideoPicker({ onSelect }: Props) {
const { activeUser, global } = useMappedStore();

const [showUpload, setShowUpload] = useState(false);
const [showGallery, setShowGallery] = useState(false);

return (
<div className="deck-threads-form-toolbar-video-picker">
{activeUser && (
<Tooltip content={_t("editor-toolbar.image")}>
<PopperDropdown toggle={videoSvg} hideOnClick={true}>
<div className="dropdown-menu">
<div className="dropdown-item" onClick={() => setShowUpload(true)}>
{_t("video-upload.upload-video")}
</div>
{global.usePrivate && (
<div className="dropdown-item" onClick={() => setShowGallery(true)}>
{_t("video-upload.video-gallery")}
</div>
)}
</div>
</PopperDropdown>
</Tooltip>
)}
<VideoUpload show={showUpload} setShow={setShowUpload} setShowGallery={setShowGallery} />
<VideoGallery
preFilter="published"
showGallery={showGallery}
setShowGallery={setShowGallery}
insertText={(v) => {
onSelect(v);
}}
/>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import { DeckThreadsFormEmojiPicker } from "./deck-threads-form-emoji-picker";
interface Props {
onAddImage: (url: string, name: string) => void;
onEmojiPick: (value: string) => void;
onAddVideo: (value: string) => void;
}

export const DeckThreadsFormToolbar = ({ onAddImage, onEmojiPick }: Props) => {
export const DeckThreadsFormToolbar = ({ onAddImage, onEmojiPick, onAddVideo }: Props) => {
return (
<div className="deck-threads-form-toolbar">
<DeckThreadsFormToolbarImagePicker onAddImage={onAddImage} />
<DeckThreadsFormEmojiPicker onPick={onEmojiPick} />
{/*<DeckThreadsFormToolbarVideoPicker onSelect={onAddVideo} />*/}
</div>
);
};
Loading

0 comments on commit 09a7232

Please sign in to comment.