Friendica dislikes
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
parent
4990e1eaa7
commit
96a8bcdf82
|
@ -20,6 +20,10 @@ const FAVOURITE_REQUEST = 'FAVOURITE_REQUEST';
|
||||||
const FAVOURITE_SUCCESS = 'FAVOURITE_SUCCESS';
|
const FAVOURITE_SUCCESS = 'FAVOURITE_SUCCESS';
|
||||||
const FAVOURITE_FAIL = 'FAVOURITE_FAIL';
|
const FAVOURITE_FAIL = 'FAVOURITE_FAIL';
|
||||||
|
|
||||||
|
const DISLIKE_REQUEST = 'DISLIKE_REQUEST';
|
||||||
|
const DISLIKE_SUCCESS = 'DISLIKE_SUCCESS';
|
||||||
|
const DISLIKE_FAIL = 'DISLIKE_FAIL';
|
||||||
|
|
||||||
const UNREBLOG_REQUEST = 'UNREBLOG_REQUEST';
|
const UNREBLOG_REQUEST = 'UNREBLOG_REQUEST';
|
||||||
const UNREBLOG_SUCCESS = 'UNREBLOG_SUCCESS';
|
const UNREBLOG_SUCCESS = 'UNREBLOG_SUCCESS';
|
||||||
const UNREBLOG_FAIL = 'UNREBLOG_FAIL';
|
const UNREBLOG_FAIL = 'UNREBLOG_FAIL';
|
||||||
|
@ -28,6 +32,10 @@ const UNFAVOURITE_REQUEST = 'UNFAVOURITE_REQUEST';
|
||||||
const UNFAVOURITE_SUCCESS = 'UNFAVOURITE_SUCCESS';
|
const UNFAVOURITE_SUCCESS = 'UNFAVOURITE_SUCCESS';
|
||||||
const UNFAVOURITE_FAIL = 'UNFAVOURITE_FAIL';
|
const UNFAVOURITE_FAIL = 'UNFAVOURITE_FAIL';
|
||||||
|
|
||||||
|
const UNDISLIKE_REQUEST = 'UNDISLIKE_REQUEST';
|
||||||
|
const UNDISLIKE_SUCCESS = 'UNDISLIKE_SUCCESS';
|
||||||
|
const UNDISLIKE_FAIL = 'UNDISLIKE_FAIL';
|
||||||
|
|
||||||
const REBLOGS_FETCH_REQUEST = 'REBLOGS_FETCH_REQUEST';
|
const REBLOGS_FETCH_REQUEST = 'REBLOGS_FETCH_REQUEST';
|
||||||
const REBLOGS_FETCH_SUCCESS = 'REBLOGS_FETCH_SUCCESS';
|
const REBLOGS_FETCH_SUCCESS = 'REBLOGS_FETCH_SUCCESS';
|
||||||
const REBLOGS_FETCH_FAIL = 'REBLOGS_FETCH_FAIL';
|
const REBLOGS_FETCH_FAIL = 'REBLOGS_FETCH_FAIL';
|
||||||
|
@ -215,6 +223,79 @@ const unfavouriteFail = (status: StatusEntity, error: AxiosError) => ({
|
||||||
skipLoading: true,
|
skipLoading: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const dislike = (status: StatusEntity) =>
|
||||||
|
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||||
|
if (!isLoggedIn(getState)) return;
|
||||||
|
|
||||||
|
dispatch(dislikeRequest(status));
|
||||||
|
|
||||||
|
api(getState).post(`/api/friendica/${status.get('id')}/dislike`).then(function() {
|
||||||
|
dispatch(dislikeSuccess(status));
|
||||||
|
}).catch(function(error) {
|
||||||
|
dispatch(dislikeFail(status, error));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const undislike = (status: StatusEntity) =>
|
||||||
|
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||||
|
if (!isLoggedIn(getState)) return;
|
||||||
|
|
||||||
|
dispatch(undislikeRequest(status));
|
||||||
|
|
||||||
|
api(getState).post(`/api/friendica/${status.get('id')}/undislike`).then(() => {
|
||||||
|
dispatch(undislikeSuccess(status));
|
||||||
|
}).catch(error => {
|
||||||
|
dispatch(undislikeFail(status, error));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleDislike = (status: StatusEntity) =>
|
||||||
|
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||||
|
if (status.disliked) {
|
||||||
|
dispatch(undislike(status));
|
||||||
|
} else {
|
||||||
|
dispatch(dislike(status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const dislikeRequest = (status: StatusEntity) => ({
|
||||||
|
type: DISLIKE_REQUEST,
|
||||||
|
status: status,
|
||||||
|
skipLoading: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const dislikeSuccess = (status: StatusEntity) => ({
|
||||||
|
type: DISLIKE_SUCCESS,
|
||||||
|
status: status,
|
||||||
|
skipLoading: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const dislikeFail = (status: StatusEntity, error: AxiosError) => ({
|
||||||
|
type: DISLIKE_FAIL,
|
||||||
|
status: status,
|
||||||
|
error: error,
|
||||||
|
skipLoading: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const undislikeRequest = (status: StatusEntity) => ({
|
||||||
|
type: UNDISLIKE_REQUEST,
|
||||||
|
status: status,
|
||||||
|
skipLoading: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const undislikeSuccess = (status: StatusEntity) => ({
|
||||||
|
type: UNDISLIKE_SUCCESS,
|
||||||
|
status: status,
|
||||||
|
skipLoading: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const undislikeFail = (status: StatusEntity, error: AxiosError) => ({
|
||||||
|
type: UNDISLIKE_FAIL,
|
||||||
|
status: status,
|
||||||
|
error: error,
|
||||||
|
skipLoading: true,
|
||||||
|
});
|
||||||
|
|
||||||
const bookmark = (status: StatusEntity) =>
|
const bookmark = (status: StatusEntity) =>
|
||||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||||
dispatch(bookmarkRequest(status));
|
dispatch(bookmarkRequest(status));
|
||||||
|
@ -498,12 +579,18 @@ export {
|
||||||
FAVOURITE_REQUEST,
|
FAVOURITE_REQUEST,
|
||||||
FAVOURITE_SUCCESS,
|
FAVOURITE_SUCCESS,
|
||||||
FAVOURITE_FAIL,
|
FAVOURITE_FAIL,
|
||||||
|
DISLIKE_REQUEST,
|
||||||
|
DISLIKE_SUCCESS,
|
||||||
|
DISLIKE_FAIL,
|
||||||
UNREBLOG_REQUEST,
|
UNREBLOG_REQUEST,
|
||||||
UNREBLOG_SUCCESS,
|
UNREBLOG_SUCCESS,
|
||||||
UNREBLOG_FAIL,
|
UNREBLOG_FAIL,
|
||||||
UNFAVOURITE_REQUEST,
|
UNFAVOURITE_REQUEST,
|
||||||
UNFAVOURITE_SUCCESS,
|
UNFAVOURITE_SUCCESS,
|
||||||
UNFAVOURITE_FAIL,
|
UNFAVOURITE_FAIL,
|
||||||
|
UNDISLIKE_REQUEST,
|
||||||
|
UNDISLIKE_SUCCESS,
|
||||||
|
UNDISLIKE_FAIL,
|
||||||
REBLOGS_FETCH_REQUEST,
|
REBLOGS_FETCH_REQUEST,
|
||||||
REBLOGS_FETCH_SUCCESS,
|
REBLOGS_FETCH_SUCCESS,
|
||||||
REBLOGS_FETCH_FAIL,
|
REBLOGS_FETCH_FAIL,
|
||||||
|
@ -546,6 +633,15 @@ export {
|
||||||
unfavouriteRequest,
|
unfavouriteRequest,
|
||||||
unfavouriteSuccess,
|
unfavouriteSuccess,
|
||||||
unfavouriteFail,
|
unfavouriteFail,
|
||||||
|
dislike,
|
||||||
|
undislike,
|
||||||
|
toggleDislike,
|
||||||
|
dislikeRequest,
|
||||||
|
dislikeSuccess,
|
||||||
|
dislikeFail,
|
||||||
|
undislikeRequest,
|
||||||
|
undislikeSuccess,
|
||||||
|
undislikeFail,
|
||||||
bookmark,
|
bookmark,
|
||||||
unbookmark,
|
unbookmark,
|
||||||
toggleBookmark,
|
toggleBookmark,
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { launchChat } from 'soapbox/actions/chats';
|
||||||
import { directCompose, mentionCompose, quoteCompose, replyCompose } from 'soapbox/actions/compose';
|
import { directCompose, mentionCompose, quoteCompose, replyCompose } from 'soapbox/actions/compose';
|
||||||
import { editEvent } from 'soapbox/actions/events';
|
import { editEvent } from 'soapbox/actions/events';
|
||||||
import { groupBlock, groupDeleteStatus, groupKick } from 'soapbox/actions/groups';
|
import { groupBlock, groupDeleteStatus, groupKick } from 'soapbox/actions/groups';
|
||||||
import { toggleBookmark, toggleFavourite, togglePin, toggleReblog } from 'soapbox/actions/interactions';
|
import { toggleBookmark, toggleDislike, toggleFavourite, togglePin, toggleReblog } from 'soapbox/actions/interactions';
|
||||||
import { openModal } from 'soapbox/actions/modals';
|
import { openModal } from 'soapbox/actions/modals';
|
||||||
import { deleteStatusModal, toggleStatusSensitivityModal } from 'soapbox/actions/moderation';
|
import { deleteStatusModal, toggleStatusSensitivityModal } from 'soapbox/actions/moderation';
|
||||||
import { initMuteModal } from 'soapbox/actions/mutes';
|
import { initMuteModal } from 'soapbox/actions/mutes';
|
||||||
|
@ -45,6 +45,7 @@ const messages = defineMessages({
|
||||||
cancel_reblog_private: { id: 'status.cancel_reblog_private', defaultMessage: 'Un-repost' },
|
cancel_reblog_private: { id: 'status.cancel_reblog_private', defaultMessage: 'Un-repost' },
|
||||||
cannot_reblog: { id: 'status.cannot_reblog', defaultMessage: 'This post cannot be reposted' },
|
cannot_reblog: { id: 'status.cannot_reblog', defaultMessage: 'This post cannot be reposted' },
|
||||||
favourite: { id: 'status.favourite', defaultMessage: 'Like' },
|
favourite: { id: 'status.favourite', defaultMessage: 'Like' },
|
||||||
|
disfavourite: { id: 'status.disfavourite', defaultMessage: 'Disike' },
|
||||||
open: { id: 'status.open', defaultMessage: 'Expand this post' },
|
open: { id: 'status.open', defaultMessage: 'Expand this post' },
|
||||||
bookmark: { id: 'status.bookmark', defaultMessage: 'Bookmark' },
|
bookmark: { id: 'status.bookmark', defaultMessage: 'Bookmark' },
|
||||||
unbookmark: { id: 'status.unbookmark', defaultMessage: 'Remove bookmark' },
|
unbookmark: { id: 'status.unbookmark', defaultMessage: 'Remove bookmark' },
|
||||||
|
@ -161,6 +162,14 @@ const StatusActionBar: React.FC<IStatusActionBar> = ({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDislikeClick: React.EventHandler<React.MouseEvent> = (e) => {
|
||||||
|
if (me) {
|
||||||
|
dispatch(toggleDislike(status));
|
||||||
|
} else {
|
||||||
|
onOpenUnauthorizedModal('DISLIKE');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleBookmarkClick: React.EventHandler<React.MouseEvent> = (e) => {
|
const handleBookmarkClick: React.EventHandler<React.MouseEvent> = (e) => {
|
||||||
dispatch(toggleBookmark(status));
|
dispatch(toggleBookmark(status));
|
||||||
};
|
};
|
||||||
|
@ -645,7 +654,7 @@ const StatusActionBar: React.FC<IStatusActionBar> = ({
|
||||||
) : (
|
) : (
|
||||||
<StatusActionButton
|
<StatusActionButton
|
||||||
title={intl.formatMessage(messages.favourite)}
|
title={intl.formatMessage(messages.favourite)}
|
||||||
icon={require('@tabler/icons/heart.svg')}
|
icon={features.dislikes ? require('@tabler/icons/thumb-up.svg') : require('@tabler/icons/heart.svg')}
|
||||||
color='accent'
|
color='accent'
|
||||||
filled
|
filled
|
||||||
onClick={handleFavouriteClick}
|
onClick={handleFavouriteClick}
|
||||||
|
@ -655,6 +664,19 @@ const StatusActionBar: React.FC<IStatusActionBar> = ({
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{features.dislikes && (
|
||||||
|
<StatusActionButton
|
||||||
|
title={intl.formatMessage(messages.disfavourite)}
|
||||||
|
icon={require('@tabler/icons/thumb-down.svg')}
|
||||||
|
color='accent'
|
||||||
|
filled
|
||||||
|
onClick={handleDislikeClick}
|
||||||
|
active={status.friendica.get('disliked')}
|
||||||
|
count={status.friendica.get('dislikes_count')}
|
||||||
|
text={withLabels ? intl.formatMessage(messages.disfavourite) : undefined }
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{canShare && (
|
{canShare && (
|
||||||
<StatusActionButton
|
<StatusActionButton
|
||||||
title={intl.formatMessage(messages.share)}
|
title={intl.formatMessage(messages.share)}
|
||||||
|
|
|
@ -15,7 +15,7 @@ const messages = defineMessages({
|
||||||
|
|
||||||
interface IUnauthorizedModal {
|
interface IUnauthorizedModal {
|
||||||
/** Unauthorized action type. */
|
/** Unauthorized action type. */
|
||||||
action: 'FOLLOW' | 'REPLY' | 'REBLOG' | 'FAVOURITE' | 'POLL_VOTE' | 'JOIN'
|
action: 'FOLLOW' | 'REPLY' | 'REBLOG' | 'FAVOURITE' | 'DISLIKE' | 'POLL_VOTE' | 'JOIN'
|
||||||
/** Close event handler. */
|
/** Close event handler. */
|
||||||
onClose: (modalType: string) => void
|
onClose: (modalType: string) => void
|
||||||
/** ActivityPub ID of the account OR status being acted upon. */
|
/** ActivityPub ID of the account OR status being acted upon. */
|
||||||
|
@ -86,6 +86,9 @@ const UnauthorizedModal: React.FC<IUnauthorizedModal> = ({ action, onClose, acco
|
||||||
} else if (action === 'FAVOURITE') {
|
} else if (action === 'FAVOURITE') {
|
||||||
header = <FormattedMessage id='remote_interaction.favourite_title' defaultMessage='Like a post remotely' />;
|
header = <FormattedMessage id='remote_interaction.favourite_title' defaultMessage='Like a post remotely' />;
|
||||||
button = <FormattedMessage id='remote_interaction.favourite' defaultMessage='Proceed to like' />;
|
button = <FormattedMessage id='remote_interaction.favourite' defaultMessage='Proceed to like' />;
|
||||||
|
} else if (action === 'DISLIKE') {
|
||||||
|
header = <FormattedMessage id='remote_interaction.dislike_title' defaultMessage='Dislike a post remotely' />;
|
||||||
|
button = <FormattedMessage id='remote_interaction.dislike' defaultMessage='Proceed to dislike' />;
|
||||||
} else if (action === 'POLL_VOTE') {
|
} else if (action === 'POLL_VOTE') {
|
||||||
header = <FormattedMessage id='remote_interaction.poll_vote_title' defaultMessage='Vote in a poll remotely' />;
|
header = <FormattedMessage id='remote_interaction.poll_vote_title' defaultMessage='Vote in a poll remotely' />;
|
||||||
button = <FormattedMessage id='remote_interaction.poll_vote' defaultMessage='Proceed to vote' />;
|
button = <FormattedMessage id='remote_interaction.poll_vote' defaultMessage='Proceed to vote' />;
|
||||||
|
|
|
@ -51,6 +51,7 @@ export const StatusRecord = ImmutableRecord({
|
||||||
favourited: false,
|
favourited: false,
|
||||||
favourites_count: 0,
|
favourites_count: 0,
|
||||||
filtered: ImmutableList<string>(),
|
filtered: ImmutableList<string>(),
|
||||||
|
friendica: ImmutableMap<string, any>(),
|
||||||
group: null as EmbeddedEntity<Group>,
|
group: null as EmbeddedEntity<Group>,
|
||||||
in_reply_to_account_id: null as string | null,
|
in_reply_to_account_id: null as string | null,
|
||||||
in_reply_to_id: null as string | null,
|
in_reply_to_id: null as string | null,
|
||||||
|
|
|
@ -343,6 +343,13 @@ const getInstanceFeatures = (instance: Instance) => {
|
||||||
v.software === PLEROMA && gte(v.version, '0.9.9'),
|
v.software === PLEROMA && gte(v.version, '0.9.9'),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see POST /api/friendica/statuses/:id/dislike
|
||||||
|
* @see POST /api/friendica/statuses/:id/undislike
|
||||||
|
* @see GET /api/friendica/statuses/:id/disliked_by
|
||||||
|
*/
|
||||||
|
dislikes: v.software === FRIENDICA && gte(v.version, '2023.03.0'),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ability to edit profile information.
|
* Ability to edit profile information.
|
||||||
* @see PATCH /api/v1/accounts/update_credentials
|
* @see PATCH /api/v1/accounts/update_credentials
|
||||||
|
|
Loading…
Reference in New Issue