Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clamz- feat: Update the design of the chat #17

Open
wants to merge 11 commits into
base: connect-tmi-to-front
Choose a base branch
from
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import ScreenTitle from '@components/ScreenTitle/ScreenTitle';
import Slideshow from '@components/Slideshow/Slideshow';

import './index.css';
import { Jumbotron } from './components/Jumbotron/Jumbotron';
import Jumbotron from './components/Jumbotron/Jumbotron';
import { CursorPoint } from './components/Cursor/CursorPoint';
import Chat from './components/Chat';

Expand Down
3 changes: 2 additions & 1 deletion src/assets/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import pokedex from './img/pokedex.jpg';
import portfolio from './img/portfolio.jpg';
import sharky from './img/sharkie.jpg';
import logo from './img/buche.png';
import buche from './img/buche.jpg';
import { Asset } from './types';

const Assets: Asset = {
pictures: { jelly, join, pokedex, portfolio, sharky, logo }
pictures: { jelly, join, pokedex, portfolio, sharky, logo, buche }
};

export default Assets;
Binary file added src/assets/img/buche.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/img/texture-chat.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/assets/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export type Project = 'pokedex' | 'join' | 'sharky' | 'portfolio' | 'jelly' | 'logo';
export type Project = 'pokedex' | 'join' | 'sharky' | 'portfolio' | 'jelly' | 'logo' | 'buche';

export interface Asset {
pictures: Record<Project, string>;
Expand Down
51 changes: 30 additions & 21 deletions src/components/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,44 @@ const StyledChat = styled('div', {
width: 500,
display: 'flex',
flexDirection: 'column',
gap: 15
boxShadow: 'inset 0 0 78px',
padding: '10px',
'&::after': {
content: '',
position: 'absolute',
inset: 0,
opacity: 0.25,
backgroundImage: 'url("src/assets/img/texture-chat.jpg")',
mixBlendMode: 'overlay'
}
});

const StyledMessage = styled('div', {
color: 'rgba(0,0,0,0.4)'
color: 'rgb(255, 168, 41)',
fontSize: 18,
lineHeight: '1.2',
textShadow:
'rgb(255 168 41) 0px 0px 4px, rgb(255 168 41) 0px 0px 11px, rgb(255 168 41) 0px 0px 19px, rgb(153 94 15) 0px 0px 40px, rgb(153 94 15) 0px 0px 80px, rgb(153 94 15) 0px 0px 90px, rgb(153 94 15) 0px 0px 100px, rgb(153 94 15) 0px 0px 150px',
animation: 'flickerMessage 1.5s infinite'
});

const Div = styled('div', {
background: 'rgb(255,255,255)',
padding: '10px 5px',
borderRadius: 20,
padding: '6px 15px',
borderRadius: 16,
display: 'flex',
gap: 10
gap: 8
});

const StyledUsername = styled('span', {
textTransform: 'uppercase',
fontWeight: 'bold'
fontWeight: 'bold',
fontSize: 15,
color: 'var(--clr-username, #fff)',
textShadow:
'var(--clr-username, #fff) 0px 0px 4px, var(--clr-username, #fff) 0px 0px 11px, var(--clr-username, #fff) 0px 0px 19px, rgb(153 94 15) 0px 0px 40px, rgb(153 94 15) 0px 0px 80px, rgb(153 94 15) 0px 0px 90px, rgb(153 94 15) 0px 0px 100px, rgb(153 94 15) 0px 0px 150px',
animation: 'flickerUsername 1.5s infinite',
whiteSpace: 'nowrap'
});

const min = 0;
const max = 1;

// Clamp number between two values with the following line:
const clamp = (num: number, min: number, max: number) => Math.min(Math.max(num, min), max);

const Chat: React.FC<IChatProps> = () => {
const [messages, setMessages] = React.useState<ChatMessage[]>([]);

Expand All @@ -62,13 +74,10 @@ const Chat: React.FC<IChatProps> = () => {
<StyledChat>
{messages.reverse().map((message, index) => {
return (
<Div
key={index}
css={{
opacity: clamp(2 - messages.length / (messages.length - index), min, max)
}}
>
<StyledUsername css={{ color: message.color }}>{message.username}</StyledUsername>
<Div key={index}>
<StyledUsername style={{ '--clr-username': message.color } as React.CSSProperties}>
{message.username} &gt;
</StyledUsername>
<StyledMessage>{message.message}</StyledMessage>
</Div>
);
Expand Down
17 changes: 15 additions & 2 deletions src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { useStore } from '@/stores';
import { ViewMode } from '@/stores/types';
import { styled } from '@stitches/react';
import { observer } from 'mobx-react-lite';
import Assets from '../../assets/assets';
import { ButtonMenu } from '../Buttons/ButtonMenu';
import { handleViewModeToggle } from './handlers';

interface IAppProps {
onMenuButtonClicked: () => void;
Expand All @@ -24,11 +28,20 @@ const StyledContainerPadding = styled('div', {
});

function Header(props: IAppProps) {
const {
storePortfolio,
storePortfolio: { viewMode }
} = useStore();
return (
<StyledHeader id={'bureau'}>
<StyledContainerPadding>
<img src={Assets.pictures.logo} width={64} />
<menu style={{ display: 'flex' }}>
<menu style={{ display: 'flex', gap: 20, alignItems: 'center' }}>
<li>
<button onClick={handleViewModeToggle(storePortfolio)}>
{viewMode === ViewMode.normal ? 'View Screen' : 'Back to default'}
</button>
</li>
<li>
<ButtonMenu onClick={props.onMenuButtonClicked} />
</li>
Expand All @@ -38,4 +51,4 @@ function Header(props: IAppProps) {
);
}

export default Header;
export default observer(Header);
6 changes: 6 additions & 0 deletions src/components/Header/handlers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { StorePortfolio } from '@/stores/StorePortfolio';

export const handleViewModeToggle = (storePortfolio: StorePortfolio) => () => {
storePortfolio.toggleViewMode();
console.log(storePortfolio.viewMode);
};
41 changes: 30 additions & 11 deletions src/components/Jumbotron/Jumbotron.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
import { useStore } from '@/stores';
import { ViewMode } from '@/stores/types';
import { observer } from 'mobx-react-lite';
import * as React from 'react';
import { CtaButton } from '../Buttons/CtaButton';
import Chat from '../Chat';
import ScreenTitle from '../ScreenTitle/ScreenTitle';
import { styled } from '../style/Style.config';
import { ContainerFlex } from '../utils/ContainerFlex';
import ContainerPadding from '../utils/ContainerPadding';

interface IJumbotronProps {
// children: React.ReactNode;
}
const StyledWrapper = styled('div', {
transition: '0.25s opacity, 0.5s transform',
variants: {
hidden: {
true: {
opacity: 0,
transform: 'translateX(-50px)'
}
}
}
});

const StyledBgTitre = styled('span', {
background: 'orange',
Expand All @@ -17,16 +30,22 @@ const StyledBgTitre = styled('span', {
padding: '0 10px'
});

export function Jumbotron(props: IJumbotronProps) {
function Jumbotron(props: IJumbotronProps) {
const { storePortfolio } = useStore();

return (
<ContainerFlex direction={'column'}>
<ScreenTitle subtitle="Banane un mot prepuce community omnivore honeybadger chapiteau grange">
<span>Salut</span>
<span>
Je m'appelle <StyledBgTitre>Console_Buche</StyledBgTitre>
</span>
</ScreenTitle>
<CtaButton />
</ContainerFlex>
<StyledWrapper hidden={storePortfolio.viewMode === ViewMode.twitchCam}>
<ContainerFlex direction={'column'}>
<ScreenTitle subtitle="Banane un mot prepuce community omnivore honeybadger chapiteau grange">
<span>Salut</span>
<span>
Je m'appelle <StyledBgTitre>Console_Buche</StyledBgTitre>
</span>
</ScreenTitle>
<CtaButton />
</ContainerFlex>
</StyledWrapper>
);
}

export default observer(Jumbotron);
2 changes: 1 addition & 1 deletion src/components/MenuDrawer/handlers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { StorePortfolio } from '@/stores/StorePortfolio';
import TransitionDirection from '@/stores/types';
import { TransitionDirection } from '@/stores/types';

export const handleAnchorClick =
(storePorfolio: StorePortfolio) => (e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
Expand Down
38 changes: 38 additions & 0 deletions src/components/Scene/CameraRegie.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useStore } from '@/stores';
import { ViewMode } from '@/stores/types';
import { useFrame } from '@react-three/fiber';
import { observer } from 'mobx-react-lite';
import * as React from 'react';
import PerspectiveCamNormalMode from './Cameras/PerspectiveCamNormalMode';
import PerspectiveCamTwitchMode from './Cameras/PerspectiveCamTwitchMode';

interface PerspectiveCamProps {}

let t = 0;

function CameraManager(props: PerspectiveCamProps) {
const { storePortfolio, storeCamera } = useStore();

useFrame(() => {
if (storePortfolio.viewMode === ViewMode.normal && t > 0) {
t = Math.min(t - 0.01, 0);
}
if (storePortfolio.viewMode === ViewMode.twitchCam && t < 1) {
t = Math.max(t + 0.01, 1);
}
storeCamera.updateTransitionValue(t);
});

const getActiveCamera = () => {
switch (storePortfolio.viewMode) {
case ViewMode.normal:
return <PerspectiveCamNormalMode />;
case ViewMode.twitchCam:
return <PerspectiveCamTwitchMode />;
}
};

return getActiveCamera();
}

export default observer(CameraManager);
42 changes: 42 additions & 0 deletions src/components/Scene/Cameras/PerspectiveCamNormalMode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { normalizeScreenTo3d } from '@/components/utils/normalizeScreenTo3d';
import { useMousePosition } from '@/hooks/mousePosition';
import { useStore } from '@/stores';
import { PerspectiveCamera } from '@react-three/drei';
import { Camera, useFrame } from '@react-three/fiber';
import { observer } from 'mobx-react-lite';
import * as React from 'react';
import { Vector3 } from 'three';

interface IPerspectiveCamNormalModeProps {}

const step = 0.05;
// const destination = new Vector3(1, 3, 5);

function PerspectiveCamNormalMode(props: IPerspectiveCamNormalModeProps) {
const ref = React.useRef<Camera>();
const { storeCamera } = useStore();

const { lerpedPosition } = useMousePosition();

useFrame(() => {
// const { x, y } = normalizeScreenTo3d(lerpedPosition.x, lerpedPosition.y);

if (!ref.current) {
return null;
}

const destination = storeCamera.curveTransition;
// lookAtPos.lerp(new Vector3(x, y, 0), step);
// ref.current.position.set(lookAtPos.x, lookAtPos.y * -1, lookAtPos.z).add(startPos);
// storeCamera.updateCurrentCameraPosition(ref.current.position.clone());
const currentPos = storeCamera.currentCameraPosition.clone().lerp(destination, step);
const { x, y, z } = currentPos;
ref.current.position.set(x, y, z);
ref.current?.lookAt(new Vector3(0, -1, -5));
storeCamera.updateCurrentCameraPosition(ref.current.position.clone());
});

return <PerspectiveCamera makeDefault ref={ref} />;
}

export default observer(PerspectiveCamNormalMode);
45 changes: 45 additions & 0 deletions src/components/Scene/Cameras/PerspectiveCamTwitchMode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { normalizeScreenTo3d } from '@/components/utils/normalizeScreenTo3d';
import { useMousePosition } from '@/hooks/mousePosition';
import { useStore } from '@/stores';
import { PerspectiveCamera } from '@react-three/drei';
import { Camera, useFrame } from '@react-three/fiber';
import { observer } from 'mobx-react-lite';
import * as React from 'react';
import { Vector3 } from 'three';

interface IPerspectiveCamTwitchModeProps {}

// const lookAtPos = new Vector3();
const step = 0.05;
// const startPos = new Vector3(6, 3, 5);

// const destination = new Vector3(6, 3, 5);

function PerspectiveCamTwitchMode(props: IPerspectiveCamTwitchModeProps) {
const ref = React.useRef<Camera>();
const { storeCamera } = useStore();

const { lerpedPosition } = useMousePosition();

useFrame(() => {
// const { x, y } = normalizeScreenTo3d(lerpedPosition.x, lerpedPosition.y);

if (!ref.current) {
return null;
}
// lookAtPos.lerp(new Vector3(x, y, 0), step);
// ref.current.position.set(lookAtPos.x, lookAtPos.y * -1, lookAtPos.z).add(startPos);

const destination = storeCamera.curveTransition;

const currentPos = storeCamera.currentCameraPosition.clone().lerp(destination, step);
const { x, y, z } = currentPos;
ref.current.position.set(x, y, z);
ref.current?.lookAt(new Vector3(-3, -2, -5));
storeCamera.updateCurrentCameraPosition(ref.current.position.clone());
});

return <PerspectiveCamera makeDefault ref={ref} />;
}

export default observer(PerspectiveCamTwitchMode);
6 changes: 6 additions & 0 deletions src/components/Scene/Cameras/helpers/curveTransition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { CatmullRomCurve3, Vector3 } from 'three';

export const curveTransition = (start: Vector3, middle: Vector3, end: Vector3) => {
const curve = new CatmullRomCurve3([start, middle, end]);
return curve;
};
10 changes: 6 additions & 4 deletions src/components/Scene/Office/Office.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useLoader } from '@react-three/fiber';
import * as React from 'react';
import { CatmullRomCurve3, Vector3 } from 'three';
import { CatmullRomCurve3, MeshBasicMaterial, TextureLoader, Vector3 } from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { bufferToVector3_neo } from '../../utils/bufferToVector3';

Expand All @@ -18,10 +18,12 @@ export function Office(props: IOfficeProps) {
gltf.scene.scale.set(0.1, 0.1, 0.1);
gltf.scene.position.set(position.x, position.y, position.z);
gltf.scene.rotation.set(0, -1.25, 0);
gltf.scene.receiveShadow = true;

gltf.scene.children.forEach((node, i) => {
gltf.scene.children[i].receiveShadow = true;
//TODO : faire ça PROPRE !!!!!!!
const ecran = gltf.scene.children[1];
const mat = new TextureLoader().load('/src/assets/img/buche.jpg', (map) => {
const m = new MeshBasicMaterial({ map });
ecran.material = m;
});

// @ts-expect-error We should find the correct type for this
Expand Down
Loading