Skip to content

Commit

Permalink
refactor / improve notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
ianharrigan committed Dec 7, 2023
1 parent e4113b7 commit fb02576
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 44 deletions.
41 changes: 41 additions & 0 deletions haxe/ui/animation/AnimationSequence.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package haxe.ui.animation;

class AnimationSequence {
public var onComplete:Void->Void = null;
public var builders:Array<AnimationBuilder> = [];

private var _activeBuilders:Array<AnimationBuilder>;

public function new() {

}

public function add(builder:AnimationBuilder) {
builders.push(builder);
}

private function onAnimationComplete() {
_activeBuilders.pop();
if (_activeBuilders.length == 0) {
if (onComplete != null) {
onComplete();
}
}
}

public function play() {
if (builders.length == 0) {
if (onComplete != null) {
onComplete();
}
return;
}
_activeBuilders = builders.copy();
for (builder in builders) {
builder.onComplete = onAnimationComplete;
}
for (builder in builders) {
builder.play();
}
}
}
23 changes: 23 additions & 0 deletions haxe/ui/events/NotificationEvent.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package haxe.ui.events;

import haxe.ui.notifications.Notification;

class NotificationEvent extends UIEvent {
public static final SHOWN:EventType<ScrollEvent> = EventType.name("notificationshown");
public static final HIDDEN:EventType<ScrollEvent> = EventType.name("notificationhidden");
public static final ACTION:EventType<ScrollEvent> = EventType.name("notificationaction");

public var notification:Notification = null;

public override function clone():NotificationEvent {
var c:NotificationEvent = new NotificationEvent(this.type);
c.notification = this.notification;
c.type = this.type;
c.bubble = this.bubble;
c.target = this.target;
c.data = this.data;
c.canceled = this.canceled;
postClone(c);
return c;
}
}
22 changes: 20 additions & 2 deletions haxe/ui/notifications/Notification.hx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package haxe.ui.notifications;

import haxe.ui.components.Button;
import haxe.ui.containers.VBox;
import haxe.ui.events.MouseEvent;
import haxe.ui.events.NotificationEvent;
import haxe.ui.notifications.NotificationData.NotificationActionData;

@:xml('
<vbox>
Expand Down Expand Up @@ -70,13 +73,28 @@ class Notification extends VBox {
actionsFooter.hide();
} else {
actionsContainer.removeAllComponents();
for (actionText in _notificationData.actions) {
for (actionData in _notificationData.actions) {
var button = new Button();
button.text = actionText;
button.text = actionData.text;
button.icon = actionData.icon;
button.userData = actionData;
button.registerEvent(MouseEvent.CLICK, onActionButton);
actionsContainer.addComponent(button);
}
actionsFooter.show();
}
return value;
}

private function onActionButton(event:MouseEvent) {
var event = new NotificationEvent(NotificationEvent.ACTION);
event.notification = this;
dispatch(event);
NotificationManager.instance.dispatch(event, this);

var actionData:NotificationActionData = event.target.userData;
if (actionData.callback != null) {
actionData.callback(actionData);
}
}
}
10 changes: 9 additions & 1 deletion haxe/ui/notifications/NotificationData.hx
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
package haxe.ui.notifications;

import haxe.ui.util.Variant;

typedef NotificationData = {
var body:String;
@:optional var title:String;
@:optional var icon:String;
@:optional var actions:Array<String>;
@:optional var actions:Array<NotificationActionData>;
@:optional var expiryMs:Int;
@:optional var type:NotificationType;
@:optional var styleNames:String;
}

typedef NotificationActionData = {
@:optional var text:String;
@:optional var icon:Variant;
@:optional var callback:NotificationActionData->Void;
}
91 changes: 50 additions & 41 deletions haxe/ui/notifications/NotificationManager.hx
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package haxe.ui.notifications;

import haxe.ui.util.Timer;
import haxe.ui.Toolkit;
import haxe.ui.animation.AnimationBuilder;
import haxe.ui.animation.AnimationSequence;
import haxe.ui.core.Screen;
import haxe.ui.events.NotificationEvent;
import haxe.ui.events.UIEvent;
import haxe.ui.util.EventDispatcher;
import haxe.ui.util.Timer;

using haxe.ui.animation.AnimationTools;

class NotificationManager {
class NotificationManager extends EventDispatcher<NotificationEvent> {
private static var _instance:NotificationManager;
public static var instance(get, null):NotificationManager;
private static function get_instance():NotificationManager {
Expand All @@ -24,9 +28,7 @@ class NotificationManager {
private static var DEFAULT_EXPIRY:Int = 3000;

public var maxNotifications:Int = -1;

private function new() {
}
public var animationFn:Array<Notification>->Array<AnimationBuilder> = AnimateFromBottom;

private var _timer:Timer = null;
private function startTimer() {
Expand Down Expand Up @@ -70,8 +72,8 @@ class NotificationManager {
if (notificationData.expiryMs == null) {
notificationData.expiryMs = DEFAULT_EXPIRY;
}
} else {
notificationData.expiryMs = -1; // we'll assume if there are actions we dont want it to expire
} else if (notificationData.expiryMs == null) {
notificationData.expiryMs = -1; // we'll assume if there are actions we dont want it to expire by default
}

var notification = new Notification();
Expand Down Expand Up @@ -113,6 +115,11 @@ class NotificationManager {

_isAnimating = true;
notification.fadeOut(function () {
var event = new NotificationEvent(NotificationEvent.HIDDEN);
event.notification = notification;
notification.dispatch(event);
dispatch(event, notification);

_isAnimating = false;
_currentNotifications.remove(notification);
Screen.instance.removeComponent(notification);
Expand All @@ -129,10 +136,9 @@ class NotificationManager {
});
}
}
_currentNotifications.insert(0, notification);

notification.opacity = 0;
Screen.instance.addComponent(notification);
notification.validateNow();
Toolkit.callLater(function () {
notification.validateNow();
var scx = Screen.instance.width;
Expand All @@ -146,6 +152,12 @@ class NotificationManager {
notification.left = scx - notification.width - GUTTER_SIZE;
notification.top = baseline - notification.height;

var event = new NotificationEvent(NotificationEvent.SHOWN);
event.notification = notification;
notification.dispatch(event);
dispatch(event, notification);

_currentNotifications.insert(0, notification);
positionNotifications();
});

Expand All @@ -163,47 +175,44 @@ class NotificationManager {
if (_isAnimating == true) {
return;
}

_isAnimating = true;

var sequence = new AnimationSequence();
var builders = animationFn(_currentNotifications);
for (builder in builders) {
sequence.add(builder);
}

sequence.onComplete = function() {
_isAnimating = false;
if (_removeQueue.length > 0) {
popNotification(_removeQueue.shift());
} else if (_addQueue.length > 0) {
pushNotification(_addQueue.shift());
}
}
sequence.play();
}

public static function AnimateFromBottom(notifications:Array<Notification>):Array<AnimationBuilder> {
var builders = [];

var scy = Screen.instance.height;
var baseline = scy - GUTTER_SIZE;
var baselineY = scy - GUTTER_SIZE;

var builder:AnimationBuilder = null;
var builders:Array<AnimationBuilder> = [];
for (notification in _currentNotifications) {
builder = new AnimationBuilder(notification);
for (notification in notifications) {
var builder = new AnimationBuilder(notification);
builder.setPosition(0, "top", Std.int(notification.top), true);
builder.setPosition(100, "top", Std.int(baseline - notification.height), true);
builder.setPosition(100, "top", Std.int(baselineY - notification.height), true);
if (notification.opacity == 0) {
builder.setPosition(0, "opacity", 0, true);
builder.setPosition(100, "opacity", 1, true);
}
builders.push(builder);
baseline -= (notification.height + SPACING);
}

if (builders.length > 0) {
builder.onComplete = function () {
_isAnimating = false;
/*
if (_addQueue.length > 0) {
pushNotification(_addQueue.shift());
} else if (_removeQueue.length > 0) {
popNotification(_removeQueue.shift());
}
*/
if (_removeQueue.length > 0) {
popNotification(_removeQueue.shift());
}
if (_addQueue.length > 0) {
pushNotification(_addQueue.shift());
}
}

for (builder in builders) {
builder.play();
}
} else {
_isAnimating = false;
baselineY -= (notification.height + SPACING);
}

return builders;
}
}

0 comments on commit fb02576

Please sign in to comment.