Skip to content

Commit

Permalink
Rework addons
Browse files Browse the repository at this point in the history
  • Loading branch information
dhelonious committed Jan 2, 2025
1 parent c82a322 commit a06793a
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 112 deletions.
5 changes: 3 additions & 2 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ This release also includes:
* libvips 8.16.0
* ffmpeg 7.1

## Changelog for 4.3.2snap5:
## Changelog for 4.3.2snap6:

* Hotfix for `mastodon-server.get-certificate` `acme.server` check
* Improve confetti animation
* Hotfix for `mastodon-server.get-certificate` `acme.server` check [4.3.2snap4]
* It's your Fediday: The day you joined the Fediverse will be celebrated by your instance with a confetti rain! 🎊 [4.3.2snap4]
* Support [BuyPass](https://buypass.com) SSL CA [4.3.2snap4]
* Yarn updated to 4.6.0 [4.3.2snap4]
Expand Down
5 changes: 2 additions & 3 deletions snap/snapcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ description: |
implements ActivityPub!)
base: core24
version: 4.3.2snap5
version: 4.3.2snap6
grade: stable
confinement: strict

Expand Down Expand Up @@ -906,8 +906,7 @@ parts:
set -eux
mkdir -p $MASTODON_JS/mastodon/addons
cp $CRAFT_STAGE/addons/*.js $MASTODON_JS/mastodon/addons/
for filename in $MASTODON_JS/mastodon/addons/*.js; do
name="$(basename $filename .js)"
for name in snow fediday; do
sed -i "1s|^|import * as $name from 'mastodon/addons/$name';\n|" $MASTODON_JS/mastodon/common.js
done
Expand Down
55 changes: 55 additions & 0 deletions src/mastodon/addons/effects.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Based on snow addon by Roni Laukkarinen
// https://github.com/ronilaukkarinen/mastodon/commit/9bf1563
function topEffect(animate, height='70px', fadeLength='30px', maxParticlesSmall=25, maxParticlesLarge=50) {
const wrapper = document.createElement('div');
wrapper.classList.add('particles');
wrapper.style.position = 'fixed';
wrapper.style.top = '0';
wrapper.style.left = '0';
wrapper.style.width = '100%';
wrapper.style.height = height;
wrapper.style.pointerEvents = 'none';
wrapper.style.zIndex = '9999';
wrapper.style.maskImage = `linear-gradient(to top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 1) ${fadeLength})`;
wrapper.style.webkitMaskImage = `linear-gradient(to top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 1) ${fadeLength})`;
wrapper.style.transition = 'opacity 0.3s ease-in-out';

const canvas = document.createElement('canvas');
canvas.style.width = '100%';
canvas.style.height = '100%';
canvas.width = window.innerWidth * 2;
canvas.height = parseInt(height, 10) * 2;

wrapper.appendChild(canvas);
document.body.appendChild(wrapper);

const ctx = canvas.getContext('2d');
const particles = [];

// Adjust max particles based on viewport width
const getMaxParticles = () => {
return window.innerWidth <= 800 ? maxParticlesSmall : maxParticlesLarge;
};
let maxParticles = getMaxParticles();
animate(ctx, canvas, particles, maxParticles);

// Update maxParticles on resize
window.addEventListener('resize', () => {
canvas.width = window.innerWidth * 2;
canvas.height = parseInt(height, 10) * 2;
maxParticles = getMaxParticles();
// Remove excess particles if viewport becomes smaller
if (particles.length > maxParticles) {
particles.length = maxParticles;
}
});

window.addEventListener('scroll', () => {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
if (scrollTop > 100) {
wrapper.style.opacity = Math.max(0, 1 - (scrollTop - 100) / 200);
} else {
wrapper.style.opacity = '1';
}
});
}
72 changes: 17 additions & 55 deletions src/mastodon/addons/fediday.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import { me, reduceMotion } from 'mastodon/initial_state';
import { store } from 'mastodon/store';
import { topEffect } from 'mastodon/addons/effects';

const confetti_colors = [
`rgb(228, 3, 3)`, // red
Expand All @@ -13,96 +14,57 @@ const confetti_colors = [
`rgb(115, 41, 130)`, // violet
];

function animate(ctx, confetti, canvas, maxConfetti) {
function animateConfetti(ctx, canvas, particles, maxParticles) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Add new confetto if we haven't reached the maximum
if (confetti.length < maxConfetti && Math.random() < 0.05) { // 5% chance each frame to add a new confetto
confetti.push({
x: Math.random() * canvas.width,
y: 0,
width: Math.random() * 2 + 5,
length: Math.random() * 4 + 10,
angle: Math.random() * 60 - 30,
speed: Math.random() * 1 + 1,
rotationSpeed: Math.random() * 1.6 - 0.8,
color: confetti_colors[Math.floor(Math.random() * confetti_colors.length)],
});
}

confetti.forEach(confetto => {
const confettoPhase = confetto.rotationSpeed / Math.abs(confetto.rotationSpeed) * (confetto.y % (confetto.speed * 100)) / (confetto.speed * 100);
const confettoWidth = Math.pow(Math.cos(confettoPhase * Math.PI), 2) * confetto.length / 2;

// Draw confetto
ctx.save();
ctx.translate(confetto.x, confetto.y);
ctx.rotate(confetto.angle / 180 * Math.PI);
ctx.fillStyle = confetto.color;
ctx.fillRect(-confetto.width / 2, -confetto.width, confetto.width, confetto.width * 2);
ctx.fillRect(-confettoWidth / 2, -confetto.length / 2, confettoWidth, confetto.length);
ctx.restore();
// Update position with gentler movement and swaying
const phase = confetto.rotationSpeed / Math.abs(confetto.rotationSpeed) * (confetto.y % (confetto.speed * 100)) / (confetto.speed * 100);
confetto.x += Math.sin(phase * 2 * Math.PI) * 0.5;

// Update position
confetto.x += Math.sin(confettoPhase * 2 * Math.PI) * 0.5;
confetto.y += confetto.speed * 0.5;
confetto.angle += confetto.rotationSpeed * 0.5;
if (confetto.y > canvas.height) {
confetto.y = 0;
confetto.x = Math.random() * canvas.width;
}
});

requestAnimationFrame(() => animate(ctx, confetti, canvas, maxConfetti));
}

document.addEventListener('DOMContentLoaded', () => {
// Check if reduced motion is enabled
// Don't create confetti effect if not logged in or reduced motion is preferred
if (!me || reduceMotion) {
return; // Don't create confetti effect if not logged in or reduced motion is preferred
return;
}

const account_fediday = new Date(store.getState().getIn(['accounts', me, 'created_at']));
if (new Date().getDate() === account_fediday.getDate() && new Date().getMonth() === account_fediday.getMonth()) {
// Set property for other addons to check
window.fediday = true;
const height = '70px';
const fadeLength = '30px';
const wrapper = document.createElement('div');
wrapper.classList.add('confetti');
wrapper.style.position = 'fixed';
wrapper.style.top = '0';
wrapper.style.left = '0';
wrapper.style.width = '100%';
wrapper.style.height = '80px';
wrapper.style.pointerEvents = 'none';
wrapper.style.zIndex = '9999';
wrapper.style.maskImage = `linear-gradient(to top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 1) ${fadeLength})`;
wrapper.style.webkitMaskImage = `linear-gradient(to top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 1) ${fadeLength})`;
wrapper.style.transition = 'opacity 0.3s ease-in-out';
const canvas = document.createElement('canvas');
canvas.style.width = '100%';
canvas.style.height = '100%';
canvas.width = window.innerWidth * 2;
canvas.height = parseInt(height, 10) * 2;
wrapper.appendChild(canvas);
document.body.appendChild(wrapper);
const ctx = canvas.getContext('2d');
const confetti = []; // Start with empty array
// Adjust max confettos based on viewport width
const getMaxConfetti = () => {
return window.innerWidth <= 800 ? 25 : 50;
};
let maxConfetti = getMaxConfetti();
animate(ctx, confetti, canvas, maxConfetti);
// Update maxConfetti on resize
window.addEventListener('resize', () => {
canvas.width = window.innerWidth * 2;
canvas.height = parseInt(height, 10) * 2;
maxConfetti = getMaxConfetti();
// Remove excess confetti if viewport becomes smaller
if (confetti.length > maxConfetti) {
confetti.length = maxConfetti;
}
});
window.addEventListener('scroll', () => {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
if (scrollTop > 100) {
wrapper.style.opacity = Math.max(0, 1 - (scrollTop - 100) / 200);
} else {
wrapper.style.opacity = '1';
}
});

topEffect(animateConfetti);
}
});
64 changes: 12 additions & 52 deletions src/mastodon/addons/snow.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
// By Roni Laukkarinen
// Based on snow addon by Roni Laukkarinen
// https://github.com/ronilaukkarinen/mastodon/commit/9bf1563

import { reduceMotion } from 'mastodon/initial_state';
import { topEffect } from 'mastodon/addons/effects';

function animate(ctx, snowflakes, canvas, maxFlakes) {
function animateSnow(ctx, canvas, particles, maxParticles) {
// Check for other effects
if (window.fediday) {
return; // Don't show snow if confetti effect is there
}
ctx.clearRect(0, 0, canvas.width, canvas.height);

// Add new snowflake if we haven't reached the maximum
if (snowflakes.length < maxFlakes && Math.random() < 0.05) { // 5% chance each frame to add a new flake
snowflakes.push({
Expand All @@ -19,6 +21,7 @@ function animate(ctx, snowflakes, canvas, maxFlakes) {
opacity: Math.random() * 0.4 + 0.6
});
}

snowflakes.forEach(flake => {
// Draw snowflake shape
ctx.save();
Expand All @@ -34,69 +37,26 @@ function animate(ctx, snowflakes, canvas, maxFlakes) {
ctx.lineWidth = 1.5;
ctx.stroke();
ctx.restore();
// Update position with gentler movement

// Update position
flake.x += Math.sin(flake.y / 50) * 0.3;
flake.y += flake.speed * 0.5;
if (flake.y > canvas.height) {
flake.y = 0;
flake.x = Math.random() * canvas.width;
}
});

requestAnimationFrame(() => animate(ctx, snowflakes, canvas, maxFlakes));
}

document.addEventListener('DOMContentLoaded', () => {
// Check if reduced motion is enabled
// Don't create snow effect if reduced motion is preferred
if (reduceMotion) {
return; // Don't create snow effect if reduced motion is preferred
return;
}

if (new Date().getMonth() === 11 && new Date().getDate() >= 23 && new Date().getDate() <= 31) {
const height = '80px';
const fadeLength = '40px';
const wrapper = document.createElement('div');
wrapper.classList.add('snow');
wrapper.style.position = 'fixed';
wrapper.style.top = '0';
wrapper.style.left = '0';
wrapper.style.width = '100%';
wrapper.style.height = '80px';
wrapper.style.pointerEvents = 'none';
wrapper.style.zIndex = '9999';
wrapper.style.maskImage = `linear-gradient(to top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 1) ${fadeLength})`;
wrapper.style.webkitMaskImage = `linear-gradient(to top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 1) ${fadeLength})`;
wrapper.style.transition = 'opacity 0.3s ease-in-out';
const canvas = document.createElement('canvas');
canvas.style.width = '100%';
canvas.style.height = '100%';
canvas.width = window.innerWidth * 2;
canvas.height = parseInt(height, 10) * 2;
wrapper.appendChild(canvas);
document.body.appendChild(wrapper);
const ctx = canvas.getContext('2d');
const snowflakes = []; // Start with empty array
// Adjust max flakes based on viewport width
const getMaxFlakes = () => {
return window.innerWidth <= 800 ? 25 : 50;
};
let maxFlakes = getMaxFlakes();
animate(ctx, snowflakes, canvas, maxFlakes);
// Update maxFlakes on resize
window.addEventListener('resize', () => {
canvas.width = window.innerWidth * 2;
canvas.height = parseInt(height, 10) * 2;
maxFlakes = getMaxFlakes();
// Remove excess snowflakes if viewport becomes smaller
if (snowflakes.length > maxFlakes) {
snowflakes.length = maxFlakes;
}
});
window.addEventListener('scroll', () => {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
if (scrollTop > 100) {
wrapper.style.opacity = Math.max(0, 1 - (scrollTop - 100) / 200);
} else {
wrapper.style.opacity = '1';
}
});
topEffect(animateSnow, height='80px', fadeLength=`40px`);
}
});

0 comments on commit a06793a

Please sign in to comment.