From 8a8936725ef34d16180203ce852d85c0748a8c3b Mon Sep 17 00:00:00 2001 From: ThibG Date: Sat, 25 Jan 2020 22:59:00 +0100 Subject: [Glitch] Fix status overflowing in report dialog Port 389e3f6094bfcc4d0338947d29434113320c8142 to glitch-soc Signed-off-by: Thibaut Girka --- app/javascript/flavours/glitch/styles/components/status.scss | 1 + 1 file changed, 1 insertion(+) (limited to 'app/javascript/flavours/glitch') diff --git a/app/javascript/flavours/glitch/styles/components/status.scss b/app/javascript/flavours/glitch/styles/components/status.scss index 00f947cdc..fa26c4706 100644 --- a/app/javascript/flavours/glitch/styles/components/status.scss +++ b/app/javascript/flavours/glitch/styles/components/status.scss @@ -510,6 +510,7 @@ .status-check-box__status { margin: 10px 0 10px 10px; flex: 1; + overflow: hidden; .media-gallery { max-width: 250px; -- cgit From e36d0a98cc10575e67c526ef3cc9eeb431a1af3f Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 26 Jan 2020 20:07:26 +0100 Subject: [Glitch] Add streaming API updates for announcements being modified or deleted Port b9d74d407673a6dbdc87c3310618b22c85358c85 to glitch-soc Signed-off-by: Thibaut Girka --- .../flavours/glitch/actions/announcements.js | 14 +++--- .../flavours/glitch/actions/streaming.js | 10 ++++- .../flavours/glitch/components/animated_number.js | 7 +-- .../getting_started/components/announcements.js | 12 ++--- .../flavours/glitch/reducers/announcements.js | 51 +++++++++++++++++----- 5 files changed, 69 insertions(+), 25 deletions(-) (limited to 'app/javascript/flavours/glitch') diff --git a/app/javascript/flavours/glitch/actions/announcements.js b/app/javascript/flavours/glitch/actions/announcements.js index 930493b6a..a19a4c708 100644 --- a/app/javascript/flavours/glitch/actions/announcements.js +++ b/app/javascript/flavours/glitch/actions/announcements.js @@ -5,6 +5,7 @@ export const ANNOUNCEMENTS_FETCH_REQUEST = 'ANNOUNCEMENTS_FETCH_REQUEST'; export const ANNOUNCEMENTS_FETCH_SUCCESS = 'ANNOUNCEMENTS_FETCH_SUCCESS'; export const ANNOUNCEMENTS_FETCH_FAIL = 'ANNOUNCEMENTS_FETCH_FAIL'; export const ANNOUNCEMENTS_UPDATE = 'ANNOUNCEMENTS_UPDATE'; +export const ANNOUNCEMENTS_DELETE = 'ANNOUNCEMENTS_DELETE'; export const ANNOUNCEMENTS_REACTION_ADD_REQUEST = 'ANNOUNCEMENTS_REACTION_ADD_REQUEST'; export const ANNOUNCEMENTS_REACTION_ADD_SUCCESS = 'ANNOUNCEMENTS_REACTION_ADD_SUCCESS'; @@ -139,8 +140,11 @@ export const updateReaction = reaction => ({ reaction, }); -export function toggleShowAnnouncements() { - return dispatch => { - dispatch({ type: ANNOUNCEMENTS_TOGGLE_SHOW }); - }; -} +export const toggleShowAnnouncements = () => ({ + type: ANNOUNCEMENTS_TOGGLE_SHOW, +}); + +export const deleteAnnouncement = id => ({ + type: ANNOUNCEMENTS_DELETE, + id, +}); diff --git a/app/javascript/flavours/glitch/actions/streaming.js b/app/javascript/flavours/glitch/actions/streaming.js index 8294fbf36..2f82ea805 100644 --- a/app/javascript/flavours/glitch/actions/streaming.js +++ b/app/javascript/flavours/glitch/actions/streaming.js @@ -8,7 +8,12 @@ import { } from './timelines'; import { updateNotifications, expandNotifications } from './notifications'; import { updateConversations } from './conversations'; -import { fetchAnnouncements, updateAnnouncements, updateReaction as updateAnnouncementsReaction } from './announcements'; +import { + fetchAnnouncements, + updateAnnouncements, + updateReaction as updateAnnouncementsReaction, + deleteAnnouncement, +} from './announcements'; import { fetchFilters } from './filters'; import { getLocale } from 'mastodon/locales'; @@ -51,6 +56,9 @@ export function connectTimelineStream (timelineId, path, pollingRefresh = null, case 'announcement.reaction': dispatch(updateAnnouncementsReaction(JSON.parse(data.payload))); break; + case 'announcement.delete': + dispatch(deleteAnnouncement(data.payload)); + break; } }, }; diff --git a/app/javascript/flavours/glitch/components/animated_number.js b/app/javascript/flavours/glitch/components/animated_number.js index 4d14d2924..6f3d30d4e 100644 --- a/app/javascript/flavours/glitch/components/animated_number.js +++ b/app/javascript/flavours/glitch/components/animated_number.js @@ -27,7 +27,8 @@ export default class AnimatedNumber extends React.PureComponent { } const styles = [{ - key: value, + key: `${value}`, + data: value, style: { y: spring(0, { damping: 35, stiffness: 400 }) }, }]; @@ -35,8 +36,8 @@ export default class AnimatedNumber extends React.PureComponent { {items => ( - {items.map(({ key, style }) => ( - 0 ? 'absolute' : 'static', transform: `translateY(${style.y * 100}%)` }}> + {items.map(({ key, data, style }) => ( + 0 ? 'absolute' : 'static', transform: `translateY(${style.y * 100}%)` }}> ))} )} diff --git a/app/javascript/flavours/glitch/features/getting_started/components/announcements.js b/app/javascript/flavours/glitch/features/getting_started/components/announcements.js index 9a7d175c4..489f53f0f 100644 --- a/app/javascript/flavours/glitch/features/getting_started/components/announcements.js +++ b/app/javascript/flavours/glitch/features/getting_started/components/announcements.js @@ -367,11 +367,13 @@ class Announcements extends ImmutablePureComponent { ))} -
- - {index + 1} / {announcements.size} - -
+ {announcements.size > 1 && ( +
+ + {index + 1} / {announcements.size} + +
+ )} ); diff --git a/app/javascript/flavours/glitch/reducers/announcements.js b/app/javascript/flavours/glitch/reducers/announcements.js index 1cfb598fb..3215c1c2d 100644 --- a/app/javascript/flavours/glitch/reducers/announcements.js +++ b/app/javascript/flavours/glitch/reducers/announcements.js @@ -9,6 +9,7 @@ import { ANNOUNCEMENTS_REACTION_REMOVE_REQUEST, ANNOUNCEMENTS_REACTION_REMOVE_FAIL, ANNOUNCEMENTS_TOGGLE_SHOW, + ANNOUNCEMENTS_DELETE, } from '../actions/announcements'; import { Map as ImmutableMap, List as ImmutableList, Set as ImmutableSet, fromJS } from 'immutable'; @@ -22,14 +23,10 @@ const initialState = ImmutableMap({ const updateReaction = (state, id, name, updater) => state.update('items', list => list.map(announcement => { if (announcement.get('id') === id) { return announcement.update('reactions', reactions => { - if (reactions.find(reaction => reaction.get('name') === name)) { - return reactions.map(reaction => { - if (reaction.get('name') === name) { - return updater(reaction); - } - - return reaction; - }); + const idx = reactions.findIndex(reaction => reaction.get('name') === name); + + if (idx > -1) { + return reactions.update(idx, reaction => updater(reaction)); } return reactions.push(updater(fromJS({ name, count: 0 }))); @@ -46,13 +43,33 @@ const addReaction = (state, id, name) => updateReaction(state, id, name, x => x. const removeReaction = (state, id, name) => updateReaction(state, id, name, x => x.set('me', false).update('count', y => y - 1)); const addUnread = (state, items) => { - if (state.get('show')) return state; + if (state.get('show')) { + return state; + } const newIds = ImmutableSet(items.map(x => x.get('id'))); const oldIds = ImmutableSet(state.get('items').map(x => x.get('id'))); + return state.update('unread', unread => unread.union(newIds.subtract(oldIds))); }; +const sortAnnouncements = list => list.sortBy(x => x.get('starts_at') || x.get('published_at')); + +const updateAnnouncement = (state, announcement) => { + const idx = state.get('items').findIndex(x => x.get('id') === announcement.get('id')); + + state = addUnread(state, [announcement]); + + if (idx > -1) { + // Deep merge is used because announcements from the streaming API do not contain + // personalized data about which reactions have been selected by the given user, + // and that is information we want to preserve + return state.update('items', list => sortAnnouncements(list.update(idx, x => x.mergeDeep(announcement)))); + } + + return state.update('items', list => sortAnnouncements(list.unshift(announcement))); +}; + export default function announcementsReducer(state = initialState, action) { switch(action.type) { case ANNOUNCEMENTS_TOGGLE_SHOW: @@ -65,15 +82,17 @@ export default function announcementsReducer(state = initialState, action) { case ANNOUNCEMENTS_FETCH_SUCCESS: return state.withMutations(map => { const items = fromJS(action.announcements); + map.set('unread', ImmutableSet()); - addUnread(map, items); map.set('items', items); map.set('isLoading', false); + + addUnread(map, items); }); case ANNOUNCEMENTS_FETCH_FAIL: return state.set('isLoading', false); case ANNOUNCEMENTS_UPDATE: - return addUnread(state, [fromJS(action.announcement)]).update('items', list => list.unshift(fromJS(action.announcement)).sortBy(announcement => announcement.get('starts_at'))); + return updateAnnouncement(state, fromJS(action.announcement)); case ANNOUNCEMENTS_REACTION_UPDATE: return updateReactionCount(state, action.reaction); case ANNOUNCEMENTS_REACTION_ADD_REQUEST: @@ -82,6 +101,16 @@ export default function announcementsReducer(state = initialState, action) { case ANNOUNCEMENTS_REACTION_REMOVE_REQUEST: case ANNOUNCEMENTS_REACTION_ADD_FAIL: return removeReaction(state, action.id, action.name); + case ANNOUNCEMENTS_DELETE: + return state.update('unread', set => set.delete(action.id)).update('items', list => { + const idx = list.findIndex(x => x.get('id') === action.id); + + if (idx > -1) { + return list.delete(idx); + } + + return list; + }); default: return state; } -- cgit From 187a82207488d293f18f19ba6ecc1402f8af3e3c Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 26 Jan 2020 22:26:50 +0100 Subject: [Glitch] Fix link colors in announcements Port 2f8c3c17ee26dc21ce94959b0ea18984e7bc5560 to glitch-soc Signed-off-by: Thibaut Girka --- app/javascript/flavours/glitch/styles/components/announcements.scss | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'app/javascript/flavours/glitch') diff --git a/app/javascript/flavours/glitch/styles/components/announcements.scss b/app/javascript/flavours/glitch/styles/components/announcements.scss index 00585cb1c..909957bf1 100644 --- a/app/javascript/flavours/glitch/styles/components/announcements.scss +++ b/app/javascript/flavours/glitch/styles/components/announcements.scss @@ -17,7 +17,7 @@ } a { - color: $highlight-text-color; + color: $secondary-text-color; text-decoration: none; &:hover { @@ -33,6 +33,10 @@ } } } + + &.unhandled-link { + color: lighten($ui-highlight-color, 8%); + } } } -- cgit From 41d0869d7f40a51246cf50a34bed8c27fa30df23 Mon Sep 17 00:00:00 2001 From: ThibG Date: Sun, 26 Jan 2020 23:13:48 +0100 Subject: [Glitch] Change last_status_at to be a date, not datetime Port 42d2a915e4aa31533032e37aaa46354cee2386da to glitch-soc Signed-off-by: Thibaut Girka --- .../flavours/glitch/components/relative_timestamp.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'app/javascript/flavours/glitch') diff --git a/app/javascript/flavours/glitch/components/relative_timestamp.js b/app/javascript/flavours/glitch/components/relative_timestamp.js index aa4b73cfe..711181dcd 100644 --- a/app/javascript/flavours/glitch/components/relative_timestamp.js +++ b/app/javascript/flavours/glitch/components/relative_timestamp.js @@ -3,6 +3,7 @@ import { injectIntl, defineMessages } from 'react-intl'; import PropTypes from 'prop-types'; const messages = defineMessages({ + today: { id: 'relative_time.today', defaultMessage: 'today' }, just_now: { id: 'relative_time.just_now', defaultMessage: 'now' }, seconds: { id: 'relative_time.seconds', defaultMessage: '{number}s' }, minutes: { id: 'relative_time.minutes', defaultMessage: '{number}m' }, @@ -65,12 +66,14 @@ const getUnitDelay = units => { } }; -export const timeAgoString = (intl, date, now, year) => { +export const timeAgoString = (intl, date, now, year, timeGiven = true) => { const delta = now - date.getTime(); let relativeTime; - if (delta < 10 * SECOND) { + if (delta < DAY && !timeGiven) { + relativeTime = intl.formatMessage(messages.today); + } else if (delta < 10 * SECOND) { relativeTime = intl.formatMessage(messages.just_now); } else if (delta < 7 * DAY) { if (delta < MINUTE) { @@ -91,12 +94,14 @@ export const timeAgoString = (intl, date, now, year) => { return relativeTime; }; -const timeRemainingString = (intl, date, now) => { +const timeRemainingString = (intl, date, now, timeGiven = true) => { const delta = date.getTime() - now; let relativeTime; - if (delta < 10 * SECOND) { + if (delta < DAY && !timeGiven) { + relativeTime = intl.formatMessage(messages.today); + } else if (delta < 10 * SECOND) { relativeTime = intl.formatMessage(messages.moments_remaining); } else if (delta < MINUTE) { relativeTime = intl.formatMessage(messages.seconds_remaining, { number: Math.floor(delta / SECOND) }); @@ -173,8 +178,9 @@ class RelativeTimestamp extends React.Component { render () { const { timestamp, intl, year, futureDate } = this.props; + const timeGiven = timestamp.includes('T'); const date = new Date(timestamp); - const relativeTime = futureDate ? timeRemainingString(intl, date, this.state.now) : timeAgoString(intl, date, this.state.now, year); + const relativeTime = futureDate ? timeRemainingString(intl, date, this.state.now, timeGiven) : timeAgoString(intl, date, this.state.now, year, timeGiven); return (