Merge branch 'develop' of https://code.gab.com/gab/social/gab-social into feature/frontend_refactor
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import api from '../api';
|
||||
import { CancelToken, isCancel } from 'axios';
|
||||
import { throttle } from 'lodash';
|
||||
import moment from 'moment';
|
||||
import { search as emojiSearch } from '../components/emoji/emoji_mart_search_light';
|
||||
import { tagHistory } from '../settings';
|
||||
import { useEmoji } from './emojis';
|
||||
@@ -20,6 +21,7 @@ export const COMPOSE_SUBMIT_REQUEST = 'COMPOSE_SUBMIT_REQUEST';
|
||||
export const COMPOSE_SUBMIT_SUCCESS = 'COMPOSE_SUBMIT_SUCCESS';
|
||||
export const COMPOSE_SUBMIT_FAIL = 'COMPOSE_SUBMIT_FAIL';
|
||||
export const COMPOSE_REPLY = 'COMPOSE_REPLY';
|
||||
export const COMPOSE_QUOTE = 'COMPOSE_QUOTE';
|
||||
export const COMPOSE_REPLY_CANCEL = 'COMPOSE_REPLY_CANCEL';
|
||||
export const COMPOSE_DIRECT = 'COMPOSE_DIRECT';
|
||||
export const COMPOSE_MENTION = 'COMPOSE_MENTION';
|
||||
@@ -60,6 +62,8 @@ export const COMPOSE_POLL_OPTION_CHANGE = 'COMPOSE_POLL_OPTION_CHANGE';
|
||||
export const COMPOSE_POLL_OPTION_REMOVE = 'COMPOSE_POLL_OPTION_REMOVE';
|
||||
export const COMPOSE_POLL_SETTINGS_CHANGE = 'COMPOSE_POLL_SETTINGS_CHANGE';
|
||||
|
||||
export const COMPOSE_SCHEDULED_AT_CHANGE = 'COMPOSE_SCHEDULED_AT_CHANGE';
|
||||
|
||||
const messages = defineMessages({
|
||||
uploadErrorLimit: { id: 'upload_error.limit', defaultMessage: 'File upload limit exceeded.' },
|
||||
uploadErrorPoll: { id: 'upload_error.poll', defaultMessage: 'File upload not allowed with polls.' },
|
||||
@@ -91,6 +95,17 @@ export function replyCompose(status, routerHistory) {
|
||||
};
|
||||
};
|
||||
|
||||
export function quoteCompose(status, routerHistory) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: COMPOSE_QUOTE,
|
||||
status: status,
|
||||
});
|
||||
|
||||
dispatch(openModal('COMPOSE'));
|
||||
};
|
||||
};
|
||||
|
||||
export function cancelReplyCompose() {
|
||||
return {
|
||||
type: COMPOSE_REPLY_CANCEL,
|
||||
@@ -125,6 +140,45 @@ export function directCompose(account, routerHistory) {
|
||||
};
|
||||
};
|
||||
|
||||
export function handleComposeSubmit(dispatch, getState, response, status) {
|
||||
if (!dispatch || !getState) return;
|
||||
|
||||
const isScheduledStatus = response.data['scheduled_at'] !== undefined;
|
||||
if (isScheduledStatus) {
|
||||
dispatch(showAlertForError({
|
||||
response: {
|
||||
data: {},
|
||||
status: 200,
|
||||
statusText: 'Successfully scheduled status',
|
||||
}
|
||||
}));
|
||||
dispatch(submitComposeSuccess({ ...response.data }));
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(insertIntoTagHistory(response.data.tags, status));
|
||||
dispatch(submitComposeSuccess({ ...response.data }));
|
||||
|
||||
// To make the app more responsive, immediately push the status into the columns
|
||||
const insertIfOnline = timelineId => {
|
||||
const timeline = getState().getIn(['timelines', timelineId]);
|
||||
|
||||
if (timeline && timeline.get('items').size > 0 && timeline.getIn(['items', 0]) !== null && timeline.get('online')) {
|
||||
let dequeueArgs = {};
|
||||
if (timelineId === 'community') dequeueArgs.onlyMedia = getState().getIn(['settings', 'community', 'other', 'onlyMedia']);
|
||||
dispatch(dequeueTimeline(timelineId, null, dequeueArgs));
|
||||
dispatch(updateTimeline(timelineId, { ...response.data }));
|
||||
}
|
||||
};
|
||||
|
||||
if (response.data.visibility !== 'direct') {
|
||||
insertIfOnline('home');
|
||||
} else if (response.data.in_reply_to_id === null && response.data.visibility === 'public') {
|
||||
insertIfOnline('community');
|
||||
insertIfOnline('public');
|
||||
}
|
||||
}
|
||||
|
||||
export function submitCompose(routerHistory, group) {
|
||||
return function (dispatch, getState) {
|
||||
if (!me) return;
|
||||
@@ -139,9 +193,20 @@ export function submitCompose(routerHistory, group) {
|
||||
dispatch(submitComposeRequest());
|
||||
dispatch(closeModal());
|
||||
|
||||
api(getState).post('/api/v1/statuses', {
|
||||
const id = getState().getIn(['compose', 'id']);
|
||||
const endpoint = id === null
|
||||
? '/api/v1/statuses'
|
||||
: `/api/v1/statuses/${id}`;
|
||||
const method = id === null ? 'post' : 'put';
|
||||
|
||||
let scheduled_at = getState().getIn(['compose', 'scheduled_at'], null);
|
||||
if (scheduled_at !== null) scheduled_at = moment.utc(scheduled_at).toDate();
|
||||
|
||||
api(getState)[method](endpoint, {
|
||||
status,
|
||||
scheduled_at,
|
||||
in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
|
||||
quote_of_id: getState().getIn(['compose', 'quote_of_id'], null),
|
||||
media_ids: media.map(item => item.get('id')),
|
||||
sensitive: getState().getIn(['compose', 'sensitive']),
|
||||
spoiler_text: getState().getIn(['compose', 'spoiler_text'], ''),
|
||||
@@ -156,33 +221,7 @@ export function submitCompose(routerHistory, group) {
|
||||
if (response.data.visibility === 'direct' && getState().getIn(['conversations', 'mounted']) <= 0 && routerHistory) {
|
||||
routerHistory.push('/messages');
|
||||
}
|
||||
|
||||
dispatch(insertIntoTagHistory(response.data.tags, status));
|
||||
dispatch(submitComposeSuccess({ ...response.data }));
|
||||
|
||||
// To make the app more responsive, immediately push the status
|
||||
// into the columns
|
||||
|
||||
const insertIfOnline = timelineId => {
|
||||
const timeline = getState().getIn(['timelines', timelineId]);
|
||||
|
||||
if (timeline && timeline.get('items').size > 0 && timeline.getIn(['items', 0]) !== null && timeline.get('online')) {
|
||||
let dequeueArgs = {};
|
||||
if (timelineId === 'community') dequeueArgs.onlyMedia = getState().getIn(['settings', 'community', 'other', 'onlyMedia']),
|
||||
|
||||
dispatch(dequeueTimeline(timelineId, null, dequeueArgs));
|
||||
dispatch(updateTimeline(timelineId, { ...response.data }));
|
||||
}
|
||||
};
|
||||
|
||||
if (response.data.visibility !== 'direct') {
|
||||
insertIfOnline('home');
|
||||
}
|
||||
|
||||
if (response.data.in_reply_to_id === null && response.data.visibility === 'public') {
|
||||
insertIfOnline('community');
|
||||
insertIfOnline('public');
|
||||
}
|
||||
handleComposeSubmit(dispatch, getState, response, status);
|
||||
}).catch(function (error) {
|
||||
dispatch(submitComposeFail(error));
|
||||
});
|
||||
@@ -561,3 +600,10 @@ export function changePollSettings(expiresIn, isMultiple) {
|
||||
isMultiple,
|
||||
};
|
||||
};
|
||||
|
||||
export function changeScheduledAt(date) {
|
||||
return {
|
||||
type: COMPOSE_SCHEDULED_AT_CHANGE,
|
||||
date,
|
||||
};
|
||||
};
|
||||
@@ -51,6 +51,10 @@ export const GROUP_REMOVE_STATUS_REQUEST = 'GROUP_REMOVE_STATUS_REQUEST';
|
||||
export const GROUP_REMOVE_STATUS_SUCCESS = 'GROUP_REMOVE_STATUS_SUCCESS';
|
||||
export const GROUP_REMOVE_STATUS_FAIL = 'GROUP_REMOVE_STATUS_FAIL';
|
||||
|
||||
export const GROUP_UPDATE_ROLE_REQUEST = 'GROUP_UPDATE_ROLE_REQUEST';
|
||||
export const GROUP_UPDATE_ROLE_SUCCESS = 'GROUP_UPDATE_ROLE_SUCCESS';
|
||||
export const GROUP_UPDATE_ROLE_FAIL = 'GROUP_UPDATE_ROLE_FAIL';
|
||||
|
||||
export const fetchGroup = id => (dispatch, getState) => {
|
||||
if (!me) return;
|
||||
|
||||
@@ -521,4 +525,43 @@ export function groupRemoveStatusFail(groupId, id, error) {
|
||||
id,
|
||||
error,
|
||||
};
|
||||
};
|
||||
|
||||
export function updateRole(groupId, id, role) {
|
||||
return (dispatch, getState) => {
|
||||
if (!me) return;
|
||||
|
||||
dispatch(updateRoleRequest(groupId, id));
|
||||
|
||||
api(getState).patch(`/api/v1/groups/${groupId}/accounts?account_id=${id}`, { role }).then(response => {
|
||||
dispatch(updateRoleSuccess(groupId, id));
|
||||
}).catch(error => {
|
||||
dispatch(updateRoleFail(groupId, id, error));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function updateRoleRequest(groupId, id) {
|
||||
return {
|
||||
type: GROUP_REMOVED_ACCOUNTS_CREATE_REQUEST,
|
||||
groupId,
|
||||
id,
|
||||
};
|
||||
};
|
||||
|
||||
export function updateRoleSuccess(groupId, id) {
|
||||
return {
|
||||
type: GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS,
|
||||
groupId,
|
||||
id,
|
||||
};
|
||||
};
|
||||
|
||||
export function updateRoleFail(groupId, id, error) {
|
||||
return {
|
||||
type: GROUP_REMOVED_ACCOUNTS_CREATE_FAIL,
|
||||
groupId,
|
||||
id,
|
||||
error,
|
||||
};
|
||||
};
|
||||
@@ -71,6 +71,10 @@ export function importFetchedStatuses(statuses) {
|
||||
processStatus(status.reblog);
|
||||
}
|
||||
|
||||
if (status.quote && status.quote.id) {
|
||||
processStatus(status.quote);
|
||||
}
|
||||
|
||||
if (status.poll && status.poll.id) {
|
||||
pushUnique(polls, normalizePoll(status.poll));
|
||||
}
|
||||
|
||||
@@ -43,13 +43,17 @@ export function normalizeStatus(status, normalOldStatus) {
|
||||
normalStatus.reblog = status.reblog.id;
|
||||
}
|
||||
|
||||
if (status.quote && status.quote.id) {
|
||||
normalStatus.quote = status.quote.id;
|
||||
}
|
||||
|
||||
if (status.poll && status.poll.id) {
|
||||
normalStatus.poll = status.poll.id;
|
||||
}
|
||||
|
||||
// Only calculate these values when status first encountered
|
||||
// Otherwise keep the ones already in the reducer
|
||||
if (normalOldStatus) {
|
||||
if (normalOldStatus && normalOldStatus.get('content') === normalStatus.content && normalOldStatus.get('spoiler_text') === normalStatus.spoiler_text) {
|
||||
normalStatus.search_index = normalOldStatus.get('search_index');
|
||||
normalStatus.contentHtml = normalOldStatus.get('contentHtml');
|
||||
normalStatus.spoilerHtml = normalOldStatus.get('spoilerHtml');
|
||||
|
||||
@@ -14,6 +14,7 @@ import { unescapeHTML } from '../utils/html';
|
||||
import { getFilters, regexFromFilters } from '../selectors';
|
||||
import { me } from 'gabsocial/initial_state';
|
||||
|
||||
export const NOTIFICATIONS_INITIALIZE = 'NOTIFICATIONS_INITIALIZE';
|
||||
export const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE';
|
||||
export const NOTIFICATIONS_UPDATE_NOOP = 'NOTIFICATIONS_UPDATE_NOOP';
|
||||
export const NOTIFICATIONS_UPDATE_QUEUE = 'NOTIFICATIONS_UPDATE_QUEUE';
|
||||
@@ -27,6 +28,7 @@ export const NOTIFICATIONS_FILTER_SET = 'NOTIFICATIONS_FILTER_SET';
|
||||
|
||||
export const NOTIFICATIONS_CLEAR = 'NOTIFICATIONS_CLEAR';
|
||||
export const NOTIFICATIONS_SCROLL_TOP = 'NOTIFICATIONS_SCROLL_TOP';
|
||||
export const NOTIFICATIONS_MARK_READ = 'NOTIFICATIONS_MARK_READ';
|
||||
|
||||
export const MAX_QUEUED_NOTIFICATIONS = 40;
|
||||
|
||||
@@ -43,6 +45,12 @@ const fetchRelatedRelationships = (dispatch, notifications) => {
|
||||
}
|
||||
};
|
||||
|
||||
export function initializeNotifications() {
|
||||
return {
|
||||
type: NOTIFICATIONS_INITIALIZE,
|
||||
};
|
||||
}
|
||||
|
||||
export function updateNotifications(notification, intlMessages, intlLocale) {
|
||||
return (dispatch, getState) => {
|
||||
const showInColumn = getState().getIn(['settings', 'notifications', 'shows', notification.type], true);
|
||||
@@ -134,6 +142,7 @@ export function dequeueNotifications() {
|
||||
dispatch({
|
||||
type: NOTIFICATIONS_DEQUEUE,
|
||||
});
|
||||
dispatch(markReadNotifications());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -225,10 +234,13 @@ export function clearNotifications() {
|
||||
};
|
||||
|
||||
export function scrollTopNotifications(top) {
|
||||
return {
|
||||
type: NOTIFICATIONS_SCROLL_TOP,
|
||||
top,
|
||||
};
|
||||
return (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: NOTIFICATIONS_SCROLL_TOP,
|
||||
top,
|
||||
});
|
||||
dispatch(markReadNotifications());
|
||||
}
|
||||
};
|
||||
|
||||
export function setFilter (filterType) {
|
||||
@@ -242,3 +254,20 @@ export function setFilter (filterType) {
|
||||
dispatch(saveSettings());
|
||||
};
|
||||
};
|
||||
|
||||
export function markReadNotifications() {
|
||||
return (dispatch, getState) => {
|
||||
if (!me) return;
|
||||
const top_notification = parseInt(getState().getIn(['notifications', 'items', 0, 'id']));
|
||||
const last_read = getState().getIn(['notifications', 'lastRead']);
|
||||
|
||||
if (top_notification && top_notification > last_read) {
|
||||
api(getState).post('/api/v1/notifications/mark_read', {id: top_notification}).then(response => {
|
||||
dispatch({
|
||||
type: NOTIFICATIONS_MARK_READ,
|
||||
notification: top_notification,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -37,7 +37,6 @@ export function submitSearch() {
|
||||
params: {
|
||||
q: value,
|
||||
resolve: true,
|
||||
limit: 5,
|
||||
},
|
||||
}).then(response => {
|
||||
if (response.data.accounts) {
|
||||
|
||||
14
app/javascript/gabsocial/actions/sidebar.js
Normal file
14
app/javascript/gabsocial/actions/sidebar.js
Normal file
@@ -0,0 +1,14 @@
|
||||
export const SIDEBAR_OPEN = 'SIDEBAR_OPEN';
|
||||
export const SIDEBAR_CLOSE = 'SIDEBAR_CLOSE';
|
||||
|
||||
export function openSidebar() {
|
||||
return {
|
||||
type: SIDEBAR_OPEN,
|
||||
};
|
||||
};
|
||||
|
||||
export function closeSidebar() {
|
||||
return {
|
||||
type: SIDEBAR_CLOSE,
|
||||
};
|
||||
};
|
||||
16
app/javascript/gabsocial/actions/status_revision_list.js
Normal file
16
app/javascript/gabsocial/actions/status_revision_list.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import api from '../api';
|
||||
|
||||
export const STATUS_REVISION_LIST_LOAD = 'STATUS_REVISION_LIST';
|
||||
export const STATUS_REVISION_LIST_LOAD_SUCCESS = 'STATUS_REVISION_LIST_SUCCESS';
|
||||
export const STATUS_REVISION_LIST_LOAD_FAIL = 'STATUS_REVISION_LIST_FAIL';
|
||||
|
||||
const loadSuccess = data => ({ type: STATUS_REVISION_LIST_LOAD_SUCCESS, payload: data });
|
||||
const loadFail = e => ({ type: STATUS_REVISION_LIST_LOAD_FAIL, payload: e });
|
||||
|
||||
export function load(statusId) {
|
||||
return (dispatch, getState) => {
|
||||
api(getState).get(`/api/v1/statuses/${statusId}/revisions`)
|
||||
.then(res => dispatch(loadSuccess(res.data)))
|
||||
.catch(e => dispatch(loadFail(e)));
|
||||
};
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import openDB from '../storage/db';
|
||||
import { evictStatus } from '../storage/modifier';
|
||||
import { deleteFromTimelines } from './timelines';
|
||||
import { importFetchedStatus, importFetchedStatuses, importAccount, importStatus } from './importer';
|
||||
import { ensureComposeIsVisible } from './compose';
|
||||
import { openModal } from './modal';
|
||||
import { me } from 'gabsocial/initial_state';
|
||||
|
||||
export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST';
|
||||
@@ -29,7 +29,7 @@ export const STATUS_UNMUTE_FAIL = 'STATUS_UNMUTE_FAIL';
|
||||
export const STATUS_REVEAL = 'STATUS_REVEAL';
|
||||
export const STATUS_HIDE = 'STATUS_HIDE';
|
||||
|
||||
export const REDRAFT = 'REDRAFT';
|
||||
export const STATUS_EDIT = 'STATUS_EDIT';
|
||||
|
||||
export function fetchStatusRequest(id, skipLoading) {
|
||||
return {
|
||||
@@ -132,15 +132,18 @@ export function fetchStatusFail(id, error, skipLoading) {
|
||||
};
|
||||
};
|
||||
|
||||
export function redraft(status, raw_text) {
|
||||
return {
|
||||
type: REDRAFT,
|
||||
status,
|
||||
raw_text,
|
||||
export function editStatus(status) {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: STATUS_EDIT,
|
||||
status,
|
||||
});
|
||||
|
||||
dispatch(openModal('COMPOSE'));
|
||||
};
|
||||
};
|
||||
|
||||
export function deleteStatus(id, routerHistory, withRedraft = false) {
|
||||
export function deleteStatus(id, routerHistory) {
|
||||
return (dispatch, getState) => {
|
||||
if (!me) return;
|
||||
|
||||
@@ -156,11 +159,6 @@ export function deleteStatus(id, routerHistory, withRedraft = false) {
|
||||
evictStatus(id);
|
||||
dispatch(deleteStatusSuccess(id));
|
||||
dispatch(deleteFromTimelines(id));
|
||||
|
||||
if (withRedraft) {
|
||||
dispatch(redraft(status, response.data.text));
|
||||
ensureComposeIsVisible(getState, routerHistory);
|
||||
}
|
||||
}).catch(error => {
|
||||
dispatch(deleteStatusFail(id, error));
|
||||
});
|
||||
@@ -272,7 +270,7 @@ export function muteStatusFail(id, error) {
|
||||
export function unmuteStatus(id) {
|
||||
return (dispatch, getState) => {
|
||||
if (!me) return;
|
||||
|
||||
|
||||
dispatch(unmuteStatusRequest(id));
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${id}/unmute`).then(() => {
|
||||
|
||||
@@ -10,6 +10,7 @@ import { updateNotificationsQueue, expandNotifications } from './notifications';
|
||||
import { updateConversations } from './conversations';
|
||||
import { fetchFilters } from './filters';
|
||||
import { getLocale } from '../locales';
|
||||
import { handleComposeSubmit } from './compose';
|
||||
|
||||
const { messages } = getLocale();
|
||||
|
||||
@@ -61,3 +62,18 @@ export const connectHashtagStream = (id, tag, accept) => connectTimelineStream
|
||||
export const connectDirectStream = () => connectTimelineStream('direct', 'direct');
|
||||
export const connectListStream = id => connectTimelineStream(`list:${id}`, `list&list=${id}`);
|
||||
export const connectGroupStream = id => connectTimelineStream(`group:${id}`, `group&group=${id}`);
|
||||
|
||||
export const connectStatusUpdateStream = () => {
|
||||
return connectStream('statuscard', null, (dispatch, getState) => {
|
||||
return {
|
||||
onConnect() {},
|
||||
onDisconnect() {},
|
||||
onReceive (data) {
|
||||
if (!data['event'] || !data['payload']) return;
|
||||
if (data.event === 'update') {
|
||||
handleComposeSubmit(dispatch, getState, {data: JSON.parse(data.payload)}, null)
|
||||
}
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user