Skip to content

Commit

Permalink
add lightbox and open image in new tab (closes #5)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucaorio committed Dec 23, 2022
1 parent 7bba5b1 commit 0f8b47e
Show file tree
Hide file tree
Showing 13 changed files with 2,730 additions and 335 deletions.
File renamed without changes.
1,718 changes: 1,547 additions & 171 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"@typescript-eslint/parser": "^5.2.0",
"builtin-modules": "^3.2.0",
"esbuild": "0.13.12",
"lightgallery": "^2.7.0",
"obsidian": "latest",
"tslib": "2.3.1",
"typescript": "^4.4.4"
Expand Down
38 changes: 38 additions & 0 deletions src/build-horizontal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const buildHorizontal = (
container: HTMLElement,
imagesList: {[key: string]: any},
settings: {[key: string]: any}
) => {
// inject the gallery wrapper
const gallery = container.createEl('div')
gallery.addClass('grid-wrapper')
gallery.style.display = 'flex'
gallery.style.flexWrap = 'wrap'
gallery.style.marginRight = `-${settings.gutter}px`

// inject and style images
imagesList.forEach((file: {[key: string]: string}) => {
const figure = gallery.createEl('figure')
figure.addClass('grid-item')
figure.style.margin = `0px ${settings.gutter}px ${settings.gutter}px 0px`
figure.style.width = 'auto'
figure.style.height = `${settings.height}px`
figure.style.borderRadius = `${settings.radius}px`
figure.style.flex = '1 0 auto'
figure.style.overflow = 'hidden'
figure.setAttribute('data-name', file.name)
figure.setAttribute('data-folder', file.name)
figure.setAttribute('data-src', file.uri)

const img = figure.createEl('img')
img.style.objectFit = 'cover'
img.style.width = '100%'
img.style.height = '100%'
img.style.borderRadius = '0px'
img.src = file.uri
})

return gallery
}

export default buildHorizontal
47 changes: 47 additions & 0 deletions src/build-lightbox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { App, Platform } from 'obsidian'
import Lightbox from 'lightgallery';
import LightboxThumbs from 'lightgallery/plugins/thumbnail'

const lightbox = (gallery: HTMLElement, imagesList: {[key: string]: any}, app: App) => {
// attach a custom button to open original image, only on desktop
if (Platform.isDesktop) globalSearchBtn(gallery, imagesList)

// setup a lightbox for the gallery
const galleryLightbox = Lightbox(gallery, {
plugins: [LightboxThumbs],
counter: false,
download: false,
thumbnail: true,
loop: false,
mode: 'lg-fade',
// todo: replace with GPLv3 compatible license whenever available
licenseKey: '1234-1234-123-1234',
})

// if we are on mobile, make sure to remove unnecessary controls
if (Platform.isIosApp || Platform.isAndroidApp) {
const elements:NodeListOf<HTMLElement> = document.querySelectorAll('.lg-close, .lg-prev, .lg-next')
for (const element of elements) {
element.style.display = 'none'
}
}

return galleryLightbox
}

const globalSearchBtn = (gallery: HTMLElement, imagesList: {[key: string]: any}) => {
gallery.addEventListener('lgInit', (event: CustomEvent) => {
const galleryInstance = event.detail.instance
const btn ='<button type="button" id="btn-glob-search" class="lg-icon btn-glob-search"></button>'
galleryInstance.outer.find('.lg-toolbar').append(btn)

galleryInstance.outer.find('#btn-glob-search').on('click', () => {
const index = galleryInstance.index
const selected = imagesList[index]
app.workspace.openLinkText(selected.name, selected.folder, true, {active: true})
galleryInstance.closeGallery()
});
})
}

export default lightbox
32 changes: 32 additions & 0 deletions src/build-vertical.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const buildVertical = (
container: HTMLElement,
imagesList: {[key: string]: any},
settings: {[key: string]: any}
) => {
// inject the gallery wrapper
const gallery = container.createEl('div')
gallery.addClass('grid-wrapper')
gallery.style.lineHeight = '0px'
gallery.style.columnCount = `${settings.columns}`
gallery.style.columnGap = `${settings.gutter}px`

// inject and style images
imagesList.forEach((file: {[key: string]: string}) => {
const figure = gallery.createEl('div')
figure.addClass('grid-item')
figure.style.marginBottom = `${settings.gutter}px`
figure.style.width = '100%'
figure.style.height = 'auto'
figure.setAttribute('data-name', file.name)
figure.setAttribute('data-folder', file.name)
figure.setAttribute('data-src', file.uri)

const img = figure.createEl('img')
img.style.borderRadius = `${settings.radius}px`
img.src = file.uri
})

return gallery
}

export default buildVertical
46 changes: 46 additions & 0 deletions src/get-imgs-list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { App, TFolder, TFile } from 'obsidian'
import renderError from './render-error'

const getImagesList = (
app: App,
container: HTMLElement,
settings: {[key: string]: any}
) => {
// retrieve a list of the files
const folder = app.vault.getAbstractFileByPath(settings.path)

let files
if (folder instanceof TFolder) { files = folder.children }
else {
const error = 'The folder doesn\'t exist, or it\'s empty!'
renderError(container, error)
throw new Error(error)
}

// filter the list of files to make sure we're dealing with images only
const validExtensions = ["jpeg", "jpg", "gif", "png", "webp", "tiff", "tif"]
const images = files.filter(file => {
if (file instanceof TFile && validExtensions.includes(file.extension)) return file
})

// sort the list by name, mtime, or ctime
const orderedImages = images.sort((a: any, b: any) => {
const refA = settings.sortby === 'name' ? a['name'].toUpperCase() : a.stat[settings.sortby]
const refB = settings.sortby === 'name' ? b['name'].toUpperCase() : b.stat[settings.sortby]
return (refA < refB) ? -1 : (refA > refB) ? 1 : 0
})

// re-sort again by ascending or descending order
const sortedImages = settings.sort === 'asc' ? orderedImages : orderedImages.reverse()

// return an array of objects
return sortedImages.map(file => {
return {
name: file.name,
folder: file.parent.path,
uri: app.vault.adapter.getResourcePath(file.path)
}
})
}

export default getImagesList
52 changes: 52 additions & 0 deletions src/get-settings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { normalizePath, parseYaml, Platform } from 'obsidian'
import renderError from './render-error'

const getSettings = (src: string, container: HTMLElement) => {
// parse the settings from the code block
const settingsSrc: any = parseYaml(src)

// check for required settings
if (settingsSrc === undefined) {
const error = 'Cannot parse YAML!'
renderError(container, error)
throw new Error(error)
}

if (!settingsSrc.path) {
const error = 'Please specify a path!'
renderError(container, error)
throw new Error(error)
}

// store settings, normalize and set sensible defaults
const settings = {
path: undefined as string,
type: undefined as string,
radius: undefined as number,
gutter: undefined as string,
sortby: undefined as string,
sort: undefined as string,
mobile: undefined as number,
columns: undefined as number,
height: undefined as number,
}

settings.path = normalizePath(settingsSrc.path)
settings.type = settingsSrc.type ?? 'horizontal'
settings.radius = settingsSrc.radius ?? 0
settings.gutter = settingsSrc.gutter ?? 8
settings.sortby = settingsSrc.sortby ?? 'ctime'
settings.sort = settingsSrc.sort ?? 'desc'

// settings for vertical mansory only
settings.mobile = settingsSrc.mobile ?? 1
if (Platform.isDesktop) settings.columns = settingsSrc.columns ?? 3
else settings.columns = settings.mobile

// settings for horizontal mansory only
settings.height = settingsSrc.height ?? 260

return settings
}

export default getSettings
162 changes: 0 additions & 162 deletions src/img-gallery-renderer.ts

This file was deleted.

Loading

0 comments on commit 0f8b47e

Please sign in to comment.