diff --git a/packages/pl-api/lib/client.ts b/packages/pl-api/lib/client.ts index 8ef031a25..6eded1f83 100644 --- a/packages/pl-api/lib/client.ts +++ b/packages/pl-api/lib/client.ts @@ -5267,7 +5267,7 @@ class PlApiClient { public readonly events = { /** * Creates an event - * @see {@link https://github.com/mkljczk/pl/blob/fork/docs/development/API/pleroma_api.md#apiv1pleromaevents} + * @see {@link https://codeberg.org/mkljczk/nicolex/src/branch/develop/docs/development/API/pleroma_api.md#api-v1-pleroma-events} */ createEvent: async (params: CreateEventParams) => { const response = await this.request('/api/v1/pleroma/events', { method: 'POST', body: params }); @@ -5277,7 +5277,7 @@ class PlApiClient { /** * Edits an event - * @see {@link https://github.com/mkljczk/pl/blob/fork/docs/development/API/pleroma_api.md#apiv1pleromaeventsid} + * @see {@link https://codeberg.org/mkljczk/nicolex/src/branch/develop/docs/development/API/pleroma_api.md#api-v1-pleroma-events-id} */ editEvent: async (statusId: string, params: EditEventParams) => { const response = await this.request(`/api/v1/pleroma/events/${statusId}`, { method: 'PUT', body: params }); @@ -5287,21 +5287,21 @@ class PlApiClient { /** * Gets user's joined events - * @see {@link https://github.com/mkljczk/pl/blob/fork/docs/development/API/pleroma_api.md#apiv1pleromaeventsjoined_events} + * @see {@link https://codeberg.org/mkljczk/nicolex/src/branch/develop/docs/development/API/pleroma_api.md#api-v1-pleroma-events-joined_events} */ getJoinedEvents: async (state?: 'pending' | 'reject' | 'accept', params?: GetJoinedEventsParams) => this.#paginatedGet('/api/v1/pleroma/events/joined_events', { params: { ...params, state } }, statusSchema), /** * Gets event participants - * @see {@link https://github.com/mkljczk/pl/blob/fork/docs/development/API/pleroma_api.md#apiv1pleromaeventsidparticipations} + * @see {@link https://codeberg.org/mkljczk/nicolex/src/branch/develop/docs/development/API/pleroma_api.md#api-v1-pleroma-events-id-participations} */ getEventParticipations: async (statusId: string, params?: GetEventParticipationsParams) => this.#paginatedGet(`/api/v1/pleroma/events/${statusId}/participations`, { params }, accountSchema), /** * Gets event participation requests - * @see {@link https://github.com/mkljczk/pl/blob/fork/docs/development/API/pleroma_api.md#apiv1pleromaeventsidparticipation_requests} + * @see {@link https://codeberg.org/mkljczk/nicolex/src/branch/develop/docs/development/API/pleroma_api.md#api-v1-pleroma-events-id-participation_requests} */ getEventParticipationRequests: async (statusId: string, params?: GetEventParticipationRequestsParams) => this.#paginatedGet(`/api/v1/pleroma/events/${statusId}/participation_requests`, { params }, v.object({ @@ -5311,7 +5311,7 @@ class PlApiClient { /** * Accepts user to the event - * @see {@link https://github.com/mkljczk/pl/blob/fork/docs/development/API/pleroma_api.md#apiv1pleromaeventsidparticipation_requestsparticipant_idauthorize} + * @see {@link https://codeberg.org/mkljczk/nicolex/src/branch/develop/docs/development/API/pleroma_api.md#api-v1-pleroma-events-id-participation_requests-participant_id-authorize} */ acceptEventParticipationRequest: async (statusId: string, accountId: string) => { const response = await this.request(`/api/v1/pleroma/events/${statusId}/participation_requests/${accountId}/authorize`, { method: 'POST' }); @@ -5321,7 +5321,7 @@ class PlApiClient { /** * Rejects user from the event - * @see {@link https://github.com/mkljczk/pl/blob/fork/docs/development/API/pleroma_api.md#rejects-user-from-the-event} + * @see {@link https://codeberg.org/mkljczk/nicolex/src/branch/develop/docs/development/API/pleroma_api.md#api-v1-pleroma-events-id-participation_requests-participant_id-reject} */ rejectEventParticipationRequest: async (statusId: string, accountId: string) => { const response = await this.request(`/api/v1/pleroma/events/${statusId}/participation_requests/${accountId}/reject`, { method: 'POST' }); @@ -5331,7 +5331,7 @@ class PlApiClient { /** * Joins the event - * @see {@link https://github.com/mkljczk/pl/blob/fork/docs/development/API/pleroma_api.md#joins-the-event} + * @see {@link https://codeberg.org/mkljczk/nicolex/src/branch/develop/docs/development/API/pleroma_api.md#api-v1-pleroma-events-id-join} */ joinEvent: async (statusId: string, participation_message?: string) => { const response = await this.request(`/api/v1/pleroma/events/${statusId}/join`, { method: 'POST', body: { participation_message } }); @@ -5341,7 +5341,7 @@ class PlApiClient { /** * Leaves the event - * @see {@link https://github.com/mkljczk/pl/blob/fork/docs/development/API/pleroma_api.md#leaves-the-event} + * @see {@link https://codeberg.org/mkljczk/nicolex/src/branch/develop/docs/development/API/pleroma_api.md#api-v1-pleroma-events-id-leave} */ leaveEvent: async (statusId: string) => { const response = await this.request(`/api/v1/pleroma/events/${statusId}/leave`, { method: 'POST' }); @@ -5351,7 +5351,7 @@ class PlApiClient { /** * Event ICS file - * @see {@link https://github.com/mkljczk/pl/blob/fork/docs/development/API/pleroma_api.md#event-ics-file} + * @see {@link https://codeberg.org/mkljczk/nicolex/src/branch/develop/docs/development/API/pleroma_api.md#event-ics-file} */ getEventIcs: async (statusId: string) => { const response = await this.request(`/api/v1/pleroma/events/${statusId}/ics`, { contentType: '' }); diff --git a/packages/pl-api/lib/entities/status.ts b/packages/pl-api/lib/entities/status.ts index 22ad9bdbf..859624fc6 100644 --- a/packages/pl-api/lib/entities/status.ts +++ b/packages/pl-api/lib/entities/status.ts @@ -36,6 +36,7 @@ const statusEventSchema = v.object({ end_time: v.fallback(v.nullable(datetimeSchema), null), join_mode: v.fallback(v.nullable(v.picklist(['free', 'restricted', 'invite', 'external'])), null), participants_count: v.fallback(v.number(), 0), + participation_request_count: v.fallback(v.number(), 0), location: v.fallback(v.nullable(locationSchema), null), join_state: v.fallback(v.nullable(v.picklist(['pending', 'reject', 'accept'])), null), }); diff --git a/packages/pl-api/lib/features.ts b/packages/pl-api/lib/features.ts index 97f256af0..cb3632631 100644 --- a/packages/pl-api/lib/features.ts +++ b/packages/pl-api/lib/features.ts @@ -966,7 +966,10 @@ const getFeatures = (instance: Instance) => { * @see GET /api/v2/notifications/:group_key/accounts * @see GET /api/v2/notifications/unread_count */ - groupedNotifications: instance.api_versions.mastodon >= 2, + groupedNotifications: any([ + instance.api_versions.mastodon >= 2, + v.software === HOLLO && gte(v.version, '0.7.0'), + ]), /** * Groups. diff --git a/packages/pl-fe/package.json b/packages/pl-fe/package.json index 0fd3d5c39..6f9950f10 100644 --- a/packages/pl-fe/package.json +++ b/packages/pl-fe/package.json @@ -44,15 +44,15 @@ "@fontsource/noto-sans-javanese": "^5.2.8", "@fontsource/roboto-mono": "^5.2.8", "@fontsource/tajawal": "^5.2.7", - "@lexical/code": "^0.38.2", - "@lexical/hashtag": "^0.38.2", - "@lexical/link": "^0.38.2", - "@lexical/list": "^0.38.2", - "@lexical/markdown": "^0.38.2", - "@lexical/react": "^0.38.2", - "@lexical/rich-text": "^0.38.2", - "@lexical/selection": "^0.38.2", - "@lexical/utils": "^0.38.2", + "@lexical/code": "^0.39.0", + "@lexical/hashtag": "^0.39.0", + "@lexical/link": "^0.39.0", + "@lexical/list": "^0.39.0", + "@lexical/markdown": "^0.39.0", + "@lexical/react": "^0.39.0", + "@lexical/rich-text": "^0.39.0", + "@lexical/selection": "^0.39.0", + "@lexical/utils": "^0.39.0", "@mkljczk/url-purify": "^0.0.5", "@phosphor-icons/core": "^2.1.1", "@reach/combobox": "^0.18.0", @@ -100,7 +100,7 @@ "intl-pluralrules": "^2.0.1", "isomorphic-dompurify": "^2.35.0", "leaflet": "^1.8.0", - "lexical": "^0.38.2", + "lexical": "^0.39.0", "line-awesome": "^1.3.0", "localforage": "^1.10.0", "lodash": "^4.17.23", diff --git a/packages/pl-fe/src/components/dropdown-menu/dropdown-menu-item.tsx b/packages/pl-fe/src/components/dropdown-menu/dropdown-menu-item.tsx index 0f3b38461..5931275cb 100644 --- a/packages/pl-fe/src/components/dropdown-menu/dropdown-menu-item.tsx +++ b/packages/pl-fe/src/components/dropdown-menu/dropdown-menu-item.tsx @@ -126,7 +126,7 @@ const DropdownMenuItem = ({ index, item, onClick, autoFocus, onSetTab }: IDropdo onClick={handleClick} onAuxClick={handleAuxClick} onKeyPress={handleItemKeyPress} - target={item.target} + target={typeof item.target === 'string' ? item.target : '_blank'} title={item.text} className={ clsx('mx-2 my-1 flex cursor-pointer items-center rounded-md px-2 py-1.5 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-800 focus:bg-gray-100 focus:text-gray-800 focus:outline-none black:hover:bg-gray-900 black:focus:bg-gray-900 dark:text-gray-300 dark:hover:bg-gray-800 dark:hover:text-gray-200 dark:focus:bg-gray-800 dark:focus:text-gray-200', { diff --git a/packages/pl-fe/src/components/modal-root.tsx b/packages/pl-fe/src/components/modal-root.tsx index 767821bb3..2c2f4eb57 100644 --- a/packages/pl-fe/src/components/modal-root.tsx +++ b/packages/pl-fe/src/components/modal-root.tsx @@ -217,7 +217,7 @@ const ModalRoot: React.FC = ({ children, onCancel, onClose, type, mo
{children}
diff --git a/packages/pl-fe/src/components/quoted-status.tsx b/packages/pl-fe/src/components/quoted-status.tsx index ce7365377..c849c99a8 100644 --- a/packages/pl-fe/src/components/quoted-status.tsx +++ b/packages/pl-fe/src/components/quoted-status.tsx @@ -3,16 +3,13 @@ import clsx from 'clsx'; import React, { MouseEventHandler } from 'react'; import { defineMessages, useIntl } from 'react-intl'; -import StatusMedia from '@/components/status-media'; import Stack from '@/components/ui/stack'; import AccountContainer from '@/containers/account-container'; import EventPreview from './event-preview'; import OutlineBox from './outline-box'; -import QuotedStatusIndicator from './quoted-status-indicator'; import StatusContent from './status-content'; import StatusReplyMentions from './status-reply-mentions'; -import SensitiveContentOverlay from './statuses/sensitive-content-overlay'; import type { SelectedStatus } from '@/selectors'; @@ -108,16 +105,9 @@ const QuotedStatus: React.FC = ({ status, onCancel, compose }) => status={status} collapsable isQuote + withMedia + compose={compose} /> - - {status.quote_id && } - - {status.media_attachments.length > 0 && ( -
- - -
- )} )} diff --git a/packages/pl-fe/src/components/status-content.tsx b/packages/pl-fe/src/components/status-content.tsx index 54f454616..50e8c27d0 100644 --- a/packages/pl-fe/src/components/status-content.tsx +++ b/packages/pl-fe/src/components/status-content.tsx @@ -23,6 +23,7 @@ import OutlineBox from './outline-box'; import { parseContent } from './parsed-content'; import { ParsedMfm } from './parsed-mfm'; import Poll from './polls/poll'; +import QuotedStatusIndicator from './quoted-status-indicator'; import StatusMedia from './status-media'; import SensitiveContentOverlay from './statuses/sensitive-content-overlay'; import TranslateButton from './translate-button'; @@ -72,6 +73,7 @@ interface IStatusContent { isQuote?: boolean; preview?: boolean; withMedia?: boolean; + compose?: boolean; } /** Renders the text content of a status */ @@ -84,6 +86,7 @@ const StatusContent: React.FC = React.memo(({ isQuote = false, preview, withMedia, + compose = false, }) => { const { urlPrivacy, displaySpoilers, renderMfm } = useSettings(); const { greentext } = useFrontendConfig(); @@ -234,7 +237,11 @@ const StatusContent: React.FC = React.memo(({ let quote; if (withMedia && status.quote_id) { - if ((status.quote_visible ?? true) === false) { + if (isQuote) { + quote = ( + + ); + } else if ((status.quote_visible ?? true) === false) { quote = (

@@ -250,7 +257,7 @@ const StatusContent: React.FC = React.memo(({ {((withMedia && status.media_attachments.length > 0) || (status.card && !quote)) && (
- {withMedia && } + {withMedia && }
)} diff --git a/packages/pl-fe/src/components/upload.tsx b/packages/pl-fe/src/components/upload.tsx index 514bdc6f7..3c528a9dd 100644 --- a/packages/pl-fe/src/components/upload.tsx +++ b/packages/pl-fe/src/components/upload.tsx @@ -159,6 +159,9 @@ const Upload: React.FC = ({ /> ); + const backgroundImage = (mediaType === 'image' || ['.png', '.jpg', '.jpeg'].some(ext => media.preview_url.endsWith(ext))) ? `url(${media.preview_url})` : undefined; + const hasBackgroundImage = !!(backgroundImage); + return (
= ({ className={clsx('compose-form__upload-thumbnail relative h-40 w-full overflow-hidden bg-contain bg-center bg-no-repeat', mediaType)} style={{ scale: styles.scale, - backgroundImage: mediaType === 'image' ? `url(${media.preview_url})` : undefined, + backgroundImage, backgroundPosition: typeof x === 'number' && typeof y === 'number' ? `${x}% ${y}%` : undefined, }} > @@ -226,7 +229,7 @@ const Upload: React.FC = ({ )} -
+
{mediaType === 'video' && (