Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into experimental
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronleopold committed Apr 28, 2024
2 parents 2f1b085 + 5ac5aec commit 1108406
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 17 deletions.
@@ -0,0 +1,28 @@
/*
Warnings:
- You are about to alter the column `size` on the `media` table. The data in that column could be lost. The data in that column will be cast from `Int` to `BigInt`.
*/
-- RedefineTables
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_media" (
"id" TEXT NOT NULL PRIMARY KEY,
"name" TEXT NOT NULL,
"size" BIGINT NOT NULL,
"extension" TEXT NOT NULL,
"pages" INTEGER NOT NULL,
"updated_at" DATETIME NOT NULL,
"created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"modified_at" DATETIME,
"hash" TEXT,
"path" TEXT NOT NULL,
"status" TEXT NOT NULL DEFAULT 'READY',
"series_id" TEXT,
CONSTRAINT "media_series_id_fkey" FOREIGN KEY ("series_id") REFERENCES "series" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO "new_media" ("created_at", "extension", "hash", "id", "modified_at", "name", "pages", "path", "series_id", "size", "status", "updated_at") SELECT "created_at", "extension", "hash", "id", "modified_at", "name", "pages", "path", "series_id", "size", "status", "updated_at" FROM "media";
DROP TABLE "media";
ALTER TABLE "new_media" RENAME TO "media";
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;
2 changes: 1 addition & 1 deletion core/prisma/schema.prisma
Expand Up @@ -179,7 +179,7 @@ model Media {
id String @id @default(uuid())
name String // derived from filename
size Int // in bytes
size BigInt // in bytes
extension String
pages Int
updated_at DateTime @updatedAt
Expand Down
2 changes: 1 addition & 1 deletion core/src/db/entity/media/entity.rs
Expand Up @@ -21,7 +21,7 @@ pub struct Media {
/// The name of the media. ex: "The Amazing Spider-Man (2018) #69"
pub name: String,
/// The size of the media in bytes.
pub size: i32,
pub size: i64,
/// The file extension of the media. ex: "cbz"
pub extension: String,
/// The number of pages in the media. ex: "69"
Expand Down
2 changes: 1 addition & 1 deletion core/src/filesystem/media/builder.rs
Expand Up @@ -65,7 +65,7 @@ impl MediaBuilder {
(m.len(), last_modified_at)
})?;
let size = raw_size.try_into().unwrap_or_else(|_| {
tracing::error!(?raw_size, "Failed to convert file size to i32");
tracing::error!(?raw_size, ?path, "Failed to convert file size to i64");
0
});

Expand Down
2 changes: 1 addition & 1 deletion packages/browser/src/components/book/BookCard.tsx
Expand Up @@ -75,7 +75,7 @@ export default function BookCard({
return (
<div className="flex items-center justify-between">
<Text size="xs" variant="muted">
{formatBytes(media.size)}
{formatBytes(media.size.valueOf())}
</Text>
</div>
)
Expand Down
Expand Up @@ -2,9 +2,12 @@ import { mediaQueryKeys } from '@stump/api'
import { queryClient } from '@stump/client'
import type { Media } from '@stump/types'
import clsx from 'clsx'
import React, { memo, useEffect } from 'react'
import React, { memo, useEffect, useMemo } from 'react'
import { useHotkeys } from 'react-hotkeys-hook'
import { useSwipeable } from 'react-swipeable'
import { useMediaMatch, useWindowSize } from 'rooks'

import { useDetectZoom } from '@/hooks/useDetectZoom'
import { useReaderStore } from '@/stores'

export type PagedReaderProps = {
Expand Down Expand Up @@ -32,6 +35,21 @@ function PagedReader({ currentPage, media, onPageChange, getPageUrl }: PagedRead
setShowToolBar: state.setShowToolBar,
showToolBar: state.showToolBar,
}))
const { innerWidth } = useWindowSize()
const { isZoomed } = useDetectZoom()

const isMobile = useMediaMatch('(max-width: 768px)')
const [imageWidth, setImageWidth] = React.useState<number | null>(null)
/**
* If the image width is >= 80% of the screen width, we want to fix the side navigation
*/
const fixSideNavigation = useMemo(() => {
if (imageWidth && innerWidth) {
return imageWidth >= innerWidth * 0.8
} else {
return isMobile
}
}, [imageWidth, innerWidth, isMobile])

/**
* This effect is responsible for updating the current page ref when the current page changes. This was
Expand Down Expand Up @@ -94,20 +112,46 @@ function PagedReader({ currentPage, media, onPageChange, getPageUrl }: PagedRead
}
})

const swipeHandlers = useSwipeable({
delta: 150,
onSwipedLeft: () => handlePageChange(currentPage + 1),
onSwipedRight: () => handlePageChange(currentPage - 1),
preventScrollOnSwipe: true,
})
const swipeEnabled = useMemo(
() => !isZoomed && !showToolBar && isMobile,
[isZoomed, showToolBar, isMobile],
)

return (
<div className="relative flex h-full w-full items-center justify-center">
<SideBarControl position="left" onClick={() => handlePageChange(currentPage - 1)} />
<div
className="relative flex h-full w-full items-center justify-center"
{...(swipeEnabled ? swipeHandlers : {})}
>
<SideBarControl
fixed={fixSideNavigation}
position="left"
onClick={() => handlePageChange(currentPage - 1)}
/>
{/* TODO: better error handling for the loaded image */}
<img
className="z-30 max-h-full w-full select-none md:w-auto"
src={getPageUrl(currentPage)}
onLoad={(e) => {
const img = e.target as HTMLImageElement
setImageWidth(img.width)
}}
onError={(err) => {
// @ts-expect-error: is oke
err.target.src = '/favicon.png'
}}
onClick={() => setShowToolBar(!showToolBar)}
/>
<SideBarControl position="right" onClick={() => handlePageChange(currentPage + 1)} />
<SideBarControl
fixed={fixSideNavigation}
position="right"
onClick={() => handlePageChange(currentPage + 1)}
/>
</div>
)
}
Expand All @@ -117,20 +161,21 @@ type SideBarControlProps = {
onClick: () => void
/** The position of the sidebar control */
position: 'left' | 'right'
/** Whether the sidebar should be fixed to the screen */
fixed: boolean
}

/**
* A component that renders an invisible div on either the left or right side of the screen that, when
* clicked, will call the onClick callback. This is used in the `PagedReader` component for
* navigating to the next/previous page.
*/
function SideBarControl({ onClick, position }: SideBarControlProps) {
function SideBarControl({ onClick, position, fixed }: SideBarControlProps) {
return (
<div
className={clsx(
'z-50 h-full border border-transparent transition-all duration-300',
'fixed w-[10%] active:border-edge-200 active:bg-background-200 active:bg-opacity-50',
'sm:relative sm:flex sm:w-full sm:flex-shrink',
'z-50 h-full shrink-0 border border-transparent transition-all duration-300 active:border-edge-200 active:bg-background-200 active:bg-opacity-50',
fixed ? 'fixed w-[10%]' : 'relative flex flex-1 flex-grow',
{ 'right-0': position === 'right' },
{ 'left-0': position === 'left' },
)}
Expand Down
1 change: 1 addition & 0 deletions packages/browser/src/hooks/index.ts
@@ -1,4 +1,5 @@
export { useCurrentOrPrevious } from './useCurrentOrPrevious'
export { useDetectZoom } from './useDetectZoom'
export { useLayoutMode } from './useLayoutMode'
export { usePageParam } from './usePageParam'
export { usePreferences } from './usePreferences'
Expand Down
23 changes: 23 additions & 0 deletions packages/browser/src/hooks/useDetectZoom.ts
@@ -0,0 +1,23 @@
import { useEffect, useState } from 'react'

/**
* A hook to detect the zoom level of the browser.
*/
export function useDetectZoom() {
const [zoom, setZoom] = useState<number>()

useEffect(() => {
const handleResize = () => {
setZoom(window.visualViewport?.scale)
}

window.visualViewport?.addEventListener('resize', handleResize)
handleResize()
return () => window.visualViewport?.removeEventListener('resize', handleResize)
}, [])

return {
isZoomed: zoom !== undefined && zoom > 1,
ratio: zoom,
}
}
2 changes: 1 addition & 1 deletion packages/browser/src/scenes/book/BookFileInformation.tsx
Expand Up @@ -38,7 +38,7 @@ export default function BookFileInformation({ media }: Props) {
<Heading size="xs">File Information</Heading>
<div className="flex space-x-4">
<Text size="sm" variant="muted">
Size: {formatBytes(media.size)}
Size: {formatBytes(media.size.valueOf())}
</Text>
<Text size="sm" variant="muted">
Kind: {media.extension?.toUpperCase()}
Expand Down
Expand Up @@ -71,9 +71,8 @@ export default function BookClubNavigation() {
key={tab.to}
underline={false}
className={cx('whitespace-nowrap border-b-2 px-1 py-3 text-sm font-medium', {
'border-brand-500 text-brand-600 dark:text-brand-400': tab.isActive,
'border-transparent text-gray-800 hover:border-gray-200 hover:text-gray-700 dark:text-gray-400 dark:hover:border-gray-700 dark:hover:text-gray-200':
!tab.isActive,
'border-brand-500 text-brand-500': tab.isActive,
'border-transparent text-muted hover:border-edge': !tab.isActive,
})}
>
{tab.label}
Expand Down
2 changes: 1 addition & 1 deletion packages/types/generated.ts
Expand Up @@ -133,7 +133,7 @@ export type Series = { id: string; name: string; path: string; description: stri
*/
export type MediaMetadata = { title: string | null; series: string | null; number: number | null; volume: number | null; summary: string | null; notes: string | null; age_rating?: number | null; genre?: string[] | null; year: number | null; month: number | null; day: number | null; writers?: string[] | null; pencillers?: string[] | null; inkers?: string[] | null; colorists?: string[] | null; letterers?: string[] | null; cover_artists?: string[] | null; editors?: string[] | null; publisher: string | null; links?: string[] | null; characters?: string[] | null; teams?: string[] | null; page_count: number | null }

export type Media = { id: string; name: string; size: number; extension: string; pages: number; updated_at: string; created_at: string; modified_at: string | null; hash: string | null; path: string; status: FileStatus; series_id: string; metadata: MediaMetadata | null; series?: Series | null; read_progresses?: ReadProgress[] | null; current_page?: number | null; current_epubcfi?: string | null; is_completed?: boolean | null; tags?: Tag[] | null; bookmarks?: Bookmark[] | null }
export type Media = { id: string; name: string; size: BigInt; extension: string; pages: number; updated_at: string; created_at: string; modified_at: string | null; hash: string | null; path: string; status: FileStatus; series_id: string; metadata: MediaMetadata | null; series?: Series | null; read_progresses?: ReadProgress[] | null; current_page?: number | null; current_epubcfi?: string | null; is_completed?: boolean | null; tags?: Tag[] | null; bookmarks?: Bookmark[] | null }

/**
* A model representing a bookmark in the database. Bookmarks are used to save specific locations
Expand Down

0 comments on commit 1108406

Please sign in to comment.