emoji picker + textarea footer for 'ask a question'

This commit is contained in:
mst 2025-02-28 07:25:38 +03:00
parent cadce98fc2
commit f0e302b58a
No known key found for this signature in database
2 changed files with 152 additions and 26 deletions

View file

@ -24,6 +24,133 @@
{% endblock %} {% endblock %}
{% block scripts %} {% block scripts %}
<script src="{{ url_for('static', filename='js/toastify.min.js') }}"></script> <script src="{{ url_for('static', filename='js/toastify.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/emoji-mart.js') }}"></script>
<script>
{% if not cfg.lockInbox %}
const input = document.getElementById('question');
const charCount = document.getElementById('charCount');
function updateCharCount() {
const maxLength = input.getAttribute('maxlength');
const currentLength = input.value.length;
const remaining = maxLength - currentLength;
charCount.textContent = remaining;
if (remaining <= 50) {
charCount.classList.add('text-warning');
} else {
charCount.classList.remove('text-warning');
}
if (remaining <= 10) {
charCount.classList.add('text-danger');
charCount.classList.remove('text-warning');
} else {
charCount.classList.remove('text-danger');
}
}
input.addEventListener('input', updateCharCount);
document.getElementById('question-form').reset();
{% endif %}
document.addEventListener("DOMContentLoaded", (event) => {
const emoji_picker = document.querySelector('em-emoji-picker');
const root_ = emoji_picker.shadowRoot;
const sheet = new CSSStyleSheet();
sheet.replaceSync(`
/* custom css start */
:host {
--font-family: var(--bs-font-sans-serif) !important;
--border-radius: var(--bs-border-radius) !important;
box-shadow: none !important;
}
#nav button[aria-selected] {
color: var(--bs-primary) !important;
}
#nav .bar {
background-color: var(--bs-primary) !important;
}
.search .icon {
color: var(--bs-tertiary-color) !important;
}
.category button .background {
background-color: var(--bs-basic-btn-hover-bg-strong);
}
:host, #root, input, button {
color: var(--bs-body-color);
}
#root {
--color-a: var(--bs-body-color) !important;
--color-b: var(--bs-secondary-color) !important;
--color-c: var(--bs-tertiary-color) !important;
}
#preview .emoji-mart-emoji {
font-size: 16px;
}
[data-theme="dark"] {
--em-rgb-background: !important;
}
.search input[type="search"] {
border: 1px solid transparent !important;
background-color: var(--bs-body-bg) !important;
}
.search input[type="search"]:focus {
box-shadow: 0 0 0 .25rem color-mix(in srgb, var(--bs-primary) 25%, transparent) !important;
border-color: color-mix(in srgb, var(--bs-primary) 80%, transparent) !important;
outline: 0;
}
.category:first-child {
margin-top: 1em;
}
/* custom css end */
`);
emoji_picker.shadowRoot.adoptedStyleSheets = [...root_.adoptedStyleSheets, sheet];
});
const question_textarea = document.getElementById('question');
function log_(a) {
if (question_textarea.value != "") {
question_textarea.value = a.native ? question_textarea.value + " " + a.native : question_textarea.value + " " + a.shortcodes;
} else {
question_textarea.value = a.native ? a.native : a.shortcodes;
}
updateCharCount();
}
const pickerOptions = {
// document.getElementById('emoji-picker')
onEmojiSelect: log_,
parent: document.getElementById('emoji-picker'),
custom: [
{
emojis: [
{% for emoji in emojis %}
{
id: "{{ emoji.name }}",
name: "{{ emoji.name }}",
keywords: ["{{ emoji.name }}"],
skins: [{ src: "{{ emoji.image }}" }],
},
{% endfor %}
],
},
{% for pack in packs %}
{
id: "{{ pack.name }}",
name: "{{ pack.name }}",
emojis: [
{% for emoji in pack.emojis %}
{
id: "{{ emoji.name }}",
name: "{{ emoji.name }}",
keywords: ["{{ emoji.name }}"],
skins: [{ src: "/{{ pack.relative_path }}/{{ emoji.file_name }}" }],
},
{% endfor %}
],
},
{% endfor %}
]
}
const picker = new EmojiMart.Picker(pickerOptions)
</script>
<script> <script>
// fix handling checkboxes // fix handling checkboxes
document.querySelectorAll('.form-check-input').forEach(function(checkbox) { document.querySelectorAll('.form-check-input').forEach(function(checkbox) {
@ -132,30 +259,6 @@
}).showToast(); }).showToast();
}; };
{% if not cfg.lockInbox %}
const input = document.getElementById('question');
const charCount = document.getElementById('charCount');
function updateCharCount() {
const maxLength = input.getAttribute('maxlength');
const currentLength = input.value.length;
const remaining = maxLength - currentLength;
charCount.textContent = remaining;
if (remaining <= 50) {
charCount.classList.add('text-warning');
} else {
charCount.classList.remove('text-warning');
}
if (remaining <= 10) {
charCount.classList.add('text-danger');
charCount.classList.remove('text-warning');
} else {
charCount.classList.remove('text-danger');
}
}
input.addEventListener('input', updateCharCount);
document.getElementById('question-form').reset();
{% endif %}
function shareOnFediverse(questionId, contentToShare) { function shareOnFediverse(questionId, contentToShare) {
const instanceDomain = document.getElementById(`fediInstance`).value.trim(); const instanceDomain = document.getElementById(`fediInstance`).value.trim();
const shareUrl = `https://${instanceDomain}/share?text=${contentToShare}`; const shareUrl = `https://${instanceDomain}/share?text=${contentToShare}`;
@ -163,8 +266,11 @@
window.open(shareUrl, '_blank'); window.open(shareUrl, '_blank');
} }
function initTooltips() {
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]'); const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl)); const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl));
}
initTooltips();
document.addEventListener('htmx:afterRequest', function(event) { document.addEventListener('htmx:afterRequest', function(event) {
const jsonResponse = event.detail.xhr.response; const jsonResponse = event.detail.xhr.response;

View file

@ -0,0 +1,20 @@
<div class="rounded-bottom border border-top-0 p-2 d-flex align-items-center justify-content-between" style="background-color: var(--bs-body-bg);">
<div class="d-flex align-items-center gap-2">
<button class="ms-1 btn btn-secondary" type="button" title="{{ _('Content warning') }}" data-bs-toggle="collapse" data-bs-target="{% if customCwTarget %}{{ customCwTarget}}{% else %}#cw-collapse{% endif %}" aria-expanded="false" aria-controls="cw-collapse">
<i class="bi bi-exclamation-triangle"></i>
</button>
{% if not noEmojiPicker %}
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle no-arrow" type="button" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false" title="{{ _('Add emoji') }}">
<i class="bi bi-emoji-smile"></i>
</button>
<div class="dropdown-menu p-0">
<div id="{% if customEmojiPickerId %}{{ customEmojiPickerId }}{% else %}emoji-picker{% endif %}" class="emoji-picker"></div>
</div>
</div>
{% endif %}
</div>
{% if includeCharLimit %}
<span id="charCount" class="small" title="{{ _('Character limit') }}">{{ cfg.charLimit }}</span>
{% endif %}
</div>