mirror of
https://github.com/emendir/EndraApp.git
synced 2026-05-19 06:08:10 -04:00
profiles dropdown
This commit is contained in:
20
install_prereqs.sh
Normal file
20
install_prereqs.sh
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
## Install kivy with more advanced font handling
|
||||
## See https://kivy.org/doc/stable/gettingstarted/installation.html#from-source
|
||||
|
||||
# the absolute path of this script's directory
|
||||
SCRIPT_DIR="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
|
||||
cd $SCRIPT_DIR
|
||||
|
||||
set -e # Exit if any command fails
|
||||
|
||||
sudo apt install libfreetype6-dev libpango1.0-dev libpangoft2-1.0-0
|
||||
|
||||
cd "$(mktemp -d)"
|
||||
curl https://raw.githubusercontent.com/kivy/kivy/master/tools/build_linux_dependencies.sh -o build_kivy_deps.sh
|
||||
chmod +x build_kivy_deps.sh
|
||||
./build_kivy_deps.sh
|
||||
KIVY_DEPS_ROOT=$(pwd)/kivy-dependencies
|
||||
export KIVY_DEPS_ROOT
|
||||
python -m pip install "kivy[full]" kivy_examples --no-binary kivy
|
||||
40
src/endra_app/_load_kivy.py
Normal file
40
src/endra_app/_load_kivy.py
Normal file
@@ -0,0 +1,40 @@
|
||||
"""This script tries to load kivy with more advanced font handling if possible.
|
||||
"""
|
||||
import os
|
||||
USING_PANGO = False
|
||||
try:
|
||||
os.environ['KIVY_TEXT'] = 'pango'
|
||||
import kivy
|
||||
from kivy.core.text import FontContextManager as FCM
|
||||
FCM.create('system://myapp')
|
||||
# family = FCM.add_font('system://myapp', 'LibertinusSerif-Regular.otf')
|
||||
# family = FCM.add_font('system://myapp', 'FreeSerif.ttf')
|
||||
# family = FCM.add_font('system://myapp', 'NotoColorEmoji.ttf')
|
||||
USING_PANGO = True
|
||||
print("Successfully loaded font context!")
|
||||
except:
|
||||
os.environ.pop('KIVY_TEXT') # = ORG_KIVY_TEXT
|
||||
print("Failed to load font context, pity. Reloading kivy.")
|
||||
import importlib
|
||||
importlib.reload(kivy)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from kivy.app import App
|
||||
from kivy.uix.label import Label
|
||||
|
||||
class MyApp(App):
|
||||
def build(self):
|
||||
return Label(
|
||||
text='''Hello there!
|
||||
⏷▼⮟⯆🞃🚀😊
|
||||
Русский
|
||||
Tiếng Việt
|
||||
العربية
|
||||
中文
|
||||
日本語
|
||||
বাংলা
|
||||
''',
|
||||
font_context='system://myapp',
|
||||
)
|
||||
MyApp().run()
|
||||
@@ -17,6 +17,7 @@
|
||||
font_size: 16
|
||||
color: 0.9, 0.9, 0.9, 1
|
||||
size_hint: 0.6, 1
|
||||
font_context: 'system://myapp'
|
||||
<MessageEditorView>
|
||||
orientation: 'vertical'
|
||||
TextInput:
|
||||
@@ -24,6 +25,7 @@
|
||||
background_color: 0.1, 0.1, 0.1, 1 # Dark background
|
||||
foreground_color: 0.9, 0.9, 0.9, 1 # Light text color
|
||||
hint_text: 'message text' # Placeholder text
|
||||
font_context: 'system://myapp'
|
||||
<MessagePageView>
|
||||
orientation: 'vertical'
|
||||
size_hint_x: 0.7
|
||||
@@ -39,7 +41,7 @@
|
||||
BoxLayout:
|
||||
id: top_bar_lyt
|
||||
orientation: 'horizontal'
|
||||
size_hint_y: 0.15
|
||||
size_hint_y: None
|
||||
|
||||
Button:
|
||||
id: invite_btn
|
||||
@@ -61,7 +63,7 @@
|
||||
BoxLayout:
|
||||
id: add_message_lyt
|
||||
orientation: 'horizontal'
|
||||
size_hint_y: 0.15
|
||||
size_hint_y: None
|
||||
BoxLayout:
|
||||
id: add_message_btn_lyt
|
||||
size_hint_x: 3
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# main.py
|
||||
from . import _load_kivy # IMPORTANT: import this before importing kivy
|
||||
from kivy.app import App
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from .side_bar import SideBar
|
||||
@@ -56,7 +56,8 @@ class MainApp(App):
|
||||
)
|
||||
profiles.update({profile.did: profile})
|
||||
return profiles
|
||||
|
||||
def get_profile_ids(self)->set[str]:
|
||||
return set(self.profiles.keys())
|
||||
def create_profile(self) -> Profile:
|
||||
tempdir = tempfile.mkdtemp()
|
||||
tempdir
|
||||
@@ -79,4 +80,5 @@ def main():
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(f"USING_PANGO: {_load_kivy.USING_PANGO}")
|
||||
main()
|
||||
|
||||
50
src/endra_app/profiles.kv
Normal file
50
src/endra_app/profiles.kv
Normal file
@@ -0,0 +1,50 @@
|
||||
<ProfilesView@DropDown>:
|
||||
|
||||
BoxLayout:
|
||||
|
||||
orientation: 'vertical'
|
||||
size_hint: 1, None # Important! Tell DropDown the height is explicit
|
||||
height: self.minimum_height # So it fits content dynamically
|
||||
padding: 10
|
||||
canvas.before:
|
||||
Color:
|
||||
rgba: 0.15, 0.15, 0.15, 1 # background colour
|
||||
Rectangle:
|
||||
size: self.size
|
||||
pos: self.pos
|
||||
ScrollView:
|
||||
id: scroll_view
|
||||
size_hint_y: None
|
||||
|
||||
GridLayout:
|
||||
id: scroll_layout
|
||||
cols: 1
|
||||
spacing: 1
|
||||
size_hint_y: None
|
||||
|
||||
Button:
|
||||
id: add_profile_btn
|
||||
text: "Add Profile"
|
||||
size_hint_y: None
|
||||
height: 50
|
||||
background_color: 0.8, 0.3, 0.3, 1 # Light red button
|
||||
|
||||
<ProfileItemView>:
|
||||
orientation: 'horizontal'
|
||||
size_hint_y: 1
|
||||
height: 50
|
||||
spacing: 5
|
||||
padding: 5
|
||||
canvas.before:
|
||||
Color:
|
||||
rgba: 0.1, 0.1, 0.1, 1 # background colour
|
||||
Rectangle:
|
||||
size: self.size
|
||||
pos: self.pos
|
||||
|
||||
Label:
|
||||
id: label
|
||||
font_size: 16
|
||||
color: 0.9, 0.9, 0.9, 1
|
||||
size_hint: 0.6, 1
|
||||
font_context: 'system://myapp'
|
||||
72
src/endra_app/profiles.py
Normal file
72
src/endra_app/profiles.py
Normal file
@@ -0,0 +1,72 @@
|
||||
# side_bar.py
|
||||
from endra import Profile
|
||||
from .utils import InvitationPopupView
|
||||
import json
|
||||
from loguru import logger
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from kivy.lang import Builder
|
||||
import os
|
||||
from kivy.uix.dropdown import DropDown
|
||||
# Load the KV file
|
||||
KV_FILE = os.path.join(os.path.dirname(__file__), "profiles.kv")
|
||||
Builder.load_file(KV_FILE)
|
||||
|
||||
|
||||
class ProfilesView(DropDown):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
# self.layout = self.ids.layout
|
||||
self.scroll_view = self.ids.scroll_view
|
||||
self.scroll_layout = self.ids.scroll_layout
|
||||
self.add_profile_btn = self.ids.add_profile_btn
|
||||
|
||||
def remove_widget_from_scroll(self, index):
|
||||
if 0 <= index < len(self.scroll_layout.children):
|
||||
self.scroll_layout.remove_widget(
|
||||
self.scroll_layout.children[index])
|
||||
|
||||
def remove_scroll_widgets(self):
|
||||
while (len(self.scroll_layout.children)):
|
||||
self.scroll_layout.remove_widget(self.scroll_layout.children[0])
|
||||
|
||||
|
||||
class Profiles(ProfilesView):
|
||||
def __init__(self, main, profile: Profile, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.main = main
|
||||
self.profile = profile
|
||||
|
||||
self.add_profile_btn.bind(on_press=self.offer_add_profile)
|
||||
self.reload_profiles()
|
||||
print("Loading Dropdown!")
|
||||
|
||||
def offer_add_profile(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def reload_profiles(self):
|
||||
logger.info("Reloading profiles...")
|
||||
|
||||
for profile in self.main.profiles.values():
|
||||
print("PROFILE", profile.did)
|
||||
self.add_profile_wdg(profile)
|
||||
|
||||
def add_profile_wdg(self, profile: Profile):
|
||||
widget = ProfileItem(
|
||||
main=self.main, profile=profile
|
||||
)
|
||||
self.scroll_layout.add_widget(widget)
|
||||
|
||||
|
||||
class ProfileItemView(BoxLayout):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.label = self.ids.label
|
||||
|
||||
|
||||
class ProfileItem(ProfileItemView):
|
||||
def __init__(self, main, profile: Profile, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.main = main
|
||||
self.profile = profile
|
||||
self.label.text = profile.did
|
||||
@@ -8,7 +8,8 @@
|
||||
orientation: 'vertical'
|
||||
Label:
|
||||
text: "Devices"
|
||||
size_hint_y: 0.1
|
||||
size_hint_y: None
|
||||
font_context: 'system://myapp'
|
||||
ScrollView:
|
||||
id: scroll_view
|
||||
size_hint: 1, 1
|
||||
@@ -25,7 +26,7 @@
|
||||
size_hint: 1, None
|
||||
height: 50
|
||||
background_color: 0.8, 0.3, 0.3, 1 # Light red button
|
||||
<DeviceHeaderView>:
|
||||
<DeviceItemView>:
|
||||
orientation: 'horizontal'
|
||||
size_hint_y: None
|
||||
height: 50
|
||||
@@ -43,3 +44,4 @@
|
||||
font_size: 16
|
||||
color: 0.9, 0.9, 0.9, 1
|
||||
size_hint: 0.6, 1
|
||||
font_context: 'system://myapp'
|
||||
|
||||
@@ -63,19 +63,19 @@ class ProfileSettingsPopup(ProfileSettingsPopupView):
|
||||
def add_device_wdg(self, device: Device):
|
||||
print("DEVICE", type(device.id))
|
||||
print(device.id)
|
||||
widget = DeviceHeader(
|
||||
widget = DeviceItem(
|
||||
main=self.main, device=device
|
||||
)
|
||||
self.scroll_layout.add_widget(widget)
|
||||
|
||||
|
||||
class DeviceHeaderView(BoxLayout):
|
||||
class DeviceItemView(BoxLayout):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.label = self.ids.label
|
||||
|
||||
|
||||
class DeviceHeader(DeviceHeaderView):
|
||||
class DeviceItem(DeviceItemView):
|
||||
def __init__(self, main, device: Device, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.main = main
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#:import QRCodeWidget kivy_garden.qrcode
|
||||
<CorrespondenceHeaderView>:
|
||||
<CorrespondenceItemView>:
|
||||
orientation: 'horizontal'
|
||||
size_hint_y: None
|
||||
height: 50
|
||||
@@ -11,12 +11,13 @@
|
||||
Rectangle:
|
||||
size: self.size
|
||||
pos: self.pos
|
||||
|
||||
Label:
|
||||
id: label
|
||||
font_size: 16
|
||||
color: 0.9, 0.9, 0.9, 1
|
||||
size_hint: 0.6, 1
|
||||
font_context: 'system://myapp'
|
||||
|
||||
<SideBarView>
|
||||
orientation: 'vertical'
|
||||
size_hint_x: 0.3
|
||||
@@ -29,12 +30,30 @@
|
||||
Rectangle:
|
||||
size: self.size
|
||||
pos: self.pos
|
||||
Button:
|
||||
id: my_profile_btn
|
||||
text: "My Profile"
|
||||
BoxLayout:
|
||||
orientation: "horizontal"
|
||||
size_hint: 1, None
|
||||
height: 50
|
||||
background_color: 0.8, 0.3, 0.3, 1 # Light red button
|
||||
id: profile_controls_lyt
|
||||
Button:
|
||||
id: my_profile_btn
|
||||
text: "My Profile"
|
||||
size_hint: 0.9, None
|
||||
height: 50
|
||||
background_color: 0.8, 0.3, 0.3, 1 # Light red button
|
||||
Button:
|
||||
id: open_profiles_btn
|
||||
# font_name: "LibertinusSerif-Regular.otf"
|
||||
# font_name: "NotoColorEmoji.ttf"
|
||||
# font_name: "NotoSans-Regular.ttf"
|
||||
# font_name: "DejaVuSans.ttf"
|
||||
font_name: "FreeSerif.ttf"
|
||||
|
||||
|
||||
text: "▼"
|
||||
size_hint: None, None
|
||||
height: 50
|
||||
background_color: 0.8, 0.3, 0.3, 1 # Light red button
|
||||
|
||||
ScrollView:
|
||||
id: scroll_view
|
||||
size_hint: 1, 1
|
||||
|
||||
@@ -49,13 +49,13 @@ class AddCorrespondencePopupView(Popup):
|
||||
self.dismiss()
|
||||
|
||||
|
||||
class CorrespondenceHeaderView(BoxLayout):
|
||||
class CorrespondenceItemView(BoxLayout):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.label = self.ids.label
|
||||
|
||||
|
||||
class CorrespondenceHeader(CorrespondenceHeaderView):
|
||||
class CorrespondenceItem(CorrespondenceItemView):
|
||||
def __init__(self, main, correspondence: Correspondence, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.main = main
|
||||
@@ -69,15 +69,16 @@ class CorrespondenceHeader(CorrespondenceHeaderView):
|
||||
print(f"Label '{self.label.text}' clicked!")
|
||||
self.main.chat_page.load_correspondence(self.correspondence)
|
||||
|
||||
|
||||
from .profiles import Profiles
|
||||
class SideBarView(BoxLayout):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.scroll_view = self.ids.scroll_view
|
||||
|
||||
self.profile_controls_lyt = self.ids.profile_controls_lyt
|
||||
self.scroll_layout = self.ids.scroll_layout
|
||||
self.my_profile_btn = self.ids.my_profile_btn
|
||||
self.open_profiles_btn = self.ids.open_profiles_btn
|
||||
self.add_corresp_btn = self.ids.add_corresp_btn
|
||||
|
||||
self.scroll_layout.bind(
|
||||
@@ -103,6 +104,7 @@ class SideBar(SideBarView):
|
||||
|
||||
self.add_corresp_btn.bind(on_press=self.offer_add_correspondence)
|
||||
self.my_profile_btn.bind(on_press=self.open_profile_settings)
|
||||
self.open_profiles_btn.bind(on_press=self.open_profiles)
|
||||
self.reload_correspondences()
|
||||
|
||||
def reload_correspondences(self):
|
||||
@@ -128,9 +130,12 @@ class SideBar(SideBarView):
|
||||
profile=self.profile,
|
||||
)
|
||||
popup.open()
|
||||
def open_profiles(self, *args, **kwargs):
|
||||
dropdown = Profiles(self.main, self.profile)
|
||||
dropdown.open(self.profile_controls_lyt)
|
||||
|
||||
def add_correspondence_header(self, correspondence):
|
||||
widget = CorrespondenceHeader(
|
||||
widget = CorrespondenceItem(
|
||||
main=self.main, correspondence=correspondence
|
||||
)
|
||||
self.scroll_layout.add_widget(widget)
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
text: "Invitation code copied to clipboard!\n(Click to copy again)"
|
||||
text_size: self.size # Enable text wrapping
|
||||
size_hint_y: 1
|
||||
font_context: 'system://myapp'
|
||||
|
||||
<InvitationPopupView@Popup>:
|
||||
title:'Invitation'
|
||||
size_hint: None, None
|
||||
size_hint: 0.9,0.9
|
||||
auto_dismiss: True
|
||||
BoxLayout:
|
||||
@@ -22,6 +22,6 @@
|
||||
# InvitationView:
|
||||
# id:invitation_view
|
||||
Button:
|
||||
size_hint_y:0.1
|
||||
size_hint_y:None
|
||||
text: 'Close'
|
||||
on_release: root.dismiss()
|
||||
|
||||
Reference in New Issue
Block a user