-
Notifications
You must be signed in to change notification settings - Fork 0
/
photo-tab.js
105 lines (94 loc) · 2.82 KB
/
photo-tab.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
const LS_KEY = "photo-cache-v2020.1.0";
const getPhotoCache = () => {
const raw = localStorage.getItem(LS_KEY);
if (raw) {
return JSON.parse(raw);
} else {
return null;
}
};
const preloadNextPhoto = (photo) => {
document.querySelector("#next-photo").src = photo.url;
};
const updatePhotoCache = (photos) => {
if (photos.length === 0) {
localStorage.removeItem(LS_KEY);
} else {
preloadNextPhoto(photos[0]);
console.log(`loaded ${photos.length} new photos into cache`);
localStorage.setItem(LS_KEY, JSON.stringify(photos));
}
};
const withPopulatedCache = () => {
const cache = getPhotoCache();
if (!cache || cache.length === 0) {
return loadPhotos().then((photos) => {
updatePhotoCache(photos);
return photos;
});
} else {
return Promise.resolve(cache);
}
};
const withNextPhoto = () => {
return withPopulatedCache().then((photos) => {
const photo = photos.shift();
updatePhotoCache(photos);
return photo;
});
};
const extractPhotoAttrs = (child) => {
const { name, url, title, permalink, author, stickied } = child.data;
return {
name, // name is the unique id
url,
title,
author,
permalink: `https://www.reddit.com${permalink}`,
stickied, // sticky posts are announcements, not photos
};
};
const filterOutHugePhotos = (photos) => {
return Promise.all(
photos.map((photo) => {
const { url } = photo;
return fetch(url, { method: "head", mode: "no-cors" })
.then((response) => {
if (response.status !== 200) {
throw new Error(
`Unexpected response HEAD ${url}: HTTP ${response.status}`
);
}
const sizeInBytes = response.headers.get("content-length") || -1;
return Object.assign({}, photo, { sizeInBytes });
})
.catch((err) => {
console.error(`Error looking up size of image at ${url}`, err);
return null;
});
})
).then((photos) => photos.filter((p) => p && p.sizeInBytes < 6000000));
};
const loadPhotos = () => {
return fetch("https://www.reddit.com/r/earthporn.json")
.then(function (response) {
if (response.status !== 200) {
throw new Error(
`Unexpected response from Reddit: HTTP ${response.status}`
);
}
return response.json();
})
.then(({ data }) =>
data.children.map(extractPhotoAttrs).filter((photo) => !photo.stickied)
)
.then((photos) => filterOutHugePhotos(photos));
};
const showPhoto = ({ url, title, permalink, author }) => {
document.querySelector("#photo").src = url;
document.querySelector("#title").innerText = title;
document.querySelector("#title").href = permalink;
document.querySelector("#author").innerText = author;
};
const onNewTab = () => withNextPhoto().then((p) => showPhoto(p));
onNewTab();