added download anime funtionality to the ui

This commit is contained in:
Benex254
2024-08-05 09:46:53 +03:00
parent 780c34a5ba
commit bc551309a2
14 changed files with 183 additions and 35 deletions

View File

@@ -1,3 +1,4 @@
from .media_card_loader import MediaCardLoader
from .show_notification import show_notification
from .data import themes_available
from .data import themes_available
from .utils import write_crash

23
app/Utility/utils.py Normal file
View File

@@ -0,0 +1,23 @@
from datetime import datetime
# import tempfile
import shutil
# import os
# utility functions
def write_crash(e:Exception):
index = datetime.today()
error = f"[b][color=#fa0000][ {index} ]:[/color][/b]\n(\n\n{e}\n\n)\n"
try:
with open("crashdump.txt","a") as file:
file.write(error)
except:
with open("crashdump.txt","w") as file:
file.write(error)
return index
def move_file(source_path,dest_path):
try:
path = shutil.move(source_path,dest_path)
return (1,path)
except Exception as e:
return (0,e)

View File

@@ -1 +0,0 @@
from .components.animdl_stream_dialog import AnimdlStreamDialog

View File

@@ -6,7 +6,7 @@ from kivymd.uix.label import MDLabel
from kivy.utils import QueryDict,get_hex_from_color
from collections import defaultdict
from . import AnimdlStreamDialog
from .components import AnimdlStreamDialog,DownloadAnimeDialog
# TODO:move the rest of the classes to their own files
@@ -286,4 +286,10 @@ class AnimeScreenView(BaseScreenView):
"""
Called when user wants to stream with custom commands
"""
AnimdlStreamDialog(self.data).open()
AnimdlStreamDialog(self.data).open()
def open_download_anime_dialog(self):
"""
Opens the download anime dialog
"""
DownloadAnimeDialog(self.data).open()

View File

@@ -0,0 +1,2 @@
from .animdl_stream_dialog import AnimdlStreamDialog
from .download_anime_dialog import DownloadAnimeDialog

View File

@@ -16,3 +16,8 @@
on_press: app.watch_on_allanime(root.screen.data["title"]["romaji"])
MDButtonText:
text:"Watch on AllAnime"
MDButton:
on_press:
if root.screen:root.screen.open_download_anime_dialog()
MDButtonText:
text:"Download Anime"

View File

@@ -0,0 +1,58 @@
<DownloadDialogLabel@MDLabel>:
adaptive_height:True
max_lines:0
shorten:False
markup:True
font_style: "Label"
role: "medium"
bold:True
<DownloadDialogHeaderLabel@MDLabel>:
adaptive_height:True
halign:"center"
max_lines:0
shorten:False
bold:True
markup:True
font_style: "Title"
role: "medium"
md_bg_color:self.theme_cls.secondaryContainerColor
padding:"10dp"
<DownloadAnimeDialog>
md_bg_color:self.theme_cls.backgroundColor
radius:8
size_hint:None,None
height:"500dp"
width:"400dp"
MDBoxLayout:
spacing: '10dp'
padding:"10dp"
orientation:"vertical"
DownloadDialogHeaderLabel:
text:"Download Anime"
DownloadDialogLabel:
text:"Title"
MDTextField:
id:title_field
required:True
DownloadDialogLabel:
text:"Range"
MDTextField:
id:range_field
required:True
DownloadDialogLabel:
text:"Quality"
MDTextField:
id:quality_field
required:True
MDBoxLayout:
orientation:"vertical"
MDButton:
pos_hint: {'center_x': 0.5}
on_press:root.download_anime(app)
MDButtonIcon:
icon:"download"
MDButtonText:
text:"Download"

View File

@@ -0,0 +1,25 @@
from kivy.uix.modalview import ModalView
from kivymd.uix.behaviors import StencilBehavior,CommonElevationBehavior,BackgroundColorBehavior
from kivymd.theming import ThemableBehavior
# from main import AniXStreamApp
class DownloadAnimeDialog(ThemableBehavior,StencilBehavior,CommonElevationBehavior,BackgroundColorBehavior,ModalView):
def __init__(self,data,**kwargs):
super(DownloadAnimeDialog,self).__init__(**kwargs)
self.data = data
if title:=data["title"].get("romaji"):
self.ids.title_field.text = title
elif title:=data["title"].get("english"):
self.ids.title_field.text = title
self.ids.quality_field.text = "best"
def download_anime(self,app):
default_cmds = {}
title=self.ids.title_field.text
default_cmds["title"] = title
if episodes_range:=self.ids.range_field.text:
default_cmds["episodes_range"] = episodes_range
if quality:=self.ids.range_field.text:
default_cmds["quality"] = quality
# print(title,episodes_range,latest,quality)
app.download_anime(default_cmds)

View File

@@ -1,18 +1,50 @@
#:import get_color_from_hex kivy.utils.get_color_from_hex
#:import StringProperty kivy.properties.StringProperty
<DownloadsScreenLabel@MDLabel>:
adaptive_height:True
max_lines:0
shorten:False
markup:True
font_style: "Label"
role: "large"
bold:True
<DownloadsScreenView>
md_bg_color: self.theme_cls.backgroundColor
# main_container:main_container
download_progress_label:download_progress_label
progress_bar:progress_bar
MDBoxLayout:
NavRail:
screen:root
MDAnchorLayout:
anchor_y: 'top'
padding:"10dp"
MDBoxLayout:
orientation: 'vertical'
SearchBar:
MDLabel:
text:"Downloads"
MDScrollView:
size_hint:1,1
MDGridLayout:
id:main_container
cols:5
adaptive_height:True
MDLabel:
text:"Dowloads"
MDBoxLayout:
size_hint_y:None
height:"40dp"
spacing:"10dp"
padding:"10dp"
md_bg_color:self.theme_cls.secondaryContainerColor
DownloadsScreenLabel:
id:download_progress_label
size_hint_x: .6
text:"current episode"
pos_hint: {'center_y': .5}
MDLinearProgressIndicator:
id: progress_bar
size_hint_x: .4
size_hint_y:None
height:"10dp"
type: "determinate"
pos_hint: {'center_y': .5}

View File

@@ -1,16 +1,15 @@
from kivy.properties import ObjectProperty
from View.base_screen import BaseScreenView
from kivy.uix.modalview import ModalView
from kivy.utils import format_bytes_to_human
class DownloadAnimePopup(ModalView):
pass
class DownloadsScreenView(BaseScreenView):
main_container = ObjectProperty()
def model_is_changed(self) -> None:
"""
Called whenever any change has occurred in the data model.
The view in this method tracks these changes and updates the UI
according to these changes.
"""
progress_bar = ObjectProperty()
download_progress_label = ObjectProperty()
def on_episode_download_progress(self,current_bytes_downloaded,total_bytes,episode_info):
percentage_completion = (current_bytes_downloaded/total_bytes)*100
self.progress_bar.value= percentage_completion
self.download_progress_label.text = f"Downloading: {episode_info['anime_title']} - {episode_info['episode']} ({format_bytes_to_human(current_bytes_downloaded)}/{format_bytes_to_human(total_bytes)})"

View File

@@ -1,3 +1,3 @@
# <MDLabel>:
# allow_copy:True
# allow_selection:True
<MDLabel>:
allow_copy:True
allow_selection:True

View File

@@ -46,7 +46,7 @@ class AnimdlApi:
return streaming_child_process
@classmethod
def download_anime_by_title(cls,title,on_episode_download_progress,on_complete,output_path=os.getcwd(),episodes_range=None,quality="best"):
def download_anime_by_title(cls,title,on_episode_download_progress,on_complete,output_path,episodes_range:str|None=None,quality:str="best"):
data = cls.get_stream_urls_by_anime_title(title,episodes_range)
if not data:
return None,None
@@ -127,7 +127,7 @@ class AnimdlApi:
successful_downloads.append(episode_number)
except:
failed_downloads.append(episode_number)
on_complete(successful_downloads,failed_downloads)
on_complete(successful_downloads,failed_downloads,anime_title)
@classmethod
def download_with_mpv(cls,url,output_path,on_progress):

View File

@@ -61,7 +61,7 @@ class AniXStreamApp(MDApp):
while True:
download_task = queue.get() # task should be a function
download_task()
self.queue.task_done()
self.downloads_queue.task_done()
def __init__(self, **kwargs):
super().__init__(**kwargs)
@@ -91,6 +91,7 @@ class AniXStreamApp(MDApp):
self.theme_cls.theme_style = theme_style
self.anime_screen = self.manager_screens.get_screen("anime screen")
self.search_screen = self.manager_screens.get_screen("search screen")
self.download_screen = self.manager_screens.get_screen("downloads screen")
return self.manager_screens
def on_start(self,*args):
@@ -164,22 +165,19 @@ class AniXStreamApp(MDApp):
show_notification("Failure",f"Failed to open {title} in browser on allanime site")
def download_anime_complete(self,successful_downloads:list,failed_downloads:list,anime_title:str):
show_notification(f"Finished Dowloading {anime_title}",f"There were {len(successful_downloads)} successful downloads and {len(failed_downloads)} failed downloads")
def open_download_anime_dialog(self):
""""
calls the download dialog
"""
DownloadAnimePopup().open()
def download_anime(self,on_complete,on_progress,default_cmds:dict[str,str]|None=None,custom_cmds:tuple[str]|None=None):
def download_anime(self,default_cmds):
# TODO:Add custom download cmds functionality
on_progress = lambda *args:self.download_screen.on_episode_download_progress(*args)
output_path = self.config.get("Preferences","downloads_dir")
if default_cmds:
if episodes_range:=default_cmds.get("episodes_range"):
download_task =lambda: AnimdlApi.download_anime_by_title(default_cmds["title"],on_progress,on_complete,output_path,episodes_range,default_cmds["quality"])
self.downloads_queue.put(download_task)
else:
download_task =lambda: AnimdlApi.download_anime_by_title(default_cmds["title"],on_progress,on_complete,output_path,None,default_cmds["quality"])
self.downloads_queue.put(download_task)
if episodes_range:=default_cmds.get("episodes_range"):
download_task =lambda: AnimdlApi.download_anime_by_title(default_cmds["title"],on_progress,self.download_anime_complete,output_path,episodes_range) # ,default_cmds["quality"]
self.downloads_queue.put(download_task)
else:
download_task =lambda: AnimdlApi.download_anime_by_title(default_cmds["title"],on_progress,self.download_anime_complete,output_path) # ,default_cmds.get("quality")
self.downloads_queue.put(download_task)
def stream_anime_with_custom_input_cmds(self,*cmds):
self.animdl_streaming_subprocess = AnimdlApi.run_custom_command("stream",*cmds)