Skip to content

Commit

Permalink
Add thumbnails header with extra UI for web target
Browse files Browse the repository at this point in the history
  • Loading branch information
tnajdek committed Sep 11, 2023
1 parent 5f4c4b9 commit e8e2dc8
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 37 deletions.
Binary file added res/icons/more-horizontal.png
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 res/icons/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
87 changes: 58 additions & 29 deletions src/common/components/sidebar/thumbnails-view.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, { Fragment, useState, useCallback, useContext, useEffect, useRef, useImperativeHandle } from 'react';
import { useIntl } from 'react-intl';
import React, { Fragment, useState, useCallback, useContext, useEffect, useRef, useImperativeHandle, memo } from 'react';
import { useIntl, FormattedMessage } from 'react-intl';
import cx from 'classnames';
import { pressedNextKey, pressedPreviousKey } from '../../lib/utilities';
import { ReaderContext } from '../../reader';

function Thumbnail({ thumbnail, selected, pageLabel, onContextMenu }) {
const Thumbnail = memo(({ thumbnail, selected, pageLabel, onContextMenu }) => {
return (
<div
className={cx('thumbnail', { selected })}
Expand All @@ -13,19 +13,24 @@ function Thumbnail({ thumbnail, selected, pageLabel, onContextMenu }) {
>
<div className="image">
{thumbnail.image
? <img width={thumbnail.width} height={thumbnail.height} src={thumbnail.image} draggable={false}/>
: <div className="placeholder" style={{ width: thumbnail.width + 'px', height: thumbnail.height + 'px' }}/>
? <img width={thumbnail.width} height={thumbnail.height} src={thumbnail.image} draggable={false} />
: <div className="placeholder" style={{ width: thumbnail.width + 'px', height: thumbnail.height + 'px' }} />
}
</div>
<div className="label">{pageLabel}</div>
</div>
);
}
});

Thumbnail.displayName = 'Thumbnail';



function ThumbnailsView(props) {
const intl = useIntl();
const [selected, setSelected] = useState([0]);
const containerRef = useRef();
const { onOpenThumbnailContextMenu } = props;
const { platform } = useContext(ReaderContext);

useEffect(() => {
Expand All @@ -42,7 +47,7 @@ function ThumbnailsView(props) {

useEffect (() => {
let options = {
root: containerRef.current.parentNode,
root: containerRef.current,
rootMargin: "200px",
threshold: 1.0
};
Expand Down Expand Up @@ -172,39 +177,63 @@ function ThumbnailsView(props) {
}
}

function handleContextMenu(event) {
const handleContextMenu = useCallback((event) => {
if (platform === 'web') {
return;
}
event.preventDefault();
props.onOpenThumbnailContextMenu({
onOpenThumbnailContextMenu({
x: event.clientX,
y: event.clientY,
pageIndexes: selected
});
}
}, [onOpenThumbnailContextMenu, platform, selected]);

const handleMoreClick = useCallback((event) => {
event.preventDefault();
const { x, bottom: y } = event.target.getBoundingClientRect();
onOpenThumbnailContextMenu({
x, y,
pageIndexes: selected,
});
}, [onOpenThumbnailContextMenu, selected]);

return (
<div
ref={containerRef}
className="thumbnails-view"
tabIndex={-1}
data-tabstop={1}
onMouseDown={handleMouseDown}
onKeyDown={handleKeyDown}
>
{props.thumbnails.map((thumbnail, index) => {
let pageLabel = props.pageLabels[index] || (index + 1).toString();
return (
<Thumbnail
key={index}
thumbnail={thumbnail}
selected={selected.includes(index)}
pageLabel={pageLabel}
onContextMenu={handleContextMenu}
<div className="thumbnails-view">
{platform === 'web' && (
<div className="thumbnails-header">
<FormattedMessage id="pdfReader.selectedPages" values={ { count: selected.length }} />
<button
tabIndex={-1}
data-tabstop={1}
className="toolbarButton"
title={intl.formatMessage({ id: 'pdfReader.pageOptions' })}
onClick={handleMoreClick}
/>
);
})}
</div>
)}
<div
className="thumbnails"
data-tabstop={1}
onKeyDown={handleKeyDown}
onMouseDown={handleMouseDown}
ref={containerRef}
tabIndex={-1}
>
{props.thumbnails.map((thumbnail, index) => {
let pageLabel = props.pageLabels[index] || (index + 1).toString();
return (
<Thumbnail
key={index}
thumbnail={thumbnail}
selected={selected.includes(index)}
pageLabel={pageLabel}
contextMenu={props.contextMenu}
onContextMenu={handleContextMenu}
/>
);
})}
</div>
</div>
);
}
Expand Down
55 changes: 48 additions & 7 deletions src/common/stylesheets/components/_thumbnails-view.scss
Original file line number Diff line number Diff line change
@@ -1,13 +1,34 @@

.thumbnails-view {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 10px;
padding: 10px 30px 0;
cursor: default;
width: 100%;
height: 100%;
user-select: none;
outline: none;
display: flex;
flex-direction: column;

.thumbnails-header {
display: flex;
position: relative;
margin: $thumbnail-header-padding;
justify-content: space-between;
align-items: center;

.toolbarButton {
@include icon("more-horizontal", 12px);
}
}

.thumbnails {
cursor: default;
display: flex;
flex-wrap: wrap;
gap: 10px;
justify-content: center;
outline: none;
overflow: auto;
padding: 10px 30px 0;
user-select: none;
}

.thumbnail {
.image {
Expand All @@ -26,6 +47,26 @@
}
}

@if $platform =="web" {
position: relative;
.more {
@include icon("more", 12px);
position: absolute;
top: 12px;
right: 12px;
display: none;
cursor: pointer;

@include state(".thumbnail:hover") {
display: block;
}

&.active {
display: block;
}
}
}

.label {
display: flex;
justify-content: center;
Expand Down
1 change: 1 addition & 0 deletions src/common/stylesheets/themes/_light-darwin.scss
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ $attach-icon-toggled: "darwin/attach-linear-white";
$thumbnail-selection-ring-focus-bg: rgba(0, 0, 0, 0.2);
$thumbnail-selection-ring-selected-bg: rgba(0, 0, 0, 0.1);
$thumbnail-image-border-color: transparent;
$thumbnail-header-padding: 6px 13px;

// Outline & attachment view
$sidebar-item-link-btn-color: $text-color;
Expand Down
4 changes: 3 additions & 1 deletion src/en-us.strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,5 +145,7 @@ export default {
'pdfReader.enterPassword': 'Enter the password to open this PDF file.',
'pdfReader.includeAnnotations': 'Include annotations',
'pdfReader.preparingDocumentForPrinting': 'Preparing document for printing…',
'pdfReader.phraseNotFound': 'Phrase not found'
'pdfReader.phraseNotFound': 'Phrase not found',
'pdfReader.selectedPages': '{count, plural, one {# page} other {# pages}} selected',
'pdfReader.pageOptions': 'Page Options'
};

0 comments on commit e8e2dc8

Please sign in to comment.