A app/javascript/flavours/glitch/features/home_timeline/components/critical_update_banner.tsx => app/javascript/flavours/glitch/features/home_timeline/components/critical_update_banner.tsx +26 -0
@@ 0,0 1,26 @@
+import { FormattedMessage } from 'react-intl';
+
+export const CriticalUpdateBanner = () => (
+ <div className='warning-banner'>
+ <div className='warning-banner__message'>
+ <h1>
+ <FormattedMessage
+ id='home.pending_critical_update.title'
+ defaultMessage='Critical security update available!'
+ />
+ </h1>
+ <p>
+ <FormattedMessage
+ id='home.pending_critical_update.body'
+ defaultMessage='Please update your Mastodon server as soon as possible!'
+ />{' '}
+ <a href='/admin/software_updates'>
+ <FormattedMessage
+ id='home.pending_critical_update.link'
+ defaultMessage='See updates'
+ />
+ </a>
+ </p>
+ </div>
+ </div>
+);
M app/javascript/flavours/glitch/features/home_timeline/index.jsx => app/javascript/flavours/glitch/features/home_timeline/index.jsx +10 -4
@@ 14,7 14,7 @@ import { fetchAnnouncements, toggleShowAnnouncements } from 'flavours/glitch/act
import { IconWithBadge } from 'flavours/glitch/components/icon_with_badge';
import { NotSignedInIndicator } from 'flavours/glitch/components/not_signed_in_indicator';
import AnnouncementsContainer from 'flavours/glitch/features/getting_started/containers/announcements_container';
-import { me } from 'flavours/glitch/initial_state';
+import { me, criticalUpdatesPending } from 'flavours/glitch/initial_state';
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
import { expandHomeTimeline } from '../../actions/timelines';
@@ 23,6 23,7 @@ import ColumnHeader from '../../components/column_header';
import StatusListContainer from '../ui/containers/status_list_container';
import { ColumnSettings } from './components/column_settings';
+import { CriticalUpdateBanner } from './components/critical_update_banner';
import { ExplorePrompt } from './components/explore_prompt';
const messages = defineMessages({
@@ 158,8 159,9 @@ class HomeTimeline extends PureComponent {
const { intl, hasUnread, columnId, multiColumn, tooSlow, hasAnnouncements, unreadAnnouncements, showAnnouncements } = this.props;
const pinned = !!columnId;
const { signedIn } = this.context.identity;
+ const banners = [];
- let announcementsButton, banner;
+ let announcementsButton;
if (hasAnnouncements) {
announcementsButton = (
@@ 174,8 176,12 @@ class HomeTimeline extends PureComponent {
);
}
+ if (criticalUpdatesPending) {
+ banners.push(<CriticalUpdateBanner key='critical-update-banner' />);
+ }
+
if (tooSlow) {
- banner = <ExplorePrompt />;
+ banners.push(<ExplorePrompt key='explore-prompt' />);
}
return (
@@ 197,7 203,7 @@ class HomeTimeline extends PureComponent {
{signedIn ? (
<StatusListContainer
- prepend={banner}
+ prepend={banners}
alwaysPrepend
trackScroll={!pinned}
scrollKey={`home_timeline-${columnId}`}
M app/javascript/flavours/glitch/initial_state.js => app/javascript/flavours/glitch/initial_state.js +2 -0
@@ 100,6 100,7 @@ export const hasMultiColumnPath = initialPath === '/'
* @typedef InitialState
* @property {Record<string, Account>} accounts
* @property {InitialStateLanguage[]} languages
+ * @property {boolean=} critical_updates_pending
* @property {InitialStateMeta} meta
* @property {object} local_settings
* @property {number} max_toot_chars
@@ 160,6 161,7 @@ export const useBlurhash = getMeta('use_blurhash');
export const usePendingItems = getMeta('use_pending_items');
export const version = getMeta('version');
export const languages = initialState?.languages;
+export const criticalUpdatesPending = initialState?.critical_updates_pending;
export const statusPageUrl = getMeta('status_page_url');
export const sso_redirect = getMeta('sso_redirect');
M app/javascript/flavours/glitch/styles/admin.scss => app/javascript/flavours/glitch/styles/admin.scss +5 -0
@@ 143,6 143,11 @@ $content-width: 840px;
}
}
+ .warning a {
+ color: $gold-star;
+ font-weight: 700;
+ }
+
.simple-navigation-active-leaf a {
color: $primary-text-color;
background-color: $ui-highlight-color;
M app/javascript/flavours/glitch/styles/components/columns.scss => app/javascript/flavours/glitch/styles/components/columns.scss +17 -1
@@ 977,7 977,8 @@ $ui-header-height: 55px;
}
}
-.dismissable-banner {
+.dismissable-banner,
+.warning-banner {
position: relative;
margin: 10px;
margin-bottom: 5px;
@@ 1055,6 1056,21 @@ $ui-header-height: 55px;
}
}
+.warning-banner {
+ border: 1px solid $warning-red;
+ background: rgba($warning-red, 0.15);
+
+ &__message {
+ h1 {
+ color: $warning-red;
+ }
+
+ a {
+ color: $primary-text-color;
+ }
+ }
+}
+
.hashtag-header {
border-bottom: 1px solid lighten($ui-base-color, 8%);
padding: 15px;
M app/javascript/flavours/glitch/styles/tables.scss => app/javascript/flavours/glitch/styles/tables.scss +5 -0
@@ 12,6 12,11 @@
border-top: 1px solid $ui-base-color;
text-align: start;
background: darken($ui-base-color, 4%);
+
+ &.critical {
+ font-weight: 700;
+ color: $gold-star;
+ }
}
& > thead > tr > th {