mirror of
https://github.com/Benexl/FastAnime.git
synced 2025-12-28 05:33:12 -08:00
completed the basic ui and anilist module
This commit is contained in:
1
app/View/components/__init__.py
Normal file
1
app/View/components/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .media_card import MediaCard,MediaCardsContainer
|
||||
1
app/View/components/media_card/__init__.py
Normal file
1
app/View/components/media_card/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .media_card import MediaCard,MediaCardsContainer
|
||||
1355
app/View/components/media_card/data.json
Normal file
1355
app/View/components/media_card/data.json
Normal file
File diff suppressed because it is too large
Load Diff
249
app/View/components/media_card/media_card.kv
Normal file
249
app/View/components/media_card/media_card.kv
Normal 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"
|
||||
185
app/View/components/media_card/media_card.py
Normal file
185
app/View/components/media_card/media_card.py
Normal 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)
|
||||
Reference in New Issue
Block a user