feat:Made trailer player better

This commit is contained in:
Benedict Xavier Wanyonyi
2024-05-31 11:20:15 +03:00
parent 1e63e6cc57
commit f24912fd1c
22 changed files with 241 additions and 41 deletions

View File

@@ -23,8 +23,8 @@ class HomeScreenController:
def __init__(self, model:HomeScreenModel):
self.model = model # Model.main_screen.MainScreenModel
self.view = HomeScreenView(controller=self, model=self.model)
if self.view.app.config.get("Preferences","is_startup_anime_enable")=="1": # type: ignore
Clock.schedule_once(lambda _:self.populate_home_screen())
# if self.view.app.config.get("Preferences","is_startup_anime_enable")=="1": # type: ignore
# Clock.schedule_once(lambda _:self.populate_home_screen())
def get_view(self) -> HomeScreenView:
return self.view
@@ -109,12 +109,12 @@ class HomeScreenController:
def populate_home_screen(self):
self.populate_errors = []
Clock.schedule_once(lambda _:self.trending_anime())
Clock.schedule_once(lambda _:self.highest_scored_anime())
Clock.schedule_once(lambda _:self.popular_anime())
Clock.schedule_once(lambda _: self.favourite_anime())
Clock.schedule_once(lambda _:self.recently_updated_anime())
Clock.schedule_once(lambda _:self.upcoming_anime())
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.favourite_anime(),4)
Clock.schedule_once(lambda _:self.recently_updated_anime(),5)
Clock.schedule_once(lambda _:self.upcoming_anime(),6)
if self.populate_errors:
show_notification(f"Failed to fetch all home screen data",f"Theres probably a problem with your internet connection or anilist servers are down.\nFailed include:{', '.join(self.populate_errors)}")

View File

@@ -19,18 +19,33 @@ class MyListScreenController:
def __init__(self, model:MyListScreenModel):
self.model = model
self.view = MyListScreenView(controller=self, model=self.model)
self.requested_update_my_list_screen()
if len(self.requested_update_my_list_screen())>30:
self.requested_update_my_list_screen(2)
def get_view(self) -> MyListScreenView:
return self.view
def requested_update_my_list_screen(self):
def requested_update_my_list_screen(self,page=None):
user_anime_list = user_data_helper.get_user_anime_list()
if animes_to_add:=difference(user_anime_list,self.model.already_in_user_anime_list):
Logger.info("My List Screen:User anime list change;updating screen")
anime_cards = self.model.update_my_anime_list_view(animes_to_add)
# if thirty:=len(animes_to_add)>30:
# self.model.already_in_user_anime_list = user_anime_list[:30]
# else:
anime_cards = self.model.update_my_anime_list_view(animes_to_add,page)
self.model.already_in_user_anime_list = user_anime_list
if isgenerator(anime_cards):
for result_card in anime_cards:
result_card.screen = self.view
self.view.update_layout(result_card)
return animes_to_add
elif page:
anime_cards = self.model.update_my_anime_list_view(self.model.already_in_user_anime_list,page)
# self.model.already_in_user_anime_list = user_anime_list
if isgenerator(anime_cards):
for result_card in anime_cards:
result_card.screen = self.view
self.view.update_layout(result_card)
return []

View File

@@ -5,8 +5,8 @@ from Utility import MediaCardLoader,show_notification
class MyListScreenModel(BaseScreenModel):
already_in_user_anime_list = []
def update_my_anime_list_view(self,not_yet_in_user_anime_list:list,**kwargs):
success,self.data = AniList.search(id_in=not_yet_in_user_anime_list)
def update_my_anime_list_view(self,not_yet_in_user_anime_list:list,page=None):
success,self.data = AniList.search(id_in=not_yet_in_user_anime_list,page=page,sort="SCORE_DESC")
if success:
return self.media_card_generator()
else:

View File

@@ -15,18 +15,18 @@ if local_data_path:=os.getenv("LOCALAPPDATA"):
config_dir = os.path.join(local_data_path,".config")
if not os.path.exists(config_dir):
os.mkdir(config_dir)
animdl_config_folder_location = os.path.join(config_dir, ".animdl")
animdl_config_folder_location = os.path.join(config_dir, "animdl")
else:
user_profile_path = plyer.storagepath.get_home_dir() # type: ignore
animdl_config_folder_location = os.path.join(user_profile_path, ".animdl")
if not os.path.exists(animdl_config_folder_location):
os.mkdir(animdl_config_folder_location)
if not os.path.exists(animdl_config_folder_location):
os.mkdir(animdl_config_folder_location)
animdl_config_location = os.path.join(animdl_config_folder_location, "config.yml")
# print(animdl_config_location)
animdl_config = YamlParser(
animdl_config_location,
{"default_player": "mpv", "default_provider": "AllAnime", "quality_string": "best"},
{"default_player": "mpv", "default_provider": "allanime", "quality_string": "best"},
AnimdlConfig,
)

View File

@@ -47,6 +47,7 @@
id:rankings_bar
Controls:
screen:root
cols:3 if root.width < 1100 else 5
MDBoxLayout:
adaptive_height:True
padding:"20dp"

View File

@@ -42,8 +42,8 @@ class AnimeScreenView(BaseScreenView):
# update header
self.header.titles = f"{english_title}\n{jp_title}"
# if banner_image := data["bannerImage"]:
self.header.banner_image = data["bannerImage"]
if banner_image := data["bannerImage"]:
self.header.banner_image = banner_image
# -----side bar-----

View File

@@ -64,6 +64,6 @@ class AnimdlStreamDialog(
cmds = [*cmds, "-q", quality]
app.watch_on_animdl(custom_options=cmds)
self.dismiss()
def stream_anime(self, app):
Clock.schedule_once(lambda _: self._stream_anime(app))

View File

@@ -3,7 +3,7 @@
padding:"10dp"
spacing:"10dp"
pos_hint: {'center_x': 0.5}
# StackLayout:
cols:3
MDButton:
on_press:
root.screen.add_to_user_anime_list()

View File

@@ -1,9 +1,9 @@
from kivy.properties import ObjectProperty
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.gridlayout import MDGridLayout
class Controls(MDBoxLayout):
class Controls(MDGridLayout):
"""The diferent controls available"""
screen = ObjectProperty()

View File

@@ -39,3 +39,4 @@ class DownloadAnimeDialog(
default_cmds["quality"] = quality
app.download_anime(self.anime_id, default_cmds)
self.dismiss()

View File

@@ -21,7 +21,7 @@
spacing: '40dp'
padding: "100dp","50dp","10dp","200dp"
id:user_anime_list_container
cols:5
cols:4 if root.width<=1100 else 5
size_hint_y:None
height:self.minimum_height

View File

@@ -1,5 +1,10 @@
from kivy.uix.video import Video
class MediaPopupVideoPlayer(Video):
pass
from kivy.uix.videoplayer import VideoPlayer
# TODO: make fullscreen exp better
class MediaPopupVideoPlayer(VideoPlayer):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def on_fullscreen(self, instance, value):
super().on_fullscreen(instance, value)
# self.state = "pause"

View File

@@ -8,11 +8,13 @@
<PopupBoxLayout@MDBoxLayout>
adaptive_height:True
<Video>:
fit_mode:"fill"
# TODO: subdivide each main component to its own file
<MediaPopup>
size_hint: None, None
height: dp(500)
height: dp(530)
width: dp(400)
radius:[5,5,5,5]
md_bg_color:self.theme_cls.backgroundColor
@@ -22,17 +24,17 @@
orientation: 'vertical'
MDRelativeLayout:
size_hint_y: None
height: dp(250)
height: dp(280)
line_color:root.caller.has_trailer_color
line_width:2
line_width:1
MediaPopupVideoPlayer:
id:player
source:root.caller.trailer_url
preview:app.default_anime_image
source: root.caller.trailer_url
thumbnail:app.default_anime_image
state:"play" if root.caller.trailer_url else "stop"
fit_mode:"fill"
# fit_mode:"fill"
size_hint_y: None
height: dp(250)
height: dp(280)
PopupBoxLayout:
padding: "10dp","5dp"
spacing:"5dp"

View File

@@ -26,6 +26,7 @@ class MediaPopup(
def __init__(self, caller, *args, **kwarg):
self.caller = caller
super(MediaPopup, self).__init__(*args, **kwarg)
self.player.bind(fullscreen=self.handle_clean_fullscreen_transition)
def open(self, *_args, **kwargs):
"""Display the modal in the Window.
@@ -62,7 +63,25 @@ class MediaPopup(
def on_leave(self, *args):
def _leave(dt):
self.player.state = "stop"
if self.player._video:
self.player._video.unload()
if not self.hovering:
self.dismiss()
Clock.schedule_once(_leave, 2)
def handle_clean_fullscreen_transition(self,instance,fullscreen):
if not fullscreen:
if not self._is_open:
instance.state = "stop"
if vid:=instance._video:
vid.unload()
else:
instance.state = "stop"
if vid:=instance._video:
vid.unload()
self.dismiss()

View File

@@ -36,7 +36,7 @@ class MediaCard(ButtonBehavior, HoverBehavior, MDBoxLayout):
stars = ListProperty([0, 0, 0, 0, 0, 0])
cover_image_url = StringProperty()
preview_image = StringProperty()
has_trailer_color = ListProperty([1, 1, 1, 0])
has_trailer_color = ListProperty([.5, .5, .5, .5])
def __init__(self, trailer_url=None, **kwargs):
super().__init__(**kwargs)
@@ -62,7 +62,9 @@ class MediaCard(ButtonBehavior, HoverBehavior, MDBoxLayout):
popup.center = self.center
def on_dismiss(self, popup: MediaPopup):
popup.player.unload()
popup.player.state = "stop"
if popup.player._video:
popup.player._video.unload()
def set_preview_image(self, image):
self.preview_image = image

40
app/anixstream_.spec Normal file
View File

@@ -0,0 +1,40 @@
# -*- mode: python ; coding: utf-8 -*-
import sys
import os
from kivy_deps import sdl2, glew
from kivymd.icon_definitions import md_icons
from kivymd import hooks_path as kivymd_hooks_path
path = os.path.abspath(".")
a = Analysis(
["main.py"],
datas=[
('./assets/*', './assets'),("./data/*","./data/*"),("./configs/*","./configs")
],
pathex=[path],
hiddenimports=["kivymd.icon_definitions.md_icons"],
hookspath=[kivymd_hooks_path],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=None,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=None)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],
debug=False,
strip=False,
upx=True,
name="AniXStream",
console=False,
icon="./assets/logo.ico"
)

View File

@@ -43,6 +43,6 @@
"desc": "Sets the animdl default player to use",
"section": "PlayerSelection",
"key": "default_player",
"options": ["mpv", "vlc", "ffpyplayer", "celluloid", "iina"]
"options": ["mpv", "vlc", "ffplay", "celluloid", "iina"]
}
]

56
app/k.spec Normal file
View File

@@ -0,0 +1,56 @@
# -*- mode: python ; coding: utf-8 -*-
import sys
import os
from kivy_deps import sdl2, glew
from kivymd.icon_definitions import md_icons
from kivymd import hooks_path as kivymd_hooks_path
path = os.path.abspath(".")
a = Analysis(
["main.py"],
datas=[
('./assets/*', './assets'),("./data/*","./data/*"),("./configs/*","./configs")
],
pathex=[path],
hiddenimports=["kivymd.icon_definitions.md_icons"],
hookspath=[kivymd_hooks_path],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=None,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=None)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],
debug=False,
strip=False,
upx=True,
name="AniXStream",
console=True,
icon="./assets/logo.ico"
bootloader_ignore_signals=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
coll = COLLECT(
exe,
a.binaries,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='anixstream',
)

View File

@@ -64,6 +64,7 @@ class AniXStreamApp(MDApp):
animdl_streaming_subprocess: Popen | None = None
default_anime_image = resource_find(random.choice(["default_1.jpg","default.jpg"]))
default_banner_image = resource_find(random.choice(["banner_1.jpg","banner.jpg"]))
# default_video = resource_find("Billyhan_When you cant afford Crunchyroll to watch anime.mp4")
def worker(self, queue: Queue):
while True:
@@ -121,10 +122,12 @@ class AniXStreamApp(MDApp):
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")
self.home_screen = self.manager_screens.get_screen("home screen")
return self.manager_screens
def on_start(self, *args):
pass
if self.config.get("Preferences","is_startup_anime_enable")=="1": # type: ignore
Clock.schedule_once(lambda _:self.home_screen.controller.populate_home_screen(),1)
def generate_application_screens(self) -> None:
for i, name_screen in enumerate(screens.keys()):

56
app/main.spec Normal file
View File

@@ -0,0 +1,56 @@
# -*- mode: python ; coding: utf-8 -*-
import sys
import os
from kivy_deps import sdl2, glew
from kivymd.icon_definitions import md_icons
from kivymd import hooks_path as kivymd_hooks_path
path = os.path.abspath(".")
a = Analysis(
["main.py"],
datas=[
('./assets/*', './assets'),("./data/*","./data/*"),("./configs/*","./configs")
],
pathex=[path],
hiddenimports=["kivymd.icon_definitions.md_icons"],
hookspath=[kivymd_hooks_path],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=None,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=None)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],
debug=False,
strip=False,
upx=True,
name="AniXStream",
console=True,
icon="./assets/logo.ico"
bootloader_ignore_signals=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
coll = COLLECT(
exe,
a.binaries,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='anixstream',
)

BIN
app/mpv-shot0001.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

BIN
app/mpv-shot0002.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB