import os , sys ; sys . path . append ( os . path . abspath ( os . path . join ( os . path . abspath ( os . path . join ( os . path . dirname ( __file__ ) , ' .. ' ) ) , ' .. ' ) ) )
from comrad import *
from kivymd . uix . label import MDLabel
from kivy . uix . gridlayout import GridLayout
from kivy . uix . image import AsyncImage , Image
from kivymd . uix . boxlayout import MDBoxLayout
from kivymd . uix . card import MDCard , MDSeparator
from kivy . uix . scrollview import ScrollView
from screens . base import ProtectedScreen , BaseScreen
from kivy . properties import ListProperty
import os , time
from datetime import datetime
from kivy . app import App
from threading import Thread
import asyncio
from misc import *
from kivy . core . window import Window
import logging
logger = logging . getLogger ( __name__ )
### POST CODE
class PostTitle ( MDLabel ) : pass
class PostGridLayout ( GridLayout ) : pass
class PostImage ( AsyncImage ) : pass
# class PostImage(CoreImage)
class PostImageBytes ( Image ) : pass
class PostContent ( MDLabel ) :
def __init__ ( self , * * kwargs ) :
super ( ) . __init__ ( * * kwargs )
self . bind ( width = lambda s , w : s . setter ( ' text_size ' ) ( s , ( w , None ) ) )
self . bind ( texture_size = self . setter ( ' size ' ) )
self . font_name = ' assets/overpass-mono-regular.otf '
#pass
class PostAuthorLayout ( MDBoxLayout ) :
pass
class PostImageLayout ( MDBoxLayout ) : pass
class PostAuthorLabel ( MDLabel ) :
def __init__ ( self , * * kwargs ) :
super ( ) . __init__ ( * * kwargs )
self . bind ( width = lambda s , w : s . setter ( ' text_size ' ) ( s , ( w , None ) ) )
self . bind ( texture_size = self . setter ( ' size ' ) )
self . font_name = ' assets/overpass-mono-regular.otf '
#self.to_changeable=False
# def on_touch_down(self,*x,**y):
# print('weeeeeee')
# stop
#def on_touch_down(self, touch):
# '''Receive a touch down event.
# :Parameters:
# `touch`: :class:`~kivy.input.motionevent.MotionEvent` class
# Touch received. The touch is in parent coordinates. See
# :mod:`~kivy.uix.relativelayout` for a discussion on
# coordinate systems.
# :Returns: bool
# If True, the dispatching of the touch event will stop.
# If False, the event will continue to be dispatched to the rest
# of the widget tree.
# '''
def on_touch_down ( self , touch ) :
if self . collide_point ( * touch . pos ) :
# username=self.text.strip().split()[1][1:]
app = App . get_running_app ( )
app . view_profile ( self . username )
return True
pass
class PostTimestampLabel ( MDLabel ) :
def __init__ ( self , * * kwargs ) :
super ( ) . __init__ ( * * kwargs )
self . bind ( width = lambda s , w : s . setter ( ' text_size ' ) ( s , ( w , None ) ) )
self . bind ( texture_size = self . setter ( ' size ' ) )
self . font_name = ' assets/overpass-mono-regular.otf '
class PostAuthorAvatar ( AsyncImage ) :
def on_touch_down ( self , touch ) :
if self . collide_point ( * touch . pos ) :
app = App . get_running_app ( )
app . view_profile ( self . username )
return True
# stop
pass
class PostLayout ( MDBoxLayout ) : pass
class PostScrollView ( ScrollView ) : pass
class PostCard ( MDCard ) :
@property
def app ( self ) : return App . get_running_app ( )
def log ( self , * x , * * y ) : self . app . log ( * x )
def __init__ ( self , data ) :
super ( ) . __init__ ( )
# self.log('PostCard() got data: '+str(data))
self . author = data . get ( ' author ' , ' [Anonymous] ' )
self . recipient = data . get ( ' to_name ' , ' ' )
self . post_data = data . get ( ' post_data ' , { } )
if not self . recipient :
self . recipient = self . app . channel
# self.img_id = data.get('file_id','')
# self.img_ext = data.get('file_ext','')
# self.img_src=self.img_id[:3]+'/'+self.img_id[3:]+'.'+self.img_ext if self.img_id else ''
# self.cache_img_src = os.path.join('cache',self.img_src) if self.img_src else ''
self . cache_img_src = self . img_src = data . get ( ' img_src ' , ' ' )
self . img_loaded = self . img_src and os . path . exists ( self . img_src )
self . content = data . get ( ' content ' , ' ' )
self . timestamp = data . get ( ' timestamp ' , None )
# self.bind(minimum_height=self.setter('height'))
author_prefix = data . get ( ' author_prefix ' , ' Comrad @ ' )
author_label_font_size = data . get ( ' author_label_font_size ' , ' 24sp ' )
recip_label_font_size = data . get ( ' author_label_font_size ' , ' 14sp ' )
# minwidth = 400
# maxwidth = 800
# abouts = int(Window.size[0]/1.5)
# if abouts < minwidth: self.width=f'{minwidth}sp'
# if abouts > maxwidth: self.width=f'{maxwidth}sp'
# self.width=f'{abouts}sp'
# self.log('PostCard.img_id =',self.img_id)
# self.log('PostCard.img_ext =',self.img_ext)
# self.log('PostCard.img_src =',self.img_src)
# self.log('PostCard.cache_img_src =',self.cache_img_src)
# pieces
self . author_section_layout = author_section_layout = PostAuthorLayout ( )
self . author_label = author_label = PostAuthorLabel ( text = author_prefix + self . author )
self . author_label . font_name = ' assets/overpass-mono-semibold.otf '
if self . recipient :
recip = self . recipient
recip = ' @ ' + recip if not recip . startswith ( ' @ ' ) else recip #(recip if recip and recip[0].isalpha() else recip[1:])
# recip=author_prefix+recip #(recip if recip and recip[0].isalpha() else recip[1:])
self . author_label . text + = f ' \n [size= { recip_label_font_size } ]to ' + recip + ' [/size] '
self . author_label . markup = True
self . author_label . font_size = author_label_font_size
self . author_label . username = self . author
avatar_img_src = os . path . join ( PATH_AVATARS , f ' { self . author } .png ' )
if not os . path . exists ( avatar_img_src ) :
avatar_img_src = os . path . join ( PATH_GUI_ASSETS , ' avatars ' , f ' { self . author } .png ' )
if not os . path . exists ( avatar_img_src ) :
avatar_img_src = PATH_DEFAULT_AVATAR
self . author_avatar = author_avatar = PostAuthorAvatar ( source = avatar_img_src ) #self.img_src)
self . author_avatar . username = self . author
self . author_section_layout . add_widget ( author_avatar )
self . author_section_layout . add_widget ( author_label )
# self.author_section_layout.add_widget(MDSeparator(height='1sp',size_hint=(None,None)))
# self.recipient_label = author_label = PostAuthorLabel(text='--> @'+self.recipient)
# self.recipient_label.font_size = '14sp'
# self.author_label.add_widget(self.recipient_label)
# timestamp
timestr = ' '
#log(self.timestamp)
if self . timestamp :
dt_object = datetime . fromtimestamp ( self . timestamp )
timestr = dt_object . strftime ( " %-d % b % Y % H: % M " )
#log('timestr: '+timestr)
self . timestamp_label = PostTimestampLabel ( text = timestr )
self . timestamp_label . font_size = ' 14sp '
author_section_layout . add_widget ( self . timestamp_label )
# author_section_layout.add_widget(author_avatar)
# self.add_widget(author_section_layout)
if self . cache_img_src :
image_layout = PostImageLayout ( )
self . image = image = PostImage ( source = self . cache_img_src )
image . height = ' 300sp '
image_layout . add_widget ( image )
image_layout . height = ' 300sp '
# self.log(image.image_ratio)
self . post_content = PostContent ( text = self . content )
self . post_content . font_size = ' 24sp '
# post_layout = PostGridLayout()
#content = PostContent()
# add to screen
# self.add_widget(title)
# post_layout.add_widget(author_section_layout)
# post_layout.add_widget(image_layout)
# post_layout.add_widget(content)
self . scroller = scroller = PostScrollView ( )
self . add_widget ( author_section_layout )
# self.add_widget(MDLabel(text='hello'))
#log('img_src ' + str(bool(self.img_src)))
if self . img_src : self . add_widget ( image_layout )
def estimate_height ( minlen = 100 , maxlen = 600 ) :
num_chars = len ( self . content )
# num_lines = num_chars
height = num_chars * 1.1
if height > maxlen : height = maxlen
if height < minlen : height = minlen
return height
scroller . size = ( ' 300sp ' , ' %s sp ' % estimate_height ( ) )
# scroller.bind(size=('300sp',scroller.setter('height'))
scroller . add_widget ( self . post_content )
self . add_widget ( scroller )
# self.add_widget(post_layout)
###
# Add any buttons? Any prompts?
if self . post_data . get ( ' type ' ) == ' prompt ' :
# # prepare button layout
# self.button_layout = MDBoxLayout()
# self.button_layout.adaptive_width=True
# self.button_layout.height='56dp'
# self.button_layout.spacing='10dp'
# self.button_layout.pos_hint={'center_x': .5, 'y':0.05}
if self . post_data . get ( ' prompt_id ' ) == ' addcontact ' :
def on_touch_down ( touch ) :
if hasattr ( self , ' _touched ' ) and self . _touched : return
if self . collide_point ( * touch . pos ) :
asyncio . create_task ( self . app . prompt_addcontact ( self . post_data ) )
self . _touched = True
self . on_touch_down = on_touch_down
# # self.stat(f"Add @{meet_name}'s public key to your address book? It will allow you and @{meet_name} to read and write encrypted messages to one another.")
# if do_adduser.strip().lower()=='y':
# import pyqrcode
# print('meet_uri',meet_uri,'???')
# qr = pyqrcode.create(meet_uri)
# fnfn = os.path.join(PATH_QRCODES,meet_name+'.png') # self.get_path_qrcode(name=name)
# qr.png(fnfn,scale=5)
# clear_screen()
# self.stat(f'The public key of @{meet_name} has been saved as a QRcode to {fnfn}')
# print(qrstr)
# do_pause()
# clear_screen()
# self.button = MDRectangleFlatButton()
# self.post_button = PostButton()
# self.post_button.screen = self
# self.post_status = PostStatus()
# self.post_status_added = False
# self.button_layout.add_widget(self.upload_button)
# self.button_layout.add_widget(self.post_button)
# self.upload_button.font_size='8sp'
# self.post_button.font_size='8sp'
# self.post_button.md_bg_color=rgb(*COLOR_CARD)
# self.upload_button.md_bg_color=rgb(*COLOR_CARD)
# self.post_status.md_bg_color=rgb(*COLOR_CARD)
# post.add_widget(self.button_layout)
# self.log('?????',self.cache_img_src, os.path.exists(self.cache_img_src), os.stat(self.cache_img_src).st_size)
if self . cache_img_src and ( not os . path . exists ( self . cache_img_src ) or not os . stat ( self . cache_img_src ) . st_size ) :
async def do_download_later ( ) :
self . log ( ' downloading... ' )
await self . app . download ( self . img_id , self . cache_img_src )
self . image . reload ( )
return True
#self.open_dialog('posting')
#Thread(target=do_download).start()
asyncio . create_task ( do_download_later ( ) )
@property
def app ( self ) :
return App . get_running_app ( )
def load_image ( self ) :
if not self . img_src : return
if self . img_loaded : return
# otherwise load image...
self . app . get_image ( self . img_src )
self . log ( ' done getting image! ' )
self . image . reload ( )
self . img_loaded = True
#####
class PostCardPopup ( PostCard ) :
def __init__ ( self , * x , msg_dialog = None , * * y ) :
super ( ) . __init__ ( * x , * * y )
self . ok_to_continue = False
self . msg_dialog = msg_dialog
def on_touch_down ( self , touch ) :
# if self.collide_point(*touch.pos):# and not self.ok_to_continue:
# logger.info('ouch!!!')
# The touch has occurred inside the widgets area. Do stuff!
self . ok_to_continue = True
if self . msg_dialog : self . msg_dialog . ok_to_continue = True
return True
class PostCardInputPopup ( PostCardPopup ) :
def on_touch_down ( self , touch ) :
pass
class FeedScreen ( ProtectedScreen ) :
posts = ListProperty ( )
updated = None
def on_pre_enter ( self ) :
if not super ( ) . on_pre_enter ( ) : return
if self . updated :
if not self . app . comrad . updated or self . updated > = self . app . comrad . updated :
self . log ( ' NOT UPDATING! ' )
return
# self.root.clear_widgets()
self . log ( ' UPDATING! ' )
if self . app . map :
self . app . map . dismiss ( )
self . root . remove_widget ( self . app . map )
if not hasattr ( self , ' get_posts ' ) : self . get_posts = self . app . comrad . posts
for post in self . posts :
self . ids . post_carousel . remove_widget ( post )
i = 0
lim = 25
async def go ( ) :
# do not get updates! leave that to refresh button!
# await self.app.get_updates()
posts = self . get_posts ( )
for i , post in enumerate ( posts ) :
if i > lim : break
data = {
' author ' : post . from_name ,
' to_name ' : post . to_name ,
' content ' : post . msg . get ( ' txt ' ) if type ( post . msg ) == dict else str ( post . msg ) ,
' timestamp ' : post . timestamp ,
' post_data ' : post . data ,
}
post_obj = PostCard ( data )
self . posts . append ( post_obj )
self . ids . post_carousel . add_widget ( post_obj )
self . updated = time . time ( )
asyncio . create_task ( go ( ) )
return True
# def on_pre_enter(self):
# self.clear_deck()
# # for i,x