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.js50
-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.js53
-rw-r--r--app/javascript/core/settings.js52
-rw-r--r--app/javascript/core/theme.yml19
7 files changed, 203 insertions, 0 deletions
diff --git a/app/javascript/core/admin.js b/app/javascript/core/admin.js
new file mode 100644
index 000000000..0c26dc18d
--- /dev/null
+++ b/app/javascript/core/admin.js
@@ -0,0 +1,50 @@
+//  This file will be loaded on admin pages, regardless of theme.
+
+import { delegate } from 'rails-ujs';
+
+function handleDeleteStatus(event) {
+  const [data] = event.detail;
+  const element = document.querySelector(`[data-id="${data.id}"]`);
+  if (element) {
+    element.parentNode.removeChild(element);
+  }
+}
+
+[].forEach.call(document.querySelectorAll('.trash-button'), (content) => {
+  content.addEventListener('ajax:success', handleDeleteStatus);
+});
+
+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, '#domain_block_severity', 'change', ({ target }) => {
+  const rejectMediaDiv = document.querySelector('.input.with_label.domain_block_reject_media');
+  if (rejectMediaDiv) {
+    rejectMediaDiv.style.display = (target.value === 'suspend') ? 'none' : 'block';
+  }
+});
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..b5014a8c7
--- /dev/null
+++ b/app/javascript/core/public.js
@@ -0,0 +1,53 @@
+//  This file will be loaded on public pages, regardless of theme.
+
+import createHistory from 'history/createBrowserHistory';
+import ready from '../mastodon/ready';
+
+const { delegate } = require('rails-ujs');
+const { length } = require('stringz');
+
+ready(() => {
+  const history = createHistory();
+  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});
+  }
+});
+
+delegate(document, '.webapp-btn', 'click', ({ target, button }) => {
+  if (button !== 0) {
+    return true;
+  }
+  window.location.href = target.href;
+  return false;
+});
+
+delegate(document, '.status__content__spoiler-link', 'click', ({ target }) => {
+  const contentEl = target.parentNode.parentNode.querySelector('.e-content');
+
+  if (contentEl.style.display === 'block') {
+    contentEl.style.display = 'none';
+    target.parentNode.style.marginBottom = 0;
+  } else {
+    contentEl.style.display = 'block';
+    target.parentNode.style.marginBottom = null;
+  }
+
+  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');
+});
diff --git a/app/javascript/core/settings.js b/app/javascript/core/settings.js
new file mode 100644
index 000000000..e48fcb9b1
--- /dev/null
+++ b/app/javascript/core/settings.js
@@ -0,0 +1,52 @@
+//  This file will be loaded on settings pages, regardless of theme.
+
+const { length } = require('stringz');
+const { delegate } = require('rails-ujs');
+import emojify from '../mastodon/features/emoji/emoji';
+
+delegate(document, '#account_display_name', 'input', ({ target }) => {
+  const nameCounter = document.querySelector('.name-counter');
+  const name        = document.querySelector('.card .display-name strong');
+
+  if (nameCounter) {
+    nameCounter.textContent = 30 - length(target.value);
+  }
+
+  if (name) {
+    name.innerHTML = emojify(target.value);
+  }
+});
+
+delegate(document, '#account_note', 'input', ({ target }) => {
+  const noteCounter = document.querySelector('.note-counter');
+
+  if (noteCounter) {
+    noteCounter.textContent = 500 - length(target.value);
+  }
+});
+
+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';
+  }
+});
diff --git a/app/javascript/core/theme.yml b/app/javascript/core/theme.yml
new file mode 100644
index 000000000..f48ab40c0
--- /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:
+  common:
+    filename: common.js
+    stylesheet: true
+  embed: embed.js
+  error:
+  home:
+  mailer:
+    filename: mailer.js
+    stylesheet: true
+  modal:
+  public: public.js
+  settings: settings.js
+  share: