зеркало из https://github.com/nextcloud/text.git
Merge pull request #2447 from nextcloud/enh/guest-name-handling
Avoid random guest names and make guest state more visible
This commit is contained in:
Коммит
21adc3f6ff
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,2 +1,2 @@
|
|||
"use strict";(self.webpackChunk_nextcloud_text=self.webpackChunk_nextcloud_text||[]).push([["files-modal"],{38002:(e,t,l)=>{l.r(t),l.d(t,{default:()=>a});var i=l(47450);const n={name:"PublicFilesEditor",components:{Modal:l.n(i)(),EditorWrapper:function(){return Promise.all([l.e("vendors"),l.e("editor")]).then(l.bind(l,19444))}},props:{fileId:{type:Number,default:null},relativePath:{type:String,default:null},active:{type:Boolean,default:!1},shareToken:{type:String,default:null},mimeType:{type:String,default:null}},computed:{fileName:function(){return this.relativePath.substring(this.relativePath.lastIndexOf("/")+1)}},methods:{close:function(){this.$emit("close")}}};const a=(0,l(51900).Z)(n,(function(){var e=this,t=e.$createElement,l=e._self._c||t;return e.active?l("Modal",{attrs:{title:e.fileName},on:{close:e.close}},[l("EditorWrapper",{attrs:{"file-id":e.fileId,"relative-path":e.relativePath,active:e.active,"share-token":e.shareToken,mime:e.mimeType}})],1):e._e()}),[],!1,null,null,null).exports}}]);
|
||||
//# sourceMappingURL=files-modal.js.map?v=122f1603802114e5b4fc
|
||||
"use strict";(self.webpackChunk_nextcloud_text=self.webpackChunk_nextcloud_text||[]).push([["files-modal"],{38002:(e,t,l)=>{l.r(t),l.d(t,{default:()=>a});var i=l(47450);const n={name:"PublicFilesEditor",components:{Modal:l.n(i)(),EditorWrapper:function(){return Promise.all([l.e("vendors"),l.e("editor")]).then(l.bind(l,41507))}},props:{fileId:{type:Number,default:null},relativePath:{type:String,default:null},active:{type:Boolean,default:!1},shareToken:{type:String,default:null},mimeType:{type:String,default:null}},computed:{fileName:function(){return this.relativePath.substring(this.relativePath.lastIndexOf("/")+1)}},methods:{close:function(){this.$emit("close")}}};const a=(0,l(51900).Z)(n,(function(){var e=this,t=e.$createElement,l=e._self._c||t;return e.active?l("Modal",{attrs:{title:e.fileName},on:{close:e.close}},[l("EditorWrapper",{attrs:{"file-id":e.fileId,"relative-path":e.relativePath,active:e.active,"share-token":e.shareToken,mime:e.mimeType}})],1):e._e()}),[],!1,null,null,null).exports}}]);
|
||||
//# sourceMappingURL=files-modal.js.map?v=d64b7a709f30e68e539f
|
|
@ -1 +1 @@
|
|||
{"version":3,"file":"files-modal.js?v=122f1603802114e5b4fc","mappings":"0JAAA,I,WCmCA,MCnCkL,EDmClL,CACAA,KAAAA,oBACAC,WAAAA,CACAC,M,MAAAA,GACAC,cAAAA,WAAA,2EAEAC,MAAAA,CACAC,OAAAA,CACAC,KAAAA,OACAC,QAAAA,MAEAC,aAAAA,CACAF,KAAAA,OACAC,QAAAA,MAEAE,OAAAA,CACAH,KAAAA,QACAC,SAAAA,GAEAG,WAAAA,CACAJ,KAAAA,OACAC,QAAAA,MAEAI,SAAAA,CACAL,KAAAA,OACAC,QAAAA,OAGAK,SAAAA,CACAC,SADA,WAEA,2EAGAC,QAAAA,CACAC,MADA,WAEA,uBEpDA,SAXgB,E,SAAA,GACd,GHRW,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAQF,EAAU,OAAEI,EAAG,QAAQ,CAACE,MAAM,CAAC,MAAQN,EAAIH,UAAUU,GAAG,CAAC,MAAQP,EAAID,QAAQ,CAACK,EAAG,gBAAgB,CAACE,MAAM,CAAC,UAAUN,EAAIX,OAAO,gBAAgBW,EAAIR,aAAa,OAASQ,EAAIP,OAAO,cAAcO,EAAIN,WAAW,KAAOM,EAAIL,aAAa,GAAGK,EAAIQ,OAC1T,IGUpB,EACA,KACA,KACA,MAI8B","sources":["webpack:///text/src/components/PublicFilesEditor.vue?vue&type=template&id=6bd0a9b3&","webpack:///text/src/components/PublicFilesEditor.vue","webpack:///text/src/components/PublicFilesEditor.vue?vue&type=script&lang=js&","webpack://text/./src/components/PublicFilesEditor.vue?4410"],"sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return (_vm.active)?_c('Modal',{attrs:{\"title\":_vm.fileName},on:{\"close\":_vm.close}},[_c('EditorWrapper',{attrs:{\"file-id\":_vm.fileId,\"relative-path\":_vm.relativePath,\"active\":_vm.active,\"share-token\":_vm.shareToken,\"mime\":_vm.mimeType}})],1):_vm._e()}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","<!--\n - @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net>\n -\n - @author Julius Härtl <jus@bitgrid.net>\n -\n - @license GNU AGPL version 3 or any later version\n -\n - This program is free software: you can redistribute it and/or modify\n - it under the terms of the GNU Affero General Public License as\n - published by the Free Software Foundation, either version 3 of the\n - License, or (at your option) any later version.\n -\n - This program is distributed in the hope that it will be useful,\n - but WITHOUT ANY WARRANTY; without even the implied warranty of\n - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n - GNU Affero General Public License for more details.\n -\n - You should have received a copy of the GNU Affero General Public License\n - along with this program. If not, see <http://www.gnu.org/licenses/>.\n -\n -->\n\n<template>\n\t<Modal v-if=\"active\" :title=\"fileName\" @close=\"close\">\n\t\t<EditorWrapper :file-id=\"fileId\"\n\t\t\t:relative-path=\"relativePath\"\n\t\t\t:active=\"active\"\n\t\t\t:share-token=\"shareToken\"\n\t\t\t:mime=\"mimeType\" />\n\t</Modal>\n</template>\n\n<script>\nimport Modal from '@nextcloud/vue/dist/Components/Modal'\n\nexport default {\n\tname: 'PublicFilesEditor',\n\tcomponents: {\n\t\tModal,\n\t\tEditorWrapper: () => import(/* webpackChunkName: \"editor\" */'./EditorWrapper.vue'),\n\t},\n\tprops: {\n\t\tfileId: {\n\t\t\ttype: Number,\n\t\t\tdefault: null,\n\t\t},\n\t\trelativePath: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\t\tactive: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t\tshareToken: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\t\tmimeType: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\tcomputed: {\n\t\tfileName() {\n\t\t\treturn this.relativePath.substring(this.relativePath.lastIndexOf('/') + 1)\n\t\t},\n\t},\n\tmethods: {\n\t\tclose() {\n\t\t\tthis.$emit('close')\n\t\t},\n\t},\n}\n</script>\n","import mod from \"-!../../node_modules/babel-loader/lib/index.js!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./PublicFilesEditor.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../node_modules/babel-loader/lib/index.js!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./PublicFilesEditor.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./PublicFilesEditor.vue?vue&type=template&id=6bd0a9b3&\"\nimport script from \"./PublicFilesEditor.vue?vue&type=script&lang=js&\"\nexport * from \"./PublicFilesEditor.vue?vue&type=script&lang=js&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"names":["name","components","Modal","EditorWrapper","props","fileId","type","default","relativePath","active","shareToken","mimeType","computed","fileName","methods","close","_vm","this","_h","$createElement","_c","_self","attrs","on","_e"],"sourceRoot":""}
|
||||
{"version":3,"file":"files-modal.js?v=d64b7a709f30e68e539f","mappings":"0JAAA,I,WCmCA,MCnCkL,EDmClL,CACAA,KAAAA,oBACAC,WAAAA,CACAC,M,MAAAA,GACAC,cAAAA,WAAA,2EAEAC,MAAAA,CACAC,OAAAA,CACAC,KAAAA,OACAC,QAAAA,MAEAC,aAAAA,CACAF,KAAAA,OACAC,QAAAA,MAEAE,OAAAA,CACAH,KAAAA,QACAC,SAAAA,GAEAG,WAAAA,CACAJ,KAAAA,OACAC,QAAAA,MAEAI,SAAAA,CACAL,KAAAA,OACAC,QAAAA,OAGAK,SAAAA,CACAC,SADA,WAEA,2EAGAC,QAAAA,CACAC,MADA,WAEA,uBEpDA,SAXgB,E,SAAA,GACd,GHRW,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAmBC,EAAGJ,EAAIK,MAAMD,IAAIF,EAAG,OAAQF,EAAU,OAAEI,EAAG,QAAQ,CAACE,MAAM,CAAC,MAAQN,EAAIH,UAAUU,GAAG,CAAC,MAAQP,EAAID,QAAQ,CAACK,EAAG,gBAAgB,CAACE,MAAM,CAAC,UAAUN,EAAIX,OAAO,gBAAgBW,EAAIR,aAAa,OAASQ,EAAIP,OAAO,cAAcO,EAAIN,WAAW,KAAOM,EAAIL,aAAa,GAAGK,EAAIQ,OAC1T,IGUpB,EACA,KACA,KACA,MAI8B","sources":["webpack:///text/src/components/PublicFilesEditor.vue?vue&type=template&id=6bd0a9b3&","webpack:///text/src/components/PublicFilesEditor.vue","webpack:///text/src/components/PublicFilesEditor.vue?vue&type=script&lang=js&","webpack://text/./src/components/PublicFilesEditor.vue?4410"],"sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return (_vm.active)?_c('Modal',{attrs:{\"title\":_vm.fileName},on:{\"close\":_vm.close}},[_c('EditorWrapper',{attrs:{\"file-id\":_vm.fileId,\"relative-path\":_vm.relativePath,\"active\":_vm.active,\"share-token\":_vm.shareToken,\"mime\":_vm.mimeType}})],1):_vm._e()}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","<!--\n - @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net>\n -\n - @author Julius Härtl <jus@bitgrid.net>\n -\n - @license GNU AGPL version 3 or any later version\n -\n - This program is free software: you can redistribute it and/or modify\n - it under the terms of the GNU Affero General Public License as\n - published by the Free Software Foundation, either version 3 of the\n - License, or (at your option) any later version.\n -\n - This program is distributed in the hope that it will be useful,\n - but WITHOUT ANY WARRANTY; without even the implied warranty of\n - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n - GNU Affero General Public License for more details.\n -\n - You should have received a copy of the GNU Affero General Public License\n - along with this program. If not, see <http://www.gnu.org/licenses/>.\n -\n -->\n\n<template>\n\t<Modal v-if=\"active\" :title=\"fileName\" @close=\"close\">\n\t\t<EditorWrapper :file-id=\"fileId\"\n\t\t\t:relative-path=\"relativePath\"\n\t\t\t:active=\"active\"\n\t\t\t:share-token=\"shareToken\"\n\t\t\t:mime=\"mimeType\" />\n\t</Modal>\n</template>\n\n<script>\nimport Modal from '@nextcloud/vue/dist/Components/Modal'\n\nexport default {\n\tname: 'PublicFilesEditor',\n\tcomponents: {\n\t\tModal,\n\t\tEditorWrapper: () => import(/* webpackChunkName: \"editor\" */'./EditorWrapper.vue'),\n\t},\n\tprops: {\n\t\tfileId: {\n\t\t\ttype: Number,\n\t\t\tdefault: null,\n\t\t},\n\t\trelativePath: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\t\tactive: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t\tshareToken: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\t\tmimeType: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\tcomputed: {\n\t\tfileName() {\n\t\t\treturn this.relativePath.substring(this.relativePath.lastIndexOf('/') + 1)\n\t\t},\n\t},\n\tmethods: {\n\t\tclose() {\n\t\t\tthis.$emit('close')\n\t\t},\n\t},\n}\n</script>\n","import mod from \"-!../../node_modules/babel-loader/lib/index.js!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./PublicFilesEditor.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../node_modules/babel-loader/lib/index.js!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./PublicFilesEditor.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./PublicFilesEditor.vue?vue&type=template&id=6bd0a9b3&\"\nimport script from \"./PublicFilesEditor.vue?vue&type=script&lang=js&\"\nexport * from \"./PublicFilesEditor.vue?vue&type=script&lang=js&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"names":["name","components","Modal","EditorWrapper","props","fileId","type","default","relativePath","active","shareToken","mimeType","computed","fileName","methods","close","_vm","this","_h","$createElement","_c","_self","attrs","on","_e"],"sourceRoot":""}
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -237,9 +237,6 @@ class ApiService {
|
|||
return new DataResponse([], 500);
|
||||
}
|
||||
|
||||
if ($guestName === '') {
|
||||
return new DataResponse([ 'message' => 'A guest name needs to be provided'], 500);
|
||||
}
|
||||
return new DataResponse($this->sessionService->updateSession($documentId, $sessionId, $sessionToken, $guestName));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ class SessionService {
|
|||
/** @var IAvatarManager */
|
||||
private $avatarManager;
|
||||
|
||||
/** @var string */
|
||||
/** @var string|null */
|
||||
private $userId;
|
||||
|
||||
/** @var Session cache current session in the request */
|
||||
|
@ -94,9 +94,7 @@ class SessionService {
|
|||
$userName = $this->userId ? $this->userId : $guestName;
|
||||
$session->setUserId($this->userId);
|
||||
$session->setToken($this->secureRandom->generate(64));
|
||||
$color = $this->avatarManager->getGuestAvatar($userName)->avatarBackgroundColor($userName);
|
||||
$color = sprintf("#%02x%02x%02x", $color->r, $color->g, $color->b);
|
||||
$session->setColor($color);
|
||||
$session->setColor($this->getColorForGuestName($guestName));
|
||||
if ($this->userId === null) {
|
||||
$session->setGuestName($guestName);
|
||||
}
|
||||
|
@ -222,9 +220,14 @@ class SessionService {
|
|||
}
|
||||
$session = $this->sessionMapper->find($documentId, $sessionId, $sessionToken);
|
||||
$session->setGuestName($guestName);
|
||||
$color = $this->avatarManager->getGuestAvatar($guestName)->avatarBackgroundColor($guestName);
|
||||
$color = sprintf("#%02x%02x%02x", $color->r, $color->g, $color->b);
|
||||
$session->setColor($color);
|
||||
$session->setColor($this->getColorForGuestName($guestName));
|
||||
return $this->sessionMapper->update($session);
|
||||
}
|
||||
|
||||
private function getColorForGuestName(string $guestName = null): string {
|
||||
$guestName = $this->userId ?? $guestName;
|
||||
$uniqueGuestId = !empty($guestName) ? $guestName : $this->secureRandom->generate(12);
|
||||
$color = $this->avatarManager->getGuestAvatar($uniqueGuestId)->avatarBackgroundColor($uniqueGuestId);
|
||||
return sprintf("#%02x%02x%02x", $color->r, $color->g, $color->b);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
<template>
|
||||
<div class="avatar-wrapper" :style="sessionAvatarStyle">
|
||||
<Avatar v-if="session.userId"
|
||||
:user="session.userId ? session.userId : session.guestName"
|
||||
:is-guest="session.userId === null"
|
||||
:disable-menu="true"
|
||||
:show-user-status="false"
|
||||
:disable-tooltip="true"
|
||||
:size="size" />
|
||||
<div v-else class="avatar" :style="sessionBackgroundStyle">
|
||||
{{ guestInitial }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Avatar from '@nextcloud/vue/dist/Components/Avatar'
|
||||
export default {
|
||||
name: 'AvatarWrapper',
|
||||
components: {
|
||||
Avatar,
|
||||
},
|
||||
props: {
|
||||
session: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: () => 32,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
sessionAvatarStyle() {
|
||||
return {
|
||||
...this.sessionBackgroundStyle,
|
||||
'border-color': this.session.color,
|
||||
'border-width': '2px',
|
||||
'border-style': 'solid',
|
||||
'--size': this.size + 'px',
|
||||
'--font-size': this.size / 2 + 'px',
|
||||
}
|
||||
},
|
||||
sessionBackgroundStyle() {
|
||||
return {
|
||||
'background-color': this.session.userId ? this.session.color + ' !important' : '#b9b9b9',
|
||||
}
|
||||
},
|
||||
guestInitial() {
|
||||
return this.session.guestName === '' ? '?' : this.session.guestName.slice(0, 1).toUpperCase()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.avatar, .avatar-wrapper {
|
||||
border-radius: 50%;
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
line-height: var(--size);
|
||||
font-size: var(--font-size);
|
||||
font-weight: normal;
|
||||
}
|
||||
</style>
|
|
@ -58,7 +58,7 @@
|
|||
{{ lastSavedStatus }}
|
||||
</div>
|
||||
<SessionList :sessions="filteredSessions">
|
||||
<GuestNameDialog v-if="isPublic && currentSession.guestName" />
|
||||
<GuestNameDialog v-if="isPublic && !currentSession.userId" :session="currentSession" />
|
||||
</SessionList>
|
||||
</div>
|
||||
<slot name="header" />
|
||||
|
@ -109,7 +109,6 @@ import {
|
|||
|
||||
import { SyncService, ERROR_TYPE, IDLE_TIMEOUT } from './../services/SyncService.js'
|
||||
import ImageResolver from './../services/ImageResolver.js'
|
||||
import { getRandomGuestName } from './../helpers/index.js'
|
||||
import { extensionHighlight } from '../helpers/mappings.js'
|
||||
import { createEditor, serializePlainText, loadSyntaxHighlight } from './../EditorFactory.js'
|
||||
import { createMarkdownSerializer } from './../extensions/Markdown.js'
|
||||
|
@ -361,8 +360,7 @@ export default {
|
|||
this.$parent.$emit('error', 'No valid file provided')
|
||||
return
|
||||
}
|
||||
|
||||
const guestName = localStorage.getItem('nick') ? localStorage.getItem('nick') : getRandomGuestName()
|
||||
const guestName = localStorage.getItem('nick') ? localStorage.getItem('nick') : ''
|
||||
|
||||
this.$syncService = new SyncService({
|
||||
guestName,
|
||||
|
|
|
@ -22,8 +22,11 @@
|
|||
|
||||
<template>
|
||||
<form v-tooltip="t('text', 'Enter your name so other users can see who is editing')" class="guest-name-dialog" @submit.prevent="setGuestName()">
|
||||
<label><Avatar :url="avatarUrl" :disable-tooltip="true" :size="32" /></label>
|
||||
<input v-model="guestName" type="text" :aria-label="t('text', 'Edit guest name')">
|
||||
<label><AvatarWrapper :session="session" :size="32" /></label>
|
||||
<input v-model="guestName"
|
||||
type="text"
|
||||
:aria-label="t('text', 'Edit guest name')"
|
||||
:placeholder="t('text', 'Guest')">
|
||||
<input type="submit"
|
||||
class="icon-confirm"
|
||||
:aria-label="t('text', 'Save guest name')"
|
||||
|
@ -33,19 +36,27 @@
|
|||
|
||||
<script>
|
||||
import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip'
|
||||
import Avatar from '@nextcloud/vue/dist/Components/Avatar'
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
import AvatarWrapper from './AvatarWrapper.vue'
|
||||
import { useSyncServiceMixin } from './EditorWrapper.provider.js'
|
||||
|
||||
export default {
|
||||
name: 'GuestNameDialog',
|
||||
components: {
|
||||
Avatar,
|
||||
AvatarWrapper,
|
||||
},
|
||||
directives: {
|
||||
tooltip: Tooltip,
|
||||
},
|
||||
mixins: [useSyncServiceMixin],
|
||||
mixins: [
|
||||
useSyncServiceMixin,
|
||||
],
|
||||
props: {
|
||||
session: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
guestName: '',
|
||||
|
|
|
@ -21,23 +21,15 @@
|
|||
-->
|
||||
|
||||
<template>
|
||||
<Popover class="session-list" placement="top">
|
||||
<Popover class="session-list" placement="bottom">
|
||||
<button slot="trigger"
|
||||
v-tooltip.bottom="t('text', 'Participants')"
|
||||
class="avatar-list">
|
||||
<div class="avatardiv icon-group" />
|
||||
<div v-for="session in sessionsVisible"
|
||||
<AvatarWrapper v-for="session in sessionsVisible"
|
||||
:key="session.id"
|
||||
class="avatar-wrapper"
|
||||
:style="sessionStyle(session)">
|
||||
<Avatar :style="avatarStyle(session)"
|
||||
:user="session.userId ? session.userId : session.guestName"
|
||||
:is-guest="session.userId === null"
|
||||
:disable-menu="true"
|
||||
:show-user-status="false"
|
||||
:disable-tooltip="true"
|
||||
:size="44" />
|
||||
</div>
|
||||
:session="session"
|
||||
:size="40" />
|
||||
</button>
|
||||
<template #default>
|
||||
<div class="session-menu">
|
||||
|
@ -46,16 +38,11 @@
|
|||
<li v-for="session in participantsPopover"
|
||||
:key="session.id"
|
||||
:style="avatarStyle(session)">
|
||||
<div class="avatar-wrapper"
|
||||
:style="sessionStyle(session)">
|
||||
<Avatar :user="session.userId ? session.userId : session.guestName"
|
||||
:is-guest="session.userId === null"
|
||||
:disable-menu="true"
|
||||
:show-user-status="false"
|
||||
:disable-tooltip="true"
|
||||
:size="32" />
|
||||
</div>
|
||||
{{ session.guestName ? session.guestName : session.displayName }}
|
||||
<AvatarWrapper :session="session" :size="32" />
|
||||
<span class="session-label">
|
||||
{{ session.userId ? session.displayName : (session.guestName ? session.guestName : t('text', 'Guest')) }}
|
||||
</span>
|
||||
<span v-if="session.userId === null" class="guest-label">({{ t('text', 'guest') }})</span>
|
||||
</li>
|
||||
</ul>
|
||||
<input id="toggle-color-annotations"
|
||||
|
@ -72,9 +59,9 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import Avatar from '@nextcloud/vue/dist/Components/Avatar'
|
||||
import Popover from '@nextcloud/vue/dist/Components/Popover'
|
||||
import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip'
|
||||
import AvatarWrapper from './AvatarWrapper.vue'
|
||||
import store from '../mixins/store.js'
|
||||
|
||||
const COLLABORATOR_IDLE_TIME = 60
|
||||
|
@ -83,7 +70,7 @@ const COLLABORATOR_DISCONNECT_TIME = 90
|
|||
export default {
|
||||
name: 'SessionList',
|
||||
components: {
|
||||
Avatar,
|
||||
AvatarWrapper,
|
||||
Popover,
|
||||
},
|
||||
directives: {
|
||||
|
@ -128,14 +115,6 @@ export default {
|
|||
currentSession() {
|
||||
return Object.values(this.sessions).find((session) => session.isCurrent)
|
||||
},
|
||||
sessionStyle() {
|
||||
return (session) => {
|
||||
return {
|
||||
'border-color': session.color,
|
||||
'background-color': session.color + ' !important',
|
||||
}
|
||||
}
|
||||
},
|
||||
avatarStyle() {
|
||||
return (session) => {
|
||||
return {
|
||||
|
@ -166,8 +145,10 @@ export default {
|
|||
|
||||
.avatar-wrapper {
|
||||
margin: 0 -8px 0 0;
|
||||
height: 44px;
|
||||
width: 44px;
|
||||
z-index: 1;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
box-sizing: content-box !important;
|
||||
}
|
||||
|
||||
.icon-more, .icon-group, .icon-settings-dark {
|
||||
|
@ -178,13 +159,6 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
.avatar-wrapper {
|
||||
z-index: 1;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
box-sizing: content-box !important;
|
||||
}
|
||||
|
||||
.session-menu {
|
||||
max-width: 280px;
|
||||
padding-top: 6px;
|
||||
|
@ -200,6 +174,14 @@ export default {
|
|||
width: 32px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.session-label {
|
||||
padding-right: 3px;
|
||||
}
|
||||
.guest-label {
|
||||
padding-left: 3px;
|
||||
color: var(--color-text-maxcontrast);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,13 +44,7 @@ const endpointUrl = (endpoint, isPublic = false) => {
|
|||
return `${_baseUrl}/${endpoint}`
|
||||
}
|
||||
|
||||
const randomGuestNames = ['Artichoke', 'Arugula', 'Asparagus', 'Avocado', 'Bamboo Shoot', 'Bean Sprout', 'Bean', 'Beet', 'Belgian Endive', 'Bell Pepper', 'Bitter Melon', 'Bitter Gourd', 'Bok Choy', 'Broccoli', 'Brussels Sprout', 'Burdock Root', 'Cabbage', 'Calabash', 'Caper', 'Carrot', 'Cassava', 'Cauliflower', 'Celery', 'Celery Root', 'Celtuce', 'Chayote', 'Chinese Broccoli', 'Corn', 'Baby Corn', 'Cucumber', 'English Cucumber', 'Gherkin', 'Pickling Cucumber', 'Daikon Radish', 'Edamame', 'Eggplant', 'Elephant Garlic', 'Endive', 'Curly', 'Escarole', 'Fennel', 'Fiddlehead', 'Galangal', 'Garlic', 'Ginger', 'Grape Leave', 'Green Bean', 'Wax Bean', 'Green', 'Amaranth Leave', 'Beet Green', 'Collard Green', 'Dandelion Green', 'Kale', 'Kohlrabi Green', 'Mustard Green', 'Rapini', 'Spinach', 'Swiss Chard', 'Turnip Green', 'Hearts of Palm', 'Horseradish', 'Jerusalem Artichoke', 'Jícama', 'Kale', 'Curly', 'Lacinato', 'Ornamental', 'Kohlrabi', 'Leeks', 'Lemongrass', 'Lettuce', 'Butterhead', 'Iceberg', 'Leaf', 'Romaine', 'Lotus Root', 'Lotus Seed', 'Mushroom', 'Napa Cabbage', 'Nopales', 'Okra', 'Olive', 'Onion', 'Green Onion', 'Parsley', 'Parsley Root', 'Parsnip', 'Pepper', 'Plantain', 'Potato', 'Pumpkin', 'Purslane', 'Radicchio', 'Radish', 'Rutabaga', 'Shallots', 'Spinach', 'Squash', 'Sweet Potato', 'Swiss Chard', 'Taro', 'Tomatillo', 'Tomato', 'Turnip', 'Water Chestnut', 'Water Spinach', 'Watercress', 'Winter Melon', 'Yams', 'Zucchini']
|
||||
const getRandomGuestName = () => {
|
||||
return randomGuestNames[Math.floor(Math.random() * randomGuestNames.length)]
|
||||
}
|
||||
|
||||
export {
|
||||
documentReady,
|
||||
endpointUrl,
|
||||
getRandomGuestName,
|
||||
}
|
||||
|
|
|
@ -1,31 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<files psalm-version="4.x-dev@">
|
||||
<file src="lib/AppInfo/Application.php">
|
||||
<InvalidArgument occurrences="1">
|
||||
<code>RegisterDirectEditorEventListener::class</code>
|
||||
</InvalidArgument>
|
||||
<UndefinedClass occurrences="3">
|
||||
<code>BeforeTemplateRenderedEvent</code>
|
||||
<code>LoadAdditionalScriptsEvent</code>
|
||||
<code>LoadViewer</code>
|
||||
</UndefinedClass>
|
||||
<InvalidArgument occurrences="3">
|
||||
<code>registerEventListener</code>
|
||||
</InvalidArgument>
|
||||
</file>
|
||||
<file src="lib/Command/ResetDocument.php">
|
||||
<ImplementedReturnTypeMismatch occurrences="1">
|
||||
<code>void</code>
|
||||
</ImplementedReturnTypeMismatch>
|
||||
</file>
|
||||
<file src="lib/Controller/DirectSessionController.php">
|
||||
<UndefinedClass occurrences="1">
|
||||
<code>InvalidTokenException</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/Controller/PublicSessionController.php">
|
||||
<InvalidCatch occurrences="1"/>
|
||||
<MissingDependency occurrences="1">
|
||||
<code>ShareNotFound</code>
|
||||
</MissingDependency>
|
||||
</file>
|
||||
<file src="lib/Controller/SettingsController.php">
|
||||
<UndefinedThisPropertyAssignment occurrences="1">
|
||||
<code>$this->userId</code>
|
||||
|
@ -35,41 +24,26 @@
|
|||
</UndefinedThisPropertyFetch>
|
||||
</file>
|
||||
<file src="lib/Controller/WorkspaceController.php">
|
||||
<InvalidCatch occurrences="2"/>
|
||||
<InvalidReturnType occurrences="3">
|
||||
<code>DataResponse</code>
|
||||
<code>DataResponse</code>
|
||||
<code>DataResponse</code>
|
||||
</InvalidReturnType>
|
||||
<MissingDependency occurrences="10">
|
||||
<code>$e</code>
|
||||
<code>$e</code>
|
||||
<MissingDependency occurrences="4">
|
||||
<code>$this->rootFolder</code>
|
||||
<code>$this->rootFolder</code>
|
||||
<code>IRootFolder</code>
|
||||
<code>IRootFolder</code>
|
||||
<code>ShareNotFound</code>
|
||||
<code>StorageNotAvailableException</code>
|
||||
<code>StorageNotAvailableException</code>
|
||||
</MissingDependency>
|
||||
<UndefinedClass occurrences="1">
|
||||
<code>Exception</code>
|
||||
</UndefinedClass>
|
||||
<UndefinedInterfaceMethod occurrences="1">
|
||||
<code>open</code>
|
||||
</UndefinedInterfaceMethod>
|
||||
<UndefinedThisPropertyFetch occurrences="1">
|
||||
<code>$this->logger</code>
|
||||
</UndefinedThisPropertyFetch>
|
||||
</file>
|
||||
<file src="lib/DAV/WorkspacePlugin.php">
|
||||
<UndefinedClass occurrences="1">
|
||||
<code>ServerPlugin</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/Db/SessionMapper.php">
|
||||
<MoreSpecificImplementedParamType occurrences="1"/>
|
||||
</file>
|
||||
<file src="lib/Db/StepMapper.php">
|
||||
<InvalidReturnStatement occurrences="1"/>
|
||||
<InvalidReturnType occurrences="1">
|
||||
|
@ -97,28 +71,18 @@
|
|||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/Service/ApiService.php">
|
||||
<InvalidArgument occurrences="1">
|
||||
<code>$file</code>
|
||||
</InvalidArgument>
|
||||
<UndefinedDocblockClass occurrences="1"/>
|
||||
</file>
|
||||
<file src="lib/Service/DocumentService.php">
|
||||
<InvalidCatch occurrences="3"/>
|
||||
<InvalidScalarArgument occurrences="1"/>
|
||||
<MismatchingDocblockReturnType occurrences="1">
|
||||
<code>Entity</code>
|
||||
</MismatchingDocblockReturnType>
|
||||
<MissingDependency occurrences="7">
|
||||
<MissingDependency occurrences="3">
|
||||
<code>$this->rootFolder</code>
|
||||
<code>IRootFolder</code>
|
||||
<code>IRootFolder</code>
|
||||
<code>ShareNotFound</code>
|
||||
<code>ShareNotFound</code>
|
||||
<code>ShareNotFound</code>
|
||||
<code>ShareNotFound</code>
|
||||
</MissingDependency>
|
||||
<UndefinedClass occurrences="2">
|
||||
<code>File</code>
|
||||
<UndefinedClass occurrences="1">
|
||||
<code>\OC\User\NoUserException</code>
|
||||
</UndefinedClass>
|
||||
<UndefinedMagicMethod occurrences="18">
|
||||
|
@ -141,20 +105,38 @@
|
|||
<code>setSessionId</code>
|
||||
<code>setVersion</code>
|
||||
</UndefinedMagicMethod>
|
||||
<UndefinedThisPropertyFetch occurrences="1">
|
||||
<code>$this->lockingProvider</code>
|
||||
</UndefinedThisPropertyFetch>
|
||||
</file>
|
||||
<file src="lib/Service/ImageService.php">
|
||||
<MissingDependency occurrences="6">
|
||||
<code>$this->rootFolder</code>
|
||||
<code>$this->rootFolder</code>
|
||||
<code>$this->rootFolder</code>
|
||||
<code>$this->rootFolder</code>
|
||||
<code>IRootFolder</code>
|
||||
<code>IRootFolder</code>
|
||||
</MissingDependency>
|
||||
<UndefinedClass occurrences="3">
|
||||
<code>ClientException</code>
|
||||
<code>ConnectException</code>
|
||||
<code>ServerException</code>
|
||||
</UndefinedClass>
|
||||
<UndefinedDocblockClass occurrences="8">
|
||||
<code>\OC\User\NoUserException</code>
|
||||
<code>\OC\User\NoUserException</code>
|
||||
<code>\OC\User\NoUserException</code>
|
||||
<code>\OC\User\NoUserException</code>
|
||||
<code>\OC\User\NoUserException</code>
|
||||
<code>\OC\User\NoUserException</code>
|
||||
<code>\OC\User\NoUserException</code>
|
||||
<code>\OC\User\NoUserException</code>
|
||||
</UndefinedDocblockClass>
|
||||
</file>
|
||||
<file src="lib/Service/SessionService.php">
|
||||
<UndefinedDocblockClass occurrences="8">
|
||||
<code>$color->b</code>
|
||||
<UndefinedDocblockClass occurrences="4">
|
||||
<code>$color->b</code>
|
||||
<code>$color->g</code>
|
||||
<code>$color->g</code>
|
||||
<code>$color->r</code>
|
||||
<code>$color->r</code>
|
||||
<code>$this->avatarManager->getGuestAvatar($guestName)->avatarBackgroundColor($guestName)</code>
|
||||
<code>$this->avatarManager->getGuestAvatar($userName)->avatarBackgroundColor($userName)</code>
|
||||
<code>$this->avatarManager->getGuestAvatar($uniqueGuestId)->avatarBackgroundColor($uniqueGuestId)</code>
|
||||
</UndefinedDocblockClass>
|
||||
<UndefinedMagicMethod occurrences="7">
|
||||
<code>setColor</code>
|
||||
|
@ -170,27 +152,10 @@
|
|||
<InvalidNullableReturnType occurrences="1">
|
||||
<code>\OCP\Files\File</code>
|
||||
</InvalidNullableReturnType>
|
||||
<MissingDependency occurrences="1">
|
||||
<code>StorageNotAvailableException</code>
|
||||
</MissingDependency>
|
||||
<NullableReturnStatement occurrences="1">
|
||||
<code>null</code>
|
||||
</NullableReturnStatement>
|
||||
</file>
|
||||
<file src="lib/Service/ImageService.php">
|
||||
<InvalidCatch occurrences="2"/>
|
||||
<MissingDependency occurrences="8">
|
||||
<code>$this->rootFolder</code>
|
||||
<code>IRootFolder</code>
|
||||
<code>ShareNotFound</code>
|
||||
</MissingDependency>
|
||||
<UndefinedClass occurrences="3">
|
||||
<code>\OC\User\NoUserException</code>
|
||||
</UndefinedClass>
|
||||
<UndefinedDocblockClass occurrences="10">
|
||||
<code>\OC\User\NoUserException</code>
|
||||
</UndefinedDocblockClass>
|
||||
</file>
|
||||
<file src="vendor/christophwurst/nextcloud/OCP/BackgroundJob/TimedJob.php">
|
||||
<ImplementedParamTypeMismatch occurrences="1">
|
||||
<code>$jobList</code>
|
||||
|
|
Загрузка…
Ссылка в новой задаче