From 1d5ca69701bd6d1060202ab663142c50359532b5 Mon Sep 17 00:00:00 2001
From: viktorstrate <viktorstrate@gmail.com>
Date: Thu, 18 Jul 2019 22:33:18 +0200
Subject: [PATCH] Layout and scanner improvements

---
 api/package.json                    |  4 ++-
 api/src/Scanner.js                  | 29 ++++++++++++++-----
 ui/src/Layout.js                    | 45 +++++++++++++++++++++++++----
 ui/src/Pages/AlbumPage/AlbumPage.js | 11 ++++---
 ui/src/Pages/HomePage/Albums.js     | 15 ++++++++--
 ui/src/Pages/HomePage/HomePage.js   |  2 +-
 6 files changed, 83 insertions(+), 23 deletions(-)

diff --git a/api/package.json b/api/package.json
index 8456587..8490665 100644
--- a/api/package.json
+++ b/api/package.json
@@ -30,12 +30,14 @@
     "fs-extra": "^8.1.0",
     "graphql-tag": "^2.10.1",
     "image-size": "^0.7.4",
-    "img-type": "^0.1.13",
+    "image-type": "^4.1.0",
+    "is-image": "^3.0.0",
     "jsonwebtoken": "^8.5.1",
     "lodash": "^4.17.14",
     "neo4j-driver": "^1.7.3",
     "neo4j-graphql-js": "^2.6.3",
     "node-fetch": "^2.3.0",
+    "read-chunk": "^3.2.0",
     "regenerator-runtime": "^0.13.2",
     "sharp": "^0.22.1",
     "uuid": "^3.3.2"
diff --git a/api/src/Scanner.js b/api/src/Scanner.js
index baa97e7..a6860d4 100644
--- a/api/src/Scanner.js
+++ b/api/src/Scanner.js
@@ -2,14 +2,31 @@ import fs from 'fs-extra'
 import path from 'path'
 import { resolve as pathResolve, basename as pathBasename } from 'path'
 import { PubSub } from 'apollo-server'
-import imgType from 'img-type'
 import uuid from 'uuid'
 import { exiftool } from 'exiftool-vendored'
 import sharp from 'sharp'
+import readChunk from 'read-chunk'
+import imageType from 'image-type'
 import config from './config'
 
 export const EVENT_SCANNER_PROGRESS = 'SCANNER_PROGRESS'
 
+const isImage = async path => {
+  const buffer = await readChunk(path, 0, 12)
+  const type = imageType(buffer)
+
+  return type != null
+}
+
+const isRawImage = async path => {
+  const buffer = await readChunk(path, 0, 12)
+  const { ext } = imageType(buffer)
+
+  const rawTypes = ['cr2', 'arw', 'crw', 'dng']
+
+  return rawTypes.includes(ext)
+}
+
 class PhotoScanner {
   constructor(driver) {
     this.driver = driver
@@ -146,7 +163,7 @@ class PhotoScanner {
           continue
         }
 
-        if (!foundImage && (await imgType.isImg(itemPath))) {
+        if (!foundImage && (await isImage(itemPath))) {
           foundImage = true
         }
       }
@@ -167,7 +184,7 @@ class PhotoScanner {
     for (const item of list) {
       const itemPath = pathResolve(path, item)
 
-      if (await imgType.isImg(itemPath)) {
+      if (await isImage(itemPath)) {
         const session = this.driver.session()
 
         const photoResult = await session.run(
@@ -217,13 +234,9 @@ class PhotoScanner {
     await fs.remove(imagePath)
     await fs.mkdirp(imagePath)
 
-    const type = await imgType.getType(photo.path)
-
     let resizeBaseImg = photo.path
 
-    const rawTypes = ['cr2', 'arw', 'crw', 'dng']
-
-    if (rawTypes.includes(type)) {
+    if (await isRawImage(photo.path)) {
       console.log('Processing RAW image')
 
       const extractedPath = path.resolve(imagePath, 'extracted.jpg')
diff --git a/ui/src/Layout.js b/ui/src/Layout.js
index d3b8dba..9a44d4d 100644
--- a/ui/src/Layout.js
+++ b/ui/src/Layout.js
@@ -1,5 +1,6 @@
 import React, { Component } from 'react'
 import styled from 'styled-components'
+import { Link } from 'react-router-dom'
 
 const Container = styled.div`
   height: 100%;
@@ -11,9 +12,9 @@ const LeftSidebar = styled.div`
   height: 100%;
   width: 80px;
   position: fixed;
-  top: 0;
+  top: 60px;
   left: 0;
-  background-color: #eee;
+  padding-top: 10px;
 `
 
 const RightSidebar = styled.div`
@@ -21,23 +22,55 @@ const RightSidebar = styled.div`
   width: 500px;
   position: fixed;
   right: 0;
-  top: 0;
-  background-color: #eee;
+  top: 60px;
+  background-color: white;
 `
 
 const Content = styled.div`
+  margin-top: 60px;
   margin-left: 80px;
   margin-right: 500px;
-  padding: 0 8px;
+  padding: 12px 8px 0;
+`
+
+const SideButton = styled(Link)`
+  border: 1px solid #eee;
+  text-align: center;
+  padding-top: 17px;
+  border-radius: 50%;
+  display: block;
+  width: 60px;
+  height: 60px;
+  margin: 10px;
+`
+
+const Header = styled.div`
+  height: 60px;
+  width: 100%;
+  position: fixed;
+  background: white;
+  top: 0;
+  /* border-bottom: 1px solid rgba(0, 0, 0, 0.1); */
+  box-shadow: 0 0 2px rgba(0, 0, 0, 0.3);
+`
+
+const Title = styled.h1`
+  font-size: 36px;
+  padding: 5px 12px;
 `
 
 class Layout extends Component {
   render() {
     return (
       <Container>
-        <LeftSidebar>Left</LeftSidebar>
+        <LeftSidebar>
+          <SideButton to="/">Albums</SideButton>
+        </LeftSidebar>
         <Content>{this.props.children}</Content>
         <RightSidebar>Right</RightSidebar>
+        <Header>
+          <Title>Photoview</Title>
+        </Header>
       </Container>
     )
   }
diff --git a/ui/src/Pages/AlbumPage/AlbumPage.js b/ui/src/Pages/AlbumPage/AlbumPage.js
index f54a784..45bc025 100644
--- a/ui/src/Pages/AlbumPage/AlbumPage.js
+++ b/ui/src/Pages/AlbumPage/AlbumPage.js
@@ -91,10 +91,13 @@ class AlbumPage extends Component {
             })
 
             return (
-              <Gallery>
-                {photos}
-                <PhotoFiller />
-              </Gallery>
+              <div>
+                <h1>{data.album.title}</h1>
+                <Gallery>
+                  {photos}
+                  <PhotoFiller />
+                </Gallery>
+              </div>
             )
           }}
         </Query>
diff --git a/ui/src/Pages/HomePage/Albums.js b/ui/src/Pages/HomePage/Albums.js
index 418bcd9..bf647a1 100644
--- a/ui/src/Pages/HomePage/Albums.js
+++ b/ui/src/Pages/HomePage/Albums.js
@@ -19,6 +19,13 @@ const getAlbumsQuery = gql`
   }
 `
 
+const Container = styled.div`
+  margin: -10px;
+  margin-top: 20px;
+  position: relative;
+  min-height: 500px;
+`
+
 const AlbumBoxLink = styled(Link)`
   width: 240px;
   height: 240px;
@@ -41,7 +48,7 @@ const AlbumBoxImage = styled.div`
 class Albums extends Component {
   render() {
     return (
-      <div style={{ position: 'relative', minHeight: '500px' }}>
+      <Container>
         <Query query={getAlbumsQuery}>
           {({ loading, error, data }) => {
             // if (loading) return <Loader active />
@@ -52,7 +59,9 @@ class Albums extends Component {
             if (data && data.myAlbums) {
               albums = data.myAlbums.map(album => (
                 <AlbumBoxLink key={album.id} to={`/album/${album.id}`}>
-                  <AlbumBoxImage image={album.photos[0].thumbnail.path} />
+                  <AlbumBoxImage
+                    image={album.photos[0] && album.photos[0].thumbnail.path}
+                  />
                   <p>{album.title}</p>
                 </AlbumBoxLink>
               ))
@@ -76,7 +85,7 @@ class Albums extends Component {
             )
           }}
         </Query>
-      </div>
+      </Container>
     )
   }
 }
diff --git a/ui/src/Pages/HomePage/HomePage.js b/ui/src/Pages/HomePage/HomePage.js
index 33b3ff3..3584896 100644
--- a/ui/src/Pages/HomePage/HomePage.js
+++ b/ui/src/Pages/HomePage/HomePage.js
@@ -6,7 +6,7 @@ class HomePage extends Component {
   render() {
     return (
       <Layout>
-        <h1>Home</h1>
+        <h1>Albums</h1>
         <Albums />
       </Layout>
     )
