Merge branch 'develop' of https://codeberg.org/mkljczk/pl-fe into develop
Some checks failed
Some checks failed
This commit is contained in:
@@ -40,10 +40,12 @@ const Blurhash: React.FC<IBlurhash> = React.memo(({
|
||||
try {
|
||||
const pixels = decode(hash, width, height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
const imageData = new ImageData(new Uint8ClampedArray(pixels), width, height);
|
||||
const imageData = ctx?.createImageData(width, height);
|
||||
imageData?.data.set(pixels);
|
||||
|
||||
if (!ctx) return;
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
if (imageData) {
|
||||
ctx?.putImageData(imageData, 0, 0);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Blurhash decoding failure', { err, hash });
|
||||
}
|
||||
|
||||
@@ -40,8 +40,15 @@ interface SizeData {
|
||||
itemsDimensions: Dimensions[];
|
||||
}
|
||||
|
||||
const getAspectRatio = (attachment: MediaAttachment) =>
|
||||
(attachment.type === 'gifv' || attachment.type === 'image' || attachment.type === 'video') && attachment.meta.original?.aspect || null;
|
||||
const getAspectRatio = (attachment: MediaAttachment) => {
|
||||
if ((attachment.type === 'gifv' || attachment.type === 'image' || attachment.type === 'video') && attachment.meta.original) {
|
||||
if (attachment.meta.original.aspect) {
|
||||
return attachment.meta.original.aspect;
|
||||
}
|
||||
return attachment.meta.original.width / attachment.meta.original.height;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const withinLimits = (aspectRatio: number) =>
|
||||
aspectRatio >= minimumAspectRatio && aspectRatio <= maximumAspectRatio;
|
||||
|
||||
@@ -105,7 +105,7 @@ const SensitiveContentOverlay = React.forwardRef<HTMLDivElement, ISensitiveConte
|
||||
<HStack alignItems='center' justifyContent='center' space={2}>
|
||||
<Button
|
||||
type='button'
|
||||
theme='outline'
|
||||
theme='outlined'
|
||||
size='sm'
|
||||
icon={require('@phosphor-icons/core/regular/eye.svg')}
|
||||
onClick={toggleVisibility}
|
||||
|
||||
@@ -10,7 +10,7 @@ const themes = {
|
||||
accent: 'border-transparent bg-secondary-500 hover:bg-secondary-400 focus:bg-secondary-500 text-gray-100 focus:ring-secondary-300',
|
||||
danger: 'border-transparent bg-danger-100 dark:bg-danger-900 text-danger-600 dark:text-danger-200 hover:bg-danger-600 hover:text-gray-100 dark:hover:text-gray-100 dark:hover:bg-danger-500 focus:ring-danger-500',
|
||||
transparent: 'border-transparent bg-transparent text-primary-600 dark:text-primary-400 dark:bg-transparent hover:bg-gray-200 dark:hover:bg-gray-800/50',
|
||||
outline: 'border-gray-100 border-2 bg-transparent text-gray-100 hover:bg-white/10',
|
||||
outlined: 'border-gray-100 border-2 bg-transparent text-gray-100 hover:bg-white/10',
|
||||
muted: 'border border-solid bg-transparent border-gray-400 dark:border-gray-800 hover:border-primary-300 dark:hover:border-primary-700 focus:border-primary-500 text-gray-800 dark:text-gray-100 focus:ring-primary-500',
|
||||
};
|
||||
|
||||
|
||||
@@ -1436,6 +1436,13 @@ const router = createRouter({
|
||||
pathParamsAllowedCharacters: ['@'],
|
||||
});
|
||||
|
||||
router.subscribe('onBeforeNavigate', (event) => {
|
||||
if (!event.fromLocation || event.hashChanged || event.hrefChanged || event.pathChanged) return;
|
||||
if (event.fromLocation.state.modalIndex === event.toLocation.state.modalIndex) {
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
});
|
||||
|
||||
declare module '@tanstack/react-router' {
|
||||
interface Register {
|
||||
router: typeof router;
|
||||
|
||||
@@ -92,6 +92,8 @@ const ProfileLayout: React.FC = () => {
|
||||
|
||||
const showTabs = !['/following', '/followers', '/pins'].some(path => pathname.endsWith(path));
|
||||
|
||||
console.log(account);
|
||||
|
||||
return (
|
||||
<>
|
||||
{account?.local === false && (
|
||||
|
||||
@@ -1717,7 +1717,7 @@
|
||||
"status.sensitive_warning": "Wrażliwa zawartość",
|
||||
"status.sensitive_warning.subtitle": "Ta treść może nie być odpowiednia dla niektórych odbiorców.",
|
||||
"status.share": "Udostępnij",
|
||||
"status.show_filter_reason": "Pokaż mimo wszystko",
|
||||
"status.show_filter_reason": "Pokaż mimo tego",
|
||||
"status.show_less_all": "Zwiń wszystkie",
|
||||
"status.show_more_all": "Rozwiń wszystkie",
|
||||
"status.show_original": "Pokaż oryginalny wpis",
|
||||
|
||||
@@ -289,9 +289,10 @@ const MediaModal: React.FC<MediaModalProps & BaseModalProps> = (props) => {
|
||||
role='presentation'
|
||||
>
|
||||
<Stack
|
||||
{...bind()}
|
||||
onClick={handleClickOutside}
|
||||
className={
|
||||
clsx('⁂-media-modal__content fixed inset-0 h-full grow transition-all', {
|
||||
clsx('⁂-media-modal__content fixed inset-0 h-full grow touch-pan-y transition-all', {
|
||||
'xl:pr-96': !isFullScreen,
|
||||
'xl:pr-0': isFullScreen,
|
||||
})
|
||||
@@ -349,7 +350,6 @@ const MediaModal: React.FC<MediaModalProps & BaseModalProps> = (props) => {
|
||||
|
||||
{/* Height based on height of top/bottom bars */}
|
||||
<div
|
||||
{...bind()}
|
||||
className='relative h-[calc(100vh-120px)] w-full grow'
|
||||
>
|
||||
{hasMultipleImages && (
|
||||
|
||||
@@ -250,7 +250,7 @@ const EditProfilePage: React.FC = () => {
|
||||
|
||||
if (fields_attributes?.length === 0) params.fields_attributes = { '0': { name: '', value: '' } };
|
||||
else if (fields_attributes) params.fields_attributes = Object.fromEntries(
|
||||
fields_attributes.map((field, i) => [i.toString(), field]),
|
||||
fields_attributes.map(({ name, value }, i) => [i.toString(), { name, value }]),
|
||||
);
|
||||
if (header.file !== undefined) params.header = header.file || '';
|
||||
if (avatar.file !== undefined) params.avatar = avatar.file || '';
|
||||
|
||||
134
packages/pl-fe/src/queries/accounts/use-antennas.ts
Normal file
134
packages/pl-fe/src/queries/accounts/use-antennas.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
import { type InfiniteData, useMutation, useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { useClient } from 'pl-fe/hooks/use-client';
|
||||
import { useFeatures } from 'pl-fe/hooks/use-features';
|
||||
|
||||
import { queryClient } from '../client';
|
||||
import { filterById } from '../utils/filter-id';
|
||||
import { makePaginatedResponseQuery } from '../utils/make-paginated-response-query';
|
||||
import { minifyAccountList } from '../utils/minify-list';
|
||||
|
||||
import type { Antenna, PaginatedResponse, CreateAntennaParams, UpdateAntennaParams } from 'pl-api';
|
||||
|
||||
const useAntennas = <T>(
|
||||
select?: ((data: Array<Antenna>) => T),
|
||||
) => {
|
||||
const client = useClient();
|
||||
const features = useFeatures();
|
||||
|
||||
return useQuery({
|
||||
queryKey: ['antennas'],
|
||||
queryFn: () => client.antennas.fetchAntennas(),
|
||||
enabled: features.antennas,
|
||||
select,
|
||||
});
|
||||
};
|
||||
|
||||
const useAntenna = (antennaId?: string) => useAntennas((data) => antennaId ? data.find(antenna => antenna.id === antennaId) : undefined);
|
||||
|
||||
const useCreateAntenna = () => {
|
||||
const client = useClient();
|
||||
|
||||
return useMutation({
|
||||
mutationKey: ['antennas', 'create'],
|
||||
mutationFn: (params: CreateAntennaParams) => client.antennas.createAntenna(params),
|
||||
onSettled: () => queryClient.invalidateQueries({ queryKey: ['antennas'] }),
|
||||
});
|
||||
};
|
||||
|
||||
const useDeleteAntenna = () => {
|
||||
const client = useClient();
|
||||
|
||||
return useMutation({
|
||||
mutationKey: ['antennas', 'delete'],
|
||||
mutationFn: (antennaId: string) => client.antennas.deleteAntenna(antennaId),
|
||||
onSuccess: (_, deletedAntennaId) => {
|
||||
queryClient.setQueryData<Array<Antenna>>(
|
||||
['antennas'],
|
||||
(prevData) => prevData?.filter(({ id }) => id !== deletedAntennaId),
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const useUpdateAntenna = (antennaId: string) => {
|
||||
const client = useClient();
|
||||
|
||||
return useMutation({
|
||||
mutationKey: ['antennas', 'update', antennaId],
|
||||
mutationFn: (params: UpdateAntennaParams) => client.antennas.updateAntenna(antennaId, params),
|
||||
onSettled: () => queryClient.invalidateQueries({ queryKey: ['antennas'] }),
|
||||
});
|
||||
};
|
||||
|
||||
const useAntennaAccounts = makePaginatedResponseQuery(
|
||||
(antennaId: string) => ['accountsLists', 'antennas', antennaId],
|
||||
(client, [antennaId]) => client.antennas.getAntennaAccounts(antennaId).then(minifyAccountList),
|
||||
);
|
||||
|
||||
const useAddAccountsToAntenna = (antennaId: string) => {
|
||||
const client = useClient();
|
||||
|
||||
return useMutation({
|
||||
mutationKey: ['accountsLists', 'antennas', antennaId, 'add'],
|
||||
mutationFn: (accountIds: Array<string>) => client.antennas.addAntennaAccounts(antennaId, accountIds),
|
||||
onSettled: (_, __, accountIds) => {
|
||||
queryClient.invalidateQueries({ queryKey: ['accountsLists', 'antennas', antennaId] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const useRemoveAccountsFromAntenna = (antennaId: string) => {
|
||||
const client = useClient();
|
||||
|
||||
return useMutation({
|
||||
mutationKey: ['accountsLists', 'antennas', antennaId, 'remove'],
|
||||
mutationFn: (accountIds: Array<string>) => client.antennas.removeAntennaAccounts(antennaId, accountIds),
|
||||
onSettled: (_, __, accountIds) => {
|
||||
queryClient.setQueryData<InfiniteData<PaginatedResponse<string>>>(['accountsLists', 'antennas', antennaId], filterById(accountIds));
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const useAntennaExcludedAccounts = makePaginatedResponseQuery(
|
||||
(antennaId: string) => ['accountsLists', 'antennas', antennaId, 'excluded'],
|
||||
(client, [antennaId]) => client.antennas.getAntennaExcludedAccounts(antennaId).then(minifyAccountList),
|
||||
);
|
||||
|
||||
const useAddExcludedAccountsToAntenna = (antennaId: string) => {
|
||||
const client = useClient();
|
||||
|
||||
return useMutation({
|
||||
mutationKey: ['accountsLists', 'antennas', antennaId, 'addExcluded'],
|
||||
mutationFn: (accountIds: Array<string>) => client.antennas.addAntennaExcludedAccounts(antennaId, accountIds),
|
||||
onSettled: (_, __, accountIds) => {
|
||||
queryClient.invalidateQueries({ queryKey: ['accountsLists', 'antennas', antennaId] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const useRemoveExcludedAccountsFromAntenna = (antennaId: string) => {
|
||||
const client = useClient();
|
||||
|
||||
return useMutation({
|
||||
mutationKey: ['accountsLists', 'antennas', antennaId, 'removeExcluded'],
|
||||
mutationFn: (accountIds: Array<string>) => client.antennas.removeAntennaExcludedAccounts(antennaId, accountIds),
|
||||
onSettled: (_, __, accountIds) => {
|
||||
queryClient.setQueryData<InfiniteData<PaginatedResponse<string>>>(['accountsLists', 'antennas', antennaId], filterById(accountIds));
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export {
|
||||
useAntennas,
|
||||
useAntenna,
|
||||
useCreateAntenna,
|
||||
useDeleteAntenna,
|
||||
useUpdateAntenna,
|
||||
useAntennaAccounts,
|
||||
useAddAccountsToAntenna,
|
||||
useRemoveAccountsFromAntenna,
|
||||
useAntennaExcludedAccounts,
|
||||
useAddExcludedAccountsToAntenna,
|
||||
useRemoveExcludedAccountsFromAntenna,
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
.empty-column-indicator {
|
||||
@apply bg-primary-50 dark:bg-gray-700 text-gray-900 dark:text-gray-300 text-center p-10 flex flex-1 items-center justify-center min-h-[160px] rounded-lg;
|
||||
@apply bg-primary-50 dark:bg-gray-700 text-gray-900 dark:text-gray-100 text-center p-10 flex flex-1 items-center justify-center min-h-[160px] rounded-lg;
|
||||
|
||||
& > span {
|
||||
@apply max-w-[400px];
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
@use 'mixins';
|
||||
|
||||
.⁂-edit-event .⁂-content-type-button {
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
right: 0.5rem;
|
||||
z-index: 11!important;
|
||||
@include mixins.button($theme: muted, $size: xs);
|
||||
.⁂-edit-event {
|
||||
@apply space-y-4;
|
||||
|
||||
.⁂-icon svg {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
.⁂-content-type-button {
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
right: 0.5rem;
|
||||
z-index: 11!important;
|
||||
@include mixins.button($theme: muted, $size: xs);
|
||||
|
||||
.⁂-icon svg {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,13 @@ html {
|
||||
--font-mono: 'Roboto Mono', ui-monospace, monospace;
|
||||
}
|
||||
|
||||
html:has(body.with-modals),
|
||||
body.with-modals {
|
||||
touch-action: none;
|
||||
overscroll-behavior: none;
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-white text-base antialiased black:bg-black dark:bg-gray-800;
|
||||
height: 100%;
|
||||
@@ -21,7 +28,7 @@ body {
|
||||
}
|
||||
|
||||
&.with-modals {
|
||||
@apply overflow-hidden;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,18 +7,27 @@
|
||||
}
|
||||
|
||||
.⁂-zoomable-image {
|
||||
@apply relative flex size-full items-center justify-center;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
scrollbar-width: none;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
|
||||
&--zoomed-in {
|
||||
@apply cursor-grab z-[9999];
|
||||
z-index: 9999;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
&--error img {
|
||||
@apply hidden;
|
||||
display: none;
|
||||
}
|
||||
|
||||
&--dragging {
|
||||
@apply cursor-grabbing;
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
&__preview {
|
||||
@@ -30,6 +39,11 @@
|
||||
}
|
||||
|
||||
img {
|
||||
@apply size-auto max-h-[80%] max-w-full object-contain shadow-2xl;
|
||||
@apply shadow-2xl;
|
||||
max-height: 80%;
|
||||
width: auto;
|
||||
height: auto;
|
||||
touch-action: none;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user