Skip to content

Commit

Permalink
Improve reading mode performance and ux
Browse files Browse the repository at this point in the history
  • Loading branch information
ngekoding committed Dec 30, 2024
1 parent 2946e50 commit 635e43f
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 84 deletions.
30 changes: 22 additions & 8 deletions src/pages/quran/QuranReaderDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
</q-header>

<!-- Quran detail -->
<keep-alive v-if="surah">
<keep-alive v-if="surah && headerHeight">
<component
ref="quranDetail"
:is="quranDetailComponent"
Expand All @@ -45,8 +45,7 @@
:verse-key="verseKey"
:header-height="headerHeight"
:surah="surah"
:pages="surah.pages"
:active-page="activePage"
:current-page.sync="currentPage"
/>
</keep-alive>

Expand Down Expand Up @@ -212,6 +211,7 @@ export default {
surahList,
headerHeight: 0,
surahId: "",
currentPage: 0,
showSurahChangerDialog: false,
contentStyles: null,
modeList: ["list", "reading", "wbw"],
Expand All @@ -237,7 +237,19 @@ export default {
surahId: "trackDetail",
mode() {
this.showModeSwitcherDialog = false;
this.currentPage = 0;
this.trackDetail();
},
currentPage(page) {
if (page == 0) return;
const surah = this.surahList.find(item => {
const [firstPage, lastPage] = item.pages;
return page >= firstPage && page <= lastPage;
});
if (this.surahId != surah.id) {
this.onSurahChanged(surah.id, false);
}
}
},
computed: {
Expand Down Expand Up @@ -282,14 +294,15 @@ export default {
trackDetail() {
this.track(this.pageTitle);
},
onSurahChanged(id) {
onSurahChanged(id, resetCurrentPage = true) {
this.$router
.replace({
params: {
surahId: id
}
})
.then(() => {
if (resetCurrentPage) this.currentPage = 0;
this.surahId = id;
});
},
Expand All @@ -300,12 +313,13 @@ export default {
this.$refs.menuMore.setState("half");
}
},
mounted() {
this.headerHeight = this.$refs.header.$el.clientHeight;
this.trackDetail();
},
created() {
this.surahId = parseInt(this.$route.params.surahId);
this.$nextTick(() => {
this.headerHeight = this.$refs.header.$el.clientHeight;
this.trackDetail();
});
this.currentPage = this.activePage;
}
};
</script>
135 changes: 59 additions & 76 deletions src/pages/quran/components/QuranReaderDetailReadingMode.vue
Original file line number Diff line number Diff line change
@@ -1,115 +1,96 @@
<template>
<div class="quran-reading-mode bg-white">
<swiper
:key="swiperKey"
ref="quranPageSwiper"
:options="swiperOptions"
dir="rtl"
@slideNextTransitionEnd="onNext"
@slidePrevTransitionEnd="onPrev"
>
<swiper-slide v-for="image in images" :key="`page-${image.page}`">
<q-img :src="image.url" :style="imageStyle" contain />
</swiper-slide>
</swiper>
@slideChange="onSlideChange"
/>
</div>
</template>

<script>
import { Swiper, SwiperSlide } from "vue-awesome-swiper";
import "swiper/css/swiper.css";
import { Swiper } from "vue-awesome-swiper";
import "swiper/css/swiper.min.css";
export default {
name: "QuranDetailReadingMode",
components: {
Swiper,
SwiperSlide
Swiper
},
props: {
surah: {
type: Object,
required: true
},
pages: {
type: Array,
required: true
},
headerHeight: {
type: Number,
default: 0
},
activePage: {
currentPage: {
type: Number,
default: 0
}
},
data() {
return {
page: "quran-reader-detail-mode",
swiperKey: 1,
swiperOptions: {},
pageCount: 0,
currentPage: this.pages[0],
pagesCount: 604,
quranImageBaseUrl: "https://android.quran.com/data/width_1024/page",
images: []
initial: false
};
},
watch: {
pages(val) {
this.swiperOptions.initialSlide = 0;
this.swiperKey = !this.swiperKey;
this.currentPage = val[0];
this.init();
},
currentPage: "saveScrollPosition"
"surah.id": "init"
},
computed: {
swiper() {
return this.$refs.quranPageSwiper.$swiper;
},
imageStyle() {
swiperOptions() {
return {
height: `calc(100vh - ${this.headerHeight}px - 10px)`,
marginTop: "10px"
dir: "rtl",
slidesPerView: 1,
virtual: {
slides: (() => {
const slides = [];
for (let page = 1; page <= this.pagesCount; page++) {
slides.push(
`<img
src="${this.getImageUrl(page)}"
style="${this.imageStyle}"
/>`
);
}
return slides;
})()
}
};
},
imageStyle() {
return `height: calc(100vh - ${this.headerHeight}px - 20px)`;
}
},
methods: {
init() {
this.images = [];
this.pageCount = this.pages[1] - this.pages[0] + 1;
// Load three first images
let endPage = this.currentPage + 2;
endPage = endPage > this.pages[1] ? this.pages[1] : endPage;
for (let page = this.pages[0]; page <= endPage; page++) {
this.images.push({
page,
url:
this.quranImageBaseUrl + page.toString().padStart(3, "0") + ".png"
});
}
getImageUrl(page) {
return this.quranImageBaseUrl + page.toString().padStart(3, "0") + ".png";
},
loadMore() {
const nextPage = this.images.slice(-1)[0].page + 1;
if (nextPage <= this.pages[1]) {
this.images.push({
page: nextPage,
url:
this.quranImageBaseUrl +
nextPage.toString().padStart(3, "0") +
".png"
});
}
},
onNext() {
this.loadMore();
this.currentPage++;
init() {
this.initial = true;
const initialPage = this.currentPage || this.surah.pages[0];
this.swiper.slideTo(initialPage - 1, 0);
this.$nextTick(() => {
this.swiper.virtual.update();
this.initial = false;
this.saveScrollPosition();
});
},
onPrev() {
this.currentPage--;
onSlideChange() {
if (this.initial) return;
this.$emit("update:currentPage", this.swiper.activeIndex + 1);
this.$nextTick(() => {
this.saveScrollPosition();
});
},
saveScrollPosition() {
this.$store.dispatch("quran/setPageScrollPosition", {
Expand All @@ -123,18 +104,20 @@ export default {
});
}
},
mounted() {
if (this.activePage != 0) {
const activePageIndex = this.activePage - this.pages[0];
this.swiperOptions.initialSlide = activePageIndex;
this.currentPage = this.activePage;
this.swiperKey = !this.swiperKey;
}
this.init();
},
activated() {
this.saveScrollPosition();
this.init();
}
};
</script>

<style lang="scss">
.swiper-slide {
text-align: center;
img {
width: 100%;
margin-top: 10px;
object-fit: contain;
object-position: top center;
}
}
</style>

0 comments on commit 635e43f

Please sign in to comment.