From 11822146e56fbe87860d6ab405e6430e85dd601e Mon Sep 17 00:00:00 2001 From: undefined Date: Fri, 17 Sep 2021 02:31:55 +0800 Subject: [PATCH] ui: at user auto complete --- .../components/header/header.page.styl | 27 --------- .../ui-default/components/monaco/index.js | 1 + .../components/monaco/languages/markdown.ts | 57 +++++++++++++++++-- .../ui-default/components/monaco/monaco.css | 4 ++ packages/ui-default/package.json | 2 +- packages/ui-default/utils/api.ts | 3 + 6 files changed, 62 insertions(+), 32 deletions(-) create mode 100644 packages/ui-default/components/monaco/monaco.css create mode 100644 packages/ui-default/utils/api.ts diff --git a/packages/ui-default/components/header/header.page.styl b/packages/ui-default/components/header/header.page.styl index 2a7400747..1d0604d7e 100644 --- a/packages/ui-default/components/header/header.page.styl +++ b/packages/ui-default/components/header/header.page.styl @@ -8,26 +8,6 @@ $header-gap-mini-domain = ($header-bg-height-mini - $nav-item-height - $header-l &.warning background: #ffe1a6 -.header - position: relative - height: rem($header-bg-height) - background: #5eafca no-repeat center top - background-size: cover - transition: height .5s - transition-timing-function: ease-out-cubic - overflow: hidden - +retina() - background-size: rem($header-bg-width $header-bg-height) - - &.mini - height: rem($header-bg-height-mini) - - +mobile() - background: #FFF - height: auto !important - .header__content - display: none - .header__logo display: block width: rem($header-logo-width-real) @@ -47,13 +27,6 @@ $header-gap-mini-domain = ($header-bg-height-mini - $nav-item-height - $header-l #panel padding-top: $header-bg-height - .header - position: absolute - left: 0 - top: 0 - width: 100% - height: 0 - .header__logo transform: scale(0) opacity: 0 diff --git a/packages/ui-default/components/monaco/index.js b/packages/ui-default/components/monaco/index.js index eff002523..371846129 100644 --- a/packages/ui-default/components/monaco/index.js +++ b/packages/ui-default/components/monaco/index.js @@ -4,6 +4,7 @@ import Notification from 'vj/components/notification'; import './languages/markdown'; import './languages/typescript'; import './languages/yaml'; +import './monaco.css'; export default monaco; diff --git a/packages/ui-default/components/monaco/languages/markdown.ts b/packages/ui-default/components/monaco/languages/markdown.ts index 4313e0599..150c9347a 100644 --- a/packages/ui-default/components/monaco/languages/markdown.ts +++ b/packages/ui-default/components/monaco/languages/markdown.ts @@ -1,6 +1,8 @@ import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; import list from 'emojis-list'; import keyword from 'emojis-keywords'; +import request from 'vj/utils/request'; +import api from 'vj/utils/api'; const qqEmojies = [ 'weixiao', @@ -109,28 +111,75 @@ function qqEmoji(range) { return qqEmojies.map((i, index) => ({ label: `/${i}`, kind: monaco.languages.CompletionItemKind.Keyword, - documentation: `/${i}`, + documentation: `![${i}](//qq-face.vercel.app/gif/s${index}.gif)`, insertText: `![${i}](//qq-face.vercel.app/gif/s${index}.gif =32x32) `, range, })); } +monaco.editor.registerCommand('hydro.openUserPage', (accesser, uid) => { + window.open(`/user/${uid}`); +}); + +monaco.languages.registerCodeLensProvider('markdown', { + async provideCodeLenses(model) { + const users = model.findMatches('\\[\\]\\(/user/(\\d+)\\)', true, true, true, null, true); + const { data } = await api(` + query { + users(ids: [${users.map((i) => i.matches[1]).join(',')}]) { + _id + uname + } + } + `); + return { + lenses: users.map((i, index) => ({ + range: i.range, + id: `${index}.${i.matches[1]}`, + command: { + id: 'hydro.openUserPage', + arguments: [i.matches[1]], + title: `@${data.users.find((doc) => doc._id.toString() === i.matches[1])?.uname || i.matches[1]}`, + }, + })), + dispose: () => { }, + }; + }, + resolveCodeLens(model, codeLens) { + return codeLens; + }, +}); + monaco.languages.registerCompletionItemProvider('markdown', { - provideCompletionItems(model, position) { + async provideCompletionItems(model, position) { const word = model.getWordAtPosition(position); + if (word.word.length < 2) return { suggestions: [] }; const prefix = model.getValueInRange({ startLineNumber: position.lineNumber, endLineNumber: position.lineNumber, startColumn: word.startColumn - 1, - endColumn: word.startColumn - 1, + endColumn: word.startColumn, }); - if (![':', '/'].includes(prefix)) return { suggestions: [] }; + if (![':', '/', '@'].includes(prefix)) return { suggestions: [] }; const range = { startLineNumber: position.lineNumber, endLineNumber: position.lineNumber, startColumn: word.startColumn - 1, endColumn: word.endColumn, }; + if (prefix === '@') { + const users = await request.get(`/user/search?q=${word.word}`); + return { + suggestions: users.map((i) => ({ + label: `@${i.uname} (UID=${i._id})`, + kind: monaco.languages.CompletionItemKind.Property, + documentation: { value: `![monaco_avatar](${i.avatarUrl})`, isTrusted: true }, + insertText: `[](/user/${i._id}) `, + range, + tags: i.priv === 0 ? [1] : [], + })), + }; + } return { suggestions: prefix === ':' ? emoji(range) : qqEmoji(range), }; diff --git a/packages/ui-default/components/monaco/monaco.css b/packages/ui-default/components/monaco/monaco.css new file mode 100644 index 000000000..9498f4674 --- /dev/null +++ b/packages/ui-default/components/monaco/monaco.css @@ -0,0 +1,4 @@ +img[alt=monaco_avatar] { + width: 64px; + height: 64px; +} diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index 223377815..b87cdf3f8 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/ui-default", - "version": "4.21.2", + "version": "4.21.3", "author": "undefined ", "license": "AGPL-3.0", "main": "hydro.js", diff --git a/packages/ui-default/utils/api.ts b/packages/ui-default/utils/api.ts new file mode 100644 index 000000000..bcc71d923 --- /dev/null +++ b/packages/ui-default/utils/api.ts @@ -0,0 +1,3 @@ +import request from './request'; + +export default (q: string) => request.post('/api', { query: q.trim() });