Skip to content

Commit

Permalink
fix(notifications): notifications not getting closed nor updated
Browse files Browse the repository at this point in the history
  • Loading branch information
sassanh committed Aug 25, 2024
1 parent 09713b1 commit 158dc51
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 100 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Version 0.15.11

- fix(notifications): notifications not getting closed nor updated

## Version 0.15.10

- refactor(core): use `dpkg-query` instead of `apt` python api as loading `Cache` in `apt` is slow and use it in docker service
Expand Down
46 changes: 23 additions & 23 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "ubo-app"
version = "0.15.10"
version = "0.15.11"
description = "Ubo main app, running on device initialization. A platform for running other apps."
authors = ["Sassan Haradji <sassanh@gmail.com>"]
license = "Apache-2.0"
Expand Down Expand Up @@ -61,13 +61,13 @@ optional = true

[tool.poetry.group.dev.dependencies]
poethepoet = "^0.24.4"
pyright = "^1.1.376"
pyright = "^1.1.377"
pytest = "^8.0.0"
pytest-asyncio = "^0.23.5.post1"
pytest-cov = "^4.1.0"
pytest-timeout = "^2.3.1"
pytest-xdist = "^3.5.0"
ruff = "^0.6.0"
ruff = "^0.6.2"
tenacity = "^8.2.3"
toml = "^0.10.2"
pytest-mock = "^3.14.0"
Expand Down
4 changes: 2 additions & 2 deletions ubo_app/menu_app/menu_central.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@ def __init__(self: MenuAppCentral, **kwargs: object) -> None:
super().__init__(**kwargs)
self.menu_widget = MenuWidgetWithHomePage(render_surroundings=True)

_self = weakref.ref(self)

self.menu_widget.bind(page_index=self.handle_page_index_change)
self.menu_widget.bind(current_menu=self.handle_page_index_change)

_self = weakref.ref(self)

@autorun(lambda state: state.main.menu)
@debounce(0.1, DebounceOptions(leading=True, trailing=True, time_window=0.1))
@mainthread
Expand Down
126 changes: 75 additions & 51 deletions ubo_app/menu_app/menu_notification_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from __future__ import annotations

import functools
import weakref
from dataclasses import replace
from typing import TYPE_CHECKING

Expand Down Expand Up @@ -31,6 +32,12 @@
from ubo_gui.menu.menu_widget import MenuWidget


class NotificationReference:
def __init__(self: NotificationReference, notification: Notification) -> None:
self.value = notification
self.is_initialized = False


class MenuNotificationHandler(UboApp):
menu_widget: MenuWidget

Expand All @@ -47,12 +54,15 @@ def display_notification( # noqa: C901
and stack_item.application.notification_id == event.notification.id
for stack_item in self.menu_widget.stack
)
) or event.notification.display_type is NotificationDisplayType.BACKGROUND:
) or (
event.notification.display_type is NotificationDisplayType.BACKGROUND
and event.index is None
):
return

subscriptions = []

notification = event.notification
notification = NotificationReference(event.notification)
is_closed = False

@mainthread
Expand All @@ -65,65 +75,85 @@ def close(_: object = None) -> None:
unsubscribe()
notification_application.unbind(on_close=close)
dispatch(CloseApplicationEvent(application=notification_application))
if notification.dismiss_on_close:
dispatch(NotificationsClearAction(notification=notification))
if notification.on_close:
notification.on_close()

notification_application = NotificationWidget(
notification_title=notification.title,
content=notification.content,
icon=notification.icon,
color=notification.color,
items=self._notification_items(notification, close),
title=f'Notification ({event.index + 1}/{event.count})'
if event.index is not None
else ' ',
)
notification_application.notification_id = notification.id

dispatch(OpenApplicationEvent(application=notification_application))
if notification.value.dismiss_on_close:
dispatch(NotificationsClearAction(notification=notification.value))
if notification.value.on_close:
notification.value.on_close()

if notification.display_type is NotificationDisplayType.FLASH:
Clock.schedule_once(close, notification.flash_time)

notification_application.bind(on_close=close)

@mainthread
def clear_notification(event: NotificationsClearEvent) -> None:
if event.notification == notification:
close()

_self = weakref.ref(self)

def renew_notification(event: NotificationsDisplayEvent) -> None:
nonlocal notification
if event.notification.id == notification.id:
notification = event.notification
self._update_notification_widget(notification_application, event, close)
self = _self()
if self is None:
return
if event.notification.id == notification.value.id:
notification.value = event.notification
self._update_notification_widget(
notification_application,
event,
notification,
close,
)

if event.notification.extra_information and (
not notification.is_initialized
or event.notification.id is None
or event.notification.id != notification.value.id
or not notification.value.extra_information
or event.notification.extra_information
!= notification.value.extra_information
):
notification.is_initialized = True
dispatch(
VoiceReadTextAction(
text=event.notification.extra_information.text,
piper_text=event.notification.extra_information.piper_text,
picovoice_text=event.notification.extra_information.picovoice_text,
),
)

notification_application = NotificationWidget(items=[None] * PAGE_MAX_ITEMS)
notification_application.notification_id = notification.value.id

if (
notification.value.display_type is NotificationDisplayType.FLASH
and event.index is None
):
Clock.schedule_once(close, notification.value.flash_time)

notification_application.bind(on_close=close)

subscriptions.append(
subscribe_event(
NotificationsClearEvent,
clear_notification,
),
)
if notification.id is not None:
if notification.value.id is not None:
subscriptions.append(
subscribe_event(
NotificationsDisplayEvent,
renew_notification,
keep_ref=False,
),
)

renew_notification(event)

dispatch(OpenApplicationEvent(application=notification_application))

def _notification_items(
self: MenuNotificationHandler,
notification: Notification,
notification: NotificationReference,
close: Callable[[], None],
) -> list[NotificationActionItem | None]:
def dismiss(_: object = None) -> None:
close()
if not notification.dismiss_on_close:
dispatch(NotificationsClearAction(notification=notification))
if not notification.value.dismiss_on_close:
dispatch(NotificationsClearAction(notification=notification.value))

def run_notification_action(action: NotificationActionItem) -> None:
result = action.action()
Expand All @@ -135,15 +165,8 @@ def run_notification_action(action: NotificationActionItem) -> None:

items: list[NotificationActionItem | None] = []

if notification.extra_information:
text = notification.extra_information.text
dispatch(
VoiceReadTextAction(
text=notification.extra_information.text,
piper_text=notification.extra_information.piper_text,
picovoice_text=notification.extra_information.picovoice_text,
),
)
if notification.value.extra_information:
text = notification.value.extra_information.text

def open_info() -> None:
info_application = NotificationInfo(text=text)
Expand All @@ -166,10 +189,10 @@ def open_info() -> None:
is_short=True,
action=functools.partial(run_notification_action, action),
)
for action in notification.actions
for action in notification.value.actions
]

if notification.dismissable:
if notification.value.dismissable:
items.append(
NotificationActionItem(
icon='󰆴',
Expand All @@ -187,14 +210,15 @@ def _update_notification_widget(
self: MenuNotificationHandler,
notification_application: NotificationWidget,
event: NotificationsDisplayEvent,
notification: NotificationReference,
close: Callable[[], None],
) -> None:
notification_application.notification_title = event.notification.title
notification_application.content = event.notification.content
notification_application.icon = event.notification.icon
notification_application.color = event.notification.color
notification_application.notification_title = notification.value.title
notification_application.content = notification.value.content
notification_application.icon = notification.value.icon
notification_application.color = notification.value.color
notification_application.items = self._notification_items(
event.notification,
notification,
close,
)
notification_application.title = (
Expand Down
11 changes: 9 additions & 2 deletions ubo_app/services/010-notifications/reducer.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from redux import (
BaseEvent,
CompleteReducerResult,
FinishAction,
InitAction,
InitializationActionError,
ReducerResult,
Expand Down Expand Up @@ -148,6 +149,12 @@ def reducer(
for notification in to_be_removed
],
)
if isinstance(action, NotificationsClearAllAction):
return replace(state, notifications=[], unread_count=0)
if isinstance(action, NotificationsClearAllAction | FinishAction):
return CompleteReducerResult(
state=replace(state, notifications=[], unread_count=0),
events=[
NotificationsClearEvent(notification=notification)
for notification in state.notifications
],
)
return state
12 changes: 2 additions & 10 deletions ubo_app/store/core/_menus.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import functools
import socket
from dataclasses import replace
from datetime import UTC, datetime
from typing import TYPE_CHECKING

Expand All @@ -21,11 +20,7 @@
SettingsCategory,
)
from ubo_app.store.main import autorun, dispatch
from ubo_app.store.services.notifications import (
Notification,
NotificationDisplayType,
NotificationsDisplayEvent,
)
from ubo_app.store.services.notifications import Notification, NotificationsDisplayEvent
from ubo_app.store.update_manager.utils import (
BASE_IMAGE,
CURRENT_VERSION,
Expand Down Expand Up @@ -116,10 +111,7 @@ def notifications_menu_items(notifications: Sequence[Notification]) -> list[Item
action=functools.partial(
dispatch,
NotificationsDisplayEvent(
notification=replace(
notification,
display_type=NotificationDisplayType.STICKY,
),
notification=notification,
index=index,
count=len(notifications),
),
Expand Down
1 change: 1 addition & 0 deletions ubo_app/store/update_manager/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from redux import BaseAction, BaseEvent

UPDATE_MANAGER_NOTIFICATION_ID = 'ubo:update_manager'
UPDATE_MANAGER_SECOND_PHASE_NOTIFICATION_ID = 'ubo:update_manager:phase-2'


class UpdateManagerAction(BaseAction): ...
Expand Down
Loading

0 comments on commit 158dc51

Please sign in to comment.