main
reng 1 month ago
parent 93d6ea9f6b
commit 1bad38a664
  1. 1009
      package-lock.json
  2. 1
      package.json
  3. BIN
      public/egg_bg(500x500).png
  4. 8
      src/comps/canvas.jsx
  5. 30
      src/pages/explore.jsx
  6. 12
      src/pages/keywords.jsx
  7. 65
      src/utils/firebase.js
  8. 0
      src/utils/useSelect.jsx
  9. 5
      src/utils/usetext.jsx

1009
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -11,6 +11,7 @@
},
"dependencies": {
"@tailwindcss/vite": "^4.1.18",
"firebase": "^12.9.0",
"lottie-react": "^2.4.1",
"react": "^19.2.0",
"react-dom": "^19.2.0",

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

@ -78,12 +78,14 @@ export default function Canvas({ lookat, ...props }) {
function movePoints(){
const width=refCanvas.current.width;
const height=refCanvas.current.height;
const moveScale=50000;
const rotateScale=0.000001;
refPoints.current.forEach(point => {
const angle=Date.now()/1000+point.start_angle;
const radius=point.radius;
point.x+=Math.cos(angle)*radius*width/10000*point.velocity.x;
point.y+=Math.sin(angle)*radius*width/10000*point.velocity.y;
point.start_angle+=0.01*point.velocity.angle;
point.x+=Math.cos(angle)*radius*width/moveScale*point.velocity.x;
point.y+=Math.sin(angle)*radius*width/moveScale*point.velocity.y;
point.start_angle+=point.velocity.angle*rotateScale;
});
}

@ -7,6 +7,7 @@ import Canvas from "../comps/canvas.jsx";
import Lottie from "lottie-react";
import hint_animation from '../assets/lottie/hint.json';
import egg_bg from '../assets/lottie/egg_bg.json';
import { lookatKeyword } from "../utils/firebase.js";
const State={
Intro: 'Intro',
@ -18,10 +19,21 @@ export default function Explore() {
const { selectedKeyword, getText } = useText();
const navigate=useNavigate();
if(selectedKeyword.length===0){
navigate('/keywords');
}
const [state, setState] = useState(State.Intro);
const [lookat, setLookat] = useState(selectedKeyword[0] || null);
const [showInfo, setShowInfo] = useState(false);
useEffect(()=>{
if(!lookat) return;
lookatKeyword(lookat);
},[lookat]);
useEffect(()=>{
const timeoutId = setTimeout(()=>{
setState(State.Explore);
@ -46,9 +58,9 @@ export default function Explore() {
return (
<>
<main className="!px-0 !gap-0 !justify-start">
<section className="absolute top-[1.5rem] left-[1.5rem] right-[1.5rem] flex flex-row justify-between items-center">
<section className="z-10 absolute top-[1.5rem] left-[1.5rem] right-[1.5rem] flex flex-row justify-between items-center">
<button className="uppercase flex flex-row" onClick={()=>{
navigate('/');
navigate('/keywords');
}}><img src="back.svg" alt="back"/>{getText('button_reselect')}</button>
<button className="z-20 w-[1.875rem] border aspect-square flex justify-center items-center rounded-full"
@ -56,15 +68,19 @@ export default function Explore() {
setShowInfo(!showInfo);
}}>{!showInfo?'i':<img src="x.svg" alt="close"/>}</button>
</section>
<div className="w-full relative aspect-[393/500]">
<div className="w-full flex-1 flex justify-center items-center overflow-hidden">
<div className="w-full relative aspect-square">
{/* <img src="egg_bg.svg" alt="egg" className="w-full object-contain"/> */}
<Lottie animationData={egg_bg} loop={true} className='w-full'/>
<Canvas className="absolute inset-0 top-0 left-0 w-full h-full"
<Canvas className="absolute inset-0 top-0 left-0 w-full h-full transform-origin-center transform-[scale(1.1)]"
lookat={selectedKeyword.indexOf(lookat)}/>
</div>
<div className="absolute inset-0 top-0 left-0 w-full h-full transform-origin-center transform-[scale(1.1)]">
<img src="egg_bg(500x500).png" alt="egg" className="absolute w-full object-contain"/>
<Lottie animationData={egg_bg} loop={true} className='absolute w-full h-full'/>
</div>
</div>
</div>
<div className="flex flex-row gap-[0.75rem] justify-center items-center mt-[1.5rem]">
<img src="eye.svg" alt="eye" className="w-[0.9965rem] object-contain"/>
<div className="text-[0.75rem]">{getText('title_observe')}</div>

@ -2,10 +2,11 @@ import { useEffect, useRef, useState } from 'react'
import {Button} from "../comps/button";
import { useText } from "../utils/usetext.jsx";
import { useNavigate } from "react-router-dom";
import { addKeywords } from '../utils/firebase';
export default function Keywords() {
const { getText, getKeywords, selectedKeyword, select } = useText();
const { getText, getKeywords, selectedKeyword, select, clearSelectedKeyword } = useText();
const keywords = getKeywords();
const rowCount=3;
const colCount = Math.ceil(keywords.length / rowCount);
@ -25,6 +26,13 @@ export default function Keywords() {
}, [keywords]);
useEffect(()=>{
// clear selected keywords when unmount
clearSelectedKeyword();
}, []);
return (
@ -57,6 +65,8 @@ export default function Keywords() {
<div className="w-full px-[1.5rem]">
<Button onClick={()=>{
addKeywords(selectedKeyword);
navigate('/explore');
}}
disabled={selectedKeyword.length<4}

@ -0,0 +1,65 @@
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getFirestore, collection, doc, writeBatch, setDoc } from "firebase/firestore";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: "AIzaSyB3Yfrh18w5VNSb36LFHJHvegTSv_W1VOU",
authDomain: "uc-23070-grayscale.firebaseapp.com",
projectId: "uc-23070-grayscale",
storageBucket: "uc-23070-grayscale.firebasestorage.app",
messagingSenderId: "866564340708",
appId: "1:866564340708:web:31eea78e6c56eeab6825f1",
measurementId: "G-NNY50B5T9F"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
export function addKeywords(keywords) {
console.log('Adding keywords to Firestore:', keywords);
const db = getFirestore(app);
const batch = writeBatch(db);
keywords.forEach((keyword) => {
const keywordRef = doc(db, "keywords", keyword.id.toString());
const keywordDoc = {
...keyword,
updatedTime: new Date(),
};
batch.set(keywordRef, keywordDoc);
});
batch.commit()
.then(() => {
console.log("Keywords added successfully!");
})
.catch((error) => {
console.error("Error adding keywords: ", error);
});
}
export function lookatKeyword(keyword) {
console.log('Looking at keyword in Firestore:', keyword);
const db = getFirestore(app);
const keywordRef = doc(collection(db, "lookat"), 'latest');
// Update the keyword document with the focused state
setDoc(keywordRef, {
id: keyword.id,
title: keyword.title,
updatedTime: new Date(),
});
}

@ -49,6 +49,9 @@ export function TextProvider({children}) {
}
}
}
function clearSelectedKeyword(){
setSelectedKeyword([]);
}
useEffect(()=>{
console.log("selectedKeyword changed", selectedKeyword);
@ -56,7 +59,7 @@ export function TextProvider({children}) {
return (
<TextContent.Provider value={{ data, getText, nextLang, toggleLang, getKeywords, selectedKeyword, select }}>
<TextContent.Provider value={{ data, getText, nextLang, toggleLang, getKeywords, selectedKeyword, select, clearSelectedKeyword }}>
{children}
</TextContent.Provider>
)

Loading…
Cancel
Save