Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add drag in drop #257

Merged
merged 1 commit into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions web/src/locales/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
"iso": "ISO",
"taken-at": "Taken At",

"drag-and-drop-photos-here": "Drag and drop photos here",

"root.tab.convert": "Convert",
"root.tab.theme-settings": "Theme Settings",
"root.tab.export-settings": "Export Settings",
Expand Down
2 changes: 2 additions & 0 deletions web/src/locales/translations/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
"iso": "ISO感度",
"taken-at": "撮影日時",

"drag-and-drop-photos-here": "写真をここにドラッグ&ドロップ",

"root.tab.convert": "変換",
"root.tab.theme-settings": "テーマ設定",
"root.tab.export-settings": "エクスポート設定",
Expand Down
2 changes: 2 additions & 0 deletions web/src/locales/translations/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
"iso": "ISO",
"taken-at": "촬영 일시",

"drag-and-drop-photos-here": "사진을 여기에 끌어다 놓거나 여기를 클릭하여 사진을 불러옵니다.",

"root.tab.convert": "프레임 씌우기",
"root.tab.theme-settings": "테마 설정",
"root.tab.export-settings": "내보내기 설정",
Expand Down
99 changes: 99 additions & 0 deletions web/src/pages/convert/components/add-photo.drag-in-drop.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { ChangeEvent } from 'react';
import Photo from '../../../core/photo';
import { useStore } from '../../../store';
import DragInDropIcon from '../../../icons/drag-in-drop.icon';
import { t } from 'i18next';

const AddPhotoDragInDrop = () => {
const { photos, setPhotos, setLoading, setOpenedAddPhotoErrorDialog, darkMode } = useStore();

const onDragEnter = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
};

const onDragLeave = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
};

const onDragOver = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
};

const onDrop = async (e: React.DragEvent<HTMLDivElement>) => {
setLoading(true);
e.preventDefault();
e.stopPropagation();
const { files } = e.dataTransfer;
if (!files) return;
try {
await Promise.all(Array.from(files).map(Photo.create)).then((newPhotos) => {
setPhotos([...photos, ...newPhotos]);
});
} catch (e) {
console.error(e);
setOpenedAddPhotoErrorDialog(true);
}
setLoading(false);
};

const onChange = async (event: ChangeEvent<HTMLInputElement>) => {
setLoading(true);
await new Promise((resolve) => setTimeout(resolve, 100));
const { files } = event.target;
if (!files) return;
try {
await Promise.all(Array.from(files).map(Photo.create)).then((newPhotos) => {
setPhotos([...photos, ...newPhotos]);
});
} catch (e) {
console.error(e);
setOpenedAddPhotoErrorDialog(true);
}
setLoading(false);
};

return (
<>
<input type="file" accept="image/*" onChange={onChange} onClick={(e) => (e.currentTarget.value = '')} multiple hidden />

<div
style={{
cursor: 'pointer',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
height: '20rem',
border: `2px dashed ${darkMode ? '#fff' : '#000'}`,
borderRadius: '0.5rem',
margin: '32px',
}}
onDragEnter={onDragEnter}
onDragLeave={onDragLeave}
onDragOver={onDragOver}
onDrop={onDrop}
onClick={() => {
const input: HTMLInputElement | null = document.querySelector('input[type="file"]');
if (input) input.click();
}}
>
<DragInDropIcon size={48} />
<div
style={{
fontSize: '1rem',
color: darkMode ? '#fff' : '#000',
marginTop: '1rem',
}}
className="text-center"
>
{t('drag-and-drop-photos-here')}
</div>
</div>
</>
);
};

export default AddPhotoDragInDrop;
3 changes: 3 additions & 0 deletions web/src/pages/convert/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import SettingsIcon from '../../icons/settings.icon';
import ImageIcon from '../../icons/image.icon';
import GenerateIcon from '../../icons/generate.icon';
import AddPhotoErrorDialog from './components/add-photo-error.dialog';
import AddPhotoDragInDrop from './components/add-photo.drag-in-drop';

const FramePage = () => {
const { t } = useTranslation();
Expand All @@ -27,6 +28,8 @@ const FramePage = () => {
<DownloadAllPhotoButton />
</Toolbar>

{photos.length === 0 && <AddPhotoDragInDrop />}

{photos.length !== 0 && (
<BlockTitle>
{t('root.loaded-photos')}
Expand Down