mirror of https://github.com/mashirozx/sakura.git
457 lines
14 KiB
Vue
457 lines
14 KiB
Vue
<template>
|
|
<div class="composer__container">
|
|
<div class="row__wrapper--textarea">
|
|
<img
|
|
class="background"
|
|
src="https://view.moezx.cc/images/2018/03/24/comment-bg.png"
|
|
:data-show="inputContent.trim().length === 0"
|
|
/>
|
|
<OutlinedTextarea
|
|
v-model:content="inputContent"
|
|
:label="messages.textareaLabel"
|
|
:enableResizer="true"
|
|
:enableCounter="true"
|
|
:maxlength="99999"
|
|
></OutlinedTextarea>
|
|
<div class="toolkits__wrapper">
|
|
<div class="toolkits__container">
|
|
<span class="markdown__tip" ref="toolkitMarkdownRef">
|
|
<i class="fab fa-markdown"></i>
|
|
</span>
|
|
<span class="emoji__tool" ref="toolkitEmojiRef">
|
|
<i class="far fa-laugh-squint"></i>
|
|
</span>
|
|
<span class="image__tool" ref="toolkitImageRef">
|
|
<i class="far fa-image"></i>
|
|
</span>
|
|
<span class="preview__tool" ref="toolkitPreviewRef">
|
|
<i class="fas fa-glasses"></i>
|
|
</span>
|
|
<span
|
|
class="privacy__tool"
|
|
ref="toolkitPrivacyRef"
|
|
@click="handleTogglePrivacyOptionsEvent"
|
|
>
|
|
<i class="fas fa-user-shield"></i>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row__wrapper--privacy">
|
|
<Toggler :show="shouldShowPrivacyOptions">
|
|
<div class="options__wrapper">
|
|
<div class="option visibility">
|
|
<span>
|
|
<i class="fas fa-lock"></i>
|
|
{{ messages.privacy.visibility.title }}
|
|
</span>
|
|
<Switcher
|
|
v-model:checked="privacyIsPrivate"
|
|
positiveLabel=""
|
|
negativeLabel=""
|
|
></Switcher>
|
|
</div>
|
|
<!-- <i class="fas fa-unlock"></i> -->
|
|
<!-- <i class="fas fa-globe"></i> -->
|
|
<div class="option anynomous">
|
|
<span>
|
|
<i class="fas fa-user-secret"></i>
|
|
{{ messages.privacy.anynomous.title }}
|
|
</span>
|
|
<Switcher
|
|
v-model:checked="privacyIsAnynomous"
|
|
positiveLabel=""
|
|
negativeLabel=""
|
|
></Switcher>
|
|
</div>
|
|
<!-- <i class="fas fa-theater-masks"></i> -->
|
|
<div class="option inform">
|
|
<span>
|
|
<i class="fas fa-envelope"></i>
|
|
{{ messages.privacy.email.title }}
|
|
</span>
|
|
<Switcher
|
|
v-model:checked="privacyShouldInform"
|
|
positiveLabel=""
|
|
negativeLabel=""
|
|
></Switcher>
|
|
</div>
|
|
</div>
|
|
</Toggler>
|
|
</div>
|
|
<div class="row__wrapper--profile">
|
|
<div class="flex-box">
|
|
<div class="column__wrapper--avatar">
|
|
<div class="avatar__wrapper mdc-elevation--z1">
|
|
<Image :src="avatar" placeholder="" :avatar="false" alt="" :draggable="false"></Image>
|
|
</div>
|
|
<div class="icon__wrapper avatar__wrapper mdc-elevation--z2">
|
|
<span class="gravatar">
|
|
<!-- <i class="fab fa-qq"></i> -->
|
|
<i class="fab fa-google"></i>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="column__wrapper--input username">
|
|
<OutlinedInput
|
|
v-model:content="inputAuthorName"
|
|
leadingIcon="fas fa-user"
|
|
:label="messages.nickname"
|
|
></OutlinedInput>
|
|
</div>
|
|
<div class="column__wrapper--input">
|
|
<OutlinedInput
|
|
v-model:content="inputAuthorEmail"
|
|
leadingIcon="fas fa-envelope"
|
|
:label="messages.email"
|
|
@blur="handleEmailInputBlurEvent"
|
|
></OutlinedInput>
|
|
</div>
|
|
<div class="column__wrapper--input">
|
|
<OutlinedInput
|
|
v-model:content="inputAuthorUrl"
|
|
leadingIcon="fas fa-home"
|
|
:label="messages.link"
|
|
></OutlinedInput>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- <div class="captcha-button">
|
|
<Captcha></Captcha>
|
|
</div> -->
|
|
<div class="row__wrapper--buttons">
|
|
<NormalButton
|
|
:context="messages.submit"
|
|
:outlined="true"
|
|
@click="handleSubmitEvent"
|
|
></NormalButton>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { defineComponent, ref } from 'vue'
|
|
import { useTippy } from 'vue-tippy'
|
|
import { useIntl, useState } from '@/hooks'
|
|
import gravatar, { WP_DEFAULT_USER_EMAIL } from '@/utils/gravatar'
|
|
import Captcha from './Captcha.vue'
|
|
import OutlinedInput from '@/components/inputs/OutlinedInput.vue'
|
|
import OutlinedTextarea from '@/components/inputs/OutlinedTextarea.vue'
|
|
import NormalButton from '@/components/buttons/NormalButton.vue'
|
|
import Toggler from '@/components/toggler/Toggler.vue'
|
|
import Switcher from '@/components/switcher/Switcher.vue'
|
|
|
|
export default defineComponent({
|
|
components: { Captcha, OutlinedInput, OutlinedTextarea, NormalButton, Toggler, Switcher },
|
|
emits: ['submit'],
|
|
setup(props, { emit }) {
|
|
const intl = useIntl()
|
|
const messages = {
|
|
markdownTips: intl.formatMessage({
|
|
id: 'posts.comment.composer.tips.markdownSupported',
|
|
defaultMessage: 'Markdown Supported',
|
|
}),
|
|
textareaLabel: intl.formatMessage({
|
|
id: 'posts.comment.composer.content.label',
|
|
defaultMessage: 'You are a surprise that I will only meet once in my life',
|
|
}),
|
|
nickname: intl.formatMessage({
|
|
id: 'posts.comment.composer.authorName.label',
|
|
defaultMessage: 'Nickname *',
|
|
}),
|
|
email: intl.formatMessage({
|
|
id: 'posts.comment.composer.authorEmail.label',
|
|
defaultMessage: 'Email *',
|
|
}),
|
|
link: intl.formatMessage({
|
|
id: 'posts.comment.composer.authorUrl.label',
|
|
defaultMessage: 'Link',
|
|
}),
|
|
submit: intl.formatMessage({
|
|
id: 'posts.comment.composer.submit.button',
|
|
defaultMessage: 'Submit',
|
|
}),
|
|
toolkits: {
|
|
previewTooltip: intl.formatMessage({
|
|
id: 'posts.comment.composer.toolkits.preview.tooltip',
|
|
defaultMessage: '\'<i class="fab fa-markdown"></i>\' Markdown preview',
|
|
}),
|
|
emojiTooltip: intl.formatMessage({
|
|
id: 'posts.comment.composer.toolkits.emoji.tooltip',
|
|
defaultMessage: 'Insert emoji',
|
|
}),
|
|
imageTooltip: intl.formatMessage({
|
|
id: 'posts.comment.composer.toolkits.image.tooltip',
|
|
defaultMessage: 'Attach image',
|
|
}),
|
|
privacyTooltip: intl.formatMessage({
|
|
id: 'posts.comment.composer.toolkits.privacy.tooltip',
|
|
defaultMessage: 'Privacy settings',
|
|
}),
|
|
markdownTooltip: intl.formatMessage({
|
|
id: 'posts.comment.composer.toolkits.preview.tooltip',
|
|
defaultMessage:
|
|
'\'<a href="https://guides.github.com/features/mastering-markdown/" target="_blank">Markdown</a>\' supported',
|
|
}),
|
|
},
|
|
privacy: {
|
|
anynomous: {
|
|
title: intl.formatMessage({
|
|
id: 'posts.comment.composer.privacy.anynomous.title',
|
|
defaultMessage: 'Comment as anynomous user',
|
|
}),
|
|
},
|
|
visibility: {
|
|
title: intl.formatMessage({
|
|
id: 'posts.comment.composer.privacy.visibility.title',
|
|
defaultMessage: 'Secret comment (only admins and peoples mentioned can see)',
|
|
}),
|
|
},
|
|
email: {
|
|
title: intl.formatMessage({
|
|
id: 'posts.comment.composer.privacy.email.title',
|
|
defaultMessage: 'Inform me with email when receive reply',
|
|
}),
|
|
},
|
|
},
|
|
}
|
|
|
|
const inputContent = ref('')
|
|
const inputAuthorName = ref('')
|
|
const inputAuthorEmail = ref('')
|
|
const inputAuthorUrl = ref('')
|
|
|
|
const privacyIsPrivate = ref(false)
|
|
const privacyIsAnynomous = ref(false)
|
|
const privacyShouldInform = ref(true)
|
|
|
|
// TODO: debounce
|
|
const handleSubmitEvent = () => {
|
|
emit('submit', {
|
|
content: inputContent.value,
|
|
authorName: inputAuthorName.value,
|
|
authorEmail: inputAuthorEmail.value,
|
|
authorUrl: inputAuthorUrl.value,
|
|
})
|
|
}
|
|
|
|
const [avatar, setAvatar] = useState(gravatar(WP_DEFAULT_USER_EMAIL))
|
|
|
|
const handleEmailInputBlurEvent = () =>
|
|
setAvatar(gravatar(inputAuthorEmail.value || WP_DEFAULT_USER_EMAIL))
|
|
|
|
const clearInputContent = () => (inputContent.value = '')
|
|
|
|
const toolkitEmojiRef = ref()
|
|
const toolkitPreviewRef = ref()
|
|
const toolkitImageRef = ref()
|
|
const toolkitPrivacyRef = ref()
|
|
const toolkitMarkdownRef = ref()
|
|
const commonTippyOpts = {
|
|
animation: 'scale',
|
|
theme: 'material',
|
|
}
|
|
const { tippy: tippyToolkitEmoji } = useTippy(toolkitEmojiRef, {
|
|
content: messages.toolkits.emojiTooltip,
|
|
...commonTippyOpts,
|
|
})
|
|
const { tippy: tippyToolkitPreview } = useTippy(toolkitPreviewRef, {
|
|
content: messages.toolkits.previewTooltip,
|
|
allowHTML: true,
|
|
...commonTippyOpts,
|
|
})
|
|
const { tippy: tippyToolkitImage } = useTippy(toolkitImageRef, {
|
|
content: messages.toolkits.imageTooltip,
|
|
...commonTippyOpts,
|
|
})
|
|
const { tippy: tippyToolkitPrivacy } = useTippy(toolkitPrivacyRef, {
|
|
content: messages.toolkits.privacyTooltip,
|
|
...commonTippyOpts,
|
|
})
|
|
const { tippy: tippyToolkitMarkdown } = useTippy(toolkitMarkdownRef, {
|
|
content: messages.toolkits.markdownTooltip,
|
|
allowHTML: true,
|
|
interactive: true,
|
|
...commonTippyOpts,
|
|
})
|
|
|
|
const [shouldShowPrivacyOptions, setShouldShowPrivacyOptions] = useState(false)
|
|
|
|
const handleTogglePrivacyOptionsEvent = () =>
|
|
setShouldShowPrivacyOptions(!shouldShowPrivacyOptions.value)
|
|
|
|
return {
|
|
messages,
|
|
inputContent,
|
|
inputAuthorName,
|
|
inputAuthorEmail,
|
|
inputAuthorUrl,
|
|
avatar,
|
|
handleSubmitEvent,
|
|
handleEmailInputBlurEvent,
|
|
clearInputContent,
|
|
toolkitEmojiRef,
|
|
toolkitPreviewRef,
|
|
toolkitImageRef,
|
|
toolkitPrivacyRef,
|
|
toolkitMarkdownRef,
|
|
shouldShowPrivacyOptions,
|
|
handleTogglePrivacyOptionsEvent,
|
|
privacyIsPrivate,
|
|
privacyIsAnynomous,
|
|
privacyShouldInform,
|
|
}
|
|
},
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
@use '@/styles/mixins/polyfills';
|
|
.composer__container {
|
|
--mdc-theme-primary: orange;
|
|
width: 100%;
|
|
> * {
|
|
width: 100%;
|
|
padding-top: 12px;
|
|
&:first-child {
|
|
padding-top: 0;
|
|
}
|
|
}
|
|
> .row__wrapper {
|
|
&--textarea {
|
|
position: relative;
|
|
width: 100%;
|
|
.background {
|
|
position: absolute;
|
|
bottom: 32px;
|
|
right: 0;
|
|
z-index: -1;
|
|
max-height: 200px;
|
|
max-width: 100%;
|
|
opacity: 0;
|
|
transition: opacity 0.5s;
|
|
&[data-show='true'] {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
.toolkits__wrapper {
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 36px;
|
|
display: flex;
|
|
justify-content: flex-start;
|
|
align-items: center;
|
|
.toolkits__container {
|
|
padding-left: 12px;
|
|
display: flex;
|
|
flex-flow: row nowrap;
|
|
justify-content: flex-end;
|
|
align-items: center;
|
|
@include polyfills.flex-gap(12px, 'row nowrap');
|
|
> * {
|
|
width: 20px;
|
|
height: 20px;
|
|
}
|
|
span {
|
|
line-height: 24px;
|
|
font-size: medium;
|
|
color: #404040;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
&--privacy {
|
|
width: 100%;
|
|
.options__wrapper {
|
|
.option {
|
|
display: flex;
|
|
flex-flow: row nowrap;
|
|
justify-content: flex-start;
|
|
align-items: center;
|
|
@include polyfills.flex-gap(12px, 'row nowrap');
|
|
}
|
|
}
|
|
}
|
|
&--profile {
|
|
> .flex-box {
|
|
position: relative;
|
|
display: flex;
|
|
flex-flow: row nowrap;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
@include polyfills.flex-gap(12px, 'row nowrap');
|
|
@media screen and (max-width: 800px) {
|
|
flex-flow: column nowrap;
|
|
@include polyfills.flex-gap-unset('row nowrap');
|
|
@include polyfills.flex-gap(12px, 'column nowrap');
|
|
}
|
|
.column__wrapper {
|
|
&--avatar {
|
|
flex: 0 0 auto;
|
|
position: relative;
|
|
@media screen and (max-width: 800px) {
|
|
position: absolute;
|
|
top: 0;
|
|
right: 0;
|
|
transform: scale(0.8);
|
|
}
|
|
> .avatar__wrapper {
|
|
width: 56px;
|
|
height: 56px;
|
|
border-radius: 50%;
|
|
overflow: hidden;
|
|
}
|
|
> .icon__wrapper {
|
|
position: absolute;
|
|
right: 0;
|
|
bottom: 0;
|
|
width: 20px;
|
|
height: 20px;
|
|
background: #03a9f4;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
span {
|
|
width: 12px;
|
|
height: 12px;
|
|
color: #fff;
|
|
line-height: 12px;
|
|
font-size: small;
|
|
&.gravatar {
|
|
transform: rotate(270deg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
&--input {
|
|
flex: 1 1 auto;
|
|
width: 100%;
|
|
@media screen and (max-width: 800px) {
|
|
&.username {
|
|
::v-deep() {
|
|
.mdc-text-field__input {
|
|
width: calc(100% - 80px);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
&--buttons {
|
|
::v-deep(.mdc-button) {
|
|
width: 100%;
|
|
height: 50px;
|
|
}
|
|
::v-deep(.mdc-button--outlined:not(:disabled):hover) {
|
|
border-color: var(--mdc-theme-primary, rgba(0, 0, 0, 0.12));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|