Skip to content

Commit

Permalink
Add ability to queue videos for download
Browse files Browse the repository at this point in the history
They cannot be processed or viewed yet, but they can be queued.

(To be clear, the code to download and mux streams does exist, but nothing will call it using items from the queue yet)

#348
  • Loading branch information
MarmadileManteater committed Jul 14, 2024
1 parent b87ce79 commit dff2772
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export default defineComponent({
selectDownloadsDirectory: async function () {
const directoryUris = []
const downloadsDirectory = await requestDirectory()
const files = downloadsDirectory.listFiles()
const files = await downloadsDirectory.listFiles()
const dirs = files.filter((file) => file.isDirectory && EXPECTED_DATA_DIRS.indexOf(file.fileName) !== -1)
if (dirs.length !== EXPECTED_DATA_DIRS.length) {
// something is missing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,16 @@ input {
.select, .ft-input-component {
margin-block-end: 1em;
}

.file-name-input {
display: flex;
}

.file-name-input .type {
justify-content: center;
display: flex;
flex-direction: column;
margin-block-start: 10px;
margin-inline-start: 7px;
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import FtInput from '../ft-input/ft-input.vue'
import FtButton from '../ft-button/ft-button.vue'
import FtPrompt from '../ft-prompt/ft-prompt.vue'
import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
import { addToDownloadQueue } from '../../helpers/android'
import { showToast } from '../../helpers/utils'

export default defineComponent({
name: 'FtaAddDownloadPrompt',
Expand Down Expand Up @@ -32,6 +34,10 @@ export default defineComponent({
suggestedTitle: {
type: String,
default: () => ''
},
videoData: {
type: Object,
required: true
}
},
data: function () {
Expand Down Expand Up @@ -155,14 +161,27 @@ export default defineComponent({
*/
placeholderTitle: function () {
if (this.formatSelected !== -1) {
return `${this.suggestedTitle}.${this.audioVideoSources[this.formatSelected].container}`
return this.suggestedTitle
} else {
return ''
}
},
container: function () {
return `.${this.audioVideoSources[this.formatSelected].container}`
}
},
methods: {
addToDownload() {
async addToDownload() {
const downloadRequest = {
videoData: this.videoData,
format: this.audioVideoSources[this.formatSelected],
captions: this.captions[this.captionSelected],
// -1 means default to what is paired in formats
languageTrackSelected: this.audioTrackSelected
}
await addToDownloadQueue(downloadRequest)
showToast(this.$t('Download Prompt.Video has been added to download queue'))
this.hide()
},
updateFormatSelected(selected) {
this.formatSelected = parseInt(selected)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,15 @@
:icon="['fas', 'globe']"
@change="updateAudioTrackSelected"
/>
<ft-input
:label="'File name'"
:show-label="true"
:placeholder="placeholderTitle"
:show-action-button="false"
/>
<div class="file-name-input">
<ft-input
:label="'File name'"
:show-label="true"
:placeholder="placeholderTitle"
:show-action-button="false"
/>
<div class="type">{{ container }}</div>
</div>
</ft-flex-box>
<div class="buttons">
<!-- using user playlists strings here is a dirty trick -->
Expand Down
4 changes: 4 additions & 0 deletions src/renderer/components/watch-video-info/watch-video-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ export default defineComponent({
type: Array,
required: true
},
downloadPromptData: {
type: Object,
required: true
},
playlistId: {
type: String,
default: null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
@click="handleDownload"
/>
<fta-add-download-prompt
:video-data="downloadPromptData"
:sources-for-download="downloadLinks"
:shown="isDownloadPromptShown"
:hide="hideDownloadPrompt"
Expand Down
58 changes: 49 additions & 9 deletions src/renderer/helpers/android.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ export function handleAmbigiousContent(content, filePath) {

/**
* @callback ListFiles
* @returns {Array<AndroidFile|DirectoryHandle>}
* @returns {Promise<Array<AndroidFile|DirectoryHandle>>}
*/

/**
Expand Down Expand Up @@ -265,18 +265,44 @@ export function restoreHandleFromDirectoryUri(uri) {
createDirectory(dirName) {
return restoreHandleFromDirectoryUri(android.createDirectoryInTree(uri, dirName))
},
listFiles() {
const files = JSON.parse(android.listFilesInTree(uri)).map((file) => {
async listFiles() {
const files = await Promise.all(JSON.parse(android.listFilesInTree(uri)).map(async (file) => {
if (file.isDirectory) {
Object.assign(file, restoreHandleFromDirectoryUri(file.uri))
Object.assign(file, await restoreHandleFromDirectoryUri(file.uri))
}
return file
})
}))
return files
}
}
}

export async function getDownloadsDirectory() {
const downloadsDirectory = JSON.parse(await readFile('data://', 'downloads-directory.json')).uri
return await restoreHandleFromDirectoryUri(downloadsDirectory)
}

export async function getNestedUri(handle, path) {
/** @type {Array<string>} */
let parts = path.split('/')
/** @type {DirectoryHandle} */
let runningHandle = handle
while (parts.length > 0) {
const startingLength = parts.length
const ls = await runningHandle.listFiles()
for (const file in ls) {
if (file === parts[0]) {
runningHandle = file
parts = parts.slice(1)
}
}
if (startingLength === parts.length) {
throw new Error('Could not find path given')
}
}
return runningHandle
}

export const EXPECTED_FILES = ['profiles.db', 'settings.db', 'history.db', 'playlists.db']

/**
Expand All @@ -287,7 +313,7 @@ export async function initalizeDatabasesInDirectory(directoryHandle) {
if (directoryHandle.canceled) {
return []
}
const files = directoryHandle.listFiles()
const files = await directoryHandle.listFiles()
const filteredFiles = files.filter(({ fileName }) => EXPECTED_FILES.indexOf(fileName) !== -1)
const filteredFileNames = filteredFiles.map((item) => item.fileName)
if (filteredFiles.length === EXPECTED_FILES.length) {
Expand Down Expand Up @@ -344,7 +370,7 @@ export const EXPECTED_DATA_DIRS = ['authors', 'videos']
* @returns {Promise<string>}
*/
export async function downloadVideoAndAudio(directoryHandle, videoFormat, audioFormat, videoId, update = () => {}) {
const files = directoryHandle.listFiles()
const files = await directoryHandle.listFiles()
/** @type {DirectoryHandle} */
let videoFolder
const prexistingFolders = files.filter(file => file.isDirectory && file.fileName === videoId)
Expand All @@ -356,7 +382,7 @@ export async function downloadVideoAndAudio(directoryHandle, videoFormat, audioF
const videoMime = videoFormat.mime_type.split('video/')[1].split(';')[0]
const audioMime = audioFormat.mime_type.split('audio/')[1].split(';')[0]
const videoFileName = `video.${videoMime}`
let alreadyExistingFiles = videoFolder.listFiles().filter((file) => file.fileName === videoFileName)
let alreadyExistingFiles = (await videoFolder.listFiles()).filter((file) => file.fileName === videoFileName)
if (alreadyExistingFiles.length > 0) {
android.deleteFileInTree(alreadyExistingFiles[0].uri)
}
Expand All @@ -372,7 +398,7 @@ export async function downloadVideoAndAudio(directoryHandle, videoFormat, audioF
}]
})
const audioFileName = `audio.${audioMime}`
alreadyExistingFiles = videoFolder.listFiles().filter((file) => file.fileName === audioFileName)
alreadyExistingFiles = (await videoFolder.listFiles()).filter((file) => file.fileName === audioFileName)
if (alreadyExistingFiles.length > 0) {
android.deleteFileInTree(alreadyExistingFiles[0].uri)
}
Expand Down Expand Up @@ -504,3 +530,17 @@ export function getDownloadFormats(formats) {
}
return pairings
}

export async function addToDownloadQueue(downloadRequest) {
const downloadsDirectory = await getDownloadsDirectory()
const files = await downloadsDirectory.listFiles()
/** setting up queue */
let queueDirectory = files.find(file => file.fileName === 'queue')
if (!queueDirectory) {
queueDirectory = downloadsDirectory.createDirectory('queue')
}
// write the request into a file which is timestamped
const requestFileName = `${new Date().getTime()}-${downloadRequest.id}.json`
const requestFileUri = queueDirectory.createFile(requestFileName)
await writeFile(requestFileUri, JSON.stringify(downloadRequest, null, 2))
}
17 changes: 17 additions & 0 deletions src/renderer/views/Watch/Watch.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,23 @@ export default defineComponent({
}
},
computed: {
downloadPromptData: function () {
return {
id: this.videoId,
title: this.videoTitle,
channelId: this.channelId,
channelName: this.channelName,
channelThumbnail: this.channelThumbnail,
published: this.videoPublished,
channelSubscriptionCountText: this.channelSubscriptionCountText,
likes: this.videoLikeCount,
lengthSeconds: this.videoLengthSeconds,
thumbnail: this.thumbnail,
chapters: this.videoChapters,
description: this.videoDescription,
descriptionHtml: this.videoDescriptionHtml
}
},
historyEntry: function () {
return this.$store.getters.getHistoryCacheById[this.videoId]
},
Expand Down
1 change: 1 addition & 0 deletions src/renderer/views/Watch/Watch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
:is-live="isLive"
:is-upcoming="isUpcoming"
:download-links="downloadLinks"
:download-prompt-data="downloadPromptData"
:playlist-id="playlistId"
:get-playlist-index="getPlaylistIndex"
:get-playlist-reverse="getPlaylistReverse"
Expand Down
1 change: 1 addition & 0 deletions static/locales-android/en-US.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ Download Prompt:
Video: Video
Captions: Captions
Audio Language: Audio Language
Video has been added to download queue: Video has been added to download queue
Log Viewer:
Console Log: Console Log

0 comments on commit dff2772

Please sign in to comment.