From a2a254625b7b1a718038b0847e89dd3c20511197 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Tue, 6 Nov 2018 16:03:53 +0100 Subject: [Glitch] Update reset.scss from upstream --- app/javascript/flavours/glitch/styles/reset.scss | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/styles/reset.scss b/app/javascript/flavours/glitch/styles/reset.scss index cc5ba9d7c..e24ba8c1c 100644 --- a/app/javascript/flavours/glitch/styles/reset.scss +++ b/app/javascript/flavours/glitch/styles/reset.scss @@ -53,9 +53,13 @@ table { border-spacing: 0; } +html { + scrollbar-color: lighten($ui-base-color, 4%) transparent; +} + ::-webkit-scrollbar { - width: 8px; - height: 8px; + width: 12px; + height: 12px; } ::-webkit-scrollbar-thumb { -- cgit From bf92e7aaa6cc6902130fcf064ea225d860c4d023 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Tue, 6 Nov 2018 17:44:28 +0100 Subject: [Glitch] Implement adding a user to a list from their profile Port bb5558de627ca9bc26949570025f6193cd7cbd98 to glitch-soc --- app/javascript/flavours/glitch/actions/lists.js | 54 ++++++++++++++++ .../features/account/components/action_bar.js | 3 + .../features/account_timeline/components/header.js | 6 ++ .../containers/header_container.js | 6 ++ .../features/list_adder/components/account.js | 43 +++++++++++++ .../glitch/features/list_adder/components/list.js | 68 ++++++++++++++++++++ .../flavours/glitch/features/list_adder/index.js | 73 ++++++++++++++++++++++ .../glitch/features/ui/components/modal_root.js | 2 + app/javascript/flavours/glitch/reducers/index.js | 2 + .../flavours/glitch/reducers/list_adder.js | 47 ++++++++++++++ .../flavours/glitch/styles/components/lists.scss | 41 ++++++++++++ .../flavours/glitch/util/async-components.js | 4 ++ 12 files changed, 349 insertions(+) create mode 100644 app/javascript/flavours/glitch/features/list_adder/components/account.js create mode 100644 app/javascript/flavours/glitch/features/list_adder/components/list.js create mode 100644 app/javascript/flavours/glitch/features/list_adder/index.js create mode 100644 app/javascript/flavours/glitch/reducers/list_adder.js (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/actions/lists.js b/app/javascript/flavours/glitch/actions/lists.js index 3c3af5fee..3021fa5b5 100644 --- a/app/javascript/flavours/glitch/actions/lists.js +++ b/app/javascript/flavours/glitch/actions/lists.js @@ -40,6 +40,13 @@ export const LIST_EDITOR_REMOVE_REQUEST = 'LIST_EDITOR_REMOVE_REQUEST'; export const LIST_EDITOR_REMOVE_SUCCESS = 'LIST_EDITOR_REMOVE_SUCCESS'; export const LIST_EDITOR_REMOVE_FAIL = 'LIST_EDITOR_REMOVE_FAIL'; +export const LIST_ADDER_RESET = 'LIST_ADDER_RESET'; +export const LIST_ADDER_SETUP = 'LIST_ADDER_SETUP'; + +export const LIST_ADDER_LISTS_FETCH_REQUEST = 'LIST_ADDER_LISTS_FETCH_REQUEST'; +export const LIST_ADDER_LISTS_FETCH_SUCCESS = 'LIST_ADDER_LISTS_FETCH_SUCCESS'; +export const LIST_ADDER_LISTS_FETCH_FAIL = 'LIST_ADDER_LISTS_FETCH_FAIL'; + export const fetchList = id => (dispatch, getState) => { if (getState().getIn(['lists', id])) { return; @@ -311,3 +318,50 @@ export const removeFromListFail = (listId, accountId, error) => ({ accountId, error, }); + +export const resetListAdder = () => ({ + type: LIST_ADDER_RESET, +}); + +export const setupListAdder = accountId => (dispatch, getState) => { + dispatch({ + type: LIST_ADDER_SETUP, + account: getState().getIn(['accounts', accountId]), + }); + dispatch(fetchLists()); + dispatch(fetchAccountLists(accountId)); +}; + +export const fetchAccountLists = accountId => (dispatch, getState) => { + dispatch(fetchAccountListsRequest(accountId)); + + api(getState).get(`/api/v1/accounts/${accountId}/lists`) + .then(({ data }) => dispatch(fetchAccountListsSuccess(accountId, data))) + .catch(err => dispatch(fetchAccountListsFail(accountId, err))); +}; + +export const fetchAccountListsRequest = id => ({ + type:LIST_ADDER_LISTS_FETCH_REQUEST, + id, +}); + +export const fetchAccountListsSuccess = (id, lists) => ({ + type: LIST_ADDER_LISTS_FETCH_SUCCESS, + id, + lists, +}); + +export const fetchAccountListsFail = (id, err) => ({ + type: LIST_ADDER_LISTS_FETCH_FAIL, + id, + err, +}); + +export const addToListAdder = listId => (dispatch, getState) => { + dispatch(addToList(listId, getState().getIn(['listAdder', 'accountId']))); +}; + +export const removeFromListAdder = listId => (dispatch, getState) => { + dispatch(removeFromList(listId, getState().getIn(['listAdder', 'accountId']))); +}; + diff --git a/app/javascript/flavours/glitch/features/account/components/action_bar.js b/app/javascript/flavours/glitch/features/account/components/action_bar.js index 3d6eeb06a..acbe46f8a 100644 --- a/app/javascript/flavours/glitch/features/account/components/action_bar.js +++ b/app/javascript/flavours/glitch/features/account/components/action_bar.js @@ -25,6 +25,7 @@ const messages = defineMessages({ showReblogs: { id: 'account.show_reblogs', defaultMessage: 'Show boosts from @{name}' }, endorse: { id: 'account.endorse', defaultMessage: 'Feature on profile' }, unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' }, + add_or_remove_from_list: { id: 'account.add_or_remove_from_list', defaultMessage: 'Add or Remove from lists' }, admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' }, }); @@ -43,6 +44,7 @@ export default class ActionBar extends React.PureComponent { onBlockDomain: PropTypes.func.isRequired, onUnblockDomain: PropTypes.func.isRequired, onEndorseToggle: PropTypes.func.isRequired, + onAddToList: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, }; @@ -85,6 +87,7 @@ export default class ActionBar extends React.PureComponent { } menu.push({ text: intl.formatMessage(account.getIn(['relationship', 'endorsed']) ? messages.unendorse : messages.endorse), action: this.props.onEndorseToggle }); + menu.push({ text: intl.formatMessage(messages.add_or_remove_from_list), action: this.props.onAddToList }); menu.push(null); } diff --git a/app/javascript/flavours/glitch/features/account_timeline/components/header.js b/app/javascript/flavours/glitch/features/account_timeline/components/header.js index 89b9be92b..8dc0be93e 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/components/header.js +++ b/app/javascript/flavours/glitch/features/account_timeline/components/header.js @@ -23,6 +23,7 @@ export default class Header extends ImmutablePureComponent { onBlockDomain: PropTypes.func.isRequired, onUnblockDomain: PropTypes.func.isRequired, onEndorseToggle: PropTypes.func.isRequired, + onAddToList: PropTypes.func.isRequired, hideTabs: PropTypes.bool, }; @@ -78,6 +79,10 @@ export default class Header extends ImmutablePureComponent { this.props.onEndorseToggle(this.props.account); } + handleAddToList = () => { + this.props.onAddToList(this.props.account); + } + render () { const { account, hideTabs } = this.props; @@ -106,6 +111,7 @@ export default class Header extends ImmutablePureComponent { onBlockDomain={this.handleBlockDomain} onUnblockDomain={this.handleUnblockDomain} onEndorseToggle={this.handleEndorseToggle} + onAddToList={this.handleAddToList} /> {!hideTabs && ( diff --git a/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js b/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js index f5f56d85c..e333c31a1 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js +++ b/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js @@ -120,6 +120,12 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ dispatch(unblockDomain(domain)); }, + onAddToList(account){ + dispatch(openModal('LIST_ADDER', { + accountId: account.get('id'), + })); + }, + }); export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(Header)); diff --git a/app/javascript/flavours/glitch/features/list_adder/components/account.js b/app/javascript/flavours/glitch/features/list_adder/components/account.js new file mode 100644 index 000000000..1369aac07 --- /dev/null +++ b/app/javascript/flavours/glitch/features/list_adder/components/account.js @@ -0,0 +1,43 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import { makeGetAccount } from '../../../selectors'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import Avatar from '../../../components/avatar'; +import DisplayName from '../../../components/display_name'; +import { injectIntl } from 'react-intl'; + +const makeMapStateToProps = () => { + const getAccount = makeGetAccount(); + + const mapStateToProps = (state, { accountId }) => ({ + account: getAccount(state, accountId), + }); + + return mapStateToProps; +}; + + +export default @connect(makeMapStateToProps) +@injectIntl +class Account extends ImmutablePureComponent { + + static propTypes = { + account: ImmutablePropTypes.map.isRequired, + }; + + render () { + const { account } = this.props; + return ( +
+
+
+
+ +
+
+
+ ); + } + +} diff --git a/app/javascript/flavours/glitch/features/list_adder/components/list.js b/app/javascript/flavours/glitch/features/list_adder/components/list.js new file mode 100644 index 000000000..cb8eb7d7a --- /dev/null +++ b/app/javascript/flavours/glitch/features/list_adder/components/list.js @@ -0,0 +1,68 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import IconButton from '../../../components/icon_button'; +import { defineMessages, injectIntl } from 'react-intl'; +import { removeFromListAdder, addToListAdder } from '../../../actions/lists'; + +const messages = defineMessages({ + remove: { id: 'lists.account.remove', defaultMessage: 'Remove from list' }, + add: { id: 'lists.account.add', defaultMessage: 'Add to list' }, +}); + +const MapStateToProps = (state, { listId, added }) => ({ + list: state.get('lists').get(listId), + added: typeof added === 'undefined' ? state.getIn(['listAdder', 'lists', 'items']).includes(listId) : added, +}); + +const mapDispatchToProps = (dispatch, { listId }) => ({ + onRemove: () => dispatch(removeFromListAdder(listId)), + onAdd: () => dispatch(addToListAdder(listId)), +}); + +export default @connect(MapStateToProps, mapDispatchToProps) +@injectIntl +class List extends ImmutablePureComponent { + + static propTypes = { + list: ImmutablePropTypes.map.isRequired, + intl: PropTypes.object.isRequired, + onRemove: PropTypes.func.isRequired, + onAdd: PropTypes.func.isRequired, + added: PropTypes.bool, + }; + + static defaultProps = { + added: false, + }; + + render () { + const { list, intl, onRemove, onAdd, added } = this.props; + + let button; + + if (added) { + button = ; + } else { + button = ; + } + + return ( +
+
+
+ + {list.get('title')} +
+ +
+ {button} +
+
+
+ ); + } + +} diff --git a/app/javascript/flavours/glitch/features/list_adder/index.js b/app/javascript/flavours/glitch/features/list_adder/index.js new file mode 100644 index 000000000..cb8a15e8c --- /dev/null +++ b/app/javascript/flavours/glitch/features/list_adder/index.js @@ -0,0 +1,73 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { connect } from 'react-redux'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { injectIntl } from 'react-intl'; +import { setupListAdder, resetListAdder } from '../../actions/lists'; +import { createSelector } from 'reselect'; +import List from './components/list'; +import Account from './components/account'; +import NewListForm from '../lists/components/new_list_form'; +// hack + +const getOrderedLists = createSelector([state => state.get('lists')], lists => { + if (!lists) { + return lists; + } + + return lists.toList().filter(item => !!item).sort((a, b) => a.get('title').localeCompare(b.get('title'))); +}); + +const mapStateToProps = state => ({ + listIds: getOrderedLists(state).map(list=>list.get('id')), +}); + +const mapDispatchToProps = dispatch => ({ + onInitialize: accountId => dispatch(setupListAdder(accountId)), + onReset: () => dispatch(resetListAdder()), +}); + +export default @connect(mapStateToProps, mapDispatchToProps) +@injectIntl +class ListAdder extends ImmutablePureComponent { + + static propTypes = { + accountId: PropTypes.string.isRequired, + onClose: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + onInitialize: PropTypes.func.isRequired, + onReset: PropTypes.func.isRequired, + listIds: ImmutablePropTypes.list.isRequired, + }; + + componentDidMount () { + const { onInitialize, accountId } = this.props; + onInitialize(accountId); + } + + componentWillUnmount () { + const { onReset } = this.props; + onReset(); + } + + render () { + const { accountId, listIds } = this.props; + + return ( +
+
+ +
+ + + + +
+ {listIds.map(ListId => )} +
+
+ ); + } + +} diff --git a/app/javascript/flavours/glitch/features/ui/components/modal_root.js b/app/javascript/flavours/glitch/features/ui/components/modal_root.js index c9f54804a..303e05db6 100644 --- a/app/javascript/flavours/glitch/features/ui/components/modal_root.js +++ b/app/javascript/flavours/glitch/features/ui/components/modal_root.js @@ -19,6 +19,7 @@ import { SettingsModal, EmbedModal, ListEditor, + ListAdder, PinnedAccountsEditor, } from 'flavours/glitch/util/async-components'; @@ -36,6 +37,7 @@ const MODAL_COMPONENTS = { 'ACTIONS': () => Promise.resolve({ default: ActionsModal }), 'EMBED': EmbedModal, 'LIST_EDITOR': ListEditor, + 'LIST_ADDER':ListAdder, 'FOCAL_POINT': () => Promise.resolve({ default: FocalPointModal }), 'PINNED_ACCOUNTS_EDITOR': PinnedAccountsEditor, }; diff --git a/app/javascript/flavours/glitch/reducers/index.js b/app/javascript/flavours/glitch/reducers/index.js index ae9e2b639..5b1ec4abc 100644 --- a/app/javascript/flavours/glitch/reducers/index.js +++ b/app/javascript/flavours/glitch/reducers/index.js @@ -26,6 +26,7 @@ import height_cache from './height_cache'; import custom_emojis from './custom_emojis'; import lists from './lists'; import listEditor from './list_editor'; +import listAdder from './list_adder'; import filters from './filters'; import pinnedAccountsEditor from './pinned_accounts_editor'; @@ -57,6 +58,7 @@ const reducers = { custom_emojis, lists, listEditor, + listAdder, filters, pinnedAccountsEditor, }; diff --git a/app/javascript/flavours/glitch/reducers/list_adder.js b/app/javascript/flavours/glitch/reducers/list_adder.js new file mode 100644 index 000000000..b8c1b0e26 --- /dev/null +++ b/app/javascript/flavours/glitch/reducers/list_adder.js @@ -0,0 +1,47 @@ +import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; +import { + LIST_ADDER_RESET, + LIST_ADDER_SETUP, + LIST_ADDER_LISTS_FETCH_REQUEST, + LIST_ADDER_LISTS_FETCH_SUCCESS, + LIST_ADDER_LISTS_FETCH_FAIL, + LIST_EDITOR_ADD_SUCCESS, + LIST_EDITOR_REMOVE_SUCCESS, +} from '../actions/lists'; + +const initialState = ImmutableMap({ + accountId: null, + + lists: ImmutableMap({ + items: ImmutableList(), + loaded: false, + isLoading: false, + }), +}); + +export default function listAdderReducer(state = initialState, action) { + switch(action.type) { + case LIST_ADDER_RESET: + return initialState; + case LIST_ADDER_SETUP: + return state.withMutations(map => { + map.set('accountId', action.account.get('id')); + }); + case LIST_ADDER_LISTS_FETCH_REQUEST: + return state.setIn(['lists', 'isLoading'], true); + case LIST_ADDER_LISTS_FETCH_FAIL: + return state.setIn(['lists', 'isLoading'], false); + case LIST_ADDER_LISTS_FETCH_SUCCESS: + return state.update('lists', lists => lists.withMutations(map => { + map.set('isLoading', false); + map.set('loaded', true); + map.set('items', ImmutableList(action.lists.map(item => item.id))); + })); + case LIST_EDITOR_ADD_SUCCESS: + return state.updateIn(['lists', 'items'], list => list.unshift(action.listId)); + case LIST_EDITOR_REMOVE_SUCCESS: + return state.updateIn(['lists', 'items'], list => list.filterNot(item => item === action.listId)); + default: + return state; + } +}; diff --git a/app/javascript/flavours/glitch/styles/components/lists.scss b/app/javascript/flavours/glitch/styles/components/lists.scss index f5837c6c4..d00a1941b 100644 --- a/app/javascript/flavours/glitch/styles/components/lists.scss +++ b/app/javascript/flavours/glitch/styles/components/lists.scss @@ -51,3 +51,44 @@ margin-bottom: 0; } } + +.list-adder { + background: $ui-base-color; + flex-direction: column; + border-radius: 8px; + box-shadow: 2px 4px 15px rgba($base-shadow-color, 0.4); + width: 380px; + overflow: hidden; + + @media screen and (max-width: 420px) { + width: 90%; + } + + &__account { + background: lighten($ui-base-color, 13%); + } + + &__lists { + background: lighten($ui-base-color, 13%); + height: 50vh; + border-radius: 0 0 8px 8px; + overflow-y: auto; + } + + .list { + padding: 10px; + border-bottom: 1px solid lighten($ui-base-color, 8%); + } + + .list__wrapper { + display: flex; + } + + .list__display-name { + flex: 1 1 auto; + overflow: hidden; + text-decoration: none; + font-size: 16px; + padding: 10px; + } +} diff --git a/app/javascript/flavours/glitch/util/async-components.js b/app/javascript/flavours/glitch/util/async-components.js index 557ce317e..e96af845f 100644 --- a/app/javascript/flavours/glitch/util/async-components.js +++ b/app/javascript/flavours/glitch/util/async-components.js @@ -145,3 +145,7 @@ export function EmbedModal () { export function GettingStartedMisc () { return import(/* webpackChunkName: "flavours/glitch/async/getting_started_misc" */'flavours/glitch/features/getting_started_misc'); } + +export function ListAdder () { + return import(/* webpackChunkName: "features/glitch/async/list_adder" */'flavours/glitch/features/list_adder'); +} -- cgit From c6fc3e0c65a0ae78e76ebb5da1a12a23727b72c8 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 9 Nov 2018 15:10:09 +0100 Subject: [Glitch] Fix form validation flash message color and input borders Port ccbdf689e824f93bc9a950bb29a4f1ce58e0f1c9 to glitch-soc --- app/javascript/flavours/glitch/styles/forms.scss | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/styles/forms.scss b/app/javascript/flavours/glitch/styles/forms.scss index 8c4c934ea..46ef85774 100644 --- a/app/javascript/flavours/glitch/styles/forms.scss +++ b/app/javascript/flavours/glitch/styles/forms.scss @@ -330,9 +330,12 @@ code { } input[type=text], + input[type=number], input[type=email], - input[type=password] { - border-bottom-color: $valid-value-color; + input[type=password], + textarea, + select { + border-color: lighten($error-red, 12%); } .error { -- cgit From 44f5f7bab4dcf7cab06ef67a22e66789f8f9075c Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sun, 4 Nov 2018 15:18:46 +0100 Subject: Fix drawer waves being displayed in the list editor --- app/javascript/flavours/glitch/styles/components/drawer.scss | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/styles/components/drawer.scss b/app/javascript/flavours/glitch/styles/components/drawer.scss index 6a9af4490..bf9962add 100644 --- a/app/javascript/flavours/glitch/styles/components/drawer.scss +++ b/app/javascript/flavours/glitch/styles/components/drawer.scss @@ -327,7 +327,7 @@ position: absolute; top: 0; left: 0; - background: lighten($ui-base-color, 13%) url('data:image/svg+xml;utf8,') no-repeat bottom / 100% auto; + background: lighten($ui-base-color, 13%); box-sizing: border-box; padding: 0; display: flex; @@ -340,11 +340,6 @@ &.darker { background: $ui-base-color; } - - > .mastodon { - background: url('~images/elephant_ui_plane.svg') no-repeat left bottom / contain; - flex: 1; - } } .pseudo-drawer { -- cgit From 0e80661e42bc0d0f364bad401cf93adf750542a3 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 9 Nov 2018 15:49:11 +0100 Subject: [Glitch] Don't remove originals of boosted toots from timeline Port 2b51b4094c18c56fe8252d90db2b62ef69913fac to glitch-soc --- app/javascript/flavours/glitch/reducers/timelines.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/reducers/timelines.js b/app/javascript/flavours/glitch/reducers/timelines.js index 19e400b19..844a0580f 100644 --- a/app/javascript/flavours/glitch/reducers/timelines.js +++ b/app/javascript/flavours/glitch/reducers/timelines.js @@ -49,7 +49,7 @@ const expandNormalizedTimeline = (state, timeline, statuses, next, isPartial) => })); }; -const updateTimeline = (state, timeline, status, references) => { +const updateTimeline = (state, timeline, status) => { const top = state.getIn([timeline, 'top']); const ids = state.getIn([timeline, 'items'], ImmutableList()); const includesId = ids.includes(status.get('id')); @@ -64,7 +64,6 @@ const updateTimeline = (state, timeline, status, references) => { return state.update(timeline, initialTimeline, map => map.withMutations(mMap => { if (!top) mMap.set('unread', unread + 1); if (top && ids.size > 40) newIds = newIds.take(20); - if (status.getIn(['reblog', 'id'], null) !== null) newIds = newIds.filterNot(item => references.includes(item)); mMap.set('items', newIds.unshift(status.get('id'))); })); }; @@ -119,7 +118,7 @@ export default function timelines(state = initialState, action) { case TIMELINE_EXPAND_SUCCESS: return expandNormalizedTimeline(state, action.timeline, fromJS(action.statuses), action.next, action.partial); case TIMELINE_UPDATE: - return updateTimeline(state, action.timeline, fromJS(action.status), action.references); + return updateTimeline(state, action.timeline, fromJS(action.status)); case TIMELINE_DELETE: return deleteStatus(state, action.id, action.accountId, action.references, action.reblogOf); case ACCOUNT_BLOCK_SUCCESS: -- cgit From 868cace7975532509c41800c7b6b9a6c7838a6b0 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 9 Nov 2018 17:58:46 +0100 Subject: [Glitch] Remove unused computation of reblog references from updateTimeline --- app/javascript/flavours/glitch/actions/timelines.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/actions/timelines.js b/app/javascript/flavours/glitch/actions/timelines.js index 7f1ff8e3b..46645752d 100644 --- a/app/javascript/flavours/glitch/actions/timelines.js +++ b/app/javascript/flavours/glitch/actions/timelines.js @@ -16,7 +16,6 @@ export const TIMELINE_CONTEXT_UPDATE = 'CONTEXT_UPDATE'; export function updateTimeline(timeline, status) { return (dispatch, getState) => { - const references = status.reblog ? getState().get('statuses').filter((item, itemId) => (itemId === status.reblog.id || item.get('reblog') === status.reblog.id)).map((_, itemId) => itemId) : []; const parents = []; if (status.in_reply_to_id) { @@ -32,7 +31,6 @@ export function updateTimeline(timeline, status) { type: TIMELINE_UPDATE, timeline, status, - references, }); if (parents.length > 0) { -- cgit From 5ebbaffaa308d4e0496f99321bbaeb1205bb8930 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 9 Nov 2018 16:47:50 +0100 Subject: [Glitch] Use local instead of global loading indicator for timelines, account timelines Port dd00cd19d2536ce70442d74d72986721427691a5 to glitch-soc --- .../flavours/glitch/actions/timelines.js | 3 +++ .../flavours/glitch/components/scrollable_list.js | 24 ++++++++++++++++++---- .../flavours/glitch/components/status_list.js | 4 ++-- .../glitch/features/account_timeline/index.js | 3 +++ .../flavours/glitch/styles/components/index.scss | 10 +++++++++ 5 files changed, 38 insertions(+), 6 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/actions/timelines.js b/app/javascript/flavours/glitch/actions/timelines.js index 46645752d..b0c19222c 100644 --- a/app/javascript/flavours/glitch/actions/timelines.js +++ b/app/javascript/flavours/glitch/actions/timelines.js @@ -101,6 +101,7 @@ export function expandTimelineRequest(timeline) { return { type: TIMELINE_EXPAND_REQUEST, timeline, + skipLoading: true, }; }; @@ -111,6 +112,7 @@ export function expandTimelineSuccess(timeline, statuses, next, partial) { statuses, next, partial, + skipLoading: true, }; }; @@ -119,6 +121,7 @@ export function expandTimelineFail(timeline, error) { type: TIMELINE_EXPAND_FAIL, timeline, error, + skipLoading: true, }; }; diff --git a/app/javascript/flavours/glitch/components/scrollable_list.js b/app/javascript/flavours/glitch/components/scrollable_list.js index 3ee710dc9..3a6893b01 100644 --- a/app/javascript/flavours/glitch/components/scrollable_list.js +++ b/app/javascript/flavours/glitch/components/scrollable_list.js @@ -8,6 +8,7 @@ import { throttle } from 'lodash'; import { List as ImmutableList } from 'immutable'; import classNames from 'classnames'; import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from 'flavours/glitch/util/fullscreen'; +import LoadingIndicator from './loading_indicator'; export default class ScrollableList extends PureComponent { @@ -23,6 +24,7 @@ export default class ScrollableList extends PureComponent { trackScroll: PropTypes.bool, shouldUpdateScroll: PropTypes.func, isLoading: PropTypes.bool, + showLoading: PropTypes.bool, hasMore: PropTypes.bool, prepend: PropTypes.node, emptyMessage: PropTypes.node, @@ -131,12 +133,14 @@ export default class ScrollableList extends PureComponent { getFirstChildKey (props) { const { children } = props; - let firstChild = children; + let firstChild = children; + if (children instanceof ImmutableList) { firstChild = children.get(0); } else if (Array.isArray(children)) { firstChild = children[0]; } + return firstChild && firstChild.key; } @@ -144,7 +148,7 @@ export default class ScrollableList extends PureComponent { this.node = c; } - handleLoadMore = (e) => { + handleLoadMore = e => { e.preventDefault(); this.props.onLoadMore(); } @@ -155,14 +159,26 @@ export default class ScrollableList extends PureComponent { } render () { - const { children, scrollKey, trackScroll, shouldUpdateScroll, isLoading, hasMore, prepend, emptyMessage, onLoadMore } = this.props; + const { children, scrollKey, trackScroll, shouldUpdateScroll, showLoading, isLoading, hasMore, prepend, emptyMessage, onLoadMore } = this.props; const { fullscreen } = this.state; const childrenCount = React.Children.count(children); const loadMore = (hasMore && childrenCount > 0 && onLoadMore) ? : null; let scrollableArea = null; - if (isLoading || childrenCount > 0 || !emptyMessage) { + if (showLoading) { + scrollableArea = ( +
+
+ {prepend} +
+ +
+ +
+
+ ); + } else if (isLoading || childrenCount > 0 || !emptyMessage) { scrollableArea = (
diff --git a/app/javascript/flavours/glitch/components/status_list.js b/app/javascript/flavours/glitch/components/status_list.js index aa902db47..d13bd72f6 100644 --- a/app/javascript/flavours/glitch/components/status_list.js +++ b/app/javascript/flavours/glitch/components/status_list.js @@ -24,7 +24,7 @@ export default class StatusList extends ImmutablePureComponent { hasMore: PropTypes.bool, prepend: PropTypes.node, emptyMessage: PropTypes.node, - timelineId: PropTypes.string.isRequired, + timelineId: PropTypes.string, }; static defaultProps = { @@ -121,7 +121,7 @@ export default class StatusList extends ImmutablePureComponent { } return ( - + {scrollableContent} ); diff --git a/app/javascript/flavours/glitch/features/account_timeline/index.js b/app/javascript/flavours/glitch/features/account_timeline/index.js index 2216f9153..6f887a145 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/index.js +++ b/app/javascript/flavours/glitch/features/account_timeline/index.js @@ -11,6 +11,7 @@ import HeaderContainer from './containers/header_container'; import ColumnBackButton from '../../components/column_back_button'; import { List as ImmutableList } from 'immutable'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import { FormattedMessage } from 'react-intl'; const mapStateToProps = (state, { params: { accountId }, withReplies = false }) => { const path = withReplies ? `${accountId}:with_replies` : accountId; @@ -77,12 +78,14 @@ export default class AccountTimeline extends ImmutablePureComponent { } + alwaysPrepend scrollKey='account_timeline' statusIds={statusIds} featuredStatusIds={featuredStatusIds} isLoading={isLoading} hasMore={hasMore} onLoadMore={this.handleLoadMore} + emptyMessage={} /> ); diff --git a/app/javascript/flavours/glitch/styles/components/index.scss b/app/javascript/flavours/glitch/styles/components/index.scss index 7d71f0d1d..b16b13d87 100644 --- a/app/javascript/flavours/glitch/styles/components/index.scss +++ b/app/javascript/flavours/glitch/styles/components/index.scss @@ -597,6 +597,16 @@ @supports(display: grid) { // hack to fix Chrome <57 contain: strict; } + + &--flex { + display: flex; + flex-direction: column; + } + + &__append { + flex: 1 1 auto; + position: relative; + } } .scrollable.fullscreen { -- cgit From c78c80f807e5e57e549496e3a76a0743c5e44ac2 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sat, 10 Nov 2018 18:01:39 +0100 Subject: [Glitch] Fix loading indicator inconsistency Port 3cecf3e5b995f5035b17fd9572c17ba1ede9346b to glitch-soc --- .../flavours/glitch/actions/custom_emojis.js | 3 +++ app/javascript/flavours/glitch/actions/favourites.js | 3 +++ .../flavours/glitch/actions/notifications.js | 16 ++++++++++------ app/javascript/flavours/glitch/actions/timelines.js | 19 ++++++++++--------- .../flavours/glitch/features/notifications/index.js | 1 + 5 files changed, 27 insertions(+), 15 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/actions/custom_emojis.js b/app/javascript/flavours/glitch/actions/custom_emojis.js index 0595a6da7..29ae72edb 100644 --- a/app/javascript/flavours/glitch/actions/custom_emojis.js +++ b/app/javascript/flavours/glitch/actions/custom_emojis.js @@ -19,6 +19,7 @@ export function fetchCustomEmojis() { export function fetchCustomEmojisRequest() { return { type: CUSTOM_EMOJIS_FETCH_REQUEST, + skipLoading: true, }; }; @@ -26,6 +27,7 @@ export function fetchCustomEmojisSuccess(custom_emojis) { return { type: CUSTOM_EMOJIS_FETCH_SUCCESS, custom_emojis, + skipLoading: true, }; }; @@ -33,5 +35,6 @@ export function fetchCustomEmojisFail(error) { return { type: CUSTOM_EMOJIS_FETCH_FAIL, error, + skipLoading: true, }; }; diff --git a/app/javascript/flavours/glitch/actions/favourites.js b/app/javascript/flavours/glitch/actions/favourites.js index 0c0f3af44..28eca8e5f 100644 --- a/app/javascript/flavours/glitch/actions/favourites.js +++ b/app/javascript/flavours/glitch/actions/favourites.js @@ -28,6 +28,7 @@ export function fetchFavouritedStatuses() { export function fetchFavouritedStatusesRequest() { return { type: FAVOURITED_STATUSES_FETCH_REQUEST, + skipLoading: true, }; }; @@ -36,6 +37,7 @@ export function fetchFavouritedStatusesSuccess(statuses, next) { type: FAVOURITED_STATUSES_FETCH_SUCCESS, statuses, next, + skipLoading: true, }; }; @@ -43,6 +45,7 @@ export function fetchFavouritedStatusesFail(error) { return { type: FAVOURITED_STATUSES_FETCH_FAIL, error, + skipLoading: true, }; }; diff --git a/app/javascript/flavours/glitch/actions/notifications.js b/app/javascript/flavours/glitch/actions/notifications.js index fb84cd01e..ddf14f78f 100644 --- a/app/javascript/flavours/glitch/actions/notifications.js +++ b/app/javascript/flavours/glitch/actions/notifications.js @@ -89,6 +89,7 @@ const noOp = () => {}; export function expandNotifications({ maxId } = {}, done = noOp) { return (dispatch, getState) => { const notifications = getState().get('notifications'); + const isLoadingMore = !!maxId; if (notifications.get('isLoading')) { done(); @@ -104,40 +105,43 @@ export function expandNotifications({ maxId } = {}, done = noOp) { params.since_id = notifications.getIn(['items', 0]); } - dispatch(expandNotificationsRequest()); + dispatch(expandNotificationsRequest(isLoadingMore)); api(getState).get('/api/v1/notifications', { params }).then(response => { const next = getLinks(response).refs.find(link => link.rel === 'next'); - dispatch(expandNotificationsSuccess(response.data, next ? next.uri : null)); + dispatch(expandNotificationsSuccess(response.data, next ? next.uri : null, isLoadingMore)); fetchRelatedRelationships(dispatch, response.data); done(); }).catch(error => { - dispatch(expandNotificationsFail(error)); + dispatch(expandNotificationsFail(error, isLoadingMore)); done(); }); }; }; -export function expandNotificationsRequest() { +export function expandNotificationsRequest(isLoadingMore) { return { type: NOTIFICATIONS_EXPAND_REQUEST, + skipLoading: !isLoadingMore, }; }; -export function expandNotificationsSuccess(notifications, next) { +export function expandNotificationsSuccess(notifications, next, isLoadingMore) { return { type: NOTIFICATIONS_EXPAND_SUCCESS, notifications, accounts: notifications.map(item => item.account), statuses: notifications.map(item => item.status).filter(status => !!status), next, + skipLoading: !isLoadingMore, }; }; -export function expandNotificationsFail(error) { +export function expandNotificationsFail(error, isLoadingMore) { return { type: NOTIFICATIONS_EXPAND_FAIL, error, + skipLoading: !isLoadingMore, }; }; diff --git a/app/javascript/flavours/glitch/actions/timelines.js b/app/javascript/flavours/glitch/actions/timelines.js index b0c19222c..27ca66e51 100644 --- a/app/javascript/flavours/glitch/actions/timelines.js +++ b/app/javascript/flavours/glitch/actions/timelines.js @@ -64,6 +64,7 @@ const noOp = () => {}; export function expandTimeline(timelineId, path, params = {}, done = noOp) { return (dispatch, getState) => { const timeline = getState().getIn(['timelines', timelineId], ImmutableMap()); + const isLoadingMore = !!params.max_id; if (timeline.get('isLoading')) { done(); @@ -74,14 +75,14 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) { params.since_id = timeline.getIn(['items', 0]); } - dispatch(expandTimelineRequest(timelineId)); + dispatch(expandTimelineRequest(timelineId, isLoadingMore)); api(getState).get(path, { params }).then(response => { const next = getLinks(response).refs.find(link => link.rel === 'next'); - dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.code === 206)); + dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.code === 206, isLoadingMore)); done(); }).catch(error => { - dispatch(expandTimelineFail(timelineId, error)); + dispatch(expandTimelineFail(timelineId, error, isLoadingMore)); done(); }); }; @@ -97,31 +98,31 @@ export const expandAccountMediaTimeline = (accountId, { maxId } = {}) => expandT export const expandHashtagTimeline = (hashtag, { maxId } = {}, done = noOp) => expandTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`, { max_id: maxId }, done); export const expandListTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done); -export function expandTimelineRequest(timeline) { +export function expandTimelineRequest(timeline, isLoadingMore) { return { type: TIMELINE_EXPAND_REQUEST, timeline, - skipLoading: true, + skipLoading: !isLoadingMore, }; }; -export function expandTimelineSuccess(timeline, statuses, next, partial) { +export function expandTimelineSuccess(timeline, statuses, next, partial, isLoadingMore) { return { type: TIMELINE_EXPAND_SUCCESS, timeline, statuses, next, partial, - skipLoading: true, + skipLoading: !isLoadingMore, }; }; -export function expandTimelineFail(timeline, error) { +export function expandTimelineFail(timeline, error, isLoadingMore) { return { type: TIMELINE_EXPAND_FAIL, timeline, error, - skipLoading: true, + skipLoading: !isLoadingMore, }; }; diff --git a/app/javascript/flavours/glitch/features/notifications/index.js b/app/javascript/flavours/glitch/features/notifications/index.js index 13ed26865..0e73f02d8 100644 --- a/app/javascript/flavours/glitch/features/notifications/index.js +++ b/app/javascript/flavours/glitch/features/notifications/index.js @@ -187,6 +187,7 @@ export default class Notifications extends React.PureComponent { scrollKey={`notifications-${columnId}`} trackScroll={!pinned} isLoading={isLoading} + showLoading={isLoading && notifications.size === 0} hasMore={hasMore} emptyMessage={emptyMessage} onLoadMore={this.handleLoadOlder} -- cgit From 2fe0cb16239ed86016ebea352425862a561b63a2 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Tue, 13 Nov 2018 15:32:29 +0100 Subject: [Glitch] Prepend account header even when status list is empty Partially port 90b64c006998ec3bae365007781c61e8a79eeeef --- app/javascript/flavours/glitch/components/scrollable_list.js | 11 ++++++++--- app/javascript/flavours/glitch/components/status_list.js | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/components/scrollable_list.js b/app/javascript/flavours/glitch/components/scrollable_list.js index 3a6893b01..a05d49829 100644 --- a/app/javascript/flavours/glitch/components/scrollable_list.js +++ b/app/javascript/flavours/glitch/components/scrollable_list.js @@ -27,6 +27,7 @@ export default class ScrollableList extends PureComponent { showLoading: PropTypes.bool, hasMore: PropTypes.bool, prepend: PropTypes.node, + alwaysPrepend: PropTypes.bool, emptyMessage: PropTypes.node, children: PropTypes.node, }; @@ -159,7 +160,7 @@ export default class ScrollableList extends PureComponent { } render () { - const { children, scrollKey, trackScroll, shouldUpdateScroll, showLoading, isLoading, hasMore, prepend, emptyMessage, onLoadMore } = this.props; + const { children, scrollKey, trackScroll, shouldUpdateScroll, showLoading, isLoading, hasMore, prepend, alwaysPrepend, emptyMessage, onLoadMore } = this.props; const { fullscreen } = this.state; const childrenCount = React.Children.count(children); @@ -203,8 +204,12 @@ export default class ScrollableList extends PureComponent { ); } else { scrollableArea = ( -
- {emptyMessage} +
+ {alwaysPrepend && prepend} + +
+ {emptyMessage} +
); } diff --git a/app/javascript/flavours/glitch/components/status_list.js b/app/javascript/flavours/glitch/components/status_list.js index d13bd72f6..68cd608b9 100644 --- a/app/javascript/flavours/glitch/components/status_list.js +++ b/app/javascript/flavours/glitch/components/status_list.js @@ -23,6 +23,7 @@ export default class StatusList extends ImmutablePureComponent { isPartial: PropTypes.bool, hasMore: PropTypes.bool, prepend: PropTypes.node, + alwaysPrepend: PropTypes.bool, emptyMessage: PropTypes.node, timelineId: PropTypes.string, }; -- cgit From 6ce7e74b46d47863f95f1fe3209437e24a4644b7 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Tue, 13 Nov 2018 16:30:07 +0100 Subject: [Glitch] Fix race condition when interacting with deleted toots Port c875f19673e923e7a6e3c2b6656e96b863ca5915 to glitch-soc --- app/javascript/flavours/glitch/reducers/statuses.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/reducers/statuses.js b/app/javascript/flavours/glitch/reducers/statuses.js index 617d96e5d..1beaf73e1 100644 --- a/app/javascript/flavours/glitch/reducers/statuses.js +++ b/app/javascript/flavours/glitch/reducers/statuses.js @@ -118,15 +118,15 @@ export default function statuses(state = initialState, action) { case FAVOURITE_REQUEST: return state.setIn([action.status.get('id'), 'favourited'], true); case FAVOURITE_FAIL: - return state.setIn([action.status.get('id'), 'favourited'], false); + return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'favourited'], false); case BOOKMARK_REQUEST: return state.setIn([action.status.get('id'), 'bookmarked'], true); case BOOKMARK_FAIL: - return state.setIn([action.status.get('id'), 'bookmarked'], false); + return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'bookmarked'], false); case REBLOG_REQUEST: return state.setIn([action.status.get('id'), 'reblogged'], true); case REBLOG_FAIL: - return state.setIn([action.status.get('id'), 'reblogged'], false); + return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'reblogged'], false); case STATUS_MUTE_SUCCESS: return state.setIn([action.id, 'muted'], true); case STATUS_UNMUTE_SUCCESS: -- cgit From 86527024aa392ad6edf5b1d0dc7fe936b7ad4968 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Thu, 15 Nov 2018 15:35:13 +0100 Subject: In detailed status view, take displayMedia setting into account when changing media Fixes #819 --- app/javascript/flavours/glitch/components/media_gallery.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/components/media_gallery.js b/app/javascript/flavours/glitch/components/media_gallery.js index e8dfd6f8e..d637d7c8e 100644 --- a/app/javascript/flavours/glitch/components/media_gallery.js +++ b/app/javascript/flavours/glitch/components/media_gallery.js @@ -232,7 +232,7 @@ export default class MediaGallery extends React.PureComponent { componentWillReceiveProps (nextProps) { if (!is(nextProps.media, this.props.media)) { - this.setState({ visible: !nextProps.sensitive }); + this.setState({ visible: nextProps.revealed === undefined ? (displayMedia !== 'hide_all' && !nextProps.sensitive || displayMedia === 'show_all') : nextProps.revealed }); } } -- cgit From a77ee0bb6dcafffebc55db145ef4bac8038ae2a1 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 16 Nov 2018 11:52:57 +0100 Subject: Fix composer not displaying on iPad --- app/javascript/flavours/glitch/styles/components/drawer.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/styles/components/drawer.scss b/app/javascript/flavours/glitch/styles/components/drawer.scss index bf9962add..a5c9d0130 100644 --- a/app/javascript/flavours/glitch/styles/components/drawer.scss +++ b/app/javascript/flavours/glitch/styles/components/drawer.scss @@ -43,8 +43,7 @@ position: relative; flex-direction: column; padding: 0; - width: 100%; - height: 100%; + flex-grow: 1; background: lighten($ui-base-color, 13%); overflow-x: hidden; overflow-y: auto; -- cgit From b3ff35a75cf04e4aba2712a9d0897257cf79af82 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Tue, 25 Sep 2018 14:46:14 +0200 Subject: Move URLs to backend in their own file --- .../glitch/components/status_action_bar.js | 17 ++++++++++++--- .../features/account/components/action_bar.js | 12 ++++++++--- .../features/composer/direct_warning/index.js | 4 +++- .../glitch/features/composer/warning/index.js | 7 +++++- .../glitch/features/drawer/account/index.js | 25 +++++++++++++--------- .../glitch/features/drawer/header/index.js | 3 ++- .../glitch/features/getting_started/index.js | 5 +++-- .../features/local_settings/navigation/index.js | 3 ++- .../features/status/components/action_bar.js | 17 ++++++++++++--- .../flavours/glitch/util/backend_links.js | 6 ++++++ 10 files changed, 74 insertions(+), 25 deletions(-) create mode 100644 app/javascript/flavours/glitch/util/backend_links.js (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/components/status_action_bar.js b/app/javascript/flavours/glitch/components/status_action_bar.js index f7e741d2d..16abcab4e 100644 --- a/app/javascript/flavours/glitch/components/status_action_bar.js +++ b/app/javascript/flavours/glitch/components/status_action_bar.js @@ -7,6 +7,7 @@ import { defineMessages, injectIntl } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { me, isStaff } from 'flavours/glitch/util/initial_state'; import RelativeTimestamp from './relative_timestamp'; +import { accountAdminLink, statusAdminLink } from 'flavours/glitch/util/backend_links'; const messages = defineMessages({ delete: { id: 'status.delete', defaultMessage: 'Delete' }, @@ -188,10 +189,20 @@ export default class StatusActionBar extends ImmutablePureComponent { menu.push({ text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick }); menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick }); menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport }); - if (isStaff) { + if (isStaff && (accountAdminLink || statusAdminLink)) { menu.push(null); - menu.push({ text: intl.formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), href: `/admin/accounts/${status.getIn(['account', 'id'])}` }); - menu.push({ text: intl.formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses/${status.get('id')}` }); + if (accountAdminLink !== undefined) { + menu.push({ + text: intl.formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), + href: accountAdminLink(status.getIn(['account', 'id'])), + }); + } + if (statusAdminLink !== undefined) { + menu.push({ + text: intl.formatMessage(messages.admin_status), + href: statusAdminLink(status.getIn(['account', 'id']), status.get('id')), + }); + } } } diff --git a/app/javascript/flavours/glitch/features/account/components/action_bar.js b/app/javascript/flavours/glitch/features/account/components/action_bar.js index acbe46f8a..ffa5b7e5e 100644 --- a/app/javascript/flavours/glitch/features/account/components/action_bar.js +++ b/app/javascript/flavours/glitch/features/account/components/action_bar.js @@ -5,6 +5,7 @@ import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_cont import { NavLink } from 'react-router-dom'; import { defineMessages, injectIntl, FormattedMessage, FormattedNumber } from 'react-intl'; import { me, isStaff } from 'flavours/glitch/util/initial_state'; +import { profileLink, accountAdminLink } from 'flavours/glitch/util/backend_links'; const messages = defineMessages({ mention: { id: 'account.mention', defaultMessage: 'Mention @{name}' }, @@ -77,7 +78,9 @@ export default class ActionBar extends React.PureComponent { menu.push(null); if (account.get('id') === me) { - menu.push({ text: intl.formatMessage(messages.edit_profile), href: '/settings/profile' }); + if (profileLink !== undefined) { + menu.push({ text: intl.formatMessage(messages.edit_profile), href: profileLink }); + } } else { if (account.getIn(['relationship', 'following'])) { if (account.getIn(['relationship', 'showing_reblogs'])) { @@ -131,9 +134,12 @@ export default class ActionBar extends React.PureComponent { } } - if (account.get('id') !== me && isStaff) { + if (account.get('id') !== me && isStaff && (accountAdminLink !== undefined)) { menu.push(null); - menu.push({ text: intl.formatMessage(messages.admin_account, { name: account.get('username') }), href: `/admin/accounts/${account.get('id')}` }); + menu.push({ + text: intl.formatMessage(messages.admin_account, { name: account.get('username') }), + href: accountAdminLink(account.get('id')), + }); } return ( diff --git a/app/javascript/flavours/glitch/features/composer/direct_warning/index.js b/app/javascript/flavours/glitch/features/composer/direct_warning/index.js index d1febdd1b..3b1369acd 100644 --- a/app/javascript/flavours/glitch/features/composer/direct_warning/index.js +++ b/app/javascript/flavours/glitch/features/composer/direct_warning/index.js @@ -2,6 +2,7 @@ import React from 'react'; import Motion from 'flavours/glitch/util/optional_motion'; import spring from 'react-motion/lib/spring'; import { defineMessages, FormattedMessage } from 'react-intl'; +import { termsLink} from 'flavours/glitch/util/backend_links'; // This is the spring used with our motion. const motionSpring = spring(1, { damping: 35, stiffness: 400 }); @@ -42,7 +43,8 @@ export default function ComposerDirectWarning () { }} > - + + { termsLink !== undefined && }
)} diff --git a/app/javascript/flavours/glitch/features/composer/warning/index.js b/app/javascript/flavours/glitch/features/composer/warning/index.js index c225b50e8..8be8acbce 100644 --- a/app/javascript/flavours/glitch/features/composer/warning/index.js +++ b/app/javascript/flavours/glitch/features/composer/warning/index.js @@ -2,6 +2,7 @@ import React from 'react'; import Motion from 'flavours/glitch/util/optional_motion'; import spring from 'react-motion/lib/spring'; import { defineMessages, FormattedMessage } from 'react-intl'; +import { profileLink } from 'flavours/glitch/util/backend_links'; // This is the spring used with our motion. const motionSpring = spring(1, { damping: 35, stiffness: 400 }); @@ -20,6 +21,10 @@ const messages = defineMessages({ // The component. export default function ComposerWarning () { + let lockedLink = ; + if (profileLink !== undefined) { + lockedLink = {lockedLink}; + } return ( }} + values={{ locked: lockedLink }} />
)} diff --git a/app/javascript/flavours/glitch/features/drawer/account/index.js b/app/javascript/flavours/glitch/features/drawer/account/index.js index 168d0c2cf..552848641 100644 --- a/app/javascript/flavours/glitch/features/drawer/account/index.js +++ b/app/javascript/flavours/glitch/features/drawer/account/index.js @@ -12,6 +12,7 @@ import Permalink from 'flavours/glitch/components/permalink'; // Utils. import { hiddenComponent } from 'flavours/glitch/util/react_helpers'; +import { profileLink } from 'flavours/glitch/util/backend_links'; // Messages. const messages = defineMessages({ @@ -28,12 +29,14 @@ export default function DrawerAccount ({ account }) { if (!account) { return (
- - - + { profileLink !== undefined && ( + + + + )}
); } @@ -59,10 +62,12 @@ export default function DrawerAccount ({ account }) { > @{account.get('acct')} - + { profileLink !== undefined && ( + + )}
); } diff --git a/app/javascript/flavours/glitch/features/drawer/header/index.js b/app/javascript/flavours/glitch/features/drawer/header/index.js index 7fefd32c9..da5599732 100644 --- a/app/javascript/flavours/glitch/features/drawer/header/index.js +++ b/app/javascript/flavours/glitch/features/drawer/header/index.js @@ -10,6 +10,7 @@ import Icon from 'flavours/glitch/components/icon'; // Utils. import { conditionalRender } from 'flavours/glitch/util/react_helpers'; +import { signOutLink } from 'flavours/glitch/util/backend_links'; // Messages. const messages = defineMessages({ @@ -109,7 +110,7 @@ export default function DrawerHeader ({ diff --git a/app/javascript/flavours/glitch/features/getting_started/index.js b/app/javascript/flavours/glitch/features/getting_started/index.js index ce1ae50e4..c87f76c5e 100644 --- a/app/javascript/flavours/glitch/features/getting_started/index.js +++ b/app/javascript/flavours/glitch/features/getting_started/index.js @@ -13,6 +13,7 @@ import { fetchFollowRequests } from 'flavours/glitch/actions/accounts'; import { List as ImmutableList } from 'immutable'; import { createSelector } from 'reselect'; import { fetchLists } from 'flavours/glitch/actions/lists'; +import { preferencesLink, profileLink, signOutLink } from 'flavours/glitch/util/backend_links'; const messages = defineMessages({ heading: { id: 'getting_started.heading', defaultMessage: 'Getting started' }, @@ -157,9 +158,9 @@ export default class GettingStarted extends ImmutablePureComponent { {listItems} - + { preferencesLink !== undefined && } - +
diff --git a/app/javascript/flavours/glitch/features/local_settings/navigation/index.js b/app/javascript/flavours/glitch/features/local_settings/navigation/index.js index cf02101cf..ce10e3f51 100644 --- a/app/javascript/flavours/glitch/features/local_settings/navigation/index.js +++ b/app/javascript/flavours/glitch/features/local_settings/navigation/index.js @@ -5,6 +5,7 @@ import { injectIntl, defineMessages } from 'react-intl'; // Our imports import LocalSettingsNavigationItem from './item'; +import { preferencesLink } from 'flavours/glitch/util/backend_links'; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -71,7 +72,7 @@ export default class LocalSettingsNavigation extends React.PureComponent { /> `/admin/accounts/${id}`; +export const statusAdminLink = (account_id, status_id) => `/admin/accounts/${account_id}/statuses/${status_id}`; -- cgit From 0d3612482e8b6fb27643dbcefce046897223e890 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Thu, 22 Nov 2018 16:43:41 +0100 Subject: Render placeholder instead of image when MediaGallery container width isn't known --- app/javascript/flavours/glitch/components/media_gallery.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/components/media_gallery.js b/app/javascript/flavours/glitch/components/media_gallery.js index d637d7c8e..10afeb2eb 100644 --- a/app/javascript/flavours/glitch/components/media_gallery.js +++ b/app/javascript/flavours/glitch/components/media_gallery.js @@ -237,7 +237,7 @@ export default class MediaGallery extends React.PureComponent { } componentDidUpdate (prevProps) { - if (this.node && this.node.offsetWidth) { + if (this.node && this.node.offsetWidth && this.node.offsetWidth != this.state.width) { this.setState({ width: this.node.offsetWidth, }); @@ -254,8 +254,7 @@ export default class MediaGallery extends React.PureComponent { handleRef = (node) => { this.node = node; - if (node /*&& this.isStandaloneEligible()*/) { - // offsetWidth triggers a layout, so only calculate when we need to + if (node && node.offsetWidth && node.offsetWidth != this.state.width) { this.setState({ width: node.offsetWidth, }); @@ -276,10 +275,14 @@ export default class MediaGallery extends React.PureComponent { const style = {}; + const computedClass = classNames('media-gallery', { 'full-width': fullwidth }); + if (this.isStandaloneEligible() && width) { style.height = width / this.props.media.getIn([0, 'meta', 'small', 'aspect']); } else if (width) { style.height = width / (16/9); + } else { + return (
); } if (!visible) { @@ -299,8 +302,6 @@ export default class MediaGallery extends React.PureComponent { } } - const computedClass = classNames('media-gallery', { 'full-width': fullwidth }); - return (
{visible ? ( -- cgit From b41d60f2d8ab0759b237e887a8161dbc8ad8c698 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Thu, 22 Nov 2018 16:50:33 +0100 Subject: Render placeholder when inline video container width isn't known --- app/javascript/flavours/glitch/features/video/index.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/features/video/index.js b/app/javascript/flavours/glitch/features/video/index.js index 4f95aea96..4c2e5e62b 100644 --- a/app/javascript/flavours/glitch/features/video/index.js +++ b/app/javascript/flavours/glitch/features/video/index.js @@ -120,7 +120,7 @@ export default class Video extends React.PureComponent { setPlayerRef = c => { this.player = c; - if (c) { + if (c && c.offsetWidth && c.offsetWidth != this.state.containerWidth) { this.setState({ containerWidth: c.offsetWidth, }); @@ -220,7 +220,7 @@ export default class Video extends React.PureComponent { } componentDidUpdate (prevProps) { - if (this.player && this.player.offsetWidth && !this.state.fullscreen) { + if (this.player && this.player.offsetWidth && this.player.offsetWidth != this.state.containerWidth && !this.state.fullscreen) { this.setState({ containerWidth: this.player.offsetWidth, }); @@ -294,6 +294,8 @@ export default class Video extends React.PureComponent { const progress = (currentTime / duration) * 100; const playerStyle = {}; + const computedClass = classNames('video-player', { inactive: !revealed, detailed, inline: inline && !fullscreen, fullscreen, letterbox, 'full-width': fullwidth }); + let { width, height } = this.props; if (inline && containerWidth) { @@ -302,6 +304,8 @@ export default class Video extends React.PureComponent { playerStyle.width = width; playerStyle.height = height; + } else if (inline) { + return (
); } let warning; @@ -322,7 +326,7 @@ export default class Video extends React.PureComponent { return (
Date: Fri, 23 Nov 2018 14:12:15 +0100 Subject: Update MediaGallery and Video props when folding/unfolding CWs in detailed statuses --- .../flavours/glitch/features/status/components/detailed_status.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/javascript/flavours') diff --git a/app/javascript/flavours/glitch/features/status/components/detailed_status.js b/app/javascript/flavours/glitch/features/status/components/detailed_status.js index 1fe0c069d..436c2df0a 100644 --- a/app/javascript/flavours/glitch/features/status/components/detailed_status.js +++ b/app/javascript/flavours/glitch/features/status/components/detailed_status.js @@ -65,6 +65,7 @@ export default class DetailedStatus extends ImmutablePureComponent { sensitive={status.get('sensitive')} letterbox={settings.getIn(['media', 'letterbox'])} fullwidth={settings.getIn(['media', 'fullwidth'])} + preventPlayback={!expanded} onOpenVideo={this.handleOpenVideo} autoplay /> @@ -78,6 +79,7 @@ export default class DetailedStatus extends ImmutablePureComponent { media={status.get('media_attachments')} letterbox={settings.getIn(['media', 'letterbox'])} fullwidth={settings.getIn(['media', 'fullwidth'])} + hidden={!expanded} onOpenMedia={this.props.onOpenMedia} /> ); -- cgit