v1.5.0 Latest
New
- Brand-new admin UI - every screen was rewritten as a clean card-panel layout with a sidebar, proper page header, and plain-English labels. No more legacy wrapper chrome.
- "WB Plugins" hub - all Wbcom plugins now share a single top-level menu with a card-grid dashboard, so the admin sidebar stays tidy even when a site runs the full community bundle. Legacy (un-migrated) Wbcom plugins coexist cleanly with the new hub.
- Overview dashboard with live counts of total messages, unique senders, unique recipients, and members with the Contact Me button on, plus a snapshot of the current configuration at a glance.
- Dedicated Notifications, Email Template, Access, and License tabs - each one focused on a single decision so site owners don't have to hunt across screens.
- License tab directly inside Contact Me - enter, activate, and check your license key without leaving the plugin's admin page.
Improve
- The inbox list view (`/members/{user}/contact/`) is now ready for accounts with thousands of received messages. The schema migration that adds the supporting indexes is hardened for the 500-site rollout: it skips on AJAX / REST / cron / WP-CLI requests, takes a 60-second `wp_cache_add()` lock so simultaneous page loads don't both fire `ALTER TABLE`, and verifies via `SHOW INDEX` that every required key actually exists post-`dbDelta()` before bumping `bcm_db_version`. On managed hosts where the DB user lacks `ALTER` privilege, `dbDelta()` silently does nothing - without the verify step we'd mark the migration "done" and the perf fix would never land. Now the version stays at the old value, the next page retries, and an `error_log()` line surfaces under `WP_DEBUG` so admins can see why. Added a composite index `(reciever, datetime, id)` plus a single-column `(reciever)` index to the `contact_me` table via a `dbDelta` migration that runs once on upgrade - existing installs pick this up automatically on the next page load with no manual intervention. EXPLAIN before the fix showed `type: ALL` + `Using filesort` (full table scan + in-memory sort on every page load); after, the same query plans as `type: ref` with no filesort. The total-count query (`COUNT(*) WHERE reciever = %d`) is now also index-covered.
- A user's unread-messages count on the inbox header now uses a dedicated `SELECT COUNT(*)` against `wp_bp_notifications` instead of loading every unread ID into PHP and counting the array. Sites with members carrying thousands of stale notifications no longer pay a multi-megabyte memory hit per inbox render.
- The "Unread" filter no longer builds an unbounded `WHERE id IN (...)` clause. The notification-IDs lookup is now capped at 1,000 rows; users with more than 1,000 unread messages see the most recent 1,000 with a hint to clear notifications. Prevents `max_allowed_packet` errors on extreme accounts.
- Inbox row rendering now batch-prefetches all sender users via `cache_users()` before the loop, eliminating the per-row `bp_core_get_user_displayname()` / `bp_members_get_user_url()` cache misses that previously fired N+1 queries on a cold cache.
- Public REST layer refactored - every `wp.apiFetch` call now goes through a centralised `bcmApi()` wrapper that attaches a 15-second AbortSignal ceiling. Previously, a hung REST server could leave the contact form's submit button or inbox delete button in a permanent loading state with no recovery. The wrapper ensures the `.catch` handler always fires within the timeout window so the UI re-enables.
- Consolidated the duplicated confirm-and-delete flow (previously copy-pasted between the single-message page and the inbox row) into a single `confirmDeleteMessage()` helper. Behaviour identical for site owners; future regressions in delete UX are now impossible by construction.
- Access tab uses a role-chip grid with select-all / clear-all actions instead of a selectize dropdown. Much friendlier on mobile and faster to scan.
- Admin assets load only on our own screens and the shared hub - other admin pages are untouched, reducing conflicts with third-party plugins.
- Toast notifications and an accessible confirmation modal replace browser alerts and confirms across the admin.
- Plain-language labels across every settings screen - "Notify the recipient", "Send a copy to…", "Who can send messages", "Who can be contacted". No jargon or internal option names.
- Per-recipient email delivery by default (each recipient gets their own email) with an explicit toggle for the multi-recipient "show other recipients" mode.
- Activation routine bookmarks the current plugin version so future upgrades have a reliable comparison point.
Fix
- The frontend Contact tab no longer paints WordPress-admin blue (#2271b1) over the active theme. The default palette is now neutral (dark grey on light, light grey on dark), so themes like BuddyX, BuddyX Pro, BuddyBoss, and Reign keep their accent color in info banners, link hovers, focus rings, unread-message tints, and the inbox count pill. A theme-overlay layer that maps these tokens onto theme variables will follow in a future release. (basecamp 9890995245)
- The inbox notification count badge ("All [N]", "Unread [N]") no longer hardcodes blue. The badge now renders in the same neutral primary as the rest of the plugin, so it sits naturally inside whatever theme is active instead of fighting the theme's notification color. (basecamp 9890995245)
- Contact tab now follows the host theme's dark mode on BuddyX, BuddyX Pro, and Reign - the inbox, message view, and intro card use a dark surface with readable text instead of staying light.
- Delete confirmation popup renders dark in dark mode, with a clearly readable title, message, and buttons.
- "Send private message" and "Delete" button colours are now correct and high-contrast in dark mode, including hover, so the theme can no longer wash them out.
- "Settings saved" and other status messages keep readable contrast in dark mode.
Security
- License activation and deactivation handlers (EDD updater) now require the `manage_options` capability in addition to the existing nonce check. Nonce alone is CSRF protection, not authorization; gating to admins prevents lower-privileged logged-in users with the nonce from writing license options.
Compat
- Tested against WordPress 6.9, BuddyPress 14.x, BuddyBoss Platform, and PHP 8.4.
Note
- Introduced `--bcm-color-on-primary` so every primary-background surface (submit button, badge pills, pagination, confirm dialog, message-view primary action) auto-inverts text color in dark mode without per-rule overrides.
- Onboarded the plugin into the Wbcom audit/manifest pattern - `audit/manifest.json`, `audit/FEATURE_AUDIT.md`, `audit/CODE_FLOWS.md`, `audit/ROLE_MATRIX.md`, and `audit/graph.html` now ship in the repo so future contributors can answer "what does this plugin do?" without grepping. `CLAUDE.md` carries a READ-FIRST pointer at the top.