scaffolding and first pass for the Follow Me block
This commit is contained in:
parent
fcc9603920
commit
773abd38d9
9 changed files with 187 additions and 25 deletions
|
@ -32,6 +32,12 @@ class Blocks {
|
||||||
'render_callback' => array( self::class, 'render_follower_block' ),
|
'render_callback' => array( self::class, 'render_follower_block' ),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
\register_block_type_from_metadata(
|
||||||
|
ACTIVITYPUB_PLUGIN_DIR . '/build/follow-me',
|
||||||
|
array(
|
||||||
|
'render_callback' => array( self::class, 'render_follow_me_block' ),
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function get_user_id( $user_string ) {
|
private static function get_user_id( $user_string ) {
|
||||||
|
@ -42,6 +48,10 @@ class Blocks {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function render_follow_me_block( $attrs, $content, $block ) {
|
||||||
|
return '<div class="lol">lol!!!!</div>';
|
||||||
|
}
|
||||||
|
|
||||||
public static function render_follower_block( $attrs, $content, $block ) {
|
public static function render_follower_block( $attrs, $content, $block ) {
|
||||||
$followee_user_id = self::get_user_id( $attrs['selectedUser'] );
|
$followee_user_id = self::get_user_id( $attrs['selectedUser'] );
|
||||||
$per_page = absint( $attrs['per_page'] );
|
$per_page = absint( $attrs['per_page'] );
|
||||||
|
|
|
@ -21,7 +21,7 @@ class Blog_User extends User {
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $type = 'Group';
|
protected $type = 'Foooob/';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is Account discoverable?
|
* Is Account discoverable?
|
||||||
|
|
23
src/follow-me/block.json
Normal file
23
src/follow-me/block.json
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schemas.wp.org/trunk/block.json",
|
||||||
|
"name": "activitypub/follow-me",
|
||||||
|
"apiVersion": 3,
|
||||||
|
"version": "1.0.0",
|
||||||
|
"title": "Follow me on the Fediverse",
|
||||||
|
"category": "widgets",
|
||||||
|
"description": "Display your Fediverse identifier so that visitors can follow you.",
|
||||||
|
"textdomain": "activitypub",
|
||||||
|
"icon": "groups",
|
||||||
|
"supports": {
|
||||||
|
"html": false
|
||||||
|
},
|
||||||
|
"attributes": {
|
||||||
|
"selectedUser": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "site"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"editorScript": "file:./index.js",
|
||||||
|
"viewScript": "file:./view.js",
|
||||||
|
"style": "file:./style-index.css"
|
||||||
|
}
|
98
src/follow-me/edit.js
Normal file
98
src/follow-me/edit.js
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { SelectControl, PanelBody, Button } from '@wordpress/components';
|
||||||
|
import { useUserOptions } from '../shared/use-user-options';
|
||||||
|
import apiFetch from '@wordpress/api-fetch';
|
||||||
|
import { useEffect, useState } from '@wordpress/element';
|
||||||
|
const { namespace } = window._activityPubOptions;
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
|
|
||||||
|
function fetchProfile( userId ) {
|
||||||
|
const fetchOptions = {
|
||||||
|
headers: { Accept: 'application/activity+json' },
|
||||||
|
path: `/${ namespace }/users/${ userId }`,
|
||||||
|
};
|
||||||
|
return apiFetch( fetchOptions );
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEFAULT_PROFILE_DATA = {
|
||||||
|
avatar: '',
|
||||||
|
handle: '@well@hello.dolly',
|
||||||
|
name: __( 'Hello Dolly Fan Account', 'fediverse' ),
|
||||||
|
url: '#',
|
||||||
|
};
|
||||||
|
|
||||||
|
function getNormalizedProfile( profile ) {
|
||||||
|
if ( ! profile ) {
|
||||||
|
return DEFAULT_PROFILE_DATA;
|
||||||
|
}
|
||||||
|
profile.handle = generateHandle( profile );
|
||||||
|
const data = { ...DEFAULT_PROFILE_DATA, ...profile };
|
||||||
|
data.avatar = data.icon.url;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateHandle( profile ) {
|
||||||
|
try {
|
||||||
|
const urlObject = new URL( profile.url );
|
||||||
|
const { host, pathname } = urlObject;
|
||||||
|
const first = pathname.replace( /^\//, '' );
|
||||||
|
return `${ first}@${ host }`;
|
||||||
|
} catch ( e ) {
|
||||||
|
return '@error@error';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Edit( { attributes, setAttributes } ) {
|
||||||
|
const [ profile, setProfile ] = useState( getNormalizedProfile() );
|
||||||
|
const { selectedUser } = attributes;
|
||||||
|
const userId = selectedUser === 'site' ? 0 : selectedUser;
|
||||||
|
function setProfileData( profile ) {
|
||||||
|
setProfile( getNormalizedProfile( profile ) );
|
||||||
|
}
|
||||||
|
useEffect( () => {
|
||||||
|
fetchProfile( userId ).then( setProfileData );
|
||||||
|
}, [ userId ] );
|
||||||
|
|
||||||
|
const blockProps = useBlockProps();
|
||||||
|
const usersOptions = useUserOptions();
|
||||||
|
return (
|
||||||
|
<div { ...blockProps }>
|
||||||
|
<InspectorControls key="setting">
|
||||||
|
<PanelBody title={ __( 'Followers Options', 'activitypub' ) }>
|
||||||
|
<SelectControl
|
||||||
|
label= { __( 'Select User', 'activitypub' ) }
|
||||||
|
value={ selectedUser }
|
||||||
|
options={ usersOptions }
|
||||||
|
onChange={ ( value ) => setAttributes( { selectedUser: value } ) }
|
||||||
|
/>
|
||||||
|
</PanelBody>
|
||||||
|
</InspectorControls>
|
||||||
|
<Profile { ...profile } />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Profile( profile ) {
|
||||||
|
const { handle, avatar, name } = profile;
|
||||||
|
return (
|
||||||
|
<div className="activitypub-profile">
|
||||||
|
<img className="activitypub-profile__avatar" src={ avatar } />
|
||||||
|
<div className="activitypub-profile__content">
|
||||||
|
<div className="activitpub-profile__name">{ name }</div>
|
||||||
|
<div className="activitypub-profile__handle">{ handle }</div>
|
||||||
|
</div>
|
||||||
|
<Follow profile={ profile } />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Follow( { profile } ) {
|
||||||
|
return (
|
||||||
|
<Button className="activitypub-profile__follow" isPrimary onClick={ () => console.log( profile ) } >
|
||||||
|
{ __( 'Follow', 'fediverse' ) }
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
5
src/follow-me/index.js
Normal file
5
src/follow-me/index.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { registerBlockType } from '@wordpress/blocks';
|
||||||
|
import { people } from '@wordpress/icons';
|
||||||
|
import edit from './edit';
|
||||||
|
const save = () => null;
|
||||||
|
registerBlockType( 'activitypub/follow-me', { edit, save, icon: people } );
|
23
src/follow-me/style.scss
Normal file
23
src/follow-me/style.scss
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
.editor-styles-wrapper {
|
||||||
|
.activitypub-profile {
|
||||||
|
display: flex;
|
||||||
|
align-items: self-start;
|
||||||
|
border: 1px solid;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 1rem;
|
||||||
|
|
||||||
|
.activitypub-profile__avatar {
|
||||||
|
height: 75px;
|
||||||
|
width: 75px;
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
.activitypub-profile__name {
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
.activitypub-profile__follow {
|
||||||
|
margin-left: auto;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
src/follow-me/view.js
Normal file
1
src/follow-me/view.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
console.log( 'view' );
|
|
@ -1,31 +1,9 @@
|
||||||
import { SelectControl, RangeControl, PanelBody, TextControl } from '@wordpress/components';
|
import { SelectControl, RangeControl, PanelBody, TextControl } from '@wordpress/components';
|
||||||
import { useSelect } from '@wordpress/data';
|
import { useState } from '@wordpress/element';
|
||||||
import { useMemo, useState } from '@wordpress/element';
|
|
||||||
import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
|
import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import { Followers } from './followers';
|
import { Followers } from './followers';
|
||||||
|
import { useUserOptions } from '../shared/use-user-options';
|
||||||
const enabled = window._activityPubOptions?.enabled;
|
|
||||||
|
|
||||||
function useUserOptions() {
|
|
||||||
const users = enabled?.users ? useSelect( ( select ) => select( 'core' ).getUsers( { who: 'authors' } ) ) : [];
|
|
||||||
return useMemo( () => {
|
|
||||||
if ( ! users ) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
const withBlogUser = enabled?.site ? [ {
|
|
||||||
label: __( 'Whole Site', 'activitypub' ),
|
|
||||||
value: 'site'
|
|
||||||
} ] : [];
|
|
||||||
return users.reduce( ( acc, user ) => {
|
|
||||||
acc.push({
|
|
||||||
label: user.name,
|
|
||||||
value: user.id
|
|
||||||
} );
|
|
||||||
return acc;
|
|
||||||
}, withBlogUser );
|
|
||||||
}, [ users ] );
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Edit( { attributes, setAttributes } ) {
|
export default function Edit( { attributes, setAttributes } ) {
|
||||||
const { order, per_page, selectedUser, title } = attributes;
|
const { order, per_page, selectedUser, title } = attributes;
|
||||||
|
|
24
src/shared/use-user-options.js
Normal file
24
src/shared/use-user-options.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { useSelect } from '@wordpress/data';
|
||||||
|
import { useMemo } from '@wordpress/element';
|
||||||
|
const enabled = window._activityPubOptions?.enabled;
|
||||||
|
|
||||||
|
export function useUserOptions() {
|
||||||
|
const users = enabled?.users ? useSelect( ( select ) => select( 'core' ).getUsers( { who: 'authors' } ) ) : [];
|
||||||
|
return useMemo( () => {
|
||||||
|
if ( ! users ) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const withBlogUser = enabled?.site ? [ {
|
||||||
|
label: __( 'Whole Site', 'activitypub' ),
|
||||||
|
value: 'site'
|
||||||
|
} ] : [];
|
||||||
|
return users.reduce( ( acc, user ) => {
|
||||||
|
acc.push({
|
||||||
|
label: user.name,
|
||||||
|
value: user.id
|
||||||
|
} );
|
||||||
|
return acc;
|
||||||
|
}, withBlogUser );
|
||||||
|
}, [ users ] );
|
||||||
|
}
|
Loading…
Reference in a new issue