completed the basic ui and anilist module

This commit is contained in:
Benedict Xavier Wanyonyi
2024-05-15 20:33:20 +03:00
commit ffe5db9e33
44 changed files with 3775 additions and 0 deletions

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,249 @@
#:import get_hex_from_color kivy.utils.get_hex_from_color
#:set yellow [.9,.9,0,.9]
# overides and customization
<MDLabel>:
adaptive_height:True
max_lines:1
valign:"top"
shorten_from:"right"
shorten:True
<MDLabelShortened@MDLabel>
bold:True
<MDIcon>
valign:"center"
<MDBoxLayout>:
# adaptive_height:True
size_hint_y:None
height:self.minimum_height
# custom components
<Tooltip>
MDTooltipPlain:
text:root.tooltip_text
# <TooltipMDIconButton>
<MediaPopup>
size_hint: None, None
height: dp(500)
width: dp(400)
radius:[5,5,5,5]
md_bg_color:self.theme_cls.backgroundColor
anchor_y: 'top'
player:player
MDBoxLayout:
orientation: 'vertical'
adaptive_height:False
anchor_y: 'top'
MDRelativeLayout:
size_hint_y: None
height: dp(250)
line_color:root.caller.has_trailer_color
line_width:2
MediaPopupVideoPlayer:
id:player
source:root.caller.trailer_url
preview:root.caller.preview_image
state:"play" if root.caller.trailer_url else "stop"
fit_mode:"fill"
size_hint_y: None
height: dp(250)
MDBoxLayout:
padding: "10dp","5dp"
spacing:"5dp"
pos_hint: {'left': 1,'top': 1}
adaptive_height:True
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
MDBoxLayout:
padding:"5dp"
pos_hint: {'bottom': 1}
adaptive_height:True
MDLabel:
text:root.caller.media_status
opacity:.8
halign:"left"
font_style:"Label"
role:"medium"
bold:True
pos_hint: {'center_y': .5}
adaptive_height:True
MDLabel:
text:root.caller.first_aired_on
opacity:.8
halign:"right"
font_style:"Label"
role:"medium"
bold:True
pos_hint: {'center_y': .5}
adaptive_height:True
MDBoxLayout:
orientation: 'vertical'
padding:"10dp"
spacing:"10dp"
adaptive_height:False
MDBoxLayout:
adaptive_height:True
MDBoxLayout:
adaptive_height:True
pos_hint: {'center_y': 0.5}
TooltipMDIconButton:
tooltip_text:root.caller.title
icon: "play-circle"
on_press: root.caller.is_play
MDIconButton:
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"
MDIconButton:
icon: "bell-circle" if not(root.caller.is_in_my_notify) else "bell-check"
MDBoxLayout:
orientation: 'vertical'
pos_hint: {'center_y': 0.5}
adaptive_height:True
MDLabelShortened:
font_style:"Label"
role:"small"
text: f"[color={get_hex_from_color(self.theme_cls.primaryColor)}]"+"Genres: "+"[/color]"+root.caller.genres
markup:True
MDBoxLayout:
adaptive_height:True
MDLabelShortened:
font_style:"Label"
role:"small"
markup:True
text: f"[color={get_hex_from_color(self.theme_cls.primaryColor)}]"+"Popularity: "+"[/color]"+root.caller.popularity
MDLabelShortened:
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
shorten:False
adaptive_height:True
# shorten_from:"right"
max_lines:0
MDBoxLayout:
orientation: 'vertical'
adaptive_height:True
MDLabelShortened:
font_style:"Label"
role:"small"
markup:True
text: f"[color={get_hex_from_color(self.theme_cls.primaryColor)}]"+"Author: "+"[/color]"+root.caller.author
MDLabelShortened:
font_style:"Label"
markup:True
role:"small"
text: f"[color={get_hex_from_color(self.theme_cls.primaryColor)}]"+"Studios: "+"[/color]"+root.caller.studios
MDLabelShortened:
font_style:"Label"
markup:True
role:"small"
text: f"[color={get_hex_from_color(self.theme_cls.primaryColor)}]"+"Characters: "+"[/color]"+root.caller.characters
MDLabelShortened:
font_style:"Label"
markup:True
role:"small"
text: f"[color={get_hex_from_color(self.theme_cls.primaryColor)}]"+"Tags: "+"[/color]"+root.caller.tags
<MediaCard>
spacing:"5dp"
image:"https://s4.anilist.co/file/anilistcdn/media/anime/cover/small/bx163270-oxwgbe43Cpog.jpg"
on_release:
self.open()
size_hint_x: None
width:dp(100)
# height:self.minimum_height
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
MDLabel:
font_style:"Label"
role:"medium"
text:root.title
max_lines:2
halign:"center"
color:self.theme_cls.secondaryColor
<MediaCardsContainer>
# adaptive_height:True
# size_hint_y:None
size_hint_x:1
# height:dp(300)
size_hint_y:None
height:max(self.minimum_height,dp(350),container.minimum_height)
# adaptive_height:True
# width:self.minimum_width
container:container
orientation: 'vertical'
padding:"10dp"
spacing:"5dp"
MDLabel:
text:root.list_name
MDScrollView:
# do_scroll_x:True
# do_scroll_y:False
size_hint:1,None
height:container.minimum_height
MDBoxLayout:
id:container
padding:"0dp","10dp","100dp","10dp"
size_hint:None,None
height:self.minimum_height
width:self.minimum_width
spacing:"10dp"

View File

@@ -0,0 +1,185 @@
import os
from kivy.clock import Clock
from kivy.uix.behaviors import ButtonBehavior
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.tooltip import MDTooltip
from kivymd.uix.behaviors import BackgroundColorBehavior,StencilBehavior,CommonElevationBehavior,HoverBehavior
from kivymd.uix.button import MDIconButton
from kivymd.theming import ThemableBehavior
from kivy.uix.modalview import ModalView
from kivy.properties import ObjectProperty,StringProperty,BooleanProperty,ListProperty,NumericProperty
from kivy.uix.video import Video
class Tooltip(MDTooltip):
pass
class TooltipMDIconButton(Tooltip,MDIconButton):
tooltip_text = StringProperty()
class MediaPopupVideoPlayer(Video):
# self.prev
pass
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)
def on_leave(self,*args):
def _leave(dt):
if not self.hovering:
self.dismiss()
Clock.schedule_once(_leave,2)
class MediaCard(ButtonBehavior,HoverBehavior,MDBoxLayout):
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()
author = StringProperty()
studios = StringProperty()
characters = StringProperty()
tags = StringProperty()
stars = ListProperty([0,0,0,0,0,0])
cover_image_url = StringProperty()
preview_image = StringProperty()
# screen_name = StringProperty()
screen = ObjectProperty()
anime_id = NumericProperty()
has_trailer_color = ListProperty([1,1,1,0])
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
# self.app = MDApp.get_running_app()
# def on_screen_name(self,instance,value):
# if self.app:
# self.screen = self.app.manager_screens.get_screen(value)
def on_enter(self):
def _open_popup(dt):
if self.hovering:
window = self.get_parent_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.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,value):
if self.screen:
self.screen.controller.update_my_list(self.anime_id,value)
def on_trailer_url(self,*args):
pass
class MediaCardsContainer(MDBoxLayout):
container = ObjectProperty()
list_name = StringProperty()
# if __name__ == "__main__":
# from kivymd.app import MDApp
# from kivy.lang import Builder
# import json
# import os
# import tracemalloc
# tracemalloc.start()
# data = {}
# with open(os.path.join(os.curdir,"View","components","media_card","data.json"),"r") as file:
# data = json.loads(file.read())
# cache = {}
# def fetch_data(key):
# yt = YouTube(key)
# preview_image = yt.thumbnail_url
# video_stream_url = yt.streams.filter(progressive=True,file_extension="mp4")[-1].url
# return preview_image,video_stream_url
# def cached_fetch_data(key):
# if key not in cache:
# cache[key] = fetch_data(key)
# return cache[key]
# class MediaCardApp(MDApp):
# def build(self):
# self.theme_cls.primary_palette = "Magenta"
# self.theme_cls.theme_style = "Dark"
# ui = Builder.load_file("./media_card.kv")
# for item in data["data"]["Page"]["media"]:
# media_card = MediaCard()
# if item["title"]["english"]:
# media_card.title = item["title"]["english"]
# else:
# media_card.title = item["title"]["romaji"]
# media_card.cover_image_url = item["coverImage"]["medium"]
# media_card.popularity = str(item["popularity"])
# media_card.favourites = str(item["favourites"])
# media_card.episodes = str(item["episodes"])
# media_card.description = item["description"]
# media_card.first_aired_on = str(item["startDate"])
# media_card.studios = str(item["studios"]["nodes"])
# media_card.tags = str(item["tags"])
# media_card.media_status = item["status"]
# if item["trailer"]:
# try:
# url = cached_fetch_data("https://youtube.com/watch?v="+item["trailer"]["id"])[1]
# media_card.trailer_url =url
# except:
# pass
# media_card.genres = ",".join(item["genres"])
# stars = int(item["averageScore"]/100*6)
# if stars:
# for i in range(stars):
# media_card.stars[i] = 1
# ui.ids.cards.add_widget(media_card) # type: ignore
# return ui
# MediaCardApp().run()
# snapshot = tracemalloc.take_snapshot()
# print("-----------------------------------------------")
# for stat in snapshot.statistics("lineno")[:10]:
# print(stat)