From 3380e964497945a5e81012eee3ec65917ac0ade0 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 28 Jul 2019 14:37:52 +0200 Subject: [Glitch] Add autosuggestions for hashtags Port cfb2ed78231758a79af038a964ab7f7b7b35274e to glitch-soc Signed-off-by: Thibaut Girka --- app/javascript/flavours/glitch/reducers/compose.js | 36 ++++++++++++++-------- 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'app/javascript/flavours/glitch/reducers/compose.js') diff --git a/app/javascript/flavours/glitch/reducers/compose.js b/app/javascript/flavours/glitch/reducers/compose.js index 5f176b832..3c769abe3 100644 --- a/app/javascript/flavours/glitch/reducers/compose.js +++ b/app/javascript/flavours/glitch/reducers/compose.js @@ -18,7 +18,6 @@ import { COMPOSE_SUGGESTIONS_CLEAR, COMPOSE_SUGGESTIONS_READY, COMPOSE_SUGGESTION_SELECT, - COMPOSE_SUGGESTION_TAGS_UPDATE, COMPOSE_TAG_HISTORY_UPDATE, COMPOSE_ADVANCED_OPTIONS_CHANGE, COMPOSE_SENSITIVITY_CHANGE, @@ -231,15 +230,20 @@ const insertSuggestion = (state, position, token, completion, path) => { }); }; -const updateSuggestionTags = (state, token) => { - const prefix = token.slice(1); +const sortHashtagsByUse = (state, tags) => { + const personalHistory = state.get('tagHistory'); - return state.merge({ - suggestions: state.get('tagHistory') - .filter(tag => tag.toLowerCase().startsWith(prefix.toLowerCase())) - .slice(0, 4) - .map(tag => '#' + tag), - suggestion_token: token, + return tags.sort((a, b) => { + const usedA = personalHistory.includes(a.name); + const usedB = personalHistory.includes(b.name); + + if (usedA === usedB) { + return 0; + } else if (usedA && !usedB) { + return 1; + } else { + return -1; + } }); }; @@ -282,6 +286,16 @@ const expiresInFromExpiresAt = expires_at => { return [300, 1800, 3600, 21600, 86400, 259200, 604800].find(expires_in => expires_in >= delta) || 24 * 3600; }; +const normalizeSuggestions = (state, { accounts, emojis, tags }) => { + if (accounts) { + return accounts.map(item => item.id); + } else if (emojis) { + return emojis; + } else { + return sortHashtagsByUse(state, tags); + } +}; + export default function compose(state = initialState, action) { switch(action.type) { case STORE_HYDRATE: @@ -412,11 +426,9 @@ export default function compose(state = initialState, action) { case COMPOSE_SUGGESTIONS_CLEAR: return state.update('suggestions', ImmutableList(), list => list.clear()).set('suggestion_token', null); case COMPOSE_SUGGESTIONS_READY: - return state.set('suggestions', ImmutableList(action.accounts ? action.accounts.map(item => item.id) : action.emojis)).set('suggestion_token', action.token); + return state.set('suggestions', ImmutableList(normalizeSuggestions(state, action))).set('suggestion_token', action.token); case COMPOSE_SUGGESTION_SELECT: return insertSuggestion(state, action.position, action.token, action.completion, action.path); - case COMPOSE_SUGGESTION_TAGS_UPDATE: - return updateSuggestionTags(state, action.token); case COMPOSE_TAG_HISTORY_UPDATE: return state.set('tagHistory', fromJS(action.tags)); case TIMELINE_DELETE: -- cgit From 3c70fb91463ead824b80e94489688e125544c412 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 29 Jul 2019 15:04:49 +0200 Subject: [Glitch] Fix emoji autosuggestions Port 784c88e16d8e0f75c0d27e34f926569607e02044 to glitch-soc Signed-off-by: Thibaut Girka --- app/javascript/flavours/glitch/actions/compose.js | 8 ++++---- app/javascript/flavours/glitch/components/autosuggest_input.js | 10 +++++----- .../flavours/glitch/components/autosuggest_textarea.js | 10 +++++----- app/javascript/flavours/glitch/reducers/compose.js | 6 +++--- 4 files changed, 17 insertions(+), 17 deletions(-) (limited to 'app/javascript/flavours/glitch/reducers/compose.js') diff --git a/app/javascript/flavours/glitch/actions/compose.js b/app/javascript/flavours/glitch/actions/compose.js index 134b69855..16b0e7ad2 100644 --- a/app/javascript/flavours/glitch/actions/compose.js +++ b/app/javascript/flavours/glitch/actions/compose.js @@ -444,13 +444,13 @@ export const readyComposeSuggestionsTags = (token, tags) => ({ export function selectComposeSuggestion(position, token, suggestion, path) { return (dispatch, getState) => { let completion; - if (typeof suggestion === 'object' && suggestion.id) { + if (suggestion.type === 'emoji') { dispatch(useEmoji(suggestion)); completion = suggestion.native || suggestion.colons; - } else if (typeof suggestion === 'object' && suggestion.name) { + } else if (suggestion.type === 'hashtag') { completion = `#${suggestion.name}`; - } else { - completion = '@' + getState().getIn(['accounts', suggestion, 'acct']); + } else if (suggestion.type === 'account') { + completion = '@' + getState().getIn(['accounts', suggestion.id, 'acct']); } dispatch({ diff --git a/app/javascript/flavours/glitch/components/autosuggest_input.js b/app/javascript/flavours/glitch/components/autosuggest_input.js index f931069a9..1ef7ee216 100644 --- a/app/javascript/flavours/glitch/components/autosuggest_input.js +++ b/app/javascript/flavours/glitch/components/autosuggest_input.js @@ -168,15 +168,15 @@ export default class AutosuggestInput extends ImmutablePureComponent { const { selectedSuggestion } = this.state; let inner, key; - if (typeof suggestion === 'object' && suggestion.shortcode) { + if (suggestion.type === 'emoji') { inner = ; key = suggestion.id; - } else if (typeof suggestion === 'object' && suggestion.name) { + } else if (suggestion.type ==='hashtag') { inner = ; key = suggestion.name; - } else { - inner = ; - key = suggestion; + } else if (suggestion.type === 'account') { + inner = ; + key = suggestion.id; } return ( diff --git a/app/javascript/flavours/glitch/components/autosuggest_textarea.js b/app/javascript/flavours/glitch/components/autosuggest_textarea.js index c057f4a5b..ec2fbbe4b 100644 --- a/app/javascript/flavours/glitch/components/autosuggest_textarea.js +++ b/app/javascript/flavours/glitch/components/autosuggest_textarea.js @@ -174,15 +174,15 @@ export default class AutosuggestTextarea extends ImmutablePureComponent { const { selectedSuggestion } = this.state; let inner, key; - if (typeof suggestion === 'object' && suggestion.shortcode) { + if (suggestion.type === 'emoji') { inner = ; key = suggestion.id; - } else if (typeof suggestion === 'object' && suggestion.name) { + } else if (suggestion.type === 'hashtag') { inner = ; key = suggestion.name; - } else { - inner = ; - key = suggestion; + } else if (suggestion.type === 'account') { + inner = ; + key = suggestion.id; } return ( diff --git a/app/javascript/flavours/glitch/reducers/compose.js b/app/javascript/flavours/glitch/reducers/compose.js index 3c769abe3..ee2905c9b 100644 --- a/app/javascript/flavours/glitch/reducers/compose.js +++ b/app/javascript/flavours/glitch/reducers/compose.js @@ -288,11 +288,11 @@ const expiresInFromExpiresAt = expires_at => { const normalizeSuggestions = (state, { accounts, emojis, tags }) => { if (accounts) { - return accounts.map(item => item.id); + return accounts.map(item => ({ id: item.id, type: 'account' })); } else if (emojis) { - return emojis; + return emojis.map(item => ({ ...item, type: 'emoji' })); } else { - return sortHashtagsByUse(state, tags); + return sortHashtagsByUse(state, tags.map(item => ({ ...item, type: 'hashtag' }))); } }; -- cgit From 12c188f5339d75616a88bf779c1f31d0076a9e24 Mon Sep 17 00:00:00 2001 From: ThibG Date: Thu, 22 Aug 2019 04:37:18 +0200 Subject: [Glitch] Restore hashtag suggestions from local tag history Port 5ab1e0e738183a0ddcec140d55184351f751b22d to glitch-soc Signed-off-by: Thibaut Girka --- app/javascript/flavours/glitch/actions/compose.js | 2 ++ .../glitch/components/autosuggest_hashtag.js | 6 ++--- app/javascript/flavours/glitch/reducers/compose.js | 27 ++++++++++++++++++++-- 3 files changed, 30 insertions(+), 5 deletions(-) (limited to 'app/javascript/flavours/glitch/reducers/compose.js') diff --git a/app/javascript/flavours/glitch/actions/compose.js b/app/javascript/flavours/glitch/actions/compose.js index 16b0e7ad2..e1da03745 100644 --- a/app/javascript/flavours/glitch/actions/compose.js +++ b/app/javascript/flavours/glitch/actions/compose.js @@ -383,6 +383,8 @@ const fetchComposeSuggestionsTags = throttle((dispatch, getState, token) => { cancelFetchComposeSuggestionsTags(); } + dispatch(updateSuggestionTags(token)); + api(getState).get('/api/v2/search', { cancelToken: new CancelToken(cancel => { cancelFetchComposeSuggestionsTags = cancel; diff --git a/app/javascript/flavours/glitch/components/autosuggest_hashtag.js b/app/javascript/flavours/glitch/components/autosuggest_hashtag.js index 93dd70383..648987dfd 100644 --- a/app/javascript/flavours/glitch/components/autosuggest_hashtag.js +++ b/app/javascript/flavours/glitch/components/autosuggest_hashtag.js @@ -9,18 +9,18 @@ export default class AutosuggestHashtag extends React.PureComponent { tag: PropTypes.shape({ name: PropTypes.string.isRequired, url: PropTypes.string, - history: PropTypes.array.isRequired, + history: PropTypes.array, }).isRequired, }; render () { const { tag } = this.props; - const weeklyUses = shortNumberFormat(tag.history.reduce((total, day) => total + (day.uses * 1), 0)); + const weeklyUses = tag.history && shortNumberFormat(tag.history.reduce((total, day) => total + (day.uses * 1), 0)); return (
#{tag.name}
-
+ {tag.history !== undefined &&
}
); } diff --git a/app/javascript/flavours/glitch/reducers/compose.js b/app/javascript/flavours/glitch/reducers/compose.js index ee2905c9b..adad205c0 100644 --- a/app/javascript/flavours/glitch/reducers/compose.js +++ b/app/javascript/flavours/glitch/reducers/compose.js @@ -18,6 +18,7 @@ import { COMPOSE_SUGGESTIONS_CLEAR, COMPOSE_SUGGESTIONS_READY, COMPOSE_SUGGESTION_SELECT, + COMPOSE_SUGGESTION_TAGS_UPDATE, COMPOSE_TAG_HISTORY_UPDATE, COMPOSE_ADVANCED_OPTIONS_CHANGE, COMPOSE_SENSITIVITY_CHANGE, @@ -286,16 +287,36 @@ const expiresInFromExpiresAt = expires_at => { return [300, 1800, 3600, 21600, 86400, 259200, 604800].find(expires_in => expires_in >= delta) || 24 * 3600; }; -const normalizeSuggestions = (state, { accounts, emojis, tags }) => { +const mergeLocalHashtagResults = (suggestions, prefix, tagHistory) => { + prefix = prefix.toLowerCase(); + if (suggestions.length < 4) { + const localTags = tagHistory.filter(tag => tag.toLowerCase().startsWith(prefix) && !suggestions.some(suggestion => suggestion.type === 'hashtag' && suggestion.name.toLowerCase() === tag.toLowerCase())); + return suggestions.concat(localTags.slice(0, 4 - suggestions.length).toJS().map(tag => ({ type: 'hashtag', name: tag }))); + } else { + return suggestions; + } +}; + +const normalizeSuggestions = (state, { accounts, emojis, tags, token }) => { if (accounts) { return accounts.map(item => ({ id: item.id, type: 'account' })); } else if (emojis) { return emojis.map(item => ({ ...item, type: 'emoji' })); } else { - return sortHashtagsByUse(state, tags.map(item => ({ ...item, type: 'hashtag' }))); + return mergeLocalHashtagResults(sortHashtagsByUse(state, tags.map(item => ({ ...item, type: 'hashtag' }))), token.slice(1), state.get('tagHistory')); } }; +const updateSuggestionTags = (state, token) => { + const prefix = token.slice(1); + + const suggestions = state.get('suggestions').toJS(); + return state.merge({ + suggestions: ImmutableList(mergeLocalHashtagResults(suggestions, prefix, state.get('tagHistory'))), + suggestion_token: token, + }); +}; + export default function compose(state = initialState, action) { switch(action.type) { case STORE_HYDRATE: @@ -429,6 +450,8 @@ export default function compose(state = initialState, action) { return state.set('suggestions', ImmutableList(normalizeSuggestions(state, action))).set('suggestion_token', action.token); case COMPOSE_SUGGESTION_SELECT: return insertSuggestion(state, action.position, action.token, action.completion, action.path); + case COMPOSE_SUGGESTION_TAGS_UPDATE: + return updateSuggestionTags(state, action.token); case COMPOSE_TAG_HISTORY_UPDATE: return state.set('tagHistory', fromJS(action.tags)); case TIMELINE_DELETE: -- cgit