Skip to content
This repository has been archived by the owner on Dec 27, 2024. It is now read-only.

Commit

Permalink
fix: stop music when disabled; add video picker;
Browse files Browse the repository at this point in the history
  • Loading branch information
sircharlo committed Jun 20, 2024
1 parent 1473872 commit dc3f6f1
Show file tree
Hide file tree
Showing 8 changed files with 299 additions and 74 deletions.
1 change: 1 addition & 0 deletions src-electron/electron-preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ const moveMediaWindow = ({
const screenPreferences = JSON.parse(
localStorage.getItem('screenPreferences') ?? '{}',
) as ScreenPreferences;
// todo: fix this, not reading right values
console.log('screenPreferences', screenPreferences);
targetScreen = screenPreferences.preferredScreenNumber;
windowedMode = screenPreferences.preferWindowed;
Expand Down
10 changes: 9 additions & 1 deletion src/components/media/MusicButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ import { date } from 'quasar';
import { getFileUrl, getPublicationDirectoryContents } from 'src/helpers/fs';
import { formatTime } from 'src/helpers/mediaPlayback';
import { useCurrentStateStore } from 'src/stores/current-state';
import { computed, onMounted, ref } from 'vue';
import { computed, onMounted, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
Expand Down Expand Up @@ -207,4 +207,12 @@ const musicRemainingTime = computed(() => {
});
const musicPopup = ref(false);
watch(
() => currentSettings.value?.enableMusicButton,
(newMusicButtonEnabled) => {
console.log('newMusicButtonEnabled', newMusicButtonEnabled);
if (!newMusicButtonEnabled) stopMusic();
},
);
</script>
18 changes: 11 additions & 7 deletions src/helpers/jw-media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ import {
FileDownloader,
} from 'src/types/media';
import {
MediaImages,
ImageSizes,
ImageTypeSizes,
MediaItemsMediator,
MediaItemsMediatorFile,
MediaLink,
Expand Down Expand Up @@ -1113,20 +1114,22 @@ const downloadMissingMedia = async (publication: PublicationFetcher) => {
return downloadedFile?.path;
};

function getBestImageUrl(images: MediaImages) {
const preferredOrder = ['wss', 'lsr', 'sqr', 'pnr'];
function getBestImageUrl(images: ImageTypeSizes, size?: keyof ImageSizes) {
const preferredOrder: (keyof ImageTypeSizes)[] = ['wss', 'lsr', 'sqr', 'pnr'];
for (const key of preferredOrder) {
if (images.hasOwnProperty(key)) {
const sizes = ['sm', 'md', 'lg', 'xl'];
const sizes: (keyof ImageSizes)[] = size
? [size]
: ['sm', 'md', 'lg', 'xl'];
for (const size of sizes) {
if (images[key].hasOwnProperty(size)) {
return images[key][size];
}
}
// If none of the preferred sizes are found, return any other size
const otherSizes = Object.keys(images[key]).filter(
(size) => !sizes.includes(size),
);
const otherSizes = (
Object.keys(images[key]) as (keyof ImageSizes)[]
).filter((size) => !sizes.includes(size));
if (otherSizes.length > 0) {
return images[key][otherSizes[0]];
}
Expand Down Expand Up @@ -1289,6 +1292,7 @@ export {
downloadPubMediaFiles,
dynamicMediaMapper,
fetchMedia,
getBestImageUrl,
getDocumentMultimediaItems,
getJwMediaInfo,
getMwMedia,
Expand Down
4 changes: 3 additions & 1 deletion src/i18n/en-US/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -173,5 +173,7 @@
"footnote": "Footnote",
"windowed": "Windowed",
"you-can-also-use-the-button-below-to-browse-for-files": "You can also browse for files manually if you prefer.",
"browse": "Browse"
"browse": "Browse",
"include-audio-description": "Include videos with audio descriptions",
"filter": "Filter"
}
4 changes: 3 additions & 1 deletion src/i18n/fr-CA/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -356,5 +356,7 @@
"congregationMeetings": "Réunions de l'assemblée locale",
"applicationConfigurationDescription": "Personnaliser le comportement et l'apparence de cette application",
"applicationConfiguration": "Configuration de l'application",
"you-can-also-use-the-button-below-to-browse-for-files": "Vous pouvez également parcourir et sélectionner des fichiers manuellement, si vous le désirez."
"you-can-also-use-the-button-below-to-browse-for-files": "Vous pouvez également parcourir et sélectionner des fichiers manuellement, si vous le désirez.",
"include-audio-description": "Inclure les vidéos avec des descriptions audio",
"filter": "Filtre"
}
180 changes: 176 additions & 4 deletions src/layouts/MainLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@
<q-item-section>{{ $t('song') }}</q-item-section>
</q-item>
<q-item
@click="localUploadPopup = true"
@click="
remoteVideoPopup = true;
getJwVideos();
"
clickable
v-close-popup
>
Expand Down Expand Up @@ -152,6 +155,90 @@
</q-card-actions>
</q-card>
</q-dialog>
<q-dialog v-model="remoteVideoPopup">
<q-card
class="non-selectable"
style="width: 80vw; max-width: 80vw; min-width: 3"
>
<q-toolbar>
<q-avatar>
<q-icon
color="primary"
name="mdi-cursor-default"
size="lg"
text-color="white"
/>
</q-avatar>

<q-toolbar-title>{{ $t('add-media-files') }}</q-toolbar-title>

<q-btn dense flat icon="close" round v-close-popup />
</q-toolbar>

<!-- <q-card-section horizontal> -->
<!-- <q-card-section> </q-card-section> -->
<div class="row q-px-sm">
<div class="col-grow">
<q-input :label="$t('filter')" dense v-model="remoteVideoFilter" />
</div>
<q-toggle
:label="$t('include-audio-description')"
left-label
v-model="remoteVideosIncludeAudioDescription"
/>
</div>
<q-separator />
<q-card-section>
<div class="row q-col-gutter-lg">
<template
:key="video.guid"
v-for="video in remoteVideosFiltered"
>
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-3">
<q-card
@click="console.log(video)"
class="text-white cursor-pointer"
style="
background-color: rgb(91, 60, 136);
border-radius: 0.75em;
"
v-ripple
>
<q-img :src="getBestImageUrl(video.images, 'md')">
<!-- <div class="absolute-bottom">
<div class="text-subtitle2">{{ video.title }}</div>
<div class="text-caption">
{{ video.naturalKey }}
</div>
</div> -->
</q-img>
<q-card-section>
<div class="text-subtitle1 q-mb-xs">
{{ video.title }}
</div>
<div>
<span class="text-caption text-grey-2">{{
video.naturalKey
}}</span>
</div>
</q-card-section>
</q-card>
</div>
</template>
</div>
</q-card-section>
<!-- </q-card-section> -->
<q-card-actions align="right">
<q-btn
:label="$t('browse')"
@click="getLocalFiles()"
color="primary"
flat
/>
<q-btn :label="$t('got-it')" color="primary" v-close-popup />
</q-card-actions>
</q-card>
</q-dialog>
</template>
<template v-else-if="route.fullPath === '/settings'">
<!-- <q-btn color="negative" v-if="invalidSettings()"> -->
Expand Down Expand Up @@ -278,6 +365,7 @@
<script setup lang="ts">
import { storeToRefs } from 'pinia';
import { Dark, LocalStorage, date } from 'quasar';
import { get } from 'src/boot/axios';
import DownloadStatus from 'src/components/media/DownloadStatus.vue';
import MediaDisplayButton from 'src/components/media/MediaDisplayButton.vue';
import MusicButton from 'src/components/media/MusicButton.vue';
Expand All @@ -287,13 +375,17 @@ import SongPicker from 'src/components/media/SongPicker.vue';
import SubtitlesButton from 'src/components/media/SubtitlesButton.vue';
import { getLookupPeriod } from 'src/helpers/date';
import { electronApi } from 'src/helpers/electron-api';
import { downloadBackgroundMusic } from 'src/helpers/jw-media';
import { downloadBackgroundMusic, getBestImageUrl } from 'src/helpers/jw-media';
import { createTemporaryNotification } from 'src/helpers/notifications';
import { useAppSettingsStore } from 'src/stores/app-settings';
import { useCongregationSettingsStore } from 'src/stores/congregation-settings';
import { useCurrentStateStore } from 'src/stores/current-state';
import { useJwStore } from 'src/stores/jw';
import { onMounted, ref, watch } from 'vue';
import {
JwVideoCategory,
MediaItemsMediatorItem,
} from 'src/types/publications';
import { Ref, computed, onMounted, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router';
Expand All @@ -307,7 +399,7 @@ appSettings.$subscribe((_, state) => {
LocalStorage.set('migrations', state.migrations);
// Use native localStorage for screen preferences, since Electron preload can't use quasar's LocalStorage
localStorage.set('screenPreferences', state.screenPreferences);
LocalStorage.set('screenPreferences', state.screenPreferences);
});
const currentState = useCurrentStateStore();
Expand Down Expand Up @@ -455,6 +547,13 @@ const getEventDates = () => {
const localUploadPopup = ref(false);
const importMediaMenuActive = ref(false);
const datePickerActive = ref(false);
const remoteVideoPopup = ref(false);
const remoteVideos: Ref<MediaItemsMediatorItem[]> = ref([]);
// const remoteVideosByCategory: Ref<{
// [key: string]: MediaItemsMediatorItem[];
// }> = ref({});
const remoteVideoFilter = ref('');
const remoteVideosIncludeAudioDescription = ref(false);
if (!migrations.value.includes('firstRun')) {
const migrationResult = runMigration('firstRun');
Expand Down Expand Up @@ -486,6 +585,79 @@ const getLocalFiles = async () => {
});
};
const getJwVideos = async () => {
const currentState = useCurrentStateStore();
const { getSettingValue } = currentState;
const getSubcategories = async (category: string) => {
return (await get(
`https://b.jw-cdn.org/apis/mediator/v1/categories/${
getSettingValue('lang') as string
}/${category}?detailed=1&mediaLimit=0&clientType=www`,
)) as JwVideoCategory;
};
const subcategories: {
key: string;
parentCategory: string;
}[] = [{ key: 'LatestVideos', parentCategory: '' }];
const subcategoriesRequest = await getSubcategories('VideoOnDemand');
console.log('subcategoriesRequest', subcategoriesRequest);
const subcategoriesFirstLevel =
subcategoriesRequest.category.subcategories.map((s) => s.key);
for (const subcategoryFirstLevel of subcategoriesFirstLevel) {
subcategories.push(
...(
await getSubcategories(subcategoryFirstLevel)
).category.subcategories.map((s) => {
return { key: s.key, parentCategory: subcategoryFirstLevel };
}),
);
}
console.log('subcategories', subcategories);
for (const category of subcategories) {
const request = (await get(
`https://b.jw-cdn.org/apis/mediator/v1/categories/${
getSettingValue('lang') as string
}/${category.key}?detailed=0&clientType=www`,
)) as JwVideoCategory;
// remoteVideosByCategory.value[category.parentCategory ?? category.key] =
// request.category.media;
remoteVideos.value = remoteVideos.value
.concat(request.category.media)
.reduce((accumulator: MediaItemsMediatorItem[], current) => {
const guids = new Set(accumulator.map((item) => item.guid));
if (!guids.has(current.guid)) {
accumulator.push(current);
}
return accumulator;
}, [])
.sort((a, b) => {
return (
new Date(b.firstPublished).getTime() -
new Date(a.firstPublished).getTime()
);
});
}
// make sure values are unique, based on guid
};
const remoteVideosFiltered = computed(() => {
return (
remoteVideoFilter.value?.length > 2
? remoteVideos.value.filter((video) =>
video.title
.toLowerCase()
.includes(remoteVideoFilter.value.toLowerCase()),
)
: remoteVideos.value
)
.filter(
(v) =>
remoteVideosIncludeAudioDescription.value ||
!v.primaryCategory.endsWith('AD'),
)
.slice(0, 100);
});
onMounted(() => {
document.title = 'Meeting Media Manager';
console.log(currentSettings.value);
Expand Down
Loading

0 comments on commit dc3f6f1

Please sign in to comment.