diff --git a/src/bitmessagekivy/identiconGeneration.py b/src/bitmessagekivy/identiconGeneration.py index a5dcf3d0..ca8bd3bd 100644 --- a/src/bitmessagekivy/identiconGeneration.py +++ b/src/bitmessagekivy/identiconGeneration.py @@ -1,16 +1,15 @@ """ -src/identiconGeneration.py -================================= +Core classes for loading images and converting them to a Texture. +The raw image data can be keep in memory for further access """ -# pylint: disable=import-error + import hashlib from io import BytesIO from PIL import Image from kivy.core.image import Image as CoreImage from kivy.uix.image import Image as kiImage -""" Core classes for loading images and converting them to a Texture. -The raw image data can be keep in memory for further access """ +# pylint: disable=import-error # constants diff --git a/src/bitmessagekivy/kivy_helper_search.py b/src/bitmessagekivy/kivy_helper_search.py index a1fe4a99..085e2aa2 100644 --- a/src/bitmessagekivy/kivy_helper_search.py +++ b/src/bitmessagekivy/kivy_helper_search.py @@ -1,11 +1,12 @@ """ -src/bitmessagekivy/kivy_helper_search.py -================================= +Sql queries for bitmessagekivy """ from helper_sql import sqlQuery -def search_sql(xAddress="toaddress", account=None, folder="inbox", where=None, what=None, unreadOnly=False): +def search_sql( + xAddress="toaddress", account=None, folder="inbox", where=None, + what=None, unreadOnly=False, start_indx=0, end_indx=20): """Method helping for searching mails""" # pylint: disable=too-many-arguments, too-many-branches if what is not None and what != "": @@ -14,14 +15,15 @@ def search_sql(xAddress="toaddress", account=None, folder="inbox", where=None, w what = None if folder == "sent" or folder == "draft": - sqlStatementBase = ''' - SELECT toaddress, fromaddress, subject, message, status, ackdata, lastactiontime - FROM sent ''' + sqlStatementBase = ( + '''SELECT toaddress, fromaddress, subject, message, status,''' + ''' ackdata, lastactiontime FROM sent ''') elif folder == "addressbook": sqlStatementBase = '''SELECT label, address From addressbook ''' else: - sqlStatementBase = '''SELECT folder, msgid, toaddress, message, fromaddress, subject, received, read - FROM inbox ''' + sqlStatementBase = ( + '''SELECT folder, msgid, toaddress, message, fromaddress,''' + ''' subject, received, read FROM inbox ''') sqlStatementParts = [] sqlArguments = [] @@ -58,8 +60,14 @@ def search_sql(xAddress="toaddress", account=None, folder="inbox", where=None, w sqlStatementParts.append("read = 0") if sqlStatementParts: sqlStatementBase += "WHERE " + " AND ".join(sqlStatementParts) - if folder == "sent": - sqlStatementBase += " ORDER BY lastactiontime DESC" + if folder == "sent" or folder == "draft": + sqlStatementBase += \ + " ORDER BY lastactiontime DESC limit {0}, {1}".format( + start_indx, end_indx) elif folder == "inbox": - sqlStatementBase += " ORDER BY received DESC" + sqlStatementBase += \ + " ORDER BY received DESC limit {0}, {1}".format( + start_indx, end_indx) + # elif folder == "addressbook": + # sqlStatementBase += " limit {0}, {1}".format(start_indx, end_indx) return sqlQuery(sqlStatementBase, sqlArguments) diff --git a/src/bitmessagekivy/main.kv b/src/bitmessagekivy/main.kv index 759bd71c..c4352cfe 100644 --- a/src/bitmessagekivy/main.kv +++ b/src/bitmessagekivy/main.kv @@ -14,6 +14,8 @@ #:import MDFloatingActionButton kivymd.button.MDFloatingActionButton #:import Factory kivy.factory.Factory #:import MDScrollViewRefreshLayout kivymd.refreshlayout.MDScrollViewRefreshLayout +#:import MDSpinner kivymd.spinner.MDSpinner +#:import NoTransition kivy.uix.screenmanager.NoTransition #:set color_button (0.784, 0.443, 0.216, 1) # brown #:set color_button_pressed (0.659, 0.522, 0.431, 1) # darker brown @@ -29,7 +31,7 @@ color: color_font : - drawer_logo: app.address_identicon() + drawer_logo: './images/drawer_logo1.png' NavigationDrawerDivider: NavigationDrawerSubheader: text: "Accounts" @@ -57,52 +59,47 @@ text: "Inbox" on_release: app.root.ids.scr_mngr.current = 'inbox' badge_text: "0" - on_press: app.refreshScreen(self) + on_press: app.load_screen(self) NavigationDrawerIconButton: id: send_cnt icon: 'send' text: "Sent" on_release: app.root.ids.scr_mngr.current = 'sent' badge_text: "0" - on_press: app.refreshScreen(self) NavigationDrawerIconButton: id: draft_cnt icon: 'message-draw' text: "Draft" on_release: app.root.ids.scr_mngr.current = 'draft' badge_text: "0" - on_press: app.refreshScreen(self) - NavigationDrawerIconButton: - text: "Starred" - icon:'star' - on_release: app.root.ids.scr_mngr.current = 'starred' - on_press: app.refreshScreen(self) - NavigationDrawerIconButton: - icon: 'archive' - text: "Archieve" - on_release: app.root.ids.scr_mngr.current = 'archieve' - badge_text: "0" - on_press: app.refreshScreen(self) - NavigationDrawerIconButton: - icon: 'email-open-outline' - text: "Spam" - on_release: app.root.ids.scr_mngr.current = 'spam' - badge_text: "0" - on_press: app.refreshScreen(self) + #NavigationDrawerIconButton: + #text: "Starred" + #icon:'star' + #on_release: app.root.ids.scr_mngr.current = 'starred' + #badge_text: "0" + #NavigationDrawerIconButton: + #icon: 'archive' + #text: "Archieve" + #on_release: app.root.ids.scr_mngr.current = 'archieve' + #badge_text: "0" + #NavigationDrawerIconButton: + #icon: 'email-open-outline' + #text: "Spam" + #on_release: app.root.ids.scr_mngr.current = 'spam' + #badge_text: "0" NavigationDrawerIconButton: id: trash_cnt icon: 'delete' text: "Trash" on_release: app.root.ids.scr_mngr.current = 'trash' badge_text: "0" - on_press: app.refreshScreen(self) NavigationDrawerIconButton: id: allmail_cnt text: "All Mails" icon:'contact-mail' on_release: app.root.ids.scr_mngr.current = 'allmails' badge_text: "0" - on_press: app.refreshScreen(self) + on_press: app.load_screen(self) NavigationDrawerDivider: NavigationDrawerSubheader: text: "All labels" @@ -110,37 +107,30 @@ text: "Address Book" icon:'book-multiple' on_release: app.root.ids.scr_mngr.current = 'addressbook' - on_press: app.refreshScreen(self) NavigationDrawerIconButton: text: "Settings" icon:'settings' on_release: app.root.ids.scr_mngr.current = 'set' - on_press: app.refreshScreen(self) NavigationDrawerIconButton: text: "Subscriptions/Payment" icon:'bell' on_release: app.root.ids.scr_mngr.current = 'payment' - on_press: app.refreshScreen(self) NavigationDrawerIconButton: text: "Credits" icon:'wallet' on_release: app.root.ids.scr_mngr.current = 'credits' - on_press: app.refreshScreen(self) NavigationDrawerIconButton: text: "new address" icon:'account-plus' on_release: app.root.ids.scr_mngr.current = 'login' - on_press: app.refreshScreen(self) NavigationDrawerIconButton: text: "Network Status" icon:'server-network' on_release: app.root.ids.scr_mngr.current = 'networkstat' - on_press: app.refreshScreen(self) NavigationDrawerIconButton: text: "My Addresses" icon:'account-multiple' on_release: app.root.ids.scr_mngr.current = 'myaddress' - on_press: app.refreshScreen(self) NavigationLayout: id: nav_layout @@ -148,78 +138,87 @@ NavigationLayout: ContentNavigationDrawer: id: nav_drawer - BoxLayout: - id: box_layout - orientation: 'vertical' - Toolbar: - id: toolbar - title: app.current_address_label() - opacity: 1 if app.addressexist() else 0 - disabled: False if app.addressexist() else True - md_bg_color: app.theme_cls.primary_color - background_palette: 'Primary' - background_hue: '500' - left_action_items: [['menu', lambda x: app.root.toggle_nav_drawer()]] - right_action_items: [['account-plus', lambda x: app.addingtoaddressbook()]] + FloatLayout: + id: float_box + BoxLayout: + id: box_layout + orientation: 'vertical' + Toolbar: + id: toolbar + title: app.current_address_label() + opacity: 1 if app.addressexist() else 0 + disabled: False if app.addressexist() else True + md_bg_color: app.theme_cls.primary_color + background_palette: 'Primary' + background_hue: '500' + left_action_items: [['menu', lambda x: app.root.toggle_nav_drawer()]] + right_action_items: [['account-plus', lambda x: app.addingtoaddressbook()]] - ScreenManager: - id: scr_mngr - Inbox: - id:sc1 - Page: - id:sc2 - Create: - id:sc3 - Sent: - id:sc4 - Trash: - id:sc5 - Login: - id:sc6 - Random: - id:sc7 - AddressSuccessful: - id:sc8 - Setting: - id:sc9 - MyAddress: - id:sc10 - AddressBook: - id:sc11 - Payment: - id:sc12 - NetworkStat: - id:sc13 - MailDetail: - id:sc14 - ShowQRCode: - id:sc15 - Draft: - id:sc16 - Allmails: - id:sc17 - Credits: - id:sc18 - Starred: - id:sc19 - Archieve: - id:sc20 - Spam: - id:sc21 + ScreenManager: + id: scr_mngr + Inbox: + id:sc1 + Page: + id:sc2 + Create: + id:sc3 + Sent: + id:sc4 + Trash: + id:sc5 + Login: + id:sc6 + Random: + id:sc7 + Spam: + id:sc8 + Setting: + id:sc9 + MyAddress: + id:sc10 + AddressBook: + id:sc11 + Payment: + id:sc12 + NetworkStat: + id:sc13 + MailDetail: + id:sc14 + ShowQRCode: + id:sc15 + Draft: + id:sc16 + Allmails: + id:sc17 + Credits: + id:sc18 + Starred: + id:sc19 + Archieve: + id:sc20 : name: 'inbox' + transition: NoTransition() BoxLayout: orientation: 'vertical' spacing: dp(10) SearchBar: - FloatLayout: - MDScrollViewRefreshLayout: - id: refresh_layout - refresh_callback: root.refresh_callback - root_layout: root + #FloatLayout: + # MDScrollViewRefreshLayout: + # id: refresh_layout + # refresh_callback: root.refresh_callback + # root_layout: root.set_root_layout() + # MDList: + # id: ml + BoxLayout: + orientation:'vertical' + ScrollView: + id: scroll_y + do_scroll_x: False MDList: id: ml + Loader: ComposerButton: : @@ -230,22 +229,27 @@ NavigationLayout: BoxLayout: orientation:'vertical' ScrollView: + id: scroll_y do_scroll_x: False MDList: id: ml + Loader: ComposerButton: : name: 'trash' ScrollView: + id: scroll_y do_scroll_x: False MDList: id: ml + Loader: ComposerButton: : name: 'draft' ScrollView: + id: scroll_y do_scroll_x: False MDList: id: ml @@ -277,13 +281,21 @@ NavigationLayout: : name: 'allmails' - FloatLayout: - MDScrollViewRefreshLayout: - id: refresh_layout - refresh_callback: root.refresh_callback - root_layout: root + #FloatLayout: + # MDScrollViewRefreshLayout: + # id: refresh_layout + # refresh_callback: root.refresh_callback + # root_layout: root.set_root_layout() + # MDList: + # id: ml + BoxLayout: + orientation:'vertical' + ScrollView: + id: scroll_y + do_scroll_x: False MDList: id: ml + Loader: ComposerButton: : @@ -300,6 +312,7 @@ NavigationLayout: : name: 'create' + Loader: : name: 'credits' @@ -369,7 +382,8 @@ NavigationLayout: size_hint_y: None font_size: '13sp' height: self.parent.height/2 - hint_text: 'type or search recipients address starting with BM-' + #hint_text: 'type or search recipients address starting with BM-' + hint_text: 'type, select or scan QR code for recipients address' RV: id: rv MDTextField: @@ -484,6 +498,7 @@ NavigationLayout: size_hint: .5, .35 height: dp(40) on_press: app.root.ids.scr_mngr.current = 'random' + on_press: app.root.ids.sc7.reset_address_label() MDLabel: font_style: 'Title' text: 'proceed' @@ -522,6 +537,7 @@ NavigationLayout: hint_text: "Label" required: True helper_text_mode: "on_error" + on_text: root.add_validation(self) BoxLayout: AnchorLayout: MDRaisedButton: @@ -536,12 +552,6 @@ NavigationLayout: color: (1,1,1,1) halign: 'center' -: - name: 'add_sucess' - Label: - text: 'Successfully created a new bit address' - color: 0,0,0,1 - : name: 'set' ScrollView: @@ -622,9 +632,10 @@ NavigationLayout: MDScrollViewRefreshLayout: id: refresh_layout refresh_callback: root.refresh_callback - root_layout: root + root_layout: root.set_root_layout() MDList: id: ml + Loader: ComposerButton: : @@ -635,9 +646,11 @@ NavigationLayout: BoxLayout: orientation:'vertical' ScrollView: + id: scroll_y do_scroll_x: False MDList: id: ml + Loader: ComposerButton: : @@ -646,7 +659,7 @@ NavigationLayout: do_scroll_x: False BoxLayout: orientation: 'vertical' - padding: [dp(app.window_size[0]/16 if app.window_size[0] <= 720 else app.window_size[0]/4*1.1), dp(10)] + padding: [dp(app.window_size[0]/16 if app.window_size[0] <= 720 else app.window_size[0]/6 if app.window_size[0] <= 800 else app.window_size[0]/18), dp(10)] spacing: 12 size_hint_y: None height: self.minimum_height + dp(app.window_size[1]) if app.window_size[1] > app.window_size[0] else dp(app.window_size[0]) @@ -810,6 +823,7 @@ NavigationLayout: hint_text: "Label" required: True helper_text_mode: "on_error" + on_text: root.checkLabel_valid(self) MDTextField: id: address hint_text: "Address" @@ -987,6 +1001,7 @@ NavigationLayout: orientation: 'vertical' size_hint_y: None height: dp(100) + self.minimum_height + Loader: : id: cpyButton @@ -1129,6 +1144,7 @@ NavigationLayout: theme_text_color: 'Primary' required: True helper_text_mode: "on_error" + on_text: root.checkLabel_valid(self) MDLabel: font_style: 'Title' theme_text_color: 'Primary' @@ -1136,6 +1152,7 @@ NavigationLayout: font_size: '17sp' halign: 'left' MDLabel: + id: address font_style: 'Subhead' theme_text_color: 'Primary' text: root.address @@ -1204,3 +1221,25 @@ NavigationLayout: id: search_field hint_text: 'Search' on_text: app.searchQuery(self) + + +: + separator_color: 1, 1, 1, 1 + background: "White.png" + Button: + id: btn + disabled: True + background_disabled_normal: "White.png" + Image: + source: './images/loader.zip' + anim_delay: 0 + #mipmap: True + size: root.size + + +: + id: spinner + size_hint: None, None + size: dp(46), dp(46) + pos_hint: {'center_x': 0.5, 'center_y': 0.5} + active: False \ No newline at end of file diff --git a/src/bitmessagekivy/mpybit.py b/src/bitmessagekivy/mpybit.py index 7270514b..cdb55a18 100644 --- a/src/bitmessagekivy/mpybit.py +++ b/src/bitmessagekivy/mpybit.py @@ -1,12 +1,12 @@ """ -src/bitmessagekivy/mpybit.py -================================= +Bitmessage android(mobile) interface """ -# pylint: disable=relative-import, unused-variable, import-error, no-name-in-module, too-many-lines +# pylint: disable=relative-import, import-error, no-name-in-module +# pylint: disable=too-few-public-methods, too-many-lines, unused-argument import os import time -from functools import partial from bmconfigparser import BMConfigParser +from functools import partial from helper_sql import sqlExecute, sqlQuery from kivy.app import App from kivy.clock import Clock @@ -36,6 +36,7 @@ from kivy.uix.screenmanager import Screen from kivy.uix.spinner import Spinner from kivy.uix.textinput import TextInput from kivy.utils import platform + import kivy_helper_search from kivymd.button import MDIconButton from kivymd.dialog import MDDialog @@ -53,17 +54,19 @@ from kivymd.navigationdrawer import ( ) from kivymd.selectioncontrols import MDCheckbox from kivymd.theming import ThemeManager + import queues from semaphores import kivyuisignaler + import state from uikivysignaler import UIkivySignaler import identiconGeneration -# pylint: disable=unused-argument, too-few-public-methods +from addresses import addBMIfNotPresent, decodeAddress def toast(text): - """Method will display the toast message.""" + """Function displays toast message""" # pylint: disable=redefined-outer-name from kivymd.toast.kivytoast import toast toast(text) @@ -71,8 +74,7 @@ def toast(text): class Navigatorss(MDNavigationDrawer): - """Navigators class contains image, title and logo.""" - + """Navigator class (image, title and logo)""" image_source = StringProperty('images/qidenticon_two.png') title = StringProperty('Navigation') drawer_logo = StringProperty() @@ -80,80 +82,54 @@ class Navigatorss(MDNavigationDrawer): class Inbox(Screen): """Inbox Screen uses screen to show widgets of screens.""" + queryreturn = ListProperty() + has_refreshed = True + account = StringProperty() def __init__(self, *args, **kwargs): """Method Parsing the address.""" super(Inbox, self).__init__(*args, **kwargs) + Clock.schedule_once(self.init_ui, 0) + + @staticmethod + def set_defaultAddress(): + """This method set default address""" if state.association == '': if BMConfigParser().addresses(): state.association = BMConfigParser().addresses()[0] - Clock.schedule_once(self.init_ui, 0) def init_ui(self, dt=0): - """Clock Schdule for method inbox accounts.""" - self.inboxaccounts() - print dt + """Clock schdule for method inbox accounts.""" + self.loadMessagelist() - def inboxaccounts(self): - """Load inbox accounts.""" - account = state.association - self.loadMessagelist(account, 'All', '') - - def loadMessagelist(self, account, where="", what=""): + def loadMessagelist(self, where="", what=""): """Load Inbox list for Inbox messages.""" # pylint: disable=too-many-locals + self.set_defaultAddress() + self.account = state.association if state.searcing_text: + self.children[2].children[0].children[0].scroll_y = 1.0 where = ['subject', 'message'] what = state.searcing_text xAddress = 'toaddress' data = [] - queryreturn = kivy_helper_search.search_sql( - xAddress, account, "inbox", where, what, False) - if queryreturn: + self.inboxDataQuery(xAddress, where, what) + if self.queryreturn: + state.kivyapp.get_inbox_count() src_mng_obj = state.kivyapp.root.children[2].children[0].ids - src_mng_obj.inbox_cnt.badge_text = str(len(queryreturn)) - state.inbox_count = str(len(queryreturn)) - state.kivyapp.root.ids.sc17.clear_widgets() - state.kivyapp.root.ids.sc17.add_widget(Allmails()) - for mail in queryreturn: - third_text = mail[3].replace('\n', ' ') + src_mng_obj.inbox_cnt.badge_text = state.inbox_count + for mail in self.queryreturn: + # third_text = mail[3].replace('\n', ' ') data.append({ 'text': mail[4].strip(), 'secondary_text': mail[5][:50] + '........' if len( - mail[5]) >= 50 else ( - mail[5] + ',' + mail[3].replace('\n', ''))[0:50] + '........', + mail[5]) >= 50 else (mail[5] + ',' + mail[3].replace( + '\n', ''))[0:50] + '........', 'msgid': mail[1]}) - for item in data: - meny = TwoLineAvatarIconListItem( - text=item['text'], - secondary_text=item['secondary_text'], - theme_text_color='Custom', - text_color=NavigateApp().theme_cls.primary_color) - meny.add_widget(AvatarSampleWidget( - source='./images/text_images/{}.png'.format( - avatarImageFirstLetter(item['secondary_text'].strip())))) - meny.bind(on_press=partial( - self.inbox_detail, item['msgid'])) - 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='Delete') - del_btn.background_normal = '' - del_btn.background_color = (1, 0, 0, 1) - del_btn.bind(on_press=partial( - self.delete, item['msgid'])) - carousel.add_widget(del_btn) - carousel.add_widget(meny) - ach_btn = Button(text='Achieve') - ach_btn.background_color = (0, 1, 0, 1) - ach_btn.bind(on_press=partial( - self.archive, item['msgid'])) - carousel.add_widget(ach_btn) - carousel.index = 1 - self.ids.ml.add_widget(carousel) + self.has_refreshed = True + self.set_mdList(data) + self.children[2].children[0].children[0].bind( + scroll_y=self.check_scroll_y) else: content = MDLabel( font_style='Body1', @@ -166,8 +142,90 @@ class Inbox(Screen): valign='top') self.ids.ml.add_widget(content) + # pylint: disable=too-many-arguments + def inboxDataQuery(self, xAddress, where, what, start_indx=0, end_indx=20): + """This method used for retrieving inbox data""" + self.queryreturn = kivy_helper_search.search_sql( + xAddress, + self.account, + "inbox", + where, + what, + False, + start_indx, + end_indx) + + def set_mdList(self, data): + """This method is used to create the mdList""" + total_message = len(self.ids.ml.children) + for item in data: + meny = TwoLineAvatarIconListItem( + text=item['text'], + secondary_text=item['secondary_text'], + theme_text_color='Custom', + text_color=NavigateApp().theme_cls.primary_color) + meny.add_widget( + AvatarSampleWidget( + source='./images/text_images/{}.png'.format( + avatarImageFirstLetter( + item['secondary_text'].strip())))) + meny.bind( + on_press=partial( + self.inbox_detail, item['msgid'])) + 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='Delete') + del_btn.background_normal = '' + del_btn.background_color = (1, 0, 0, 1) + del_btn.bind( + on_press=partial( + self.delete, item['msgid'])) + carousel.add_widget(del_btn) + carousel.add_widget(meny) + ach_btn = Button(text='Achieve') + ach_btn.background_color = (0, 1, 0, 1) + ach_btn.bind( + on_press=partial( + self.archive, item['msgid'])) + carousel.add_widget(ach_btn) + carousel.index = 1 + self.ids.ml.add_widget(carousel) + update_message = len(self.ids.ml.children) + self.has_refreshed = True if total_message != update_message else False + + def check_scroll_y(self, instance, somethingelse): + """This method is used to load data on scroll""" + if self.children[2].children[0].children[ + 0].scroll_y <= -0.0 and self.has_refreshed: + self.children[2].children[0].children[0].scroll_y = 0.06 + total_message = len(self.ids.ml.children) + self.update_inbox_screen_on_scroll(total_message) + else: + pass + + def update_inbox_screen_on_scroll(self, total_message, where="", what=""): + """This method is used to load more data on scroll down""" + data = [] + if state.searcing_text: + where = ['subject', 'message'] + what = state.searcing_text + self.inboxDataQuery('toaddress', where, what, total_message, 5) + for mail in self.queryreturn: + # third_text = mail[3].replace('\n', ' ') + data.append({ + 'text': mail[4].strip(), + 'secondary_text': mail[5][:50] + '........' if len( + mail[5]) >= 50 else (mail[5] + ',' + mail[3].replace( + '\n', ''))[0:50] + '........', + 'msgid': mail[1]}) + self.set_mdList(data) + def inbox_detail(self, msg_id, *args): - """Load inbox page details.""" + """Load inbox page details""" state.detailPageType = 'inbox' state.mail_id = msg_id if self.manager: @@ -179,14 +237,17 @@ class Inbox(Screen): src_mng_obj.current = 'mailDetail' def delete(self, data_index, instance, *args): - """Delete inbox mail from inbox listing.""" + """Delete inbox mail from inbox listing""" sqlExecute( "UPDATE inbox SET folder = 'trash' WHERE msgid = ?;", str( data_index)) try: - msg_count_objs = self.parent.parent.parent.parent.children[2].children[0].ids + msg_count_objs = ( + self.parent.parent.parent.parent.children[2].children[0].ids) except Exception: - msg_count_objs = self.parent.parent.parent.parent.parent.children[2].children[0].ids + msg_count_objs = ( + self.parent.parent.parent.parent.parent.children[ + 2].children[0].ids) if int(state.inbox_count) > 0: msg_count_objs.inbox_cnt.badge_text = str( int(state.inbox_count) - 1) @@ -206,7 +267,7 @@ class Inbox(Screen): self.update_trash() def archive(self, data_index, instance, *args): - """Archive inbox mail from inbox listing.""" + """Archive inbox mail from inbox listing""" sqlExecute( "UPDATE inbox SET folder = 'trash' WHERE msgid = ?;", str( data_index)) @@ -214,7 +275,7 @@ class Inbox(Screen): self.update_trash() def update_trash(self): - """Update trash screen mails which is deleted from inbox.""" + """Update trash screen mails which is deleted from inbox""" try: self.parent.screens[4].clear_widgets() self.parent.screens[4].add_widget(Trash()) @@ -224,53 +285,51 @@ class Inbox(Screen): # pylint: disable=attribute-defined-outside-init def refresh_callback(self, *args): - """Method updates the state of application, While the spinner remains on the screen.""" + """Method updates the state of application, + While the spinner remains on the screen""" def refresh_callback(interval): - """Method used for loading the inbox screen data.""" + """Method used for loading the inbox screen data""" state.searcing_text = '' self.children[2].children[1].ids.search_field.text = '' self.ids.ml.clear_widgets() self.loadMessagelist(state.association) + self.has_refreshed = True self.ids.refresh_layout.refresh_done() self.tick = 0 Clock.schedule_once(refresh_callback, 1) + # def set_root_layout(self): + # """Setting root layout""" + # return self.parent.parent.parent + class MyAddress(Screen): - """MyAddress Screen uses screen to show widgets of screens.""" + """MyAddress screen uses screen to show widgets of screens.""" + addresses_list = ListProperty() + has_refreshed = True + is_add_created = False def __init__(self, *args, **kwargs): - """Clock Schdule for method inbox accounts.""" + """Clock schdule for method Myaddress accounts.""" super(MyAddress, self).__init__(*args, **kwargs) Clock.schedule_once(self.init_ui, 0) def init_ui(self, dt=0): - """Clock Schdule for method inbox accounts.""" + """Clock schdule for method Myaddress accounts""" # pylint: disable=unnecessary-lambda, deprecated-lambda - addresses_list = state.kivyapp.variable_1 + self.addresses_list = state.kivyapp.variable_1 if state.searcing_text: + self.ids.refresh_layout.scroll_y = 1.0 filtered_list = filter( lambda addr: self.filter_address( addr), BMConfigParser().addresses()) - addresses_list = filtered_list - if addresses_list: - data = [] - for address in addresses_list: - data.append({ - 'text': BMConfigParser().get(address, 'label'), - 'secondary_text': address}) - for item in data: - meny = TwoLineAvatarIconListItem( - text=item['text'], - secondary_text=item['secondary_text'], - theme_text_color='Custom', - text_color=NavigateApp().theme_cls.primary_color) - meny.add_widget(AvatarSampleWidget( - source='./images/text_images/{}.png'.format(avatarImageFirstLetter(item['text'].strip())))) - meny.bind(on_press=partial( - self.myadd_detail, item['secondary_text'], item['text'])) - self.ids.ml.add_widget(meny) + self.addresses_list = filtered_list + self.addresses_list = [obj for obj in reversed(self.addresses_list)] + if self.addresses_list: + self.has_refreshed = True + self.set_mdList(0, 15) + self.ids.refresh_layout.bind(scroll_y=self.check_scroll_y) else: content = MDLabel( font_style='Body1', @@ -282,26 +341,65 @@ class MyAddress(Screen): size_hint_y=None, valign='top') self.ids.ml.add_widget(content) - if not state.searcing_text: + if not state.searcing_text and not self.is_add_created: try: self.manager.current = 'login' except Exception: pass + def set_mdList(self, first_index, last_index): + """Creating the mdlist""" + data = [] + for address in self.addresses_list[first_index:last_index]: + data.append({ + 'text': BMConfigParser().get(address, 'label'), + 'secondary_text': address}) + for item in data: + meny = TwoLineAvatarIconListItem( + text=item['text'], + secondary_text=item['secondary_text'], + theme_text_color='Custom', + text_color=NavigateApp().theme_cls.primary_color) + meny.add_widget(AvatarSampleWidget( + source='./images/text_images/{}.png'.format( + avatarImageFirstLetter(item['text'].strip())))) + meny.bind(on_press=partial( + self.myadd_detail, item['secondary_text'], item['text'])) + self.ids.ml.add_widget(meny) + + def check_scroll_y(self, instance, somethingelse): + """Load data on scroll down""" + if self.ids.refresh_layout.scroll_y <= -0.0 and self.has_refreshed: + self.ids.refresh_layout.scroll_y = 0.06 + my_addresses = len(self.ids.ml.children) + if my_addresses != len(self.addresses_list): + self.update_addressBook_on_scroll(my_addresses) + self.has_refreshed = True if my_addresses != len( + self.addresses_list) else False + else: + pass + + def update_addressBook_on_scroll(self, my_addresses): + """Loads more data on scroll down""" + self.set_mdList(my_addresses, my_addresses + 20) + @staticmethod def myadd_detail(fromaddress, label, *args): - """Myaddress Details.""" + """Load myaddresses details""" p = MyaddDetailPopup() p.open() p.set_address(fromaddress, label) # pylint: disable=attribute-defined-outside-init def refresh_callback(self, *args): - """Method updates the state of application, While the spinner remains on the screen.""" + """Method updates the state of application, + While the spinner remains on the screen""" def refresh_callback(interval): - """Method used for loading the myaddress screen data.""" + """Method used for loading the myaddress screen data""" state.searcing_text = '' + state.kivyapp.root.ids.sc10.children[2].active = False self.children[2].children[1].ids.search_field.text = '' + self.has_refreshed = True self.ids.ml.clear_widgets() self.init_ui() self.ids.refresh_layout.refresh_done() @@ -310,7 +408,7 @@ class MyAddress(Screen): @staticmethod def filter_address(address): - """Method will filter the my address list data.""" + """Method will filter the my address list data""" # pylint: disable=deprecated-lambda if filter(lambda x: (state.searcing_text).lower() in x, [ BMConfigParser().get( @@ -318,53 +416,40 @@ class MyAddress(Screen): return True return False + def set_root_layout(self): + """Setting root layout""" + return self.manager.parent.parent + class AddressBook(Screen): - """AddressBook Screen uses screen to show widgets of screens.""" + """AddressBook Screen uses screen to show widgets of screens""" + queryreturn = ListProperty() + has_refreshed = True def __init__(self, *args, **kwargs): - """Getting AddressBook Details.""" + """Getting AddressBook Details""" super(AddressBook, self).__init__(*args, **kwargs) Clock.schedule_once(self.init_ui, 0) def init_ui(self, dt=0): - """Clock Schdule for method AddressBook.""" + """Clock Schdule for method AddressBook""" self.loadAddresslist(None, 'All', '') print dt def loadAddresslist(self, account, where="", what=""): - """Clock Schdule for method AddressBook.""" + """Clock Schdule for method AddressBook""" if state.searcing_text: + self.ids.scroll_y.scroll_y = 1.0 where = ['label', 'address'] what = state.searcing_text xAddress = '' - queryreturn = kivy_helper_search.search_sql( + self.queryreturn = kivy_helper_search.search_sql( xAddress, account, "addressbook", where, what, False) - if queryreturn: - for item in 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_press=partial( - self.addBook_detail, item[1], item[0])) - 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='Delete') - del_btn.background_normal = '' - del_btn.background_color = (1, 0, 0, 1) - del_btn.bind(on_press=partial(self.delete_address, item[1])) - carousel.add_widget(del_btn) - carousel.add_widget(meny) - carousel.index = 1 - self.ids.ml.add_widget(carousel) + self.queryreturn = [obj for obj in reversed(self.queryreturn)] + if self.queryreturn: + self.has_refreshed = True + self.set_mdList(0, 20) + self.ids.scroll_y.bind(scroll_y=self.check_scroll_y) else: content = MDLabel( font_style='Body1', @@ -377,57 +462,100 @@ class AddressBook(Screen): valign='top') self.ids.ml.add_widget(content) + def set_mdList(self, start_index, end_index): + """Creating the mdList""" + for item in self.queryreturn[start_index:end_index]: + 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_press=partial( + self.addBook_detail, item[1], item[0])) + 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='Delete') + del_btn.background_normal = '' + del_btn.background_color = (1, 0, 0, 1) + del_btn.bind(on_press=partial(self.delete_address, item[1])) + carousel.add_widget(del_btn) + carousel.add_widget(meny) + carousel.index = 1 + self.ids.ml.add_widget(carousel) + + def check_scroll_y(self, instance, somethingelse): + """Load data on scroll""" + if self.ids.scroll_y.scroll_y <= -0.0 and self.has_refreshed: + self.ids.scroll_y.scroll_y = 0.06 + exist_addresses = len(self.ids.ml.children) + if exist_addresses != len(self.queryreturn): + self.update_addressBook_on_scroll(exist_addresses) + self.has_refreshed = True if exist_addresses != len( + self.queryreturn) else False + else: + pass + + def update_addressBook_on_scroll(self, exist_addresses): + """Load more data on scroll down""" + self.set_mdList(exist_addresses, exist_addresses + 5) + @staticmethod def refreshs(*args): - """Refresh the Widget.""" + """Refresh the Widget""" # state.navinstance.ids.sc11.ids.ml.clear_widgets() # state.navinstance.ids.sc11.loadAddresslist(None, 'All', '') pass @staticmethod def addBook_detail(address, label, *args): - """Addressbook Details.""" + """Addressbook details""" p = AddbookDetailPopup() p.open() p.set_addbook_data(address, label) def delete_address(self, address, instance, *args): - """Delete inbox mail from inbox listing.""" + """Delete inbox mail from inbox listing""" self.ids.ml.remove_widget(instance.parent.parent) sqlExecute( "DELETE FROM addressbook WHERE address = '{}';".format(address)) -class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior, - RecycleBoxLayout): - """Adds selection and focus behaviour to the view.""" - +class SelectableRecycleBoxLayout( + FocusBehavior, LayoutSelectionBehavior, RecycleBoxLayout): + """Adds selection and focus behaviour to the view""" + # pylint: disable = too-many-ancestors, duplicate-bases pass class SelectableLabel(RecycleDataViewBehavior, Label): - """Add selection support to the Label.""" - + """Add selection support to the Label""" index = None selected = BooleanProperty(False) selectable = BooleanProperty(True) def refresh_view_attrs(self, rv, index, data): - """Catch and handle the view changes.""" + """Catch and handle the view changes""" self.index = index return super(SelectableLabel, self).refresh_view_attrs( rv, index, data) # pylint: disable=inconsistent-return-statements def on_touch_down(self, touch): - """Add selection on touch down.""" + """Add selection on touch down""" if super(SelectableLabel, self).on_touch_down(touch): return True if self.collide_point(*touch.pos) and self.selectable: return self.parent.select_with_touch(self.index, touch) def apply_selection(self, rv, index, is_selected): - """Respond to the selection of items in the view.""" + """Respond to the selection of items in the view""" self.selected = is_selected if is_selected: print "selection changed to {0}".format(rv.data[index]) @@ -436,23 +564,22 @@ class SelectableLabel(RecycleDataViewBehavior, Label): class RV(RecycleView): - """Recycling View.""" + """Recycling View""" - def __init__(self, **kwargs): - """Recycling Method.""" - # pylint: disable=useless-super-delegation + def __init__(self, **kwargs): # pylint: disable=useless-super-delegation + """Recycling Method""" super(RV, self).__init__(**kwargs) class DropDownWidget(BoxLayout): - """Adding Dropdown Widget.""" - # pylint: disable=too-many-statements, inconsistent-return-statements, too-many-locals - + """Adding Dropdown Widget""" + # pylint: disable=too-many-statements, too-many-locals + # pylint: disable=inconsistent-return-statements txt_input = ObjectProperty() rv = ObjectProperty() def send(self, navApp): - """Send message from one address to another.""" + """Send message from one address to another""" fromAddress = str(self.ids.ti.text) toAddress = str(self.ids.txt_input.text) subject = self.ids.subject.text.encode('utf-8').strip() @@ -462,10 +589,12 @@ class DropDownWidget(BoxLayout): sendMessageToPeople = True if sendMessageToPeople: if toAddress != '' and subject and message: - from addresses import decodeAddress - status, addressVersionNumber, streamNumber, ripe = decodeAddress(toAddress) + status, addressVersionNumber, streamNumber, ripe = ( + decodeAddress(toAddress)) if status == 'success': - if state.detailPageType == 'draft' and state.send_draft_mail: + navApp.root.ids.sc3.children[0].active = True + if state.detailPageType == 'draft' \ + and state.send_draft_mail: sqlExecute( "UPDATE sent SET toaddress = ?" ", fromaddress = ? , subject = ?" @@ -478,15 +607,13 @@ class DropDownWidget(BoxLayout): str(state.send_draft_mail)) self.parent.parent.screens[15].clear_widgets() self.parent.parent.screens[15].add_widget(Draft()) - state.detailPageType = '' - state.send_draft_mail = None else: - from addresses import addBMIfNotPresent toAddress = addBMIfNotPresent(toAddress) statusIconColor = 'red' - if addressVersionNumber > 4 or addressVersionNumber <= 1: - print "addressVersionNumber > 4 \ - or addressVersionNumber <= 1" + if (addressVersionNumber > 4) or ( + addressVersionNumber <= 1): + print "addressVersionNumber > 4"\ + " or addressVersionNumber <= 1" if streamNumber > 1 or streamNumber == 0: print "streamNumber > 1 or streamNumber == 0" if statusIconColor == 'red': @@ -495,7 +622,7 @@ class DropDownWidget(BoxLayout): 'bitmessagesettings', 'ackstealthlevel') from helper_ackPayload import genAckPayload ackdata = genAckPayload(streamNumber, stealthLevel) - t = () + # t = () sqlExecute( '''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', @@ -517,20 +644,23 @@ class DropDownWidget(BoxLayout): 'bitmessagesettings', 'ttl')) state.check_sent_acc = fromAddress state.msg_counter_objs = self.parent.parent.parent.parent\ - .parent.parent.children[0].children[2].children[0].ids - self.parent.parent.screens[3].ids.ml.clear_widgets() - self.parent.parent.screens[3].loadSent(state.association) - self.parent.parent.screens[16].clear_widgets() - self.parent.parent.screens[16].add_widget(Allmails()) - toLabel = '' - + .parent.parent.children[2].children[0].ids + if state.detailPageType == 'draft' \ + and state.send_draft_mail: + state.draft_count = str(int(state.draft_count) - 1) + state.msg_counter_objs.draft_cnt.badge_text = state.draft_count + state.detailPageType = '' + state.send_draft_mail = None + # self.parent.parent.screens[0].ids.ml.clear_widgets() + # self.parent.parent.screens[0].loadMessagelist(state.association) + self.parent.parent.screens[3].update_sent_messagelist() + # self.parent.parent.screens[16].clear_widgets() + # self.parent.parent.screens[16].add_widget(Allmails()) + Clock.schedule_once(self.callback_for_msgsend, 3) queues.workerQueue.put(('sendmessage', toAddress)) print "sqlExecute successfully #######################" - self.parent.parent.current = 'inbox' state.in_composer = True - navApp.back_press() - toast('send') - return None + return else: msg = 'Enter a valid recipients address' elif not toAddress: @@ -539,9 +669,17 @@ class DropDownWidget(BoxLayout): msg = 'Please fill the form' self.address_error_message(msg) + @staticmethod + def callback_for_msgsend(dt=0): + """Callback method for messagesend""" + state.kivyapp.root.ids.sc3.children[0].active = False + state.in_sent_method = True + state.kivyapp.back_press() + toast('sent') + # pylint: disable=attribute-defined-outside-init def address_error_message(self, msg): - """Show Error Message.""" + """Generates error message""" msg_dialog = MDDialog( text=msg, title='', size_hint=(.8, .25), text_button_ok='Ok', @@ -550,11 +688,11 @@ class DropDownWidget(BoxLayout): @staticmethod def callback_for_menu_items(text_item): - """Method is used for getting the callback of alert box""" + """Callback of alert box""" toast(text_item) def reset_composer(self): - """Method will reset composer.""" + """Method will reset composer""" self.ids.ti.text = '' self.ids.btn.text = 'Select' self.ids.txt_input.text = '' @@ -563,27 +701,25 @@ class DropDownWidget(BoxLayout): toast("Reset message") def auto_fill_fromaddr(self): - """Mehtod used to fill the text automatically From Address.""" + """Fill the text automatically From Address""" self.ids.ti.text = self.ids.btn.text self.ids.ti.focus = True class MyTextInput(TextInput): - """Takes the text input in the field.""" - + """Takes the text input in the field""" txt_input = ObjectProperty() flt_list = ObjectProperty() word_list = ListProperty() starting_no = NumericProperty(3) suggestion_text = '' - def __init__(self, **kwargs): - """Getting Text Input.""" - # pylint: disable=useless-super-delegation + def __init__(self, **kwargs): # pylint: disable=useless-super-delegation + """Getting Text Input""" super(MyTextInput, self).__init__(**kwargs) def on_text(self, instance, value): - """Find all the occurrence of the word.""" + """Find all the occurrence of the word""" self.parent.parent.parent.parent.ids.rv.data = [] matches = [self.word_list[i] for i in range( len(self.word_list)) if self.word_list[ @@ -598,7 +734,7 @@ class MyTextInput(TextInput): self.parent.height = 400 def keyboard_on_key_down(self, window, keycode, text, modifiers): - """Key Down.""" + """Key Down""" if self.suggestion_text and keycode[1] == 'tab': self.insert_text(self.suggestion_text + ' ') return True @@ -607,36 +743,37 @@ class MyTextInput(TextInput): class Payment(Screen): - """Payment Method.""" + """Payment module""" - def get_available_credits(self, instance): - """Method helps to get the available credits""" - # pylint: disable=no-self-use + def get_available_credits(self, instance): # pylint: disable=no-self-use + """Get the available credits""" state.availabe_credit = instance.parent.children[1].text - existing_credits = state.kivyapp.root.ids.sc18.ids.ml.children[0].children[0].children[0].children[0].text + existing_credits = ( + state.kivyapp.root.ids.sc18.ids.ml.children[0].children[ + 0].children[0].children[0].text) if len(existing_credits.split(' ')) > 1: - toast('We already have added free coins for the subscription to your account!') + toast( + 'We already have added free coins' + ' for the subscription to your account!') else: toast('Coins added to your account!') - state.kivyapp.root.ids.sc18.ids.ml.children[0].children[0].children[ - 0].children[0].text = '{0}'.format(state.availabe_credit) + state.kivyapp.root.ids.sc18.ids.ml.children[0].children[ + 0].children[0].children[0].text = '{0}'.format( + state.availabe_credit) class Credits(Screen): - """Credits Method""" - available_credits = StringProperty( - '{0}'.format('0')) + """Credits Module""" + available_credits = StringProperty('{0}'.format('0')) class Login(Screen): - """Login Screeen.""" - + """Login Screeen""" pass class NetworkStat(Screen): - """Method used to show network stat.""" - + """Method used to show network stat""" text_variable_1 = StringProperty( '{0}::{1}'.format('Total Connections', '0')) text_variable_2 = StringProperty( @@ -648,12 +785,12 @@ class NetworkStat(Screen): 'Processed {0} object to be synced'.format('0')) def __init__(self, *args, **kwargs): - """Init method for network stat.""" + """Init method for network stat""" super(NetworkStat, self).__init__(*args, **kwargs) Clock.schedule_interval(self.init_ui, 1) def init_ui(self, dt=0): - """Clock Schdule for method inbox accounts.""" + """Clock Schdule for method networkstat screen""" import network.stats import shared from network import objectracker @@ -670,25 +807,27 @@ class NetworkStat(Screen): class ContentNavigationDrawer(Navigatorss): - """Navigate Content Drawer.""" - + """Navigate Content Drawer""" pass class Random(Screen): - """Generates Random Address.""" - + """Generates Random Address""" is_active = BooleanProperty(False) checked = StringProperty("") def generateaddress(self, navApp): - """Method for Address Generator.""" + """Method for Address Generator""" + entered_label = str(self.ids.label.text).strip() streamNumberForAddress = 1 label = self.ids.label.text eighteenByteRipe = False nonceTrialsPerByte = 1000 payloadLengthExtraBytes = 1000 - if str(self.ids.label.text).strip(): + lables = [BMConfigParser().get(obj, 'label') + for obj in BMConfigParser().addresses()] + if entered_label and entered_label not in lables: + toast('Address Creating...') queues.addressGeneratorQueue.put(( 'createRandomAddress', 4, streamNumberForAddress, @@ -696,23 +835,48 @@ class Random(Screen): nonceTrialsPerByte, payloadLengthExtraBytes)) self.ids.label.text = '' - self.parent.parent.parent.parent.ids.toolbar.opacity = 1 - self.parent.parent.parent.parent.ids.toolbar.disabled = False - self.parent.parent.parent.parent.ids.sc10.ids.ml.clear_widgets() + self.parent.parent.children[1].opacity = 1 + self.parent.parent.children[1].disabled = False + state.kivyapp.root.ids.sc10.children[1].active = True self.manager.current = 'myaddress' - self.parent.parent.parent.parent.ids.sc10.init_ui() - self.manager.current = 'myaddress' - toast('New address created') + Clock.schedule_once(self.address_created_callback, 6) + @staticmethod + def address_created_callback(dt=0): + """New address created""" + state.kivyapp.root.ids.sc10.children[1].active = 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() + toast('New address created') -class AddressSuccessful(Screen): - """Getting Address Detail.""" + def add_validation(self, 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'\ + ' can try this Ex. ( {0}_1, {0}_2 )'.format( + entered_label) + elif entered_label: + self.ids.label.error = False + else: + self.ids.label.error = False + self.ids.label.helper_text = 'This field is required' - pass + def reset_address_label(self): + """Resetting address labels""" + self.ids.label.text = '' class Sent(Screen): - """Sent Screen uses screen to show widgets of screens.""" + """Sent Screen uses screen to show widgets of screens""" + queryreturn = ListProperty() + has_refreshed = True + account = StringProperty() + def __init__(self, *args, **kwargs): """Association with the screen.""" super(Sent, self).__init__(*args, **kwargs) @@ -722,73 +886,32 @@ class Sent(Screen): Clock.schedule_once(self.init_ui, 0) def init_ui(self, dt=0): - """Clock Schdule for method sent accounts.""" - self.sentaccounts() + """Clock Schdule for method sent accounts""" + self.loadSent() print dt - def sentaccounts(self): - """Load sent accounts.""" - account = state.association - self.loadSent(account, 'All', '') - - def loadSent(self, account, where="", what=""): + def loadSent(self, where="", what=""): """Load Sent list for Sent messages.""" + self.account = state.association if state.searcing_text: + self.ids.scroll_y.scroll_y = 1.0 where = ['subject', 'message'] what = state.searcing_text xAddress = 'fromaddress' data = [] - queryreturn = kivy_helper_search.search_sql( - xAddress, account, "sent", where, what, False) - if state.msg_counter_objs and state.association == state.check_sent_acc: - state.msg_counter_objs.send_cnt.badge_text = str(len(queryreturn)) - state.sent_count = str(int(state.sent_count) + 1) - state.all_count = str(int(state.all_count) + 1) - state.msg_counter_objs.allmail_cnt.badge_text = state.all_count - state.check_sent_acc = None - - if queryreturn: - src_mng_obj = state.kivyapp.root.children[2].children[0].ids - src_mng_obj.send_cnt.badge_text = str(len(queryreturn)) - state.sent_count = str(len(queryreturn)) - for mail in queryreturn: + self.sentDataQuery(xAddress, where, what) + if self.queryreturn: + self.set_sentCount(state.sent_count) + for mail in self.queryreturn: data.append({ 'text': mail[1].strip(), 'secondary_text': mail[2][:50] + '........' if len( - mail[2]) >= 50 else ( - mail[2] + ',' + mail[3].replace('\n', ''))[0:50] + '........', + mail[2]) >= 50 else (mail[2] + ',' + mail[3].replace( + '\n', ''))[0:50] + '........', 'ackdata': mail[5]}) - for item in data: - meny = TwoLineAvatarIconListItem( - text=item['text'], - secondary_text=item['secondary_text'], - theme_text_color='Custom', - text_color=NavigateApp().theme_cls.primary_color) - meny.add_widget(AvatarSampleWidget( - source='./images/text_images/{}.png'.format( - avatarImageFirstLetter(item['secondary_text'].strip())))) - meny.bind(on_press=partial( - self.sent_detail, item['ackdata'])) - 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='Delete') - del_btn.background_normal = '' - del_btn.background_color = (1, 0, 0, 1) - del_btn.bind(on_press=partial( - self.delete, item['ackdata'])) - carousel.add_widget(del_btn) - carousel.add_widget(meny) - ach_btn = Button(text='Achieve') - ach_btn.background_color = (0, 1, 0, 1) - ach_btn.bind(on_press=partial( - self.archive, item['ackdata'])) - carousel.add_widget(ach_btn) - carousel.index = 1 - self.ids.ml.add_widget(carousel) + self.set_mdlist(data, 0) + self.has_refreshed = True + self.ids.scroll_y.bind(scroll_y=self.check_scroll_y) else: content = MDLabel( font_style='Body1', @@ -801,8 +924,117 @@ class Sent(Screen): valign='top') self.ids.ml.add_widget(content) + # pylint: disable=too-many-arguments + def sentDataQuery(self, xAddress, where, what, start_indx=0, end_indx=20): + """This method is used to retrieving data from sent table""" + self.queryreturn = kivy_helper_search.search_sql( + xAddress, + self.account, + "sent", + where, + what, + False, + start_indx, + end_indx) + + def set_mdlist(self, data, set_index=0): + """This method is used to create the mdList""" + total_sent_msg = len(self.ids.ml.children) + for item in data: + meny = TwoLineAvatarIconListItem( + text=item['text'], + secondary_text=item['secondary_text'], + theme_text_color='Custom', + text_color=NavigateApp().theme_cls.primary_color) + meny.add_widget(AvatarSampleWidget( + source='./images/text_images/{}.png'.format( + avatarImageFirstLetter(item['secondary_text'].strip())))) + meny.bind(on_press=partial( + self.sent_detail, item['ackdata'])) + 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='Delete') + del_btn.background_normal = '' + del_btn.background_color = (1, 0, 0, 1) + del_btn.bind(on_press=partial( + self.delete, item['ackdata'])) + carousel.add_widget(del_btn) + carousel.add_widget(meny) + ach_btn = Button(text='Achieve') + ach_btn.background_color = (0, 1, 0, 1) + ach_btn.bind(on_press=partial( + self.archive, item['ackdata'])) + carousel.add_widget(ach_btn) + carousel.index = 1 + self.ids.ml.add_widget(carousel, index=set_index) + updated_msgs = len(self.ids.ml.children) + self.has_refreshed = True if total_sent_msg != updated_msgs else False + + def update_sent_messagelist(self): + """This method is used to update screen when new mail is sent""" + self.account = state.association + if len(self.ids.ml.children) < 3: + self.ids.ml.clear_widgets() + self.loadSent() + total_sent = int(state.sent_count) + 1 + self.set_sentCount(total_sent) + else: + data = [] + self.sentDataQuery('fromaddress', '', '', 0, 1) + total_sent = int(state.sent_count) + 1 + self.set_sentCount(total_sent) + for mail in self.queryreturn: + data.append({ + 'text': mail[1].strip(), + 'secondary_text': mail[2][:50] + '........' if len( + mail[2]) >= 50 else (mail[2] + ',' + mail[3].replace( + '\n', ''))[0:50] + '........', + 'ackdata': mail[5]}) + self.set_mdlist(data, total_sent - 1) + if state.msg_counter_objs and state.association == ( + state.check_sent_acc): + state.all_count = str(int(state.all_count) + 1) + state.msg_counter_objs.allmail_cnt.badge_text = state.all_count + state.check_sent_acc = None + + def check_scroll_y(self, instance, somethingelse): + """Load data on scroll down""" + if self.ids.scroll_y.scroll_y <= -0.0 and self.has_refreshed: + self.ids.scroll_y.scroll_y = 0.06 + total_sent_msg = len(self.ids.ml.children) + self.update_sent_screen_on_scroll(total_sent_msg) + else: + pass + + def update_sent_screen_on_scroll(self, total_sent_msg, where="", what=""): + """This method is used to load more data on scroll down""" + if state.searcing_text: + where = ['subject', 'message'] + what = state.searcing_text + self.sentDataQuery('fromaddress', where, what, total_sent_msg, 5) + data = [] + for mail in self.queryreturn: + data.append({ + 'text': mail[1].strip(), + 'secondary_text': mail[2][:50] + '........' if len( + mail[2]) >= 50 else (mail[2] + ',' + mail[3].replace( + '\n', ''))[0:50] + '........', + 'ackdata': mail[5]}) + self.set_mdlist(data, 0) + + @staticmethod + def set_sentCount(total_sent): + """Set the total no. of sent message count""" + src_mng_obj = state.kivyapp.root.children[2].children[0].ids + src_mng_obj.send_cnt.badge_text = str(total_sent) + state.sent_count = str(total_sent) + def sent_detail(self, ackdata, *args): - """Load sent mail details.""" + """Load sent mail details""" state.detailPageType = 'sent' state.mail_id = ackdata if self.manager: @@ -814,7 +1046,7 @@ class Sent(Screen): src_mng_obj.current = 'mailDetail' def delete(self, data_index, instance, *args): - """Delete sent mail from sent mail listing.""" + """Delete sent mail from sent mail listing""" try: msg_count_objs = self.parent.parent.parent.parent.children[ 2].children[0].ids @@ -839,7 +1071,7 @@ class Sent(Screen): self.update_trash() def archive(self, data_index, instance, *args): - """Archive sent mail from sent mail listing.""" + """Archive sent mail from sent mail listing""" sqlExecute( "UPDATE sent SET folder = 'trash'" " WHERE ackdata = ?;", str(data_index)) @@ -847,7 +1079,7 @@ class Sent(Screen): self.update_trash() def update_trash(self): - """Update trash screen mails which is deleted from inbox.""" + """Update trash screen mails which is deleted from inbox""" try: self.parent.screens[4].clear_widgets() self.parent.screens[4].add_widget(Trash()) @@ -861,59 +1093,28 @@ class Sent(Screen): class Trash(Screen): - """Trash Screen uses screen to show widgets of screens.""" + """Trash Screen uses screen to show widgets of screens""" + trash_messages = ListProperty() + has_refreshed = True + delete_index = StringProperty() + table_name = StringProperty() def __init__(self, *args, **kwargs): - """Trash method, delete sent message and add in Trash.""" + """Trash method, delete sent message and add in Trash""" super(Trash, self).__init__(*args, **kwargs) Clock.schedule_once(self.init_ui, 0) def init_ui(self, dt=0): - """Clock Schdule for method inbox accounts.""" + """Clock Schdule for method trash screen.""" if state.association == '': if BMConfigParser().addresses(): state.association = BMConfigParser().addresses()[0] - inbox = sqlQuery( - "SELECT toaddress, fromaddress, subject, message, folder, received from" - " inbox WHERE folder = 'trash' and toaddress = '{}';".format( - state.association)) - sent = sqlQuery( - "SELECT toaddress, fromaddress, subject, message, folder, lastactiontime from" - " sent WHERE folder = 'trash' and fromaddress = '{}';".format( - state.association)) - trash_data = inbox + sent - - if trash_data: + self.trashDataQuery(0, 20) + if self.trash_messages: src_mng_obj = state.kivyapp.root.children[2].children[0].ids - src_mng_obj.trash_cnt.badge_text = str(len(trash_data)) - state.trash_count = str(len(trash_data)) - for item in trash_data: - meny = TwoLineAvatarIconListItem( - text=item[1], - secondary_text=item[2][:50] + '........' if len( - item[2]) >= 50 else ( - item[2] + ',' + item[3].replace('\n', ''))[0:50] + '........', - theme_text_color='Custom', - text_color=NavigateApp().theme_cls.primary_color) - img_latter = './images/text_images/{}.png'.format( - item[2][0].upper() if (item[2][0].upper() >= 'A' and item[ - 2][0].upper() <= 'Z') else '!') - meny.add_widget(AvatarSampleWidget(source=img_latter)) - 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='Delete') - del_btn.background_normal = '' - del_btn.background_color = (1, 0, 0, 1) - del_btn.bind(on_press=partial( - self.delete_permanently, item[5])) - carousel.add_widget(del_btn) - carousel.add_widget(meny) - carousel.index = 1 - self.ids.ml.add_widget(carousel) + src_mng_obj.trash_cnt.badge_text = state.trash_count + self.set_mdList() + self.ids.scroll_y.bind(scroll_y=self.check_scroll_y) else: content = MDLabel( font_style='Body1', @@ -925,22 +1126,126 @@ class Trash(Screen): valign='top') self.ids.ml.add_widget(content) - def delete_permanently(self, data_index, instance, *args): - """Deleting trash mail permanently.""" - pass + def trashDataQuery(self, start_indx, end_indx): + """Trash message query""" + self.trash_messages = sqlQuery( + "SELECT toaddress, fromaddress, subject, message," + " folder ||',' || 'sent' as folder, ackdata As" + " id, DATE(lastactiontime) As actionTime FROM sent" + " WHERE folder = 'trash' and fromaddress = '{0}' UNION" + " SELECT toaddress, fromaddress, subject, message," + " folder ||',' || 'inbox' as folder, msgid As id," + " DATE(received) As actionTime FROM inbox" + " WHERE folder = 'trash' and toaddress = '{0}'" + " ORDER BY actionTime DESC limit {1}, {2}".format( + state.association, start_indx, end_indx)) + + def set_mdList(self): + """This method is used to create the mdlist""" + total_trash_msg = len(self.ids.ml.children) + for item in self.trash_messages: + meny = TwoLineAvatarIconListItem( + text=item[1], + secondary_text=item[2][:50] + '........' if len( + item[2]) >= 50 else (item[2] + ',' + item[3].replace( + '\n', ''))[0:50] + '........', + theme_text_color='Custom', + text_color=NavigateApp().theme_cls.primary_color) + img_latter = './images/text_images/{}.png'.format( + item[2][0].upper() if (item[2][0].upper() >= 'A' and item[ + 2][0].upper() <= 'Z') else '!') + meny.add_widget(AvatarSampleWidget(source=img_latter)) + 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='Delete') + del_btn.background_normal = '' + del_btn.background_color = (1, 0, 0, 1) + del_btn.bind(on_press=partial( + self.delete_permanently, item[5], item[4])) + carousel.add_widget(del_btn) + carousel.add_widget(meny) + carousel.index = 1 + self.ids.ml.add_widget(carousel) + self.has_refreshed = True if total_trash_msg != len( + self.ids.ml.children) else False + + def check_scroll_y(self, instance, somethingelse): + """Load data on scroll""" + if self.ids.scroll_y.scroll_y <= -0.0 and self.has_refreshed: + self.ids.scroll_y.scroll_y = 0.06 + total_trash_msg = len(self.ids.ml.children) + self.update_trash_screen_on_scroll(total_trash_msg) + else: + pass + + def update_trash_screen_on_scroll(self, total_trash_msg): + """Load more data on scroll down""" + self.trashDataQuery(total_trash_msg, 5) + self.set_mdList() + + def delete_permanently(self, data_index, folder, instance, *args): + """Deleting trash mail permanently""" + self.table_name = folder.split(',')[1] + self.delete_index = data_index + self.delete_confirmation() + + def callback_for_screen_load(self, dt=0): + """This methos is for loading screen""" + self.ids.ml.clear_widgets() + self.init_ui(0) + self.children[1].active = False + toast('Message is permanently deleted') + + def delete_confirmation(self): + """Show confirmation delete popup""" + delete_msg_dialog = MDDialog( + text='Are you sure you want to delete this' + ' message permanently from trash?', + title='', + size_hint=(.8, .25), + text_button_ok='Yes', + text_button_cancel='No', + events_callback=self.callback_for_delete_msg) + delete_msg_dialog.open() + + def callback_for_delete_msg(self, text_item): + """Getting the callback of alert box""" + if text_item == 'Yes': + self.delete_message_from_trash() + else: + toast(text_item) + + def delete_message_from_trash(self): + """Deleting message from trash""" + self.children[1].active = True + if self.table_name == 'inbox': + sqlExecute("DELETE FROM inbox WHERE msgid = ?;", str( + self.delete_index)) + elif self.table_name == 'sent': + sqlExecute("DELETE FROM sent WHERE ackdata = ?;", str( + self.delete_index)) + msg_count_objs = state.kivyapp.root.children[2].children[0].ids + if int(state.trash_count) > 0: + msg_count_objs.trash_cnt.badge_text = str( + int(state.trash_count) - 1) + state.trash_count = str(int(state.trash_count) - 1) + Clock.schedule_once(self.callback_for_screen_load, 1) class Page(Screen): - """Page Screen show widgets of page.""" - + """Page Screen show widgets of page""" pass class Create(Screen): - """Creates the screen widgets.""" + """Creates the screen widgets""" def __init__(self, **kwargs): - """Getting Labels and address from addressbook.""" + """Getting Labels and address from addressbook""" super(Create, self).__init__(**kwargs) widget_1 = DropDownWidget() widget_1.ids.txt_input.word_list = [ @@ -951,15 +1256,12 @@ class Create(Screen): class Setting(Screen): - """Setting the Screen components.""" - + """Setting the Screen components""" pass -class NavigateApp(App): - """Navigation Layout of class.""" - # pylint: disable=too-many-public-methods - +class NavigateApp(App): # pylint: disable=too-many-public-methods + """Navigation Layout of class""" theme_cls = ThemeManager() previous_date = ObjectProperty() obj_1 = ObjectProperty() @@ -988,7 +1290,7 @@ class NavigateApp(App): ] def build(self): - """Method builds the widget.""" + """Method builds the widget""" main_widget = Builder.load_file( os.path.join(os.path.dirname(__file__), 'main.kv')) self.nav_drawer = Navigatorss() @@ -1000,14 +1302,14 @@ class NavigateApp(App): return main_widget def run(self): - """Running the widgets.""" + """Running the widgets""" kivyuisignaler.release() super(NavigateApp, self).run() # pylint: disable=inconsistent-return-statements @staticmethod def showmeaddresses(name="text"): - """Show the addresses in spinner to make as dropdown.""" + """Show the addresses in spinner to make as dropdown""" if name == "text": if BMConfigParser().addresses(): return BMConfigParser().addresses()[0][:16] + '..' @@ -1019,25 +1321,253 @@ class NavigateApp(App): return "valuesdemo" def getCurrentAccountData(self, text): - """Get Current Address Account Data.""" + """Get Current Address Account Data""" self.set_identicon(text) address_label = self.current_address_label( BMConfigParser().get(text, 'label'), text) self.root_window.children[1].ids.toolbar.title = address_label state.association = text state.searcing_text = '' + LoadingPopup().open() + self.set_message_count() + Clock.schedule_once(self.setCurrentAccountData, 0.5) + + def setCurrentAccountData(self, dt=0): + """This method set the current accout data on all the screens.""" self.root.ids.sc1.ids.ml.clear_widgets() self.root.ids.sc1.loadMessagelist(state.association) + + self.root.ids.sc4.ids.ml.clear_widgets() + self.root.ids.sc4.children[2].children[1].ids.search_field.text = '' + self.root.ids.sc4.loadSent(state.association) + + self.root.ids.sc16.clear_widgets() + self.root.ids.sc16.add_widget(Draft()) + + self.root.ids.sc5.clear_widgets() + self.root.ids.sc5.add_widget(Trash()) + + self.root.ids.sc17.clear_widgets() + self.root.ids.sc17.add_widget(Allmails()) + self.root.ids.scr_mngr.current = 'inbox' - msg_counter_objs = self.root_window.children[1].children[2].children[0].ids - state.sent_count = str( - sqlQuery( - "SELECT COUNT(*) FROM sent WHERE fromaddress = '{}' and" - " folder = 'sent' ;".format(state.association))[0][0]) + + @staticmethod + def getCurrentAccount(): + """It uses to get current account label""" + if state.association: + return state.association + return "Bitmessage Login" + + @staticmethod + def addingtoaddressbook(): + """Adding to address Book""" + p = GrashofPopup() + p.open() + + def getDefaultAccData(self): + """Getting Default Account Data""" + if BMConfigParser().addresses(): + img = identiconGeneration.generate(BMConfigParser().addresses()[0]) + self.createFolder('./images/default_identicon/') + 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)) + else: + img.texture.save( + './images/default_identicon/{}.png'.format( + BMConfigParser().addresses()[0])) + return BMConfigParser().addresses()[0] + return 'Select Address' + + @staticmethod + def createFolder(directory): + """Create directory when app starts""" + try: + if not os.path.exists(directory): + os.makedirs(directory) + except OSError: + print 'Error: Creating directory. ' + directory + + @staticmethod + def get_default_image(): + """Getting default image on address""" + if BMConfigParser().addresses(): + return './images/default_identicon/{}.png'.format( + BMConfigParser().addresses()[0]) + return './images/no_identicons.png' + + @staticmethod + def addressexist(): + """Checking address existence""" + if BMConfigParser().addresses(): + return True + return False + + def on_key(self, window, key, *args): + """Method is used for going on previous screen""" + if key == 27: + if state.in_search_mode and self.root.ids.scr_mngr.current != ( + "mailDetail"): + 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() + elif self.root.ids.scr_mngr.current == "create": + self.save_draft() + self.set_common_header() + state.in_composer = False + self.root.ids.scr_mngr.current = 'inbox' + elif self.root.ids.scr_mngr.current == "showqrcode": + self.root.ids.scr_mngr.current = 'myaddress' + elif self.root.ids.scr_mngr.current == "random": + self.root.ids.scr_mngr.current = 'login' + else: + 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: + if state.search_screen == 'inbox': + self.root.ids.sc1.children[1].active = True + Clock.schedule_once(self.search_callback, 0.5) + elif state.search_screen == 'addressbook': + self.root.ids.sc11.children[1].active = True + Clock.schedule_once(self.search_callback, 0.5) + elif state.search_screen == 'myaddress': + self.root.ids.sc10.children[1].active = True + Clock.schedule_once(self.search_callback, 0.5) + elif state.search_screen == 'sent': + self.root.ids.sc4.children[1].active = True + Clock.schedule_once(self.search_callback, 0.5) + + def search_callback(self, dt=0): + """Show data after loader is loaded""" + if state.search_screen == 'inbox': + self.root.ids.sc1.ids.ml.clear_widgets() + self.root.ids.sc1.loadMessagelist(state.association) + self.root.ids.sc1.children[1].active = False + elif state.search_screen == 'addressbook': + self.root.ids.sc11.ids.ml.clear_widgets() + self.root.ids.sc11.loadAddresslist(None, 'All', '') + self.root.ids.sc11.children[1].active = False + elif state.search_screen == 'myaddress': + self.root.ids.sc10.ids.ml.clear_widgets() + self.root.ids.sc10.init_ui() + self.root.ids.sc10.children[1].active = False + else: + self.root.ids.sc4.ids.ml.clear_widgets() + self.root.ids.sc4.loadSent(state.association) + self.root.ids.sc4.children[1].active = False + self.root.ids.scr_mngr.current = state.search_screen + + def save_draft(self): + """Saving drafts messages""" + composer_objs = self.root + from_addr = str(self.root.ids.sc3.children[1].ids.ti.text) + to_addr = str(self.root.ids.sc3.children[1].ids.txt_input.text) + if from_addr and to_addr and state.detailPageType != 'draft' \ + and not state.in_sent_method: + Draft().draft_msg(composer_objs) + return + + def reset(self, *args): + """Set transition direction""" + self.root.ids.scr_mngr.transition.direction = 'left' + self.root.ids.scr_mngr.transition.unbind(on_complete=self.reset) + + @staticmethod + def status_dispatching(data): + """Dispatching Status acknowledgment""" + ackData, message = data + if state.ackdata == ackData: + state.status.status = message + + def clear_composer(self): + """If slow down, the new composer edit screen""" + self.set_navbar_for_composer() + composer_obj = self.root.ids.sc3.children[1].ids + composer_obj.ti.text = '' + composer_obj.btn.text = 'Select' + composer_obj.txt_input.text = '' + composer_obj.subject.text = '' + composer_obj.body.text = '' + state.in_composer = True + state.in_sent_method = False + + def set_navbar_for_composer(self): + """Clearing toolbar data when composer open""" + self.root.ids.toolbar.left_action_items = [ + ['arrow-left', lambda x: self.back_press()]] + self.root.ids.toolbar.right_action_items = [ + ['refresh', + lambda x: self.root.ids.sc3.children[1].reset_composer()], + ['send', + lambda x: self.root.ids.sc3.children[1].send(self)]] + + def set_common_header(self): + """Common header for all window""" + self.root.ids.toolbar.right_action_items = [ + ['account-plus', lambda x: self.addingtoaddressbook()]] + self.root.ids.toolbar.left_action_items = [ + ['menu', lambda x: self.root.toggle_nav_drawer()]] + return + + def back_press(self): + """Method for, reverting composer to previous page""" + self.save_draft() + if self.root.ids.scr_mngr.current == \ + 'mailDetail' and state.in_search_mode: + 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 = '' + else: + self.set_common_header() + self.root.ids.scr_mngr.current = 'inbox' \ + if state.in_composer else 'allmails'\ + if state.is_allmail else state.detailPageType\ + if state.detailPageType else 'inbox' + 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': + state.is_allmail = False + state.detailPageType = '' + state.in_composer = False + + @staticmethod + def get_inbox_count(): + """Getting inbox count""" state.inbox_count = str( sqlQuery( "SELECT COUNT(*) FROM inbox WHERE toaddress = '{}' and" " folder = 'inbox' ;".format(state.association))[0][0]) + + @staticmethod + def get_sent_count(): + """Getting sent count""" + state.sent_count = str( + sqlQuery( + "SELECT COUNT(*) FROM sent WHERE fromaddress = '{}' and" + " folder = 'sent' ;".format(state.association))[0][0]) + + def set_message_count(self): + """Setting message count""" + try: + msg_counter_objs = ( + self.root_window.children[0].children[2].children[0].ids) + except Exception: + msg_counter_objs = ( + self.root_window.children[2].children[2].children[0].ids) + self.get_inbox_count() + self.get_sent_count() state.trash_count = str(sqlQuery( "SELECT (SELECT count(*) FROM sent" " where fromaddress = '{0}' and folder = 'trash' )" @@ -1056,140 +1586,20 @@ class NavigateApp(App): msg_counter_objs.draft_cnt.badge_text = state.draft_count msg_counter_objs.allmail_cnt.badge_text = state.all_count - @staticmethod - def getCurrentAccount(): - """It uses to get current account label.""" - if state.association: - return state.association - return "Bitmessage Login" - - @staticmethod - def addingtoaddressbook(): - """Adding to address Book.""" - p = GrashofPopup() - p.open() - - def getDefaultAccData(self): - """Getting Default Account Data.""" - if BMConfigParser().addresses(): - img = identiconGeneration.generate(BMConfigParser().addresses()[0]) - self.createFolder('./images/default_identicon/') - 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)) - else: - img.texture.save('./images/default_identicon/{}.png'.format(BMConfigParser().addresses()[0])) - return BMConfigParser().addresses()[0] - return 'Select Address' - - @staticmethod - def createFolder(directory): - """This method is used to create the directory when app starts""" - try: - if not os.path.exists(directory): - os.makedirs(directory) - except OSError: - print 'Error: Creating directory. ' + directory - - @staticmethod - def get_default_image(): - """Getting default image on address""" - if BMConfigParser().addresses(): - return './images/default_identicon/{}.png'.format(BMConfigParser().addresses()[0]) - return './images/no_identicons.png' - - @staticmethod - def addressexist(): - """Checking address existence.""" - if BMConfigParser().addresses(): - return True - return False - - def on_key(self, window, key, *args): - """Method is used for going on previous screen.""" - if key == 27: - if 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() - elif self.root.ids.scr_mngr.current == "create": - composer_objs = self.root - from_addr = str(self.root.ids.sc3.children[0].ids.ti.text) - to_addr = str(self.root.ids.sc3.children[0].ids.txt_input.text) - if from_addr and to_addr and state.detailPageType != 'draft': - Draft().draft_msg(composer_objs) - self.root.ids.scr_mngr.current = 'inbox' - self.back_press() - elif self.root.ids.scr_mngr.current == "showqrcode": - self.root.ids.scr_mngr.current = 'myaddress' - elif self.root.ids.scr_mngr.current == "random": - self.root.ids.scr_mngr.current = 'login' - else: - 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 - - def reset(self, *args): - """Method used to set transition direction.""" - self.root.ids.scr_mngr.transition.direction = 'left' - self.root.ids.scr_mngr.transition.unbind(on_complete=self.reset) - - @staticmethod - def status_dispatching(data): - """Method used for status dispatching acknowledgment.""" - ackData, message = data - if state.ackdata == ackData: - state.status.status = message - - def clear_composer(self): - """If slow down the nwe will make new composer edit screen.""" - self.set_navbar_for_composer() - # self.root.ids.search_bar.clear_widgets() - composer_obj = self.root.ids.sc3.children[0].ids - composer_obj.ti.text = '' - composer_obj.btn.text = 'Select' - composer_obj.txt_input.text = '' - composer_obj.subject.text = '' - composer_obj.body.text = '' - state.in_composer = True - - def set_navbar_for_composer(self): - """This method is used for clearing toolbar data when composer open""" - self.root.ids.toolbar.left_action_items = [ - ['arrow-left', lambda x: self.back_press()]] - self.root.ids.toolbar.right_action_items = [ - ['refresh', lambda x: self.root.ids.sc3.children[0].reset_composer()], - ['send', lambda x: self.root.ids.sc3.children[0].send(self)]] - - def back_press(self): - """Method used for going back from composer to previous page.""" - self.root.ids.toolbar.right_action_items = [['account-plus', lambda x: self.addingtoaddressbook()]] - self.root.ids.toolbar.left_action_items = [['menu', lambda x: self.root.toggle_nav_drawer()]] - self.root.ids.scr_mngr.current = 'inbox' \ - if state.in_composer else 'allmails'\ - if state.is_allmail else state.detailPageType\ - if state.detailPageType else 'inbox' - 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': - state.is_allmail = False - state.detailPageType = '' - state.in_composer = False + def on_start(self): + """Method activates on start""" + self.set_message_count() @staticmethod def on_stop(): - """On stop methos is used for stoping the runing script.""" + """On stop methos is used for stoping the runing script""" print "*******************EXITING FROM APPLICATION*******************" import shutdown shutdown.doCleanShutdown() @staticmethod def current_address_label(current_add_label=None, current_addr=None): - """Getting current address labels.""" + """Getting current address labels""" if BMConfigParser().addresses(): if current_add_label: first_name = current_add_label @@ -1198,100 +1608,133 @@ class NavigateApp(App): addr = BMConfigParser().addresses()[0] first_name = BMConfigParser().get(addr, 'label') f_name = first_name.split() - label = f_name[0][:14].capitalize() + '...' if len(f_name[0]) > 15 else f_name[0].capitalize() + label = f_name[0][:14].capitalize() + '...' if len( + f_name[0]) > 15 else f_name[0].capitalize() address = ' (' + addr + '...)' return label + address return '' def searchQuery(self, instance): - """Method used for showing searched mails.""" + """Showing searched mails""" state.search_screen = self.root.ids.scr_mngr.current state.searcing_text = str(instance.text).strip() - if state.search_screen == 'inbox': - self.root.ids.sc1.ids.ml.clear_widgets() - self.root.ids.sc1.loadMessagelist(state.association) - elif state.search_screen == 'addressbook': - self.root.ids.sc11.ids.ml.clear_widgets() - self.root.ids.sc11.loadAddresslist(None, 'All', '') - elif state.search_screen == 'myaddress': - self.root.ids.sc10.ids.ml.clear_widgets() - self.root.ids.sc10.init_ui() - else: - self.root.ids.sc4.ids.ml.clear_widgets() - self.root.ids.sc4.loadSent(state.association) - self.root.ids.scr_mngr.current = state.search_screen + if instance.focus 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 = '' + state.in_search_mode = True - def refreshScreen(self, instance): - """Method show search button only on inbox or sent screen.""" + def closeSearchScreen(self): + """Function for close search screen""" + self.set_common_header() + address_label = self.current_address_label( + BMConfigParser().get( + state.association, 'label'), state.association) + self.root.ids.toolbar.title = address_label state.searcing_text = '' - if instance.text == 'Sent': - self.root.ids.sc4.ids.ml.clear_widgets() - self.root.ids.sc4.children[1].children[1].ids.search_field.text = '' - self.root.ids.sc4.loadSent(state.association) - elif instance.text == 'Inbox': - self.root.ids.sc1.ids.ml.clear_widgets() + self.refreshScreen() + state.in_search_mode = False + + def refreshScreen(self): # pylint: disable=unused-variable + """Method show search button only on inbox or sent screen""" + state.searcing_text = '' + if state.search_screen == 'inbox': try: - self.root.ids.sc1.children[2].children[1].ids.search_field.text = '' + self.root.ids.sc1.children[ + 3].children[1].ids.search_field.text = '' except Exception: - self.root.ids.sc1.children[1].children[1].ids.search_field.text = '' - self.root.ids.sc1.loadMessagelist(state.association) - elif instance.text == 'Draft': - self.root.ids.sc16.clear_widgets() - self.root.ids.sc16.add_widget(Draft()) - elif instance.text == 'Trash': - self.root.ids.sc5.clear_widgets() - self.root.ids.sc5.add_widget(Trash()) - elif instance.text == 'All Mails': - self.root.ids.sc17.clear_widgets() - self.root.ids.sc17.add_widget(Allmails()) - elif instance.text == 'Address Book': - self.root.ids.sc11.ids.ml.clear_widgets() - self.root.ids.sc11.children[1].children[1].ids.search_field.text = '' - self.root.ids.sc11.loadAddresslist(None, 'All', '') - elif instance.text == 'My Addresses': - self.root.ids.sc10.ids.ml.clear_widgets() + self.root.ids.sc1.children[ + 2].children[1].ids.search_field.text = '' + self.root.ids.sc1.children[1].active = True + Clock.schedule_once(self.search_callback, 0.5) + elif state.search_screen == 'addressbook': + self.root.ids.sc11.children[ + 2].children[1].ids.search_field.text = '' + self.root.ids.sc11.children[ + 1].active = True + Clock.schedule_once(self.search_callback, 0.5) + elif state.search_screen == 'myaddress': try: - self.root.ids.sc10.children[1].children[1].ids.search_field.text = '' + self.root.ids.sc10.children[ + 3].children[1].ids.search_field.text = '' except Exception: - self.root.ids.sc10.children[2].children[1].ids.search_field.text = '' - self.root.ids.sc10.init_ui() + self.root.ids.sc10.children[ + 2].children[1].ids.search_field.text = '' + self.root.ids.sc10.children[1].active = True + Clock.schedule_once(self.search_callback, 0.5) + else: + self.root.ids.sc4.children[ + 2].children[1].ids.search_field.text = '' + self.root.ids.sc4.children[1].active = True + Clock.schedule_once(self.search_callback, 0.5) return def set_identicon(self, text): - """This method is use for showing identicon in address spinner""" + """Show identicon in address spinner""" img = identiconGeneration.generate(text) - self.root.children[2].children[0].ids.btn.children[1].texture = img.texture - - @staticmethod - def address_identicon(): - """Address identicon""" - return './images/drawer_logo1.png' + self.root.children[2].children[0].ids.btn.children[1].texture = ( + img.texture) def set_mail_detail_header(self): - """Method is used for setting the details of the page""" + """Setting the details of the page""" toolbar_obj = self.root.ids.toolbar - toolbar_obj.left_action_items = [['arrow-left', lambda x: self.back_press()]] - delete_btn = ['delete-forever', lambda x: self.root.ids.sc14.delete_mail()] + toolbar_obj.left_action_items = [ + ['arrow-left', lambda x: self.back_press()]] + delete_btn = ['delete-forever', + lambda x: self.root.ids.sc14.delete_mail()] dynamic_list = [] if state.detailPageType == 'inbox': - dynamic_list = [['reply', lambda x: self.root.ids.sc14.inbox_reply()], delete_btn] + dynamic_list = [ + ['reply', lambda x: self.root.ids.sc14.inbox_reply()], + delete_btn] elif state.detailPageType == 'sent': dynamic_list = [delete_btn] elif state.detailPageType == 'draft': - dynamic_list = [['pencil', lambda x: self.root.ids.sc14.write_msg(self)], delete_btn] + dynamic_list = [ + ['pencil', lambda x: self.root.ids.sc14.write_msg(self)], + delete_btn] toolbar_obj.right_action_items = dynamic_list + def load_screen(self, instance): + """This method is used for loading screen on every click""" + if instance.text == 'Inbox': + self.root.ids.scr_mngr.current = 'inbox' + self.root.ids.sc1.children[1].active = True + elif instance.text == 'All Mails': + self.root.ids.scr_mngr.current = 'allmails' + try: + self.root.ids.sc17.children[1].active = True + except Exception: + self.root.ids.sc17.children[0].children[1].active = True + Clock.schedule_once(partial(self.load_screen_callback, instance), 1) + + def load_screen_callback(self, instance, dt=0): + """This method is rotating loader for few seconds""" + if instance.text == 'Inbox': + self.root.ids.sc1.ids.ml.clear_widgets() + self.root.ids.sc1.loadMessagelist(state.association) + self.root.ids.sc1.children[1].active = False + elif instance.text == 'All Mails': + self.root.ids.sc17.clear_widgets() + self.root.ids.sc17.add_widget(Allmails()) + try: + self.root.ids.sc17.children[1].active = False + except Exception: + self.root.ids.sc17.children[0].children[1].active = False + class GrashofPopup(Popup): - """Methods for saving contacts, error messages.""" + """Moule for save contacts and error messages""" + valid = False - def __init__(self, **kwargs): - """Grash of pop screen settings.""" - # pylint: disable=useless-super-delegation + def __init__(self, **kwargs): # pylint: disable=useless-super-delegation + """Grash of pop screen settings""" super(GrashofPopup, self).__init__(**kwargs) def savecontact(self): - """Method is used for Saving Contacts.""" + """Method is used for saving contacts""" label = self.ids.label.text.strip() address = self.ids.address.text.strip() if label == '' and address == '': @@ -1304,19 +1747,22 @@ class GrashofPopup(Popup): stored_address = [addr[1] for addr in kivy_helper_search.search_sql( folder="addressbook")] - if label and address and address not in stored_address: + stored_labels = [labels[0] for labels in kivy_helper_search.search_sql( + folder="addressbook")] + if label and address and address not in stored_address \ + and label not in stored_labels and self.valid: # state.navinstance = self.parent.children[1] queues.UISignalQueue.put(('rerenderAddressBook', '')) self.dismiss() sqlExecute("INSERT INTO addressbook VALUES(?,?)", label, address) - state.kivyapp.root.ids.sc11.ids.ml.clear_widgets() - state.kivyapp.root.ids.sc11.loadAddresslist(None, 'All', '') + self.parent.children[1].ids.sc11.ids.ml.clear_widgets() + self.parent.children[1].ids.sc11.loadAddresslist(None, 'All', '') self.parent.children[1].ids.scr_mngr.current = 'addressbook' toast('Saved') # pylint: disable=attribute-defined-outside-init def show_error_message(self): - """Showing error message.""" + """Showing error message""" content = MDLabel( font_style='Body1', theme_text_color='Secondary', @@ -1336,12 +1782,13 @@ class GrashofPopup(Popup): @staticmethod def close_pop(): - """Pop is Canceled.""" + """Pop is Canceled""" toast('Canceled') def checkAddress_valid(self, instance): - """Checking is address is valid or not""" - my_addresses = self.parent.children[1].children[2].children[0].ids.btn.values + """Checking address is valid or not""" + my_addresses = ( + self.parent.children[1].children[2].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() @@ -1349,57 +1796,95 @@ class GrashofPopup(Popup): text = 'Address is already in the addressbook.' elif entered_text in my_addresses: text = 'You can not save your own address.' + elif entered_text: + text = self.addressChanged(entered_text) if entered_text in my_addresses or entered_text in add_book: - if len(self.ids.popup_box.children) <= 2: - err_msg = MDLabel( - id='erro_msg', - font_style='Body2', - text=text, - font_size=5) - err_msg.color = 1, 0, 0, 1 - self.ids.popup_box.add_widget(err_msg) - self.ids.save_addr.disabled = True - elif len(self.ids.popup_box.children) > 2: - self.ids.popup_box.remove_widget(self.ids.popup_box.children[0]) - self.ids.save_addr.disabled = False + self.ids.address.error = True + self.ids.address.helper_text = text + elif entered_text and self.valid: + self.ids.address.error = False + elif entered_text: + self.ids.address.error = True + self.ids.address.helper_text = text + else: + self.ids.address.error = False + self.ids.address.helper_text = 'This field is required' + + def checkLabel_valid(self, instance): + """Checking address label is unique or not""" + entered_label = instance.text.strip() + addr_labels = [labels[0] for labels in kivy_helper_search.search_sql( + folder="addressbook")] + if entered_label in addr_labels: + self.ids.label.error = True + self.ids.label.helper_text = 'label name already exists.' + elif entered_label: + self.ids.label.error = False + else: + self.ids.label.error = False + self.ids.label.helper_text = 'This field is required' + + def _onSuccess(self, addressVersion, streamNumber, ripe): + pass + + def addressChanged(self, addr): + """Address validation callback, performs validation and gives feedback""" + status, addressVersion, streamNumber, ripe = decodeAddress( + str(addr)) + self.valid = status == 'success' + if self.valid: + text = "Address is valid." + self._onSuccess(addressVersion, streamNumber, ripe) + elif status == 'missingbm': + text = "The address should start with ''BM-''" + elif status == 'checksumfailed': + text = "The address is not typed or copied correctly(the checksum failed)." + elif status == 'versiontoohigh': + text = "The version number of this address is higher"\ + " than this software can support. Please upgrade Bitmessage." + elif status == 'invalidcharacters': + text = "The address contains invalid characters." + elif status == 'ripetooshort': + text = "Some data encoded in the address is too short." + elif status == 'ripetoolong': + text = "Some data encoded in the address is too long." + elif status == 'varintmalformed': + text = "Some data encoded in the address is malformed." + return text class AvatarSampleWidget(ILeftBody, Image): - """Avatar Sample Widget.""" - + """Avatar Sample Widget""" pass class IconLeftSampleWidget(ILeftBodyTouch, MDIconButton): - """Left icon sample widget.""" - + """Left icon sample widget""" pass class IconRightSampleWidget(IRightBodyTouch, MDCheckbox): - """Right icon sample widget.""" - + """Right icon sample widget""" pass class NavigationDrawerTwoLineListItem( TwoLineListItem, NavigationDrawerHeaderBase): - """Navigation Drawer in Listitems.""" - + """Navigation Drawer in Listitems""" address_property = StringProperty() def __init__(self, **kwargs): - """Method for Navigation Drawer.""" + """Method for Navigation Drawer""" super(NavigationDrawerTwoLineListItem, self).__init__(**kwargs) Clock.schedule_once(lambda dt: self.setup()) def setup(self): - """Bind Controller.current_account property.""" + """Bind Controller.current_account property""" pass def on_current_account(self, account): - """Account detail.""" + """Account detail""" pass def _update_specific_text_color(self, instance, value): @@ -1410,8 +1895,7 @@ class NavigationDrawerTwoLineListItem( class MailDetail(Screen): - """MailDetail Screen uses to show the detail of mails.""" - + """MailDetail Screen uses to show the detail of mails""" to_addr = StringProperty() from_addr = StringProperty() subject = StringProperty() @@ -1420,12 +1904,12 @@ class MailDetail(Screen): page_type = StringProperty() def __init__(self, *args, **kwargs): - """Mail Details method.""" + """Mail Details method""" super(MailDetail, self).__init__(*args, **kwargs) Clock.schedule_once(self.init_ui, 0) def init_ui(self, dt=0): - """Clock Schdule for method MailDetail mails.""" + """Clock Schdule for method MailDetail mails""" self.page_type = state.detailPageType if state.detailPageType else '' if state.detailPageType == 'sent' or state.detailPageType == 'draft': data = sqlQuery( @@ -1443,7 +1927,7 @@ class MailDetail(Screen): state.kivyapp.set_mail_detail_header() def assign_mail_details(self, data): - """Assigning mail details.""" + """Assigning mail details""" self.to_addr = data[0][0] self.from_addr = data[0][1] self.subject = data[0][2].upper( @@ -1457,9 +1941,13 @@ class MailDetail(Screen): 'message': self.message} def delete_mail(self): - """Method for mail delete.""" + """Method for mail delete""" msg_count_objs = state.kivyapp.root.children[2].children[0].ids + state.searcing_text = '' + self.children[0].children[0].active = True if state.detailPageType == 'sent': + state.kivyapp.root.ids.sc4.children[ + 2].children[1].ids.search_field.text = '' sqlExecute( "UPDATE sent SET folder = 'trash' WHERE" " ackdata = ?;", str(state.mail_id)) @@ -1468,68 +1956,84 @@ class MailDetail(Screen): self.parent.screens[3].ids.ml.clear_widgets() self.parent.screens[3].loadSent(state.association) elif state.detailPageType == 'inbox': + state.kivyapp.root.ids.sc1.children[ + 2].children[1].ids.search_field.text = '' + self.parent.screens[0].children[2].children[ + 1].ids.search_field.text = '' sqlExecute( "UPDATE inbox SET folder = 'trash' WHERE" " msgid = ?;", str(state.mail_id)) - msg_count_objs.inbox_cnt.badge_text = str(int(state.inbox_count) - 1) + msg_count_objs.inbox_cnt.badge_text = str( + int(state.inbox_count) - 1) state.inbox_count = str(int(state.inbox_count) - 1) self.parent.screens[0].ids.ml.clear_widgets() self.parent.screens[0].loadMessagelist(state.association) + elif state.detailPageType == 'draft': sqlExecute("DELETE FROM sent WHERE ackdata = ?;", str( state.mail_id)) - msg_count_objs.draft_cnt.badge_text = str(int(state.draft_count) - 1) + msg_count_objs.draft_cnt.badge_text = str( + int(state.draft_count) - 1) state.draft_count = str(int(state.draft_count) - 1) self.parent.screens[15].clear_widgets() self.parent.screens[15].add_widget(Draft()) - self.parent.current = 'allmails' if state.is_allmail else state.detailPageType + # self.parent.current = 'allmails' \ + # if state.is_allmail else state.detailPageType if state.detailPageType != 'draft': - msg_count_objs.trash_cnt.badge_text = str(int(state.trash_count) + 1) - msg_count_objs.allmail_cnt.badge_text = str(int(state.all_count) - 1) + msg_count_objs.trash_cnt.badge_text = str( + int(state.trash_count) + 1) + msg_count_objs.allmail_cnt.badge_text = str( + int(state.all_count) - 1) state.trash_count = str(int(state.trash_count) + 1) state.all_count = str(int(state.all_count) - 1) self.parent.screens[4].clear_widgets() self.parent.screens[4].add_widget(Trash()) - self.parent.screens[16].clear_widgets() - self.parent.screens[16].add_widget(Allmails()) - state.kivyapp.back_press() + self.parent.screens[16].ids.ml.clear_widgets() + self.parent.screens[16].init_ui(dt=0) + Clock.schedule_once(self.callback_for_delete, 4) + + def callback_for_delete(self, dt=0): + """Delete method from allmails""" + self.children[0].children[0].active = False + state.kivyapp.set_common_header() + self.parent.current = 'allmails' \ + if state.is_allmail else state.detailPageType + state.detailPageType = '' toast('Deleted') def inbox_reply(self): - """Method used for replying inbox messages.""" + """Reply inbox messages""" data = sqlQuery( "select toaddress, fromaddress, subject, message from inbox where" " msgid = ?;", str(state.mail_id)) - composer_obj = self.parent.screens[2].children[0].ids + composer_obj = self.parent.screens[2].children[1].ids composer_obj.ti.text = data[0][0] composer_obj.btn.text = data[0][0] composer_obj.txt_input.text = data[0][1] composer_obj.subject.text = data[0][2] composer_obj.body.text = '' - state.kivyapp.root.ids.sc3.children[0].ids.rv.data = '' + state.kivyapp.root.ids.sc3.children[1].ids.rv.data = '' self.parent.current = 'create' state.kivyapp.set_navbar_for_composer() - def copy_sent_mail(self): - """Method used for copying sent mail to the composer.""" - pass - def write_msg(self, navApp): - """Method used to write on draft mail.""" + """Write on draft mail""" state.send_draft_mail = state.mail_id - composer_ids = self.parent.parent.parent.parent.ids.sc3.children[0].ids + composer_ids = ( + self.parent.parent.parent.parent.parent.ids.sc3.children[1].ids) composer_ids.ti.text = state.write_msg['from_addr'] composer_ids.btn.text = state.write_msg['from_addr'] composer_ids.txt_input.text = state.write_msg['to_addr'] - composer_ids.subject.text = state.write_msg['subject'] + composer_ids.subject.text = state.write_msg[ + 'subject'] if state.write_msg['subject'] != '(no subject)' else '' composer_ids.body.text = state.write_msg['message'] self.parent.current = 'create' navApp.set_navbar_for_composer() @staticmethod def copy_composer_text(instance, *args): - """This method is used for copying the data from mail detail page""" + """Copy the data from mail detail page""" if len(instance.parent.text.split(':')) > 1: cpy_text = instance.parent.text.split(':')[1].strip() else: @@ -1539,87 +2043,109 @@ class MailDetail(Screen): class MyaddDetailPopup(Popup): - """MyaddDetailPopup pop is used for showing my address detail.""" - + """MyaddDetailPopup pop is used for showing my address detail""" address_label = StringProperty() address = StringProperty() - def __init__(self, **kwargs): - """My Address Details screen setting.""" - # pylint: disable=useless-super-delegation + def __init__(self, **kwargs): # pylint: disable=useless-super-delegation + """My Address Details screen setting""" super(MyaddDetailPopup, self).__init__(**kwargs) def set_address(self, address, label): - """Getting address for displaying details on popup.""" + """Getting address for displaying details on popup""" self.address_label = label self.address = address def send_message_from(self): - """Method used to fill from address of composer autofield.""" + """Method used to fill from address of composer autofield""" + state.kivyapp.set_navbar_for_composer() window_obj = self.parent.children[1].ids - window_obj.sc3.children[0].ids.ti.text = self.address - window_obj.sc3.children[0].ids.btn.text = self.address - window_obj.sc3.children[0].ids.txt_input.text = '' - window_obj.sc3.children[0].ids.subject.text = '' - window_obj.sc3.children[0].ids.body.text = '' + window_obj.sc3.children[1].ids.ti.text = self.address + window_obj.sc3.children[1].ids.btn.text = self.address + window_obj.sc3.children[1].ids.txt_input.text = '' + window_obj.sc3.children[1].ids.subject.text = '' + window_obj.sc3.children[1].ids.body.text = '' window_obj.scr_mngr.current = 'create' self.dismiss() @staticmethod def close_pop(): - """Pop is Canceled.""" + """Pop is Canceled""" toast('Canceled') class AddbookDetailPopup(Popup): - """AddbookDetailPopup pop is used for showing my address detail.""" - + """AddbookDetailPopup pop is used for showing my address detail""" address_label = StringProperty() address = StringProperty() def __init__(self, **kwargs): - """Method used set screen of address detail page.""" + """Set screen of address detail page""" # pylint: disable=useless-super-delegation super(AddbookDetailPopup, self).__init__(**kwargs) def set_addbook_data(self, address, label): - """Getting address book data for detial dipaly.""" + """Getting address book data for detial dipaly""" self.address_label = label self.address = address def update_addbook_label(self, address): - """Updating the label of address book address.""" - if str(self.ids.add_label.text): + """Updating the label of address book address""" + address_list = kivy_helper_search.search_sql(folder="addressbook") + stored_labels = [labels[0] for labels in address_list] + add_dict = dict(address_list) + label = str(self.ids.add_label.text) + if label in stored_labels and self.address == add_dict[label]: + stored_labels.remove(label) + if label and label not in stored_labels: sqlExecute( "UPDATE addressbook SET label = '{}' WHERE" - " address = '{}';".format(str(self.ids.add_label.text), address)) + " address = '{}';".format( + str(self.ids.add_label.text), address)) self.parent.children[1].ids.sc11.ids.ml.clear_widgets() self.parent.children[1].ids.sc11.loadAddresslist(None, 'All', '') self.dismiss() toast('Saved') def send_message_to(self): - """Method used to fill to_address of composer autofield.""" + """Method used to fill to_address of composer autofield""" + state.kivyapp.set_navbar_for_composer() window_obj = self.parent.children[1].ids - window_obj.sc3.children[0].ids.txt_input.text = self.address - window_obj.sc3.children[0].ids.ti.text = '' - window_obj.sc3.children[0].ids.btn.text = 'Select' - window_obj.sc3.children[0].ids.subject.text = '' - window_obj.sc3.children[0].ids.body.text = '' + window_obj.sc3.children[1].ids.txt_input.text = self.address + window_obj.sc3.children[1].ids.ti.text = '' + window_obj.sc3.children[1].ids.btn.text = 'Select' + window_obj.sc3.children[1].ids.subject.text = '' + window_obj.sc3.children[1].ids.body.text = '' window_obj.scr_mngr.current = 'create' self.dismiss() @staticmethod def close_pop(): - """Pop is Canceled.""" + """Pop is Canceled""" toast('Canceled') + def checkLabel_valid(self, instance): + """Checking address label is unique of not""" + entered_label = str(instance.text.strip()) + address_list = kivy_helper_search.search_sql(folder="addressbook") + addr_labels = [labels[0] for labels in address_list] + add_dict = dict(address_list) + if self.address and entered_label in addr_labels \ + and self.address != add_dict[entered_label]: + self.ids.add_label.error = True + self.ids.add_label.helper_text = 'label name already exists.' + elif entered_label: + self.ids.add_label.error = False + else: + self.ids.add_label.error = False + self.ids.add_label.helper_text = 'This field is required' + class ShowQRCode(Screen): - """ShowQRCode Screen uses to show the detail of mails.""" + """ShowQRCode Screen uses to show the detail of mails""" def qrdisplay(self): - """Method used for showing QR Code.""" + """Showing QR Code""" # self.manager.parent.parent.parent.ids.search_bar.clear_widgets() self.ids.qr.clear_widgets() from kivy.garden.qrcode import QRCodeWidget @@ -1629,12 +2155,14 @@ class ShowQRCode(Screen): class Draft(Screen): - """Draft screen is used to show the list of draft messages.""" - + """Draft screen is used to show the list of draft messages""" data = ListProperty() + account = StringProperty() + queryreturn = ListProperty() + has_refreshed = True def __init__(self, *args, **kwargs): - """Method used for storing draft messages.""" + """Method used for storing draft messages""" super(Draft, self).__init__(*args, **kwargs) if state.association == '': if BMConfigParser().addresses(): @@ -1642,60 +2170,27 @@ class Draft(Screen): Clock.schedule_once(self.init_ui, 0) def init_ui(self, dt=0): - """Clock Schdule for method draft accounts.""" + """Clock Schdule for method draft accounts""" self.sentaccounts() print dt def sentaccounts(self): """Load draft accounts.""" - account = state.association - self.loadDraft(account, 'All', '') + self.account = state.association + self.loadDraft() - def loadDraft(self, account, where="", what=""): + def loadDraft(self, where="", what=""): """Load draft list for Draft messages.""" xAddress = 'fromaddress' - queryreturn = kivy_helper_search.search_sql( - xAddress, account, "draft", where, what, False) + self.draftDataQuery(xAddress, where, what) if state.msg_counter_objs: - state.msg_counter_objs.draft_cnt.badge_text = str(len(queryreturn)) - if queryreturn: + state.msg_counter_objs.draft_cnt.badge_text = str( + len(self.queryreturn)) + if self.queryreturn: src_mng_obj = state.kivyapp.root.children[2].children[0].ids - src_mng_obj.draft_cnt.badge_text = str(len(queryreturn)) - state.draft_count = str(len(queryreturn)) - for mail in queryreturn: - third_text = mail[3].replace('\n', ' ') - self.data.append({ - 'text': mail[1].strip(), - 'secondary_text': mail[2][:10] + '...........' if len( - mail[2]) > 10 else mail[2] + '\n' + " " + ( - third_text[:25] + '...!') if len( - third_text) > 25 else third_text, - 'ackdata': mail[5]}) - for item in self.data: - meny = TwoLineAvatarIconListItem( - text='Draft', - secondary_text=item['text'], - theme_text_color='Custom', - text_color=NavigateApp().theme_cls.primary_color) - meny.add_widget(AvatarSampleWidget( - source='./images/avatar.png')) - meny.bind(on_press=partial( - self.draft_detail, item['ackdata'])) - 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='Delete') - del_btn.background_normal = '' - del_btn.background_color = (1, 0, 0, 1) - del_btn.bind(on_press=partial( - self.delete_draft, item['ackdata'])) - carousel.add_widget(del_btn) - carousel.add_widget(meny) - carousel.index = 1 - self.ids.ml.add_widget(carousel) + src_mng_obj.draft_cnt.badge_text = state.draft_count + self.set_mdList() + self.ids.scroll_y.bind(scroll_y=self.check_scroll_y) else: content = MDLabel( font_style='Body1', @@ -1707,8 +2202,76 @@ class Draft(Screen): valign='top') self.ids.ml.add_widget(content) + # pylint: disable=too-many-arguments + def draftDataQuery(self, xAddress, where, what, start_indx=0, end_indx=20): + """This methosd is for retrieving draft messages""" + self.queryreturn = kivy_helper_search.search_sql( + xAddress, + self.account, + "draft", + where, + what, + False, + start_indx, + end_indx) + + def set_mdList(self): + """This method is used to create mdlist""" + data = [] + total_draft_msg = len(self.ids.ml.children) + for mail in self.queryreturn: + third_text = mail[3].replace('\n', ' ') + data.append({ + 'text': mail[1].strip(), + 'secondary_text': mail[2][:10] + '...........' if len( + mail[2]) > 10 else mail[2] + '\n' + " " + ( + third_text[:25] + '...!') if len( + third_text) > 25 else third_text, + 'ackdata': mail[5]}) + for item in data: + meny = TwoLineAvatarIconListItem( + text='Draft', + secondary_text=item['text'], + theme_text_color='Custom', + text_color=NavigateApp().theme_cls.primary_color) + meny.add_widget(AvatarSampleWidget( + source='./images/avatar.png')) + meny.bind(on_press=partial( + self.draft_detail, item['ackdata'])) + 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='Delete') + del_btn.background_normal = '' + del_btn.background_color = (1, 0, 0, 1) + del_btn.bind(on_press=partial( + self.delete_draft, item['ackdata'])) + carousel.add_widget(del_btn) + carousel.add_widget(meny) + carousel.index = 1 + self.ids.ml.add_widget(carousel) + updated_msg = len(self.ids.ml.children) + self.has_refreshed = True if total_draft_msg != updated_msg else False + + def check_scroll_y(self, instance, somethingelse): + """Load data on scroll""" + if self.ids.scroll_y.scroll_y <= -0.0 and self.has_refreshed: + self.ids.scroll_y.scroll_y = 0.06 + total_draft_msg = len(self.ids.ml.children) + self.update_draft_screen_on_scroll(total_draft_msg) + else: + pass + + def update_draft_screen_on_scroll(self, total_draft_msg, where='', what=''): + """Load more data on scroll down""" + self.draftDataQuery('fromaddress', where, what, total_draft_msg, 5) + self.set_mdList() + def draft_detail(self, ackdata, *args): - """Method used to show draft Details.""" + """Show draft Details""" state.detailPageType = 'draft' state.mail_id = ackdata if self.manager: @@ -1720,11 +2283,13 @@ class Draft(Screen): src_mng_obj.current = 'mailDetail' def delete_draft(self, data_index, instance, *args): - """Method used to delete draft message permanently.""" + """Delete draft message permanently""" sqlExecute("DELETE FROM sent WHERE ackdata = ?;", str( data_index)) try: - msg_count_objs = self.parent.parent.parent.parent.children[2].children[0].ids + msg_count_objs = ( + self.parent.parent.parent.parent.parent.parent.children[ + 2].children[0].ids) except Exception: msg_count_objs = self.parent.parent.parent.parent.parent.children[ 2].children[0].ids @@ -1736,11 +2301,9 @@ class Draft(Screen): toast('Deleted') @staticmethod - def draft_msg(src_object): - """Method used for saving draft mails.""" - # pylint: disable=too-many-locals - composer_object = src_object.children[1].children[0].children[ - 0].children[0].children[0].ids + def draft_msg(src_object): # pylint: disable=too-many-locals + """Save draft mails""" + composer_object = state.kivyapp.root.ids.sc3.children[1].ids fromAddress = str(composer_object.ti.text) toAddress = str(composer_object.txt_input.text) subject = str(composer_object.subject.text) @@ -1748,16 +2311,12 @@ class Draft(Screen): encoding = 3 sendMessageToPeople = True if sendMessageToPeople: - from addresses import decodeAddress - status, addressVersionNumber, streamNumber, ripe = decodeAddress(toAddress) - from addresses import addBMIfNotPresent + streamNumber, ripe = decodeAddress(toAddress)[2:] toAddress = addBMIfNotPresent(toAddress) - statusIconColor = 'red' stealthLevel = BMConfigParser().safeGetInt( 'bitmessagesettings', 'ackstealthlevel') from helper_ackPayload import genAckPayload ackdata = genAckPayload(streamNumber, stealthLevel) - t = () sqlExecute( '''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', @@ -1786,18 +2345,20 @@ class Draft(Screen): class CustomSpinner(Spinner): - """This class is used for setting spinner size.""" + """This class is used for setting spinner size""" def __init__(self, *args, **kwargs): - """Method used for setting size of spinner.""" + """Setting size of spinner""" super(CustomSpinner, self).__init__(*args, **kwargs) self.dropdown_cls.max_height = Window.size[1] / 3 class Allmails(Screen): - """all mails Screen uses screen to show widgets of screens.""" - + """All mails Screen uses screen to show widgets of screens""" data = ListProperty() + has_refreshed = True + all_mails = ListProperty() + account = StringProperty() def __init__(self, *args, **kwargs): """Method Parsing the address.""" @@ -1808,53 +2369,24 @@ class Allmails(Screen): Clock.schedule_once(self.init_ui, 0) def init_ui(self, dt=0): - """Clock Schdule for method all mails.""" - self.mailaccounts() + """Clock Schdule for method all mails""" + self.loadMessagelist() print dt - def mailaccounts(self): - """Load all mails for account.""" - account = state.association - self.loadMessagelist(account, 'All', '') - - def loadMessagelist(self, account, where="", what=""): + def loadMessagelist(self): """Load Inbox, Sent anf Draft list of messages.""" - all_mails = sqlQuery( - "SELECT toaddress, fromaddress, subject, message, folder, ackdata As id, DATE(lastactiontime)" - " As actionTime FROM sent WHERE folder = 'sent' UNION" - " SELECT toaddress, fromaddress, subject, message, folder, msgid As id, DATE(received) As" - " actionTime FROM inbox WHERE folder = 'inbox' ORDER BY actionTime DESC") - if all_mails: - state.kivyapp.root.children[2].children[0].ids.allmail_cnt.badge_text = str(len(all_mails)) - state.all_count = str(len(all_mails)) - for item in all_mails: - meny = TwoLineAvatarIconListItem( - text=item[1], - secondary_text=item[2][:50] + '........' if len( - item[2]) >= 50 else ( - item[2] + ',' + item[3].replace('\n', ''))[0:50] + '........', - theme_text_color='Custom', - text_color=NavigateApp().theme_cls.primary_color) - meny.add_widget(AvatarSampleWidget( - source='./images/text_images/{}.png'.format( - avatarImageFirstLetter(item[2].strip())))) - meny.bind(on_press=partial( - self.mail_detail, item[5], item[4])) - 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='Delete') - del_btn.background_normal = '' - del_btn.background_color = (1, 0, 0, 1) - del_btn.bind(on_press=partial( - self.swipe_delete, item[5], item[4])) - carousel.add_widget(del_btn) - carousel.add_widget(meny) - carousel.index = 1 - self.ids.ml.add_widget(carousel) + self.account = state.association + self.allMessageQuery(0, 20) + if self.all_mails: + state.kivyapp.get_inbox_count() + state.kivyapp.get_sent_count() + state.all_count = str( + int(state.sent_count) + int(state.inbox_count)) + state.kivyapp.root.children[2].children[ + 0].ids.allmail_cnt.badge_text = state.all_count + self.set_mdlist() + # self.ids.refresh_layout.bind(scroll_y=self.check_scroll_y) + self.ids.scroll_y.bind(scroll_y=self.check_scroll_y) else: content = MDLabel( font_style='Body1', @@ -1866,8 +2398,70 @@ class Allmails(Screen): valign='top') self.ids.ml.add_widget(content) + def allMessageQuery(self, start_indx, end_indx): + """Retrieving data from inbox or sent both tables""" + self.all_mails = sqlQuery( + "SELECT toaddress, fromaddress, subject, message, folder, ackdata" + " As id, DATE(lastactiontime) As actionTime FROM sent WHERE" + " folder = 'sent' and fromaddress = '{0}'" + " UNION SELECT toaddress, fromaddress, subject, message, folder," + " msgid As id, DATE(received) As actionTime FROM inbox" + " WHERE folder = 'inbox' and toaddress = '{0}'" + " ORDER BY actionTime DESC limit {1}, {2}".format( + self.account, start_indx, end_indx)) + + def set_mdlist(self): + """This method is used to create mdList for allmaills""" + data_exist = len(self.ids.ml.children) + for item in self.all_mails: + meny = TwoLineAvatarIconListItem( + text=item[1], + secondary_text=item[2][:50] + '........' if len( + item[2]) >= 50 else ( + item[2] + ',' + item[3].replace( + '\n', ''))[0:50] + '........', + theme_text_color='Custom', + text_color=NavigateApp().theme_cls.primary_color) + meny.add_widget(AvatarSampleWidget( + source='./images/text_images/{}.png'.format( + avatarImageFirstLetter(item[2].strip())))) + meny.bind(on_press=partial( + self.mail_detail, item[5], item[4])) + 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='Delete') + del_btn.background_normal = '' + del_btn.background_color = (1, 0, 0, 1) + del_btn.bind(on_press=partial( + self.swipe_delete, item[5], item[4])) + carousel.add_widget(del_btn) + carousel.add_widget(meny) + carousel.index = 1 + self.ids.ml.add_widget(carousel) + updated_data = len(self.ids.ml.children) + self.has_refreshed = True if data_exist != updated_data else False + + def check_scroll_y(self, instance, somethingelse): + """Scroll fixed length""" + if self.ids.scroll_y.scroll_y <= -0.00 and self.has_refreshed: + self.ids.scroll_y.scroll_y = .06 + load_more = len(self.ids.ml.children) + self.updating_allmail(load_more) + else: + pass + + def updating_allmail(self, load_more): + """This method is used to update the all mail + listing value on the scroll of screen""" + self.allMessageQuery(load_more, 5) + self.set_mdlist() + def mail_detail(self, unique_id, folder, *args): - """Load sent and inbox mail details.""" + """Load sent and inbox mail details""" state.detailPageType = folder state.is_allmail = True state.mail_id = unique_id @@ -1880,7 +2474,7 @@ class Allmails(Screen): src_mng_obj.current = 'mailDetail' def swipe_delete(self, unique_id, folder, instance, *args): - """Delete inbox mail from all mail listing listing.""" + """Delete inbox mail from all mail listing""" if folder == 'inbox': sqlExecute( "UPDATE inbox SET folder = 'trash' WHERE msgid = ?;", str( @@ -1891,13 +2485,13 @@ class Allmails(Screen): unique_id)) self.ids.ml.remove_widget(instance.parent.parent) try: - msg_count_objs = self.parent.parent.parent.parent.children[ - 2].children[0].ids - nav_lay_obj = self.parent.parent.parent.parent.ids - except Exception: msg_count_objs = self.parent.parent.parent.parent.parent.children[ 2].children[0].ids nav_lay_obj = self.parent.parent.parent.parent.parent.ids + except Exception: + msg_count_objs = self.parent.parent.parent.parent.parent.parent.children[ + 2].children[0].ids + nav_lay_obj = self.parent.parent.parent.parent.parent.parent.ids if folder == 'inbox': msg_count_objs.inbox_cnt.badge_text = str( int(state.inbox_count) - 1) @@ -1918,14 +2512,14 @@ class Allmails(Screen): state.all_count = str(int(state.all_count) - 1) nav_lay_obj.sc5.clear_widgets() nav_lay_obj.sc5.add_widget(Trash()) - nav_lay_obj.sc17.clear_widgets() - nav_lay_obj.sc17.add_widget(Allmails()) + nav_lay_obj.sc17.remove_widget(instance.parent.parent) # pylint: disable=attribute-defined-outside-init def refresh_callback(self, *args): - """Method updates the state of application, While the spinner remains on the screen.""" + """Method updates the state of application, + While the spinner remains on the screen""" def refresh_callback(interval): - """Method used for loading the allmails screen data.""" + """Load the allmails screen data""" self.ids.ml.clear_widgets() self.remove_widget(self.children[1]) try: @@ -1937,32 +2531,51 @@ class Allmails(Screen): self.tick = 0 Clock.schedule_once(refresh_callback, 1) + def set_root_layout(self): + """Setting root layout""" + try: + return self.manager.parent.parent + except Exception: + return state.kivyapp.root.ids.float_box + def avatarImageFirstLetter(letter_string): - """This method is used to the first letter for the avatar image""" - 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] + """This function is used to the first letter for the avatar image""" + if letter_string: + 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: img_latter = '!' - return img_latter class Starred(Screen): - """Starred Screen show widgets of page.""" - + """Starred Screen show widgets of page""" pass class Archieve(Screen): - """Archieve Screen show widgets of page.""" - + """Archieve Screen show widgets of page""" pass class Spam(Screen): - """Spam Screen show widgets of page.""" - + """Spam Screen show widgets of page""" pass + + +class LoadingPopup(Popup): + """Class for loading Popup""" + + def __init__(self, **kwargs): + super(LoadingPopup, self).__init__(**kwargs) + # call dismiss_popup in 2 seconds + Clock.schedule_once(self.dismiss_popup, 0.5) + + def dismiss_popup(self, dt): + """Dismiss popups""" + self.dismiss() diff --git a/src/buildozer.spec b/src/buildozer.spec index 444bf8ca..0dfeb191 100644 --- a/src/buildozer.spec +++ b/src/buildozer.spec @@ -13,7 +13,7 @@ package.domain = org.test source.dir = . # (list) Source files to include (let empty to include all the files) -source.include_exts = py,png,jpg,kv,atlas +source.include_exts = py,png,jpg,kv,atlas,gif,zip # (list) List of inclusions using pattern matching #source.include_patterns = assets/*,images/*.png diff --git a/src/class_singleCleaner.py b/src/class_singleCleaner.py index 0ee7921a..e16ddcf4 100644 --- a/src/class_singleCleaner.py +++ b/src/class_singleCleaner.py @@ -21,12 +21,12 @@ It resends messages when there has been no response: # pylint: disable=relative-import, protected-access import gc import os +from datetime import datetime, timedelta import time import shared import knownnodes import queues -import shared import state import tr from bmconfigparser import BMConfigParser @@ -111,7 +111,7 @@ class singleCleaner(StoppableThread): self.resendPubkeyRequest(toAddress) elif status == 'msgsent': self.resendMsg(ackData) - + deleteTrashMsgPermonantly() try: # Cleanup knownnodes and handle possible severe exception # while writing it to disk @@ -193,3 +193,12 @@ class singleCleaner(StoppableThread): 'updateStatusBar', 'Doing work necessary to again attempt to deliver a message...' )) + + +def deleteTrashMsgPermonantly(): + """This method is used to delete old messages""" + ndays_before_time = datetime.now() - timedelta(days=30) + old_messages = time.mktime(ndays_before_time.timetuple()) + sqlExecute("delete from sent where folder = 'trash' and lastactiontime <= ?;", int(old_messages)) + sqlExecute("delete from inbox where folder = 'trash' and received <= ?;", int(old_messages)) + return diff --git a/src/images/3.zip b/src/images/3.zip new file mode 100644 index 00000000..34d555fe Binary files /dev/null and b/src/images/3.zip differ diff --git a/src/images/loader.gif b/src/images/loader.gif new file mode 100644 index 00000000..29064d57 Binary files /dev/null and b/src/images/loader.gif differ diff --git a/src/images/loader.zip b/src/images/loader.zip new file mode 100644 index 00000000..c80a3a17 Binary files /dev/null and b/src/images/loader.zip differ diff --git a/src/state.py b/src/state.py index add12096..8abd211d 100644 --- a/src/state.py +++ b/src/state.py @@ -121,3 +121,7 @@ in_composer = False write_msg = {} availabe_credit = 0 + +in_sent_method = False + +in_search_mode = False