pl-api: basic support for pleroma shoutbox

Signed-off-by: Nicole Mikołajczyk <git@mkljczk.pl>
This commit is contained in:
Nicole Mikołajczyk
2025-03-28 21:12:42 +01:00
parent 42c5e6a151
commit e211dad0be
8 changed files with 156 additions and 1 deletions

View File

@ -131,5 +131,7 @@ export {
fetchMeSuccess,
fetchMeFail,
patchMeSuccess,
getMeToken,
getMeUrl,
type MeAction,
};

View File

@ -0,0 +1,59 @@
import { verifyCredentials } from './auth';
import { getMeToken, getMeUrl } from './me';
import type { PlApiClient, ShoutMessage } from 'pl-api';
import type { AppDispatch, RootState } from 'pl-fe/store';
const SHOUTBOX_MESSAGE_IMPORT = 'SHOUTBOX_MESSAGE_IMPORT' as const;
const SHOUTBOX_MESSAGES_IMPORT = 'SHOUTBOX_MESSAGES_IMPORT' as const;
const SHOUTBOX_CONNECT = 'SHOUTBOX_CONNECT' as const;
const importShoutboxMessages = (messages: ShoutMessage[]) => ({
type: SHOUTBOX_MESSAGES_IMPORT,
messages,
});
const importShoutboxMessage = (message: ShoutMessage) => ({
type: SHOUTBOX_MESSAGE_IMPORT,
message,
});
const connectShoutbox = (dispatch: AppDispatch, getState: () => RootState) => {
const state = getState();
const token = getMeToken(state);
const accountUrl = getMeUrl(state);
if (!accountUrl) return;
return dispatch(verifyCredentials(token, accountUrl)).then((account) => {
if (account.__meta.pleroma?.chat_token) {
const socket = state.auth.client.shoutbox.connect(account.__meta.pleroma?.chat_token, {
onMessage: (message) => dispatch(importShoutboxMessage(message)),
onMessages: (messages) => dispatch(importShoutboxMessages(messages)),
});
return dispatch({
type: SHOUTBOX_CONNECT,
socket,
});
}
});
};
type ShoutboxAction =
| {
type: typeof SHOUTBOX_CONNECT;
socket: ReturnType<(InstanceType<typeof PlApiClient>)['shoutbox']['connect']>;
}
| ReturnType<typeof importShoutboxMessages>
| ReturnType<typeof importShoutboxMessage>;
export {
SHOUTBOX_MESSAGES_IMPORT,
SHOUTBOX_MESSAGE_IMPORT,
SHOUTBOX_CONNECT,
importShoutboxMessages,
importShoutboxMessage,
connectShoutbox,
type ShoutboxAction,
};

View File

@ -158,7 +158,7 @@ const Preview: React.FC<PreviewProps> = ({ media, position: [x, y], onPositionCh
</div>
{withFocalPoint && (
<div
className='pointer-events-none absolute h-24 w-24 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white'
className='pointer-events-none absolute size-24 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white'
style={{
top: `${y * 100}%`,
left: `${x * 100}%`,

View File

@ -27,6 +27,7 @@ import plfe from './pl-fe';
import polls from './polls';
import push_notifications from './push-notifications';
import security from './security';
import shoutbox from './shoutbox';
import status_lists from './status-lists';
import statuses from './statuses';
import timelines from './timelines';
@ -56,6 +57,7 @@ const reducers = {
polls,
push_notifications,
security,
shoutbox,
status_lists,
statuses,
timelines,

View File

@ -0,0 +1,28 @@
import { SHOUTBOX_CONNECT, SHOUTBOX_MESSAGES_IMPORT, SHOUTBOX_MESSAGE_IMPORT, type ShoutboxAction } from 'pl-fe/actions/shoutbox';
import type { PlApiClient, ShoutMessage } from 'pl-api';
interface State {
socket: ReturnType<(InstanceType<typeof PlApiClient>)['shoutbox']['connect']> | null;
messages: Array<ShoutMessage>;
}
const initialState: State = {
socket: null,
messages: [],
};
const shoutboxReducer = (state = initialState, action: ShoutboxAction) => {
switch (action.type) {
case SHOUTBOX_CONNECT:
return { ...state, socket: action.socket };
case SHOUTBOX_MESSAGES_IMPORT:
return { ...state, messages: action.messages };
case SHOUTBOX_MESSAGE_IMPORT:
return { ...state, messages: [...state.messages, action.message] };
default:
return state;
}
};
export { shoutboxReducer as default };