profiles dropdown

This commit is contained in:
Emendir
2025-03-14 07:44:32 +01:00
parent 731fd5d2de
commit 08bb63c783
11 changed files with 235 additions and 23 deletions

20
install_prereqs.sh Normal file
View 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

View 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()

View File

@@ -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

View File

@@ -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
View 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
View 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

View File

@@ -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'

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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()