diff --git a/.github/changelog/1709-from-description b/.github/changelog/1709-from-description new file mode 100644 index 000000000..e163eebad --- /dev/null +++ b/.github/changelog/1709-from-description @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Titles added through a Heading block in the Reactions block now stay properly hidden when there are no reactions. diff --git a/build/reactions/index.asset.php b/build/reactions/index.asset.php index 4d44de3fa..eb61e354b 100644 --- a/build/reactions/index.asset.php +++ b/build/reactions/index.asset.php @@ -1 +1 @@ - array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => '3a159dbba14b00d4163c'); + array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => '49eb4f69734089479cfd'); diff --git a/build/reactions/index.js b/build/reactions/index.js index e9a8d424b..2140e6f1d 100644 --- a/build/reactions/index.js +++ b/build/reactions/index.js @@ -1,3 +1,3 @@ -(()=>{"use strict";var e,t={29:(e,t,n)=>{const r=window.wp.blocks,a=[{attributes:{title:{type:"string",default:"Fediverse reactions"}},supports:{html:!1,align:!0,layout:{default:{type:"constrained",orientation:"vertical",justifyContent:"center"}}},isEligible:e=>!!e.title,migrate(e){const{title:t,...n}=e;return[n,[(0,r.createBlock)("core/heading",{content:t,level:6})]]}}],l=window.React,o=window.wp.blockEditor,i=window.wp.element,s=window.wp.i18n,c=window.wp.components,u=window.wp.apiFetch;var m=n.n(u);function p(){return window._activityPubOptions||{}}const h=({reactions:e})=>{const{defaultAvatarUrl:t}=p(),[n,r]=(0,i.useState)(new Set),[a,o]=(0,i.useState)(new Map),s=(0,i.useRef)([]),c=()=>{s.current.forEach((e=>clearTimeout(e))),s.current=[]},u=(t,n)=>{c();const a=100,l=e.length;n&&o((e=>{const n=new Map(e);return n.set(t,"clockwise"),n}));const i=e=>{const i="right"===e,c=i?l-1:0,u=i?1:-1;for(let e=i?t:t-1;i?e<=c:e>=c;e+=u){const l=Math.abs(e-t),i=setTimeout((()=>{r((t=>{const r=new Set(t);return n?r.add(e):r.delete(e),r})),n&&e!==t&&o((t=>{const n=new Map(t),r=e-u,a=n.get(r);return n.set(e,"clockwise"===a?"counter":"clockwise"),n}))}),l*a);s.current.push(i)}};if(i("right"),i("left"),!n){const e=Math.max((l-t)*a,t*a),n=setTimeout((()=>{o(new Map)}),e+a);s.current.push(n)}};return(0,i.useEffect)((()=>()=>c()),[]),(0,l.createElement)("ul",{className:"reaction-avatars"},e.map(((e,r)=>{const o=a.get(r),i=["reaction-avatar",n.has(r)?"wave-active":"",o?`rotate-${o}`:""].filter(Boolean).join(" "),s=e.avatar||t;return(0,l.createElement)("li",{key:r},(0,l.createElement)("a",{href:e.url,target:"_blank",rel:"noopener noreferrer",onMouseEnter:()=>u(r,!0),onMouseLeave:()=>u(r,!1)},(0,l.createElement)("img",{src:s,alt:e.name,className:i,width:"32",height:"32",onError:e=>{e.target.src=t}})))})))},f=({reactions:e,type:t})=>(0,l.createElement)("ul",{className:"activitypub-reaction-list"},e.map(((e,t)=>(0,l.createElement)("li",{key:t},(0,l.createElement)("a",{href:e.url,className:"reaction-item",target:"_blank",rel:"noopener noreferrer"},(0,l.createElement)("img",{src:e.avatar,alt:e.name,width:"32",height:"32"}),(0,l.createElement)("span",null,e.name)))))),d=({items:e,label:t})=>{const[n,r]=(0,i.useState)(!1),[a,o]=(0,i.useState)(null),[s,u]=(0,i.useState)(e.length),m=(0,i.useRef)(null);(0,i.useEffect)((()=>{if(!m.current)return;const t=()=>{const t=m.current;if(!t)return;const n=t.offsetWidth-(a?.offsetWidth||0)-12,r=Math.max(1,Math.floor((n-32)/22));u(Math.min(r,e.length))};t();const n=new ResizeObserver(t);return n.observe(m.current),()=>{n.disconnect()}}),[a,e.length]);const p=e.slice(0,s);return(0,l.createElement)("div",{className:"reaction-group",ref:m},(0,l.createElement)(h,{reactions:p}),(0,l.createElement)(c.Button,{ref:o,className:"reaction-label is-link",onClick:()=>r(!n),"aria-expanded":n},t),n&&a&&(0,l.createElement)(c.Popover,{anchor:a,onClose:()=>r(!1)},(0,l.createElement)(f,{reactions:e})))};function g({postId:e=null,reactions:t=null,title:n=null}){const{namespace:r}=p(),[a,o]=(0,i.useState)(t),[s,c]=(0,i.useState)(!t);return(0,i.useEffect)((()=>{if(t)return o(t),void c(!1);e?(c(!0),m()({path:`/${r}/posts/${e}/reactions`}).then((e=>{o(e),c(!1)})).catch((()=>c(!1)))):c(!1)}),[e,t]),s?null:a&&Object.values(a).some((e=>e.items?.length>0))?(0,l.createElement)(l.Fragment,null,n&&(0,l.createElement)("h6",null,n),Object.entries(a).map((([e,t])=>t.items?.length?(0,l.createElement)(d,{key:e,items:t.items,label:t.label}):null))):null}const v=e=>{const t=["#FF6B6B","#4ECDC4","#45B7D1","#96CEB4","#FFEEAD","#D4A5A5","#9B59B6","#3498DB","#E67E22"],n=(()=>{const e=["Bouncy","Cosmic","Dancing","Fluffy","Giggly","Hoppy","Jazzy","Magical","Nifty","Perky","Quirky","Sparkly","Twirly","Wiggly","Zippy"],t=["Badger","Capybara","Dolphin","Echidna","Flamingo","Giraffe","Hedgehog","Iguana","Jellyfish","Koala","Lemur","Manatee","Narwhal","Octopus","Penguin"];return`${e[Math.floor(Math.random()*e.length)]} ${t[Math.floor(Math.random()*t.length)]}`})(),r=t[Math.floor(Math.random()*t.length)],a=n.charAt(0),l=document.createElement("canvas");l.width=64,l.height=64;const o=l.getContext("2d");return o.fillStyle=r,o.beginPath(),o.arc(32,32,32,0,2*Math.PI),o.fill(),o.fillStyle="#FFFFFF",o.font="32px sans-serif",o.textAlign="center",o.textBaseline="middle",o.fillText(a,32,32),{name:n,url:"#",avatar:l.toDataURL()}},b=JSON.parse('{"UU":"activitypub/reactions"}');(0,r.registerBlockType)(b.UU,{deprecated:a,edit:function({attributes:e,__unstableLayoutClassNames:t}){const n=(0,o.useBlockProps)({className:t}),[r]=(0,i.useState)({likes:{label:(0,s.sprintf)(/* translators: %d: Number of likes */ /* translators: %d: Number of likes */ +(()=>{"use strict";var e,t={29:(e,t,n)=>{const r=window.wp.blocks,a=[{attributes:{title:{type:"string",default:"Fediverse reactions"}},supports:{html:!1,align:!0,layout:{default:{type:"constrained",orientation:"vertical",justifyContent:"center"}}},isEligible:e=>!!e.title,migrate(e){const{title:t,...n}=e;return[n,[(0,r.createBlock)("core/heading",{content:t,level:6})]]}}],l=window.React,o=window.wp.blockEditor,i=window.wp.element,s=window.wp.i18n,c=window.wp.components,u=window.wp.apiFetch;var m=n.n(u);function p(){return window._activityPubOptions||{}}const f=({reactions:e})=>{const{defaultAvatarUrl:t}=p(),[n,r]=(0,i.useState)(new Set),[a,o]=(0,i.useState)(new Map),s=(0,i.useRef)([]),c=()=>{s.current.forEach((e=>clearTimeout(e))),s.current=[]},u=(t,n)=>{c();const a=100,l=e.length;n&&o((e=>{const n=new Map(e);return n.set(t,"clockwise"),n}));const i=e=>{const i="right"===e,c=i?l-1:0,u=i?1:-1;for(let e=i?t:t-1;i?e<=c:e>=c;e+=u){const l=Math.abs(e-t),i=setTimeout((()=>{r((t=>{const r=new Set(t);return n?r.add(e):r.delete(e),r})),n&&e!==t&&o((t=>{const n=new Map(t),r=e-u,a=n.get(r);return n.set(e,"clockwise"===a?"counter":"clockwise"),n}))}),l*a);s.current.push(i)}};if(i("right"),i("left"),!n){const e=Math.max((l-t)*a,t*a),n=setTimeout((()=>{o(new Map)}),e+a);s.current.push(n)}};return(0,i.useEffect)((()=>()=>c()),[]),(0,l.createElement)("ul",{className:"reaction-avatars"},e.map(((e,r)=>{const o=a.get(r),i=["reaction-avatar",n.has(r)?"wave-active":"",o?`rotate-${o}`:""].filter(Boolean).join(" "),s=e.avatar||t;return(0,l.createElement)("li",{key:r},(0,l.createElement)("a",{href:e.url,target:"_blank",rel:"noopener noreferrer",onMouseEnter:()=>u(r,!0),onMouseLeave:()=>u(r,!1)},(0,l.createElement)("img",{src:s,alt:e.name,className:i,width:"32",height:"32",onError:e=>{e.target.src=t}})))})))},h=({reactions:e,type:t})=>(0,l.createElement)("ul",{className:"activitypub-reaction-list"},e.map(((e,t)=>(0,l.createElement)("li",{key:t},(0,l.createElement)("a",{href:e.url,className:"reaction-item",target:"_blank",rel:"noopener noreferrer"},(0,l.createElement)("img",{src:e.avatar,alt:e.name,width:"32",height:"32"}),(0,l.createElement)("span",null,e.name)))))),d=({items:e,label:t})=>{const[n,r]=(0,i.useState)(!1),[a,o]=(0,i.useState)(null),[s,u]=(0,i.useState)(e.length),m=(0,i.useRef)(null);(0,i.useEffect)((()=>{if(!m.current)return;const t=()=>{const t=m.current;if(!t)return;const n=t.offsetWidth-(a?.offsetWidth||0)-12,r=Math.max(1,Math.floor((n-32)/22));u(Math.min(r,e.length))};t();const n=new ResizeObserver(t);return n.observe(m.current),()=>{n.disconnect()}}),[a,e.length]);const p=e.slice(0,s);return(0,l.createElement)("div",{className:"reaction-group",ref:m},(0,l.createElement)(f,{reactions:p}),(0,l.createElement)(c.Button,{ref:o,className:"reaction-label is-link",onClick:()=>r(!n),"aria-expanded":n},t),n&&a&&(0,l.createElement)(c.Popover,{anchor:a,onClose:()=>r(!1)},(0,l.createElement)(h,{reactions:e})))};function g({postId:e=null,reactions:t=null}){const{namespace:n}=p(),[r,a]=(0,i.useState)(t),[o,s]=(0,i.useState)(!t);return(0,i.useEffect)((()=>{if(t)return a(t),void s(!1);e?(s(!0),m()({path:`/${n}/posts/${e}/reactions`}).then((e=>{a(e),s(!1)})).catch((()=>s(!1)))):s(!1)}),[e,t]),o?null:r&&Object.values(r).some((e=>e.items?.length>0))?(0,l.createElement)(l.Fragment,null,Object.entries(r).map((([e,t])=>t.items?.length?(0,l.createElement)(d,{key:e,items:t.items,label:t.label}):null))):null}const v=e=>{const t=["#FF6B6B","#4ECDC4","#45B7D1","#96CEB4","#FFEEAD","#D4A5A5","#9B59B6","#3498DB","#E67E22"],n=(()=>{const e=["Bouncy","Cosmic","Dancing","Fluffy","Giggly","Hoppy","Jazzy","Magical","Nifty","Perky","Quirky","Sparkly","Twirly","Wiggly","Zippy"],t=["Badger","Capybara","Dolphin","Echidna","Flamingo","Giraffe","Hedgehog","Iguana","Jellyfish","Koala","Lemur","Manatee","Narwhal","Octopus","Penguin"];return`${e[Math.floor(Math.random()*e.length)]} ${t[Math.floor(Math.random()*t.length)]}`})(),r=t[Math.floor(Math.random()*t.length)],a=n.charAt(0),l=document.createElement("canvas");l.width=64,l.height=64;const o=l.getContext("2d");return o.fillStyle=r,o.beginPath(),o.arc(32,32,32,0,2*Math.PI),o.fill(),o.fillStyle="#FFFFFF",o.font="32px sans-serif",o.textAlign="center",o.textBaseline="middle",o.fillText(a,32,32),{name:n,url:"#",avatar:l.toDataURL()}},b=JSON.parse('{"UU":"activitypub/reactions"}');(0,r.registerBlockType)(b.UU,{deprecated:a,edit:function({attributes:e,__unstableLayoutClassNames:t}){const n=(0,o.useBlockProps)({className:t}),[r]=(0,i.useState)({likes:{label:(0,s.sprintf)(/* translators: %d: Number of likes */ /* translators: %d: Number of likes */ (0,s._x)("%d likes","number of likes","activitypub"),9),items:Array.from({length:9},((e,t)=>v()))},reposts:{label:(0,s.sprintf)(/* translators: %d: Number of reposts */ /* translators: %d: Number of reposts */ (0,s._x)("%d reposts","number of reposts","activitypub"),6),items:Array.from({length:6},((e,t)=>v()))}}),a=[["core/heading",{level:6,placeholder:(0,s.__)("Fediverse Reactions","activitypub"),content:(0,s.__)("Fediverse Reactions","activitypub")}]];return(0,l.createElement)("div",{...n},(0,l.createElement)(o.InnerBlocks,{template:a,allowedBlocks:["core/heading"],templateLock:"all",renderAppender:!1}),(0,l.createElement)(g,{reactions:r}))},save:function(){return(0,l.createElement)(l.Fragment,null,(0,l.createElement)(o.InnerBlocks.Content,null),(0,l.createElement)("div",{className:"activitypub-reactions-block"}))}})}},n={};function r(e){var a=n[e];if(void 0!==a)return a.exports;var l=n[e]={exports:{}};return t[e](l,l.exports,r),l.exports}r.m=t,e=[],r.O=(t,n,a,l)=>{if(!n){var o=1/0;for(u=0;u=l)&&Object.keys(r.O).every((e=>r.O[e](n[s])))?n.splice(s--,1):(i=!1,l0&&e[u-1][2]>l;u--)e[u]=e[u-1];e[u]=[n,a,l]},r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={608:0,104:0};r.O.j=t=>0===e[t];var t=(t,n)=>{var a,l,[o,i,s]=n,c=0;if(o.some((t=>0!==e[t]))){for(a in i)r.o(i,a)&&(r.m[a]=i[a]);if(s)var u=s(r)}for(t&&t(n);cr(29)));a=r.O(a)})(); \ No newline at end of file diff --git a/build/reactions/view.asset.php b/build/reactions/view.asset.php index 2f63d937d..e11e98193 100644 --- a/build/reactions/view.asset.php +++ b/build/reactions/view.asset.php @@ -1 +1 @@ - array('react', 'wp-api-fetch', 'wp-components', 'wp-dom-ready', 'wp-element', 'wp-i18n'), 'version' => '2f19592adb33b4030d68'); + array('react', 'wp-api-fetch', 'wp-components', 'wp-dom-ready', 'wp-element', 'wp-i18n'), 'version' => '55dea90f19d1cfa3aa15'); diff --git a/build/reactions/view.js b/build/reactions/view.js index 666da2de3..59f4e583f 100644 --- a/build/reactions/view.js +++ b/build/reactions/view.js @@ -1 +1 @@ -(()=>{"use strict";var e={n:t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return e.d(n,{a:n}),n},d:(t,n)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.React,n=window.wp.element,r=window.wp.domReady;var a=e.n(r);const c=window.wp.components,o=window.wp.apiFetch;var l=e.n(o);function s(){return window._activityPubOptions||{}}window.wp.i18n;const i=({reactions:e})=>{const{defaultAvatarUrl:r}=s(),[a,c]=(0,n.useState)(new Set),[o,l]=(0,n.useState)(new Map),i=(0,n.useRef)([]),u=()=>{i.current.forEach((e=>clearTimeout(e))),i.current=[]},m=(t,n)=>{u();const r=100,a=e.length;n&&l((e=>{const n=new Map(e);return n.set(t,"clockwise"),n}));const o=e=>{const o="right"===e,s=o?a-1:0,u=o?1:-1;for(let e=o?t:t-1;o?e<=s:e>=s;e+=u){const a=Math.abs(e-t),o=setTimeout((()=>{c((t=>{const r=new Set(t);return n?r.add(e):r.delete(e),r})),n&&e!==t&&l((t=>{const n=new Map(t),r=e-u,a=n.get(r);return n.set(e,"clockwise"===a?"counter":"clockwise"),n}))}),a*r);i.current.push(o)}};if(o("right"),o("left"),!n){const e=Math.max((a-t)*r,t*r),n=setTimeout((()=>{l(new Map)}),e+r);i.current.push(n)}};return(0,n.useEffect)((()=>()=>u()),[]),(0,t.createElement)("ul",{className:"reaction-avatars"},e.map(((e,n)=>{const c=o.get(n),l=["reaction-avatar",a.has(n)?"wave-active":"",c?`rotate-${c}`:""].filter(Boolean).join(" "),s=e.avatar||r;return(0,t.createElement)("li",{key:n},(0,t.createElement)("a",{href:e.url,target:"_blank",rel:"noopener noreferrer",onMouseEnter:()=>m(n,!0),onMouseLeave:()=>m(n,!1)},(0,t.createElement)("img",{src:s,alt:e.name,className:l,width:"32",height:"32",onError:e=>{e.target.src=r}})))})))},u=({reactions:e,type:n})=>(0,t.createElement)("ul",{className:"activitypub-reaction-list"},e.map(((e,n)=>(0,t.createElement)("li",{key:n},(0,t.createElement)("a",{href:e.url,className:"reaction-item",target:"_blank",rel:"noopener noreferrer"},(0,t.createElement)("img",{src:e.avatar,alt:e.name,width:"32",height:"32"}),(0,t.createElement)("span",null,e.name)))))),m=({items:e,label:r})=>{const[a,o]=(0,n.useState)(!1),[l,s]=(0,n.useState)(null),[m,p]=(0,n.useState)(e.length),h=(0,n.useRef)(null);(0,n.useEffect)((()=>{if(!h.current)return;const t=()=>{const t=h.current;if(!t)return;const n=t.offsetWidth-(l?.offsetWidth||0)-12,r=Math.max(1,Math.floor((n-32)/22));p(Math.min(r,e.length))};t();const n=new ResizeObserver(t);return n.observe(h.current),()=>{n.disconnect()}}),[l,e.length]);const f=e.slice(0,m);return(0,t.createElement)("div",{className:"reaction-group",ref:h},(0,t.createElement)(i,{reactions:f}),(0,t.createElement)(c.Button,{ref:s,className:"reaction-label is-link",onClick:()=>o(!a),"aria-expanded":a},r),a&&l&&(0,t.createElement)(c.Popover,{anchor:l,onClose:()=>o(!1)},(0,t.createElement)(u,{reactions:e})))};function p({postId:e=null,reactions:r=null,title:a=null}){const{namespace:c}=s(),[o,i]=(0,n.useState)(r),[u,p]=(0,n.useState)(!r);return(0,n.useEffect)((()=>{if(r)return i(r),void p(!1);e?(p(!0),l()({path:`/${c}/posts/${e}/reactions`}).then((e=>{i(e),p(!1)})).catch((()=>p(!1)))):p(!1)}),[e,r]),u?null:o&&Object.values(o).some((e=>e.items?.length>0))?(0,t.createElement)(t.Fragment,null,a&&(0,t.createElement)("h6",null,a),Object.entries(o).map((([e,n])=>n.items?.length?(0,t.createElement)(m,{key:e,items:n.items,label:n.label}):null))):null}a()((()=>{[].forEach.call(document.querySelectorAll(".activitypub-reactions-block"),(e=>{const r=JSON.parse(e.dataset.attrs||e.parentElement.dataset.attrs);(0,n.createRoot)(e).render((0,t.createElement)(p,{...r}))}))}))})(); \ No newline at end of file +(()=>{"use strict";var e={n:t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return e.d(n,{a:n}),n},d:(t,n)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.React,n=window.wp.element,r=window.wp.domReady;var a=e.n(r);const c=window.wp.components,o=window.wp.apiFetch;var s=e.n(o);function l(){return window._activityPubOptions||{}}window.wp.i18n;const i=({reactions:e})=>{const{defaultAvatarUrl:r}=l(),[a,c]=(0,n.useState)(new Set),[o,s]=(0,n.useState)(new Map),i=(0,n.useRef)([]),u=()=>{i.current.forEach((e=>clearTimeout(e))),i.current=[]},m=(t,n)=>{u();const r=100,a=e.length;n&&s((e=>{const n=new Map(e);return n.set(t,"clockwise"),n}));const o=e=>{const o="right"===e,l=o?a-1:0,u=o?1:-1;for(let e=o?t:t-1;o?e<=l:e>=l;e+=u){const a=Math.abs(e-t),o=setTimeout((()=>{c((t=>{const r=new Set(t);return n?r.add(e):r.delete(e),r})),n&&e!==t&&s((t=>{const n=new Map(t),r=e-u,a=n.get(r);return n.set(e,"clockwise"===a?"counter":"clockwise"),n}))}),a*r);i.current.push(o)}};if(o("right"),o("left"),!n){const e=Math.max((a-t)*r,t*r),n=setTimeout((()=>{s(new Map)}),e+r);i.current.push(n)}};return(0,n.useEffect)((()=>()=>u()),[]),(0,t.createElement)("ul",{className:"reaction-avatars"},e.map(((e,n)=>{const c=o.get(n),s=["reaction-avatar",a.has(n)?"wave-active":"",c?`rotate-${c}`:""].filter(Boolean).join(" "),l=e.avatar||r;return(0,t.createElement)("li",{key:n},(0,t.createElement)("a",{href:e.url,target:"_blank",rel:"noopener noreferrer",onMouseEnter:()=>m(n,!0),onMouseLeave:()=>m(n,!1)},(0,t.createElement)("img",{src:l,alt:e.name,className:s,width:"32",height:"32",onError:e=>{e.target.src=r}})))})))},u=({reactions:e,type:n})=>(0,t.createElement)("ul",{className:"activitypub-reaction-list"},e.map(((e,n)=>(0,t.createElement)("li",{key:n},(0,t.createElement)("a",{href:e.url,className:"reaction-item",target:"_blank",rel:"noopener noreferrer"},(0,t.createElement)("img",{src:e.avatar,alt:e.name,width:"32",height:"32"}),(0,t.createElement)("span",null,e.name)))))),m=({items:e,label:r})=>{const[a,o]=(0,n.useState)(!1),[s,l]=(0,n.useState)(null),[m,p]=(0,n.useState)(e.length),f=(0,n.useRef)(null);(0,n.useEffect)((()=>{if(!f.current)return;const t=()=>{const t=f.current;if(!t)return;const n=t.offsetWidth-(s?.offsetWidth||0)-12,r=Math.max(1,Math.floor((n-32)/22));p(Math.min(r,e.length))};t();const n=new ResizeObserver(t);return n.observe(f.current),()=>{n.disconnect()}}),[s,e.length]);const h=e.slice(0,m);return(0,t.createElement)("div",{className:"reaction-group",ref:f},(0,t.createElement)(i,{reactions:h}),(0,t.createElement)(c.Button,{ref:l,className:"reaction-label is-link",onClick:()=>o(!a),"aria-expanded":a},r),a&&s&&(0,t.createElement)(c.Popover,{anchor:s,onClose:()=>o(!1)},(0,t.createElement)(u,{reactions:e})))};function p({postId:e=null,reactions:r=null}){const{namespace:a}=l(),[c,o]=(0,n.useState)(r),[i,u]=(0,n.useState)(!r);return(0,n.useEffect)((()=>{if(r)return o(r),void u(!1);e?(u(!0),s()({path:`/${a}/posts/${e}/reactions`}).then((e=>{o(e),u(!1)})).catch((()=>u(!1)))):u(!1)}),[e,r]),i?null:c&&Object.values(c).some((e=>e.items?.length>0))?(0,t.createElement)(t.Fragment,null,Object.entries(c).map((([e,n])=>n.items?.length?(0,t.createElement)(m,{key:e,items:n.items,label:n.label}):null))):null}a()((()=>{[].forEach.call(document.querySelectorAll(".activitypub-reactions-block"),(e=>{const r=JSON.parse(e.dataset.attrs||e.parentElement.dataset.attrs);(0,n.createRoot)(e).render((0,t.createElement)(p,{...r}))}))}))})(); \ No newline at end of file diff --git a/includes/class-blocks.php b/includes/class-blocks.php index 3de550b65..f09e206c9 100644 --- a/includes/class-blocks.php +++ b/includes/class-blocks.php @@ -182,30 +182,38 @@ public static function register_blocks() { */ public static function render_post_reactions_block( $attrs, $content ) { if ( ! isset( $attrs['postId'] ) ) { - $attrs['postId'] = get_the_ID(); + $attrs['postId'] = \get_the_ID(); } - $args = array( 'data-attrs' => wp_json_encode( $attrs ) ); + // Fallback for v1.0.0 blocks. if ( empty( $content ) ) { - if ( isset( $attrs['title'] ) ) { - $content = '
'; - } else { - $has_comments = \get_comments( - array( - 'post_id' => $attrs['postId'], - 'fields' => 'ids', - 'type' => Comment::get_comment_type_slugs(), - ) - ); - if ( $has_comments ) { - $content = '
' . \__( 'Fediverse Reactions', 'activitypub' ) . '
'; - } + $title = $attrs['title'] ?? \__( 'Fediverse Reactions', 'activitypub' ); + $content = '
' . \esc_html( $title ) . '
' . "\n" + . '
'; + unset( $attrs['title'], $attrs['className'] ); + } + + // Hide the title if there are no comments. + $has_comments = \get_comments( + array( + 'post_id' => $attrs['postId'], + 'fields' => 'ids', + 'type' => Comment::get_comment_type_slugs(), + ) + ); + if ( ! $has_comments ) { + $tags = new \WP_HTML_Tag_Processor( $content ); + + while ( $tags->next_tag( array( 'class_name' => 'wp-block-heading' ) ) ) { + $tags->set_attribute( 'hidden', true ); } + + $content = $tags->get_updated_html(); } - return sprintf( + return \sprintf( '
%2$s
', - get_block_wrapper_attributes( $args ), + \get_block_wrapper_attributes( array( 'data-attrs' => \wp_json_encode( $attrs ) ) ), $content ); } diff --git a/src/reactions/reactions.js b/src/reactions/reactions.js index 0bd36f1e3..9459caf50 100644 --- a/src/reactions/reactions.js +++ b/src/reactions/reactions.js @@ -305,13 +305,11 @@ const ReactionGroup = ( { items, label } ) => { * @param {Object} props Component props. * @param {?number} props.postId The post ID. * @param {?Object} props.reactions Optional reactions data. - * @param {?string} props.title Optional title attribute. * @return {?JSX.Element} The rendered component. */ export function Reactions( { postId = null, reactions: providedReactions = null, - title = null, } ) { const { namespace } = useOptions(); const [ reactions, setReactions ] = useState( providedReactions ); @@ -356,7 +354,6 @@ export function Reactions( { return ( <> - { title &&
{ title }
} { Object.entries( reactions ).map( ( [ key, group ] ) => { if ( ! group.items?.length ) { return null; diff --git a/tests/includes/class-test-blocks.php b/tests/includes/class-test-blocks.php index a39b97b4c..8891b417c 100644 --- a/tests/includes/class-test-blocks.php +++ b/tests/includes/class-test-blocks.php @@ -8,7 +8,7 @@ namespace Activitypub\Tests; use Activitypub\Blocks; -use WP_UnitTestCase; +use Activitypub\Collection\Interactions; /** * Test class for Blocks. @@ -201,4 +201,113 @@ public function test_filter_import_mastodon_post_data_with_reply() { $this->assertStringContainsString( '', $result['post_content'] ); $this->assertStringContainsString( "\n

This is a reply

\n", $result['post_content'] ); } + + /** + * Test the reactions block with deprecated markup. + * + * @covers ::render_post_reactions_block + */ + public function test_render_reactions_block() { + $block_markup = ' + +

Fediverse Custom

+
+'; + $output = do_blocks( $block_markup ); + $expected = '
+ + +
+
'; + + $this->assertSame( $expected, $output ); + + // Reactions block with reactions. + $post_id = $this->get_post_id_with_reactions(); + $block_markup = sprintf( + ' + +

Fediverse Custom

+
+', + $post_id + ); + $output = do_blocks( $block_markup ); + $expected = sprintf( + '
+ +

Fediverse Custom

+
+
', + $post_id + ); + + $this->assertSame( $expected, $output ); + } + + /** + * Test the reactions block with deprecated markup. + * + * @covers ::render_post_reactions_block + */ + public function test_render_reactions_block_with_deprecated_markup() { + $block_markup = ''; + $output = do_blocks( $block_markup ); + $expected = '
+
'; + + $this->assertSame( $expected, $output ); + + $block_markup = ''; + $output = do_blocks( $block_markup ); + $expected = '
+
'; + + $this->assertSame( $expected, $output ); + + // Reactions block with reactions. + $post_id = $this->get_post_id_with_reactions(); + $block_markup = sprintf( '', $post_id ); + $output = do_blocks( $block_markup ); + $expected = '
Fediverse Reactions
+
'; + + $this->assertSame( $expected, $output ); + } + + /** + * Get a post ID with reactions. + * + * @return int Post ID. + */ + private function get_post_id_with_reactions() { + $post_id = self::factory()->post->create(); + + $activity = array( + 'type' => 'Like', + 'actor' => 'https://example.com/users/test', + 'object' => get_permalink( $post_id ), + 'id' => 'https://example.com/activities/like/123', + ); + + // Mock actor metadata. + add_filter( + 'pre_get_remote_metadata_by_actor', + function () { + return array( + 'name' => 'Test User', + 'preferredUsername' => 'test', + 'id' => 'https://example.com/users/test', + 'url' => 'https://example.com/@test', + ); + } + ); + + Interactions::add_reaction( $activity ); + + // Clean up. + remove_all_filters( 'pre_get_remote_metadata_by_actor' ); + + return $post_id; + } }