From 2fddbe36a6c4920eb9747fe4b2ad09ef516d83e3 Mon Sep 17 00:00:00 2001 From: MathNodes Date: Mon, 17 Oct 2022 21:13:27 -0400 Subject: [PATCH] Pip release v0.10.3.2 --- CHANGELOG.md | 20 ++++++++ setup.py | 2 +- src/cli/sentinel.py | 6 +-- src/cli/wallet.py | 29 ++++++----- src/kv/meile.kv | 51 +++++++++++++------ src/main/main.py | 9 ++-- src/meile_gui.egg-info/PKG-INFO | 2 +- src/ui/screens.py | 54 ++++++++++++++++---- src/ui/widgets.py | 87 +++++++++++++++++++++------------ 9 files changed, 183 insertions(+), 77 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89186af0..85bb0b7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ CHANGELOG ======================== +# v0.10.3-pip (17/10/2022) +* NEW: Clickable Pin map with total node listings +* NEW: Refresh button in wallet screen +* NEW: Copy button for seed phrase on wallet restore/create +* NEW: Visible and draggable scrollbar on nodes +* CHANGE: Removed elevation from node cards as shadow rendering is broken in Kivy 1.1.1 +* CHANGE: Padding on "wallet" in the fiat interface (binary release only) +* CHANGE: Using rpc.mathnodes.com:443 for subs fixing country block of port 4444 +* FIX: Connection switch bug that displayed random on in nodes when refreshing leading to confusion +* FIX: Poor resize of screen with node cards. Resizes fast and clean +* FIX: Offline node consumed/allocated data progress bar and status text +* FIX: Divide by 0 bug and convert 0.00B to float + + +# v0.10.2-pip (11/10/2022) +* FIX: Python 3.8 kivy_garden error + +# v0.10.1-pip (09/10/2022) +* FIX: Minor bug fixes + # v0.10.0-pip (09/10/2022) * NEW: Meile Pin map of country nodes * NEW: Clickable pins diff --git a/setup.py b/setup.py index 1f689532..a92628d7 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ setup( name='meile-gui', - version='0.10.2', + version='0.10.3.2', description='Meile dVPN powered by the Sentinel Network', long_description=readme, long_description_content_type="text/markdown", diff --git a/src/cli/sentinel.py b/src/cli/sentinel.py index 032aa670..0c79b811 100644 --- a/src/cli/sentinel.py +++ b/src/cli/sentinel.py @@ -137,7 +137,7 @@ def get_subscriptions(self, ADDRESS): SubsNodesInfo = [] SubsFinalResult = [] print("Geting Subscriptions... %s" % ADDRESS) - subsCMD = [sentinelcli, "query", "subscriptions", "--node", "https://rpc.mathnodes.com:4444", "--status", "Active", "--limit", "100", "--address" ,ADDRESS] + subsCMD = [sentinelcli, "query", "subscriptions", "--node", "https://rpc.mathnodes.com:443", "--status", "Active", "--limit", "100", "--address" ,ADDRESS] proc = Popen(subsCMD, stdout=PIPE) k=1 @@ -171,8 +171,8 @@ def get_subscriptions(self, ADDRESS): FinalSubsKeys[3] : SubsResult[SubsInfoKeys[6]][k], FinalSubsKeys[4] : SubsResult[SubsInfoKeys[7]][k], FinalSubsKeys[5] : None, - FinalSubsKeys[6] : "0B", - FinalSubsKeys[7] : "0B" + FinalSubsKeys[6] : "0.00GB", + FinalSubsKeys[7] : "0.00B" }) print("Sub not found in list") k += 1 diff --git a/src/cli/wallet.py b/src/cli/wallet.py index d0fbea33..04800267 100644 --- a/src/cli/wallet.py +++ b/src/cli/wallet.py @@ -82,7 +82,7 @@ def create(self, wallet_name, keyring_passphrase, seed_phrase): else: WalletDict['address'] = addy_seed[1].split(":")[-1].lstrip().rstrip() WalletDict['seed'] = lines[-1].lstrip().rstrip().replace('\n', '') - remove(WALLETINFO) + #remove(WALLETINFO) return WalletDict else: @@ -95,19 +95,24 @@ def subscribe(self, KEYNAME, NODE, DEPOSIT): CONFIG = MeileGuiConfig.read_configuration(MeileGuiConfig, MeileGuiConfig.CONFFILE) PASSWORD = CONFIG['wallet'].get('password', '') - ofile = open(SUBSCRIBEINFO, "wb") + ofile = open(SUBSCRIBEINFO, "wb") + + if not KEYNAME: + return (False, 1337) SCMD = "%s tx subscription subscribe-to-node --yes --keyring-backend file --keyring-dir %s --gas-prices 0.1udvpn --chain-id sentinelhub-2 --node https://rpc.mathnodes.com:443 --from '%s' '%s' %s" % (sentinelcli, KEYRINGDIR, KEYNAME, NODE, DEPOSIT) - - child = pexpect.spawn(SCMD) - child.logfile = ofile - - child.expect(".*") - child.sendline(PASSWORD) - child.expect(pexpect.EOF) - - ofile.flush() - ofile.close() + try: + child = pexpect.spawn(SCMD) + child.logfile = ofile + + child.expect(".*") + child.sendline(PASSWORD) + child.expect(pexpect.EOF) + + ofile.flush() + ofile.close() + except pexpect.exceptions.TIMEOUT: + return (False, 1415) return self.ParseSubscribe(self) diff --git a/src/kv/meile.kv b/src/kv/meile.kv index 01137d54..b19f48ee 100644 --- a/src/kv/meile.kv +++ b/src/kv/meile.kv @@ -207,7 +207,10 @@ WindowManager: normal_color: app.theme_cls.accent_color MDFloatLayout: - + MDRaisedButton: + pos_hint: {'x' : .1 , 'top': .9 } + text: "REFRESH" + on_release: root.refresh_wallet() Image: source: root.get_qr_code_address() pos_hint: {'x': 0, 'top': 1} @@ -308,6 +311,7 @@ WindowManager: pos_hint: {"center_x": .5, "center_y": .80} MDLabel: + id: seed_hint text: "Leave blank if creating a new wallet" theme_text_color: "Custom" text_color: get_color_from_hex("#4a4545") @@ -351,7 +355,7 @@ WindowManager: MDRaisedButton: id: restore_wallet_button - text: "Restore" + text: "Create" pos_hint: {"center_x": .5, "center_y": .4} on_press: root.restore_wallet_from_seed_phrase() @@ -359,6 +363,8 @@ WindowManager: : key_viewclass: "viewclass" + bar_width: dp(12) + scroll_type: ["bars", "content"] canvas.before: Color: rgba: get_color_from_hex("#fccf62") @@ -376,6 +382,7 @@ WindowManager: spacing: 15 padding: 4,4,4,4 + @@ -408,8 +415,6 @@ WindowManager: padding: 10,10 border_radius: 20 radius: [10] - shadow_pos: 0,0 - elevation: 42 num_text: "" country_text: " " source_image: " " @@ -455,8 +460,6 @@ WindowManager: padding: 10,10 border_radius: 20 radius: [10] - shadow_pos: 0,0 - elevation: 42 md_bg_color: get_color_from_hex("#0d021b") moniker_text: "." country_text: "." @@ -542,8 +545,6 @@ WindowManager: padding: 10,10 border_radius: 20 radius: [10] - shadow_pos: 0,0 - elevation: 42 md_bg_color: get_color_from_hex("#0d021b") moniker_text: "." sub_id_text: " " @@ -563,7 +564,7 @@ WindowManager: font_style: "H6" font_size: "24sp" text_color: get_color_from_hex("#fcb711") - width: "300dp" + width: "350dp" pos_hint: {"x" : 0, "top" : 1.45} size_hint_x: None Image: @@ -635,7 +636,7 @@ WindowManager: text_color: 1,1,1,1 pos_hint: {"x" : 0.2, "top" : 1.03 } MDProgressBar: - value: root.get_data_used(root.allocated_text, root.consumed_text) + value: root.get_data_used(root.allocated_text, root.consumed_text, root.address_text) color: app.theme_cls.accent_color #back_color: get_color_from_hex("#ffffff") pos_hint: {"x" : 0, "top" : .475 } @@ -650,6 +651,7 @@ WindowManager: text_color: 1,1,1,1 pos_hint: {"x" : .5, "top" : 1.03 } Switch: + id: node_switch canvas.after: Color: rgb: get_color_from_hex("#fab40c") @@ -702,9 +704,10 @@ WindowManager: MDTextField: id: seed_phrase + multiline: True hint_text: root.hint_text text: root.text - password: False + password: True icon_left: "key-variant" mode: "rectangle" @@ -747,7 +750,7 @@ WindowManager: id: wallet_password hint_text: root.hint_text text: root.text - password: False + password: True icon_left: "key-variant" mode: "rectangle" @@ -788,19 +791,33 @@ WindowManager: orientation: "vertical" - spacing: "4dp" + spacing: "15dp" size_hint_y: None - height: "260dp" + height: "300dp" seed_phrase: "" wallet_address: "" wallet_password: "" wallet_name: "" - + padding: 0,10,0,10 MDTextField: multiline: True hint_text: "Mnemonic Seed" text: root.seed_phrase readonly: True + MDBoxLayout: + id: seed_box + orientation: "horizontal" + padding: 0,0,20,20 + spacing: "20dp" + MDRaisedButton: + id: copy_seed_button + text: "COPY SEED" + font_size: dp(9) + pos_hint: {"center_x": .1, "center_y": .5} + on_press: root.copy_seed_phrase() + size_hint: None, None + size: 15,10 + MDTextField: hint_text: "Wallet" mode: "rectangle" @@ -934,7 +951,7 @@ WindowManager: text_color: get_color_from_hex("#fcb711") MDLabel: font_name: "Roboto-Bold" - text: "v1.0.0" + text: "v1.1.1" font_size: "16sp" size_hint_y: .1 width: dp(500) @@ -1073,6 +1090,8 @@ WindowManager: md_bg_color: get_color_from_hex("#FFB908") height: "70dp" type: "top" + padding: 0,20,0,0 + MDTextField: hint_text: "Address" diff --git a/src/main/main.py b/src/main/main.py index f7561127..7e67735d 100644 --- a/src/main/main.py +++ b/src/main/main.py @@ -19,6 +19,7 @@ class MyMainApp(MDApp): title = "Meile dVPN" icon = MeileConfig.resource_path("../imgs/icon.png") + manager = None def __init__(self,**kwargs): super(MyMainApp,self).__init__(**kwargs) from kivy.core.window import Window @@ -48,18 +49,18 @@ def build(self): kv = Builder.load_file(MeileConfig.resource_path("../kv/meile.kv")) - manager = WindowManager() + self.manager = WindowManager() theme = ThemeManager() self.theme_cls.primary_palette = "Amber" self.theme_cls.theme_style = "Dark" #self.theme_cls.disabled_primary_color = "Amber" self.theme_cls.accent_palette = "DeepPurple" #self.theme_cls.opposite_disabled_primary_color = "Amber" - manager.add_widget(PreLoadWindow(name=WindowNames.PRELOAD)) + self.manager.add_widget(PreLoadWindow(name=WindowNames.PRELOAD)) #manager.add_widget(MainWindow(name=WindowNames.MAIN_WINDOW)) - manager.add_widget(WalletRestore(name=WindowNames.WALLET_RESTORE)) + #manager.add_widget(WalletRestore(name=WindowNames.WALLET_RESTORE)) #MeileConfig.read_configuration(MeileGuiConfig, MeileGuiConfig.CONFFILE) - return manager + return self.manager diff --git a/src/meile_gui.egg-info/PKG-INFO b/src/meile_gui.egg-info/PKG-INFO index 8f4f38b9..59faf21d 100644 --- a/src/meile_gui.egg-info/PKG-INFO +++ b/src/meile_gui.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: meile-gui -Version: 0.10.2 +Version: 0.10.3.2 Summary: Meile dVPN powered by the Sentinel Network Home-page: https://meile.app Author: MathNodes diff --git a/src/ui/screens.py b/src/ui/screens.py index 14e22d14..2139b5d7 100644 --- a/src/ui/screens.py +++ b/src/ui/screens.py @@ -47,6 +47,21 @@ class WalletRestore(Screen): screemanager = ObjectProperty() dialog = None + + def __init__(self, **kwargs): + super(WalletRestore, self).__init__() + self.build() + + def build(self): + if Meile.app.manager.get_screen(WindowNames.MAIN_WINDOW).NewWallet: + self.ids.seed.opacity = 0 + self.ids.seed_hint.opacity = 0 + self.ids.restore_wallet_button.text = "Create" + else: + self.ids.seed.opacity = 1 + self.ids.seed_hint.opacity = 1 + self.ids.restore_wallet_button.text = "Restore" + def restore_wallet_from_seed_phrase(self): if not self.manager.get_screen(WindowNames.WALLET_RESTORE).ids.name.ids.wallet_name.text and not self.manager.get_screen(WindowNames.WALLET_RESTORE).ids.password.ids.wallet_password.text: self.manager.get_screen(WindowNames.WALLET_RESTORE).ids.wallet_name_warning.opacity = 1 @@ -102,7 +117,7 @@ def switch_window(self, inst): self.dialog = None except AttributeError: pass - + Meile.app.root.remove_widget(self) Meile.app.root.transition = SlideTransition(direction = "down") Meile.app.root.current = WindowNames.MAIN_WINDOW @@ -176,7 +191,7 @@ def __init__(self, **kwargs): self.CreateWarpConfig() # Schedule the functions to be called every n seconds - Clock.schedule_once(partial(self.NodeTree.get_nodes, "12s"), 3) + Clock.schedule_once(partial(self.NodeTree.get_nodes, "11s"), 3) Clock.schedule_interval(self.update_status_text, 0.6) def CreateWarpConfig(self): @@ -280,6 +295,8 @@ class MainWindow(Screen): Sort = SortOptions[0] MeileMap = None MeileMapBuilt = False + NodeSwitch = {"node" : None, "switch" : False} + NewWallet = False def __init__(self, node_tree, **kwargs): #Builder.load_file("./src/kivy/meile.kv") @@ -484,6 +501,7 @@ def disconnect_from_node(self): print("Disconnect RTNCODE: %s" % returncode) self.get_ip_address(None) self.set_protected_icon(False, "") + self.NodeSwitch = {"node" : None, "switch" : False} except Exception as e: print(str(e)) self.dialog = None @@ -517,11 +535,18 @@ def wallet_dialog(self): text="Wallet Restore/Create", md_bg_color=get_color_from_hex("#0d021b"), buttons=[ + MDFlatButton( + text="CREATE", + theme_text_color="Custom", + text_color=(1,1,1,1), + on_release=partial(self.wallet_restore, True) + ), + MDRaisedButton( - text="Restore/Create", + text="RESTORE", theme_text_color="Custom", text_color=(1,1,1,1), - on_release= self.wallet_restore + on_release=partial(self.wallet_restore, False) ), ], ) @@ -529,6 +554,18 @@ def wallet_dialog(self): else: self.build_wallet_interface() + def wallet_restore(self, NewWallet, inst): + if NewWallet: + self.NewWallet = True + else: + self.NewWallet = False + + self.dialog.dismiss() + self.dialog = None + Meile.app.manager.add_widget(WalletRestore(name=WindowNames.WALLET_RESTORE)) + Meile.app.root.transition = SlideTransition(direction = "right") + Meile.app.root.current = WindowNames.WALLET_RESTORE + def build_wallet_interface(self): Meile.app.root.add_widget(WalletScreen(name=WindowNames.WALLET, ADDRESS=self.address)) Meile.app.root.transition = SlideTransition(direction = "up") @@ -538,12 +575,6 @@ def build_help_screen_interface(self): Meile.app.root.add_widget(HelpScreen(name=WindowNames.HELP)) Meile.app.root.transition = SlideTransition(direction = "left") Meile.app.root.current = WindowNames.HELP - - def wallet_restore(self, inst): - self.dialog.dismiss() - self.dialog = None - self.switch_window(WindowNames.WALLET_RESTORE) - def wallet_create(self, inst): pass @@ -813,6 +844,9 @@ def build(self, dt): Wallet = HandleWalletFunctions() self.SetBalances(Wallet.get_balance(self.ADDRESS)) + def refresh_wallet(self): + self.build(None) + def open_fiat_interface(self): pass diff --git a/src/ui/widgets.py b/src/ui/widgets.py index dd9d5974..73afcccb 100644 --- a/src/ui/widgets.py +++ b/src/ui/widgets.py @@ -1,6 +1,7 @@ from kivy.properties import BooleanProperty, StringProperty from kivy.uix.recycleview.views import RecycleDataViewBehavior from kivy.uix.label import Label +from kivymd.uix.label import MDLabel from kivymd.uix.card import MDCard from kivymd.uix.dialog import MDDialog from kivymd.uix.button import MDFlatButton, MDRaisedButton,MDFillRoundFlatButton @@ -16,7 +17,8 @@ from kivymd.theming import ThemableBehavior from kivy.core.window import Window from kivymd.uix.behaviors.elevation import RectangularElevationBehavior - +from kivy.core.clipboard import Clipboard +from kivy.animation import Animation from functools import partial @@ -24,6 +26,7 @@ import requests import re from os import path +from subprocess import Popen, TimeoutExpired from cli.sentinel import IBCCOINS #from ui.interfaces import SubscribeContent @@ -34,13 +37,29 @@ class WalletInfoContent(BoxLayout): def __init__(self, seed_phrase, name, address, password, **kwargs): - super(WalletInfoContent, self).__init__() + super(WalletInfoContent, self).__init__(**kwargs) self.seed_phrase = seed_phrase self.wallet_address = address self.wallet_password = password self.wallet_name = name - + def copy_seed_phrase(self): + Clipboard.copy(self.seed_phrase) + self.AnimateCopiedLabel() + + def AnimateCopiedLabel(self): + label = MDLabel(text='Seed Phrase Copied!', + theme_text_color="Custom", + text_color=get_color_from_hex("#fcb711"), + font_size=dp(10)) + self.ids.seed_box.add_widget(label) + + anim = Animation(color=(0, 0, 0, 1), duration=.2) + Animation(color=get_color_from_hex("#fcb711"), duration=.2) + anim.repeat = True + + anim.start(label) + + return label class SubscribeContent(BoxLayout): @@ -146,7 +165,7 @@ def apply_selection(self, rv, index, is_selected): class NodeRV(RecycleView): pass -class OnHoverMDRaisedButton(MDRaisedButton, ThemableBehavior, HoverBehavior): +class OnHoverMDRaisedButton(MDRaisedButton, HoverBehavior): def on_enter(self, *args): self.md_bg_color = get_color_from_hex("#fad783") Window.set_system_cursor('arrow') @@ -269,7 +288,7 @@ def subscribe(self, subscribe_dialog, *kwargs): else: self.dialog.dismiss() self.dialog = MDDialog( - title="Error: %s" % returncode[1], + title="Error: %s" % "No wallet found!" if returncode[1] == 1337 else returncode[1], md_bg_color=get_color_from_hex("#0d021b"), buttons=[ MDFlatButton( @@ -326,15 +345,18 @@ def closeDialog(self, inst): except Exception as e: print(str(e)) return - - - + class RecycleViewSubRow(MDCard,RectangularElevationBehavior): text = StringProperty() dialog = None - def get_data_used(self, allocated, consumed): + def get_data_used(self, allocated, consumed, node_address): try: + if Meile.app.root.get_screen(WindowNames.MAIN_WINDOW).NodeSwitch['node'] == node_address: + self.ids.node_switch.active = True + else: + self.ids.node_switch.active = False + allocated = float(allocated.replace('GB','')) if "GB" in consumed: @@ -347,6 +369,10 @@ def get_data_used(self, allocated, consumed): consumed = 0.0 else: consumed = float(float(re.findall(r'[0-9]+\.[0-9]+', consumed)[0].replace('B', '')) / (1024*1024*1024)) + if allocated == 0: + self.ids.consumed_data.text = "0%" + return 0 + self.ids.consumed_data.text = str(round(float(float(consumed/allocated)*100),2)) + "%" return float(float(consumed/allocated)*100) except Exception as e: @@ -357,6 +383,7 @@ def add_loading_popup(self, title_text): self.dialog = None self.dialog = MDDialog(title=title_text,md_bg_color=get_color_from_hex("#0d021b")) self.dialog.open() + def remove_loading_widget(self): try: self.dialog.dismiss() @@ -364,17 +391,28 @@ def remove_loading_widget(self): except Exception as e: print(str(e)) return + @delayable - def connect_to_node(self, ID, naddress, moniker, switchValue): - if switchValue == False: + def connect_to_node(self, ID, naddress, moniker, switchValue, *kwargs): + + ''' + These two conditionals are needed to check + and verify the switch in the sub card and ensure + it is on, when connected, and does not try to disconnect + or reconnect. + ''' + if Meile.app.root.get_screen(WindowNames.MAIN_WINDOW).NodeSwitch['switch'] and naddress == Meile.app.root.get_screen(WindowNames.MAIN_WINDOW).NodeSwitch['node'] and not switchValue: + print("DISCONNECTING!!!") Meile.app.root.get_screen(WindowNames.MAIN_WINDOW).disconnect_from_node() + return True + + if Meile.app.root.get_screen(WindowNames.MAIN_WINDOW).CONNECTED: return self.add_loading_popup("Connecting...") yield 0.6 UUID = Meile.app.root.get_screen(WindowNames.PRELOAD).UUID - print(UUID) try: SERVER_ADDRESS = "https://aimokoivunen.mathnodes.com:5000" API_ENDPOINT = "/api/ping" @@ -391,6 +429,11 @@ def connect_to_node(self, ID, naddress, moniker, switchValue): connected = HandleWalletFunctions.connect(HandleWalletFunctions, ID, naddress) if connected: + Meile.app.root.get_screen(WindowNames.MAIN_WINDOW).NodeSwitch['node'] = naddress + Meile.app.root.get_screen(WindowNames.MAIN_WINDOW).NodeSwitch['switch'] = True + print("%s, %s" % (Meile.app.root.get_screen(WindowNames.MAIN_WINDOW).NodeSwitch['node'], + Meile.app.root.get_screen(WindowNames.MAIN_WINDOW).NodeSwitch['switch'] + )) self.remove_loading_widget() self.dialog = MDDialog( title="Connected!", @@ -462,10 +505,7 @@ def change_dns(self): yield 1.2 Meile.app.root.get_screen(WindowNames.MAIN_WINDOW).get_ip_address(None) self.remove_loading_widget() - -# In case I go for word wrapping bigger textfield. - - + class MDMapCountryButton(MDFillRoundFlatButton,ThemableBehavior, HoverBehavior): def on_enter(self, *args): self.md_bg_color = get_color_from_hex("#fcb711") @@ -477,17 +517,4 @@ def on_leave(self, *args): self.md_bg_color = get_color_from_hex("#0d021b") Window.set_system_cursor('arrow') - -''' -class MySeedBox(MDTextFieldRect): - - def insert_text(self, substring, from_undo=False): - - line_length = 65 - seq = ' '.join(substring.split()) - - if len(seq) > line_length: - seq = '\n'.join([seq[i:i+line_length] for i in range(0, len(seq), line_length)]) - - return super(MySeedtBox, self).insert_text(seq, from_undo=from_undo) -''' + \ No newline at end of file