fix(js): fixes #4452 action buttons not showing externally while mobile (#4547)

This commit is contained in:
Gabe Kangas
2025-09-14 14:28:57 -07:00
committed by GitHub
parent c12ef0ec57
commit 8568f43310
4 changed files with 33 additions and 13 deletions
@@ -3,7 +3,7 @@ import { Button, Dropdown } from 'antd';
import classNames from 'classnames'; import classNames from 'classnames';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import styles from './ActionButtonMenu.module.scss'; import styles from './ActionButtonMenu.module.scss';
import { ExternalAction } from '../../../interfaces/external-action'; import { ExternalAction, ExternalActionUtils } from '../../../interfaces/external-action';
// Lazy loaded components // Lazy loaded components
@@ -50,12 +50,15 @@ export const ActionButtonMenu: FC<ActionButtonMenuProps> = ({
followItemSelected(); followItemSelected();
return; return;
} }
const action = actions.find(x => x.url === a.key); // Find the action using the utility function
externalActionSelected(action); const action = ExternalActionUtils.findByKey(actions, a.key);
if (action) {
externalActionSelected(action);
}
}; };
const items = actions.map(action => ({ const items = actions.map(action => ({
key: action.url, key: ExternalActionUtils.generateKey(action),
label: ( label: (
<span className={styles.item}> <span className={styles.item}>
{action.icon && <img className={styles.icon} src={action.icon} alt={action.title} />}{' '} {action.icon && <img className={styles.icon} src={action.icon} alt={action.title} />}{' '}
+5 -8
View File
@@ -1,7 +1,7 @@
import { Dispatch, FC, SetStateAction } from 'react'; import { Dispatch, FC, SetStateAction } from 'react';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import { Skeleton } from 'antd'; import { Skeleton } from 'antd';
import { ExternalAction } from '../../../interfaces/external-action'; import { ExternalAction, ExternalActionUtils } from '../../../interfaces/external-action';
import { ActionButtonMenu } from '../../action-buttons/ActionButtonMenu/ActionButtonMenu'; import { ActionButtonMenu } from '../../action-buttons/ActionButtonMenu/ActionButtonMenu';
import { ActionButtonRow } from '../../action-buttons/ActionButtonRow/ActionButtonRow'; import { ActionButtonRow } from '../../action-buttons/ActionButtonRow/ActionButtonRow';
import { FollowButton } from '../../action-buttons/FollowButton'; import { FollowButton } from '../../action-buttons/FollowButton';
@@ -17,7 +17,6 @@ interface ActionButtonProps {
setShowFollowModal: Dispatch<SetStateAction<boolean>>; setShowFollowModal: Dispatch<SetStateAction<boolean>>;
setShowNotifyModal: Dispatch<SetStateAction<boolean>>; setShowNotifyModal: Dispatch<SetStateAction<boolean>>;
disableNotifyReminderPopup: () => void; disableNotifyReminderPopup: () => void;
setExternalActionToDisplay: any;
externalActionSelected: (action: ExternalAction) => void; externalActionSelected: (action: ExternalAction) => void;
} }
@@ -37,12 +36,11 @@ const ActionButtons: FC<ActionButtonProps> = ({
setShowNotifyModal, setShowNotifyModal,
disableNotifyReminderPopup, disableNotifyReminderPopup,
externalActions, externalActions,
setExternalActionToDisplay,
externalActionSelected, externalActionSelected,
}) => { }) => {
const externalActionButtons = externalActions.map(action => ( const externalActionButtons = externalActions.map(action => (
<ActionButton <ActionButton
key={action.url || action.html} key={ExternalActionUtils.generateKey(action)}
action={action} action={action}
externalActionSelected={externalActionSelected} externalActionSelected={externalActionSelected}
/> />
@@ -70,13 +68,12 @@ const ActionButtons: FC<ActionButtonProps> = ({
<div className={styles.mobileActionButtons}> <div className={styles.mobileActionButtons}>
{(supportsBrowserNotifications || {(supportsBrowserNotifications ||
supportsBrowserNotifications || supportsBrowserNotifications ||
externalActionButtons.length > 0) && ( externalActions.length > 0) && (
<ActionButtonMenu <ActionButtonMenu
className={styles.actionButtonMenu} actions={externalActions}
showFollowItem={supportFediverseFeatures} showFollowItem={supportFediverseFeatures}
showNotifyItem={supportsBrowserNotifications} showNotifyItem={supportsBrowserNotifications}
actions={externalActions} externalActionSelected={externalActionSelected}
externalActionSelected={setExternalActionToDisplay}
notifyItemSelected={() => setShowNotifyModal(true)} notifyItemSelected={() => setShowNotifyModal(true)}
followItemSelected={() => setShowFollowModal(true)} followItemSelected={() => setShowFollowModal(true)}
/> />
-1
View File
@@ -274,7 +274,6 @@ export const Content: FC = () => {
setShowNotifyModal={setShowNotifyModal} setShowNotifyModal={setShowNotifyModal}
disableNotifyReminderPopup={disableNotifyReminderPopup} disableNotifyReminderPopup={disableNotifyReminderPopup}
externalActions={externalActions || []} externalActions={externalActions || []}
setExternalActionToDisplay={setExternalActionToDisplay}
setShowFollowModal={setShowFollowModal} setShowFollowModal={setShowFollowModal}
externalActionSelected={externalActionSelected} externalActionSelected={externalActionSelected}
/> />
+21
View File
@@ -7,3 +7,24 @@ export interface ExternalAction {
icon?: string; icon?: string;
openExternally?: boolean; openExternally?: boolean;
} }
/**
* Utility functions for working with ExternalAction objects
*/
export namespace ExternalActionUtils {
/**
* Generates a unique key for an external action based on its properties.
* This ensures each action has a unique identifier for React rendering.
*/
export function generateKey(action: ExternalAction): string {
return `${action.title}-${action.url || action.html || 'no-url'}-${action.color || 'no-color'}`;
}
/**
* Finds an action from an array based on a generated key.
* Useful for finding actions in event handlers when only the key is available.
*/
export function findByKey(actions: ExternalAction[], key: string): ExternalAction | undefined {
return actions.find(action => generateKey(action) === key);
}
}