forked from JSKitty/scc-web3
-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Alert refactor * Initial alert refactor * Use createAlert function instead of AlertController * Fix alert animation * Prettier * Clean up and improve key * Add alert test * Change key to improve animations * Prettier * Remove console.logs * Cap alert array at 1000
- Loading branch information
Showing
30 changed files
with
394 additions
and
119 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<script setup> | ||
import { computed, toRefs } from 'vue'; | ||
const props = defineProps({ | ||
message: String, | ||
level: String, | ||
}); | ||
const { message, level } = toRefs(props); | ||
const icon = computed(() => { | ||
switch (level.value) { | ||
case 'warning': | ||
return 'fa-exclamation'; | ||
case 'info': | ||
return 'fa-info'; | ||
case 'success': | ||
return 'fa-check'; | ||
default: | ||
throw new Error('Invalid type'); | ||
} | ||
}); | ||
</script> | ||
|
||
<template> | ||
<div | ||
class="notifyWrapper" | ||
@click="$emit('click')" | ||
:class="{ [level]: true }" | ||
:style="{ opacity: 1 }" | ||
> | ||
<div class="notifyIcon" :class="{ ['notify-' + level]: true }"> | ||
<i class="fas fa-xl" :class="{ [icon]: true }"> </i> | ||
</div> | ||
<div class="notifyText" v-html="message"></div> | ||
</div> | ||
</template> |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
<script setup> | ||
import { useAlerts } from '../composables/use_alerts'; | ||
import { computed, watch, ref } from 'vue'; | ||
import Alert from './Alert.vue'; | ||
const alerts = useAlerts(); | ||
const foldedAlerts = ref([]); | ||
watch(alerts, () => { | ||
const res = []; | ||
let previousAlert; | ||
let count = 1; | ||
const pushAlert = () => { | ||
if (previousAlert) { | ||
const countStr = count === 1 ? '' : ` (x${count})`; | ||
const timeout = | ||
previousAlert.created + previousAlert.timeout - Date.now(); | ||
const show = timeout > 0; | ||
if (!show) return; | ||
const alert = ref({ | ||
...previousAlert, | ||
message: `${previousAlert.message}${countStr}`, | ||
show, | ||
// Store original message so we can use it as key. | ||
// This skips the animation in case of multiple errors | ||
original: previousAlert.message, | ||
}); | ||
res.push(alert); | ||
if (timeout > 0) { | ||
setTimeout(() => { | ||
alert.value.show = false; | ||
}, timeout); | ||
} | ||
} | ||
}; | ||
for (const alert of alerts.alerts) { | ||
if (previousAlert && previousAlert?.message === alert.message) { | ||
count++; | ||
} else { | ||
pushAlert(); | ||
count = 1; | ||
} | ||
previousAlert = alert; | ||
} | ||
pushAlert(); | ||
foldedAlerts.value = res; | ||
}); | ||
</script> | ||
<template> | ||
<transition-group name="alert"> | ||
<div | ||
v-for="alert of foldedAlerts.filter((a) => a.value.show)" | ||
:key="alert.value.original" | ||
> | ||
<Alert | ||
:message="alert.value.message" | ||
:level="alert.value.level" | ||
@click="alert.value.show = false" | ||
/> | ||
</div> | ||
</transition-group> | ||
</template> | ||
<style> | ||
.alert-enter-active, | ||
.alert-leave-active { | ||
transition: all 0.5s ease; | ||
} | ||
.alert-enter-from, | ||
.alert-leave-to { | ||
opacity: 0; | ||
} | ||
</style> |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
export class Alert { | ||
/** | ||
* @type{string} Message of the alert. Can contain <html> | ||
* and must be properly escaped if it contains untrusted input | ||
*/ | ||
message; | ||
|
||
/** | ||
* @type{'success'|'info'|'warning'} Alert level | ||
*/ | ||
level; | ||
|
||
/** | ||
* @type{number} timeout of the alert, in milliseconds | ||
*/ | ||
timeout; | ||
|
||
/** | ||
* @type{number} Time of creation in ms since unix epoch. Defaults to `Date.now()` | ||
*/ | ||
created; | ||
|
||
constructor({ message, level, timeout = 0, created = Date.now() }) { | ||
this.message = message; | ||
this.level = level; | ||
this.timeout = timeout; | ||
this.created = created; | ||
} | ||
} | ||
|
||
export class AlertController { | ||
/** | ||
* @type{Alert[]} | ||
*/ | ||
#alerts = []; | ||
|
||
/** | ||
* @param{((alert: Alert)=>void)[]} array of subscribers | ||
*/ | ||
#subscribers = []; | ||
|
||
/** | ||
* @returns the array of alerts | ||
* DO NOT PUSH TO THIS ARRAY. Use `createAlert` or `addAlert` instead | ||
*/ | ||
getAlerts() { | ||
return this.#alerts; | ||
} | ||
|
||
/** | ||
* Create a custom GUI Alert popup | ||
* | ||
* ### Do NOT display arbitrary / external errors: | ||
* - The use of `.innerHTML` allows for input styling at this cost. | ||
* @param {'success'|'info'|'warning'} type - The alert level | ||
* @param {string} message - The message to relay to the user | ||
* @param {number?} timeout - The time in `ms` until the alert expires (Defaults to never expiring) | ||
*/ | ||
createAlert(level, message, timeout = 0) { | ||
this.addAlert(new Alert({ level, message, timeout })); | ||
} | ||
|
||
/** | ||
* @param {Alert} alert - alert to add | ||
*/ | ||
addAlert(alert) { | ||
this.#alerts.push(alert); | ||
this.#alerts.splice(0, this.#alerts.length - 1000); | ||
for (const sub of this.#subscribers) { | ||
// Notify subscribers of the new alert | ||
sub(alert); | ||
} | ||
} | ||
|
||
/** | ||
* @param {(alert: Alert) => void} When a new alert is created, calls the `fn` callback | ||
*/ | ||
subscribe(fn) { | ||
this.#subscribers.push(fn); | ||
} | ||
|
||
static #instance = new AlertController(); | ||
|
||
static getInstance() { | ||
return this.#instance; | ||
} | ||
} | ||
|
||
/** | ||
* Create a custom GUI Alert popup | ||
* | ||
* ### Do NOT display arbitrary / external errors: | ||
* - The use of `.innerHTML` allows for input styling at this cost. | ||
* @param {'success'|'info'|'warning'} type - The alert level | ||
* @param {string} message - The message to relay to the user | ||
* @param {number?} [timeout] - The time in `ms` until the alert expires (Defaults to never expiring) | ||
*/ | ||
export function createAlert(type, message, timeout = 0) { | ||
const alertController = AlertController.getInstance(); | ||
return alertController.createAlert(type, message, timeout); | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { ref } from 'vue'; | ||
import { defineStore } from 'pinia'; | ||
import { AlertController } from '../alerts/alert.js'; | ||
|
||
export const useAlerts = defineStore('alerts', () => { | ||
const alerts = ref([]); | ||
|
||
const alertController = AlertController.getInstance(); | ||
|
||
/** | ||
* Create a custom GUI Alert popup | ||
* | ||
* ### Do NOT display arbitrary / external errors: | ||
* - The use of `.innerHTML` allows for input styling at this cost. | ||
* @param {'success'|'info'|'warning'} type - The alert level | ||
* @param {string} message - The message to relay to the user | ||
* @param {number?} timeout - The time in `ms` until the alert expires (Defaults to never expiring) | ||
*/ | ||
const createAlert = (type, message, timeout) => { | ||
alertController.createAlert(type, message, timeout); | ||
}; | ||
|
||
alertController.subscribe(() => { | ||
alerts.value = [...alertController.getAlerts()]; | ||
}); | ||
|
||
return { | ||
alerts, | ||
createAlert, | ||
}; | ||
}); |
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Oops, something went wrong.