renamed app to anixstream

This commit is contained in:
Benedict Xavier Wanyonyi
2024-05-31 18:12:02 +03:00
parent f24912fd1c
commit 7e9060bb2d
126 changed files with 47 additions and 57 deletions

View File

@@ -0,0 +1 @@
from .media_card import MediaCard,MediaCardsContainer

View File

@@ -0,0 +1,4 @@
from kivy.uix.modalview import ModalView
class AnimdlDialogPopup(ModalView):
pass

View File

@@ -0,0 +1,3 @@
<MDLabel>:
allow_copy:True
allow_selection:True

View File

@@ -0,0 +1 @@
from .media_card import MediaCard,MediaCardsContainer

View File

@@ -0,0 +1,2 @@
from .media_player import MediaPopupVideoPlayer
from .media_popup import MediaPopup

View File

@@ -0,0 +1,19 @@
<MediaCardsContainer>
size_hint:1,None
height:max(self.minimum_height,dp(350),container.minimum_height)
container:container
orientation: 'vertical'
padding:"10dp"
spacing:"5dp"
MDLabel:
text:root.list_name
MDScrollView:
size_hint:1,None
height:container.minimum_height
MDBoxLayout:
id:container
spacing:"10dp"
padding:"0dp","10dp","100dp","10dp"
size_hint:None,None
height:self.minimum_height
width:self.minimum_width

View File

@@ -0,0 +1,10 @@
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

@@ -0,0 +1,170 @@
#:import get_hex_from_color kivy.utils.get_hex_from_color
#:set yellow [.9,.9,0,.9]
<SingleLineLabel@MDLabel>:
shorten:True
shorten_from:"right"
adaptive_height:True
<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(530)
width: dp(400)
radius:[5,5,5,5]
md_bg_color:self.theme_cls.backgroundColor
anchor_y: 'top'
player:player
MDBoxLayout:
orientation: 'vertical'
MDRelativeLayout:
size_hint_y: None
height: dp(280)
line_color:root.caller.has_trailer_color
line_width:1
MediaPopupVideoPlayer:
id:player
source: root.caller.trailer_url
thumbnail:app.default_anime_image
state:"play" if root.caller.trailer_url else "stop"
# fit_mode:"fill"
size_hint_y: None
height: dp(280)
PopupBoxLayout:
padding: "10dp","5dp"
spacing:"5dp"
pos_hint: {'left': 1,'top': 1}
MDIcon:
icon: "star"
color:yellow
disabled: not(root.caller.stars[0])
MDIcon:
color:yellow
disabled: not(root.caller.stars[1])
icon: "star"
MDIcon:
color:yellow
disabled: not(root.caller.stars[2])
icon: "star"
MDIcon:
color:yellow
disabled: not(root.caller.stars[3])
icon: "star"
MDIcon:
color:yellow
icon: "star"
disabled: not(root.caller.stars[4])
MDIcon:
color: yellow
icon: "star"
disabled: not(root.caller.stars[5])
MDLabel:
text: f"{root.caller.episodes} Episodes"
halign:"right"
font_style:"Label"
role:"medium"
bold:True
pos_hint: {'center_y': 0.5}
adaptive_height:True
color: 0,0,0,.7
PopupBoxLayout:
padding:"5dp"
pos_hint: {'bottom': 1}
SingleLineLabel:
text:root.caller.media_status
opacity:.8
halign:"left"
font_style:"Label"
role:"medium"
bold:True
pos_hint: {'center_y': .5}
SingleLineLabel:
text:root.caller.first_aired_on
opacity:.8
halign:"right"
font_style:"Label"
role:"medium"
bold:True
pos_hint: {'center_y': .5}
# header
MDBoxLayout:
orientation: 'vertical'
padding:"10dp"
spacing:"10dp"
PopupBoxLayout:
PopupBoxLayout:
pos_hint: {'center_y': 0.5}
TooltipMDIconButton:
tooltip_text:root.caller.title
icon: "play-circle"
on_press:
root.dismiss()
app.show_anime_screen(root.caller.anime_id,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"
on_release:
root.caller.is_in_my_list = not(root.caller.is_in_my_list)
self.icon = "plus-circle" if not(root.caller.is_in_my_list) else "check-circle"
TooltipMDIconButton:
disabled:True
tooltip_text:"Coming soon"
icon: "bell-circle" if not(root.caller.is_in_my_notify) else "bell-check"
PopupBoxLayout:
pos_hint: {'center_y': 0.5}
orientation: 'vertical'
SingleLineLabel:
font_style:"Label"
role:"small"
text: f"[color={get_hex_from_color(self.theme_cls.primaryColor)}]"+"Genres: "+"[/color]"+root.caller.genres
markup:True
PopupBoxLayout:
SingleLineLabel:
font_style:"Label"
role:"small"
markup:True
text: f"[color={get_hex_from_color(self.theme_cls.primaryColor)}]"+"Popularity: "+"[/color]"+root.caller.popularity
SingleLineLabel:
font_style:"Label"
markup:True
role:"small"
text: f"[color={get_hex_from_color(self.theme_cls.primaryColor)}]"+"Favourites: "+"[/color]"+root.caller.favourites
MDScrollView:
size_hint:1,1
do_scroll_y:True
MDLabel:
font_style:"Body"
role:"small"
text:root.caller.description
adaptive_height:True
# footer
PopupBoxLayout:
orientation:"vertical"
SingleLineLabel:
font_style:"Label"
markup:True
role:"small"
text: f"[color={get_hex_from_color(self.theme_cls.primaryColor)}]"+"Next Airing Episode: "+"[/color]"+root.caller.next_airing_episode
SingleLineLabel:
font_style:"Label"
role:"small"
markup:True
text: f"[color={get_hex_from_color(self.theme_cls.primaryColor)}]"+"Studios: " + "[/color]"+root.caller.studios
SingleLineLabel:
font_style:"Label"
markup:True
role:"small"
text: f"[color={get_hex_from_color(self.theme_cls.primaryColor)}]"+"Producers: " + "[/color]"+root.caller.producers
SingleLineLabel:
font_style:"Label"
markup:True
role:"small"
text: f"[color={get_hex_from_color(self.theme_cls.primaryColor)}]"+"Tags: "+"[/color]"+root.caller.tags

View File

@@ -0,0 +1,87 @@
from kivy.properties import ObjectProperty
from kivy.clock import Clock
from kivy.animation import Animation
from kivy.uix.modalview import ModalView
from kivymd.theming import ThemableBehavior
from kivymd.uix.behaviors import (
BackgroundColorBehavior,
StencilBehavior,
CommonElevationBehavior,
HoverBehavior,
)
class MediaPopup(
ThemableBehavior,
HoverBehavior,
StencilBehavior,
CommonElevationBehavior,
BackgroundColorBehavior,
ModalView,
):
caller = ObjectProperty()
player = ObjectProperty()
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.
When the view is opened, it will be faded in with an animation. If you
don't want the animation, use::
view.open(animation=False)
"""
from kivy.core.window import Window
if self._is_open:
return
self._window = Window
self._is_open = True
self.dispatch("on_pre_open")
Window.add_widget(self)
Window.bind(on_resize=self._align_center, on_keyboard=self._handle_keyboard)
self.center = self.caller.to_window(*self.caller.center)
self.fbind("center", self._align_center)
self.fbind("size", self._align_center)
if kwargs.get("animation", True):
ani = Animation(_anim_alpha=1.0, d=self._anim_duration)
ani.bind(on_complete=lambda *_args: self.dispatch("on_open"))
ani.start(self)
else:
self._anim_alpha = 1.0
self.dispatch("on_open")
def _align_center(self, *_args):
if self._is_open:
self.center = self.caller.to_window(*self.caller.center)
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

@@ -0,0 +1,3 @@
<Tooltip>
MDTooltipPlain:
text:root.tooltip_text

View File

@@ -0,0 +1,24 @@
<MediaCard>
adaptive_height:True
spacing:"5dp"
image:"https://s4.anilist.co/file/anilistcdn/media/anime/cover/small/bx163270-oxwgbe43Cpog.jpg"
size_hint_x: None
width:dp(100)
on_release:
self.open()
FitImage:
source:root.cover_image_url
fit_mode:"fill"
size_hint: None, None
width: dp(100)
height: dp(150)
MDDivider:
color:root.has_trailer_color
SingleLineLabel:
font_style:"Label"
role:"medium"
text:root.title
max_lines:2
halign:"center"
color:self.theme_cls.secondaryColor

View File

@@ -0,0 +1,96 @@
from kivy.properties import (
ObjectProperty,
StringProperty,
BooleanProperty,
ListProperty,
NumericProperty,
)
from kivy.clock import Clock
from kivy.uix.behaviors import ButtonBehavior
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.behaviors import HoverBehavior
from .components import MediaPopup
class MediaCard(ButtonBehavior, HoverBehavior, MDBoxLayout):
screen = ObjectProperty()
anime_id = NumericProperty()
title = StringProperty()
is_play = ObjectProperty()
trailer_url = StringProperty()
episodes = StringProperty()
favourites = StringProperty()
popularity = StringProperty()
media_status = StringProperty("Releasing")
is_in_my_list = BooleanProperty(False)
is_in_my_notify = BooleanProperty(False)
genres = StringProperty()
first_aired_on = StringProperty()
description = StringProperty()
producers = StringProperty()
studios = StringProperty()
next_airing_episode = StringProperty()
tags = StringProperty()
stars = ListProperty([0, 0, 0, 0, 0, 0])
cover_image_url = StringProperty()
preview_image = StringProperty()
has_trailer_color = ListProperty([.5, .5, .5, .5])
def __init__(self, trailer_url=None, **kwargs):
super().__init__(**kwargs)
self.orientation = "vertical"
if trailer_url:
self.trailer_url = trailer_url
self.adaptive_size = True
def on_enter(self):
def _open_popup(dt):
if self.hovering:
window = self.get_parent_window()
if window:
for widget in window.children: # type: ignore
if isinstance(widget, MediaPopup):
return
self.open()
Clock.schedule_once(_open_popup, 5)
def on_popup_open(self, popup: MediaPopup):
popup.center = self.center
def on_dismiss(self, popup: MediaPopup):
popup.player.state = "stop"
if popup.player._video:
popup.player._video.unload()
def set_preview_image(self, image):
self.preview_image = image
def set_trailer_url(self, trailer_url):
self.trailer_url = trailer_url
self.has_trailer_color = self.theme_cls.primaryColor
def open(self, *_):
popup = MediaPopup(self)
popup.title = self.title
popup.bind(on_dismiss=self.on_dismiss, on_open=self.on_popup_open)
popup.open(self)
# ---------------respond to user actions and call appropriate model-------------------------
def on_is_in_my_list(self, instance, in_user_anime_list):
if self.screen:
if in_user_anime_list:
self.screen.app.add_anime_to_user_anime_list(self.anime_id)
else:
self.screen.app.remove_anime_from_user_anime_list(self.anime_id)
def on_trailer_url(self, *args):
pass
class MediaCardsContainer(MDBoxLayout):
container = ObjectProperty()
list_name = StringProperty()

View File

@@ -0,0 +1,45 @@
<CommonNavigationRailItem>
MDNavigationRailItemIcon:
icon:root.icon
MDNavigationRailItemLabel:
text: root.text
<NavRail>:
anchor:"top"
type: "labeled"
md_bg_color: self.theme_cls.secondaryContainerColor
MDNavigationRailFabButton:
icon: "home"
on_press:
root.screen.manager_screens.current = "home screen"
CommonNavigationRailItem:
icon: "magnify"
text: "Search"
on_press:
root.screen.manager_screens.current = "search screen"
CommonNavigationRailItem:
icon: "bookmark"
text: "MyList"
on_press:
root.screen.manager_screens.current = "my list screen"
CommonNavigationRailItem:
icon: "download-circle"
text: "Downloads"
on_press:
root.screen.manager_screens.current = "downloads screen"
CommonNavigationRailItem:
icon: "cog"
text: "settings"
on_press:app.open_settings()
CommonNavigationRailItem:
icon: "help-circle"
text: "Help"
on_press:
root.screen.manager_screens.current = "help screen"
CommonNavigationRailItem:
icon: "bug"
text: "debug"
on_press:
root.screen.manager_screens.current = "crashlog screen"

View File

@@ -0,0 +1,3 @@
<Tooltip>
MDTooltipPlain:
text:root.tooltip_text

View File

@@ -0,0 +1,18 @@
<SearchBar>:
pos_hint: {'center_x': 0.5,'top': 1}
padding: "10dp"
adaptive_height:True
size_hint_x:.75
spacing: '20dp'
MDTextField:
size_hint_x:1
required:True
on_text_validate:
app.search_for_anime(args[0])
MDTextFieldLeadingIcon:
icon: "magnify"
MDTextFieldHintText:
text: "Search for anime"
MDIconButton:
pos_hint: {'center_y': 0.5}
icon: "account-circle"