Skip to content

Commit

Permalink
Moved link share settings to sidebar
Browse files Browse the repository at this point in the history
Moved link share settings to the settings tab in the right sidebar.
Moved "Share link" and renamed to "Allow guests" to match conversation
messages wording.
Added "Copy link" also in settings, for convenience.
Added notifications after success/error when saving.
Added field disabling logic while saving which provides some visual
feedback.

Signed-off-by: Vincent Petry <vincent@nextcloud.com>
  • Loading branch information
PVince81 committed Nov 11, 2020
1 parent 7f54b9f commit 29e7d5d
Show file tree
Hide file tree
Showing 4 changed files with 196 additions and 89 deletions.
23 changes: 10 additions & 13 deletions src/components/RightSidebar/RightSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
:id="conversation.token"
type="room"
:name="conversation.displayName" />
<LinkShareSettings
v-if="token && canFullModerate && showModerationOptions" />
<div id="app-settings">
<div id="app-settings-header">
<button class="settings-button" @click="showSettings">
Expand All @@ -82,11 +84,12 @@ import AppSidebarTab from '@nextcloud/vue/dist/Components/AppSidebarTab'
import ChatView from '../ChatView'
import { CollectionList } from 'nextcloud-vue-collections'
import BrowserStorage from '../../services/BrowserStorage'
import { CONVERSATION, WEBINAR, PARTICIPANT } from '../../constants'
import { CONVERSATION, PARTICIPANT } from '../../constants'
import ParticipantsTab from './Participants/ParticipantsTab'
import MatterbridgeSettings from './Matterbridge/MatterbridgeSettings'
import isInLobby from '../../mixins/isInLobby'
import SetGuestUsername from '../SetGuestUsername'
import LinkShareSettings from './Settings/LinkShareSettings'
import { EventBus } from '../../services/EventBus'

export default {
Expand All @@ -99,6 +102,7 @@ export default {
ParticipantsTab,
SetGuestUsername,
MatterbridgeSettings,
LinkShareSettings,
},

mixins: [
Expand Down Expand Up @@ -137,18 +141,7 @@ export default {
return this.$store.getters.getToken()
},
conversation() {
if (this.$store.getters.conversation(this.token)) {
return this.$store.getters.conversation(this.token)
}
return {
token: '',
displayName: '',
isFavorite: false,
hasPassword: false,
type: CONVERSATION.TYPE.PUBLIC,
lobbyState: WEBINAR.LOBBY.NONE,
lobbyTimer: 0,
}
return this.$store.getters.conversation(this.token) || this.$store.getters.dummyConversation
},

getUserId() {
Expand Down Expand Up @@ -183,6 +176,10 @@ export default {
return this.conversation.type !== CONVERSATION.TYPE.ONE_TO_ONE && (this.canFullModerate || this.participantType === PARTICIPANT.TYPE.GUEST_MODERATOR)
},

showModerationOptions() {
return this.conversation.type !== CONVERSATION.TYPE.ONE_TO_ONE && this.canModerate
},

/**
* The conversation title value passed into the AppSidebar component.
* @returns {string} The conversation's title.
Expand Down
174 changes: 174 additions & 0 deletions src/components/RightSidebar/Settings/LinkShareSettings.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<!--
- @copyright Copyright (c) 2020 Vincent Petry <vincent@nextcloud.com>
-
- @author Vincent Petry <vincent@nextcloud.com>
-
- @license GNU AGPL version 3 or any later version
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-->

<template>
<ul>
<ActionButton
icon="icon-clippy"
:close-after-click="true"
@click="handleCopyLink">
{{ t('spreed', 'Copy link') }}
</ActionButton>
<ActionCheckbox
:disabled="isSaving"
:checked="isSharedPublicly"
@change="toggleGuests">
{{ t('spreed', 'Allow guests') }}
</ActionCheckbox>
<ActionCheckbox
v-if="isSharedPublicly"
class="share-link-password-checkbox"
:disabled="isSaving"
:checked="conversation.hasPassword"
@check="handlePasswordEnable"
@uncheck="handlePasswordDisable">
{{ t('spreed', 'Password protection') }}
</ActionCheckbox>
<ActionInput
v-show="showPasswordField"
class="share-link-password"
icon="icon-password"
type="password"
:disabled="isSaving"
:value.sync="password"
autocomplete="new-password"
@submit="handleSetNewPassword">
{{ t('spreed', 'Enter a password') }}
</ActionInput>
</ul>
</template>

<script>
import { showError, showSuccess } from '@nextcloud/dialogs'
import { CONVERSATION } from '../../../constants'
import {
setConversationPassword,
} from '../../../services/conversationsService'
import { generateUrl } from '@nextcloud/router'
import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
import ActionCheckbox from '@nextcloud/vue/dist/Components/ActionCheckbox'
import ActionInput from '@nextcloud/vue/dist/Components/ActionInput'

export default {
name: 'LinkShareSettings',

components: {
ActionButton,
ActionCheckbox,
ActionInput,
},

data() {
return {
// The conversation's password
password: '',
// Switch for the password-editing operation
showPasswordField: false,
isSaving: false,
}
},

computed: {
isSharedPublicly() {
return this.conversation.type === CONVERSATION.TYPE.PUBLIC
},

token() {
return this.$store.getters.getToken()
},

conversation() {
return this.$store.getters.conversation(this.token) || this.$store.getters.dummyConversation
},
},

methods: {
async handleCopyLink() {
try {
await this.$copyText(window.location.protocol + '//' + window.location.host + generateUrl('/call/' + this.token))
showSuccess(t('spreed', 'Conversation link copied to clipboard.'))
} catch (error) {
showError(t('spreed', 'The link could not be copied.'))
}
},

async setConversationPassword(newPassword) {
this.isSaving = true
try {
await setConversationPassword(this.token, newPassword)
if (newPassword !== '') {
showSuccess(t('spreed', 'Conversation password has been saved'))
} else {
showSuccess(t('spreed', 'Conversation password has been removed'))
}
} catch (e) {
console.error('Error saving conversation password', e)
showError(t('spreed', 'Error occurred while saving conversation password'))
}
this.isSaving = false
},

async toggleGuests() {
const enabled = this.conversation.type !== CONVERSATION.TYPE.PUBLIC
this.isSaving = true
try {
await this.$store.dispatch('toggleGuests', {
token: this.token,
allowGuests: enabled,
})

if (enabled) {
showSuccess(t('spreed', 'You allowed guests'))
} else {
showSuccess(t('spreed', 'You disallowed guests'))
}
} catch (e) {
if (enabled) {
showError(t('spreed', 'Error occurred while allowing guests'))
} else {
showError(t('spreed', 'Error occurred while disallowing guests'))
}
console.error('Error toggling guest mode', e)
}
this.isSaving = false
},

async handlePasswordDisable() {
// disable the password protection for the current conversation
if (this.conversation.hasPassword) {
await this.setConversationPassword('')
}
this.password = ''
this.showPasswordField = false
},

async handlePasswordEnable() {
this.showPasswordField = true
},

async handleSetNewPassword() {
await this.setConversationPassword(this.password)
this.password = ''
this.showPasswordField = false
},
},
}
</script>
77 changes: 1 addition & 76 deletions src/components/TopBar/TopBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,6 @@
@click="handleRenameConversation">
{{ t('spreed', 'Rename conversation') }}
</ActionButton>
<ActionSeparator
v-if="canFullModerate" />
<ActionCheckbox
v-if="canFullModerate"
:checked="isSharedPublicly"
@change="toggleGuests">
{{ t('spreed', 'Share link') }}
</ActionCheckbox>
</template>
<ActionButton
v-if="!isOneToOneConversation"
Expand All @@ -96,28 +88,8 @@
@click="handleCopyLink">
{{ t('spreed', 'Copy link') }}
</ActionButton>
<!-- password -->
<template
v-if="showModerationOptions">
<ActionCheckbox
v-if="isSharedPublicly"
class="share-link-password-checkbox"
:checked="isPasswordProtected"
@check="handlePasswordEnable"
@uncheck="handlePasswordDisable">
{{ t('spreed', 'Password protection') }}
</ActionCheckbox>
<ActionInput
v-show="isEditingPassword"
class="share-link-password"
icon="icon-password"
type="password"
:value.sync="password"
autocomplete="new-password"
@submit="handleSetNewPassword">
{{ t('spreed', 'Enter a password') }}
</ActionInput>
<ActionSeparator />
<ActionCheckbox
:checked="isReadOnly"
:disabled="readOnlyStateLoading"
Expand Down Expand Up @@ -185,9 +157,6 @@ import ActionInput from '@nextcloud/vue/dist/Components/ActionInput'
import ActionLink from '@nextcloud/vue/dist/Components/ActionLink'
import ActionSeparator from '@nextcloud/vue/dist/Components/ActionSeparator'
import { CONVERSATION, WEBINAR, PARTICIPANT } from '../../constants'
import {
setConversationPassword,
} from '../../services/conversationsService'
import { generateUrl } from '@nextcloud/router'
import { callParticipantCollection } from '../../utils/webrtc/index'

Expand Down Expand Up @@ -216,10 +185,6 @@ export default {
return {
showLayoutHint: false,
hintDismissed: false,
// The conversation's password
password: '',
// Switch for the password-editing operation
isEditingPassword: false,
lobbyTimerLoading: false,
readOnlyStateLoading: false,
}
Expand Down Expand Up @@ -304,22 +269,8 @@ export default {
token() {
return this.$store.getters.getToken()
},
isSharedPublicly() {
return this.conversation.type === CONVERSATION.TYPE.PUBLIC
},
conversation() {
if (this.$store.getters.conversation(this.token)) {
return this.$store.getters.conversation(this.token)
}
return {
token: '',
displayName: '',
isFavorite: false,
hasPassword: false,
type: CONVERSATION.TYPE.PUBLIC,
lobbyState: WEBINAR.LOBBY.NONE,
lobbyTimer: 0,
}
return this.$store.getters.conversation(this.token) || this.$store.getters.dummyConversation
},
linkToConversation() {
if (this.token !== '') {
Expand All @@ -338,9 +289,6 @@ export default {
isReadOnly() {
return this.conversation.readOnly === CONVERSATION.STATE.READ_ONLY
},
isPasswordProtected() {
return this.conversation.hasPassword
},
lobbyTimer() {
// A timestamp of 0 means that there is no lobby, but it would be
// interpreted as the Unix epoch by the DateTimePicker.
Expand Down Expand Up @@ -453,12 +401,6 @@ export default {
this.$store.dispatch('selectedVideoPeerId', null)
this.showLayoutHint = false
},
async toggleGuests() {
await this.$store.dispatch('toggleGuests', {
token: this.token,
allowGuests: this.conversation.type !== CONVERSATION.TYPE.PUBLIC,
})
},

async toggleLobby() {
await this.$store.dispatch('toggleLobby', {
Expand Down Expand Up @@ -507,23 +449,6 @@ export default {
this.readOnlyStateLoading = false
},

async handlePasswordDisable() {
// disable the password protection for the current conversation
if (this.conversation.hasPassword) {
await setConversationPassword(this.token, '')
}
this.password = ''
this.isEditingPassword = false
},
async handlePasswordEnable() {
this.isEditingPassword = true
},

async handleSetNewPassword() {
await setConversationPassword(this.token, this.password)
this.password = ''
this.isEditingPassword = false
},
async handleCopyLink() {
try {
await this.$copyText(this.linkToConversation)
Expand Down
11 changes: 11 additions & 0 deletions src/store/conversationsStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ import {
import { getCurrentUser } from '@nextcloud/auth'
import { CONVERSATION, WEBINAR } from '../constants'

const DUMMY_CONVERSATION = {
token: '',
displayName: '',
isFavorite: false,
hasPassword: false,
type: CONVERSATION.TYPE.PUBLIC,
lobbyState: WEBINAR.LOBBY.NONE,
lobbyTimer: 0,
}

const getDefaultState = () => {
return {
conversations: {
Expand All @@ -55,6 +65,7 @@ const getters = {
* @returns {object} The conversation object
*/
conversation: state => token => state.conversations[token],
dummyConversation: state => Object.assign({}, DUMMY_CONVERSATION),
}

const mutations = {
Expand Down

0 comments on commit 29e7d5d

Please sign in to comment.