ArnabChatterjee20k / PickPalette-PaletteFromImage

https://www.producthunt.com/posts/pickpalette
21 stars 20 forks source link

Palette Browse Optimisation - Adding virtualisation #11

Open ArnabChatterjee20k opened 6 months ago

ArnabChatterjee20k commented 6 months ago

Currently in the browse section, all new palettes are getting loaded and both state and dom are getting synced. If state is having 1000 elements then the dom is also loading 1000 nodes which is a big performance bottleneck. Use tanstack virtualisation for adding virtualisation support which is basically loading only the visible items. The same strategy used by spotify,facebook,twitter,instagram,etc

rajat99-default commented 6 months ago

Please assign me this issue I would Like to work on this issue

ArnabChatterjee20k commented 6 months ago

I am assigning this to you @rajat99-default . Update me every 24 hours. Completion deadline 3days Setup a dummy express server. I am giving you the code

const express = require('express');
const app = express();

// Sample colors data
const colors = [
    "#69d2e7", "#a7dbd8", "#e0e4cc", "#f38630", "#fa6900",
    "#fe4365", "#fc9d9a", "#f9cdad", "#c8c8a9", "#83af9b",
    "#ecd078", "#d95b43", "#c02942", "#542437", "#53777a",
    "#556270", "#4ecdc4", "#c7f464", "#ff6b6b", "#c44d58",
    "#774f38", "#e08e79", "#f1d4af", "#ece5ce", "#c5e0dc",
    "#e8ddcb", "#cdb380", "#036564", "#033649", "#031634",
    "#490a3d", "#bd1550", "#e97f02", "#f8ca00", "#8a9b0f",
    "#594f4f", "#547980", "#45ada8", "#9de0ad", "#e5fcc2",
    "#00a0b0", "#6a4a3c", "#cc333f", "#eb6841", "#edc951",
    "#e94e77", "#d68189", "#c6a49a", "#c6e5d9", "#f4ead5",
    "#3fb8af", "#7fc7af", "#dad8a7", "#ff9e9d", "#ff3d7f",
    "#d9ceb2", "#948c75", "#d5ded9", "#7a6a53", "#99b2b7",
    "#ffffff", "#cbe86b", "#f2e9e1", "#1c140d", "#cbe86b",
    "#efffcd", "#dce9be", "#555152", "#2e2633", "#99173c",
    "#343838", "#005f6b", "#008c9e", "#00b4cc", "#00dffc",
    "#413e4a", "#73626e", "#b38184", "#f0b49e", "#f7e4be",
    "#ff4e50", "#fc913a", "#f9d423", "#ede574", "#e1f5c4",
    "#99b898", "#fecea8", "#ff847c", "#e84a5f", "#2a363b",
    "#655643", "#80bca3", "#f6f7bd", "#e6ac27", "#bf4d28"
];

// Endpoint to get colors with pagination
app.get('/colors', (req, res) => {
    // Extract page and limit from query parameters, default to 1 and 10 respectively
    const page = parseInt(req.query.page) || 1;
    const limit = parseInt(req.query.limit) || 10;

    // Calculate start and end index based on page and limit
    const startIndex = (page - 1) * limit;
    const endIndex = page * limit;

    // Get colors for the requested page
    const colorsPage = colors.slice(startIndex, endIndex);

    // Return the colors for the requested page
    res.json({
        page,
        limit,
        totalItems: colors.length,
        totalPages: Math.ceil(colors.length / limit),
        colors: colorsPage
    });
});

// Start the server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});

Modify the .env and add your express server url in the PALETTE_API For better testing add more dummy data.

rajat99-default commented 6 months ago

So I have to implement virtualization in Palette.jsx am right

ArnabChatterjee20k commented 6 months ago

Explore the project structure first. The pages are present in pages directory. Here is the directory you have to work with https://github.com/ArnabChatterjee20k/PickPalette-PaletteFromImage/tree/master/src/Page/Explore

rajat99-default commented 6 months ago

I dont think I will be able to do this

import styled from "styled-components"; import useIsMobile from "../../../hooks/useIsMobile"; import getContrastingColor from "../../../utils/getContrastingColor"; import { usePaletteConext } from "../cotext/paletteContext"; import useColorClipboard from "../../../hooks/useColorClipboard"; import { FixedSizeList as List } from 'react-window'; // Import FixedSizeList

import { LikeButton, LivePreviewButton, UsePaletteInProject, } from "../Components/Buttons";

const Item = styled.li` span { opacity: 0; font-weight: bold; transition: all 0.5s ease; color: ${({ color }) => getContrastingColor(color)}; }

width: ${({ totalPalettes }) => 100 / totalPalettes}%;

&:hover { width: ${({ totalPalettes }) => 100 / totalPalettes + 10}%; transition: all 0.1s ease; }

&:hover span { opacity: 1; } `;

export default function ColorPalette({ colors }) { const lastIndex = colors.length - 1; const { lastPaletteReference, isVisible } = usePaletteConext();

const itemSize = 60;

return ( <div ref={lastPaletteReference} className="flex flex-col w-full overflow-hidden bg-neutral-800/50 rounded-xl p-4 border-2 transition-all duration-150 ease-in-out border-neutral-800 shadow-sm"

  <List
    className="flex gap-2 w-full mb-4 overflow-x-scroll sm:overflow-hidden"
    height={80} 
    itemCount={colors.length}
    itemSize={itemSize}
    width="100%"
  >
    {({ index, style }) => {
      const color = colors[index];
      if (!color) return null;
      return (
        <PaletteItem
          key={`${color + index}`}
          className="rounded-lg"
          color={color}
          totalPalettes={colors.length}
          style={style}
        />
      );
    }}
  </List>
  <div className="flex justify-between">
    <div className="flex gap-3">
      <UsePaletteInProject />
      <LivePreviewButton palettes={colors}/>
    </div>
    <LikeButton palettes={colors}/>
  </div>
</div>

); }

const PaletteItem = ({ className, color, totalPalettes, style }) => { const isMobile = useIsMobile(); const { defaultText, clickHandler } = useColorClipboard(color, "copied"); return ( <Item totalPalettes={totalPalettes} color={color} className={h-14 sm:h-16 flex justify-center items-center cursor-pointer ${className}} style={{ backgroundColor: color, ...style }} // here will be the styles from react-windows onClick={() => clickHandler(color)}

{defaultText} ); };

you can re-assignee this issue to someone else

Programer3 commented 6 months ago

Hi @ArnabChatterjee20k, may I take over this issue #11 after @rajat99-default? As @rajat99-default's has abandoned this issue, Please assign me, I'd like to work on it as GSSoC'24 contributor.

ArnabChatterjee20k commented 6 months ago

Hi @ArnabChatterjee20k, may I take over this issue #11 after @rajat99-default? As @rajat99-default's has abandoned this issue, Please assign me, I'd like to work on it as GSSoC'24 contributor.

Fine I am assigning this to @Programer3 . Read this issue thread

Programer3 commented 6 months ago

Thank You

ArnabChatterjee20k commented 6 months ago

Just update me every 24 hours

Programer3 commented 6 months ago

Hey @ArnabChatterjee20k,

I've made some progress on this issue and would appreciate your feedback. You can find the commits on GitHub.

Implemented | Tanstack virtualization for better DOM handling

I've tested these changes locally and the /colors endpoint is responding as expected.

If you're happy with these updates, I can create a pull request for further review and merging.

Thanks!

ArnabChatterjee20k commented 6 months ago

Send me a video Follow these steps while doing - 1) Open devtools (elements tab) 2) Capture a video of the container where the virtualisation is added 3) Capture the video while scrolling the palettes

ArnabChatterjee20k commented 6 months ago

Can you share youtube video link as it is opening in my side

ArnabChatterjee20k commented 5 months ago

@Programer3 ??

SanskritiGupta-03 commented 5 months ago

@Programer3 Any updates on the video? The link is not redirecting to a video.