mirror of
https://codeberg.org/catask-org/catask.git
synced 2025-04-19 13:23:41 -05:00
312 lines
10 KiB
HTML
312 lines
10 KiB
HTML
{% extends 'base.html' %}
|
|
{% block title %}{{ _('Home') }}{% endblock %}
|
|
{% set homeLink = 'active' %}
|
|
{% block additionalHeadItems %}
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/toastify.css') }}">
|
|
{% if cfg.antispam.enabled %}
|
|
{% if cfg.antispam.type == 'recaptcha' %}
|
|
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
|
|
{% elif cfg.antispam.type == 'turnstile' %}
|
|
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" defer></script>
|
|
{% elif cfg.antispam.type == 'frc' %}
|
|
<script type="module" src="https://cdn.jsdelivr.net/npm/@friendlycaptcha/sdk@0.1.9/site.min.js" async defer></script>
|
|
<script nomodule src="https://cdn.jsdelivr.net/npm/@friendlycaptcha/sdk@0.1.9/site.compat.min.js" async defer></script>
|
|
{% endif %}
|
|
{% endif %}
|
|
{% endblock %}
|
|
{% block content %}
|
|
<div id="top-response-container"></div>
|
|
{% if cfg.style.homepageLayout == 'catask' %}
|
|
{% include 'snippets/layout/homepage/normal.html' %}
|
|
{% elif cfg.style.homepageLayout == 'retrospring' %}
|
|
{% include 'snippets/layout/homepage/retrospring.html' %}
|
|
{% endif %}
|
|
{% endblock %}
|
|
{% block scripts %}
|
|
<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>
|
|
// fix handling checkboxes
|
|
document.querySelectorAll('.form-check-input').forEach(function(checkbox) {
|
|
checkbox.addEventListener('change', function() {
|
|
checkbox.nextElementSibling.value = this.checked ? '1' : '0';
|
|
});
|
|
});
|
|
</script>
|
|
<script>
|
|
function nativeShare(title, text, url) {
|
|
const shareData = {
|
|
title: title,
|
|
text: text,
|
|
url: url,
|
|
};
|
|
|
|
const shareBtns = document.querySelectorAll(".nativeShareBtn");
|
|
shareBtns.forEach((shareBtn) => {
|
|
shareBtn.addEventListener("click", async () => {
|
|
try {
|
|
if (navigator.canShare(shareData)) {
|
|
await navigator.share(shareData);
|
|
}
|
|
}
|
|
catch (err) {
|
|
console.error(err);
|
|
}
|
|
});
|
|
});
|
|
};
|
|
</script>
|
|
<script>
|
|
const questionModal = document.getElementById('question-modal');
|
|
questionModal.addEventListener('show.bs.modal', event => {
|
|
// Button that triggered the modal
|
|
let button = event.relatedTarget;
|
|
// Extract info from data-bs-* attributes
|
|
let questionId = button.getAttribute('data-q-id');
|
|
let questionContent = document.querySelector(`.question-${questionId}`).innerText;
|
|
let answerContent = document.getElementById(`a-${questionId}-content`).innerText;
|
|
let submitBtn = document.getElementById('q-modal-submit');
|
|
|
|
// Define the cfg variables
|
|
const trimContentAfter = "{{ cfg.trimContentAfter }}";
|
|
const instanceFullBaseUrl = "{{ cfg.instance.fullBaseUrl }}";
|
|
|
|
let questionText = questionContent.length > trimContentAfter ? questionContent.substring(0, trimContentAfter) + '…' : questionContent;
|
|
let answerText = answerContent.length > trimContentAfter ? answerContent.substring(0, trimContentAfter) + '…' : answerContent;
|
|
let questionUrl = `${instanceFullBaseUrl}/q/${questionId}/`;
|
|
|
|
let encodedContent = encodeURI(`${questionText} — ${answerText} ${questionUrl}`);
|
|
// Set up the shareOnFediverse function
|
|
submitBtn.addEventListener('click', function() {
|
|
shareOnFediverse(questionId, encodedContent);
|
|
});
|
|
});
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
const collapseElements = document.querySelectorAll('.collapse.question-cw');
|
|
const toggleButtons = document.querySelectorAll('.cw-btn');
|
|
const cwTexts = document.querySelectorAll('.cw-text');
|
|
|
|
collapseElements.forEach(function (collapseElement, index) {
|
|
let toggleButton = toggleButtons[index];
|
|
let cwText = cwTexts[index];
|
|
let buttonText = toggleButton.querySelector('.cw-btn-text');
|
|
let buttonCharsText = toggleButton.querySelector('.cw-btn-chars');
|
|
|
|
collapseElement.addEventListener('show.bs.collapse', function () {
|
|
buttonText.textContent = "{{ _('Hide content') }}";
|
|
buttonCharsText.classList.add('d-none');
|
|
cwText.classList.remove('text-center');
|
|
cwText.classList.remove('fw-bold');
|
|
});
|
|
|
|
collapseElement.addEventListener('hide.bs.collapse', function () {
|
|
buttonText.textContent = "{{ _('Show content') }}";
|
|
buttonCharsText.classList.remove('d-none');
|
|
cwText.classList.add('text-center');
|
|
cwText.classList.add('fw-bold');
|
|
});
|
|
});
|
|
});
|
|
|
|
function copy(questionId) {
|
|
navigator.clipboard.writeText("{{ cfg.instance.fullBaseUrl }}/q/" + questionId + "/");
|
|
Toastify({
|
|
text: "Successfully copied link to clipboard!",
|
|
duration: 3000,
|
|
gravity: "top",
|
|
position: "right",
|
|
stopOnFocus: true,
|
|
className: `alert alert-success shadow alert-dismissible`,
|
|
close: true
|
|
}).showToast();
|
|
};
|
|
function copyFull(text) {
|
|
navigator.clipboard.writeText(text);
|
|
Toastify({
|
|
text: "Successfully copied text to clipboard!",
|
|
duration: 3000,
|
|
gravity: "top",
|
|
position: "right",
|
|
stopOnFocus: true,
|
|
className: `alert alert-success shadow alert-dismissible`,
|
|
close: true
|
|
}).showToast();
|
|
};
|
|
|
|
function shareOnFediverse(questionId, contentToShare) {
|
|
const instanceDomain = document.getElementById(`fediInstance`).value.trim();
|
|
const shareUrl = `https://${instanceDomain}/share?text=${contentToShare}`;
|
|
|
|
window.open(shareUrl, '_blank');
|
|
}
|
|
|
|
function initTooltips() {
|
|
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
|
|
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl));
|
|
}
|
|
initTooltips();
|
|
|
|
document.addEventListener('htmx:afterRequest', function(event) {
|
|
const jsonResponse = event.detail.xhr.response;
|
|
if (jsonResponse) {
|
|
const parsed = JSON.parse(jsonResponse);
|
|
const alertType = event.detail.successful ? 'success' : 'danger';
|
|
msgType = event.detail.successful ? parsed.message : parsed.error;
|
|
let targetElementId = event.detail.target.id;
|
|
if (targetElementId != "question-count") {
|
|
// WARNING: HACK
|
|
// we use this hack to avoid triggering the event listener twice when making a request to api.returnToInbox and api.(un)pinQuestion
|
|
if (
|
|
(document.getElementById(targetElementId) && event.detail.requestConfig.elt.dataset.deletetarget === "")
|
|
||
|
|
document.getElementById(targetElementId) && event.detail.requestConfig.elt.dataset.deletetarget === ""
|
|
) {
|
|
targetElementId = event.detail.requestConfig.elt.dataset.target;
|
|
document.getElementById(targetElementId).outerHTML = '';
|
|
}
|
|
if (msgType) {
|
|
Toastify({
|
|
text: msgType,
|
|
duration: 3000,
|
|
gravity: "top",
|
|
position: "right",
|
|
stopOnFocus: true,
|
|
className: `alert alert-${alertType} shadow alert-dismissible`,
|
|
close: true
|
|
}).showToast();
|
|
}
|
|
if (event.detail.requestConfig.elt.id == 'question-form') {
|
|
document.getElementById('question-form').reset();
|
|
document.getElementById('charCount').textContent = "{{ cfg.charLimit }}";
|
|
}
|
|
}
|
|
}
|
|
});
|
|
</script>
|
|
{% endblock %}
|