From 44a7d87cb1f5df953b6c14c16c59e2e4ead1bcb9 Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Mon, 20 Feb 2023 03:20:59 +0100 Subject: Rename JSX files with proper `.jsx` extension (#23733) --- app/javascript/packs/admin.js | 245 ----------------------------- app/javascript/packs/admin.jsx | 245 +++++++++++++++++++++++++++++ app/javascript/packs/public.js | 332 ---------------------------------------- app/javascript/packs/public.jsx | 332 ++++++++++++++++++++++++++++++++++++++++ app/javascript/packs/share.js | 26 ---- app/javascript/packs/share.jsx | 26 ++++ 6 files changed, 603 insertions(+), 603 deletions(-) delete mode 100644 app/javascript/packs/admin.js create mode 100644 app/javascript/packs/admin.jsx delete mode 100644 app/javascript/packs/public.js create mode 100644 app/javascript/packs/public.jsx delete mode 100644 app/javascript/packs/share.js create mode 100644 app/javascript/packs/share.jsx (limited to 'app/javascript/packs') diff --git a/app/javascript/packs/admin.js b/app/javascript/packs/admin.js deleted file mode 100644 index 038e9b434..000000000 --- a/app/javascript/packs/admin.js +++ /dev/null @@ -1,245 +0,0 @@ -import './public-path'; -import { delegate } from '@rails/ujs'; -import ready from '../mastodon/ready'; - -const setAnnouncementEndsAttributes = (target) => { - const valid = target?.value && target?.validity?.valid; - const element = document.querySelector('input[type="datetime-local"]#announcement_ends_at'); - if (valid) { - element.classList.remove('optional'); - element.required = true; - element.min = target.value; - } else { - element.classList.add('optional'); - element.removeAttribute('required'); - element.removeAttribute('min'); - } -}; - -delegate(document, 'input[type="datetime-local"]#announcement_starts_at', 'change', ({ target }) => { - setAnnouncementEndsAttributes(target); -}); - -const batchCheckboxClassName = '.batch-checkbox input[type="checkbox"]'; - -const showSelectAll = () => { - const selectAllMatchingElement = document.querySelector('.batch-table__select-all'); - selectAllMatchingElement.classList.add('active'); -}; - -const hideSelectAll = () => { - const selectAllMatchingElement = document.querySelector('.batch-table__select-all'); - const hiddenField = document.querySelector('#select_all_matching'); - const selectedMsg = document.querySelector('.batch-table__select-all .selected'); - const notSelectedMsg = document.querySelector('.batch-table__select-all .not-selected'); - - selectAllMatchingElement.classList.remove('active'); - selectedMsg.classList.remove('active'); - notSelectedMsg.classList.add('active'); - hiddenField.value = '0'; -}; - -delegate(document, '#batch_checkbox_all', 'change', ({ target }) => { - const selectAllMatchingElement = document.querySelector('.batch-table__select-all'); - - [].forEach.call(document.querySelectorAll(batchCheckboxClassName), (content) => { - content.checked = target.checked; - }); - - if (selectAllMatchingElement) { - if (target.checked) { - showSelectAll(); - } else { - hideSelectAll(); - } - } -}); - -delegate(document, '.batch-table__select-all button', 'click', () => { - const hiddenField = document.querySelector('#select_all_matching'); - const active = hiddenField.value === '1'; - const selectedMsg = document.querySelector('.batch-table__select-all .selected'); - const notSelectedMsg = document.querySelector('.batch-table__select-all .not-selected'); - - if (active) { - hiddenField.value = '0'; - selectedMsg.classList.remove('active'); - notSelectedMsg.classList.add('active'); - } else { - hiddenField.value = '1'; - notSelectedMsg.classList.remove('active'); - selectedMsg.classList.add('active'); - } -}); - -delegate(document, batchCheckboxClassName, 'change', () => { - const checkAllElement = document.querySelector('#batch_checkbox_all'); - const selectAllMatchingElement = document.querySelector('.batch-table__select-all'); - - if (checkAllElement) { - checkAllElement.checked = [].every.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked); - checkAllElement.indeterminate = !checkAllElement.checked && [].some.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked); - - if (selectAllMatchingElement) { - if (checkAllElement.checked) { - showSelectAll(); - } else { - hideSelectAll(); - } - } - } -}); - -delegate(document, '.media-spoiler-show-button', 'click', () => { - [].forEach.call(document.querySelectorAll('button.media-spoiler'), (element) => { - element.click(); - }); -}); - -delegate(document, '.media-spoiler-hide-button', 'click', () => { - [].forEach.call(document.querySelectorAll('.spoiler-button.spoiler-button--visible button'), (element) => { - element.click(); - }); -}); - -delegate(document, '.filter-subset--with-select select', 'change', ({ target }) => { - target.form.submit(); -}); - -const onDomainBlockSeverityChange = (target) => { - const rejectMediaDiv = document.querySelector('.input.with_label.domain_block_reject_media'); - const rejectReportsDiv = document.querySelector('.input.with_label.domain_block_reject_reports'); - - if (rejectMediaDiv) { - rejectMediaDiv.style.display = (target.value === 'suspend') ? 'none' : 'block'; - } - - if (rejectReportsDiv) { - rejectReportsDiv.style.display = (target.value === 'suspend') ? 'none' : 'block'; - } -}; - -delegate(document, '#domain_block_severity', 'change', ({ target }) => onDomainBlockSeverityChange(target)); - -const onEnableBootstrapTimelineAccountsChange = (target) => { - const bootstrapTimelineAccountsField = document.querySelector('#form_admin_settings_bootstrap_timeline_accounts'); - - if (bootstrapTimelineAccountsField) { - bootstrapTimelineAccountsField.disabled = !target.checked; - if (target.checked) { - bootstrapTimelineAccountsField.parentElement.classList.remove('disabled'); - bootstrapTimelineAccountsField.parentElement.parentElement.classList.remove('disabled'); - } else { - bootstrapTimelineAccountsField.parentElement.classList.add('disabled'); - bootstrapTimelineAccountsField.parentElement.parentElement.classList.add('disabled'); - } - } -}; - -delegate(document, '#form_admin_settings_enable_bootstrap_timeline_accounts', 'change', ({ target }) => onEnableBootstrapTimelineAccountsChange(target)); - -const onChangeRegistrationMode = (target) => { - const enabled = target.value === 'approved'; - - [].forEach.call(document.querySelectorAll('#form_admin_settings_require_invite_text'), (input) => { - input.disabled = !enabled; - if (enabled) { - let element = input; - do { - element.classList.remove('disabled'); - element = element.parentElement; - } while (element && !element.classList.contains('fields-group')); - } else { - let element = input; - do { - element.classList.add('disabled'); - element = element.parentElement; - } while (element && !element.classList.contains('fields-group')); - } - }); -}; - -const convertUTCDateTimeToLocal = (value) => { - const date = new Date(value + 'Z'); - const twoChars = (x) => (x.toString().padStart(2, '0')); - return `${date.getFullYear()}-${twoChars(date.getMonth()+1)}-${twoChars(date.getDate())}T${twoChars(date.getHours())}:${twoChars(date.getMinutes())}`; -}; - -const convertLocalDatetimeToUTC = (value) => { - const re = /^([0-9]{4,})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2})/; - const match = re.exec(value); - const date = new Date(match[1], match[2] - 1, match[3], match[4], match[5]); - const fullISO8601 = date.toISOString(); - return fullISO8601.slice(0, fullISO8601.indexOf('T') + 6); -}; - -delegate(document, '#form_admin_settings_registrations_mode', 'change', ({ target }) => onChangeRegistrationMode(target)); - -ready(() => { - const domainBlockSeverityInput = document.getElementById('domain_block_severity'); - if (domainBlockSeverityInput) onDomainBlockSeverityChange(domainBlockSeverityInput); - - const enableBootstrapTimelineAccounts = document.getElementById('form_admin_settings_enable_bootstrap_timeline_accounts'); - if (enableBootstrapTimelineAccounts) onEnableBootstrapTimelineAccountsChange(enableBootstrapTimelineAccounts); - - const registrationMode = document.getElementById('form_admin_settings_registrations_mode'); - if (registrationMode) onChangeRegistrationMode(registrationMode); - - const checkAllElement = document.querySelector('#batch_checkbox_all'); - if (checkAllElement) { - checkAllElement.checked = [].every.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked); - checkAllElement.indeterminate = !checkAllElement.checked && [].some.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked); - } - - document.querySelector('a#add-instance-button')?.addEventListener('click', (e) => { - const domain = document.querySelector('input[type="text"]#by_domain')?.value; - - if (domain) { - const url = new URL(event.target.href); - url.searchParams.set('_domain', domain); - e.target.href = url; - } - }); - - [].forEach.call(document.querySelectorAll('input[type="datetime-local"]'), element => { - if (element.value) { - element.value = convertUTCDateTimeToLocal(element.value); - } - if (element.placeholder) { - element.placeholder = convertUTCDateTimeToLocal(element.placeholder); - } - }); - - delegate(document, 'form', 'submit', ({ target }) => { - [].forEach.call(target.querySelectorAll('input[type="datetime-local"]'), element => { - if (element.value && element.validity.valid) { - element.value = convertLocalDatetimeToUTC(element.value); - } - }); - }); - - const announcementStartsAt = document.querySelector('input[type="datetime-local"]#announcement_starts_at'); - if (announcementStartsAt) { - setAnnouncementEndsAttributes(announcementStartsAt); - } - - const React = require('react'); - const ReactDOM = require('react-dom'); - - [].forEach.call(document.querySelectorAll('[data-admin-component]'), element => { - const componentName = element.getAttribute('data-admin-component'); - const { locale, ...componentProps } = JSON.parse(element.getAttribute('data-props')); - - import('../mastodon/containers/admin_component').then(({ default: AdminComponent }) => { - return import('../mastodon/components/admin/' + componentName).then(({ default: Component }) => { - ReactDOM.render(( - - - - ), element); - }); - }).catch(error => { - console.error(error); - }); - }); -}); diff --git a/app/javascript/packs/admin.jsx b/app/javascript/packs/admin.jsx new file mode 100644 index 000000000..038e9b434 --- /dev/null +++ b/app/javascript/packs/admin.jsx @@ -0,0 +1,245 @@ +import './public-path'; +import { delegate } from '@rails/ujs'; +import ready from '../mastodon/ready'; + +const setAnnouncementEndsAttributes = (target) => { + const valid = target?.value && target?.validity?.valid; + const element = document.querySelector('input[type="datetime-local"]#announcement_ends_at'); + if (valid) { + element.classList.remove('optional'); + element.required = true; + element.min = target.value; + } else { + element.classList.add('optional'); + element.removeAttribute('required'); + element.removeAttribute('min'); + } +}; + +delegate(document, 'input[type="datetime-local"]#announcement_starts_at', 'change', ({ target }) => { + setAnnouncementEndsAttributes(target); +}); + +const batchCheckboxClassName = '.batch-checkbox input[type="checkbox"]'; + +const showSelectAll = () => { + const selectAllMatchingElement = document.querySelector('.batch-table__select-all'); + selectAllMatchingElement.classList.add('active'); +}; + +const hideSelectAll = () => { + const selectAllMatchingElement = document.querySelector('.batch-table__select-all'); + const hiddenField = document.querySelector('#select_all_matching'); + const selectedMsg = document.querySelector('.batch-table__select-all .selected'); + const notSelectedMsg = document.querySelector('.batch-table__select-all .not-selected'); + + selectAllMatchingElement.classList.remove('active'); + selectedMsg.classList.remove('active'); + notSelectedMsg.classList.add('active'); + hiddenField.value = '0'; +}; + +delegate(document, '#batch_checkbox_all', 'change', ({ target }) => { + const selectAllMatchingElement = document.querySelector('.batch-table__select-all'); + + [].forEach.call(document.querySelectorAll(batchCheckboxClassName), (content) => { + content.checked = target.checked; + }); + + if (selectAllMatchingElement) { + if (target.checked) { + showSelectAll(); + } else { + hideSelectAll(); + } + } +}); + +delegate(document, '.batch-table__select-all button', 'click', () => { + const hiddenField = document.querySelector('#select_all_matching'); + const active = hiddenField.value === '1'; + const selectedMsg = document.querySelector('.batch-table__select-all .selected'); + const notSelectedMsg = document.querySelector('.batch-table__select-all .not-selected'); + + if (active) { + hiddenField.value = '0'; + selectedMsg.classList.remove('active'); + notSelectedMsg.classList.add('active'); + } else { + hiddenField.value = '1'; + notSelectedMsg.classList.remove('active'); + selectedMsg.classList.add('active'); + } +}); + +delegate(document, batchCheckboxClassName, 'change', () => { + const checkAllElement = document.querySelector('#batch_checkbox_all'); + const selectAllMatchingElement = document.querySelector('.batch-table__select-all'); + + if (checkAllElement) { + checkAllElement.checked = [].every.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked); + checkAllElement.indeterminate = !checkAllElement.checked && [].some.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked); + + if (selectAllMatchingElement) { + if (checkAllElement.checked) { + showSelectAll(); + } else { + hideSelectAll(); + } + } + } +}); + +delegate(document, '.media-spoiler-show-button', 'click', () => { + [].forEach.call(document.querySelectorAll('button.media-spoiler'), (element) => { + element.click(); + }); +}); + +delegate(document, '.media-spoiler-hide-button', 'click', () => { + [].forEach.call(document.querySelectorAll('.spoiler-button.spoiler-button--visible button'), (element) => { + element.click(); + }); +}); + +delegate(document, '.filter-subset--with-select select', 'change', ({ target }) => { + target.form.submit(); +}); + +const onDomainBlockSeverityChange = (target) => { + const rejectMediaDiv = document.querySelector('.input.with_label.domain_block_reject_media'); + const rejectReportsDiv = document.querySelector('.input.with_label.domain_block_reject_reports'); + + if (rejectMediaDiv) { + rejectMediaDiv.style.display = (target.value === 'suspend') ? 'none' : 'block'; + } + + if (rejectReportsDiv) { + rejectReportsDiv.style.display = (target.value === 'suspend') ? 'none' : 'block'; + } +}; + +delegate(document, '#domain_block_severity', 'change', ({ target }) => onDomainBlockSeverityChange(target)); + +const onEnableBootstrapTimelineAccountsChange = (target) => { + const bootstrapTimelineAccountsField = document.querySelector('#form_admin_settings_bootstrap_timeline_accounts'); + + if (bootstrapTimelineAccountsField) { + bootstrapTimelineAccountsField.disabled = !target.checked; + if (target.checked) { + bootstrapTimelineAccountsField.parentElement.classList.remove('disabled'); + bootstrapTimelineAccountsField.parentElement.parentElement.classList.remove('disabled'); + } else { + bootstrapTimelineAccountsField.parentElement.classList.add('disabled'); + bootstrapTimelineAccountsField.parentElement.parentElement.classList.add('disabled'); + } + } +}; + +delegate(document, '#form_admin_settings_enable_bootstrap_timeline_accounts', 'change', ({ target }) => onEnableBootstrapTimelineAccountsChange(target)); + +const onChangeRegistrationMode = (target) => { + const enabled = target.value === 'approved'; + + [].forEach.call(document.querySelectorAll('#form_admin_settings_require_invite_text'), (input) => { + input.disabled = !enabled; + if (enabled) { + let element = input; + do { + element.classList.remove('disabled'); + element = element.parentElement; + } while (element && !element.classList.contains('fields-group')); + } else { + let element = input; + do { + element.classList.add('disabled'); + element = element.parentElement; + } while (element && !element.classList.contains('fields-group')); + } + }); +}; + +const convertUTCDateTimeToLocal = (value) => { + const date = new Date(value + 'Z'); + const twoChars = (x) => (x.toString().padStart(2, '0')); + return `${date.getFullYear()}-${twoChars(date.getMonth()+1)}-${twoChars(date.getDate())}T${twoChars(date.getHours())}:${twoChars(date.getMinutes())}`; +}; + +const convertLocalDatetimeToUTC = (value) => { + const re = /^([0-9]{4,})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2})/; + const match = re.exec(value); + const date = new Date(match[1], match[2] - 1, match[3], match[4], match[5]); + const fullISO8601 = date.toISOString(); + return fullISO8601.slice(0, fullISO8601.indexOf('T') + 6); +}; + +delegate(document, '#form_admin_settings_registrations_mode', 'change', ({ target }) => onChangeRegistrationMode(target)); + +ready(() => { + const domainBlockSeverityInput = document.getElementById('domain_block_severity'); + if (domainBlockSeverityInput) onDomainBlockSeverityChange(domainBlockSeverityInput); + + const enableBootstrapTimelineAccounts = document.getElementById('form_admin_settings_enable_bootstrap_timeline_accounts'); + if (enableBootstrapTimelineAccounts) onEnableBootstrapTimelineAccountsChange(enableBootstrapTimelineAccounts); + + const registrationMode = document.getElementById('form_admin_settings_registrations_mode'); + if (registrationMode) onChangeRegistrationMode(registrationMode); + + const checkAllElement = document.querySelector('#batch_checkbox_all'); + if (checkAllElement) { + checkAllElement.checked = [].every.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked); + checkAllElement.indeterminate = !checkAllElement.checked && [].some.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked); + } + + document.querySelector('a#add-instance-button')?.addEventListener('click', (e) => { + const domain = document.querySelector('input[type="text"]#by_domain')?.value; + + if (domain) { + const url = new URL(event.target.href); + url.searchParams.set('_domain', domain); + e.target.href = url; + } + }); + + [].forEach.call(document.querySelectorAll('input[type="datetime-local"]'), element => { + if (element.value) { + element.value = convertUTCDateTimeToLocal(element.value); + } + if (element.placeholder) { + element.placeholder = convertUTCDateTimeToLocal(element.placeholder); + } + }); + + delegate(document, 'form', 'submit', ({ target }) => { + [].forEach.call(target.querySelectorAll('input[type="datetime-local"]'), element => { + if (element.value && element.validity.valid) { + element.value = convertLocalDatetimeToUTC(element.value); + } + }); + }); + + const announcementStartsAt = document.querySelector('input[type="datetime-local"]#announcement_starts_at'); + if (announcementStartsAt) { + setAnnouncementEndsAttributes(announcementStartsAt); + } + + const React = require('react'); + const ReactDOM = require('react-dom'); + + [].forEach.call(document.querySelectorAll('[data-admin-component]'), element => { + const componentName = element.getAttribute('data-admin-component'); + const { locale, ...componentProps } = JSON.parse(element.getAttribute('data-props')); + + import('../mastodon/containers/admin_component').then(({ default: AdminComponent }) => { + return import('../mastodon/components/admin/' + componentName).then(({ default: Component }) => { + ReactDOM.render(( + + + + ), element); + }); + }).catch(error => { + console.error(error); + }); + }); +}); diff --git a/app/javascript/packs/public.js b/app/javascript/packs/public.js deleted file mode 100644 index a5e2014f7..000000000 --- a/app/javascript/packs/public.js +++ /dev/null @@ -1,332 +0,0 @@ -import './public-path'; -import escapeTextContentForBrowser from 'escape-html'; -import loadPolyfills from '../mastodon/load_polyfills'; -import ready from '../mastodon/ready'; -import { start } from '../mastodon/common'; -import loadKeyboardExtensions from '../mastodon/load_keyboard_extensions'; -import 'cocoon-js-vanilla'; - -start(); - -window.addEventListener('message', e => { - const data = e.data || {}; - - if (!window.parent || data.type !== 'setHeight') { - return; - } - - ready(() => { - window.parent.postMessage({ - type: 'setHeight', - id: data.id, - height: document.getElementsByTagName('html')[0].scrollHeight, - }, '*'); - }); -}); - -function main() { - const IntlMessageFormat = require('intl-messageformat').default; - const { timeAgoString } = require('../mastodon/components/relative_timestamp'); - const { delegate } = require('@rails/ujs'); - const emojify = require('../mastodon/features/emoji/emoji').default; - const { getLocale } = require('../mastodon/locales'); - const { messages } = getLocale(); - const React = require('react'); - const ReactDOM = require('react-dom'); - const { createBrowserHistory } = require('history'); - - const scrollToDetailedStatus = () => { - const history = createBrowserHistory(); - const detailedStatuses = document.querySelectorAll('.public-layout .detailed-status'); - const location = history.location; - - if (detailedStatuses.length === 1 && (!location.state || !location.state.scrolledToDetailedStatus)) { - detailedStatuses[0].scrollIntoView(); - history.replace(location.pathname, { ...location.state, scrolledToDetailedStatus: true }); - } - }; - - const getEmojiAnimationHandler = (swapTo) => { - return ({ target }) => { - target.src = target.getAttribute(swapTo); - }; - }; - - ready(() => { - const locale = document.documentElement.lang; - - const dateTimeFormat = new Intl.DateTimeFormat(locale, { - year: 'numeric', - month: 'long', - day: 'numeric', - hour: 'numeric', - minute: 'numeric', - }); - - const dateFormat = new Intl.DateTimeFormat(locale, { - year: 'numeric', - month: 'short', - day: 'numeric', - timeFormat: false, - }); - - const timeFormat = new Intl.DateTimeFormat(locale, { - timeStyle: 'short', - hour12: false, - }); - - [].forEach.call(document.querySelectorAll('.emojify'), (content) => { - content.innerHTML = emojify(content.innerHTML); - }); - - [].forEach.call(document.querySelectorAll('time.formatted'), (content) => { - const datetime = new Date(content.getAttribute('datetime')); - const formattedDate = dateTimeFormat.format(datetime); - - content.title = formattedDate; - content.textContent = formattedDate; - }); - - const isToday = date => { - const today = new Date(); - - return date.getDate() === today.getDate() && - date.getMonth() === today.getMonth() && - date.getFullYear() === today.getFullYear(); - }; - const todayFormat = new IntlMessageFormat(messages['relative_format.today'] || 'Today at {time}', locale); - - [].forEach.call(document.querySelectorAll('time.relative-formatted'), (content) => { - const datetime = new Date(content.getAttribute('datetime')); - - let formattedContent; - - if (isToday(datetime)) { - const formattedTime = timeFormat.format(datetime); - - formattedContent = todayFormat.format({ time: formattedTime }); - } else { - formattedContent = dateFormat.format(datetime); - } - - content.title = formattedContent; - content.textContent = formattedContent; - }); - - [].forEach.call(document.querySelectorAll('time.time-ago'), (content) => { - const datetime = new Date(content.getAttribute('datetime')); - const now = new Date(); - - content.title = dateTimeFormat.format(datetime); - content.textContent = timeAgoString({ - formatMessage: ({ id, defaultMessage }, values) => (new IntlMessageFormat(messages[id] || defaultMessage, locale)).format(values), - formatDate: (date, options) => (new Intl.DateTimeFormat(locale, options)).format(date), - }, datetime, now, now.getFullYear(), content.getAttribute('datetime').includes('T')); - }); - - const reactComponents = document.querySelectorAll('[data-component]'); - - if (reactComponents.length > 0) { - import(/* webpackChunkName: "containers/media_container" */ '../mastodon/containers/media_container') - .then(({ default: MediaContainer }) => { - [].forEach.call(reactComponents, (component) => { - [].forEach.call(component.children, (child) => { - component.removeChild(child); - }); - }); - - const content = document.createElement('div'); - - ReactDOM.render(, content); - document.body.appendChild(content); - scrollToDetailedStatus(); - }) - .catch(error => { - console.error(error); - scrollToDetailedStatus(); - }); - } else { - scrollToDetailedStatus(); - } - - delegate(document, '#registration_user_password_confirmation,#registration_user_password', 'input', () => { - const password = document.getElementById('registration_user_password'); - const confirmation = document.getElementById('registration_user_password_confirmation'); - if (confirmation.value && confirmation.value.length > password.maxLength) { - confirmation.setCustomValidity((new IntlMessageFormat(messages['password_confirmation.exceeds_maxlength'] || 'Password confirmation exceeds the maximum password length', locale)).format()); - } else if (password.value && password.value !== confirmation.value) { - confirmation.setCustomValidity((new IntlMessageFormat(messages['password_confirmation.mismatching'] || 'Password confirmation does not match', locale)).format()); - } else { - confirmation.setCustomValidity(''); - } - }); - - delegate(document, '#user_password,#user_password_confirmation', 'input', () => { - const password = document.getElementById('user_password'); - const confirmation = document.getElementById('user_password_confirmation'); - if (!confirmation) return; - - if (confirmation.value && confirmation.value.length > password.maxLength) { - confirmation.setCustomValidity((new IntlMessageFormat(messages['password_confirmation.exceeds_maxlength'] || 'Password confirmation exceeds the maximum password length', locale)).format()); - } else if (password.value && password.value !== confirmation.value) { - confirmation.setCustomValidity((new IntlMessageFormat(messages['password_confirmation.mismatching'] || 'Password confirmation does not match', locale)).format()); - } else { - confirmation.setCustomValidity(''); - } - }); - - delegate(document, '.custom-emoji', 'mouseover', getEmojiAnimationHandler('data-original')); - delegate(document, '.custom-emoji', 'mouseout', getEmojiAnimationHandler('data-static')); - - delegate(document, '.status__content__spoiler-link', 'click', function() { - const statusEl = this.parentNode.parentNode; - - if (statusEl.dataset.spoiler === 'expanded') { - statusEl.dataset.spoiler = 'folded'; - this.textContent = (new IntlMessageFormat(messages['status.show_more'] || 'Show more', locale)).format(); - } else { - statusEl.dataset.spoiler = 'expanded'; - this.textContent = (new IntlMessageFormat(messages['status.show_less'] || 'Show less', locale)).format(); - } - - return false; - }); - - [].forEach.call(document.querySelectorAll('.status__content__spoiler-link'), (spoilerLink) => { - const statusEl = spoilerLink.parentNode.parentNode; - const message = (statusEl.dataset.spoiler === 'expanded') ? (messages['status.show_less'] || 'Show less') : (messages['status.show_more'] || 'Show more'); - spoilerLink.textContent = (new IntlMessageFormat(message, locale)).format(); - }); - }); - - delegate(document, '#account_display_name', 'input', ({ target }) => { - const name = document.querySelector('.card .display-name strong'); - if (name) { - if (target.value) { - name.innerHTML = emojify(escapeTextContentForBrowser(target.value)); - } else { - name.textContent = target.dataset.default; - } - } - }); - - delegate(document, '#account_avatar', 'change', ({ target }) => { - const avatar = document.querySelector('.card .avatar img'); - const [file] = target.files || []; - const url = file ? URL.createObjectURL(file) : avatar.dataset.originalSrc; - - avatar.src = url; - }); - - const getProfileAvatarAnimationHandler = (swapTo) => { - //animate avatar gifs on the profile page when moused over - return ({ target }) => { - const swapSrc = target.getAttribute(swapTo); - //only change the img source if autoplay is off and the image src is actually different - if(target.getAttribute('data-autoplay') !== 'true' && target.src !== swapSrc) { - target.src = swapSrc; - } - }; - }; - - delegate(document, 'img#profile_page_avatar', 'mouseover', getProfileAvatarAnimationHandler('data-original')); - - delegate(document, 'img#profile_page_avatar', 'mouseout', getProfileAvatarAnimationHandler('data-static')); - - delegate(document, '#account_header', 'change', ({ target }) => { - const header = document.querySelector('.card .card__img img'); - const [file] = target.files || []; - const url = file ? URL.createObjectURL(file) : header.dataset.originalSrc; - - header.src = url; - }); - - delegate(document, '#account_locked', 'change', ({ target }) => { - const lock = document.querySelector('.card .display-name i'); - - if (lock) { - if (target.checked) { - delete lock.dataset.hidden; - } else { - lock.dataset.hidden = 'true'; - } - } - }); - - delegate(document, '.input-copy input', 'click', ({ target }) => { - target.focus(); - target.select(); - target.setSelectionRange(0, target.value.length); - }); - - delegate(document, '.input-copy button', 'click', ({ target }) => { - const input = target.parentNode.querySelector('.input-copy__wrapper input'); - - const oldReadOnly = input.readonly; - - input.readonly = false; - input.focus(); - input.select(); - input.setSelectionRange(0, input.value.length); - - try { - if (document.execCommand('copy')) { - input.blur(); - target.parentNode.classList.add('copied'); - - setTimeout(() => { - target.parentNode.classList.remove('copied'); - }, 700); - } - } catch (err) { - console.error(err); - } - - input.readonly = oldReadOnly; - }); - - const toggleSidebar = () => { - const sidebar = document.querySelector('.sidebar ul'); - const toggleButton = document.querySelector('.sidebar__toggle__icon'); - - if (sidebar.classList.contains('visible')) { - document.body.style.overflow = null; - toggleButton.setAttribute('aria-expanded', false); - } else { - document.body.style.overflow = 'hidden'; - toggleButton.setAttribute('aria-expanded', true); - } - - toggleButton.classList.toggle('active'); - sidebar.classList.toggle('visible'); - }; - - delegate(document, '.sidebar__toggle__icon', 'click', () => { - toggleSidebar(); - }); - - delegate(document, '.sidebar__toggle__icon', 'keydown', e => { - if (e.key === ' ' || e.key === 'Enter') { - e.preventDefault(); - toggleSidebar(); - } - }); - - // Empty the honeypot fields in JS in case something like an extension - // automatically filled them. - delegate(document, '#registration_new_user,#new_user', 'submit', () => { - ['user_website', 'user_confirm_password', 'registration_user_website', 'registration_user_confirm_password'].forEach(id => { - const field = document.getElementById(id); - if (field) { - field.value = ''; - } - }); - }); -} - -loadPolyfills() - .then(main) - .then(loadKeyboardExtensions) - .catch(error => { - console.error(error); - }); diff --git a/app/javascript/packs/public.jsx b/app/javascript/packs/public.jsx new file mode 100644 index 000000000..a5e2014f7 --- /dev/null +++ b/app/javascript/packs/public.jsx @@ -0,0 +1,332 @@ +import './public-path'; +import escapeTextContentForBrowser from 'escape-html'; +import loadPolyfills from '../mastodon/load_polyfills'; +import ready from '../mastodon/ready'; +import { start } from '../mastodon/common'; +import loadKeyboardExtensions from '../mastodon/load_keyboard_extensions'; +import 'cocoon-js-vanilla'; + +start(); + +window.addEventListener('message', e => { + const data = e.data || {}; + + if (!window.parent || data.type !== 'setHeight') { + return; + } + + ready(() => { + window.parent.postMessage({ + type: 'setHeight', + id: data.id, + height: document.getElementsByTagName('html')[0].scrollHeight, + }, '*'); + }); +}); + +function main() { + const IntlMessageFormat = require('intl-messageformat').default; + const { timeAgoString } = require('../mastodon/components/relative_timestamp'); + const { delegate } = require('@rails/ujs'); + const emojify = require('../mastodon/features/emoji/emoji').default; + const { getLocale } = require('../mastodon/locales'); + const { messages } = getLocale(); + const React = require('react'); + const ReactDOM = require('react-dom'); + const { createBrowserHistory } = require('history'); + + const scrollToDetailedStatus = () => { + const history = createBrowserHistory(); + const detailedStatuses = document.querySelectorAll('.public-layout .detailed-status'); + const location = history.location; + + if (detailedStatuses.length === 1 && (!location.state || !location.state.scrolledToDetailedStatus)) { + detailedStatuses[0].scrollIntoView(); + history.replace(location.pathname, { ...location.state, scrolledToDetailedStatus: true }); + } + }; + + const getEmojiAnimationHandler = (swapTo) => { + return ({ target }) => { + target.src = target.getAttribute(swapTo); + }; + }; + + ready(() => { + const locale = document.documentElement.lang; + + const dateTimeFormat = new Intl.DateTimeFormat(locale, { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + }); + + const dateFormat = new Intl.DateTimeFormat(locale, { + year: 'numeric', + month: 'short', + day: 'numeric', + timeFormat: false, + }); + + const timeFormat = new Intl.DateTimeFormat(locale, { + timeStyle: 'short', + hour12: false, + }); + + [].forEach.call(document.querySelectorAll('.emojify'), (content) => { + content.innerHTML = emojify(content.innerHTML); + }); + + [].forEach.call(document.querySelectorAll('time.formatted'), (content) => { + const datetime = new Date(content.getAttribute('datetime')); + const formattedDate = dateTimeFormat.format(datetime); + + content.title = formattedDate; + content.textContent = formattedDate; + }); + + const isToday = date => { + const today = new Date(); + + return date.getDate() === today.getDate() && + date.getMonth() === today.getMonth() && + date.getFullYear() === today.getFullYear(); + }; + const todayFormat = new IntlMessageFormat(messages['relative_format.today'] || 'Today at {time}', locale); + + [].forEach.call(document.querySelectorAll('time.relative-formatted'), (content) => { + const datetime = new Date(content.getAttribute('datetime')); + + let formattedContent; + + if (isToday(datetime)) { + const formattedTime = timeFormat.format(datetime); + + formattedContent = todayFormat.format({ time: formattedTime }); + } else { + formattedContent = dateFormat.format(datetime); + } + + content.title = formattedContent; + content.textContent = formattedContent; + }); + + [].forEach.call(document.querySelectorAll('time.time-ago'), (content) => { + const datetime = new Date(content.getAttribute('datetime')); + const now = new Date(); + + content.title = dateTimeFormat.format(datetime); + content.textContent = timeAgoString({ + formatMessage: ({ id, defaultMessage }, values) => (new IntlMessageFormat(messages[id] || defaultMessage, locale)).format(values), + formatDate: (date, options) => (new Intl.DateTimeFormat(locale, options)).format(date), + }, datetime, now, now.getFullYear(), content.getAttribute('datetime').includes('T')); + }); + + const reactComponents = document.querySelectorAll('[data-component]'); + + if (reactComponents.length > 0) { + import(/* webpackChunkName: "containers/media_container" */ '../mastodon/containers/media_container') + .then(({ default: MediaContainer }) => { + [].forEach.call(reactComponents, (component) => { + [].forEach.call(component.children, (child) => { + component.removeChild(child); + }); + }); + + const content = document.createElement('div'); + + ReactDOM.render(, content); + document.body.appendChild(content); + scrollToDetailedStatus(); + }) + .catch(error => { + console.error(error); + scrollToDetailedStatus(); + }); + } else { + scrollToDetailedStatus(); + } + + delegate(document, '#registration_user_password_confirmation,#registration_user_password', 'input', () => { + const password = document.getElementById('registration_user_password'); + const confirmation = document.getElementById('registration_user_password_confirmation'); + if (confirmation.value && confirmation.value.length > password.maxLength) { + confirmation.setCustomValidity((new IntlMessageFormat(messages['password_confirmation.exceeds_maxlength'] || 'Password confirmation exceeds the maximum password length', locale)).format()); + } else if (password.value && password.value !== confirmation.value) { + confirmation.setCustomValidity((new IntlMessageFormat(messages['password_confirmation.mismatching'] || 'Password confirmation does not match', locale)).format()); + } else { + confirmation.setCustomValidity(''); + } + }); + + delegate(document, '#user_password,#user_password_confirmation', 'input', () => { + const password = document.getElementById('user_password'); + const confirmation = document.getElementById('user_password_confirmation'); + if (!confirmation) return; + + if (confirmation.value && confirmation.value.length > password.maxLength) { + confirmation.setCustomValidity((new IntlMessageFormat(messages['password_confirmation.exceeds_maxlength'] || 'Password confirmation exceeds the maximum password length', locale)).format()); + } else if (password.value && password.value !== confirmation.value) { + confirmation.setCustomValidity((new IntlMessageFormat(messages['password_confirmation.mismatching'] || 'Password confirmation does not match', locale)).format()); + } else { + confirmation.setCustomValidity(''); + } + }); + + delegate(document, '.custom-emoji', 'mouseover', getEmojiAnimationHandler('data-original')); + delegate(document, '.custom-emoji', 'mouseout', getEmojiAnimationHandler('data-static')); + + delegate(document, '.status__content__spoiler-link', 'click', function() { + const statusEl = this.parentNode.parentNode; + + if (statusEl.dataset.spoiler === 'expanded') { + statusEl.dataset.spoiler = 'folded'; + this.textContent = (new IntlMessageFormat(messages['status.show_more'] || 'Show more', locale)).format(); + } else { + statusEl.dataset.spoiler = 'expanded'; + this.textContent = (new IntlMessageFormat(messages['status.show_less'] || 'Show less', locale)).format(); + } + + return false; + }); + + [].forEach.call(document.querySelectorAll('.status__content__spoiler-link'), (spoilerLink) => { + const statusEl = spoilerLink.parentNode.parentNode; + const message = (statusEl.dataset.spoiler === 'expanded') ? (messages['status.show_less'] || 'Show less') : (messages['status.show_more'] || 'Show more'); + spoilerLink.textContent = (new IntlMessageFormat(message, locale)).format(); + }); + }); + + delegate(document, '#account_display_name', 'input', ({ target }) => { + const name = document.querySelector('.card .display-name strong'); + if (name) { + if (target.value) { + name.innerHTML = emojify(escapeTextContentForBrowser(target.value)); + } else { + name.textContent = target.dataset.default; + } + } + }); + + delegate(document, '#account_avatar', 'change', ({ target }) => { + const avatar = document.querySelector('.card .avatar img'); + const [file] = target.files || []; + const url = file ? URL.createObjectURL(file) : avatar.dataset.originalSrc; + + avatar.src = url; + }); + + const getProfileAvatarAnimationHandler = (swapTo) => { + //animate avatar gifs on the profile page when moused over + return ({ target }) => { + const swapSrc = target.getAttribute(swapTo); + //only change the img source if autoplay is off and the image src is actually different + if(target.getAttribute('data-autoplay') !== 'true' && target.src !== swapSrc) { + target.src = swapSrc; + } + }; + }; + + delegate(document, 'img#profile_page_avatar', 'mouseover', getProfileAvatarAnimationHandler('data-original')); + + delegate(document, 'img#profile_page_avatar', 'mouseout', getProfileAvatarAnimationHandler('data-static')); + + delegate(document, '#account_header', 'change', ({ target }) => { + const header = document.querySelector('.card .card__img img'); + const [file] = target.files || []; + const url = file ? URL.createObjectURL(file) : header.dataset.originalSrc; + + header.src = url; + }); + + delegate(document, '#account_locked', 'change', ({ target }) => { + const lock = document.querySelector('.card .display-name i'); + + if (lock) { + if (target.checked) { + delete lock.dataset.hidden; + } else { + lock.dataset.hidden = 'true'; + } + } + }); + + delegate(document, '.input-copy input', 'click', ({ target }) => { + target.focus(); + target.select(); + target.setSelectionRange(0, target.value.length); + }); + + delegate(document, '.input-copy button', 'click', ({ target }) => { + const input = target.parentNode.querySelector('.input-copy__wrapper input'); + + const oldReadOnly = input.readonly; + + input.readonly = false; + input.focus(); + input.select(); + input.setSelectionRange(0, input.value.length); + + try { + if (document.execCommand('copy')) { + input.blur(); + target.parentNode.classList.add('copied'); + + setTimeout(() => { + target.parentNode.classList.remove('copied'); + }, 700); + } + } catch (err) { + console.error(err); + } + + input.readonly = oldReadOnly; + }); + + const toggleSidebar = () => { + const sidebar = document.querySelector('.sidebar ul'); + const toggleButton = document.querySelector('.sidebar__toggle__icon'); + + if (sidebar.classList.contains('visible')) { + document.body.style.overflow = null; + toggleButton.setAttribute('aria-expanded', false); + } else { + document.body.style.overflow = 'hidden'; + toggleButton.setAttribute('aria-expanded', true); + } + + toggleButton.classList.toggle('active'); + sidebar.classList.toggle('visible'); + }; + + delegate(document, '.sidebar__toggle__icon', 'click', () => { + toggleSidebar(); + }); + + delegate(document, '.sidebar__toggle__icon', 'keydown', e => { + if (e.key === ' ' || e.key === 'Enter') { + e.preventDefault(); + toggleSidebar(); + } + }); + + // Empty the honeypot fields in JS in case something like an extension + // automatically filled them. + delegate(document, '#registration_new_user,#new_user', 'submit', () => { + ['user_website', 'user_confirm_password', 'registration_user_website', 'registration_user_confirm_password'].forEach(id => { + const field = document.getElementById(id); + if (field) { + field.value = ''; + } + }); + }); +} + +loadPolyfills() + .then(main) + .then(loadKeyboardExtensions) + .catch(error => { + console.error(error); + }); diff --git a/app/javascript/packs/share.js b/app/javascript/packs/share.js deleted file mode 100644 index 1225d7b52..000000000 --- a/app/javascript/packs/share.js +++ /dev/null @@ -1,26 +0,0 @@ -import './public-path'; -import loadPolyfills from '../mastodon/load_polyfills'; -import { start } from '../mastodon/common'; - -start(); - -function loaded() { - const ComposeContainer = require('../mastodon/containers/compose_container').default; - const React = require('react'); - const ReactDOM = require('react-dom'); - const mountNode = document.getElementById('mastodon-compose'); - - if (mountNode !== null) { - const props = JSON.parse(mountNode.getAttribute('data-props')); - ReactDOM.render(, mountNode); - } -} - -function main() { - const ready = require('../mastodon/ready').default; - ready(loaded); -} - -loadPolyfills().then(main).catch(error => { - console.error(error); -}); diff --git a/app/javascript/packs/share.jsx b/app/javascript/packs/share.jsx new file mode 100644 index 000000000..1225d7b52 --- /dev/null +++ b/app/javascript/packs/share.jsx @@ -0,0 +1,26 @@ +import './public-path'; +import loadPolyfills from '../mastodon/load_polyfills'; +import { start } from '../mastodon/common'; + +start(); + +function loaded() { + const ComposeContainer = require('../mastodon/containers/compose_container').default; + const React = require('react'); + const ReactDOM = require('react-dom'); + const mountNode = document.getElementById('mastodon-compose'); + + if (mountNode !== null) { + const props = JSON.parse(mountNode.getAttribute('data-props')); + ReactDOM.render(, mountNode); + } +} + +function main() { + const ready = require('../mastodon/ready').default; + ready(loaded); +} + +loadPolyfills().then(main).catch(error => { + console.error(error); +}); -- cgit