Skip to content

Commit

Permalink
feat: add media from study bible
Browse files Browse the repository at this point in the history
  • Loading branch information
mtdvlpr committed Nov 15, 2024
1 parent 73bcff9 commit a18903e
Show file tree
Hide file tree
Showing 5 changed files with 395 additions and 1 deletion.
258 changes: 258 additions & 0 deletions src/components/dialog/DialogStudyBible.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
<template>
<q-dialog v-model="open">
<div
class="items-center q-pb-lg q-px-lg q-gutter-y-lg bg-secondary-contrast large-overlay"
>
<div class="text-h6 row">{{ $t('add-media-study-bible') }}</div>
<div class="row">{{ $t('add-media-study-bible-explain') }}</div>
<div v-if="bibleBook" class="text-h6 row">
{{ $t('media-gallery') }} - {{ bibleBooks[bibleBook].standardName }}
</div>
<div
v-if="!!(loadingProgress < 1 && Object.keys(bibleBooks).length === 0)"
class="text-center row items-center justify-center"
>
<q-spinner color="primary" size="md" />
</div>
<div class="row">
<q-scroll-area
:bar-style="barStyle"
:thumb-style="thumbStyle"
style="width: 100vw; height: 40vh"
>
<div v-if="bibleBook" class="row q-col-gutter-md">
<template v-for="mediaItem in bibleBookMedia" :key="mediaItem.id">
<div class="col-xs-4 col-sm-3 col-md-2 col-lg-2 col-xl-1">
<div
v-ripple
:class="{
'cursor-pointer': true,
'rounded-borders-lg': true,
'full-height': true,
'bg-accent-100': hoveredMediaItem === mediaItem.id,
}"
flat
@click="addResource(mediaItem.resource)"
@mouseout="hoveredMediaItem = 0"
@mouseover="hoveredMediaItem = mediaItem.id"
>
<q-card-section class="q-pa-sm">
<q-img
:src="
getBestImageUrl(
{ sqr: mediaItem.thumbnail.sizes },
'md',
)
"
class="rounded-borders"
>
<q-badge
v-if="mediaItem.type === 'video'"
class="q-mt-sm q-ml-sm bg-semi-black rounded-borders-sm"
style="padding: 5px !important"
>
<q-icon class="q-mr-xs" color="white" name="mmm-play" />
{{ $t('video') }}
</q-badge>
</q-img>
</q-card-section>
<q-card-section class="q-pa-sm">
<div class="text-subtitle2 q-mb-xs">
{{ mediaItem.label }}
</div>
</q-card-section>
</div>
</div>
</template>
</div>
<div v-else class="row q-col-gutter-md">
<template
v-for="[bookNr, book] in Object.entries(bibleBooks)"
:key="bookNr"
>
<div
v-if="book.hasMultimedia"
class="col-xs-4 col-sm-3 col-md-2 col-lg-2 col-xl-1"
>
<div
v-ripple
:class="{
'cursor-pointer': true,
'rounded-borders-lg': true,
'full-height': true,
'bg-accent-100': hoveredBibleBook === bookNr,
}"
flat
@click="getBibleBookMedia(+bookNr)"
@mouseout="hoveredBibleBook = ''"
@mouseover="hoveredBibleBook = bookNr"
>
<q-card-section class="q-pa-sm">
<q-img
:src="
getBestImageUrl(
bibleBookImagesToImageTypeSizes(book.images),
'md',
)
"
class="rounded-borders"
>
</q-img>
</q-card-section>
<q-card-section class="q-pa-sm">
<div class="text-subtitle2 q-mb-xs">
{{ book.standardName }}
</div>
</q-card-section>
</div>
</div>
</template>
</div>
</q-scroll-area>
</div>
<div class="row items-center">
<div class="col"></div>
<div class="col text-right">
<q-btn
v-if="bibleBook"
:label="$t('back')"
color="primary"
flat
@click="resetBibleBook"
/>
<q-btn v-close-popup :label="$t('cancel')" color="negative" flat />
</div>
</div>
</div>
</q-dialog>
</template>
<script setup lang="ts">
import { storeToRefs } from 'pinia';
// Packages
import { ref } from 'vue';
// Composables
import { useScrollbar } from 'src/composables/useScrollbar';
// Helpers
import { getBestImageUrl } from 'src/helpers/jw-media';
// Types
import type {
BibleBook,
BibleBookImage,
BibleBookMedia,
BibleBookResource,
BibleBooksResult,
ImageTypeSizes,
MediaSection,
} from 'src/types';
import { whenever } from '@vueuse/core';
import { fetchJson } from 'src/helpers/api';
import { errorCatcher } from 'src/helpers/error-catcher';
import { useCurrentStateStore } from 'src/stores/current-state';
import { useJwStore } from 'src/stores/jw';
// Stores
const jwStore = useJwStore();
const { urlVariables } = storeToRefs(jwStore);
const currentState = useCurrentStateStore();
const { currentSettings } = storeToRefs(currentState);
// Props
defineProps<{
section?: MediaSection;
}>();
const open = defineModel<boolean>({ default: false });
const { barStyle, thumbStyle } = useScrollbar();
const bibleBook = ref(0);
const bibleBookMedia = ref<BibleBookMedia[]>([]);
const bibleBooks = ref<Record<number, BibleBook>>({});
const loadingProgress = ref<number>(0);
const hoveredBibleBook = ref('');
const hoveredMediaItem = ref(0);
whenever(open, () => {
getBibleBooks();
});
const bibleBookImagesToImageTypeSizes = (
images: BibleBookImage[],
): ImageTypeSizes => {
const imageTypeSizes: ImageTypeSizes = {};
images.forEach((image) => {
imageTypeSizes[image.type] = image.sizes;
});
return imageTypeSizes;
};
const getBibleBooks = async () => {
try {
if (!currentSettings.value) return;
const result = await fetchJson<BibleBooksResult>(
`https://www.${urlVariables.value.base}/en/library/bible/study-bible/books/json/data`,
);
bibleBooks.value = result?.editionData.books || {};
} catch (error) {
errorCatcher(error);
} finally {
loadingProgress.value = 1;
}
};
const resetBibleBook = () => {
bibleBook.value = 0;
bibleBookMedia.value = [];
};
const getBibleBookMedia = async (book: number) => {
bibleBook.value = book;
loadingProgress.value = 0;
try {
const result = await fetchJson<BibleBooksResult>(
`https://www.${urlVariables.value.base}/en/library/bible/study-bible/books/json/multimedia/${book}`,
);
if (!result) {
resetBibleBook();
return;
}
const key = Object.keys(result.ranges)[0];
if (!key) {
resetBibleBook();
return;
}
bibleBookMedia.value = result.ranges[key].multimedia;
} catch (e) {
errorCatcher(e);
resetBibleBook();
} finally {
loadingProgress.value = 1;
}
};
const addResource = async (resource: BibleBookResource) => {
try {
console.log('addResource', resource);
if (typeof resource.src == 'string') {
console.log('image', getBestImageUrl({ sqr: resource.sizes }, 'md'));
} else {
const src = resource.src[0];
if (typeof src === 'string') {
console.log('video cdn url', src);
} else {
console.log('video object', src);
}
}
} catch (error) {
errorCatcher(error);
}
};
</script>
20 changes: 19 additions & 1 deletion src/components/header/HeaderCalendar.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<template>
<SongPicker v-model="chooseSong" :section="section" />
<PublicTalkMediaPicker v-model="publicTalkMediaPopup" />
<DialogRemoteVideo v-model="remoteVideoPopup" :section="section" />
<DialogStudyBible v-model="studyBiblePopup" :section="section" />
<q-btn
:disable="mediaPlaying || !mediaSortForDay"
color="white-transparent"
Expand Down Expand Up @@ -74,6 +76,20 @@
<q-item-label caption>{{ $t('media-from-s34mp') }}</q-item-label>
</q-item-section>
</q-item>
<q-item
v-close-popup
:disable="!online"
clickable
@click="studyBiblePopup = true"
>
<q-item-section avatar>
<q-icon color="primary" name="mmm-guide" />
</q-item-section>
<q-item-section>
<q-item-label>{{ $t('study-bible') }}</q-item-label>
<q-item-label caption>{{ $t('study-bible-media') }}</q-item-label>
</q-item-section>
</q-item>
<q-item-label header>{{ $t('from-local-computer') }}</q-item-label>
<template
v-for="[icon, name] in [
Expand Down Expand Up @@ -185,7 +201,6 @@
<!-- </q-date> -->
</q-popup-proxy>
</q-btn>
<DialogRemoteVideo v-model="remoteVideoPopup" :section="section" />
</template>
<script setup lang="ts">
// Packages
Expand Down Expand Up @@ -213,6 +228,8 @@ import { useJwStore } from 'src/stores/jw';
// Types
import type { MediaSection } from 'src/types';
import DialogStudyBible from '../dialog/DialogStudyBible.vue';
const { formatDate, getDateDiff, getMaxDate, getMinDate } = date;
const jwStore = useJwStore();
Expand All @@ -236,6 +253,7 @@ const section = ref<MediaSection | undefined>();
const publicTalkMediaPopup = ref(false);
const datePickerActive = ref(false);
const remoteVideoPopup = ref(false);
const studyBiblePopup = ref(false);
const openDragAndDropper = () => {
window.dispatchEvent(
Expand Down
5 changes: 5 additions & 0 deletions src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
"add-a-video-explain": "Add one of the videos from the official website of Jehovah's Witnesses to the media list. The latest videos are displayed here, but you can also search through all videos if needed.",
"add-an-opening-song": "Add an opening song",
"add-extra-media": "Add extra media",
"add-media-study-bible": "Add media from the Study Bible",
"add-media-study-bible-explain": "Select a specific Bible book and chapter to view a list of study materials like images, videos, maps and historical references.",
"add-video-jw-org": "Add a video",
"additional-scenes": "Additional scenes",
"advanced": "Advanced",
Expand Down Expand Up @@ -185,6 +187,7 @@
"media-display": "Media display",
"media-display-settings": "Media display settings",
"media-from-s34mp": "Media from the S-34mp",
"media-gallery": "Media gallery",
"media-only": "Media only",
"media-playback": "Media playback",
"media-sync": "Media sync",
Expand Down Expand Up @@ -323,6 +326,8 @@
"stop-music": "Stop music",
"stop-playing-media-first": "To navigate to a different page, please stop the media playback first.",
"stop-playing-media-first-explain": "Page navigation is disabled while media is being presented.",
"study-bible": "Study Bible",
"study-bible-media": "Images, videos, maps",
"subtitles": "Subtitles",
"successfully-migrated-from-the-previous-version": "Successfully migrated from the previous version",
"sureStopVideo": "Are you sure you want to stop the video?",
Expand Down
1 change: 1 addition & 0 deletions src/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export * from './electron';
export * from './fs';
export * from './general';
export * from './github';
export * from './jw/bible';
export * from './jw/lang';
export * from './jw/publications';
export * from './jw/sqlite';
Expand Down
Loading

0 comments on commit a18903e

Please sign in to comment.