2022-04-16 02:07:29 +00:00
import type { GetServerSideProps , NextPage } from "next" ;
import { getSession , useSession } from "next-auth/react" ;
import { useState } from "react" ;
import { dehydrate , QueryClient , useQuery } from "react-query" ;
import { CustomHead } from "../components/CustomHead" ;
import { Layout } from "../components/Layout" ;
2022-04-16 17:51:47 +00:00
import NextImage from "next/image" ;
2022-04-18 17:51:41 +00:00
import { getDownloads , sendDeleteAllQueuedIgnored , sendDeleteVideoQueuedIgnored , sendMoveVideoQueuedIgnored } from "../lib/getDownloads" ;
2022-04-17 01:03:17 +00:00
import { sendDownloads } from "../lib/getDownloads" ;
2022-04-16 17:51:47 +00:00
import RescanIcon from "../images/icon-rescan.svg" ;
import DownloadIcon from "../images/icon-download.svg" ;
import AddIcon from "../images/icon-add.svg" ;
import GridViewIcon from "../images/icon-gridview.svg" ;
import ListViewIcon from "../images/icon-listview.svg" ;
2022-04-18 18:57:01 +00:00
import StopIcon from "../images/icon-stop.svg" ;
import CloseIcon from "../images/icon-close.svg" ;
2022-04-17 19:47:18 +00:00
import { getTAUrl } from "../lib/constants" ;
2022-04-16 02:07:29 +00:00
2022-04-17 19:47:18 +00:00
const TA_BASE_URL = getTAUrl ( ) ;
2022-04-16 22:26:30 +00:00
2022-04-16 02:07:29 +00:00
type ViewStyle = "grid" | "list" ;
2022-04-16 22:26:30 +00:00
type IgnoredStatus = boolean ;
2022-04-17 01:03:17 +00:00
type FormHidden = boolean ;
2022-04-21 15:56:48 +00:00
type ErrorMessage = string ;
2022-04-21 17:39:48 +00:00
type PageNumber = number ;
2022-04-20 16:37:33 +00:00
2022-04-16 02:07:29 +00:00
export const getServerSideProps : GetServerSideProps = async ( context ) = > {
const queryClient = new QueryClient ( ) ;
const session = await getSession ( context ) ;
if ( ! session ) {
return {
redirect : {
destination : "/auth/login" ,
permanent : false ,
} ,
} ;
}
2022-04-21 17:39:48 +00:00
await queryClient . prefetchQuery ( [ "downloads" , session . ta_token . token , false , 1 ] , ( ) = >
getDownloads ( session . ta_token . token , false , 1 )
2022-04-16 22:26:30 +00:00
) ;
2022-04-16 02:07:29 +00:00
return {
props : {
dehydratedState : dehydrate ( queryClient ) ,
session ,
} ,
} ;
} ;
const Download : NextPage = ( ) = > {
2022-04-16 22:26:30 +00:00
const { data : session } = useSession ( ) ;
2022-04-17 23:32:10 +00:00
const [ ignoredStatus , setIgnoredStatus ] = useState < IgnoredStatus > ( false ) ;
2022-04-21 17:39:48 +00:00
const [ pageNumber , setPageNumber ] = useState < PageNumber > ( 1 ) ;
2022-04-17 23:32:10 +00:00
2022-04-16 22:26:30 +00:00
const {
data : downloads ,
error ,
isLoading ,
2022-04-17 19:47:18 +00:00
refetch ,
2022-04-16 22:26:30 +00:00
} = useQuery (
2022-04-21 17:39:48 +00:00
[ "downloads" , session . ta_token . token , ignoredStatus , pageNumber ] ,
( ) = > getDownloads ( session . ta_token . token , ignoredStatus , pageNumber ) ,
2022-04-16 22:26:30 +00:00
{
enabled : ! ! session ? . ta_token ? . token ,
2022-04-18 16:00:53 +00:00
refetchInterval : 1500 ,
refetchIntervalInBackground : false ,
2022-04-16 22:26:30 +00:00
}
) ;
2022-04-16 02:07:29 +00:00
2022-04-21 15:15:57 +00:00
const [ formHidden , setFormHidden ] = useState < FormHidden > ( true ) ;
2022-04-16 22:39:33 +00:00
const [ viewStyle , setViewStyle ] = useState < ViewStyle > ( downloads ? . config ? . default_view ? . downloads ) ;
2022-04-21 15:56:48 +00:00
const [ errorMessage , setErrorMessage ] = useState < ErrorMessage > ( null ) ;
2022-04-16 02:07:29 +00:00
const handleSetViewstyle = ( selectedViewStyle : ViewStyle ) = > {
setViewStyle ( selectedViewStyle ) ;
} ;
2022-04-17 23:32:10 +00:00
2022-04-16 22:26:30 +00:00
const handleSetIgnoredStatus = ( selectedIgnoredStatus : IgnoredStatus ) = > {
setIgnoredStatus ( selectedIgnoredStatus ) ;
2022-04-17 19:47:18 +00:00
refetch ( ) ;
2022-04-16 22:26:30 +00:00
} ;
2022-04-17 01:03:17 +00:00
const handleSetFormHidden = ( selectedFormHidden : FormHidden ) = > {
setFormHidden ( selectedFormHidden ) ;
} ;
2022-04-18 16:00:53 +00:00
const handleSetErrorMessage = ( selectedErrorMessage : ErrorMessage ) = > {
setErrorMessage ( selectedErrorMessage ) ;
} ;
2022-04-21 17:39:48 +00:00
const handleSetPageNumber = ( selectedPageNumber : PageNumber ) = > {
setPageNumber ( selectedPageNumber ) ;
} ;
2022-04-17 01:03:17 +00:00
const addToDownloadQueue = event = > {
event . preventDefault ( ) ;
2022-04-21 15:56:48 +00:00
sendDownloads ( session . ta_token . token , event . target . vid_url . value ) . then ( ( ) = > {
handleSetErrorMessage ( null ) ;
handleSetFormHidden ( true ) ;
} )
. catch ( error = > handleSetErrorMessage ( error . message ) ) ;
2022-04-17 01:03:17 +00:00
}
2022-04-21 16:44:59 +00:00
const handleMoveVideoQueuedIgnored = ( session : string , youtube_id : string , status : string ) = > {
sendMoveVideoQueuedIgnored ( session , youtube_id , status ) . then ( ( ) = > {
handleSetErrorMessage ( null ) ;
} )
. catch ( error = > handleSetErrorMessage ( error . message ) ) ;
}
const handleDeleteVideoQueuedIgnored = ( session : string , youtube_id : string ) = > {
sendDeleteVideoQueuedIgnored ( session , youtube_id ) . then ( ( ) = > {
handleSetErrorMessage ( null ) ;
} )
. catch ( error = > handleSetErrorMessage ( error . message ) ) ;
}
const handleDeleteAllQueuedIgnored = ( session : string , filter : string ) = > {
sendDeleteAllQueuedIgnored ( session , filter ) . then ( ( ) = > {
handleSetErrorMessage ( null ) ;
} )
. catch ( error = > handleSetErrorMessage ( error . message ) ) ;
}
2022-04-16 02:07:29 +00:00
return (
< >
< CustomHead title = "Downloads" / >
< Layout >
< div className = "boxed-content" >
< div className = "title-bar" >
< h1 > Downloads < / h1 >
< / div >
2022-04-18 18:57:01 +00:00
< div id = "notifications" >
2022-04-21 16:08:48 +00:00
{ ( error || ! downloads ? . data ) && ! isLoading &&
2022-04-20 18:33:58 +00:00
< div className = "error notification" >
2022-04-21 15:56:48 +00:00
< h3 > API Connection Error < / h3 >
2022-04-21 16:03:36 +00:00
< p > < / p >
2022-04-20 18:33:58 +00:00
< / div >
}
2022-04-18 18:57:01 +00:00
{ errorMessage &&
2022-04-18 17:24:53 +00:00
< div className = "error notification" >
2022-04-21 15:56:48 +00:00
< h3 > Failed to add downloads to the queue . < / h3 >
< p > { errorMessage } < / p >
2022-04-18 17:24:53 +00:00
< / div >
2022-04-18 18:57:01 +00:00
}
{
// <div className="info notification">
// <h3>Adding new videos to download queue.</h3>
// <p>Extracting lists</p>
// <p>Progress: 0/0</p>
// </div>
}
{
// <div className="info notification">
// <h3>Rescanning channels and playlists.</h3>
// <p>Looking for new videos.</p>
// </div>
}
{
// <div className="info notification">
// <h3>Downloading: `VIDEO_TITLE`</h3>
// <p>processing</p>
// <p>`DOWNLOADED_PERCENTAGE`% of `VIDEO_SIVE``VIDEO_SIZE_UNIT` at `DOWNLOAD_SPEED``DOWNLOAD_SPEED_UNIT` - time left: `DOWNLOAD_TIME_LEFT`</p>
// <p>processing</p>
// <p>Moving</p>
// <p>Completed</p>
// </div>
}
< / div >
< div id = "downloadControl" >
{ /* Appears when video is downloading */ }
{ / * < d i v c l a s s N a m e = " d l - c o n t r o l - i c o n s " >
< NextImage
width = { 30 }
height = { 30 }
src = { StopIcon }
alt = "stop icon"
title = "Stop Download Queue"
id = "stop-icon"
onClick = { ( ) = > console . log ( "stopQueue()" ) }
/ >
< NextImage
width = { 30 }
height = { 30 }
src = { CloseIcon }
alt = "kill icon"
title = "Kill Download Queue"
id = "kill-icon"
onClick = { ( ) = > console . log ( "killQueue()" ) }
/ >
< / div > * / }
< / div >
2022-04-16 02:07:29 +00:00
< div className = "info-box info-box-3" >
< div className = "icon-text" >
2022-04-16 17:51:47 +00:00
< NextImage
width = { 80 }
height = { 80 }
src = { RescanIcon }
2022-04-16 02:07:29 +00:00
alt = "rescan-icon"
title = "Rescan subscriptions"
2022-04-18 18:57:01 +00:00
// className="rotate-img" // Set when rescanning
2022-04-16 17:51:47 +00:00
onClick = { ( ) = > console . log ( "rescanPending()" ) }
2022-04-16 02:07:29 +00:00
/ >
{ /* <img id="rescan-icon" onclick="rescanPending()" src="{% static 'img/icon-rescan.svg' %}" alt="rescan-icon"></img> */ }
< p > Rescan subscriptions < / p >
< / div >
< div className = "icon-text" >
2022-04-16 17:51:47 +00:00
< NextImage
width = { 80 }
height = { 80 }
src = { DownloadIcon }
2022-04-16 02:07:29 +00:00
alt = "download-icon"
title = "Start download"
2022-04-18 18:57:01 +00:00
// className="bounce-img" // Set when video is downloading
2022-04-16 17:51:47 +00:00
onClick = { ( ) = > console . log ( "dlPending()" ) }
2022-04-16 02:07:29 +00:00
/ >
{ /* <img id="download-icon" onclick="dlPending()" src="{% static 'img/icon-download.svg' %}" alt="download-icon"></img> */ }
< p > Start download < / p >
< / div >
< div className = "icon-text" >
2022-04-16 17:51:47 +00:00
< NextImage
width = { 80 }
height = { 80 }
src = { AddIcon }
2022-04-16 02:07:29 +00:00
alt = "add-icon"
title = "Add to download queue"
2022-04-17 01:03:17 +00:00
onClick = { ( ) = > formHidden ? handleSetFormHidden ( false ) : handleSetFormHidden ( true ) }
2022-04-16 02:07:29 +00:00
/ >
< p > Add to download queue < / p >
2022-04-17 01:03:17 +00:00
{ ! formHidden &&
< div className = "show-form" >
< form id = "hidden-form" onSubmit = { addToDownloadQueue } >
< textarea name = "vid_url" cols = { 40 } rows = { 4 } placeholder = "Enter Video Urls or IDs here..." required id = "id_vid_url" spellCheck = "false" / >
< button type = "submit" > Add to download queue < / button >
< / form >
< / div >
}
2022-04-16 02:07:29 +00:00
< / div >
< / div >
< div className = "view-controls" >
< div className = "toggle" >
< span > Show only ignored videos : < / span >
2022-04-17 19:47:18 +00:00
< div className = "toggleBox" >
< input
id = "show_ignored_only"
onChange = { ( ) = > handleSetIgnoredStatus ( ! ignoredStatus ) }
type = "checkbox"
checked = { ignoredStatus }
/ >
< label htmlFor = "" className = { ignoredStatus ? "onbtn" : "ofbtn" } >
{ ignoredStatus ? "On" : "Off" }
< / label >
< / div >
2022-04-16 02:07:29 +00:00
< / div >
< div className = "view-icons" >
2022-04-20 16:37:33 +00:00
< div className = "view-icons-margin" >
< NextImage
width = { 30 }
height = { 34 }
src = { GridViewIcon }
alt = "grid view"
title = "Switch to grid view"
onClick = { ( ) = > handleSetViewstyle ( "grid" ) }
/ >
< / div >
2022-04-16 02:07:29 +00:00
{ /* <img src="{% static 'img/icon-gridview.svg' %}" onclick="changeView(this)" data-origin="downloads" data-value="grid" alt="grid view"> */ }
2022-04-20 16:37:33 +00:00
< div className = "view-icons-margin" >
< NextImage
width = { 30 }
height = { 34 }
src = { ListViewIcon }
alt = "list view"
title = "Switch to list view"
onClick = { ( ) = > handleSetViewstyle ( "list" ) }
/ >
< / div >
2022-04-16 02:07:29 +00:00
{ /* <img src="{% static 'img/icon-listview.svg' %}" onclick="changeView(this)" data-origin="downloads" data-value="list" alt="list view"> */ }
< / div >
< / div >
2022-04-17 04:01:10 +00:00
{ ignoredStatus &&
< div className = "title-split" >
< h2 > Ignored from download < / h2 >
2022-04-21 16:44:59 +00:00
< button onClick = { ( ) = > handleDeleteAllQueuedIgnored ( session . ta_token . token , "ignore" ) } title = "Remove all ignored videos." > Remove all ignored < / button >
2022-04-17 04:01:10 +00:00
< / div >
}
{ ! ignoredStatus &&
< div className = "title-split" >
< h2 > Download queue < / h2 >
2022-04-21 16:44:59 +00:00
< button onClick = { ( ) = > handleDeleteAllQueuedIgnored ( session . ta_token . token , "pending" ) } title = "Remove all videos from the queue." > Remove all queued < / button >
2022-04-17 04:01:10 +00:00
< / div >
}
2022-04-21 17:39:48 +00:00
< h3 > Total videos : { downloads ? . paginate ? . total_hits } { ! downloads ? . paginate ? . total_hits && ! downloads ? . message && ! ignoredStatus && < p > No videos queued for download . Press rescan subscriptions to check if there are any new videos . < / p > } < / h3 >
2022-04-18 16:00:53 +00:00
< div className = { ` dl-list ${ viewStyle } ` } >
2022-04-20 18:33:58 +00:00
{ ! isLoading && ! error && ! downloads ? . message &&
2022-04-17 04:01:10 +00:00
downloads ? . data ? . map ( ( video ) = > {
2022-04-16 22:26:30 +00:00
return (
2022-04-17 04:01:10 +00:00
< div key = { video ? . youtube_id } className = { ` dl-item ${ viewStyle } ` } >
2022-04-16 22:26:30 +00:00
< div className = { ` dl-thumb ${ viewStyle } ` } >
2022-04-17 19:47:18 +00:00
< img src = { ` ${ TA_BASE_URL . server } ${ video ? . vid_thumb_url } ` } alt = "video_thumb" > < / img >
2022-04-16 22:26:30 +00:00
{ ignoredStatus && < span > ignored < / span > }
{ /* {% if show_ignored_only %} */ }
{ /* <span>ignored</span> */ }
{ ! ignoredStatus && < span > queued < / span > }
{ /* {% else %} */ }
{ /* <span>queued</span> */ }
{ /* {% endif %} */ }
< / div >
< div className = { ` dl-desc ${ viewStyle } ` } >
2022-04-17 01:03:17 +00:00
< h3 > { video ? . title } < / h3 >
2022-04-17 04:01:10 +00:00
{ video ? . channel_indexed && < a href = { ` /channel/ ${ video ? . channel_id } ` } > { video ? . channel_name } < / a > }
2022-04-16 22:26:30 +00:00
{ /* {% if video.source.channel_indexed %} */ }
{ /* <a href="{% url 'channel_id' video.source.channel_id %}">{{ video.source.channel_name }}</a> */ }
2022-04-17 04:01:10 +00:00
{ ! video ? . channel_indexed && < span > { video ? . channel_name } < / span > }
2022-04-16 22:26:30 +00:00
{ /* {% else %} */ }
{ /* <span>{{ video.source.channel_name }}</span> */ }
{ /* {% endif %} */ }
2022-04-17 04:01:10 +00:00
< p > Published : { video ? . published } | Duration : { video ? . duration } | { video ? . youtube_id } < / p >
2022-04-16 22:26:30 +00:00
{ /* <p>Published: {{ video.source.published }} | Duration: {{ video.source.duration }} | {{ video.source.youtube_id }}</p> */ }
{ ignoredStatus &&
< div >
2022-04-21 16:44:59 +00:00
< button className = "button-padding" title = "Move this video to the download queue." onClick = { ( ) = > handleMoveVideoQueuedIgnored ( session . ta_token . token , video ? . youtube_id , "pending" ) } > Add to queue < / button >
< button className = "button-padding" title = "Remove this video from the ignored list." onClick = { ( ) = > handleDeleteVideoQueuedIgnored ( session . ta_token . token , video ? . youtube_id ) } > Remove < / button >
2022-04-16 22:26:30 +00:00
< / div >
}
{ /* {% if show_ignored_only %} */ }
{ /* <button data-id="{{ video.source.youtube_id }}" onclick="forgetIgnore(this)">Forget</button> */ }
{ /* <button data-id="{{ video.source.youtube_id }}" onclick="addSingle(this)">Add to queue</button> */ }
{ ! ignoredStatus &&
< div >
2022-04-21 16:44:59 +00:00
< button className = "button-padding" title = "Ignore this video." onClick = { ( ) = > handleMoveVideoQueuedIgnored ( session . ta_token . token , video ? . youtube_id , "ignore" ) } > Ignore < / button >
2022-04-20 16:37:33 +00:00
< button className = "button-padding" title = "Download this video now." onClick = { ( ) = > console . log ( "downloadNow(this)" ) } > Download now < / button >
2022-04-21 16:44:59 +00:00
< button className = "button-padding" title = "Remove this video from the queue." onClick = { ( ) = > handleDeleteVideoQueuedIgnored ( session . ta_token . token , video ? . youtube_id ) } > Remove < / button >
2022-04-16 22:26:30 +00:00
< / div >
}
{ /* {% else %} */ }
{ /* <button data-id="{{ video.source.youtube_id }}" onclick="toIgnore(this)">Ignore</button> */ }
{ /* <button id="{{ video.source.youtube_id }}" data-id="{{ video.source.youtube_id }}" onclick="downloadNow(this)">Download now</button> */ }
{ /* {% endif %} */ }
< / div >
< / div >
) ;
} )
}
2022-04-16 02:07:29 +00:00
{ /* {% if results %} */ }
{ /* {% for video in results %} */ }
{ /* <div className="dl-item {{ view_style }}" id="dl-{{ video.source.youtube_id }}"> */ }
{ /* <div className="dl-thumb {{ view_style }}"> */ }
{ /* <img src="/cache/{{ video.source.vid_thumb_url }}" alt="video_thumb"> */ }
{ /* {% if show_ignored_only %} */ }
{ /* <span>ignored</span> */ }
{ /* {% else %} */ }
{ /* <span>queued</span> */ }
{ /* {% endif %} */ }
{ /* </div> */ }
{ /* <div className="dl-desc {{ view_style }}"> */ }
{ /* <h3>{{ video.source.title }}</h3> */ }
{ /* {% if video.source.channel_indexed %} */ }
{ /* <a href="{% url 'channel_id' video.source.channel_id %}">{{ video.source.channel_name }}</a> */ }
{ /* {% else %} */ }
{ /* <span>{{ video.source.channel_name }}</span> */ }
{ /* {% endif %} */ }
{ /* <p>Published: {{ video.source.published }} | Duration: {{ video.source.duration }} | {{ video.source.youtube_id }}</p> */ }
{ /* {% if show_ignored_only %} */ }
{ /* <button data-id="{{ video.source.youtube_id }}" onclick="forgetIgnore(this)">Forget</button> */ }
{ /* <button data-id="{{ video.source.youtube_id }}" onclick="addSingle(this)">Add to queue</button> */ }
{ /* {% else %} */ }
{ /* <button data-id="{{ video.source.youtube_id }}" onclick="toIgnore(this)">Ignore</button> */ }
{ /* <button id="{{ video.source.youtube_id }}" data-id="{{ video.source.youtube_id }}" onclick="downloadNow(this)">Download now</button> */ }
{ /* {% endif %} */ }
{ /* </div> */ }
{ /* </div> */ }
{ /* {% endfor %} */ }
{ /* {% endif %} */ }
2022-04-16 22:26:30 +00:00
< / div >
2022-04-16 02:07:29 +00:00
< / div >
2022-04-21 17:39:48 +00:00
< div className = "boxed-content" >
< div className = "pagination" >
{ pageNumber != 1 ? < a className = "pagination-item" onClick = { ( ) = > handleSetPageNumber ( 1 ) } > First < / a > : ` ` }
{ downloads ? . paginate ? . prev_pages &&
downloads ? . paginate ? . prev_pages ? . map ( ( page ) = > {
return (
< a key = { ` ${ page } ` } className = "pagination-item" onClick = { ( ) = > handleSetPageNumber ( page ) } > { page } < / a >
) } )
}
2022-04-21 17:53:14 +00:00
{ downloads ? . paginate ? . prev_pages &&
< span > & lt ; < / span >
}
< span > Page { pageNumber } < / span >
{ downloads ? . paginate ? . next_pages &&
< span > & gt ; < / span >
}
2022-04-21 17:39:48 +00:00
{ downloads ? . paginate ? . next_pages &&
downloads ? . paginate ? . next_pages ? . map ( ( page ) = > {
return (
< a key = { ` ${ page } ` } className = "pagination-item" onClick = { ( ) = > handleSetPageNumber ( page ) } > { page } < / a >
) } )
}
{ downloads ? . paginate ? . next_pages ? . forEach ( ( page ) = >
< a className = "pagination-item" onClick = { ( ) = > handleSetPageNumber ( page ) } > { page } < / a >
) }
{ downloads ? . paginate ? . last_page &&
< a className = "pagination-item" onClick = { ( ) = > handleSetPageNumber ( downloads ? . paginate ? . last_page ) } > Last ( { downloads ? . paginate ? . last_page } ) < / a >
}
< / div >
< / div >
2022-04-16 02:07:29 +00:00
{ /* <script type="text/javascript" src="{% static 'progress.js' %}"></script> */ }
< / Layout >
< / >
) ;
} ;
2022-04-17 04:01:10 +00:00
export default Download ;