更新视频播放组件

This commit is contained in:
al 2024-12-19 18:33:13 +08:00
parent 663b8a20c0
commit 750f1ab18e
20 changed files with 797 additions and 687 deletions

View File

@ -96,7 +96,7 @@ textarea {
.custom-tabs .adm-tabs-tab-line {
background: none;
background-image: url("https://filecdn01.tiefen.fun/web_app_public/icons/tabindicator.png");
background-image: url("https://filecdntx01.tiefen.fun/web_app_public/icons/tabindicator.png");
height: 34px;
background-position: -2px -18px;
background-size: cover;
@ -179,6 +179,7 @@ textarea {
.adm-list-body,
.adm-list-item {
padding: 0 !important;
border: none !important;
background: none !important;
}
@ -194,7 +195,7 @@ textarea {
.tabPinkLine::after {
content: "";
position: absolute;
background-image: url("https://filecdn01.tiefen.fun/web_app_public/icons/tabindicator.png");
background-image: url("https://filecdntx01.tiefen.fun/web_app_public/icons/tabindicator.png");
height: 34px;
background-position: -2px -18px;
background-size: cover;
@ -207,7 +208,7 @@ textarea {
.titlePinkLine::after {
content: "";
position: absolute;
background-image: url("https://filecdn01.tiefen.fun/web_app_public/icons/pinkline.png");
background-image: url("https://filecdntx01.tiefen.fun/web_app_public/icons/pinkline.png");
height: 12px;
width: inherit;
min-width: 42px;
@ -304,6 +305,7 @@ textarea {
.adm-list-item-content {
padding: 0;
border: none!important;
}
.customize-body img {
max-height: 90vh;
@ -390,3 +392,11 @@ textarea {
}
}
}
.adm-slider-track{
background-color: #ff669e40 !important;
}
.adm-slider-thumb{
background-color: #ff669e !important;
transform: scale(0.5);
}

View File

@ -16,7 +16,7 @@
.custom-tabs .adm-tabs-tab-line {
background: none;
background-image: url("https://filecdn01.tiefen.fun/web_app_public/icons/tabindicator.png");
background-image: url("https://filecdntx01.tiefen.fun/web_app_public/icons/tabindicator.png");
height: 34px;
background-position: -2px -18px;
background-size: cover;
@ -30,11 +30,11 @@
.adm-list-body-inner {
/* margin-top: 8px; */
}
.adm-image-viewer-indicator{
.adm-image-viewer-indicator {
color: #fff;
}
.imagesBtnsControllers{
.imagesBtnsControllers {
position: fixed;
top: 50%;
width: 100%;
@ -44,19 +44,20 @@
z-index: 10001;
pointer-events: none;
}
.imagesBtnsControllerLeft,.imagesBtnsControllerRight{
.imagesBtnsControllerLeft,
.imagesBtnsControllerRight {
width: 42px;
height: 42px;
border-radius: 53px;
background-color: #0000001A;
background-color: #0000001a;
background-size: contain;
background-repeat: no-repeat;
pointer-events: all;
}
.imagesBtnsControllerLeft{
.imagesBtnsControllerLeft {
background-image: url("/icons/left.png");
opacity: 0.5;
}
.imagesBtnsControllerRight{
.imagesBtnsControllerRight {
background-image: url("/icons/right.png");
}
}

View File

@ -15,7 +15,7 @@
}
.customTabs>div>div:last-child>div:first-child::after{
content: "";
background-image: url("https://filecdn01.tiefen.fun/web_app_public/icons/tabindicator.png");
background-image: url("https://filecdntx01.tiefen.fun/web_app_public/icons/tabindicator.png");
height: 44px;
background-size: cover;
background-repeat: no-repeat;

View File

@ -3,10 +3,12 @@
import React, { useEffect, useState } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faAngleRight } from "@fortawesome/free-solid-svg-icons";
import { Avatar, Image, Toast, Space } from "antd-mobile";
import { Avatar, Toast, Space } from "antd-mobile";
import { useRouter } from "next/navigation";
import { get } from "@/utils/storeInfo";
import requireAPI from "@/utils/requireAPI";
import OwnIcon from "@/components/OwnIcon";
import OwnImage from "@/components/OwnImage";
const My = () => {
const [userInfo, setUserInfo] = useState({});
const router = useRouter();
@ -87,35 +89,35 @@ const My = () => {
url: !zoneLength
? `my/createProfile`
: `space/${account.data.account.mid}`,
iconUrl: `icons/32DP/space.png`,
iconUrl: `/icons/32DP/space.png`,
title: !zoneLength ? "开通空间" : "我的空间",
subTitle:
account.data.account.role == 3 ? "创作者功能" : "完善资料后解锁",
},
{
url: `streamerPosts/${account.data.account.mid}`,
iconUrl: "icons/32DP/myposts.png",
iconUrl: "/icons/32DP/myposts.png",
title: "广场动态",
subTitle:
account.data.account.role == 3 ? "创作者功能" : "完善资料后解锁",
},
{
url: `my/wechatWaitingToAdd`,
iconUrl: "icons/32DP/wechat.png",
iconUrl: "/icons/32DP/wechat.png",
title: "待添加微信",
subTitle:
account.data.account.role == 3 ? "创作者功能" : "完善资料后解锁",
},
{
url: `my/editprofile`,
iconUrl: "icons/32DP/editprofile.png",
iconUrl: "/icons/32DP/editprofile.png",
title: "编辑资料",
subTitle:
account.data.account.role == 3 ? "创作者功能" : "完善资料后解锁",
},
{
url: `my/refund/refundList`,
iconUrl: "icons/32DP/wallet.png",
iconUrl: "/icons/32DP/wallet.png",
title: "退款审核",
subTitle:
account.data.account.role == 3 ? "创作者功能" : "完善资料后解锁",
@ -126,7 +128,7 @@ const My = () => {
currentOld = [
{
url: `my/streamerVerification/completeStreamerInformation`,
iconUrl: "icons/32DP/editprofile.png",
iconUrl: "/icons/32DP/editprofile.png",
title: "完善资料",
subTitle: "完善后解锁全部功能",
status:
@ -148,27 +150,27 @@ const My = () => {
let currentOld = [
{
url: `my/wallet`,
iconUrl: "icons/32DP/wallet.png",
iconUrl: "/icons/32DP/wallet.png",
title: "我的钱包",
},
{
url: `my/unlockedWechat`,
iconUrl: "icons/32DP/wechat.png",
iconUrl: "/icons/32DP/wechat.png",
title: "已解锁微信",
},
{
url: `my/streamerVerification/joinEntrance`,
iconUrl: "icons/32DP/join.png",
iconUrl: "/icons/32DP/join.png",
title: "申请入驻",
},
{
url: `/messageDetail`,
iconUrl: "icons/32DP/contact.png",
iconUrl: "/icons/32DP/contact.png",
title: "联系客服",
},
{
url: `/my/addToHome`,
iconUrl: "icons/32DP/toScreen.png",
iconUrl: "/icons/32DP/toScreen.png",
title: "添加到主屏幕",
},
];
@ -229,12 +231,9 @@ const My = () => {
}}
>
<div className="flex items-center">
<Image
className="mr-2"
width={32}
src={`${process.env.NEXT_PUBLIC_WEB_ASSETS_URL}/${iconUrl}`}
placeholder=""
/>
<div className="mr-2">
<OwnIcon className="w-[32px] h-[32px]" src={iconUrl} />
</div>
<span className="text-base">{title}</span>
</div>
<div className={`flex items-center text-[#FFFFFF80]`}>
@ -281,26 +280,20 @@ const My = () => {
router.push("my/editUserProfile/selectUserProfileItem")
}
>
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/icons/32DP/edit.png"
}
<OwnIcon
src="/icons/32DP/edit.png"
width={32}
className="w-4 h-full"
placeholder=""
className="h-full w-full"
/>
</div>
<div
className="w-9 h-9 flex items-center justify-center bg-[#FFFFFF1A] rounded-full"
onClick={() => router.push("my/setting")}
>
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/icons/32DP/setting.png"
}
<OwnIcon
src="/icons/32DP/setting.png"
width={32}
className="w-4 h-full"
placeholder=""
className="h-full w-full"
/>
</div>
</div>
@ -310,12 +303,15 @@ const My = () => {
onClick={() => router.push("profile/" + userInfo.mid)}
>
<div className="flex items-center">
<Avatar
rounded-full
src={userInfo.avatar?.images[0].urls[0]}
className="mr-4"
style={{ "--size": "76px", "--border-radius": "50%" }}
/>
<div className="mr-4">
<OwnImage
width="76px"
height="76px"
roundedFull
src={userInfo.avatar?.images[0].urls[0]}
className="rounded-full"
/>
</div>
<div>
<Space align="center">
<p
@ -327,27 +323,15 @@ const My = () => {
{userInfo.name}
</p>
{userInfo?.is_a_member === 1 && (
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
"/icons/vipbig.png"
}
width={32}
height={32}
placeholder=""
/>
<OwnIcon src="/icons/vipbig.png" width={32} height={32} />
)}
</Space>
<div className="h-4 flex items-center text-xs bg-[#ffffff18] rounded-full px-2 py-2.5 mt-1 w-max">
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
"/icons/info/ID.png"
}
<OwnIcon
src="/icons/info/ID.png"
width={14}
height={14}
className="w-4 h-full mr-1"
placeholder=""
/>
<span>{userInfo.user_id}</span>
</div>
@ -363,12 +347,15 @@ const My = () => {
) : (
<div className="flex items-center justify-between mb-4">
<div className="flex items-center">
<Avatar
rounded-full
src={userInfo.avatar?.images[0].urls[0]}
className="mr-4"
style={{ "--size": "76px", "--border-radius": "50%" }}
/>
<div className="mr-4">
<OwnImage
width="76px"
height="76px"
roundedFull
src={userInfo.avatar?.images[0].urls[0]}
className="rounded-full"
/>
</div>
<div>
<Space align="center">
<p
@ -380,27 +367,15 @@ const My = () => {
{userInfo.name}
</p>
{userInfo?.is_a_member === 1 && (
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
"/icons/vipbig.png"
}
width={32}
height={32}
placeholder=""
/>
<OwnIcon src="/icons/vipbig.png" width={32} height={32} />
)}
</Space>
<div className="h-4 flex items-center text-xs bg-[#ffffff18] rounded-full px-2 py-2.5 mt-1 w-max">
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
"/icons/info/ID.png"
}
<OwnIcon
src="/icons/info/ID.png"
width={14}
height={14}
className="w-4 h-full mr-1"
placeholder=""
/>
<span>{userInfo.user_id}</span>
</div>

View File

@ -15,7 +15,7 @@
}
.customTabs>div>div:last-child>div:first-child::after{
content: "";
background-image: url("https://filecdn01.tiefen.fun/web_app_public/icons/tabindicator.png");
background-image: url("https://filecdntx01.tiefen.fun/web_app_public/icons/tabindicator.png");
height: 44px;
background-size: cover;
background-repeat: no-repeat;

View File

@ -78,14 +78,12 @@ export default function JoinEntrance() {
</div>
{/* 内容 */}
<div className="h-screen relative">
<div className="absolute inset-x-0 bottom-24 top-24 flex flex-col items-center justify-center gap-12">
<div className="mt-20 flex flex-col items-center justify-center gap-6">
<div
className="max-w-80"
onClick={() =>
(streamerState?.basic_status === 2 ||
streamerState?.basic_status === 4) &&
(streamerState?.details_status === 2 ||
streamerState?.details_status === 4) &&
router.push("joinStreamer")
}
>
@ -93,10 +91,10 @@ export default function JoinEntrance() {
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
`/images/${
streamerState?.basic_status === 1 &&
streamerState?.details_status === 1
? "streamerJoined"
: "streamerJoin"
streamerState?.basic_status === 2 ||
streamerState?.basic_status === 4
? "streamerJoin"
: "streamerJoined"
}.png`
}
placeholder=""

View File

@ -15,7 +15,7 @@
}
.customTabs>div>div:last-child>div:first-child::after{
content: "";
background-image: url("https://filecdn01.tiefen.fun/web_app_public/icons/tabindicator.png");
background-image: url("https://filecdntx01.tiefen.fun/web_app_public/icons/tabindicator.png");
height: 44px;
background-size: cover;
background-repeat: no-repeat;

View File

@ -11,7 +11,8 @@ import requireAPI from "@/utils/requireAPI";
import { connect } from "react-redux";
import { changeNoticeCount } from "@/store/actions";
import { Image, Badge, Toast } from "antd-mobile";
const MessageList = ({ mid, changeNoticeCount, refInstance }) => {
import OwnImage from "@/components/OwnImage";
const MessageList = ({ mid, changeNoticeCount, refInstance, noticeCount }) => {
const router = useRouter();
const [data, setData] = useState([]);
const [scollNotice, setScollNotice] = useState("");
@ -66,6 +67,7 @@ const MessageList = ({ mid, changeNoticeCount, refInstance }) => {
});
return;
}
changeNoticeCount(0);
} catch (error) {
console.error(error);
}
@ -79,7 +81,7 @@ const MessageList = ({ mid, changeNoticeCount, refInstance }) => {
getData();
getActiveNotice();
}, []);
}, [noticeCount]);
const getData = async () => {
try {
const body = {
@ -104,9 +106,6 @@ const MessageList = ({ mid, changeNoticeCount, refInstance }) => {
return;
}
const noticeObj = _data.data.result;
changeNoticeCount(_data.data.total);
// console.log("noticeObjNum", noticeObj);
setData(noticeObj);
setInfoItems((old) => {
const newInfoItems = [...old];
@ -163,15 +162,13 @@ const MessageList = ({ mid, changeNoticeCount, refInstance }) => {
}
className="flex flex-row items-center py-4 mb-2 rounded-xl bg-[#ffffff1a] gap-3 px-4"
>
<div className="">
<Image
width={54}
height={54}
className="rounded-full"
src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL + icon}
fit="cover"
/>
</div>
<OwnImage
width={54}
height={54}
className="rounded-full"
src={icon}
fit="cover"
/>
<div className="flex flex-row justify-between items-center flex-1">
<div className="flex flex-col">
<div className="flex flex-row items-center mb-2">
@ -219,7 +216,7 @@ const MessageList = ({ mid, changeNoticeCount, refInstance }) => {
className="flex flex-row items-center py-4 mb-2 rounded-xl"
>
<div className="px-4">
<Image
<OwnImage
width={36}
height={36}
className="rounded-full"
@ -248,11 +245,15 @@ const MessageList = ({ mid, changeNoticeCount, refInstance }) => {
</div>
);
};
const mapStateToProps = ({ reducer }) => {
return {
noticeCount: reducer.noticeCount,
};
};
const mapDispatchToProps = {
changeNoticeCount,
};
const Component = connect(null, mapDispatchToProps)(MessageList);
const Component = connect(mapStateToProps, mapDispatchToProps)(MessageList);
export default forwardRef((props, ref) => (
<Component {...props} refInstance={ref} />
));

View File

@ -29,7 +29,9 @@ export default function NoticeItem({ navigation, leftIcon, hasLink, data }) {
</div>
<p className="text-lg font-medium mr-2 ">{data?.title}</p>
</div>
<p className="text-base font-medium my-2">{data?.message}</p>
<pre className="text-base font-medium my-2 whitespace-pre-wrap">
{data?.message}
</pre>
{/* 链接跳转 */}
{!!data?.hyperlinks && (
<div

View File

@ -15,7 +15,7 @@
}
.customTabs>div>div:last-child>div:first-child::after{
content: "";
background-image: url("https://filecdn01.tiefen.fun/web_app_public/icons/tabindicator.png");
background-image: url("https://filecdntx01.tiefen.fun/web_app_public/icons/tabindicator.png");
height: 44px;
background-size: cover;
background-repeat: no-repeat;

View File

@ -24,7 +24,10 @@ export default function AddToHome() {
fit="cover"
className="rounded-md mr-3"
// src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL+"/icons/nodata.png"}
src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/images/icon.png"}
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
"/images/icon_border.png"
}
placeholder=""
width={46}
height={46}

View File

@ -9,7 +9,7 @@ import { changeNoticeCount, changeInviter } from "@/store/actions";
import { connect } from "react-redux";
import { get } from "@/utils/storeInfo";
import requireAPI from "@/utils/requireAPI";
import { ErrorBoundary } from "react-error-boundary";
import OwnIcon from "../OwnIcon";
function BottomNav({ changeNoticeCount, changeInviter, noticeCount }) {
const searchParams = useSearchParams();
const pathname = usePathname();
@ -37,12 +37,12 @@ function BottomNav({ changeNoticeCount, changeInviter, noticeCount }) {
if (_data.ret === -1) {
return;
}
changeNoticeCount(_data.data.total);
if (!noticeCount) changeNoticeCount(_data.data.total);
} catch (error) {}
};
getDtata();
return () => {};
}, []);
}, [noticeCount]);
const setRouteActive = (value) => {
router.replace(value);
};
@ -50,80 +50,36 @@ function BottomNav({ changeNoticeCount, changeInviter, noticeCount }) {
{
key: "/",
title: "广场",
icon: (
<div className="w-8 h-8">
<Image
placeholder=""
src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/icons/postblur.png"}
/>
</div>
),
activeIcon: (
<div className="w-8 h-8">
<Image
placeholder=""
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/icons/postfocus.png"
}
/>
</div>
),
icon: <OwnIcon className="w-8 h-8" src="/icons/postblur.png" />,
activeIcon: <OwnIcon className="w-8 h-8" src="/icons/postfocus.png" />,
},
{
key: "/space",
title: "空间",
icon: (
<div className="w-8 h-8">
<Image
placeholder=""
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/icons/space_blur.png"
}
/>
</div>
),
activeIcon: (
<div className="w-8 h-8">
<Image
placeholder=""
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/icons/space_focus.png"
}
/>
</div>
),
icon: <OwnIcon className="w-8 h-8" src="/icons/space_blur.png" />,
activeIcon: <OwnIcon className="w-8 h-8" src="/icons/space_focus.png" />,
},
{
key: "/noticeDetail",
title: "消息",
icon: (
<div className="w-8 h-8 relative">
<Image
placeholder=""
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/icons/streamblur.png"
}
/>
<div className="relative">
<OwnIcon className="w-8 h-8" src="/icons/streamblur.png" />
{!!noticeCount && (
<Badge
content={noticeCount > 99 ? "+99" : noticeCount}
className="absolute top-0 right-1"
className="absolute top-0 right-0 z-10"
/>
)}
</div>
),
activeIcon: (
<div className="w-8 h-8 relative">
<Image
placeholder=""
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/icons/streamfocus.png"
}
/>
<div className="relative">
<OwnIcon className="w-8 h-8" src="/icons/streamfocus.png" />
{!!noticeCount && (
<Badge
content={noticeCount > 99 ? "+99" : noticeCount}
className="absolute top-0 right-1"
className="absolute top-0 right-0 z-10"
/>
)}
</div>
@ -132,22 +88,8 @@ function BottomNav({ changeNoticeCount, changeInviter, noticeCount }) {
{
key: "/my",
title: "我的",
icon: (
<div className="w-8 h-8">
<Image
placeholder=""
src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/icons/myblur.png"}
/>
</div>
),
activeIcon: (
<div className="w-8 h-8">
<Image
placeholder=""
src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/icons/myfocus.png"}
/>
</div>
),
icon: <OwnIcon className="w-8 h-8" src="/icons/myblur.png" />,
activeIcon: <OwnIcon className="w-8 h-8" src="/icons/myfocus.png" />,
},
];
const checkPath = () => {

View File

@ -0,0 +1,34 @@
import React from "react";
import { Image } from "antd-mobile";
export default function OwnIcon({
src,
width = "100%",
height = "100%",
className,
outClassName,
imageClassName,
}) {
return (
<div
className={`flex flex-col justify-center items-center relative ${outClassName}`}
>
<div className={`w-12 h-12 ${className} z-[0]`}>
<Image
height={height}
width={width}
fit="cover"
className={imageClassName}
src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL + src}
// placeholder=""
fallback={
<div className="w-full h-full bg-gray-700 rounded-full absolute top-0 scale-75 z-0 animate-pulse" />
}
placeholder={
<div className="w-full h-full bg-gray-700 rounded-full absolute top-0 scale-75 z-0 animate-pulse" />
}
/>
<div className="w-full h-full bg-transparent absolute top-0 z-20" />
</div>
</div>
);
}

View File

@ -0,0 +1,33 @@
import React from "react";
import { Image } from "antd-mobile";
export default function OwnImage({
src,
width = "100%",
height = "100%",
className,
roundedFull,
...others
}) {
return (
<div className="flex flex-col justify-center items-center relative">
<div className={`${className}`}>
<Image
height={height}
width={width}
fit="cover"
src={src}
className={roundedFull ? "rounded-full" : ""}
// placeholder=""
fallback={
<div className="w-full h-full bg-gray-500 absolute top-0 z-0 animate-pulse" />
}
placeholder={
<div className="w-full h-full bg-gray-700 absolute top-0 z-0 animate-pulse" />
}
{...others}
/>
<div className="w-full h-full bg-transparent absolute top-0 z-20" />
</div>
</div>
);
}

View File

@ -5,7 +5,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faClose } from "@fortawesome/free-solid-svg-icons";
// import styles from "./index.module.scss";
export default function OwnInput({
value,
onChange,
type = "text",
name,
@ -16,21 +15,22 @@ export default function OwnInput({
inputClassName = "",
id,
maxLength = 999,
...other
}) {
return (
<div className={`flex flex-1 relative ${className}`}>
<input
{...other}
id={id}
placeholder={placeholder}
disabled={disabled}
name={name}
type={type}
maxLength={maxLength}
onChange={(e) => onChange(e.target?.value)}
value={value}
onChange={(e) => onChange && onChange(e.target?.value)}
className={`w-full placeholder:text-[#FFFFFF80] text-[16px] focus:text-[16px] ${inputClassName}`}
/>
{clearable && value != "" && (
{clearable && other?.value != "" && (
<div className="w-4 h-4 absolute right-2 top-[2px] flex justify-center items-center bg-[#ffffff33] p-1 rounded-full">
<FontAwesomeIcon
color="#ffffff40"

View File

@ -1,14 +1,16 @@
"use client";
import React, { useEffect, useState, useRef } from "react";
import { Image, ImageViewer, Dialog } from "antd-mobile";
import { ImageViewer } from "antd-mobile";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faAngleUp, faClose } from "@fortawesome/free-solid-svg-icons";
import { faAngleUp } from "@fortawesome/free-solid-svg-icons";
import { useRouter } from "next/navigation";
import baseRequest from "@/utils/baseRequest";
import { handleShowVideo } from "@/utils/tools/handleFuns";
import OwnImage from "../OwnImage";
// import dynamic from 'next/dynamic'
import ImagesMask from "@/components/ImagesMask";
import OwnIcon from "../OwnIcon";
// const ImagesMask = dynamic(() =>
// import('@/components/ImagesMask'), { ssr: false }
// )
@ -24,7 +26,6 @@ export default function Photos({
const [seeAllPhotos, setSeeAllPhotos] = useState(false);
const [currentPhotos, setCurrentPhotos] = useState([]);
const [photos, setPhotos] = useState([]);
const [visible, setVisible] = useState(false);
const currentIndex = useRef();
const swiper = useRef(null);
const imagesMaskRef = useRef(null);
@ -269,11 +270,11 @@ export default function Photos({
currentPhotos.length > 1 ? "h-[24vw]" : ""
}`}
>
<Image
<OwnImage
// lazy={true}
placeholder={
<div className="w-full min-h-[24vw] bg-[#1d1d1d] rounded"></div>
}
// placeholder={
// <div className="w-full min-h-[24vw] bg-[#1d1d1d] rounded"></div>
// }
width={
currentPhotos.length > 1
? "24vw"
@ -306,16 +307,11 @@ export default function Photos({
}
{item?.mp4 && (
<div className="absolute top-0 w-full h-full rounded flex justify-center items-center">
<Image
className=""
width={98}
height={98}
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/icons/play.png"
}
placeholder={
<div className="w-full h-full min-h-96 bg-[#1d1d1d] rounded"></div>
}
<OwnIcon
width={68}
height={68}
imageClassName="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2"
src="/icons/play.png"
/>
</div>
)}

View File

@ -4,7 +4,9 @@ import React, { useEffect, useState, useMemo, useCallback } from "react";
import Photos from "../Photos";
import { useRouter } from "next/navigation";
import PaySpacePost from "../PaySpacePost";
import { Image, Popover, Divider, Toast } from "antd-mobile";
import { Popover, Toast } from "antd-mobile";
import OwnImage from "../OwnImage";
import OwnIcon from "../OwnIcon";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faAngleRight } from "@fortawesome/free-solid-svg-icons";
import { handleFollow, thumbsUp, handleBlock } from "@/api/public";
@ -144,11 +146,7 @@ export default function PostItem({
return (
<div>
{type == "space" && data?.is_headed === 1 && (
<Image
src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/images/top_post.png"}
width={76}
className="mb-2"
/>
<OwnIcon src="/images/top_post.png" width={76} outClassName="mb-2" />
)}
<div className="flex">
<div
@ -157,13 +155,12 @@ export default function PostItem({
router.push("/profile/" + data.mid);
}}
>
<Image
<OwnImage
className="flex-none w-8 h-8 rounded-full mr-2"
fit="cover"
width={"2rem"}
height={"2rem"}
roundedFull
src={data.streamer_ext?.avatar.images[0].urls[0]}
alt=""
/>
</div>
@ -287,14 +284,11 @@ export default function PostItem({
>
{data.streamer_ext.is_active_within_a_week ? (
<>
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
"/icons/space_new_post.png"
}
<OwnIcon
src="/icons/space_new_post.png"
width={18}
className="w-4 h-full mr-1"
placeholder=""
className="w-4 h-full "
outClassName="mr-1"
/>
<span className="mr-1 text-primary text-xs">
{/* {data.streamer_ext.days_elapsed_since_the_last_zones_update < 7 &&
@ -364,16 +358,14 @@ export default function PostItem({
thumbsUp(data.id, isThumbsUp, setIsThumbsUp, type == "space")
}
>
<Image
<OwnIcon
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
(isThumbsUp == 1
isThumbsUp == 1
? "/icons/thumbup.png"
: "/icons/notthumbup.png")
: "/icons/notthumbup.png"
}
width={32}
className="w-4 h-full"
placeholder=""
className="w-full h-full"
/>
<span
className={`text-xs ${

View File

@ -0,0 +1,106 @@
import React, { useEffect, useState, useRef } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faPlayCircle, faPauseCircle } from "@fortawesome/free-solid-svg-icons";
import { Slider, Toast } from "antd-mobile";
import BackgroundPlayer from "next-video/background-player";
export default function VideoPlayer({ video }) {
const [videoState, setVideoState] = useState({
play: true,
currentTimePercentage: 0,
});
const isSliding = useRef(null);
// const currentTime = useMemo(()=>{
// const videoPlayer = document.getElementById("videoPlayer");
// if (videoPlayer) {
// return videoPlayer.currentTime;
// }
// return 0;
// })
useEffect(() => {
const videoPlayer = document.getElementById("videoPlayer");
if (videoPlayer) {
videoPlayer.addEventListener("ended", () => {
setVideoState((old) => ({ ...old, play: false }));
});
videoPlayer.addEventListener("timeupdate", () => {
console.log((videoPlayer.currentTime / videoPlayer.duration) * 100);
if (!isSliding.current)
setVideoState((old) => ({
...old,
currentTimePercentage:
(videoPlayer.currentTime / videoPlayer.duration) * 100,
}));
});
}
}, []);
const toastValue = (value) => {
isSliding.current = true;
const videoPlayer = document.getElementById("videoPlayer");
if (!videoPlayer) return;
videoPlayer.pause();
const totalTime = videoPlayer.duration;
let timeSec = 0;
if (videoPlayer) {
timeSec = (totalTime * value) / 100;
}
const hour = Math.floor(timeSec / (60 * 60));
const minute = Math.floor((timeSec - hour * (60 * 60)) / 60);
const second = Math.floor(timeSec - hour * (60 * 60) - minute * 60);
Toast.show(
`${hour > 9 ? hour : "0" + hour}:${minute > 9 ? minute : "0" + minute}:${
second > 9 ? second : "0" + second
}`
);
videoPlayer.currentTime = timeSec;
setVideoState((old) => ({ ...old, currentTimePercentage: value }));
};
const handleStart = () => {
const videoPlayer = document.getElementById("videoPlayer");
if (!videoPlayer) return;
videoPlayer.play();
isSliding.current = false;
};
return (
<div className="relative">
<BackgroundPlayer
src={video.mp4}
id="videoPlayer"
// controlsList="none"
poster={video?.url.src}
blurDataURL={video?.url.blurDataURL}
autoPlay={videoState.play}
// style={{ height: "calc(100vh)" }}
/>
<div
className="absolute w-full px-4 grid justify-between items-center"
style={{
bottom: "12px",
gridTemplateColumns: "calc(100% - 32px) 32px",
}}
>
<Slider
value={videoState.currentTimePercentage}
onAfterChange={handleStart}
onChange={toastValue}
icon={<div></div>}
style={{ "--fill-color": "#ff669e" }}
/>
<FontAwesomeIcon
icon={videoState.play ? faPauseCircle : faPlayCircle}
style={{ maxWidth: "32px" }}
size="2xl"
onClick={() => {
const videoPlayer = document.getElementById("videoPlayer");
if (videoState.play) {
setVideoState((old) => ({ ...old, play: false }));
videoPlayer.pause();
} else {
setVideoState((old) => ({ ...old, play: true }));
videoPlayer.play();
}
}}
/>
</div>
</div>
);
}

View File

@ -3,7 +3,7 @@ import { faClose } from "@fortawesome/free-solid-svg-icons";
import { Dialog, Toast } from "antd-mobile";
import html2canvas from "html2canvas";
import { checkRole } from "../auth";
import Player from "next-video/player";
import VideoPlayer from "@/components/VideoPlayer";
// export const handleShowVideos = (video) => {
// Dialog.className = "videoMask";
// Dialog.show({
@ -52,7 +52,7 @@ export const handleShowVideo = (video) => {
Dialog.className = "videoMask";
Dialog.show({
title: "",
bodyStyle: { paddingTop: 0 },
bodyClassName: "!p-0",
content: (
<div className="h-screen flex justify-center items-center relative">
<div
@ -60,16 +60,10 @@ export const handleShowVideo = (video) => {
onClick={() => Dialog.clear()}
></div>
<div className="w-screen flex flex-col gap-2 pointer-events-none absolute top-0">
<div className="flex w-full justify-end">
<div
className="pointer-events-auto flex w-12 h-12 justify-center items-center bg-[#33333348] rounded-full"
key="closeBtn"
onClick={() => Dialog.clear()}
>
<FontAwesomeIcon icon={faClose} size="2xl" />
</div>
</div>
<div className="my-2 pointer-events-auto">
<div
className="w-full h-screen pointer-events-auto relative "
style={{ background: "#00000080" }}
>
{/* <video
width="100%"
height="100%"
@ -83,14 +77,37 @@ export const handleShowVideo = (video) => {
您的浏览器不支持 Video 标签
</video> */}
{/* <Video as={ReactPlayer} src={video.mp4} /> */}
<Player
src={video.mp4}
controlslist="nodownload"
poster={video?.url.src}
blurDataURL={video?.url.blurDataURL}
autoPlay={true}
style={{ height: "calc(100vh - 180px)" }}
/>
<div className="absolute top-1/2 -translate-y-1/2 w-full">
<VideoPlayer video={video} />
</div>
{/* <label
onClick={() => {
const videoPlayer = document.getElementById("videoPlayer");
console.log("videoPlayer", videoPlayer, videoPlayer.click);
// videoPlayer.play();
if (state.play) {
state.play = false;
videoPlayer.pause();
} else {
state.play = true;
videoPlayer.play();
}
}}
className="block w-full h-screen bg-[#ab27275e] absolute top-0"
/> */}
<div
className="max-w-max absolute top-[21px] right-4 z-30"
style={{ top: "21px", zIndex: 30 }}
>
<div
className="pointer-events-auto flex w-12 h-12 justify-center items-center bg-[#33333348] rounded-full"
key="closeBtn"
onClick={() => Dialog.clear()}
>
<FontAwesomeIcon icon={faClose} size="2xl" />
</div>
</div>
{/* <Player
src="https://www.mydomain.com/remote-video.mp4"
poster="https://www.mydomain.com/remote-poster.webp"