diff --git a/[core]/es_extended/client/functions.lua b/[core]/es_extended/client/functions.lua index 953296d2..535c24e7 100644 --- a/[core]/es_extended/client/functions.lua +++ b/[core]/es_extended/client/functions.lua @@ -154,9 +154,10 @@ end ---@param notifyType? string The type of notification to show ---@param length? number The length of the notification ---@param title? string The title of the notification +---@param position? string The position of the notification ---@return nil -function ESX.ShowNotification(message, notifyType, length, title) - return IsResourceFound('esx_notify') and exports['esx_notify']:Notify(notifyType, length, message, title) +function ESX.ShowNotification(message, notifyType, length, title, position) + return IsResourceFound('esx_notify') and exports['esx_notify']:Notify(notifyType, length, message, title, position) end function ESX.TextUI(...) diff --git a/[core]/es_extended/server/classes/player.lua b/[core]/es_extended/server/classes/player.lua index a2359e0a..ee8f0a3e 100644 --- a/[core]/es_extended/server/classes/player.lua +++ b/[core]/es_extended/server/classes/player.lua @@ -103,7 +103,7 @@ ---@field setMeta fun(index: string, value: any, subValue?: any) # Set metadata value(s). ---@field clearMeta fun(index: string, subValues?: string|table) # Clear metadata value(s). --- Notification Functions ----@field showNotification fun(msg: string, notifyType?: string, length?: number) # Show a simple notification. +---@field showNotification fun(msg: string, notifyType?: string, length?: number, title?: string, position?: string) # Show a simple notification. ---@field showAdvancedNotification fun(sender: string, subject: string, msg: string, textureDict: string, iconType: string, flash: boolean, saveToBrief: boolean, hudColorIndex: number) # Show advanced notification. ---@field showHelpNotification fun(msg: string, thisFrame?: boolean, beep?: boolean, duration?: number) # Show help notification. --- Misc Functions @@ -793,11 +793,10 @@ function CreateExtendedPlayer(playerId, identifier, ssn, group, accounts, invent return nil, nil end - function self.showNotification(msg, notifyType, length) - self.triggerEvent("esx:showNotification", msg, notifyType, length) + function self.showNotification(msg, notifyType, length, title, position) + self.triggerEvent("esx:showNotification", msg, notifyType, length, title, position) end - function self.showAdvancedNotification(sender, subject, msg, textureDict, iconType, flash, saveToBrief, hudColorIndex) self.triggerEvent("esx:showAdvancedNotification", sender, subject, msg, textureDict, iconType, flash, saveToBrief, hudColorIndex) end diff --git a/[core]/esx_notify/Config.lua b/[core]/esx_notify/Config.lua index e56a8901..21b40d59 100644 --- a/[core]/esx_notify/Config.lua +++ b/[core]/esx_notify/Config.lua @@ -1,3 +1,4 @@ Config = {} -Config.notificationSoundEnabled = true \ No newline at end of file +Config.notificationSoundEnabled = true +Config.position = "middle-right" -- top-right, top-left, top-middle, bottom-right, bottom-left, bottom-middle, middle-left, middle-right \ No newline at end of file diff --git a/[core]/esx_notify/Notify.lua b/[core]/esx_notify/Notify.lua index 0061974e..d690fbd6 100644 --- a/[core]/esx_notify/Notify.lua +++ b/[core]/esx_notify/Notify.lua @@ -1,16 +1,28 @@ local Debug = ESX.GetConfig().EnableDebug +local possiblePosition = { + ["top-right"] = true, + ["top-left"] = true, + ["top-middle"] = true, + ["bottom-right"] = true, + ["bottom-left"] = true, + ["bottom-middle"] = true, + ["middle-left"] = true, + ["middle-right"] = true +} ---@param notificatonType string the notification type ---@param length number the length of the notification ---@param message any the message :D ---@param title string optional title for the notification -local function Notify(notificatonType, length, message, title) +---@param position string optional position for the notification +local function Notify(notificatonType, length, message, title, position) if Debug then print("1 ".. tostring(notificatonType)) print("2 "..tostring(length)) print("3 "..message) print("4 "..tostring(title)) + print("5 "..tostring(position)) end if type(notificatonType) ~= "string" then @@ -21,11 +33,16 @@ local function Notify(notificatonType, length, message, title) length = 3000 end + if not possiblePosition[position] then + position = Config.position or "middle-right" + end + if Debug then - print("5 ".. tostring(notificatonType)) - print("6 "..tostring(length)) - print("7 "..message) - print("8 "..tostring(title)) + print("6 ".. tostring(notificatonType)) + print("7 "..tostring(length)) + print("8 "..message) + print("9 "..tostring(title)) + print("10 "..tostring(position)) end if type(message) == "string" then @@ -37,7 +54,8 @@ local function Notify(notificatonType, length, message, title) length = length or 5000, message = message or "ESX-Notify", title = title or "New Notification", - notificationSoundEnabled = Config.notificationSoundEnabled + position = position, + notificationSoundEnabled = Config.notificationSoundEnabled or false })) end @@ -67,5 +85,5 @@ if Debug then RegisterCommand("notify4", function() ESX.ShowNotification("You Did something ~r~WRONG~s~!", "warning", 3000, "~y~Warning~s~") - end) -end + end) +end \ No newline at end of file diff --git a/[core]/esx_notify/nui/css/style.css b/[core]/esx_notify/nui/css/style.css index acb1b142..6d02c9a1 100644 --- a/[core]/esx_notify/nui/css/style.css +++ b/[core]/esx_notify/nui/css/style.css @@ -1,196 +1,337 @@ @import url("https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600&display=swap"); :root { - --background: rgba(20, 20, 20, 0.9); - --text-color: #ffffff; - --text-secondary: rgba(255, 255, 255, 0.7); - --success-color: #2ecc71; - --success-border: #1f9c4d; - --error-color: #e74c3c; - --error-border: #c0392b; - --info-color: #3498db; - --info-border: #2980b9; - --warning-color: #f39c12; - --warning-border: #d35400; + --background: rgba(20, 20, 20, 0.9); + --text-color: #ffffff; + --text-secondary: rgba(255, 255, 255, 0.7); + --success-color: #2ecc71; + --success-border: #1f9c4d; + --error-color: #e74c3c; + --error-border: #c0392b; + --info-color: #3498db; + --info-border: #2980b9; + --warning-color: #f39c12; + --warning-border: #d35400; } * { - margin: 0; - padding: 0; - box-sizing: border-box; + margin: 0; + padding: 0; + box-sizing: border-box; } body { - width: 100vw; - height: 100vh; - font-family: "Poppins", sans-serif; - overflow: hidden; + width: 100vw; + height: 100vh; + font-family: "Poppins", sans-serif; + overflow: hidden; } -#root { - position: fixed; - right: 2rem; - top: 50%; - transform: translateY(-50%); - display: flex; - flex-direction: column; - align-items: flex-end; - gap: 10px; - max-height: 80vh; - z-index: 1000; +.notification-container { + position: fixed; + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 10px; + max-height: 80vh; + z-index: 1000; +} + +#middle-right { + right: 2rem; + top: 50%; + transform: translateY(-50%); +} + +#middle-left { + left: 2rem; + top: 50%; + transform: translateY(-50%); +} + +#top-right { + right: 2rem; + top: 2rem; +} + +#top-left { + left: 2rem; + top: 2rem; +} + +#top-middle { + left: 50%; + top: 2rem; + transform: translateX(-50%); +} + +#bottom-right { + right: 2rem; + bottom: 2rem; +} + +#bottom-left { + left: 2rem; + bottom: 2rem; +} + +#bottom-middle { + left: 50%; + bottom: 2rem; + transform: translateX(-50%); } .notify { - display: flex; - width: 300px; - background: var(--background); - border-radius: 8px; - overflow: hidden; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); - position: relative; - padding: 12px; - align-items: center; - border-left: 4px solid #555; + display: flex; + width: 300px; + background: var(--background); + border-radius: 8px; + overflow: hidden; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + position: relative; + padding: 12px; + align-items: center; + border-left: 4px solid #555; } .notify-success { - border-left-color: var(--success-border); + border-left-color: var(--success-border); } .notify-error { - border-left-color: var(--error-border); + border-left-color: var(--error-border); } .notify-info { - border-left-color: var(--info-border); + border-left-color: var(--info-border); } .notify-warning { - border-left-color: var(--warning-border); + border-left-color: var(--warning-border); } .notify-icon-container { - margin-right: 12px; - display: flex; - align-items: center; - justify-content: center; + margin-right: 12px; + display: flex; + align-items: center; + justify-content: center; } .hexagon { - position: relative; - width: 40px; - height: 40px; - display: flex; - align-items: center; - justify-content: center; - clip-path: polygon(50% 0%, 95% 25%, 95% 75%, 50% 100%, 5% 75%, 5% 25%); - background: linear-gradient(145deg, var(--icon-color), rgba(0, 0, 0, 0.7)); - box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); + position: relative; + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + clip-path: polygon(50% 0%, 95% 25%, 95% 75%, 50% 100%, 5% 75%, 5% 25%); + background: linear-gradient(145deg, var(--icon-color), rgba(0, 0, 0, 0.7)); + box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); } .hexagon::before { - content: ""; - position: absolute; - top: 3px; - left: 3px; - right: 3px; - bottom: 3px; - background: var(--background); - clip-path: polygon(50% 0%, 95% 25%, 95% 75%, 50% 100%, 5% 75%, 5% 25%); - z-index: 1; + content: ""; + position: absolute; + top: 3px; + left: 3px; + right: 3px; + bottom: 3px; + background: var(--background); + clip-path: polygon(50% 0%, 95% 25%, 95% 75%, 50% 100%, 5% 75%, 5% 25%); + z-index: 1; } .hexagon::after { - content: ""; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: linear-gradient(145deg, var(--icon-color) 10%, transparent 70%); - opacity: 0.4; - clip-path: polygon(50% 0%, 95% 25%, 95% 75%, 50% 100%, 5% 75%, 5% 25%); - z-index: 2; + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: linear-gradient(145deg, var(--icon-color) 10%, transparent 70%); + opacity: 0.4; + clip-path: polygon(50% 0%, 95% 25%, 95% 75%, 50% 100%, 5% 75%, 5% 25%); + z-index: 2; } .hexagon .material-symbols-outlined { - color: var(--icon-color); - font-size: 20px; - position: relative; - z-index: 3; - filter: drop-shadow(0 0 2px rgba(0, 0, 0, 0.5)); - display: flex; - align-items: center; - justify-content: center; - height: 24px; - width: 24px; - margin-top: -1px; + color: var(--icon-color); + font-size: 20px; + position: relative; + z-index: 3; + filter: drop-shadow(0 0 2px rgba(0, 0, 0, 0.5)); + display: flex; + align-items: center; + justify-content: center; + height: 24px; + width: 24px; + margin-top: -1px; } .notify-content { - flex: 1; - position: relative; - padding-bottom: 8px; + flex: 1; + position: relative; + padding-bottom: 8px; } .notify-title { - color: var(--text-color); - font-size: 14px; - font-weight: 600; - margin-bottom: 2px; + color: var(--text-color); + font-size: 14px; + font-weight: 600; + margin-bottom: 2px; } .notify-text { - color: var(--text-secondary); - font-size: 12px; - font-weight: 400; + color: var(--text-secondary); + font-size: 12px; + font-weight: 400; } .notify-progress { - position: absolute; - bottom: 0; - left: 0; - height: 2px; - width: 100%; - border-radius: 1px; + position: absolute; + bottom: 0; + left: 0; + height: 2px; + width: 100%; + border-radius: 1px; } .material-symbols-outlined { - font-variation-settings: "FILL" 1, "wght" 400, "GRAD" 0, "opsz" 48; + font-variation-settings: "FILL" 1, "wght" 400, "GRAD" 0, "opsz" 48; } .notify-warning .material-symbols-outlined, .notify-error .material-symbols-outlined { - margin-top: -2px; + margin-top: -2px; } -.fadeIn { - animation: fadeIn 0.3s ease-in-out; +#top-right .fadeIn, +#bottom-right .fadeIn, +#middle-right .fadeIn { + animation: fadeIn-right 0.3s ease-in-out; +} + +#top-left .fadeIn, +#bottom-left .fadeIn, +#middle-left .fadeIn { + animation: fadeIn-left 0.3s ease-in-out; +} + +#top-middle .fadeIn { + animation: fadeIn-top 0.3s ease-in-out; +} + +#bottom-middle .fadeIn { + animation: fadeIn-bottom 0.3s ease-in-out; } .fadeOut { - animation: fadeOut 0.5s ease-in-out; - opacity: 0; + opacity: 0; } -@keyframes fadeIn { - from { - opacity: 0; - transform: translateX(50px); - } - to { - opacity: 1; - transform: translateX(0); - } +#top-right .fadeOut, +#bottom-right .fadeOut, +#middle-right .fadeOut { + animation: fadeOut-right 0.5s ease-in-out; } -@keyframes fadeOut { - from { - opacity: 1; - transform: translateX(0); - } - to { - opacity: 0; - transform: translateX(50px); - } +#top-left .fadeOut, +#bottom-left .fadeOut, +#middle-left .fadeOut { + animation: fadeOut-left 0.5s ease-in-out; +} + +#top-middle .fadeOut { + animation: fadeOut-top 0.5s ease-in-out; +} +#bottom-middle .fadeOut { + animation: fadeOut-bottom 0.5s ease-in-out; +} + +@keyframes fadeIn-right { + from { + opacity: 0; + transform: translateX(50px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes fadeIn-left { + from { + opacity: 0; + transform: translateX(-50px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes fadeIn-top { + from { + opacity: 0; + transform: translateY(-50px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes fadeIn-bottom { + from { + opacity: 0; + transform: translateY(50px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes fadeOut-right { + from { + opacity: 1; + transform: translateX(0); + } + to { + opacity: 0; + transform: translateX(50px); + } +} + +@keyframes fadeOut-left { + from { + opacity: 1; + transform: translateX(0); + } + to { + opacity: 0; + transform: translateX(-50px); + } +} + +@keyframes fadeOut-top { + from { + opacity: 1; + transform: translateY(0); + } + to { + opacity: 0; + transform: translateY(-50px); + } +} + +@keyframes fadeOut-bottom { + from { + opacity: 1; + transform: translateY(0); + } + to { + opacity: 0; + transform: translateY(50px); + } } diff --git a/[core]/esx_notify/nui/index.html b/[core]/esx_notify/nui/index.html index 76a62faa..9bdb502c 100644 --- a/[core]/esx_notify/nui/index.html +++ b/[core]/esx_notify/nui/index.html @@ -1,15 +1,39 @@ - - - - - ESX Notifications - - -
- -
- - - + + + + + + ESX Notifications + + + +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+ + + + \ No newline at end of file diff --git a/[core]/esx_notify/nui/js/script.js b/[core]/esx_notify/nui/js/script.js index 1152ed14..e8c15e86 100644 --- a/[core]/esx_notify/nui/js/script.js +++ b/[core]/esx_notify/nui/js/script.js @@ -1,160 +1,167 @@ -const w = window +const w = window; const types = { - ["success"]: { - ["icon"]: "check_circle", - ["frequency"]: 800, - ["duration"]: 100, - ["color"]: "#2ecc71", - ["borderColor"]: "#1f9c4d", - }, - ["error"]: { - ["icon"]: "error", - ["frequency"]: 300, - ["duration"]: 150, - ["color"]: "#e74c3c", - ["borderColor"]: "#c0392b", - }, - ["info"]: { - ["icon"]: "info", - ["frequency"]: 600, - ["duration"]: 100, - ["color"]: "#3498db", - ["borderColor"]: "#2980b9", - }, - ["warning"]: { - ["icon"]: "warning_amber", - ["frequency"]: 450, - ["duration"]: 125, - ["color"]: "#f39c12", - ["borderColor"]: "#d35400", - }, -} + ["success"]: { + ["icon"]: "check_circle", + ["frequency"]: 800, + ["duration"]: 100, + ["color"]: "#2ecc71", + ["borderColor"]: "#1f9c4d", + }, + ["error"]: { + ["icon"]: "error", + ["frequency"]: 300, + ["duration"]: 150, + ["color"]: "#e74c3c", + ["borderColor"]: "#c0392b", + }, + ["info"]: { + ["icon"]: "info", + ["frequency"]: 600, + ["duration"]: 100, + ["color"]: "#3498db", + ["borderColor"]: "#2980b9", + }, + ["warning"]: { + ["icon"]: "warning_amber", + ["frequency"]: 450, + ["duration"]: 125, + ["color"]: "#f39c12", + ["borderColor"]: "#d35400", + }, +}; // the color codes example `i ~r~love~s~ donuts` const codes = { - "~r~": "#c0392b", - "~b~": "#378cbf", - "~g~": "#2ecc71", - "~y~": "yellow", - "~p~": "purple", - "~c~": "grey", - "~m~": "#212121", - "~u~": "black", - "~o~": "#fb9b04", -} + "~r~": "#c0392b", + "~b~": "#378cbf", + "~g~": "#2ecc71", + "~y~": "yellow", + "~p~": "purple", + "~c~": "grey", + "~m~": "#212121", + "~u~": "black", + "~o~": "#fb9b04", +}; // Audio context for sound effects -let audioContext +let audioContext; // Initialize audio context on user interaction -document.addEventListener("click", initAudioContext, { once: true }) -document.addEventListener("keydown", initAudioContext, { once: true }) +document.addEventListener("click", initAudioContext, { once: true }); +document.addEventListener("keydown", initAudioContext, { once: true }); function initAudioContext() { - if (!audioContext) { - audioContext = new (window.AudioContext || window.webkitAudioContext)() - } + if (!audioContext) { + audioContext = new (window.AudioContext || window.webkitAudioContext)(); + } } function playNotificationSound(type) { - if (!audioContext) initAudioContext() + if (!audioContext) initAudioContext(); - const typeConfig = types[type] || types["info"] - const oscillator = audioContext.createOscillator() - const gainNode = audioContext.createGain() + const typeConfig = types[type] || types["info"]; + const oscillator = audioContext.createOscillator(); + const gainNode = audioContext.createGain(); - oscillator.type = "sine" - oscillator.frequency.setValueAtTime(typeConfig.frequency, audioContext.currentTime) + oscillator.type = "sine"; + oscillator.frequency.setValueAtTime(typeConfig.frequency, audioContext.currentTime); - gainNode.gain.setValueAtTime(0.3, audioContext.currentTime) - gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + typeConfig.duration / 1000) + gainNode.gain.setValueAtTime(0.3, audioContext.currentTime); + gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + typeConfig.duration / 1000); - oscillator.connect(gainNode) - gainNode.connect(audioContext.destination) + oscillator.connect(gainNode); + gainNode.connect(audioContext.destination); - oscillator.start() - oscillator.stop(audioContext.currentTime + typeConfig.duration / 1000) + oscillator.start(); + oscillator.stop(audioContext.currentTime + typeConfig.duration / 1000); } w.addEventListener("message", (event) => { - notification({ - type: event.data.type, - title: event.data.title || "New Notification", - message: event.data.message, - length: event.data.length, - notificationSoundEnabled: event.data.notificationSoundEnabled, - }) -}) + notification({ + type: event.data.type, + title: event.data.title || "New Notification", + message: event.data.message, + length: event.data.length, + position: event.data.position, + notificationSoundEnabled: event.data.notificationSoundEnabled, + }); +}); const replaceColors = (str, obj) => { - let strToReplace = str + let strToReplace = str; - for (const id in obj) { - strToReplace = strToReplace.replace(new RegExp(id, "g"), obj[id]) - } + for (const id in obj) { + strToReplace = strToReplace.replace(new RegExp(id, "g"), obj[id]); + } - return strToReplace -} + return strToReplace; +}; const sanitizeHTML = (str) => { - const temp = document.createElement("div") - temp.textContent = str - return temp.innerHTML -} + const temp = document.createElement("div"); + temp.textContent = str; + return temp.innerHTML; +}; const processLineBreaks = (str) => { - // Replace
tags with actual line breaks - return str.replace(/<br>/g, "
") -} + // Replace
tags with actual line breaks + return str.replace(/<br>/g, "
"); +}; const notification = (data) => { - if (typeof $ === "undefined") { - console.error("jQuery is not loaded. Please ensure jQuery is included in your project.") - return - } + if (typeof $ === "undefined") { + console.error("jQuery is not loaded. Please ensure jQuery is included in your project."); + return; + } - if (data.message) { - // Remove any standalone ~s~ tags (not preceded by a color code) - data.message = data.message.replace(/~s~/g, "") - } + if (data.message) { + // Remove any standalone ~s~ tags (not preceded by a color code) + data.message = data.message.replace(/~s~/g, ""); + } - if (data.title) { - // Remove any standalone ~s~ tags (not preceded by a color code) - data.title = data.title.replace(/~s~/g, "") - } + if (data.title) { + // Remove any standalone ~s~ tags (not preceded by a color code) + data.title = data.title.replace(/~s~/g, ""); + } - let sanitizedTitle = data.title ? sanitizeHTML(data.title) : "" - let sanitizedMessage = data.message ? sanitizeHTML(data.message) : "" + let sanitizedTitle = data.title ? sanitizeHTML(data.title) : ""; + let sanitizedMessage = data.message ? sanitizeHTML(data.message) : ""; - if (data.title) { - for (const color in codes) { - if (sanitizedTitle.includes(color)) { - const objArr = {} - objArr[color] = `` - objArr["~s~"] = "" - sanitizedTitle = replaceColors(sanitizedTitle, objArr) - } - } - } + if (data.title) { + for (const color in codes) { + if (sanitizedTitle.includes(color)) { + const objArr = {}; + objArr[color] = ``; + objArr["~s~"] = ""; + sanitizedTitle = replaceColors(sanitizedTitle, objArr); + } + } + } - for (const color in codes) { - if (sanitizedMessage.includes(color)) { - const objArr = {} - objArr[color] = `` - objArr["~s~"] = "" - sanitizedMessage = replaceColors(sanitizedMessage, objArr) - } - } + for (const color in codes) { + if (sanitizedMessage.includes(color)) { + const objArr = {}; + objArr[color] = ``; + objArr["~s~"] = ""; + sanitizedMessage = replaceColors(sanitizedMessage, objArr); + } + } - sanitizedMessage = processLineBreaks(sanitizedMessage) - sanitizedTitle = processLineBreaks(sanitizedTitle) + sanitizedMessage = processLineBreaks(sanitizedMessage); + sanitizedTitle = processLineBreaks(sanitizedTitle); - const id = Math.floor(Math.random() * 100000) - const typeInfo = types[data.type] || types["info"] - const duration = data.length || 3000 + const id = Math.floor(Math.random() * 100000); + const typeInfo = types[data.type] || types["info"]; + const duration = data.length || 3000; + const containerToAppend = data.position ? `#${data.position}` : "#middle-right"; - const notificationElement = $(` + if (!$(containerToAppend).length) { + console.error(`Container ${containerToAppend} to add the notification not found.`); + return; + } + + const notificationElement = $(`
@@ -167,28 +174,27 @@ const notification = (data) => {
- `).appendTo(`#root`) + `).appendTo(containerToAppend); - $(`#${id} .notify-progress`).css({ - transition: `width ${duration}ms linear`, - width: "0%", - }) + $(`#${id} .notify-progress`).css({ + transition: `width ${duration}ms linear`, + width: "0%", + }); - if (data.notificationSoundEnabled) { - playNotificationSound(data.type) - } - + if (data.notificationSoundEnabled) { + playNotificationSound(data.type); + } - setTimeout(() => { - $(`#${id} .notify-progress`).css("width", "100%") - }, 10) + setTimeout(() => { + $(`#${id} .notify-progress`).css("width", "100%"); + }, 10); - setTimeout(() => { - $(`#${id}`).removeClass("fadeIn").addClass("fadeOut") - setTimeout(() => { - $(`#${id}`).remove() - }, 500) - }, duration) + setTimeout(() => { + $(`#${id}`).removeClass("fadeIn").addClass("fadeOut"); + setTimeout(() => { + $(`#${id}`).remove(); + }, 500); + }, duration); - return notificationElement -} + return notificationElement; +}; diff --git a/[core]/esx_notify/readme.md b/[core]/esx_notify/readme.md index 430f8a34..121a77bc 100644 --- a/[core]/esx_notify/readme.md +++ b/[core]/esx_notify/readme.md @@ -17,6 +17,20 @@ ESX.ShowNotification("text here") -- Default will time and type will be info/300 -- With title (optional 4th parameter) ESX.ShowNotification("message here", "success", 3000, "Achievement") + +--[[ +With position (optional 5th parameter) +Possible positions: + "top-right" + "top-left" + "top-middle" + "bottom-right" + "bottom-left" + "bottom-middle" + "middle-left" + "middle-right" +]] +ESX.ShowNotification("Your message here", "info", 3000, "Info Title", "top-right") ``` `

`Export Usage`

` @@ -28,6 +42,9 @@ exports["esx_notify"]:Notify("info", 3000, "message here") -- With title exports["esx_notify"]:Notify("success", 3000, "Item purchased!", "Shop") +-- With position +exports["esx_notify"]:Notify("warning", 4000, "Inventory full!", "Warning", "bottom-left") + -- With line break exports["esx_notify"]:Notify("warning", 4000, "Inventory full!~br~Some items were dropped.", "Warning") ``` @@ -40,6 +57,9 @@ TriggerEvent("ESX:Notify", "info", 3000, "message here") -- With title TriggerEvent("ESX:Notify", "error", 5000, "You don't have enough money!", "Transaction Failed") + +-- With position +TriggerEvent("ESX:Notify", "success", 4000, "Welcome!", "Greetings", "top-middle") ``` `

`Color Code Usage`

` @@ -75,4 +95,4 @@ This program Is free software: you can redistribute it And/Or modify it under th This program Is distributed In the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty Of MERCHANTABILITY Or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License For more details. -You should have received a copy Of the GNU General Public License along with this program. If Not, see ``. \ No newline at end of file +You should have received a copy Of the GNU General Public License along with this program. If Not, see ``.