diff --git a/files/assets/css/main.css b/files/assets/css/main.css
index b1a435b61..881f8883d 100644
--- a/files/assets/css/main.css
+++ b/files/assets/css/main.css
@@ -5284,7 +5284,7 @@ textarea {
}
}
.img, img[alt^="![]("],
-.preview img:not(img[src^="/uid/"], img[src^="/pp/"], img[src$="/pic"], img[src$="/i/hand.webp"], img[src$="/i/talking.webp"], img[src*="/e/"]) {
+.preview img:not(img[src^="/uid/"], img[src^="/pp/"], img[src$="/pic"], img[src$="/i/hand.webp"], img[src$="/i/talking.webp"], img[src$="/i/typing-hands.webp"], img[src*="/e/"]) {
max-height: 150px !important;
max-width: 100% !important;
border-radius: 0.2rem !important;
@@ -5446,6 +5446,12 @@ span > img[src$="/i/talking.webp"] {
position: absolute;
width: 70%;
}
+span > img[src$="/i/typing-hands.webp"] {
+ position: absolute;
+ width: 100%;
+ bottom: 0;
+ z-index: 1;
+}
span > img[src$="/i/hand.webp"] ~ img {
animation: pat-pfp-anim 0.3s infinite;
transform-origin: bottom center;
@@ -5489,6 +5495,10 @@ span > img[src$="/i/talking.webp"]+img[src$="/i/hand.webp"]+img {
bottom: calc(2px + 2%) !important;
}
+.typing-hands-preview {
+ bottom: calc(2px + 2%) !important;
+}
+
span > img[src$="/i/love-foreground.webp"]+img[src$="/i/love-background.webp"]+img {
position: absolute;
z-index: 50;
@@ -5499,6 +5509,26 @@ span > img[src$="/i/love-foreground.webp"]+img[src$="/i/love-background.webp"]+i
transform: scaleX(-1) rotate(-10deg);
}
+span > img[src$="/i/love-foreground.webp"]+img[src$="/i/love-background.webp"]+img[src$="/i/typing-hands.webp"] {
+ position: absolute;
+ z-index: 51;
+ height: unset;
+ width: 50%;
+ bottom: -2%;
+ left: 33%;
+ transform: rotate(10deg);
+}
+
+span > img[src$="/i/love-foreground.webp"]+img[src$="/i/love-background.webp"]+img+img {
+ position: absolute;
+ z-index: 50;
+ height: 60%;
+ width: 60%;
+ bottom: -2%;
+ left: 33%;
+ transform: scaleX(-1) rotate(-10deg);
+}
+
span > img[src$="/i/love-foreground.webp"] {
position: absolute;
z-index: 100;
diff --git a/files/assets/images/typing-hands.webp b/files/assets/images/typing-hands.webp
new file mode 100644
index 000000000..6188577f5
Binary files /dev/null and b/files/assets/images/typing-hands.webp differ
diff --git a/files/assets/js/markdown.js b/files/assets/js/markdown.js
index 6e4039979..640949f30 100644
--- a/files/assets/js/markdown.js
+++ b/files/assets/js/markdown.js
@@ -74,6 +74,7 @@ const MODIFIERS = {
REVERSED_MODIFIER: 6,
GENOCIDE: 7,
LOVE: 8,
+ TYPING: 9,
};
const findAllEmojiEndings = (word) => {
@@ -121,6 +122,16 @@ const findAllEmojiEndings = (word) => {
continue;
}
+ if(currWord.endsWith('typing')) {
+ if(currEndings.indexOf(MODIFIERS.TYPING) !== -1) {
+ hasReachedNonModifer = true;
+ continue;
+ }
+ currWord = currWord.slice(0, -6);
+ currEndings.push(MODIFIERS.TYPING);
+ continue;
+ }
+
hasReachedNonModifer = true;
}
@@ -204,12 +215,13 @@ function markdown(t) {
const imgClass = modifiers.has(MODIFIERS.REVERSED) && modifiers.has(MODIFIERS.REVERSED_MODIFIER) ? mirroredClass : ''
const lovedClass = modifiers.has(MODIFIERS.LOVE) ? 'love-preview' : '';
- if ([MODIFIERS.TALKING, MODIFIERS.GENOCIDE, MODIFIERS.PAT, MODIFIERS.LOVE].some((modifer) => modifiers.has(modifer))) {
+ if ([MODIFIERS.TALKING, MODIFIERS.GENOCIDE, MODIFIERS.PAT, MODIFIERS.LOVE, MODIFIERS.TYPING].some((modifer) => modifiers.has(modifer))) {
+ const typingHtml = modifiers.has(MODIFIERS.TYPING) ? `` : '';
const talkingHtml = modifiers.has(MODIFIERS.TALKING) ? `
` : '';
const patHtml = modifiers.has(MODIFIERS.PAT) ? `
` : '';
const loveHtml = modifiers.has(MODIFIERS.LOVE) ? `
` : '';
const url = modifiers.has(MODIFIERS.USER) ? `/@${emoji}/pic` : `${SITE_FULL_IMAGES}/e/${emoji}.webp`;
- const modifierHtml = isTalkingFirst ? `${talkingHtml}${patHtml}${loveHtml}` : `${patHtml}${talkingHtml}${loveHtml}`;
+ const modifierHtml = isTalkingFirst ? `${talkingHtml}${patHtml}${loveHtml}${typingHtml}` : `${patHtml}${talkingHtml}${loveHtml}${typingHtml}`;
input = input.replace(old, `${modifierHtml}
`);
} else {
input = input.replace(old, `
`);
diff --git a/files/helpers/sanitize.py b/files/helpers/sanitize.py
index 345c1bb6d..ebf5c238e 100644
--- a/files/helpers/sanitize.py
+++ b/files/helpers/sanitize.py
@@ -210,6 +210,14 @@ def find_all_emoji_endings(emoji):
emoji = emoji[:-4]
continue
+ if emoji.endswith('typing'):
+ if 'typing' in endings:
+ is_non_ending_found = True
+ continue
+ endings.append('typing')
+ emoji = emoji[:-6]
+ continue
+
is_non_ending_found = True
if emoji.endswith('random'):
@@ -254,6 +262,7 @@ def render_emoji(html, regexp, golden, emojis_used, b=False, is_title=False):
is_talking_first = ending_modifiers.index('pat') > ending_modifiers.index('talking') if is_talking and is_patted else False
is_loved = 'love' in ending_modifiers
is_genocided = 'genocide' in ending_modifiers
+ is_typing = 'typing' in ending_modifiers
is_user = emoji.startswith('@')
end_modifier_length = 3 if is_patted else 0
@@ -261,6 +270,7 @@ def render_emoji(html, regexp, golden, emojis_used, b=False, is_title=False):
hand_html = f'
' if is_patted and emoji != 'marseyunpettable' else ''
talking_html = f'
' if is_talking else ''
+ typing_html = f'
' if is_typing else ''
loved_html = f'
'
genocide_attr = ' cide' if is_genocided else ''
@@ -275,7 +285,10 @@ def render_emoji(html, regexp, golden, emojis_used, b=False, is_title=False):
if is_loved:
modifier_html = f'{modifier_html}{loved_html}'
- if (is_patted and emoji != 'marseyunpettable') or is_talking or is_genocided or is_loved:
+ if is_typing:
+ modifier_html = f'{modifier_html}{typing_html}'
+
+ if (is_patted and emoji != 'marseyunpettable') or is_talking or is_genocided or is_loved or is_typing:
if path.isfile(f"files/assets/images/emojis/{emoji}.webp"):
emoji_html = f'{modifier_html}{emoji_partial_pat.format(old, f"{SITE_FULL_IMAGES}/e/{emoji}.webp", attrs)}'
elif is_user:
diff --git a/files/templates/formatting.html b/files/templates/formatting.html
index 007f0de26..74ff353bd 100644
--- a/files/templates/formatting.html
+++ b/files/templates/formatting.html
@@ -152,11 +152,20 @@