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

Commit

Permalink
chore: implement remote video download
Browse files Browse the repository at this point in the history
  • Loading branch information
sircharlo committed Jun 20, 2024
1 parent dc3f6f1 commit 5edd891
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 136 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"cSpell.words": [
"akamaihd",
"alllangs",
"axios",
"ayfm",
"AYFM",
"cctv",
Expand Down
18 changes: 11 additions & 7 deletions src-electron/electron-preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,17 @@ const moveMediaWindow = ({
const mediaWindow = getMediaWindow();
if (!mediaWindow || !mainWindow) return;
if (targetScreen === undefined || windowedMode === undefined) {
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;
try {
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;
} catch (err) {
console.error(err);
}
}
const getWindowScreen = (window: Electron.BrowserWindow) => {
const windowDisplay = screen.getDisplayMatching(window.getBounds());
Expand Down
23 changes: 15 additions & 8 deletions src/components/media/MediaDisplayButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@
screen.mainWindow
? 'mdi-monitor-dashboard'
: screenPreferences.preferredScreenNumber === index
? 'mdi-monitor-shimmer'
: 'mdi-monitor'
? 'mdi-monitor-shimmer'
: 'mdi-monitor'
"
:text-color="
screenList.length < 2 ||
Expand Down Expand Up @@ -130,8 +130,7 @@ import { useAppSettingsStore } from 'src/stores/app-settings';
import { useCurrentStateStore } from 'src/stores/current-state';
import { onMounted, onUnmounted, ref, watch } from 'vue';
const { getAllScreens, moveMediaWindow, toggleMediaWindow } =
electronApi;
const { getAllScreens, moveMediaWindow, toggleMediaWindow } = electronApi;
defineProps<{
disabled?: boolean;
Expand Down Expand Up @@ -178,13 +177,21 @@ watch(
);
const targetScreenListener = (event: CustomEventInit) => {
console.log('targetScreen-update', event.detail);
screenPreferences.value.preferredScreenNumber = event.detail;
try {
console.log('targetScreen-update', event.detail);
screenPreferences.value.preferredScreenNumber = event.detail;
} catch (error) {
console.error(error);
}
};
const windowedModeListener = (event: CustomEventInit) => {
console.log('windowedMode-update', event.detail);
screenPreferences.value.preferWindowed = event.detail;
try {
console.log('windowedMode-update', event.detail);
screenPreferences.value.preferWindowed = event.detail;
} catch (error) {
console.error(error);
}
};
onMounted(() => {
Expand Down
33 changes: 31 additions & 2 deletions src/helpers/jw-media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1017,7 +1017,7 @@ const getPubMediaLinks = async (publication: PublicationFetcher) => {
};

export function findBestResolution(
mediaLinks: (MediaItemsMediatorFile | MediaLink)[],
mediaLinks: MediaItemsMediatorFile[] | MediaLink[],
) {
const currentState = useCurrentStateStore();
const { getSettingValue } = currentState;
Expand All @@ -1033,7 +1033,9 @@ export function findBestResolution(
mediaLink.frameHeight <= maxRes &&
mediaLink.frameHeight >= bestHeight
) {
bestItem = mediaLink;
bestItem = Object.hasOwn(mediaLink, 'progressiveDownloadURL')
? (mediaLink as MediaItemsMediatorFile)
: (mediaLink as MediaLink);
bestHeight = mediaLink.frameHeight;
}
}
Expand Down Expand Up @@ -1114,6 +1116,32 @@ const downloadMissingMedia = async (publication: PublicationFetcher) => {
return downloadedFile?.path;
};

const downloadAdditionalRemoteVideo = async (
mediaItemLinks: MediaItemsMediatorFile[],
) => {
window.dispatchEvent(
new CustomEvent('remoteVideo-loading', {
detail: true,
}),
);
const currentState = useCurrentStateStore();
const { getDatedAdditionalMediaDirectory } = storeToRefs(currentState);
const bestItem = findBestResolution(mediaItemLinks) as MediaItemsMediatorFile;
let downloadedFile: DownloadedFile = { path: '' };
if (bestItem) {
downloadedFile = (await downloadFileIfNeeded({
dir: getDatedAdditionalMediaDirectory.value,
size: bestItem.filesize,
url: bestItem.progressiveDownloadURL,
})) as DownloadedFile;
}
window.dispatchEvent(
new CustomEvent('remoteVideo-loaded', {
detail: downloadedFile,
}),
);
};

function getBestImageUrl(images: ImageTypeSizes, size?: keyof ImageSizes) {
const preferredOrder: (keyof ImageTypeSizes)[] = ['wss', 'lsr', 'sqr', 'pnr'];
for (const key of preferredOrder) {
Expand Down Expand Up @@ -1287,6 +1315,7 @@ const downloadJwpub = async (

export {
addFullFilePathToMultimediaItem,
downloadAdditionalRemoteVideo,
downloadBackgroundMusic,
downloadFileIfNeeded,
downloadPubMediaFiles,
Expand Down
164 changes: 83 additions & 81 deletions src/layouts/MainLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -169,17 +169,20 @@
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> -->
<q-linear-progress
:value="remoteVideosLoadingProgress"
class="q-mt-md"
/>
<div class="row q-px-sm">
<div class="col-grow">
<q-input :label="$t('filter')" dense v-model="remoteVideoFilter" />
<q-input
:label="$t('filter')"
dense
v-model="remoteVideoFilter"
/>
</div>
<q-toggle
:label="$t('include-audio-description')"
Expand All @@ -196,7 +199,7 @@
>
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-3">
<q-card
@click="console.log(video)"
@click="downloadAdditionalRemoteVideo(video.files); remoteVideoPopup = false"
class="text-white cursor-pointer"
style="
background-color: rgb(91, 60, 136);
Expand Down Expand Up @@ -227,16 +230,6 @@
</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>
Expand Down Expand Up @@ -375,7 +368,11 @@ 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, getBestImageUrl } from 'src/helpers/jw-media';
import {
downloadAdditionalRemoteVideo,
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';
Expand Down Expand Up @@ -548,6 +545,7 @@ const localUploadPopup = ref(false);
const importMediaMenuActive = ref(false);
const datePickerActive = ref(false);
const remoteVideoPopup = ref(false);
const remoteVideosLoadingProgress = ref(0);
const remoteVideos: Ref<MediaItemsMediatorItem[]> = ref([]);
// const remoteVideosByCategory: Ref<{
// [key: string]: MediaItemsMediatorItem[];
Expand Down Expand Up @@ -586,81 +584,85 @@ 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()
try {
if (remoteVideosLoadingProgress.value < 1) {
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);
let index = 0;
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()
);
});
index++;
remoteVideosLoadingProgress.value = index / subcategories.length;
}
}
} catch (error) {
console.error(error);
}
// 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(
const useableVideos = ref(
remoteVideos.value.filter(
(v) =>
remoteVideosIncludeAudioDescription.value ||
!v.primaryCategory.endsWith('AD'),
)
.slice(0, 100);
),
);
if (remoteVideoFilter.value?.length > 2)
useableVideos.value = useableVideos.value.filter((video) =>
video.title.toLowerCase().includes(remoteVideoFilter.value.toLowerCase()),
);
return useableVideos.value.slice(0, 50);
});
onMounted(() => {
document.title = 'Meeting Media Manager';
console.log(currentSettings.value);
if (!currentSettings.value) navigateToCongregationSelector();
});
</script>
Loading

0 comments on commit 5edd891

Please sign in to comment.