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:
0
app/View/MainScreen/__init__.py
Normal file
0
app/View/MainScreen/__init__.py
Normal file
0
app/View/MainScreen/components/__init__.py
Normal file
0
app/View/MainScreen/components/__init__.py
Normal file
96
app/View/MainScreen/main_screen.kv
Normal file
96
app/View/MainScreen/main_screen.kv
Normal file
@@ -0,0 +1,96 @@
|
||||
#:import get_color_from_hex kivy.utils.get_color_from_hex
|
||||
#:import StringProperty kivy.properties.StringProperty
|
||||
|
||||
# custom sets for existing
|
||||
<MDBoxLayout>
|
||||
size_hint: 1,1
|
||||
|
||||
|
||||
# custom components
|
||||
|
||||
<CommonNavigationRailItem@MDNavigationRailItem>
|
||||
icon:""
|
||||
text:""
|
||||
<CommonNavigationRailItem>
|
||||
MDNavigationRailItemIcon:
|
||||
icon:root.icon
|
||||
|
||||
MDNavigationRailItemLabel:
|
||||
text: root.text
|
||||
|
||||
|
||||
<MainScreenView>
|
||||
md_bg_color: self.theme_cls.backgroundColor
|
||||
main_container:main_container
|
||||
MDBoxLayout:
|
||||
MDNavigationRail:
|
||||
anchor:"top"
|
||||
type: "selected"
|
||||
md_bg_color: self.theme_cls.secondaryContainerColor
|
||||
|
||||
MDNavigationRailFabButton:
|
||||
icon: "home-outline"
|
||||
|
||||
CommonNavigationRailItem:
|
||||
icon: "magnify"
|
||||
text: "Search"
|
||||
on_release:
|
||||
# print("r")
|
||||
root.manager_screens.current = "search screen"
|
||||
|
||||
CommonNavigationRailItem:
|
||||
icon: "bookmark-outline"
|
||||
text: "Bookmark"
|
||||
|
||||
CommonNavigationRailItem:
|
||||
icon: "library-outline"
|
||||
text: "Library"
|
||||
|
||||
CommonNavigationRailItem:
|
||||
icon: "cog"
|
||||
text: "settings"
|
||||
|
||||
MDAnchorLayout:
|
||||
anchor_y: 'top'
|
||||
padding:"10dp"
|
||||
MDBoxLayout:
|
||||
orientation: 'vertical'
|
||||
id:p
|
||||
MDBoxLayout:
|
||||
pos_hint: {'center_x': 0.5,'top': 1}
|
||||
padding: "10dp"
|
||||
size_hint_y:None
|
||||
height: self.minimum_height
|
||||
size_hint_x:.75
|
||||
spacing: '20dp'
|
||||
MDTextField:
|
||||
size_hint_x:1
|
||||
MDTextFieldLeadingIcon:
|
||||
icon: "magnify"
|
||||
MDTextFieldHintText:
|
||||
text: "Search for anime"
|
||||
# MDTextFieldTrailingIcon:
|
||||
# icon: "filter"
|
||||
MDIconButton:
|
||||
pos_hint: {'center_y': 0.5}
|
||||
icon: "account-circle"
|
||||
# size: 32,32
|
||||
MDScrollView:
|
||||
# do_scroll_y:True
|
||||
# do_scroll_x:False
|
||||
size_hint:1,1
|
||||
# height:main_container.minimum_height
|
||||
MDBoxLayout:
|
||||
id:main_container
|
||||
padding:"50dp","5dp","50dp","150dp"
|
||||
spacing:"10dp"
|
||||
orientation: 'vertical'
|
||||
size_hint_y:None
|
||||
height:max(self.minimum_height,p.height,1800)
|
||||
adaptive_height:True
|
||||
# MDBoxLayout:
|
||||
# size_hint_y:None
|
||||
# height:self.minimum_height
|
||||
# MDLabel:
|
||||
# text: "By BeneX"
|
||||
|
||||
16
app/View/MainScreen/main_screen.py
Normal file
16
app/View/MainScreen/main_screen.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from kivy.properties import ObjectProperty
|
||||
from View.base_screen import BaseScreenView
|
||||
|
||||
|
||||
class MainScreenView(BaseScreenView):
|
||||
main_container = ObjectProperty()
|
||||
def write_data(self):
|
||||
self.controller.write_data()
|
||||
|
||||
def model_is_changed(self) -> None:
|
||||
"""
|
||||
Called whenever any change has occurred in the data model.
|
||||
The view in this method tracks these changes and updates the UI
|
||||
according to these changes.
|
||||
"""
|
||||
|
||||
76
app/View/MylistScreen/my_list_screen.kv
Normal file
76
app/View/MylistScreen/my_list_screen.kv
Normal file
@@ -0,0 +1,76 @@
|
||||
<MyListScreenView>
|
||||
md_bg_color: self.theme_cls.backgroundColor
|
||||
my_list_container:my_list_container
|
||||
MDBoxLayout:
|
||||
size_hint:1,1
|
||||
MDNavigationRail:
|
||||
anchor:"top"
|
||||
type: "selected"
|
||||
md_bg_color: self.theme_cls.secondaryContainerColor
|
||||
MDNavigationRailFabButton:
|
||||
icon: "home"
|
||||
on_release:
|
||||
root.manager_screens.current = "main screen"
|
||||
CommonNavigationRailItem:
|
||||
icon: "magnify"
|
||||
text: "Search"
|
||||
# on_release:
|
||||
# root.manager_screens.current_screen = "search screen"
|
||||
CommonNavigationRailItem:
|
||||
icon: "bookmark-outline"
|
||||
text: "Bookmark"
|
||||
|
||||
CommonNavigationRailItem:
|
||||
icon: "library-outline"
|
||||
text: "Library"
|
||||
|
||||
CommonNavigationRailItem:
|
||||
icon: "cog"
|
||||
text: "settings"
|
||||
|
||||
# ScreenManager:
|
||||
# MDScreen:
|
||||
# name:"main"
|
||||
MDAnchorLayout:
|
||||
anchor_y: 'top'
|
||||
padding:"10dp"
|
||||
size_hint:1,1
|
||||
|
||||
MDBoxLayout:
|
||||
orientation: 'vertical'
|
||||
id:p
|
||||
size_hint:1,1
|
||||
MDBoxLayout:
|
||||
pos_hint: {'center_x': 0.5,'top': 1}
|
||||
padding: "10dp"
|
||||
size_hint_y:None
|
||||
height: self.minimum_height
|
||||
size_hint_x:.75
|
||||
spacing: '20dp'
|
||||
MDTextField:
|
||||
size_hint_x:1
|
||||
required:True
|
||||
on_text_validate:
|
||||
root.handle_search_for_anime(args[0])
|
||||
|
||||
MDTextFieldLeadingIcon:
|
||||
icon: "magnify"
|
||||
MDTextFieldHintText:
|
||||
text: "Search for anime"
|
||||
# MDTextFieldTrailingIcon:
|
||||
# icon: "filter"
|
||||
MDIconButton:
|
||||
pos_hint: {'center_y': 0.5}
|
||||
icon: "account-circle"
|
||||
# size: 32,32
|
||||
MDScrollView:
|
||||
size_hint:1,1
|
||||
MDGridLayout:
|
||||
spacing: '10dp'
|
||||
padding: "75dp","50dp","10dp","100dp"
|
||||
id:my_list_container
|
||||
cols:5
|
||||
size_hint_y:None
|
||||
height:self.minimum_height
|
||||
|
||||
|
||||
28
app/View/MylistScreen/my_list_screen.py
Normal file
28
app/View/MylistScreen/my_list_screen.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from kivy.properties import ObjectProperty,StringProperty,DictProperty
|
||||
from View.base_screen import BaseScreenView
|
||||
|
||||
|
||||
class MyListScreenView(BaseScreenView):
|
||||
my_list_container = ObjectProperty()
|
||||
def model_is_changed(self) -> None:
|
||||
"""
|
||||
Called whenever any change has occurred in the data model.
|
||||
The view in this method tracks these changes and updates the UI
|
||||
according to these changes.
|
||||
"""
|
||||
|
||||
def handle_search_for_anime(self,search_widget):
|
||||
search_term = search_widget.text
|
||||
if search_term and not(self.is_searching):
|
||||
self.search_term = search_term
|
||||
self.search_results_container.clear_widgets()
|
||||
if self.filters:
|
||||
self.controller.requested_search_for_anime(search_term,**self.filters)
|
||||
else:
|
||||
self.controller.requested_search_for_anime(search_term)
|
||||
|
||||
def update_layout(self,widget):
|
||||
self.search_results_container.add_widget(widget)
|
||||
|
||||
def add_pagination(self,pagination_info):
|
||||
pass
|
||||
0
app/View/SearchScreen/__init__.py
Normal file
0
app/View/SearchScreen/__init__.py
Normal file
80
app/View/SearchScreen/search_screen.kv
Normal file
80
app/View/SearchScreen/search_screen.kv
Normal file
@@ -0,0 +1,80 @@
|
||||
<SearchScreenView>
|
||||
md_bg_color: self.theme_cls.backgroundColor
|
||||
search_results_container:search_results_container
|
||||
MDBoxLayout:
|
||||
size_hint:1,1
|
||||
MDNavigationRail:
|
||||
anchor:"top"
|
||||
type: "selected"
|
||||
md_bg_color: self.theme_cls.secondaryContainerColor
|
||||
|
||||
MDNavigationRailFabButton:
|
||||
icon: "home"
|
||||
on_release:
|
||||
root.manager_screens.current = "main screen"
|
||||
|
||||
CommonNavigationRailItem:
|
||||
icon: "magnify"
|
||||
text: "Search"
|
||||
# on_release:
|
||||
# root.manager_screens.current_screen = "search screen"
|
||||
|
||||
CommonNavigationRailItem:
|
||||
icon: "bookmark-outline"
|
||||
text: "My Anime List"
|
||||
on_release:
|
||||
root.manager_screens.current = "my list screen"
|
||||
CommonNavigationRailItem:
|
||||
icon: "library-outline"
|
||||
text: "Library"
|
||||
|
||||
CommonNavigationRailItem:
|
||||
icon: "cog"
|
||||
text: "settings"
|
||||
|
||||
# ScreenManager:
|
||||
# MDScreen:
|
||||
# name:"main"
|
||||
MDAnchorLayout:
|
||||
anchor_y: 'top'
|
||||
padding:"10dp"
|
||||
size_hint:1,1
|
||||
|
||||
MDBoxLayout:
|
||||
orientation: 'vertical'
|
||||
id:p
|
||||
size_hint:1,1
|
||||
MDBoxLayout:
|
||||
pos_hint: {'center_x': 0.5,'top': 1}
|
||||
padding: "10dp"
|
||||
size_hint_y:None
|
||||
height: self.minimum_height
|
||||
size_hint_x:.75
|
||||
spacing: '20dp'
|
||||
MDTextField:
|
||||
size_hint_x:1
|
||||
required:True
|
||||
on_text_validate:
|
||||
root.handle_search_for_anime(args[0])
|
||||
|
||||
MDTextFieldLeadingIcon:
|
||||
icon: "magnify"
|
||||
MDTextFieldHintText:
|
||||
text: "Search for anime"
|
||||
# MDTextFieldTrailingIcon:
|
||||
# icon: "filter"
|
||||
MDIconButton:
|
||||
pos_hint: {'center_y': 0.5}
|
||||
icon: "account-circle"
|
||||
# size: 32,32
|
||||
MDScrollView:
|
||||
size_hint:1,1
|
||||
MDGridLayout:
|
||||
id:search_results_container
|
||||
spacing: '10dp'
|
||||
padding: "75dp","75dp","10dp","200dp"
|
||||
cols:5
|
||||
size_hint_y:None
|
||||
height:self.minimum_height
|
||||
|
||||
|
||||
31
app/View/SearchScreen/search_screen.py
Normal file
31
app/View/SearchScreen/search_screen.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from kivy.properties import ObjectProperty,StringProperty,DictProperty
|
||||
from View.base_screen import BaseScreenView
|
||||
|
||||
|
||||
class SearchScreenView(BaseScreenView):
|
||||
search_results_container = ObjectProperty()
|
||||
search_term = StringProperty()
|
||||
filters = DictProperty()
|
||||
is_searching = False
|
||||
def model_is_changed(self) -> None:
|
||||
"""
|
||||
Called whenever any change has occurred in the data model.
|
||||
The view in this method tracks these changes and updates the UI
|
||||
according to these changes.
|
||||
"""
|
||||
|
||||
def handle_search_for_anime(self,search_widget):
|
||||
search_term = search_widget.text
|
||||
if search_term and not(self.is_searching):
|
||||
self.search_term = search_term
|
||||
self.search_results_container.clear_widgets()
|
||||
if self.filters:
|
||||
self.controller.requested_search_for_anime(search_term,**self.filters)
|
||||
else:
|
||||
self.controller.requested_search_for_anime(search_term)
|
||||
|
||||
def update_layout(self,widget):
|
||||
self.search_results_container.add_widget(widget)
|
||||
|
||||
def add_pagination(self,pagination_info):
|
||||
pass
|
||||
3
app/View/__init__.py
Normal file
3
app/View/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from .MainScreen.main_screen import MainScreenView
|
||||
from .SearchScreen.search_screen import SearchScreenView
|
||||
from .MylistScreen.my_list_screen import MyListScreenView
|
||||
45
app/View/base_screen.py
Normal file
45
app/View/base_screen.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from kivy.properties import ObjectProperty
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.screen import MDScreen
|
||||
|
||||
from Utility.observer import Observer
|
||||
|
||||
|
||||
class BaseScreenView(MDScreen, Observer):
|
||||
"""
|
||||
A base class that implements a visual representation of the model data.
|
||||
The view class must be inherited from this class.
|
||||
"""
|
||||
|
||||
controller = ObjectProperty()
|
||||
"""
|
||||
Controller object - :class:`~Controller.controller_screen.ClassScreenControler`.
|
||||
|
||||
:attr:`controller` is an :class:`~kivy.properties.ObjectProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
model = ObjectProperty()
|
||||
"""
|
||||
Model object - :class:`~Model.model_screen.ClassScreenModel`.
|
||||
|
||||
:attr:`model` is an :class:`~kivy.properties.ObjectProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
manager_screens = ObjectProperty()
|
||||
"""
|
||||
Screen manager object - :class:`~kivymd.uix.screenmanager.MDScreenManager`.
|
||||
|
||||
:attr:`manager_screens` is an :class:`~kivy.properties.ObjectProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
def __init__(self, **kw):
|
||||
super().__init__(**kw)
|
||||
# Often you need to get access to the application object from the view
|
||||
# class. You can do this using this attribute.
|
||||
self.app = MDApp.get_running_app()
|
||||
# Adding a view class as observer.
|
||||
self.model.add_observer(self)
|
||||
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)
|
||||
21
app/View/screens.py
Normal file
21
app/View/screens.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# The screens dictionary contains the objects of the models and controllers
|
||||
# of the screens of the application.
|
||||
|
||||
|
||||
from Controller import SearchScreenController,MainScreenController,MyListScreenController
|
||||
from Model import MainScreenModel,SearchScreenModel,MyListScreenModel
|
||||
|
||||
screens = {
|
||||
"main screen": {
|
||||
"model": MainScreenModel,
|
||||
"controller": MainScreenController,
|
||||
},
|
||||
"search screen": {
|
||||
"model": SearchScreenModel,
|
||||
"controller": SearchScreenController,
|
||||
},
|
||||
"my list screen": {
|
||||
"model": MyListScreenModel,
|
||||
"controller": MyListScreenController,
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user