Merge remote-tracking branch 'origin/main' into renovate/html-react-parser-5.x

environments/review-main-yi2y9f/deployments/4326^2
Alex Gleason 2023-12-21 10:10:05 -06:00
commit b7f18a5dcc
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 7211D1F99744FBB7
47 zmienionych plików z 1875 dodań i 1251 usunięć

Wyświetl plik

@ -61,7 +61,7 @@ module.exports = {
'URLSearchParams', // core-js
],
tailwindcss: {
config: 'tailwind.config.cjs',
config: 'tailwind.config.ts',
},
},
@ -268,7 +268,7 @@ module.exports = {
'error',
{
classRegex: '^(base|container|icon|item|list|outer|wrapper)?[c|C]lass(Name)?$',
config: 'tailwind.config.cjs',
config: 'tailwind.config.ts',
},
],
'tailwindcss/migration-from-tailwind-2': 'error',

Wyświetl plik

@ -1,4 +1,4 @@
image: node:20
image: node:21
variables:
NODE_ENV: test
@ -111,9 +111,9 @@ pages:
docker:
stage: deploy
image: docker:24.0.6
image: docker:24.0.7
services:
- docker:24.0.6-dind
- docker:24.0.7-dind
tags:
- dind
# https://medium.com/devops-with-valentine/how-to-build-a-docker-image-and-push-it-to-the-gitlab-container-registry-from-a-gitlab-ci-pipeline-acac0d1f26df

Wyświetl plik

@ -1 +1 @@
nodejs 20.0.0
nodejs 21.4.0

Wyświetl plik

@ -1,4 +1,4 @@
FROM node:20 as build
FROM node:21 as build
WORKDIR /app
COPY package.json .
COPY yarn.lock .

Wyświetl plik

@ -1,4 +1,4 @@
FROM node:20
FROM node:21
RUN apt-get update &&\
apt-get install -y inotify-tools &&\

Wyświetl plik

@ -62,14 +62,14 @@
"@reach/popover": "^0.18.0",
"@reach/rect": "^0.18.0",
"@reach/tabs": "^0.18.0",
"@reduxjs/toolkit": "^1.8.1",
"@reduxjs/toolkit": "^2.0.1",
"@sentry/browser": "^7.74.1",
"@sentry/react": "^7.74.1",
"@soapbox.pub/wasmboy": "^0.8.0",
"@tabler/icons": "^2.0.0",
"@tailwindcss/aspect-ratio": "^0.4.2",
"@tailwindcss/forms": "^0.5.3",
"@tailwindcss/typography": "^0.5.9",
"@tailwindcss/forms": "^0.5.7",
"@tailwindcss/typography": "^0.5.10",
"@tanstack/react-query": "^5.0.0",
"@types/escape-html": "^1.0.1",
"@types/http-link-header": "^1.0.3",
@ -86,7 +86,7 @@
"@types/react-router-dom": "^5.3.3",
"@types/react-sparklines": "^1.7.2",
"@types/react-swipeable-views": "^0.13.1",
"@types/redux-mock-store": "^1.0.3",
"@types/redux-mock-store": "^1.0.6",
"@types/semver": "^7.3.9",
"@types/uuid": "^9.0.0",
"@vitejs/plugin-react": "^4.0.4",
@ -145,7 +145,7 @@
"react-motion": "^0.5.2",
"react-overlays": "^0.9.0",
"react-popper": "^2.3.0",
"react-redux": "^8.0.0",
"react-redux": "^9.0.4",
"react-router-dom": "^5.3.0",
"react-router-dom-v5-compat": "^6.6.2",
"react-router-scroll-4": "^1.0.0-beta.2",
@ -154,12 +154,12 @@
"react-sticky-box": "^2.0.0",
"react-swipeable-views": "^0.14.0",
"react-virtuoso": "^4.3.11",
"redux": "^4.1.1",
"redux": "^5.0.0",
"redux-immutable": "^4.0.0",
"redux-thunk": "^2.2.0",
"reselect": "^4.0.0",
"redux-thunk": "^3.1.0",
"reselect": "^5.0.0",
"resize-observer-polyfill": "^1.5.1",
"sass": "^1.66.1",
"sass": "^1.69.5",
"semver": "^7.3.8",
"stringz": "^2.0.0",
"substring-trie": "^1.0.2",
@ -170,11 +170,11 @@
"typescript": "^5.1.3",
"util": "^0.12.4",
"uuid": "^9.0.0",
"vite": "^4.4.9",
"vite": "^5.0.10",
"vite-plugin-compile-time": "^0.2.1",
"vite-plugin-html": "^3.2.0",
"vite-plugin-require": "^1.1.10",
"vite-plugin-static-copy": "^0.17.0",
"vite-plugin-static-copy": "^1.0.0",
"wicg-inert": "^3.1.1",
"zod": "^3.21.4"
},
@ -202,17 +202,17 @@
"eslint-plugin-tailwindcss": "^3.13.0",
"fake-indexeddb": "^5.0.0",
"husky": "^8.0.0",
"jsdom": "^22.1.0",
"jsdom": "^23.0.0",
"lint-staged": ">=10",
"react-intl-translations-manager": "^5.0.3",
"react-refresh": "^0.14.0",
"rollup-plugin-visualizer": "^5.9.2",
"stylelint": "^15.10.3",
"stylelint-config-standard-scss": "^11.0.0",
"tailwindcss": "^3.3.3",
"tailwindcss": "^3.4.0",
"vite-plugin-checker": "^0.6.2",
"vite-plugin-pwa": "^0.17.0",
"vitest": "^0.34.4"
"vitest": "^1.0.0"
},
"resolutions": {
"@types/react": "^18.0.26",

Wyświetl plik

@ -41,7 +41,7 @@ function useGroupValidation(name: string = '') {
...queryInfo,
data: {
...queryInfo.data,
isValid: !queryInfo.data?.error ?? true,
isValid: !queryInfo.data?.error,
},
};
}

Wyświetl plik

@ -12,7 +12,7 @@ const BigCard: React.FC<IBigCard> = ({ title, subtitle, children }) => {
return (
<Card variant='rounded' size='xl'>
<CardBody>
<div className='-mx-4 mb-4 border-b border-solid border-gray-200 pb-4 dark:border-gray-800 sm:-mx-10 sm:pb-10'>
<div className='-mx-4 mb-4 border-b border-solid border-gray-200 pb-4 sm:-mx-10 sm:pb-10 dark:border-gray-800'>
<Stack space={2}>
<Text size='2xl' align='center' weight='bold'>{title}</Text>
{subtitle && <Text theme='muted' align='center'>{subtitle}</Text>}

Wyświetl plik

@ -28,7 +28,7 @@ const GdprBanner: React.FC = () => {
return (
<Banner theme='opaque' className={clsx('transition-transform', { 'translate-y-full': slideout })}>
<div className='flex flex-col space-y-4 rtl:space-x-reverse lg:flex-row lg:items-center lg:justify-between lg:space-x-4 lg:space-y-0'>
<div className='flex flex-col space-y-4 lg:flex-row lg:items-center lg:justify-between lg:space-x-4 lg:space-y-0 rtl:space-x-reverse'>
<Stack space={2}>
<Text size='xl' weight='bold'>
<FormattedMessage id='gdpr.title' defaultMessage='{siteTitle} uses cookies' values={{ siteTitle: instance.title }} />

Wyświetl plik

@ -84,7 +84,7 @@ const SiteErrorBoundary: React.FC<ISiteErrorBoundary> = ({ children }) => {
<div className='py-8'>
<div className='mx-auto max-w-xl space-y-2 text-center'>
<h1 className='text-3xl font-extrabold tracking-tight text-gray-900 dark:text-gray-500 sm:text-4xl'>
<h1 className='text-3xl font-extrabold tracking-tight text-gray-900 sm:text-4xl dark:text-gray-500'>
<FormattedMessage id='alert.unexpected.message' defaultMessage='Something went wrong.' />
</h1>
<p className='text-lg text-gray-700 dark:text-gray-600'>

Wyświetl plik

@ -13,7 +13,7 @@ const Select = React.forwardRef<HTMLSelectElement, ISelect>((props, ref) => {
<select
ref={ref}
className={clsx(
'w-full truncate rounded-md border-gray-300 py-2 pl-3 pr-10 text-base focus:border-primary-500 focus:outline-none focus:ring-primary-500 disabled:opacity-50 dark:border-gray-800 dark:bg-gray-900 dark:text-gray-100 dark:ring-1 dark:ring-gray-800 dark:focus:border-primary-500 dark:focus:ring-primary-500 sm:text-sm',
'w-full truncate rounded-md border-gray-300 py-2 pl-3 pr-10 text-base focus:border-primary-500 focus:outline-none focus:ring-primary-500 disabled:opacity-50 sm:text-sm dark:border-gray-800 dark:bg-gray-900 dark:text-gray-100 dark:ring-1 dark:ring-gray-800 dark:focus:border-primary-500 dark:focus:ring-primary-500',
className,
)}
{...filteredProps}

Wyświetl plik

@ -45,7 +45,7 @@ const TagInput: React.FC<ITagInput> = ({ tags, onChange, placeholder }) => {
return (
<div className='relative mt-1 grow shadow-sm'>
<HStack
className='block w-full rounded-md border-gray-400 bg-white p-2 pb-0 text-gray-900 placeholder:text-gray-600 focus:border-primary-500 focus:ring-primary-500 dark:border-gray-800 dark:bg-gray-900 dark:text-gray-100 dark:ring-1 dark:ring-gray-800 dark:placeholder:text-gray-600 dark:focus:border-primary-500 dark:focus:ring-primary-500 sm:text-sm'
className='block w-full rounded-md border-gray-400 bg-white p-2 pb-0 text-gray-900 placeholder:text-gray-600 focus:border-primary-500 focus:ring-primary-500 sm:text-sm dark:border-gray-800 dark:bg-gray-900 dark:text-gray-100 dark:ring-1 dark:ring-gray-800 dark:placeholder:text-gray-600 dark:focus:border-primary-500 dark:focus:ring-primary-500'
space={2}
wrap
>

Wyświetl plik

@ -91,7 +91,7 @@ const Textarea = React.forwardRef(({
ref={ref}
rows={rows}
onChange={handleChange}
className={clsx('block w-full rounded-md text-gray-900 placeholder:text-gray-600 dark:text-gray-100 dark:placeholder:text-gray-600 sm:text-sm', {
className={clsx('block w-full rounded-md text-gray-900 placeholder:text-gray-600 sm:text-sm dark:text-gray-100 dark:placeholder:text-gray-600', {
'bg-white dark:bg-transparent shadow-sm border-gray-400 dark:border-gray-800 dark:ring-1 dark:ring-gray-800 focus:ring-primary-500 focus:border-primary-500 dark:focus:ring-primary-500 dark:focus:border-primary-500':
theme === 'default',
'bg-transparent border-0 focus:border-0 focus:ring-0': theme === 'transparent',

Wyświetl plik

@ -110,7 +110,7 @@ const Header: React.FC<IHeader> = ({ account }) => {
return (
<div className='-mx-4 -mt-4 sm:-mx-6 sm:-mt-6'>
<div>
<div className='relative h-32 w-full bg-gray-200 dark:bg-gray-900/50 md:rounded-t-xl lg:h-48' />
<div className='relative h-32 w-full bg-gray-200 md:rounded-t-xl lg:h-48 dark:bg-gray-900/50' />
</div>
<div className='px-4 sm:px-6'>
@ -620,7 +620,7 @@ const Header: React.FC<IHeader> = ({ account }) => {
)}
<div>
<div className='relative isolate flex h-32 w-full flex-col justify-center overflow-hidden bg-gray-200 dark:bg-gray-900/50 md:rounded-t-xl lg:h-48'>
<div className='relative isolate flex h-32 w-full flex-col justify-center overflow-hidden bg-gray-200 md:rounded-t-xl lg:h-48 dark:bg-gray-900/50'>
{renderHeader()}
<div className='absolute left-2 top-2'>

Wyświetl plik

@ -44,7 +44,7 @@ const Search: React.FC = () => {
<span style={{ display: 'none' }}>{intl.formatMessage(messages.search)}</span>
<input
className='block w-full rounded-full focus:border-primary-500 focus:ring-primary-500 dark:bg-gray-800 dark:text-white dark:placeholder:text-gray-500 sm:text-sm'
className='block w-full rounded-full focus:border-primary-500 focus:ring-primary-500 sm:text-sm dark:bg-gray-800 dark:text-white dark:placeholder:text-gray-500'
type='text'
value={value}
onChange={handleChange}

Wyświetl plik

@ -16,7 +16,7 @@ const ConsumersList: React.FC<IConsumersList> = () => {
if (providers.length > 0) {
return (
<Card className='bg-gray-50 p-4 dark:bg-primary-800 sm:rounded-xl'>
<Card className='bg-gray-50 p-4 sm:rounded-xl dark:bg-primary-800'>
<Text size='xs' theme='muted'>
<FormattedMessage id='oauth_consumers.title' defaultMessage='Other ways to sign in' />
</Text>

Wyświetl plik

@ -60,7 +60,7 @@ const ChatPage: React.FC<IChatPage> = ({ chatId }) => {
<div
ref={containerRef}
style={{ height }}
className='h-screen overflow-hidden bg-white text-gray-900 shadow-lg dark:bg-primary-900 dark:text-gray-100 dark:shadow-none sm:rounded-t-xl'
className='h-screen overflow-hidden bg-white text-gray-900 shadow-lg sm:rounded-t-xl dark:bg-primary-900 dark:text-gray-100 dark:shadow-none'
>
{isOnboarded ? (
<div
@ -68,7 +68,7 @@ const ChatPage: React.FC<IChatPage> = ({ chatId }) => {
data-testid='chat-page'
>
<Stack
className={clsx('dark:inset col-span-9 overflow-hidden bg-gradient-to-r from-white to-gray-100 dark:bg-gray-900 dark:bg-none sm:col-span-3', {
className={clsx('dark:inset col-span-9 overflow-hidden bg-gradient-to-r from-white to-gray-100 sm:col-span-3 dark:bg-gray-900 dark:bg-none', {
'hidden sm:block': isSidebarHidden,
})}
>

Wyświetl plik

@ -121,7 +121,7 @@ const ChatPageMain = () => {
<HStack alignItems='center'>
<IconButton
src={require('@tabler/icons/arrow-left.svg')}
className='mr-2 h-7 w-7 rtl:rotate-180 sm:mr-0 sm:hidden'
className='mr-2 h-7 w-7 sm:mr-0 sm:hidden rtl:rotate-180'
onClick={() => history.push('/chats')}
/>

Wyświetl plik

@ -24,7 +24,7 @@ const ChatPageNew: React.FC<IChatPageNew> = () => {
<HStack alignItems='center'>
<IconButton
src={require('@tabler/icons/arrow-left.svg')}
className='mr-2 h-7 w-7 rtl:rotate-180 sm:mr-0 sm:hidden'
className='mr-2 h-7 w-7 sm:mr-0 sm:hidden rtl:rotate-180'
onClick={() => history.push('/chats')}
/>

Wyświetl plik

@ -51,7 +51,7 @@ const ChatPageSettings = () => {
<HStack alignItems='center'>
<IconButton
src={require('@tabler/icons/arrow-left.svg')}
className='mr-2 h-7 w-7 rtl:rotate-180 sm:mr-0 sm:hidden'
className='mr-2 h-7 w-7 sm:mr-0 sm:hidden rtl:rotate-180'
onClick={() => history.push('/chats')}
/>

Wyświetl plik

@ -39,9 +39,9 @@ const ChatTextarea: React.FC<IChatTextarea> = React.forwardRef(({
bg-white text-gray-900
shadow-sm placeholder:text-gray-600
focus-within:border-primary-500
focus-within:ring-1 focus-within:ring-primary-500 dark:border-gray-800 dark:bg-gray-800
dark:text-gray-100 dark:ring-1 dark:ring-gray-800 dark:placeholder:text-gray-600 dark:focus-within:border-primary-500
dark:focus-within:ring-primary-500 sm:text-sm
focus-within:ring-1 focus-within:ring-primary-500 sm:text-sm dark:border-gray-800
dark:bg-gray-800 dark:text-gray-100 dark:ring-1 dark:ring-gray-800 dark:placeholder:text-gray-600
dark:focus-within:border-primary-500 dark:focus-within:ring-primary-500
`}
>
{(!!attachments?.length || isUploading) && (

Wyświetl plik

@ -36,7 +36,7 @@ const HeaderPicker = React.forwardRef<HTMLInputElement, IMediaInput>(({ src, onC
<label
ref={picker}
className={clsx(
'dark:sm:shadow-inset relative h-24 w-full cursor-pointer overflow-hidden rounded-lg bg-primary-100 text-primary-500 dark:bg-gray-800 dark:text-accent-blue sm:h-36 sm:shadow',
'dark:sm:shadow-inset relative h-24 w-full cursor-pointer overflow-hidden rounded-lg bg-primary-100 text-primary-500 sm:h-36 sm:shadow dark:bg-gray-800 dark:text-accent-blue',
{
'border-2 border-primary-600 border-dashed !z-[99]': isDragging,
'ring-2 ring-offset-2 ring-primary-600': isDraggedOver,

Wyświetl plik

@ -80,7 +80,7 @@ const EventHeader: React.FC<IEventHeader> = ({ status }) => {
return (
<>
<div className='-mx-4 -mt-4'>
<div className='relative h-32 w-full bg-gray-200 dark:bg-gray-900/50 md:rounded-t-xl lg:h-48' />
<div className='relative h-32 w-full bg-gray-200 md:rounded-t-xl lg:h-48 dark:bg-gray-900/50' />
</div>
<PlaceholderEventHeader />
@ -364,7 +364,7 @@ const EventHeader: React.FC<IEventHeader> = ({ status }) => {
return (
<>
<div className='-mx-4 -mt-4'>
<div className='relative h-32 w-full bg-gray-200 dark:bg-gray-900/50 md:rounded-t-xl lg:h-48'>
<div className='relative h-32 w-full bg-gray-200 md:rounded-t-xl lg:h-48 dark:bg-gray-900/50'>
{banner && (
<a href={banner.url} onClick={handleHeaderClick} target='_blank'>
<StillImage

Wyświetl plik

@ -24,7 +24,7 @@ const SuggestionItem: React.FC<ISuggestionItem> = ({ accountId }) => {
if (!account) return null;
return (
<Stack space={3} className='w-52 shrink-0 rounded-md border border-solid border-gray-300 p-4 dark:border-gray-800 md:w-full md:shrink md:border-transparent md:p-0 dark:md:border-transparent'>
<Stack space={3} className='w-52 shrink-0 rounded-md border border-solid border-gray-300 p-4 md:w-full md:shrink md:border-transparent md:p-0 dark:border-gray-800 dark:md:border-transparent'>
<Link
to={`/@${account.acct}`}
title={account.acct}

Wyświetl plik

@ -36,7 +36,7 @@ const GroupHeader: React.FC<IGroupHeader> = ({ group }) => {
return (
<div className='-mx-4 -mt-4 sm:-mx-6 sm:-mt-6' data-testid='group-header-missing'>
<div>
<div className='relative h-32 w-full bg-gray-200 dark:bg-gray-900/50 md:rounded-t-xl lg:h-48' />
<div className='relative h-32 w-full bg-gray-200 md:rounded-t-xl lg:h-48 dark:bg-gray-900/50' />
</div>
<div className='px-4 sm:px-6'>
@ -92,7 +92,7 @@ const GroupHeader: React.FC<IGroupHeader> = ({ group }) => {
<StillImage
src={group.header}
alt={intl.formatMessage(messages.header)}
className='relative h-32 w-full bg-gray-200 object-center dark:bg-gray-900/50 md:rounded-t-xl lg:h-52'
className='relative h-32 w-full bg-gray-200 object-center md:rounded-t-xl lg:h-52 dark:bg-gray-900/50'
onError={() => setIsHeaderMissing(true)}
/>
);
@ -109,7 +109,7 @@ const GroupHeader: React.FC<IGroupHeader> = ({ group }) => {
return (
<div
data-testid='group-header-image'
className='flex h-32 w-full items-center justify-center bg-gray-200 dark:bg-gray-800/30 md:rounded-t-xl lg:h-52'
className='flex h-32 w-full items-center justify-center bg-gray-200 md:rounded-t-xl lg:h-52 dark:bg-gray-800/30'
>
{isHeaderMissing ? (
<Icon src={require('@tabler/icons/photo-off.svg')} className='h-6 w-6 text-gray-500 dark:text-gray-700' />

Wyświetl plik

@ -26,7 +26,7 @@ const FediverseStep = ({ onNext }: { onNext: () => void }) => {
</Text>
<Stack space={4}>
<div className='border-b border-solid border-gray-200 pb-2 dark:border-gray-800 sm:pb-5'>
<div className='border-b border-solid border-gray-200 pb-2 sm:pb-5 dark:border-gray-800'>
<Stack space={4}>
<Text theme='muted'>
<FormattedMessage

Wyświetl plik

@ -8,7 +8,7 @@ import PlaceholderStatusContent from './placeholder-status-content';
/** Fake notification to display while data is loading. */
const PlaceholderNotification = () => (
<div className='bg-white px-4 py-6 dark:bg-primary-900 sm:p-6'>
<div className='bg-white px-4 py-6 sm:p-6 dark:bg-primary-900'>
<div className='w-full animate-pulse'>
<div className='mb-2'>
<PlaceholderStatusContent minLength={20} maxLength={20} />

Wyświetl plik

@ -209,7 +209,7 @@ const ComposeEventModal: React.FC<IComposeEventModal> = ({ onClose }) => {
<FormGroup
labelText={<FormattedMessage id='compose_event.fields.banner_label' defaultMessage='Event banner' />}
>
<div className='dark:sm:shadow-inset relative flex h-24 items-center justify-center overflow-hidden rounded-lg bg-primary-100 text-primary-500 dark:bg-gray-800 dark:text-white sm:h-32 sm:shadow'>
<div className='dark:sm:shadow-inset relative flex h-24 items-center justify-center overflow-hidden rounded-lg bg-primary-100 text-primary-500 sm:h-32 sm:shadow dark:bg-gray-800 dark:text-white'>
{banner ? (
<>
<img className='h-full w-full object-cover' src={banner.url} alt='' />
@ -234,7 +234,7 @@ const ComposeEventModal: React.FC<IComposeEventModal> = ({ onClose }) => {
labelText={<FormattedMessage id='compose_event.fields.description_label' defaultMessage='Event description' />}
>
<ComposeEditor
className='block w-full rounded-md border border-gray-400 bg-white px-3 py-2 text-base text-gray-900 ring-1 placeholder:text-gray-600 focus-within:border-primary-500 focus-within:ring-primary-500 dark:border-gray-800 dark:bg-gray-900 dark:text-gray-100 dark:ring-gray-800 dark:placeholder:text-gray-600 dark:focus-within:border-primary-500 dark:focus-within:ring-primary-500 sm:text-sm'
className='block w-full rounded-md border border-gray-400 bg-white px-3 py-2 text-base text-gray-900 ring-1 placeholder:text-gray-600 focus-within:border-primary-500 focus-within:ring-primary-500 sm:text-sm dark:border-gray-800 dark:bg-gray-900 dark:text-gray-100 dark:ring-gray-800 dark:placeholder:text-gray-600 dark:focus-within:border-primary-500 dark:focus-within:ring-primary-500'
placeholderClassName='pt-2'
composeId='compose-event-modal'
placeholder={intl.formatMessage(messages.eventDescriptionPlaceholder)}

Wyświetl plik

@ -42,7 +42,7 @@ const ConfirmationStep: React.FC<IConfirmationStep> = ({ group }) => {
<Stack space={3}>
<Stack>
<label
className='dark:sm:shadow-inset relative h-24 w-full cursor-pointer overflow-hidden rounded-lg bg-primary-100 text-primary-500 dark:bg-gray-800 dark:text-accent-blue sm:h-36 sm:shadow'
className='dark:sm:shadow-inset relative h-24 w-full cursor-pointer overflow-hidden rounded-lg bg-primary-100 text-primary-500 sm:h-36 sm:shadow dark:bg-gray-800 dark:text-accent-blue'
>
{group.header && <img className='h-full w-full object-cover' src={group.header} alt='' />}
</label>

Wyświetl plik

@ -76,7 +76,7 @@ const Navbar = () => {
<div className='mx-auto max-w-7xl px-2 sm:px-6 lg:px-8'>
<div className='relative flex h-12 justify-between lg:h-16'>
{account && (
<div className='absolute inset-y-0 left-0 flex items-center rtl:left-auto rtl:right-0 lg:hidden'>
<div className='absolute inset-y-0 left-0 flex items-center lg:hidden rtl:left-auto rtl:right-0'>
<button onClick={onOpenSidebar}>
<Avatar src={account.avatar} size={34} />
</button>
@ -125,7 +125,7 @@ const Navbar = () => {
</Button>
</div>
) : (
<Form className='hidden items-center space-x-2 rtl:space-x-reverse xl:flex' onSubmit={handleSubmit}>
<Form className='hidden items-center space-x-2 xl:flex rtl:space-x-reverse' onSubmit={handleSubmit}>
<Input
required
value={username}

Wyświetl plik

@ -494,7 +494,7 @@ const UI: React.FC<IUI> = ({ children }) => {
</Layout>
{(me && !shouldHideFAB()) && (
<div className='fixed bottom-24 right-4 z-40 transition-all rtl:left-4 rtl:right-auto lg:hidden'>
<div className='fixed bottom-24 right-4 z-40 transition-all lg:hidden rtl:left-4 rtl:right-auto'>
<FloatingActionButton />
</div>
)}

Wyświetl plik

@ -9,7 +9,7 @@ import { IntlProvider } from 'react-intl';
import { Provider } from 'react-redux';
import { MemoryRouter } from 'react-router-dom';
import { Action, applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';
import { thunk } from 'redux-thunk';
import { ChatProvider } from 'soapbox/contexts/chat-context';
import { StatProvider } from 'soapbox/contexts/stat-context';

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1 @@
{}

Wyświetl plik

@ -198,6 +198,9 @@
"birthdays_modal.empty": "Żaden z Twoich znajomych nie ma dziś urodzin.",
"boost_modal.combo": "Naciśnij {combo}, aby pominąć to następnym razem",
"boost_modal.title": "Repost?",
"bundle_column_error.body": "Coś poszło nie tak podczas ładowania tej strony.",
"bundle_column_error.retry": "Spróbuj ponownie",
"bundle_column_error.title": "Błąd sieci",
"card.back.label": "Wstecz",
"chat.actions.send": "Wyślij",
"chat.failed_to_send": "Nie udało się wysłać wiadomości.",
@ -1369,6 +1372,8 @@
"soapbox_config.redirect_root_no_login_label": "Przekieruj stronę główną",
"soapbox_config.save": "Zapisz",
"soapbox_config.saved": "Zapisano konfigurację Soapbox!",
"soapbox_config.sentry_dsn_hint": "Adres URL DSN do zgłaszania błędów. Działa z Sentry i GlitchTip.",
"soapbox_config.sentry_dsn_label": "DSN Sentry",
"soapbox_config.tile_server_attribution_label": "Atrybucja kafelków map",
"soapbox_config.tile_server_label": "Serwer kafelków map",
"soapbox_config.verified_can_edit_name_label": "Pozwól zweryfikowanym użytkownikom na zmianę swojej nazwy wyświetlanej.",

Wyświetl plik

@ -198,6 +198,9 @@
"birthdays_modal.empty": "今天您的朋友中无人过生日。",
"boost_modal.combo": "下次按住 {combo} 即可跳过此提示",
"boost_modal.title": "转发?",
"bundle_column_error.body": "载入页面时发生错误。",
"bundle_column_error.retry": "重试",
"bundle_column_error.title": "网络错误",
"card.back.label": "返回",
"chat.actions.send": "发送",
"chat.failed_to_send": "消息发送失败。",

Wyświetl plik

@ -1,7 +1,6 @@
import toast from 'soapbox/toast';
import type { AnyAction } from 'redux';
import type { ThunkMiddleware } from 'redux-thunk';
import type { AnyAction, Middleware } from 'redux';
/** Whether the action is considered a failure. */
const isFailType = (type: string): boolean => type.endsWith('_FAIL');
@ -21,8 +20,9 @@ const shouldShowError = ({ type, skipAlert, error }: AnyAction): boolean => {
};
/** Middleware to display Redux errors to the user. */
const errorsMiddleware = (): ThunkMiddleware =>
() => next => action => {
const errorsMiddleware = (): Middleware =>
() => next => anyAction => {
const action = anyAction as AnyAction;
if (shouldShowError(action)) {
toast.showAlertForError(action.error);
}

Wyświetl plik

@ -1,8 +1,7 @@
import { AnyAction } from 'redux';
import { play, soundCache } from 'soapbox/utils/sounds';
import type { ThunkMiddleware } from 'redux-thunk';
import type { AnyAction, Middleware } from 'redux';
import type { Sounds } from 'soapbox/utils/sounds';
interface Action extends AnyAction {
@ -12,8 +11,9 @@ interface Action extends AnyAction {
}
/** Middleware to play sounds in response to certain Redux actions. */
export default function soundsMiddleware(): ThunkMiddleware {
return () => next => (action: Action) => {
export default function soundsMiddleware(): Middleware {
return () => next => anyAction => {
const action = anyAction as Action;
if (action.meta?.sound && soundCache[action.meta.sound]) {
play(soundCache[action.meta.sound]);
}

Wyświetl plik

@ -50,7 +50,7 @@ const HomePage: React.FC<IHomePage> = ({ children }) => {
return (
<>
<Layout.Main className='space-y-3 pt-3 dark:divide-gray-800 sm:pt-0'>
<Layout.Main className='space-y-3 pt-3 sm:pt-0 dark:divide-gray-800'>
{me && (
<Card
className={clsx('relative z-[1] transition', {

Wyświetl plik

@ -20,7 +20,7 @@ const LandingPage: React.FC<ILandingPage> = ({ children }) => {
return (
<>
<Layout.Main className='space-y-3 pt-3 dark:divide-gray-800 sm:pt-0'>
<Layout.Main className='space-y-3 pt-3 sm:pt-0 dark:divide-gray-800'>
{children}
{!me && (

Wyświetl plik

@ -39,7 +39,7 @@ async function startSentry(dsn: string): Promise<void> {
/^moz-extension:\/\//i,
],
tracesSampleRate: 1.0,
tracesSampleRate: .1,
});
Sentry.setContext('soapbox', sourceCode);

Wyświetl plik

@ -1,5 +1,5 @@
import { configureStore } from '@reduxjs/toolkit';
import thunk, { ThunkDispatch } from 'redux-thunk';
import { configureStore, Tuple } from '@reduxjs/toolkit';
import { thunk, type ThunkDispatch } from 'redux-thunk';
import errorsMiddleware from './middleware/errors';
import soundsMiddleware from './middleware/sounds';
@ -9,11 +9,11 @@ import type { AnyAction } from 'redux';
export const store = configureStore({
reducer: appReducer,
middleware: [
middleware: () => new Tuple(
thunk,
errorsMiddleware(),
soundsMiddleware(),
],
),
devTools: true,
});

Wyświetl plik

@ -1,7 +1,11 @@
const { parseColorMatrix } = require('./tailwind/colors.cjs');
import aspectRatioPlugin from '@tailwindcss/aspect-ratio';
import formsPlugin from '@tailwindcss/forms';
import typographyPlugin from '@tailwindcss/typography';
import { type Config } from 'tailwindcss';
/** @type {import('tailwindcss').Config} */
module.exports = {
import { parseColorMatrix } from './tailwind/colors';
const config: Config = {
content: ['./src/**/*.{html,js,ts,tsx}', './custom/instance/**/*.html', './index.html'],
darkMode: 'class',
theme: {
@ -98,8 +102,10 @@ module.exports = {
},
},
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography'),
require('@tailwindcss/aspect-ratio'),
aspectRatioPlugin,
formsPlugin,
typographyPlugin,
],
};
export default config;

Wyświetl plik

@ -1,46 +0,0 @@
// https://tailwindcss.com/docs/customizing-colors#using-css-variables
function withOpacityValue(variable) {
return ({ opacityValue }) => {
if (opacityValue === undefined) {
return `rgb(var(${variable}))`;
}
return `rgb(var(${variable}) / ${opacityValue})`;
};
}
// Parse a single color as a CSS variable
const toColorVariable = (colorName, tint = null) => {
const suffix = tint ? `-${tint}` : '';
const variable = `--color-${colorName}${suffix}`;
return withOpacityValue(variable);
};
// Parse list of tints into Tailwind function with CSS variables
const parseTints = (colorName, tints) => {
return tints.reduce((colorObj, tint) => {
colorObj[tint] = toColorVariable(colorName, tint);
return colorObj;
}, {});
};
// Parse color matrix into Tailwind color palette
const parseColorMatrix = colorMatrix => {
return Object.entries(colorMatrix).reduce((palette, colorData) => {
const [colorName, tints] = colorData;
// Conditionally parse array or single-tint colors
if (Array.isArray(tints)) {
palette[colorName] = parseTints(colorName, tints);
} else if (tints === true) {
palette[colorName] = toColorVariable(colorName);
}
return palette;
}, {});
};
module.exports = {
withOpacityValue,
parseColorMatrix,
};

Wyświetl plik

@ -1,7 +1,7 @@
import {
withOpacityValue,
parseColorMatrix,
} from './colors.cjs';
} from './colors';
describe('withOpacityValue()', () => {
it('returns a Tailwind color function with alpha support', () => {
@ -11,8 +11,7 @@ describe('withOpacityValue()', () => {
expect(typeof result).toBe('function');
// Test calling the function
expect(result({})).toBe('rgb(var(--color-primary-500))');
expect(result({ opacityValue: .5 })).toBe('rgb(var(--color-primary-500) / 0.5)');
expect(result).toBe('rgb(var(--color-primary-500) / <alpha-value>)');
});
});
@ -29,8 +28,8 @@ describe('parseColorMatrix()', () => {
const result = parseColorMatrix(colorMatrix);
// Colors are mapped to functions which return CSS values
expect(result.primary[500]({})).toEqual('rgb(var(--color-primary-500))');
expect(result.accent[300]({ opacityValue: .3 })).toEqual('rgb(var(--color-accent-300) / 0.3)');
// @ts-ignore
expect(result.accent['300']).toEqual('rgb(var(--color-accent-300) / <alpha-value>)');
});
it('parses single-tint values', () => {
@ -46,6 +45,6 @@ describe('parseColorMatrix()', () => {
const result = parseColorMatrix(colorMatrix);
expect(result['gradient-start']({ opacityValue: .7 })).toEqual('rgb(var(--color-gradient-start) / 0.7)');
expect(result['gradient-start']).toEqual('rgb(var(--color-gradient-start) / <alpha-value>)');
});
});

47
tailwind/colors.ts 100644
Wyświetl plik

@ -0,0 +1,47 @@
import { type RecursiveKeyValuePair } from 'tailwindcss/types/config';
/** https://tailwindcss.com/docs/customizing-colors#using-css-variables */
function withOpacityValue(variable: string): string {
return `rgb(var(${variable}) / <alpha-value>)`;
}
/** Parse a single color as a CSS variable. */
const toColorVariable = (colorName: string, tint: number | null = null): string => {
const suffix = tint ? `-${tint}` : '';
const variable = `--color-${colorName}${suffix}`;
return withOpacityValue(variable);
};
/** Parse list of tints into Tailwind function with CSS variables. */
const parseTints = (colorName: string, tints: number[]): RecursiveKeyValuePair => {
return tints.reduce<Record<string, string>>((colorObj, tint) => {
colorObj[tint] = toColorVariable(colorName, tint);
return colorObj;
}, {});
};
interface ColorMatrix {
[colorName: string]: number[] | boolean;
}
/** Parse color matrix into Tailwind color palette. */
const parseColorMatrix = (colorMatrix: ColorMatrix): RecursiveKeyValuePair => {
return Object.entries(colorMatrix).reduce<RecursiveKeyValuePair>((palette, colorData) => {
const [colorName, tints] = colorData;
// Conditionally parse array or single-tint colors
if (Array.isArray(tints)) {
palette[colorName] = parseTints(colorName, tints);
} else if (tints === true) {
palette[colorName] = toColorVariable(colorName);
}
return palette;
}, {});
};
export {
withOpacityValue,
parseColorMatrix,
};

967
yarn.lock

Plik diff jest za duży Load Diff