Releases: mikefreemantn/SourceHub
v2.2.0 - Message Reactions & Enhancements
🎉 New Features
Message Reactions System
- 6 Emoji Reactions: 👍 👎 ❤️ 😂 🎉 🤔
- Hover-based Picker: Reaction options appear when hovering over messages
- Reaction Display: Shows counts and user names who reacted
- Visual Feedback: Your reactions are highlighted in green
Message Menu (3-Dot Menu)
- Copy Text: Copy message content to clipboard with visual confirmation
- Delete Message: Anyone can delete any message (admin environment)
- Clean UI: Discord-style dropdown menu
🐛 Bug Fixes
- Fixed OG tag preview infinite reload loop
- Fixed OG preview disappearing after a few seconds
- OG data now cached and persists across message refreshes
- Fixed data-message-id attribute for proper element selection
🗄️ Database Changes
- New Table:
wp_sourcehub_message_reactions- Stores reaction_type, user_id, message_id, created_at
- Action Required: Deactivate and reactivate plugin to create the new table
📦 Installation
Download the latest release and install via WordPress admin or use GitUpdater for automatic updates.
⚠️ Impo## ⚠️ Impo## ⚠️ Impo## ⚠️ Impo## ⚠️ Impo## ⚠️ Impo## ⚠er updating to create the reactions table
- Message reactions feature requires the new database table to function
- All users can - All user message (designed f- All users can - All user message (designed f- All users can - All user m0
- Deactivate the plugin
- Reactivate the plugin (creates new database table)
- Test message reactions and menu features
v2.1.0 - Complete Messaging System with Notifications
New Features
- Automatic Link Previews: URLs in messages automatically display Open Graph data with images, titles, and descriptions
- Sound Notifications: Different notification sounds for individual messages (individualmessage.mp3) and group messages (groupmessage.mp3)
- Group Name in Notifications: Group message notifications now display 'Sender in GroupName' format
- Image Thumbnails: Notification popups show image previews when messages contain attachments
- Real-time Badge Updates: Unread message badges clear immediately when messages are read
- Infinite Scroll: Load older messages by scrolling up in conversations
Improvements
- Fixed group creation to work with new database schema
- Added missing AJAX handler for updating group names
- Fixed remove member from group functionality
- Notification clicks now open the correct group or conversation
- Online indicator properly posi- Online indicator properly posi- Online indicator properly posi- Online indicator properly posi- Online indicatle- Online indicator properly posi- Online indicator properly posi- Online indicator properly posi- Online indicator properle - Online indicator properly posi- Online indicator properly posi- Online indicator properly posi- Online indicator properly posi- Online indior- Online indicator properly posi- Online indicator properly posi- Online indicator properly posi- Onldat- Online indicator properly posi- Online indicator properly posi- Online indicator properly posess Heartbeat API for real-time updates
- Implemented proper AJAX handlers for all messaging oper- Implemented proper AJAX handlers for all messaging oper- Implemellation Not- ImplementedT**- Implemented proper AJAX handlers for all messagid reac- Implemented proper AJAX handlers for all messatabase tables.
v2.0.2.8 - Fix Spoke Dashboard Last Sync Display
Fix: Spoke Dashboard Last Sync Display
This release fixes the spoke dashboard showing scheduled post publish date instead of actual sync time.
Problem
- Dashboard query used post_date (scheduled publish date like 5/18/26 @ 1PM) instead of actual sync timestamp
- For scheduled posts, this showed the future publish date instead of when the post was actually synced
- Example: Post synced on 4/17/26 morning but scheduled for 5/18/26 @ 1PM showed 5/18/26 8:00 AM as Last Sync
- Time was also showing in UTC instead of site's local timezone
Solution
- Modified dashboard query to use _sourcehub_last_sync meta field instead of post_date
- Checks last 100 synced posts and finds the most recent _sourcehub_last_sync timestamp
- Falls back to _sourcehub_received_at if _sourcehub_last_sync not found
- Time display already uses site's local timezone via get_date_from_gmt() in time_ago() function
- Result: Dashboard no- Result: Dashboard no- Result: Dashboard no- Result: Dashboard no- Result: Dashboard no- Result: Dashboard no- Result: Dashboard no- R-so- Result: Dashboard no- Result: Dashboard no- Result: Dashboard no- Result: Dashboard no- Result: Dreased posts_per_p- Result: Dashboard no- Result: Dashboard no- Result: Dashboard no- Result: Dashboard no- Result: Dashboard mp- Result: Dashboard no- Result: Dashboard no- Result: Dashboard no- Result: Dashboard no- Result: ync
- Timezone conversion already handled by existing time_ago() function using get_date_from_gmt()
Impact
- Spoke dashboard now accurately shows when last sync occurred
- No longer misleading for scheduled posts
- Displays time in site's local timezone (not UTC)
- More accur- More accur- More accur- More accur- More accur- More accur- More accur- More accur- (fixes dashboard display)
- Hub sites: No changes needed for this fix
Files Changed
- admin/class-sourcehub-admin.php
- sourcehub.php
- CHANGELOG.md
v2.0.2.7 - Fix Duplicate UPDATE Requests from Race Condition Prevention
Critical Fix: Duplicate UPDATE Prevention for Race Conditions
This release fixes the hub sending multiple UPDATE requests when race condition prevention creates one post but multiple jobs report completion.
Problem
- Hub sends multiple simultaneous CREATE requests (due to duplicate delayed sync triggers)
- Spoke race condition prevention creates only ONE post but ALL job IDs send completion callbacks
- Hub receives multiple callbacks with same spoke_post_id but different job IDs
- Hub tracks all job IDs in sync_status and tries to UPDATE each one
- Result: Multiple UPDATE requests sent to same spoke post
- Example: 3 CREATE jobs → 1 post created, 2 race-prevented → 3 callbacks → hub tries to send 3 UPDATEs
Solution
- Deduplicate syndicated_spokes before sending UPDATEs by mapping spoke_post_id to connection_id
- Only send ONE UPDATE per unique spoke post instead of one per - Only send ONE UPDATE per unique spoke post instead of one per - Only send ONE UPDATE per unique spoke post instead of one per - Only send ONE UPDATE per unique spoke post instead UPD- Only send ONE UPDATE per unique spoke post instead of one per - Only send ONE UPDATE per unique spoke post instead of one per - Only send ONete(- Only sect - Only send ONE UPDATE per unique spoke post instead of one per - Only send ONE UPDATE peto- Only send ONE UPDATE per unique spoke post instead of one per - Only send ONE UPDATE per uniqura- Only send ONE UPDATE per unique spoke post instead of one per - Only send OPDA- Only send ONE UPDATE per unique spoke post instead of one per - Oup- Only send ONE UPDATE per unique spoke post instead of oand potential for conflicts
- Maintains all existing race condition prevention benefits
- Backward compatible with older spoke- Backward compatible with older spoke- Backward compatible with older spoke- Backward coATE prevention)
- Spoke sites: Update to v2.0.2.7 (recommended but not required - already sends post IDs correctly)
Files Changed
- includes/class-sourcehub-hub-manager.php
- includes/class-sourcehub-spoke-manager.php
- sourcehub.php
- CHANGELOG.md
v2.0.2.6 - Fix Hub Status Tracking for Stuck Posts
Critical Fix: Accurate Status Tracking
This release fixes the hub showing posts as completed when they are actually stuck in draft on spoke sites.
Problem
- Hub was clearing status transient immediately after sending requests, before callbacks were received
- syndicate_post() cleared transient after sending CREATE requests
- update_syndicated_post() cleared transient after sending UPDATE requests
- If delayed sync failed or UPDATE never fired, hub had no status tracking
- UI would show completed even when spokes were stuck in draft state
- This masked the real issue: delayed sync not firing in poor hosting environments
Solution
- Removed premature delete_transient() calls from both functions
- Transient now only cleared in handle_sync_complete() when all callbacks received
- Hub now accurately shows which spokes are stuck vs completed
- Each spoke tracked independently - one failure does not affect others
Impact
- Hub status accurately reflects actual spoke state (draft vs published)
- Admins can identify which posts need manual intervention
- Reveals underlying issues (delayed sync failures, Action Scheduler problems)
- No impact on successful syncs - they still complete normally
- Each spoke operates independently - partial failures visible
Technical Details
- Modified syndicate_post() in class-sourcehub-hub-manager.php (line 2195-2198)
- Modified update_syndicated_post() in class-sourcehub-hub-manager.php (line 2396-2399)
- Removed delete_transient calls from both functions
- Transient clearing logic remains in handle_sync_complete() (lines 395-398)
- Only clears when all spokes report back (success OR failure)
Deployment
- Hub sites: Update to v2.0.2.6 (fixes status tracking)
- Spoke sites: Can stay on v2.0.2.4 or v2.0.2.5 (no spoke-side changes)
Files Changed
- includes/class-sourcehub-hub-manager.php
- sourcehub.php
- CHANGELOG.md
v2.0.2.5 - Fix Duplicate UPDATE Calls
Critical Fix: Duplicate UPDATE Prevention (Part 2)
This release fixes the remaining duplicate UPDATE issue found in v2.0.2.4 where was calling twice internally within a single execution.
Problem
- v2.0.2.4's delayed sync lock prevented the function from running twice, but didn't prevent duplicate calls WITHIN a single execution
- had multiple code paths that both called
- When flag was set AND existed, both paths would execute
- Result: Two UPDATE requests sent in the same second with different job IDs
Solution
- Modified to only call once when completing drafts
- Other code paths now skip and log warnings instead of calling update again
- Added warning for debugging edge cases
- Result: Only ONE UPDATE request sent per delayed sync execution
Technical Details
- Modified in (lines 3157-3185)
- Changed else-if branches to skip updates and log warnings instead of calling
- Only the path calls now
- Added warning logs for unexpected states
Deployment
- Hub sites: Update to v2.0.2.5 (fixes duplicate UPDATEs)
- Spoke sites: Can stay on v2.0.2.4 (already has hub wake-up fix)
Files Changed
v2.0.2.2 - Fix Callback Processing Bug
What's Fixed
- Critical bug fix: Prevents HTTP 500 errors when processing spoke callbacks
- Adds array safety check for meta value in function
- Eliminates 30-second retry delays caused by callback crashes
- Improves syndication reliability and speed
Technical Details
The hub was calling on a potentially non-array value when logging callback completion, causing a TypeError in PHP 8+. This resulted in:
- HTTP 500 responses to spoke callbacks
- Forced 30-second retry delays
- Missing sync_completed log entries
The fix adds proper array validation before using the value, matching the pattern used throughout the rest of the codebase.
Impact
- Callbacks now succeed immediately instead of requiring retries
- Faster syndication completion times
- More reliable callback processing
- Cleaner hub logs
v2.0.2.1 - Critical Syndication Retry Fixes
New Features
- 1-minute retry checks (was hourly) with 6 quick retries (1 min apart, 6 min total)
- Post Syndication Logs clear button for manual cleanup of failed posts
- 24-hour age limit for retries to prevent processing ancient stuck posts
Bug Fixes
- Fixed delayed sync not scheduling when spoke count mismatched expected callbacks
- Fixed HTTP 200 responses with error payloads being incorrectly marked as success
- Fixed delayed sync trying to update spokes that failed initial draft creation
- Fixed failed update statuses being overwritten by old success statuses from database
- Fixed failed spokes excluded from syndicated array preventing retry logic
- Fixed Custom Smart Links permission check (now allows Editors, not just Admins)
Improvements
- Webhook spam prevention - max 2 webhooks per failure (initial + permanent)
- All spokes included in syndicated array regardless of success/failure
- Retry attempts logged as WARNING (no webhook), initial/permanent failures as ERROR (webhook)
- Failed spokes properly tracked and eligible for auto-retry logic
- Delayed sync skips spokes that failed initial creation to prevent errors
Technical Details
This release addresses critical issues with the syndication retry system that could cause posts to get stuck in processing state or fail to publish to all spokes when one spoke experienced temporary issues.
v2.0.1.4
Error notification system with email/webhook support, collapsible settings, and bug fixes
v2.0.1.3
Full Changelog: v2.0.1.2...v2.0.1.3