Fixed msg composer UI-Fixed import error in buildozer spec file

This commit is contained in:
shekhar-cis 2021-07-12 15:10:17 +05:30
parent 60b4f9a180
commit a82bf19b94
Signed by untrusted user: shekhar-cis
GPG Key ID: 8B2A6C8D5F7F1635
13 changed files with 128 additions and 35 deletions

View File

@ -31,6 +31,7 @@ from addresses import decodeAddress, addBMIfNotPresent
from bitmessagekivy.baseclass.common import ( from bitmessagekivy.baseclass.common import (
toast, showLimitedCnt toast, showLimitedCnt
) )
from kivymd.uix.textfield import MDTextField
class Create(Screen): class Create(Screen):
@ -238,7 +239,7 @@ class DropDownWidget(BoxLayout):
toast(text_item) toast(text_item)
class MyTextInput(TextInput): class MyTextInput(MDTextField):
"""MyTextInput class for kivy Ui""" """MyTextInput class for kivy Ui"""
txt_input = ObjectProperty() txt_input = ObjectProperty()

View File

@ -44,6 +44,7 @@
on_press: app.clear_composer() on_press: app.clear_composer()
<ToggleBtn>: <ToggleBtn>:
size_hint: None, None size_hint: None, None
size: dp(36), dp(48) size: dp(36), dp(48)

View File

@ -9,24 +9,29 @@
BoxLayout: BoxLayout:
orientation: 'vertical' orientation: 'vertical'
size_hint_y: None size_hint_y: None
height: self.minimum_height + 3 * self.parent.height/4 height: self.minimum_height + 3 * self.parent.height/5
padding: dp(20) padding: dp(20)
spacing: 15 spacing: 15
BoxLayout: BoxLayout:
orientation: 'vertical' orientation: 'vertical'
MyMDTextField: MDTextField:
id: ti id: ti
hint_text: 'type or select sender address'
size_hint_y: None size_hint_y: None
height: 100 hint_text: 'Type or Select sender address'
font_size: dp(15) icon_right: 'account'
icon_right_color: app.theme_cls.primary_light
font_size: '15sp'
multiline: False multiline: False
required: True required: True
# height: self.parent.height/2
height: 100
current_hint_text_color: 0,0,0,0.5
helper_text_mode: "on_error" helper_text_mode: "on_error"
canvas.before: canvas.before:
Color: Color:
rgba: (0,0,0,1) rgba: (0,0,0,1)
BoxLayout: BoxLayout:
size_hint_y: None size_hint_y: None
height: dp(40) height: dp(40)
@ -44,7 +49,8 @@
font_size: '13.5sp' font_size: '13.5sp'
ArrowImg: ArrowImg:
BoxLayout:
RelativeLayout:
orientation: 'horizontal' orientation: 'horizontal'
BoxLayout: BoxLayout:
orientation: 'vertical' orientation: 'vertical'
@ -55,13 +61,23 @@
id: txt_input id: txt_input
size_hint_y: None size_hint_y: None
font_size: '15sp' font_size: '15sp'
height: self.parent.height/2 color: color_font
hint_text: app.tr._('type, select or scan QR code for recipients address') required: True
# height: self.parent.height/2
current_hint_text_color: 0,0,0,0.5
height: 100
hint_text: app.tr._('Type or Scan QR code for recipients address')
helper_text_mode: "on_focus"
canvas.before:
Color:
rgba: (0,0,0,1)
RV: RV:
id: rv id: rv
MDIconButton: MDIconButton:
icon: 'qrcode-scan' icon: 'qrcode-scan'
pos_hint: {'center_x': 0, 'center_y': .8} pos_hint: {'center_x': 0.95, 'y': 0.6}
on_release: on_release:
if root.is_camara_attached(): app.root.ids.scr_mngr.current = 'scanscreen' if root.is_camara_attached(): app.root.ids.scr_mngr.current = 'scanscreen'
else: root.camera_alert() else: root.camera_alert()
@ -70,13 +86,17 @@
MyMDTextField: MyMDTextField:
id: subject id: subject
hint_text: 'subject' hint_text: 'Subject'
required: True
height: 100 height: 100
font_size: '15sp' font_size: '15sp'
icon_right: 'text-subject'
icon_right_color: app.theme_cls.primary_light
current_hint_text_color: 0,0,0,0.5
font_color_normal: 0, 0, 0, 1
size_hint_y: None size_hint_y: None
required: True
multiline: False multiline: False
helper_text_mode: "on_error" helper_text_mode: "on_focus"
canvas.before: canvas.before:
Color: Color:
rgba: (0,0,0,1) rgba: (0,0,0,1)
@ -94,12 +114,20 @@
# rgba: (0,0,0,1) # rgba: (0,0,0,1)
ScrollView: ScrollView:
id: scrlv id: scrlv
TextInput: MDTextField:
id: body id: body
# text: 'srggdfsfhgfg' hint_text: 'Body'
hint_text: 'body' mode: "fill"
size_hint: 1, None fill_color: 1/255, 144/255, 254/255, 0.1
multiline: True
font_color_normal: 0, 0, 0, .4
icon_right: 'grease-pencil'
icon_right_color: app.theme_cls.primary_light
size_hint: 1, 1
height: app.window_size[1]/4 height: app.window_size[1]/4
canvas.before:
Color:
rgba: 125/255, 125/255, 125/255, 1
BoxLayout: BoxLayout:
spacing:50 spacing:50

View File

@ -14,11 +14,13 @@
height: dp(200) height: dp(200)
OneLineListItem: OneLineListItem:
text: app.tr._("Total Connections") text: app.tr._("Total Connections")
_no_ripple_effect: True
BoxLayout: BoxLayout:
orientation: 'vertical' orientation: 'vertical'
size_hint_y: None size_hint_y: None
height: dp(58) height: dp(58)
MDRaisedButton: MDRaisedButton:
_no_ripple_effect: True
# size_hint: .6, 0 # size_hint: .6, 0
# height: dp(40) # height: dp(40)
text: app.tr._(root.text_variable_1) text: app.tr._(root.text_variable_1)
@ -41,11 +43,14 @@
height: dp(500) height: dp(500)
OneLineListItem: OneLineListItem:
text: app.tr._("person-to-person") text: app.tr._("person-to-person")
_no_ripple_effect: True
BoxLayout: BoxLayout:
orientation: 'vertical' orientation: 'vertical'
size_hint_y: None size_hint_y: None
height: dp(58) height: dp(58)
MDRaisedButton: MDRaisedButton:
_no_ripple_effect: True
# size_hint: .6, 0 # size_hint: .6, 0
# height: dp(40) # height: dp(40)
text: app.tr._(root.text_variable_2) text: app.tr._(root.text_variable_2)
@ -60,11 +65,14 @@
# halign: 'center' # halign: 'center'
OneLineListItem: OneLineListItem:
text: app.tr._("Brodcast") text: app.tr._("Brodcast")
_no_ripple_effect: True
BoxLayout: BoxLayout:
orientation: 'vertical' orientation: 'vertical'
size_hint_y: None size_hint_y: None
height: dp(58) height: dp(58)
MDRaisedButton: MDRaisedButton:
_no_ripple_effect: True
# size_hint: .6, 0 # size_hint: .6, 0
# height: dp(40) # height: dp(40)
text: app.tr._(root.text_variable_3) text: app.tr._(root.text_variable_3)
@ -79,11 +87,14 @@
# halign: 'center' # halign: 'center'
OneLineListItem: OneLineListItem:
text: app.tr._("publickeys") text: app.tr._("publickeys")
_no_ripple_effect: True
BoxLayout: BoxLayout:
orientation: 'vertical' orientation: 'vertical'
size_hint_y: None size_hint_y: None
height: dp(58) height: dp(58)
MDRaisedButton: MDRaisedButton:
_no_ripple_effect: True
# size_hint: .6, 0 # size_hint: .6, 0
# height: dp(40) # height: dp(40)
text: app.tr._(root.text_variable_4) text: app.tr._(root.text_variable_4)
@ -98,11 +109,14 @@
# halign: 'center' # halign: 'center'
OneLineListItem: OneLineListItem:
text: app.tr._("objects") text: app.tr._("objects")
_no_ripple_effect: True
BoxLayout: BoxLayout:
orientation: 'vertical' orientation: 'vertical'
size_hint_y: None size_hint_y: None
height: dp(58) height: dp(58)
MDRaisedButton: MDRaisedButton:
_no_ripple_effect: True
# size_hint: .6, 0 # size_hint: .6, 0
#height: dp(40) #height: dp(40)
text: app.tr._(root.text_variable_5) text: app.tr._(root.text_variable_5)

View File

@ -95,8 +95,10 @@
<MyaddDetailPopup>: <MyaddDetailPopup>:
id: myadd_popup id: myadd_popup
size_hint_y: None size_hint_y: None
height: "130dp"
spacing:dp(25) spacing:dp(25)
# height: dp(1.2*(myaddr_label.height))
#height: dp(1.5*(myaddr_label.height))
orientation: 'vertical' orientation: 'vertical'
MDLabel: MDLabel:
id: myaddr_label id: myaddr_label

View File

@ -14,7 +14,7 @@ class AddressBook(TeleniumTestProcess):
def test_save_address(self): def test_save_address(self):
"""Save Address On Address Book Screen/Window""" """Save Address On Address Book Screen/Window"""
print("=====================Test -Save Address In Address Book=====================") print("=====================Test -Save Address In Address Book=====================")
self.cli.sleep(6) self.cli.sleep(12)
self.cli.click_on('//MDToolbar/BoxLayout[0]/MDActionTopAppBarButton[0]') self.cli.click_on('//MDToolbar/BoxLayout[0]/MDActionTopAppBarButton[0]')
self.cli.sleep(4) self.cli.sleep(4)
self.cli.drag("//NavigationItem[@text=\"Sent\"]", "//NavigationItem[@text=\"Inbox\"]", 1) self.cli.drag("//NavigationItem[@text=\"Sent\"]", "//NavigationItem[@text=\"Inbox\"]", 1)
@ -84,8 +84,9 @@ class AddressBook(TeleniumTestProcess):
self.cli.sleep(3) self.cli.sleep(3)
self.cli.click_on( self.cli.click_on(
'//DropDownWidget/ScrollView[0]/BoxLayout[0]/BoxLayout[0]/BoxLayout[0]/CustomSpinner[0]/ArrowImg[0]') '//DropDownWidget/ScrollView[0]/BoxLayout[0]/BoxLayout[0]/BoxLayout[0]/CustomSpinner[0]/ArrowImg[0]')
self.cli.sleep(2) self.cli.sleep(5)
self.cli.click_on('//DropDownWidget/ScrollView[0]/BoxLayout[0]/BoxLayout[1]/BoxLayout[0]/MyTextInput[0]') # self.cli.click_on('//DropDownWidget/ScrollView[0]/BoxLayout[0]/BoxLayout[1]/BoxLayout[0]/MyTextInput[0]')
self.cli.click_on('//DropDownWidget/ScrollView[0]/BoxLayout[0]/RelativeLayout[0]/BoxLayout[0]/MyTextInput')
self.cli.sleep(3) self.cli.sleep(3)
self.cli.setattr('//DropDownWidget/ScrollView[0]/BoxLayout[0]/MyMDTextField[0]', 'text', 'Second') self.cli.setattr('//DropDownWidget/ScrollView[0]/BoxLayout[0]/MyMDTextField[0]', 'text', 'Second')
self.cli.sleep(3) self.cli.sleep(3)
@ -93,7 +94,7 @@ class AddressBook(TeleniumTestProcess):
for char in "Hey This is Message From Address Book": for char in "Hey This is Message From Address Book":
random_label += char random_label += char
self.cli.setattr( self.cli.setattr(
'//DropDownWidget/ScrollView[0]/BoxLayout[0]/ScrollView[0]/TextInput[0]', 'text', random_label) '//DropDownWidget/ScrollView[0]/BoxLayout[0]/ScrollView[0]/MDTextField[0]', 'text', random_label)
self.cli.sleep(0.2) self.cli.sleep(0.2)
self.cli.click_on('//MDActionTopAppBarButton[2]') self.cli.click_on('//MDActionTopAppBarButton[2]')
self.cli.sleep(4) self.cli.sleep(4)

View File

@ -9,7 +9,7 @@ class AllMailMessage(TeleniumTestProcess):
def test_show_allmail_list(self): def test_show_allmail_list(self):
"""Show All Messages on Mail Screen/Window""" """Show All Messages on Mail Screen/Window"""
print("=====================Test -Show Messages Of Mail Screen=====================") print("=====================Test -Show Messages Of Mail Screen=====================")
self.cli.sleep(5) self.cli.sleep(10)
self.cli.click_on('//MDToolbar/BoxLayout[0]/MDActionTopAppBarButton[0]') self.cli.click_on('//MDToolbar/BoxLayout[0]/MDActionTopAppBarButton[0]')
self.cli.sleep(4) self.cli.sleep(4)
self.cli.click_on('//NavigationItem[5]') self.cli.click_on('//NavigationItem[5]')

View File

@ -46,9 +46,10 @@ class DraftMessage(TeleniumTestProcess):
self.cli.click_on('//MyTextInput[0]') self.cli.click_on('//MyTextInput[0]')
self.cli.sleep(3) self.cli.sleep(3)
# ADD FROM MESSAGE # ADD FROM MESSAGE
self.cli.setattr('//DropDownWidget/ScrollView[0]/BoxLayout[0]/BoxLayout[1]/BoxLayout[0]/MyTextInput[0]', self.cli.setattr('//DropDownWidget/ScrollView[0]/BoxLayout[0]/RelativeLayout[0]/BoxLayout[0]/MyTextInput',
"text", 'BM-2cSsuH1bUWBski8bvdqnK2DivMqQCeQA1J') "text", 'BM-2cSsuH1bUWBski8bvdqnK2DivMqQCeQA1J')
self.cli.sleep(4) self.cli.sleep(4)
# Add SUBJECT
random_label = "" random_label = ""
for char in "Another Draft message": for char in "Another Draft message":
random_label += char random_label += char
@ -83,7 +84,7 @@ class DraftMessage(TeleniumTestProcess):
random_label = "" random_label = ""
for char in "Hey,This is draft Message Body": for char in "Hey,This is draft Message Body":
random_label += char random_label += char
self.cli.setattr('//DropDownWidget/ScrollView[0]/BoxLayout[0]/ScrollView[0]/TextInput[0]', self.cli.setattr('//DropDownWidget/ScrollView[0]/BoxLayout[0]/ScrollView[0]/MDTextField[0]',
'text', random_label) 'text', random_label)
self.cli.sleep(0.2) self.cli.sleep(0.2)
self.cli.sleep(3) self.cli.sleep(3)

View File

@ -14,7 +14,7 @@ class MyAddressScreen(TeleniumTestProcess):
def test_select_myaddress_list(self): def test_select_myaddress_list(self):
"""Select Address From List of Address""" """Select Address From List of Address"""
print("=====================Test -Select Address From List of Address=====================") print("=====================Test -Select Address From List of Address=====================")
self.cli.sleep(4) self.cli.sleep(12)
self.cli.click_on('//MDToolbar/BoxLayout[0]/MDActionTopAppBarButton[0]') self.cli.click_on('//MDToolbar/BoxLayout[0]/MDActionTopAppBarButton[0]')
self.cli.sleep(3) self.cli.sleep(3)
self.cli.drag("//NavigationItem[@text=\"Sent\"]", "//NavigationItem[@text=\"Inbox\"]", 1) self.cli.drag("//NavigationItem[@text=\"Sent\"]", "//NavigationItem[@text=\"Inbox\"]", 1)
@ -39,6 +39,7 @@ class MyAddressScreen(TeleniumTestProcess):
self.cli.sleep(3) self.cli.sleep(3)
self.assertExists("//MyAddress[@name~=\"myaddress\"]", timeout=2) self.assertExists("//MyAddress[@name~=\"myaddress\"]", timeout=2)
@ordered @ordered
def test_send_message_from(self): def test_send_message_from(self):
"""Send Message From Send Message From Button""" """Send Message From Send Message From Button"""
@ -52,7 +53,7 @@ class MyAddressScreen(TeleniumTestProcess):
self.assertExists("//Create[@name~=\"create\"]", timeout=2) self.assertExists("//Create[@name~=\"create\"]", timeout=2)
self.cli.sleep(3) self.cli.sleep(3)
self.cli.setattr( self.cli.setattr(
'//DropDownWidget/ScrollView[0]/BoxLayout[0]/BoxLayout[1]/BoxLayout[0]/MyTextInput', "text", data[1]) '//DropDownWidget/ScrollView[0]/BoxLayout[0]/RelativeLayout[0]/BoxLayout[0]/MyTextInput', "text", data[1])
self.cli.sleep(3) self.cli.sleep(3)
self.cli.setattr('//DropDownWidget/ScrollView[0]/BoxLayout[0]/MyMDTextField[0]', 'text', 'Hey') self.cli.setattr('//DropDownWidget/ScrollView[0]/BoxLayout[0]/MyMDTextField[0]', 'text', 'Hey')
self.cli.sleep(3) self.cli.sleep(3)
@ -60,10 +61,38 @@ class MyAddressScreen(TeleniumTestProcess):
for char in "Hey,i am sending message directly from MyAddress book": for char in "Hey,i am sending message directly from MyAddress book":
random_label += char random_label += char
self.cli.setattr( self.cli.setattr(
'//DropDownWidget/ScrollView[0]/BoxLayout[0]/ScrollView[0]/TextInput[0]', 'text', random_label) '//DropDownWidget/ScrollView[0]/BoxLayout[0]/ScrollView[0]/MDTextField[0]', 'text', random_label)
self.cli.sleep(0.2) self.cli.sleep(0.2)
self.cli.sleep(2) self.cli.sleep(2)
self.cli.click_on('//MDActionTopAppBarButton[2]') self.cli.click_on('//MDActionTopAppBarButton[2]')
self.cli.sleep(4) self.cli.sleep(4)
self.assertExists("//Inbox[@name~=\"inbox\"]", timeout=2) self.assertExists("//Inbox[@name~=\"inbox\"]", timeout=2)
@ordered
def test_disable_address(self):
"""Disable Addresses"""
self.cli.sleep(5)
self.cli.click_on('//MDToolbar/BoxLayout[0]/MDActionTopAppBarButton[0]')
self.cli.sleep(3)
self.cli.drag("//NavigationItem[@text=\"Sent\"]", "//NavigationItem[@text=\"Inbox\"]", 1)
self.cli.sleep(3)
self.cli.click_on('//NavigationItem[11]')
self.cli.sleep(3)
# ADDRESS DISABLED
self.cli.click_on('//Thumb')
self.cli.sleep(3)
# CLICK ON DISABLE ACCOUNT TO OPEN POPUP
self.cli.click_on('//MyAddress/BoxLayout[0]/FloatLayout[0]/MDScrollViewRefreshLayout[0]/MDList[0]/CustomTwoLineAvatarIconListItem[0]')
self.cli.sleep(3)
self.cli.click_on('//MDFlatButton[@text=\"ok\"]')
self.cli.sleep(3)
self.cli.click_on('//MDToolbar/BoxLayout[0]/MDActionTopAppBarButton[0]')
self.cli.sleep(3)
# ADDRESS ENABLED
self.cli.click_on('//Thumb')
self.cli.sleep(3)
self.assertExists("//MyAddress[@name~=\"myaddress\"]", timeout=5)

View File

@ -6,8 +6,8 @@ class NetwrokStatusScreen(TeleniumTestProcess):
def test_network_status(self): def test_network_status(self):
"""Show NetwrokStatus""" """Show NetwrokStatus"""
print("=====================Test -Show NetwrokStatus=====================") print("=====================Test -Show Network Status=====================")
self.cli.sleep(4) self.cli.sleep(10)
self.cli.click_on('//MDToolbar/BoxLayout[0]/MDActionTopAppBarButton[0]') self.cli.click_on('//MDToolbar/BoxLayout[0]/MDActionTopAppBarButton[0]')
self.cli.sleep(3) self.cli.sleep(3)
self.cli.drag("//NavigationItem[@text=\"Sent\"]", "//NavigationItem[@text=\"Inbox\"]", 1) self.cli.drag("//NavigationItem[@text=\"Sent\"]", "//NavigationItem[@text=\"Inbox\"]", 1)

View File

@ -27,7 +27,7 @@ class SendMessage(TeleniumTestProcess):
self.cli.click_on('//Inbox/ComposerButton[0]/MDFloatingActionButton[0]') self.cli.click_on('//Inbox/ComposerButton[0]/MDFloatingActionButton[0]')
self.assertExists("//Create[@name~=\"create\"]", timeout=2) self.assertExists("//Create[@name~=\"create\"]", timeout=2)
self.cli.sleep(3) self.cli.sleep(3)
self.cli.click_on('//DropDownWidget/ScrollView[0]/BoxLayout[0]/BoxLayout[0]/MyMDTextField[0]') self.cli.click_on('//DropDownWidget/ScrollView[0]/BoxLayout[0]/BoxLayout[0]/MDTextField')
self.cli.sleep(3) self.cli.sleep(3)
self.cli.click_on('//DropDownWidget/ScrollView[0]/BoxLayout[0]/BoxLayout[1]/MyTextInput[0]') self.cli.click_on('//DropDownWidget/ScrollView[0]/BoxLayout[0]/BoxLayout[1]/MyTextInput[0]')
self.cli.sleep(3) self.cli.sleep(3)
@ -49,15 +49,17 @@ class SendMessage(TeleniumTestProcess):
self.cli.sleep(3) self.cli.sleep(3)
self.cli.click_on('//DropDownWidget/ScrollView[0]/BoxLayout[0]/MyMDTextField[0]') self.cli.click_on('//DropDownWidget/ScrollView[0]/BoxLayout[0]/MyMDTextField[0]')
self.cli.sleep(2) self.cli.sleep(2)
# ADD SUBJECT
self.cli.setattr('//DropDownWidget/ScrollView[0]/BoxLayout[0]/MyMDTextField[0]', 'text', 'heyyyyyy') self.cli.setattr('//DropDownWidget/ScrollView[0]/BoxLayout[0]/MyMDTextField[0]', 'text', 'heyyyyyy')
self.cli.sleep(3) self.cli.sleep(3)
self.cli.click_on('//DropDownWidget/ScrollView[0]/BoxLayout[0]/ScrollView[0]/TextInput[0]') self.cli.click_on('//DropDownWidget/ScrollView[0]/BoxLayout[0]/ScrollView[0]/MDTextField[0]')
self.cli.sleep(4) self.cli.sleep(4)
# ADD BODY
random_label = "" random_label = ""
for char in "how are you this is message body": for char in "how are you this is message body":
random_label += char random_label += char
self.cli.setattr( self.cli.setattr(
'//DropDownWidget/ScrollView[0]/BoxLayout[0]/ScrollView[0]/TextInput[0]', 'text', random_label) '//DropDownWidget/ScrollView[0]/BoxLayout[0]/ScrollView[0]/MDTextField[0]', 'text', random_label)
self.cli.sleep(0.2) self.cli.sleep(0.2)
self.cli.sleep(3) self.cli.sleep(3)
self.cli.click_on('//MDActionTopAppBarButton[2]') self.cli.click_on('//MDActionTopAppBarButton[2]')
@ -65,7 +67,7 @@ class SendMessage(TeleniumTestProcess):
self.cli.click_on('//MDFlatButton[0]') self.cli.click_on('//MDFlatButton[0]')
self.cli.sleep(6) self.cli.sleep(6)
self.cli.setattr( self.cli.setattr(
'//DropDownWidget/ScrollView[0]/BoxLayout[0]/BoxLayout[1]/BoxLayout[0]/MyTextInput[0]', "text", data[0]) '//DropDownWidget/ScrollView[0]/BoxLayout[0]/RelativeLayout[0]/BoxLayout[0]/MyTextInput[0]', "text", data[0])
self.cli.sleep(3) self.cli.sleep(3)
self.cli.click_on('//MDActionTopAppBarButton[2]') self.cli.click_on('//MDActionTopAppBarButton[2]')
self.cli.sleep(3) self.cli.sleep(3)

View File

@ -1,7 +1,19 @@
from datetime import datetime
from os import wait
from socket import timeout
from time import sleep
from telenium.mods.telenium_client import selectFirst, kivythread, TeleniumMotionEvent, nextid, telenium_input, run_telenium
from .telenium_process import TeleniumTestProcess from .telenium_process import TeleniumTestProcess
class TrashMessage(TeleniumTestProcess): class TrashMessage(TeleniumTestProcess):
def smart_click(self, click_on, sleep):
click_on = self.cli.click_on(click_on)
sleep = self.cli.sleep(sleep)
"""Trash Screen Functionality Testing""" """Trash Screen Functionality Testing"""
def test_delete_trash_message(self): def test_delete_trash_message(self):

View File

@ -49,7 +49,9 @@ requirements =
pyzbar, pyzbar,
bitmsghash, bitmsghash,
git+https://github.com/kivymd/KivyMD#egg=kivymd, git+https://github.com/kivymd/KivyMD#egg=kivymd,
kivy_garden.qrcode,
qrcode, qrcode,
kivy_garden,
msgpack msgpack
# (str) Custom source folders for requirements # (str) Custom source folders for requirements