[FEAT] update fullscreen management
This commit is contained in:
parent
ae9f00a60a
commit
57a48de52f
4
.gitignore
vendored
4
.gitignore
vendored
@ -53,6 +53,8 @@ testem.log
|
|||||||
# System Files
|
# System Files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
/env_dev/data
|
||||||
|
/env_dev/dataMongo
|
||||||
|
|
||||||
backPY/env
|
backPY/env
|
||||||
|
|
||||||
@ -62,3 +64,5 @@ __pycache__
|
|||||||
|
|
||||||
.design/
|
.design/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
front/storybook-static
|
||||||
|
back/bin
|
||||||
|
78
Dockerfile
78
Dockerfile
@ -3,23 +3,31 @@
|
|||||||
## buyilding-end install applications:
|
## buyilding-end install applications:
|
||||||
##
|
##
|
||||||
######################################################################################
|
######################################################################################
|
||||||
FROM archlinux:base-devel AS builder
|
FROM archlinux:base-devel AS common
|
||||||
# update system
|
# update system
|
||||||
RUN pacman -Syu --noconfirm && pacman-db-upgrade \
|
RUN pacman -Syu --noconfirm && pacman-db-upgrade \
|
||||||
&& pacman -S --noconfirm jdk-openjdk maven npm pnpm \
|
&& pacman -S --noconfirm jdk-openjdk wget\
|
||||||
|
&& pacman -Scc --noconfirm
|
||||||
|
|
||||||
|
WORKDIR /tmp
|
||||||
|
|
||||||
|
FROM common AS builder
|
||||||
|
# update system
|
||||||
|
RUN pacman -Syu --noconfirm && pacman-db-upgrade \
|
||||||
|
&& pacman -S --noconfirm maven npm pnpm \
|
||||||
&& pacman -Scc --noconfirm
|
&& pacman -Scc --noconfirm
|
||||||
|
|
||||||
ENV PATH /tmp/node_modules/.bin:$PATH
|
ENV PATH /tmp/node_modules/.bin:$PATH
|
||||||
WORKDIR /tmp
|
|
||||||
|
|
||||||
######################################################################################
|
######################################################################################
|
||||||
##
|
##
|
||||||
## Build back:
|
## Build back:
|
||||||
##
|
##
|
||||||
######################################################################################
|
######################################################################################
|
||||||
FROM builder AS buildBack
|
FROM builder AS build_back
|
||||||
COPY back/pom.xml /tmp
|
COPY back/pom.xml ./
|
||||||
COPY back/src /tmp/src/
|
COPY back/Formatter.xml ./
|
||||||
|
COPY back/src ./src/
|
||||||
RUN mvn clean compile assembly:single
|
RUN mvn clean compile assembly:single
|
||||||
|
|
||||||
######################################################################################
|
######################################################################################
|
||||||
@ -27,27 +35,44 @@ RUN mvn clean compile assembly:single
|
|||||||
## Build front:
|
## Build front:
|
||||||
##
|
##
|
||||||
######################################################################################
|
######################################################################################
|
||||||
FROM builder AS buildFront
|
FROM builder AS dependency_front
|
||||||
|
|
||||||
RUN echo "@kangaroo-and-rabbit:registry=https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/npm/" > /root/.npmrc
|
RUN echo "@kangaroo-and-rabbit:registry=https://gitea.atria-soft.org/api/packages/kangaroo-and-rabbit/npm/" > /root/.npmrc
|
||||||
|
|
||||||
ADD front/package.json \
|
ADD front/package.json \
|
||||||
front/karma.conf.js \
|
front/pnpm-lock.yaml \
|
||||||
front/protractor.conf.js \
|
./
|
||||||
/tmp/
|
ADD front/src/theme ./src/theme
|
||||||
|
|
||||||
# install and cache app dependencies
|
# install and cache app dependencies
|
||||||
RUN pnpm install
|
RUN pnpm install --prod=false
|
||||||
|
|
||||||
ADD front/e2e \
|
###############################################################
|
||||||
|
## Install sources
|
||||||
|
###############################################################
|
||||||
|
FROM dependency_front AS load_sources_front
|
||||||
|
|
||||||
|
# JUST to get the vertion of the application and his sha...
|
||||||
|
COPY \
|
||||||
front/tsconfig.json \
|
front/tsconfig.json \
|
||||||
front/tslint.json \
|
front/tsconfig.node.json \
|
||||||
front/angular.json \
|
front/vite.config.mts \
|
||||||
/tmp/
|
front/index.html \
|
||||||
ADD front/src /tmp/src
|
./
|
||||||
|
|
||||||
# generate build
|
COPY front/public ./public
|
||||||
RUN ng build --output-path=dist --configuration=production --base-href=/karideo/ --deploy-url=/karideo/
|
COPY front/src ./src
|
||||||
|
|
||||||
|
#We are not in prod mode ==> we need to overwrite the production env.
|
||||||
|
ARG env=front/.env.production
|
||||||
|
COPY ${env} .env
|
||||||
|
|
||||||
|
###############################################################
|
||||||
|
## Build the sources
|
||||||
|
###############################################################
|
||||||
|
FROM load_sources_front AS build_front
|
||||||
|
# build in bundle mode all the application
|
||||||
|
RUN pnpm static:build
|
||||||
|
|
||||||
######################################################################################
|
######################################################################################
|
||||||
##
|
##
|
||||||
@ -55,17 +80,22 @@ RUN ng build --output-path=dist --configuration=production --base-href=/karideo/
|
|||||||
##
|
##
|
||||||
######################################################################################
|
######################################################################################
|
||||||
|
|
||||||
FROM bellsoft/liberica-openjdk-alpine:latest
|
#FROM bellsoft/liberica-openjdk-alpine:latest
|
||||||
# add wget to manage the health check...
|
## add wget to manage the health check...
|
||||||
RUN apk add --no-cache wget
|
#RUN apk add --no-cache wget
|
||||||
|
FROM common
|
||||||
|
|
||||||
ENV LANG=C.UTF-8
|
ENV LANG C.UTF-8
|
||||||
|
|
||||||
COPY --from=buildBack /tmp/out/maven/*.jar /application/application.jar
|
COPY --from=build_back /tmp/out/maven/*.jar /application/application.jar
|
||||||
COPY --from=buildFront /tmp/dist /application/front/
|
COPY --from=build_front /tmp/dist /application/front/
|
||||||
|
|
||||||
WORKDIR /application/
|
WORKDIR /application/
|
||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
|
# To verify health-check: docker inspect --format "{{json .State.Health }}" YOUR_SERVICE_NAME | jq
|
||||||
|
HEALTHCHECK --start-period=10s --start-interval=2s --interval=30s --timeout=5s --retries=10 \
|
||||||
|
CMD wget --no-verbose --tries=1 --spider http://localhost:80/api/health_check || exit 1
|
||||||
|
|
||||||
CMD ["java", "-Xms64M", "-Xmx1G", "-cp", "/application/application.jar", "org.kar.karideo.WebLauncher"]
|
CMD ["java", "-Xms64M", "-Xmx1G", "-cp", "/application/application.jar", "org.kar.karideo.WebLauncher"]
|
||||||
|
125
README.md
Normal file
125
README.md
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
Karideo
|
||||||
|
=======
|
||||||
|
|
||||||
|
**K**angaroo **A**nd **R**abbit (v)ideo is a simple framework to propose video streaming for personal network
|
||||||
|
|
||||||
|
Run in local:
|
||||||
|
=============
|
||||||
|
|
||||||
|
Start tools
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Start the server basic interfaces: (DB(mySQL), Adminer)
|
||||||
|
|
||||||
|
```{.bash}
|
||||||
|
# start the Bdd interface (no big data > 50Mo)
|
||||||
|
docker compose -f env_dev/docker-compose.yaml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Start the Back-end:
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
backend is developed in JAVA
|
||||||
|
|
||||||
|
The first step is configuring your JAVA version (or select the JVM with the OS)
|
||||||
|
```bash
|
||||||
|
export PATH=$(ls -d --color=never /usr/lib/jvm/java-2*-openjdk)/bin:$PATH
|
||||||
|
```
|
||||||
|
|
||||||
|
Install the dependency:
|
||||||
|
```bash
|
||||||
|
mvn install
|
||||||
|
```
|
||||||
|
|
||||||
|
Run the test
|
||||||
|
```bash
|
||||||
|
mvn test
|
||||||
|
```
|
||||||
|
|
||||||
|
Install it for external use
|
||||||
|
```bash
|
||||||
|
mvn install
|
||||||
|
```
|
||||||
|
|
||||||
|
Execute the local server:
|
||||||
|
```bash
|
||||||
|
mvn exec:java@dev-mode
|
||||||
|
```
|
||||||
|
|
||||||
|
Start the Front-end:
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
backend is developed in JAVA
|
||||||
|
```bash
|
||||||
|
cd front
|
||||||
|
pnpm install
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Display the result:
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
[show the webpage: http://localhost:4203](http://localhost:4203)
|
||||||
|
|
||||||
|
Some other dev tools:
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Format code:
|
||||||
|
------------
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export PATH=$(ls -d --color=never /usr/lib/jvm/java-2*-openjdk)/bin:$PATH
|
||||||
|
mvn formatter:format
|
||||||
|
mvn test
|
||||||
|
```
|
||||||
|
|
||||||
|
Tools in production mode
|
||||||
|
========================
|
||||||
|
|
||||||
|
Changing the Log Level
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
In a production environment, you can adjust the log level to help diagnose bugs more effectively.
|
||||||
|
|
||||||
|
The available log levels are:
|
||||||
|
| **Log Level Tag** | **org.kar.karideo** | **org.kar.archidata** | **other** |
|
||||||
|
| ----------------- | ------------------- | --------------------- | --------- |
|
||||||
|
| `prod` | INFO | INFO | INFO |
|
||||||
|
| `prod-debug` | DEBUG | INFO | INFO |
|
||||||
|
| `prod-trace` | TRACE | DEBUG | INFO |
|
||||||
|
| `prod-trace-full` | TRACE | TRACE | INFO |
|
||||||
|
| `dev` | TRACE | DEBUG | INFO |
|
||||||
|
|
||||||
|
|
||||||
|
Manual set in production:
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Connect on the registry
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
To log-in and log-out from the registry:
|
||||||
|
```bash
|
||||||
|
export REGISTRY_ADDRESS=gitea.atria-soft.org
|
||||||
|
docker login -u <<YOUR_USER_NAME>> ${REGISTRY_ADDRESS}
|
||||||
|
docker logout ${REGISTRY_ADDRESS}
|
||||||
|
```
|
||||||
|
|
||||||
|
pull the root image of dockers
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker pull archlinux:base-devel
|
||||||
|
docker pull bellsoft/liberica-openjdk-alpine:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
Create the version
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Execute in the local folder: (use ```dev``` for development and ```latest``` for production release)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export TAG_DOCKER=latest
|
||||||
|
export REGISTRY_ADDRESS=gitea.atria-soft.org
|
||||||
|
docker build -t ${REGISTRY_ADDRESS}/kangaroo-and-rabbit/karideo:${TAG_DOCKER} .
|
||||||
|
docker push ${REGISTRY_ADDRESS}/kangaroo-and-rabbit/karideo:${TAG_DOCKER}
|
||||||
|
```
|
@ -1,2 +1,2 @@
|
|||||||
# URL for database connection
|
# URL for database connection
|
||||||
VITE_API_BASE_URL=karusic/api/
|
VITE_API_BASE_URL=karideo/api/
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ErrorBoundary } from '@/errors/ErrorBoundary';
|
import { ErrorBoundary } from '@/errors/ErrorBoundary';
|
||||||
|
|
||||||
import { AudioPlayer } from './components';
|
import { VideoPlayer } from './components';
|
||||||
import { EnvDevelopment } from './components/EnvDevelopment/EnvDevelopment';
|
import { EnvDevelopment } from './components/EnvDevelopment/EnvDevelopment';
|
||||||
import { AppRoutes } from './scene/AppRoutes';
|
import { AppRoutes } from './scene/AppRoutes';
|
||||||
import { ServiceContextProvider } from './service/ServiceContext';
|
import { ServiceContextProvider } from './service/ServiceContext';
|
||||||
@ -12,7 +12,7 @@ export const App = () => {
|
|||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<AppRoutes />
|
<AppRoutes />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
<AudioPlayer />
|
<VideoPlayer />
|
||||||
</ServiceContextProvider>
|
</ServiceContextProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
/**
|
|
||||||
* Interface of the server (auto-generated code)
|
|
||||||
*/
|
|
||||||
import { z as zod } from "zod";
|
|
||||||
|
|
||||||
import {ZodLong} from "./long";
|
|
||||||
import {ZodUUIDGenericDataSoftDelete, ZodUUIDGenericDataSoftDeleteWrite } from "./uuid-generic-data-soft-delete";
|
|
||||||
|
|
||||||
export const ZodData = ZodUUIDGenericDataSoftDelete.extend({
|
|
||||||
/**
|
|
||||||
* Sha512 of the data
|
|
||||||
*/
|
|
||||||
sha512: zod.string().max(128),
|
|
||||||
/**
|
|
||||||
* Mime -type of the media
|
|
||||||
*/
|
|
||||||
mimeType: zod.string().max(128),
|
|
||||||
/**
|
|
||||||
* Size in Byte of the data
|
|
||||||
*/
|
|
||||||
size: ZodLong,
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
export type Data = zod.infer<typeof ZodData>;
|
|
||||||
|
|
||||||
export function isData(data: any): data is Data {
|
|
||||||
try {
|
|
||||||
ZodData.parse(data);
|
|
||||||
return true;
|
|
||||||
} catch (e: any) {
|
|
||||||
console.log(`Fail to parse data type='ZodData' error=${e}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export const ZodDataWrite = ZodUUIDGenericDataSoftDeleteWrite.extend({
|
|
||||||
/**
|
|
||||||
* Sha512 of the data
|
|
||||||
*/
|
|
||||||
sha512: zod.string().max(128).optional(),
|
|
||||||
/**
|
|
||||||
* Mime -type of the media
|
|
||||||
*/
|
|
||||||
mimeType: zod.string().max(128).optional(),
|
|
||||||
/**
|
|
||||||
* Size in Byte of the data
|
|
||||||
*/
|
|
||||||
size: ZodLong.optional(),
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
export type DataWrite = zod.infer<typeof ZodDataWrite>;
|
|
||||||
|
|
||||||
export function isDataWrite(data: any): data is DataWrite {
|
|
||||||
try {
|
|
||||||
ZodDataWrite.parse(data);
|
|
||||||
return true;
|
|
||||||
} catch (e: any) {
|
|
||||||
console.log(`Fail to parse data type='ZodDataWrite' error=${e}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
/**
|
|
||||||
* Interface of the server (auto-generated code)
|
|
||||||
*/
|
|
||||||
import { z as zod } from "zod";
|
|
||||||
|
|
||||||
import {ZodUUIDGenericData, ZodUUIDGenericDataWrite } from "./uuid-generic-data";
|
|
||||||
|
|
||||||
export const ZodUUIDGenericDataSoftDelete = ZodUUIDGenericData.extend({
|
|
||||||
/**
|
|
||||||
* Deleted state
|
|
||||||
*/
|
|
||||||
deleted: zod.boolean().readonly().optional(),
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
export type UUIDGenericDataSoftDelete = zod.infer<typeof ZodUUIDGenericDataSoftDelete>;
|
|
||||||
|
|
||||||
export function isUUIDGenericDataSoftDelete(data: any): data is UUIDGenericDataSoftDelete {
|
|
||||||
try {
|
|
||||||
ZodUUIDGenericDataSoftDelete.parse(data);
|
|
||||||
return true;
|
|
||||||
} catch (e: any) {
|
|
||||||
console.log(`Fail to parse data type='ZodUUIDGenericDataSoftDelete' error=${e}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export const ZodUUIDGenericDataSoftDeleteWrite = ZodUUIDGenericDataWrite.extend({
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
export type UUIDGenericDataSoftDeleteWrite = zod.infer<typeof ZodUUIDGenericDataSoftDeleteWrite>;
|
|
||||||
|
|
||||||
export function isUUIDGenericDataSoftDeleteWrite(data: any): data is UUIDGenericDataSoftDeleteWrite {
|
|
||||||
try {
|
|
||||||
ZodUUIDGenericDataSoftDeleteWrite.parse(data);
|
|
||||||
return true;
|
|
||||||
} catch (e: any) {
|
|
||||||
console.log(`Fail to parse data type='ZodUUIDGenericDataSoftDeleteWrite' error=${e}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
/**
|
|
||||||
* Interface of the server (auto-generated code)
|
|
||||||
*/
|
|
||||||
import { z as zod } from "zod";
|
|
||||||
|
|
||||||
import {ZodUUID} from "./uuid";
|
|
||||||
import {ZodGenericTiming, ZodGenericTimingWrite } from "./generic-timing";
|
|
||||||
|
|
||||||
export const ZodUUIDGenericData = ZodGenericTiming.extend({
|
|
||||||
/**
|
|
||||||
* Unique UUID of the object
|
|
||||||
*/
|
|
||||||
uuid: ZodUUID.readonly(),
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
export type UUIDGenericData = zod.infer<typeof ZodUUIDGenericData>;
|
|
||||||
|
|
||||||
export function isUUIDGenericData(data: any): data is UUIDGenericData {
|
|
||||||
try {
|
|
||||||
ZodUUIDGenericData.parse(data);
|
|
||||||
return true;
|
|
||||||
} catch (e: any) {
|
|
||||||
console.log(`Fail to parse data type='ZodUUIDGenericData' error=${e}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export const ZodUUIDGenericDataWrite = ZodGenericTimingWrite.extend({
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
export type UUIDGenericDataWrite = zod.infer<typeof ZodUUIDGenericDataWrite>;
|
|
||||||
|
|
||||||
export function isUUIDGenericDataWrite(data: any): data is UUIDGenericDataWrite {
|
|
||||||
try {
|
|
||||||
ZodUUIDGenericDataWrite.parse(data);
|
|
||||||
return true;
|
|
||||||
} catch (e: any) {
|
|
||||||
console.log(`Fail to parse data type='ZodUUIDGenericDataWrite' error=${e}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
import { ReactElement, useEffect, useState } from 'react';
|
import { ReactElement, useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { Box, BoxProps, Flex, FlexProps } from '@chakra-ui/react';
|
import { Box, BoxProps, Flex, Image } from '@chakra-ui/react';
|
||||||
import { Image } from '@chakra-ui/react';
|
|
||||||
|
|
||||||
import { ObjectId } from '@/back-api';
|
import { ObjectId } from '@/back-api';
|
||||||
import { DataUrlAccess } from '@/utils/data-url-access';
|
import { DataUrlAccess } from '@/utils/data-url-access';
|
||||||
@ -17,6 +16,7 @@ export type CoversProps = Omit<BoxProps, 'iconEmpty'> & {
|
|||||||
|
|
||||||
export const Covers = ({
|
export const Covers = ({
|
||||||
data,
|
data,
|
||||||
|
onClick,
|
||||||
iconEmpty,
|
iconEmpty,
|
||||||
size = '100px',
|
size = '100px',
|
||||||
slideshow = false,
|
slideshow = false,
|
||||||
@ -45,7 +45,7 @@ export const Covers = ({
|
|||||||
|
|
||||||
if (!data || data.length < 1) {
|
if (!data || data.length < 1) {
|
||||||
if (iconEmpty) {
|
if (iconEmpty) {
|
||||||
return <Icon children={iconEmpty} sizeIcon={size} />;
|
return <Icon children={iconEmpty} sizeIcon={size} onClick={onClick} />;
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@ -56,6 +56,7 @@ export const Covers = ({
|
|||||||
borderColor="blue"
|
borderColor="blue"
|
||||||
borderWidth="1px"
|
borderWidth="1px"
|
||||||
margin="auto"
|
margin="auto"
|
||||||
|
onClick={onClick}
|
||||||
{...rest}
|
{...rest}
|
||||||
></Box>
|
></Box>
|
||||||
);
|
);
|
||||||
@ -69,6 +70,7 @@ export const Covers = ({
|
|||||||
src={url}
|
src={url}
|
||||||
maxWidth={size}
|
maxWidth={size}
|
||||||
boxSize={size} /*{...rest}*/
|
boxSize={size} /*{...rest}*/
|
||||||
|
onClick={onClick}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ export const EmptyEnd = () => {
|
|||||||
<Box
|
<Box
|
||||||
width="full"
|
width="full"
|
||||||
height="25%"
|
height="25%"
|
||||||
minHeight="250px"
|
minHeight="calc(max(50vh,500px))"
|
||||||
// borderWidth="1px"
|
// borderWidth="1px"
|
||||||
// borderColor="red"
|
// borderColor="red"
|
||||||
></Box>
|
></Box>
|
||||||
|
@ -1,18 +1,21 @@
|
|||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
|
||||||
import { Box, Flex, IconButton, SliderTrack, Text } from '@chakra-ui/react';
|
import { Box, chakra, Flex, IconButton, SliderTrack, Spacer, Text, useBreakpointValue } from '@chakra-ui/react';
|
||||||
import {
|
import {
|
||||||
MdFastForward,
|
MdFastForward,
|
||||||
MdFastRewind,
|
MdFastRewind,
|
||||||
|
MdFullscreen,
|
||||||
MdLooksOne,
|
MdLooksOne,
|
||||||
MdNavigateBefore,
|
MdNavigateBefore,
|
||||||
MdNavigateNext,
|
MdNavigateNext,
|
||||||
|
MdOutlinePictureInPictureAlt,
|
||||||
MdPause,
|
MdPause,
|
||||||
|
MdPictureInPictureAlt,
|
||||||
MdPlayArrow,
|
MdPlayArrow,
|
||||||
MdRepeat,
|
MdRepeat,
|
||||||
MdRepeatOne,
|
MdRepeatOne,
|
||||||
MdStop,
|
MdStop,
|
||||||
MdTrendingFlat,
|
MdTrendingFlat
|
||||||
} from 'react-icons/md';
|
} from 'react-icons/md';
|
||||||
|
|
||||||
import { useColorModeValue } from '@/components/ui/color-mode';
|
import { useColorModeValue } from '@/components/ui/color-mode';
|
||||||
@ -59,10 +62,44 @@ const formatTime = (time) => {
|
|||||||
return '00:00';
|
return '00:00';
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AudioPlayer = ({}: AudioPlayerProps) => {
|
export const VideoPlayer = ({}: AudioPlayerProps) => {
|
||||||
const { playMediaList, MediaOffset, previous, next, first } =
|
const [time, setTime] = useState(10);
|
||||||
|
const [isRunning, setIsRunning] = useState(true);
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isRunning || time <= 0) {
|
||||||
|
console.log(`exit timer`);
|
||||||
|
setIsRunning(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const timer = setInterval(() => {
|
||||||
|
setTime((prevTime) => {
|
||||||
|
console.log(`current time : ${prevTime}`);
|
||||||
|
return prevTime - 1;
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
return () => clearInterval(timer);
|
||||||
|
}, [time, isRunning]);
|
||||||
|
|
||||||
|
const resetTimer = () => {
|
||||||
|
setTime(10);
|
||||||
|
setIsRunning(true);
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
const resetTimer = () => {
|
||||||
|
setTime(10);
|
||||||
|
setIsRunning(true);
|
||||||
|
};
|
||||||
|
window.addEventListener("mousemove", resetTimer);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("mousemove", resetTimer);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const { playMediaList, MediaOffset, previous, next, first, clear } =
|
||||||
useActivePlaylistService();
|
useActivePlaylistService();
|
||||||
const audioRef = useRef<HTMLAudioElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
const videoRef = useRef<HTMLVideoElement>(null);
|
||||||
const [isPlaying, setIsPlaying] = useState<boolean>(false);
|
const [isPlaying, setIsPlaying] = useState<boolean>(false);
|
||||||
const [timeProgress, setTimeProgress] = useState<number>(0);
|
const [timeProgress, setTimeProgress] = useState<number>(0);
|
||||||
const [playingMode, setPlayingMode] = useState<PlayMode>(PlayMode.PLAY_ALL);
|
const [playingMode, setPlayingMode] = useState<PlayMode>(PlayMode.PLAY_ALL);
|
||||||
@ -74,6 +111,7 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
|
|||||||
const { dataType } = useSpecificType(dataMedia?.typeId);
|
const { dataType } = useSpecificType(dataMedia?.typeId);
|
||||||
const { dataSeries } = useSpecificSeries(dataMedia?.seriesId);
|
const { dataSeries } = useSpecificSeries(dataMedia?.seriesId);
|
||||||
|
|
||||||
|
const isMobile = useBreakpointValue({ base: false, sm: true });
|
||||||
const [mediaSource, setMediaSource] = useState<string>('');
|
const [mediaSource, setMediaSource] = useState<string>('');
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMediaSource(
|
setMediaSource(
|
||||||
@ -83,7 +121,16 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
|
|||||||
);
|
);
|
||||||
}, [dataMedia, setMediaSource]);
|
}, [dataMedia, setMediaSource]);
|
||||||
const backColor = useColorModeValue('back.100', 'back.800');
|
const backColor = useColorModeValue('back.100', 'back.800');
|
||||||
const configButton = {
|
const configButton = isMobile ? {
|
||||||
|
borderRadius: 'full',
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
_hover: {
|
||||||
|
bgColor: 'brand.500',
|
||||||
|
},
|
||||||
|
width: '35px',
|
||||||
|
height: '35px',
|
||||||
|
padding: '2px',
|
||||||
|
} : {
|
||||||
borderRadius: 'full',
|
borderRadius: 'full',
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
_hover: {
|
_hover: {
|
||||||
@ -95,15 +142,15 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!audioRef || !audioRef.current) {
|
if (!videoRef || !videoRef.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isPlaying) {
|
if (isPlaying) {
|
||||||
audioRef.current.play();
|
videoRef.current.play();
|
||||||
} else {
|
} else {
|
||||||
audioRef.current.pause();
|
videoRef.current.pause();
|
||||||
}
|
}
|
||||||
}, [isPlaying, audioRef]);
|
}, [isPlaying, videoRef]);
|
||||||
|
|
||||||
const onAudioEnded = () => {
|
const onAudioEnded = () => {
|
||||||
if (playMediaList.length === 0 || isNullOrUndefined(MediaOffset)) {
|
if (playMediaList.length === 0 || isNullOrUndefined(MediaOffset)) {
|
||||||
@ -124,46 +171,46 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
|
|||||||
};
|
};
|
||||||
const onSeek = (newValue) => {
|
const onSeek = (newValue) => {
|
||||||
console.log(`onSeek: ${newValue}`);
|
console.log(`onSeek: ${newValue}`);
|
||||||
if (!audioRef || !audioRef.current) {
|
if (!videoRef || !videoRef.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
audioRef.current.currentTime = newValue;
|
videoRef.current.currentTime = newValue;
|
||||||
};
|
};
|
||||||
const onPlay = () => {
|
const onPlay = () => {
|
||||||
if (!audioRef || !audioRef.current) {
|
if (!videoRef || !videoRef.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isPlaying) {
|
if (isPlaying) {
|
||||||
audioRef.current.pause();
|
videoRef.current.pause();
|
||||||
} else {
|
} else {
|
||||||
audioRef.current.play();
|
videoRef.current.play();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const onStop = () => {
|
const onStop = () => {
|
||||||
if (!audioRef || !audioRef.current) {
|
if (!videoRef || !videoRef.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (audioRef.current.currentTime == 0 && audioRef.current.paused) {
|
if (videoRef.current.currentTime <= 0.5 && videoRef.current.paused) {
|
||||||
// TODO remove current playing value
|
clear();
|
||||||
} else {
|
} else {
|
||||||
audioRef.current.pause();
|
videoRef.current.pause();
|
||||||
audioRef.current.currentTime = 0;
|
videoRef.current.currentTime = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const onNavigatePrevious = () => {
|
const onNavigatePrevious = () => {
|
||||||
previous();
|
previous();
|
||||||
};
|
};
|
||||||
const onFastRewind = () => {
|
const onFastRewind = () => {
|
||||||
if (!audioRef || !audioRef.current) {
|
if (!videoRef || !videoRef.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
audioRef.current.currentTime -= 10;
|
videoRef.current.currentTime -= 10;
|
||||||
};
|
};
|
||||||
const onFastForward = () => {
|
const onFastForward = () => {
|
||||||
if (!audioRef || !audioRef.current) {
|
if (!videoRef || !videoRef.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
audioRef.current.currentTime += 10;
|
videoRef.current.currentTime += 10;
|
||||||
};
|
};
|
||||||
const onNavigateNext = () => {
|
const onNavigateNext = () => {
|
||||||
next();
|
next();
|
||||||
@ -185,17 +232,17 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
|
|||||||
* Call when meta-data is updated
|
* Call when meta-data is updated
|
||||||
*/
|
*/
|
||||||
function onChangeMetadata(): void {
|
function onChangeMetadata(): void {
|
||||||
const seconds = audioRef.current?.duration;
|
const seconds = videoRef.current?.duration;
|
||||||
if (seconds !== undefined) {
|
if (seconds !== undefined) {
|
||||||
setDuration(seconds);
|
setDuration(seconds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const onTimeUpdate = () => {
|
const onTimeUpdate = () => {
|
||||||
if (!audioRef || !audioRef.current) {
|
if (!videoRef || !videoRef.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log(`onTimeUpdate ${audioRef.current.currentTime}`);
|
//console.log(`onTimeUpdate ${videoRef.current.currentTime}`);
|
||||||
setTimeProgress(audioRef.current.currentTime);
|
setTimeProgress(videoRef.current.currentTime);
|
||||||
};
|
};
|
||||||
const onDurationChange = (event) => {};
|
const onDurationChange = (event) => {};
|
||||||
const onChangeStateToPlay = () => {
|
const onChangeStateToPlay = () => {
|
||||||
@ -212,12 +259,57 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
const onFullScreen = () => {
|
||||||
|
if (containerRef.current) {
|
||||||
|
if (!document.fullscreenElement) {
|
||||||
|
if (containerRef.current.requestFullscreen) {
|
||||||
|
resetTimer();
|
||||||
|
containerRef.current.requestFullscreen();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
document.exitFullscreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const [isPiPSupported, setIsPiPSupported] = useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
setIsPiPSupported(!!document.pictureInPictureEnabled);
|
||||||
|
}, []);
|
||||||
|
const [isPiP, setIsPiP] = useState(false);
|
||||||
|
const onPictureInPicture = async () => {
|
||||||
|
if (videoRef.current) {
|
||||||
|
try {
|
||||||
|
if (!isPiP) {
|
||||||
|
await videoRef.current.requestPictureInPicture();
|
||||||
|
setIsPiP(true);
|
||||||
|
} else {
|
||||||
|
document.exitPictureInPicture();
|
||||||
|
setIsPiP(false);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Erreur avec Picture-in-Picture:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const [isFullScreen, setIsFullScreen] = useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
const handleFullScreenChange = () => {
|
||||||
|
console.log(`changeFullScreen: ${!!document.fullscreenElement}`)
|
||||||
|
setIsFullScreen(!!document.fullscreenElement);
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener("fullscreenchange", handleFullScreenChange);
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("fullscreenchange", handleFullScreenChange);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!isNullOrUndefined(MediaOffset) && (
|
{!isNullOrUndefined(MediaOffset) && (
|
||||||
|
<>
|
||||||
<Flex
|
<Flex
|
||||||
position="absolute"
|
position="absolute"
|
||||||
height="150px"
|
//height="500px"
|
||||||
minHeight="150px"
|
minHeight="150px"
|
||||||
paddingY="5px"
|
paddingY="5px"
|
||||||
paddingX="10px"
|
paddingX="10px"
|
||||||
@ -228,11 +320,30 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
|
|||||||
zIndex={1000}
|
zIndex={1000}
|
||||||
borderWidth="1px"
|
borderWidth="1px"
|
||||||
borderColor="brand.900"
|
borderColor="brand.900"
|
||||||
bgColor={backColor}
|
bgColor={isFullScreen ? "0x000000" : backColor}
|
||||||
borderTopRadius="10px"
|
borderTopRadius="10px"
|
||||||
direction="column"
|
direction="column"
|
||||||
|
ref={containerRef}
|
||||||
>
|
>
|
||||||
<Text
|
<chakra.video
|
||||||
|
position={isFullScreen ? "absolute" : "relative"}
|
||||||
|
maxHeight={isFullScreen ? undefined : "30vh"}
|
||||||
|
maxWidth={isFullScreen ? undefined : "100%"}
|
||||||
|
height={isFullScreen ? "100%" : undefined}
|
||||||
|
width={isFullScreen ? "100%": undefined}
|
||||||
|
marginX="auto"
|
||||||
|
src={mediaSource}
|
||||||
|
ref={videoRef}
|
||||||
|
//preload={true}
|
||||||
|
onPlay={onChangeStateToPlay}
|
||||||
|
onPause={onChangeStateToPause}
|
||||||
|
onTimeUpdate={onTimeUpdate}
|
||||||
|
onDurationChange={onDurationChange}
|
||||||
|
onLoadedMetadata={onChangeMetadata}
|
||||||
|
autoPlay={true}
|
||||||
|
onEnded={onAudioEnded}
|
||||||
|
/>
|
||||||
|
{(!isFullScreen || (!isMobile || isRunning)) && <><Text
|
||||||
alignContent="left"
|
alignContent="left"
|
||||||
fontSize="20px"
|
fontSize="20px"
|
||||||
fontWeight="bold"
|
fontWeight="bold"
|
||||||
@ -255,6 +366,7 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
|
|||||||
{dataSeason && dataSeason?.name}
|
{dataSeason && dataSeason?.name}
|
||||||
{dataType && ` / ${dataType.name}`}
|
{dataType && ` / ${dataType.name}`}
|
||||||
</Text>
|
</Text>
|
||||||
|
{isFullScreen && <Spacer/>}
|
||||||
<Box width="full" paddingX="15px">
|
<Box width="full" paddingX="15px">
|
||||||
<Slider
|
<Slider
|
||||||
defaultValue={[0]}
|
defaultValue={[0]}
|
||||||
@ -353,22 +465,29 @@ export const AudioPlayer = ({}: AudioPlayerProps) => {
|
|||||||
>
|
>
|
||||||
{playModeIcon[playingMode]}
|
{playModeIcon[playingMode]}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
{...configButton}
|
||||||
|
aria-label={'Fullscreen'}
|
||||||
|
onClick={onFullScreen}
|
||||||
|
variant="ghost"
|
||||||
|
>
|
||||||
|
<MdFullscreen style={{ width: '100%', height: '100%' }} />
|
||||||
|
</IconButton>
|
||||||
|
{isPiPSupported && !isMobile &&
|
||||||
|
<IconButton
|
||||||
|
{...configButton}
|
||||||
|
aria-label={'Fullscreen'}
|
||||||
|
onClick={onPictureInPicture}
|
||||||
|
variant="ghost"
|
||||||
|
>
|
||||||
|
{isPiP ? <MdOutlinePictureInPictureAlt style={{ width: '100%', height: '100%' }} /> : <MdPictureInPictureAlt style={{ width: '100%', height: '100%' }} /> }
|
||||||
|
</IconButton>
|
||||||
|
}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
</>}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<audio
|
|
||||||
src={mediaSource}
|
|
||||||
ref={audioRef}
|
|
||||||
//preload={true}
|
|
||||||
onPlay={onChangeStateToPlay}
|
|
||||||
onPause={onChangeStateToPause}
|
|
||||||
onTimeUpdate={onTimeUpdate}
|
|
||||||
onDurationChange={onDurationChange}
|
|
||||||
onLoadedMetadata={onChangeMetadata}
|
|
||||||
autoPlay={true}
|
|
||||||
onEnded={onAudioEnded}
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
@ -17,16 +17,15 @@ export const VignetteDetail = ({ icon, text, ...rest }: VignetteProps) => {
|
|||||||
border="1px"
|
border="1px"
|
||||||
borderColor="brand.900"
|
borderColor="brand.900"
|
||||||
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
||||||
key={data.id}
|
|
||||||
padding="5px"
|
padding="5px"
|
||||||
as="button"
|
as="button"
|
||||||
_hover={{
|
_hover={{
|
||||||
boxShadow: 'outline-over',
|
boxShadow: 'outline-over',
|
||||||
bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'),
|
bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'),
|
||||||
}}
|
}}
|
||||||
onClick={() => onSelectItem(data.id)}
|
//onClick={() => onSelectItem(data.id)}
|
||||||
>
|
>
|
||||||
<DisplayType dataType={data} />
|
{/* <DisplayType dataType={data} /> */}
|
||||||
</Flex>
|
</Flex>
|
||||||
// <Flex
|
// <Flex
|
||||||
// align="flex-start"
|
// align="flex-start"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
export * from './AudioPlayer';
|
|
||||||
export * from './Cover';
|
export * from './Cover';
|
||||||
export * from './EmptyEnd';
|
export * from './EmptyEnd';
|
||||||
export * from './Icon';
|
export * from './Icon';
|
||||||
export * from './SearchInput';
|
export * from './SearchInput';
|
||||||
|
export * from './VideoPlayer';
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Flex, Text } from '@chakra-ui/react';
|
import { Flex, Spacer, Text } from '@chakra-ui/react';
|
||||||
import { LuMusic2, LuPlay } from 'react-icons/lu';
|
import { LuMusic2, LuPlay } from 'react-icons/lu';
|
||||||
|
|
||||||
import { Media } from '@/back-api';
|
import { Media } from '@/back-api';
|
||||||
@ -45,6 +45,7 @@ export const DisplayMediaFull = ({
|
|||||||
overflowX="hidden"
|
overflowX="hidden"
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
|
<Spacer/>
|
||||||
<Text
|
<Text
|
||||||
as="span"
|
as="span"
|
||||||
alignContent="left"
|
alignContent="left"
|
||||||
|
@ -45,7 +45,7 @@ const environment_local: Environment = {
|
|||||||
ssoSignUp: `${serverSSOAddress}/karso/signup/karideo-dev/`,
|
ssoSignUp: `${serverSSOAddress}/karso/signup/karideo-dev/`,
|
||||||
ssoSignOut: `${serverSSOAddress}/karso/signout/karideo-dev/`,
|
ssoSignOut: `${serverSSOAddress}/karso/signout/karideo-dev/`,
|
||||||
tokenStoredInPermanentStorage: false,
|
tokenStoredInPermanentStorage: false,
|
||||||
replaceDataToRealServer: false,
|
replaceDataToRealServer: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,13 +12,13 @@ import { HomePage } from '@/scene/home/HomePage';
|
|||||||
import { SSORoutes } from '@/scene/sso/SSORoutes';
|
import { SSORoutes } from '@/scene/sso/SSORoutes';
|
||||||
import { useHasRight } from '@/service/session';
|
import { useHasRight } from '@/service/session';
|
||||||
|
|
||||||
|
import { AddPage } from './home/AddPage';
|
||||||
|
import { SettingsPage } from './home/SettingsPage';
|
||||||
|
import { MediaRoutes } from './media/MediaRoutes';
|
||||||
|
import { OnAirPage } from './onAir/OnAirPage';
|
||||||
import { SeasonRoutes } from './season/SeasonRoutes';
|
import { SeasonRoutes } from './season/SeasonRoutes';
|
||||||
import { SeriesRoutes } from './series/SeriesRoutes';
|
import { SeriesRoutes } from './series/SeriesRoutes';
|
||||||
import { TypeRoutes } from './type/TypesRoutes';
|
import { TypeRoutes } from './type/TypesRoutes';
|
||||||
import { AddPage } from './home/AddPage';
|
|
||||||
import { SettingsPage } from './home/SettingsPage';
|
|
||||||
import { OnAirPage } from './onAir/OnAirPage';
|
|
||||||
import { MediaRoutes } from './media/MediaRoutes';
|
|
||||||
|
|
||||||
export const AppRoutes = () => {
|
export const AppRoutes = () => {
|
||||||
const { isReadable } = useHasRight('USER');
|
const { isReadable } = useHasRight('USER');
|
||||||
@ -45,6 +45,7 @@ export const AppRoutes = () => {
|
|||||||
<Route path="Media/*" element={<MediaRoutes />} />
|
<Route path="Media/*" element={<MediaRoutes />} />
|
||||||
<Route path="*" element={<Error404 />} />
|
<Route path="*" element={<Error404 />} />
|
||||||
</>
|
</>
|
||||||
|
|
||||||
) : (
|
) : (
|
||||||
<Route path="*" element={<Error401 />} />
|
<Route path="*" element={<Error401 />} />
|
||||||
)}
|
)}
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
import { Box, Button, Flex, Text } from '@chakra-ui/react';
|
import { Box, Button, Flex, Text } from '@chakra-ui/react';
|
||||||
import { LuDisc3 } from 'react-icons/lu';
|
import { LuDisc3 } from 'react-icons/lu';
|
||||||
import { MdAdd, MdEdit } from 'react-icons/md';
|
import { MdEdit } from 'react-icons/md';
|
||||||
import { Route, Routes, useNavigate, useParams } from 'react-router-dom';
|
import { Route, Routes, useNavigate, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { Covers } from '@/components/Cover';
|
import { Covers } from '@/components/Cover';
|
||||||
import { EmptyEnd } from '@/components/EmptyEnd';
|
import { EmptyEnd } from '@/components/EmptyEnd';
|
||||||
import { PageLayout } from '@/components/Layout/PageLayout';
|
import { PageLayout } from '@/components/Layout/PageLayout';
|
||||||
import { PageLayoutInfoCenter } from '@/components/Layout/PageLayoutInfoCenter';
|
import { PageLayoutInfoCenter } from '@/components/Layout/PageLayoutInfoCenter';
|
||||||
import { DisplayMediaFull } from '@/components/media/DisplayMediaFull';
|
|
||||||
import { SeasonEditPopUp } from '@/components/popup/AlbumEditPopUp';
|
import { SeasonEditPopUp } from '@/components/popup/AlbumEditPopUp';
|
||||||
import { MediaEditPopUp } from '@/components/popup/TrackEditPopUp';
|
import { MediaEditPopUp } from '@/components/popup/TrackEditPopUp';
|
||||||
import { BUTTON_TOP_BAR_PROPERTY, TopBar } from '@/components/TopBar/TopBar';
|
import { BUTTON_TOP_BAR_PROPERTY, TopBar } from '@/components/TopBar/TopBar';
|
||||||
@ -107,7 +106,7 @@ export const SeasonDetailPage = () => {
|
|||||||
bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'),
|
bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DisplayMediaFull
|
{/* <DisplaySeasonFull
|
||||||
media={{...data, dataId: "0-not-defined"}}
|
media={{...data, dataId: "0-not-defined"}}
|
||||||
onClick={() => onSelectItem(data.id)}
|
onClick={() => onSelectItem(data.id)}
|
||||||
contextMenu={[
|
contextMenu={[
|
||||||
@ -125,7 +124,7 @@ export const SeasonDetailPage = () => {
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
data-testid="Season-detail-page_display-detail"
|
data-testid="Season-detail-page_display-detail"
|
||||||
/>
|
/> */}
|
||||||
</Box>
|
</Box>
|
||||||
))}
|
))}
|
||||||
<EmptyEnd />
|
<EmptyEnd />
|
||||||
|
@ -1,17 +1,15 @@
|
|||||||
import { Box, Button, Flex, Text } from '@chakra-ui/react';
|
import { Button, Flex, Text } from '@chakra-ui/react';
|
||||||
import { LuDisc3 } from 'react-icons/lu';
|
import { LuDisc3 } from 'react-icons/lu';
|
||||||
import { MdAdd, MdEdit, MdPerson } from 'react-icons/md';
|
import { MdEdit, MdPerson } from 'react-icons/md';
|
||||||
import { Route, Routes, useNavigate, useParams } from 'react-router-dom';
|
import { Route, Routes, useNavigate, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { Covers } from '@/components/Cover';
|
import { Covers } from '@/components/Cover';
|
||||||
import { EmptyEnd } from '@/components/EmptyEnd';
|
import { EmptyEnd } from '@/components/EmptyEnd';
|
||||||
import { PageLayout } from '@/components/Layout/PageLayout';
|
import { PageLayout } from '@/components/Layout/PageLayout';
|
||||||
import { PageLayoutInfoCenter } from '@/components/Layout/PageLayoutInfoCenter';
|
import { PageLayoutInfoCenter } from '@/components/Layout/PageLayoutInfoCenter';
|
||||||
import { DisplayMedia } from '@/components/media/DisplayMedia';
|
|
||||||
import { SeasonEditPopUp } from '@/components/popup/AlbumEditPopUp';
|
import { SeasonEditPopUp } from '@/components/popup/AlbumEditPopUp';
|
||||||
import { MediaEditPopUp } from '@/components/popup/TrackEditPopUp';
|
import { MediaEditPopUp } from '@/components/popup/TrackEditPopUp';
|
||||||
import { BUTTON_TOP_BAR_PROPERTY, TopBar } from '@/components/TopBar/TopBar';
|
import { BUTTON_TOP_BAR_PROPERTY, TopBar } from '@/components/TopBar/TopBar';
|
||||||
import { useColorModeValue } from '@/components/ui/color-mode';
|
|
||||||
import { useActivePlaylistService } from '@/service/ActivePlaylist';
|
import { useActivePlaylistService } from '@/service/ActivePlaylist';
|
||||||
import { useSeasonVideo, useSpecificSeason } from '@/service/Season';
|
import { useSeasonVideo, useSpecificSeason } from '@/service/Season';
|
||||||
import { useSpecificSeries } from '@/service/Series';
|
import { useSpecificSeries } from '@/service/Series';
|
||||||
@ -112,7 +110,7 @@ export const SeriesSeasonDetailPage = () => {
|
|||||||
padding="20px"
|
padding="20px"
|
||||||
width="80%"
|
width="80%"
|
||||||
>
|
>
|
||||||
{seasonVideo?.map((data) => (
|
{/* {seasonVideo?.map((data) => (
|
||||||
<Box
|
<Box
|
||||||
minWidth="100%"
|
minWidth="100%"
|
||||||
height="60px"
|
height="60px"
|
||||||
@ -147,7 +145,7 @@ export const SeriesSeasonDetailPage = () => {
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
))}
|
))} */}
|
||||||
<EmptyEnd />
|
<EmptyEnd />
|
||||||
</Flex>
|
</Flex>
|
||||||
<Routes>
|
<Routes>
|
||||||
|
@ -45,8 +45,8 @@ export const TypesPage = () => {
|
|||||||
{dataTypes.map((data) => (
|
{dataTypes.map((data) => (
|
||||||
<Flex
|
<Flex
|
||||||
align="flex-start"
|
align="flex-start"
|
||||||
width="200px"
|
width={{ base: "200px", sm: "160px" }}
|
||||||
height="280px"
|
height={{ base: "280px", sm: "200px" }}
|
||||||
border="1px"
|
border="1px"
|
||||||
borderColor="brand.900"
|
borderColor="brand.900"
|
||||||
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
||||||
|
@ -38,6 +38,7 @@ export const TypesSeriesDetailPage = () => {
|
|||||||
const onSelectItem = (mediaId: number) => {
|
const onSelectItem = (mediaId: number) => {
|
||||||
let currentPlay = 0;
|
let currentPlay = 0;
|
||||||
const listMediaId: number[] = [];
|
const listMediaId: number[] = [];
|
||||||
|
console.log(`select item:${mediaId}`);
|
||||||
if (!videoWithType) {
|
if (!videoWithType) {
|
||||||
console.log('Fail to get Type...');
|
console.log('Fail to get Type...');
|
||||||
return;
|
return;
|
||||||
@ -55,7 +56,7 @@ export const TypesSeriesDetailPage = () => {
|
|||||||
if (!dataType) {
|
if (!dataType) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TopBar title="Type detail" />
|
<TopBar title="Series detail" />
|
||||||
<PageLayoutInfoCenter>
|
<PageLayoutInfoCenter>
|
||||||
Fail to load Series id: {typeId}/{seriesId}
|
Fail to load Series id: {typeId}/{seriesId}
|
||||||
</PageLayoutInfoCenter>
|
</PageLayoutInfoCenter>
|
||||||
@ -149,7 +150,7 @@ export const TypesSeriesDetailPage = () => {
|
|||||||
<Box
|
<Box
|
||||||
key={data.id}
|
key={data.id}
|
||||||
width="200px"
|
width="200px"
|
||||||
height="280px"
|
height="300px"
|
||||||
border="1px"
|
border="1px"
|
||||||
borderColor="brand.900"
|
borderColor="brand.900"
|
||||||
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
||||||
|
@ -8,7 +8,7 @@ import { EmptyEnd } from '@/components/EmptyEnd';
|
|||||||
import { PageLayout } from '@/components/Layout/PageLayout';
|
import { PageLayout } from '@/components/Layout/PageLayout';
|
||||||
import { PageLayoutInfoCenter } from '@/components/Layout/PageLayoutInfoCenter';
|
import { PageLayoutInfoCenter } from '@/components/Layout/PageLayoutInfoCenter';
|
||||||
import { BUTTON_TOP_BAR_PROPERTY, TopBar } from '@/components/TopBar/TopBar';
|
import { BUTTON_TOP_BAR_PROPERTY, TopBar } from '@/components/TopBar/TopBar';
|
||||||
import { DisplayMediaFull } from '@/components/media/DisplayMediaFull';
|
import { DisplayMediaListFull } from '@/components/media/DisplayMediaListFull';
|
||||||
import { TypeEditPopUp } from '@/components/popup/GenderEditPopUp';
|
import { TypeEditPopUp } from '@/components/popup/GenderEditPopUp';
|
||||||
import { MediaEditPopUp } from '@/components/popup/TrackEditPopUp';
|
import { MediaEditPopUp } from '@/components/popup/TrackEditPopUp';
|
||||||
import { useColorModeValue } from '@/components/ui/color-mode';
|
import { useColorModeValue } from '@/components/ui/color-mode';
|
||||||
@ -19,7 +19,6 @@ import {
|
|||||||
useSpecificType,
|
useSpecificType,
|
||||||
useTypeSeriesSeasonGetVideo,
|
useTypeSeriesSeasonGetVideo,
|
||||||
} from '@/service';
|
} from '@/service';
|
||||||
import { DisplayMediaListFull } from '@/components/media/DisplayMediaListFull';
|
|
||||||
|
|
||||||
export const TypesSeriesSeasonDetailPage = () => {
|
export const TypesSeriesSeasonDetailPage = () => {
|
||||||
const { typeId, seriesId, seasonId } = useParams();
|
const { typeId, seriesId, seasonId } = useParams();
|
||||||
@ -108,7 +107,7 @@ export const TypesSeriesSeasonDetailPage = () => {
|
|||||||
{videos?.map((data) => (
|
{videos?.map((data) => (
|
||||||
<Box
|
<Box
|
||||||
key={data.id}
|
key={data.id}
|
||||||
width="calc(max(300px,50%))"
|
width={{sm:"95%", base:"calc(max(300px,50%))"}}
|
||||||
height="60px"
|
height="60px"
|
||||||
border="1px"
|
border="1px"
|
||||||
borderColor="brand.900"
|
borderColor="brand.900"
|
||||||
|
@ -19,6 +19,7 @@ export type ActivePlaylistServiceProps = {
|
|||||||
previous: () => void;
|
previous: () => void;
|
||||||
next: () => void;
|
next: () => void;
|
||||||
first: () => void;
|
first: () => void;
|
||||||
|
clear: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useActivePlaylistService = (): ActivePlaylistServiceProps => {
|
export const useActivePlaylistService = (): ActivePlaylistServiceProps => {
|
||||||
@ -140,5 +141,6 @@ export const useActivePlaylistServiceWrapped = (
|
|||||||
next,
|
next,
|
||||||
MediaActive,
|
MediaActive,
|
||||||
first,
|
first,
|
||||||
|
clear,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user