diff --git a/src/bitmessagekivy/kv/chat_list.kv b/src/bitmessagekivy/kv/chat_list.kv new file mode 100644 index 00000000..2a480abf --- /dev/null +++ b/src/bitmessagekivy/kv/chat_list.kv @@ -0,0 +1,58 @@ +: + name: 'chlist' + canvas.before: + Color: + rgba: 1,1,1,1 + Rectangle: + pos: self.pos + size: self.size + MDTabs: + id: chat_panel + tab_display_mode:'text' + + Tab: + text: "Chats" + BoxLayout: + id: chat_box + orientation: 'vertical' + ScrollView: + id: scroll_y + do_scroll_x: False + MDList: + id: ml + MDLabel: + font_style: 'Caption' + theme_text_color: 'Primary' + text: 'No Chat' + halign: 'center' + size_hint_y: None + bold: True + valign: 'top' + # OneLineAvatarListItem: + # text: "Single-line item with avatar" + # divider: None + # _no_ripple_effect: True + # ImageLeftWidget: + # source: './images/text_images/A.png' + # OneLineAvatarListItem: + # text: "Single-line item with avatar" + # divider: None + # _no_ripple_effect: True + # ImageLeftWidget: + # source: './images/text_images/B.png' + # OneLineAvatarListItem: + # text: "Single-line item with avatar" + # divider: None + # _no_ripple_effect: True + # ImageLeftWidget: + # source: './images/text_images/A.png' + Tab: + text: "Contacts" + BoxLayout: + id: contact_box + orientation: 'vertical' + ScrollView: + id: scroll_y + do_scroll_x: False + MDList: + id: ml diff --git a/src/bitmessagekivy/kv/chat_room.kv b/src/bitmessagekivy/kv/chat_room.kv new file mode 100644 index 00000000..25edfd69 --- /dev/null +++ b/src/bitmessagekivy/kv/chat_room.kv @@ -0,0 +1,45 @@ +#:import C kivy.utils.get_color_from_hex + +: + name: 'chroom' + BoxLayout: + orientation: 'vertical' + canvas.before: + Color: + rgba: 1,1,1,1 + Rectangle: + pos: self.pos + size: self.size + ScrollView: + Label: + id: chat_logs + text: '' + color: C('#101010') + text_size: (self.width, None) + halign: 'left' + valign: 'top' + padding: (0, 0) # fixed in Kivy 1.8.1 + size_hint: (1, None) + height: self.texture_size[1] + markup: True + font_size: sp(20) + BoxLayout: + height: 50 + orientation: 'horizontal' + padding: 0 + size_hint: (1, None) + + TextInput: + id: message + size_hint: (1, 1) + multiline: False + font_size: sp(20) + on_text_validate: root.send_msg() + + MDRaisedButton: + text: "Send" + elevation_normal: 2 + opposite_colors: True + size_hint: (0.3, 1) + pos_hint: {"center_x": .5} + on_press: root.send_msg() diff --git a/src/bitmessagekivy/kv/composer.kv b/src/bitmessagekivy/kv/composer.kv index b68e281d..180412ab 100644 --- a/src/bitmessagekivy/kv/composer.kv +++ b/src/bitmessagekivy/kv/composer.kv @@ -1,10 +1,11 @@ : ScrollView: + id: id_scroll BoxLayout: orientation: 'vertical' size_hint_y: None height: self.minimum_height + 2 * self.parent.height/4 - padding: dp(32) + padding: dp(20) spacing: 15 BoxLayout: orientation: 'vertical' @@ -13,7 +14,7 @@ hint_text: 'type or select sender address' size_hint_y: None height: 100 - font_size: '15sp' + font_size: dp(15) multiline: False required: True helper_text_mode: "on_error" diff --git a/src/bitmessagekivy/kv/inbox.kv b/src/bitmessagekivy/kv/inbox.kv index 106d2d47..4aadf21f 100644 --- a/src/bitmessagekivy/kv/inbox.kv +++ b/src/bitmessagekivy/kv/inbox.kv @@ -29,4 +29,9 @@ MDList: id: ml Loader: - ComposerButton: \ No newline at end of file + ComposerButton: + +: + size_hint:(None, None) + font_style: 'Caption' + halign: 'center' diff --git a/src/bitmessagekivy/kv/login.kv b/src/bitmessagekivy/kv/login.kv index c6c90330..2548a758 100644 --- a/src/bitmessagekivy/kv/login.kv +++ b/src/bitmessagekivy/kv/login.kv @@ -5,7 +5,7 @@ BoxLayout: orientation: 'vertical' size_hint_y: None - height: dp(400) + self.minimum_height + height: dp(450) + self.minimum_height padding: dp(10) BoxLayout: MDLabel: @@ -21,6 +21,9 @@ text: root.log_text2 halign: 'left' color:app.theme_cls.primary_dark + Widget: + size_hint: (None, None) + height: dp(10) MDCheckbox: id: grp_chkbox_1 group: 'test' @@ -55,7 +58,8 @@ BoxLayout: AnchorLayout: MDRaisedButton: - height: dp(40) + size_hint: (.2, None) + # height: dp(40) on_press: app.root.ids.scr_mngr.current = 'random' on_press: app.root.ids.sc7.reset_address_label() MDLabel: @@ -68,44 +72,49 @@ : name: 'random' ScrollView: - BoxLayout: - orientation: 'vertical' - size_hint_y: None - height: self.minimum_height - padding: dp(20) - spacing: 100 - MDLabel: - font_style: 'Subtitle2' - theme_text_color: 'Primary' - text: "Random Addresses" - halign: 'center' - color:app.theme_cls.primary_dark + id: add_random_bx - MDLabel: - font_style: 'Subtitle2' - theme_text_color: 'Primary' - text: "Here you may generate as many addresses as you like, Indeed creating and abandoning addresses is encouraged" - halign: 'center' - color:app.theme_cls.primary_dark - MDTextField: - id: label - multiline: False - hint_text: "Label" - required: True - helper_text_mode: "on_error" - on_text: root.add_validation(self) - canvas.before: - Color: - rgba: (0,0,0,1) - BoxLayout: - AnchorLayout: - MDRaisedButton: - height: dp(40) - on_release: root.generateaddress(app) - opposite_colors: True - MDLabel: - font_style: 'H6' - text: 'next' - font_size: '13sp' - color: (1,1,1,1) - halign: 'center' +: + orientation: 'vertical' + size_hint_y: None + height: self.minimum_height + padding: dp(20) + spacing: 100 + MDLabel: + font_style: 'Subtitle2' + theme_text_color: 'Primary' + text: "Random Addresses" + halign: 'center' + color:app.theme_cls.primary_dark + + MDLabel: + font_style: 'Subtitle2' + theme_text_color: 'Primary' + text: "Here you may generate as many addresses as you like, Indeed creating and abandoning addresses is encouraged" + halign: 'left' + color:app.theme_cls.primary_dark + + MDTextField: + id: label + multiline: False + hint_text: "Label" + required: True + helper_text_mode: "on_error" + on_text: app.root.ids.sc7.add_validation(self) + canvas.before: + Color: + rgba: (0,0,0,1) + + BoxLayout: + AnchorLayout: + MDRaisedButton: + size_hint: (.2, None) + # height: dp(40) + on_release: app.root.ids.sc7.generateaddress(app) + opposite_colors: True + MDLabel: + font_style: 'H6' + text: 'next' + font_size: '13sp' + color: (1,1,1,1) + halign: 'center' diff --git a/src/bitmessagekivy/kv/maildetail.kv b/src/bitmessagekivy/kv/maildetail.kv index 018818f8..714e56b6 100644 --- a/src/bitmessagekivy/kv/maildetail.kv +++ b/src/bitmessagekivy/kv/maildetail.kv @@ -7,7 +7,7 @@ orientation: 'vertical' # height: dp(bod.height) + self.minimum_height height: self.minimum_height - padding: dp(20) + padding: dp(10) # MDLabel: # size_hint_y: None # id: subj @@ -32,17 +32,21 @@ divider: None on_press: root.detailedPopup() BadgeText: + size_hint:(None, None) + size:[120, 140] if app.app_platform == 'android' else [64, 80] text: root.time_tag - halign:'right' + halign:'center' font_style:'Caption' pos_hint: {'center_y': .8} + _txt_right_pad: dp(70) + font_size: '11sp' MDChip: - size_hint: (None, None) + size_hint: (.16 if app.app_platform == 'android' else .07 , None) label: root.page_type icon: '' - pos_hint: {'center_x': .94, 'center_y': .3} + pos_hint: {'center_x': .91 if app.app_platform == 'android' else .95, 'center_y': .3} radius: 8 - height: 18 + height: self.parent.height/4 AvatarSampleWidget: source: root.avatarImg MDLabel: diff --git a/src/bitmessagekivy/kv/network.kv b/src/bitmessagekivy/kv/network.kv index 25f2bacc..c7cb9a2f 100644 --- a/src/bitmessagekivy/kv/network.kv +++ b/src/bitmessagekivy/kv/network.kv @@ -19,12 +19,18 @@ size_hint_y: None height: dp(58) MDRaisedButton: - size_hint: .5, 0 + size_hint: .6, 0 height: dp(40) - text: root.text_variable_1 + # text: root.text_variable_1 elevation_normal: 2 opposite_colors: True pos_hint: {'center_x': .5} + MDLabel: + font_style: 'H6' + text: root.text_variable_1 + font_size: '13sp' + color: (1,1,1,1) + halign: 'center' Tab: text: 'Processes' ScrollView: @@ -40,12 +46,18 @@ size_hint_y: None height: dp(58) MDRaisedButton: - size_hint: .5, 0 + size_hint: .6, 0 height: dp(40) - text: root.text_variable_2 + # text: root.text_variable_2 elevation_normal: 2 opposite_colors: True pos_hint: {'center_x': .5} + MDLabel: + font_style: 'H6' + text: root.text_variable_2 + font_size: '13sp' + color: (1,1,1,1) + halign: 'center' OneLineListItem: text: "Brodcast" BoxLayout: @@ -53,12 +65,18 @@ size_hint_y: None height: dp(58) MDRaisedButton: - size_hint: .5, 0 + size_hint: .6, 0 height: dp(40) - text: root.text_variable_3 + # text: root.text_variable_3 elevation_normal: 2 opposite_colors: True pos_hint: {'center_x': .5} + MDLabel: + font_style: 'H6' + text: root.text_variable_3 + font_size: '13sp' + color: (1,1,1,1) + halign: 'center' OneLineListItem: text: "publickeys" BoxLayout: @@ -66,12 +84,18 @@ size_hint_y: None height: dp(58) MDRaisedButton: - size_hint: .5, 0 + size_hint: .6, 0 height: dp(40) - text: root.text_variable_4 + # text: root.text_variable_4 elevation_normal: 2 opposite_colors: True pos_hint: {'center_x': .5} + MDLabel: + font_style: 'H6' + text: root.text_variable_4 + font_size: '13sp' + color: (1,1,1,1) + halign: 'center' OneLineListItem: text: "objects" BoxLayout: @@ -79,9 +103,15 @@ size_hint_y: None height: dp(58) MDRaisedButton: - size_hint: .5, 0 + size_hint: .6, 0 height: dp(40) - text: root.text_variable_5 + # text: root.text_variable_5 elevation_normal: 2 opposite_colors: True pos_hint: {'center_x': .5} + MDLabel: + font_style: 'H6' + text: root.text_variable_5 + font_size: '13sp' + color: (1,1,1,1) + halign: 'center' diff --git a/src/bitmessagekivy/kv/payment.kv b/src/bitmessagekivy/kv/payment.kv index a5cb1047..4e41cd02 100644 --- a/src/bitmessagekivy/kv/payment.kv +++ b/src/bitmessagekivy/kv/payment.kv @@ -45,7 +45,7 @@ Rectangle: pos: self.pos size: self.size - size: dp(app.window_size[0] - 2*self.parent.parent.padding[0]) - 10 , 1 + size: app.window_size[0] - 2*self.parent.parent.padding[0] - dp(10) , 1 height: dp(40) on_press: root.get_free_credits(self) MDLabel: @@ -91,7 +91,7 @@ Rectangle: pos: self.pos size: self.size - size: dp(app.window_size[0] - 2*self.parent.parent.padding[0]) - 10 , 1 + size: app.window_size[0] - 2*self.parent.parent.padding[0] - dp(10) , 1 height: dp(40) on_press: root.create_hidden_payment_address(self) MDLabel: @@ -137,7 +137,7 @@ Rectangle: pos: self.pos size: self.size - size: dp(app.window_size[0] - 2*self.parent.parent.padding[0]) - 10 , 1 + size: app.window_size[0] - 2*self.parent.parent.padding[0] - dp(10) , 1 height: dp(40) on_press: root.create_hidden_payment_address(self) MDLabel: diff --git a/src/bitmessagekivy/kv/popup.kv b/src/bitmessagekivy/kv/popup.kv index f35ee211..26ff017c 100644 --- a/src/bitmessagekivy/kv/popup.kv +++ b/src/bitmessagekivy/kv/popup.kv @@ -102,7 +102,7 @@ BoxLayout: size_hint_y: None orientation: 'vertical' - spacing:dp(20) + spacing:dp(15) MDLabel: font_style: 'Subtitle2' theme_text_color: 'Primary' @@ -128,6 +128,9 @@ text: "Address" font_size: '17sp' halign: 'left' + Widget: + size_hint_y: None + height: dp(1) BoxLayout: orientation: 'horizontal' MDLabel: @@ -338,6 +341,19 @@ id: myadd_popup_box size_hint_y: None orientation: 'vertical' + spacing:dp(8 if app.app_platform == 'android' else 3) + BoxLayout: + orientation: 'vertical' + MDLabel: + id: from_add_label + font_style: 'Subtitle2' + theme_text_color: 'Primary' + text: "From :" + font_size: '15sp' + halign: 'left' + Widget: + size_hint_y: None + height: dp(1 if app.app_platform == 'android' else 0) BoxLayout: size_hint_y: None height: 50 @@ -346,13 +362,23 @@ id: sd_label font_style: 'Body2' theme_text_color: 'Primary' - text: "From : [b]" + root.from_addr + "[/b]" + text: "[b]" + root.from_addr + "[/b]" font_size: '15sp' halign: 'left' markup: True IconRightSampleWidget: icon: 'content-copy' on_press: app.copy_composer_text(root.from_addr) + Widget: + id: space_1 + size_hint_y: None + height: dp(2 if app.app_platform == 'android' else 0) + BoxLayout: + id: to_addtitle + Widget: + id:space_2 + size_hint_y: None + height: dp(1 if app.app_platform == 'android' else 0) BoxLayout: id: to_addId BoxLayout: @@ -370,7 +396,8 @@ orientation: 'vertical' MDRaisedButton: on_press: root.dismiss() - pos_hint: {'x': 0.85, 'y': 0} + size_hint: .2, 0 + pos_hint: {'x': 0.8, 'y': 0} MDLabel: font_style: 'H6' text: 'Cancel' @@ -383,9 +410,19 @@ MDLabel: font_style: 'Body2' theme_text_color: 'Primary' - text: "To : " + root.to_addr + text: root.to_addr font_size: '15sp' halign: 'left' IconRightSampleWidget: icon: 'content-copy' - on_press: app.copy_composer_text(root.to_addr) \ No newline at end of file + on_press: app.copy_composer_text(root.to_addr) + +: + orientation: 'vertical' + MDLabel: + id: to_add_label + font_style: 'Subtitle2' + theme_text_color: 'Primary' + text: "To :" + font_size: '15sp' + halign: 'left' \ No newline at end of file diff --git a/src/bitmessagekivy/kv/settings.kv b/src/bitmessagekivy/kv/settings.kv index 0ca5c4ab..05d3486b 100644 --- a/src/bitmessagekivy/kv/settings.kv +++ b/src/bitmessagekivy/kv/settings.kv @@ -11,10 +11,12 @@ BoxLayout: size_hint_y: None orientation: 'vertical' - height: dp(400) + self.minimum_height + height: dp(250) + self.minimum_height padding: 10 BoxLayout: + size_hint_y: None orientation: 'horizontal' + height: self.minimum_height MDCheckbox: id: chkbox size_hint: None, None @@ -29,23 +31,6 @@ halign: 'left' pos_hint: {'center_x': 0, 'center_y': 0.6} disabled: True - BoxLayout: - orientation: 'vertical' - padding: [0, 10, 0, 0] - spacing: 10 - MDLabel: - font_style: 'Body1' - theme_text_color: 'Primary' - text: "Interface Language" - halign: 'right' - bold: True - MDDropDownItem: - id: dropdown_item - text: 'italiano' - dropdown_max_height: 150 - dropdown_bg: [1, 1, 1, 1] - pos_hint: {'center_x': 0.8, 'center_y': 0} - items: [f"{i}" for i in ['System Setting','U.S. English','italiano','Esperanto','dansk','Deutsch','Pirate English','francais','Nederlands','norsk bokmal','polski','portugues europeu']] BoxLayout: size_hint_y: None orientation: 'vertical' @@ -105,51 +90,53 @@ halign: 'left' pos_hint: {'x': 0, 'y': .5} BoxLayout: - orientation: 'horizontal' - MDCheckbox: - id: chkbox - size_hint: None, None - size: dp(48), dp(50) - # active: True - halign: 'center' - MDLabel: - font_style: 'Body1' - theme_text_color: 'Primary' - text: "Hide connection notifications" - halign: 'left' - pos_hint: {'x': 0, 'y': 0.1} + size_hint_y: None + orientation: 'vertical' + height: dp(100) + self.minimum_height + BoxLayout: + orientation: 'horizontal' + MDCheckbox: + id: chkbox + size_hint: None, None + size: dp(48), dp(50) + # active: True + halign: 'center' + MDLabel: + font_style: 'Body1' + theme_text_color: 'Primary' + text: "Hide connection notifications" + halign: 'left' + pos_hint: {'x': 0, 'y': 0.2} + BoxLayout: + orientation: 'horizontal' + MDCheckbox: + id: chkbox + size_hint: None, None + size: dp(48), dp(50) + active: True + halign: 'center' + MDLabel: + font_style: 'Body1' + theme_text_color: 'Primary' + text: "Show notification when message received" + halign: 'left' + pos_hint: {'x': 0, 'y': 0.2} + BoxLayout: + orientation: 'horizontal' + MDCheckbox: + id: chkbox + size_hint: None, None + size: dp(48), dp(50) + # active: True + halign: 'center' + MDLabel: + font_style: 'Body1' + theme_text_color: 'Primary' + text: "Run in Portable Mode" + halign: 'left' + pos_hint: {'x': 0, 'y': 0.2} BoxLayout: - orientation: 'horizontal' - MDCheckbox: - id: chkbox - size_hint: None, None - size: dp(48), dp(50) - active: True - halign: 'center' - MDLabel: - font_style: 'Body1' - theme_text_color: 'Primary' - text: "Show notification when message received" - halign: 'left' - pos_hint: {'x': 0, 'y': 0.1} - BoxLayout: - orientation: 'horizontal' - MDCheckbox: - id: chkbox - size_hint: None, None - size: dp(48), dp(50) - # active: True - halign: 'center' - MDLabel: - font_style: 'Body1' - theme_text_color: 'Primary' - text: "Run in Portable Mode" - halign: 'left' - pos_hint: {'x': 0, 'y': 0.1} - BoxLayout: - # id: box_height - orientation: 'horizontal' - padding: 10 + orientation: 'vertical' MDLabel: font_style: 'Body1' theme_text_color: 'Primary' @@ -157,74 +144,84 @@ # text: 'huiiiii' halign: 'left' BoxLayout: - orientation: 'horizontal' - MDCheckbox: - id: chkbox - size_hint: None, None - size: dp(48), dp(50) - halign: 'center' - MDLabel: - font_style: 'Body1' - theme_text_color: 'Primary' - text: "Willingly include unencrypted destination address when sending to a mobile device" - halign: 'left' - pos_hint: {'x': 0, 'y': 0.1} - BoxLayout: - orientation: 'horizontal' - MDCheckbox: - id: chkbox - size_hint: None, None - size: dp(48), dp(50) - active: True - halign: 'center' - MDLabel: - font_style: 'Body1' - theme_text_color: 'Primary' - text: "Use identicons" - halign: 'left' - pos_hint: {'x': 0, 'y': 0.1} - BoxLayout: - orientation: 'horizontal' - MDCheckbox: - id: chkbox - size_hint: None, None - size: dp(48), dp(50) - halign: 'center' - MDLabel: - font_style: 'Body1' - theme_text_color: 'Primary' - text: "Reply below Quote" - halign: 'left' - pos_hint: {'x': 0, 'y': 0.1} + size_hint_y: None + orientation: 'vertical' + height: dp(100) + self.minimum_height + BoxLayout: + orientation: 'horizontal' + MDCheckbox: + id: chkbox + size_hint: None, None + size: dp(48), dp(50) + halign: 'center' + MDLabel: + font_style: 'Body1' + theme_text_color: 'Primary' + text: "Willingly include unencrypted destination address when sending to a mobile device" + halign: 'left' + pos_hint: {'x': 0, 'y': 0.2} + BoxLayout: + orientation: 'horizontal' + MDCheckbox: + id: chkbox + size_hint: None, None + size: dp(48), dp(50) + active: True + halign: 'center' + MDLabel: + font_style: 'Body1' + theme_text_color: 'Primary' + text: "Use identicons" + halign: 'left' + pos_hint: {'x': 0, 'y': 0.2} + BoxLayout: + orientation: 'horizontal' + MDCheckbox: + id: chkbox + size_hint: None, None + size: dp(48), dp(50) + halign: 'center' + MDLabel: + font_style: 'Body1' + theme_text_color: 'Primary' + text: "Reply below Quote" + halign: 'left' + pos_hint: {'x': 0, 'y': 0.2} Widget: size_hint_y: None height: 10 - # BoxLayout: - # orientation: 'vertical' - # spacing: 10 - # padding: 10 - - # MDLabel: - # font_style: 'Body1' - # theme_text_color: 'Primary' - # text: "Interface Language" - # halign: 'left' - # bold: True - # MDDropDownItem: - # id: dropdown_item - # # on_select - # text: 'italiano' - # dropdown_max_height: 150 - # pos_hint: {'center_x': 0.1, 'center_y': 0} - # items: [f"{i}" for i in ['System Setting','U.S. English','italiano','Esperanto','dansk','Deutsch','Pirate English','francais','Nederlands','norsk bokmal','polski','portugues europeu']] + BoxLayout: + size_hint_y: None + orientation: 'vertical' + # padding: [0, 10, 0, 0] + spacing: 10 + padding: [20, 0, 0, 0] + height: dp(20) + self.minimum_height + MDLabel: + font_style: 'Body1' + theme_text_color: 'Primary' + text: "Interface Language" + # halign: 'right' + bold: True + MDDropDownItem: + id: dropdown_item + text: 'italiano' + dropdown_max_height: 150 + dropdown_bg: [1, 1, 1, 1] + # pos_hint: {'center_x': 0.5, 'center_y': 0} + items: [f"{i}" for i in ['System Setting','U.S. English','italiano','Esperanto','dansk','Deutsch','Pirate English','francais','Nederlands','norsk bokmal','polski','portugues europeu']] BoxLayout: spacing:5 orientation: 'horizontal' - pos_hint: {'x':.76} - MDRaisedButton: - text: 'Reset' - MDRaisedButton: - text: 'Ok' + # pos_hint: {'x':.76} + BoxLayout: + orientation: 'horizontal' + # padding: [0, 10, 0, 0] + spacing: 10 + MDRaisedButton: + text: 'Reset' + MDRaisedButton: + text: 'Ok' Tab: text: 'Network Settings' ScrollView: @@ -232,7 +229,7 @@ BoxLayout: size_hint_y: None orientation: 'vertical' - height: dp(550) + self.minimum_height + height: dp(500) + self.minimum_height padding: 10 BoxLayout: id: box_height @@ -275,7 +272,7 @@ theme_text_color: 'Primary' text: "UPnP" halign: 'left' - pos_hint: {'x': 0, 'y': 0.1} + pos_hint: {'x': 0, 'y': 0} BoxLayout: orientation: 'vertical' MDLabel: @@ -301,9 +298,11 @@ pos_hint: {'x': 0.9, 'y': 0} items: [f"{i}" for i in ['System Setting','U.S. English']] BoxLayout: - orientation: 'horizontal' + size_hint_y: None + orientation: 'vertical' padding: [30, 0, 0, 0] spacing: 10 + height: dp(100) + self.minimum_height BoxLayout: orientation: 'horizontal' MDLabel: @@ -337,10 +336,6 @@ hint_text: '9050' pos_hint: {'center_y': .5, 'center_x': .5} input_filter: "int" - BoxLayout: - orientation: 'horizontal' - padding: [30, 0, 0, 0] - spacing: 10 BoxLayout: orientation: 'horizontal' MDLabel: @@ -377,7 +372,7 @@ theme_text_color: 'Primary' text: "Authentication" halign: 'left' - pos_hint: {'x': 0, 'y': 0.1} + pos_hint: {'x': 0, 'y': 0} BoxLayout: orientation: 'horizontal' padding: [30, 0, 0, 0] @@ -392,7 +387,7 @@ theme_text_color: 'Primary' text: "Listen for incoming connections when using proxy" halign: 'left' - pos_hint: {'x': 0, 'y': 0.1} + pos_hint: {'x': 0, 'y': 0} BoxLayout: orientation: 'horizontal' padding: [30, 0, 0, 0] @@ -407,7 +402,7 @@ theme_text_color: 'Primary' text: "Only connect to onion services(*.onion)" halign: 'left' - pos_hint: {'x': 0, 'y': 0.1} + pos_hint: {'x': 0, 'y': 0} BoxLayout: orientation: 'vertical' MDLabel: @@ -417,8 +412,10 @@ halign: 'left' bold: True BoxLayout: + size_hint_y: None orientation: 'horizontal' padding: [30, 0, 0, 0] + height: dp(30) + self.minimum_height MDLabel: font_style: 'Body1' theme_text_color: 'Primary' @@ -426,13 +423,15 @@ halign: 'left' MDTextFieldRect: size_hint: None, None - size: dp(app.window_size[0]/2), dp(30) + size: app.window_size[0]/2, dp(30) hint_text: '0' pos_hint: {'center_y': .5, 'center_x': .5} input_filter: "int" BoxLayout: + size_hint_y: None orientation: 'horizontal' padding: [30, 0, 0, 0] + height: dp(30) + self.minimum_height MDLabel: font_style: 'Body1' theme_text_color: 'Primary' @@ -440,13 +439,15 @@ halign: 'left' MDTextFieldRect: size_hint: None, None - size: dp(app.window_size[0]/2), dp(30) + size: app.window_size[0]/2, dp(30) hint_text: '0' pos_hint: {'center_y': .5, 'center_x': .5} input_filter: "int" BoxLayout: + size_hint_y: None orientation: 'horizontal' padding: [30, 0, 0, 0] + height: dp(30) + self.minimum_height MDLabel: font_style: 'Body1' theme_text_color: 'Primary' @@ -454,14 +455,14 @@ halign: 'left' MDTextFieldRect: size_hint: None, None - size: dp(app.window_size[0]/2), dp(30) + size: app.window_size[0]/2, dp(30) hint_text: '8' pos_hint: {'center_y': .5, 'center_x': .5} input_filter: "int" BoxLayout: spacing:5 orientation: 'horizontal' - pos_hint: {'x':.76} + # pos_hint: {'x':.76} MDRaisedButton: text: 'Reset' MDRaisedButton: @@ -473,28 +474,34 @@ BoxLayout: size_hint_y: None orientation: 'vertical' - height: dp(200) + self.minimum_height + height: dp(210 if app.app_platform == 'android' else 100)+ self.minimum_height padding: 20 - spacing: 10 + # spacing: 10 BoxLayout: - id: box_height + # size_hint_y: None + id: box1_height orientation: 'vertical' + # height: dp(100) + self.minimum_height MDLabel: font_style: 'Body1' theme_text_color: 'Primary' text: root.exp_text halign: 'left' BoxLayout: - id: box_height + id: box2_height + size_hint_y: None orientation: 'vertical' + height: dp(30) + self.minimum_height MDLabel: font_style: 'Body1' theme_text_color: 'Primary' text: "Leave these input fields blank for the default behavior." halign: 'left' BoxLayout: - orientation: 'horizontal' + size_hint_y: None + orientation: 'vertical' padding: [10, 0, 0, 0] + height: dp(50) + self.minimum_height BoxLayout: orientation: 'horizontal' MDLabel: @@ -525,10 +532,12 @@ text: "months" halign: 'left' BoxLayout: + size_hint_y: None spacing:5 orientation: 'horizontal' # pos_hint: {'left': 0} - pos_hint: {'x':.75} + # pos_hint: {'x':.75} + height: dp(50) + self.minimum_height MDRaisedButton: text: 'Reset' MDRaisedButton: diff --git a/src/bitmessagekivy/main.kv b/src/bitmessagekivy/main.kv index 0e6ec253..dba77d71 100644 --- a/src/bitmessagekivy/main.kv +++ b/src/bitmessagekivy/main.kv @@ -85,6 +85,7 @@ source: app.get_default_logo() ScrollView: + id: scroll_y pos_hint: {"top": 1} GridLayout: @@ -97,7 +98,8 @@ text: "Accounts" height:"35dp" NavigationItem: - size: 50,50 + # size: 50,50 + height: dp(48) CustomSpinner: id: btn pos_hint:{"x":0,"y":0} @@ -155,6 +157,13 @@ on_release: app.root.ids.scr_mngr.current = 'allmails' on_release: root.parent.set_state() on_press: app.load_screen(self) + NavigationItem: + id: chat_rm + text: 'Chat Room' + icon: 'wechat' + divider: None + on_release: app.root.ids.scr_mngr.current = 'chlist' + on_release: root.parent.set_state() NavigationDrawerDivider: NavigationDrawerSubheader: text: "All labels" @@ -188,6 +197,7 @@ divider: None on_release: app.root.ids.scr_mngr.current = 'login' on_release: root.parent.set_state() + on_press: app.reset_login_screen() NavigationItem: text: 'Network status' icon: 'server-network' @@ -259,6 +269,10 @@ NavigationLayout: id:sc19 Archieve: id:sc20 + ChatRoom: + id:sc21 + ChatList: + id:sc22 MDNavigationDrawer: id: nav_drawer @@ -288,7 +302,7 @@ NavigationLayout: orientation: 'vertical' size_hint: (None, None) pos_hint:{'center_x': .5, 'top': 0.9} - size: (app.window_size[0]/2, app.window_size[0]/2) + size: (app.window_size[0]/1.8, app.window_size[0]/1.8) id: qr BoxLayout: orientation: 'vertical' @@ -302,9 +316,9 @@ NavigationLayout: line_color_normal: [0,0,0,0] _current_line_color: [0,0,0,0] line_color_focus: [0,0,0,0] - font_size: '18sp' + halign: 'center' + font_size: dp(15) bold: True - pos_hint: {'x': .26, 'y': 0.5} # MDLabel: # size_hint_y: None # font_style: 'Body1' diff --git a/src/bitmessagekivy/mpybit.py b/src/bitmessagekivy/mpybit.py index 6813b8de..f2a77f07 100644 --- a/src/bitmessagekivy/mpybit.py +++ b/src/bitmessagekivy/mpybit.py @@ -3,6 +3,7 @@ Bitmessage android(mobile) interface """ # pylint: disable=too-many-lines,import-error,no-name-in-module,unused-argument # pylint: disable=too-many-ancestors,too-many-locals,useless-super-delegation +# pylint: disable=protected-access import os import time from bitmessagekivy import identiconGeneration @@ -57,6 +58,11 @@ from kivymd.uix.list import ( # ) from kivymd.uix.selectioncontrol import MDCheckbox, MDSwitch from kivymd.uix.chip import MDChip +from kivy.uix.screenmanager import ( + RiseInTransition, + SlideTransition, + FallOutTransition +) import queues from semaphores import kivyuisignaler @@ -65,15 +71,18 @@ import state from addresses import decodeAddress from kivy.uix.modalview import ModalView from datetime import datetime -from kivy.config import Config -Config.set('input', 'mouse', 'mouse,multitouch_on_demand') + +if platform != 'android': + from kivy.config import Config + Config.set('input', 'mouse', 'mouse,multitouch_on_demand') # pylint: disable=too-few-public-methods,too-many-arguments,attribute-defined-outside-init KVFILES = [ 'settings', 'popup', 'allmails', 'draft', 'maildetail', 'common_widgets', 'addressbook', 'myaddress', 'composer', 'payment', 'sent', - 'network', 'login', 'credits', 'trash', 'inbox' + 'network', 'login', 'credits', 'trash', 'inbox', + 'chat_room', 'chat_list' ] @@ -106,22 +115,22 @@ def ShowTimeHistoy(act_time): def AddTimeWidget(time): # pylint: disable=redefined-outer-name """This method is used to create TimeWidget""" - action_time = BadgeText( - size_hint=(None, None), + action_time = TimeTagRightSampleWidget( text=str(ShowTimeHistoy(time)), - halign='right', font_style='Caption', - size=[65, 70]) + size=[120, 140] if platform == 'android' else [64, 80]) + action_time.font_size = '11sp' return action_time def chipTag(text): """This method is used for showing chip tag""" obj = MDChip() - obj.size_hint = (None, None) + # obj.size_hint = (None, None) + obj.size_hint = (.16 if platform == 'android' else .07, None) obj.label = text obj.icon = '' - obj.pos_hint = {'center_x': .96, 'center_y': .2} + obj.pos_hint = {'center_x': .91 if platform == 'android' else .94, 'center_y': .3} obj.height = dp(18) obj.radius = 8 return obj @@ -213,6 +222,7 @@ class Inbox(Screen): text=item['text'], secondary_text=item['secondary_text'], theme_text_color='Custom', text_color=NavigateApp().theme_cls.primary_color) + meny._txt_right_pad = dp(70) meny.add_widget(AvatarSampleWidget( source='./images/text_images/{}.png'.format( avatarImageFirstLetter(item['secondary_text'].strip())))) @@ -398,6 +408,7 @@ class MyAddress(Screen): text=item['text'], secondary_text=item['secondary_text'], theme_text_color='Custom' if is_enable == 'true' else 'Primary', text_color=NavigateApp().theme_cls.primary_color,) + meny._txt_right_pad = dp(70) try: meny.canvas.children[6].rgba = [0, 0, 0, 0] if is_enable == 'true' else [0.5, 0.5, 0.5, 0.5] except Exception: @@ -408,31 +419,17 @@ class MyAddress(Screen): meny.bind(on_press=partial( self.myadd_detail, item['secondary_text'], item['text'])) if state.association == item['secondary_text']: - meny.add_widget( - BadgeText( - size_hint=(None, None), - text='Active', halign='right', - font_style='Body1', size=[50, 60], - theme_text_color='Custom', - text_color=NavigateApp().theme_cls.primary_color)) + badge_obj = BadgeText( + size_hint=(None, None), + size=[85 if platform == 'android' else 50, 60], + text='Active', halign='center', + font_style='Body1', theme_text_color='Custom', + text_color=NavigateApp().theme_cls.primary_color + ) + badge_obj.font_size = '13sp' + meny.add_widget(badge_obj) else: meny.add_widget(ToggleBtn(active=True if is_enable == 'true' else False)) - # carousel = Carousel(direction='right') - # carousel.height = meny.height - # carousel.size_hint_y = None - # carousel.ignore_perpendicular_swipes = True - # carousel.data_index = 0 - # carousel.min_move = 0.2 - # del_btn = Button(text='Disable' if is_enable == 'true' else 'Enable') - # if is_enable == 'true': - # del_btn.background_normal = '' - # del_btn.background_color = (1, 0, 0, 1) if is_enable == 'true' else (0, 1, 0, 1) - # del_btn.bind( - # on_press=partial( - # self.disableAddress if is_enable == 'true' else self.enableAddress , item['secondary_text'])) - # carousel.add_widget(del_btn) - # carousel.add_widget(meny) - # carousel.index = 1 self.ids.ml.add_widget(meny) def check_scroll_y(self, instance, somethingelse): @@ -968,7 +965,19 @@ class NetworkStat(Screen): class ContentNavigationDrawer(BoxLayout): """Navigate Content Drawer""" - pass + def __init__(self, *args, **kwargs): + """Method used for contentNavigationDrawer""" + super(ContentNavigationDrawer, self).__init__(*args, **kwargs) + Clock.schedule_once(self.init_ui, 0) + + def init_ui(self, dt=0): + """Clock Schdule for class contentNavigationDrawer""" + self.ids.scroll_y.bind(scroll_y=self.check_scroll_y) + + def check_scroll_y(self, instance, somethingelse): + """show data on scroll down""" + if self.ids.btn.is_open: + self.ids.btn.is_open = False class Random(Screen): @@ -979,13 +988,12 @@ class Random(Screen): def generateaddress(self, navApp): """Method for Address Generator""" - entered_label = str(self.ids.label.text).strip() + entered_label = str(self.ids.add_random_bx.children[0].ids.label.text).strip() if not entered_label: - self.ids.label.focus = True + self.ids.add_random_bx.children[0].ids.label.focus = True # self.ids.label.error = True # self.ids.label.helper_text = 'This field is required' streamNumberForAddress = 1 - label = self.ids.label.text eighteenByteRipe = False nonceTrialsPerByte = 1000 payloadLengthExtraBytes = 1000 @@ -994,44 +1002,54 @@ class Random(Screen): if entered_label and entered_label not in lables: toast('Address Creating...') queues.addressGeneratorQueue.put(( - 'createRandomAddress', 4, streamNumberForAddress, label, 1, + 'createRandomAddress', 4, streamNumberForAddress, entered_label, 1, "", eighteenByteRipe, nonceTrialsPerByte, payloadLengthExtraBytes)) - self.ids.label.text = '' self.parent.parent.ids.toolbar.opacity = 1 self.parent.parent.ids.toolbar.disabled = False state.kivyapp.loadMyAddressScreen(True) self.manager.current = 'myaddress' Clock.schedule_once(self.address_created_callback, 6) - @staticmethod - def address_created_callback(dt=0): + def address_created_callback(self, dt=0): """New address created""" state.kivyapp.loadMyAddressScreen(False) state.kivyapp.root.ids.sc10.ids.ml.clear_widgets() state.kivyapp.root.ids.sc10.is_add_created = True state.kivyapp.root.ids.sc10.init_ui() + self.reset_address_spinner() toast('New address created') - def add_validation(self, instance): + def reset_address_spinner(self): + """reseting spinner address and UI""" + addresses = [addr for addr in BMConfigParser().addresses() + if BMConfigParser().get(str(addr), 'enabled') == 'true'] + self.manager.parent.ids.content_drawer.ids.btn.values = [] + self.manager.parent.ids.sc3.children[1].ids.btn.values = [] + self.manager.parent.ids.content_drawer.ids.btn.values = addresses + self.manager.parent.ids.sc3.children[1].ids.btn.values = addresses + + @staticmethod + def add_validation(instance): """Checking validation at address creation time""" entered_label = str(instance.text.strip()) lables = [BMConfigParser().get(obj, 'label') for obj in BMConfigParser().addresses()] if entered_label in lables: - self.ids.label.error = True - self.ids.label.helper_text = 'Label name is already exist you'\ + instance.error = True + instance.helper_text = 'Label name is already exist you'\ ' can try this Ex. ( {0}_1, {0}_2 )'.format( entered_label) elif entered_label: - self.ids.label.error = False + instance.error = False else: - self.ids.label.error = False - self.ids.label.helper_text = 'This field is required' + instance.error = False + instance.helper_text = 'This field is required' def reset_address_label(self): """Resetting address labels""" - self.ids.label.text = '' + if not self.ids.add_random_bx.children: + self.ids.add_random_bx.add_widget(RandomBoxlayout()) class Sent(Screen): @@ -1110,6 +1128,7 @@ class Sent(Screen): text=item['text'], secondary_text=item['secondary_text'], theme_text_color='Custom', text_color=NavigateApp().theme_cls.primary_color) + meny._txt_right_pad = dp(70) meny.add_widget(AvatarSampleWidget( source='./images/text_images/{}.png'.format( avatarImageFirstLetter(item['secondary_text'].strip())))) @@ -1328,6 +1347,7 @@ class Trash(Screen): subject) >= 50 else (subject + ',' + body)[0:50] + '........').replace('\t', '').replace(' ', ''), theme_text_color='Custom', text_color=NavigateApp().theme_cls.primary_color) + meny._txt_right_pad = dp(70) img_latter = './images/text_images/{}.png'.format( subject[0].upper() if (subject[0].upper() >= 'A' and subject[0].upper() <= 'Z') else '!') meny.add_widget(AvatarSampleWidget(source=img_latter)) @@ -1433,6 +1453,12 @@ class Create(Screen): "SELECT label, address from addressbook")] widget_1.ids.txt_input.starting_no = 2 self.add_widget(widget_1) + self.children[0].ids.id_scroll.bind(scroll_y=self.check_scroll_y) + + def check_scroll_y(self, instance, somethingelse): + """show data on scroll down""" + if self.children[1].ids.btn.is_open: + self.children[1].ids.btn.is_open = False class Setting(Screen): @@ -1554,10 +1580,12 @@ class NavigateApp(MDApp): if platform == 'android': # android_path = os.path.expanduser # ("~/user/0/org.test.bitapp/files/app/") - android_path = os.path.join( - os.environ['ANDROID_PRIVATE'] + '/app/') - img.texture.save('{1}/images/default_identicon/{0}.png'.format( - BMConfigParser().addresses()[0], android_path)) + if not os.path.exists('./images/default_identicon/{}.png'.format( + BMConfigParser().addresses()[0])): + android_path = os.path.join( + os.environ['ANDROID_PRIVATE'] + '/app/') + img.texture.save('{1}/images/default_identicon/{0}.png'.format( + BMConfigParser().addresses()[0], android_path)) else: if not os.path.exists('./images/default_identicon/{}.png'.format( BMConfigParser().addresses()[0])): @@ -1602,14 +1630,20 @@ class NavigateApp(MDApp): # pylint: disable=inconsistent-return-statements, too-many-branches """Method is used for going on previous screen""" if key == 27: - if state.in_search_mode and self.root.ids.scr_mngr.current != ( - "mailDetail"): + if state.in_search_mode and self.root.ids.scr_mngr.current not in [ + "mailDetail", "create"]: self.closeSearchScreen() elif self.root.ids.scr_mngr.current == "mailDetail": self.root.ids.scr_mngr.current = 'sent'\ if state.detailPageType == 'sent' else 'inbox' \ if state.detailPageType == 'inbox' else 'draft' self.back_press() + if state.in_search_mode and state.searcing_text: + toolbar_obj = self.root.ids.toolbar + toolbar_obj.left_action_items = [ + ['arrow-left', lambda x: self.closeSearchScreen()]] + toolbar_obj.right_action_items = [] + self.root.ids.toolbar.title = '' elif self.root.ids.scr_mngr.current == "create": self.save_draft() self.set_common_header() @@ -1622,13 +1656,23 @@ class NavigateApp(MDApp): elif self.root.ids.scr_mngr.current == 'pay-options': self.set_common_header() self.root.ids.scr_mngr.current = 'payment' + elif self.root.ids.scr_mngr.current == 'chroom': + if state.association: + address_label = self.current_address_label( + BMConfigParser().get( + state.association, 'label'), state.association) + self.root.ids.toolbar.title = address_label + self.set_common_header() + self.root.ids.scr_mngr.transition = FallOutTransition() + self.root.ids.scr_mngr.current = 'chlist' + self.root.ids.scr_mngr.transition = SlideTransition() else: if state.kivyapp.variable_1: self.root.ids.scr_mngr.current = 'inbox' self.root.ids.scr_mngr.transition.direction = 'right' self.root.ids.scr_mngr.transition.bind(on_complete=self.reset) return True - elif key == 13 and state.searcing_text: + elif key == 13 and state.searcing_text and not state.in_composer: if state.search_screen == 'inbox': self.root.ids.sc1.children[1].active = True Clock.schedule_once(self.search_callback, 0.5) @@ -1742,12 +1786,21 @@ class NavigateApp(MDApp): self.root.ids.toolbar.title = '' else: self.set_common_header() + if self.root.ids.scr_mngr.current == 'chroom' and state.association: + self.root.ids.scr_mngr.transition = FallOutTransition() + address_label = self.current_address_label( + BMConfigParser().get( + state.association, 'label'), state.association) + self.root.ids.toolbar.title = address_label self.root.ids.scr_mngr.current = 'inbox' \ if state.in_composer else 'allmails'\ if state.is_allmail else state.detailPageType\ if state.detailPageType else 'myaddress'\ if self.root.ids.scr_mngr.current == 'showqrcode' else 'payment'\ - if self.root.ids.scr_mngr.current == 'pay-options' else 'inbox' + if self.root.ids.scr_mngr.current == 'pay-options' else 'chlist'\ + if self.root.ids.scr_mngr.current == 'chroom' else 'inbox' + if self.root.ids.scr_mngr.current == 'chlist': + self.root.ids.scr_mngr.transition = SlideTransition() self.root.ids.scr_mngr.transition.direction = 'right' self.root.ids.scr_mngr.transition.bind(on_complete=self.reset) if state.is_allmail or state.detailPageType == 'draft': @@ -1892,6 +1945,11 @@ class NavigateApp(MDApp): def set_mail_detail_header(self): """Setting the details of the page""" + if state.association and state.in_search_mode: + address_label = self.current_address_label( + BMConfigParser().get( + state.association, 'label'), state.association) + self.root.ids.toolbar.title = address_label toolbar_obj = self.root.ids.toolbar toolbar_obj.left_action_items = [ ['arrow-left', lambda x: self.back_press()]] @@ -1960,24 +2018,51 @@ class NavigateApp(MDApp): ext=['.png', '.jpg'] ) self.manager.add_widget(self.file_manager) - self.file_manager.show(os.environ["HOME"]) + # self.file_manager.show(os.environ["HOME"]) + if platform == 'android': + from android.permissions import request_permissions, Permission + request_permissions([Permission.WRITE_EXTERNAL_STORAGE, Permission.READ_EXTERNAL_STORAGE]) + + # from android.storage import app_storage_path + # settings_path = app_storage_path() + # print('path1................................', settings_path) + + # from android.storage import primary_external_storage_path + # primary_ext_storage = primary_external_storage_path() + # print('path1................................', primary_ext_storage) + + # from android.storage import secondary_external_storage_path + # secondary_ext_storage = secondary_external_storage_path() + # print('path1................................', secondary_ext_storage) + + # from kivy.app import user_data_dir + # from os.path import dirname, join + # out = join(dirname(user_data_dir), 'DCIM') + # DCIM = join('/sdcard', 'DCIM') + self.file_manager.show(os.getenv('EXTERNAL_STORAGE') if platform == 'android' else os.environ["HOME"]) + # self.file_manager.show(os.getenv('EXTERNAL_STORAGE')) self.manager_open = True self.manager.open() def select_path(self, path): """This method is used to save the select image""" from PIL import Image as PilImage - if not os.path.exists('./images/default_identicon/'): - os.makedirs('./images/default_identicon/') newImg = PilImage.open(path).resize((300, 300)) - newImg.save('./images/default_identicon/{0}.png'.format(state.association)) + if platform == 'android': + android_path = os.path.join( + os.environ['ANDROID_PRIVATE'] + '/app/') + newImg.save('{1}/images/default_identicon/{0}.png'.format( + state.association, android_path)) + else: + if not os.path.exists('./images/default_identicon/'): + os.makedirs('./images/default_identicon/') + newImg.save('./images/default_identicon/{0}.png'.format(state.association)) self.load_selected_Image(state.association) self.exit_manager() toast('Image changed') def exit_manager(self, *args): """Called when the user reaches the root of the directory tree.""" - self.manager.dismiss() self.manager_open = False @@ -1995,6 +2080,11 @@ class NavigateApp(MDApp): Clipboard.copy(text) toast('Copied') + def reset_login_screen(self): + """This method is used for clearing random screen""" + if self.root.ids.sc7.ids.add_random_bx.children: + self.root.ids.sc7.ids.add_random_bx.clear_widgets() + class GrashofPopup(Popup): """Moule for save contacts and error messages""" @@ -2040,9 +2130,9 @@ class GrashofPopup(Popup): def checkAddress_valid(self, instance): """Checking address is valid or not""" # my_addresses = ( - # self.parent.children[1].children[2].children[0].ids.btn.values) + # self.parent.children[1].children[0].children[0].ids.btn.values) my_addresses = ( - self.parent.children[1].children[0].children[0].ids.btn.values) + state.kivyapp.root.children[0].children[0].ids.btn.values) add_book = [addr[1] for addr in kivy_helper_search.search_sql( folder="addressbook")] entered_text = str(instance.text).strip() @@ -2129,6 +2219,12 @@ class IconRightSampleWidget(IRightBodyTouch, MDIconButton): pass +class TimeTagRightSampleWidget(IRightBodyTouch, MDLabel): + """Right icon sample widget""" + + pass + + class ToggleBtn(IRightBodyTouch, MDSwitch): """Right toggle button widget""" pass @@ -2254,6 +2350,7 @@ class MailDetail(Screen): # pylint: disable=too-many-instance-attributes def inbox_reply(self): """Reply inbox messages""" + state.in_composer = True data = sqlQuery( "select toaddress, fromaddress, subject, message, received from inbox where" " msgid = ?;", state.mail_id) @@ -2265,10 +2362,11 @@ class MailDetail(Screen): # pylint: disable=too-many-instance-attributes composer_obj.subject.text = 'Re: ' + (split_subject[1] if len(split_subject) > 1 else split_subject[0]) time_obj = datetime.fromtimestamp(int(data[0][4])) time_tag = time_obj.strftime("%d %b %Y, %I:%M %p") - sender_name = BMConfigParser().get(data[0][1], 'label') + # sender_name = BMConfigParser().get(data[0][1], 'label') + sender_name = data[0][1] composer_obj.body.text = ( - '\n\n ------------------------On ' + time_tag + ', ' - + sender_name + ' wrote:-----------------------\n' + data[0][3]) + '\n\n --------------On ' + time_tag + ', ' + + sender_name + ' wrote:--------------\n' + data[0][3]) composer_obj.body.focus = True composer_obj.body.cursor = (0, 0) state.kivyapp.root.ids.sc3.children[1].ids.rv.data = '' @@ -2507,6 +2605,7 @@ class Draft(Screen): text='Draft', secondary_text=item['text'], theme_text_color='Custom', text_color=NavigateApp().theme_cls.primary_color) + meny._txt_right_pad = dp(70) meny.add_widget(AvatarSampleWidget( source='./images/avatar.png')) meny.bind(on_press=partial( @@ -2709,6 +2808,7 @@ class Allmails(Screen): subject + ',' + body)[0:50] + '........').replace('\t', '').replace(' ', ''), theme_text_color='Custom', text_color=NavigateApp().theme_cls.primary_color) + meny._txt_right_pad = dp(70) meny.add_widget(AvatarSampleWidget( source='./images/text_images/{}.png'.format( avatarImageFirstLetter(body.strip())))) @@ -2798,6 +2898,7 @@ class Allmails(Screen): nav_lay_obj.sc5.clear_widgets() nav_lay_obj.sc5.add_widget(Trash()) nav_lay_obj.sc17.remove_widget(instance.parent.parent) + toast('Deleted') def refresh_callback(self, *args): """Method updates the state of application, @@ -2818,16 +2919,16 @@ class Allmails(Screen): def avatarImageFirstLetter(letter_string): """This function is used to the first letter for the avatar image""" - if letter_string: + try: if letter_string[0].upper() >= 'A' and letter_string[0].upper() <= 'Z': img_latter = letter_string[0].upper() elif int(letter_string[0]) >= 0 and int(letter_string[0]) <= 9: img_latter = letter_string[0] else: img_latter = '!' - else: + except ValueError: img_latter = '!' - return img_latter + return img_latter if img_latter else '!' class Starred(Screen): @@ -2945,18 +3046,23 @@ class SenderDetailPopup(Popup): self.from_addr = from_addr time_obj = datetime.fromtimestamp(int(timeinseconds)) self.time_tag = time_obj.strftime("%d %b %Y, %I:%M %p") - pop_height = 1.2 * (self.ids.sd_label.height + self.ids.sd_btn.children[0].height) + device_type = 2 if platform == 'android' else 1.5 + pop_height = device_type * (self.ids.sd_label.height + self.ids.sd_btn.children[0].height) if len(to_addr) > 3: self.height = 0 self.height = pop_height self.ids.to_addId.size_hint_y = None self.ids.to_addId.height = 50 + self.ids.to_addtitle.add_widget(ToAddressTitle()) frmaddbox = ToAddrBoxlayout() frmaddbox.set_toAddress(to_addr) self.ids.to_addId.add_widget(frmaddbox) else: + self.ids.space_1.height = dp(0) + self.ids.space_2.height = dp(0) + self.ids.myadd_popup_box.spacing = dp(8 if platform == 'android' else 3) self.height = 0 - self.height = pop_height / 1.5 + self.height = pop_height / 1.2 class OneLineListTitle(OneLineListItem): @@ -3006,3 +3112,91 @@ class ToAddrBoxlayout(BoxLayout): def set_toAddress(self, to_addr): """This method is use to set to address""" self.to_addr = to_addr + + +class ToAddressTitle(BoxLayout): + """class for BoxLayout behaviour""" + pass + + +class RandomBoxlayout(BoxLayout): + """class for BoxLayout behaviour""" + pass + + +def esc_markup(msg): + """this method is for replacing some property""" + return (msg.replace('&', '&') + .replace('[', '&bl;') + .replace(']', '&br;')) + + +class ChatRoom(Screen): + """class for chatroom screen""" + def send_msg(self): + """This method is for sending message""" + msg = self.ids.message.text + if msg: + self.ids.chat_logs.text += ( + '[b][color=2980b9]{}:[/color][/b] {}\n' + .format('Me', esc_markup(msg))) + # obj = MDChip(label=msg, radius=7) + # obj.icon = '' + # self.ids.ml.add_widget(obj) + self.ids.message.text = '' + + +class ChatList(Screen): + """class for showing chat list""" + queryreturn = ListProperty() + has_refreshed = True + + def __init__(self, *args, **kwargs): + """Getting ChatList Details""" + super(ChatList, self).__init__(*args, **kwargs) + Clock.schedule_once(self.init_ui, 0) + + def init_ui(self, dt=0): + """Clock Schdule for method ChatList""" + self.loadAddresslist(None, 'All', '') + print(dt) + + def loadAddresslist(self, account="", where="", what=""): + """Clock Schdule for method ChatList""" + self.queryreturn = kivy_helper_search.search_sql( + '', account, "addressbook", where, what, False) + self.queryreturn = [obj for obj in reversed(self.queryreturn)] + if self.queryreturn: + self.set_mdList() + else: + content = MDLabel( + font_style='Caption', + theme_text_color='Primary', + text="No contact found!", + halign='center', + size_hint_y=None, + valign='top') + self.ids.ml.add_widget(content) + + def set_mdList(self): + """Creating the mdList""" + for item in self.queryreturn: + meny = TwoLineAvatarIconListItem( + text=item[0], secondary_text=item[1], theme_text_color='Custom', + text_color=NavigateApp().theme_cls.primary_color) + meny.add_widget(AvatarSampleWidget( + source='./images/text_images/{}.png'.format( + avatarImageFirstLetter(item[0].strip())))) + meny.bind(on_release=partial( + self.redirect_to_chat, item[0], item[1])) + self.ids.ml.add_widget(meny) + + def redirect_to_chat(self, label, addr, *args): + """This method is redirecting on chatroom""" + self.manager.transition = RiseInTransition() + state.kivyapp.set_toolbar_for_QrCode() + label = label[:14].capitalize() + '...' if len(label) > 15 else label.capitalize() + addrs = ' (' + addr + ')' + self.manager.parent.ids.toolbar.title = label + addrs + self.manager.parent.ids.sc21.ids.chat_logs.text = '' + self.manager.current = 'chroom' diff --git a/src/bitmessageqt/newaddresswizard.py b/src/bitmessageqt/newaddresswizard.py index 2311239c..2ecae305 100644 --- a/src/bitmessageqt/newaddresswizard.py +++ b/src/bitmessageqt/newaddresswizard.py @@ -234,7 +234,7 @@ class NewAddressWizardWaitPage(QtGui.QWizardPage): self.wizard().button(QtGui.QWizard.NextButton).click() return elif i == 101: - print "haha" + print("haha") return self.progressBar.setValue(i) if i == 50: @@ -347,8 +347,8 @@ if __name__ == '__main__': wizard = Ui_NewAddressWizard(["a", "b", "c", "d"]) if (wizard.exec_()): - print "Email: " + ("yes" if wizard.field("emailAsWell").toBool() else "no") - print "BM: " + ("yes" if wizard.field("onlyBM").toBool() else "no") + print("Email: " + ("yes" if wizard.field("emailAsWell").toBool() else "no")) + print("BM: " + ("yes" if wizard.field("onlyBM").toBool() else "no")) else: - print "Wizard cancelled" + print("Wizard cancelled") sys.exit() diff --git a/src/bmconfigparser.py b/src/bmconfigparser.py index c19db688..3056741d 100644 --- a/src/bmconfigparser.py +++ b/src/bmconfigparser.py @@ -57,9 +57,7 @@ class BMConfigParser(configparser.ConfigParser): return configparser.ConfigParser.set(self, section, option, value) def get(self, section, option, raw=False, vars=None): - # import pdb;pdb.set_trace() # pylint: disable=unused-argument - # import pdb; pdb.set_trace() try: if section == "bitmessagesettings" and option == "timeformat": return configparser.ConfigParser.get( diff --git a/src/buildozer.spec b/src/buildozer.spec index 0dfeb191..3c4c0180 100644 --- a/src/buildozer.spec +++ b/src/buildozer.spec @@ -1,10 +1,10 @@ [app] # (str) Title of your application -title = bitapp +title = py3 # (str) Package name -package.name = bitapp +package.name = py3 # (str) Package domain (needed for android/ios packaging) package.domain = org.test @@ -37,12 +37,13 @@ version = 0.1 # (list) Application requirements # comma separated e.g. requirements = sqlite3,kivy requirements = + python3, openssl, sqlite3, - python2, kivy, - bitmsghash, - kivymd, + bitmsghash, + #git+https://github.com/surbhicis/KivyMD-1.git, + git+https://github.com/surbhicis/KivyMD-1#egg=kivymd, kivy-garden, qrcode, Pillow, @@ -206,7 +207,7 @@ android.arch = armeabi-v7a # # (str) python-for-android git clone directory (if empty, it will be automatically cloned from github) -#p4a.source_dir = +p4a.source_dir = /home/cis/Music/androidp4a/python-for-android # (str) The directory in which python-for-android should look for your own build recipes (if any) p4a.local_recipes = /home/cis/navjotrepo/PyBitmessage/src/bitmessagekivy/android/python-for-android/recipes/ diff --git a/src/class_sqlThread.py b/src/class_sqlThread.py index 6bfdcb25..82bd79b4 100644 --- a/src/class_sqlThread.py +++ b/src/class_sqlThread.py @@ -390,7 +390,24 @@ class sqlThread(threading.Thread): logger.debug( 'In messages.dat database, done adding address field to the pubkeys table' ' and removing the hash field.') - self.cur.execute('''update settings set value=10 WHERE key='version';''') + query = '''update settings set value=? WHERE key='version';''' + parameters = (10,) + self.cur.execute(query, parameters) + + # Add a new table: chat and chatdata for storing chating conversation + item = '''SELECT value FROM settings WHERE key='version';''' + parameters = '' + self.cur.execute(item, parameters) + currentVersion = int(self.cur.fetchall()[0][0]) + if currentVersion == 10: + self.cur.execute( + '''CREATE TABLE chat''' + ''' (msgid blob, senderaddress text, receiveraddress text, message text,''' + ''' receivedtime text, image blob, audio blob, reference blob,''' + ''' UNIQUE(msgid) ON CONFLICT REPLACE)''') + item = '''update settings set value=? WHERE key='version';''' + parameters = (11,) + self.cur.execute(item, parameters) # Are you hoping to add a new option to the keys.dat file of existing # Bitmessage users or modify the SQLite database? Add it right diff --git a/src/depends.py b/src/depends.py index ead33cae..105244ee 100755 --- a/src/depends.py +++ b/src/depends.py @@ -4,6 +4,10 @@ and suggest how it may be installed """ import sys +import logging +import os +import state +from importlib import import_module # Only really old versions of Python don't have sys.hexversion. We don't # support them. The logging module was introduced in Python 2.3 @@ -14,10 +18,6 @@ if not hasattr(sys, 'hexversion') or sys.hexversion < 0x20300F0: % sys.version ) -import logging -import os -from importlib import import_module -import state # We can now use logging so set up a simple configuration formatter = logging.Formatter('%(levelname)s: %(message)s') handler = logging.StreamHandler(sys.stdout) @@ -304,7 +304,10 @@ def check_openssl(): ' OpenSSL 0.9.8b or later with AES, Elliptic Curves (EC),' ' ECDH, and ECDSA enabled.') return False - matches = cflags_regex.findall(openssl_cflags) + if sys.version_info >= (3, 0, 0): + matches = cflags_regex.findall(str(openssl_cflags)) + else: + matches = cflags_regex.findall(openssl_cflags) if matches: logger.error( 'This OpenSSL library is missing the following required' @@ -356,7 +359,8 @@ def check_curses(): # The pythondialog author does not like Python2 str, so we have to use # unicode for just the version otherwise we get the repr form which # includes the module and class names along with the actual version. - logger.info('dialog Utility Version %s', unicode(dialog_util_version)) + # logger.info('dialog Utility Version %s', unicode(dialog_util_version)) + logger.info('dialog Utility Version %s', str(dialog_util_version)) return True diff --git a/src/messagetypes/__init__.py b/src/messagetypes/__init__.py index 54d32794..417fd169 100644 --- a/src/messagetypes/__init__.py +++ b/src/messagetypes/__init__.py @@ -20,7 +20,7 @@ class MsgBase(object): # pylint: disable=too-few-public-methods def constructObject(data): """Constructing an object""" - whitelist = ["message"] + whitelist = ["message", "chatmsg"] if data[""] not in whitelist: return None try: diff --git a/src/messagetypes/chatmsg.py b/src/messagetypes/chatmsg.py new file mode 100644 index 00000000..41109b6d --- /dev/null +++ b/src/messagetypes/chatmsg.py @@ -0,0 +1,34 @@ +import logging + +from messagetypes import MsgBase +# pylint: disable=attribute-defined-outside-init + +logger = logging.getLogger('default') + + +class Chatmsg(MsgBase): + """Encapsulate a chatmsg""" + # pylint: disable=attribute-defined-outside-init + + def decode(self, data): + """Decode a message""" + # UTF-8 and variable type validator + if isinstance(data["message"], str): + # Unicode is depreciated + self.message = data["message"] + else: + # Unicode is depreciated + self.message = str(data["message"]) + + def encode(self, data): + """Encode a message""" + super(Chatmsg, self).__init__() + try: + self.data["message"] = data["message"] + except KeyError as e: + logger.error("Missing key %s", e) + return self.data + + def process(self): + """Process a message""" + logger.debug("Message: %i bytes", len(self.message)) diff --git a/src/namecoin.py b/src/namecoin.py index ae2bde79..c6afdb24 100644 --- a/src/namecoin.py +++ b/src/namecoin.py @@ -174,7 +174,7 @@ class namecoinConnection(object): message = ('failed', tr._translate("MainWindow", 'Couldn\'t understand NMControl.')) else: - print "Unsupported Namecoin type" + print("Unsupported Namecoin type") sys.exit(1) return message diff --git a/src/network/bmproto.py b/src/network/bmproto.py index 066da94c..9530ef8d 100644 --- a/src/network/bmproto.py +++ b/src/network/bmproto.py @@ -542,15 +542,11 @@ class BMProto(AdvancedDispatcher, ObjectTracker): '%(host)s:%(port)i sending version', self.destination._asdict()) if self.services & protocol.NODE_SSL == protocol.NODE_SSL: - # self.isSSL = True - pass + self.isSSL = True if not self.verackReceived: return True - # self.set_state( - # "tls_init" if self.isSSL else "connection_fully_established", - # length=self.payloadLength, expectBytes=0) self.set_state( - "connection_fully_established", + "tls_init" if self.isSSL else "connection_fully_established", length=self.payloadLength, expectBytes=0) return False diff --git a/src/network/http.py b/src/network/http.py index 4a21b63e..9fe85255 100644 --- a/src/network/http.py +++ b/src/network/http.py @@ -19,19 +19,19 @@ class HttpConnection(AdvancedDispatcher): self.destination = (host, 80) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.connect(self.destination) - print "connecting in background to %s:%i" % (self.destination[0], self.destination[1]) + print("connecting in background to %s:%i" % (self.destination[0], self.destination[1])) def state_init(self): self.append_write_buf( "GET %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n" % ( self.path, self.destination[0])) - print "Sending %ib" % (len(self.write_buf)) + print("Sending %ib" % (len(self.write_buf))) self.set_state("http_request_sent", 0) return False def state_http_request_sent(self): if self.read_buf: - print "Received %ib" % (len(self.read_buf)) + print("Received %ib" % (len(self.read_buf))) self.read_buf = b"" if not self.connected: self.set_state("close", 0) @@ -63,13 +63,13 @@ if __name__ == "__main__": for host in ("bootstrap8080.bitmessage.org", "bootstrap8444.bitmessage.org"): proxy = Socks5Resolver(host=host) while asyncore.socket_map: - print "loop %s, len %i" % (proxy.state, len(asyncore.socket_map)) + print("loop %s, len %i" % (proxy.state, len(asyncore.socket_map))) asyncore.loop(timeout=1, count=1) proxy.resolved() proxy = Socks4aResolver(host=host) while asyncore.socket_map: - print "loop %s, len %i" % (proxy.state, len(asyncore.socket_map)) + print("loop %s, len %i" % (proxy.state, len(asyncore.socket_map))) asyncore.loop(timeout=1, count=1) proxy.resolved() diff --git a/src/network/http_old.py b/src/network/http_old.py index c46a5d09..68d8b29b 100644 --- a/src/network/http_old.py +++ b/src/network/http_old.py @@ -49,7 +49,7 @@ if __name__ == "__main__": if len(asyncore.socket_map) < parallel: for i in range(parallel - len(asyncore.socket_map)): HTTPClient('127.0.0.1', '/') - print "Active connections: %i" % (len(asyncore.socket_map)) + print("Active connections: %i" % (len(asyncore.socket_map))) asyncore.loop(count=len(asyncore.socket_map) / 2) if requestCount % 100 == 0: - print "Processed %i total messages" % (requestCount) + print("Processed %i total messages" % (requestCount)) diff --git a/src/network/tls.py b/src/network/tls.py index 5b80f8ef..b2f1847d 100644 --- a/src/network/tls.py +++ b/src/network/tls.py @@ -68,6 +68,7 @@ class TLSDispatcher(AdvancedDispatcher): self.tlsDone = False self.tlsVersion = "N/A" self.isSSL = False + self.sslSocket = None def state_tls_init(self): """Prepare sockets for TLS handshake""" @@ -76,28 +77,6 @@ class TLSDispatcher(AdvancedDispatcher): self.tlsStarted = True # Once the connection has been established, # it's safe to wrap the socket. - if sys.version_info >= (2, 7, 9): - context = ssl.create_default_context( - purpose=ssl.Purpose.SERVER_AUTH - if self.server_side else ssl.Purpose.CLIENT_AUTH) - context.set_ciphers(self.ciphers) - context.set_ecdh_curve("secp256k1") - context.check_hostname = False - context.verify_mode = ssl.CERT_NONE - # also exclude TLSv1 and TLSv1.1 in the future - context.options = ssl.OP_ALL | ssl.OP_NO_SSLv2 |\ - ssl.OP_NO_SSLv3 | ssl.OP_SINGLE_ECDH_USE |\ - ssl.OP_CIPHER_SERVER_PREFERENCE - self.sslSocket = context.wrap_socket( - self.socket, server_side=self.server_side, - do_handshake_on_connect=False) - else: - self.sslSocket = ssl.wrap_socket( - self.socket, server_side=self.server_side, - ssl_version=sslProtocolVersion, - certfile=self.certfile, keyfile=self.keyfile, - ciphers=self.ciphers, do_handshake_on_connect=False) - self.sslSocket.setblocking(0) self.want_read = self.want_write = True self.set_state("tls_handshake") return False @@ -127,7 +106,6 @@ class TLSDispatcher(AdvancedDispatcher): # during TLS handshake, and after flushing write buffer, # return status of last handshake attempt if self.tlsStarted and not self.tlsDone and not self.write_buf: - # print "tls readable, %r" % (self.want_read) return self.want_read # prior to TLS handshake, # receiveDataThread should emulate synchronous behaviour @@ -145,7 +123,6 @@ class TLSDispatcher(AdvancedDispatcher): and normal reads must be ignored. """ try: - # wait for write buffer flush if self.tlsStarted and not self.tlsDone and not self.write_buf: # logger.debug( # "%s:%i TLS handshaking (read)", self.destination.host, @@ -182,9 +159,6 @@ class TLSDispatcher(AdvancedDispatcher): # self.destination.port) self.tls_handshake() else: - # logger.debug( - # "%s:%i Not TLS handshaking (write)", self.destination.host, - # self.destination.port) return AdvancedDispatcher.handle_write(self) except AttributeError: return AdvancedDispatcher.handle_write(self) @@ -198,11 +172,37 @@ class TLSDispatcher(AdvancedDispatcher): self.handle_close() return - def tls_handshake(self): + def tls_handshake(self): # pylint:disable=too-many-branches """Perform TLS handshake and handle its stages""" # wait for flush + # self.sslSocket.setblocking(0) if self.write_buf: return False + if not self.sslSocket: + self.del_channel() + if sys.version_info >= (2, 7, 9): + context = ssl.create_default_context( + purpose=ssl.Purpose.SERVER_AUTH + if self.server_side else ssl.Purpose.CLIENT_AUTH) + context.set_ciphers(self.ciphers) + context.set_ecdh_curve("secp256k1") + context.check_hostname = False + context.verify_mode = ssl.CERT_NONE + # also exclude TLSv1 and TLSv1.1 in the future + context.options = ssl.OP_ALL | ssl.OP_NO_SSLv2 |\ + ssl.OP_NO_SSLv3 | ssl.OP_SINGLE_ECDH_USE |\ + ssl.OP_CIPHER_SERVER_PREFERENCE + self.sslSocket = context.wrap_socket( + self.socket, server_side=self.server_side, + do_handshake_on_connect=False) + else: + self.sslSocket = ssl.wrap_socket( + self.socket, server_side=self.server_side, + ssl_version=sslProtocolVersion, + certfile=self.certfile, keyfile=self.keyfile, + ciphers=self.ciphers, do_handshake_on_connect=False) + self.sslSocket.setblocking(0) + self.set_socket(self.sslSocket) # Perform the handshake. try: self.sslSocket.do_handshake() @@ -233,8 +233,6 @@ class TLSDispatcher(AdvancedDispatcher): '%s:%i: TLS handshake success', self.destination.host, self.destination.port) # The handshake has completed, so remove this channel and... - self.del_channel() - self.set_socket(self.sslSocket) self.tlsDone = True self.bm_proto_reset() diff --git a/src/protocol.py b/src/protocol.py index 53223b3c..a9886819 100644 --- a/src/protocol.py +++ b/src/protocol.py @@ -231,7 +231,6 @@ def haveSSL(server=False): python < 2.7.9's ssl library does not support ECDSA server due to missing initialisation of available curves, but client works ok """ - return False if not server: return True elif sys.version_info >= (2, 7, 9): diff --git a/src/pyelliptic/openssl.py b/src/pyelliptic/openssl.py index 20d2100f..68364504 100644 --- a/src/pyelliptic/openssl.py +++ b/src/pyelliptic/openssl.py @@ -82,7 +82,7 @@ class _OpenSSL(object): """Build the wrapper""" self._lib = ctypes.CDLL(library) self._version, self._hexversion, self._cflags = get_version(self._lib) - self._libreSSL = (self._version).decode("utf-8").startswith("OpenSSL") + self._libreSSL = (self._version).decode("utf-8").startswith("LibreSSL") self.pointer = ctypes.pointer self.c_int = ctypes.c_int diff --git a/src/tests/test_chatmsg.py b/src/tests/test_chatmsg.py new file mode 100644 index 00000000..06542f4e --- /dev/null +++ b/src/tests/test_chatmsg.py @@ -0,0 +1,22 @@ +""" +Test for chatmsg group +""" +import unittest +from messagetypes.chatmsg import Chatmsg + + +class TestCharMessage(unittest.TestCase): + """ + Test case for chat message group + """ + def test_decode(self): + """Test various types of decode method""" + import messagetypes + result = messagetypes.constructObject({'': 'chatmsg', 'message': 'hello world'}) + self.assertTrue(isinstance(result.message, str)) + + def test_encode(self): + """Test various types of encode method""" + chat_obj = Chatmsg() + result = chat_obj.encode({'message': 'hello world'}) + self.assertTrue(True if result['message'] else False)