File size: 3,828 Bytes
61e6dfe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2babd61
61e6dfe
 
 
 
 
 
 
 
4699c39
61e6dfe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { useRef, useState } from "react";
import { HistoryIcon } from "lucide-react";
import { useSearchParams } from "next/navigation";
import { useUpdateEffect } from "react-use";

import { Button } from "@/components/ui/button";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";
import { Commit } from "@/lib/type";
import { cn, humanizeNumber } from "@/lib/utils";

export const Commits = function ({ commits }: { commits?: Commit[] }) {
  const searchParams = useSearchParams();
  const commitParam = searchParams.get("commit");

  const commitsContainer = useRef<HTMLUListElement>(null);
  const commitSelected = useRef<HTMLLIElement>(null);
  const [open, setOpen] = useState(false);
  const [selectedCommit, setSelectedCommit] = useState<string | null>(
    commitParam
      ? commitParam
      : commits && commits.length > 0
      ? commits[0]?.oid
      : null
  );

  const handleViewCommit = (commitId: string) => {
    let url = window.location.pathname;
    if (commitId !== commits?.[0].oid) {
      url += `?commit=${commitId}`;
    }
    window.location.replace(url);
  };

  useUpdateEffect(() => {
    if (open) {
      setTimeout(() => {
        if (commitSelected.current && commitsContainer.current) {
          const container = commitsContainer.current;
          const selected = commitSelected.current;
          if (!container || !selected) return;
          const offsetTop = selected.offsetTop;
          const offsetHeight = selected.offsetHeight;
          const containerHeight = container.offsetHeight;
          const scrollTop = offsetTop - containerHeight / 2 + offsetHeight / 2;
          container.scrollTo({
            top: scrollTop,
            behavior: "smooth",
          });
        }
      }, 200);
    }
  }, [open]);

  useUpdateEffect(() => {
    if (selectedCommit !== commits?.[0].oid && !commitParam) {
      setSelectedCommit(commits ? commits[0]?.oid : null);
    }
  }, [commits]);

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <form>
        <PopoverTrigger asChild>
          <Button variant={open ? "default" : "ghost"} size="icon-xs">
            <HistoryIcon className="size-3.5" />
          </Button>
        </PopoverTrigger>
        <PopoverContent
          align="start"
          className="rounded-2xl! p-0! overflow-hidden!"
        >
          <header className="bg-background px-3 py-2 border-b border-background-foreground text-xs text-muted-foreground font-medium flex items-center justify-center gap-1.5">
            Historical Versions
            <span className="py-0.5 px-1 text-[10px] inline-flex items-center justify-center rounded font-semibold bg-accent text-primary font-mono">
              {humanizeNumber(commits ? commits.length : 0)}
            </span>
          </header>
          <ul
            ref={commitsContainer}
            className="p-1 space-y-1 max-h-80 overflow-y-auto"
          >
            {commits?.map((commit) => (
              <li
                key={commit.oid}
                className={cn(
                  "overflow-hidden group relative px-3 py-2 text-xs cursor-pointer rounded-lg",
                  selectedCommit === commit.oid
                    ? "bg-indigo-500/10 text-indigo-600"
                    : "hover:bg-accent"
                )}
                ref={selectedCommit === commit.oid ? commitSelected : undefined}
                onClick={() => handleViewCommit(commit.oid)}
              >
                <p className="truncate break-all">{commit.title}</p>
                <p className="text-[10px] text-muted-foreground mt-0.5">
                  {new Date(commit.date).toLocaleString()}
                </p>
              </li>
            ))}
          </ul>
        </PopoverContent>
      </form>
    </Popover>
  );
};