File size: 3,912 Bytes
f152ae2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { Carousel } from "@mantine/carousel";
import { Button, Group, Stack, Text, Transition, rem } from "@mantine/core";
import { useEffect, useState } from "react";
import type { SearchResults } from "../../../../modules/search";
import "@mantine/carousel/styles.css";
import Lightbox from "yet-another-react-lightbox";
import Captions from "yet-another-react-lightbox/plugins/captions";
import "yet-another-react-lightbox/styles.css";
import "yet-another-react-lightbox/plugins/captions.css";
import { addLogEntry } from "../../../../modules/logEntries";
import { getHostname } from "../../../../modules/stringFormatters";

export default function ImageResultsList({
  imageResults,
}: {
  imageResults: SearchResults["imageResults"];
}) {
  const [isLightboxOpen, setLightboxOpen] = useState(false);
  const [lightboxIndex, setLightboxIndex] = useState(0);
  const [isMounted, setMounted] = useState(false);
  useEffect(() => setMounted(true), []);

  const handleImageClick = (index: number) => {
    setLightboxIndex(index);
    setLightboxOpen(true);
  };

  const imageStyle = {
    objectFit: "cover",
    height: rem(180),
    width: rem(240),
    borderRadius: rem(4),
    border: `${rem(2)} solid var(--mantine-color-default-border)`,
    cursor: "zoom-in",
  } as const;

  return (
    <>
      <Carousel slideSize="0" slideGap="xs" align="start" dragFree loop>
        {imageResults.map(([title, sourceUrl, thumbnailUrl], index) => (
          <Transition
            key={`${title}-${sourceUrl}-${thumbnailUrl}`}
            mounted={isMounted}
            transition="fade"
            timingFunction="ease"
            enterDelay={index * 250}
            duration={1500}
          >
            {(styles) => (
              <Carousel.Slide style={styles}>
                <img
                  alt={title}
                  src={thumbnailUrl}
                  onClick={() => handleImageClick(index)}
                  onKeyDown={(e) => {
                    if (e.key === "Enter") {
                      handleImageClick(index);
                    }
                  }}
                  style={imageStyle}
                />
              </Carousel.Slide>
            )}
          </Transition>
        ))}
      </Carousel>
      <Lightbox
        open={isLightboxOpen}
        close={() => setLightboxOpen(false)}
        plugins={[Captions]}
        index={lightboxIndex}
        slides={imageResults.map(([title, url, thumbnailUrl, sourceUrl]) => ({
          src: thumbnailUrl,
          description: (
            <Stack align="center" gap="md">
              {title && (
                <Text component="cite" ta="center">
                  {title}
                </Text>
              )}
              <Group align="center" justify="center" gap="xs">
                <Button
                  variant="subtle"
                  component="a"
                  size="xs"
                  href={sourceUrl}
                  target="_blank"
                  title="Click to see the image in full size"
                  rel="noopener noreferrer"
                  onClick={() => {
                    addLogEntry("User visited an image result in full size");
                  }}
                >
                  View in full resolution
                </Button>
                <Button
                  variant="subtle"
                  component="a"
                  href={url}
                  target="_blank"
                  size="xs"
                  title="Click to visit the page where the image was found"
                  rel="noopener noreferrer"
                  onClick={() => {
                    addLogEntry("User visited an image result source");
                  }}
                >
                  Visit {getHostname(url)}
                </Button>
              </Group>
            </Stack>
          ),
        }))}
      />
    </>
  );
}