about summary refs log tree commit diff
path: root/app/javascript/core
diff options
context:
space:
mode:
Diffstat (limited to 'app/javascript/core')
-rw-r--r--app/javascript/core/admin.js75
-rw-r--r--app/javascript/core/common.js5
-rw-r--r--app/javascript/core/embed.js23
-rw-r--r--app/javascript/core/mailer.js1
-rw-r--r--app/javascript/core/public.js51
-rw-r--r--app/javascript/core/settings.js74
-rw-r--r--app/javascript/core/theme.yml19
7 files changed, 248 insertions, 0 deletions
diff --git a/app/javascript/core/admin.js b/app/javascript/core/admin.js
new file mode 100644
index 000000000..f2334c254
--- /dev/null
+++ b/app/javascript/core/admin.js
@@ -0,0 +1,75 @@
+//  This file will be loaded on admin pages, regardless of theme.
+
+import { delegate } from '@rails/ujs';
+import ready from '../mastodon/ready';
+
+const batchCheckboxClassName = '.batch-checkbox input[type="checkbox"]';
+
+delegate(document, '#batch_checkbox_all', 'change', ({ target }) => {
+  [].forEach.call(document.querySelectorAll(batchCheckboxClassName), (content) => {
+    content.checked = target.checked;
+  });
+});
+
+delegate(document, batchCheckboxClassName, 'change', () => {
+  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);
+  }
+});
+
+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');
+    } else {
+      bootstrapTimelineAccountsField.parentElement.classList.add('disabled');
+    }
+  }
+};
+
+delegate(document, '#form_admin_settings_enable_bootstrap_timeline_accounts', 'change', ({ target }) => onEnableBootstrapTimelineAccountsChange(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);
+});
diff --git a/app/javascript/core/common.js b/app/javascript/core/common.js
new file mode 100644
index 000000000..3b038ca40
--- /dev/null
+++ b/app/javascript/core/common.js
@@ -0,0 +1,5 @@
+//  This file will be loaded on all pages, regardless of theme.
+
+import 'font-awesome/css/font-awesome.css';
+
+require.context('../images/', true);
diff --git a/app/javascript/core/embed.js b/app/javascript/core/embed.js
new file mode 100644
index 000000000..6146e6592
--- /dev/null
+++ b/app/javascript/core/embed.js
@@ -0,0 +1,23 @@
+//  This file will be loaded on embed pages, regardless of theme.
+
+window.addEventListener('message', e => {
+  const data = e.data || {};
+
+  if (!window.parent || data.type !== 'setHeight') {
+    return;
+  }
+
+  function setEmbedHeight () {
+    window.parent.postMessage({
+      type: 'setHeight',
+      id: data.id,
+      height: document.getElementsByTagName('html')[0].scrollHeight,
+    }, '*');
+  };
+
+  if (['interactive', 'complete'].includes(document.readyState)) {
+    setEmbedHeight();
+  } else {
+    document.addEventListener('DOMContentLoaded', setEmbedHeight);
+  }
+});
diff --git a/app/javascript/core/mailer.js b/app/javascript/core/mailer.js
new file mode 100644
index 000000000..baef7e7fb
--- /dev/null
+++ b/app/javascript/core/mailer.js
@@ -0,0 +1 @@
+import 'styles/mailer.scss';
diff --git a/app/javascript/core/public.js b/app/javascript/core/public.js
new file mode 100644
index 000000000..8c26f1404
--- /dev/null
+++ b/app/javascript/core/public.js
@@ -0,0 +1,51 @@
+//  This file will be loaded on public pages, regardless of theme.
+
+import ready from '../mastodon/ready';
+
+const { delegate } = require('@rails/ujs');
+const { length } = require('stringz');
+
+delegate(document, '.webapp-btn', 'click', ({ target, button }) => {
+  if (button !== 0) {
+    return true;
+  }
+  window.location.href = target.href;
+  return false;
+});
+
+delegate(document, '.modal-button', 'click', e => {
+  e.preventDefault();
+
+  let href;
+
+  if (e.target.nodeName !== 'A') {
+    href = e.target.parentNode.href;
+  } else {
+    href = e.target.href;
+  }
+
+  window.open(href, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes');
+});
+
+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;
+});
diff --git a/app/javascript/core/settings.js b/app/javascript/core/settings.js
new file mode 100644
index 000000000..e02c91cc7
--- /dev/null
+++ b/app/javascript/core/settings.js
@@ -0,0 +1,74 @@
+//  This file will be loaded on settings pages, regardless of theme.
+
+import escapeTextContentForBrowser from 'escape-html';
+const { delegate } = require('@rails/ujs');
+import emojify from '../mastodon/features/emoji/emoji';
+
+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 = document.querySelector('#default_account_display_name').textContent;
+    }
+  }
+});
+
+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;
+});
+
+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 (target.checked) {
+    lock.style.display = 'inline';
+  } else {
+    lock.style.display = 'none';
+  }
+});
+
+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;
+});
diff --git a/app/javascript/core/theme.yml b/app/javascript/core/theme.yml
new file mode 100644
index 000000000..dc641772c
--- /dev/null
+++ b/app/javascript/core/theme.yml
@@ -0,0 +1,19 @@
+#  These packs will be loaded on every appropriate page, regardless of
+#  theme.
+pack:
+  about:
+  admin: admin.js
+  auth: settings.js
+  common:
+    filename: common.js
+    stylesheet: true
+  embed: embed.js
+  error:
+  home:
+  mailer:
+    filename: mailer.js
+    stylesheet: true
+  modal: public.js
+  public: public.js
+  settings: settings.js
+  share: