42083efb7e
* Add group plan selection modal for upgrades Allow users to select an existing group to upgrade before creating a new one. * crlf -> lf lint * set selection of group plan Also tiny UI fixes * Update group plan selection to include expired plans * Add includeExpiredPlans option to group fetching * force flag when fetching group plans * Update group plan eligibility check * Fix eslint error in push notification import * replace chaining (?.) w/null check * Remove comment * set initial selected group plan, and fix card rounding * format member count * Show warning for pending party invites when upgrading to paid group plan Show warning for pending party invites when upgrading to paid group plan. If user upgrades from party to group, remove any pending invites * suppress error toasts for group modal, and UI tweaks for group modal suppress error toast for 404 on party fetch for users without a party (for group modal), Increase check SVG size in selectableCard, and show "Previously upgraded" label for parties that were canceled group plans * Clear upgradingGroup state after group plan payment * Update emoji system to native Unicode rendering * Fix line endings in habiticaMarkdown test * fix indented code block detection for markdown-it v14 * update habitica-markdown to include v3 emoji dataset (pointed towards test branch) * size emoji in markdown * emoji autocomplete to chat, messages, tasks, and profile add :emoji shortcode autocomplete dropdown (reusing existing autocomplete mixin w/new helper) * try upping github-action fix * trying another github actions fix * update habitica-markdown package version (v3.0.0 -> v4.0.0) * Fix emoji autocomplete overlapping actual text position dropdown below text * update group-plans info card styles * Support Melior emoji autocomplete & more places for emoji autocomplete Include emoji autocomplete in task checklists, tags, challenge name/summary/description * position emoji autocomplete dropdown below text area * fix: replace nested ternary * Emoji autocomplete fixes Fix emoji autocomplete overlapping checklist text, and add short name emoji autocomplete * Have emoji autocomplete dropdown directly below text, add to task tag * Fix emoji autocomplete starting at beginning/end initially * lint/line length * Add group plan selection modal for upgrades Allow users to select an existing group to upgrade before creating a new one. * crlf -> lf lint * set selection of group plan Also tiny UI fixes * Update group plan selection to include expired plans * Add includeExpiredPlans option to group fetching * force flag when fetching group plans * Update group plan eligibility check * Fix eslint error in push notification import * replace chaining (?.) w/null check * Remove comment * set initial selected group plan, and fix card rounding * format member count * Show warning for pending party invites when upgrading to paid group plan Show warning for pending party invites when upgrading to paid group plan. If user upgrades from party to group, remove any pending invites * suppress error toasts for group modal, and UI tweaks for group modal suppress error toast for 404 on party fetch for users without a party (for group modal), Increase check SVG size in selectableCard, and show "Previously upgraded" label for parties that were canceled group plans * Clear upgradingGroup state after group plan payment * Update emoji system to native Unicode rendering * Fix line endings in habiticaMarkdown test * fix indented code block detection for markdown-it v14 * update habitica-markdown to include v3 emoji dataset (pointed towards test branch) * size emoji in markdown * emoji autocomplete to chat, messages, tasks, and profile add :emoji shortcode autocomplete dropdown (reusing existing autocomplete mixin w/new helper) * try upping github-action fix * trying another github actions fix * update habitica-markdown package version (v3.0.0 -> v4.0.0) * Fix emoji autocomplete overlapping actual text position dropdown below text * update group-plans info card styles * Support Melior emoji autocomplete & more places for emoji autocomplete Include emoji autocomplete in task checklists, tags, challenge name/summary/description * position emoji autocomplete dropdown below text area * fix: replace nested ternary * Emoji autocomplete fixes Fix emoji autocomplete overlapping checklist text, and add short name emoji autocomplete * Have emoji autocomplete dropdown directly below text, add to task tag * Fix emoji autocomplete starting at beginning/end initially * lint/line length * Revert "trying another github actions fix" This reverts commit72fc7fc20e. * Revert "try upping github-action fix" This reverts commit70e48a57aa. * fix(git): revert ci changes --------- Co-authored-by: Kalista Payne <kalista@habitica.com>
301 lines
7.7 KiB
Vue
301 lines
7.7 KiB
Vue
<template>
|
|
<div class="row chat-row">
|
|
<div class="col-12">
|
|
<h3
|
|
class="float-left label"
|
|
:class="{accepted: communityGuidelinesAccepted }"
|
|
>
|
|
{{ label }}
|
|
</h3>
|
|
<div
|
|
v-markdown="$t('markdownFormattingHelp')"
|
|
class="float-right"
|
|
></div>
|
|
<div
|
|
v-if="communityGuidelinesAccepted"
|
|
class="row"
|
|
>
|
|
<textarea
|
|
ref="user-entry"
|
|
v-model="newMessage"
|
|
dir="auto"
|
|
:placeholder="placeholder"
|
|
:class="{'user-entry': newMessage}"
|
|
:maxlength="MAX_MESSAGE_LENGTH"
|
|
@keydown="autoCompleteMixinUpdateCarretPosition"
|
|
@keyup.ctrl.enter="sendMessageShortcut()"
|
|
@keydown.tab="autoCompleteMixinHandleTab($event)"
|
|
@keydown.up="autoCompleteMixinSelectPreviousAutocomplete($event)"
|
|
@keydown.down="autoCompleteMixinSelectNextAutocomplete($event)"
|
|
@keypress.enter="autoCompleteMixinSelectAutocomplete($event)"
|
|
@keydown.esc="autoCompleteMixinHandleEscape($event)"
|
|
@paste="disableMessageSendShortcut()"
|
|
></textarea>
|
|
<span>{{ currentLength }} / {{ MAX_MESSAGE_LENGTH }}</span>
|
|
<autocomplete
|
|
ref="autocomplete"
|
|
:text="newMessage"
|
|
:textbox="textbox"
|
|
:coords="mixinData.autoComplete.coords"
|
|
:caret-position="mixinData.autoComplete.caretPosition"
|
|
:chat="group.chat"
|
|
@select="selectedAutocomplete"
|
|
/>
|
|
<emoji-auto-complete
|
|
ref="emojiAutocomplete"
|
|
:text="newMessage"
|
|
:textbox="textbox"
|
|
:coords="mixinData.autoComplete.coords"
|
|
:caret-position="mixinData.autoComplete.caretPosition"
|
|
@select="selectedAutocomplete"
|
|
/>
|
|
</div>
|
|
<community-guidelines />
|
|
<div class="row chat-actions">
|
|
<div class="col-6 chat-receive-actions">
|
|
<button
|
|
v-once
|
|
class="btn btn-secondary float-left fetch"
|
|
@click="fetchRecentMessages()"
|
|
>
|
|
{{ $t('fetchRecentMessages') }}
|
|
</button>
|
|
<button
|
|
v-once
|
|
class="btn btn-secondary float-left"
|
|
@click="reverseChat()"
|
|
>
|
|
{{ $t('reverseChat') }}
|
|
</button>
|
|
</div>
|
|
<div class="col-6 chat-send-actions">
|
|
<button
|
|
class="btn btn-primary send-chat float-right"
|
|
:disabled="!communityGuidelinesAccepted"
|
|
:class="{ disabled: !communityGuidelinesAccepted }"
|
|
@click="sendMessage()"
|
|
>
|
|
{{ $t('send') }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<slot name="additionRow"></slot>
|
|
<div class="row">
|
|
<div class="hr col-12"></div>
|
|
<chat-messages
|
|
:chat.sync="group.chat"
|
|
:group-type="group.type"
|
|
:group-id="group._id"
|
|
:group-name="group.name"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { MAX_MESSAGE_LENGTH } from '@/../../common/script/constants';
|
|
import externalLinks from '../../mixins/externalLinks';
|
|
|
|
import autocomplete from '../chat/autoComplete';
|
|
import emojiAutoComplete from '../chat/emojiAutoComplete';
|
|
import communityGuidelines from './communityGuidelines';
|
|
import chatMessages from '../chat/chatMessages';
|
|
import { mapState } from '@/libs/store';
|
|
import markdownDirective from '@/directives/markdown';
|
|
import { autoCompleteHelperMixin } from '@/mixins/autoCompleteHelper';
|
|
|
|
export default {
|
|
directives: {
|
|
markdown: markdownDirective,
|
|
},
|
|
components: {
|
|
autocomplete,
|
|
emojiAutoComplete,
|
|
communityGuidelines,
|
|
chatMessages,
|
|
},
|
|
mixins: [externalLinks, autoCompleteHelperMixin],
|
|
props: ['label', 'group', 'placeholder'],
|
|
data () {
|
|
return {
|
|
newMessage: '',
|
|
sending: false,
|
|
chat: {
|
|
submitDisable: false,
|
|
submitTimeout: null,
|
|
},
|
|
textbox: null,
|
|
MAX_MESSAGE_LENGTH: MAX_MESSAGE_LENGTH.toString(),
|
|
};
|
|
},
|
|
computed: {
|
|
...mapState({ user: 'user.data' }),
|
|
currentLength () {
|
|
return this.newMessage.length;
|
|
},
|
|
communityGuidelinesAccepted () {
|
|
return this.user.flags.communityGuidelinesAccepted;
|
|
},
|
|
},
|
|
mounted () {
|
|
this.textbox = this.$refs['user-entry'];
|
|
this.handleExternalLinks();
|
|
},
|
|
updated () {
|
|
this.handleExternalLinks();
|
|
},
|
|
methods: {
|
|
async sendMessageShortcut () {
|
|
// If the user recently pasted in the text field, don't submit
|
|
if (!this.chat.submitDisable) {
|
|
this.sendMessage();
|
|
}
|
|
},
|
|
async sendMessage () {
|
|
if (this.sending) return;
|
|
this.sending = true;
|
|
let response;
|
|
|
|
try {
|
|
response = await this.$store.dispatch('chat:postChat', {
|
|
group: this.group,
|
|
message: this.newMessage,
|
|
});
|
|
} catch (e) {
|
|
// catch exception to allow function to continue
|
|
}
|
|
|
|
if (response) {
|
|
this.group.chat.unshift(response.message);
|
|
this.newMessage = '';
|
|
}
|
|
|
|
this.sending = false;
|
|
|
|
// @TODO: I would like to not reload everytime we send. Why are we reloading?
|
|
// The response has all the necessary data...
|
|
const chat = await this.$store.dispatch('chat:getChat', { groupId: this.group._id });
|
|
this.group.chat = chat;
|
|
},
|
|
|
|
disableMessageSendShortcut () {
|
|
// Some users were experiencing accidental sending of messages after pasting
|
|
// So, after pasting, disable the shortcut for a second.
|
|
this.chat.submitDisable = true;
|
|
|
|
if (this.chat.submitTimeout) {
|
|
// If someone pastes during the disabled period, prevent early re-enable
|
|
clearTimeout(this.chat.submitTimeout);
|
|
this.chat.submitTimeout = null;
|
|
}
|
|
|
|
this.chat.submitTimeout = window.setTimeout(() => {
|
|
this.chat.submitTimeout = null;
|
|
this.chat.submitDisable = false;
|
|
}, 500);
|
|
},
|
|
|
|
selectedAutocomplete (newText, newCaret) {
|
|
this.newMessage = newText;
|
|
// Wait for v-modal to update
|
|
this.$nextTick(() => {
|
|
this.textbox.setSelectionRange(newCaret, newCaret);
|
|
this.textbox.focus();
|
|
});
|
|
},
|
|
fetchRecentMessages () {
|
|
this.$emit('fetchRecentMessages');
|
|
},
|
|
reverseChat () {
|
|
this.group.chat.reverse();
|
|
},
|
|
},
|
|
beforeRouteUpdate (to, from, next) {
|
|
// Reset chat
|
|
this.newMessage = '';
|
|
this.autoCompleteMixinResetCoordsPosition();
|
|
|
|
next();
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
@import '@/assets/scss/colors.scss';
|
|
@import '@/assets/scss/variables.scss';
|
|
|
|
.chat-actions {
|
|
margin-top: 1em;
|
|
|
|
.chat-receive-actions {
|
|
padding-left: 0;
|
|
|
|
button {
|
|
margin-bottom: 1em;
|
|
|
|
&:not(:last-child) {
|
|
margin-right: 1em;
|
|
}
|
|
}
|
|
}
|
|
|
|
.chat-send-actions {
|
|
padding-right: 0;
|
|
}
|
|
}
|
|
|
|
.chat-row {
|
|
position: relative;
|
|
|
|
.label:not(.accepted) {
|
|
color: #a5a1ac;
|
|
}
|
|
|
|
.row {
|
|
margin-left: 0;
|
|
margin-right: 0;
|
|
clear: both;
|
|
}
|
|
|
|
textarea {
|
|
min-height: 150px;
|
|
width: 100%;
|
|
background-color: $white;
|
|
border: solid 1px $gray-400;
|
|
font-style: italic;
|
|
line-height: 1.43;
|
|
color: $gray-300;
|
|
padding: 10px 12px;
|
|
}
|
|
|
|
.user-entry {
|
|
font-style: normal;
|
|
color: $black;
|
|
}
|
|
|
|
.hr {
|
|
width: 100%;
|
|
height: 20px;
|
|
border-bottom: 1px solid $gray-500;
|
|
text-align: center;
|
|
margin: 2em 0;
|
|
}
|
|
|
|
.hr-middle {
|
|
font-size: 16px;
|
|
font-weight: bold;
|
|
font-family: 'Roboto Condensed';
|
|
line-height: 1.5;
|
|
text-align: center;
|
|
color: $gray-200;
|
|
background-color: $gray-700;
|
|
padding: .2em;
|
|
margin-top: .2em;
|
|
display: inline-block;
|
|
width: 100px;
|
|
}
|
|
}
|
|
|
|
</style>
|