2
0
mirror of https://github.com/ComradCollective/Comrad synced 2024-11-17 21:25:37 +00:00
Comrad/app/screens/profile/profile.py

333 lines
11 KiB
Python
Raw Normal View History

2020-08-13 07:55:59 +00:00
from screens.base import BaseScreen
from kivymd.uix.boxlayout import MDBoxLayout
2020-08-13 17:41:31 +00:00
from kivymd.uix.chip import MDChip
2020-08-13 07:55:59 +00:00
from kivymd.uix.textfield import MDTextField
2020-08-13 17:41:31 +00:00
from kivymd.uix.button import MDRectangleFlatButton,MDRectangleFlatIconButton,MDIconButton
from kivymd.uix.label import MDLabel, MDIcon
2020-08-13 07:55:59 +00:00
from kivy.uix.image import AsyncImage, Image
from kivy.metrics import dp
from kivy.properties import StringProperty
from kivy.core.window import Window
from kivy.core.image import Image as CoreImage
2020-08-19 20:15:38 +00:00
import io,asyncio
2020-08-13 09:35:03 +00:00
from kivy.uix.carousel import Carousel
from screens.feed.feed import PostCard
2020-08-13 17:41:31 +00:00
from kivy.clock import Clock
from functools import partial
from copy import copy,deepcopy
from kivy.animation import Animation
2020-08-19 23:26:25 +00:00
from main import MyLabel,COLOR_ICON
2020-08-13 17:41:31 +00:00
from misc import *
2020-08-13 07:55:59 +00:00
2020-08-13 17:41:31 +00:00
class ProfileAvatar(Image):
def on_touch_down(self, touch):
if self.screen.carousel.index and self.collide_point(*touch.pos) and self.screen.carousel.slides:
start = self.screen.carousel.slides[0]
start.opacity=0
self.screen.carousel.index=0
anim = Animation(opacity=1, duration=0.1)
anim.start(start)
# start = self.screen.carousel.slides[0]
# log('????',start)
# self.screen.carousel.load_slide(start)
# self.screen.carousel.load_next()
2020-08-13 07:55:59 +00:00
class LayoutAvatar(MDBoxLayout): pass
2020-08-13 09:35:03 +00:00
class AuthorInfoLayout(MDBoxLayout): pass
2020-08-13 07:55:59 +00:00
class LayoutCover(MDBoxLayout):
source=StringProperty()
pass
class CoverImage(Image): pass
2020-08-19 20:15:38 +00:00
def binarize_image(image, threshold=200):
"""Binarize an image."""
image = image.convert('L') # convert image to monochrome
import numpy
image = numpy.array(image)
image = binarize_array(image, threshold)
imsave(target_path, image)
return image
def binarize_array(numpy_array, threshold=200):
"""Binarize a numpy array."""
import numpy
for i in range(len(numpy_array)):
for j in range(len(numpy_array[0])):
if numpy_array[i][j] > threshold:
numpy_array[i][j] = 255
else:
numpy_array[i][j] = 0
return numpy_array
2020-08-13 07:55:59 +00:00
def crop_square(pil_img, crop_width, crop_height):
img_width, img_height = pil_img.size
return pil_img.crop(((img_width - crop_width) // 2,
(img_height - crop_height) // 2,
(img_width + crop_width) // 2,
(img_height + crop_height) // 2))
2020-08-19 20:15:38 +00:00
def circularize_img(img_fn, width, im=None, do_crop=True,bw=False,resize=True,circularize=True):
2020-08-13 07:55:59 +00:00
from PIL import Image, ImageOps, ImageDraw
2020-08-19 20:15:38 +00:00
from kivy.app import App
import numpy as np
log=App.get_running_app().log
2020-08-13 07:55:59 +00:00
2020-08-19 20:15:38 +00:00
#if not im:
2020-08-13 07:55:59 +00:00
im = Image.open(img_fn)
2020-08-19 20:15:38 +00:00
log('??',im)
2020-08-13 07:55:59 +00:00
# get center
2020-08-13 17:41:31 +00:00
if do_crop: im = crop_square(im, width, width)
2020-08-19 20:15:38 +00:00
if resize: im = im.resize((width,width))
if bw:
thresh = 175
fn = lambda x : 255 if x > thresh else 0
im = im.convert('L').point(fn, mode='1').convert('RGB')
orig_color = (255,255,255)
2020-08-19 23:26:25 +00:00
replacement_color = COLOR_ICON #(255,0,0)
2020-08-19 20:15:38 +00:00
# img = im.convert('RGB')
data = np.array(im)
data[(data == orig_color).all(axis = -1)] = replacement_color
im = Image.fromarray(data, mode='RGB').convert('RGBA')
if circularize_img:
bigsize = (im.size[0] * 3, im.size[1] * 3)
mask = Image.new('L', bigsize, 0)
draw = ImageDraw.Draw(mask)
draw.ellipse((0, 0) + bigsize, fill=255)
mask = mask.resize(im.size, Image.ANTIALIAS)
im.putalpha(mask)
# give back bytes
log('!!',im)
2020-08-13 07:55:59 +00:00
output = ImageOps.fit(im, mask.size, centering=(0.5, 0.5))
imgByteArr = io.BytesIO()
output.save(imgByteArr, format='PNG')
# imgByteArr = imgByteArr.getvalue()
imgByteArr.seek(0)
return imgByteArr
# output.putalpha(mask)
# output.save('output.png')
# background = Image.open('back.jpg')
# background.paste(im, (150, 10), im)
# background.save('overlap.png')
# return output
2020-08-13 09:35:03 +00:00
class ProfilePageLayout(MDBoxLayout): pass
2020-08-13 17:41:31 +00:00
class FollowerLayout(MDBoxLayout): pass
class AuthorName(MyLabel): pass
class AuthorUsername(MyLabel): pass
class AuthorDesc(MyLabel): pass
class AuthorPronouns(MyChip): pass
class AuthorPlace(MyChip): pass
class AuthorWebsite(MyChip): pass
class AuthorFollowers(MyChip): pass
class AuthorFollowing(MyChip): pass
def update_screen_on_carousel_move(self,dt,width=75):
# screen.author_name.text=str(screen.carousel.index)
# avatar_layout = copy(screen.avatar_layout)
# avatar_layout.width=dp(100)
# avatar_layout.height=dp(100)
if self.carousel.index:
if not hasattr(self,'avatar_layout_small'):
self.avatar_img.seek(0)
2020-08-19 20:15:38 +00:00
img,byte,avatar,avatar_layout = self.make_profile_img(width,do_crop=False,bw=True,circularize=False)
2020-08-13 17:41:31 +00:00
avatar.screen = self
avatar_layout.pos_hint = {'right':0.995, 'top':0.995}
avatar_layout.opacity=0
# avatar_layout.animate()
self.add_widget(avatar_layout)
self.avatar_layout_small=avatar_layout
self.avatar_layout_small_visible=False
if not self.avatar_layout_small_visible:
self.avatar_layout_small_visible=True
anim = Animation(opacity=1, duration=0.25)
anim.start(self.avatar_layout_small)
else:
if hasattr(self,'avatar_layout_small'):
if self.avatar_layout_small_visible:
self.avatar_layout_small_visible=False
anim = Animation(opacity=0, duration=0.25)
anim.start(self.avatar_layout_small)
# self.remove_widget(self.avatar_layout_small)
# del self.avatar_layout_small
# avatar_layout = self.avatar_layout
# self.remove_widget(avatar_layout)
# self.add_widget(avatar_layout)
2020-08-13 09:35:03 +00:00
2020-08-13 07:55:59 +00:00
class ProfileScreen(BaseScreen):
#def on_pre_enter(self):
# global app
# if app.is_logged_in():
# app.root.change_screen('feed')
2020-08-13 17:41:31 +00:00
username = None
clock_scheduled=None
2020-08-19 20:15:38 +00:00
def make_profile_img(self,width,do_crop=True,circ_img=None,bw=False,circularize=True):
2020-08-23 13:22:00 +00:00
img_src = f'assets/avatars/{self.app.username}.png'
2020-08-19 20:15:38 +00:00
circ_img = circularize_img(img_src,width,do_crop=do_crop,bw=bw,circularize=circularize)
2020-08-13 17:41:31 +00:00
avatar_layout = LayoutAvatar()
byte=io.BytesIO(circ_img.read())
img = CoreImage(byte,ext='png')
avatar = ProfileAvatar()
avatar.texture = img.texture
avatar_layout.height=dp(width)
avatar_layout.width=dp(width)
avatar_layout.add_widget(avatar)
return (circ_img,byte,avatar,avatar_layout)
2020-08-23 13:22:00 +00:00
def on_pre_enter(self, width=300):
2020-08-13 09:35:03 +00:00
2020-08-13 17:41:31 +00:00
# query author info
2020-08-23 13:22:00 +00:00
#if not self.username: self.username=self.app.username
2020-08-13 17:41:31 +00:00
# @TODO
if not self.clock_scheduled:
Clock.schedule_interval(partial(update_screen_on_carousel_move, self), 0.1)
self.clock_scheduled=True
2020-08-13 09:35:03 +00:00
# clear
2020-08-13 17:41:31 +00:00
if hasattr(self,'carousel'):
2020-08-13 09:35:03 +00:00
for post in self.posts:
self.carousel.remove_widget(post)
2020-08-13 17:41:31 +00:00
self.remove_widget(self.carousel)
del self.carousel
self.posts=[]
self.carousel = Carousel()
self.carousel.direction='right'
self.carousel.loop=True
self.posts=[]
2020-08-13 07:55:59 +00:00
# get circular image
2020-08-13 17:41:31 +00:00
self.avatar_img, self.avatar_img_bytes, self.avatar, self.avatar_layout = \
self.make_profile_img(width)
self.avatar.screen = self
2020-08-13 09:35:03 +00:00
## author info
self.author_info_layout = AuthorInfoLayout()
2020-08-23 13:22:00 +00:00
#self.app.name_irl = 'Marx Zuckerberg'
self.app.name_irl = 'Komrade @'+self.app.username
2020-08-13 09:35:03 +00:00
if hasattr(self.app,'name_irl'):
self.author_name_irl = AuthorName(text=self.app.name_irl)
2020-08-13 17:41:31 +00:00
self.author_name_irl.font_name = 'assets/font.otf'
self.author_name_irl.font_size = '28sp'
2020-08-13 09:35:03 +00:00
self.author_info_layout.add_widget(self.author_name_irl)
2020-08-23 13:22:00 +00:00
self.author_name = AuthorUsername(text='@'+self.app.username)
2020-08-13 09:35:03 +00:00
self.author_name.font_name = 'assets/font.otf'
2020-08-13 17:41:31 +00:00
self.author_name.font_size = '20sp'
2020-08-23 13:22:00 +00:00
# self.author_info_layout.add_widget(self.author_name)
2020-08-13 17:41:31 +00:00
## AUTHOR DESCRIPTION
2020-08-23 13:22:00 +00:00
self.author_desc = AuthorDesc(text='... etc ...')
2020-08-13 17:41:31 +00:00
self.author_desc.font_name='assets/font.otf'
self.author_desc.font_size='18sp'
# self.author_desc.halign='left'
## Pronouns
self.author_pronouns = AuthorPronouns(label='he/him',icon='gender-transgender')
## AUTHOR PLACE
2020-08-23 13:22:00 +00:00
self.author_place = AuthorPlace(label='Earth',icon='map-marker-outline')
2020-08-13 17:41:31 +00:00
## Website
2020-08-23 13:22:00 +00:00
self.author_website = AuthorWebsite(label='website.org', icon='link-variant')
2020-08-13 17:41:31 +00:00
## Followers
self.follower_layout = FollowerLayout()
2020-08-23 13:22:00 +00:00
# self.author_followers = AuthorFollowers(label='13 followers',icon='account-arrow-left')
self.author_following = AuthorFollowing(label='13 komrades',icon='account-multiple')
2020-08-13 17:41:31 +00:00
## add to layout
self.author_info_layout.add_widget(self.author_desc)
self.author_info_layout.add_widget(self.author_pronouns)
self.author_info_layout.add_widget(self.author_place)
2020-08-23 13:22:00 +00:00
# self.author_info_layout.add_widget(self.author_website)
2020-08-13 17:41:31 +00:00
self.follower_layout.add_widget(self.author_following)
2020-08-23 13:22:00 +00:00
# self.follower_layout.add_widget(self.author_followers)
2020-08-13 17:41:31 +00:00
self.author_info_layout.add_widget(self.follower_layout)
# class AuthorPlace(MDLabel): pass
# class AuthorWebsite(MDLabel): pass
# class AuthorFollowers(MDLabel): pass
# class AuthorFollowing(MDLabel): pass
2020-08-13 09:35:03 +00:00
## add root widgets
self.page_layout = ProfilePageLayout()
self.page_layout.add_widget(self.avatar_layout)
self.page_layout.add_widget(self.author_info_layout)
self.add_widget(self.carousel)
self.carousel.add_widget(self.page_layout)
## add posts
2020-08-19 20:15:38 +00:00
asyncio.create_task(self.add_author_posts())
2020-08-13 09:35:03 +00:00
2020-08-19 20:15:38 +00:00
async def add_author_posts(self):
2020-08-13 09:35:03 +00:00
# add posts
lim=25
2020-08-19 20:15:38 +00:00
posts=await self.app.get_my_posts()
2020-08-22 21:20:27 +00:00
self.log('POSTS!?',posts)
2020-08-21 13:12:13 +00:00
# stop
2020-08-19 20:15:38 +00:00
for i,post in enumerate(posts):
2020-08-13 09:35:03 +00:00
if i>lim: break
post_obj = PostCard(post)
2020-08-19 10:29:56 +00:00
self.log(post)
2020-08-13 09:35:03 +00:00
self.posts.append(post_obj)
2020-08-13 17:41:31 +00:00
self.carousel.add_widget(post_obj)
# def on_touch_move(self, ent):
# if self.carousel.index:
# self.author_name.text='moved!'
# else:
# self.author_name.text=self.username