From 6cae5cb7d121bf5f38e10f45a7ffaf2b66c1d9f3 Mon Sep 17 00:00:00 2001 From: undefined Date: Mon, 5 Apr 2021 02:32:04 +0800 Subject: [PATCH] =?UTF-8?q?ui:=20=E6=94=B6=E5=88=B0=E7=AB=99=E5=86=85?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E6=98=AF=E5=A2=9E=E5=8A=A0=E6=8F=90=E9=86=92?= =?UTF-8?q?=20(#86)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/hydrooj/package.json | 2 +- packages/hydrooj/src/entry/common.ts | 8 +-- packages/hydrooj/src/handler/home.ts | 8 ++- packages/hydrooj/src/model/message.ts | 1 + packages/hydrooj/src/model/setting.ts | 2 +- packages/hydrooj/src/service/bus.ts | 1 + .../components/message/index.page.js | 27 +++++--- .../components/notification/index.js | 65 +++++-------------- .../notification/notification.page.styl | 13 ++++ packages/ui-default/package.json | 2 +- 10 files changed, 62 insertions(+), 67 deletions(-) diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index 625fbfd7b..322de22df 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "2.21.5", + "version": "2.21.6", "bin": "bin/hydrooj.js", "main": "dist/loader.js", "typings": "dist/loader.d.ts", diff --git a/packages/hydrooj/src/entry/common.ts b/packages/hydrooj/src/entry/common.ts index 855a3c4be..250897b37 100644 --- a/packages/hydrooj/src/entry/common.ts +++ b/packages/hydrooj/src/entry/common.ts @@ -1,6 +1,6 @@ /* eslint-disable no-await-in-loop */ /* eslint-disable no-eval */ -import fs from 'fs'; +import fs from 'fs-extra'; import os from 'os'; import path from 'path'; import yaml from 'js-yaml'; @@ -130,9 +130,7 @@ export async function template(pending: string[], fail: string[]) { try { const files = getFiles(p); for (const file of files) { - global.Hydro.ui.template[file] = fs.readFileSync( - path.resolve(p, file), - ).toString(); + global.Hydro.ui.template[file] = await fs.readFile(path.resolve(p, file), 'utf-8'); } logger.info('Template init: %s', i); } catch (e) { @@ -216,7 +214,7 @@ export async function service(pending: string[], fail: string[]) { export async function script(pending: string[], fail: string[], active: string[]) { for (const i of pending) { const p = path.resolve(i, 'script.js'); - if (fs.existsSync(p) && !fail.includes(i)) { + if (await fs.pathExists(p) && !fail.includes(i)) { try { logger.info('Script init: %s', i); eval('require')(p); diff --git a/packages/hydrooj/src/handler/home.ts b/packages/hydrooj/src/handler/home.ts index c355c02e1..4436abe98 100644 --- a/packages/hydrooj/src/handler/home.ts +++ b/packages/hydrooj/src/handler/home.ts @@ -3,6 +3,7 @@ import { VerifyPasswordError, UserAlreadyExistError, InvalidTokenError, NotFoundError, UserNotFoundError, PermissionError, DomainAlreadyExistsError, } from '../error'; +import { Mdoc } from '../interface'; import * as bus from '../service/bus'; import { Route, Connection, Handler, ConnectionHandler, param, Types, @@ -328,6 +329,7 @@ class HomeMessagesHandler extends Handler { ['Hydro', 'homepage'], ['home_messages', null], ]; + await user.setById(this.user._id, { unreadMsg: 0 }); this.response.body = { messages: parsed, path }; this.response.template = 'home_messages.html'; } @@ -367,9 +369,11 @@ class HomeMessagesConnectionHandler extends ConnectionHandler { this.dispose = bus.on('user/message', this.onMessageReceived.bind(this)); } - async onMessageReceived(uid: number, e: any) { + async onMessageReceived(uid: number, mdoc: Mdoc) { if (uid !== this.user._id) return; - this.send(e); + const udoc = await user.getById(this.domainId, mdoc.from); + udoc.gravatar_url = misc.gravatar(udoc.gravatar, 64); + this.send({ udoc, mdoc }); } async cleanup() { diff --git a/packages/hydrooj/src/model/message.ts b/packages/hydrooj/src/model/message.ts index 8794fede2..8e33e5f07 100644 --- a/packages/hydrooj/src/model/message.ts +++ b/packages/hydrooj/src/model/message.ts @@ -27,6 +27,7 @@ class MessageModel { const udoc = await user.getById('system', to); bus.boardcast('user/message', to, mdoc, udoc); } + await user.inc(to, 'unreadMsg', 1); return mdoc; } diff --git a/packages/hydrooj/src/model/setting.ts b/packages/hydrooj/src/model/setting.ts index 8d0791cd4..5afc2a6e8 100644 --- a/packages/hydrooj/src/model/setting.ts +++ b/packages/hydrooj/src/model/setting.ts @@ -114,7 +114,7 @@ AccountSetting( Setting('setting_customize', 'backgroundImage', '/components/profile/backgrounds/1.jpg', 'text', 'Profile Background Image', 'Choose the background image in your profile page.'), - Setting('setting_storage', 'usage', 0, 'number', 'Userfile Usage', null, FLAG_DISABLED | FLAG_HIDDEN), + Setting('setting_storage', 'unreadMsg', 0, 'number', 'Unread Message Count', null, FLAG_DISABLED | FLAG_HIDDEN), Setting('setting_storage', 'checkincnt', 0, 'number', 'Check In Counter', null, FLAG_DISABLED | FLAG_HIDDEN), Setting('setting_storage', 'lastcheckin', 0, 'number', 'Last checkin time', null, FLAG_DISABLED | FLAG_HIDDEN), ); diff --git a/packages/hydrooj/src/service/bus.ts b/packages/hydrooj/src/service/bus.ts index d96d2c2df..863e20e44 100644 --- a/packages/hydrooj/src/service/bus.ts +++ b/packages/hydrooj/src/service/bus.ts @@ -146,6 +146,7 @@ export async function parallel(name: K, ...args: Param const tasks: Promise[] = []; if (argv.showBus) logger.debug('parallel: %s %o', name, args); for (const callback of _hooks[name] || []) { + if (argv.busDetail) logger.debug(callback.toString()); tasks.push(callback.apply(this, args)); } await Promise.all(tasks); diff --git a/packages/ui-default/components/message/index.page.js b/packages/ui-default/components/message/index.page.js index 65f90c95d..e06ec5425 100644 --- a/packages/ui-default/components/message/index.page.js +++ b/packages/ui-default/components/message/index.page.js @@ -7,27 +7,38 @@ import tpl from 'vj/utils/tpl'; const messagePage = new AutoloadPage('messagePage', () => { async function init() { + if (UserContext.unreadMsg) { + new Notification({ + type: 'info', + message: i18n('You have mew message.'), + action: () => window.open('/home/messages', '_blank'), + }).show(); + } + const { default: SockJs } = await import('../socket'); const sock = new SockJs('/home/messages-conn'); sock.onmessage = (message) => { const msg = JSON.parse(message.data); - if (msg.mdoc.flag | FLAG_ALERT) { + console.log('Received message', msg); + if (msg.mdoc.flag & FLAG_ALERT) { // Is alert - const dialog = new InfoDialog({ + new InfoDialog({ $body: tpl`
-

${i18n(msg.udoc.content)}

+

${i18n('Message from {0}:', msg.mdoc.from)}

+

${i18n(msg.mdoc.content)}

`, - }); - dialog.open(); + }).open(); } else { // Is message - Notification.show({ + new Notification({ title: msg.udoc.uname, - avatar: msg.udoc.gravatar, + avatar: msg.udoc.gravatar_url, message: msg.mdoc.content, - }); + duration: 15000, + action: () => window.open(`/home/messages?uid=${msg.udoc._id}`, '_blank'), + }).show(); } }; } diff --git a/packages/ui-default/components/notification/index.js b/packages/ui-default/components/notification/index.js index 4917d0eae..6fef5f78a 100644 --- a/packages/ui-default/components/notification/index.js +++ b/packages/ui-default/components/notification/index.js @@ -1,9 +1,6 @@ import tpl from 'vj/utils/tpl'; import zIndexManager from 'vj/utils/zIndexManager'; -let lastNotification = null; -let autoHideTimer = null; - export default class Notification { constructor({ avatar, title, message, type = '', duration = 3000, action, @@ -11,78 +8,48 @@ export default class Notification { this.type = type; if (avatar) this.type += ' avatar'; if (title) this.type += ' title'; - this.action = (() => { }) || action; + this.action = action || (() => { }); this.$dom = $(tpl`
`); if (avatar) $(tpl``).appendTo(this.$dom); - if (title) $(tpl`

${title}

`).appendTo(this.$dom); - $(tpl`

${message}

`).appendTo(this.$dom); - this.$dom.on('clink', this.handleClick.bind(this)); + if (title) { + $(tpl`

${title}

${message}

`).appendTo(this.$dom); + } else $(tpl`

${message}

`).appendTo(this.$dom); + this.$dom.on('click', this.handleClick.bind(this)); this.$n = this.$dom .css('z-index', zIndexManager.getNext()) - .appendTo('body'); + .appendTo(document.body); this.$n.width(); // force reflow - this.$n.removeClass('hide'); - if (duration) this.autoHideTimer = setTimeout(this.hide.bind(this), duration); + this.duration = duration; } handleClick() { this.action(); } + show(autohide = true) { + this.$n.removeClass('hide'); + if (this.duration && autohide) this.autoHideTimer = setTimeout(this.hide.bind(this), this.duration); + } + hide() { this.$n.addClass('hide'); setTimeout(() => this.$n.remove(), 200); } static success(message, duration) { - return Notification.show({ type: 'success', message, duration }); + return new Notification({ type: 'success', message, duration }).show(); } static info(message, duration) { - return Notification.show({ type: 'info', message, duration }); + return new Notification({ type: 'info', message, duration }).show(); } static warn(message, duration) { - return Notification.show({ type: 'warn', message, duration }); + return new Notification({ type: 'warn', message, duration }).show(); } static error(message, duration) { - return Notification.show({ type: 'error', message, duration }); - } - - static show({ - avatar, title, message, type = '', duration = 3000, action, - }) { - if (lastNotification) Notification.hide(); - if (avatar) type += ' avatar'; - if (title) type += ' title'; - const $dom = $(tpl`
`); - if (avatar) $(tpl``).appendTo($dom); - if (title) $(tpl`

${title}

`).appendTo($dom); - $(tpl`

${message}

`).appendTo($dom); - $dom.on('clink', action); - const $n = $dom - .css('z-index', zIndexManager.getNext()) - .appendTo('body'); - $n.width(); // force reflow - $n.removeClass('hide'); - lastNotification = $n; - autoHideTimer = setTimeout(Notification.hide, duration); - return $n; - } - - static hide() { - if (!lastNotification) { - return; - } - if (autoHideTimer) { - clearTimeout(autoHideTimer); - autoHideTimer = null; - } - const $n = lastNotification; - $n.addClass('hide'); - setTimeout(() => $n.remove(), 200); - lastNotification = null; + return new Notification({ type: 'error', message, duration }).show(); } } diff --git a/packages/ui-default/components/notification/notification.page.styl b/packages/ui-default/components/notification/notification.page.styl index 506a6cd59..cb12bfe4d 100644 --- a/packages/ui-default/components/notification/notification.page.styl +++ b/packages/ui-default/components/notification/notification.page.styl @@ -47,3 +47,16 @@ width: 100% min-width: auto bottom: 0 + +.notification-content + float: right + margin-top: rem(7px) + margin-left: rem(10px) + margin-right: rem(15px) + + h2 + color: #FFFFFF + + p + margin-top: rem(7px); + font-size: larger diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index e95a3fc83..147d04399 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/ui-default", - "version": "4.5.4", + "version": "4.5.5", "author": "undefined ", "license": "AGPL-3.0", "main": "hydro.js",