You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

193 lines
6.2 KiB

import sys
import requests
from kivy import base, utils
from kivy.clock import Clock
from kivy.core.window import Window
from kivy.factory import Factory
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.utils import platform
from electrum.base_crash_reporter import BaseCrashReporter
from electrum.i18n import _
Builder.load_string('''
<CrashReporter@Popup>
BoxLayout:
orientation: 'vertical'
Label:
id: crash_message
text_size: root.width, None
size: self.texture_size
size_hint: None, None
Label:
id: request_help_message
text_size: root.width*.95, None
size: self.texture_size
size_hint: None, None
BoxLayout:
size_hint: 1, 0.1
Button:
text: 'Show report contents'
height: '48dp'
size_hint: 1, None
on_press: root.show_contents()
BoxLayout:
size_hint: 1, 0.1
Label:
id: describe_error_message
text_size: root.width, None
size: self.texture_size
size_hint: None, None
TextInput:
id: user_message
size_hint: 1, 0.3
BoxLayout:
size_hint: 1, 0.7
BoxLayout:
size_hint: 1, None
height: '48dp'
orientation: 'horizontal'
Button:
height: '48dp'
text: 'Send'
on_release: root.send_report()
Button:
text: 'Never'
on_release: root.show_never()
Button:
text: 'Not now'
on_release: root.dismiss()
<CrashReportDetails@Popup>
BoxLayout:
orientation: 'vertical'
ScrollView:
do_scroll_x: False
Label:
id: contents
text_size: root.width*.9, None
size: self.texture_size
size_hint: None, None
Button:
text: 'Close'
height: '48dp'
size_hint: 1, None
on_release: root.dismiss()
''')
class CrashReporter(BaseCrashReporter, Factory.Popup):
issue_template = """[b]Traceback[/b]
[i]{traceback}[/i]
[b]Additional information[/b]
* Electrum version: {app_version}
* Operating system: {os}
* Wallet type: {wallet_type}
* Locale: {locale}
"""
def __init__(self, main_window, exctype, value, tb):
BaseCrashReporter.__init__(self, exctype, value, tb)
Factory.Popup.__init__(self)
self.main_window = main_window
self.title = BaseCrashReporter.CRASH_TITLE
self.title_size = "24sp"
self.ids.crash_message.text = BaseCrashReporter.CRASH_MESSAGE
self.ids.request_help_message.text = BaseCrashReporter.REQUEST_HELP_MESSAGE
self.ids.describe_error_message.text = BaseCrashReporter.DESCRIBE_ERROR_MESSAGE
def show_contents(self):
details = CrashReportDetails(self.get_report_string())
details.open()
def show_popup(self, title, content):
popup = Factory.Popup(title=title,
content=Label(text=content, text_size=(Window.size[0] * 3/4, None)),
size_hint=(3/4, 3/4))
popup.open()
def send_report(self):
try:
response = BaseCrashReporter.send_report(self, "/crash.json").json()
except requests.exceptions.RequestException:
self.show_popup(_('Unable to send report'), _("Please check your network connection."))
else:
self.show_popup(_('Report sent'), response["text"])
if response["location"]:
self.open_url(response["location"])
self.dismiss()
def open_url(self, url):
if platform != 'android':
return
from jnius import autoclass, cast
String = autoclass("java.lang.String")
url = String(url)
PythonActivity = autoclass('org.kivy.android.PythonActivity')
activity = PythonActivity.mActivity
Intent = autoclass('android.content.Intent')
Uri = autoclass('android.net.Uri')
browserIntent = Intent()
# This line crashes the app:
# browserIntent.setAction(Intent.ACTION_VIEW)
# Luckily we don't need it because the OS is smart enough to recognize the URL
browserIntent.setData(Uri.parse(url))
currentActivity = cast('android.app.Activity', activity)
currentActivity.startActivity(browserIntent)
def show_never(self):
self.main_window.electrum_config.set_key(BaseCrashReporter.config_key, False)
self.dismiss()
def get_user_description(self):
return self.ids.user_message.text
def get_wallet_type(self):
return self.main_window.wallet.wallet_type
def get_os_version(self):
if utils.platform is not "android":
return utils.platform
import jnius
bv = jnius.autoclass('android.os.Build$VERSION')
b = jnius.autoclass('android.os.Build')
return "Android {} on {} {} ({})".format(bv.RELEASE, b.BRAND, b.DEVICE, b.DISPLAY)
class CrashReportDetails(Factory.Popup):
def __init__(self, text):
Factory.Popup.__init__(self)
self.title = "Report Details"
self.ids.contents.text = text
print(text)
class ExceptionHook(base.ExceptionHandler):
def __init__(self, main_window):
super().__init__()
self.main_window = main_window
if not main_window.electrum_config.get(BaseCrashReporter.config_key, default=True):
return
# For exceptions in Kivy:
base.ExceptionManager.add_handler(self)
# For everything else:
sys.excepthook = lambda exctype, value, tb: self.handle_exception(value)
def handle_exception(self, _inst):
exc_info = sys.exc_info()
# Check if this is an exception from within the exception handler:
import traceback
for item in traceback.extract_tb(exc_info[2]):
if item.filename.endswith("crash_reporter.py"):
return
e = CrashReporter(self.main_window, *exc_info)
# Open in main thread:
Clock.schedule_once(lambda _: e.open(), 0)
return base.ExceptionManager.PASS