Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0675c9f7d8 | |||
| c7d49b383a | |||
| f661eabba1 | |||
| 8c38d38a3a |
@@ -9,6 +9,90 @@ Format: [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/) — versi
|
||||
|
||||
---
|
||||
|
||||
## [0.1.3] — 2026-05-27
|
||||
|
||||
### Fixed — Wink no longer gets stuck
|
||||
|
||||
The v0.1.1 wink was implemented as a static SVG render (left eye drawn as a closed curved line). Once the random 5% chance picked the `wink` tone, the page rendered with one eye closed and stayed that way until the next page reload — and 95% of subsequent reloads went back to a non-wink tone, but if the dashboard sat idle, Buddy was stuck mid-wink indefinitely. David reported it as *"buddy has the wink face but the eye does not unblink."*
|
||||
|
||||
v0.1.2's lower probability (30% → 5%) reduced how often you'd see the stuck state but did not fix the underlying issue.
|
||||
|
||||
v0.1.3 makes the wink a real CSS animation:
|
||||
|
||||
- **sprite.php** no longer renders the left eye as a closed path when tone is `wink` — both eyes are always open circles in the SVG.
|
||||
- **buddy.css** has a new `@keyframes buddyWink` that briefly closes the left eye (`scaleY(0.1)`) for ~250 ms every 2.5 s. The right eye keeps its normal 5 s blink. That asymmetric pattern is what makes it read as a wink rather than a synchronised blink.
|
||||
- The wink animation only runs when the parent has the `buddy-sprite--wink` class, which is still controlled by the same 5% probability gate from v0.1.2.
|
||||
- The mouth (asymmetric smirk), cheek opacity (rosier), and mood label (`Cheeky 😉`) all still differ for the wink tone — those are valid static state changes. Only the eye behaviour moved from static-state to transient-animation.
|
||||
|
||||
Net effect: when the 5% chance fires, Buddy now actually winks (closes left eye, opens it, closes it, opens it, etc., every 2.5 s) instead of freezing one-eye-shut.
|
||||
|
||||
---
|
||||
|
||||
## [0.1.2] — 2026-05-26
|
||||
|
||||
### Tuned — Wink probability lowered from 30% to 5%
|
||||
The wink Easter-egg added in v0.1.1 fired at 30% per page render
|
||||
when Buddy's mood was ≥ 75. Default mood is 80, so most admin
|
||||
visits hit the gate and ~30% of those flipped to wink. Stacked
|
||||
across the main admin page + dashboard widget visible on the same
|
||||
screen, Buddy ended up looking like he had one eye closed all the
|
||||
time — "stuck" rather than "playful".
|
||||
|
||||
Dropped to 5%. Same wink visuals when it fires; just rare enough
|
||||
to feel magical instead of constant. Refresh ~20 times when mood
|
||||
is high and you'll catch one.
|
||||
|
||||
### Changed
|
||||
- **`inc/state.php`**: `buddy_mood_label()` probability gate
|
||||
`mt_rand( 1, 100 ) <= 30` changed to `<= 5`. Docstring updated
|
||||
to reflect new ~5% rate.
|
||||
- **Plugin version bumped**: header + `BUDDY_VERSION` constant
|
||||
0.1.1 → 0.1.2.
|
||||
- **About page** version-history card leads with v0.1.2; v0.1.1
|
||||
demoted.
|
||||
|
||||
### Not changed
|
||||
- Wink visuals (`inc/sprite.php`) — same closed-eye arc, smirk,
|
||||
rosy cheeks when it fires. Just rarer.
|
||||
- All other behavior identical to v0.1.1.
|
||||
|
||||
---
|
||||
|
||||
## [0.1.1] — 2026-05-25
|
||||
|
||||
### Added — Wink expression 😉
|
||||
Buddy now has a fourth mood tone: **`wink`** — one eye closed, an
|
||||
asymmetric smirk, and rosier cheeks. Rendered as a small variant
|
||||
inside the existing inline-SVG sprite (still zero image files, no
|
||||
new assets). When Buddy's overall mood is ≥ 75, there's a ~30%
|
||||
chance on each page render that the wink replaces the standard
|
||||
happy face. Refresh a few times when Buddy is content and you'll
|
||||
catch it.
|
||||
|
||||
Why this commit exists: the v0.1.0 sprite had three tones
|
||||
(happy / neutral / sad). Adding `wink` was the smallest possible
|
||||
demo that the SVG expression engine is properly extensible — every
|
||||
future mood/state/species can be added the same way. ~20 lines of
|
||||
PHP, ~2 lines of CSS, no bundle weight, no dependencies.
|
||||
|
||||
### Changed
|
||||
- **`inc/sprite.php`**: added `wink` to the allowed-tones list.
|
||||
Left eye renders as a closed-eye curve (a small downward arc)
|
||||
instead of the open circle. Right eye stays normal. Mouth shifts
|
||||
to an asymmetric smirk curve. Cheek opacity bumped from 0.55 to
|
||||
0.75 for extra cheekiness.
|
||||
- **`inc/state.php`**: `buddy_mood_label()` now has a 30% chance of
|
||||
returning the wink tone when the overall mood score is ≥ 75.
|
||||
- **`assets/css/buddy.css`**: new `.buddy-widget__mood--wink` and
|
||||
`.buddy-main__mood--wink` rules — warm amber pill matching the
|
||||
cheeky vibe.
|
||||
- **About page** version-history card leads with v0.1.1; v0.1.0
|
||||
demoted to the previous entry.
|
||||
- **Plugin version bumped**: header + `BUDDY_VERSION` constant
|
||||
0.1.0 → 0.1.1.
|
||||
|
||||
---
|
||||
|
||||
## [0.1.0] — 2026-05-25
|
||||
|
||||
**Buddy is born.** First release of a new standalone WordPress plugin extracted-and-rebuilt from the tamagotchi feature that once lived inside A-WP-Notes v1.1.5 (now gracefully retired). Buddy stands on its own as a focused, charming companion plugin for the WordPress dashboard.
|
||||
|
||||
@@ -24,6 +24,17 @@
|
||||
animation-duration: 7s; /* sadder Buddy blinks slower */
|
||||
}
|
||||
|
||||
/* Cheeky wink: when the mood-label picks the 'wink' tone, the LEFT eye
|
||||
runs a faster, more dramatic keyframe that closes for ~250ms every
|
||||
2.5s. The right eye keeps its normal 5s blink — that asymmetry is
|
||||
what makes it read as a wink rather than a synchronised blink.
|
||||
v0.1.3 fix: previously the wink was a static SVG render (left eye
|
||||
drawn as a closed curve), which got stuck on the page until the next
|
||||
render. Now it's a real transient animation, so Buddy unblinks. */
|
||||
.buddy-sprite--wink .buddy-sprite__eye--left {
|
||||
animation: buddyWink 2.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes buddyBob {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-4px); }
|
||||
@@ -32,6 +43,10 @@
|
||||
0%, 92%, 100% { transform: scaleY(1); }
|
||||
94%, 98% { transform: scaleY(0.1); }
|
||||
}
|
||||
@keyframes buddyWink {
|
||||
0%, 80%, 100% { transform: scaleY(1); } /* eye open most of the cycle */
|
||||
85%, 95% { transform: scaleY(0.1); } /* closes briefly = the wink */
|
||||
}
|
||||
|
||||
/* ── Dashboard widget ───────────────────────────────────────────── */
|
||||
|
||||
@@ -57,6 +72,7 @@
|
||||
vertical-align: middle;
|
||||
}
|
||||
.buddy-widget__mood--happy { background:#e8f5ea; color:#1b6f2d; }
|
||||
.buddy-widget__mood--wink { background:#fef3c7; color:#92400e; }
|
||||
.buddy-widget__mood--neutral { background:#f0f0f1; color:#3c434a; }
|
||||
.buddy-widget__mood--sad { background:#fcf0f1; color:#8a2424; }
|
||||
|
||||
@@ -138,6 +154,7 @@
|
||||
vertical-align: middle;
|
||||
}
|
||||
.buddy-main__mood--happy { background:#e8f5ea; color:#1b6f2d; }
|
||||
.buddy-main__mood--wink { background:#fef3c7; color:#92400e; }
|
||||
.buddy-main__mood--neutral { background:#f0f0f1; color:#3c434a; }
|
||||
.buddy-main__mood--sad { background:#fcf0f1; color:#8a2424; }
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Plugin Name: Buddy
|
||||
* Plugin URI: https://icanhelp.ie/buddy
|
||||
* Description: Adopt a small companion that lives in your WordPress dashboard. Its mood reflects your site's health — published posts feed it, outdated plugins make it sick, clearing spam makes it happy. Gamifies WordPress maintenance with a bit of charm.
|
||||
* Version: 0.1.0
|
||||
* Version: 0.1.3
|
||||
* Requires at least: 5.0
|
||||
* Requires PHP: 7.4
|
||||
* Author: David Keane
|
||||
@@ -20,7 +20,7 @@
|
||||
if ( ! defined( 'ABSPATH' ) ) { exit; }
|
||||
|
||||
// Plugin coordinates.
|
||||
if ( ! defined( 'BUDDY_VERSION' ) ) { define( 'BUDDY_VERSION', '0.1.0' ); }
|
||||
if ( ! defined( 'BUDDY_VERSION' ) ) { define( 'BUDDY_VERSION', '0.1.3' ); }
|
||||
if ( ! defined( 'BUDDY_FILE' ) ) { define( 'BUDDY_FILE', __FILE__ ); }
|
||||
if ( ! defined( 'BUDDY_PATH' ) ) { define( 'BUDDY_PATH', plugin_dir_path( __FILE__ ) ); }
|
||||
if ( ! defined( 'BUDDY_URL' ) ) { define( 'BUDDY_URL', plugin_dir_url( __FILE__ ) ); }
|
||||
|
||||
+9
-1
@@ -98,7 +98,15 @@ function buddy_render_about_page() {
|
||||
<h2><?php esc_html_e( 'Version history', 'buddy' ); ?></h2>
|
||||
<ul>
|
||||
<li>
|
||||
<span class="ver">v0.1.0</span> — 25 May 2026 <span class="latest">latest</span><br>
|
||||
<span class="ver">v0.1.2</span> — 26 May 2026 <span class="latest">latest</span><br>
|
||||
<?php esc_html_e( 'Wink, tuned. The Easter-egg wink from v0.1.1 was firing at 30% per render — felt closer to "stuck" than "playful". Dropped to 5%: same cheeky face when it lands, just rare enough to feel like a treat.', 'buddy' ); ?>
|
||||
</li>
|
||||
<li>
|
||||
<span class="ver">v0.1.1</span> — 25 May 2026<br>
|
||||
<?php esc_html_e( 'Cheeky face! New wink expression that occasionally appears when Buddy is in a good mood — one eye closed, asymmetric smirk, rosier cheeks. Pure SVG, no image files. Proof that the expression engine is properly extensible.', 'buddy' ); ?>
|
||||
</li>
|
||||
<li>
|
||||
<span class="ver">v0.1.0</span> — 25 May 2026<br>
|
||||
<?php esc_html_e( 'First release. Phase A complete: Buddy exists. Dashboard widget + dedicated admin page show the SVG character, name, mood label, four stats bars. Self-hosted update checker wired up to Gitea from commit 1. No interactions yet — that\'s next.', 'buddy' ); ?>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
+20
-11
@@ -8,8 +8,10 @@
|
||||
* dog / dragon / sprite / etc.
|
||||
*
|
||||
* Mood tone changes the expression: 'happy' = open smile, 'neutral'
|
||||
* = flat mouth, 'sad' = downturned. Eyes blink via CSS keyframes
|
||||
* regardless of tone (it's always alive).
|
||||
* = flat mouth, 'sad' = downturned, 'wink' = asymmetric smirk + rosier
|
||||
* cheeks + CSS-driven left-eye wink animation. Eyes blink via CSS
|
||||
* keyframes regardless of tone (it's always alive); the wink keyframe
|
||||
* lives in buddy.css alongside the regular blink.
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) { exit; }
|
||||
@@ -23,14 +25,15 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
|
||||
*/
|
||||
function buddy_render_sprite( $species = 'default', $tone = 'happy', $size = 'md' ) {
|
||||
$species = sanitize_key( $species );
|
||||
$tone = in_array( $tone, array( 'happy', 'neutral', 'sad' ), true ) ? $tone : 'happy';
|
||||
$tone = in_array( $tone, array( 'happy', 'neutral', 'sad', 'wink' ), true ) ? $tone : 'happy';
|
||||
$size = in_array( $size, array( 'sm', 'md', 'lg' ), true ) ? $size : 'md';
|
||||
|
||||
// Mouth path varies by tone.
|
||||
$mouth = array(
|
||||
'happy' => 'M 42 60 Q 50 70 58 60', // smile
|
||||
'happy' => 'M 42 60 Q 50 70 58 60', // symmetric smile
|
||||
'neutral' => 'M 42 64 L 58 64', // flat
|
||||
'sad' => 'M 42 66 Q 50 58 58 66', // frown
|
||||
'sad' => 'M 42 66 Q 50 58 58 66', // frown (curves up at edges)
|
||||
'wink' => 'M 42 60 Q 50 70 58 62', // asymmetric smirk — right corner a touch higher
|
||||
);
|
||||
$mouth_d = $mouth[ $tone ];
|
||||
|
||||
@@ -44,12 +47,16 @@ function buddy_render_sprite( $species = 'default', $tone = 'happy', $size = 'md
|
||||
aria-label="<?php echo esc_attr( sprintf( __( 'Buddy is %s', 'buddy' ), $tone ) ); ?>">
|
||||
<!-- body -->
|
||||
<circle cx="50" cy="55" r="32" fill="<?php echo esc_attr( $body_fill ); ?>" stroke="#c9941d" stroke-width="2" />
|
||||
<!-- left eye -->
|
||||
<!-- left eye — always an open circle in the SVG. When the
|
||||
tone is 'wink', the buddy-sprite--wink class on the parent
|
||||
triggers a CSS keyframe animation (buddyWink in buddy.css)
|
||||
that briefly closes this eye every couple of seconds.
|
||||
That way the wink is a transient action, not a stuck state. -->
|
||||
<g class="buddy-sprite__eye buddy-sprite__eye--left">
|
||||
<circle cx="40" cy="46" r="5" fill="#2c3338" />
|
||||
<circle cx="41.2" cy="45" r="1.5" fill="#fff" />
|
||||
</g>
|
||||
<!-- right eye -->
|
||||
<!-- right eye — always open, normal slow blink even during wink -->
|
||||
<g class="buddy-sprite__eye buddy-sprite__eye--right">
|
||||
<circle cx="60" cy="46" r="5" fill="#2c3338" />
|
||||
<circle cx="61.2" cy="45" r="1.5" fill="#fff" />
|
||||
@@ -57,10 +64,12 @@ function buddy_render_sprite( $species = 'default', $tone = 'happy', $size = 'md
|
||||
<!-- mouth -->
|
||||
<path d="<?php echo esc_attr( $mouth_d ); ?>"
|
||||
stroke="#2c3338" stroke-width="2" fill="none" stroke-linecap="round" />
|
||||
<!-- cheeks (only when happy or neutral) -->
|
||||
<?php if ( $tone !== 'sad' ) : ?>
|
||||
<circle cx="33" cy="58" r="3" fill="#f4866a" opacity="0.55" />
|
||||
<circle cx="67" cy="58" r="3" fill="#f4866a" opacity="0.55" />
|
||||
<!-- cheeks: not on the sad face; extra-rosy on the wink (cheeky vibe) -->
|
||||
<?php if ( $tone !== 'sad' ) :
|
||||
$cheek_opacity = ( $tone === 'wink' ) ? '0.75' : '0.55';
|
||||
?>
|
||||
<circle cx="33" cy="58" r="3" fill="#f4866a" opacity="<?php echo esc_attr( $cheek_opacity ); ?>" />
|
||||
<circle cx="67" cy="58" r="3" fill="#f4866a" opacity="<?php echo esc_attr( $cheek_opacity ); ?>" />
|
||||
<?php endif; ?>
|
||||
<!-- tiny feet -->
|
||||
<ellipse cx="42" cy="88" rx="6" ry="3" fill="#c9941d" />
|
||||
|
||||
+12
-2
@@ -101,10 +101,20 @@ function buddy_overall_mood( array $state ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick a one-word emoji / status label based on overall mood. Pure
|
||||
* cosmetic, used in the dashboard widget header.
|
||||
* Pick a one-word status label + sprite tone based on overall mood.
|
||||
* Pure cosmetic, used in the dashboard widget header and the main
|
||||
* admin page.
|
||||
*
|
||||
* Easter-egg: when Buddy is genuinely happy (mood >= 75) there's a
|
||||
* ~5% chance per page-render of returning the "Cheeky" wink tone
|
||||
* instead of the standard happy face. Rare enough to feel magical
|
||||
* rather than disturbing — refresh the page a few dozen times and
|
||||
* you'll catch it.
|
||||
*/
|
||||
function buddy_mood_label( $mood_score ) {
|
||||
if ( $mood_score >= 75 && mt_rand( 1, 100 ) <= 5 ) {
|
||||
return array( 'label' => __( 'Cheeky 😉', 'buddy' ), 'tone' => 'wink' );
|
||||
}
|
||||
if ( $mood_score >= 80 ) { return array( 'label' => __( 'Thriving', 'buddy' ), 'tone' => 'happy' ); }
|
||||
if ( $mood_score >= 60 ) { return array( 'label' => __( 'Content', 'buddy' ), 'tone' => 'happy' ); }
|
||||
if ( $mood_score >= 40 ) { return array( 'label' => __( 'Okay', 'buddy' ), 'tone' => 'neutral' ); }
|
||||
|
||||
Reference in New Issue
Block a user