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' ),
|
||||
)
|
||||
);
|
||||
\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 ) {
|
||||
|
@ -42,6 +48,10 @@ class Blocks {
|
|||
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 ) {
|
||||
$followee_user_id = self::get_user_id( $attrs['selectedUser'] );
|
||||
$per_page = absint( $attrs['per_page'] );
|
||||
|
|
|
@ -21,7 +21,7 @@ class Blog_User extends User {
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $type = 'Group';
|
||||
protected $type = 'Foooob/';
|
||||
|
||||
/**
|
||||
* 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 { useSelect } from '@wordpress/data';
|
||||
import { useMemo, useState } from '@wordpress/element';
|
||||
import { useState } from '@wordpress/element';
|
||||
import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Followers } from './followers';
|
||||
|
||||
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 ] );
|
||||
}
|
||||
import { useUserOptions } from '../shared/use-user-options';
|
||||
|
||||
export default function Edit( { attributes, setAttributes } ) {
|
||||
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