1 import escapeTextContentForBrowser
from 'escape-html';
2 import loadPolyfills
from '../mastodon/load_polyfills';
3 import ready
from '../mastodon/ready';
4 import { start
} from '../mastodon/common';
8 window
.addEventListener('message', e
=> {
9 const data
= e
.data
|| {};
11 if (!window
.parent
|| data
.type
!== 'setHeight') {
16 window
.parent
.postMessage({
19 height: document
.getElementsByTagName('html')[0].scrollHeight
,
25 const IntlMessageFormat
= require('intl-messageformat').default;
26 const { timeAgoString
} = require('../mastodon/components/relative_timestamp');
27 const { delegate
} = require('rails-ujs');
28 const emojify
= require('../mastodon/features/emoji/emoji').default;
29 const { getLocale
} = require('../mastodon/locales');
30 const { messages
} = getLocale();
31 const React
= require('react');
32 const ReactDOM
= require('react-dom');
33 const Rellax
= require('rellax');
34 const createHistory
= require('history').createBrowserHistory
;
36 const scrollToDetailedStatus
= () => {
37 const history
= createHistory();
38 const detailedStatuses
= document
.querySelectorAll('.public-layout .detailed-status');
39 const location
= history
.location
;
41 if (detailedStatuses
.length
=== 1 && (!location
.state
|| !location
.state
.scrolledToDetailedStatus
)) {
42 detailedStatuses
[0].scrollIntoView();
43 history
.replace(location
.pathname
, { ...location
.state
, scrolledToDetailedStatus: true });
48 const locale
= document
.documentElement
.lang
;
50 const dateTimeFormat
= new Intl
.DateTimeFormat(locale
, {
58 [].forEach
.call(document
.querySelectorAll('.emojify'), (content
) => {
59 content
.innerHTML
= emojify(content
.innerHTML
);
62 [].forEach
.call(document
.querySelectorAll('time.formatted'), (content
) => {
63 const datetime
= new Date(content
.getAttribute('datetime'));
64 const formattedDate
= dateTimeFormat
.format(datetime
);
66 content
.title
= formattedDate
;
67 content
.textContent
= formattedDate
;
70 [].forEach
.call(document
.querySelectorAll('time.time-ago'), (content
) => {
71 const datetime
= new Date(content
.getAttribute('datetime'));
72 const now
= new Date();
74 content
.title
= dateTimeFormat
.format(datetime
);
75 content
.textContent
= timeAgoString({
76 formatMessage: ({ id
, defaultMessage
}, values
) => (new IntlMessageFormat(messages
[id
] || defaultMessage
, locale
)).format(values
),
77 formatDate: (date
, options
) => (new Intl
.DateTimeFormat(locale
, options
)).format(date
),
78 }, datetime
, now
, now
.getFullYear());
81 const reactComponents
= document
.querySelectorAll('[data-component]');
83 if (reactComponents
.length
> 0) {
84 import(/* webpackChunkName: "containers/media_container" */ '../mastodon/containers/media_container')
85 .then(({ default: MediaContainer
}) => {
86 const content
= document
.createElement('div');
88 ReactDOM
.render(<MediaContainer locale
={locale
} components
={reactComponents
} />, content
);
89 document
.body
.appendChild(content
);
90 scrollToDetailedStatus();
94 scrollToDetailedStatus();
97 scrollToDetailedStatus();
100 const parallaxComponents
= document
.querySelectorAll('.parallax');
102 if (parallaxComponents
.length
> 0 ) {
103 new Rellax('.parallax', { speed: -1 });
107 delegate(document
, '.webapp-btn', 'click', ({ target
, button
}) => {
111 window
.location
.href
= target
.href
;
115 delegate(document
, '.status__content__spoiler-link', 'click', ({ target
}) => {
116 const contentEl
= target
.parentNode
.parentNode
.querySelector('.e-content');
118 if (contentEl
.style
.display
=== 'block') {
119 contentEl
.style
.display
= 'none';
120 target
.parentNode
.style
.marginBottom
= 0;
122 contentEl
.style
.display
= 'block';
123 target
.parentNode
.style
.marginBottom
= null;
129 delegate(document
, '.modal-button', 'click', e
=> {
134 if (e
.target
.nodeName
!== 'A') {
135 href
= e
.target
.parentNode
.href
;
137 href
= e
.target
.href
;
140 window
.open(href
, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes');
143 delegate(document
, '#account_display_name', 'input', ({ target
}) => {
144 const name
= document
.querySelector('.card .display-name strong');
147 name
.innerHTML
= emojify(escapeTextContentForBrowser(target
.value
));
149 name
.textContent
= document
.querySelector('#default_account_display_name').textContent
;
154 delegate(document
, '#account_avatar', 'change', ({ target
}) => {
155 const avatar
= document
.querySelector('.card .avatar img');
156 const [file
] = target
.files
|| [];
157 const url
= file
? URL
.createObjectURL(file
) : avatar
.dataset
.originalSrc
;
162 delegate(document
, '#account_header', 'change', ({ target
}) => {
163 const header
= document
.querySelector('.card .card__img img');
164 const [file
] = target
.files
|| [];
165 const url
= file
? URL
.createObjectURL(file
) : header
.dataset
.originalSrc
;
170 delegate(document
, '#account_locked', 'change', ({ target
}) => {
171 const lock
= document
.querySelector('.card .display-name i');
173 if (target
.checked
) {
174 lock
.style
.display
= 'inline';
176 lock
.style
.display
= 'none';
180 delegate(document
, '.input-copy input', 'click', ({ target
}) => {
184 delegate(document
, '.input-copy button', 'click', ({ target
}) => {
185 const input
= target
.parentNode
.querySelector('.input-copy__wrapper input');
191 if (document
.execCommand('copy')) {
193 target
.parentNode
.classList
.add('copied');
196 target
.parentNode
.classList
.remove('copied');
205 loadPolyfills().then(main
).catch(error
=> {
206 console
.error(error
);