Last active
April 8, 2023 19:32
-
-
Save johnatandias/6ae5ecd052f714c0787763703e8f2557 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A simple broadcast class created in a "Reactive" model | |
* @constructor | |
* @template T t | |
*/ | |
export class Subject<T> { | |
_changeObservers: { (param: T): void; }[] = []; | |
/** | |
* Subscribe to listener new messages about this subject | |
* @public | |
* @memberof Subject | |
* @param {function(t: T)} fn function passed as parameter | |
*/ | |
subscribe = (fn: (T) => void) => { | |
this._changeObservers.push(fn); | |
}; | |
/** | |
* Remove subscription about this subject | |
* It's a best practice unsubscribe in the app dispose life cycle | |
* @public | |
* @memberof Subject | |
* @param {function(t: T)} fn function passed as parameter | |
*/ | |
unsubscribe = (fn: (T) => void) => { | |
this._changeObservers = this | |
._changeObservers | |
.filter((item) => { | |
if (item !== fn) return item; | |
}); | |
}; | |
/** | |
* Emits a new value on this stream | |
* @param {T} newObject | |
* @memberof Subject | |
*/ | |
emit = (newObject: T) => { | |
this._changeObservers.forEach((observer) => observer(newObject)); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Subject } from "@kaios/apis"; | |
export interface ToastRequest { | |
/** Text to display on Toast */ | |
text: string; | |
/** Delay to keep on the screen */ | |
delay?: number | |
}; | |
export interface ToastItem extends ToastRequest { removed: boolean }; | |
class ToastSystemClass { | |
/** A change subject listener */ | |
public onchange = new Subject<ToastItem>(); | |
// A FIFO queue | |
private queue: ToastRequest[] = []; | |
// a simple semaphore to skip Toast process | |
private processing = false; | |
// Delay between Toasts | |
private delayBetween = 1000; | |
// Internal Toast process | |
private display = () => { | |
// indicate that system is in process | |
this.processing = true; | |
// since there is no items on queue, release the process | |
if (this.queue.length === 0) { | |
this.processing = false; | |
// clean up listeners | |
//this.onchange.emit(null); | |
return; | |
} | |
// FIFO queue, pop tha last Toast on queue to be the next | |
const nextToast: ToastItem = { ...this.queue.pop(), removed: false }; | |
// emit a new Toast from the system | |
this.onchange.emit(nextToast); | |
setTimeout(() => { | |
// Immutable approach | |
// Flag this Toast to be removed from the screen | |
const changed: ToastItem = { ...nextToast, removed: true }; | |
this.onchange.emit(changed); | |
}, nextToast.delay); | |
// Schedule the next check | |
setTimeout(() => this.display(), nextToast.delay + this.delayBetween); | |
} | |
/** | |
* Show/Schedule a new Toast on screen | |
* Keep in mind the multiple Toasts wiprocessingl be schedule in a queue | |
* | |
* The default delay is 3s seconds | |
*/ | |
public show = (request: ToastRequest) => { | |
if (request === null) throw new Error("ToastRequest can not be null"); | |
request.delay = request.delay || 3000; | |
this.queue.push(request); | |
// skip since we are already processing Toasts | |
if (this.processing) | |
return; | |
else | |
// call internally to display a new Toast | |
this.display(); | |
} | |
} | |
/** | |
* ### Toast System | |
* | |
* #### Sample | |
* | |
* ```typescript | |
* import {ToastSystem} from '../systems/Toast.system'; | |
* | |
* // create a Toast request | |
* const Toast: Toastrequest = { | |
* text: "Hey dude!", | |
* delay: 3500 | |
* }; | |
* | |
* // Queue a new Toast | |
* ToastSystem.show(Toast); | |
* | |
* ``` | |
*/ | |
export const ToastSystem = new ToastSystemClass() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Text } from '@kaios/kcomponents'; | |
import React, { useEffect, useState } from 'react'; | |
import css from './toast.css'; | |
import { ToastItem, ToastSystem } from './toast.system'; | |
export const Toast = (): JSX.Element | null => { | |
useEffect(() => { | |
// Component mounted | |
ToastSystem.onchange.subscribe(onChange); | |
// Destroying component | |
return function onDestroy() { | |
ToastSystem.onchange.unsubscribe(onChange); | |
} | |
}, []); | |
const [Toast, setToast] = useState<ToastItem>(null); | |
const onChange = (Toast) => setToast(Toast); | |
// skip non Toasts | |
if (!Toast) return null; | |
// Conditional apply removed class | |
const stateClass = Toast.removed ? css.leave : css.enter; | |
return <Text text={Toast.text} className={` ${css.container} ${stateClass}`} />; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment