aboutsummaryrefslogtreecommitdiff
path: root/juick-server/src/main/assets
diff options
context:
space:
mode:
authorGravatar Vitaly Takmazov2018-11-08 21:38:27 +0300
committerGravatar Vitaly Takmazov2018-11-08 21:38:27 +0300
commit7aaa3f9a29c280f01c677c918932620be45cdbd7 (patch)
tree39947b2c889afd08f9c73ba54fab91159d2af258 /juick-server/src/main/assets
parent3ea9770d0d43fbe45449ac4531ec4b0a374d98ea (diff)
Merge everything into single Spring Boot application
Diffstat (limited to 'juick-server/src/main/assets')
-rw-r--r--juick-server/src/main/assets/embed.js334
-rw-r--r--juick-server/src/main/assets/logo.pngbin2447 -> 0 bytes
-rw-r--r--juick-server/src/main/assets/logo@2x.pngbin4822 -> 0 bytes
-rw-r--r--juick-server/src/main/assets/scripts.js935
-rw-r--r--juick-server/src/main/assets/style.css956
5 files changed, 0 insertions, 2225 deletions
diff --git a/juick-server/src/main/assets/embed.js b/juick-server/src/main/assets/embed.js
deleted file mode 100644
index d4cbab8e..00000000
--- a/juick-server/src/main/assets/embed.js
+++ /dev/null
@@ -1,334 +0,0 @@
-
-function insertAfter(newNode, referenceNode) {
- referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
-}
-
-function setContent(containerNode, ...newNodes) {
- removeAllFrom(containerNode);
- newNodes.forEach(n => containerNode.appendChild(n));
- return containerNode;
-}
-
-function removeAllFrom(fromNode) {
- for (let c; c = fromNode.lastChild; ) { fromNode.removeChild(c); }
-}
-
-function htmlEscape(html) {
- let textarea = document.createElement('textarea');
- textarea.textContent = html;
- return textarea.innerHTML;
-}
-
-// rules :: [{pr: number, re: RegExp, with: string}]
-// rules :: [{pr: number, re: RegExp, with: Function}]
-// rules :: [{pr: number, re: RegExp, brackets: true, with: [string, string]}]
-// rules :: [{pr: number, re: RegExp, brackets: true, with: [string, string, Function]}]
-function formatText(txt, rules) {
- let idCounter = 0;
- function nextId() { return idCounter++; }
- function ft(txt, rules) {
- let matches = rules.map(r => { r.re.lastIndex = 0; return [r, r.re.exec(txt)]; })
- .filter(([,m]) => m !== null)
- .sort(([r1,m1],[r2,m2]) => (r1.pr - r2.pr) || (m1.index - m2.index));
- if (matches && matches.length > 0) {
- let [rule, match] = matches[0];
- let subsequentRules = rules.filter(r => r.pr >= rule.pr);
- let idStr = `<>(${nextId()})<>`;
- let outerStr = txt.substring(0, match.index) + idStr + txt.substring(rule.re.lastIndex);
- let innerStr = (rule.brackets)
- ? (() => { let [l ,r ,f] = rule.with; return l + ft((f ? f(match[1]) : match[1]), subsequentRules) + r; })()
- : match[0].replace(rule.re, rule.with);
- return ft(outerStr, subsequentRules).replace(idStr, innerStr);
- }
- return txt;
- }
- return ft(htmlEscape(txt), rules); // idStr above relies on the fact the text is escaped
-}
-
-function fixWwwLink(url) {
- return url.replace(/^(?!([a-z]+:)?\/\/)/i, '//');
-}
-
-function makeNewNode(embedType, aNode, reResult) {
- const withClasses = el => {
- if (embedType.className) {
- el.classList.add(...embedType.className.split(' '));
- }
- return el;
- };
- return embedType.makeNode(aNode, reResult, withClasses(document.createElement('div')));
-}
-
-function makeIframe(src, w, h, scrolling='no') {
- let iframe = document.createElement('iframe');
- iframe.style.width = w;
- iframe.style.height = h;
- iframe.frameBorder = 0;
- iframe.scrolling = scrolling;
- iframe.setAttribute('allowFullScreen', '');
- iframe.src = src;
- iframe.innerHTML = 'Cannot show iframes.';
- return iframe;
-}
-
-function makeResizableToRatio(element, ratio) {
- element.dataset['ratio'] = ratio;
- makeResizable(element, w => w * element.dataset['ratio']);
-}
-
-// calcHeight :: Number -> Number -- calculate element height for a given width
-function makeResizable(element, calcHeight) {
- const setHeight = el => {
- if (document.body.contains(el) && (el.offsetWidth > 0)) {
- el.style.height = (calcHeight(el.offsetWidth)).toFixed(2) + 'px';
- }
- };
- window.addEventListener('resize', () => setHeight(element));
- setHeight(element);
-}
-
-function extractDomain(url) {
- const domainRe = /^(?:https?:\/\/)?(?:[^@\/\n]+@)?(?:www\.)?([^:\/\n]+)/i;
- return domainRe.exec(url)[1];
-}
-
-function urlReplace(match, p1, p2, p3) {
- let isBrackets = (p1 !== undefined);
- return (isBrackets)
- ? `<a href="${fixWwwLink(p2 || p3)}">${p1}</a>`
- : `<a href="${fixWwwLink(match)}">${extractDomain(match)}</a>`;
-}
-
-function urlReplaceInCode(match, p1, p2, p3) {
- let isBrackets = (p1 !== undefined);
- return (isBrackets)
- ? `<a href="${fixWwwLink(p2 || p3)}">${match}</a>`
- : `<a href="${fixWwwLink(match)}">${match}</a>`;
-}
-
-function messageReplyReplace(messageId) {
- return function(match, mid, rid) {
- let replyPart = (rid && rid != '0') ? '#' + rid : '';
- return `<a href="/${mid || messageId}${replyPart}">${match}</a>`;
- };
-}
-
-/**
- * Given "txt" message in unescaped plaintext with Juick markup, this function
- * returns escaped formatted HTML string.
- *
- * @param {string} txt
- * @param {string} messageId - current message id
- * @param {boolean} isCode
- * @returns {string}
- */
-function juickFormat(txt, messageId, isCode) {
- const urlRe = /(?:\[([^\]\[]+)\](?:\[([^\]]+)\]|\(((?:[a-z]+:\/\/|www\.|ftp\.)(?:\([-\w+*&@#/%=~|$?!:;,.]*\)|[-\w+*&@#/%=~|$?!:;,.])*(?:\([-\w+*&@#/%=~|$?!:;,.]*\)|[\w+*&@#/%=~|$]))\))|\b(?:[a-z]+:\/\/|www\.|ftp\.)(?:\([-\w+*&@#/%=~|$?!:;,.]*\)|[-\w+*&@#/%=~|$?!:;,.])*(?:\([-\w+*&@#/%=~|$?!:;,.]*\)|[\w+*&@#/%=~|$]))/gi;
- const bqReplace = m => m.replace(/^(?:>|&gt;)\s?/gmi, '');
- return (isCode)
- ? formatText(txt, [
- { pr: 1, re: urlRe, with: urlReplaceInCode },
- { pr: 1, re: /\B(?:#(\d+))?(?:\/(\d+))?\b/g, with: messageReplyReplace(messageId) },
- { pr: 1, re: /\B@([\w-]+)\b/gi, with: '<a href="/$1">@$1</a>' },
- ])
- : formatText(txt, [
- { pr: 0, re: /((?:^(?:>|&gt;)\s?[\s\S]+?$\n?)+)/gmi, brackets: true, with: ['<q>', '</q>', bqReplace] },
- { pr: 1, re: urlRe, with: urlReplace },
- { pr: 1, re: /\B(?:#(\d+))?(?:\/(\d+))?\b/g, with: messageReplyReplace(messageId) },
- { pr: 1, re: /\B@([\w-]+)\b/gi, with: '<a href="/$1">@$1</a>' },
- { pr: 2, re: /\B\*([^\n]+?)\*((?=\s)|(?=$)|(?=[!\"#$%&'*+,\-./:;<=>?@[\]^_`{|}~()]+))/g, brackets: true, with: ['<b>', '</b>'] },
- { pr: 2, re: /\B\/([^\n]+?)\/((?=\s)|(?=$)|(?=[!\"#$%&'*+,\-./:;<=>?@[\]^_`{|}~()]+))/g, brackets: true, with: ['<i>', '</i>'] },
- { pr: 2, re: /\b\_([^\n]+?)\_((?=\s)|(?=$)|(?=[!\"#$%&'*+,\-./:;<=>?@[\]^_`{|}~()]+))/g, brackets: true, with: ['<span class="u">', '</span>'] },
- { pr: 3, re: /\n/g, with: '<br/>' },
- ]);
-}
-
-function getEmbeddableLinkTypes() {
- return [
- {
- name: 'Jpeg and png images',
- id: 'embed_jpeg_and_png_images',
- className: 'picture compact',
- ctsDefault: false,
- re: /\.(jpe?g|png|svg)(:[a-zA-Z]+)?(?:\?[\w&;\?=]*)?$/i,
- makeNode: function(aNode, reResult, div) {
- div.innerHTML = `<a href="${aNode.href}"><img src="${aNode.href}"></a>`;
- return div;
- }
- },
- {
- name: 'Gif images',
- id: 'embed_gif_images',
- className: 'picture compact',
- ctsDefault: true,
- re: /\.gif(:[a-zA-Z]+)?(?:\?[\w&;\?=]*)?$/i,
- makeNode: function(aNode, reResult, div) {
- div.innerHTML = `<a href="${aNode.href}"><img src="${aNode.href}"></a>`;
- return div;
- }
- },
- {
- name: 'Video (webm, mp4, ogv)',
- id: 'embed_webm_and_mp4_videos',
- className: 'video compact',
- ctsDefault: false,
- re: /\.(webm|mp4|m4v|ogv)(?:\?[\w&;\?=]*)?$/i,
- makeNode: function(aNode, reResult, div) {
- div.innerHTML = `<video src="${aNode.href}" title="${aNode.href}" controls></video>`;
- return div;
- }
- },
- {
- name: 'Audio (mp3, ogg, weba, opus, m4a, oga, wav)',
- id: 'embed_sound_files',
- className: 'audio singleColumn',
- ctsDefault: false,
- re: /\.(mp3|ogg|weba|opus|m4a|oga|wav)(?:\?[\w&;\?=]*)?$/i,
- makeNode: function(aNode, reResult, div) {
- div.innerHTML = `<audio src="${aNode.href}" title="${aNode.href}" controls></audio>`;
- return div;
- }
- },
- {
- name: 'YouTube videos (and playlists)',
- id: 'embed_youtube_videos',
- className: 'youtube resizableV singleColumn',
- ctsDefault: false,
- re: /^(?:https?:)?\/\/(?:www\.|m\.|gaming\.)?(?:youtu(?:(?:\.be\/|be\.com\/(?:v|embed)\/)([-\w]+)|be\.com\/watch)((?:(?:\?|&(?:amp;)?)(?:\w+=[-\.\w]*[-\w]))*)|youtube\.com\/playlist\?list=([-\w]*)(&(amp;)?[-\w\?=]*)?)/i,
- makeNode: function(aNode, reResult, div) {
- let [url, v, args, plist] = reResult;
- let iframeUrl;
- if (plist) {
- iframeUrl = '//www.youtube-nocookie.com/embed/videoseries?list=' + plist;
- } else {
- let pp = {}; args.replace(/^\?/, '')
- .split('&')
- .map(s => s.split('='))
- .forEach(z => pp[z[0]] = z[1]);
- let embedArgs = { rel: '0' };
- if (pp.t) {
- const tre = /^(?:(\d+)|(?:(\d+)h)?(?:(\d+)m)?(\d+)s|(?:(\d+)h)?(\d+)m|(\d+)h)$/i;
- let [, t, h, m, s, h1, m1, h2] = tre.exec(pp.t);
- embedArgs['start'] = (+t) || ((+(h || h1 || h2 || 0))*60*60 + (+(m || m1 || 0))*60 + (+(s || 0)));
- }
- if (pp.list) {
- embedArgs['list'] = pp.list;
- }
- v = v || pp.v;
- let argsStr = Object.keys(embedArgs)
- .map(k => `${k}=${embedArgs[k]}`)
- .join('&');
- iframeUrl = `//www.youtube-nocookie.com/embed/${v}?${argsStr}`;
- }
- let iframe = makeIframe(iframeUrl, '100%', '360px');
- iframe.onload = () => makeResizableToRatio(iframe, 9.0 / 16.0);
- return setContent(div, iframe);
- }
- },
- {
- name: 'Vimeo videos',
- id: 'embed_vimeo_videos',
- className: 'vimeo resizableV',
- ctsDefault: false,
- re: /^(?:https?:)?\/\/(?:www\.)?(?:player\.)?vimeo\.com\/(?:video\/|album\/[\d]+\/video\/)?([\d]+)/i,
- makeNode: function(aNode, reResult, div) {
- let iframe = makeIframe('//player.vimeo.com/video/' + reResult[1], '100%', '360px');
- iframe.onload = () => makeResizableToRatio(iframe, 9.0 / 16.0);
- return setContent(div, iframe);
- }
- }
- ];
-}
-
-function embedLink(aNode, linkTypes, container, afterNode) {
- let anyEmbed = false;
- let linkId = (aNode.href.replace(/^https?:/i, '').replace(/\'/gi,''));
- let sameEmbed = container.querySelector(`*[data-linkid='${linkId}']`); // do not embed the same thing twice
- if (sameEmbed === null) {
- anyEmbed = [].some.call(linkTypes, function(linkType) {
- let reResult = linkType.re.exec(aNode.href);
- if (reResult) {
- if (linkType.match && (linkType.match(aNode, reResult) === false)) { return false; }
- let newNode = makeNewNode(linkType, aNode, reResult);
- if (!newNode) { return false; }
- newNode.setAttribute('data-linkid', linkId);
- if (afterNode) {
- insertAfter(newNode, afterNode);
- } else {
- container.appendChild(newNode);
- }
- aNode.classList.add('embedLink');
- return true;
- }
- });
- }
- return anyEmbed;
-}
-
-function embedLinks(aNodes, container) {
- let anyEmbed = false;
- let embeddableLinkTypes = getEmbeddableLinkTypes();
- Array.from(aNodes).forEach(aNode => {
- let isEmbedded = embedLink(aNode, embeddableLinkTypes, container);
- anyEmbed = anyEmbed || isEmbedded;
- });
- return anyEmbed;
-}
-
-/**
- * Embed all the links inside element "x" that match to "allLinksSelector".
- * All the embedded media is placed inside "div.embedContainer".
- * "div.embedContainer" is inserted before an element matched by "beforeNodeSelector"
- * if not present. Existing container is used otherwise.
- *
- * @param {Element} x
- * @param {string} beforeNodeSelector
- * @param {string} allLinksSelector
- */
-export function embedLinksToX(x, beforeNodeSelector, allLinksSelector) {
- let isCtsPost = false;
- let allLinks = x.querySelectorAll(allLinksSelector);
-
- let existingContainer = x.querySelector('div.embedContainer');
- if (existingContainer) {
- embedLinks(allLinks, existingContainer);
- } else {
- let embedContainer = document.createElement('div');
- embedContainer.className = 'embedContainer';
-
- let anyEmbed = embedLinks(allLinks, embedContainer);
- if (anyEmbed) {
- let beforeNode = x.querySelector(beforeNodeSelector);
- x.insertBefore(embedContainer, beforeNode);
- }
- }
-}
-
-function embedLinksToArticles() {
- let beforeNodeSelector = 'nav.l';
- let allLinksSelector = 'p:not(.ir) a, pre a';
- Array.from(document.querySelectorAll('#content article')).forEach(article => {
- embedLinksToX(article, beforeNodeSelector, allLinksSelector);
- });
-}
-
-function embedLinksToPost() {
- let beforeNodeSelector = '.msg-txt + *';
- let allLinksSelector = '.msg-txt a';
- Array.from(document.querySelectorAll('#content .msg-cont')).forEach(msg => {
- embedLinksToX(msg, beforeNodeSelector, allLinksSelector);
- });
-}
-
-/**
- * Embed all the links in all messages/replies on the page.
- */
-export function embedAll() {
- if (document.querySelector('#content article[data-mid]')) {
- embedLinksToArticles();
- } else {
- embedLinksToPost();
- }
-}
-
-export const format = juickFormat;
diff --git a/juick-server/src/main/assets/logo.png b/juick-server/src/main/assets/logo.png
deleted file mode 100644
index 4e0f6d56..00000000
--- a/juick-server/src/main/assets/logo.png
+++ /dev/null
Binary files differ
diff --git a/juick-server/src/main/assets/logo@2x.png b/juick-server/src/main/assets/logo@2x.png
deleted file mode 100644
index 6febeaf9..00000000
--- a/juick-server/src/main/assets/logo@2x.png
+++ /dev/null
Binary files differ
diff --git a/juick-server/src/main/assets/scripts.js b/juick-server/src/main/assets/scripts.js
deleted file mode 100644
index 9ee0639e..00000000
--- a/juick-server/src/main/assets/scripts.js
+++ /dev/null
@@ -1,935 +0,0 @@
-require('element-closest');
-require('classlist.js');
-require('url-polyfill');
-require('formdata-polyfill');
-import { embedLinksToX, embedAll, format } from './embed';
-
-if (!('remove' in Element.prototype)) { // Firefox <23
- Element.prototype.remove = function() {
- if (this.parentNode) {
- this.parentNode.removeChild(this);
- }
- };
-}
-
-NodeList.prototype.forEach = Array.prototype.forEach;
-HTMLCollection.prototype.forEach = Array.prototype.forEach;
-
-NodeList.prototype.filter = Array.prototype.filter;
-HTMLCollection.prototype.filter = Array.prototype.filter;
-
-Element.prototype.selectText = function() {
- let d = document;
- if (d.body.createTextRange) {
- let range = d.body.createTextRange();
- range.moveToElementText(this);
- range.select();
- } else if (window.getSelection) {
- let selection = window.getSelection();
- let rangeSel = d.createRange();
- rangeSel.selectNodeContents(this);
- selection.removeAllRanges();
- selection.addRange(rangeSel);
- }
-};
-
-function autosize(el) {
- let offset = (!window.opera)
- ? (el.offsetHeight - el.clientHeight)
- : (el.offsetHeight + parseInt(window.getComputedStyle(el, null).getPropertyValue('border-top-width')));
-
- let resize = function(el) {
- el.style.height = 'auto';
- el.style.height = (el.scrollHeight + offset) + 'px';
- };
-
- if (el.addEventListener) {
- el.addEventListener('input', () => resize(el));
- } else if (el.attachEvent) {
- el.attachEvent('onkeyup', () => resize(el));
- }
-}
-
-function evilIcon(name) {
- return `<div class="icon icon--${name}"><svg class="icon__cnt"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#${name}-icon"></use></svg></div>`;
-}
-
-/* eslint-disable only-ascii/only-ascii */
-const translations = {
- 'en': {
- 'message.inReplyTo': 'in reply to',
- 'message.reply': 'Reply',
- 'message.likeThisMessage?': 'Recommend this message?',
- 'postForm.pleaseInputMessageText': 'Please input message text',
- 'postForm.upload': 'Upload',
- 'postForm.newMessage': 'New message...',
- 'postForm.imageLink': 'Link to image',
- 'postForm.imageFormats': 'JPG/PNG, up to 10 MB',
- 'postForm.or': 'or',
- 'postForm.tags': 'Tags (space separated)',
- 'postForm.submit': 'Send',
- 'comment.writeComment': 'Write a comment...',
- 'shareDialog.linkToMessage': 'Link to message',
- 'shareDialog.messageNumber': 'Message number',
- 'shareDialog.share': 'Share',
- 'loginDialog.pleaseIntroduceYourself': 'Please introduce yourself',
- 'loginDialog.registeredAlready': 'Registered already?',
- 'loginDialog.username': 'Username',
- 'loginDialog.password': 'Password',
- 'loginDialog.facebook': 'Login with Facebook',
- 'loginDialog.vk': 'Login with VK',
- 'loginDialog.email': 'Registration',
- 'error.error': 'Error'
- },
- 'ru': {
- 'message.inReplyTo': 'в ответ на',
- 'message.reply': 'Ответить',
- 'message.likeThisMessage?': 'Рекомендовать это сообщение?',
- 'postForm.pleaseInputMessageText': 'Пожалуйста, введите текст сообщения',
- 'postForm.upload': 'загрузить',
- 'postForm.newMessage': 'Новое сообщение...',
- 'postForm.imageLink': 'Ссылка на изображение',
- 'postForm.imageFormats': 'JPG/PNG, до 10Мб',
- 'postForm.or': 'или',
- 'postForm.tags': 'Теги (через пробел)',
- 'postForm.submit': 'Отправить',
- 'comment.writeComment': 'Написать комментарий...',
- 'shareDialog.linkToMessage': 'Ссылка на сообщение',
- 'shareDialog.messageNumber': 'Номер сообщения',
- 'shareDialog.share': 'Поделиться',
- 'loginDialog.pleaseIntroduceYourself': 'Пожалуйста, представьтесь',
- 'loginDialog.registeredAlready': 'Уже зарегистрированы?',
- 'loginDialog.username': 'Имя пользователя',
- 'loginDialog.password': 'Пароль',
- 'loginDialog.facebook': 'Войти через Facebook',
- 'loginDialog.vk': 'Войти через ВКонтакте',
- 'loginDialog.email': 'Регистрация',
- 'error.error': 'Ошибка'
- }
-};
-/* eslint-enable only-ascii/only-ascii */
-
-function getLang() {
- return (window.navigator.languages && window.navigator.languages[0])
- || window.navigator.userLanguage
- || window.navigator.language;
-}
-function i18n(key, lang = undefined) {
- const fallbackLang = 'ru';
- lang = lang || getLang().split('-')[0];
- return (translations[lang] && translations[lang][key])
- || translations[fallbackLang][key]
- || key;
-}
-
-var es, pageTitle;
-
-function initES() {
- if (!('EventSource' in window)) {
- return;
- }
- let url = '/api/events';
- let hash = document.getElementById('body').getAttribute('data-hash');
- if (hash) {
- url += '?hash=' + hash;
- }
-
- es = new EventSource(url);
- es.onopen = function() {
- console.log('online');
- if (!document.querySelector('#wsthread')) {
- var d = document.createElement('div');
- d.id = 'wsthread';
- d.addEventListener('click', nextReply);
- document.querySelector('body').appendChild(d);
- pageTitle = document.title;
- }
- };
- es.addEventListener('msg', msg => {
- try {
- var jsonMsg = JSON.parse(msg.data);
- console.log('data: ' + msg.data);
- if (jsonMsg.service) {
- return;
- }
- wsIncomingReply(jsonMsg);
- } catch (err) {
- console.log(err);
- }
- });
-}
-
-function wsIncomingReply(msg) {
- let content = document.getElementById('content');
- if (!content) { return; }
- let pageMID = content.getAttribute('data-mid');
- if (!pageMID || pageMID != msg.mid) { return; }
- let msgNum = '/' + msg.rid;
- if (msg.replyto > 0) {
- msgNum += ` ${i18n('message.inReplyTo')} <a href="#${msg.replyto}">/${msg.replyto}</a>`;
- }
- let photoDiv = (msg.attach == null) ? '' : `
- <div class="msg-media"><a href="//i.juick.com/p/${msg.mid}-${msg.rid}.${msg.attach}">
- <img src="//i.juick.com/photos-512/${msg.mid}-${msg.rid}.${msg.attach}"/></a>
- </div>`;
- let msgContHtml = `
- <div class="msg-cont">
- <div class="msg-header">
- <a href="/${msg.user.uname}/">${msg.user.uname}</a>:
- <div class="msg-avatar">
- <a href="/${msg.user.uname}/"><img src="//i.juick.com/a/${msg.user.uid}.png" alt="${msg.user.uname}"/></a>
- </div>
- <div class="msg-ts">
- <a href="/m/${msg.mid}#${msg.rid}" title="${msg.timestamp}GMT">${msg.timestamp}</a>
- </div>
- </div>
- <div class="msg-txt">${format(msg.body, msg.mid, false)}</div>${photoDiv}
- <div class="msg-links">${msgNum} &middot; <a class="msg-reply-link" href="#">${i18n('message.reply')}</a></div>
- <div class="msg-comment-target msg-comment-hidden"></div>
- </div>`;
-
- let li = document.createElement('li');
- li.setAttribute('class', 'msg reply-new');
- li.setAttribute('id', msg.rid);
- li.innerHTML = msgContHtml;
- li.addEventListener('click', newReply);
- li.addEventListener('mouseover', newReply);
- li.querySelector('a.msg-reply-link').addEventListener('click', function(e) {
- showCommentForm(msg.mid, msg.rid);
- e.preventDefault();
- });
-
- embedLinksToX(li.querySelector('.msg-cont'), '.msg-links', '.msg-txt a');
-
- document.getElementById('replies').appendChild(li);
-
- updateRepliesCounter();
-}
-
-function newReply(e) {
- var li = e.target;
- li.classList.remove('reply-new');
- li.removeEventListener('click', e);
- li.removeEventListener('mouseover', e);
- updateRepliesCounter();
-}
-
-function nextReply() {
- var li = document.querySelector('#replies>li.reply-new');
- if (li) {
- li.classList.remove('reply-new');
- li.removeEventListener('click', this);
- li.children[0].scrollIntoView();
- updateRepliesCounter();
- }
-}
-
-function updateRepliesCounter() {
- var replies = document.querySelectorAll('#replies>li.reply-new').length;
- var wsthread = document.getElementById('wsthread');
- if (replies) {
- wsthread.textContent = replies;
- wsthread.style.display = 'block';
- document.title = '[' + replies + '] ' + pageTitle;
- } else {
- wsthread.style.display = 'none';
- document.title = pageTitle;
- }
-}
-
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-
-function postformListener(formEl, ev) {
- if (ev.ctrlKey && (ev.keyCode == 10 || ev.keyCode == 13)) {
- let form = formEl.closest('form');
- if (!form.onsubmit || form.onsubmit()) {
- form.querySelector('input[type="submit"]').click();
- }
- }
-}
-function closeDialogListener(ev) {
- ev = ev || window.event;
- if (ev.keyCode == 27) {
- closeDialog();
- }
-}
-
-function newMessage(evt) {
- document.querySelectorAll('#newmessage .dialogtxt').forEach(t => {
- t.remove();
- });
- if (document.querySelector('#newmessage textarea').value.length == 0
- && document.querySelector('#newmessage .img').value.length == 0
- && !document.querySelector('#newmessage input[type="file"]')) {
- document.querySelector('#newmessage').insertAdjacentHTML('afterbegin', `<p class="dialogtxt">${i18n('postForm.pleaseInputMessageText')}</p>`);
- evt.preventDefault();
- }
-}
-
-function handleErrors(response) {
- if (!response.ok) {
- throw Error(response.statusText);
- }
- return response;
-}
-
-function showCommentForm(mid, rid) {
- let reply = document.getElementById(rid);
- let formTarget = reply.querySelector('div.msg-cont .msg-comment-target');
- if (formTarget) {
- let formHtml = `
- <form>
- <input type="hidden" name="mid" value="${mid}">
- <input type="hidden" name="rid" value="${rid}">
- <div class="msg-comment">
- <div class="ta-wrapper">
- <textarea name="body" rows="1" class="reply" placeholder="${i18n('comment.writeComment')}"></textarea>
- <div class="attach-photo">${evilIcon('ei-camera')}</div>
- </div>
- <input type="submit" value="OK">
- </div>
- </form>`;
- formTarget.insertAdjacentHTML('afterend', formHtml);
- formTarget.remove();
-
- let form = reply.querySelector('form');
- let submitButton = form.querySelector('input[type="submit"]');
-
- let attachButton = form.querySelector('.msg-comment .attach-photo');
- attachButton.addEventListener('click', e => attachCommentPhoto(e.target));
-
- let textarea = form.querySelector('.msg-comment textarea');
- textarea.addEventListener('keypress', e => postformListener(e.target, e));
- autosize(textarea);
-
- let validateMessage = () => {
- let len = textarea.value.length;
- if (len > 4096) { return 'Message is too long'; }
- return '';
- };
- form.addEventListener('submit', e => {
- let validationResult = validateMessage();
- if (validationResult) {
- e.preventDefault();
- alert(validationResult);
- return false;
- }
- submitButton.disabled = true;
- let formData = new FormData(form);
- fetch('/api/comment' + '?hash=' + document.getElementById('body').getAttribute('data-hash'), {
- method: 'POST',
- body: formData,
- credentials: 'omit'
- }).then(handleErrors)
- .then(response => {
- if (response.ok) {
- response.json().then(result => {
- if (result.newMessage) {
- window.location.href = new URL(`${mid}#${result.newMessage.rid}`, window.location.href);
- } else {
- alert(result.text);
- }
- window.location.reload(true);
- });
- }
- }).catch(error => {
- alert(error.message);
- });
- e.preventDefault();
- });
- }
- reply.querySelector('.msg-comment textarea').focus();
-}
-
-function attachInput() {
- let inp = document.createElement('input');
- inp.setAttribute('type', 'file');
- inp.setAttribute('name', 'attach');
- inp.setAttribute('accept', 'image/jpeg,image/png');
- inp.style.visibility = 'hidden';
- return inp;
-}
-
-function attachCommentPhoto(div) {
- let input = div.querySelector('input');
- if (input) {
- input.remove();
- div.classList.remove('attach-photo-active');
- } else {
- let newInput = attachInput();
- newInput.addEventListener('change', function() {
- div.classList.add('attach-photo-active');
- });
- newInput.click();
- div.appendChild(newInput);
- }
-}
-
-function attachMessagePhoto(div) {
- var f = div.closest('form'),
- finput = f.querySelector('input[type="file"]');
- if (!finput) {
- var inp = attachInput();
- inp.style.float = 'left';
- inp.style.width = 0;
- inp.style.height = 0;
- inp.addEventListener('change', function() {
- div.textContent = i18n('postForm.upload') + ' (✓)';
- });
- f.appendChild(inp);
- inp.click();
- } else {
- finput.remove();
- div.textContent = i18n('postForm.upload');
- }
-}
-
-function showMessageLinksDialog(mid, rid) {
- let hlink = window.location.protocol + '//juick.com/' + mid;
- let mlink = '#' + mid;
- if (rid > 0) {
- hlink += '#' + rid;
- mlink += '/' + rid;
- }
- let hlinkenc = encodeURIComponent(hlink);
- let html = `
- <div class="dialogshare">
- ${i18n('shareDialog.linkToMessage')}: <div onclick="this.selectText()" class="dialogl">${hlink}</div>
- ${i18n('shareDialog.messageNumber')}: <div onclick="this.selectText()" class="dialogl">${mlink}</div>
- ${i18n('shareDialog.share')}:
- <ul>
- <li><a href="https://www.facebook.com/sharer/sharer.php?u=${hlinkenc}" onclick="return openSocialWindow(this)">${evilIcon('ei-sc-facebook')}</a></li>
- <li><a href="https://twitter.com/intent/tweet?url=${hlinkenc}" onclick="return openSocialWindow(this)">${evilIcon('ei-sc-twitter')}</a></li>
- <li><a href="https://vk.com/share.php?url=${hlinkenc}" onclick="return openSocialWindow(this)">${evilIcon('ei-sc-vk')}</a></li>
- </ul>
- </div>`;
-
- openDialog(html);
-}
-
-function showPhotoDialog(fname) {
- let width = window.innerWidth;
- let height = window.innerHeight;
- let minDimension = (width < height) ? width : height;
- if (minDimension < 640) {
- return true; // no dialog, open the link
- } else if (minDimension < 1280) {
- openDialog(`<a href="//i.juick.com/p/${fname}"><img src="//i.juick.com/photos-1024/${fname}"/></a>`, true);
- return false;
- } else {
- openDialog(`<a href="//i.juick.com/p/${fname}"><img src="//i.juick.com/p/${fname}"/></a>`, true);
- return false;
- }
-}
-
-function openPostDialog() {
- let newmessageTemplate = `
- <form id="newmessage" action="/post" method="post" enctype="multipart/form-data">
- <textarea name="body" placeholder="${i18n('postForm.newMessage')}"></textarea>
- <div>
- <input class="img" name="img" placeholder="${i18n('postForm.imageLink')} (${i18n('postForm.imageFormats')})"/>
- ${i18n('postForm.or')} <a href="#">${i18n('postForm.upload')}</a><br/>
- <input id="tags_input" class="tags" name="tags" placeholder="${i18n('postForm.tags')}"/><br/>
- <input type="submit" class="subm" value="${i18n('postForm.submit')}"/>
- </div>
- </form>
- `;
- return openDialog(newmessageTemplate);
-}
-
-function openDialog(html, image) {
- var dialogHtml = `
- <div id="dialogt">
- <div id="dialogb"></div>
- <div id="dialogw">
- <div id="dialog_header">
- <div id="dialogc">${evilIcon('ei-close')}</div>
- </div>
- ${html}
- </div>
- </div>`;
- let body = document.querySelector('body');
- body.classList.add('dialog-opened');
- body.insertAdjacentHTML('afterbegin', dialogHtml);
- if (image) {
- let header = document.querySelector('#dialog_header');
- header.classList.add('header_image');
- }
- document.addEventListener('keydown', closeDialogListener);
- document.querySelector('#dialogb').addEventListener('click', closeDialog);
- document.querySelector('#dialogc').addEventListener('click', closeDialog);
-}
-
-function closeDialog() {
- let draft = document.querySelector('#newmessage textarea');
- if (draft) {
- window.draft = draft.value;
- }
- document.querySelector('body').classList.remove('dialog-opened');
- document.querySelector('#dialogb').remove();
- document.querySelector('#dialogt').remove();
-}
-
-function openSocialWindow(a) {
- var w = window.open(a.href, 'juickshare', 'width=640,height=400');
- if (window.focus) { w.focus(); }
- return false;
-}
-
-function checkUsername() {
- var uname = document.querySelector('#username').textContent,
- style = document.querySelector('#username').style;
- fetch('/api/users?uname=' + uname)
- .then(handleErrors)
- .then(function() {
- style.background = '#FFCCCC';
- })
- .catch(function() {
- style.background = '#CCFFCC';
- });
-}
-
-/******************************************************************************/
-
-function openDialogLogin() {
- let html = `
- <div class="dialoglogin">
- <p>${i18n('loginDialog.pleaseIntroduceYourself')}:</p>
- <a href="mailto:juick@juick.com?subject=LOGIN" id="signemail">${evilIcon('ei-envelope')}${i18n('loginDialog.email')}</a>
- <a href="/_fblogin" id="signfb">${evilIcon('ei-sc-facebook')}${i18n('loginDialog.facebook')}</a>
- <a href="/_vklogin" id="signvk">${evilIcon('ei-sc-vk')}${i18n('loginDialog.vk')}</a>
- <p>${i18n('loginDialog.registeredAlready')}</p>
- <form action="/login" method="POST">
- <input class="signinput" type="text" name="username" placeholder="${i18n('loginDialog.username')}"/><br/>
- <input class="signinput" type="password" name="password" placeholder="${i18n('loginDialog.password')}"/><br/>
- <input class="signsubmit" type="submit" value="OK"/>
- </form>
- </div>`;
- openDialog(html);
- return false;
-}
-
-/******************************************************************************/
-
-function resultMessage(str) {
- var result = document.createElement('p');
- result.textContent = str;
- return result;
-}
-
-function likeMessage(e, mid) {
- if (confirm(i18n('message.likeThisMessage?'))) {
- fetch('/api/like?mid=' + mid
- + '&hash=' + document.getElementById('body').getAttribute('data-hash'), {
- method: 'POST',
- credentials: 'omit'
- })
- .then(handleErrors)
- .then(function(response) {
- if (response.ok) {
- e.closest('article').appendChild(resultMessage('OK!'));
- }
- })
- .catch(function() {
- e.closest('article').appendChild(resultMessage(i18n('error.error')));
- });
- }
- return false;
-}
-
-function subscribeMessage(e, mid) {
- fetch('/api/subscribe?mid=' + mid
- + '&hash=' + document.getElementById('body').getAttribute('data-hash'), {
- method: 'POST',
- credentials: 'omit'
- })
- .then(handleErrors)
- .then(function(response) {
- if (response.ok) {
- window.location.reload(true);
- } else {
- alert('Something went wrong :(');
- }
- })
- .catch(error => {
- alert(error.message);
- });
- return false;
-}
-
-/******************************************************************************/
-
-function setPopular(e, mid, popular) {
- fetch('/api/messages/set_popular?mid=' + mid
- + '&popular=' + popular
- + '&hash=' + document.getElementById('body').getAttribute('data-hash'), {
- credentials: 'same-origin'
- })
- .then(handleErrors)
- .then(function() {
- e.closest('article').append(resultMessage('OK!'));
- });
- return false;
-}
-
-function setPrivacy(e, mid) {
- fetch('/api/messages/set_privacy?mid=' + mid
- + '&hash=' + document.getElementById('body').getAttribute('data-hash'), {
- credentials: 'same-origin'
- })
- .then(handleErrors)
- .then(function() {
- e.closest('article').append(resultMessage('OK!'));
- });
- return false;
-}
-
-function getTags() {
- fetch('/api/tags?hash=' + document.getElementById('body').getAttribute('data-hash'), {
- credentials: 'omit'
- })
- .then(handleErrors)
- .then(response => {
- return response.json();
- })
- .then(json => {
- let tags = json.map(t => t.tag);
- let input = document.getElementById('tags_input');
- });
- return false;
-}
-
-function addTag(tag) {
- document.forms['postmsg'].body.value = '*' + tag + ' ' + document.forms['postmsg'].body.value;
- return false;
-}
-
-var users = {};
-
-function fetchUserUri(dataUri, callback) {
- if (users[dataUri]) {
- callback(users[dataUri]);
- } else {
- let data = new FormData();
- data.append('uri', dataUri);
- fetch('/u/', {
- method: 'POST',
- body: data
- }).then(handleErrors)
- .then(response => {
- return response.json();
- })
- .then(json => {
- users[dataUri] = json;
- callback(json);
- });
- }
-}
-
-/******************************************************************************/
-
-function ready(fn) {
- if (document.readyState != 'loading') {
- fn();
- } else {
- document.addEventListener('DOMContentLoaded', fn);
- }
-}
-
-ready(function() {
- document.querySelectorAll('textarea').forEach((ta) => {
- autosize(ta);
- });
-
- var insertPMButtons = function(e) {
- e.target.classList.add('narrowpm');
- e.target.parentNode.insertAdjacentHTML('afterend', '<input type="submit" value="OK"/>');
- e.target.removeEventListener('click', insertPMButtons);
- e.preventDefault();
- };
- document.querySelectorAll('textarea.replypm').forEach(function(e) {
- e.addEventListener('click', insertPMButtons);
- e.addEventListener('keypress', function(e) {
- postformListener(e.target, e);
- });
- });
- document.querySelectorAll('#postmsg textarea').forEach(function(e) {
- e.addEventListener('keypress', function(e) {
- postformListener(e.target, e);
- });
- });
-
- var content = document.getElementById('content');
- if (content) {
- var pageMID = content.getAttribute('data-mid');
- if (pageMID > 0) {
- document.querySelectorAll('li.msg').forEach(li => {
- let showReplyFormBtn = li.querySelector('.a-thread-comment');
- if (showReplyFormBtn) {
- showReplyFormBtn.addEventListener('click', function(e) {
- showCommentForm(pageMID, li.id);
- e.preventDefault();
- });
- }
- });
- let opMessage = document.querySelector('.msgthread');
- if (opMessage) {
- let replyTextarea = opMessage.querySelector('textarea.reply');
- if (replyTextarea) {
- replyTextarea.addEventListener('focus', e => showCommentForm(pageMID, 0));
- replyTextarea.addEventListener('keypress', e => postformListener(e.target, e));
- if (!window.location.hash) {
- replyTextarea.focus();
- }
- }
- }
- }
- }
-
- var postmsg = document.getElementById('postmsg');
- if (postmsg) {
- document.querySelectorAll('a').filter(t => t.href.indexOf('?') >= 0).forEach(t => {
- t.addEventListener('click', e => {
- let params = new URLSearchParams(t.href.slice(t.href.indexOf('?') + 1));
- if (params.has('tag')) {
- addTag(params.get('tag'));
- e.preventDefault();
- }
- });
- });
- postmsg.addEventListener('submit', e => {
- let formData = new FormData(postmsg);
- fetch('/api/post' + '?hash=' + document.getElementById('body').getAttribute('data-hash'), {
- method: 'POST',
- body: formData,
- credentials: 'omit'
- }).then(handleErrors)
- .then(response => {
- if (response.ok) {
- response.json().then(result => {
- if (result.newMessage) {
- window.location = new URL(`/m/${result.newMessage.mid}`, window.location.href);
- } else {
- alert(result.text);
- }
- });
- } else {
- alert('Something went wrong :(');
- }
- }).catch(error => {
- alert(error.message);
- });
- e.preventDefault();
- });
- }
- document.querySelectorAll('.pmmsg').forEach(pmmsg => {
- pmmsg.addEventListener('submit', e => {
- let formData = new FormData(pmmsg);
- fetch('/api/pm' + '?hash=' + document.getElementById('body').getAttribute('data-hash'), {
- method: 'POST',
- body: formData,
- credentials: 'omit'
- }).then(handleErrors)
- .then(response => {
- if (response.ok) {
- response.json().then(result => {
- if (result.to) {
- window.location = new URL('/pm/sent', window.location.href);
- } else {
- alert('Something went wrong :(');
- }
- });
- } else {
- alert('Something went wrong :(');
- }
- }).catch(error => {
- alert(error.message);
- });
- e.preventDefault();
- });
- });
-
- document.querySelectorAll('.msg-menu').forEach(function(el) {
- el.addEventListener('click', function(e) {
- var reply = e.target.closest('li');
- var rid = reply ? parseInt(reply.id) : 0;
- var message = e.target.closest('section');
- var mid = message.getAttribute('data-mid') || e.target.closest('article').getAttribute('data-mid');
- showMessageLinksDialog(mid, rid);
- e.preventDefault();
- });
- });
- document.querySelectorAll('.l .a-privacy').forEach(function(e) {
- e.addEventListener('click', function(e) {
- setPrivacy(
- e.target,
- e.target.closest('article').getAttribute('data-mid'));
- e.preventDefault();
- });
- });
- document.querySelectorAll('.ir a[data-fname], .msg-media a[data-fname]').forEach(function(el) {
- el.addEventListener('click', function(e) {
- let fname = e.target.closest('[data-fname]').getAttribute('data-fname');
- if (!showPhotoDialog(fname)) {
- e.preventDefault();
- }
- });
- });
- document.querySelectorAll('.social a').forEach(function(e) {
- e.addEventListener('click', function(e) {
- openSocialWindow(e.target);
- e.preventDefault();
- });
- });
- var username = document.getElementById('username');
- if (username) {
- username.addEventListener('blur', function() {
- checkUsername();
- });
- }
-
- document.querySelectorAll('.l .a-like').forEach(function(e) {
- e.addEventListener('click', function(e) {
- likeMessage(
- e.target,
- e.target.closest('article').getAttribute('data-mid'));
- e.preventDefault();
- });
- });
- document.querySelectorAll('.l .a-sub').forEach(function(e) {
- e.addEventListener('click', function(e) {
- subscribeMessage(
- e.target,
- document.getElementById('content').getAttribute('data-mid'));
- e.preventDefault();
- });
- });
- document.querySelectorAll('.a-login').forEach(function(el) {
- el.addEventListener('click', function(e) {
- openDialogLogin();
- e.preventDefault();
- });
- });
- var unfoldall = document.getElementById('unfoldall');
- if (unfoldall) {
- unfoldall.addEventListener('click', function(e) {
- document.querySelectorAll('#replies>li').forEach(function(e) {
- e.style.display = 'block';
- });
- document.querySelectorAll('#replies .msg-comments').forEach(function(e) {
- e.style.display = 'none';
- });
- e.preventDefault();
- });
- }
- document.querySelectorAll('article').forEach(function(article) {
- if (Array.prototype.some.call(
- article.querySelectorAll('.msg-tags a'),
- function(a) {
- return a.textContent === 'NSFW';
- }
- )) {
- article.classList.add('nsfw');
- }
- });
- document.querySelectorAll('[data-uri]').forEach(el => {
- let dataUri = el.getAttribute('data-uri');
- if (dataUri) {
- setTimeout(() => fetchUserUri(dataUri, user => {
- let header = el.closest('.msg-header');
- header.querySelectorAll('.a-username').forEach(a => {
- a.setAttribute('href', user.uri);
- let img = a.querySelector('img');
- if (img && user.avatar) {
- img.setAttribute('src', user.avatar);
- img.setAttribute('alt', user.uname);
- }
- let textNode = a.childNodes[0];
- if (textNode.nodeType === Node.TEXT_NODE && textNode.nodeValue.trim().length > 0) {
- let uname = document.createTextNode(user.uname);
- a.replaceChild(uname, a.firstChild);
- }
- });
- }), 100);
- }
- });
- document.querySelectorAll('[data-user-uri]').forEach(el => {
- let dataUri = el.getAttribute('href');
- if (dataUri) {
- setTimeout(() => fetchUserUri(dataUri, user => {
- let textNode = el.childNodes[0];
- if (textNode.nodeType === Node.TEXT_NODE && textNode.nodeValue.trim().length > 0) {
- let uname = document.createTextNode(`@${user.uname}`);
- el.replaceChild(uname, el.firstChild);
- }
- }), 100);
- }
- });
- initES();
-
- embedAll();
- var elSelector = 'header',
- elClassHidden = 'header--hidden',
- elClassBackground = 'header--background',
- throttleTimeout = 500,
- element = document.querySelector(elSelector);
-
- if (element) {
-
- var dHeight = 0,
- wHeight = 0,
- wScrollCurrent = 0,
- wScrollBefore = 0,
- wScrollDiff = 0,
-
- throttle = function(delay, fn) {
- var last, deferTimer;
- return function() {
- var context = this, args = arguments, now = +new Date;
- if (last && now < last + delay) {
- clearTimeout(deferTimer);
- deferTimer = setTimeout(
- function() {
- last = now;
- fn.apply(context, args);
- },
- delay);
- } else {
- last = now;
- fn.apply(context, args);
- }
- };
- };
-
- window.addEventListener('scroll', throttle(throttleTimeout, function() {
- dHeight = document.body.offsetHeight;
- wHeight = window.innerHeight;
- wScrollCurrent = window.pageYOffset;
- wScrollDiff = wScrollBefore - wScrollCurrent;
-
- if (wScrollCurrent <= 0) {
- // scrolled to the very top; element sticks to the top
- element.classList.remove(elClassHidden);
- element.classList.remove(elClassBackground);
- } else if (wScrollDiff > 0 && element.classList.contains(elClassHidden)) {
- // scrolled up; element slides in
- element.classList.remove(elClassHidden);
- element.classList.add(elClassBackground);
- } else if (wScrollDiff < 0) {
- // scrolled down
- if (wScrollCurrent + wHeight >= dHeight && element.classList.contains(elClassHidden)) {
- // scrolled to the very bottom; element slides in
- element.classList.remove(elClassHidden);
- element.classList.add(elClassBackground);
- } else {
- // scrolled down; element slides out
- element.classList.add(elClassHidden);
- }
- }
-
- wScrollBefore = wScrollCurrent;
- }));
- }
-});
diff --git a/juick-server/src/main/assets/style.css b/juick-server/src/main/assets/style.css
deleted file mode 100644
index 02c59aad..00000000
--- a/juick-server/src/main/assets/style.css
+++ /dev/null
@@ -1,956 +0,0 @@
-/* #region generic */
-
-html,
-body,
-div,
-h1,
-h2,
-ul,
-li,
-p,
-form,
-input,
-textarea,
-pre {
- margin: 0;
- padding: 0;
-}
-textarea {
- overflow: auto;
-}
-html,
-input,
-textarea {
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
- font-size: 12pt;
- -webkit-font-smoothing: subpixel-antialiased;
-}
-h1,
-h2 {
- font-weight: normal;
-}
-ul {
- list-style-type: none;
-}
-a {
- color: #069;
- text-decoration: none;
-}
-img,
-hr {
- border: none;
-}
-hr {
- background: #CCC;
- height: 1px;
- margin: 10px 0;
-}
-pre {
- background: #1e2028;
- color: #41b645;
- overflow-x: auto;
- padding: 6px 20px;
- white-space: pre;
-}
-pre::selection {
- background: #41b645;
- color: #1e2028;
-}
-pre::-moz-selection {
- background: #41b645;
- color: #1e2028;
-}
-.u {
- text-decoration: underline;
-}
-
-/* #endregion */
-
-/* #region overall layout */
-
-html {
- background: #f8f8f8;
- color: #222;
-}
-#wrapper {
- margin: 0 auto;
- width: 1000px;
- margin-top: 52px;
-}
-#column {
- float: left;
- margin-left: 10px;
- overflow: hidden;
- padding-top: 10px;
- width: 240px;
-}
-#content {
- float: right;
- margin: 12px 0 0 0;
- width: 728px;
-}
-#minimal_content {
- margin: 0 auto;
- min-width: 310px;
- width: auto;
-}
-*::selection {
- background: #006699;
- color: #fff;
-}
-body > header {
- position: fixed;
- top: 0;
- width: 100%;
- z-index: 10;
- transition-duration: 0.5s;
- transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
- transition-property: transform;
-}
-@supports (backdrop-filter: blur(10px)) {
- body > header--background {
- background: rgba(255, 255, 255, 0.8);
- backdrop-filter: blur(10px);
- }
-}
-#header_wrapper {
- margin: 0 auto;
- width: 1000px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- flex-wrap: wrap;
- padding: 4px;
-}
-.header--background {
- box-shadow: 0 0 3px rgba(0, 0, 0, 0.28);
- background: #fff;
-}
-.header--hidden {
- transform: translateY(-100%);
-}
-#footer {
- clear: both;
- color: #999;
- font-size: 10pt;
- margin: 40px;
- padding: 10px 0;
-}
-
-@media screen and (max-width: 850px) {
- body {
- text-size-adjust: 100%;
- }
- body,
- #wrapper,
- #topwrapper,
- #content,
- #footer {
- float: none;
- margin: 0 auto;
- min-width: 310px;
- width: auto;
- }
- #wrapper {
- margin-top: 50px;
- }
- body > header {
- margin-bottom: 15px;
- }
- #column {
- float: none;
- margin: 0 10px;
- padding-top: 0;
- width: auto;
- }
-}
-
-/* #endregion */
-
-/* #region header internals */
-
-#logo {
- height: 36px;
- width: 110px;
-}
-#logo a {
- background: url("logo@2x.png") no-repeat;
- background-size: cover;
- border: 0;
- display: block;
- height: 36px;
- overflow: hidden;
- text-indent: 100%;
- white-space: nowrap;
- width: 110px;
-}
-#global {
- display: flex;
-}
-#global a {
- color: #888;
- display: inline-block;
- font-size: 13pt;
- padding: 14px 6px;
-}
-#global li {
- display: inline-block;
-}
-#ctitle a {
- padding: 14px;
-}
-#global li:hover,
-#ctitle a:hover,
-.l a:hover {
- background-color: #fff;
- box-shadow: 0 0 3px rgba(0, 0, 0, 0.16);
- cursor: pointer;
- transition: box-shadow 0.2s ease-in;
-}
-#search input {
- background: #FFF;
- border: 1px solid #ccc;
- outline: none !important;
- padding: 4px;
- -webkit-appearance: none;
- border-radius: 0;
-}
-
-/* #endregion */
-
-/* #region left column internals */
-
-.toolbar {
- border-top: 1px solid #CCC;
-}
-
-#column ul,
-#column p,
-#column hr {
- margin: 10px 0;
-}
-#column li > a {
- display: block;
- height: 100%;
- padding: 6px;
-}
-#column li > a:hover {
- background-color: #fff;
- box-shadow: 0 0 3px rgba(0, 0, 0, 0.16);
- transition: background-color 0.2s ease-in;
-}
-#column .margtop {
- margin-top: 15px;
-}
-
-#column .tags {
- background: #fff;
- box-shadow: 0 0 3px rgba(0, 0, 0, 0.16);
- line-height: 140%;
- padding: 6px;
- text-align: justify;
-}
-#column .inp {
- background: #fff;
- border: 1px solid #ddddd5;
- outline: none !important;
- padding: 4px;
- width: 222px;
-}
-#column .tags h4 {
- background: #eee;
- border: 1px solid #eee;
- color: #888;
- display: block;
- text-align: center;
-}
-#ctitle {
- font-size: 14pt;
-}
-#ctitle img {
- margin-right: 5px;
- vertical-align: middle;
- max-width: 48px;
- max-height: 48px;
-}
-#ustats li {
- font-size: 10pt;
- margin: 3px 0;
-}
-#column table.iread {
- width: 100%;
-}
-#column table.iread td {
- text-align: center;
-}
-#column table.iread img {
- height: 48px;
- width: 48px;
-}
-
-/* #endregion */
-
-/* #region main content */
-#content > p,
-#content > h1,
-#content > h2,
-#minimal_content > p,
-#minimal_content > h1,
-#minimal_content > h2 {
- margin: 1em 0;
-}
-.page {
- background: #eee;
- padding: 6px;
- text-align: center;
-}
-
-.page a {
- color: #888;
-}
-
-/* #endregion */
-
-/* #region article, message internals */
-
-article {
- background: #fff;
- box-shadow: 0 0 3px rgba(0, 0, 0, 0.16);
- line-height: 140%;
- margin-bottom: 10px;
- padding: 20px;
-}
-article time {
- color: #999;
- font-size: 10pt;
-}
-article p {
- clear: left;
- margin: 5px 0 15px 0;
- word-wrap: break-word;
- overflow-wrap: break-word;
-}
-article .ir {
- text-align: center;
-}
-article .ir a {
- cursor: zoom-in;
- display: block;
-}
-article .ir img {
- max-width: 100%;
-}
-article > nav.l,
-.msg-cont > nav.l {
- border-top: 1px solid #eee;
- display: flex;
- justify-content: space-around;
- font-size: 10pt;
-}
-article > nav.l a,
-.msg-cont > nav.l a {
- color: #888;
- margin-right: 15px;
-}
-article .likes {
- padding-left: 20px;
-}
-article .replies {
- margin-left: 18px;
-}
-article .tags {
- margin-top: 3px;
-}
-.msg-tags {
- margin-top: 12px;
- min-height: 1px;
-}
-article .tags > a,
-.badge,
-.msg-tags > a {
- background: #eee;
- border: 1px solid #eee;
- color: #888;
- display: inline-block;
- font-size: 10pt;
- margin-bottom: 5px;
- margin-right: 5px;
- padding: 0 10px;
-}
-.l .msg-button {
- align-items: center;
- display: flex;
- flex-basis: 0;
- flex-direction: column;
- flex-grow: 1;
- padding-top: 12px;
-}
-.l .msg-button-icon {
- font-weight: bold;
-}
-.msgthread {
- margin-bottom: 0;
-}
-.msg-avatar {
- float: left;
- max-height: 48px;
- margin-right: 10px;
- max-width: 48px;
-}
-.msg-avatar img {
- max-height: 48px;
- vertical-align: top;
- max-width: 48px;
-}
-.msg-cont {
- background: #FFF;
- box-shadow: 0 0 3px rgba(0, 0, 0, 0.16);
- line-height: 140%;
- margin-bottom: 12px;
- padding: 20px;
- width: 640px;
-}
-.reply-new .msg-cont {
- border-right: 5px solid #0C0;
-}
-.msg-ts {
- font-size: small;
- vertical-align: top;
-}
-.msg-ts,
-.msg-ts > a {
- color: #999;
-}
-.msg-txt {
- clear: both;
- margin: 0 0 12px;
- padding-top: 10px;
- word-wrap: break-word;
- overflow-wrap: break-word;
-}
-.msg-media {
- text-align: center;
-}
-.msg-links {
- color: #999;
- font-size: small;
- margin: 5px 0 0 0;
-}
-.msg-comments {
- color: #AAA;
- font-size: small;
- margin-top: 10px;
- overflow: hidden;
- text-indent: 10px;
-}
-.ta-wrapper {
- border: 1px solid #DDD;
- display: flex;
- flex-grow: 1;
-}
-.msg-comment {
- display: flex;
- width: 100%;
- margin-top: 10px;
-}
-.msg-comment-hidden {
- display: none;
-}
-.msg-comment textarea {
- border: 0;
- flex-grow: 1;
- outline: none !important;
- padding: 4px;
- resize: vertical;
- vertical-align: top;
-}
-.attach-photo {
- cursor: pointer;
-}
-.attach-photo-active {
- color: green;
-}
-.msg-comment input {
- align-self: flex-start;
- background: #EEE;
- border: 1px solid #CCC;
- color: #999;
- margin: 0 0 0 6px;
- position: -webkit-sticky;
- position: sticky;
- top: 70px;
- vertical-align: top;
- width: 50px;
-}
-.msg-recomms {
- color: #AAA;
- font-size: small;
- margin-top: 10px;
- overflow: hidden;
- text-indent: 10px;
-}
-#replies .msg-txt,
-#private-messages .msg-txt {
- margin: 0;
-}
-.title2 {
- background: #fff;
- margin: 20px 0;
- padding: 10px 20px;
- width: 640px;
-}
-.title2-right {
- float: right;
- line-height: 24px;
-}
-#content .title2 h2 {
- font-size: x-large;
- margin: 0;
-}
-
-@media screen and (max-width: 850px) {
- #header_wrapper {
- width: auto;
- }
- #global {
- justify-content: space-around;
- flex-grow: 1;
- }
- #search {
- padding: 4px;
- }
- article {
- overflow: auto;
- }
- article p {
- margin: 10px 0 8px 0;
- }
- .msg,
- .msg-cont {
- min-width: 280px;
- width: auto;
- }
- .msg-cont {
- margin: 8px 0;
- }
- .msg-media {
- overflow: auto;
- }
- .title2 h2 {
- font-size: large;
- }
- .msg-comment {
- flex-direction: column;
- }
- .msg-comment input {
- align-self: flex-end;
- margin: 6px 0 0 0;
- width: 100px;
- }
-}
-
-@media screen and (max-width: 480px) {
- #wrapper {
- margin-top: 104px;
- }
- #search {
- display: none;
- }
- #global a {
- padding: 14px 2px;
- font-size: 11pt;
- }
- .msg-cont > nav.l,
- article > nav.l {
- font-size: 9pt;
- }
- .msg-txt {
- padding-top: 5px;
- }
- .title2 {
- font-size: 11pt;
- width: auto;
- }
- #content .title2 h2 {
- font-size: 11pt;
- }
- .title2-right {
- line-height: initial;
- }
-}
-
-/* #endregion */
-
-/* #region user-generated texts */
-
-q:before,
-q:after {
- content: "";
-}
-q,
-blockquote {
- border-left: 3px solid #CCC;
- color: #666;
- display: block;
- margin: 10px 0 10px 10px;
- padding-left: 10px;
-}
-
-/* #endregion */
-
-/* #region new message form internals */
-
-#newmessage {
- background: #E5E5E0;
- margin-bottom: 20px;
- padding: 15px;
-}
-#newmessage textarea {
- border: 1px solid #CCC;
- box-sizing: border-box;
- margin: 0 0 5px 0;
- margin-top: 20px;
- max-height: 6em;
- min-width: 280px;
- padding: 4px;
- width: 100%;
-}
-#newmessage input {
- border: 1px solid #CCC;
- margin: 5px 0;
- padding: 2px 4px;
-}
-#newmessage .img {
- width: 500px;
-}
-#newmessage .tags {
- width: 500px;
-}
-#newmessage .subm {
- background: #EEEEE5;
- width: 150px;
-}
-@media screen and (max-width: 850px) {
- #newmessage .img,
- #newmessage .tags {
- width: 100%;
- }
-}
-
-/* #endregion */
-
-/* #region user lists */
-
-.users {
- margin: 10px 0;
- width: 100%;
- display: flex;
- flex-wrap: wrap;
-}
-.users > span {
- overflow: hidden;
- padding: 6px 0;
- width: 200px;
-}
-.users img {
- height: 32px;
- margin-right: 6px;
- vertical-align: middle;
- width: 32px;
-}
-
-/* #endregion */
-
-/* #region signup form */
-
-.signup-h1 > img {
- margin-right: 10px;
- vertical-align: middle;
-}
-.signup-h1 {
- font-size: x-large;
- margin: 20px 0 10px 0;
-}
-.signup-h2 {
- font-size: large;
- margin: 10px 0 5px 0;
-}
-.signup-hr {
- margin: 20px 0;
-}
-
-/* #endregion */
-
-/* #region PM */
-
-.newpm {
- margin: 20px 60px 30px 60px;
-}
-.newpm textarea {
- resize: vertical;
- width: 100%;
-}
-.newpm-send input {
- width: 100px;
-}
-
-/* #endregion */
-
-/* #region popup dialog (lightbox) */
-
-#dialogb {
- background: #222;
- height: 100%;
- left: 0;
- opacity: 0.6;
- position: fixed;
- top: 0;
- width: 100%;
- z-index: 10;
-}
-#dialogt {
- height: 100%;
- left: 0;
- position: fixed;
- top: 0;
- width: 100%;
- z-index: 10;
- display: flex;
- align-items: center;
- justify-content: center;
-}
-#dialogw {
- z-index: 11;
- max-width: 96%;
- max-height: calc(100% - 100px);
- position: fixed;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
-}
-#dialogw a {
- display: block;
-}
-#dialogw img {
- max-height: 100%;
- max-height: 90vh;
- max-width: 100%;
-}
-#dialog_header {
- width: 100%;
- height: 44px;
- position: fixed;
- display: flex;
- flex-direction: row-reverse;
- align-items: center;
-}
-.header_image {
- background: rgba(0, 0, 0, 0.28);
-}
-#dialogc {
- cursor: pointer;
- color: #ccc;
- padding-right: 6px;
-}
-.dialoglogin {
- background: #fff;
- padding: 25px;
- width: 300px;
-}
-.dialog-opened {
- overflow: hidden;
-}
-#signemail,
-#signfb,
-#signvk {
- display: block;
- line-height: 32px;
- margin: 10px 0;
- text-decoration: none;
- width: 100%;
-}
-#signvk {
- margin-bottom: 30px;
-}
-.dialoglogin form {
- margin-top: 7px;
-}
-.signinput,
-.signsubmit {
- border: 1px solid #CCC;
- margin: 3px 0;
- padding: 3px;
-}
-.signinput {
- width: 292px;
-}
-.signsubmit {
- width: 70px;
-}
-.dialogshare {
- background: #fff;
- min-width: 300px;
- overflow: auto;
- padding: 20px;
-}
-.dialogl {
- background: #fff;
- border: 1px solid #DDD;
- margin: 3px 0 20px;
- padding: 5px;
-}
-.dialogshare li {
- float: left;
- margin: 5px 10px 0 0;
-}
-.dialogshare a {
- display: block;
-}
-.dialogtxt {
- background: #fff;
- padding: 20px;
-}
-
-@media screen and (max-width: 480px) {
- .dialog-opened {
- position: fixed;
- width: 100%;
- }
-}
-
-/* #endregion */
-
-/* #region misc */
-
-#wsthread {
- background: #CCC;
- bottom: 20px;
- cursor: pointer;
- display: none;
- padding: 5px 10px;
- position: fixed;
- right: 20px;
-}
-.sharenew {
- display: inline-block;
- line-height: 32px;
- min-height: 32px;
- min-width: 200px;
- padding: 0 12px 0 37px;
-}
-.icon {
- margin-top: -2px;
- vertical-align: middle;
-}
-.icon--ei-link {
- margin-top: -1px;
-}
-.icon--ei-comment {
- margin-top: -5px;
-}
-.newmessage {
- /* textarea on the /post page */
- border: 1px solid #DDD;
- padding: 2px;
- resize: vertical;
- width: 100%;
-}
-
-/* #endregion */
-
-/* #region footer internals */
-
-#footer-social {
- float: left;
-}
-#footer-social a {
- border: 0;
- display: inline-block;
-}
-#footer-left {
- margin-left: 286px;
- margin-right: 350px;
-}
-#footer-right {
- float: right;
-}
-
-@media screen and (max-width: 850px) {
- #footer {
- margin: 0 10px;
- }
- #footer div {
- float: none;
- margin: 10px 0;
- }
-}
-
-/* #endregion */
-
-/* #region settings */
-
-fieldset {
- border: 1px dotted #ccc;
- margin-top: 25px;
-}
-
-/* #endregion */
-
-/* #region embeds */
-
-.embedContainer {
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- justify-content: center;
- padding: 0;
- margin: 30px -3px 15px -3px;
-}
-.embedContainer > * {
- box-sizing: border-box;
- flex-grow: 1;
- margin: 3px;
- min-width: 49%;
-}
-.embedContainer > .compact {
- flex-grow: 0;
-}
-.embedContainer .picture img {
- display: block;
-}
-.embedContainer img,
-.embedContainer video {
- max-width: 100%;
- max-height: 80vh;
-}
-.embedContainer > .audio,
-.embedContainer > .youtube {
- min-width: 90%;
-}
-.embedContainer audio {
- width: 100%;
-}
-.embedContainer iframe {
- overflow: hidden;
- resize: vertical;
- display: block;
-}
-
-/* #endregion */
-
-/* #region nsfw */
-
-article.nsfw .embedContainer img,
-article.nsfw .embedContainer video,
-article.nsfw .embedContainer iframe,
-article.nsfw .ir img {
- opacity: 0.1;
-}
-article.nsfw .embedContainer img:hover,
-article.nsfw .embedContainer video:hover,
-article.nsfw .embedContainer iframe:hover,
-article.nsfw .ir img:hover {
- opacity: 1;
-}
-
-/* #endregion */