photopod

PhotoPod

PhotoPod stores, organises and views your photos and videos in your own Solid Pod. Everything lives under photopod/data/ on your own server, in ordinary image and video files that any other Solid application can read.

Sections

The navigation rail down the left hand side offers four ways to look at the same album.

Features

Storage

Photos and videos are written under photopod/data/ through solidpod’s writePod, the same way every app in this family stores its data: the content is encrypted, wrapped in Turtle and given an access control list. A photo added as beach.jpg is stored as beach.jpg.enc.ttl alongside beach.jpg.enc.ttl.acl, and PhotoPod shows the name without the suffix.

Storing media this way keeps it visible to the shared Solid file browsers, which list only .ttl resources, and gives each file the access control list that sharing works through. The cost is that a thumbnail cannot be read without decrypting the photo first, so thumbnails are cached in memory and fetched only for the page on screen.

Favourites and albums are small unencrypted JSON files of Pod-relative paths. Favourites lives in photopod/data/favourites.json; each album is a file of its own in photopod/data/albums/, named after the album, so there are exactly as many albums as files there. The Library hides the albums folder.

Reading still copes with a plain, unencrypted resource, so anything already in the album, or put there by another tool, stays visible.

Resource names

A name on the Pod may hold only letters, digits and - _ . ! ~ ' ( ). A file added from this device has anything else — a space, an accent, a character outside the Latin alphabet — replaced with an underscore, and PhotoPod says which files it renamed on the way in. A folder name typed into a dialogue is refused rather than quietly changed.

The restriction is not cosmetic. solidpod files a resource’s encryption key under a URL it rebuilds from the resource’s own URL, and the two halves of that round trip disagree about escaping: the path is taken out of the URL with Uri.pathSegments, which decodes each segment, and the URL is put back together by joining the segments verbatim, which does not encode them again. A photo stored as my%20photo.jpg.enc.ttl therefore has its key filed under .../my photo.jpg.enc.ttl, where nothing ever looks for it, and the key file is left holding a subject IRI with a raw space in it — which is not valid Turtle, and which costs every key written after it when that file is next read back. Keeping every name inside the unescaped set makes the round trip the identity, and the problem disappears.

The hearts live in photopod/data/favourites.json, a small list of the Pod-relative paths that carry one. It is deliberately not encrypted: asking for the security key merely to find out which photos are favourites would put a password prompt in front of an album that may hold nothing yet, and the file names it holds are already plain to see in the container listing.

Photo details and the map

The size, dates and address of a file come from the Solid server. The dimensions, the camera, the exposure and the coordinates come from the photo’s own EXIF block, which means the file has to be fetched, decrypted and decoded before any of it is known.

That decode is the same one that produces the grid thumbnail, and both results are cached together, so a photo already looked at in the Library costs nothing to describe or to place on the map, and vice versa.

The Favourites, Videos and Maps sections are views over the whole album rather than over one folder, so they walk the folders once and share the result. The walk stops after 400 folders or 12 levels, and says so when it has.

Sample album

PhotoPod does not ask anyone to log in before they can look around. A visitor goes straight into the app and finds every section filled with a sample album bundled in assets/demo/:

Every sample photo is from Wikimedia Commons and is in the public domain or released under CC0, so none needs attribution. The video is the authors’ own.

Nothing in the sample album is stored in a Pod, so adding, deleting, renaming and sharing ask the visitor to log in instead. Logging in, from the banner above each section or from the profile menu, replaces the samples with the user’s own album.

Getting started

flutter pub get
flutter run

Before submitting a pull request:

make prep