mirror of
https://github.com/Benexl/FastAnime.git
synced 2025-12-29 14:13:22 -08:00
feat:Made trailer player better
This commit is contained in:
@@ -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)}")
|
||||
|
||||
@@ -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 []
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
id:rankings_bar
|
||||
Controls:
|
||||
screen:root
|
||||
cols:3 if root.width < 1100 else 5
|
||||
MDBoxLayout:
|
||||
adaptive_height:True
|
||||
padding:"20dp"
|
||||
|
||||
@@ -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-----
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -39,3 +39,4 @@ class DownloadAnimeDialog(
|
||||
default_cmds["quality"] = quality
|
||||
|
||||
app.download_anime(self.anime_id, default_cmds)
|
||||
self.dismiss()
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -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
40
app/anixstream_.spec
Normal 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"
|
||||
)
|
||||
@@ -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
56
app/k.spec
Normal 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',
|
||||
)
|
||||
@@ -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
56
app/main.spec
Normal 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
BIN
app/mpv-shot0001.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 202 KiB |
BIN
app/mpv-shot0002.jpg
Normal file
BIN
app/mpv-shot0002.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 240 KiB |
Reference in New Issue
Block a user