Bookmark folders

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak
2024-03-20 23:58:53 +01:00
parent 460e22ce2b
commit eceafedec4
31 changed files with 748 additions and 60 deletions

View File

@ -15,70 +15,77 @@ const BOOKMARKED_STATUSES_EXPAND_FAIL = 'BOOKMARKED_STATUSES_EXPAND_FAIL';
const noOp = () => new Promise(f => f(undefined));
const fetchBookmarkedStatuses = () =>
const fetchBookmarkedStatuses = (folderId?: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (getState().status_lists.get('bookmarks')?.isLoading) {
if (getState().status_lists.get(folderId ? `bookmarks:${folderId}` : 'bookmarks')?.isLoading) {
return dispatch(noOp);
}
dispatch(fetchBookmarkedStatusesRequest());
dispatch(fetchBookmarkedStatusesRequest(folderId));
return api(getState).get('/api/v1/bookmarks').then(response => {
return api(getState).get(`/api/v1/bookmarks${folderId ? `?folder_id=${folderId}` : ''}`).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data));
return dispatch(fetchBookmarkedStatusesSuccess(response.data, next ? next.uri : null));
return dispatch(fetchBookmarkedStatusesSuccess(response.data, next ? next.uri : null, folderId));
}).catch(error => {
dispatch(fetchBookmarkedStatusesFail(error));
dispatch(fetchBookmarkedStatusesFail(error, folderId));
});
};
const fetchBookmarkedStatusesRequest = () => ({
const fetchBookmarkedStatusesRequest = (folderId?: string) => ({
type: BOOKMARKED_STATUSES_FETCH_REQUEST,
folderId,
});
const fetchBookmarkedStatusesSuccess = (statuses: APIEntity[], next: string | null) => ({
const fetchBookmarkedStatusesSuccess = (statuses: APIEntity[], next: string | null, folderId?: string) => ({
type: BOOKMARKED_STATUSES_FETCH_SUCCESS,
statuses,
next,
folderId,
});
const fetchBookmarkedStatusesFail = (error: unknown) => ({
const fetchBookmarkedStatusesFail = (error: unknown, folderId?: string) => ({
type: BOOKMARKED_STATUSES_FETCH_FAIL,
error,
folderId,
});
const expandBookmarkedStatuses = () =>
const expandBookmarkedStatuses = (folderId?: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const url = getState().status_lists.get('bookmarks')?.next || null;
const list = folderId ? `bookmarks:${folderId}` : 'bookmarks';
const url = getState().status_lists.get(list)?.next || null;
if (url === null || getState().status_lists.get('bookmarks')?.isLoading) {
if (url === null || getState().status_lists.get(list)?.isLoading) {
return dispatch(noOp);
}
dispatch(expandBookmarkedStatusesRequest());
dispatch(expandBookmarkedStatusesRequest(folderId));
return api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data));
return dispatch(expandBookmarkedStatusesSuccess(response.data, next ? next.uri : null));
return dispatch(expandBookmarkedStatusesSuccess(response.data, next ? next.uri : null, folderId));
}).catch(error => {
dispatch(expandBookmarkedStatusesFail(error));
dispatch(expandBookmarkedStatusesFail(error, folderId));
});
};
const expandBookmarkedStatusesRequest = () => ({
const expandBookmarkedStatusesRequest = (folderId?: string) => ({
type: BOOKMARKED_STATUSES_EXPAND_REQUEST,
folderId,
});
const expandBookmarkedStatusesSuccess = (statuses: APIEntity[], next: string | null) => ({
const expandBookmarkedStatusesSuccess = (statuses: APIEntity[], next: string | null, folderId?: string) => ({
type: BOOKMARKED_STATUSES_EXPAND_SUCCESS,
statuses,
next,
folderId,
});
const expandBookmarkedStatusesFail = (error: unknown) => ({
const expandBookmarkedStatusesFail = (error: unknown, folderId?: string) => ({
type: BOOKMARKED_STATUSES_EXPAND_FAIL,
error,
folderId,
});
export {

View File

@ -1,12 +1,14 @@
import { defineMessages } from 'react-intl';
import toast from 'soapbox/toast';
import toast, { type IToastOptions } from 'soapbox/toast';
import { isLoggedIn } from 'soapbox/utils/auth';
import { getFeatures } from 'soapbox/utils/features';
import api, { getLinks } from '../api';
import { fetchRelationships } from './accounts';
import { importFetchedAccounts, importFetchedStatus } from './importer';
import { openModal } from './modals';
import { expandGroupFeaturedTimeline } from './timelines';
import type { AppDispatch, RootState } from 'soapbox/store';
@ -85,7 +87,9 @@ const ZAP_FAIL = 'ZAP_FAIL';
const messages = defineMessages({
bookmarkAdded: { id: 'status.bookmarked', defaultMessage: 'Bookmark added.' },
bookmarkRemoved: { id: 'status.unbookmarked', defaultMessage: 'Bookmark removed.' },
folderChanged: { id: 'status.bookmark_folder_changed', defaultMessage: 'Changed folder' },
view: { id: 'toast.view', defaultMessage: 'View' },
selectFolder: { id: 'status.bookmark.select_folder', defaultMessage: 'Select folder' },
});
const reblog = (status: StatusEntity) =>
@ -342,17 +346,35 @@ const zapFail = (status: StatusEntity, error: unknown) => ({
skipLoading: true,
});
const bookmark = (status: StatusEntity) =>
const bookmark = (status: StatusEntity, folderId?: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const state = getState();
const instance = state.instance;
const features = getFeatures(instance);
dispatch(bookmarkRequest(status));
api(getState).post(`/api/v1/statuses/${status.id}/bookmark`).then(function(response) {
return api(getState).post(`/api/v1/statuses/${status.id}/bookmark`, {
folder_id: folderId,
}).then(function(response) {
dispatch(importFetchedStatus(response.data));
dispatch(bookmarkSuccess(status, response.data));
toast.success(messages.bookmarkAdded, {
let opts: IToastOptions = {
actionLabel: messages.view,
actionLink: '/bookmarks',
});
actionLink: folderId ? `/bookmarks/${folderId}` : '/bookmarks/all',
};
if (features.bookmarkFolders && typeof folderId !== 'string') {
opts = {
actionLabel: messages.selectFolder,
action: () => dispatch(openModal('SELECT_BOOKMARK_FOLDER', {
statusId: status.id,
})),
};
}
toast.success(typeof folderId === 'string' ? messages.folderChanged : messages.bookmarkAdded, opts);
}).catch(function(error) {
dispatch(bookmarkFail(status, error));
});