Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 140 additions & 3 deletions PortMaster/pylibs/pugscene.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,50 @@
_ = gettext.gettext


def get_startup_warnings(device_info):
"""
Check for unsupported configurations that should warn the user.

Returns a list of (keyword, reason, suggestion) tuples describing each problem.
"""
warnings = []

firmware_suggestion = _('For the best experience, switch to a supported firmware such as muOS or KNULLI.')

# Unsupported firmware checks, most-specific first
if Path('/mnt/SDCARD/spruce/').exists():
warnings.append(('spruce', _('SpruceOS is not supported by PortMaster.'), firmware_suggestion))

try:
if 'CrossMix-OS' in Path('/mnt/SDCARD/autorun.inf').read_text():
warnings.append(('crossmix', _('CrossMix-OS is not supported by PortMaster.'), firmware_suggestion))
except (OSError, UnicodeDecodeError):
pass

# TODO: add checks for NextUI, PakUI when we have unique markers

# Generic catch-all for TrimUI-based OSes we can't identify specifically
if not warnings and Path('/etc/trimui_device.txt').exists():
warnings.append(('trimui', _('Your OS is not supported by PortMaster.'), firmware_suggestion))

# Low RAM check
if device_info.get('ram', 1024) < 1024:
warnings.append(('lowram', _('Your device has less than 1GB of RAM.'), None))

return warnings


def get_next_warning_time():
"""
Returns an ISO date string for when to show the warning again.
"""
import random
import datetime

next_warning = datetime.datetime.now() + datetime.timedelta(days=random.choice([5, 7, 11, 13]))
return next_warning.date().isoformat()


class StringFormatter:
def __init__(self, data_dict):
self.data_dict = data_dict
Expand Down Expand Up @@ -384,6 +428,8 @@ def __init__(self, gui):
self.set_buttons({})

def do_update(self, events):
import datetime

self.scene_deactivate()
self.gui.updated = True

Expand All @@ -395,9 +441,17 @@ def do_update(self, events):
]

else:
self.gui.scenes = [
('root', [MainMenuScene(self.gui)]),
]
warnings = get_startup_warnings(harbourmaster.device_info())
warning_time = cfg_data.get('warning_time', '')

if warnings and warning_time < datetime.datetime.now().date().isoformat():
self.gui.scenes = [
('root', [StartupWarningScene(self.gui, warnings)]),
]
else:
self.gui.scenes = [
('root', [MainMenuScene(self.gui)]),
]

return True

Expand Down Expand Up @@ -451,6 +505,89 @@ def do_update(self, events):
cfg_data['disclaimer'] = True
self.gui.save_config(cfg_data)

self.scene_deactivate()
self.gui.updated = True

warnings = get_startup_warnings(harbourmaster.device_info())
if warnings:
self.gui.scenes = [
('root', [StartupWarningScene(self.gui, warnings)]),
]
else:
self.gui.scenes = [
('root', [MainMenuScene(self.gui)]),
]

return True

if events.was_pressed('B'):
self.button_back()
if self.gui.message_box(
_("Are you sure you want to exit PortMaster?"),
want_cancel=True):

self.gui.do_cancel()
return True


class StartupWarningScene(BaseScene):

def __init__(self, gui, warnings):
super().__init__(gui)
self.scene_title = _("Warning")

## Wait x seconds.
self.warning_wait = 10

self.load_regions("disclaimer", ['disclaimer_text'])

# Build message from warnings: each reason, then suggestions, then common footer
parts = []
suggestions = []
for keyword, reason, suggestion in warnings:
parts.append(reason)
if suggestion is not None and suggestion not in suggestions:
suggestions.append(suggestion)

parts.append(_('Many ports will not work.'))

if suggestions:
parts.append('')
parts.extend(suggestions)

self.tags['disclaimer_text'].text = '\n'.join(parts)
self.tags['disclaimer_text'].fontsize = int(self.tags['disclaimer_text'].fontsize * 1.5)

self.last_elapsed = None

def do_draw(self):
elapsed = self.gui.timers.since('warning_wait') // 1000

elapsed = min(elapsed, self.warning_wait)

if elapsed != self.last_elapsed:
if elapsed < self.warning_wait:
self.tags['button_bar'].bar = [f'Wait {self.warning_wait - elapsed} seconds']
else:
self.set_buttons({'A': _('I Understand'), 'B': _('Quit')})

self.last_elapsed = elapsed

super().do_draw()

def do_update(self, events):
super().do_update(events)

elapsed = self.gui.timers.since('warning_wait') // 1000

elapsed = min(elapsed, self.warning_wait)

if elapsed == self.warning_wait:
if events.was_pressed('A'):
cfg_data = self.gui.get_config()
cfg_data['warning_time'] = get_next_warning_time()
self.gui.save_config(cfg_data)

self.scene_deactivate()
self.gui.updated = True
self.gui.scenes = [
Expand Down