From fa50031f0a74ff45cd745e8808119fbfb78ed3d4 Mon Sep 17 00:00:00 2001 From: Chuck Dries Date: Tue, 7 Mar 2023 21:49:27 -0800 Subject: [PATCH] WIP working on sorting recently published by capture date when published in batches --- gatsby-node.ts | 16 ++- scratchpad.js | 193 ++++++++++++++++++++++++++++++ src/components/MasonryGallery.tsx | 19 ++- src/components/Select.tsx | 2 +- src/gatsby-types.d.ts | 8 +- src/pages/photogallery.tsx | 50 +++++--- src/utils.ts | 50 ++++++-- 7 files changed, 293 insertions(+), 45 deletions(-) create mode 100644 scratchpad.js diff --git a/gatsby-node.ts b/gatsby-node.ts index 558d62e..82a96db 100644 --- a/gatsby-node.ts +++ b/gatsby-node.ts @@ -10,6 +10,10 @@ import sharp from "sharp"; import { Palette } from "node-vibrant/lib/color"; import { performance } from "perf_hooks"; +import util from 'node:util'; +import { exec as _exec } from "child_process"; +const exec = util.promisify(_exec) + // const path = require("path"); // const Vibrant = require("node-vibrant"); // const chroma = require("chroma-js"); @@ -114,7 +118,8 @@ function transformMetaToNodeData( metaData: Record, vibrantData: Palette, imagePath: string, - { r, g, b }: { r: number; b: number; g: number } + { r, g, b }: { r: number; b: number; g: number }, + datePublished: string, ) { const vibrant = vibrantData ? processColors(vibrantData, imagePath) : null; const vibrantHue = vibrantData.Vibrant!.getHsl()[0] * 360; @@ -131,6 +136,7 @@ function transformMetaToNodeData( } return { dateTaken: metaData.DateTimeOriginal, + datePublished, meta: { Make: metaData.Make, Model: metaData.Model, @@ -174,6 +180,11 @@ export const onCreateNode: GatsbyNode["onCreateNode"] = async function ({ const { createNodeField } = actions; if (node.internal.type === "File" && node.sourceInstanceName === "gallery") { + const { stdout: datePublished, stderr } = await exec(`git log --diff-filter=A --follow --format=%aI -1 -- ${node.absolutePath}`) + if (stderr.length) { + console.error('something went wrong checking publish date: ', stderr); + } + const metaData = await exifr.parse(node.absolutePath as string, { iptc: true, xmp: true, @@ -201,7 +212,8 @@ export const onCreateNode: GatsbyNode["onCreateNode"] = async function ({ metaData, vibrantData, node.absolutePath as string, - dominant + dominant, + datePublished ), }); } diff --git a/scratchpad.js b/scratchpad.js new file mode 100644 index 0000000..b60d075 --- /dev/null +++ b/scratchpad.js @@ -0,0 +1,193 @@ +a = { + ApplicationRecordVersion: '\x00\x04', + DateCreated: '2015-10-18T17:59:38', + TimeCreated: '175938', + DigitalCreationDate: '20151018', + DigitalCreationTime: '175938', + format: 'image/jpeg', + CreatorTool: 'Adobe Lightroom 5.4 (Macintosh)', + ModifyDate: '2022-07-09T21:16:39.000Z', + CreateDate: '2015-10-19T00:59:38.000Z', + MetadataDate: '2022-07-09T14:16:39-07:00', + Rating: 5, + LensInfo: [ 50, 50, 1.8, 1.8 ], + Lens: 'DT 50mm F1.8 SAM', + DocumentID: 'xmp.did:27795bf1-8bb2-49a0-807a-cf6150bd505b', + OriginalDocumentID: 'CE2B8F240393ADFDF9F092CF395C6632', + InstanceID: 'xmp.iid:27795bf1-8bb2-49a0-807a-cf6150bd505b', + History: [ + { action: 'derived', parameters: 'saved to new location' }, + { + action: 'saved', + instanceID: 'xmp.iid:27795bf1-8bb2-49a0-807a-cf6150bd505b', + when: '2022-07-09T14:16:39-07:00', + softwareAgent: 'Adobe Lightroom 5.4 (Macintosh)', + changed: '/' + } + ], + DerivedFrom: { + documentID: 'CE2B8F240393ADFDF9F092CF395C6632', + originalDocumentID: 'CE2B8F240393ADFDF9F092CF395C6632' + }, + good: true, + Version: 14.4, + ProcessVersion: 6.7, + WhiteBalance: 'Manual', + IncrementalTemperature: -11, + IncrementalTint: 23, + Exposure2012: 0, + Contrast2012: 6, + Highlights2012: 0, + Shadows2012: 0, + Whites2012: 35, + Blacks2012: -22, + Texture: 0, + Clarity2012: 0, + Dehaze: 0, + Vibrance: 0, + Saturation: 'Normal', + ParametricShadows: 0, + ParametricDarks: 0, + ParametricLights: 0, + ParametricHighlights: 0, + ParametricShadowSplit: 25, + ParametricMidtoneSplit: 50, + ParametricHighlightSplit: 75, + Sharpness: 'Normal', + LuminanceSmoothing: 0, + ColorNoiseReduction: 0, + HueAdjustmentRed: 0, + HueAdjustmentOrange: 0, + HueAdjustmentYellow: 0, + HueAdjustmentGreen: 0, + HueAdjustmentAqua: 0, + HueAdjustmentBlue: 0, + HueAdjustmentPurple: 0, + HueAdjustmentMagenta: 0, + SaturationAdjustmentRed: 0, + SaturationAdjustmentOrange: 0, + SaturationAdjustmentYellow: 0, + SaturationAdjustmentGreen: 0, + SaturationAdjustmentAqua: 0, + SaturationAdjustmentBlue: 0, + SaturationAdjustmentPurple: 0, + SaturationAdjustmentMagenta: 0, + LuminanceAdjustmentRed: 0, + LuminanceAdjustmentOrange: 0, + LuminanceAdjustmentYellow: 0, + LuminanceAdjustmentGreen: 0, + LuminanceAdjustmentAqua: 0, + LuminanceAdjustmentBlue: 0, + LuminanceAdjustmentPurple: 0, + LuminanceAdjustmentMagenta: 0, + SplitToningShadowHue: 0, + SplitToningShadowSaturation: 0, + SplitToningHighlightHue: 0, + SplitToningHighlightSaturation: 0, + SplitToningBalance: 0, + ColorGradeMidtoneHue: 0, + ColorGradeMidtoneSat: 0, + ColorGradeShadowLum: 0, + ColorGradeMidtoneLum: 0, + ColorGradeHighlightLum: 0, + ColorGradeBlending: 50, + ColorGradeGlobalHue: 0, + ColorGradeGlobalSat: 0, + ColorGradeGlobalLum: 0, + AutoLateralCA: 0, + LensProfileEnable: 0, + LensManualDistortionAmount: 0, + VignetteAmount: 0, + DefringePurpleAmount: 0, + DefringePurpleHueLo: 30, + DefringePurpleHueHi: 70, + DefringeGreenAmount: 0, + DefringeGreenHueLo: 40, + DefringeGreenHueHi: 60, + PerspectiveUpright: 0, + PerspectiveVertical: 0, + PerspectiveHorizontal: 0, + PerspectiveRotate: 0, + PerspectiveAspect: 0, + PerspectiveScale: 100, + PerspectiveX: 0, + PerspectiveY: 0, + GrainAmount: 0, + PostCropVignetteAmount: 0, + ShadowTint: 0, + RedHue: 0, + RedSaturation: 0, + GreenHue: 0, + GreenSaturation: 0, + BlueHue: 0, + BlueSaturation: 0, + ConvertToGrayscale: false, + OverrideLookVignette: false, + ToneCurveName2012: 'Linear', + CameraProfile: 'Embedded', + CameraProfileDigest: '54650A341B5B5CCAE8442D0B43A92BCE', + HasSettings: true, + CropTop: 0, + CropLeft: 0, + CropBottom: 1, + CropRight: 1, + CropAngle: 0, + CropConstrainToWarp: 0, + HasCrop: false, + AlreadyApplied: true, + ToneCurvePV2012: [ '0, 0', '255, 255' ], + ToneCurvePV2012Red: [ '0, 0', '255, 255' ], + ToneCurvePV2012Green: [ '0, 0', '255, 255' ], + ToneCurvePV2012Blue: [ '0, 0', '255, 255' ], + Make: 'SONY', + Model: 'SLT-A55V', + XResolution: 240, + YResolution: 240, + ResolutionUnit: 'inches', + Software: 'Adobe Lightroom 5.4 (Macintosh)', + ExposureTime: 0.01, + FNumber: 1.8, + ExposureProgram: 'Manual', + ISO: 200, + SensitivityType: 2, + RecommendedExposureIndex: 200, + ExifVersion: '2.3.1', + DateTimeOriginal: '2015-10-19T00:59:38.000Z', + OffsetTime: '-07:00', + ShutterSpeedValue: 6.643856, + ApertureValue: 1.695994, + BrightnessValue: 3, + ExposureCompensation: 0, + MaxApertureValue: 1.7, + MeteringMode: 'Pattern', + LightSource: 'Cloudy weather', + Flash: 'Flash did not fire, compulsory flash mode', + FocalLength: 50, + ColorSpace: 1, + FileSource: 'Digital Camera', + SceneType: 'Directly photographed', + CustomRendered: 'Normal', + ExposureMode: 'Manual', + FocalLengthIn35mmFormat: 75, + SceneCaptureType: 'Standard', + Contrast: 'Normal', + LensModel: 'DT 50mm F1.8 SAM', + GPSVersionID: '2.2.0.0', + GPSLatitudeRef: 'N', + GPSLatitude: [ 33, 25.7121, 0 ], + GPSLongitudeRef: 'W', + GPSLongitude: [ 111, 55.57122, 0 ], + GPSAltitude: 354.7, + GPSTimeStamp: '19:2:7', + GPSStatus: 'V', + GPSMeasureMode: '3', + GPSSpeedRef: 'K', + GPSSpeed: 33.8, + GPSTrackRef: 'T', + GPSTrack: 0.36, + GPSMapDatum: 'WGS-84', + GPSDateStamp: '2015:10:09', + GPSDifferential: 0, + latitude: 33.428535, + longitude: -111.926187 +} \ No newline at end of file diff --git a/src/components/MasonryGallery.tsx b/src/components/MasonryGallery.tsx index 269c5c1..ac3d1d1 100644 --- a/src/components/MasonryGallery.tsx +++ b/src/components/MasonryGallery.tsx @@ -30,7 +30,7 @@ interface MasonryGalleryProps { } const MasonryGallery = ({ - images, + images: _images, aspectsByBreakpoint: aspectTargetsByBreakpoint, debugHue, debugRating, @@ -59,8 +59,8 @@ const MasonryGallery = ({ }px)`; const aspectRatios = React.useMemo( - () => R.map(getAspectRatio, images).filter(Boolean), - [images] + () => R.map(getAspectRatio, _images).filter(Boolean), + [_images] ) as number[]; const targetAspect = aspectTargetsByBreakpoint[breakpoint]; @@ -87,10 +87,7 @@ const MasonryGallery = ({ } // no-op instead of starting a new row if (singleRow) { - return [ - ...acc, - currentRow, - ] + return [currentRow]; } // start a new row return [ @@ -107,14 +104,16 @@ const MasonryGallery = ({ ), R.indexBy(R.prop("startIndex")) )(aspectRatios), - [aspectRatios, targetAspect] + [aspectRatios, targetAspect, singleRow] ); const sortedImageList = React.useMemo( - () => images.map((image) => image.base), - [images] + () => _images.map((image) => image.base), + [_images] ); + const images = singleRow ? _images.slice(0, rows[0].images) : _images; + let cursor = 0; return (
(props: AriaSelectProps) {
-

Recently updated

+

+ Recently published +

) => { "2xl": 6.1, "3xl": 8, }} - images={data.recents.nodes} + images={recents} singleRow />
-

All images

+

+ All images +

) => { selectedKey={sortKey} > Curated - Date Updated + Date published Date taken Hue
- ) => { filterKeyword, }} showPalette={showPalette} - /> + /> */} ); }; @@ -292,7 +304,7 @@ export const query = graphql` query GalleryPageQuery { recents: allFile( filter: { sourceInstanceName: { eq: "gallery" } } - sort: { fields: { imageMeta: { meta: { ModifyDate: DESC } } } } + sort: { fields: { imageMeta: { datePublished: DESC } } } limit: 7 ) { ...GalleryImageFile @@ -307,7 +319,6 @@ export const query = graphql` fragment GalleryImageFile on FileConnection { nodes { - relativePath base childImageSharp { fluid { @@ -324,6 +335,7 @@ export const query = graphql` vibrantHue dominantHue dateTaken + datePublished meta { Keywords Rating diff --git a/src/utils.ts b/src/utils.ts index bb93290..89be968 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,18 +1,23 @@ +import React from "react"; + +import { pathOr } from "ramda"; // import kebabCase from 'lodash/kebabCase'; -import React from "react"; import { HomepageImage } from "./pages"; import { GalleryImage } from "./pages/photogallery"; -export const getMeta = (image: T) => image.fields?.imageMeta; +export const getMeta = (image: T) => + image.fields?.imageMeta; export const getName = (image: GalleryImage) => -image.fields?.imageMeta?.meta?.ObjectName || image.base; + image.fields?.imageMeta?.meta?.ObjectName || image.base; // some pleasing default colors for SSR and initial hydration -export const getVibrant = (image: GalleryImage | HomepageImage) => getMeta(image)?.vibrant; +export const getVibrant = (image: GalleryImage | HomepageImage) => + getMeta(image)?.vibrant; -export const hasName = (image: GalleryImage) => Boolean(image.fields?.imageMeta?.meta?.ObjectName); +export const hasName = (image: GalleryImage) => + Boolean(image.fields?.imageMeta?.meta?.ObjectName); export const getAspectRatio = (image: GalleryImage | HomepageImage): number => image.childImageSharp?.fluid?.aspectRatio ?? 1; @@ -25,7 +30,10 @@ export const getCanonicalSize = (image: GalleryImage) => ({ export const getRgba = (palette: string[], alpha: number) => `rgba(${palette[0]}, ${palette[1]}, ${palette[2]}, ${alpha || 1})`; -export const getVibrantStyle = (vibrant: Queries.FileFieldsImageMetaVibrant, screenHeight?: number) => ({ +export const getVibrantStyle = ( + vibrant: Queries.FileFieldsImageMetaVibrant, + screenHeight?: number +) => ({ "--muted": vibrant.Muted, "--dark-muted": vibrant.DarkMuted, "--light-muted": vibrant.LightMuted, @@ -40,10 +48,12 @@ export const getHelmetSafeBodyStyle = (style: React.CSSProperties) => { if (typeof window === "undefined") { return style; } - return Object.keys(style) - // @ts-ignore - .map((key) => `${key}: ${style[key]};`) - .join(""); + return ( + Object.keys(style) + // @ts-ignore + .map((key) => `${key}: ${style[key]};`) + .join("") + ); }; const gcd = (a: number, b: number): number => { @@ -94,7 +104,10 @@ interface galleryPageUrlProps { sortKey: string; } -export const getGalleryPageUrl = ({ keyword, sortKey }: galleryPageUrlProps, hash: string) => { +export const getGalleryPageUrl = ( + { keyword, sortKey }: galleryPageUrlProps, + hash: string +) => { const url = new URL( `${ typeof window !== "undefined" @@ -121,3 +134,18 @@ export const getGalleryPageUrl = ({ keyword, sortKey }: galleryPageUrlProps, has } return url.href.toString().replace(url.origin, ""); }; + +export function compareDates( + date_path: readonly string[], + left: T, + right: T +): number { + const d1 = pathOr("", date_path, left); + console.log("🚀 ~ file: utils.ts:129 ~ d1:", d1); + const date1 = new Date(d1); + console.log("🚀 ~ file: utils.ts:146 ~ new Date(d1):", new Date(d1)) + console.log("🚀 ~ file: utils.ts:133 ~ date1:", date1); + const date2 = new Date(pathOr("", date_path, right)); + const diff = -1 * (date1.getTime() - date2.getTime()); + return diff; +}