diff --git a/demo/src/ChatContainer.vue b/demo/src/ChatContainer.vue
index 9d6421f6..27655e83 100644
--- a/demo/src/ChatContainer.vue
+++ b/demo/src/ChatContainer.vue
@@ -51,6 +51,7 @@
:room-actions="roomActions"
:menu-actions="menuActions"
:room-message="roomMessage"
+ :templates-text="templatesText"
@fetch-more-rooms="fetchMoreRooms"
@fetch-messages="fetchMessages"
@send-message="sendMessage"
@@ -141,7 +142,21 @@ export default {
{ name: 'removeUser', title: 'Remove User' },
{ name: 'deleteRoom', title: 'Delete Room' }
],
- styles: { container: { borderRadius: '4px' } }
+ styles: { container: { borderRadius: '4px' } },
+ templatesText: [
+ {
+ tag: 'help',
+ text: 'This is the help'
+ },
+ {
+ tag: 'action',
+ text: 'this is the action'
+ },
+ {
+ tag: 'action 2',
+ text: 'this is the second action'
+ }
+ ]
// ,dbRequestCount: 0
}
},
diff --git a/package.json b/package.json
index c1aa3e03..64a29fce 100644
--- a/package.json
+++ b/package.json
@@ -68,7 +68,7 @@
"typescript": "^4.0.5",
"vue": "^2.6.14",
"vue-jest": "^3.0.7",
- "vue-template-compiler": "^2.6.11"
+ "vue-template-compiler": "^2.6.14"
},
"peerDependencies": {
"vue": "^2.6.14"
diff --git a/src/lib/ChatWindow.vue b/src/lib/ChatWindow.vue
index d29c4f15..a1658d68 100644
--- a/src/lib/ChatWindow.vue
+++ b/src/lib/ChatWindow.vue
@@ -54,6 +54,7 @@
:room-info-enabled="roomInfoEnabled"
:textarea-action-enabled="textareaActionEnabled"
:accepted-files="acceptedFiles"
+ :templates-text="templatesText"
@toggle-rooms-list="toggleRoomsList"
@room-info="roomInfo"
@fetch-messages="fetchMessages"
@@ -138,7 +139,8 @@ export default {
roomInfoEnabled: { type: Boolean, default: false },
textareaActionEnabled: { type: Boolean, default: false },
roomMessage: { type: String, default: '' },
- acceptedFiles: { type: String, default: '*' }
+ acceptedFiles: { type: String, default: '*' },
+ templatesText: { type: Array, default: null }
},
emits: [
diff --git a/src/lib/Room/Room.vue b/src/lib/Room/Room.vue
index dd7101a5..5d07fd40 100644
--- a/src/lib/Room/Room.vue
+++ b/src/lib/Room/Room.vue
@@ -140,6 +140,14 @@
@select-user-tag="selectUserTag($event)"
/>
+
+
@@ -264,7 +278,7 @@
type="file"
multiple
:accept="acceptedFiles"
- style="display:none"
+ style="display: none"
@change="onFileChange($event.target.files)"
/>
@@ -298,9 +312,10 @@ import RoomFiles from './RoomFiles/RoomFiles'
import RoomMessageReply from './RoomMessageReply/RoomMessageReply'
import RoomUsersTag from './RoomUsersTag/RoomUsersTag'
import RoomEmojis from './RoomEmojis/RoomEmojis'
+import RoomTemplatesText from './RoomTemplatesText/RoomTemplatesText'
import Message from '../Message/Message'
-import filteredUsers from '../../utils/filter-items'
+import filteredItems from '../../utils/filter-items'
import Recorder from '../../utils/recorder'
const { detectMobile, iOSDevice } = require('../../utils/mobile-detection')
@@ -327,6 +342,7 @@ export default {
RoomMessageReply,
RoomUsersTag,
RoomEmojis,
+ RoomTemplatesText,
Message
},
@@ -360,7 +376,8 @@ export default {
linkOptions: { type: Object, required: true },
loadingRooms: { type: Boolean, required: true },
roomInfoEnabled: { type: Boolean, required: true },
- textareaActionEnabled: { type: Boolean, required: true }
+ textareaActionEnabled: { type: Boolean, required: true },
+ templatesText: { type: Array, default: null }
},
emits: [
@@ -398,6 +415,9 @@ export default {
filteredEmojis: [],
filteredUsersTag: [],
selectedUsersTag: [],
+ filteredTemplatesText: [],
+ activeTemplate: null,
+ activeUpOrDown: null,
textareaCursorPosition: null,
cursorRangePosition: null,
emojisDB: new Database(),
@@ -442,6 +462,7 @@ export default {
return (
!!this.filteredEmojis.length ||
!!this.filteredUsersTag.length ||
+ !!this.filteredTemplatesText.length ||
!!this.files.length ||
!!this.messageReply
)
@@ -515,7 +536,7 @@ export default {
if (isMobile) {
this.message = this.message + '\n'
setTimeout(() => this.onChangeInput())
- } else {
+ } else if (this.filteredTemplatesText.length === 0) {
this.sendMessage()
}
}
@@ -523,6 +544,7 @@ export default {
setTimeout(() => {
this.updateFooterList('@')
this.updateFooterList(':')
+ this.updateFooterList('/')
}, 60)
}),
50
@@ -533,6 +555,7 @@ export default {
this.updateFooterList('@')
this.updateFooterList(':')
+ this.updateFooterList('/')
})
this.$refs['roomTextarea'].addEventListener('blur', () => {
@@ -642,6 +665,10 @@ export default {
return
}
+ if (tagChar === '/' && !this.templatesText) {
+ return
+ }
+
if (
this.textareaCursorPosition ===
this.$refs['roomTextarea'].selectionStart
@@ -676,6 +703,8 @@ export default {
this.updateEmojis(query)
} else if (tagChar === '@') {
this.updateShowUsersTag(query)
+ } else if (tagChar === '/') {
+ this.updateShowTemplatesText(query)
}
} else {
this.resetFooterList(tagChar)
@@ -717,7 +746,7 @@ export default {
this.focusTextarea()
},
updateShowUsersTag(query) {
- this.filteredUsersTag = filteredUsers(
+ this.filteredUsersTag = filteredItems(
this.room.users,
'username',
query,
@@ -743,14 +772,55 @@ export default {
position + user.username.length + space.length + 1
this.focusTextarea()
},
+ updateShowTemplatesText(query) {
+ this.filteredTemplatesText = filteredItems(
+ this.templatesText,
+ 'tag',
+ query,
+ true
+ )
+ },
+ selectTemplateText(template) {
+ this.activeTemplate = false
+ if (!template) return
+ const { position, endPosition } = this.getCharPosition('/')
+
+ const space = this.message.substr(endPosition, endPosition).length
+ ? ''
+ : ' '
+
+ this.message =
+ this.message.substr(0, position - 1) +
+ template.text +
+ space +
+ this.message.substr(endPosition, this.message.length - 1)
+
+ this.cursorRangePosition =
+ position + template.text.length + space.length + 1
+ this.focusTextarea()
+ },
+ beforeEnter() {
+ if (this.filteredTemplatesText.length > 0) {
+ this.activeTemplate = true
+ }
+ },
+ upActiveTemplate() {
+ this.activeUpOrDown = -1
+ },
+ downActiveTemplate() {
+ this.activeUpOrDown = 1
+ },
resetFooterList(tagChar = null) {
if (tagChar === ':') {
this.filteredEmojis = []
} else if (tagChar === '@') {
this.filteredUsersTag = []
+ } else if (tagChar === '/') {
+ this.filteredTemplatesText = []
} else {
this.filteredEmojis = []
this.filteredUsersTag = []
+ this.filteredTemplatesText = []
}
this.textareaCursorPosition = null
@@ -758,7 +828,9 @@ export default {
escapeTextarea() {
if (this.filteredEmojis.length) this.filteredEmojis = []
else if (this.filteredUsersTag.length) this.filteredUsersTag = []
- else this.resetMessage()
+ else if (this.filteredTemplatesText.length) {
+ this.filteredTemplatesText = []
+ } else this.resetMessage()
},
resetMessage(disableMobileFocus = false, initRoom = false) {
if (!initRoom) {
diff --git a/src/lib/Room/RoomTemplatesText/RoomTemplatesText.scss b/src/lib/Room/RoomTemplatesText/RoomTemplatesText.scss
new file mode 100644
index 00000000..42fee667
--- /dev/null
+++ b/src/lib/Room/RoomTemplatesText/RoomTemplatesText.scss
@@ -0,0 +1,45 @@
+.vac-template-container {
+ position: absolute;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 100%;
+
+ .vac-template-box {
+ display: flex;
+ width: 100%;
+ height: 54px;
+ overflow: hidden;
+ cursor: pointer;
+ background: var(--chat-footer-bg-color-tag);
+ transition: background-color 0.3s cubic-bezier(0.25, 0.8, 0.5, 1);
+ }
+ .vac-template-active {
+ background: var(--chat-footer-bg-color-tag-active);
+ transition: background-color 0.3s cubic-bezier(0.25, 0.8, 0.5, 1) !important;
+ }
+ .vac-template-info {
+ display: flex;
+ overflow: hidden;
+ padding: 0 20px;
+ align-items: center;
+ }
+ .vac-template-tag {
+ font-size: 14px;
+ font-weight: bold;
+ margin-right: 10px;
+ }
+ .vac-template-text {
+ font-size: 14px;
+ }
+
+ @media only screen and (max-width: 768px) {
+ .vac-template-box {
+ height: 50px;
+ }
+
+ .vac-template-info {
+ padding: 0 12px;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/lib/Room/RoomTemplatesText/RoomTemplatesText.vue b/src/lib/Room/RoomTemplatesText/RoomTemplatesText.vue
new file mode 100644
index 00000000..fd7cedb4
--- /dev/null
+++ b/src/lib/Room/RoomTemplatesText/RoomTemplatesText.vue
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+/{{ template.tag }}
+
+
+ {{ template.text }}
+
+
+
+
+
+
+
+
diff --git a/src/styles/index.scss b/src/styles/index.scss
index 62ef80c9..9c7d721f 100644
--- a/src/styles/index.scss
+++ b/src/styles/index.scss
@@ -11,6 +11,7 @@
@import '../lib/Room/RoomFiles/RoomFiles';
@import '../lib/Room/RoomFile/RoomFile';
@import '../lib/Room/RoomUsersTag/RoomUsersTag';
+@import '../lib/Room/RoomTemplatesText/RoomTemplatesText';
@import '../lib/RoomsList/RoomsList';
@import '../lib/RoomsList/RoomContent/RoomContent';
diff --git a/src/themes/index.js b/src/themes/index.js
index 1517fb40..cf1a4cb1 100644
--- a/src/themes/index.js
+++ b/src/themes/index.js
@@ -28,7 +28,8 @@ export const defaultThemeStyles = {
borderStyleInput: '1px solid #e1e4e8',
borderInputSelected: '#1976d2',
backgroundReply: '#e5e5e6',
- backgroundTagActive: '#e5e5e6'
+ backgroundTagActive: '#e5e5e6',
+ backgroundTag: '#fff'
},
content: {
@@ -167,7 +168,8 @@ export const defaultThemeStyles = {
borderStyleInput: 'none',
borderInputSelected: '#1976d2',
backgroundReply: '#1b1c1c',
- backgroundTagActive: '#1b1c1c'
+ backgroundTagActive: '#1b1c1c',
+ backgroundTag: '#131415'
},
content: {
@@ -319,6 +321,7 @@ export const cssThemeVars = ({
'--chat-border-color-input-selected': footer.borderInputSelected,
'--chat-footer-bg-color-reply': footer.backgroundReply,
'--chat-footer-bg-color-tag-active': footer.backgroundTagActive,
+ '--chat-footer-bg-color-tag': footer.backgroundTag,
// content
'--chat-content-bg-color': content.background,