openvibers/openvibe.shared Commits

4.179.0: Share to OpenVibe Community (#398)

OP OpenVibers committed 3 days ago · 9e321da1a0 · 9 files, +31 −6

* Share: post it to OpenVibe Community

A Community tile beside OpenVibe Chat: it opens Community's new-topic form with the title and the link filled in;
the person picks the forum and posts it themselves. First-party tiles lead the grid and wear the accent. Not on
Community's own pages. Hold the release until Community's /discuss prefill is deployed.

* Share to Community: the form is at /forum/discuss

* The share test expects /forum/discuss

* 4.179.0: Share to OpenVibe Community

Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex 7f9fb8b..ec1d576 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -1,5 +1,12 @@
# Changelog
++## 4.179.0 — 2026-11-09
++
++**Share to OpenVibe Community.** The share sheet (`ov-share.js`) has a Community tile beside OpenVibe Chat: it opens
++Community's new-topic form (`/forum/discuss?title=&body=`) with the title and the link filled in; the person picks the
++forum and posts it themselves. OpenVibe's own places lead the grid and wear the accent. Not shown on Community's own
++pages.
++
## 4.178.0 — 2026-11-09
**What's new reads like news (plan §9).** `shipped.js` uses the tags Blog now writes on every change (`kind`: new,
ddiff --git a/README.md b/README.md
iindex 5641cd1..952289f 100644
---- a/README.md
++++ b/README.md
@@@ -2,7 +2,7 @@
> Versioned UI, the OpenVibe Frame (the navbar, footer and "shipped" views every site sits in), SEO, legal and release-client packages every OpenVibe site renders.
--**Status:** alpha, v4.178.0 (every release is a tag; see [CHANGELOG.md](CHANGELOG.md)). Every deployed
++**Status:** alpha, v4.179.0 (every release is a tag; see [CHANGELOG.md](CHANGELOG.md)). Every deployed
consumer installs a tagged release and none keeps a vendored copy
([docs/migration-plan.md](docs/migration-plan.md) is done); each repository's `package.json` names
the tag it pins.
ddiff --git a/STATUS.json b/STATUS.json
iindex 1168501..1d11bd8 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -4,7 +4,7 @@
"code": true,
"wave": "W2",
"package": "openvibe-shared",
-- "version": "4.178.0",
++ "version": "4.179.0",
"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)",
"deployed": false,
"deployment": "none of its own: a package released as git tags; OpenVibe.Network serves /shared/* from its pinned tag, and a site can serve its own pinned copy (openvibe-shared/serve)",
ddiff --git a/navbar.js b/navbar.js
iindex 564a356..200a74f 100644
---- a/navbar.js
++++ b/navbar.js
@@@ -572,7 +572,7 @@
const NAV_ICONS_REV = '1091daee9c7e'; // sha256(nav-icons.js), first 12 hex: its ?v= (cacheable forever)
// END generated
// The files loaded from beside this one, by content (scripts/sibling-revs.js): a release changes their URLs.
-- const SIBLING_REV = { 'ov-mark.js': 'd7e87def8fff', 'ov-glyphs.js': '6f8c8dd2a10d', 'ov-brand.woff2': '3b4e6a8a5878', 'ov-look.js': '2d3a47d3535c', 'ov-fx.js': '46fce1e2b8db', 'ov-labels.js': 'a30b178391f5', 'ov-forms.js': '20f4ef41d127', 'ov-forms.css': '98cf0f28bb68', 'ov-share.js': '8e55bfe93238', 'ov-share.css': 'cbd18e6ce991', 'search.js': 'bbae7542436f', 'dock.js': '7ff462f31951', 'presence.js': '1b675c37d888', 'panels.js': 'd90bfe987d81', 'surfaces.js': 'e72f5a304f2d', 'notification-ui.js': 'e06f1388b696', 'history.js': '1e6598f78ba4', 'site-switcher.js': '292bea111aa8', 'appbar.js': '1edf7532f228', 'release-watch.js': '25f02a3f0684', 'ov-icons.js': 'ba3981246bc0', 'sso-client.js': '52439265b980', 'overlay.js': 'd18308ab8a63', 'ov-home.js': '631efe800b13', 'nav-slots.js': 'a5af310d62e0', 'ov-wallet.js': '5c4d7fdb448d', 'ov-wallet.css': 'e46f653fa59e' };
++ const SIBLING_REV = { 'ov-mark.js': 'd7e87def8fff', 'ov-glyphs.js': '6f8c8dd2a10d', 'ov-brand.woff2': '3b4e6a8a5878', 'ov-look.js': '2d3a47d3535c', 'ov-fx.js': '46fce1e2b8db', 'ov-labels.js': 'a30b178391f5', 'ov-forms.js': '20f4ef41d127', 'ov-forms.css': '98cf0f28bb68', 'ov-share.js': '44a863d7a267', 'ov-share.css': '45b92b654148', 'search.js': 'bbae7542436f', 'dock.js': '7ff462f31951', 'presence.js': '1b675c37d888', 'panels.js': 'd90bfe987d81', 'surfaces.js': 'e72f5a304f2d', 'notification-ui.js': 'e06f1388b696', 'history.js': '1e6598f78ba4', 'site-switcher.js': '292bea111aa8', 'appbar.js': '1edf7532f228', 'release-watch.js': '25f02a3f0684', 'ov-icons.js': 'ba3981246bc0', 'sso-client.js': '52439265b980', 'overlay.js': 'd18308ab8a63', 'ov-home.js': '631efe800b13', 'nav-slots.js': 'a5af310d62e0', 'ov-wallet.js': '5c4d7fdb448d', 'ov-wallet.css': 'e46f653fa59e' };
// The navbar's icons are filled paths (no Font Awesome CSS needed): the ones above ship here, the rest
// (nav-icons.js) load after first paint when a link, chip or menu row names one, into an empty <svg> of their
// size. Anything unknown, or nav-icons.js failing, falls back to <i class="fa-solid">.
ddiff --git a/ov-share.css b/ov-share.css
iindex afe68ff..2885f6e 100644
---- a/ov-share.css
++++ b/ov-share.css
@@@ -366,3 +366,5 @@ html.ov-share-locked, html.ov-share-locked body { overflow: hidden; overscroll-b
.ov-share { border: 1px solid CanvasText; }
.ov-share-segopt:has(input:checked), .ov-share-radio:has(input:checked) { outline: 2px solid Highlight; }
}
++/* OpenVibe’s own places (Chat, Community) wear the accent, so they read apart from the outside networks. */
++.ov-share-tileic.is-ovchat, .ov-share-tileic.is-ovcommunity { background: color-mix(in srgb, var(--ovs-accent) 16%, transparent); color: var(--ovs-accent); }
ddiff --git a/ov-share.js b/ov-share.js
iindex c69405b..1390fb9 100644
---- a/ov-share.js
++++ b/ov-share.js
@@@ -272,6 +272,7 @@
embed: '<path d="m8.5 8-4.5 4 4.5 4M15.5 8l4.5 4-4.5 4M13.5 5.5l-3 13"/>',
more: '<circle cx="6" cy="12" r="1.4"/><circle cx="12" cy="12" r="1.4"/><circle cx="18" cy="12" r="1.4"/>',
ovchat: '<path d="M5 6.5h14a1.5 1.5 0 0 1 1.5 1.5v8a1.5 1.5 0 0 1-1.5 1.5h-7l-4 3v-3H5A1.5 1.5 0 0 1 3.5 16V8A1.5 1.5 0 0 1 5 6.5z"/>',
++ ovcommunity: '<path d="M4 5.5h9.5A1.5 1.5 0 0 1 15 7v5a1.5 1.5 0 0 1-1.5 1.5H9l-3 2.5v-2.5H4A1.5 1.5 0 0 1 2.5 12V7A1.5 1.5 0 0 1 4 5.5z"/><path d="M18 9.5h2a1.5 1.5 0 0 1 1.5 1.5v4.5A1.5 1.5 0 0 1 20 17h-1v2.5L16 17h-3.5"/>',
};
function tileIcon(id, slug) {
const s = el('span', `ov-share-tileic is-${id}`, { 'aria-hidden': 'true' });
@@@ -360,6 +361,14 @@
close(st, true);
dock.share({ text: o.title ? `${o.title} ${href}` : href, title: o.title || '' });
}]] : [];
++ // OpenVibe Community (4.179.0): start a topic about it. The link opens Community's new-topic form with the title
++ // and the link filled in; the person picks the forum, reads it over and posts it themselves. Not on Community's
++ // own pages, which have their own Discuss.
++ const onCommunity = /(^|\.)openvibe\.community$/.test(String(root.location && root.location.hostname || ''));
++ if (!onCommunity) {
++ const body = `${o.text ? `${o.text}\n\n` : ''}${href}`;
++ first.push(['ovcommunity', 'Community', null, `https://openvibe.community/forum/discuss?title=${E(String(o.title || '').slice(0, 200))}&body=${E(body.slice(0, 4000))}`, null]);
++ }
const room = SHOWN - extra.length - first.length;
const ordered = [...first, ...tiles.slice(0, room), ...extra, ...tiles.slice(room)];
const grid = el('div', 'ov-share-grid', { role: 'group', 'aria-label': 'Send it to' });
ddiff --git a/package-lock.json b/package-lock.json
iindex 85b09b5..be54279 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -1,12 +1,12 @@
{
"name": "openvibe-shared",
-- "version": "4.178.0",
++ "version": "4.179.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "openvibe-shared",
-- "version": "4.178.0",
++ "version": "4.179.0",
"license": "MIT",
"dependencies": {
"jsonwebtoken": "^9.0.0",
ddiff --git a/package.json b/package.json
iindex 1607366..536b8c0 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-shared",
-- "version": "4.178.0",
++ "version": "4.179.0",
"description": "Shared navbar, footer, themes, icons, legal pages, SEO, auth and analytics for every OpenVibe site",
"main": "index.js",
"bin": {
ddiff --git a/test/ov-share-chrome.test.js b/test/ov-share-chrome.test.js
iindex c97a119..85388a1 100644
---- a/test/ov-share-chrome.test.js
++++ b/test/ov-share-chrome.test.js
@@@ -208,6 +208,13 @@ const server = http.createServer((req, res) => {
assert.strictEqual(await p.evaluate(`${q('copy')}.textContent`), 'Copied');
// No Dock on this page (signed out): no OpenVibe Chat tile.
assert.strictEqual(await p.evaluate(`!!${q('to-ovchat')}`), false, 'no OpenVibe Chat without the Dock');
++ // OpenVibe Community is offered to everyone (4.179.0): a link to its new-topic form, the title and the link filled in.
++ const comm = await p.evaluate(`(() => { const a = ${q('to-ovcommunity')}; return a ? { href: a.getAttribute('href'), text: a.textContent, first: document.querySelector('dialog.ov-share .ov-share-grid .ov-share-tile') === a } : null; })()`);
++ assert.ok(comm, 'the Community tile');
++ assert.strictEqual(comm.text, 'Community');
++ assert.ok(comm.first, 'first-party places lead the grid');
++ assert.ok(/^https:\/\/openvibe\.community\/forum\/discuss\?title=[^&]*&body=/.test(comm.href), comm.href);
++ assert.ok(decodeURIComponent(comm.href.split('&body=')[1]).includes('http'), 'the body carries the link');
const x = await p.evaluate(`${q('to-x')}.getAttribute('href')`);
assert.strictEqual(x, 'https://x.com/intent/post?text=A%20robot%20%26%20a%20wave&url=https%3A%2F%2Fvideo.test%2Fv%2F1', 'X gets the title and the link, encoded');
assert.strictEqual(await p.evaluate(`${q('to-x')}.getAttribute('rel')`), 'noopener noreferrer');