From 773abd38d9c2e64bd25c3bbf750919dfc57bdb2b Mon Sep 17 00:00:00 2001 From: Matt Wiebe Date: Wed, 9 Aug 2023 21:44:46 -0500 Subject: [PATCH] scaffolding and first pass for the Follow Me block --- includes/class-blocks.php | 10 +++ includes/model/class-blog-user.php | 2 +- src/follow-me/block.json | 23 +++++++ src/follow-me/edit.js | 98 ++++++++++++++++++++++++++++++ src/follow-me/index.js | 5 ++ src/follow-me/style.scss | 23 +++++++ src/follow-me/view.js | 1 + src/followers/edit.js | 26 +------- src/shared/use-user-options.js | 24 ++++++++ 9 files changed, 187 insertions(+), 25 deletions(-) create mode 100644 src/follow-me/block.json create mode 100644 src/follow-me/edit.js create mode 100644 src/follow-me/index.js create mode 100644 src/follow-me/style.scss create mode 100644 src/follow-me/view.js create mode 100644 src/shared/use-user-options.js diff --git a/includes/class-blocks.php b/includes/class-blocks.php index a59c4df..acd3c5e 100644 --- a/includes/class-blocks.php +++ b/includes/class-blocks.php @@ -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 '
lol!!!!
'; + } + public static function render_follower_block( $attrs, $content, $block ) { $followee_user_id = self::get_user_id( $attrs['selectedUser'] ); $per_page = absint( $attrs['per_page'] ); diff --git a/includes/model/class-blog-user.php b/includes/model/class-blog-user.php index 471f2c5..eea336b 100644 --- a/includes/model/class-blog-user.php +++ b/includes/model/class-blog-user.php @@ -21,7 +21,7 @@ class Blog_User extends User { * * @var string */ - protected $type = 'Group'; + protected $type = 'Foooob/'; /** * Is Account discoverable? diff --git a/src/follow-me/block.json b/src/follow-me/block.json new file mode 100644 index 0000000..48d18ee --- /dev/null +++ b/src/follow-me/block.json @@ -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" +} \ No newline at end of file diff --git a/src/follow-me/edit.js b/src/follow-me/edit.js new file mode 100644 index 0000000..8ba21e9 --- /dev/null +++ b/src/follow-me/edit.js @@ -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 ( +
+ + + setAttributes( { selectedUser: value } ) } + /> + + + +
+ ); +} + +function Profile( profile ) { + const { handle, avatar, name } = profile; + return ( +
+ +
+
{ name }
+
{ handle }
+
+ +
+ ); +} + +function Follow( { profile } ) { + return ( + + ); +} + diff --git a/src/follow-me/index.js b/src/follow-me/index.js new file mode 100644 index 0000000..550af60 --- /dev/null +++ b/src/follow-me/index.js @@ -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 } ); \ No newline at end of file diff --git a/src/follow-me/style.scss b/src/follow-me/style.scss new file mode 100644 index 0000000..86bc5fe --- /dev/null +++ b/src/follow-me/style.scss @@ -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; + } + } +} \ No newline at end of file diff --git a/src/follow-me/view.js b/src/follow-me/view.js new file mode 100644 index 0000000..24f37fd --- /dev/null +++ b/src/follow-me/view.js @@ -0,0 +1 @@ +console.log( 'view' ); \ No newline at end of file diff --git a/src/followers/edit.js b/src/followers/edit.js index 80156bb..1b72d71 100644 --- a/src/followers/edit.js +++ b/src/followers/edit.js @@ -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; diff --git a/src/shared/use-user-options.js b/src/shared/use-user-options.js new file mode 100644 index 0000000..c43723b --- /dev/null +++ b/src/shared/use-user-options.js @@ -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 ] ); +} \ No newline at end of file