diff --git a/CHANGELOG.md b/CHANGELOG.md index b6971b861..df61f477b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,123 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added +- Compatibility: rudimentary support for Takahē. +- UI: added backdrop blur behind modals. +- Admin: let admins configure media preview for attachment thumbnails. +- Login: accept `?server` param in external login, eg `fe.soapbox.pub/login/external?server=gleasonator.com`. +- Backups: restored Pleroma backups functionality. +- Export: restored "Export data" to CSV. + +### Changed +- Posts: letterbox images to 19:6 again. +- Status Info: moved context (repost, pinned) to improve UX. +- Posts: remove file icon from empty link previews. +- Settings: moved "Import data" under settings. + +### Fixed +- Layout: use accent color for "floating action button" (mobile compose button). +- ServiceWorker: don't serve favicon, robots.txt, and others from ServiceWorker. +- Datepicker: correctly default to the current year. +- Scheduled posts: fix page crashing on deleting a scheduled post. +- Events: don't crash when searching for a location. +- Search: fixes an abort error when using the navbar search component. +- Posts: fix monospace font in Markdown code blocks. +- Modals: fix action buttons overflow +- Editing: don't insert edited posts to the top of the feed. +- Modals: close modal when navigating to a different page. +- Modals: fix "View context" button in media modal. +- Posts: let unauthenticated users to translate posts if allowed by backend. +- Chats: fix jumpy scrollbar. + +## [3.0.0] - 2022-12-25 + +### Added +- Editing: ability to edit posts and view edit history (on Rebased, Pleroma, and Mastodon). +- Events: ability to create, view, and comment on Events (on Rebased). +- Onboarding: display an introduction wizard to newly registered accounts. +- Posts: translate foreign language posts into your native language (on Rebased, Mastodon; if configured by the admin). +- Posts: ability to view quotes of a post (on Rebased). +- Posts: hover the "replying to" line to see a preview card of the parent post. +- Chats: ability to leave a chat (on Rebased, Truth Social). +- Chats: ability to disable chats for yourself. +- Layout: added right-to-left support for Arabic, Hebrew, Persian, and Central Kurdish languages. +- Composer: support custom emoji categories. +- Search: ability to search posts from a specific account (on Pleroma, Rebased). +- Theme: auto-detect system theme by default. +- Profile: remove a specific user from your followers (on Rebased, Mastodon). +- Suggestions: ability to view all suggested profiles. +- Feeds: display suggested accounts in Home feed (optional by admin). +- Compatibility: added compatibility with Truth Social, Fedibird, Pixelfed, Akkoma, and Glitch. +- Developers: added Test feed, Service Worker debugger, and Network Error preview. +- Reports: display server rules in reports. Let users select rule violations when submitting a report. +- Admin: added Theme Editor, a GUI for customizing the color scheme. +- Admin: custom badges. Admins can add non-federating badges to any user's profile (on Rebased, Pleroma). +- Admin: consolidated user dropdown actions (verify/suggest/etc) into a unified "Moderate User" modal. +- i18n: updated translations for Italian, Polish, Arabic, Hebrew, and German. +- Toast: added the ability to dismiss toast notifications. + +### Changed +- UI: the whole UI has been overhauled both inside and out. 97% of the codebase has been rewritten to TypeScript, and a new component library has been introduced with Tailwind CSS. +- Chats: redesigned chats. Includes an improved desktop UI, unified chat widget, expanding textarea, and autosuggestions. +- Lists: ability to edit and delete a list. +- Settings: unified settings under one path with separate sections. +- Posts: changed the thumbs-up icon to a heart. +- Posts: move instance favicon beside username instead of post timestamp. +- Posts: changed the behavior of content warnings. CWs and sensitive media are unified into one design. +- Posts: redesigned interaction counters to use text instead of icons. +- Posts: letterbox images taller than 1:1. +- Profile: overhauled user profiles to be consistent with the rest of the UI. +- Composer: move emoji button alongside other composer buttons, add numerical counter. +- Birthdays: move today's birthdays out of notifications into right sidebar. +- Performance: improve scrolling/navigation between feeds by using a virtual window library. +- Admin: reorganize UI into 3-column layout. +- Admin: include external link to frontend repo for the running commit. +- Toast: redesigned toast notifications. + +### Removed +- Theme: Halloween theme. +- Settings: advanced notification settings. +- Settings: dyslexic mode. +- Settings: demetricator. +- Profile: ability to set and view private notes on an account. +- Feeds: per-feed filters for replies, media, etc. +- Backup and export functionality (for now). +- Posts: hide non-emoji images embedded in post content. + +### Security +- Glitch Social: fixed XSS vulnerability on Glitch Social where custom emojis could be exploited to embed a script tag. + +## [2.0.0] - 2022-05-01 +### Added +- Quote Posting: repost with comment on Fedibird and Rebased. +- Profile: ability to feature other users on your profile (on Rebased, Mastodon). +- Profile: ability to add location to the user's profile (on Rebased, Truth Social). +- Birthdays: ability to add a birthday to your profile (on Rebased, Pleroma). +- Birthdays: support for age-gated registration if configured by the admin (on Rebased, Pleroma). +- Birthdays: display today's birthdays in notifications. +- Notifications: added unread badge to favicon when user has notifications. +- Notifications: display full attachments in notifications instead of links. +- Search: added a dedicated search page with prefilled suggestions. +- Compatibility: improved support for Mastodon, added support for Mitra. +- Ethereum: Metamask sign-in with Mitra. +- i18n: added Shavian alphabet (`en-Shaw`) transliteration. +- i18n: added Icelandic translation. + +### Changed +- Feeds: added gaps between posts in feeds. +- Feeds: automatically load new posts when scrolled to the top of the feed. +- Layout: improved design of top navigation bar. +- Layout: add left sidebar navigation. +- Icons: replaced Fork Awesome icons with Tabler icons. +- Posts: moved mentions out of the post content into an area above the post for replies (on Pleroma and Rebased - Mastodon falls back to the old behavior). +- Composer: use graphical ring counter for character count. + +### Fixed +- Multi-Account: fix switching between profiles on different servers with the same local username. + ## [1.3.0] - 2021-07-02 ### Changed - Layout: show right sidebar on all pages. diff --git a/app/soapbox/components/account.tsx b/app/soapbox/components/account.tsx index 2f7ff01e9..9f48c2db9 100644 --- a/app/soapbox/components/account.tsx +++ b/app/soapbox/components/account.tsx @@ -164,9 +164,9 @@ const Account = ({ const LinkEl: any = withLinkToProfile ? Link : 'div'; return ( -
+
- + {children}} @@ -186,7 +186,7 @@ const Account = ({ -
+
{children}} @@ -210,7 +210,7 @@ const Account = ({ - + @{username} {account.favicon && ( diff --git a/app/soapbox/components/announcements/announcement-content.tsx b/app/soapbox/components/announcements/announcement-content.tsx index f4265d1fd..a76ad9894 100644 --- a/app/soapbox/components/announcements/announcement-content.tsx +++ b/app/soapbox/components/announcements/announcement-content.tsx @@ -30,7 +30,7 @@ const AnnouncementContent: React.FC = ({ announcement }) = if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { e.preventDefault(); e.stopPropagation(); - history.push(`/tags/${hashtag}`); + history.push(`/tag/${hashtag}`); } }; diff --git a/app/soapbox/components/hashtag.tsx b/app/soapbox/components/hashtag.tsx index 6c1440c9b..d5618f60c 100644 --- a/app/soapbox/components/hashtag.tsx +++ b/app/soapbox/components/hashtag.tsx @@ -23,7 +23,7 @@ const Hashtag: React.FC = ({ hashtag }) => { return ( - + #{hashtag.name} diff --git a/app/soapbox/components/status.tsx b/app/soapbox/components/status.tsx index 7ec9c65dc..57c6ec2f4 100644 --- a/app/soapbox/components/status.tsx +++ b/app/soapbox/components/status.tsx @@ -287,14 +287,14 @@ const Status: React.FC = (props) => { data-id={status.id} > -
-
+
+
{ status.reblog && typeof status.reblog === 'object' && ( event.stopPropagation()} - className='flex items-center mb-3 text-gray-700 dark:text-gray-600 text-xs font-medium space-x-1 hover:underline' + className='flex items-center text-gray-700 dark:text-gray-600 text-xs font-medium space-x-1 hover:underline' > @@ -312,21 +312,21 @@ const Status: React.FC = (props) => { ) } -
-
- +
+ +
{!group && actualStatus.group && ( diff --git a/app/soapbox/components/status_content.tsx b/app/soapbox/components/status_content.tsx index 3fdfe7ecf..0a02625cb 100644 --- a/app/soapbox/components/status_content.tsx +++ b/app/soapbox/components/status_content.tsx @@ -99,7 +99,7 @@ const StatusContent: React.FC = ({ status, expanded = false, onE if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { e.preventDefault(); e.stopPropagation(); - history.push(`/tags/${hashtag}`); + history.push(`/tag/${hashtag}`); } }; diff --git a/app/soapbox/features/backups/index.tsx b/app/soapbox/features/backups/index.tsx index c74b1bf60..3564e0540 100644 --- a/app/soapbox/features/backups/index.tsx +++ b/app/soapbox/features/backups/index.tsx @@ -1,9 +1,9 @@ -import classNames from 'classnames'; import React, { useEffect, useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { fetchBackups, createBackup } from 'soapbox/actions/backups'; import ScrollableList from 'soapbox/components/scrollable_list'; +import { Button, FormActions, Text, Spinner } from 'soapbox/components/ui'; import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; import Column from '../ui/components/better_column'; @@ -24,22 +24,14 @@ const Backups = () => { const [isLoading, setIsLoading] = useState(true); - const handleCreateBackup: React.MouseEventHandler = e => { + const handleCreateBackup: React.MouseEventHandler = e => { dispatch(createBackup()); e.preventDefault(); }; - const makeColumnMenu = () => { - return [{ - text: intl.formatMessage(messages.create), - action: handleCreateBackup, - icon: require('@tabler/icons/plus.svg'), - }]; - }; - useEffect(() => { dispatch(fetchBackups()).then(() => { - setIsLoading(true); + setIsLoading(false); }).catch(() => {}); }, []); @@ -47,30 +39,47 @@ const Backups = () => { const emptyMessageAction = ( - {intl.formatMessage(messages.emptyMessageAction)} + + {intl.formatMessage(messages.emptyMessageAction)} + ); return ( - + - {backups.map((backup) => ( -
- {backup.processed - ? {backup.inserted_at} - :
{intl.formatMessage(messages.pending)}: {backup.inserted_at}
- } -
- ))} + {backups.map((backup) => { + const insertedAt = new Date(backup.inserted_at).toLocaleDateString(undefined, { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }); + return ( +
+
+ {backup.processed + ? {insertedAt} + : {insertedAt} - {intl.formatMessage(messages.pending)} + } +
+ { + !backup.processed && + } +
+ ); + })}
+
+ + + +
); }; diff --git a/app/soapbox/features/settings/index.tsx b/app/soapbox/features/settings/index.tsx index dd5b84388..a989cf525 100644 --- a/app/soapbox/features/settings/index.tsx +++ b/app/soapbox/features/settings/index.tsx @@ -33,6 +33,9 @@ const messages = defineMessages({ domainBlocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Hidden domains' }, mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' }, filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' }, + backups: { id: 'column.backups', defaultMessage: 'Backups' }, + importData: { id: 'navigation_bar.import_data', defaultMessage: 'Import data' }, + exportData: { id: 'column.export_data', defaultMessage: 'Export data' }, }); /** User settings page. */ @@ -54,6 +57,9 @@ const Settings = () => { const navigateToDeleteAccount = () => history.push('/settings/account'); const navigateToMoveAccount = () => history.push('/settings/migration'); const navigateToAliases = () => history.push('/settings/aliases'); + const navigateToBackups = () => history.push('/settings/backups'); + const navigateToImportData = () => history.push('/settings/import'); + const navigateToExportData = () => history.push('/settings/export'); const navigateToBlocks = () => history.push('/blocks'); const navigateToMutes = () => history.push('/mutes'); @@ -150,14 +156,27 @@ const Settings = () => { - {features.security && ( - + {features.importData && ( + )} + + {features.exportData && ( + + )} + + {features.backups && ( + + )} + {features.federating && (features.accountMoving ? ( ) : features.accountAliases && ( ))} + + {features.security && ( + + )} diff --git a/app/soapbox/features/ui/components/link_footer.tsx b/app/soapbox/features/ui/components/link_footer.tsx index 4a78372a1..c0d3841fa 100644 --- a/app/soapbox/features/ui/components/link_footer.tsx +++ b/app/soapbox/features/ui/components/link_footer.tsx @@ -46,9 +46,6 @@ const LinkFooter: React.FC = (): JSX.Element => { {account.locked && ( )} - {features.import && ( - - )} }
diff --git a/app/soapbox/features/ui/index.tsx b/app/soapbox/features/ui/index.tsx index e0fdcbbde..a5c199f69 100644 --- a/app/soapbox/features/ui/index.tsx +++ b/app/soapbox/features/ui/index.tsx @@ -83,9 +83,9 @@ import { EmailConfirmation, DeleteAccount, SoapboxConfig, - // ExportData, + ExportData, ImportData, - // Backups, + Backups, MfaForm, ChatIndex, ChatRoom, @@ -209,7 +209,7 @@ const SwitchingColumnsArea: React.FC = ({ children }) => { - + @@ -245,7 +245,7 @@ const SwitchingColumnsArea: React.FC = ({ children }) => { - + {features.lists && } {features.lists && } @@ -283,11 +283,11 @@ const SwitchingColumnsArea: React.FC = ({ children }) => { {features.scheduledStatuses && } - {/* FIXME: this could DDoS our API? :\ */} - {/* */} + {features.exportData && } {features.importData && } {features.accountAliases && } {features.accountMoving && } + {features.backups && } { !isLdapEnabled && ( @@ -299,7 +299,6 @@ const SwitchingColumnsArea: React.FC = ({ children }) => { - {/* */} diff --git a/app/soapbox/locales/fr.json b/app/soapbox/locales/fr.json index 858c873c5..eb442ac18 100644 --- a/app/soapbox/locales/fr.json +++ b/app/soapbox/locales/fr.json @@ -173,10 +173,10 @@ "auth.invalid_credentials": "Wrong username or password", "auth.logged_out": "Logged out.", "auth_layout.register": "Create an account", - "backups.actions.create": "Create backup", - "backups.empty_message": "No backups found. {action}", - "backups.empty_message.action": "Create one now?", - "backups.pending": "Pending", + "backups.actions.create": "Créer une sauvegarde", + "backups.empty_message": "Pas de sauvegarde. {action}", + "backups.empty_message.action": "Créer une sauvegarde maintenant ?", + "backups.pending": "Sauvegarde en cours", "birthday_panel.title": "Birthdays", "birthdays_modal.empty": "None of your friends have birthday today.", "boost_modal.combo": "Vous pouvez appuyer sur {combo} pour passer ceci, la prochaine fois", @@ -213,7 +213,7 @@ "column.aliases.subheading_add_new": "Ajouter un alias", "column.aliases.subheading_aliases": "Alias courants", "column.app_create": "Create app", - "column.backups": "Backups", + "column.backups": "Sauvegardes", "column.birthdays": "Birthdays", "column.blocks": "Comptes bloqués", "column.bookmarks": "Marque-pages", @@ -225,7 +225,7 @@ "column.directory": "Annuaire", "column.domain_blocks": "Domaines cachés", "column.edit_profile": "Éditer le profil", - "column.export_data": "Export data", + "column.export_data": "Exporter vos données", "column.familiar_followers": "People you know following {name}", "column.favourited_statuses": "Liked posts", "column.favourites": "Likes", @@ -508,18 +508,18 @@ "empty_column.search.statuses": "Il n'y a pas de statuts correspondant à la recherche \"{term}\"", "empty_column.test": "The test timeline is empty.", "export_data.actions.export": "Export", - "export_data.actions.export_blocks": "Export blocks", - "export_data.actions.export_follows": "Export follows", - "export_data.actions.export_mutes": "Export mutes", - "export_data.blocks_label": "Blocks", - "export_data.follows_label": "Follows", - "export_data.hints.blocks": "Get a CSV file containing a list of blocked accounts", - "export_data.hints.follows": "Get a CSV file containing a list of followed accounts", - "export_data.hints.mutes": "Get a CSV file containing a list of muted accounts", - "export_data.mutes_label": "Mutes", - "export_data.success.blocks": "Blocks exported successfully", - "export_data.success.followers": "Followers exported successfully", - "export_data.success.mutes": "Mutes exported successfully", + "export_data.actions.export_blocks": "Exporter les comptes bloqués", + "export_data.actions.export_follows": "Exporter les comptes suivis", + "export_data.actions.export_mutes": "Exporter les comptes masqués", + "export_data.blocks_label": "Comptes bloqués", + "export_data.follows_label": "Comptes suivis", + "export_data.hints.blocks": "Obtenez un fichier csv contenant la liste des comptes bloqués", + "export_data.hints.follows": "Obtenez un fichier csv contenant la liste des comptes suivis", + "export_data.hints.mutes": "Obtenez un fichier csv contenant la liste des comptes masqués", + "export_data.mutes_label": "Comptes masqués", + "export_data.success.blocks": "Comptes bloqués exportés", + "export_data.success.followers": "Comptes suivis exportés", + "export_data.success.mutes": "Comptes masqués exportés", "federation_restriction.federated_timeline_removal": "Fediverse timeline removal", "federation_restriction.followers_only": "Hidden except to followers", "federation_restriction.full_media_removal": "Full media removal", @@ -989,14 +989,14 @@ "security.update_email.success": "Email mis à jour.", "security.update_password.fail": "Echec de la mise à jour du mot de passe.", "security.update_password.success": "Mot de passe mis à jour.", - "settings.account_migration": "Move Account", + "settings.account_migration": "Migrer votre compte", "settings.change_email": "Changer d'email", "settings.change_password": "Changer de mot de passe", "settings.configure_mfa": "Configurer le MFA", "settings.content": "Contenu", "settings.delete_account": "Supprimer le compte", "settings.edit_profile": "Mettre à jour le profil", - "settings.other": "Other options", + "settings.other": "Compte", "settings.preferences": "Préférences", "settings.profile": "Profil", "settings.save.success": "Vos préférences ont été enregistrées.", diff --git a/app/soapbox/utils/features.ts b/app/soapbox/utils/features.ts index 92334bf77..6f4064b70 100644 --- a/app/soapbox/utils/features.ts +++ b/app/soapbox/utils/features.ts @@ -166,6 +166,13 @@ const getInstanceFeatures = (instance: Instance) => { */ announcementsReactions: v.software === MASTODON && gte(v.compatVersion, '3.1.0'), + /** + * Pleroma backups. + * @see GET /api/v1/pleroma/backups + * @see POST /api/v1/pleroma/backups + */ + backups: v.software === PLEROMA || v.software === AKKOMA, + /** * Set your birthday and view upcoming birthdays. * @see GET /api/v1/pleroma/birthdays @@ -288,6 +295,9 @@ const getInstanceFeatures = (instance: Instance) => { v.software === TRUTHSOCIAL, ]), + /** Whether to allow exporting follows/blocks/mutes to CSV by paginating the API. */ + exportData: true, + /** Whether the accounts who favourited or emoji-reacted to a status can be viewed through the API. */ exposableReactions: any([ v.software === MASTODON, diff --git a/app/styles/application.scss b/app/styles/application.scss index ec7669778..abd8d1800 100644 --- a/app/styles/application.scss +++ b/app/styles/application.scss @@ -66,7 +66,6 @@ @import 'components/accordion'; @import 'components/server-info'; @import 'components/admin'; -@import 'components/backups'; @import 'components/crypto-donate'; @import 'components/remote-timeline'; @import 'components/aliases'; diff --git a/app/styles/components/backups.scss b/app/styles/components/backups.scss deleted file mode 100644 index 57f1144f7..000000000 --- a/app/styles/components/backups.scss +++ /dev/null @@ -1,13 +0,0 @@ -.backup { - padding: 15px; - border-bottom: 1px solid var(--brand-color--faint); - - a { - color: var(--brand-color--hicontrast); - } - - &--pending { - font-style: italic; - color: var(--primary-text-color--faint); - } -} diff --git a/app/styles/components/snackbar.scss b/app/styles/components/snackbar.scss index 7ebdf19eb..d9500583e 100644 --- a/app/styles/components/snackbar.scss +++ b/app/styles/components/snackbar.scss @@ -26,7 +26,7 @@ &::before { @apply ml-4; - content: '\f057'; + content: '\f06a'; } }