Skip to content

Commit

Permalink
feat: Replace crappy missing-cover cover with Hardcover-inspired Publ…
Browse files Browse the repository at this point in the history
…ic Domain paintings

Thank you @hardccoverapp!
  • Loading branch information
phildenhoff committed Jan 1, 2025
1 parent 54f2609 commit 912731a
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 15 deletions.
Binary file added src/assets/1.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/2.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/3.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/4.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/5.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
56 changes: 42 additions & 14 deletions src/components/atoms/BookCover.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { shortenToChars } from "$lib/domain/book";
import { LibraryBook } from "@/bindings";
import { AspectRatio, Overlay, Text, Transition } from "@mantine/core";
import { HTMLAttributes, useState } from "react";
import { HTMLAttributes, useEffect, useState } from "react";
import { formatAuthorList } from "@/lib/authors";
import { selectByStringHash } from "@/lib/hash-string";

import img1Url from "../../assets/1.jpg";
import img2Url from "../../assets/2.jpg";
import img3Url from "../../assets/3.jpg";
import img4Url from "../../assets/4.jpg";
import img5Url from "../../assets/5.jpg";

type LibraryBookWithCoverImage = LibraryBook & {
cover_image: NonNullable<LibraryBook["cover_image"]>;
Expand Down Expand Up @@ -65,10 +72,16 @@ const BookCoverWithPlaceholder = ({
} & HTMLAttributes<HTMLDivElement>) => {
const [isHovering, setIsHovering] = useState(false);

const imgUrl = selectByStringHash(
[img1Url, img2Url, img3Url, img4Url, img5Url],
book.title,
);

return (
<AspectRatio
ratio={9 / 6}
h={200}
w={150}
w={133}
m="xs"
onPointerOver={() => {
setIsHovering(true);
Expand All @@ -80,29 +93,44 @@ const BookCoverWithPlaceholder = ({
<div
{...props}
style={{
width: "150px",
width: "133px",
height: "200px",
background: "linear-gradient(#555, #111)",
backgroundColor: "#555",
padding: "0.5rem",
display: "grid",
gridTemplateAreas: "overlap",
}}
>
<img
alt="App-provided placeholder cover."
src={imgUrl}
style={{
width: "inherit",
height: "inherit",
gridArea: "overlap",
filter: "brightness(0.7)",
}}
/>
<div
style={{
border: "2px solid #888",
height: "100%",
width: "auto",
display: "flex",
flexDirection: "column",
alignContent: "center",
justifyContent: "space-between",
textAlign: "center",
padding: "0.5rem",
alignContent: "flex-start",
justifyContent: "flex-end",
gridArea: "overlap",
padding: "0.3rem",
zIndex: 1,
}}
>
<Text size="sm" c="white">
{shortenToChars(book.title, 50)}
<Text
size="lg"
fw="bolder"
c="white"
style={{ textShadow: "0px 1px #888" }}
>
{shortenToChars(book.title, 45)}
</Text>
<Text size="sm" c="white">
<Text size="md" c="#ccc" style={{ textShadow: "0px 2px #222" }}>
{formatAuthorList(book.author_list)}
</Text>
<Transition
Expand Down
6 changes: 5 additions & 1 deletion src/components/pages/Books.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,11 @@ const BookDetails = ({ book }: { book: LibraryBook }) => {
<Stack h={"100%"}>
<Group wrap={"nowrap"} align="flex-start">
<BookCover book={book} disableFade />
<Stack justify="space-between" mih={"200px"}>
<Stack
justify="space-between"
mih={"200px"}
maw="calc(400px - 133px)"
>
<Stack ml={"sm"} align="flex-start" justify="flex-start">
<Text size="xl" fw={"700"}>
{book.title}
Expand Down
34 changes: 34 additions & 0 deletions src/lib/hash-string.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Selects an item from an array using a string as a key.
*
* @param options - Array of options to select from
* @param key - String key used for selection
* @returns Selected item from the array
*/
export const selectByStringHash = <T>(options: T[], key: string): T => {
if (!Array.isArray(options) || options.length === 0) {
throw new Error("Options must be a non-empty array");
}
if (typeof key !== "string") {
throw new Error("Key must be a string");
}

const hash = hashString(key);
const index = hash % options.length;
return options[index];
};

/**
* Creates a simple hash from a string.
* @param str - Input string to hash
* @returns Hash value
*/
const hashString = (str: string) => {
let hash = 0;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
hash = (hash << 5) - hash + char;
hash = hash & hash; // Convert to 32-bit integer
}
return Math.abs(hash);
};

0 comments on commit 912731a

Please sign in to comment.