diff --git a/app/Utility/__init__.py b/app/Utility/__init__.py index fb125d7..d36b010 100644 --- a/app/Utility/__init__.py +++ b/app/Utility/__init__.py @@ -1,3 +1,4 @@ from .media_card_loader import MediaCardLoader from .show_notification import show_notification -from .data import themes_available \ No newline at end of file +from .data import themes_available +from .utils import write_crash \ No newline at end of file diff --git a/app/Utility/utils.py b/app/Utility/utils.py new file mode 100644 index 0000000..dec9726 --- /dev/null +++ b/app/Utility/utils.py @@ -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) \ No newline at end of file diff --git a/app/View/AnimeScreen/__init__.py b/app/View/AnimeScreen/__init__.py deleted file mode 100644 index 9ed563a..0000000 --- a/app/View/AnimeScreen/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .components.animdl_stream_dialog import AnimdlStreamDialog \ No newline at end of file diff --git a/app/View/AnimeScreen/anime_screen.py b/app/View/AnimeScreen/anime_screen.py index 907ead8..effbf2c 100644 --- a/app/View/AnimeScreen/anime_screen.py +++ b/app/View/AnimeScreen/anime_screen.py @@ -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() \ No newline at end of file + AnimdlStreamDialog(self.data).open() + + def open_download_anime_dialog(self): + """ + Opens the download anime dialog + """ + DownloadAnimeDialog(self.data).open() \ No newline at end of file diff --git a/app/View/AnimeScreen/components/__init__.py b/app/View/AnimeScreen/components/__init__.py new file mode 100644 index 0000000..a32deaf --- /dev/null +++ b/app/View/AnimeScreen/components/__init__.py @@ -0,0 +1,2 @@ +from .animdl_stream_dialog import AnimdlStreamDialog +from .download_anime_dialog import DownloadAnimeDialog \ No newline at end of file diff --git a/app/View/AnimeScreen/components/controls.kv b/app/View/AnimeScreen/components/controls.kv index 37d56c4..236fb3f 100644 --- a/app/View/AnimeScreen/components/controls.kv +++ b/app/View/AnimeScreen/components/controls.kv @@ -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" diff --git a/app/View/AnimeScreen/components/download_anime_dialog.kv b/app/View/AnimeScreen/components/download_anime_dialog.kv new file mode 100644 index 0000000..73b9df5 --- /dev/null +++ b/app/View/AnimeScreen/components/download_anime_dialog.kv @@ -0,0 +1,58 @@ +: + adaptive_height:True + max_lines:0 + shorten:False + markup:True + font_style: "Label" + role: "medium" + bold:True +: + 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" + + + + + 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" \ No newline at end of file diff --git a/app/View/AnimeScreen/components/download_anime_dialog.py b/app/View/AnimeScreen/components/download_anime_dialog.py new file mode 100644 index 0000000..c64ef8f --- /dev/null +++ b/app/View/AnimeScreen/components/download_anime_dialog.py @@ -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) \ No newline at end of file diff --git a/app/View/DownloadsScreen/download_screen.kv b/app/View/DownloadsScreen/download_screen.kv index 8906643..8fb2d2f 100644 --- a/app/View/DownloadsScreen/download_screen.kv +++ b/app/View/DownloadsScreen/download_screen.kv @@ -1,18 +1,50 @@ #:import get_color_from_hex kivy.utils.get_color_from_hex #:import StringProperty kivy.properties.StringProperty +: + adaptive_height:True + max_lines:0 + shorten:False + markup:True + font_style: "Label" + role: "large" + bold:True 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" \ No newline at end of file + 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} diff --git a/app/View/DownloadsScreen/download_screen.py b/app/View/DownloadsScreen/download_screen.py index 1d9c98b..2f8d579 100644 --- a/app/View/DownloadsScreen/download_screen.py +++ b/app/View/DownloadsScreen/download_screen.py @@ -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)})" diff --git a/app/View/components/general.kv b/app/View/components/general.kv index 444dc32..31019bc 100644 --- a/app/View/components/general.kv +++ b/app/View/components/general.kv @@ -1,3 +1,3 @@ -# : -# allow_copy:True -# allow_selection:True \ No newline at end of file +: + allow_copy:True + allow_selection:True \ No newline at end of file diff --git a/app/libs/animdl/animdl_api.py b/app/libs/animdl/animdl_api.py index ae3c06d..95c1e12 100644 --- a/app/libs/animdl/animdl_api.py +++ b/app/libs/animdl/animdl_api.py @@ -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): diff --git a/app/main.py b/app/main.py index a57ea23..4a2d34e 100644 --- a/app/main.py +++ b/app/main.py @@ -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) diff --git a/app/vids/Death note rewrite/Episode 1/Death note b/app/vids/Death note rewrite/Episode 1/Death note new file mode 100644 index 0000000..e69de29