2388 lines
87 KiB
Python
2388 lines
87 KiB
Python
import kivy
|
|
from kivymd.app import MDApp
|
|
from kivy.lang import Builder
|
|
from kivy.clock import Clock
|
|
|
|
from kivymd.uix.label import MDLabel
|
|
from kivymd.uix.button import MDIconButton, MDRaisedButton
|
|
from kivymd.uix.behaviors.magic_behavior import MagicBehavior
|
|
from kivymd.uix.textfield import MDTextField
|
|
from kivymd.uix.list import OneLineAvatarIconListItem, TwoLineAvatarIconListItem, ThreeLineAvatarIconListItem, IconRightWidget, MDList
|
|
from kivymd.uix.fitimage import FitImage
|
|
from kivymd.uix.snackbar import Snackbar
|
|
from kivymd.uix.menu import MDDropdownMenu
|
|
from kivymd.uix.bottomnavigation import MDBottomNavigationItem
|
|
from kivymd.uix.list import IRightBodyTouch
|
|
from kivy.uix.camera import Camera
|
|
|
|
from kivymd.uix.screen import MDScreen
|
|
from kivymd.uix.screenmanager import MDScreenManager
|
|
from kivy.core.window import Window
|
|
from kivymd.uix.controllers import WindowController
|
|
from kivymd.uix.dialog import MDDialog
|
|
from kivymd.uix.button import MDFlatButton
|
|
|
|
from kivymd.uix.boxlayout import MDBoxLayout
|
|
from kivymd.uix.relativelayout import MDRelativeLayout
|
|
|
|
import socketio
|
|
import os
|
|
from android.storage import app_storage_path
|
|
android_root_path = app_storage_path()
|
|
|
|
## remove before production
|
|
import time
|
|
## remove before production
|
|
|
|
kivy.require('2.1.0')
|
|
__version__ = "0.0.2"
|
|
|
|
# IMPORTS
|
|
import uuid as uniqueid
|
|
from modules.session.session import session_info, wait, db
|
|
from modules.session.time import timestamp
|
|
from modules.session.session import setting as setting_info
|
|
from modules.handler.request import request, account_page
|
|
from modules.handler.info import image as image_info
|
|
def generate_uuid():
|
|
uuid = str(uniqueid.uuid4())
|
|
return uuid
|
|
|
|
def dict_key_verify(dictionary, keys, mode="and", *args, **kwargs):
|
|
if mode != "and" and mode != "or":
|
|
mode = "and"
|
|
if type(keys) != list:
|
|
keys = [keys]
|
|
|
|
verified = []
|
|
if type(keys) != list:
|
|
keys = [keys]
|
|
|
|
for key in keys:
|
|
if type(dictionary) != dict or key not in dictionary or not dictionary[key]:
|
|
verified.append(False)
|
|
else:
|
|
verified.append(True)
|
|
|
|
if mode == "and":
|
|
if all(verified) == True:
|
|
return True
|
|
if mode == "or":
|
|
if True in verified:
|
|
return True
|
|
return False
|
|
|
|
def go_to(string, previous_line, file):
|
|
line = previous_line
|
|
while line != string:
|
|
line = file.readline().strip()
|
|
return line
|
|
|
|
def read_to(string, file):
|
|
line = file.readline().strip()
|
|
lines = []
|
|
while line != string:
|
|
lines.append(line)
|
|
line = file.readline().strip()
|
|
return lines
|
|
|
|
def get_dialog_content(dialog_title):
|
|
with open("./data/assets/help.txt", "r") as f:
|
|
line = f.readline().strip()
|
|
line = go_to(f"[{dialog_title}:START]", line, f)
|
|
line = go_to(f"(title:START)", line, f)
|
|
title = read_to(f"(title:END)", f)
|
|
line = go_to(f"(body:START)", line, f)
|
|
body_lines = read_to(f"(body:END)", f)
|
|
|
|
body = ""
|
|
for line in body_lines:
|
|
body += line + "\n"
|
|
body = body[:-2]
|
|
return {'title': title[0], 'body': body}
|
|
|
|
def open_help(app, page, dialog_title):
|
|
content = get_dialog_content(dialog_title)
|
|
page.dialog_help = HelpDialog(page, app, title=content['title'], text=content['body'])
|
|
page.dialog_help.open()
|
|
# IMPORTS
|
|
|
|
#================== socketio START ==================
|
|
sio = socketio.Client()
|
|
session = session_info()
|
|
|
|
# http://localhost:9999
|
|
def start_client(sio, url):
|
|
print("DEBUG: starting socketio client...")
|
|
try:
|
|
if not url:
|
|
url = "http://localhost:9999"
|
|
print(f"DEBUG: Connecting with url {url}")
|
|
sio.connect(url)
|
|
print("DEBUG: socketio client online!")
|
|
return True
|
|
except:
|
|
print("DEGUB: socketio client failed to connect!")
|
|
return False
|
|
|
|
def stop_client(sio):
|
|
print("DEBUG: stopping socketio client...")
|
|
sio.disconnect()
|
|
|
|
# connect/disconnect START
|
|
@sio.event
|
|
def connect():
|
|
print("DEBUG: Connected!")
|
|
|
|
@sio.event
|
|
def connect_error(data):
|
|
print("DEBUG: connection error")
|
|
|
|
@sio.event
|
|
def disconnect():
|
|
print("Disconnected")
|
|
# connect/disconnect END
|
|
|
|
@sio.event
|
|
def recv_status(data):
|
|
session.status = data
|
|
string = f"{data['time']} | {data['level']} | {data['message']}"
|
|
print(string)
|
|
#:import Snackbar kivymd.uix.snackbar.Snackbar
|
|
|
|
# auth START
|
|
@sio.event
|
|
def recv_token(data):
|
|
wait(session).wait_username()
|
|
session.auth_tokens.append(data['token'])
|
|
db().execute("INSERT INTO tokens(token, username, expire) VALUES(?, ?, ?)", (data['token'], session.username, data['expire']))
|
|
|
|
def login_cred(username="user", password="pass"):
|
|
data = {'username': username, 'password': password}
|
|
sio.emit('login', data, callback=auth)
|
|
|
|
def auth(callback, data):
|
|
print(data)
|
|
# auth END
|
|
|
|
# other events START
|
|
@sio.event
|
|
def notification(data):
|
|
pass
|
|
# other events END
|
|
|
|
#================== socketio END ==================
|
|
|
|
|
|
#================== kivy START ==================
|
|
|
|
# Utility START
|
|
class ExpandText(MDLabel):
|
|
pass
|
|
|
|
class ExpandPage(MDScreen):
|
|
def __init__(self, expand_text, banner, previous_page, **kwargs):
|
|
super(ExpandPage, self).__init__(**kwargs)
|
|
self.expand_text = expand_text
|
|
self.previous_page = previous_page
|
|
self.load_content()
|
|
self.toolbar.title = banner
|
|
|
|
@property
|
|
def expand_text(self):
|
|
return self._expand_text
|
|
@expand_text.setter
|
|
def expand_text(self, value):
|
|
if type(value) != str or type(value) != list:
|
|
if type(value) == str:
|
|
value = [value]
|
|
else:
|
|
value=None
|
|
self._expand_text = value
|
|
|
|
def load_content(self):
|
|
self.text_area.clear_widgets()
|
|
for text in self.expand_text:
|
|
item = ExpandText(text=text)
|
|
self.text_area.add_widget(item)
|
|
|
|
def back(self, app):
|
|
app.set_screen(self.previous_page.name, "right")
|
|
app.sm.remove_widget(self)
|
|
|
|
class HelpDialog(MDDialog):
|
|
def __init__(self, page, app, **kwargs):
|
|
kwargs["buttons"] = [MDFlatButton(text="Close", on_release=self.close, theme_text_color = "Custom", text_color=app.theme_cls.primary_color), MDFlatButton(text="Turn off help?", on_release=self.settings, theme_text_color = "Custom", text_color=app.theme_cls.primary_color)]
|
|
super().__init__(**kwargs)
|
|
self.page = page
|
|
self.app = app
|
|
|
|
def close(self, button):
|
|
self.page.dialog_help.dismiss()
|
|
|
|
def settings(self, button):
|
|
self.close(button)
|
|
if self.page.name == "SettingsPageScreen":
|
|
return
|
|
settings_screen_name = "SettingsPageScreen"
|
|
settings_screen = SettingsPage(self.page, name=settings_screen_name)
|
|
self.app.sm.add_widget(settings_screen)
|
|
|
|
self.app.set_screen(settings_screen_name, "left")
|
|
# Utility END
|
|
|
|
# HomePage START
|
|
class HomeSwiper(MDBoxLayout):
|
|
@property
|
|
def username(self):
|
|
return self._username
|
|
@username.setter
|
|
def username(self, value):
|
|
self.ids.username.text = value
|
|
self._username = value
|
|
|
|
@property
|
|
def caption(self):
|
|
return self._caption
|
|
@caption.setter
|
|
def caption(self, value):
|
|
if value == None:
|
|
value = ""
|
|
self.ids.caption.text = value
|
|
self._caption = value
|
|
|
|
@property
|
|
def content(self):
|
|
return self._content
|
|
@content.setter
|
|
def content(self, value):
|
|
self.load_image(value)
|
|
self.ids.content.source = self.image.path
|
|
self._content = self.image.path
|
|
|
|
def __init__(self, page, post_id, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.post_id = post_id
|
|
self.page = page
|
|
self.action_menu = None
|
|
|
|
self.load_content()
|
|
|
|
def load_image(self, value):
|
|
self.image = image_info(self.post_id)
|
|
self.image.load(value)
|
|
self.ids.content.source = self.image.path
|
|
|
|
def load_content(self):
|
|
post_data = {'post_id': self.post_id}
|
|
post_content = request(sio, session).emit('post_get', post_data)['posts']
|
|
|
|
self.username = post_content['username']
|
|
self.caption = post_content['caption']
|
|
self.content = post_content['content']
|
|
|
|
user_impression_data = {'items': ['username'], 'post_id': self.post_id, 'impression_type': "like"}
|
|
post_likes = request(sio, session).emit('post_impression_get_post', user_impression_data)['impressions']
|
|
|
|
impression_data = {'post_id': self.post_id, 'impression_type': "like"}
|
|
num_post_likes = request(sio, session).emit('post_impression_count', impression_data)['impression_count']
|
|
|
|
self.ids.like_number.text = str(num_post_likes)
|
|
if post_likes:
|
|
for like in post_likes:
|
|
if self.page.username in like['username']:
|
|
self.ids.like.icon = "heart"
|
|
|
|
def like(self):
|
|
server = request(sio, session)
|
|
|
|
if self.ids.like.icon == "heart-outline":
|
|
self.ids.like.icon = "heart"
|
|
|
|
data = {'impression_type': "like", 'post_id': self.post_id}
|
|
server.emit('post_impression_set', data, None)
|
|
self.ids.like_number.text = str(int(self.ids.like_number.text) + 1)
|
|
else:
|
|
self.ids.like.icon = "heart-outline"
|
|
|
|
data = {'impression_type': "like", 'post_id': self.post_id, 'items': ['username','impression_id']}
|
|
impression_info = server.emit('post_impression_get_post', data)
|
|
|
|
if dict_key_verify(impression_info, 'impressions'):
|
|
for impression in impression_info['impressions']:
|
|
if impression['username'] == self.page.username:
|
|
impression_id = impression['impression_id']
|
|
|
|
data = {'impression_type': "like", 'impression_id': impression_id}
|
|
server.emit('post_impression_delete', data, None)
|
|
self.ids.like_number.text = str(int(self.ids.like_number.text) - 1)
|
|
|
|
def switch_to_comments(self, app, direction='up'):
|
|
comments_screen_name = "CommentsPageScreen_"+self.post_id
|
|
comments_screen = CommentsPage(self.post_id, name=comments_screen_name)
|
|
app.sm.add_widget(comments_screen)
|
|
app.set_screen(comments_screen_name, direction)
|
|
|
|
def post_options(self, app, direction='right'):
|
|
data = {'post_id': self.post_id}
|
|
delete_allowed = request(sio, session).emit("post_get_permissions", data)['delete']
|
|
|
|
if delete_allowed:
|
|
profile_item = {'text': "view profile", 'viewclass': "OneLineListItem", 'on_release': lambda x=app: self.switch_to_account(app)}
|
|
delete_item = {'text': "delete post", 'viewclass': "OneLineListItem", 'on_release': lambda: self.delete_post()}
|
|
items = [profile_item, delete_item]
|
|
self.action_menu = MDDropdownMenu(caller=self.account_button, items=items, width_mult=3)
|
|
self.action_menu.open()
|
|
else:
|
|
self.switch_to_account(app, direction)
|
|
|
|
def delete_post(self):
|
|
if self.action_menu:
|
|
self.action_menu.dismiss()
|
|
data = {'post_id': self.post_id}
|
|
request(sio, session).emit("post_delete", data, None)
|
|
self.page.home_swiper_grid.remove_widget(self)
|
|
if len(self.page.home_swiper_grid.children) == 1:
|
|
self.page.load_home()
|
|
|
|
def switch_to_account(self, app, direction='right'):
|
|
if self.action_menu:
|
|
self.action_menu.dismiss()
|
|
self.page.switch_to_account(app, self.username, direction)
|
|
|
|
class HomeLoadButton(MDBoxLayout):
|
|
def __init__(self, **kwargs):
|
|
if 'home_obj' in kwargs and kwargs['home_obj']:
|
|
if kwargs['home_obj']:
|
|
self.home_obj = kwargs['home_obj']
|
|
del kwargs['home_obj']
|
|
super().__init__(**kwargs)
|
|
|
|
def load_content(self):
|
|
self.home_obj.home_swiper_grid.remove_widget(self)
|
|
self.home_obj.load_home()
|
|
|
|
class NoPostLabel(MDBoxLayout):
|
|
pass
|
|
|
|
class MemoriesMonth(MDBoxLayout):
|
|
def get_memories_swiper_height(self):
|
|
swiper_height = Window.height * 0.8 * 0.02
|
|
return swiper_height
|
|
|
|
class SwiperMagicButton(MagicBehavior,MDIconButton):
|
|
pass
|
|
|
|
class MemoriesSwiper(MDBoxLayout):
|
|
pass
|
|
|
|
class OccupationPageButton(MDRaisedButton):
|
|
def __init__(self, tab, page, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.tab = tab
|
|
self.page = page
|
|
|
|
def switch_to_occupation(self, app):
|
|
self.tab.switch_to_occupation(app)
|
|
|
|
class OrganisationBottomItem(MDBottomNavigationItem):
|
|
def __init__(self, page, username, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.page = page
|
|
self.load_content()
|
|
self.username = username
|
|
|
|
def load_content(self):
|
|
occupation_button = OccupationPageButton(self, self.page)
|
|
level = request(sio, session).emit('auth_get')['level']
|
|
if level != "member":
|
|
self.occupation_button_area.add_widget(occupation_button)
|
|
|
|
def switch_to_occupation(self, app, direction="left"):
|
|
occupation_screen_name = "OccupationPageScreen"
|
|
occupation_screen = OccupationPage(self.page, name=occupation_screen_name)
|
|
|
|
app.sm.add_widget(occupation_screen)
|
|
app.set_screen(occupation_screen_name, direction)
|
|
|
|
def switch_to_team(self, app, direction="left"):
|
|
team_screen_name = "TeamPageScreen"
|
|
team_screen = TeamPage(self.page, self.username, name=team_screen_name)
|
|
|
|
app.sm.add_widget(team_screen)
|
|
app.set_screen(team_screen_name, direction)
|
|
|
|
class MonthListItem(OneLineAvatarIconListItem):
|
|
def __init__(self, date, posts, month_list, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.month_list = month_list
|
|
self.posts = posts
|
|
self.date = date
|
|
|
|
def day_view(self):
|
|
day_list = DayList(self.date, self.posts, self.month_list)
|
|
self.month_list.page.root_scroll.remove_widget(self.month_list)
|
|
self.month_list.page.root_scroll.add_widget(day_list)
|
|
|
|
class MonthList(MDBoxLayout):
|
|
def __init__(self, page, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.page = page
|
|
self.back_stack = [self]
|
|
self.load_content()
|
|
|
|
def load_content(self):
|
|
month_list = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
|
|
data = {'items': ['post_id', 'date']}
|
|
post_response = request(sio, session).emit("post_get_memories", data)
|
|
|
|
if dict_key_verify(post_response, 'posts'):
|
|
posts = post_response['posts']
|
|
post_months = {}
|
|
|
|
for post in posts:
|
|
# groups posts into a list in a dictionary where the key is their respective month
|
|
if dict_key_verify(post, 'date'):
|
|
date = post['date']
|
|
date_list = date.split("-")
|
|
if dict_key_verify(post_months, date):
|
|
post_months[date].append(post)
|
|
else:
|
|
post_months[date] = [post]
|
|
|
|
for post_group in post_months:
|
|
# for each list of posts that were created within a certain month
|
|
date = post_group.split("-")
|
|
month_name = month_list[int(date[1])-1]
|
|
date_string = date[0] + ": " + month_name
|
|
|
|
item = MonthListItem(date, post_months[post_group], self, text=date_string)
|
|
self.scroll.add_widget(item)
|
|
|
|
else:
|
|
# To handle for the case where no past posts exist
|
|
item = OneLineAvatarIconListItem(text="No memories :(")
|
|
self.scroll.add_widget(item)
|
|
|
|
class DayListItem(OneLineAvatarIconListItem):
|
|
def __init__(self, date, post, day_list, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.day_list = day_list
|
|
self.post = post
|
|
self.date = date
|
|
|
|
def post_open(self):
|
|
memory = MemoryLayout(self.post, self.day_list)
|
|
area = self.day_list.month_list.page.root_scroll
|
|
area.clear_widgets()
|
|
area.add_widget(memory)
|
|
|
|
class DayList(MDBoxLayout):
|
|
def __init__(self, date, posts, month_list, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.month_list = month_list
|
|
self.posts = posts
|
|
self.date = date
|
|
self.back_stack = self.month_list.back_stack
|
|
|
|
self.back_stack.append(self)
|
|
self.load_content()
|
|
|
|
def load_content(self):
|
|
for post in self.posts:
|
|
date_string = self.date[2]
|
|
item = DayListItem(self.date, post, self, text=date_string)
|
|
self.scroll.add_widget(item)
|
|
|
|
def back(self):
|
|
last = len(self.back_stack)-1
|
|
self.month_list.page.root_scroll.clear_widgets()
|
|
self.month_list.page.root_scroll.add_widget(self.back_stack[last-1])
|
|
self.back_stack.pop(last)
|
|
|
|
class MemoryLayout(MDBoxLayout):
|
|
def __init__(self, post, day_list, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.post = post
|
|
self.day_list = day_list
|
|
self.page = self.day_list.month_list.page
|
|
self.back_stack = self.day_list.back_stack
|
|
|
|
self.back_stack.append(self)
|
|
self.load_content()
|
|
|
|
def remove_username(self, post):
|
|
# the normal post widget is used, so we just have to remove the username.
|
|
post.ids.username.text = self.post['date']
|
|
post.ids.profile_area.remove_widget(post.ids.account_button)
|
|
|
|
def load_content(self):
|
|
post = HomeSwiper(self.page, self.post['post_id'])
|
|
self.remove_username(post)
|
|
self.post_area.add_widget(post)
|
|
|
|
class HomePage(MDScreen, WindowController):
|
|
def __init__(self, username=None, app=None, **kwargs):
|
|
super().__init__(**kwargs)
|
|
post_login()
|
|
|
|
self.username = username
|
|
self.app = app
|
|
|
|
self.account_screens = []
|
|
self.notifications_screens = []
|
|
self.settings_screen = None
|
|
self.settings_screen_name = None
|
|
|
|
self.posts_displayed = []
|
|
self.post_exist = False
|
|
self.camera_widget_exists = False
|
|
self.camera_page_screen = None
|
|
|
|
self.organisation_item_exists = False
|
|
|
|
self.post_slot = request(sio, session).emit("post_slot_get")
|
|
self.posted_today()
|
|
self.load_content()
|
|
|
|
self.selected_tab = "Home"
|
|
self.help_tool = ["help", lambda x: self.open_help(self.app)]
|
|
|
|
def login(self):
|
|
login_cred()
|
|
|
|
def load_content(self):
|
|
self.load_home()
|
|
self.load_memories()
|
|
self.load_organisation()
|
|
Clock.schedule_interval(self.check_post_time, 1)
|
|
self.load_toolbar()
|
|
|
|
def load_toolbar(self):
|
|
# Loading the toolbar is used to refresh when the "help boxes" setting is configured.
|
|
# Saves entire page having to be re-loaded and just updates toolbar
|
|
if not setting_info("Help boxes").value:
|
|
for i, option in enumerate(self.toolbar.right_action_items):
|
|
if option[0].lower() == "help":
|
|
self.toolbar.right_action_items.pop(i)
|
|
else:
|
|
toolbar_len = len(self.toolbar.right_action_items)
|
|
for i in range(toolbar_len):
|
|
if self.toolbar.right_action_items[i][0] == "help":
|
|
return
|
|
new_toolbar = [self.help_tool] + self.toolbar.right_action_items[0:]
|
|
self.toolbar.right_action_items = new_toolbar
|
|
|
|
def on_tab_press(self, name):
|
|
self.selected_tab = name
|
|
|
|
def open_help(self, app):
|
|
level = request(sio, session).emit('auth_get')['level']
|
|
|
|
if self.selected_tab == "Home":
|
|
open_help(app, self, "Home")
|
|
elif self.selected_tab == "Memories":
|
|
open_help(app, self, "Memories")
|
|
elif self.selected_tab == "Organisation" and level == "member":
|
|
open_help(app, self, "Organisation")
|
|
elif self.selected_tab == "Organisation" and level != "member":
|
|
open_help(app, self, "Organisation-admin")
|
|
|
|
# SWITCHING
|
|
def switch_to_settings(self, app, direction='left'):
|
|
settings_screen_name = "SettingsPageScreen"
|
|
settings_screen = SettingsPage(self, name=settings_screen_name)
|
|
app.sm.add_widget(settings_screen)
|
|
|
|
app.set_screen(settings_screen_name, direction)
|
|
|
|
def switch_to_account(self, app, username=None, direction='right', *args, **kwargs):
|
|
if not username:
|
|
username = self.username
|
|
account_screen_name = "AccountPageScreen_"+username
|
|
|
|
account_screen = AccountPage(username, self, name=account_screen_name)
|
|
app.sm.add_widget(account_screen)
|
|
app.set_screen(account_screen_name, direction)
|
|
|
|
def switch_to_notifications(self, app, username=None, direction='right', *args, **kwargs):
|
|
if not username:
|
|
username = self.username
|
|
notifications_screen_name = "NotificationsScreen-"+username
|
|
notifications_screen = NotificationsPage(username, self, name=notifications_screen_name)
|
|
app.sm.add_widget(notifications_screen)
|
|
app.set_screen(notifications_screen_name, direction)
|
|
|
|
# FETCHING DATA
|
|
def fetch_posts(self):
|
|
data = {'items': ['post_id']}
|
|
posts = request(sio, session).emit('post_get_feed', data)['posts']
|
|
post_list = []
|
|
|
|
if self.post_made:
|
|
post = request(sio, session).emit("post_get_user")
|
|
if dict_key_verify(post, "posts"):
|
|
post = post['posts']
|
|
if dict_key_verify(post, "post_id"):
|
|
if post['post_id'] not in self.posts_displayed:
|
|
post_list.append(post)
|
|
|
|
if posts:
|
|
for i, post in enumerate(posts):
|
|
if post:
|
|
post_list.append(post)
|
|
|
|
return post_list
|
|
|
|
# HOME
|
|
def load_home(self):
|
|
posts = self.fetch_posts()
|
|
post_list = []
|
|
|
|
if posts:
|
|
for i, post in enumerate(posts):
|
|
if post['post_id'] not in self.posts_displayed:
|
|
post_list.append(post)
|
|
posts = post_list
|
|
|
|
for i, post in enumerate(posts):
|
|
|
|
if not self.post_exist:
|
|
self.home_swiper_grid.clear_widgets()
|
|
self.post_exist = True
|
|
home_swiper = HomeSwiper(self, post['post_id'])
|
|
if i == 0:
|
|
first_home_swiper = home_swiper
|
|
|
|
self.home_swiper_grid.add_widget(home_swiper)
|
|
self.posts_displayed.append(post['post_id'])
|
|
if i == 4:
|
|
break
|
|
|
|
if "first_home_swiper" in locals():
|
|
self.home_swiper_scroll.scroll_to(first_home_swiper)
|
|
|
|
if not posts:
|
|
Snackbar(text="Sorry, no more posts").open()
|
|
|
|
else:
|
|
if not self.post_exist:
|
|
self.home_swiper_grid.clear_widgets()
|
|
self.home_swiper_grid.add_widget(NoPostLabel())
|
|
|
|
self.load_more_button = HomeLoadButton(home_obj=self)
|
|
self.home_swiper_grid.add_widget(self.load_more_button)
|
|
|
|
def get_home_swiper_height(self):
|
|
swiper_height = Window.height * 0.70
|
|
return swiper_height
|
|
|
|
# MEMORIES
|
|
def get_memories_swiper_height(self):
|
|
month_height = self.get_memories_month_height()
|
|
swiper_height = month_height * 0.8 * 0.02
|
|
return swiper_height
|
|
|
|
def get_memories_month_height(self):
|
|
month_height = Window.height * 2
|
|
return month_height
|
|
|
|
def load_memories(self):
|
|
self.root_scroll.clear_widgets()
|
|
item = MonthList(self)
|
|
self.root_scroll.add_widget(item)
|
|
|
|
# STATS
|
|
def load_stats(self):
|
|
pass
|
|
|
|
# ORGANISATION
|
|
def load_organisation(self):
|
|
if not self.organisation_item_exists:
|
|
self.organisation_item_exists = True
|
|
self.bottom_navigation.add_widget(OrganisationBottomItem(self, self.username))
|
|
|
|
# SIZE
|
|
def update(self):
|
|
self.home_swiper_grid.row_default_height = self.get_home_swiper_height()
|
|
|
|
def on_size(self, *args):
|
|
self.update()
|
|
|
|
# Post time
|
|
def posted_today(self):
|
|
date = {'items': ['date']}
|
|
posts = request(sio, session).emit("post_get_memories", date)['posts']
|
|
if posts:
|
|
date = request(sio, session).emit("get_date")['date']
|
|
for post in posts:
|
|
if date == post['date']:
|
|
self.post_made = True
|
|
return
|
|
self.post_made = False
|
|
|
|
def check_post_time(self, dt):
|
|
now = timestamp().now
|
|
if self.post_slot['post_slot_start'] < now and self.post_slot['post_slot_end'] > now and not self.post_made:
|
|
if not self.camera_widget_exists:
|
|
self.toolbar.right_action_items.append(["camera", lambda x: self.switch_to_camera(self.app, direction='up')])
|
|
self.camera_widget_exists = True
|
|
else:
|
|
for i, action_item in enumerate(self.toolbar.right_action_items):
|
|
if "camera" in action_item:
|
|
self.toolbar.right_action_items.pop(i)
|
|
break
|
|
|
|
def switch_to_camera(self, app, direction="up"):
|
|
camera_page_screen_name = "CameraPageScreen"
|
|
self.camera_page_screen = CameraPage(self, name=camera_page_screen_name)
|
|
app.sm.add_widget(self.camera_page_screen)
|
|
app.set_screen(camera_page_screen_name, direction)
|
|
|
|
# First time
|
|
def check_first_time(self, app):
|
|
occupation = request(sio, session).emit("occupation_get")
|
|
profile = request(sio, session).emit("profile_get", {'items': ['role', 'name']})
|
|
friends = request(sio, session).emit("friend_get")['friends']
|
|
if not occupation['occupation_id'] and not friends and not profile['role'] and not profile['name']:
|
|
first_time_page_screen_name = "FirstTimePage"
|
|
first_time_page_screen = FirstTimePage(name=first_time_page_screen_name)
|
|
app.sm.add_widget(first_time_page_screen)
|
|
app.set_screen(first_time_page_screen_name, "down")
|
|
# HomePage END
|
|
|
|
|
|
# Comments START
|
|
class CommentContainer(IRightBodyTouch, MDBoxLayout):
|
|
pass
|
|
|
|
class Comment(TwoLineAvatarIconListItem):
|
|
def __init__(self, username, comment_id, page, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.username = username
|
|
self.comment_id = comment_id
|
|
self.page = page
|
|
self.screen_prefix = "comment"
|
|
self.action_menu = None
|
|
|
|
self.load_content()
|
|
|
|
def liked_previously(self):
|
|
data = {'comment_id': self.comment_id}
|
|
impressions = request(sio, session).emit("comment_impression_get_comment", data)['impressions']
|
|
|
|
if impressions:
|
|
for impression in impressions:
|
|
if dict_key_verify(impression, "username"):
|
|
if session.username == impression['username']:
|
|
self.impression_id = impression['impression_id']
|
|
return True
|
|
return False
|
|
|
|
def load_content(self):
|
|
if self.liked_previously():
|
|
self.like_button.icon = "heart"
|
|
|
|
data = {'impression_type': "like", 'comment_id': self.comment_id}
|
|
count = request(sio, session).emit("comment_impression_count", data)['impression_count']
|
|
self.like_count.text = str(count)
|
|
|
|
def expand(self, app):
|
|
expand_page_name = f"{self.screen_prefix}_expand_page_{self.username}"
|
|
expand_page = ExpandPage(self.secondary_text, self.text+"'s comment", self.page, name=expand_page_name)
|
|
app.sm.add_widget(expand_page)
|
|
app.set_screen(expand_page_name, "left")
|
|
|
|
def like(self):
|
|
if self.like_button.icon == "heart-outline":
|
|
data = {'impression_type': "like", 'comment_id': self.comment_id}
|
|
request(sio, session).emit('comment_impression_set', data, None)
|
|
if self.liked_previously():
|
|
self.like_button.icon = "heart"
|
|
self.like_count.text = str(int(self.like_count.text)+1)
|
|
else:
|
|
self.like_button.icon = "heart-outline"
|
|
data = {'impression_id': self.impression_id}
|
|
request(sio, session).emit("comment_impression_delete", data, None)
|
|
self.like_count.text = str(int(self.like_count.text)-1)
|
|
|
|
def profile(self, app):
|
|
if self.action_menu:
|
|
self.action_menu.dismiss()
|
|
account_page_name = f"{self.screen_prefix}_account_page_{self.username}"
|
|
account_page = AccountPage(self.username, self.page, remove_on_exit=True, name=account_page_name)
|
|
app.sm.add_widget(account_page)
|
|
app.set_screen(account_page_name, "right")
|
|
|
|
def delete_comment(self):
|
|
if self.action_menu:
|
|
self.action_menu.dismiss()
|
|
data = {'comment_id': self.comment_id}
|
|
request(sio, session).emit("comment_delete", data, None)
|
|
self.page.comment_stack.remove_widget(self)
|
|
if not self.page.comment_stack.children:
|
|
self.page.load_content()
|
|
|
|
def action_options(self, app):
|
|
data = {'comment_id': self.comment_id}
|
|
delete_allowed = request(sio, session).emit("comment_get_permissions", data)['delete']
|
|
|
|
if delete_allowed:
|
|
profile_item = {'text': "view profile", 'viewclass': "OneLineListItem", 'on_release': lambda x=app: self.profile(app)}
|
|
delete_item = {'text': "delete comment", 'viewclass': "OneLineListItem", 'on_release': lambda: self.delete_comment()}
|
|
items = [profile_item, delete_item]
|
|
self.action_menu = MDDropdownMenu(caller=self.profile_button, items=items, width_mult=3)
|
|
self.action_menu.open()
|
|
else:
|
|
self.profile(app)
|
|
|
|
class CommentsPage(MDScreen):
|
|
def __init__(self, post_id, **kwargs):
|
|
super(CommentsPage, self).__init__(**kwargs)
|
|
self.post_id = post_id
|
|
self.comments = []
|
|
self.comments_exist = False
|
|
self.load_content()
|
|
|
|
def get_comments(self):
|
|
data = {'post_id': self.post_id}
|
|
comments = request(sio, session).emit("comment_get_post", data)['comments']
|
|
return comments
|
|
|
|
def add_comment(self, comment):
|
|
if not self.comments:
|
|
self.comment_stack.clear_widgets()
|
|
|
|
comment_id = comment['comment_id']
|
|
username = comment['username']
|
|
|
|
comment_item = Comment(username, comment_id, self, text=username, secondary_text=comment['content'])
|
|
self.comments.append(comment_id)
|
|
self.comment_stack.add_widget(comment_item)
|
|
|
|
# LOADING
|
|
def load_content(self):
|
|
self.comment_stack.clear_widgets()
|
|
comments = self.get_comments()
|
|
|
|
if comments:
|
|
for comment in comments:
|
|
self.add_comment(comment)
|
|
else:
|
|
item = OneLineAvatarIconListItem(text="No comments :(")
|
|
self.comment_stack.add_widget(item)
|
|
|
|
def submit(self):
|
|
content = self.comment_field.text
|
|
data = {'post_id': self.post_id, 'content': content}
|
|
request(sio, session).emit("comment_set", data, None)
|
|
self.comment_field.text = ""
|
|
comments = self.get_comments()
|
|
for comment in comments:
|
|
if comment['username'] == session.username and comment['content'] == content and comment['comment_id'] not in self.comments:
|
|
self.add_comment(comment)
|
|
break
|
|
|
|
# SWITCHING
|
|
def switch_to_home(self, app):
|
|
app.set_screen("HomePageScreen", 'down')
|
|
app.sm.remove_widget(self)
|
|
# Comments END
|
|
|
|
|
|
# Post START
|
|
class CameraPage(MDScreen):
|
|
def __init__(self, previous_page, **kwargs):
|
|
super(CameraPage, self).__init__(**kwargs)
|
|
self.path = "data/images/post.png"
|
|
self.post_slot = request(sio, session).emit("post_slot_get")
|
|
self.previous_page = previous_page
|
|
Window.size = (800, 600)
|
|
|
|
self.load_content()
|
|
self.refresh_time()
|
|
Clock.schedule_interval(self.refresh_time, 1)
|
|
|
|
def load_content(self):
|
|
self.camera = Camera(play=True)
|
|
self.camera_area.add_widget(self.camera)
|
|
|
|
if not setting_info("Help boxes").value:
|
|
for i, option in enumerate(self.toolbar.right_action_items):
|
|
if option[0].lower() == "help":
|
|
self.toolbar.right_action_items.pop(i)
|
|
|
|
def open_help(self, app):
|
|
open_help(app, self, "Camera")
|
|
|
|
def format_time(self, time_left):
|
|
time_left = int(time_left)
|
|
# time is given in Unix time so we convert it
|
|
seconds = time_left%60
|
|
# integer division means we only get how many whole minutes are left
|
|
# we modded seconds by 60 to get the number of seconds - numbe
|
|
minutes = time_left//60
|
|
if minutes > 60:
|
|
hours = minutes//60
|
|
minutes = minutes - hours*60
|
|
time_format = f"{hours}:{minutes}:{seconds}"
|
|
return time_format
|
|
|
|
def refresh_time(self, dt=None):
|
|
length = self.post_slot['post_slot_end'] - self.post_slot['post_slot_start']
|
|
time_in = timestamp().now - self.post_slot['post_slot_start']
|
|
time_left = round(length - time_in, 2)
|
|
time_format = self.format_time(time_left)
|
|
self.top_bar.title = f"Time left: {time_format}"
|
|
|
|
def capture(self, app):
|
|
self.camera.export_to_png(self.path)
|
|
self.camera_to_post(app)
|
|
|
|
def camera_to_post(self, app):
|
|
post_review_page_screen_name = "PostReviewPage"
|
|
post_review_page_screen = PostReviewPage(self, self.path, name=post_review_page_screen_name)
|
|
app.sm.add_widget(post_review_page_screen)
|
|
app.set_screen(post_review_page_screen_name, "left")
|
|
|
|
def exit(self, app):
|
|
app.set_screen("HomePageScreen", "down")
|
|
app.sm.remove_widget(self)
|
|
Window.size = (800, 1000)
|
|
|
|
class PostReviewPage(MDScreen):
|
|
def __init__(self, camera_page, path, **kwargs):
|
|
super(PostReviewPage, self).__init__(**kwargs)
|
|
self.path = path
|
|
self.camera_page = camera_page
|
|
self.post_slot = request(sio, session).emit("post_slot_get")
|
|
|
|
self.load_content()
|
|
self.refresh_time()
|
|
Clock.schedule_interval(self.refresh_time, 1)
|
|
|
|
def load_content(self):
|
|
self.image.source = self.path
|
|
|
|
if not setting_info("Help boxes").value:
|
|
for i, option in enumerate(self.toolbar.right_action_items):
|
|
if option[0].lower() == "help":
|
|
self.toolbar.right_action_items.pop(i)
|
|
|
|
def open_help(self, app):
|
|
open_help(app, self, "PostReview")
|
|
|
|
def refresh_time(self, dt=None):
|
|
length = self.post_slot['post_slot_end'] - self.post_slot['post_slot_start']
|
|
time_in = timestamp().now - self.post_slot['post_slot_start']
|
|
time_left = round(length - time_in, 2)
|
|
time_format = self.camera_page.format_time(time_left)
|
|
self.top_bar.title = f"Time left: {time_format}"
|
|
|
|
def post(self, app):
|
|
with open(self.path, "rb") as image:
|
|
image_data = image.read()
|
|
data = {'content': image_data, 'caption': self.caption.text}
|
|
request(sio, session).emit("post_set", data, None)
|
|
self.camera_page.previous_page.post_made = True
|
|
self.image.source = ""
|
|
os.remove(self.path)
|
|
self.exit(app, "down")
|
|
self.camera_page.previous_page.load_memories()
|
|
self.camera_page.previous_page.load_home()
|
|
|
|
def retake(self, app):
|
|
os.remove(self.path)
|
|
self.post_to_camera(app)
|
|
|
|
def post_to_camera(self, app, direction="right"):
|
|
app.set_screen(self.camera_page.name, direction)
|
|
self.ids.image_area.remove_widget(self.image)
|
|
app.sm.remove_widget(self)
|
|
|
|
def exit(self, app, direction="down"):
|
|
app.set_screen("HomePageScreen", "down")
|
|
if not self.camera_page.previous_page.post_made:
|
|
os.remove(self.path)
|
|
app.sm.remove_widget(self.camera_page)
|
|
app.sm.remove_widget(self)
|
|
Window.size = (800, 1000)
|
|
# Post END
|
|
|
|
|
|
# Acccount START
|
|
class ProfileInfo(TwoLineAvatarIconListItem):
|
|
def __init__(self, account_page=None, info_type=None, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.info_type = info_type
|
|
self.account_page = account_page
|
|
|
|
def set_title(self, text):
|
|
if text and type(text) == str:
|
|
text = (text.replace("_", " ")).capitalize()
|
|
self.text = text
|
|
|
|
def set_content(self, text):
|
|
if text and type(text) == str:
|
|
self.secondary_text = text
|
|
|
|
def make_editable(self):
|
|
button = InfoEditButton(self.account_page, self.info_type)
|
|
self.add_widget(button)
|
|
|
|
class InfoEditButton(IconRightWidget):
|
|
def __init__(self, account_page_obj=None, info_type=None, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.info_type = info_type
|
|
self.account_page_obj = account_page_obj
|
|
self.account_page_obj.currently_editing = None
|
|
|
|
def change_info(self):
|
|
if self.icon == "pencil":
|
|
if self.account_page_obj.currently_editing:
|
|
self.account_page_obj.currently_editing.icon = "pencil"
|
|
self.account_page_obj.currently_editing = self
|
|
self.account_page_obj.picture_to_textbox(self.info_type)
|
|
else:
|
|
self.account_page_obj.textbox_to_picture()
|
|
|
|
class BioEditButton(MDIconButton):
|
|
def __init__(self, account_page_obj=None, info_type="biography", **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.info_type = info_type
|
|
self.account_page_obj = account_page_obj
|
|
self.account_page_obj.currently_editing = None
|
|
|
|
def change_info(self):
|
|
if self.icon == "pencil":
|
|
if self.account_page_obj.currently_editing:
|
|
self.account_page_obj.currently_editing.icon = "pencil"
|
|
self.account_page_obj.currently_editing = self
|
|
self.account_page_obj.picture_to_textbox(self.info_type)
|
|
else:
|
|
self.account_page_obj.textbox_to_picture()
|
|
|
|
class ProfilePicture(FitImage):
|
|
pass
|
|
|
|
class InfoChangeBox(MDBoxLayout):
|
|
def __init__(self, page, info_type, username=session.username, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.username = username
|
|
self.info_type = info_type
|
|
self.page = page
|
|
|
|
self.load_content()
|
|
|
|
def load_content(self):
|
|
self.text_field.text = self.page.info[self.info_type]
|
|
|
|
def save(self):
|
|
new_value = self.text_field.text
|
|
self.page.info[self.info_type] = new_value
|
|
account_page(sio).set_profile(self.info_type, new_value, self.username)
|
|
self.page.refresh_content()
|
|
self.page.textbox_to_picture()
|
|
|
|
class OccupationChange(MDBoxLayout):
|
|
def __init__(self, page=None, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.occupations = request(sio, session).emit('occupation_get_all')
|
|
self.current_selection = None
|
|
self.occupations_info = []
|
|
self.menu = None
|
|
if page:
|
|
self.page = page
|
|
|
|
def selection_menu(self):
|
|
if dict_key_verify(self.occupations, 'occupations'):
|
|
self.occupations_info = self.occupations['occupations']
|
|
items = []
|
|
for i, occupation in enumerate(self.occupations_info):
|
|
item = {'text': occupation['name'], 'viewclass': "OneLineListItem", 'on_release': lambda x=i: self.selection(x)}
|
|
items.append(item)
|
|
self.menu = MDDropdownMenu(caller=self.occupation_select, items=items, width_mult=2)
|
|
self.menu.open()
|
|
else:
|
|
message = "No occupations"
|
|
Snackbar(text=message).open()
|
|
|
|
def selection(self, item_num):
|
|
self.occupation_select.text = self.occupations_info[item_num]['name']
|
|
self.occupation_description.text = self.occupations_info[item_num]['description']
|
|
self.current_selection = item_num
|
|
self.menu.dismiss()
|
|
|
|
|
|
class UserOccupationChange(OccupationChange):
|
|
def __init__(self, page=None, **kwargs):
|
|
super().__init__(page, **kwargs)
|
|
self.load_content()
|
|
|
|
def cancel(self):
|
|
request(sio, session).emit('occupation_delete_request', {}, None)
|
|
message = f"{session.status['level']}: {session.status['message']}"
|
|
Snackbar(text=message).open()
|
|
self.load_content()
|
|
self.page.textbox_to_picture()
|
|
|
|
def submit(self):
|
|
if self.current_selection or self.current_selection == 0:
|
|
data = {'occupation_id': self.occupations_info[self.current_selection]['occupation_id']}
|
|
request(sio, session).emit('occupation_set_request', data, None)
|
|
else:
|
|
message = "No selection made"
|
|
Snackbar(text=message).open()
|
|
self.load_content()
|
|
self.occupation_select.text = "Select an occupation"
|
|
self.occupation_description.text = ""
|
|
self.page.textbox_to_picture()
|
|
|
|
def load_content(self):
|
|
occupation_request = request(sio, session).emit('occupation_get_request')
|
|
if dict_key_verify(occupation_request, 'occupation_id'):
|
|
occupation = request(sio, session).emit('occupation_get', {'occupation_id': occupation_request['occupation_id']})
|
|
|
|
if occupation:
|
|
self.request_occupation.text = occupation['name']
|
|
|
|
if occupation_request['approved']:
|
|
request_status = "Approved"
|
|
else:
|
|
request_status = "Pending"
|
|
|
|
self.request_status.text = "Status: "+request_status
|
|
else:
|
|
Snackbar(text=session.status).open()
|
|
|
|
class ManagementOccupationChange(OccupationChange):
|
|
def __init__(self, page, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.page = page
|
|
|
|
def submit(self):
|
|
if self.occupations_info:
|
|
data = {'occupation_id': self.occupations_info[self.current_selection]['occupation_id']}
|
|
request(sio, session).emit('occupation_set', data, None)
|
|
message = f"{session.status['message']}"
|
|
self.occupation_select.text = "Select an occupation"
|
|
self.occupation_description.text = ""
|
|
else:
|
|
message = f"No occupation selected"
|
|
Snackbar(text=message).open()
|
|
|
|
if self.occupations_info:
|
|
self.page.textbox_to_picture()
|
|
|
|
class AccountPage(MDScreen):
|
|
def __init__(self, username=session.username, previous_page=None, remove_on_exit=True, **kwargs):
|
|
super(AccountPage, self).__init__(**kwargs)
|
|
self.username = username
|
|
self.info_objs = []
|
|
self.bio_edit_button = None
|
|
self.load_content()
|
|
self.friend_page_screen = None
|
|
self.remove_on_exit = remove_on_exit
|
|
if previous_page == None:
|
|
self.previous_page = "HomePageScreen"
|
|
else:
|
|
self.previous_page = previous_page.name
|
|
|
|
def load_content(self):
|
|
# clears the page of its contents
|
|
self.above_info.clear_widgets()
|
|
self.profile_info_view.clear_widgets()
|
|
if self.bio_edit_button:
|
|
self.profile_bio_view.remove_widget(self.bio_edit_button)
|
|
|
|
req = request(sio, session)
|
|
self.info = req.emit("profile_get")
|
|
|
|
permissions_data = {'username': session.username, 'target_username': self.username}
|
|
self.permissions = req.emit("profile_get_permissions", permissions_data)
|
|
|
|
# this is for when another user clicks in to see someone elses profile
|
|
if self.username != session.username:
|
|
self.toolbar.title = self.username+"'s Profile"
|
|
|
|
level = req.emit('auth_get')['level']
|
|
# if their management or admin staff they can also click into see the persons friends
|
|
# else this is not available so we remove the buttons
|
|
if level == "member":
|
|
self.toolbar.left_action_items = []
|
|
|
|
if dict_key_verify(self.info, "occupation_id"):
|
|
# adds to the profile info the team name
|
|
team_data = {'occupation_id': self.info['occupation_id'], 'items': ["name"]}
|
|
self.info['team'] = req.emit("team_get", team_data)['name']
|
|
|
|
# adds the occupation name to the profile info
|
|
occupation_data = {'occupation_id': self.info['occupation_id'], 'items': ["name"]}
|
|
self.info['occupation'] = req.emit("occupation_get", occupation_data)['name']
|
|
else:
|
|
# if occupation_id is none it means the person doesnt have any teams etc
|
|
self.info['team'] = ""
|
|
self.info['occupation'] = ""
|
|
# deletes occupation_id to stop it being added later on as a value displayed to the user
|
|
del self.info['occupation_id']
|
|
|
|
self.info['username'] = self.username
|
|
# defines the list order
|
|
order = ['username', 'name', 'role', 'occupation', 'team']
|
|
|
|
# biography doesnt exist in the same list of profile attributes because it is given more space, since these can often be longer
|
|
# this means they have to be delt with in their own way
|
|
self.bio_edit_button = BioEditButton(self)
|
|
if self.info['biography']:
|
|
self.biography_content.text = self.info['biography']
|
|
else:
|
|
self.biography_content.text = ""
|
|
self.info['biography'] = ""
|
|
self.profile_bio_view.add_widget(self.bio_edit_button)
|
|
|
|
for key in order:
|
|
# per profile attribute it pulls the value adds it to the list
|
|
if not self.info[key]:
|
|
self.info[key] = ""
|
|
profile_info = ProfileInfo(self, key)
|
|
# this section checks if the value is editable by the user viewing the page. If so it adds an edit button
|
|
if self.permissions['edit'] and key in ['name', 'role', 'occupation', 'team']:
|
|
profile_info.make_editable()
|
|
profile_info.set_title(key)
|
|
profile_info.set_content(self.info[key])
|
|
self.profile_info_view.add_widget(profile_info)
|
|
# keeps a list of the objects being used
|
|
self.info_objs.append(profile_info)
|
|
|
|
self.profile_picture = ProfilePicture()
|
|
self.above_info.add_widget(self.profile_picture)
|
|
|
|
if not setting_info("Help boxes").value:
|
|
for i, option in enumerate(self.toolbar.right_action_items):
|
|
if option[0].lower() == "help":
|
|
self.toolbar.right_action_items.pop(i)
|
|
|
|
def open_help(self, app):
|
|
open_help(app, self, "Profile")
|
|
|
|
def refresh_content(self):
|
|
self.load_content()
|
|
|
|
def picture_to_textbox(self, info_type):
|
|
self.currently_editing.icon = "close"
|
|
self.above_info.clear_widgets()
|
|
level = request(sio, session).emit('auth_get')['level']
|
|
if info_type == 'occupation' or info_type == 'team':
|
|
if level == "member":
|
|
self.change = UserOccupationChange(self)
|
|
else:
|
|
self.change = ManagementOccupationChange(self)
|
|
else:
|
|
self.change = InfoChangeBox(self, info_type, self.username)
|
|
self.above_info.add_widget(self.change)
|
|
|
|
def textbox_to_picture(self):
|
|
self.above_info.clear_widgets()
|
|
self.above_info.add_widget(self.profile_picture)
|
|
self.currently_editing.icon = "pencil"
|
|
self.refresh_content()
|
|
|
|
def switch_to_friend(self, app, direction="right"):
|
|
friend_page_screen_name = "FriendPageScreen_" + self.username
|
|
if not self.friend_page_screen:
|
|
self.friend_page_screen = FriendPage(self, self.username, name=friend_page_screen_name)
|
|
app.sm.add_widget(self.friend_page_screen)
|
|
app.set_screen(friend_page_screen_name, direction)
|
|
|
|
def back(self, app, direction="left"):
|
|
app.set_screen(self.previous_page, direction)
|
|
if self.remove_on_exit:
|
|
app.sm.remove_widget(self)
|
|
# Acccount END
|
|
|
|
|
|
# Settings START
|
|
class SettingRoot(MDBoxLayout):
|
|
def __init__(self, title, page, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.title = title
|
|
self.page = page
|
|
self.load_content()
|
|
|
|
def load_content(self):
|
|
self.setting = setting_info(self.title)
|
|
self.set_title(self.setting.title)
|
|
self.set_description(self.setting.description)
|
|
self.setting_icon.icon = self.setting.icon
|
|
|
|
def set_title(self, text):
|
|
if text and type(text) == str:
|
|
self.setting_title.text = text
|
|
|
|
def set_description(self, text):
|
|
if text and type(text) == str:
|
|
self.setting_description.text = text
|
|
|
|
class SettingSwitch(SettingRoot):
|
|
def load_content(self):
|
|
super().load_content()
|
|
self.toggle.active = self.setting.value
|
|
|
|
def on_toggle(self, app):
|
|
self.page.help_tool = ["help", lambda app: self.page.open_help(app)]
|
|
self.setting.change_value(self.toggle.active)
|
|
self.page.load_toolbar()
|
|
app.homepage_screen.load_toolbar()
|
|
|
|
class SettingTextField(SettingRoot):
|
|
def __init__(self, title, **kwargs):
|
|
super().__init__(title, **kwargs)
|
|
self.submission_func = self.submit_url
|
|
|
|
def load_content(self):
|
|
super().load_content()
|
|
self.input_field.text = self.setting.value
|
|
|
|
def submit_func(self):
|
|
self.setting.change_value(self.input_field.text)
|
|
self.submission_func()
|
|
self.page.load_toolbar()
|
|
app.homepage_screen.load_toolbar()
|
|
|
|
def submit_url(self):
|
|
self.error = True
|
|
|
|
try:
|
|
result = urlopen(self.text)
|
|
except HTTPError as e:
|
|
pass
|
|
except URLError as e:
|
|
pass
|
|
except ValueError as e:
|
|
pass
|
|
|
|
else:
|
|
self.error = False
|
|
|
|
class ShutdownButton(MDRaisedButton):
|
|
def __init__(self, page, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.page = page
|
|
|
|
def shutdown(self, app):
|
|
request(sio, session).emit("shutdown", None, None)
|
|
#app.disconnected()
|
|
|
|
class SettingsPage(MDScreen):
|
|
def __init__(self, previous_page, **kwargs):
|
|
super(SettingsPage, self).__init__(**kwargs)
|
|
self.previous_page = previous_page
|
|
|
|
self.load_content()
|
|
|
|
def load_content(self):
|
|
self.settings_stack.clear_widgets()
|
|
settings = db().execute("SELECT title, state FROM settings")
|
|
if settings:
|
|
for setting in settings:
|
|
if setting[1] != None:
|
|
setting_obj = SettingSwitch(setting[0], self)
|
|
else:
|
|
setting_obj = SettingTextField(setting[0], self)
|
|
|
|
self.settings_stack.add_widget(setting_obj)
|
|
|
|
self.level = request(sio, session).emit('auth_get')['level']
|
|
if self.level == "admin":
|
|
button = ShutdownButton(self)
|
|
self.static_buttons.add_widget(button)
|
|
|
|
self.load_toolbar()
|
|
|
|
def load_toolbar(self):
|
|
if not self.toolbar.right_action_items:
|
|
self.toolbar.right_action_items = [self.help_tool]
|
|
if not setting_info("Help boxes").value:
|
|
for i, option in enumerate(self.toolbar.right_action_items):
|
|
if option[0].lower() == "help":
|
|
self.toolbar.right_action_items.pop(i)
|
|
|
|
def open_help(self, app):
|
|
open_help(app, self, "Settings")
|
|
|
|
def logout(self, app):
|
|
clean_directories()
|
|
session.clear()
|
|
app.switch_to_login()
|
|
|
|
def back(self, app):
|
|
app.sm.remove_widget(self)
|
|
self.previous_page.load_content()
|
|
app.set_screen(self.previous_page.name, "right")
|
|
# Settings END
|
|
|
|
|
|
# Notification START
|
|
class NotificationItem(TwoLineAvatarIconListItem):
|
|
def __init__(self, page, notification_id, username, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.notification_id = notification_id
|
|
self.username = username
|
|
self.page = page
|
|
self.content = ""
|
|
|
|
def set_title(self, text):
|
|
if text and type(text) == str:
|
|
self.text = text
|
|
self.title = text
|
|
|
|
def set_content(self, text):
|
|
if text and type(text) == str:
|
|
self.secondary_text = text
|
|
self.content = text
|
|
|
|
def delete(self):
|
|
data = {'notification_id': self.notification_id, 'username': self.username}
|
|
request(sio, session).emit('notification_remove', data, None)
|
|
self.page.notification_stack.remove_widget(self)
|
|
self.page.load_content()
|
|
|
|
def expand(self, app):
|
|
expand_page = ExpandPage([self.title, self.content], app)
|
|
app.sm.add_widget(expand_page)
|
|
|
|
class NotificationsPage(MDScreen):
|
|
def __init__(self, username=None, previous_page=None, **kwargs):
|
|
super(NotificationsPage, self).__init__(**kwargs)
|
|
session.notification_page = self
|
|
self.username = username
|
|
self.previous_page = previous_page
|
|
self.notifications = None
|
|
self.load_content()
|
|
|
|
def load_content(self):
|
|
self.notifications = request(sio, session).emit('notification_get', {'username': self.username})['notifications']
|
|
self.notification_stack.clear_widgets()
|
|
|
|
if self.notifications:
|
|
# fetches list of all non-expired notifications and adds them to the notifications list
|
|
for notification in self.notifications:
|
|
notification_obj = NotificationItem(self, notification['notification_id'], self.username)
|
|
|
|
if dict_key_verify(notification, 'title'):
|
|
notification_obj.set_title(notification['title'])
|
|
if dict_key_verify(notification, 'content'):
|
|
content_text = notification['content']
|
|
notification_obj.set_content(content_text)
|
|
|
|
self.notification_stack.add_widget(notification_obj)
|
|
else:
|
|
item = OneLineAvatarIconListItem(text="No notifications")
|
|
self.notification_stack.add_widget(item)
|
|
|
|
if self.username and self.username != session.username:
|
|
self.toolbar.title = self.username+"'s Notifications"
|
|
|
|
# deals with the help boxes setting
|
|
if not setting_info("Help boxes").value:
|
|
for i, option in enumerate(self.toolbar.right_action_items):
|
|
if option[0].lower() == "help":
|
|
self.toolbar.right_action_items.pop(i)
|
|
|
|
def open_help(self, app):
|
|
open_help(app, self, "Notifications")
|
|
|
|
def add_notification(self, notification):
|
|
notification_item = NotificationItem(self, notification['notification_id'], self.username)
|
|
content_text = notification['title']
|
|
if dict_key_verify(notification, 'content'):
|
|
notification_item.set_content(notification['content'])
|
|
|
|
self.notification_stack.add_widget(notification_item)
|
|
|
|
def back(self, app, direction="left"):
|
|
app.set_screen(self.previous_page.name, direction)
|
|
app.sm.remove_widget(self)
|
|
# Notification END
|
|
|
|
|
|
# Friend START
|
|
class BaseFriendItem(OneLineAvatarIconListItem):
|
|
def __init__(self, obj=None, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.page_obj = obj
|
|
self.friend_profile_screen_name = None
|
|
self.friend_profile_screen = None
|
|
|
|
def refresh_content(self):
|
|
if self.page_obj:
|
|
self.page_obj.load_content()
|
|
|
|
def profile(self, app):
|
|
new_friend_profile_screen_name = self.profile_prefix+"ProfilePage"+self.text
|
|
if new_friend_profile_screen_name != self.friend_profile_screen_name:
|
|
if self.friend_profile_screen_name:
|
|
app.sm.remove_widget(self.friend_profile_screen)
|
|
self.friend_profile_screen_name = new_friend_profile_screen_name
|
|
self.friend_profile_screen = AccountPage(self.text, self.page_obj, name=self.friend_profile_screen_name)
|
|
app.sm.add_widget(self.friend_profile_screen)
|
|
app.set_screen(self.friend_profile_screen_name, "right")
|
|
|
|
class IncomingRequestItem(BaseFriendItem):
|
|
def __init__(self, obj=None, **kwargs):
|
|
super().__init__(obj, **kwargs)
|
|
self.profile_prefix = "IncomingRequest"
|
|
|
|
def accept(self):
|
|
self.verdict('approve')
|
|
|
|
def reject(self):
|
|
self.verdict('reject')
|
|
|
|
def verdict(self, verdict):
|
|
data = {'friend_username': self.text}
|
|
request(sio, session).emit('friend_'+verdict+'_request', data, None)
|
|
self.refresh_content()
|
|
|
|
class OutgoingRequestItem(BaseFriendItem):
|
|
def __init__(self, obj=None, **kwargs):
|
|
super().__init__(obj, **kwargs)
|
|
self.profile_prefix = "OutgoingRequest"
|
|
|
|
def cancel(self):
|
|
data = {'friend_username': self.text}
|
|
request(sio, session).emit('friend_remove_request', data, None)
|
|
self.refresh_content()
|
|
|
|
class RecomendationItem(BaseFriendItem):
|
|
def __init__(self, obj=None, **kwargs):
|
|
super().__init__(obj, **kwargs)
|
|
self.profile_prefix = ""
|
|
|
|
def add_friend(self):
|
|
self.page_obj.add_friend(self.text)
|
|
|
|
class FriendItem(BaseFriendItem):
|
|
def __init__(self, obj=None, **kwargs):
|
|
super().__init__(obj, **kwargs)
|
|
self.profile_prefix = "Friend"
|
|
|
|
def remove(self):
|
|
data = {'friend_username': self.text}
|
|
request(sio, session).emit('friend_remove', data, None)
|
|
self.refresh_content()
|
|
|
|
class FriendPage(MDScreen):
|
|
def __init__(self, account_page, username, **kwargs):
|
|
super(FriendPage, self).__init__(**kwargs)
|
|
self.account_page = account_page
|
|
self.username = username
|
|
self.friend_request_screens = []
|
|
self.load_content()
|
|
|
|
def load_content(self):
|
|
data = {'username': self.username}
|
|
self.friends = request(sio, session).emit("friend_get")['friends']
|
|
self.friend_list.clear_widgets()
|
|
|
|
if self.friends:
|
|
for friend in self.friends:
|
|
friend_info = FriendItem(self, text=friend['username'])
|
|
self.friend_list.add_widget(friend_info)
|
|
else:
|
|
friend_info = OneLineAvatarIconListItem(text="No friends")
|
|
self.friend_list.add_widget(friend_info)
|
|
|
|
if not setting_info("Help boxes").value:
|
|
for i, option in enumerate(self.toolbar.left_action_items):
|
|
if option[0].lower() == "help":
|
|
self.toolbar.left_action_items.pop(i)
|
|
self.account_page.load_content()
|
|
|
|
def open_help(self, app):
|
|
open_help(app, self, "Friends")
|
|
|
|
def switch_to_friend_request(self, app, username=None, direction='right'):
|
|
if not username:
|
|
username = self.username
|
|
friend_request_screen_name = "FriendRequestPageScreen_"+username
|
|
friend_request_screen = FriendRequestPage(self, username, name=friend_request_screen_name)
|
|
app.sm.add_widget(friend_request_screen)
|
|
|
|
app.set_screen(friend_request_screen_name, direction)
|
|
|
|
def switch_to_account(self, app):
|
|
app.set_screen(self.account_page.name, "left")
|
|
|
|
class FriendRequestPage(MDScreen):
|
|
def __init__(self, friend_page, username, **kwargs):
|
|
super(FriendRequestPage, self).__init__(**kwargs)
|
|
self.username = username
|
|
self.friend_page = friend_page
|
|
self.load_content()
|
|
|
|
def _get_request(self, mode="incoming", username=None):
|
|
requests_data = request(sio, session).emit("friend_get_requests", {'username': username, 'mode': mode})
|
|
if dict_key_verify(requests_data, "requests"):
|
|
requests = requests_data['requests']
|
|
else:
|
|
requests = []
|
|
return requests
|
|
|
|
def load_content(self):
|
|
self.incoming_requests.clear_widgets()
|
|
self.outgoing_requests.clear_widgets()
|
|
self.recomendations.clear_widgets()
|
|
|
|
# adds incoming and outgoing requests to their respective lists
|
|
self.incoming = self._get_request("incoming", self.username)
|
|
if not self.incoming:
|
|
self.incoming = []
|
|
self.incoming_requests.add_widget(OneLineAvatarIconListItem(text="No incoming requests"))
|
|
|
|
self.outgoing = self._get_request("outgoing", self.username)
|
|
if not self.outgoing:
|
|
self.outgoing = []
|
|
self.outgoing_requests.add_widget(OneLineAvatarIconListItem(text="No outgoing requests"))
|
|
|
|
for incoming in self.incoming:
|
|
self.incoming_requests.add_widget(IncomingRequestItem(self, text=incoming))
|
|
for outgoing in self.outgoing:
|
|
self.outgoing_requests.add_widget(OutgoingRequestItem(self, text=outgoing))
|
|
|
|
data = {'amount': 5} #This client simply chooses to get 5 recomendations from the server
|
|
# gets friend recomendations and adds them to the recomendations list
|
|
self.friend_recomends = request(sio, session).emit('friend_get_recomendations', data)
|
|
if dict_key_verify(self.friend_recomends, "recomended"):
|
|
self.friend_recomends = self.friend_recomends["recomended"]
|
|
if not self.friend_recomends:
|
|
self.friend_recomends = []
|
|
self.recomendations.add_widget(OneLineAvatarIconListItem(text="No recomendations"))
|
|
|
|
# acctually adds the recomendations to the recomendations list
|
|
for recomend in self.friend_recomends:
|
|
self.recomendations.add_widget(RecomendationItem(self, text=recomend['username']))
|
|
|
|
def add_friend_search(self):
|
|
message = "No username entered"
|
|
if username:
|
|
self.add_friend(self.username_select.text)
|
|
if session.status['level'].lower() != "info":
|
|
self.username_select.error = True
|
|
else:
|
|
self.username_select.text = ""
|
|
else:
|
|
self.username_select.error = True
|
|
|
|
def add_friend(self, username):
|
|
data = {'friend_username': username}
|
|
request(sio, session).emit('friend_add_request', data, None)
|
|
message = f"{session.status['level']}: {session.status['message']}"
|
|
Snackbar(text=message).open()
|
|
self.load_content()
|
|
|
|
def switch_to_friend(self, app, username=None, direction='left'):
|
|
app.set_screen(self.friend_page.name, direction)
|
|
app.sm.remove_widget(self)
|
|
# Friend END
|
|
|
|
|
|
# OCCUPATION START
|
|
class ManageOccupationChange(OccupationChange):
|
|
def submit(self):
|
|
if self.current_selection:
|
|
data = {'occupation_id': occupations[i]['occupation_id'], 'username': self.username_select.text}
|
|
request(sio, session).emit('occupation_set', data)
|
|
message = f"{session.status['level']}: {session.status['message']}"
|
|
Snackbar(text=message).open()
|
|
if session.status['level'].lower() != "info":
|
|
self.username_select.error = True
|
|
else:
|
|
message = "No selection made"
|
|
Snackbar(text=message).open()
|
|
|
|
class BaseOccupationItem(ThreeLineAvatarIconListItem):
|
|
def __init__(self, occupation_id, obj=None, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.occupation_id = occupation_id
|
|
self.page_obj = obj
|
|
data = {'occupation_id': self.occupation_id}
|
|
|
|
class OccupationItem(BaseOccupationItem):
|
|
def edit(self):
|
|
self.page_obj.occupation_edit(self.occupation_id, self.text, self.secondary_text)
|
|
|
|
def delete(self):
|
|
self.page_obj.occupation_delete(self.occupation_id)
|
|
self.page_obj.load_content()
|
|
|
|
class OccupationRequestItem(BaseOccupationItem):
|
|
def refresh_content(self):
|
|
self.page_obj.load_content()
|
|
|
|
def accept(self):
|
|
self.verdict("approve")
|
|
|
|
def reject(self):
|
|
self.verdict("reject")
|
|
|
|
def verdict(self, verdict):
|
|
data = {'username': self.text}
|
|
request(sio, session).emit('occupation_'+verdict+'_request', data, None)
|
|
self.refresh_content()
|
|
|
|
class OccupationEdit(MDBoxLayout):
|
|
def __init__(self, page, occupation_id, name, description, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.name = name
|
|
self.description = description
|
|
self.occupation_id = occupation_id
|
|
self.page = page
|
|
self.load_content()
|
|
|
|
def load_content(self):
|
|
self.ids.name.text = self.name
|
|
self.ids.description.text = self.description
|
|
|
|
def submit(self):
|
|
data = {'name': self.ids.name.text, 'description': self.ids.description.text, 'occupation_id': self.occupation_id}
|
|
request(sio, session).emit('occupation_edit', data, None)
|
|
self.page.load_content()
|
|
self.page.edit_area.clear_widgets()
|
|
self.page.edit_area.add_widget(OccupationCreate(self))
|
|
|
|
class OccupationCreate(MDBoxLayout):
|
|
def __init__(self, page, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.page = page
|
|
|
|
def create(self):
|
|
data = {'name': self.ids.name.text, 'description': self.ids.description.text}
|
|
request(sio, session).emit('occupation_create', data, None)
|
|
message = f"{session.status['level']}: {session.status['message']}"
|
|
Snackbar(text=message).open()
|
|
self.ids.name.text = ""
|
|
self.ids.description.text = ""
|
|
self.page.load_content()
|
|
|
|
class OccupationPage(MDScreen):
|
|
def __init__(self, previous_page, **kwargs):
|
|
super(OccupationPage, self).__init__(**kwargs)
|
|
self.previous_page = previous_page
|
|
self.load_content()
|
|
|
|
def load_content(self):
|
|
occupations = request(sio, session).emit('occupation_get_all')['occupations']
|
|
self.occupations.clear_widgets()
|
|
|
|
if occupations:
|
|
for occupation in occupations:
|
|
item = OccupationItem(occupation['occupation_id'], self, text=occupation['name'], secondary_text=occupation['description'])
|
|
self.occupations.add_widget(item)
|
|
else:
|
|
item = OneLineAvatarIconListItem(text="No occupations")
|
|
self.occupations.add_widget(item)
|
|
|
|
self.edit_area.clear_widgets()
|
|
self.edit_area.add_widget(OccupationCreate(self))
|
|
|
|
if not setting_info("Help boxes").value:
|
|
for i, option in enumerate(self.toolbar.right_action_items):
|
|
if option[0].lower() == "help":
|
|
self.toolbar.right_action_items.pop(i)
|
|
self.previous_page.load_toolbar()
|
|
|
|
def open_help(self, app):
|
|
open_help(app, self, "Occupation")
|
|
|
|
def occupation_edit(self, occupation_id, name, description):
|
|
edit_space = OccupationEdit(self, occupation_id, name, description)
|
|
self.edit_area.clear_widgets()
|
|
self.edit_area.add_widget(edit_space)
|
|
|
|
def occupation_delete(self, occupation_id):
|
|
data = {'occupation_id': occupation_id}
|
|
request(sio, session).emit('occupation_delete_occupation', data, None)
|
|
Snackbar(text="Occupation deleted").open()
|
|
|
|
def switch_to_occupation_request(self, app, direction='left'):
|
|
occupation_request_screen_name = "OccupationRequestPageScreen"
|
|
occupation_request_screen = OccupationRequestPage(self, name=occupation_request_screen_name)
|
|
app.sm.add_widget(occupation_request_screen)
|
|
app.set_screen(occupation_request_screen_name, direction)
|
|
|
|
def back(self, app, direction="right"):
|
|
app.set_screen("HomePageScreen", direction)
|
|
app.sm.remove_widget(self)
|
|
|
|
class OccupationRequestPage(MDScreen):
|
|
def __init__(self, previous_page, **kwargs):
|
|
super(OccupationRequestPage, self).__init__(**kwargs)
|
|
self.previous_page = previous_page
|
|
self.load_content()
|
|
|
|
def load_content(self):
|
|
requests = request(sio, session).emit('occupation_get_all_requests')['requests']
|
|
self.change_requests.clear_widgets()
|
|
|
|
if requests:
|
|
for request_info in requests:
|
|
data = {'occupation_id': request_info['occupation_id']}
|
|
occupation = request(sio, session).emit('occupation_get', data)
|
|
occupation_request = OccupationRequestItem(request_info['occupation_id'], self, text=request_info['username'], secondary_text = occupation['name'], tertiary_text=occupation['description'])
|
|
self.change_requests.add_widget(occupation_request)
|
|
else:
|
|
self.change_requests.add_widget(OneLineAvatarIconListItem(text="No requests"))
|
|
|
|
def back(self, app, direction='right'):
|
|
app.set_screen(self.previous_page.name, direction)
|
|
app.sm.remove_widget(self)
|
|
# OCCUPATION END
|
|
|
|
|
|
# TEAM START
|
|
class LeaderItem(OneLineAvatarIconListItem):
|
|
def __init__(self, leader_username, page=None, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.page = page
|
|
self.leader_username = leader_username
|
|
self.text = leader_username
|
|
|
|
def delete(self):
|
|
data = {'leaders': [{'username': self.leader_username}]}
|
|
request(sio, session).emit('team_delete_leaders', data, None)
|
|
self.page.load_content()
|
|
|
|
class AddLeaderButton(MDRaisedButton):
|
|
def __init__(self, page=None, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.page = page
|
|
|
|
def add_leader(self):
|
|
self.page.button_to_add()
|
|
|
|
class ChangeNameButton(MDRaisedButton):
|
|
def __init__(self, page=None, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.page = page
|
|
|
|
def change_name(self):
|
|
self.page.button_to_add("name")
|
|
|
|
class AddLeader(MDBoxLayout):
|
|
def __init__(self, page=None, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.page = page
|
|
|
|
def submit(self):
|
|
data = {'leaders': [{'username': self.ids.username.text}]}
|
|
request(sio, session).emit('team_set', data, None)
|
|
self.page.add_to_button()
|
|
|
|
class ChangeName(MDBoxLayout):
|
|
def __init__(self, page=None, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.page = page
|
|
|
|
def submit(self):
|
|
team_data = {'name': self.ids.name.text}
|
|
request(sio, session).emit('team_set', team_data, None)
|
|
self.page.add_to_button()
|
|
|
|
class TeamPage(MDScreen):
|
|
def __init__(self, previous_page, username, **kwargs):
|
|
super(TeamPage, self).__init__(**kwargs)
|
|
self.previous_page = previous_page
|
|
self.username = username
|
|
self.load_content()
|
|
|
|
def load_content(self):
|
|
server = request(sio, session)
|
|
leaders = []
|
|
members = []
|
|
|
|
leaders_info = server.emit('team_get_leaders')
|
|
if dict_key_verify(leaders_info, 'leaders'):
|
|
leaders = leaders_info['leaders']
|
|
|
|
members_info = server.emit('team_get_members')
|
|
if dict_key_verify(members_info, 'members'):
|
|
members = members_info['members']
|
|
team = server.emit('team_get')
|
|
|
|
self.members.clear_widgets()
|
|
self.leaders.clear_widgets()
|
|
self.edit_area.clear_widgets()
|
|
|
|
# Simply adds leader widgets containing their username, and makes them clickable
|
|
if leaders:
|
|
for leader in leaders:
|
|
item = LeaderItem(leader['username'], self)
|
|
self.leaders.add_widget(item)
|
|
else:
|
|
item = OneLineAvatarIconListItem(text="No leaders")
|
|
self.leaders.add_widget(item)
|
|
|
|
# checks if the user is privalidged to change team name or add leaders, if so adds said buttons
|
|
self.level = server.emit('auth_get')['level']
|
|
if self.level != "member" or self.username in leaders:
|
|
if members:
|
|
self.edit_area.add_widget(ChangeNameButton(self))
|
|
self.edit_area.add_widget(AddLeaderButton(self))
|
|
|
|
# Adds the member widgets making them clickable and displaying their username
|
|
if members:
|
|
self.team_name.text = team['name']
|
|
for member in members:
|
|
item = OneLineAvatarIconListItem(text=member['username'])
|
|
self.members.add_widget(item)
|
|
|
|
# if no widgets were added to the members list
|
|
if not self.members:
|
|
item = OneLineAvatarIconListItem(text="No members")
|
|
self.members.add_widget(item)
|
|
|
|
else:
|
|
item = OneLineAvatarIconListItem(text="No members")
|
|
self.members.add_widget(item)
|
|
if self.team_name.text == "":
|
|
self.team_name.text = "No team"
|
|
|
|
# deals with loading the help boxes setting
|
|
if not setting_info("Help boxes").value:
|
|
for i, option in enumerate(self.toolbar.right_action_items):
|
|
if option[0].lower() == "help":
|
|
self.toolbar.right_action_items.pop(i)
|
|
self.previous_page.load_toolbar()
|
|
|
|
def button_to_add(self, input_mode="leader"):
|
|
self.edit_area.clear_widgets()
|
|
if input_mode == "leader":
|
|
add_widget = AddLeader(self)
|
|
elif input_mode == "name":
|
|
add_widget = ChangeName(self)
|
|
self.edit_area.add_widget(add_widget)
|
|
|
|
def add_to_button(self):
|
|
self.load_content()
|
|
|
|
def open_help(self, app):
|
|
open_help(app, self, "Team")
|
|
|
|
def back(self, app, direction="right"):
|
|
app.set_screen("HomePageScreen", direction)
|
|
app.sm.remove_widget(self)
|
|
# TEAM END
|
|
|
|
|
|
# Auth START
|
|
class Auth():
|
|
def load_content(self, obj, obj_id):
|
|
for field in obj.fields:
|
|
if "password" in field.lower():
|
|
auth_field = PasswordField(info_type=field)
|
|
else:
|
|
auth_field = AuthField(info_type=field)
|
|
obj_id.add_widget(auth_field)
|
|
obj.auth_field_objs.append(auth_field)
|
|
|
|
class PasswordField(MDRelativeLayout):
|
|
def __init__(self, info_type=None, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.info_type = info_type.lower()
|
|
self.load_content()
|
|
|
|
def load_content(self):
|
|
self.ids.password_field.hint_text = self.info_type.capitalize()
|
|
|
|
class AuthField(MDTextField):
|
|
def __init__(self, info_type=None, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.info_type = info_type.lower()
|
|
self.load_content()
|
|
|
|
def load_content(self):
|
|
self.hint_text = self.info_type.capitalize()
|
|
|
|
def change_hint(self, text):
|
|
self.hint_text = text
|
|
|
|
class AuthButton(MDRaisedButton):
|
|
def __init__(self, function=None, text=None, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.function = function
|
|
self.text = text
|
|
|
|
def action(self, app):
|
|
self.function(app)
|
|
|
|
def change_text(self, text):
|
|
self.text = text
|
|
|
|
class LoginPage(MDScreen):
|
|
def __init__(self, app, **kwargs):
|
|
super(LoginPage, self).__init__(**kwargs)
|
|
self.app = app
|
|
self.fields = ["Username", "Password"]
|
|
self.auth_field_objs = []
|
|
self.register_page = None
|
|
self.logged_in = False
|
|
self.load_content()
|
|
self.login_token()
|
|
|
|
def load_content(self):
|
|
Auth().load_content(self, self.login_view)
|
|
self.login_view.add_widget(AuthButton(self.login, 'Login'))
|
|
self.login_view.add_widget(AuthButton(self.register, 'Register'))
|
|
|
|
def login_token(self):
|
|
results = db().execute("SELECT * FROM tokens")
|
|
data = {'logged_in': False}
|
|
|
|
if results:
|
|
# tries to use every token stored in the databsae to log in
|
|
# stops once found a working token
|
|
for result in results:
|
|
token = result[0]
|
|
expire = float(result[2])
|
|
if timestamp().now > float(expire):
|
|
db().execute("DELETE FROM tokens WHERE token = ?", (token,))
|
|
else:
|
|
info = {'token': token}
|
|
data = request(sio, session).emit("login", info)
|
|
|
|
if data['logged_in']:
|
|
username = request(sio, session).emit("auth_get", {'items': ['username']})['username']
|
|
self.login_confirmation(self.app, data, username)
|
|
break
|
|
|
|
def login(self, app):
|
|
username = self.auth_field_objs[0].text
|
|
password = self.auth_field_objs[1].text
|
|
if not username and not password:
|
|
username = "user"
|
|
password = "pass"
|
|
info = {'username': username, 'password': password}
|
|
data = request(sio, session).emit('login', info)
|
|
self.login_confirmation(app, data, username)
|
|
|
|
def login_confirmation(self, app, data, username):
|
|
message = f"{session.status['level']}: {session.status['message']}"
|
|
if data['logged_in'] == True:
|
|
app.switch_to_homepage("down", username)
|
|
session.username = username
|
|
session.level = request(sio, session).emit('auth_get')['level']
|
|
self.logged_in = True
|
|
else:
|
|
for field in self.auth_field_objs:
|
|
field.error = True
|
|
self.logged_in = False
|
|
Snackbar(text=message).open()
|
|
|
|
def register(self, app):
|
|
if not self.register_page:
|
|
self.register_page = RegisterPage(name='RegisterPageScreen')
|
|
app.sm.add_widget(self.register_page)
|
|
app.set_screen('RegisterPageScreen', 'left')
|
|
|
|
class RegisterPage(MDScreen):
|
|
def __init__(self, **kwargs):
|
|
super(RegisterPage, self).__init__(**kwargs)
|
|
self.fields = ["Username", "Password", "Re-enter Password", "Registration Code"]
|
|
self.auth_field_objs = []
|
|
self.load_content()
|
|
self.mode = "member"
|
|
|
|
def load_content(self):
|
|
Auth().load_content(self, self.register_view)
|
|
self.register_view.add_widget(AuthButton(self.register, 'Register'))
|
|
self.mode_button = AuthButton(self.mode, 'Admin Register')
|
|
self.register_view.add_widget(self.mode_button)
|
|
|
|
def register(self, app):
|
|
info_points = ['username', 'password', 'repassword', 'key']
|
|
info = {point: self.auth_field_objs[i].text for i, point in enumerate(info_points)}
|
|
if self.mode == "member":
|
|
event = "register"
|
|
else:
|
|
event = "admin_register"
|
|
data = request(sio, session).emit(event, info)
|
|
self.register_confirmation(data, app)
|
|
|
|
def register_confirmation(self, data, app):
|
|
message = f"{session.status['level']}: {session.status['message']}"
|
|
if data['is_registered'] == True:
|
|
app.set_screen("LoginPageScreen", "right")
|
|
else:
|
|
Snackbar(text=message).open()
|
|
for field in self.auth_field_objs:
|
|
field.error = True
|
|
Snackbar(text=message).open()
|
|
|
|
def mode(self, app):
|
|
# searches through the available fields and breaks once it finds the the field where the registration/admin code is entered
|
|
# essentially just keeps going until "field" is the correct field obj
|
|
for field in self.auth_field_objs:
|
|
if "code" in field.info_type:
|
|
break
|
|
|
|
# below deals with switching the UI to address if a user is registering to be an admin or a member
|
|
if self.mode == "member":
|
|
self.mode_button.change_text("Member Register")
|
|
field.hint_text = "Admin Registration Code"
|
|
self.mode = "admin"
|
|
else:
|
|
self.mode_button.change_text("Admin Register")
|
|
field.hint_text = "Registration Code"
|
|
self.mode = "member"
|
|
|
|
class ServerPage(MDScreen):
|
|
def __init__(self, **kwargs):
|
|
super(ServerPage, self).__init__(**kwargs)
|
|
|
|
def get_server_code(self):
|
|
response = request(sio, session).emit("server_code_get")
|
|
if dict_key_verify(response, 'server_code'):
|
|
session.server_code = response['server_code']
|
|
else:
|
|
message = "WARNING: Badly behaving server, please contact administrator"
|
|
Snackbar(text=message).open()
|
|
|
|
def connect(self, app):
|
|
connected = start_client(sio, self.url.text)
|
|
if not connected:
|
|
self.url.error = True
|
|
message = "Unsuccessful connection"
|
|
else:
|
|
self.get_server_code()
|
|
app.switch_to_decrypt()
|
|
message = "Successful connection"
|
|
Snackbar(text=message).open()
|
|
|
|
class ShareInput(MDBoxLayout):
|
|
pass
|
|
|
|
class DecryptPage(MDScreen):
|
|
def __init__(self, app, **kwargs):
|
|
super(DecryptPage, self).__init__(**kwargs)
|
|
self.share_inputs = []
|
|
self.min_shares = None
|
|
self.app = app
|
|
self.load_content()
|
|
|
|
def load_content(self):
|
|
mode_info = request(sio, session).emit("get_mode")
|
|
self.sss_enabled = mode_info['sss']
|
|
if self.sss_enabled:
|
|
self.min_shares = int(mode_info['min_shares'])
|
|
for i in range(self.min_shares):
|
|
share_input = ShareInput()
|
|
self.share_inputs.append(share_input)
|
|
self.input_area.add_widget(share_input)
|
|
|
|
def submit(self):
|
|
encrypt_data = {'shares': None, 'password': None}
|
|
data = {'success': False}
|
|
|
|
if self.en_password.text:
|
|
encrypt_data['password'] = self.en_password.text
|
|
data = request(sio, session).emit("decrypt", encrypt_data)
|
|
|
|
elif self.sss_enabled:
|
|
encrypt_data['shares'] = []
|
|
for share in self.share_inputs:
|
|
try:
|
|
share_num = int(share.share_num.text)
|
|
share_secret = int(share.share_secret.text)
|
|
|
|
except:
|
|
# errors out any input fields that contain invalid data
|
|
share.share_num.error = True
|
|
share.share_secret.error = True
|
|
continue
|
|
encrypt_data['shares'].append({'num': share_num, 'secret': share_secret})
|
|
|
|
if len(encrypt_data['shares']) >= self.min_shares:
|
|
data = request(sio, session).emit("decrypt", encrypt_data)
|
|
|
|
if data['success']:
|
|
self.app.sm.remove_widget(self)
|
|
self.app.switch_to_login()
|
|
else:
|
|
self.en_password.error = True
|
|
# loops over share inputs and errors them all
|
|
if encrypt_data['shares']:
|
|
for share in self.share_inputs:
|
|
share.share_num.error = True
|
|
share.share_secret.error = True
|
|
# Auth END
|
|
|
|
class FirstTimePage(MDScreen):
|
|
def __init__(self, **kwargs):
|
|
super(FirstTimePage, self).__init__(**kwargs)
|
|
self.load_content()
|
|
|
|
def load_content(self):
|
|
data = {'items': ['level']}
|
|
level = request(sio, session).emit("auth_get", data)['level']
|
|
if level == "member":
|
|
occupation_change = UserOccupationChange(self)
|
|
occupation_change.ids.new_request_area.remove_widget(occupation_change.ids.new_request_title)
|
|
elif level == "management" or level == "admin":
|
|
occupation_change = ManagementOccupationChange(self)
|
|
self.ids.step3.add_widget(occupation_change)
|
|
|
|
def set_role(self):
|
|
if self.role_input.text:
|
|
request(sio, session).emit("profile_set", {'role': self.role_input.text}, None)
|
|
|
|
def set_name(self):
|
|
if self.name_input.text:
|
|
request(sio, session).emit("profile_set", {'name': self.name_input.text}, None)
|
|
|
|
def textbox_to_picture(self):
|
|
pass
|
|
|
|
def done(self, app):
|
|
self.set_name()
|
|
self.set_role()
|
|
app.set_screen("HomePageScreen", "down")
|
|
app.sm.remove_widget(self)
|
|
|
|
class BeOpen(MDApp):
|
|
def set_screen(self, screen, trans):
|
|
self.sm.current = screen
|
|
self.sm.transition.direction = trans
|
|
|
|
def build(self):
|
|
Builder.load_file('./modules/ui/beopen.kv')
|
|
|
|
self.theme_cls.material_style = "M3"
|
|
self.theme_cls.theme_style = "Light"
|
|
self.theme_cls.primary_palette = "Orange"
|
|
|
|
self.homepage_screen = None
|
|
self.login_screen = None
|
|
|
|
self.sm = MDScreenManager()
|
|
self.sm.add_widget(ServerPage(name='ServerPageScreen'))
|
|
|
|
Window.size = (800, 1000)
|
|
|
|
return self.sm
|
|
|
|
def disconnected(self):
|
|
self.sm.clear_widgets()
|
|
stop_client(sio)
|
|
self.sm.add_widget(ServerPage(name='ServerPageScreen'))
|
|
|
|
def switch_to_comments(self, transition='up'):
|
|
self.comments_screen = CommentsPage(name='CommentsPageScreen')
|
|
self.sm.add_widget(self.comments_screen)
|
|
self.set_screen('CommentsPageScreen', transition)
|
|
|
|
def switch_to_homepage(self, transition=None, username=None):
|
|
if self.homepage_screen:
|
|
self.sm.remove_widget(self.homepage_screen)
|
|
self.homepage_screen = HomePage(username, self, name='HomePageScreen')
|
|
self.sm.add_widget(self.homepage_screen)
|
|
|
|
if self.first_time_login():
|
|
first_time_page_screen_name = "FirstTimePage"
|
|
first_time_page_screen = FirstTimePage(name=first_time_page_screen_name)
|
|
self.sm.add_widget(first_time_page_screen)
|
|
self.set_screen(first_time_page_screen_name, "down")
|
|
else:
|
|
self.sm.switch_to(self.homepage_screen)
|
|
|
|
def switch_to_decrypt(self):
|
|
crypt_data = request(sio, session).emit("get_mode")
|
|
print(f"crytp data: {crypt_data}")
|
|
if crypt_data['mode'] == "decrypt":
|
|
decrypt_screen_name = 'DecryptPageScreen'
|
|
decrypt_screen = DecryptPage(self, name=decrypt_screen_name)
|
|
self.sm.add_widget(decrypt_screen)
|
|
self.set_screen(decrypt_screen_name, "down")
|
|
else:
|
|
self.switch_to_login()
|
|
|
|
def switch_to_login(self, transition="up"):
|
|
login_screen_name = "LoginPageScreen"
|
|
if self.login_screen:
|
|
self.sm.remove_widget(self.login_screen)
|
|
|
|
self.login_screen = LoginPage(self, name=login_screen_name)
|
|
if not self.login_screen.logged_in:
|
|
self.sm.add_widget(self.login_screen)
|
|
self.set_screen(login_screen_name, transition)
|
|
|
|
def comments_to_homepage(self, transition='down'):
|
|
self.set_screen('HomePageScreen', transition)
|
|
self.sm.remove_widget(self.comments_screen)
|
|
|
|
def first_time_login(self):
|
|
occupation = request(sio, session).emit("occupation_get")
|
|
profile = request(sio, session).emit("profile_get", {'items': ['role', 'name']})
|
|
friends = request(sio, session).emit("friend_get")['friends']
|
|
if not occupation['occupation_id'] and not friends and not profile['role'] and not profile['name']:
|
|
return True
|
|
else:
|
|
return False
|
|
first_time_page_screen_name = "FirstTimePage"
|
|
first_time_page_screen = FirstTimePage(name=first_time_page_screen_name)
|
|
self.sm.add_widget(first_time_page_screen)
|
|
self.set_screen(first_time_page_screen_name, "down")
|
|
#================== kivy END ==================
|
|
|
|
def create_settings():
|
|
#programattically creates the settings available in the database
|
|
settings = [{'title': "Help boxes",
|
|
'description': "Turn of the help buttons that appear as clickable question marks",
|
|
'default_value': True,
|
|
'icon': "help"}]
|
|
|
|
settings_db = db()
|
|
saved_settings = settings_db.execute("SELECT title FROM settings")
|
|
|
|
for setting in settings:
|
|
if saved_settings:
|
|
if (setting['title'],) in saved_settings:
|
|
continue
|
|
|
|
# verifies the input data, the inputs come from the "settings" list above
|
|
# this is done for developer ease
|
|
if isinstance(setting['default_value'], bool):
|
|
settings_db.execute("INSERT INTO settings (title, description, state, icon) VALUES (?, ?, ?, ?)", (setting['title'], setting['description'], setting['default_value'], setting['icon']))
|
|
else:
|
|
settings_db.execute("INSERT INTO settings (title, description, value, icon) VALUES (?, ?, ?, ?)", (setting['title'], setting['description'], setting['default_value'], setting['icon']))
|
|
|
|
def create_directories():
|
|
paths = ["data", "data/images"]
|
|
for path in paths:
|
|
path = android_root_path + path
|
|
if not os.path.exists(path):
|
|
os.mkdir(path)
|
|
|
|
def clean_directories():
|
|
paths = ["data/images"]
|
|
for path in paths:
|
|
path = android_root_path + path
|
|
for file in os.listdir(path):
|
|
os.remove(os.path.join(path, file))
|
|
|
|
def setup():
|
|
create_directories()
|
|
clean_directories()
|
|
create_settings()
|
|
|
|
def post_login():
|
|
db().execute("DELETE FROM tokens WHERE username != ?", (session.username,))
|
|
|
|
def main():
|
|
setup()
|
|
BeOpen().run()
|
|
stop_client(sio)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|