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

Improve 3speak video upload #1432

Merged
merged 12 commits into from
Aug 8, 2023
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
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