diff --git a/app/assets/css/launcher.css b/app/assets/css/launcher.css index 7cf91cce..20bc9ca8 100644 --- a/app/assets/css/launcher.css +++ b/app/assets/css/launcher.css @@ -2136,6 +2136,17 @@ input:checked + .toggleSwitchSlider:before { stroke: rgba(255, 255, 255, 0.75); } +/* Icon which indicates there is new news. */ +#newsButtonAlert { + width: 5px; + height: 5px; + position: absolute; + border-radius: 50%; + background: red; + right: -1px; + top: 50%; +} + /* Arrow image which floats above the news button. */ #newsButtonSVG { height: 11px; diff --git a/app/assets/js/assetguard.js b/app/assets/js/assetguard.js index 8c4c8658..07d9e4f7 100644 --- a/app/assets/js/assetguard.js +++ b/app/assets/js/assetguard.js @@ -22,19 +22,19 @@ * @module assetguard */ // Requirements -const AdmZip = require('adm-zip') -const async = require('async') +const AdmZip = require('adm-zip') +const async = require('async') const child_process = require('child_process') -const crypto = require('crypto') -const EventEmitter = require('events') -const fs = require('fs') -const isDev = require('electron-is-dev') -const mkpath = require('mkdirp'); -const path = require('path') -const Registry = require('winreg') -const request = require('request') -const tar = require('tar-fs') -const zlib = require('zlib') +const crypto = require('crypto') +const EventEmitter = require('events') +const fs = require('fs') +const isDev = require('electron-is-dev') +const mkpath = require('mkdirp'); +const path = require('path') +const Registry = require('winreg') +const request = require('request') +const tar = require('tar-fs') +const zlib = require('zlib') // Constants const PLATFORM_MAP = { diff --git a/app/assets/js/configmanager.js b/app/assets/js/configmanager.js index 37e9563c..5bc60f3a 100644 --- a/app/assets/js/configmanager.js +++ b/app/assets/js/configmanager.js @@ -44,6 +44,11 @@ const DEFAULT_CONFIG = { allowPrerelease: false } }, + newsCache: { + date: null, + content: null, + dismissed: false + }, commonDirectory: path.join(dataPath, 'common'), instanceDirectory: path.join(dataPath, 'instances'), clientToken: uuidV4().replace(/-/g, ''), @@ -143,9 +148,39 @@ exports.getTempNativeFolder = function(){ // System Settings (Unconfigurable on UI) +/** + * Retrieve the news cache to determine + * whether or not there is newer news. + * + * @returns {Object} The news cache object. + */ +exports.getNewsCache = function(){ + return config.newsCache +} + +/** + * Set the new news cache object. + * + * @param {Object} newsCache The new news cache object. + */ +exports.setNewsCache = function(newsCache){ + config.newsCache = newsCache +} + +/** + * Set whether or not the news has been dismissed (checked) + * + * @param {boolean} dismissed Whether or not the news has been dismissed (checked). + */ +exports.setNewsCacheDismissed = function(dismissed){ + config.newsCache.dismissed = dismissed +} + /** * Retrieve the common directory for shared * game files (assets, libraries, etc). + * + * @returns {string} The launcher's common directory. */ exports.getCommonDirectory = function(){ return config.commonDirectory @@ -154,6 +189,8 @@ exports.getCommonDirectory = function(){ /** * Retrieve the instance directory for the per * server game directories. + * + * @returns {string} The launcher's instance directory. */ exports.getInstanceDirectory = function(){ return config.instanceDirectory @@ -419,7 +456,8 @@ exports.setGameWidth = function(resWidth){ /** * Validate a potential new width value. * - * @param {*} resWidth The width value to validate. + * @param {number} resWidth The width value to validate. + * @returns {boolean} Whether or not the value is valid. */ exports.validateGameWidth = function(resWidth){ const nVal = Number.parseInt(resWidth) @@ -448,7 +486,8 @@ exports.setGameHeight = function(resHeight){ /** * Validate a potential new height value. * - * @param {*} resHeight The height value to validate. + * @param {number} resHeight The height value to validate. + * @returns {boolean} Whether or not the value is valid. */ exports.validateGameHeight = function(resHeight){ const nVal = Number.parseInt(resHeight) diff --git a/app/assets/js/scripts/landing.js b/app/assets/js/scripts/landing.js index 5a850e17..7b027e6e 100644 --- a/app/assets/js/scripts/landing.js +++ b/app/assets/js/scripts/landing.js @@ -3,6 +3,7 @@ */ // Requirements const cp = require('child_process') +const crypto = require('crypto') const {URL} = require('url') // Internal Requirements @@ -774,11 +775,17 @@ function slide_(up){ document.getElementById('newsButton').onclick = () => { // Toggle tabbing. if(newsActive){ - $("#landingContainer *").removeAttr('tabindex') - $("#newsContainer *").attr('tabindex', '-1') + $('#landingContainer *').removeAttr('tabindex') + $('#newsContainer *').attr('tabindex', '-1') } else { - $("#landingContainer *").attr('tabindex', '-1') - $("#newsContainer, #newsContainer *, #lower, #lower #center *").removeAttr('tabindex') + $('#landingContainer *').attr('tabindex', '-1') + $('#newsContainer, #newsContainer *, #lower, #lower #center *').removeAttr('tabindex') + if(newsAlertShown){ + $('#newsButtonAlert').fadeOut(2000) + newsAlertShown = false + ConfigManager.setNewsCacheDismissed(true) + ConfigManager.save() + } } slide_(!newsActive) newsActive = !newsActive @@ -841,6 +848,16 @@ function reloadNews(){ }) } +let newsAlertShown = false + +/** + * Show the news alert indicating there is new news. + */ +function showNewsAlert(){ + newsAlertShown = true + $(newsButtonAlert).fadeIn(250) +} + /** * Initialize News UI. This will load the news and prepare * the UI accordingly. @@ -871,6 +888,13 @@ function initNews(){ // No News Articles setNewsLoading(false) + ConfigManager.setNewsCache({ + date: null, + content: null, + dismissed: false + }) + ConfigManager.save() + $('#newsErrorLoading').fadeOut(250, () => { $('#newsErrorNone').fadeIn(250, () => { resolve() @@ -880,6 +904,46 @@ function initNews(){ // Success setNewsLoading(false) + const lN = newsArr[0] + const cached = ConfigManager.getNewsCache() + let newHash = crypto.createHash('sha1').update(lN.content).digest('hex') + let newDate = new Date(lN.date) + let isNew = false + + if(cached.date != null && cached.content != null){ + + if(new Date(cached.date) >= newDate){ + + // Compare Content + if(cached.content !== newHash){ + isNew = true + showNewsAlert() + } else { + if(!cached.dismissed){ + isNew = true + showNewsAlert() + } + } + + } else { + isNew = true + showNewsAlert() + } + + } else { + isNew = true + showNewsAlert() + } + + if(isNew){ + ConfigManager.setNewsCache({ + date: newDate.getTime(), + content: newHash, + dismissed: false + }) + ConfigManager.save() + } + const switchHandler = (forward) => { let cArt = parseInt(newsContent.getAttribute('article')) let nxtArt = forward ? (cArt >= newsArr.length-1 ? 0 : cArt + 1) : (cArt <= 0 ? newsArr.length-1 : cArt - 1) diff --git a/app/landing.ejs b/app/landing.ejs index 3c968061..d592da75 100644 --- a/app/landing.ejs +++ b/app/landing.ejs @@ -126,6 +126,7 @@