Skip to content
This repository has been archived by the owner on Apr 30, 2021. It is now read-only.

Check for Update on Application Start (lightweight) #34

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions pkg/xlsform-offline-win.spec
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ exe = EXE(pyz,
a.zipfiles,
a.datas,
[('res\\about.html', os.getcwd() + '\\src\\res\\about.html', 'DATA')],
[('res\\update.html', os.getcwd() + '\\src\\res\\update.html', 'DATA')],
[('pyxform\\validators\\odk_validate\\bin\\ODK_Validate.jar', validate_path, 'DATA')],
[('pyxform\\iana_subtags.txt', iana_path, 'DATA')],
name='ODK-XLSForm-Offline.exe',
Expand Down
60 changes: 56 additions & 4 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,23 @@
import wx
import worker

import update_checker

# TODO pull out all strings
# TODO why is the first button selected

TITLE = 'ODK XLSForm Offline'

VERSION = "2.0.0"

APP_QUIT = 1
APP_ABOUT = 2

MAIN_WINDOW_WIDTH = 475
MAIN_WINDOW_HEIGHT = 620
ABOUT_WINDOW_WIDTH = 360
ABOUT_WINDOW_HEIGHT = 365
UPDATE_WINDOW_WIDTH = 360
UPDATE_WINDOW_HEIGHT = 365
MAX_PATH_LENGTH = 45
HEADER_SPACER = 6
CHOOSE_BORDER = 5
Expand All @@ -34,6 +39,8 @@
MAIN_WINDOW_HEIGHT = 750
ABOUT_WINDOW_WIDTH = 360
ABOUT_WINDOW_HEIGHT = 315
UPDATE_WINDOW_WIDTH = 360
UPDATE_WINDOW_HEIGHT = 315
MAX_PATH_LENGTH = 40
HEADER_SPACER = 0
CHOOSE_BORDER = 1
Expand All @@ -44,6 +51,27 @@
WORKER_PROGRESS = 'WORKER_PROGRESS'
WORKER_PROGRESS_SLEEP = .05

class UpdateAvailableFrame(wx.Frame):
def __init__(self, parent, update_info):
wx.Frame.__init__(self, parent, wx.ID_ANY, title='Update ' + update_info['latest_version'] + ' available',
size=(UPDATE_WINDOW_WIDTH, UPDATE_WINDOW_HEIGHT),
style=wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX)
html = HtmlWindow(self)
html.SetStandardFonts()
update_html_path = ''
if getattr(sys, 'frozen', False):
update_html_path = os.path.join(sys._MEIPASS, 'res', 'update.html')
else:
update_html_path = os.path.join('src', 'res', 'update.html')

update_html_text = ''
with open(update_html_path, 'r') as file:
update_html_text = file.read()

filled_update_html_text = update_html_text.replace('@desc', update_info['update_desc']).replace(
'@download_url', update_info['download_url']).replace('@download_name', update_info['download_name'])

html.SetPage(filled_update_html_text)

class AboutFrame(wx.Frame):
def __init__(self, parent):
Expand All @@ -52,11 +80,20 @@ def __init__(self, parent):
style=wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX)
html = HtmlWindow(self)
html.SetStandardFonts()
about = os.path.join('res','about.html')
about_html_path = os.path.join('res','about.html')

if getattr(sys, 'frozen', False):
html.LoadPage(os.path.join(sys._MEIPASS, about))
about_html_path = os.path.join(sys._MEIPASS, about_html_path)
else:
html.LoadPage(os.path.join('src', about))
about_html_path = os.path.join('src', about_html_path)

about_html_text = ''
with open(about_html_path, 'r') as file:
about_html_text = file.read()

filled_about_html_text = about_html_text.replace('@version', VERSION)

html.SetPage(filled_about_html_text)


class HtmlWindow(wx.html.HtmlWindow):
Expand Down Expand Up @@ -88,6 +125,7 @@ def __init__(self, parent, title):

self.quit_menu_item = wx.MenuItem(self.file_menu, APP_QUIT, '&Quit\tCtrl+Q')
self.about_menu_item = wx.MenuItem(self.help_menu, APP_ABOUT, '&About ' + TITLE)
self.update_window = None

self.file_menu.Append(self.quit_menu_item)
self.help_menu.Append(self.about_menu_item)
Expand Down Expand Up @@ -222,6 +260,9 @@ def __init__(self, parent, title):
self.Centre()
self.Show()

update_checker.evt_update_check_done(self, self.check_update_and_show)
update_checker.UpdateChecker(self, VERSION).start()

@staticmethod
def shorten_string(string, max_length):
if len(string) >= max_length:
Expand Down Expand Up @@ -290,6 +331,8 @@ def on_quit(self, e):
self.Destroy()
if self.about_window:
self.about_window.Close()
if self.update_window:
self.update_window.Close()

def on_about(self, e):
if self.about_window:
Expand All @@ -314,6 +357,15 @@ def on_progress(self, event):
if self.result_thread is not None and self.result_thread.is_alive():
self.status_gauge.Pulse()

def check_update_and_show(self, event):
if self.update_window:
self.update_window.Close()

if event.data['update_available']:
self.update_window = UpdateAvailableFrame(None, event.data)
self.update_window.Centre()
self.update_window.Show()

@staticmethod
def is_java_installed():

Expand Down
2 changes: 1 addition & 1 deletion src/res/about.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<b>ODK is a community-powered project and the community lives on the <a href="https://forum.getodk.org">ODK Forum</a>. Join the forum to get support, request features, meet other ODKers, and contribute to the project!</b>
</p>
<p align="center"><u><small>
<a href="https://github.com/getodk/xlsform-offline/releases/tag/v2.0.0">v2.0.0</a></small></u>
<a href="https://github.com/getodk/xlsform-offline/releases/tag/v@version">v@version</a></small></u>
</p>
</body>
</html>
19 changes: 19 additions & 0 deletions src/res/update.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>

<head>
<title></title>
</head>

<body>
<p>
@desc
<br />
<br />
<br />
<b>Download New Version</b><br />
<a href="@download_url">@download_name</a>
</p>
</body>

</html>
76 changes: 76 additions & 0 deletions src/update_checker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import wx
import sys

import threading
import json
import urllib

GITHUB_RELEASES_API = "https://api.github.com/repos/getodk/xlsform-offline/releases/latest"
GITHUB_MARKDOWN_API = "https://api.github.com/markdown/raw"

OS_MAP = {
'win32': 'windows',
'darwin': 'macos'
}

EVT_UPDATE_CHECKER = wx.NewId()


def evt_update_check_done(win, func):
'''Define Update Check Done Event.'''
win.Connect(-1, -1, EVT_UPDATE_CHECKER, func)


class UpdateCheckDoneEvent(wx.PyEvent):
'''Simple event to check for updates.'''

def __init__(self, data):
'''Init Update Check Done Event.'''
wx.PyEvent.__init__(self)
self.SetEventType(EVT_UPDATE_CHECKER)
self.data = data


class UpdateChecker(threading.Thread):
def __init__(self, parent, current_version):
threading.Thread.__init__(self)
self._parent = parent
self._current_version = current_version

def run(self):
try:
response = urllib.request.urlopen(GITHUB_RELEASES_API)
if response.getcode() == 200:
json_response = json.load(response)
latest_version = json_response["tag_name"]
if latest_version[1:] > self._current_version:
download_url = ''
download_name = ''
for asset in json_response['assets']:
if OS_MAP[sys.platform] in asset['name'].lower():
download_url = asset['browser_download_url']
download_name = asset['name']
break

# second request is for markdown conversion
data = json_response["body"].encode('utf-8')
headers = {'Content-Type': 'text/plain'}

request = urllib.request.Request(url=GITHUB_MARKDOWN_API, data=data, headers=headers)
html_body = urllib.request.urlopen(request).read().decode('utf-8')

wx.PostEvent(self._parent, UpdateCheckDoneEvent({
'update_available': True,
'latest_version': latest_version,
'download_url': download_url,
'download_name': download_name,
'update_desc': html_body
}))
else:
wx.PostEvent(self._parent, UpdateCheckDoneEvent({
'update_available': False
}))
except Exception as ex:
print("EXCEPTION")
print(ex)
pass