Progress
This commit is contained in:
parent
763694b5ab
commit
c3d0d8bde2
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Api::BaseController < ApplicationController
|
||||
DEFAULT_STATUSES_LIMIT = 20
|
||||
DEFAULT_STATUSES_LIMIT = 10
|
||||
DEFAULT_ACCOUNTS_LIMIT = 40
|
||||
|
||||
include RateLimitHeaders
|
||||
|
|
|
@ -1,74 +1,83 @@
|
|||
import api from '../api';
|
||||
import { me } from '../initial_state';
|
||||
import api from '../api'
|
||||
import { me } from '../initial_state'
|
||||
|
||||
export const GROUP_CREATE_REQUEST = 'GROUP_CREATE_REQUEST';
|
||||
export const GROUP_CREATE_SUCCESS = 'GROUP_CREATE_SUCCESS';
|
||||
export const GROUP_CREATE_FAIL = 'GROUP_CREATE_FAIL';
|
||||
export const GROUP_CREATE_REQUEST = 'GROUP_CREATE_REQUEST'
|
||||
export const GROUP_CREATE_SUCCESS = 'GROUP_CREATE_SUCCESS'
|
||||
export const GROUP_CREATE_FAIL = 'GROUP_CREATE_FAIL'
|
||||
|
||||
export const GROUP_UPDATE_REQUEST = 'GROUP_UPDATE_REQUEST';
|
||||
export const GROUP_UPDATE_SUCCESS = 'GROUP_UPDATE_SUCCESS';
|
||||
export const GROUP_UPDATE_FAIL = 'GROUP_UPDATE_FAIL';
|
||||
export const GROUP_UPDATE_REQUEST = 'GROUP_UPDATE_REQUEST'
|
||||
export const GROUP_UPDATE_SUCCESS = 'GROUP_UPDATE_SUCCESS'
|
||||
export const GROUP_UPDATE_FAIL = 'GROUP_UPDATE_FAIL'
|
||||
|
||||
export const GROUP_EDITOR_VALUE_CHANGE = 'GROUP_EDITOR_VALUE_CHANGE';
|
||||
export const GROUP_EDITOR_RESET = 'GROUP_EDITOR_RESET';
|
||||
export const GROUP_EDITOR_SETUP = 'GROUP_EDITOR_SETUP';
|
||||
export const GROUP_EDITOR_TITLE_CHANGE = 'GROUP_EDITOR_TITLE_CHANGE'
|
||||
export const GROUP_EDITOR_DESCRIPTION_CHANGE = 'GROUP_EDITOR_DESCRIPTION_CHANGE'
|
||||
export const GROUP_EDITOR_COVER_IMAGE_CHANGE = 'GROUP_EDITOR_COVER_IMAGE_CHANGE'
|
||||
|
||||
export const GROUP_EDITOR_RESET = 'GROUP_EDITOR_RESET'
|
||||
export const GROUP_EDITOR_SETUP = 'GROUP_EDITOR_SETUP'
|
||||
|
||||
export const submit = (routerHistory) => (dispatch, getState) => {
|
||||
const groupId = getState().getIn(['group_editor', 'groupId']);
|
||||
const title = getState().getIn(['group_editor', 'title']);
|
||||
const description = getState().getIn(['group_editor', 'description']);
|
||||
const coverImage = getState().getIn(['group_editor', 'coverImage']);
|
||||
if (!me) return
|
||||
|
||||
const groupId = getState().getIn(['group_editor', 'groupId'])
|
||||
const title = getState().getIn(['group_editor', 'title'])
|
||||
const description = getState().getIn(['group_editor', 'description'])
|
||||
const coverImage = getState().getIn(['group_editor', 'coverImage'])
|
||||
|
||||
if (groupId === null) {
|
||||
dispatch(create(title, description, coverImage, routerHistory));
|
||||
dispatch(create(title, description, coverImage, routerHistory))
|
||||
} else {
|
||||
dispatch(update(groupId, title, description, coverImage, routerHistory));
|
||||
dispatch(update(groupId, title, description, coverImage, routerHistory))
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export const create = (title, description, coverImage, routerHistory) => (dispatch, getState) => {
|
||||
if (!me) return;
|
||||
const create = (title, description, coverImage, routerHistory) => (dispatch, getState) => {
|
||||
if (!me) return
|
||||
|
||||
dispatch(createRequest());
|
||||
dispatch(createRequest())
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('title', title);
|
||||
formData.append('description', description);
|
||||
const formData = new FormData()
|
||||
formData.append('title', title)
|
||||
formData.append('description', description)
|
||||
|
||||
if (coverImage !== null) {
|
||||
formData.append('cover_image', coverImage);
|
||||
formData.append('cover_image', coverImage)
|
||||
}
|
||||
|
||||
api(getState).post('/api/v1/groups', formData, { headers: { 'Content-Type': 'multipart/form-data' } }).then(({ data }) => {
|
||||
dispatch(createSuccess(data));
|
||||
routerHistory.push(`/groups/${data.id}`);
|
||||
}).catch(err => dispatch(createFail(err)));
|
||||
};
|
||||
api(getState).post('/api/v1/groups', formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
}).then(({ data }) => {
|
||||
dispatch(createSuccess(data))
|
||||
routerHistory.push(`/groups/${data.id}`)
|
||||
}).catch(err => dispatch(createFail(err)))
|
||||
};
|
||||
|
||||
|
||||
export const createRequest = id => ({
|
||||
export const createRequest = (id) => ({
|
||||
type: GROUP_CREATE_REQUEST,
|
||||
id,
|
||||
});
|
||||
})
|
||||
|
||||
export const createSuccess = group => ({
|
||||
export const createSuccess = (group) => ({
|
||||
type: GROUP_CREATE_SUCCESS,
|
||||
group,
|
||||
});
|
||||
})
|
||||
|
||||
export const createFail = error => ({
|
||||
export const createFail = (error) => ({
|
||||
type: GROUP_CREATE_FAIL,
|
||||
error,
|
||||
});
|
||||
})
|
||||
|
||||
export const update = (groupId, title, description, coverImage, routerHistory) => (dispatch, getState) => {
|
||||
if (!me) return;
|
||||
const update = (groupId, title, description, coverImage, routerHistory) => (dispatch, getState) => {
|
||||
if (!me) return
|
||||
|
||||
dispatch(updateRequest());
|
||||
dispatch(updateRequest())
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('title', title);
|
||||
const formData = new FormData()
|
||||
formData.append('title', title)
|
||||
formData.append('description', description);
|
||||
|
||||
if (coverImage !== null) {
|
||||
|
@ -79,35 +88,44 @@ export const update = (groupId, title, description, coverImage, routerHistory) =
|
|||
dispatch(updateSuccess(data));
|
||||
routerHistory.push(`/groups/${data.id}`);
|
||||
}).catch(err => dispatch(updateFail(err)));
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
export const updateRequest = id => ({
|
||||
export const updateRequest = (id) => ({
|
||||
type: GROUP_UPDATE_REQUEST,
|
||||
id,
|
||||
});
|
||||
|
||||
export const updateSuccess = group => ({
|
||||
export const updateSuccess = (group) => ({
|
||||
type: GROUP_UPDATE_SUCCESS,
|
||||
group,
|
||||
});
|
||||
|
||||
export const updateFail = error => ({
|
||||
export const updateFail = (error) => ({
|
||||
type: GROUP_UPDATE_FAIL,
|
||||
error,
|
||||
});
|
||||
})
|
||||
|
||||
export const changeValue = (field, value) => ({
|
||||
type: GROUP_EDITOR_VALUE_CHANGE,
|
||||
field,
|
||||
value,
|
||||
});
|
||||
|
||||
export const reset = () => ({
|
||||
export const resetEditor = () => ({
|
||||
type: GROUP_EDITOR_RESET
|
||||
});
|
||||
|
||||
export const setUp = (group) => ({
|
||||
export const setGroup = (group) => ({
|
||||
type: GROUP_EDITOR_SETUP,
|
||||
group,
|
||||
});
|
||||
|
||||
export const changeGroupTitle = (title) => ({
|
||||
type: GROUP_EDITOR_TITLE_CHANGE,
|
||||
title,
|
||||
})
|
||||
|
||||
export const changeGroupDescription = (description) => ({
|
||||
type: GROUP_EDITOR_DESCRIPTION_CHANGE,
|
||||
description,
|
||||
})
|
||||
|
||||
export const changeGroupCoverImage = (imageData) => ({
|
||||
type: GROUP_EDITOR_COVER_IMAGE_CHANGE,
|
||||
value: imageData,
|
||||
})
|
|
@ -30,6 +30,10 @@ export const UNPIN_REQUEST = 'UNPIN_REQUEST';
|
|||
export const UNPIN_SUCCESS = 'UNPIN_SUCCESS';
|
||||
export const UNPIN_FAIL = 'UNPIN_FAIL';
|
||||
|
||||
export const LIKES_FETCH_REQUEST = 'LIKES_FETCH_REQUEST';
|
||||
export const LIKES_FETCH_SUCCESS = 'LIKES_FETCH_SUCCESS';
|
||||
export const LIKES_FETCH_FAIL = 'LIKES_FETCH_FAIL';
|
||||
|
||||
export function repost(status) {
|
||||
return function (dispatch, getState) {
|
||||
if (!me) return;
|
||||
|
@ -308,3 +312,38 @@ export function unpinFail(status, error) {
|
|||
skipLoading: true,
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchLikes(id) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch(fetchLikesRequest(id));
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${id}/favourited_by`).then(response => {
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(fetchLikesSuccess(id, response.data));
|
||||
}).catch(error => {
|
||||
dispatch(fetchLikesFail(id, error));
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchLikesRequest(id) {
|
||||
return {
|
||||
type: LIKES_FETCH_REQUEST,
|
||||
id,
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchLikesSuccess(id, accounts) {
|
||||
return {
|
||||
type: LIKES_FETCH_SUCCESS,
|
||||
id,
|
||||
accounts,
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchLikesFail(id, error) {
|
||||
return {
|
||||
type: LIKES_FETCH_FAIL,
|
||||
error,
|
||||
};
|
||||
};
|
|
@ -98,20 +98,22 @@ export const fetchListsRequest = () => ({
|
|||
type: LISTS_FETCH_REQUEST,
|
||||
});
|
||||
|
||||
export const fetchListsSuccess = lists => ({
|
||||
export const fetchListsSuccess = (lists) => ({
|
||||
type: LISTS_FETCH_SUCCESS,
|
||||
lists,
|
||||
});
|
||||
|
||||
export const fetchListsFail = error => ({
|
||||
export const fetchListsFail = (error) => ({
|
||||
type: LISTS_FETCH_FAIL,
|
||||
error,
|
||||
});
|
||||
|
||||
export const submitListEditor = shouldReset => (dispatch, getState) => {
|
||||
export const submitListEditor = (shouldReset) => (dispatch, getState) => {
|
||||
const listId = getState().getIn(['listEditor', 'listId']);
|
||||
const title = getState().getIn(['listEditor', 'title']);
|
||||
|
||||
console.log("submitListEditor:", title)
|
||||
|
||||
if (listId === null) {
|
||||
dispatch(createList(title, shouldReset));
|
||||
} else {
|
||||
|
@ -119,7 +121,7 @@ export const submitListEditor = shouldReset => (dispatch, getState) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const setupListEditor = listId => (dispatch, getState) => {
|
||||
export const setupListEditor = (listId) => (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: LIST_EDITOR_SETUP,
|
||||
list: getState().getIn(['lists', listId]),
|
||||
|
@ -128,7 +130,7 @@ export const setupListEditor = listId => (dispatch, getState) => {
|
|||
dispatch(fetchListAccounts(listId));
|
||||
};
|
||||
|
||||
export const changeListEditorTitle = value => ({
|
||||
export const changeListEditorTitle = (value) => ({
|
||||
type: LIST_EDITOR_TITLE_CHANGE,
|
||||
value,
|
||||
});
|
||||
|
@ -151,12 +153,12 @@ export const createListRequest = () => ({
|
|||
type: LIST_CREATE_REQUEST,
|
||||
});
|
||||
|
||||
export const createListSuccess = list => ({
|
||||
export const createListSuccess = (list) => ({
|
||||
type: LIST_CREATE_SUCCESS,
|
||||
list,
|
||||
});
|
||||
|
||||
export const createListFail = error => ({
|
||||
export const createListFail = (error) => ({
|
||||
type: LIST_CREATE_FAIL,
|
||||
error,
|
||||
});
|
||||
|
@ -195,7 +197,7 @@ export const resetListEditor = () => ({
|
|||
type: LIST_EDITOR_RESET,
|
||||
});
|
||||
|
||||
export const deleteList = id => (dispatch, getState) => {
|
||||
export const deleteList = (id) => (dispatch, getState) => {
|
||||
if (!me) return;
|
||||
|
||||
dispatch(deleteListRequest(id));
|
||||
|
@ -205,12 +207,12 @@ export const deleteList = id => (dispatch, getState) => {
|
|||
.catch(err => dispatch(deleteListFail(id, err)));
|
||||
};
|
||||
|
||||
export const deleteListRequest = id => ({
|
||||
export const deleteListRequest = (id) => ({
|
||||
type: LIST_DELETE_REQUEST,
|
||||
id,
|
||||
});
|
||||
|
||||
export const deleteListSuccess = id => ({
|
||||
export const deleteListSuccess = (id) => ({
|
||||
type: LIST_DELETE_SUCCESS,
|
||||
id,
|
||||
});
|
||||
|
@ -221,7 +223,7 @@ export const deleteListFail = (id, error) => ({
|
|||
error,
|
||||
});
|
||||
|
||||
export const fetchListAccounts = listId => (dispatch, getState) => {
|
||||
export const fetchListAccounts = (listId) => (dispatch, getState) => {
|
||||
if (!me) return;
|
||||
|
||||
dispatch(fetchListAccountsRequest(listId));
|
||||
|
@ -232,7 +234,7 @@ export const fetchListAccounts = listId => (dispatch, getState) => {
|
|||
}).catch(err => dispatch(fetchListAccountsFail(listId, err)));
|
||||
};
|
||||
|
||||
export const fetchListAccountsRequest = id => ({
|
||||
export const fetchListAccountsRequest = (id) => ({
|
||||
type: LIST_ACCOUNTS_FETCH_REQUEST,
|
||||
id,
|
||||
});
|
||||
|
@ -250,7 +252,7 @@ export const fetchListAccountsFail = (id, error) => ({
|
|||
error,
|
||||
});
|
||||
|
||||
export const fetchListSuggestions = q => (dispatch, getState) => {
|
||||
export const fetchListSuggestions = (q) => (dispatch, getState) => {
|
||||
if (!me) return;
|
||||
|
||||
const params = {
|
||||
|
@ -277,7 +279,7 @@ export const clearListSuggestions = () => ({
|
|||
type: LIST_EDITOR_SUGGESTIONS_CLEAR,
|
||||
});
|
||||
|
||||
export const changeListSuggestions = value => ({
|
||||
export const changeListSuggestions = (value) => ({
|
||||
type: LIST_EDITOR_SUGGESTIONS_CHANGE,
|
||||
value,
|
||||
});
|
||||
|
@ -361,7 +363,7 @@ export const setupListAdder = accountId => (dispatch, getState) => {
|
|||
dispatch(fetchAccountLists(accountId));
|
||||
};
|
||||
|
||||
export const fetchAccountLists = accountId => (dispatch, getState) => {
|
||||
export const fetchAccountLists = (accountId) => (dispatch, getState) => {
|
||||
if (!me) return;
|
||||
|
||||
dispatch(fetchAccountListsRequest(accountId));
|
||||
|
@ -371,7 +373,7 @@ export const fetchAccountLists = accountId => (dispatch, getState) => {
|
|||
.catch(err => dispatch(fetchAccountListsFail(accountId, err)));
|
||||
};
|
||||
|
||||
export const fetchAccountListsRequest = id => ({
|
||||
export const fetchAccountListsRequest = (id) => ({
|
||||
type:LIST_ADDER_LISTS_FETCH_REQUEST,
|
||||
id,
|
||||
});
|
||||
|
@ -388,10 +390,10 @@ export const fetchAccountListsFail = (id, err) => ({
|
|||
err,
|
||||
});
|
||||
|
||||
export const addToListAdder = listId => (dispatch, getState) => {
|
||||
export const addToListAdder = (listId) => (dispatch, getState) => {
|
||||
dispatch(addToList(listId, getState().getIn(['listAdder', 'accountId'])));
|
||||
};
|
||||
|
||||
export const removeFromListAdder = listId => (dispatch, getState) => {
|
||||
export const removeFromListAdder = (listId) => (dispatch, getState) => {
|
||||
dispatch(removeFromList(listId, getState().getIn(['listAdder', 'accountId'])));
|
||||
};
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
export const MODAL_OPEN = 'MODAL_OPEN';
|
||||
export const MODAL_CLOSE = 'MODAL_CLOSE';
|
||||
export const MODAL_OPEN = 'MODAL_OPEN'
|
||||
export const MODAL_CLOSE = 'MODAL_CLOSE'
|
||||
|
||||
export function openModal(type, props) {
|
||||
return {
|
||||
type: MODAL_OPEN,
|
||||
modalType: type,
|
||||
modalProps: props,
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function closeModal() {
|
||||
return {
|
||||
type: MODAL_CLOSE,
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
const CogIcon = ({
|
||||
className = '',
|
||||
size = '16px',
|
||||
title = '',
|
||||
}) => (
|
||||
<svg
|
||||
className={className}
|
||||
version='1.1'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
x='0px'
|
||||
y='0px'
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox='0 0 24 24'
|
||||
xmlSpace='preserve'
|
||||
aria-label={title}
|
||||
>
|
||||
<g>
|
||||
<path d='M 23.40625 9.769531 L 21.261719 9.511719 C 21.042969 8.695312 20.722656 7.921875 20.3125 7.207031 L 21.640625 5.511719 C 21.847656 5.253906 21.824219 4.851562 21.585938 4.617188 L 19.378906 2.410156 C 19.148438 2.175781 18.746094 2.152344 18.484375 2.355469 L 16.789062 3.6875 C 16.074219 3.273438 15.304688 2.953125 14.488281 2.738281 L 14.230469 0.59375 C 14.191406 0.269531 13.890625 0 13.558594 0 L 10.4375 0 C 10.109375 0 9.804688 0.269531 9.765625 0.59375 L 9.507812 2.738281 C 8.695312 2.953125 7.921875 3.277344 7.207031 3.6875 L 5.511719 2.355469 C 5.253906 2.152344 4.851562 2.175781 4.617188 2.410156 L 2.410156 4.621094 C 2.175781 4.851562 2.152344 5.253906 2.359375 5.515625 L 3.6875 7.210938 C 3.277344 7.925781 2.953125 8.695312 2.738281 9.511719 L 0.597656 9.769531 C 0.269531 9.808594 0 10.109375 0 10.441406 L 0 13.5625 C 0 13.894531 0.269531 14.195312 0.597656 14.234375 L 2.738281 14.492188 C 2.957031 15.304688 3.277344 16.078125 3.6875 16.792969 L 2.359375 18.488281 C 2.15625 18.746094 2.179688 19.148438 2.414062 19.382812 L 4.617188 21.59375 C 4.851562 21.824219 5.253906 21.851562 5.511719 21.648438 L 7.207031 20.3125 C 7.921875 20.726562 8.695312 21.046875 9.511719 21.265625 L 9.769531 23.40625 C 9.808594 23.734375 10.109375 24 10.4375 24 L 13.5625 24 C 13.890625 24 14.195312 23.734375 14.230469 23.40625 L 14.488281 21.265625 C 15.304688 21.046875 16.078125 20.726562 16.792969 20.3125 L 18.488281 21.644531 C 18.746094 21.847656 19.148438 21.824219 19.382812 21.589844 L 21.589844 19.382812 C 21.824219 19.148438 21.847656 18.746094 21.644531 18.484375 L 20.3125 16.792969 C 20.722656 16.078125 21.042969 15.304688 21.261719 14.492188 L 23.402344 14.234375 C 23.730469 14.195312 24 13.894531 24 13.5625 L 24 10.441406 C 24 10.109375 23.734375 9.808594 23.40625 9.769531 Z M 12 18 C 8.6875 18 6 15.3125 6 12 C 6 8.6875 8.6875 6 12 6 C 15.316406 6 18 8.6875 18 12 C 18 15.3125 15.316406 18 12 18 Z M 12 18' />
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
|
||||
export default CogIcon
|
|
@ -1,5 +1,5 @@
|
|||
const ErrorIcon = ({
|
||||
className = '',
|
||||
className = _s.fillColorPrimary,
|
||||
size = '32px',
|
||||
title = 'Error',
|
||||
}) => (
|
||||
|
@ -16,7 +16,10 @@ const ErrorIcon = ({
|
|||
aria-label={title}
|
||||
>
|
||||
<g>
|
||||
<path d='M 54.67 9.37 C 42.18 -3.12 21.86 -3.12 9.37 9.37 C -3.13 21.86 -3.12 42.18 9.37 54.67 C 21.86 67.16 42.18 67.16 54.67 54.67 C 67.16 42.18 67.16 21.86 54.67 9.37 Z M 51.18 51.18 C 40.61 61.74 23.43 61.74 12.86 51.18 C 2.3 40.61 2.3 23.42 12.86 12.86 C 23.43 2.3 40.61 2.3 51.18 12.86 C 61.74 23.43 61.74 40.61 51.18 51.18 Z M 46.5 44.68 C 46.9 45.6 46.48 46.66 45.56 47 C 44.64 47.46 43.57 47 43.18 46.12 C 41.43 42 37.3 39.47 32.66 39.47 C 27.91 39.47 23.75 42 22 46.11 C 21.79 46.81 21.11 47.23 20.41 47.23 C 20.18 47.23 19.94 47.18 19.71 47 C 18.79 46.71 18.35 45.65 18.73 44.72 C 20.97 39.33 26.44 35.85 32.66 35.85 C 38.75 35.85 44.18 39.31 46.5 44.68 Z M 20 23.35 C 20 21.28 21.75 19.61 23.81 19.61 C 25.88 19.61 27.56 21.28 27.56 23.35 C 27.56 25.42 25.88 27 23.81 27 C 21.75 27 20 25.42 20 23.35 Z M 37 23.35 C 37 21.28 38.72 19.61 40.79 19.61 C 42.86 19.61 44.54 21.28 44.54 23.35 C 44.54 25.42 42.86 27 40.79 27 C 38.72 27 37 25.42 37 23.35 Z M 37 23.35' />
|
||||
<path d='M 32 0 C 14.355469 0 0 14.355469 0 32 C 0 49.644531 14.355469 64 32 64 C 49.644531 64 64 49.644531 64 32 C 64 14.355469 49.644531 0 32 0 Z M 32 61.332031 C 15.824219 61.332031 2.667969 48.175781 2.667969 32 C 2.667969 15.824219 15.824219 2.667969 32 2.667969 C 48.175781 2.667969 61.332031 15.824219 61.332031 32 C 61.332031 48.175781 48.175781 61.332031 32 61.332031 Z M 32 61.332031' />
|
||||
<path d='M 24 24 C 24 25.472656 22.804688 26.667969 21.332031 26.667969 C 19.859375 26.667969 18.667969 25.472656 18.667969 24 C 18.667969 22.527344 19.859375 21.332031 21.332031 21.332031 C 22.804688 21.332031 24 22.527344 24 24 Z M 24 24' />
|
||||
<path d='M 45.332031 24 C 45.332031 25.472656 44.140625 26.667969 42.667969 26.667969 C 41.195312 26.667969 40 25.472656 40 24 C 40 22.527344 41.195312 21.332031 42.667969 21.332031 C 44.140625 21.332031 45.332031 22.527344 45.332031 24 Z M 45.332031 24' />
|
||||
<path d='M 32 40 L 31.996094 40 C 20.792969 40 16.445312 45.628906 16.265625 45.867188 C 15.828125 46.453125 15.945312 47.28125 16.527344 47.722656 C 17.113281 48.167969 17.949219 48.054688 18.394531 47.472656 C 18.546875 47.277344 22.21875 42.667969 31.996094 42.667969 L 32 42.667969 C 41.777344 42.667969 45.453125 47.277344 45.601562 47.46875 C 45.863281 47.816406 46.261719 48 46.667969 48 C 46.945312 48 47.226562 47.914062 47.46875 47.734375 C 48.054688 47.292969 48.175781 46.457031 47.734375 45.867188 C 47.554688 45.628906 43.203125 40 32 40 Z M 32 40' />
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
|
|
|
@ -165,7 +165,7 @@ class Account extends ImmutablePureComponent {
|
|||
<NavLink
|
||||
title={account.get('acct')}
|
||||
to={`/${account.get('acct')}`}
|
||||
className={[_s.default, _s.alignItemsStart, _s.noUnderline, _s.px10, _s.flexGrow1].join(' ')}
|
||||
className={[_s.default, _s.alignItemsStart, _s.noUnderline, _s.px10, _s.overflowHidden, _s.flexNormal].join(' ')}
|
||||
>
|
||||
<DisplayName account={account} isMultiline={compact} />
|
||||
{!compact && actionButton}
|
||||
|
|
|
@ -164,13 +164,13 @@ export default class Button extends PureComponent {
|
|||
|
||||
underline_onHover: underlineOnHover,
|
||||
|
||||
backgroundColorSubtle2Dark_onHover: backgroundColor === COLORS.tertiary || backgroundColor === COLORS.secondary,
|
||||
backgroundColorBlackOpaque_onHover: backgroundColor === COLORS.black,
|
||||
backgroundColorBrandDark_onHover: backgroundColor === COLORS.brand,
|
||||
backgroundColorDangerDark_onHover: backgroundColor === COLORS.danger,
|
||||
backgroundColorSubtle2Dark_onHover: backgroundColor === COLORS.tertiary || backgroundColor === COLORS.secondary && !isDisabled,
|
||||
backgroundColorBlackOpaque_onHover: backgroundColor === COLORS.black && !isDisabled,
|
||||
backgroundColorBrandDark_onHover: backgroundColor === COLORS.brand && !isDisabled,
|
||||
backgroundColorDangerDark_onHover: backgroundColor === COLORS.danger && !isDisabled,
|
||||
|
||||
backgroundColorBrand_onHover: color === COLORS.brand && isOutline,
|
||||
colorWhite_onHover: !!children && color === COLORS.brand && isOutline,
|
||||
backgroundColorBrand_onHover: color === COLORS.brand && isOutline && !isDisabled,
|
||||
colorWhite_onHover: !!children && color === COLORS.brand && isOutline && !isDisabled,
|
||||
|
||||
fillColorSecondary: !!icon && color === COLORS.secondary,
|
||||
fillColorWhite: !!icon && color === COLORS.white,
|
||||
|
|
|
@ -27,7 +27,7 @@ class ColumnIndicator extends PureComponent {
|
|||
render() {
|
||||
const { type, message, intl } = this.props
|
||||
|
||||
const title = type !== 'error' ? intl.formatMessage(messages[type]) : message
|
||||
const title = type !== 'error' && !message ? intl.formatMessage(messages[type]) : message
|
||||
|
||||
return (
|
||||
<div className={[_s.default, _s.width100PC, _s.justifyContentCenter, _s.alignItemsCenter, _s.py15].join(' ')}>
|
||||
|
|
|
@ -60,7 +60,7 @@ class Comment extends ImmutablePureComponent {
|
|||
<Avatar account={status.get('account')} size={32} />
|
||||
</NavLink>
|
||||
|
||||
<div className={[_s.default, _s.flexNormal].join(' ')}>
|
||||
<div className={_s.default}>
|
||||
<div className={[_s.default, _s.px10, _s.pt5, _s.pb10, _s.radiusSmall, _s.backgroundColorSubtle].join(' ')}>
|
||||
<CommentHeader status={status} />
|
||||
<StatusContent
|
||||
|
|
|
@ -161,7 +161,7 @@ class DisplayName extends ImmutablePureComponent {
|
|||
/>
|
||||
{
|
||||
!noRelationship && account.get('locked') &&
|
||||
<Icon id='lock-filled' size={iconSize} className={_s.ml5} />
|
||||
<Icon id='lock-filled' size={iconSize} className={[_s.fillColorPrimary, _s.ml5].join(' ')} />
|
||||
}
|
||||
</bdi>
|
||||
{
|
||||
|
|
|
@ -31,8 +31,6 @@ class FloatingActionButton extends PureComponent {
|
|||
return (
|
||||
<Button
|
||||
onClick={onOpenCompose}
|
||||
color='white'
|
||||
backgroundColor='brand'
|
||||
className={[_s.posFixed, _s.z4, _s.py15, _s.mb15, _s.mr15, _s.bottom0, _s.right0].join(' ')}
|
||||
title={message}
|
||||
aria-label={message}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
import Text from './text'
|
||||
|
||||
export default class Form extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
children: PropTypes.any,
|
||||
errorMessage: PropTypes.string,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
componentDidUpdate (prevProps) {
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
children,
|
||||
errorMessage,
|
||||
onSubmit,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<form onSubmit={onSubmit} className={_s.default}>
|
||||
{
|
||||
!!errorMessage &&
|
||||
<Text color='danger' className={_s.my10}>
|
||||
{errorMessage}
|
||||
</Text>
|
||||
}
|
||||
<div className={_s.default}>
|
||||
{children}
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
|
@ -4,6 +4,7 @@ import { Fragment } from 'react'
|
|||
import { NavLink } from 'react-router-dom'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import classNames from 'classnames/bind'
|
||||
import { PLACEHOLDER_MISSING_HEADER_SRC } from '../constants'
|
||||
import { shortNumberFormat } from '../utils/numbers'
|
||||
import Button from './button'
|
||||
import DotTextSeperator from './dot_text_seperator'
|
||||
|
@ -34,10 +35,16 @@ class GroupCollectionItem extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
group: ImmutablePropTypes.map,
|
||||
relationships: ImmutablePropTypes.map,
|
||||
isHidden: PropTypes.bool,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, group, relationships } = this.props
|
||||
const {
|
||||
intl,
|
||||
group,
|
||||
relationships,
|
||||
isHidden,
|
||||
} = this.props
|
||||
|
||||
if (!relationships) return null
|
||||
|
||||
|
@ -53,7 +60,20 @@ class GroupCollectionItem extends ImmutablePureComponent {
|
|||
|
||||
const isMember = relationships.get('member')
|
||||
const isAdmin = relationships.get('admin')
|
||||
const coverSrc = group.get('cover')
|
||||
const coverSrc = group.get('cover_image_url') || ''
|
||||
const coverMissing = coverSrc.indexOf(PLACEHOLDER_MISSING_HEADER_SRC) > -1 || !coverSrc
|
||||
|
||||
|
||||
if (isHidden) {
|
||||
return (
|
||||
<Fragment>
|
||||
{group.get('title')}
|
||||
{subtitle}
|
||||
{isMember && intl.formatMessage(messages.member)}
|
||||
{isAdmin && intl.formatMessage(messages.admin)}
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
const navLinkClasses = cx({
|
||||
default: 1,
|
||||
|
@ -77,7 +97,7 @@ class GroupCollectionItem extends ImmutablePureComponent {
|
|||
className={navLinkClasses}
|
||||
>
|
||||
{
|
||||
!!coverSrc &&
|
||||
!!coverSrc && !coverMissing &&
|
||||
<Image
|
||||
src={coverSrc}
|
||||
alt={group.get('title')}
|
||||
|
@ -86,7 +106,7 @@ class GroupCollectionItem extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
{
|
||||
!coverSrc && (isMember || isAdmin) &&
|
||||
(!coverSrc || coverMissing) && (isMember || isAdmin) &&
|
||||
<div className={[_s.default, _s.height40PX, _s.backgroundColorSubtle, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')} />
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ class GroupHeader extends ImmutablePureComponent {
|
|||
},
|
||||
]
|
||||
|
||||
const coverSrc = !!group ? group.get('cover') : undefined
|
||||
const coverSrc = !!group ? group.get('cover_image_url') : undefined
|
||||
const title = !!group ? group.get('title') : undefined
|
||||
|
||||
return (
|
||||
|
|
|
@ -4,6 +4,7 @@ import { Fragment } from 'react'
|
|||
import { NavLink } from 'react-router-dom'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import classNames from 'classnames/bind'
|
||||
import { PLACEHOLDER_MISSING_HEADER_SRC } from '../constants'
|
||||
import { shortNumberFormat } from '../utils/numbers'
|
||||
import Image from './image'
|
||||
import Text from './text'
|
||||
|
@ -31,6 +32,7 @@ class GroupListItem extends ImmutablePureComponent {
|
|||
relationships: ImmutablePropTypes.map,
|
||||
slim: PropTypes.bool,
|
||||
isLast: PropTypes.bool,
|
||||
isHidden: PropTypes.bool,
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
|
@ -39,9 +41,16 @@ class GroupListItem extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { intl, group, relationships, slim, isLast } = this.props
|
||||
const {
|
||||
intl,
|
||||
group,
|
||||
relationships,
|
||||
slim,
|
||||
isLast,
|
||||
isHidden,
|
||||
} = this.props
|
||||
|
||||
if (!relationships) return null
|
||||
if (!relationships || !group) return null
|
||||
|
||||
const unreadCount = relationships.get('unread_count')
|
||||
|
||||
|
@ -53,6 +62,15 @@ class GroupListItem extends ImmutablePureComponent {
|
|||
</Fragment>
|
||||
) : intl.formatMessage(messages.no_recent_activity)
|
||||
|
||||
if (isHidden) {
|
||||
return (
|
||||
<Fragment>
|
||||
{group.get('title')}
|
||||
{subtitle}
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
const containerClasses = cx({
|
||||
default: 1,
|
||||
noUnderline: 1,
|
||||
|
@ -80,10 +98,12 @@ class GroupListItem extends ImmutablePureComponent {
|
|||
default: 1,
|
||||
px10: 1,
|
||||
mt5: 1,
|
||||
flexShrink1: slim,
|
||||
mb10: !slim,
|
||||
})
|
||||
|
||||
const coverSrc = group.get('cover')
|
||||
const coverSrc = group.get('cover_image_url') || ''
|
||||
const coverMissing = coverSrc.indexOf(PLACEHOLDER_MISSING_HEADER_SRC) > -1 || !coverSrc
|
||||
|
||||
return (
|
||||
<NavLink
|
||||
|
@ -92,7 +112,7 @@ class GroupListItem extends ImmutablePureComponent {
|
|||
>
|
||||
|
||||
{
|
||||
(!!coverSrc || slim) &&
|
||||
(!!coverSrc || slim) && !coverMissing &&
|
||||
<Image
|
||||
src={coverSrc}
|
||||
alt={group.get('title')}
|
||||
|
|
|
@ -11,6 +11,7 @@ import ChatIcon from '../assets/chat_icon'
|
|||
import CircleIcon from '../assets/circle_icon'
|
||||
import CloseIcon from '../assets/close_icon'
|
||||
import CodeIcon from '../assets/code_icon'
|
||||
import CogIcon from '../assets/cog_icon'
|
||||
import CommentIcon from '../assets/comment_icon'
|
||||
import CopyIcon from '../assets/copy_icon'
|
||||
import DissenterIcon from '../assets/dissenter_icon'
|
||||
|
@ -80,6 +81,7 @@ const ICONS = {
|
|||
'chat': ChatIcon,
|
||||
'close': CloseIcon,
|
||||
'code': CodeIcon,
|
||||
'cog': CogIcon,
|
||||
'comment': CommentIcon,
|
||||
'copy': CopyIcon,
|
||||
'dissenter': DissenterIcon,
|
||||
|
|
|
@ -7,6 +7,7 @@ import Text from './text'
|
|||
const cx = classNames.bind(_s)
|
||||
|
||||
export default class Input extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
placeholder: PropTypes.string,
|
||||
prependIcon: PropTypes.string,
|
||||
|
@ -25,6 +26,10 @@ export default class Input extends PureComponent {
|
|||
hideLabel: PropTypes.bool,
|
||||
}
|
||||
|
||||
handleOnChange = (e) => {
|
||||
this.props.onChange(e.target.value)
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
placeholder,
|
||||
|
@ -55,6 +60,7 @@ export default class Input extends PureComponent {
|
|||
py5: small,
|
||||
backgroundTransparent: !readOnly,
|
||||
backgroundColorSubtle2: readOnly,
|
||||
colorPrimary: !readOnly,
|
||||
colorSecondary: readOnly,
|
||||
fontSize15PX: !small,
|
||||
fontSize13PX: small,
|
||||
|
@ -101,7 +107,7 @@ export default class Input extends PureComponent {
|
|||
placeholder={placeholder}
|
||||
ref={inputRef}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onChange={this.handleOnChange}
|
||||
onKeyUp={onKeyUp}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { Fragment } from 'react'
|
||||
import classNames from 'classnames/bind'
|
||||
import Button from './button'
|
||||
import Icon from './icon'
|
||||
|
@ -9,6 +10,7 @@ export default class ListItem extends PureComponent {
|
|||
static propTypes = {
|
||||
icon: PropTypes.string,
|
||||
isLast: PropTypes.bool,
|
||||
isHidden: PropTypes.bool,
|
||||
to: PropTypes.string,
|
||||
href: PropTypes.string,
|
||||
title: PropTypes.string,
|
||||
|
@ -29,8 +31,17 @@ export default class ListItem extends PureComponent {
|
|||
size,
|
||||
icon,
|
||||
hideArrow,
|
||||
isHidden,
|
||||
} = this.props
|
||||
|
||||
if (isHidden) {
|
||||
return (
|
||||
<Fragment>
|
||||
{title}
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
const small = size === 'small'
|
||||
const large = size === 'large'
|
||||
|
||||
|
@ -77,7 +88,7 @@ export default class ListItem extends PureComponent {
|
|||
/>
|
||||
}
|
||||
|
||||
<Text color='primary' size={textSize}>
|
||||
<Text color='primary' size={textSize} className={[_s.overflowHidden, _s.flexNormal, _s.pr5, _s.textOverflowEllipsis].join(' ')}>
|
||||
{title}
|
||||
</Text>
|
||||
|
||||
|
@ -86,7 +97,7 @@ export default class ListItem extends PureComponent {
|
|||
<Icon
|
||||
id='angle-right'
|
||||
size='10px'
|
||||
className={[_s.mlAuto, _s.fillColorSecondary].join(' ')}
|
||||
className={[_s.mlAuto, _s.fillColorSecondary, _s.flexShrink1].join(' ')}
|
||||
/>
|
||||
}
|
||||
</Button>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import Button from './button'
|
||||
import Icon from './icon'
|
||||
import Text from './text'
|
||||
|
||||
const messages = defineMessages({
|
||||
|
@ -15,8 +14,6 @@ class LoadMore extends PureComponent {
|
|||
onClick: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
visible: PropTypes.bool,
|
||||
maxId: PropTypes.string,
|
||||
gap: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
|
@ -24,13 +21,16 @@ class LoadMore extends PureComponent {
|
|||
visible: true,
|
||||
}
|
||||
|
||||
handleClick = () => {
|
||||
const { gap, maxId } = this.props
|
||||
this.props.onClick(gap ? maxId : undefined)
|
||||
handleClick = (e) => {
|
||||
this.props.onClick()
|
||||
}
|
||||
|
||||
render() {
|
||||
const { disabled, visible, gap, intl } = this.props
|
||||
const {
|
||||
disabled,
|
||||
visible,
|
||||
intl,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<div className={[_s.default, _s.py10, _s.px10].join(' ')}>
|
||||
|
@ -40,22 +40,15 @@ class LoadMore extends PureComponent {
|
|||
backgroundColor='tertiary'
|
||||
color='primary'
|
||||
disabled={disabled || !visible}
|
||||
style={{ visibility: visible ? 'visible' : 'hidden' }}
|
||||
style={{
|
||||
visibility: visible ? 'visible' : 'hidden',
|
||||
}}
|
||||
onClick={this.handleClick}
|
||||
aria-label={intl.formatMessage(messages.load_more)}
|
||||
>
|
||||
{
|
||||
!gap &&
|
||||
<Text color='inherit' align='center'>
|
||||
{intl.formatMessage(messages.load_more)}
|
||||
</Text>
|
||||
}
|
||||
{
|
||||
gap &&
|
||||
<Text align='center'>
|
||||
<Icon id='ellipsis' size='14px' />
|
||||
</Text>
|
||||
}
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -13,13 +13,14 @@ const cx = classNames.bind(_s)
|
|||
export default class MediaItem extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
attachment: ImmutablePropTypes.map.isRequired,
|
||||
small: PropTypes.bool
|
||||
isSmall: PropTypes.bool,
|
||||
}
|
||||
|
||||
state = {
|
||||
visible: displayMedia !== 'hide_all' && !this.props.attachment.getIn(['status', 'sensitive']) || displayMedia === 'show_all',
|
||||
loaded: false,
|
||||
visible: displayMedia !== 'hide_all' && !this.props.attachment.getIn(['status', 'sensitive']) || displayMedia === 'show_all',
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -59,7 +60,11 @@ export default class MediaItem extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { attachment, small } = this.props
|
||||
const {
|
||||
account,
|
||||
attachment,
|
||||
isSmall,
|
||||
} = this.props
|
||||
const { visible, loaded } = this.state
|
||||
|
||||
const status = attachment.get('status')
|
||||
|
@ -81,8 +86,8 @@ export default class MediaItem extends ImmutablePureComponent {
|
|||
top0: 1,
|
||||
height100PC: 1,
|
||||
width100PC: 1,
|
||||
py5: !small,
|
||||
px5: !small,
|
||||
py2: !isSmall,
|
||||
px2: !isSmall,
|
||||
})
|
||||
|
||||
const linkClasses = cx({
|
||||
|
@ -91,15 +96,16 @@ export default class MediaItem extends ImmutablePureComponent {
|
|||
height100PC: 1,
|
||||
overflowHidden: 1,
|
||||
border1PX: 1,
|
||||
borderColorPrimary: !small,
|
||||
borderColorPrimary: small,
|
||||
borderColorPrimary: 1,
|
||||
})
|
||||
|
||||
const statusUrl = `/${account.getIn(['acct'])}/posts/${status.get('id')}`;
|
||||
|
||||
return (
|
||||
<div className={[_s.default, _s.width25PC, _s.pt25PC].join(' ')}>
|
||||
<div className={containerClasses}>
|
||||
<NavLink
|
||||
to={status.get('url')} /* : todo : */
|
||||
to={statusUrl}
|
||||
title={title}
|
||||
className={linkClasses}
|
||||
>
|
||||
|
|
|
@ -51,7 +51,7 @@ class CommunityTimelineSettingsModal extends ImmutablePureComponent {
|
|||
|
||||
return (
|
||||
<ModalLayout
|
||||
width='320'
|
||||
width={320}
|
||||
title={intl.formatMessage(messages.title)}
|
||||
>
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import { muteAccount } from '../../actions/accounts'
|
||||
|
||||
const messages = defineMessages({
|
||||
muteMessage: { id: 'confirmations.mute.message', defaultMessage: 'Are you sure you want to mute {name}?' },
|
||||
cancel: { id: 'confirmation_modal.cancel', defaultMessage: 'Cancel' },
|
||||
title: { id: 'display_options', defaultMessage: 'Display Options' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class DisplayOptionsModal extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
isSubmitting: PropTypes.bool.isRequired,
|
||||
account: PropTypes.object.isRequired,
|
||||
onConfirm: PropTypes.func.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.button.focus()
|
||||
}
|
||||
|
||||
handleClick = () => {
|
||||
this.props.onClose()
|
||||
this.props.onConfirm(this.props.account, this.props.notifications)
|
||||
}
|
||||
|
||||
handleCancel = () => {
|
||||
this.props.onClose()
|
||||
}
|
||||
|
||||
// document.documentElement.style.setProperty("--color-surface", "black");
|
||||
|
||||
render() {
|
||||
const { account, intl } = this.props
|
||||
|
||||
return (
|
||||
<ModalLayout
|
||||
width={320}
|
||||
title={intl.formatMessage(messages.title)}
|
||||
>
|
||||
</ModalLayout>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
|
@ -28,10 +28,11 @@ class EditProfileModal extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { account, intl } = this.props
|
||||
const { account, intl, onClose } = this.props
|
||||
|
||||
const headerSrc = !!account ? account.get('header') : ''
|
||||
|
||||
|
@ -40,6 +41,7 @@ class EditProfileModal extends ImmutablePureComponent {
|
|||
title={intl.formatMessage(messages.edit_profile)}
|
||||
noPadding
|
||||
width={460}
|
||||
onClose={onClose}
|
||||
>
|
||||
<div className={[_s.default, _s.py5, _s.px5, _s.width100PC, _s.overflowHidden].join(' ')}>
|
||||
<Image
|
||||
|
|
|
@ -4,7 +4,7 @@ import ModalLayout from './modal_layout'
|
|||
import GroupCreate from '../../features/group_create'
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'create_group', defaultMessage: 'Create Group' },
|
||||
title: { id: 'create_group', defaultMessage: 'Create group' },
|
||||
})
|
||||
|
||||
export default
|
||||
|
@ -22,7 +22,7 @@ class GroupCreateModal extends ImmutablePureComponent {
|
|||
return (
|
||||
<ModalLayout
|
||||
title={intl.formatMessage(messages.title)}
|
||||
width='440'
|
||||
width={440}
|
||||
onClose={onClose}
|
||||
>
|
||||
<GroupCreate onCloseModal={onClose} />
|
||||
|
|
|
@ -54,7 +54,7 @@ class HashtagTimelineSettingsModal extends ImmutablePureComponent {
|
|||
|
||||
return (
|
||||
<ModalLayout
|
||||
width='320'
|
||||
width={320}
|
||||
title={intl.formatMessage(messages.title)}
|
||||
onClose={onClose}
|
||||
>
|
||||
|
|
|
@ -55,7 +55,7 @@ class HomeTimelineSettingsModal extends ImmutablePureComponent {
|
|||
|
||||
return (
|
||||
<ModalLayout
|
||||
width='320'
|
||||
width={320}
|
||||
title={intl.formatMessage(messages.title)}
|
||||
onClose={onClose}
|
||||
>
|
||||
|
|
|
@ -22,10 +22,10 @@ class ListCreateModal extends ImmutablePureComponent {
|
|||
return (
|
||||
<ModalLayout
|
||||
title={intl.formatMessage(messages.title)}
|
||||
width='500'
|
||||
width={500}
|
||||
onClose={onClose}
|
||||
>
|
||||
<ListCreate />
|
||||
<ListCreate isModal />
|
||||
</ModalLayout>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import { makeGetAccount } from '../../selectors'
|
||||
import { blockAccount } from '../../actions/accounts'
|
||||
import { deleteList } from '../../actions/lists'
|
||||
import ConfirmationModal from './confirmation_modal'
|
||||
|
||||
const messages = defineMessages({
|
||||
|
@ -10,14 +9,14 @@ const messages = defineMessages({
|
|||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onConfirm(account) {
|
||||
// dispatch(blockAccount(account.get('id')))
|
||||
onConfirm(listId) {
|
||||
dispatch(deleteList(listId))
|
||||
},
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(null, mapDispatchToProps)
|
||||
@injectIntl
|
||||
@connect(null, mapDispatchToProps)
|
||||
class ListDeleteModal extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
|
@ -27,17 +26,17 @@ class ListDeleteModal extends PureComponent {
|
|||
}
|
||||
|
||||
handleClick = () => {
|
||||
this.props.onConfirm(this.props.account)
|
||||
this.props.onConfirm(this.props.list.get('id'))
|
||||
}
|
||||
|
||||
render() {
|
||||
const { list, intl, onClose } = this.props
|
||||
|
||||
const title = intl.formatMessage(messages.title, {
|
||||
list: !!list ? account.get('title') : '',
|
||||
list: !!list ? list.get('title') : '',
|
||||
})
|
||||
const message = intl.formatMessage(messages.listMessage, {
|
||||
list: !!list ? account.get('title') : '',
|
||||
list: !!list ? list.get('title') : '',
|
||||
})
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,68 +1,33 @@
|
|||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import { muteAccount } from '../../actions/accounts'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ModalLayout from './modal_layout'
|
||||
import ListEdit from '../../features/list_edit'
|
||||
|
||||
const messages = defineMessages({
|
||||
muteMessage: { id: 'confirmations.mute.message', defaultMessage: 'Are you sure you want to mute {name}?' },
|
||||
cancel: { id: 'confirmation_modal.cancel', defaultMessage: 'Cancel' },
|
||||
confirm: { id: 'confirmations.mute.confirm', defaultMessage: 'Mute' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
isSubmitting: state.getIn(['reports', 'new', 'isSubmitting']),
|
||||
account: state.getIn(['mutes', 'new', 'account']),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onConfirm(account, notifications) {
|
||||
dispatch(muteAccount(account.get('id'), notifications))
|
||||
},
|
||||
title: { id: 'lists.edit', defaultMessage: 'Edit list' },
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class UnfollowModal extends PureComponent {
|
||||
class ListEditorModal extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
isSubmitting: PropTypes.bool.isRequired,
|
||||
account: PropTypes.object.isRequired,
|
||||
onConfirm: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.button.focus()
|
||||
}
|
||||
|
||||
handleClick = () => {
|
||||
this.props.onClose()
|
||||
this.props.onConfirm(this.props.account, this.props.notifications)
|
||||
}
|
||||
|
||||
handleCancel = () => {
|
||||
this.props.onClose()
|
||||
onClose: PropTypes.func.isRequired,
|
||||
listId: PropTypes.string.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { account, intl } = this.props
|
||||
|
||||
// , {
|
||||
// message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
||||
// confirm: intl.formatMessage(messages.unfollowConfirm),
|
||||
// onConfirm: () => dispatch(unfollowAccount(account.get('id'))),
|
||||
// }));
|
||||
const { intl, onClose, listId } = this.props
|
||||
|
||||
return (
|
||||
<ConfirmationModal
|
||||
title={`Mute @${account.get('acct')}`}
|
||||
message={<FormattedMessage id='confirmations.mute.message' defaultMessage='Are you sure you want to mute @{name}?' values={{ name: account.get('acct') }} />}
|
||||
confirm={<FormattedMessage id='mute' defaultMessage='Mute' />}
|
||||
onConfirm={() => {
|
||||
// dispatch(blockDomain(domain))
|
||||
// dispatch(blockDomain(domain))
|
||||
}}
|
||||
/>
|
||||
<ModalLayout
|
||||
title={intl.formatMessage(messages.title)}
|
||||
width={500}
|
||||
onClose={onClose}
|
||||
>
|
||||
<ListEdit listId={listId} />
|
||||
</ModalLayout>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ class ListTimelineSettingsModal extends ImmutablePureComponent {
|
|||
|
||||
return (
|
||||
<ModalLayout
|
||||
width='320'
|
||||
width={320}
|
||||
title={intl.formatMessage(messages.title)}
|
||||
onClose={onClose}
|
||||
>
|
||||
|
|
|
@ -17,7 +17,6 @@ class ModalLayout extends PureComponent {
|
|||
title: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
handleCloseModal: PropTypes.func.isRequired,
|
||||
width: PropTypes.number,
|
||||
hideClose: PropTypes.bool,
|
||||
noPadding: PropTypes.bool,
|
||||
|
|
|
@ -2,73 +2,101 @@ import { closeModal } from '../../actions/modal'
|
|||
import { cancelReplyCompose } from '../../actions/compose'
|
||||
import Bundle from '../../features/ui/util/bundle'
|
||||
import {
|
||||
MuteModal,
|
||||
ReportModal,
|
||||
MODAL_ACTIONS,
|
||||
MODAL_BLOCK_ACCOUNT,
|
||||
MODAL_BLOCK_DOMAIN,
|
||||
MODAL_BOOST,
|
||||
MODAL_COMMUNITY_TIMELINE_SETTINGS,
|
||||
MODAL_COMPOSE,
|
||||
MODAL_CONFIRM,
|
||||
MODAL_DISPLAY_OPTIONS,
|
||||
MODAL_EDIT_PROFILE,
|
||||
MODAL_EMBED,
|
||||
MODAL_GIF_PICKER,
|
||||
MODAL_GROUP_CREATE,
|
||||
MODAL_GROUP_DELETE,
|
||||
MODAL_GROUP_EDITOR,
|
||||
MODAL_HASHTAG_TIMELINE_SETTINGS,
|
||||
MODAL_HOME_TIMELINE_SETTINGS,
|
||||
MODAL_HOTKEYS,
|
||||
MODAL_LIST_CREATE,
|
||||
MODAL_LIST_DELETE,
|
||||
MODAL_LIST_EDITOR,
|
||||
MODAL_LIST_TIMELINE_SETTINGS,
|
||||
MODAL_MEDIA,
|
||||
MODAL_MUTE,
|
||||
MODAL_PRO_UPGRADE,
|
||||
MODAL_REPORT,
|
||||
MODAL_STATUS_REVISIONS,
|
||||
MODAL_UNAUTHORIZED,
|
||||
MODAL_UNFOLLOW,
|
||||
MODAL_VIDEO,
|
||||
} from '../../constants'
|
||||
import {
|
||||
ActionsModal,
|
||||
BlockAccountModal,
|
||||
BlockDomainModal,
|
||||
BoostModal,
|
||||
CommunityTimelineSettingsModal,
|
||||
ComposeModal,
|
||||
ConfirmationModal,
|
||||
DisplayOptionsModal,
|
||||
EditProfileModal,
|
||||
EmbedModal,
|
||||
// ListEditor,
|
||||
// ListAdder,
|
||||
GifPickerModal,
|
||||
GroupCreateModal,
|
||||
GroupDeleteModal,
|
||||
GroupEditorModal,
|
||||
HashtagTimelineSettingsModal,
|
||||
HomeTimelineSettingsModal,
|
||||
HotkeysModal,
|
||||
ListCreateModal,
|
||||
ListDeleteModal,
|
||||
ListEditorModal,
|
||||
ListTimelineSettingsModal,
|
||||
MediaModal,
|
||||
MuteModal,
|
||||
ProUpgradeModal,
|
||||
ReportModal,
|
||||
StatusRevisionsModal,
|
||||
UnauthorizedModal,
|
||||
UnfollowModal,
|
||||
VideoModal,
|
||||
} from '../../features/ui/util/async_components'
|
||||
|
||||
import ModalBase from './modal_base'
|
||||
import BundleModalError from '../bundle_modal_error'
|
||||
|
||||
import ActionsModal from './actions_modal'
|
||||
import BlockAccountModal from './block_account_modal'
|
||||
import BlockDomainModal from './block_domain_modal'
|
||||
import BoostModal from './boost_modal'
|
||||
import CommunityTimelineSettingsModal from './community_timeline_settings_modal'
|
||||
import ComposeModal from './compose_modal'
|
||||
import ConfirmationModal from './confirmation_modal'
|
||||
import EditProfileModal from './edit_profile_modal'
|
||||
import GifPickerModal from './gif_picker_modal'
|
||||
import GroupCreateModal from './group_create_modal'
|
||||
import GroupDeleteModal from './group_delete_modal'
|
||||
import GroupEditorModal from './group_editor_modal'
|
||||
import HashtagTimelineSettingsModal from './hashtag_timeline_settings_modal'
|
||||
import HomeTimelineSettingsModal from './home_timeline_settings_modal'
|
||||
import HotkeysModal from './hotkeys_modal'
|
||||
import ListCreateModal from './list_create_modal'
|
||||
import ListDeleteModal from './list_delete_modal'
|
||||
import ListEditorModal from './list_editor_modal'
|
||||
import ListTimelineSettingsModal from './list_timeline_settings_modal'
|
||||
import MediaModal from './media_modal'
|
||||
import ModalLoading from './modal_loading'
|
||||
import ProUpgradeModal from './pro_upgrade_modal'
|
||||
import VideoModal from './video_modal'
|
||||
import UnauthorizedModal from './unauthorized_modal'
|
||||
import UnfollowModal from './unfollow_modal'
|
||||
|
||||
const MODAL_COMPONENTS = {
|
||||
ACTIONS: () => Promise.resolve({ default: ActionsModal }),
|
||||
BLOCK_ACCOUNT: () => Promise.resolve({ default: BlockAccountModal }),
|
||||
BLOCK_DOMAIN: () => Promise.resolve({ default: BlockDomainModal }),
|
||||
BOOST: () => Promise.resolve({ default: BoostModal }),
|
||||
COMMUNITY_TIMELINE_SETTINGS: () => Promise.resolve({ default: CommunityTimelineSettingsModal }),
|
||||
COMPOSE: () => Promise.resolve({ default: ComposeModal }),
|
||||
CONFIRM: () => Promise.resolve({ default: ConfirmationModal }),
|
||||
EDIT_PROFILE: () => Promise.resolve({ default: EditProfileModal }),
|
||||
EMBED: () => Promise.resolve({ default: EmbedModal }),
|
||||
GIF_PICKER: () => Promise.resolve({ default: GifPickerModal }),
|
||||
GROUP_CREATE: () => Promise.resolve({ default: GroupCreateModal }),
|
||||
GROUP_DELETE: () => Promise.resolve({ default: GroupDeleteModal }),
|
||||
GROUP_EDITOR: () => Promise.resolve({ default: GroupEditorModal }),
|
||||
HASHTAG_TIMELINE_SETTINGS: () => Promise.resolve({ default: HashtagTimelineSettingsModal }),
|
||||
HOME_TIMELINE_SETTINGS: () => Promise.resolve({ default: HomeTimelineSettingsModal }),
|
||||
HOTKEYS: () => Promise.resolve({ default: HotkeysModal }),
|
||||
LIST_CREATE: () => Promise.resolve({ default: ListCreateModal }),
|
||||
LIST_DELETE: () => Promise.resolve({ default: ListDeleteModal }),
|
||||
LIST_EDITOR: () => Promise.resolve({ default: ListEditorModal }),
|
||||
LIST_TIMELINE_SETTINGS: () => Promise.resolve({ default: ListTimelineSettingsModal }),
|
||||
MEDIA: () => Promise.resolve({ default: MediaModal }),
|
||||
MUTE: MuteModal,
|
||||
PRO_UPGRADE: () => Promise.resolve({ default: ProUpgradeModal }),
|
||||
REPORT: ReportModal,
|
||||
STATUS_REVISIONS: StatusRevisionsModal,
|
||||
UNAUTHORIZED: () => Promise.resolve({ default: UnauthorizedModal }),
|
||||
UNFOLLOW: () => Promise.resolve({ default: UnfollowModal }),
|
||||
VIDEO: () => Promise.resolve({ default: VideoModal }),
|
||||
}
|
||||
const MODAL_COMPONENTS = {}
|
||||
MODAL_COMPONENTS[MODAL_ACTIONS] = ActionsModal
|
||||
MODAL_COMPONENTS[MODAL_BLOCK_ACCOUNT] = BlockAccountModal
|
||||
MODAL_COMPONENTS[MODAL_BLOCK_DOMAIN] = BlockDomainModal
|
||||
MODAL_COMPONENTS[MODAL_BOOST] = BoostModal
|
||||
MODAL_COMPONENTS[MODAL_COMMUNITY_TIMELINE_SETTINGS] = CommunityTimelineSettingsModal
|
||||
MODAL_COMPONENTS[MODAL_COMPOSE] = ComposeModal
|
||||
MODAL_COMPONENTS[MODAL_CONFIRM] = ConfirmationModal
|
||||
MODAL_COMPONENTS[MODAL_DISPLAY_OPTIONS] = DisplayOptionsModal
|
||||
MODAL_COMPONENTS[MODAL_EDIT_PROFILE] = EditProfileModal
|
||||
MODAL_COMPONENTS[MODAL_EMBED] = EmbedModal
|
||||
MODAL_COMPONENTS[MODAL_GIF_PICKER] = GifPickerModal
|
||||
MODAL_COMPONENTS[MODAL_GROUP_CREATE] = GroupCreateModal
|
||||
MODAL_COMPONENTS[MODAL_GROUP_DELETE] = GroupDeleteModal
|
||||
MODAL_COMPONENTS[MODAL_GROUP_EDITOR] = GroupEditorModal
|
||||
MODAL_COMPONENTS[MODAL_HASHTAG_TIMELINE_SETTINGS] = HashtagTimelineSettingsModal
|
||||
MODAL_COMPONENTS[MODAL_HOME_TIMELINE_SETTINGS] = HomeTimelineSettingsModal
|
||||
MODAL_COMPONENTS[MODAL_HOTKEYS] = HotkeysModal
|
||||
MODAL_COMPONENTS[MODAL_LIST_CREATE] = ListCreateModal
|
||||
MODAL_COMPONENTS[MODAL_LIST_DELETE] = ListDeleteModal
|
||||
MODAL_COMPONENTS[MODAL_LIST_EDITOR] = ListEditorModal
|
||||
MODAL_COMPONENTS[MODAL_LIST_TIMELINE_SETTINGS] = ListTimelineSettingsModal
|
||||
MODAL_COMPONENTS[MODAL_MEDIA] = MediaModal
|
||||
MODAL_COMPONENTS[MODAL_MUTE] = MuteModal
|
||||
MODAL_COMPONENTS[MODAL_PRO_UPGRADE] = ProUpgradeModal
|
||||
MODAL_COMPONENTS[MODAL_REPORT] = ReportModal
|
||||
MODAL_COMPONENTS[MODAL_STATUS_REVISIONS] = StatusRevisionsModal
|
||||
MODAL_COMPONENTS[MODAL_UNAUTHORIZED] = UnauthorizedModal
|
||||
MODAL_COMPONENTS[MODAL_UNFOLLOW] = UnfollowModal
|
||||
MODAL_COMPONENTS[MODAL_VIDEO] = VideoModal
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
type: state.getIn(['modal', 'modalType']),
|
||||
|
|
|
@ -25,7 +25,7 @@ class ProUpgradeModal extends ImmutablePureComponent {
|
|||
return (
|
||||
<ModalLayout
|
||||
title={intl.formatMessage(messages.title)}
|
||||
width='460'
|
||||
width={460}
|
||||
onClose={onClose}
|
||||
>
|
||||
<Text>
|
||||
|
|
|
@ -5,7 +5,6 @@ import classNames from 'classnames/bind'
|
|||
import { loadStatusRevisions } from '../../actions/status_revisions'
|
||||
import ModalLayout from './modal_layout'
|
||||
import RelativeTimestamp from '../relative_timestamp'
|
||||
import ScrollableList from '../scrollable_list'
|
||||
import Text from '../text'
|
||||
|
||||
const cx = classNames.bind(_s)
|
||||
|
@ -56,11 +55,10 @@ class StatusRevisionsModal extends ImmutablePureComponent {
|
|||
return (
|
||||
<ModalLayout
|
||||
title={intl.formatMessage(messages.title)}
|
||||
width='480'
|
||||
width={480}
|
||||
onClose={onClose}
|
||||
>
|
||||
<div className={[_s.default]}>
|
||||
<ScrollableList>
|
||||
{
|
||||
revisions.map((revision, i) => {
|
||||
const isFirst = i === 0
|
||||
|
@ -91,7 +89,6 @@ class StatusRevisionsModal extends ImmutablePureComponent {
|
|||
)
|
||||
})
|
||||
}
|
||||
</ScrollableList>
|
||||
</div>
|
||||
</ModalLayout>
|
||||
)
|
||||
|
|
|
@ -43,10 +43,18 @@ class Notification extends ImmutablePureComponent {
|
|||
createdAt: PropTypes.string,
|
||||
statusId: PropTypes.string,
|
||||
type: PropTypes.string.isRequired,
|
||||
isHidden: PropTypes.bool,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, accounts, createdAt, type, statusId } = this.props
|
||||
const {
|
||||
intl,
|
||||
accounts,
|
||||
createdAt,
|
||||
type,
|
||||
statusId,
|
||||
isHidden,
|
||||
} = this.props
|
||||
|
||||
const count = !!accounts ? accounts.size : 0
|
||||
|
||||
|
@ -83,6 +91,10 @@ class Notification extends ImmutablePureComponent {
|
|||
return null
|
||||
}
|
||||
|
||||
if (isHidden) {
|
||||
// : todo :
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={[_s.default, _s.px10, _s.cursorPointer, _s.backgroundColorSubtle_onHover].join(' ')}>
|
||||
<div className={[_s.default, _s.borderBottom1PX, _s.borderColorSecondary].join(' ')}>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Fragment } from 'react'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import { shortNumberFormat } from '../../utils/numbers'
|
||||
|
@ -9,6 +9,7 @@ import Divider from '../divider'
|
|||
import Heading from '../heading'
|
||||
import Icon from '../icon'
|
||||
import Text from '../text'
|
||||
import RelativeTimestamp from '../relative_timestamp'
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'about', defaultMessage: 'About' },
|
||||
|
@ -27,15 +28,19 @@ class GroupInfoPanel extends ImmutablePureComponent {
|
|||
render() {
|
||||
const { intl, group } = this.props
|
||||
|
||||
console.log("group:", group)
|
||||
|
||||
return (
|
||||
<PanelLayout title={intl.formatMessage(messages.title)}>
|
||||
{
|
||||
!!group &&
|
||||
<Fragment>
|
||||
|
||||
<Heading size='h2'>
|
||||
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
|
||||
<Text weight='medium'>
|
||||
{group.get('title')}
|
||||
</Heading>
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<Divider isSmall />
|
||||
|
||||
|
@ -63,6 +68,23 @@ class GroupInfoPanel extends ImmutablePureComponent {
|
|||
|
||||
<Divider isSmall />
|
||||
|
||||
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
|
||||
<Icon id='calendar' size='12px' className={_s.fillColorSecondary} />
|
||||
<Text
|
||||
size='small'
|
||||
color='secondary'
|
||||
className={_s.ml5}
|
||||
>
|
||||
{
|
||||
<FormattedMessage id='lists.panel_created' defaultMessage='Created: {date}' values={{
|
||||
date: <RelativeTimestamp timestamp={group.get('created_at')} />,
|
||||
}} />
|
||||
}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<Divider isSmall />
|
||||
|
||||
<Text>
|
||||
{group.get('description')}
|
||||
</Text>
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { fetchGroups } from '../../actions/groups'
|
||||
import PanelLayout from './panel_layout'
|
||||
import GroupListItem from '../group_list_item'
|
||||
import Button from '../button'
|
||||
import ScrollableList from '../scrollable_list'
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'groups.sidebar-panel.title', defaultMessage: 'Groups you\'re in' },
|
||||
|
@ -15,13 +16,41 @@ const mapStateToProps = (state) => ({
|
|||
groupIds: state.getIn(['group_lists', 'member']),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onFetchGroups: (type) => {
|
||||
dispatch(fetchGroups(type))
|
||||
}
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps)
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class GroupSidebarPanel extends ImmutablePureComponent {
|
||||
static propTypes = {
|
||||
groupIds: ImmutablePropTypes.list,
|
||||
slim: PropTypes.bool,
|
||||
isLazy: PropTypes.bool,
|
||||
isSlim: PropTypes.bool,
|
||||
onFetchGroups: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
state = {
|
||||
fetched: false,
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState) {
|
||||
if (!nextProps.isHidden && nextProps.isIntersecting && !prevState.fetched) {
|
||||
return {
|
||||
fetched: true
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
if (!prevState.fetched && this.state.fetched && this.props.isLazy) {
|
||||
this.props.onFetchGroups('member')
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -42,6 +71,9 @@ class GroupSidebarPanel extends ImmutablePureComponent {
|
|||
noPadding={slim}
|
||||
>
|
||||
<div className={_s.default}>
|
||||
<ScrollableList
|
||||
scrollKey='groups-panel'
|
||||
>
|
||||
{
|
||||
groupIds.slice(0, maxCount).map((groupId, i) => (
|
||||
<GroupListItem
|
||||
|
@ -52,6 +84,7 @@ class GroupSidebarPanel extends ImmutablePureComponent {
|
|||
/>
|
||||
))
|
||||
}
|
||||
</ScrollableList>
|
||||
</div>
|
||||
</PanelLayout>
|
||||
)
|
||||
|
|
|
@ -1,57 +1,48 @@
|
|||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { fetchSuggestions, dismissSuggestion } from '../../actions/suggestions'
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import PanelLayout from './panel_layout'
|
||||
import Avatar from '../avatar'
|
||||
import Divider from '../divider'
|
||||
import Icon from '../icon'
|
||||
import Heading from '../heading'
|
||||
import RelativeTimestamp from '../relative_timestamp'
|
||||
import Text from '../text'
|
||||
|
||||
const messages = defineMessages({
|
||||
dismissSuggestion: { id: 'suggestions.dismiss', defaultMessage: 'Dismiss suggestion' },
|
||||
memberCount: { id: 'lists.panel_members', defaultMessage: 'Members: {count}' },
|
||||
createdAt: { id: 'lists.panel_created', defaultMessage: 'Created: {date}' },
|
||||
title: { id: 'lists_information', defaultMessage: 'List Information' },
|
||||
edit: { id: 'edit', defaultMessage: 'Edit' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
// accountIds: state.getIn(['listEditor', 'accounts', 'items']),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class ListDetailsPanel extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
onEdit: PropTypes.func.isRequired,
|
||||
list: ImmutablePropTypes.map,
|
||||
}
|
||||
|
||||
handleShowAllLists() {
|
||||
|
||||
handleOnEdit = () => {
|
||||
this.props.onEdit()
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl } = this.props
|
||||
const { intl, list } = this.props
|
||||
|
||||
const title = !!list ? list.get('title') : ''
|
||||
const createdAt = !!list ? list.get('created_at') : ''
|
||||
|
||||
return (
|
||||
<PanelLayout
|
||||
title={intl.formatMessage(messages.title)}
|
||||
headerButtonTitle={intl.formatMessage(messages.edit)}
|
||||
headerButtonAction={this.handleShowAllLists}
|
||||
headerButtonAction={this.handleOnEdit}
|
||||
>
|
||||
<div className={_s.default}>
|
||||
|
||||
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter,].join(' ')}>
|
||||
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
|
||||
<Text weight='medium'>
|
||||
Some List Title
|
||||
{title}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
|
@ -65,42 +56,13 @@ class ListDetailsPanel extends ImmutablePureComponent {
|
|||
className={_s.ml5}
|
||||
>
|
||||
{
|
||||
intl.formatMessage(messages.createdAt, {
|
||||
date: '12-25-2019'
|
||||
})
|
||||
<FormattedMessage id='lists.panel_created' defaultMessage='Created: {date}' values={{
|
||||
date: <RelativeTimestamp timestamp={createdAt} />,
|
||||
}} />
|
||||
}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<Divider isSmall />
|
||||
|
||||
<div className={[_s.default].join(' ')}>
|
||||
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
|
||||
<Icon id='group' size='12px' className={_s.fillColorSecondary} />
|
||||
<Text
|
||||
size='small'
|
||||
color='secondary'
|
||||
className={_s.ml5}
|
||||
>
|
||||
{
|
||||
intl.formatMessage(messages.memberCount, {
|
||||
count: 10
|
||||
})
|
||||
}
|
||||
</Text>
|
||||
</div>
|
||||
<div className={[_s.default, _s.flexRow, _s.flexWrap, _s.pt10].join(' ')}>
|
||||
|
||||
{
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9].map(item => (
|
||||
<div className={[_s.default, _s.mr5].join(' ')}>
|
||||
<Avatar size={26} />
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</PanelLayout>
|
||||
)
|
||||
|
|
|
@ -32,9 +32,29 @@ class ListsPanel extends ImmutablePureComponent {
|
|||
intl: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
state = {
|
||||
fetched: false,
|
||||
}
|
||||
|
||||
updateOnProps = [
|
||||
'lists',
|
||||
]
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState) {
|
||||
if (!nextProps.isHidden && nextProps.isIntersecting && !prevState.fetched) {
|
||||
return {
|
||||
fetched: true,
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
if (!prevState.fetched && this.state.fetched) {
|
||||
this.props.onFetchLists()
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, lists } = this.props
|
||||
|
|
|
@ -66,11 +66,12 @@ class MediaGalleryPanel extends ImmutablePureComponent {
|
|||
>
|
||||
<div className={[_s.default, _s.flexRow, _s.flexWrap, _s.px10, _s.py10].join(' ')}>
|
||||
{
|
||||
attachments.slice(0, 16).map((attachment) => (
|
||||
attachments.slice(0, 16).map((attachment, i) => (
|
||||
<MediaItem
|
||||
small
|
||||
isSmall
|
||||
key={attachment.get('id')}
|
||||
attachment={attachment}
|
||||
account={account}
|
||||
/>
|
||||
))
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import SettingSwitch from '../setting_switch'
|
|||
const messages = defineMessages({
|
||||
title: { id: 'notification_filters', defaultMessage: 'Notification Filters' },
|
||||
onlyVerified: { id: 'notification_only_verified', defaultMessage: 'Only Verified Users' },
|
||||
onlyFollowing: { id: 'notification_only_following', defaultMessage: 'Only People I Follow' },
|
||||
// onlyFollowing: { id: 'notification_only_following', defaultMessage: 'Only People I Follow' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
|
@ -55,13 +55,14 @@ class NotificationFilterPanel extends ImmutablePureComponent {
|
|||
label={intl.formatMessage(messages.onlyVerified)}
|
||||
/>
|
||||
|
||||
{ /* : todo :
|
||||
<SettingSwitch
|
||||
prefix='notification'
|
||||
settings={settings}
|
||||
settingPath={'onlyFollowing'}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage(messages.onlyFollowing)}
|
||||
/>
|
||||
/> */ }
|
||||
</PanelLayout>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
|||
import { fetchGabTrends } from '../../actions/gab_trends'
|
||||
import PanelLayout from './panel_layout'
|
||||
import ColumnIndicator from '../column_indicator'
|
||||
import ScrollableList from '../scrollable_list'
|
||||
import TrendingItem from '../trends_item'
|
||||
|
||||
const messages = defineMessages({
|
||||
|
@ -29,7 +30,7 @@ class TrendsPanel extends ImmutablePureComponent {
|
|||
onFetchGabTrends: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
componentDidMount() {
|
||||
this.props.onFetchGabTrends()
|
||||
}
|
||||
|
||||
|
@ -47,7 +48,12 @@ class TrendsPanel extends ImmutablePureComponent {
|
|||
<ColumnIndicator type='loading' />
|
||||
}
|
||||
{
|
||||
gabtrends && gabtrends.slice(0, 8).map((trend, i) => (
|
||||
!gabtrends.isEmpty() &&
|
||||
<ScrollableList
|
||||
scrollKey='trending-items'
|
||||
>
|
||||
{
|
||||
gabtrends.slice(0, 8).map((trend, i) => (
|
||||
<TrendingItem
|
||||
key={`gab-trend-${i}`}
|
||||
index={i + 1}
|
||||
|
@ -61,6 +67,8 @@ class TrendsPanel extends ImmutablePureComponent {
|
|||
/>
|
||||
))
|
||||
}
|
||||
</ScrollableList>
|
||||
}
|
||||
</div>
|
||||
</PanelLayout>
|
||||
)
|
||||
|
|
|
@ -36,19 +36,34 @@ class WhoToFollowPanel extends ImmutablePureComponent {
|
|||
'suggestions',
|
||||
]
|
||||
|
||||
componentDidMount () {
|
||||
state = {
|
||||
fetched: false,
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState) {
|
||||
if (!nextProps.isHidden && nextProps.isIntersecting && !prevState.fetched) {
|
||||
return {
|
||||
fetched: true
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
if (!prevState.fetched && this.state.fetched) {
|
||||
this.props.fetchSuggestions()
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, suggestions, dismissSuggestion } = this.props
|
||||
|
||||
if (suggestions.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
if (suggestions.isEmpty()) return null
|
||||
|
||||
return (
|
||||
<PanelLayout
|
||||
noPadding
|
||||
title={intl.formatMessage(messages.title)}
|
||||
footerButtonTitle={intl.formatMessage(messages.show_more)}
|
||||
footerButtonTo='/explore'
|
||||
|
@ -57,6 +72,7 @@ class WhoToFollowPanel extends ImmutablePureComponent {
|
|||
{
|
||||
suggestions.map(accountId => (
|
||||
<Account
|
||||
compact
|
||||
showDismiss
|
||||
key={accountId}
|
||||
id={accountId}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import PopoverLayout from './popover_layout'
|
||||
import Text from '../text'
|
||||
|
||||
export default class UserInfoPopover extends PureComponent {
|
||||
render() {
|
||||
return (
|
||||
<PopoverLayout>
|
||||
<Text>testing</Text>
|
||||
</PopoverLayout>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -2,8 +2,6 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
|||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { Manager, Reference, Popper } from 'react-popper'
|
||||
import classnames from 'classnames/bind'
|
||||
import spring from 'react-motion/lib/spring'
|
||||
import Motion from '../../features/ui/util/optional_motion'
|
||||
import { openPopover, closePopover } from '../../actions/popover'
|
||||
import { openModal, closeModal } from '../../actions/modal'
|
||||
import { isUserTouching } from '../../utils/is_mobile'
|
||||
|
@ -117,7 +115,6 @@ class PopoverBase extends ImmutablePureComponent {
|
|||
targetRef,
|
||||
innerRef,
|
||||
} = this.props
|
||||
const open = this.state.id === openPopoverType
|
||||
|
||||
const containerClasses = cx({
|
||||
default: 1,
|
||||
|
@ -125,8 +122,6 @@ class PopoverBase extends ImmutablePureComponent {
|
|||
displayNone: !visible,
|
||||
})
|
||||
|
||||
console.log('targetRef:', targetRef)
|
||||
|
||||
return (
|
||||
<Manager>
|
||||
<Popper
|
||||
|
|
|
@ -1,37 +1,51 @@
|
|||
import detectPassiveEvents from 'detect-passive-events'
|
||||
import { closePopover } from '../../actions/popover'
|
||||
import {
|
||||
POPOVER_CONTENT_WARNING,
|
||||
POPOVER_DATE_PICKER,
|
||||
POPOVER_EMOJI_PICKER,
|
||||
POPOVER_GROUP_INFO,
|
||||
POPOVER_PROFILE_OPTIONS,
|
||||
POPOVER_REPOST_OPTIONS,
|
||||
POPOVER_SEARCH,
|
||||
POPOVER_SIDEBAR_MORE,
|
||||
POPOVER_STATUS_OPTIONS,
|
||||
POPOVER_STATUS_SHARE,
|
||||
POPOVER_STATUS_VISIBILITY,
|
||||
POPOVER_USER_INFO,
|
||||
} from '../../constants'
|
||||
import {
|
||||
ContentWarningPopover,
|
||||
DatePickerPopover,
|
||||
EmojiPickerPopover,
|
||||
GroupInfoPopover,
|
||||
ProfileOptionsPopover,
|
||||
RepostOptionsPopover,
|
||||
SearchPopover,
|
||||
SidebarMorePopover,
|
||||
StatusOptionsPopover,
|
||||
StatusSharePopover,
|
||||
StatusVisibilityPopover,
|
||||
UserInfoPopover,
|
||||
} from '../../features/ui/util/async_components'
|
||||
import Bundle from '../../features/ui/util/bundle'
|
||||
import BundleModalError from '../bundle_modal_error'
|
||||
import PopoverBase from './popover_base'
|
||||
import ContentWarningPopover from './content_warning_popover'
|
||||
import DatePickerPopover from './date_picker_popover'
|
||||
import EmojiPickerPopover from './emoji_picker_popover'
|
||||
import GroupInfoPopover from './group_info_popover'
|
||||
import ProfileOptionsPopover from './profile_options_popover'
|
||||
import RepostOptionsPopover from './repost_options_popover'
|
||||
import SearchPopover from './search_popover'
|
||||
import SidebarMorePopover from './sidebar_more_popover'
|
||||
import StatusOptionsPopover from './status_options_popover'
|
||||
import StatusSharePopover from './status_share_popover'
|
||||
import StatusVisibilityPopover from './status_visibility_popover'
|
||||
import UserInfoPopover from './user_info_popover'
|
||||
|
||||
const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false
|
||||
|
||||
const POPOVER_COMPONENTS = {
|
||||
CONTENT_WARNING: () => Promise.resolve({ default: ContentWarningPopover }),
|
||||
DATE_PICKER: () => Promise.resolve({ default: DatePickerPopover }),
|
||||
EMOJI_PICKER: () => Promise.resolve({ default: EmojiPickerPopover }),
|
||||
GROUP_INFO: () => GroupInfoPopover,
|
||||
PROFILE_OPTIONS: () => Promise.resolve({ default: ProfileOptionsPopover }),
|
||||
REPOST_OPTIONS: () => Promise.resolve({ default: RepostOptionsPopover }),
|
||||
SEARCH: () => Promise.resolve({ default: SearchPopover }),
|
||||
SIDEBAR_MORE: () => Promise.resolve({ default: SidebarMorePopover }),
|
||||
STATUS_OPTIONS: () => Promise.resolve({ default: StatusOptionsPopover }),
|
||||
STATUS_SHARE: () => Promise.resolve({ default: StatusSharePopover }),
|
||||
STATUS_VISIBILITY: () => Promise.resolve({ default: StatusVisibilityPopover }),
|
||||
USER_INFO: () => Promise.resolve({ default: UserInfoPopover }),
|
||||
}
|
||||
const POPOVER_COMPONENTS = {}
|
||||
POPOVER_COMPONENTS[POPOVER_CONTENT_WARNING] = ContentWarningPopover
|
||||
POPOVER_COMPONENTS[POPOVER_DATE_PICKER] = DatePickerPopover
|
||||
POPOVER_COMPONENTS[POPOVER_EMOJI_PICKER] = EmojiPickerPopover
|
||||
POPOVER_COMPONENTS[POPOVER_GROUP_INFO] = GroupInfoPopover
|
||||
POPOVER_COMPONENTS[POPOVER_PROFILE_OPTIONS] = ProfileOptionsPopover
|
||||
POPOVER_COMPONENTS[POPOVER_REPOST_OPTIONS] = RepostOptionsPopover
|
||||
POPOVER_COMPONENTS[POPOVER_SEARCH] = SearchPopover
|
||||
POPOVER_COMPONENTS[POPOVER_SIDEBAR_MORE] = SidebarMorePopover
|
||||
POPOVER_COMPONENTS[POPOVER_STATUS_OPTIONS] = StatusOptionsPopover
|
||||
POPOVER_COMPONENTS[POPOVER_STATUS_SHARE] = StatusSharePopover
|
||||
POPOVER_COMPONENTS[POPOVER_STATUS_VISIBILITY] = StatusVisibilityPopover
|
||||
POPOVER_COMPONENTS[POPOVER_USER_INFO] = UserInfoPopover
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
type: state.getIn(['popover', 'popoverType']),
|
||||
|
@ -84,14 +98,10 @@ class PopoverRoot extends PureComponent {
|
|||
document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions)
|
||||
}
|
||||
|
||||
setRef = c => {
|
||||
setRef = (c) => {
|
||||
this.node = c
|
||||
}
|
||||
|
||||
setFocusRef = c => {
|
||||
this.focusedItem = c
|
||||
}
|
||||
|
||||
handleKeyDown = e => {
|
||||
const items = Array.from(this.node.getElementsByTagName('a'))
|
||||
const index = items.indexOf(document.activeElement)
|
||||
|
@ -150,8 +160,6 @@ class PopoverRoot extends PureComponent {
|
|||
const { type, props } = this.props
|
||||
const visible = !!type
|
||||
|
||||
console.log("POPOVER_COMPONENTS[type]:", type, POPOVER_COMPONENTS[type]);
|
||||
|
||||
return (
|
||||
<PopoverBase
|
||||
visible={visible}
|
||||
|
@ -162,12 +170,12 @@ class PopoverRoot extends PureComponent {
|
|||
visible &&
|
||||
<Bundle
|
||||
fetchComponent={POPOVER_COMPONENTS[type]}
|
||||
loading={this.renderLoading(type)}
|
||||
loading={this.renderLoading()}
|
||||
error={this.renderError}
|
||||
renderDelay={200}
|
||||
>
|
||||
{
|
||||
(SpecificComponent) => <SpecificComponent {...props} />
|
||||
(Component) => <Component {...props} />
|
||||
}
|
||||
</Bundle>
|
||||
}
|
||||
|
|
|
@ -1,8 +1,39 @@
|
|||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { MODAL_DISPLAY_OPTIONS } from '../../constants'
|
||||
import { openModal } from '../../actions/modal'
|
||||
import PopoverLayout from './popover_layout'
|
||||
import List from '../list'
|
||||
|
||||
export default class SidebarMorePopover extends PureComponent {
|
||||
const messages = defineMessages({
|
||||
display: { id: 'display_options', defaultMessage: 'Display Options' },
|
||||
help: { id: 'getting_started.help', defaultMessage: 'Help' },
|
||||
settings: { id: 'settings', defaultMessage: 'Settings' },
|
||||
logout: { 'id': 'confirmations.logout.confirm', 'defaultMessage': 'Log out' },
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onOpenDisplayModal: () => {
|
||||
dispatch(openModal(MODAL_DISPLAY_OPTIONS))
|
||||
},
|
||||
})
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
@connect(null, mapDispatchToProps)
|
||||
class SidebarMorePopover extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
onOpenDisplayModal: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
handleOnOpenDisplayModal = () => {
|
||||
this.props.onOpenDisplayModal()
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl } = this.props
|
||||
|
||||
return (
|
||||
<PopoverLayout className={_s.width240PX}>
|
||||
<List
|
||||
|
@ -10,15 +41,19 @@ export default class SidebarMorePopover extends PureComponent {
|
|||
scrollKey='profile_options'
|
||||
items={[
|
||||
{
|
||||
title: 'Help',
|
||||
title: intl.formatMessage(messages.help),
|
||||
href: 'https://help.gab.com',
|
||||
},
|
||||
{
|
||||
title: 'Settings',
|
||||
title: intl.formatMessage(messages.display),
|
||||
onClick: this.handleOnOpenDisplayModal,
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage(messages.settings),
|
||||
href: '/settings',
|
||||
},
|
||||
{
|
||||
title: 'Log Out',
|
||||
title: intl.formatMessage(messages.logout),
|
||||
href: '/auth/log_out',
|
||||
},
|
||||
]}
|
||||
|
|
|
@ -47,7 +47,7 @@ class StatusVisibilityDropdown extends PureComponent {
|
|||
this.props.onChange(value)
|
||||
}
|
||||
|
||||
componentWillMount () {
|
||||
componentDidMount () {
|
||||
const { intl } = this.props
|
||||
|
||||
this.options = [
|
||||
|
|
|
@ -6,7 +6,9 @@ import {
|
|||
CX,
|
||||
POPOVER_PROFILE_OPTIONS,
|
||||
PLACEHOLDER_MISSING_HEADER_SRC,
|
||||
MODAL_EDIT_PROFILE,
|
||||
} from '../constants'
|
||||
import { openModal } from '../actions/modal'
|
||||
import { openPopover } from '../actions/popover'
|
||||
import { me } from '../initial_state'
|
||||
import AccountActionButton from './account_action_button'
|
||||
|
@ -27,6 +29,7 @@ const messages = defineMessages({
|
|||
comments: { id: 'comments', defaultMessage: 'Comments' },
|
||||
media: { id: 'media', defaultMessage: 'Media' },
|
||||
accountFollowsYou: { id: 'account.follows_you', defaultMessage: 'Follows you' },
|
||||
editProfile: { id: "account.edit_profile", defaultMessage: "Edit profile" },
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
|
@ -35,6 +38,10 @@ const mapDispatchToProps = (dispatch) => ({
|
|||
dispatch(openPopover(POPOVER_PROFILE_OPTIONS, props))
|
||||
},
|
||||
|
||||
onEditProfile() {
|
||||
dispatch(openModal(MODAL_EDIT_PROFILE))
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
export default
|
||||
|
@ -45,6 +52,7 @@ class ProfileHeader extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onEditProfile: PropTypes.func.isRequired,
|
||||
openProfileOptionsPopover: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
|
@ -52,6 +60,10 @@ class ProfileHeader extends ImmutablePureComponent {
|
|||
stickied: false,
|
||||
}
|
||||
|
||||
handleOnEditProfile = () => {
|
||||
this.props.onEditProfile()
|
||||
}
|
||||
|
||||
handleOpenMore = () => {
|
||||
const { openProfileOptionsPopover, account } = this.props
|
||||
|
||||
|
@ -164,15 +176,10 @@ class ProfileHeader extends ImmutablePureComponent {
|
|||
backgroundColor='none'
|
||||
color='brand'
|
||||
className={[_s.justifyContentCenter, _s.alignItemsCenter].join(' ')}
|
||||
href=''
|
||||
onClick={this.handleOnEditProfile}
|
||||
>
|
||||
<Text
|
||||
color='inherit'
|
||||
weight='bold'
|
||||
size='medium'
|
||||
className={[_s.px15].join(' ')}
|
||||
>
|
||||
Edit Profile
|
||||
<Text color='inherit' weight='bold' size='medium' className={_s.px15}>
|
||||
{intl.formatMessage(messages.editProfile)}
|
||||
</Text>
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
@ -196,7 +196,7 @@ export default class ScrollableList extends PureComponent {
|
|||
return firstChild && firstChild.key;
|
||||
}
|
||||
|
||||
handleLoadMore = e => {
|
||||
handleLoadMore = (e) => {
|
||||
e.preventDefault();
|
||||
this.props.onLoadMore();
|
||||
}
|
||||
|
@ -213,9 +213,7 @@ export default class ScrollableList extends PureComponent {
|
|||
} = this.props
|
||||
const childrenCount = React.Children.count(children);
|
||||
|
||||
const trackScroll = true; //placeholder
|
||||
|
||||
const loadMore = (hasMore && onLoadMore) ? <LoadMore visible={!isLoading} onClick={this.handleLoadMore} /> : null;
|
||||
const loadMore = (hasMore && onLoadMore) ? <LoadMore visible={!isLoading} onClick={this.handleLoadMore} /> : null
|
||||
|
||||
if (showLoading) {
|
||||
return <ColumnIndicator type='loading' />
|
||||
|
@ -232,7 +230,7 @@ export default class ScrollableList extends PureComponent {
|
|||
index={index}
|
||||
listLength={childrenCount}
|
||||
intersectionObserverWrapper={this.intersectionObserverWrapper}
|
||||
saveHeightKey={trackScroll ? `${this.context.router.route.location.key}:${scrollKey}` : null}
|
||||
saveHeightKey={`${this.context.router.route.location.key}:${scrollKey}`}
|
||||
>
|
||||
{
|
||||
React.cloneElement(child, {
|
||||
|
|
|
@ -57,8 +57,8 @@ class Search extends PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
handleChange = (e) => {
|
||||
this.props.onChange(e.target.value)
|
||||
handleChange = (value) => {
|
||||
this.props.onChange(value)
|
||||
}
|
||||
|
||||
handleFocus = () => {
|
||||
|
|
|
@ -43,8 +43,13 @@ const mapStateToProps = (state, { timelineId }) => {
|
|||
const getStatusIds = makeGetStatusIds();
|
||||
const promotion = promotions.length > 0 && sample(promotions.filter(p => p.timeline_id === timelineId));
|
||||
|
||||
const statusIds = getStatusIds(state, {
|
||||
type: timelineId.substring(0,5) === 'group' ? 'group' : timelineId,
|
||||
id: timelineId
|
||||
})
|
||||
|
||||
return {
|
||||
statusIds: getStatusIds(state, { type: timelineId.substring(0,5) === 'group' ? 'group' : timelineId, id: timelineId }),
|
||||
statusIds,
|
||||
isLoading: state.getIn(['timelines', timelineId, 'isLoading'], true),
|
||||
isPartial: state.getIn(['timelines', timelineId, 'isPartial'], false),
|
||||
hasMore: state.getIn(['timelines', timelineId, 'hasMore']),
|
||||
|
|
|
@ -28,7 +28,7 @@ export default class TabBar extends PureComponent {
|
|||
onClick={tab.onClick}
|
||||
icon={tab.icon}
|
||||
to={tab.to}
|
||||
active={tab.active}
|
||||
isActive={tab.active}
|
||||
isLarge={isLarge}
|
||||
/>
|
||||
))
|
||||
|
|
|
@ -13,22 +13,23 @@ export default class Textarea extends PureComponent {
|
|||
onKeyUp: PropTypes.func,
|
||||
onFocus: PropTypes.func,
|
||||
onBlur: PropTypes.func,
|
||||
onClear: PropTypes.func,
|
||||
title: PropTypes.string,
|
||||
}
|
||||
|
||||
handleOnChange = (e) => {
|
||||
this.props.onChange(e.target.value)
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
placeholder,
|
||||
prependIcon,
|
||||
value,
|
||||
hasClear,
|
||||
onChange,
|
||||
onKeyUp,
|
||||
onFocus,
|
||||
onBlur,
|
||||
onClear,
|
||||
title
|
||||
title,
|
||||
} = this.props
|
||||
|
||||
const inputClasses = cx({
|
||||
|
@ -64,7 +65,7 @@ export default class Textarea extends PureComponent {
|
|||
type='text'
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onChange={this.handleOnChange}
|
||||
onKeyUp={onKeyUp}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { Fragment } from 'react'
|
||||
import classNames from 'classnames/bind'
|
||||
import { urlRegex } from '../features/compose/util/url_regex'
|
||||
import Button from './button'
|
||||
|
@ -19,6 +20,7 @@ export default class TrendingItem extends PureComponent {
|
|||
author: PropTypes.string,
|
||||
publishDate: PropTypes.string,
|
||||
isLast: PropTypes.bool,
|
||||
isHidden: PropTypes.bool,
|
||||
wide: PropTypes.bool,
|
||||
}
|
||||
|
||||
|
@ -51,9 +53,24 @@ export default class TrendingItem extends PureComponent {
|
|||
publishDate,
|
||||
isLast,
|
||||
wide,
|
||||
isHidden,
|
||||
} = this.props
|
||||
const { hovering } = this.state
|
||||
|
||||
const correctedAuthor = author.replace('www.', '')
|
||||
const correctedDescription = description.length >= 120 ? `${description.substring(0, 120).trim()}...` : description
|
||||
const descriptionHasLink = correctedDescription.match(urlRegex)
|
||||
|
||||
if (isHidden) {
|
||||
return (
|
||||
<Fragment>
|
||||
{title}
|
||||
{!descriptionHasLink && correctedDescription}
|
||||
{correctedAuthor}
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
const containerClasses = cx({
|
||||
default: 1,
|
||||
noUnderline: 1,
|
||||
|
@ -70,10 +87,6 @@ export default class TrendingItem extends PureComponent {
|
|||
underline: hovering,
|
||||
})
|
||||
|
||||
const correctedAuthor = author.replace('www.', '')
|
||||
const correctedDescription = description.length >= 120 ? `${description.substring(0, 120).trim()}...` : description
|
||||
const descriptionHasLink = correctedDescription.match(urlRegex)
|
||||
|
||||
const image = (
|
||||
<Image
|
||||
nullable
|
||||
|
|
|
@ -12,7 +12,47 @@ export const BREAKPOINT_EXTRA_SMALL = 992
|
|||
export const ALLOWED_AROUND_SHORT_CODE = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d'
|
||||
export const MAX_POST_CHARACTER_COUNT = 3000
|
||||
|
||||
export const PLACEHOLDER_MISSING_HEADER_SRC = '/headers/original/missing.png'
|
||||
export const PLACEHOLDER_MISSING_HEADER_SRC = '/original/missing.png'
|
||||
|
||||
export const POPOVER_CONTENT_WARNING = 'CONTENT_WARNING'
|
||||
export const POPOVER_DATE_PICKER = 'DATE_PICKER'
|
||||
export const POPOVER_EMOJI_PICKER = 'EMOJI_PICKER'
|
||||
export const POPOVER_GROUP_INFO = 'GROUP_INFO'
|
||||
export const POPOVER_PROFILE_OPTIONS = 'PROFILE_OPTIONS'
|
||||
export const POPOVER_REPOST_OPTIONS = 'REPOST_OPTIONS'
|
||||
export const POPOVER_SEARCH = 'SEARCH'
|
||||
export const POPOVER_SIDEBAR_MORE = 'SIDEBAR_MORE'
|
||||
export const POPOVER_STATUS_OPTIONS = 'STATUS_OPTIONS'
|
||||
export const POPOVER_STATUS_SHARE = 'STATUS_SHARE'
|
||||
export const POPOVER_STATUS_VISIBILITY = 'STATUS_VISIBILITY'
|
||||
export const POPOVER_USER_INFO = 'USER_INFO'
|
||||
|
||||
export const MODAL_ACTIONS = 'ACTIONS'
|
||||
export const MODAL_BLOCK_ACCOUNT = 'BLOCK_ACCOUNT'
|
||||
export const MODAL_BLOCK_DOMAIN = 'BLOCK_DOMAIN'
|
||||
export const MODAL_BOOST = 'BOOST'
|
||||
export const MODAL_COMMUNITY_TIMELINE_SETTINGS = 'COMMUNITY_TIMELINE_SETTINGS'
|
||||
export const MODAL_COMPOSE = 'COMPOSE'
|
||||
export const MODAL_CONFIRM = 'CONFIRM'
|
||||
export const MODAL_DISPLAY_OPTIONS = 'DISPLAY_OPTIONS'
|
||||
export const MODAL_EDIT_PROFILE = 'EDIT_PROFILE'
|
||||
export const MODAL_EMBED = 'EMBED'
|
||||
export const MODAL_GIF_PICKER = 'GIF_PICKER'
|
||||
export const MODAL_GROUP_CREATE = 'GROUP_CREATE'
|
||||
export const MODAL_GROUP_DELETE = 'GROUP_DELETE'
|
||||
export const MODAL_GROUP_EDITOR = 'GROUP_EDITOR'
|
||||
export const MODAL_HASHTAG_TIMELINE_SETTINGS = 'HASHTAG_TIMELINE_SETTINGS'
|
||||
export const MODAL_HOME_TIMELINE_SETTINGS = 'HOME_TIMELINE_SETTINGS'
|
||||
export const MODAL_HOTKEYS = 'HOTKEYS'
|
||||
export const MODAL_LIST_CREATE = 'LIST_CREATE'
|
||||
export const MODAL_LIST_DELETE = 'LIST_DELETE'
|
||||
export const MODAL_LIST_EDITOR = 'LIST_EDITOR'
|
||||
export const MODAL_LIST_TIMELINE_SETTINGS = 'LIST_TIMELINE_SETTINGS'
|
||||
export const MODAL_MEDIA = 'MEDIA'
|
||||
export const MODAL_MUTE = 'MUTE'
|
||||
export const MODAL_PRO_UPGRADE = 'PRO_UPGRADE'
|
||||
export const MODAL_REPORT = 'REPORT'
|
||||
export const MODAL_STATUS_REVISIONS = 'STATUS_REVISIONS'
|
||||
export const MODAL_UNAUTHORIZED = 'UNAUTHORIZED'
|
||||
export const MODAL_UNFOLLOW = 'UNFOLLOW'
|
||||
export const MODAL_VIDEO = 'VIDEO'
|
||||
|
|
|
@ -98,8 +98,12 @@ class AccountGallery extends ImmutablePureComponent {
|
|||
>
|
||||
|
||||
{
|
||||
attachments.map((attachment) => (
|
||||
<MediaItem key={attachment.get('id')} attachment={attachment} />
|
||||
attachments.map((attachment, i) => (
|
||||
<MediaItem
|
||||
key={attachment.get('id')}
|
||||
attachment={attachment}
|
||||
account={account}
|
||||
/>
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -108,16 +112,16 @@ class AccountGallery extends ImmutablePureComponent {
|
|||
<ColumnIndicator type='loading' />
|
||||
}
|
||||
|
||||
{ /*
|
||||
attachments.size === 0 &&
|
||||
<ColumnIndicator type='empty' message={intl.formatMessage(messages.none)} />
|
||||
*/ }
|
||||
{
|
||||
!isLoading && attachments.size === 0 &&
|
||||
<ColumnIndicator type='error' message={intl.formatMessage(messages.none)} />
|
||||
}
|
||||
</div>
|
||||
|
||||
{
|
||||
hasMore && !(isLoading && attachments.size === 0) &&
|
||||
<LoadMore visible={!isLoading} onClick={this.handleLoadOlder} />
|
||||
}
|
||||
</div>
|
||||
</Block>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { fetchReposts } from '../actions/interactions';
|
||||
import { fetchStatus } from '../actions/statuses';
|
||||
import { makeGetStatus } from '../selectors';
|
||||
import Account from '../components/account';
|
||||
import ColumnIndicator from '../components/column_indicator';
|
||||
import ScrollableList from '../components/scrollable_list';
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
const getStatus = makeGetStatus();
|
||||
const status = getStatus(state, {
|
||||
id: props.params.statusId,
|
||||
username: props.params.username,
|
||||
});
|
||||
|
||||
return {
|
||||
status,
|
||||
accountIds: state.getIn(['user_lists', 'favorites', props.params.statusId]),
|
||||
};
|
||||
};
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps)
|
||||
class Favorites extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
status: ImmutablePropTypes.map,
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
this.props.dispatch(fetchReposts(this.props.params.statusId));
|
||||
this.props.dispatch(fetchStatus(this.props.params.statusId));
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) {
|
||||
this.props.dispatch(fetchReposts(nextProps.params.statusId));
|
||||
this.props.dispatch(fetchStatus(nextProps.params.statusId));
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { accountIds, status } = this.props;
|
||||
|
||||
if (!accountIds) {
|
||||
return <ColumnIndicator type='loading' />
|
||||
} else if (!status) {
|
||||
return <ColumnIndicator type='missing' />
|
||||
}
|
||||
|
||||
return (
|
||||
<ScrollableList
|
||||
scrollKey='reposts'
|
||||
emptyMessage={<FormattedMessage id='status.reposts.empty' defaultMessage='No one has reposted this gab yet. When someone does, they will show up here.' />}
|
||||
>
|
||||
{
|
||||
accountIds.map(id =>
|
||||
<Account key={id} id={id} />
|
||||
)
|
||||
}
|
||||
</ScrollableList>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -41,7 +41,7 @@ class Following extends ImmutablePureComponent {
|
|||
hasMore: PropTypes.bool,
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
componentDidMount() {
|
||||
const { accountId } = this.props
|
||||
|
||||
if (!!accountId && accountId !== -1) {
|
||||
|
@ -67,7 +67,7 @@ class Following extends ImmutablePureComponent {
|
|||
account,
|
||||
accountIds,
|
||||
hasMore,
|
||||
intl
|
||||
intl,
|
||||
} = this.props
|
||||
|
||||
if (!account) return null
|
||||
|
|
|
@ -2,12 +2,20 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
|||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import isObject from 'lodash.isobject'
|
||||
import { changeValue, submit, setUp, reset } from '../actions/group_editor'
|
||||
import ColumnIndicator from '../components/column_indicator';
|
||||
import {
|
||||
changeGroupTitle,
|
||||
changeGroupDescription,
|
||||
changeGroupCoverImage,
|
||||
submit,
|
||||
setGroup,
|
||||
resetEditor,
|
||||
} from '../actions/group_editor'
|
||||
import ColumnIndicator from '../components/column_indicator'
|
||||
import Button from '../components/button'
|
||||
import Divider from '../components/divider'
|
||||
import Input from '../components/input'
|
||||
import Text from '../components/text'
|
||||
import Form from '../components/form'
|
||||
import Textarea from '../components/textarea'
|
||||
import FileInput from '../components/file_input'
|
||||
|
||||
|
@ -18,6 +26,8 @@ const messages = defineMessages({
|
|||
coverImageChange: { id: 'groups.form.coverImageChange', defaultMessage: 'Banner image selected' },
|
||||
create: { id: 'groups.form.create', defaultMessage: 'Create group' },
|
||||
update: { id: 'groups.form.update', defaultMessage: 'Update group' },
|
||||
titlePlaceholder: { id: 'groups.form.title_placeholder', defaultMessage: 'New group title...' },
|
||||
descriptionPlaceholder: { id: 'groups.form.description_placeholder', defaultMessage: 'Some group description...' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state, { params }) => {
|
||||
|
@ -27,26 +37,37 @@ const mapStateToProps = (state, { params }) => {
|
|||
return {
|
||||
group,
|
||||
error: groupId && !group,
|
||||
title: state.getIn(['group_editor', 'title']),
|
||||
description: state.getIn(['group_editor', 'description']),
|
||||
titleValue: state.getIn(['group_editor', 'title']),
|
||||
descriptionValue: state.getIn(['group_editor', 'description']),
|
||||
coverImage: state.getIn(['group_editor', 'coverImage']),
|
||||
disabled: state.getIn(['group_editor', 'isSubmitting']),
|
||||
isSubmitting: state.getIn(['group_editor', 'isSubmitting']),
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onTitleChange: value => dispatch(changeValue('title', value)),
|
||||
onDescriptionChange: value => dispatch(changeValue('description', value)),
|
||||
onCoverImageChange: value => dispatch(changeValue('coverImage', value)),
|
||||
onSubmit: routerHistory => dispatch(submit(routerHistory)),
|
||||
reset: () => dispatch(reset()),
|
||||
setUp: group => dispatch(setUp(group)),
|
||||
onTitleChange: (value) => {
|
||||
dispatch(changeGroupTitle(value))
|
||||
},
|
||||
onDescriptionChange: (value) => {
|
||||
dispatch(changeGroupDescription(value))
|
||||
},
|
||||
onCoverImageChange: (imageData) => {
|
||||
console.log("imageData:", imageData)
|
||||
dispatch(changeGroupCoverImage(imageData))
|
||||
},
|
||||
onResetEditor: () => {
|
||||
dispatch(resetEditor())
|
||||
},
|
||||
onSetGroup: (group) => {
|
||||
dispatch(setGroup(group))
|
||||
},
|
||||
onSubmit: (routerHistory) => dispatch(submit(routerHistory)),
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class Create extends ImmutablePureComponent {
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
class GroupCreate extends ImmutablePureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
router: PropTypes.object
|
||||
|
@ -54,43 +75,45 @@ class Create extends ImmutablePureComponent {
|
|||
|
||||
static propTypes = {
|
||||
group: ImmutablePropTypes.map,
|
||||
title: PropTypes.string.isRequired,
|
||||
description: PropTypes.string.isRequired,
|
||||
titleValue: PropTypes.string.isRequired,
|
||||
descriptionValue: PropTypes.string.isRequired,
|
||||
coverImage: PropTypes.object,
|
||||
disabled: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onTitleChange: PropTypes.func.isRequired,
|
||||
onDescriptionChange: PropTypes.func.isRequired,
|
||||
onResetEditor: PropTypes.func.isRequired,
|
||||
onSetGroup: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
onCloseModal: PropTypes.func,
|
||||
isSubmitting: PropTypes.bool,
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
updateOnProps = [
|
||||
'group',
|
||||
'titleValue',
|
||||
'descriptionValue',
|
||||
'coverImage',
|
||||
'isSubmitting',
|
||||
]
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.props.group) {
|
||||
this.props.reset()
|
||||
this.props.onResetEditor()
|
||||
} else {
|
||||
this.props.setUp(this.props.group)
|
||||
this.props.onSetGroup(this.props.group)
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.group !== nextProps.group && !!nextProps.group) {
|
||||
this.props.setUp(nextProps.group)
|
||||
this.props.onSetGroup(nextProps.group)
|
||||
}
|
||||
}
|
||||
|
||||
handleTitleChange = e => {
|
||||
this.props.onTitleChange(e.target.value)
|
||||
}
|
||||
|
||||
handleDescriptionChange = e => {
|
||||
this.props.onDescriptionChange(e.target.value)
|
||||
}
|
||||
|
||||
handleCoverImageChange = e => {
|
||||
handleCoverImageChange = (e) => {
|
||||
this.props.onCoverImageChange(e.target.files[0])
|
||||
}
|
||||
|
||||
handleSubmit = e => {
|
||||
handleSubmit = (e) => {
|
||||
e.preventDefault()
|
||||
this.props.onSubmit(this.context.router.history)
|
||||
}
|
||||
|
@ -99,11 +122,14 @@ class Create extends ImmutablePureComponent {
|
|||
const {
|
||||
group,
|
||||
error,
|
||||
title,
|
||||
description,
|
||||
titleValue,
|
||||
descriptionValue,
|
||||
coverImage,
|
||||
disabled,
|
||||
intl
|
||||
intl,
|
||||
onTitleChange,
|
||||
onDescriptionChange,
|
||||
isSubmitting,
|
||||
onSubmit,
|
||||
} = this.props
|
||||
|
||||
if (!group && error) {
|
||||
|
@ -111,30 +137,30 @@ class Create extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<Form onSubmit={onSubmit}>
|
||||
<Input
|
||||
title={intl.formatMessage(messages.title)}
|
||||
value={title}
|
||||
disabled={disabled}
|
||||
onChange={this.handleTitleChange}
|
||||
placeholder={'New group title...'}
|
||||
value={titleValue}
|
||||
onChange={onTitleChange}
|
||||
disabled={isSubmitting}
|
||||
placeholder={intl.formatMessage(messages.titlePlaceholder)}
|
||||
/>
|
||||
|
||||
<Divider isInvisible />
|
||||
|
||||
<Textarea
|
||||
title={intl.formatMessage(messages.description)}
|
||||
value={description}
|
||||
disabled={disabled}
|
||||
onChange={this.handleDescriptionChange}
|
||||
placeholder={'Some group description...'}
|
||||
value={descriptionValue}
|
||||
onChange={onDescriptionChange}
|
||||
placeholder={intl.formatMessage(messages.descriptionPlaceholder)}
|
||||
disabled={isSubmitting}
|
||||
/>
|
||||
|
||||
<Divider isInvisible />
|
||||
|
||||
<FileInput
|
||||
disabled={isSubmitting}
|
||||
title={intl.formatMessage(coverImage === null ? messages.coverImage : messages.coverImageChange)}
|
||||
disabled={disabled}
|
||||
onChange={this.handleCoverImageChange}
|
||||
width='340px'
|
||||
height='145px'
|
||||
|
@ -142,13 +168,16 @@ class Create extends ImmutablePureComponent {
|
|||
|
||||
<Divider isInvisible />
|
||||
|
||||
<Button className={_s.ml10}>
|
||||
<Text color='white'>
|
||||
<Button
|
||||
isDisabled={!titleValue || !descriptionValue && !isSubmitting}
|
||||
onClick={this.handleSubmit}
|
||||
>
|
||||
<Text color='inherit' align='center'>
|
||||
{intl.formatMessage(!!group ? messages.update : messages.create)}
|
||||
</Text>
|
||||
</Button>
|
||||
|
||||
</form>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ class GroupTimeline extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
return (
|
||||
<StatusListContainer
|
||||
<StatusList
|
||||
alwaysPrepend
|
||||
scrollKey={`group_timeline-${columnId}`}
|
||||
timelineId={`group:${id}`}
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { changeListEditorTitle, submitListEditor } from '../actions/lists'
|
||||
import { closeModal } from '../actions/modal'
|
||||
import { MODAL_LIST_CREATE } from '../constants'
|
||||
import Button from '../components/button'
|
||||
import Input from '../components/input'
|
||||
import Form from '../components/form'
|
||||
import Text from '../components/text'
|
||||
|
||||
const messages = defineMessages({
|
||||
label: { id: 'lists.new.title_placeholder', defaultMessage: 'New list title' },
|
||||
create: { id: 'lists.new.create_title', defaultMessage: 'Create' },
|
||||
create: { id: 'lists.new.create_title', defaultMessage: 'Create list' },
|
||||
list_description: { id: 'list.description', defaultMessage: 'Lists are private and only you can see who is on a list.\nNo one else can view your lists. No one knows that they are on your list.' },
|
||||
new_list_placeholder: { id: 'list.title_placeholder', defaultMessage: 'My new list...', },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
|
@ -14,9 +19,12 @@ const mapStateToProps = (state) => ({
|
|||
disabled: state.getIn(['listEditor', 'isSubmitting']),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onChange: value => dispatch(changeListEditorTitle(value)),
|
||||
onSubmit: () => dispatch(submitListEditor(true)),
|
||||
const mapDispatchToProps = (dispatch, { isModal }) => ({
|
||||
onChange: (value) => dispatch(changeListEditorTitle(value)),
|
||||
onSubmit: () => {
|
||||
if (isModal) dispatch(closeModal(MODAL_LIST_CREATE))
|
||||
dispatch(submitListEditor(true))
|
||||
},
|
||||
})
|
||||
|
||||
export default
|
||||
|
@ -25,49 +33,47 @@ export default
|
|||
class ListCreate extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
value: PropTypes.string.isRequired,
|
||||
disabled: PropTypes.bool,
|
||||
value: PropTypes.string,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
isModal: PropTypes.bool,
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
value,
|
||||
disabled,
|
||||
intl,
|
||||
onSubmit,
|
||||
onChange
|
||||
onChange,
|
||||
} = this.props
|
||||
|
||||
const isDisabled = !value
|
||||
|
||||
return (
|
||||
<form onSubmit={onSubmit}>
|
||||
<Form>
|
||||
<Input
|
||||
title={intl.formatMessage(messages.label)}
|
||||
placeholder='My new list...'
|
||||
placeholder={intl.formatMessage(messages.new_list_placeholder)}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onSubmit={onSubmit}
|
||||
disabled={disabled}
|
||||
/>
|
||||
|
||||
<div className={[_s.default, _s.my10, _s.py5, _s.ml10].join(' ')}>
|
||||
<Text color='secondary' size='small'>
|
||||
Lists are private and only you can see who is on a list.<br/>
|
||||
No one else can view your lists. No one knows that they are on your list.
|
||||
{intl.formatMessage(messages.list_description)}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
className={_s.ml10}
|
||||
type='submit'
|
||||
isDisabled={isDisabled}
|
||||
onClick={onSubmit}
|
||||
>
|
||||
<Text color='white'>
|
||||
<Text color='inherit' align='center'>
|
||||
{intl.formatMessage(messages.create)}
|
||||
</Text>
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -12,9 +12,9 @@ const mapStateToProps = (state) => ({
|
|||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onSubmit: value => dispatch(fetchListSuggestions(value)),
|
||||
onSubmit: (value) => dispatch(fetchListSuggestions(value)),
|
||||
onClear: () => dispatch(clearListSuggestions()),
|
||||
onChange: value => dispatch(changeListSuggestions(value)),
|
||||
onChange: (value) => dispatch(changeListSuggestions(value)),
|
||||
});
|
||||
|
||||
export default
|
||||
|
|
|
@ -7,6 +7,7 @@ import Account from './components/account'
|
|||
import ListEditorSearch from './components/list_editor_search'
|
||||
import EditListForm from './components/edit_list_form/edit_list_form'
|
||||
import Button from '../../components/button'
|
||||
import Form from '../../components/form'
|
||||
import Input from '../../components/input'
|
||||
|
||||
const mapStateToProps = (state, { params }) => {
|
||||
|
@ -24,7 +25,7 @@ const mapStateToProps = (state, { params }) => {
|
|||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onInitialize: listId => dispatch(setupListEditor(listId)),
|
||||
onInitialize: (listId) => dispatch(setupListEditor(listId)),
|
||||
onReset: () => dispatch(resetListEditor()),
|
||||
})
|
||||
|
||||
|
@ -80,7 +81,7 @@ class ListEdit extends ImmutablePureComponent {
|
|||
console.log("title:", title)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Form>
|
||||
<Input
|
||||
title={intl.formatMessage(messages.editListTitle)}
|
||||
placeholder='My new list title...'
|
||||
|
@ -90,8 +91,6 @@ class ListEdit extends ImmutablePureComponent {
|
|||
// disabled={disabled}
|
||||
/>
|
||||
|
||||
{
|
||||
/*
|
||||
<div className='compose-modal__header'>
|
||||
<h3 className='compose-modal__header__title'>
|
||||
{intl.formatMessage(messages.editList)}
|
||||
|
@ -119,9 +118,8 @@ class ListEdit extends ImmutablePureComponent {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
*/ }
|
||||
|
||||
</div>
|
||||
</Form>
|
||||
)
|
||||
|
||||
}
|
||||
|
|
|
@ -1,26 +1,22 @@
|
|||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
||||
import { connectListStream } from '../actions/streaming';
|
||||
import { expandListTimeline } from '../actions/timelines';
|
||||
import { fetchList, deleteList } from '../actions/lists';
|
||||
import { openModal } from '../actions/modal';
|
||||
import StatusList from '../components/status_list';
|
||||
import ColumnIndicator from '../components/column_indicator';
|
||||
import Button from '../components/button';
|
||||
|
||||
const messages = defineMessages({
|
||||
deleteMessage: { id: 'confirmations.delete_list.message', defaultMessage: 'Are you sure you want to permanently delete this list?' },
|
||||
deleteConfirm: { id: 'confirmations.delete_list.confirm', defaultMessage: 'Delete' },
|
||||
});
|
||||
import { Fragment } from 'react'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
import { connectListStream } from '../actions/streaming'
|
||||
import { expandListTimeline } from '../actions/timelines'
|
||||
import { fetchList, deleteList } from '../actions/lists'
|
||||
import { openModal } from '../actions/modal'
|
||||
import StatusList from '../components/status_list'
|
||||
import ColumnIndicator from '../components/column_indicator'
|
||||
import Button from '../components/button'
|
||||
import Text from '../components/text'
|
||||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
list: state.getIn(['lists', props.params.id]),
|
||||
});
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps)
|
||||
@injectIntl
|
||||
class ListTimeline extends ImmutablePureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
|
@ -35,84 +31,76 @@ class ListTimeline extends ImmutablePureComponent {
|
|||
PropTypes.bool,
|
||||
]),
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.handleConnect(this.props.params.id);
|
||||
this.handleConnect(this.props.params.id)
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.handleDisconnect();
|
||||
this.handleDisconnect()
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.params.id !== this.props.params.id) {
|
||||
this.handleDisconnect();
|
||||
this.handleConnect(nextProps.params.id);
|
||||
this.handleDisconnect()
|
||||
this.handleConnect(nextProps.params.id)
|
||||
}
|
||||
}
|
||||
|
||||
handleConnect(id) {
|
||||
const { dispatch } = this.props;
|
||||
const { dispatch } = this.props
|
||||
|
||||
dispatch(fetchList(id));
|
||||
dispatch(expandListTimeline(id));
|
||||
dispatch(fetchList(id))
|
||||
dispatch(expandListTimeline(id))
|
||||
|
||||
this.disconnect = dispatch(connectListStream(id));
|
||||
this.disconnect = dispatch(connectListStream(id))
|
||||
}
|
||||
|
||||
handleDisconnect() {
|
||||
if (this.disconnect) {
|
||||
this.disconnect();
|
||||
this.disconnect = null;
|
||||
this.disconnect()
|
||||
this.disconnect = null
|
||||
}
|
||||
}
|
||||
|
||||
handleLoadMore = maxId => {
|
||||
const { id } = this.props.params;
|
||||
this.props.dispatch(expandListTimeline(id, { maxId }));
|
||||
handleLoadMore = (maxId) => {
|
||||
const { id } = this.props.params
|
||||
this.props.dispatch(expandListTimeline(id, { maxId }))
|
||||
}
|
||||
|
||||
handleEditClick = () => {
|
||||
this.props.dispatch(openModal('LIST_EDITOR', { listId: this.props.params.id }));
|
||||
}
|
||||
|
||||
handleDeleteClick = () => {
|
||||
const { dispatch, intl } = this.props;
|
||||
const { id } = this.props.params;
|
||||
|
||||
dispatch(openModal('CONFIRM', {
|
||||
message: intl.formatMessage(messages.deleteMessage),
|
||||
confirm: intl.formatMessage(messages.deleteConfirm),
|
||||
onConfirm: () => {
|
||||
dispatch(deleteList(id));
|
||||
this.context.router.history.push('/lists');
|
||||
},
|
||||
}));
|
||||
this.props.dispatch(openModal('LIST_EDITOR', { listId: this.props.params.id }))
|
||||
}
|
||||
|
||||
render() {
|
||||
const { list } = this.props;
|
||||
const { id } = this.props.params;
|
||||
const title = list ? list.get('title') : id;
|
||||
const { list } = this.props
|
||||
const { id } = this.props.params
|
||||
const title = list ? list.get('title') : id
|
||||
|
||||
if (typeof list === 'undefined') {
|
||||
return (<ColumnIndicator type='loading' />);
|
||||
return <ColumnIndicator type='loading' />
|
||||
} else if (list === false) {
|
||||
return (<ColumnIndicator type='missing' />);
|
||||
return <ColumnIndicator type='missing' />
|
||||
}
|
||||
|
||||
const emptyMessage = (
|
||||
<div>
|
||||
<div className={[_s.default].join(' ')}>
|
||||
<FormattedMessage
|
||||
id='empty_column.list'
|
||||
defaultMessage='There is nothing in this list yet. When members of this list post new statuses, they will appear here.' />
|
||||
<br/><br/>
|
||||
<Button onClick={this.handleEditClick}>
|
||||
defaultMessage='There is nothing in this list yet. When members of this list post new statuses, they will appear here.'
|
||||
/>
|
||||
|
||||
<Button
|
||||
onClick={this.handleEditClick}
|
||||
className={[_s.mt10]}
|
||||
>
|
||||
<Text color='inherit'>
|
||||
<FormattedMessage id='list.click_to_add' defaultMessage='Click here to add people' />
|
||||
</Text>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
|
||||
return (
|
||||
<StatusList
|
||||
|
@ -121,7 +109,7 @@ class ListTimeline extends ImmutablePureComponent {
|
|||
onLoadMore={this.handleLoadMore}
|
||||
emptyMessage={emptyMessage}
|
||||
/>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ class Notifications extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
handleLoadGap = (maxId) => {
|
||||
// maxId={index > 0 ? notifications.getIn([index - 1, 'id']) : null}
|
||||
this.props.dispatch(expandNotifications({ maxId }))
|
||||
}
|
||||
|
||||
|
@ -122,13 +123,7 @@ class Notifications extends ImmutablePureComponent {
|
|||
scrollableContent = this.scrollableContent
|
||||
} else if (notifications.size > 0 || hasMore) {
|
||||
scrollableContent = notifications.map((item, index) => item === null ? (
|
||||
<LoadMore
|
||||
gap
|
||||
key={'gap:' + notifications.getIn([index + 1, 'id'])}
|
||||
disabled={isLoading}
|
||||
maxId={index > 0 ? notifications.getIn([index - 1, 'id']) : null}
|
||||
onClick={this.handleLoadGap}
|
||||
/>
|
||||
<LoadMore disabled={isLoading} onClick={this.handleLoadGap} />
|
||||
) : (
|
||||
<NotificationContainer
|
||||
key={`notification-${index}`}
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ColumnIndicator from '../components/column_indicator'
|
||||
import { fetchLikes } from '../actions/interactions'
|
||||
import Account from '../components/account'
|
||||
import ScrollableList from '../components/scrollable_list'
|
||||
|
||||
const messages = defineMessages({
|
||||
refresh: { id: 'refresh', defaultMessage: 'Refresh' },
|
||||
});
|
||||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
accountIds: state.getIn(['user_lists', 'favourited_by', props.params.statusId]),
|
||||
});
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
@connect(mapStateToProps)
|
||||
class StatusLikes extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
multiColumn: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
if (!this.props.accountIds) {
|
||||
this.props.dispatch(fetchLikes(this.props.params.statusId));
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) {
|
||||
this.props.dispatch(fetchLikes(nextProps.params.statusId));
|
||||
}
|
||||
}
|
||||
|
||||
handleRefresh = () => {
|
||||
this.props.dispatch(fetchLikes(this.props.params.statusId));
|
||||
}
|
||||
|
||||
render () {
|
||||
const { intl, shouldUpdateScroll, accountIds, multiColumn } = this.props;
|
||||
|
||||
if (!accountIds) {
|
||||
return <ColumnIndicator type='loading' />
|
||||
}
|
||||
|
||||
const emptyMessage = <FormattedMessage id='empty_column.favourites' defaultMessage='No one has favourited this toot yet. When someone does, they will show up here.' />;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ScrollableList
|
||||
scrollKey='favourites'
|
||||
shouldUpdateScroll={shouldUpdateScroll}
|
||||
emptyMessage={emptyMessage}
|
||||
bindToDocument={!multiColumn}
|
||||
>
|
||||
{accountIds.map(id =>
|
||||
<Account key={id} id={id} withNote={false} />,
|
||||
)}
|
||||
</ScrollableList>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -23,7 +23,7 @@ const mapStateToProps = (state, props) => {
|
|||
|
||||
export default
|
||||
@connect(mapStateToProps)
|
||||
class Reposts extends ImmutablePureComponent {
|
||||
class StatusReposts extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
|
@ -6,6 +6,7 @@ import { Switch, Redirect, withRouter } from 'react-router-dom'
|
|||
import debounce from 'lodash.debounce'
|
||||
import { uploadCompose, resetCompose } from '../../actions/compose'
|
||||
import { expandHomeTimeline } from '../../actions/timelines'
|
||||
import { fetchGroups } from '../../actions/groups'
|
||||
import {
|
||||
initializeNotifications,
|
||||
expandNotifications,
|
||||
|
@ -40,7 +41,6 @@ import {
|
|||
BlockedAccounts,
|
||||
BlockedDomains,
|
||||
CommunityTimeline,
|
||||
// Favorites,
|
||||
// Filters,
|
||||
Followers,
|
||||
Following,
|
||||
|
@ -61,17 +61,17 @@ import {
|
|||
ListTimeline,
|
||||
Mutes,
|
||||
Notifications,
|
||||
Reposts,
|
||||
Search,
|
||||
// Shortcuts,
|
||||
Status,
|
||||
StatusLikes,
|
||||
StatusReposts,
|
||||
} from './util/async_components'
|
||||
import { me, meUsername } from '../../initial_state'
|
||||
|
||||
// Dummy import, to make sure that <Status /> ends up in the application bundle.
|
||||
// Without this it ends up in ~8 very commonly used bundles.
|
||||
import '../../components/status'
|
||||
import { fetchGroups } from '../../actions/groups'
|
||||
|
||||
const messages = defineMessages({
|
||||
beforeUnload: { id: 'ui.beforeunload', defaultMessage: 'Your draft will be lost if you leave Gab Social.' },
|
||||
|
@ -116,7 +116,7 @@ class SwitchingArea extends PureComponent {
|
|||
onLayoutChange: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
componentDidMount() {
|
||||
window.addEventListener('resize', this.handleResize, {
|
||||
passive: true
|
||||
})
|
||||
|
@ -209,10 +209,10 @@ class SwitchingArea extends PureComponent {
|
|||
<WrappedRoute path='/:username/posts/:statusId' publicRoute exact page={BasicPage} component={Status} content={children} componentParams={{ title: 'Status' }} />
|
||||
|
||||
<Redirect from='/@:username/posts/:statusId/reposts' to='/:username/posts/:statusId/reposts' />
|
||||
<WrappedRoute path='/:username/posts/:statusId/reposts' page={BasicPage} component={Reposts} content={children} componentParams={{ title: 'Reposts' }} />
|
||||
<WrappedRoute path='/:username/posts/:statusId/reposts' page={BasicPage} component={StatusReposts} content={children} componentParams={{ title: 'Reposts' }} />
|
||||
|
||||
{ /* <Redirect from='/@:username/posts/:statusId/favorites' to='/:username/posts/:statusId/favorites' />
|
||||
<WrappedRoute path='/:username/posts/:statusId/favorites' page={BasicPage} component={Favorites} content={children} componentParams={{ title: 'Favorites' }} /> */ }
|
||||
<Redirect from='/@:username/posts/:statusId/likes' to='/:username/posts/:statusId/likes' />
|
||||
<WrappedRoute path='/:username/posts/:statusId/likes' page={BasicPage} component={StatusLikes} content={children} componentParams={{ title: 'Likes' }} />
|
||||
|
||||
<WrappedRoute page={ErrorPage} component={GenericNotFound} content={children} />
|
||||
</Switch>
|
||||
|
@ -349,7 +349,13 @@ class UI extends PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
// componentWillMount() {
|
||||
|
||||
// }
|
||||
|
||||
componentDidMount() {
|
||||
// if (!me) return
|
||||
|
||||
window.addEventListener('beforeunload', this.handleBeforeUnload, false)
|
||||
|
||||
document.addEventListener('dragenter', this.handleDragEnter, false)
|
||||
|
@ -370,15 +376,9 @@ class UI extends PureComponent {
|
|||
this.props.dispatch(expandHomeTimeline())
|
||||
this.props.dispatch(expandNotifications())
|
||||
this.props.dispatch(initializeNotifications())
|
||||
this.props.dispatch(fetchGroups('member'))
|
||||
|
||||
setTimeout(() => this.props.dispatch(fetchFilters()), 500)
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (!me) return
|
||||
|
||||
// this.hotkeys.__mousetrap__.stopCallback = (e, element) => {
|
||||
// return ['TEXTAREA', 'SELECT', 'INPUT'].includes(element.tagName)
|
||||
// }
|
||||
|
@ -435,7 +435,7 @@ class UI extends PureComponent {
|
|||
}
|
||||
|
||||
handleHotkeyToggleHelp = () => {
|
||||
this.props.dispatch(openModal("HOTKEYS"))
|
||||
this.props.dispatch(openModal('HOTKEYS'))
|
||||
}
|
||||
|
||||
handleHotkeyGoToHome = () => {
|
||||
|
@ -471,7 +471,7 @@ class UI extends PureComponent {
|
|||
}
|
||||
|
||||
handleOpenComposeModal = () => {
|
||||
this.props.dispatch(openModal("COMPOSE"))
|
||||
this.props.dispatch(openModal('COMPOSE'))
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
@ -1,34 +1,74 @@
|
|||
export function AccountTimeline() { return import(/* webpackChunkName: "features/account_timeline" */'../../account_timeline') }
|
||||
export function AccountGallery() { return import(/* webpackChunkName: "features/account_gallery" */'../../account_gallery') }
|
||||
export function ActionsModal() { return import(/* webpackChunkName: "components/actions_modal" */'../../../components/modal/actions_modal') }
|
||||
export function BlockAccountModal() { return import(/* webpackChunkName: "components/block_account_modal" */'../../../components/modal/block_account_modal') }
|
||||
export function BlockDomainModal() { return import(/* webpackChunkName: "components/block_domain_modal" */'../../../components/modal/block_domain_modal') }
|
||||
export function BlockedAccounts() { return import(/* webpackChunkName: "features/blocked_accounts" */'../../blocked_accounts') }
|
||||
export function BlockedDomains() { return import(/* webpackChunkName: "features/blocked_domains" */'../../blocked_domains') }
|
||||
export function BoostModal() { return import(/* webpackChunkName: "components/boost_modal" */'../../../components/modal/boost_modal') }
|
||||
export function CommunityTimeline() { return import(/* webpackChunkName: "features/community_timeline" */'../../community_timeline') }
|
||||
export function CommunityTimelineSettingsModal() { return import(/* webpackChunkName: "components/community_timeline_settings_modal" */'../../../components/modal/community_timeline_settings_modal') }
|
||||
export function Compose() { return import(/* webpackChunkName: "features/compose" */'../../compose') }
|
||||
export function ComposeForm() { return import(/* webpackChunkName: "components/compose_form" */'../../compose/components/compose_form') }
|
||||
export function ComposeModal() { return import(/* webpackChunkName: "components/compose_modal" */'../../../components/modal/compose_modal') }
|
||||
export function ConfirmationModal() { return import(/* webpackChunkName: "components/confirmation_modal" */'../../../components/modal/confirmation_modal') }
|
||||
export function ContentWarningPopover() { return import(/* webpackChunkName: "components/content_warning_popover" */'../../../components/popover/content_warning_popover') }
|
||||
export function DatePickerPopover() { return import(/* webpackChunkName: "components/date_picker_popover" */'../../../components/popover/date_picker_popover') }
|
||||
export function DisplayOptionsModal() { return import(/* webpackChunkName: "components/display_options_modal" */'../../../components/modal/display_options_modal') }
|
||||
export function EditProfileModal() { return import(/* webpackChunkName: "components/edit_profile_modal" */'../../../components/modal/edit_profile_modal') }
|
||||
export function EmbedModal() { return import(/* webpackChunkName: "modals/embed_modal" */'../../../components/modal/embed_modal') }
|
||||
export function EmojiPicker() { return import(/* webpackChunkName: "emoji_picker" */'../../../components/emoji/emoji_picker') }
|
||||
export function EmojiPickerPopover() { return import(/* webpackChunkName: "components/emoji_picker_popover" */'../../../components/popover/emoji_picker_popover') }
|
||||
export function Followers() { return import(/* webpackChunkName: "features/followers" */'../../followers') }
|
||||
export function Following() { return import(/* webpackChunkName: "features/following" */'../../following') }
|
||||
export function FollowRequests() { return import(/* webpackChunkName: "features/follow_requests" */'../../follow_requests') }
|
||||
export function LikedStatuses() { return import(/* webpackChunkName: "features/liked_statuses" */'../../liked_statuses') }
|
||||
export function GenericNotFound() { return import(/* webpackChunkName: "features/generic_not_found" */'../../generic_not_found') }
|
||||
export function GifPickerModal() { return import(/* webpackChunkName: "components/gif_picker_modal" */'../../../components/modal/gif_picker_modal') }
|
||||
export function GroupsCollection() { return import(/* webpackChunkName: "features/groups_collection" */'../../groups_collection') }
|
||||
export function GroupCreate() { return import(/* webpackChunkName: "features/group_create" */'../../group_create') }
|
||||
export function GroupCreateModal() { return import(/* webpackChunkName: "components/group_create_modal" */'../../../components/modal/group_create_modal') }
|
||||
export function GroupDeleteModal() { return import(/* webpackChunkName: "components/group_delete_modal" */'../../../components/modal/group_delete_modal') }
|
||||
export function GroupEditorModal() { return import(/* webpackChunkName: "components/group_editor_modal" */'../../../components/modal/group_editor_modal') }
|
||||
export function GroupInfoPopover() { return import(/* webpackChunkName: "components/group_info_popover" */'../../../components/popover/group_info_popover') }
|
||||
export function GroupMembers() { return import(/* webpackChunkName: "features/group_members" */'../../group_members') }
|
||||
export function GroupRemovedAccounts() { return import(/* webpackChunkName: "features/group_removed_accounts" */'../../group_removed_accounts') }
|
||||
export function GroupTimeline() { return import(/* webpackChunkName: "features/group_timeline" */'../../group_timeline') }
|
||||
export function HashtagTimeline() { return import(/* webpackChunkName: "features/hashtag_timeline" */'../../hashtag_timeline') }
|
||||
export function HashtagTimelineSettingsModal() { return import(/* webpackChunkName: "components/hashtag_timeline_settings_modal" */'../../../components/modal/hashtag_timeline_settings_modal') }
|
||||
export function HomeTimeline() { return import(/* webpackChunkName: "features/home_timeline" */'../../home_timeline') }
|
||||
export function HomeTimelineSettingsModal() { return import(/* webpackChunkName: "components/home_timeline_settings_modal" */'../../../components/modal/home_timeline_settings_modal') }
|
||||
export function HotkeysModal() { return import(/* webpackChunkName: "components/hotkeys_modal" */'../../../components/modal/hotkeys_modal') }
|
||||
export function ListCreate() { return import(/* webpackChunkName: "features/list_create" */'../../list_create') }
|
||||
export function ListCreateModal() { return import(/* webpackChunkName: "components/list_create_modal" */'../../../components/modal/list_create_modal') }
|
||||
export function ListDeleteModal() { return import(/* webpackChunkName: "components/list_delete_modal" */'../../../components/modal/list_delete_modal') }
|
||||
export function ListsDirectory() { return import(/* webpackChunkName: "features/lists_directory" */'../../lists_directory') }
|
||||
export function ListEdit() { return import(/* webpackChunkName: "features/list_editor" */'../../list_edit') }
|
||||
export function ListEditorModal() { return import(/* webpackChunkName: "components/list_editor_modal" */'../../../components/modal/list_editor_modal') }
|
||||
export function ListTimeline() { return import(/* webpackChunkName: "features/list_timeline" */'../../list_timeline') }
|
||||
export function ListTimelineSettingsModal() { return import(/* webpackChunkName: "components/list_timeline_settings_modal" */'../../../components/modal/list_timeline_settings_modal') }
|
||||
export function MediaGallery() { return import(/* webpackChunkName: "components/media_gallery" */'../../../components/media_gallery') }
|
||||
export function MediaModal() { return import(/* webpackChunkName: "components/media_modal" */'../../../components/modal/media_modal') }
|
||||
export function ModalLoading() { return import(/* webpackChunkName: "components/modal_loading" */'../../../components/modal/modal_loading') }
|
||||
export function Mutes() { return import(/* webpackChunkName: "features/mutes" */'../../mutes') }
|
||||
export function MuteModal() { return import(/* webpackChunkName: "modals/mute_modal" */'../../../components/modal/mute_modal') }
|
||||
export function Notifications() { return import(/* webpackChunkName: "features/notifications" */'../../notifications') }
|
||||
export function Reposts() { return import(/* webpackChunkName: "features/reposts" */'../../reposts') }
|
||||
export function ProfileOptionsPopover() { return import(/* webpackChunkName: "components/profile_options_popover" */'../../../components/popover/profile_options_popover') }
|
||||
export function ProUpgradeModal() { return import(/* webpackChunkName: "components/pro_upgrade_modal" */'../../../components/modal/pro_upgrade_modal') }
|
||||
export function ReportModal() { return import(/* webpackChunkName: "modals/report_modal" */'../../../components/modal/report_modal') }
|
||||
export function RepostOptionsPopover() { return import(/* webpackChunkName: "components/repost_options_popover" */'../../../components/popover/repost_options_popover') }
|
||||
export function Search() { return import(/*webpackChunkName: "features/search" */'../../search') }
|
||||
export function Status() { return import(/* webpackChunkName: "components/status" */'../../../components/status') }
|
||||
export function SearchPopover() { return import(/* webpackChunkName: "components/search_popover" */'../../../components/popover/search_popover') }
|
||||
export function SidebarMorePopover() { return import(/* webpackChunkName: "components/sidebar_more_popover" */'../../../components/popover/sidebar_more_popover') }
|
||||
export function StatusLikes() { return import(/* webpackChunkName: "features/status_likes" */'../../status_likes') }
|
||||
export function StatusOptionsPopover() { return import(/* webpackChunkName: "components/status_options_popover" */'../../../components/popover/status_options_popover') }
|
||||
export function StatusReposts() { return import(/* webpackChunkName: "features/status_reposts" */'../../status_reposts') }
|
||||
export function StatusRevisionsModal() { return import(/* webpackChunkName: "modals/status_revisions_modal" */'../../../components/modal/status_revisions_modal') }
|
||||
export function StatusSharePopover() { return import(/* webpackChunkName: "components/status_share_popover" */'../../../components/popover/status_share_popover') }
|
||||
export function StatusVisibilityPopover() { return import(/* webpackChunkName: "components/status_visibility_popover" */'../../../components/popover/status_visibility_popover') }
|
||||
export function UnauthorizedModal() { return import(/* webpackChunkName: "components/unauthorized_modal" */'../../../components/modal/unauthorized_modal') }
|
||||
export function UnfollowModal() { return import(/* webpackChunkName: "components/unfollow_modal" */'../../../components/modal/unfollow_modal') }
|
||||
export function UserInfoPopover() { return import(/* webpackChunkName: "components/user_info_popover" */'../../../components/popover/user_info_popover') }
|
||||
export function Video() { return import(/* webpackChunkName: "components/video" */'../../../components/video') }
|
||||
export function VideoModal() { return import(/* webpackChunkName: "components/video_modal" */'../../../components/modal/video_modal') }
|
|
@ -1,7 +1,7 @@
|
|||
import {
|
||||
fetchBundleRequest,
|
||||
fetchBundleSuccess,
|
||||
fetchBundleFail
|
||||
fetchBundleFail,
|
||||
} from '../../../actions/bundles'
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import api from '../../../api'
|
||||
import { Route } from 'react-router-dom'
|
||||
import BundleColumnError from '../../../components/bundle_column_error'
|
||||
import Bundle from './bundle'
|
||||
|
@ -51,6 +52,15 @@ export default class WrappedRoute extends PureComponent {
|
|||
...rest
|
||||
} = this.props
|
||||
|
||||
// : todo :
|
||||
// api().get('/api/v1/accounts/verify_credentials')
|
||||
// .then((res) => {
|
||||
// console.log("res:", res)
|
||||
// })
|
||||
// .catch((err) => {
|
||||
// console.log("err:", err)
|
||||
// })
|
||||
|
||||
if (!publicRoute && !me) {
|
||||
const actualUrl = encodeURIComponent(this.props.computedMatch.url)
|
||||
return <Route path={this.props.path} component={() => {
|
||||
|
|
|
@ -32,7 +32,7 @@ export default class GroupLayout extends ImmutablePureComponent {
|
|||
actions={actions}
|
||||
showBackBtn={showBackBtn}
|
||||
>
|
||||
<div className={[_s.default, _s.width1015PX, _s.pl15, _s.py15].join(' ')}>
|
||||
<div className={[_s.default, _s.width100PC].join(' ')}>
|
||||
|
||||
<GroupHeader group={group} relationships={relationships} />
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import LinkFooter from '../components/link_footer'
|
|||
import WhoToFollowPanel from '../components/panel/who_to_follow_panel'
|
||||
import ProgressPanel from '../components/panel/progress_panel'
|
||||
import TrendsPanel from '../components/panel/trends_panel'
|
||||
import HashtagsPanel from '../components/panel/hashtags_panel'
|
||||
import DefaultLayout from '../layouts/default_layout'
|
||||
import TimelineComposeBlock from '../components/timeline_compose_block'
|
||||
import Divider from '../components/divider'
|
||||
|
@ -51,7 +50,6 @@ class CommunityPage extends PureComponent {
|
|||
<Fragment>
|
||||
<ProgressPanel />
|
||||
<TrendsPanel />
|
||||
<HashtagsPanel />
|
||||
<WhoToFollowPanel />
|
||||
<GroupSidebarPanel />
|
||||
<LinkFooter />
|
||||
|
|
|
@ -92,7 +92,7 @@ class GroupPage extends ImmutablePureComponent {
|
|||
<Fragment>
|
||||
<GroupInfoPanel group={group} />
|
||||
<WhoToFollowPanel />
|
||||
<GroupSidebarPanel slim />
|
||||
<GroupSidebarPanel isSlim />
|
||||
<LinkFooter />
|
||||
</Fragment>
|
||||
)}
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Fragment } from 'react'
|
|||
import { me } from '../initial_state'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { openModal } from '../actions/modal'
|
||||
import { MODAL_GROUP_CREATE } from '../constants'
|
||||
import PageTitle from '../features/ui/util/page_title'
|
||||
import LinkFooter from '../components/link_footer'
|
||||
import GroupsPanel from '../components/panel/groups_panel'
|
||||
|
@ -22,7 +23,7 @@ const mapStateToProps = (state) => ({
|
|||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onOpenGroupCreateModal() {
|
||||
dispatch(openModal('GROUP_CREATE'))
|
||||
dispatch(openModal(MODAL_GROUP_CREATE))
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -81,6 +82,7 @@ class GroupsPage extends PureComponent {
|
|||
showBackBtn
|
||||
title={title}
|
||||
actions={actions}
|
||||
tabs={tabs}
|
||||
layout={(
|
||||
<Fragment>
|
||||
<WhoToFollowPanel />
|
||||
|
@ -88,7 +90,6 @@ class GroupsPage extends PureComponent {
|
|||
<LinkFooter />
|
||||
</Fragment>
|
||||
)}
|
||||
tabs={tabs}
|
||||
>
|
||||
<PageTitle path={title} />
|
||||
{ children }
|
||||
|
|
|
@ -6,7 +6,6 @@ import LinkFooter from '../components/link_footer'
|
|||
import WhoToFollowPanel from '../components/panel/who_to_follow_panel'
|
||||
import ProgressPanel from '../components/panel/progress_panel'
|
||||
import TrendsPanel from '../components/panel/trends_panel'
|
||||
import HashtagsPanel from '../components/panel/hashtags_panel'
|
||||
import DefaultLayout from '../layouts/default_layout'
|
||||
|
||||
const messages = defineMessages({
|
||||
|
@ -53,7 +52,6 @@ class HashtagPage extends PureComponent {
|
|||
<Fragment>
|
||||
<ProgressPanel />
|
||||
<TrendsPanel />
|
||||
<HashtagsPanel />
|
||||
<WhoToFollowPanel />
|
||||
<LinkFooter />
|
||||
</Fragment>
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { Fragment } from 'react'
|
||||
import { openModal } from '../actions/modal'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import IntersectionObserverArticle from '../components/intersection_observer_article'
|
||||
import IntersectionObserverWrapper from '../features/ui/util/intersection_observer_wrapper'
|
||||
import PageTitle from '../features/ui/util/page_title'
|
||||
import GroupsPanel from '../components/panel/groups_panel'
|
||||
import ListsPanel from '../components/panel/lists_panel'
|
||||
|
@ -9,7 +11,6 @@ import WhoToFollowPanel from '../components/panel/who_to_follow_panel'
|
|||
import ProgressPanel from '../components/panel/progress_panel'
|
||||
import UserPanel from '../components/panel/user_panel'
|
||||
import TrendsPanel from '../components/panel/trends_panel'
|
||||
import HashtagsPanel from '../components/panel/hashtags_panel'
|
||||
import DefaultLayout from '../layouts/default_layout'
|
||||
import TimelineComposeBlock from '../components/timeline_compose_block'
|
||||
import Divider from '../components/divider'
|
||||
|
@ -40,6 +41,25 @@ class HomePage extends PureComponent {
|
|||
onOpenHomePageSettingsModal: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
intersectionObserverWrapper = new IntersectionObserverWrapper()
|
||||
|
||||
componentDidMount() {
|
||||
this.attachIntersectionObserver()
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.detachIntersectionObserver()
|
||||
}
|
||||
|
||||
attachIntersectionObserver() {
|
||||
this.intersectionObserverWrapper.connect()
|
||||
}
|
||||
|
||||
detachIntersectionObserver() {
|
||||
this.intersectionObserverWrapper.disconnect()
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const {
|
||||
intl,
|
||||
|
@ -62,10 +82,30 @@ class HomePage extends PureComponent {
|
|||
<UserPanel />
|
||||
<ProgressPanel />
|
||||
<TrendsPanel />
|
||||
<IntersectionObserverArticle
|
||||
id={'home-sidebar-lists-panel'}
|
||||
listLength={7}
|
||||
index={4}
|
||||
intersectionObserverWrapper={this.intersectionObserverWrapper}
|
||||
>
|
||||
<ListsPanel />
|
||||
<HashtagsPanel />
|
||||
</IntersectionObserverArticle>
|
||||
<IntersectionObserverArticle
|
||||
id={'home-sidebar-wtf-panel'}
|
||||
listLength={7}
|
||||
index={5}
|
||||
intersectionObserverWrapper={this.intersectionObserverWrapper}
|
||||
>
|
||||
<WhoToFollowPanel />
|
||||
<GroupsPanel />
|
||||
</IntersectionObserverArticle>
|
||||
<IntersectionObserverArticle
|
||||
id={'home-sidebar-groups-panel'}
|
||||
listLength={7}
|
||||
index={6}
|
||||
intersectionObserverWrapper={this.intersectionObserverWrapper}
|
||||
>
|
||||
<GroupsPanel isLazy />
|
||||
</IntersectionObserverArticle>
|
||||
<LinkFooter />
|
||||
</Fragment>
|
||||
)}
|
||||
|
|
|
@ -3,6 +3,10 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
|||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { openModal } from '../actions/modal'
|
||||
import {
|
||||
MODAL_LIST_EDITOR,
|
||||
// MODAL_LIST_TIMELINE_SETTINGS,
|
||||
} from '../constants'
|
||||
import PageTitle from '../features/ui/util/page_title'
|
||||
import LinkFooter from '../components/link_footer'
|
||||
import DefaultLayout from '../layouts/default_layout'
|
||||
|
@ -18,15 +22,16 @@ const mapStateToProps = (state, props) => ({
|
|||
list: state.getIn(['lists', props.params.id]),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch, { list }) => ({
|
||||
onOpenListEditModal() {
|
||||
dispatch(openModal('LIST_EDIT', {
|
||||
list,
|
||||
}))
|
||||
},
|
||||
onOpenListTimelineSettingsModal() {
|
||||
dispatch(openModal('LIST_TIMELINE_SETTINGS'))
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onOpenListEditModal(list) {
|
||||
if (!list) return
|
||||
const listId = list.get('id')
|
||||
dispatch(openModal(MODAL_LIST_EDITOR, { listId }))
|
||||
},
|
||||
// : todo :
|
||||
// onOpenListTimelineSettingsModal() {
|
||||
// dispatch(openModal(MODAL_LIST_TIMELINE_SETTINGS))
|
||||
// },
|
||||
})
|
||||
|
||||
export default
|
||||
|
@ -39,7 +44,11 @@ class ListPage extends ImmutablePureComponent {
|
|||
list: ImmutablePropTypes.map,
|
||||
children: PropTypes.node.isRequired,
|
||||
onOpenListEditModal: PropTypes.func.isRequired,
|
||||
onOpenListTimelineSettingsModal: PropTypes.func.isRequired,
|
||||
// onOpenListTimelineSettingsModal: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
handleOnOpenListEditModal = () => {
|
||||
this.props.onOpenListEditModal(this.props.list)
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -48,33 +57,33 @@ class ListPage extends ImmutablePureComponent {
|
|||
children,
|
||||
list,
|
||||
onOpenListEditModal,
|
||||
onOpenListTimelineSettingsModal
|
||||
// onOpenListTimelineSettingsModal
|
||||
} = this.props
|
||||
|
||||
const title = !!list ? list.get('title') : ''
|
||||
|
||||
return (
|
||||
<DefaultLayout
|
||||
showBackBtn
|
||||
title={title}
|
||||
actions={[
|
||||
{
|
||||
icon: 'list-edit',
|
||||
onClick: onOpenListEditModal,
|
||||
},
|
||||
{
|
||||
icon: 'ellipsis',
|
||||
onClick: onOpenListTimelineSettingsModal,
|
||||
icon: 'cog',
|
||||
onClick: this.handleOnOpenListEditModal,
|
||||
},
|
||||
// {
|
||||
// icon: 'ellipsis',
|
||||
// onClick: onOpenListTimelineSettingsModal,
|
||||
// },
|
||||
]}
|
||||
layout={(
|
||||
<Fragment>
|
||||
<ListDetailsPanel />
|
||||
<ListDetailsPanel list={list} onEdit={this.handleOnOpenListEditModal} />
|
||||
<TrendsPanel />
|
||||
<WhoToFollowPanel />
|
||||
<LinkFooter />
|
||||
</Fragment>
|
||||
)}
|
||||
showBackBtn
|
||||
>
|
||||
<PageTitle path={[title, intl.formatMessage(messages.list)]} />
|
||||
{ children }
|
||||
|
|
|
@ -93,9 +93,11 @@ class NotificationsPage extends PureComponent {
|
|||
const tabs = filters.map((filter) => ({
|
||||
title: intl.formatMessage(messages[filter]),
|
||||
onClick: () => this.onChangeActiveFilter(filter),
|
||||
active: selectedFilter === filter,
|
||||
active: selectedFilter.toLowerCase() === filter.toLowerCase(),
|
||||
}))
|
||||
|
||||
console.log("selectedFilter, filter: ", tabs, selectedFilter)
|
||||
|
||||
return (
|
||||
<DefaultLayout
|
||||
title={intl.formatMessage(messages.notifications)}
|
||||
|
@ -117,4 +119,4 @@ class NotificationsPage extends PureComponent {
|
|||
</DefaultLayout>
|
||||
)
|
||||
}
|
||||
}
|
||||
}{}
|
|
@ -6,7 +6,6 @@ import WhoToFollowPanel from '../components/panel/who_to_follow_panel'
|
|||
import ProgressPanel from '../components/panel/progress_panel'
|
||||
import UserPanel from '../components/panel/user_panel'
|
||||
import TrendsPanel from '../components/panel/trends_panel'
|
||||
import HashtagsPanel from '../components/panel/hashtags_panel'
|
||||
import DefaultLayout from '../layouts/default_layout'
|
||||
|
||||
export default
|
||||
|
@ -24,7 +23,6 @@ class ShortcutsPage extends PureComponent {
|
|||
<UserPanel />
|
||||
<ProgressPanel />
|
||||
<TrendsPanel />
|
||||
<HashtagsPanel />
|
||||
<WhoToFollowPanel />
|
||||
<GroupSidebarPanel />
|
||||
<LinkFooter />
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Map as ImmutableMap } from 'immutable';
|
||||
import { Map as ImmutableMap } from 'immutable'
|
||||
import {
|
||||
GROUP_CREATE_REQUEST,
|
||||
GROUP_CREATE_FAIL,
|
||||
|
@ -8,8 +8,10 @@ import {
|
|||
GROUP_UPDATE_SUCCESS,
|
||||
GROUP_EDITOR_RESET,
|
||||
GROUP_EDITOR_SETUP,
|
||||
GROUP_EDITOR_VALUE_CHANGE,
|
||||
} from '../actions/group_editor';
|
||||
GROUP_EDITOR_TITLE_CHANGE,
|
||||
GROUP_EDITOR_DESCRIPTION_CHANGE,
|
||||
GROUP_EDITOR_COVER_IMAGE_CHANGE,
|
||||
} from '../actions/group_editor'
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
groupId: null,
|
||||
|
@ -18,40 +20,50 @@ const initialState = ImmutableMap({
|
|||
title: '',
|
||||
description: '',
|
||||
coverImage: null,
|
||||
});
|
||||
})
|
||||
|
||||
export default function groupEditorReducer(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case GROUP_EDITOR_RESET:
|
||||
return initialState;
|
||||
return initialState
|
||||
case GROUP_EDITOR_SETUP:
|
||||
return state.withMutations(map => {
|
||||
map.set('groupId', action.group.get('id'));
|
||||
map.set('title', action.group.get('title'));
|
||||
map.set('description', action.group.get('description'));
|
||||
map.set('isSubmitting', false);
|
||||
});
|
||||
case GROUP_EDITOR_VALUE_CHANGE:
|
||||
map.set('groupId', action.group.get('id'))
|
||||
map.set('title', action.group.get('title'))
|
||||
map.set('description', action.group.get('description'))
|
||||
map.set('isSubmitting', false)
|
||||
})
|
||||
case GROUP_EDITOR_TITLE_CHANGE:
|
||||
return state.withMutations(map => {
|
||||
map.set(action.field, action.value);
|
||||
map.set('isChanged', true);
|
||||
});
|
||||
map.set('title', action.title)
|
||||
map.set('isChanged', true)
|
||||
})
|
||||
case GROUP_EDITOR_DESCRIPTION_CHANGE:
|
||||
return state.withMutations(map => {
|
||||
map.set('description', action.description)
|
||||
map.set('isChanged', true)
|
||||
})
|
||||
case GROUP_EDITOR_COVER_IMAGE_CHANGE:
|
||||
return state.withMutations(map => {
|
||||
map.set('coverImage', action.value)
|
||||
map.set('isChanged', true)
|
||||
})
|
||||
case GROUP_CREATE_REQUEST:
|
||||
case GROUP_UPDATE_REQUEST:
|
||||
return state.withMutations(map => {
|
||||
map.set('isSubmitting', true);
|
||||
map.set('isChanged', false);
|
||||
});
|
||||
map.set('isSubmitting', true)
|
||||
map.set('isChanged', false)
|
||||
})
|
||||
case GROUP_CREATE_FAIL:
|
||||
case GROUP_UPDATE_FAIL:
|
||||
return state.set('isSubmitting', false);
|
||||
return state.set('isSubmitting', false)
|
||||
case GROUP_CREATE_SUCCESS:
|
||||
case GROUP_UPDATE_SUCCESS:
|
||||
return state.withMutations(map => {
|
||||
map.set('isSubmitting', false);
|
||||
map.set('groupId', action.group.id);
|
||||
});
|
||||
map.set('isSubmitting', false)
|
||||
map.set('groupId', action.group.id)
|
||||
})
|
||||
default:
|
||||
return state;
|
||||
return state
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,16 @@
|
|||
:root {
|
||||
--radius: 8px;
|
||||
--radius-small: 8px;
|
||||
--radius-circle: 9999px;
|
||||
|
||||
/* Default Font Sizes */
|
||||
|
||||
--font_size_extra_small: 12px;
|
||||
--font_size_small: 13px;
|
||||
--font_size_normal: 14px;
|
||||
--font_size_medium: 15px;
|
||||
--font_size_large: 16px;
|
||||
--font_size_extra_large: 19px;
|
||||
--font_size_extra_extra_large: 24px;
|
||||
|
||||
--color_brand-dark: #38a16b;
|
||||
--color_brand-light: #36e991;
|
||||
|
@ -9,13 +20,13 @@
|
|||
--color_white: #fff;
|
||||
--color_black: #2d3436;
|
||||
--color_black-opaque: rgba(0, 0, 0, .8);
|
||||
--color_black-opaquer: rgba(0, 0, 0, .4);
|
||||
--color_black-opaquer: rgba(0, 0, 0, .5);
|
||||
--color_gold: #ffd700;
|
||||
--color_red: #de2960;
|
||||
--color_red-dark: #c72c5b;
|
||||
|
||||
/* LIGHT THEME */
|
||||
/* --solid_color_primary: #fff;
|
||||
--solid_color_primary: #fff;
|
||||
--solid_color_primary-opaque:rgba(255, 255, 255,.6);
|
||||
--solid_color_secondary: #e2e8ec;
|
||||
--solid_color_secondary-dark: #d9e0e5;
|
||||
|
@ -26,7 +37,7 @@
|
|||
--text_color_secondary: #4b4f55;
|
||||
--text_color_tertiary: #777;
|
||||
|
||||
--border_color_secondary: #ececed; */
|
||||
--border_color_secondary: #ececed;
|
||||
|
||||
/* MUTED THEME */
|
||||
/* --solid_color_primary: #222;
|
||||
|
@ -43,7 +54,7 @@
|
|||
--border_color_secondary: #424141;*/
|
||||
|
||||
/* BLACK THEME */
|
||||
--solid_color_primary: #13171b;
|
||||
/* --solid_color_primary: #13171b;
|
||||
--solid_color_primary-opaque:rgba(19, 23, 27, .6);
|
||||
--solid_color_secondary: #4f5050;
|
||||
--solid_color_secondary-dark: #424343;
|
||||
|
@ -54,7 +65,7 @@
|
|||
--text_color_secondary: #61686E;
|
||||
--text_color_tertiary: #656565;
|
||||
|
||||
--border_color_secondary: #212020;
|
||||
--border_color_secondary: #212020; */
|
||||
}
|
||||
|
||||
html,
|
||||
|
@ -62,6 +73,7 @@ body {
|
|||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: var(--solid_color_tertiary);
|
||||
}
|
||||
|
||||
body {
|
||||
|
@ -78,7 +90,7 @@ body {
|
|||
.statusContent * {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
font-size: 15px;
|
||||
font-size: var(--font_size_medium);
|
||||
overflow-wrap: break-word;
|
||||
color: var(--text_color_primary);
|
||||
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif;
|
||||
|
@ -102,7 +114,7 @@ body {
|
|||
}
|
||||
|
||||
.statusContent h1 {
|
||||
font-size: 1.5rem;
|
||||
font-size: var(--font_size_extra_large);
|
||||
font-weight: 700;
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
|
@ -119,7 +131,7 @@ body {
|
|||
.dangerousContent * {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
font-size: 14px;
|
||||
font-size: var(--font_size_normal);
|
||||
overflow-wrap: break-word;
|
||||
color: var(--text_color_primary);
|
||||
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif;
|
||||
|
@ -224,8 +236,12 @@ body {
|
|||
|
||||
.resizeNone { resize: none; }
|
||||
|
||||
.circle { border-radius: 9999px; }
|
||||
.radiusSmall { border-radius: var(--radius); }
|
||||
.circle { border-radius: var(--radius-circle); }
|
||||
.radiusSmall { border-radius: var(--radius-small); }
|
||||
.topLeftRadiusSmall { border-top-left-radius: var(--radius-small); }
|
||||
.topRightRadiusSmall { border-top-right-radius: var(--radius-small); }
|
||||
.bottomRightRadiusSmall { border-bottom-right-radius: var(--radius-small); }
|
||||
.bottomLeftRadiusSmall { border-bottom-left-radius: var(--radius-small); }
|
||||
|
||||
.borderColorPrimary { border-color: var(--solid_color_primary); }
|
||||
.borderColorSecondary { border-color: var(--border_color_secondary); }
|
||||
|
@ -509,13 +525,13 @@ body {
|
|||
.textAlignLeft { text-align: left; }
|
||||
.textAlignCenter { text-align: center; }
|
||||
|
||||
.fontSize24PX { font-size: 24px; }
|
||||
.fontSize19PX { font-size: 19px; }
|
||||
.fontSize16PX { font-size: 16px; }
|
||||
.fontSize15PX { font-size: 15px; }
|
||||
.fontSize14PX { font-size: 14px; }
|
||||
.fontSize13PX { font-size: 13px; }
|
||||
.fontSize12PX { font-size: 12px; }
|
||||
.fontSize24PX { font-size: var(--font_size_extra_extra_large); }
|
||||
.fontSize19PX { font-size: var(--font_size_extra_large); }
|
||||
.fontSize16PX { font-size: var(--font_size_large); }
|
||||
.fontSize15PX { font-size: var(--font_size_medium); }
|
||||
.fontSize14PX { font-size: var(--font_size_normal); }
|
||||
.fontSize13PX { font-size: var(--font_size_small); }
|
||||
.fontSize12PX { font-size: var(--font_size_extra_small); }
|
||||
.fontSize0 { font-size: 0; }
|
||||
|
||||
.fontWeightNormal { font-weight: 400; }
|
||||
|
@ -588,6 +604,7 @@ body {
|
|||
.pl0 { padding-left: 0; }
|
||||
|
||||
.pr15 { padding-right: 15px; }
|
||||
.pr5 { padding-right: 5px; }
|
||||
.pr0 { padding-right: 0; }
|
||||
|
||||
.px15 {
|
||||
|
@ -677,7 +694,7 @@ body {
|
|||
.select {
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
font-size: 18px;
|
||||
font-size: var(--font_size_extra_large);
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
|
@ -708,7 +725,7 @@ body {
|
|||
|
||||
/* :global(.public-DraftEditorPlaceholder-inner) {
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
font-size: var(--font_size_large);
|
||||
} */
|
||||
|
||||
:global(.RichEditor-blockquote) {
|
||||
|
@ -722,14 +739,14 @@ body {
|
|||
:global(.public-DraftStyleDefault-pre) {
|
||||
background-color: rgba(0,0,0,.05);
|
||||
font-family: 'Inconsolata', 'Menlo', 'Consolas', monospace;
|
||||
font-size: 16px;
|
||||
font-size: var(--font_size_large);
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
:global(.emoji-mart-search input) {
|
||||
border-radius: 9999px !important;
|
||||
border-radius: var(--radius-circle) !important;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
class REST::GroupSerializer < ActiveModel::Serializer
|
||||
include RoutingHelper
|
||||
|
||||
attributes :id, :title, :description, :cover_image_url, :is_archived, :member_count
|
||||
attributes :id, :title, :description, :cover_image_url, :is_archived, :member_count, :created_at
|
||||
|
||||
def id
|
||||
object.id.to_s
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
= render 'stream_entries/meta', stream_entry: @stream_entry, account: @account
|
||||
- elsif @account && @account.local?
|
||||
= render 'accounts/meta', account: @account, older_url: nil, newer_url: nil
|
||||
- else
|
||||
- description = strip_tags(t('about.about_gabsocial_html'))
|
||||
%meta{ name: 'description', content: description }/
|
||||
|
||||
%title= content_for?(:page_title) ? safe_join([yield(:page_title).chomp.html_safe, title], ' - ') : title
|
||||
|
||||
|
|
Loading…
Reference in New Issue