Skip to content

Commit f3bd7f7

Browse files
committed
🐛 Fix scrolling
1 parent fb42266 commit f3bd7f7

File tree

2 files changed

+46
-51
lines changed

2 files changed

+46
-51
lines changed

pages/episode/[id].vue

Lines changed: 44 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ const displayCount = ref(10);
1818
const sentinel = ref<HTMLElement | null>(null);
1919
let observer: IntersectionObserver;
2020
const imageRefs = ref<HTMLElement[]>([]);
21-
const isFirstSave = ref(true);
2221
2322
const {data: episode} = await useAsyncData<EpisodeWithProgression>(
2423
`episode-${id}`,
@@ -30,7 +29,6 @@ const {data: images} = await useAsyncData<string[]>(
3029
3130
const token = useCookie("token").value;
3231
const {data: currentProgression} = await useAsyncData<number>(`progression-${id}`, async() => {
33-
// TODO: Implement local storage saving
3432
if(!token) return 0;
3533
try{
3634
const progression = await $fetch<Progression>(`${serverUrl.value}/user/progression/episode/${id}`, {
@@ -41,7 +39,6 @@ const {data: currentProgression} = await useAsyncData<number>(`progression-${id}
4139
displayCount.value += progression.progression;
4240
return progression.progression;
4341
}catch{
44-
firstTimeScroll.value = true;
4542
return 0;
4643
}
4744
}, {server: false});
@@ -54,34 +51,6 @@ const hasMore = computed(() => {
5451
return images.value && displayCount.value < images.value.length;
5552
});
5653
57-
onMounted(() => {
58-
setTimeout(() => {
59-
if(!currentProgression.value && currentProgression.value <= 0)
60-
return;
61-
triggerScroll(currentProgression.value);
62-
}, 100);
63-
observer = new IntersectionObserver((entries) => {
64-
if (entries[0].isIntersecting && hasMore.value){
65-
displayCount.value += 10;
66-
}
67-
}, {
68-
root: document.querySelector(".flex-1"),
69-
rootMargin: "100px 0px"
70-
});
71-
72-
watchEffect(() => {
73-
if (sentinel.value && hasMore.value){
74-
observer.observe(sentinel.value);
75-
} else if (sentinel.value){
76-
observer.unobserve(sentinel.value);
77-
}
78-
});
79-
80-
onBeforeUnmount(() => {
81-
observer.disconnect();
82-
});
83-
});
84-
8554
async function saveProgressionAPI(progress: number){
8655
if(progress <= 0)
8756
return;
@@ -99,55 +68,81 @@ async function saveProgressionAPI(progress: number){
9968
});
10069
}
10170
102-
103-
// Configuration initiale du debounce
10471
const debouncedSetProgression = debounce((progress: number) => {
105-
if(isFirstSave.value)
106-
return;
10772
saveProgressionAPI(progress);
10873
}, 250);
10974
110-
const firstTimeScroll = ref(false);
75+
let triggeredScroll = false;
76+
function tryTriggerScroll(){
77+
if(!triggeredScroll
78+
&& currentProgression.value
79+
&& currentProgression.value !== 0
80+
&& imageRefs.value[currentProgression.value]
81+
){
82+
triggerScroll(currentProgression.value);
83+
triggeredScroll = true;
84+
}
85+
}
11186
function triggerScroll(value: number){
11287
setTimeout(() => {
113-
firstTimeScroll.value = true;
11488
imageRefs.value[value]?.scrollIntoView({
11589
behavior: "smooth",
11690
block: "start"
11791
});
11892
}, 100);
11993
}
120-
watch([currentProgression, images], ([newValue]) => {
121-
if(!firstTimeScroll.value && imageRefs.value[newValue])
122-
triggerScroll(Math.max(newValue - 2, 0));
123-
});
94+
95+
// Scroll to the current progression if it exists
96+
watch([currentProgression, imageRefs], ([newCurrentProgression]) => {
97+
if(newCurrentProgression === 1)
98+
triggeredScroll = true;
99+
tryTriggerScroll();
100+
}, {immediate: true});
124101
125102
onMounted(() => {
103+
// Trigger scroll after 500ms to current progression if it exists
126104
setTimeout(() => {
127-
saveProgressionAPI(currentProgression.value || 0);
128-
isFirstSave.value = false;
129-
}, 2000);
130-
105+
tryTriggerScroll();
106+
}, 100);
107+
// Progression observers
131108
const imageObserver = new IntersectionObserver((entries) => {
132109
entries.forEach(entry => {
133-
if (entry.isIntersecting){
110+
if(entry.isIntersecting){
134111
const index = imageRefs.value.indexOf(entry.target as HTMLElement);
135-
if (index > currentProgression.value){
112+
if(index > (currentProgression.value || 0)){
136113
currentProgression.value = index;
137114
debouncedSetProgression(index);
138115
}
139116
}
140117
});
141118
}, {root: document.querySelector(".flex-1"), threshold: 0.1});
142-
143119
imageRefs.value.forEach(el => el && imageObserver.observe(el));
144120
watch(imageRefs, (newRefs) => {
145121
newRefs.forEach(el => el && imageObserver.observe(el));
146122
}, {deep: true});
147-
148123
onBeforeUnmount(() => {
149124
imageObserver.disconnect();
150125
});
126+
127+
// Sentinel observer
128+
observer = new IntersectionObserver((entries) => {
129+
if (entries[0].isIntersecting && hasMore.value){
130+
displayCount.value += 10;
131+
}
132+
}, {
133+
root: document.querySelector(".flex-1"),
134+
rootMargin: "100px 0px"
135+
});
136+
watchEffect(() => {
137+
if (sentinel.value && hasMore.value){
138+
observer.observe(sentinel.value);
139+
} else if (sentinel.value){
140+
observer.unobserve(sentinel.value);
141+
}
142+
});
143+
onBeforeUnmount(() => {
144+
observer.disconnect();
145+
});
151146
});
152147
</script>
153148

pages/index.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ const sortedWebtoons = computed(() => {
5959
6060
const isWebtoonLiked = computed(() => {
6161
if (!likes.value || !webtoons.value) return {};
62-
const likedWebtoons = {};
62+
const likedWebtoons: any = {};
6363
for (const id of likes.value)
6464
likedWebtoons[id] = true;
6565
for (const webtoon of webtoons.value)
@@ -90,7 +90,7 @@ function likedStateChange(webtoonId: number, newState: boolean){
9090
v-for="webtoon in sortedWebtoons"
9191
:key="webtoon.id"
9292
:webtoon="webtoon"
93-
:liked="isWebtoonLiked[webtoon.id]"
93+
:liked="isWebtoonLiked[webtoon.id] || false"
9494
@update:liked="likedStateChange"
9595
/>
9696
</div>

0 commit comments

Comments
 (0)