diff --git a/files/assets/css/awards.css b/files/assets/css/awards.css index 358afc0c5..59fe0edda 100644 --- a/files/assets/css/awards.css +++ b/files/assets/css/awards.css @@ -1,3 +1,5 @@ +/*generic*/ + #awards-container { position: absolute; overflow: hidden; @@ -14,58 +16,32 @@ animation-timing-function: linear !important; } -.scooter img { - width: min(7vw, 50px) !important; -} -.emoji-award img { +/*emoji*/ + +.emoji-award img, .emoji-hz-award img { width: min(10vw, 60px) !important; } -.train img { - width: min(10vw, 80px) !important; +.emoji-award:nth-child(even) { + animation-direction: alternate-reverse; } - -.emoji-award:nth-child(even), .emoji-award:nth-child(n+2):nth-child(n+3) img { +.emoji-award:nth-child(2) img, .emoji-award:nth-child(3) img, .emoji-award:nth-child(6) img, .emoji-award:nth-child(7) img, .emoji-award:nth-child(10) img, .emoji-award:nth-child(11) img, .emoji-award:nth-child(14) img, .emoji-award:nth-child(15) img, .emoji-award:nth-child(18) img, .emoji-award:nth-child(19) img { animation-direction: alternate-reverse; } @keyframes emojiX { - 0% { - opacity: 1; - } 100% { - opacity: 1; transform: translateX(98vw); } } @keyframes emojiY { - 0% { - opacity: 1; - } 100% { - opacity: 1; transform: translateY(80vh); } } -.train:nth-child(1), .scooter:nth-child(1) {top:2%} -.train:nth-child(2), .scooter:nth-child(2) {top:27%} -.train:nth-child(3), .scooter:nth-child(3) {top:52%} -.train:nth-child(4), .scooter:nth-child(4) {top:77%} - -.train:nth-child(odd) {animation-direction: reverse;} -.train:nth-child(odd) img {transform: scaleX(-1);} - -@keyframes train { - from {transform: translateX(-10vw)} - to {transform: translateX(110vw)} -} - -.scooter:nth-child(even) {animation-direction: reverse;} -.scooter:nth-child(even) img {transform: scaleX(-1);} - .emoji-award { animation: emojiX 8s alternate; } @@ -73,10 +49,6 @@ animation: emojiY 9s alternate; } -.train, .scooter { - animation: train 12s; -} - @media (max-width: 768px) { .emoji-award { animation: emojiX 6s alternate; @@ -84,9 +56,62 @@ .emoji-award img { animation: emojiY 7s alternate; } - .train, .scooter { - animation: train 6s; +} + +.emoji-hz-award:nth-child(odd) { + animation-direction: reverse; +} +.emoji-hz-award:nth-child(odd) img { + transform: scaleX(-1); +} +.emoji-hz-award:nth-child(1), .emoji-hz-award:nth-child(5), .emoji-hz-award:nth-child(9), .emoji-hz-award:nth-child(13), .emoji-hz-award:nth-child(17) { + top: 2%; +} +.emoji-hz-award:nth-child(2), .emoji-hz-award:nth-child(6), .emoji-hz-award:nth-child(10), .emoji-hz-award:nth-child(14), .emoji-hz-award:nth-child(18) { + top: 27%; +} +.emoji-hz-award:nth-child(3), .emoji-hz-award:nth-child(7), .emoji-hz-award:nth-child(11), .emoji-hz-award:nth-child(15), .emoji-hz-award:nth-child(19) { + top: 52%; +} +.emoji-hz-award:nth-child(4), .emoji-hz-award:nth-child(8), .emoji-hz-award:nth-child(12), .emoji-hz-award:nth-child(16), .emoji-hz-award:nth-child(20) { + top: 77%; +} + + +@keyframes emoji-hz { + 0% { + transform: translateX(-10vw); } + 100% { + transform: translateX(110vw); + } +} + +.emoji-hz-award { + animation: emoji-hz 12s; +} + +@media (max-width: 768px) { + .emoji-hz-award { + animation: emoji-hz 6s; + } +} + +.animation-delay-1 { + animation-delay: 1s !important; +} +.animation-delay-2 { + animation-delay: 2s !important; +} +.animation-delay-3 { + animation-delay: 3s !important; +} +.animation-delay-4 { + animation-delay: 4s !important; +} + +.emoji-award, .emoji-hz-award { + transform: translateX(-10vw); } /*confetti*/ @@ -222,7 +247,7 @@ animation: 60s linear 0s infinite move-colors; } -.queen:not(a):not(.ectoplasm), h1.queen.post-title a { +.queen:not(a) img, .emoji-award:not(.ectoplasm), h1.queen.post-title a { color: hotpink !important; font-weight: 700 !important; text-transform: lowercase !important; @@ -274,44 +299,6 @@ font-weight: 400; } -.animation-delay-1 { - opacity: 0; - animation-delay: 1s; -} -.animation-delay-2 { - opacity: 0; - animation-delay: 2s; -} -.animation-delay-3 { - opacity: 0; - animation-delay: 3s; -} -.animation-delay-4 { - opacity: 0; - animation-delay: 4s; -} -.animation-delay-5 { - opacity: 0; - animation-delay: 5s; -} -.animation-delay-6 { - opacity: 0; - animation-delay: 6s; -} -.animation-delay-7 { - opacity: 0; - animation-delay: 7s; -} -.animation-delay-8 { - opacity: 0; - animation-delay: 8s; -} -.animation-delay-9 { - opacity: 0; - animation-delay: 9s; -} - - @keyframes move-colors { from {background-position: 0px;} to {background-position: 1000px;} diff --git a/files/assets/css/main.css b/files/assets/css/main.css index 5c8a30b72..5a917a5fa 100644 --- a/files/assets/css/main.css +++ b/files/assets/css/main.css @@ -7187,12 +7187,12 @@ input::-webkit-inner-spin-button { min-height: 60px; } -#notelabel { +#notelabel, #emoji_behavior_label { font-size: 16px; } @media (max-width: 768px) { - #note, #notelabel { + #note, #notelabel, #emoji_behavior_label { font-size: 14px !important; } } diff --git a/files/assets/js/award_modal.js b/files/assets/js/award_modal.js index 14a4be074..1eccdde06 100644 --- a/files/assets/js/award_modal.js +++ b/files/assets/js/award_modal.js @@ -92,6 +92,9 @@ function vote(type, id, dir) { let global_price; +const note_section = document.getElementById('note_section') +const gif_button = note_section.querySelector('[title="Add GIF"]') + function pick(kind, price, coins, marseybux) { global_price = price; @@ -120,11 +123,22 @@ function pick(kind, price, coins, marseybux) { if (kind == "chud") { document.getElementById('phrase_section').classList.remove("d-none") - document.getElementById('note_section').classList.add("d-none") + note_section.classList.add("d-none") } else { document.getElementById('phrase_section').classList.add("d-none") - document.getElementById('note_section').classList.remove("d-none") + note_section.classList.remove("d-none") + } + + if (kind == "emoji") { + document.getElementById('emoji_behavior_section').classList.remove("d-none") + document.getElementById('note').setAttribute("style", "min-height:35px;max-height:35px;height:35px;min-width:min(300px,80vw)") + gif_button.classList.add('d-none') + } + else { + document.getElementById('emoji_behavior_section').classList.add("d-none") + document.getElementById('note').removeAttribute("style") + gif_button.classList.remove('d-none') } if (kind == "flairlock") { @@ -185,7 +199,8 @@ function giveaward(t) { postToast(t, t.dataset.action, { "kind": kind, - "note": document.getElementById(note_id).value + "note": document.getElementById(note_id).value, + "emoji_behavior": document.getElementById("emoji_behavior").value }, () => { let owned = document.getElementById(`${kind}-owned`) diff --git a/files/classes/comment.py b/files/classes/comment.py index 318eb4396..fb6fe4ae0 100644 --- a/files/classes/comment.py +++ b/files/classes/comment.py @@ -20,6 +20,13 @@ from files.helpers.sorting_and_time import * from .saves import CommentSaveRelationship +def get_emoji_awards_emojis(obj, v, kind, OVER_18_EMOJIS): + if g.show_nsfw: + emojis = [x.note for x in obj.awards if x.kind == kind] + else: + emojis = [x.note for x in obj.awards if x.kind == kind and x.note not in OVER_18_EMOJIS] + return reversed(emojis[:20]) + def get_award_classes(obj, v, title=False): classes = [] @@ -321,12 +328,6 @@ class Comment(Base): return 0 return len([x for x in self.awards if x.kind == kind]) - @lazy - def emoji_award_emojis(self, v, OVER_18_EMOJIS): - if g.show_nsfw: - return [x.note for x in self.awards if x.kind == "emoji"][:10] - return [x.note for x in self.awards if x.kind == "emoji" and x.note not in OVER_18_EMOJIS][:10] - @property @lazy def json(self): @@ -505,3 +506,7 @@ class Comment(Base): @lazy def award_classes(self, v): return get_award_classes(self, v) + + @lazy + def emoji_awards_emojis(self, v, kind, OVER_18_EMOJIS): + return get_emoji_awards_emojis(self, v, kind, OVER_18_EMOJIS) diff --git a/files/classes/post.py b/files/classes/post.py index 44a2d1f02..318020b10 100644 --- a/files/classes/post.py +++ b/files/classes/post.py @@ -15,7 +15,7 @@ from files.helpers.lazy import lazy from files.helpers.regex import * from files.helpers.sorting_and_time import make_age_string -from .comment import normalize_urls_runtime, add_options, get_award_classes +from .comment import * from .polls import * from .hole import * from .subscriptions import * @@ -262,12 +262,6 @@ class Post(Base): return 4 return num - @lazy - def emoji_award_emojis(self, v, OVER_18_EMOJIS): - if g.show_nsfw: - return [x.note for x in self.awards if x.kind == "emoji"][:10] - return [x.note for x in self.awards if x.kind == "emoji" and x.note not in OVER_18_EMOJIS][:10] - @lazy def realurl(self, v): url = self.url @@ -383,3 +377,7 @@ class Post(Base): @lazy def award_classes(self, v, title=False): return get_award_classes(self, v, title) + + @lazy + def emoji_awards_emojis(self, v, kind, OVER_18_EMOJIS): + return get_emoji_awards_emojis(self, v, kind, OVER_18_EMOJIS) diff --git a/files/helpers/config/awards.py b/files/helpers/config/awards.py index 89d5d251f..542a449ab 100644 --- a/files/helpers/config/awards.py +++ b/files/helpers/config/awards.py @@ -463,36 +463,10 @@ AWARDS = { "enabled": True, "positive": True, }, - "train": { - "kind": "train", - "title": "Train", - "description": "Summons a train on the post.", - "icon": "fas fa-train", - "color": "text-pink", - "price": 300, - "deflectable": False, - "cosmetic": True, - "ghost": True, - "enabled": True, - "positive": True, - }, - "scooter": { - "kind": "scooter", - "title": "Scooter", - "description": "Summons a scooter on the post.", - "icon": "fas fa-flag-usa", - "color": "text-muted", - "price": 300, - "deflectable": False, - "cosmetic": True, - "ghost": True, - "enabled": True, - "positive": True, - }, "emoji": { "kind": "emoji", "title": "Emoji", - "description": "Summons a bouncing emoji on the post.", + "description": "Summons a moving emoji on the post.", "icon": "fas fa-smile-beam", "color": "text-yellow", "price": 300, @@ -502,6 +476,19 @@ AWARDS = { "enabled": True, "positive": True, }, + "emoji-hz": { + "kind": "emoji-hz", + "title": "Emoji", + "description": "Summons a moving emoji on the post.", + "icon": "fas fa-smile-beam", + "color": "text-yellow", + "price": 300, + "deflectable": False, + "cosmetic": True, + "ghost": True, + "enabled": False, + "positive": True, + }, "firework": { "kind": "firework", "title": "Fireworks", diff --git a/files/routes/awards.py b/files/routes/awards.py index aa2ccf1f6..872ebb67b 100644 --- a/files/routes/awards.py +++ b/files/routes/awards.py @@ -158,6 +158,8 @@ def award_thing(v, thing_type, id): if kind not in AWARDS: abort(404, "This award doesn't exist") + award_title = AWARDS[kind]['title'] + award = g.db.query(AwardRelationship).filter( AwardRelationship.kind == kind, AwardRelationship.user_id == v.id, @@ -189,15 +191,15 @@ def award_thing(v, thing_type, id): if v.id != author.id: if author.deflector and v.deflector and AWARDS[kind]['deflectable']: - msg = f"@{v.username} has tried to give your [{thing_type}]({thing.shortlink}) the {AWARDS[kind]['title']} Award but it was deflected on them, they also had a deflector up, so it bounced back and forth until it vaporized!" + msg = f"@{v.username} has tried to give your [{thing_type}]({thing.shortlink}) the {award_title} Award but it was deflected on them, they also had a deflector up, so it bounced back and forth until it vaporized!" send_repeatable_notification(author.id, msg) - msg = f"{safe_username} under the effect of a deflector award; your {AWARDS[kind]['title']} Award has been deflected back to you but your deflector protected you, the award bounced back and forth until it vaporized!" + msg = f"{safe_username} under the effect of a deflector award; your {award_title} Award has been deflected back to you but your deflector protected you, the award bounced back and forth until it vaporized!" send_repeatable_notification(v.id, msg) g.db.delete(award) - return {"message": f"{AWARDS[kind]['title']} award given to {thing_type} successfully!"} + return {"message": f"{award_title} award given to {thing_type} successfully!"} if author.deflector and AWARDS[kind]['deflectable']: author = v @@ -586,12 +588,12 @@ def award_thing(v, thing_type, id): if v.id != author.id: if author.deflector and AWARDS[kind]['deflectable']: - msg = f"@{v.username} has tried to give your [{thing_type}]({thing.shortlink}) the {AWARDS[kind]['title']} Award but it was deflected and applied to them :marseytroll:" + msg = f"@{v.username} has tried to give your [{thing_type}]({thing.shortlink}) the {award_title} Award but it was deflected and applied to them :marseytroll:" send_repeatable_notification(author.id, msg) - msg = f"{safe_username} under the effect of a deflector award; your {AWARDS[kind]['title']} Award has been deflected back to you :marseytroll:" + msg = f"{safe_username} under the effect of a deflector award; your {award_title} Award has been deflected back to you :marseytroll:" send_repeatable_notification(v.id, msg) elif kind != 'spider': - msg = f"@{v.username} has given [{link_text_in_notif}]({thing.shortlink}) the {AWARDS[kind]['title']} Award" + msg = f"@{v.username} has given [{link_text_in_notif}]({thing.shortlink}) the {award_title} Award" if kind == 'shit': msg += f" and has stolen from you {awarded_coins} coins as a result" @@ -613,7 +615,12 @@ def award_thing(v, thing_type, id): g.db.add(thing) - return {"message": f"{AWARDS[kind]['title']} award given to {thing_type} successfully!"} + if award.kind == "emoji": + emoji_behavior = request.values.get("emoji_behavior").strip() + if emoji_behavior == "horizontal": + award.kind = "emoji-hz" + + return {"message": f"{award_title} award given to {thing_type} successfully!"} @app.post("/trick-or-treat") @limiter.limit("1/hour", key_func=lambda:f'{SITE}-{session.get("lo_user")}') diff --git a/files/templates/awards.html b/files/templates/awards.html index 8c10c7a52..f9690964a 100644 --- a/files/templates/awards.html +++ b/files/templates/awards.html @@ -9,25 +9,19 @@ {% endmacro %} - {% if p.award_count("emoji", v) %} -
- {% for emoji in p.emoji_award_emojis(v, OVER_18_EMOJIS) %} - {% set src = '/e/' + emoji + '.webp' %} - {% set alt = ':#' + emoji + ':' %} - {% set delay = 'animation-delay-' ~ (loop.index-1) %} -
- {{alt}} -
- {% endfor %} -
- {% endif %} - - {% if p.award_count("train", v) %} - {{stackable_award('train', '/e/marseytrain.webp', ':#marseytrain:')}} - {% endif %} - - {% if p.award_count("scooter", v) %} - {{stackable_award('scooter', '/e/marseyscooter.webp', ':#marseyscooter:')}} + {% if p.award_count("emoji", v) or p.award_count("emoji-hz", v) %} + {% for kind in ["emoji", "emoji-hz"] %} +
+ {% for emoji in p.emoji_awards_emojis(v, kind, OVER_18_EMOJIS) %} + {% set src = '/e/' + emoji + '.webp' %} + {% set alt = ':#' + emoji + ':' %} + {% set delay = 'animation-delay-' ~ ((loop.index-1)/4)|int %} +
+ {{alt}} +
+ {% endfor %} +
+ {% endfor %} {% endif %} {% if p.award_count("firework", v) %} diff --git a/files/templates/modals/award.html b/files/templates/modals/award.html index 3d8a6c78f..553f4bf0c 100644 --- a/files/templates/modals/award.html +++ b/files/templates/modals/award.html @@ -53,18 +53,35 @@ -
- - - {{macros.emoji_btn('note', 'awardModal')}} - {{macros.gif_btn('note', 'awardModal')}} +
+
+ + + {{macros.emoji_btn('note', 'awardModal')}} + {{macros.gif_btn('note', 'awardModal')}} +
+ +
+ + +
+ +
+
- + - + -
+
Price: coins/marseybux
diff --git a/migrations/20231009-replace-train-and-scooter-awards.sql b/migrations/20231009-replace-train-and-scooter-awards.sql new file mode 100644 index 000000000..c1aa0dd18 --- /dev/null +++ b/migrations/20231009-replace-train-and-scooter-awards.sql @@ -0,0 +1,2 @@ +update award_relationships set kind='emoji-hz', note='marseytrain' where kind='train'; +update award_relationships set kind='emoji-hz', note='marseyscooter' where kind='scooter';