You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Comrad/app/screens/post/post.py

441 lines
15 KiB
Python

from screens.base import ProtectedScreen,BaseScreen
from plyer import filechooser
4 years ago
from kivy.uix.button import Button
from kivymd.uix.label import MDLabel
from kivymd.uix.textfield import MDTextField
from kivymd.uix.boxlayout import MDBoxLayout
4 years ago
from kivymd.uix.stacklayout import MDStackLayout
from kivymd.uix.button import MDRectangleFlatButton, MDIconButton, MDRaisedButton,MDFillRoundFlatButton,MDRoundFlatIconButton
from kivy.properties import ListProperty,ObjectProperty
from kivy.app import App
from screens.feed.feed import *
import os,time,threading
from threading import Thread
from kivymd.uix.dialog import MDDialog
from kivy.core.image import Image as CoreImage
4 years ago
from kivymd.uix.gridlayout import MDGridLayout
4 years ago
import io,shutil,asyncio
4 years ago
from kivymd.uix.chip import MDChip
from main import rgb,COLOR_TEXT,COLOR_ACCENT,COLOR_CARD,COLOR_INACTIVE,COLOR_ACTIVE
from misc import *
from kivy.animation import Animation
from kivy.lang import Builder
from kivy.metrics import dp
4 years ago
from kivymd.uix.dropdownitem import MDDropDownItem
from kivymd.uix.menu import MDDropdownMenu
4 years ago
from kivy.properties import (
BooleanProperty,
ListProperty,
NumericProperty,
ObjectProperty,
StringProperty,
)
from kivy.uix.boxlayout import BoxLayout
from kivymd.theming import ThemableBehavior
from kivymd.uix.button import MDIconButton
from kivymd.uix.stacklayout import MDStackLayout
from main import COLOR_TEXT,rgb,COLOR_ICON,COLOR_ACCENT,COLOR_INACTIVE
class ProgressPopup(MDDialog): pass
class MessagePopup(MDDialog): pass
class UploadButton(MDRectangleFlatButton):
'''
Button that triggers 'filechooser.open_file()' and processes
the data response from filechooser Activity.
'''
selection = ListProperty([])
def choose(self):
'''
Call plyer filechooser API to run a filechooser Activity.
'''
filechooser.open_file(on_selection=self.handle_selection)
def handle_selection(self, selection):
'''
Callback function for handling the selection response from Activity.
'''
self.selection = selection
def on_selection(self, *a, **k):
'''
Update TextInput.text after FileChoose.selection is changed
via FileChoose.handle_selection.
'''
pass
#App.get_running_app().root.ids.result.text = str(self.selection)
class AddPostTextField(MDTextField): pass
class ButtonLayout(MDBoxLayout): pass
class PostButton(MDRectangleFlatButton): pass
class PostStatus(MDRectangleFlatButton): pass
4 years ago
class SelectAddressee(DropDownWidget):
def __init__(self, wordlist, **kwargs):
super().__init__(**kwargs)
self.pos_hint = {'center_x':.5,'center_y':.5}
self.size_hint = (None, None)
self.size = (600, 60)
self.ids.txt_input.word_list = wordlist
self.ids.txt_input.starting_no = 1
class ChannelLayout(MDStackLayout):
pass
class ChannelChip(MDRoundFlatIconButton):
def callback(self):
val=self.check if hasattr(self,'check') else False
self.check = not val
4 years ago
self.icon='check-box-outline' if self.check else 'checkbox-blank-outline'
self.parent.parent.parent.parent.to_channels[self.text]=self.check
4 years ago
# self.md_bg_color=rgb(*COLOR_INACTIVE) if not self.check else rgb(*COLOR_ACTIVE)
# raise Exception(['GOT VALL',val])
pass
# def on_icon(self, instance, value):
# self.log('on_icon',instance,value)
# if value == "":
# self.icon = "check-box-outline"
# self.remove_widget(self.ids.icon)
# def on_touch_down(self, touch):
# colorobj=self.children[1]
# if not self.check:
# self.check=True
# self.icon="check-box-outline"
# self.color=rgb(*COLOR_ACTIVE)
# self.selected_chip_color=rgb(*COLOR_ACTIVE)
# colorobj.md_bg_color=rgb(*COLOR_ACTIVE)
# self.log(f'check = {self.check} and icon = {self.icon} and color = {self.color}')
# else:
# self.selected_chip_color=rgb(*COLOR_INACTIVE)
# self.check=False
# self.icon="checkbox-blank-outline"
# self.color=rgb(*COLOR_INACTIVE)
# colorobj.md_bg_color=rgb(*COLOR_INACTIVE)
# self.log(f'check = {self.check} and icon = {self.icon} and color = {self.color}')
# self.md_bg_color=rgb(*COLOR_INACTIVE)
# self.parent.parent.to_channels[self.label]=self.check
# self.color=rgb(*COLOR_ACCENT) if self.check else (rgb(50,50,50))
# self.log(md_choose_chip.parent.to_channels)
# self.ids.chiplayout.md_bg_color=self.color
# if self.selected_chip_color:
# Animation(
# color=self.theme_cls.primary_dark
# if not self.selected_chip_color
# else self.selected_chip_color,
# d=0.3,
# ).start(self)
# if issubclass(md_choose_chip.__class__, MDChooseChip):
# for chip in md_choose_chip.children:
# if chip is not self:
# chip.color = self.theme_cls.primary_color
# if self.check:
# if not len(self.ids.box_check.children):
# self.ids.box_check.add_widget(
# MDIconButton(
# icon="check-box-outline",
# size_hint_y=None,
# height=dp(20),
# disabled=True,
# user_font_size=dp(20),
# pos_hint={"center_y": 0.5},
# )
# )
# else:
# check = self.ids.box_check.children[0]
# self.ids.box_check.remove_widget(check)
# if self.callback:
# self.callback(self, self.label)
4 years ago
class AuthorDropdown(MDDropdownMenu): pass
class SenderMenuItem(MDDropDownItem): pass
4 years ago
class PostScreen(ProtectedScreen):
post_id = ObjectProperty()
def on_pre_enter(self):
super().on_pre_enter()
4 years ago
self.to_channels = {}
# clear
if hasattr(self,'post_status'): self.remove_widget(self.post_status)
if hasattr(self,'post_textfield'): self.post_textfield.text=''
post_json = {'author':self.app.username, 'timestamp':time.time()}
self.post_card = post = PostCard(post_json)
4 years ago
self.post_card.add_widget(get_separator('15sp'),1)
self.post_card.add_widget(get_separator('15sp'),1)
self.post_textfield = post_TextField = AddPostTextField()
post_TextField.line_color_focus=rgb(*COLOR_TEXT)
post_TextField.line_color_normal=rgb(*COLOR_TEXT)
post_TextField.current_hint_text_color=rgb(*COLOR_TEXT)
post_TextField.font_name='assets/overpass-mono-regular.otf'
post_TextField.hint_text='word?'
4 years ago
self.post_card.author_label.text=self.app.username
# self.post_card.author_section_layout.remove_widget(self.post_card.author_label)
# self.post_card.author_dropdown = AuthorDropdown()
#[self.post_card.author_dropdown.set_item('@'+key) for key in self.app.keys]
# for key in self.app.keys:
# btn = Ca
# self.post_card.author_dropdown.add_widget(btn)
# self.post_card.author_section_layout.add_widget(self.post_card.author_dropdown)
# self.menu.bind(on_release=self.menu_callback)
#self.post_card.author_dropdown.items = ['@'+key
# self.post_card.author_dropdown.font_name='assets/font.otf'
# self.post_card.author_section_layout.add_widget(self.post_card.author_dropdown,1)
# self.post_card.author_label = AuthorDropdown()
4 years ago
#self.addressee = SelectAddressee(list(self.app.keys.keys()))
#post.add_widget(self.addressee)
4 years ago
self.fields_values = MDBoxLayout()
self.fields_values.orientation='horizontal'
self.fields_values.cols=2
self.fields_values.size_hint=(1,None)
# self.fields_values.md_bg_color=1,1,0,1
post.add_widget(self.fields_values,2)
4 years ago
# post.remove_widget(post.scroller)
4 years ago
self.to_label = MDLabel(text="To:",size_hint=(None,None))
self.to_label.pos_hint={'center_y':0.5}
self.fields_values.add_widget(self.to_label)
4 years ago
self.channel_layout = ChannelLayout() #MDBoxLayout(size_hint=(1,None),orientation='horizontal',cols=3)
4 years ago
self.fields_values.add_widget(self.channel_layout)
4 years ago
4 years ago
# self.fields_values.add_widget(get_separator('10sp'))
# self.fields_values.add_widget(get_separator('10sp'))
self.to_label.font_name='assets/font.otf'
# self.to_label.padding=(0,0,0,0)
# self.to_label.spacing=(10,10)
# self.channel_layout.add_widget(self.to_label)
# post.add_widget(self.channel_layout,1)
# menu_labels = [
# {"viewclass": "SenderMenuItem",
# "text": "Label1",
# "caller":self.post_card.author_dropdown},
# {"viewclass": "SenderMenuItem",
# "text": "Label2",
# "caller":self.post_card.author_dropdown},
# ]
4 years ago
for channel in self.app.keys:
chip = ChannelChip()
4 years ago
chip.check=False
4 years ago
self.log(f'adding channel {channel}')
chip.text = '@'+channel
chip.font_name='assets/font.otf'
chip.md_bg_color=rgb(*COLOR_INACTIVE)
4 years ago
# chip2= SenderMenuItem()
# chip2.text = '@'+channel
# chip2.font_name='assets/font.otf'
# chip2.caller = self.post_card.author_dropdown
# chip2.md_bg_color=rgb(*COLOR_INACTIVE)
# # self.post_card.author_dropdown.add_widget(chip2)
# self.post_card.author_dropdown.add_widget(chip2)
4 years ago
# chip.theme_text_color='Custom'
# chip.text_color=rgb(*COLOR_INACTIVE)
self.channel_layout.add_widget(chip)
4 years ago
self.to_channels[channel]=False
4 years ago
4 years ago
# self.post_card.author_dropdown.items = menu_labels
# self.post_card.author_dropdown.width_mult = 4
4 years ago
post.scroller.remove_widget(post.post_content)
post.scroller.add_widget(post_TextField)
post.scroller.size=('300dp','300dp')
self.add_widget(post)
self.button_layout = ButtonLayout()
self.upload_button = UploadButton()
self.upload_button.screen = self
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.post_button.md_bg_color=(0,0,0,1)
self.upload_button.md_bg_color=(0,0,0,1)
self.post_status.md_bg_color=(0,0,0,1)
self.add_widget(self.button_layout)
# self.add_widget(self.post_status)
def write_post_status(self,x):
self.post_status.text=str(x)
if not self.post_status_added:
self.add_widget(self.post_status)
self.post_status_added=True
def open_dialog(self,msg):
if not hasattr(self,'dialog') or not self.dialog:
self.dialog = ProgressPopup()
self.dialog.ids.progress_label.text=msg
self.dialog.open()
def open_msg_dialog(self,msg):
if not hasattr(self,'msg_dialog') or not self.msg_dialog:
self.msg_dialog = MessagePopup()
self.msg_dialog.ids.msg_label.text=msg
self.msg_dialog.open()
def close_dialog(self):
if hasattr(self,'dialog'):
self.dialog.dismiss()
def close_msg_dialog(self):
if hasattr(self,'msg_dialog'):
self.msg_dialog.dismiss()
def choose(self):
# time.sleep(5)
self.upload_button.choose()
self.orig_img_src = self.upload_button.selection
# self.open_dialog('uploading')
# self.upload()
# self.close_dialog()
#mythread = threading.Thread(target=self.upload)
#mythread.start()
self.upload()
def upload(self):
# get file id
filename=self.orig_img_src[0] if self.orig_img_src and os.path.exists(self.orig_img_src[0]) else ''
if not filename: return
self.img_id = file_id = get_random_id()
self.img_ext = os.path.splitext(filename)[-1][1:]
# cache
tmp_img_fn = 'cache/'+self.img_id[:3]+'/'+self.img_id[3:]+'.'+self.img_ext
tmp_img_dir = os.path.dirname(tmp_img_fn)
if not os.path.exists(tmp_img_dir): os.makedirs(tmp_img_dir)
shutil.copyfile(filename, tmp_img_fn)
# add
self.add_image(tmp_img_fn)
# upload
#def do_upload():
4 years ago
asyncio.create_task(self.app.upload(tmp_img_fn, file_id=file_id))
# Thread(target=do_upload).start()
# self.close_dialog()
def add_image(self,filename):
if hasattr(self,'image_layout'):
self.post_card.remove_widget(self.image_layout)
self.image_layout = image_layout = PostImageLayout()
self.image = image = PostImage(source=filename)
# self.image.texture = img.texture
self.image.height = '300dp'
self.image_layout.add_widget(self.image)
self.image_layout.height='300dp'
self.post_card.add_widget(self.image_layout,index=1)
def post(self):
# check?
maxlen = 500
content = self.post_textfield.text
lencontent = content.strip().replace(' ',' ').count(' ')
# maxlen = int(self.post_textfield.max_text_length)
lendiff = lencontent - maxlen
if lendiff>0:
self.open_msg_dialog(f'Text is currently {lencontent} words long, which is {lendiff} over the maximum text length of {maxlen} words.\n\n({lencontent}/{maxlen})')
return
4 years ago
channels = [k[1:] for k,v in self.to_channels.items() if v]
if not channels:
self.log('no place was selected')
# self.='No place was selected'
return
# log('?????????????????'+self.media_uid)
4 years ago
# if not hasattr(self,'img_id') and self.upload_button.selection:
# log('REUPLOADING')
# self.upload()
async def do_post():
file_id = self.img_id if hasattr(self,'img_id') else None
file_ext = self.img_ext if hasattr(self,'img_ext') else None
4 years ago
await self.app.post(content=content, channels = channels, file_id=file_id, file_ext=file_ext)
import time
self.close_dialog()
self.open_dialog('posting')
#Thread(target=do_post).start()
asyncio.create_task(do_post())
# class ViewPostScreen(ProtectedScreen):
# post_id = ObjectProperty()
# def on_pre_enter(self):
# for child in self.children:
# log('child: '+str(child))
# self.remove_widget(child)
4 years ago
# post_json = self.app.get_post(self.root.post_id)
# post = PostCard(post_json)
# self.add_widget(post)
4 years ago
# def on_enter(self):
# for child in self.children: child.load_image()
# pass
def get_random_id():
import uuid
return uuid.uuid4().hex