mirror of
https://github.com/Benexl/FastAnime.git
synced 2025-12-12 07:40:41 -08:00
added download anime funtionality to the ui
This commit is contained in:
@@ -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
23
app/Utility/utils.py
Normal 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)
|
||||
@@ -1 +0,0 @@
|
||||
from .components.animdl_stream_dialog import AnimdlStreamDialog
|
||||
@@ -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()
|
||||
2
app/View/AnimeScreen/components/__init__.py
Normal file
2
app/View/AnimeScreen/components/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from .animdl_stream_dialog import AnimdlStreamDialog
|
||||
from .download_anime_dialog import DownloadAnimeDialog
|
||||
@@ -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"
|
||||
|
||||
58
app/View/AnimeScreen/components/download_anime_dialog.kv
Normal file
58
app/View/AnimeScreen/components/download_anime_dialog.kv
Normal 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"
|
||||
25
app/View/AnimeScreen/components/download_anime_dialog.py
Normal file
25
app/View/AnimeScreen/components/download_anime_dialog.py
Normal 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)
|
||||
@@ -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}
|
||||
|
||||
@@ -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)})"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# <MDLabel>:
|
||||
# allow_copy:True
|
||||
# allow_selection:True
|
||||
<MDLabel>:
|
||||
allow_copy:True
|
||||
allow_selection:True
|
||||
@@ -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):
|
||||
|
||||
26
app/main.py
26
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)
|
||||
|
||||
0
app/vids/Death note rewrite/Episode 1/Death note
Normal file
0
app/vids/Death note rewrite/Episode 1/Death note
Normal file
Reference in New Issue
Block a user