diff --git a/.gitignore b/.gitignore index 4e7bc42..50d6ae9 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ *.ass vids data/ +.project/ crashdump.txt # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/.project/changes_outline.md b/.project/changes_outline.md index 44086ff..403f5c9 100644 --- a/.project/changes_outline.md +++ b/.project/changes_outline.md @@ -1,14 +1,44 @@ # Changes -# # only load trailers when needed +-# # only load trailers when needed - change how media card loader class works - create function to get a trailer url and cache it for 360 secs - refactor the codebase to reflect proposed changes -# # # change how media card loader class works +-# # # change how media card loader class works - remove unnecesarry code - make the media card function to still work so it doesn't cause a break in existing functionality- add a get trailer function which takes a callback -# # Use one media popup for all the media cards +# - # Use one media popup for all the media cards + +# 9 june + +# # search screen + +change the search results layout to be a recycle grid layout + +change the trending bar to be a recyle box layout + +AFFECTED: + +- search results +- trendig bar + +# # anime screen + +# # # Features + +- video player +- controls + - next button + previous button + - auto next + - refresh button + - play in mpv button +- episodes bar +- servers bar + +NOTE: + the affected: + anime screen model, view, controller diff --git a/fastanime/Controller/anime_screen.py b/fastanime/Controller/anime_screen.py index b3f60ab..3742768 100644 --- a/fastanime/Controller/anime_screen.py +++ b/fastanime/Controller/anime_screen.py @@ -21,6 +21,9 @@ class AnimeScreenController: anime_title ) self.view.current_links = self.model.get_episode_streams(episode) + # TODO: add auto start + # + # self.view.current_link = self.view.current_links[0]["gogoanime"][0] def update_anime_view(self, id, title, caller_screen_name): self.fetch_streams(title) diff --git a/fastanime/Controller/home_screen.py b/fastanime/Controller/home_screen.py index c0e4b6e..fe9195b 100644 --- a/fastanime/Controller/home_screen.py +++ b/fastanime/Controller/home_screen.py @@ -119,9 +119,9 @@ class HomeScreenController: self.populate_errors = [] Clock.schedule_once(lambda _: self.trending_anime(), 1) Clock.schedule_once(lambda _: self.highest_scored_anime(), 2) - Clock.schedule_once(lambda _: self.popular_anime(), 3) + Clock.schedule_once(lambda _: self.recently_updated_anime(), 5) + # Clock.schedule_once(lambda _: self.popular_anime(), 3) # Clock.schedule_once(lambda _: self.favourite_anime(), 4) - # Clock.schedule_once(lambda _: self.recently_updated_anime(), 5) # Clock.schedule_once(lambda _: self.upcoming_anime(), 6) if self.populate_errors: diff --git a/fastanime/Controller/search_screen.py b/fastanime/Controller/search_screen.py index bb8055a..f159fff 100644 --- a/fastanime/Controller/search_screen.py +++ b/fastanime/Controller/search_screen.py @@ -21,10 +21,10 @@ class SearchScreenController: """Gets and adds the trending anime to the search screen""" trending_cards_generator = self.model.get_trending_anime() if isgenerator(trending_cards_generator): - self.view.trending_anime_sidebar.clear_widgets() + # self.view.trending_anime_sidebar.data = [] for card in trending_cards_generator: - card.screen = self.view - card.pos_hint = {"center_x": 0.5} + card["screen"] = self.view + # card["pos_hint"] = {"center_x": 0.5} self.view.update_trending_sidebar(card) else: Logger.error("Home Screen:Failed to load trending anime") @@ -34,7 +34,7 @@ class SearchScreenController: search_Results = self.model.search_for_anime(anime_title, **kwargs) if isgenerator(search_Results): for result_card in search_Results: - result_card.screen = self.view + result_card["screen"] = self.view self.view.update_layout(result_card) Clock.schedule_once( lambda _: self.view.update_pagination(self.model.pagination_info) diff --git a/fastanime/Model/anime_screen.py b/fastanime/Model/anime_screen.py index ab94659..10d5586 100644 --- a/fastanime/Model/anime_screen.py +++ b/fastanime/Model/anime_screen.py @@ -6,7 +6,7 @@ from fuzzywuzzy import fuzz def anime_title_percentage_match( - possible_user_requested_anime_title: str, title: str + possible_user_requested_anime_title: str, title: tuple ) -> int: """Returns the percentage match between the possible title and user title @@ -19,7 +19,10 @@ def anime_title_percentage_match( """ print(locals()) - percentage_ratio = fuzz.ratio(title, possible_user_requested_anime_title) + percentage_ratio = max( + fuzz.ratio(title[0].lower(), possible_user_requested_anime_title.lower()), + fuzz.ratio(title[1].lower(), possible_user_requested_anime_title.lower()), + ) print(percentage_ratio) return percentage_ratio @@ -36,11 +39,11 @@ class AnimeScreenModel(BaseScreenModel): current_anime_id = "0" current_title = "" - def get_anime_data_from_provider(self, anime_title: str, id=None): + def get_anime_data_from_provider(self, anime_title: tuple, id=None): if self.current_title == anime_title and self.current_anime_data: return self.current_anime_data - search_results = anime_provider.search_for_anime(anime_title) + search_results = anime_provider.search_for_anime(anime_title[0]) if search_results: _search_results = search_results["shows"]["edges"] diff --git a/fastanime/Utility/media_card_loader.py b/fastanime/Utility/media_card_loader.py index fc21047..b775fe4 100644 --- a/fastanime/Utility/media_card_loader.py +++ b/fastanime/Utility/media_card_loader.py @@ -16,13 +16,22 @@ class MediaCardDataLoader(object): anime_item: AnilistBaseMediaDataSchema, ): media_card_data = {} + media_card_data["viewclass"] = "MediaCard" media_card_data["anime_id"] = anime_id = anime_item["id"] # TODO: ADD language preference if anime_item["title"].get("romaji"): media_card_data["title"] = anime_item["title"]["romaji"] + media_card_data["_title"] = ( + anime_item["title"]["romaji"], + str(anime_item["title"]["english"]), + ) else: media_card_data["title"] = anime_item["title"]["english"] + media_card_data["_title"] = ( + anime_item["title"]["english"], + str(anime_item["title"]["romaji"]), + ) media_card_data["cover_image_url"] = anime_item["coverImage"]["medium"] diff --git a/fastanime/View/AnimeScreen/anime_screen.kv b/fastanime/View/AnimeScreen/anime_screen.kv index 90601bc..72f0730 100644 --- a/fastanime/View/AnimeScreen/anime_screen.kv +++ b/fastanime/View/AnimeScreen/anime_screen.kv @@ -6,49 +6,78 @@ adaptive_height:True bold:True +: + pos_hint:{"center_y":0.5,"center_x":0.5} + on_press:root.change_episode_callback(root.text) + radius: 10 + MDButtonText: + text:root.text + + + : md_bg_color: self.theme_cls.backgroundColor + episodes_container:episodes_container MDBoxLayout: + padding:"10dp" orientation: 'vertical' MDBoxLayout: adaptive_height:True MDIconButton: icon:"arrow-left" on_press:root.manager_screens.current = root.caller_screen_name - MDTextField: - on_text_validate: - root.update_current_link(self) - - VideoPlayer: - source:root.current_link + + MDBoxLayout: + VideoPlayer: + source:root.current_link AnimeBoxLayout: - AnimeLabel: - text:"Sub" - MDSegmentedButton: - id:pl - multiselect:False - MDSegmentedButtonItem: - on_active: - pl.selected_segments = [self] - root.update_current_video_stream("gogoanime") - MDSegmentButtonLabel: - text:"GoGoAnime" - MDSegmentedButtonItem: - on_active: - root.update_current_video_stream("dropbox") - pl.selected_segments = [self] - MDSegmentButtonLabel: - text:"DropBox" - MDSegmentedButtonItem: - on_active: - root.update_current_video_stream("sharepoint") - pl.selected_segments = [self] - MDSegmentButtonLabel: - text:"Share Point" - MDSegmentedButtonItem: - on_active: - root.update_current_video_stream("wetransfer") - pl.selected_segments = [self] - MDSegmentButtonLabel: - text:"weTransfer" + padding: "20dp" + radius:5 + spacing:"10dp" + md_bg_color: self.theme_cls.surfaceContainerLowColor + AnimeBoxLayout: + AnimeLabel: + text:"Sub servers: " + MDSegmentedButton: + id:pl + multiselect:False + MDSegmentedButtonItem: + on_active: + pl.selected_segments = [self] + root.update_current_video_stream("gogoanime") + MDSegmentButtonLabel: + text:"GoGoAnime" + MDSegmentedButtonItem: + on_active: + root.update_current_video_stream("dropbox") + pl.selected_segments = [self] + MDSegmentButtonLabel: + text:"DropBox" + MDSegmentedButtonItem: + on_active: + root.update_current_video_stream("sharepoint") + pl.selected_segments = [self] + MDSegmentButtonLabel: + text:"Share Point" + MDSegmentedButtonItem: + on_active: + root.update_current_video_stream("wetransfer") + pl.selected_segments = [self] + MDSegmentButtonLabel: + text:"weTransfer" + MDDivider: + MDRecycleView: + id: episodes_container + size_hint_y:None + height:"50dp" + key_viewclass:"viewclass" + RecycleBoxLayout: + size_hint: None,1 + key_size:"width" + spacing:"10dp" + width:self.minimum_width + default_size_hint:0,0 + default_size:30,30 + default_pos_hint:{"center_y":0.5,"center_x":0.5} + diff --git a/fastanime/View/AnimeScreen/anime_screen.py b/fastanime/View/AnimeScreen/anime_screen.py index f96a9a1..4effc31 100644 --- a/fastanime/View/AnimeScreen/anime_screen.py +++ b/fastanime/View/AnimeScreen/anime_screen.py @@ -1,33 +1,60 @@ from kivy.properties import ListProperty, ObjectProperty, StringProperty +from kivy.uix.widget import Factory +from kivymd.uix.button import MDButton + from ...libs.anilist import AnilistBaseMediaDataSchema from ...View.base_screen import BaseScreenView +class EpisodeButton(MDButton): + text = StringProperty() + change_episode_callback = ObjectProperty() + + +Factory.register("EpisodeButton", cls=EpisodeButton) + + class AnimeScreenView(BaseScreenView): """The anime screen view""" - current_link = StringProperty( - "https://uc951f724c20bbec8df447bac605.dl.dropboxusercontent.com/cd/0/get/CUdx6k2qw-zqY86ftfFHqkmPqGuVrfjpE68B_EkcvZXcZLnjim_ZTHd-qNVb_mEbos9UsuhY8FJGdgf86RUZ-IJqZtz3tt8_CUVTloQAeZ47HtNiKjQ0ESvYdLuwqDjqwK2rNfsfiZI2cXBaKiUyJtljEeRL8whSff2wA9Z4tX1cow/file" - ) + current_link = StringProperty() current_links = ListProperty([]) current_anime_data = ObjectProperty() caller_screen_name = ObjectProperty() - current_title = StringProperty() + current_title = () + episodes_container = ObjectProperty() - def update_layout(self, data: AnilistBaseMediaDataSchema, caller_screen_name: str): - return + def __init__(self, **kwargs): + super().__init__(**kwargs) + # self.update_episodes(100) + + def update_episodes(self, episodes_list): + self.episodes_container.data = [] + for episode in episodes_list: + self.episodes_container.data.append( + { + "viewclass": "EpisodeButton", + "text": str(episode), + "change_episode_callback": lambda x=episode: self.update_current_episode( + x + ), + } + ) + + def on_current_anime_data(self, instance, value): + data = value["show"] + self.update_episodes(data["availableEpisodesDetail"]["sub"][::-1]) + + def update_current_episode(self, episode): + self.controller.fetch_streams(self.current_title, episode) + # self.current_link = self.current_links[0]["gogoanime"][0] def update_current_video_stream(self, server, is_dub=False): for link in self.current_links: if stream_link := link.get(server): - print(link) self.current_link = stream_link[0] break - # print(link) - - def update_current_link(self, field): - self.controller.fetch_streams(self.current_title, field.text) def add_to_user_anime_list(self, *args): self.app.add_anime_to_user_anime_list(self.model.anime_id) diff --git a/fastanime/View/SearchScreen/components/trending_sidebar.kv b/fastanime/View/SearchScreen/components/trending_sidebar.kv index 33fe030..1dbb321 100644 --- a/fastanime/View/SearchScreen/components/trending_sidebar.kv +++ b/fastanime/View/SearchScreen/components/trending_sidebar.kv @@ -1,6 +1,23 @@ : - orientation: 'vertical' - adaptive_height:True md_bg_color:self.theme_cls.surfaceContainerLowColor + padding:"25dp","25dp","25dp","200dp" pos_hint: {'center_x': 0.5} - padding:"25dp","25dp","25dp","200dp" \ No newline at end of file + key_viewclass:"viewclass" + size_hint: None,1 + width:"250dp" + pos_hint: {'center_x':.5} + RecycleBoxLayout: + orientation: 'vertical' + key_size:"height" + key_viewclass:"viewclass" + pos_hint: {'center_x': 0.8} + size_hint:None,None + default_size_hint:None, None + default_pos_hint:{"center_x":0.8} + default_size:dp(150),dp(100) + width:"250dp" + spacing:"10dp" + height:max(self.minimum_height,500) +#padding:"0dp","10dp","100dp","10dp" + # height:max(self.parent.parent.height,self.minimum_height+100) + diff --git a/fastanime/View/SearchScreen/components/trending_sidebar.py b/fastanime/View/SearchScreen/components/trending_sidebar.py index 682662a..f5adfd3 100644 --- a/fastanime/View/SearchScreen/components/trending_sidebar.py +++ b/fastanime/View/SearchScreen/components/trending_sidebar.py @@ -1,5 +1,5 @@ -from kivymd.uix.boxlayout import MDBoxLayout +from kivymd.uix.recycleview import MDRecycleView -class TrendingAnimeSideBar(MDBoxLayout): +class TrendingAnimeSideBar(MDRecycleView): pass diff --git a/fastanime/View/SearchScreen/search_screen.kv b/fastanime/View/SearchScreen/search_screen.kv index 8fd70c7..e6c1cc9 100644 --- a/fastanime/View/SearchScreen/search_screen.kv +++ b/fastanime/View/SearchScreen/search_screen.kv @@ -33,17 +33,22 @@ orientation: 'vertical' size_hint_y:None height:max(self.parent.parent.height,self.minimum_height) - MDGridLayout: - pos_hint: {'center_x': 0.5} + MDRecycleView: id:search_results_container - spacing: '40dp' - padding: "25dp","50dp","75dp","200dp" - cols:3 if root.width <= 1100 else 5 - size_hint_y:None - height:max(self.parent.parent.height,self.minimum_height) + key_viewclass:"viewclass" + MDRecycleGridLayout: + pos_hint: {'center_x': 0.5} + spacing: '40dp' + padding: "25dp","50dp","75dp","200dp" + default_size_hint:None,None + default_size:dp(100),dp(150) + cols:3 if root.width <= 1100 else 5 + size_hint_y:None + height:max(self.parent.parent.height,self.minimum_height) SearchResultsPagination: id:search_results_pagination search_view:root + MDBoxLayout: orientation:"vertical" size_hint_y:1 @@ -51,8 +56,5 @@ width: dp(250) HeaderLabel: text:"Trending" - MDScrollView: - TrendingAnimeSideBar: - id:trending_anime_sidebar - height:max(self.parent.parent.height,self.minimum_height) - + TrendingAnimeSideBar: + id:trending_anime_sidebar diff --git a/fastanime/View/SearchScreen/search_screen.py b/fastanime/View/SearchScreen/search_screen.py index ef17cc2..4b346b5 100644 --- a/fastanime/View/SearchScreen/search_screen.py +++ b/fastanime/View/SearchScreen/search_screen.py @@ -28,7 +28,7 @@ class SearchScreenView(BaseScreenView): if search_term and not (self.is_searching): self.search_term = search_term - self.search_results_container.clear_widgets() + self.search_results_container.data = [] if filters := self.filters.filters: Clock.schedule_once( lambda _: self.controller.requested_search_for_anime( @@ -43,7 +43,7 @@ class SearchScreenView(BaseScreenView): ) def update_layout(self, widget): - self.search_results_container.add_widget(widget) + self.search_results_container.data.append(widget) def update_pagination(self, pagination_info): self.search_results_pagination.current_page = self.current_page = ( @@ -65,4 +65,4 @@ class SearchScreenView(BaseScreenView): self.handle_search_for_anime(page=page) def update_trending_sidebar(self, trending_anime): - self.trending_anime_sidebar.add_widget(trending_anime) + self.trending_anime_sidebar.data.append(trending_anime) diff --git a/fastanime/View/components/media_card/components/media_cards_container.kv b/fastanime/View/components/media_card/components/media_cards_container.kv index 80880c6..dec8f95 100644 --- a/fastanime/View/components/media_card/components/media_cards_container.kv +++ b/fastanime/View/components/media_card/components/media_cards_container.kv @@ -9,15 +9,14 @@ bold:True adaptive_height:True text:root.list_name - MDScrollView: - MDRecycleView: - id:container - key_viewclass:"viewclass" - key_size:"width" - RecycleBoxLayout: - size_hint:None,1 - width:self.minimum_width - default_size_hint:None, None - default_size:dp(150),dp(100) - spacing:"10dp" - padding:"0dp","10dp","100dp","10dp" + MDRecycleView: + id:container + key_viewclass:"viewclass" + key_size:"width" + RecycleBoxLayout: + size_hint:None,1 + width:self.minimum_width + default_size_hint:None, None + default_size:dp(150),dp(100) + spacing:"10dp" + padding:"0dp","10dp","100dp","10dp" diff --git a/fastanime/View/components/media_card/components/media_popup.kv b/fastanime/View/components/media_card/components/media_popup.kv index a564ad1..87ebcd5 100644 --- a/fastanime/View/components/media_card/components/media_popup.kv +++ b/fastanime/View/components/media_card/components/media_popup.kv @@ -30,9 +30,11 @@ # TODO: Remove the test source MediaPopupVideoPlayer: id:player - source: root.caller.trailer_url if root.caller.trailer_url else 'https://www088.vipanicdn.net/streamhls/abae70787c7bd2fcd4fab986c2a5aeba/ep.7.1703900604.m3u8' + source: root.caller.trailer_url #if root.caller.trailer_url else 'https://www088.vipanicdn.net/streamhls/abae70787c7bd2fcd4fab986c2a5aeba/ep.7.1703900604.m3u8' thumbnail:app.default_anime_image - state:"play" if root.caller.trailer_url else "stop" + #state:"play" if root.caller.trailer_url else "stop" + on_state: + root.caller._get_trailer() # fit_mode:"fill" size_hint_y: None height: dp(280) @@ -103,11 +105,12 @@ PopupBoxLayout: pos_hint: {'center_y': 0.5} TooltipMDIconButton: - tooltip_text:root.caller.title + tooltip_text:"Play" + icon: "play-circle" on_press: root.dismiss() - app.show_anime_screen(root.caller.anime_id,root.caller.title,root.caller.screen.name) + app.show_anime_screen(root.caller.anime_id,root.caller._title,root.caller.screen.name) TooltipMDIconButton: tooltip_text:"Add to your anime list" icon: "plus-circle" if not(root.caller.is_in_my_list) else "check-circle" diff --git a/fastanime/View/components/media_card/media_card.kv b/fastanime/View/components/media_card/media_card.kv index ef2ba9c..00f91ab 100644 --- a/fastanime/View/components/media_card/media_card.kv +++ b/fastanime/View/components/media_card/media_card.kv @@ -3,6 +3,7 @@ spacing:"5dp" size_hint_x: None width:dp(100) + height: dp(150) FitImage: source:root.cover_image_url fit_mode:"fill" diff --git a/fastanime/View/components/media_card/media_card.py b/fastanime/View/components/media_card/media_card.py index 4cb5b88..83f61ed 100644 --- a/fastanime/View/components/media_card/media_card.py +++ b/fastanime/View/components/media_card/media_card.py @@ -39,6 +39,7 @@ class MediaCard(HoverBehavior, MDBoxLayout): preview_image = StringProperty() has_trailer_color = ListProperty([0.5, 0.5, 0.5, 0.5]) _popup_opened = False + _title = () def __init__(self, trailer_url=None, **kwargs): super().__init__(**kwargs) @@ -118,19 +119,19 @@ class MediaCard(HoverBehavior, MDBoxLayout): popup.bind(on_dismiss=self.on_dismiss, on_open=self.on_popup_open) popup.open(self) - def _get_trailer(dt): - if trailer := self._trailer_url: - # trailer stuff - from ....Utility.media_card_loader import media_card_loader + def _get_trailer(self): + if self.trailer_url: + return + if trailer := self._trailer_url: + # trailer stuff + from ....Utility.media_card_loader import media_card_loader - if trailer_url := media_card_loader.get_trailer_from_pytube( - trailer, self.title - ): - self.trailer_url = trailer_url - else: - self._trailer_url = "" - - Clock.schedule_once(_get_trailer, 1) + if trailer_url := media_card_loader.get_trailer_from_pytube( + trailer, self.title + ): + self.trailer_url = trailer_url + else: + self._trailer_url = "" # ---------------respond to user actions and call appropriate model------------------------- def on_is_in_my_list(self, instance, in_user_anime_list): diff --git a/fastanime/View/screens.py b/fastanime/View/screens.py index 23f645b..709dfcc 100644 --- a/fastanime/View/screens.py +++ b/fastanime/View/screens.py @@ -26,14 +26,14 @@ screens = { "model": SearchScreenModel, "controller": SearchScreenController, }, - "my list screen": { - "model": MyListScreenModel, - "controller": MyListScreenController, - }, "anime screen": { "model": AnimeScreenModel, "controller": AnimeScreenController, }, + "my list screen": { + "model": MyListScreenModel, + "controller": MyListScreenController, + }, "crashlog screen": { "model": CrashLogScreenModel, "controller": CrashLogScreenController,