tangled
alpha
login
or
join now
vt3e.cat
/
www
2
fork
atom
this repo has no descr,ription
vt3e.cat
2
fork
atom
overview
issues
pulls
pipelines
feat: queue image loads
vt3e.cat
3 weeks ago
a700e88b
a803a33f
verified
This commit was signed with the committer's
known signature
.
vt3e.cat
SSH Key Fingerprint:
SHA256:MaVgF6bXxDdD131G4rXizPh+sttp3IVsdPrj48HV0X0=
+76
-3
2 changed files
expand all
collapse all
unified
split
pkgs
web
src
components
Gallery
GalleryItem.vue
utils
imageLoadQueue.ts
+12
-3
pkgs/web/src/components/Gallery/GalleryItem.vue
···
5
5
import { CatVt3eGalleryImage } from '@vt3e/gallery'
6
6
7
7
import { DID } from '@/utils/links'
8
8
+
import { enqueueLoad } from '@/utils/imageLoadQueue'
8
9
9
10
const props = defineProps<{
10
11
item: CatVt3eGalleryImage.Main
···
20
21
return props.item.width / props.item.height
21
22
})
22
23
24
24
+
const cid = computed(() =>
25
25
+
isLegacyBlob(props.item.image) ? props.item.image.cid : props.item.image.ref.$link,
26
26
+
)
27
27
+
23
28
const blobUrl = computed(() => {
24
29
const parts = [
25
30
'https://pds.vt3e.cat/xrpc/com.atproto.sync.getBlob',
26
31
`?did=${DID}`,
27
27
-
`&cid=${isLegacyBlob(props.item.image) ? props.item.image.cid : props.item.image.ref.$link}`,
32
32
+
`&cid=${cid.value}`,
28
33
]
29
34
return parts.join('')
30
35
})
31
36
37
37
+
const shortLabel = computed(() => cid.value.slice(0, 12))
38
38
+
32
39
const blurhashData = computed(() => {
33
40
if (!props.item.blurhash) return null
34
41
try {
···
86
93
}
87
94
}
88
95
96
96
+
let cancelQueue: (() => void) | null = null
89
97
let observer: IntersectionObserver | null = null
90
98
91
99
onMounted(() => {
···
94
102
observer = new IntersectionObserver(
95
103
(entries) => {
96
104
if (entries[0]?.isIntersecting) {
97
97
-
loadImage()
105
105
+
cancelQueue = enqueueLoad(shortLabel.value, loadImage)
98
106
observer?.disconnect()
99
107
}
100
108
},
···
106
114
107
115
onUnmounted(() => {
108
116
observer?.disconnect()
117
117
+
cancelQueue?.()
109
118
if (imageUrl.value) URL.revokeObjectURL(imageUrl.value)
110
119
})
111
120
</script>
···
141
150
border-radius: 0.75rem;
142
151
overflow: hidden;
143
152
background-color: hsla(var(--surface0) / 0.5);
144
144
-
transform: translateZ(0); /* try to force hardware accel */
153
153
+
transform: translateZ(0);
145
154
146
155
&:hover {
147
156
filter: brightness(1.1);
+64
pkgs/web/src/utils/imageLoadQueue.ts
···
1
1
+
const MAX_CONCURRENT = 1;
2
2
+
3
3
+
type LoadFn = () => Promise<void>;
4
4
+
interface QueueEntry {
5
5
+
label: string;
6
6
+
load: LoadFn;
7
7
+
cancelled: boolean;
8
8
+
}
9
9
+
10
10
+
const pending: QueueEntry[] = [];
11
11
+
let activeCount = 0;
12
12
+
13
13
+
const status = () => `(active: ${activeCount}, pending: ${pending.length})`;
14
14
+
15
15
+
function processNext() {
16
16
+
while (activeCount < MAX_CONCURRENT) {
17
17
+
const entry = pending.shift();
18
18
+
if (!entry) break;
19
19
+
20
20
+
if (entry.cancelled) {
21
21
+
console.debug("[gallery-queue] skip (cancelled):", entry.label);
22
22
+
continue;
23
23
+
}
24
24
+
25
25
+
activeCount++;
26
26
+
console.groupCollapsed(`[gallery-queue] ${entry.label}`);
27
27
+
console.debug("started", status());
28
28
+
console.groupEnd();
29
29
+
30
30
+
entry
31
31
+
.load()
32
32
+
.then(() => {
33
33
+
console.groupCollapsed(`[gallery-queue] ✓ ${entry.label}`);
34
34
+
console.debug("completed", status());
35
35
+
console.groupEnd();
36
36
+
})
37
37
+
.catch((err) => {
38
38
+
console.group(`[gallery-queue] ✗ ${entry.label}`);
39
39
+
console.warn("failed", err);
40
40
+
console.debug(status());
41
41
+
console.groupEnd();
42
42
+
})
43
43
+
.finally(() => {
44
44
+
activeCount--;
45
45
+
processNext();
46
46
+
});
47
47
+
}
48
48
+
}
49
49
+
50
50
+
export function enqueueLoad(label: string, load: LoadFn): () => void {
51
51
+
const entry: QueueEntry = { label, load, cancelled: false };
52
52
+
pending.push(entry);
53
53
+
54
54
+
console.groupCollapsed(`[gallery-queue] + ${entry.label}`);
55
55
+
console.debug("enqueued", status());
56
56
+
console.groupEnd();
57
57
+
58
58
+
processNext();
59
59
+
60
60
+
return () => {
61
61
+
entry.cancelled = true;
62
62
+
console.debug(`[gallery-queue] − ${entry.label} (cancelled)`);
63
63
+
};
64
64
+
}