{ _t("Send a Direct Message") }
diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx
index 03277a84f9..ab5b93794c 100644
--- a/src/components/structures/LoggedInView.tsx
+++ b/src/components/structures/LoggedInView.tsx
@@ -88,6 +88,7 @@ interface IProps {
currentUserId?: string;
currentGroupId?: string;
currentGroupIsNew?: boolean;
+ justRegistered?: boolean;
}
interface IUsageLimit {
@@ -573,7 +574,7 @@ class LoggedInView extends React.Component {
break;
case PageTypes.HomePage:
- pageElement = ;
+ pageElement = ;
break;
case PageTypes.UserView:
diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx
index 3a4b74762e..22cd73eff7 100644
--- a/src/components/structures/MatrixChat.tsx
+++ b/src/components/structures/MatrixChat.tsx
@@ -62,7 +62,7 @@ import DMRoomMap from '../../utils/DMRoomMap';
import ThemeWatcher from "../../settings/watchers/ThemeWatcher";
import { FontWatcher } from '../../settings/watchers/FontWatcher';
import { storeRoomAliasInCache } from '../../RoomAliasCache';
-import { defer, IDeferred } from "../../utils/promise";
+import { defer, IDeferred, sleep } from "../../utils/promise";
import ToastStore from "../../stores/ToastStore";
import * as StorageManager from "../../utils/StorageManager";
import type LoggedInViewType from "./LoggedInView";
@@ -201,6 +201,7 @@ interface IState {
roomOobData?: object;
viaServers?: string[];
pendingInitialSync?: boolean;
+ justRegistered?: boolean;
}
export default class MatrixChat extends React.PureComponent {
@@ -479,6 +480,7 @@ export default class MatrixChat extends React.PureComponent {
}
const newState = {
currentUserId: null,
+ justRegistered: false,
};
Object.assign(newState, state);
this.setState(newState);
@@ -669,7 +671,7 @@ export default class MatrixChat extends React.PureComponent {
this.viewWelcome();
break;
case 'view_home_page':
- this.viewHome();
+ this.viewHome(payload.justRegistered);
break;
case 'view_start_chat_or_reuse':
this.chatCreateOrReuse(payload.user_id);
@@ -953,10 +955,11 @@ export default class MatrixChat extends React.PureComponent {
this.themeWatcher.recheck();
}
- private viewHome() {
+ private viewHome(justRegistered = false) {
// The home page requires the "logged in" view, so we'll set that.
this.setStateForNewView({
view: Views.LOGGED_IN,
+ justRegistered,
});
this.setPage(PageTypes.HomePage);
this.notifyNewScreen('home');
@@ -1190,7 +1193,7 @@ export default class MatrixChat extends React.PureComponent {
if (welcomeUserRoom === null) {
// We didn't redirect to the welcome user room, so show
// the homepage.
- dis.dispatch({action: 'view_home_page'});
+ dis.dispatch({action: 'view_home_page', justRegistered: true});
}
} else if (ThreepidInviteStore.instance.pickBestInvite()) {
// The user has a 3pid invite pending - show them that
@@ -1203,7 +1206,7 @@ export default class MatrixChat extends React.PureComponent {
} else {
// The user has just logged in after registering,
// so show the homepage.
- dis.dispatch({action: 'view_home_page'});
+ dis.dispatch({action: 'view_home_page', justRegistered: true});
}
} else {
this.showScreenAfterLogin();
@@ -1211,6 +1214,8 @@ export default class MatrixChat extends React.PureComponent {
StorageManager.tryPersistStorage();
+ // defer the following actions by 30 seconds to not throw them at the user immediately
+ await sleep(30);
if (SettingsStore.getValue("showCookieBar") &&
(Analytics.canEnable() || CountlyAnalytics.instance.canEnable())
) {
@@ -1343,8 +1348,8 @@ export default class MatrixChat extends React.PureComponent {
this.firstSyncComplete = true;
this.firstSyncPromise.resolve();
- if (Notifier.shouldShowPrompt()) {
- showNotificationsToast();
+ if (Notifier.shouldShowPrompt() && !MatrixClientPeg.userRegisteredWithinLastHours(24)) {
+ showNotificationsToast(false);
}
dis.fire(Action.FocusComposer);
diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx
index 160e9c0ec6..0cb4a5d305 100644
--- a/src/components/structures/RoomView.tsx
+++ b/src/components/structures/RoomView.tsx
@@ -74,6 +74,8 @@ import { IThreepidInvite } from "../../stores/ThreepidInviteStore";
import { CallState, CallType, MatrixCall } from "matrix-js-sdk/lib/webrtc/call";
import WidgetStore from "../../stores/WidgetStore";
import {UPDATE_EVENT} from "../../stores/AsyncStore";
+import Notifier from "../../Notifier";
+import {showToast as showNotificationsToast} from "../../toasts/DesktopNotificationsToast";
const DEBUG = false;
let debuglog = function(msg: string) {};
@@ -1050,6 +1052,11 @@ export default class RoomView extends React.Component {
let joinedOrInvitedMemberCount = room.getJoinedMemberCount() + room.getInvitedMemberCount();
if (countInfluence) joinedOrInvitedMemberCount += countInfluence;
this.setState({isAlone: joinedOrInvitedMemberCount === 1});
+
+ // if they are not alone additionally prompt the user about notifications so they don't miss replies
+ if (joinedOrInvitedMemberCount > 1 && Notifier.shouldShowPrompt()) {
+ showNotificationsToast(true);
+ }
}
private updateDMState() {
diff --git a/src/components/views/rooms/RoomList.tsx b/src/components/views/rooms/RoomList.tsx
index 3a4d27e666..62fd70e1ec 100644
--- a/src/components/views/rooms/RoomList.tsx
+++ b/src/components/views/rooms/RoomList.tsx
@@ -332,6 +332,8 @@ export default class RoomList extends React.PureComponent {
return p;
}, [] as TagID[]);
+ const showSkeleton = tagOrder.every(tag => !this.state.sublists[tag]?.length);
+
for (const orderedTagId of tagOrder) {
const orderedRooms = this.state.sublists[orderedTagId] || [];
const extraTiles = orderedTagId === DefaultTagID.Invite ? this.renderCommunityInvites() : null;
@@ -356,6 +358,7 @@ export default class RoomList extends React.PureComponent {
addRoomContextMenu={aesthetics.addRoomContextMenu}
isMinimized={this.props.isMinimized}
onResize={this.props.onResize}
+ showSkeleton={showSkeleton}
extraBadTilesThatShouldntExist={extraTiles}
/>);
}
@@ -365,13 +368,28 @@ export default class RoomList extends React.PureComponent {
public render() {
let explorePrompt: JSX.Element;
- if (!this.props.isMinimized && RoomListStore.instance.getFirstNameFilterCondition()) {
- explorePrompt =
-
{_t("Can't see what you’re looking for?")}
-
- {_t("Explore all public rooms")}
-
-
;
+ if (!this.props.isMinimized) {
+ if (RoomListStore.instance.getFirstNameFilterCondition()) {
+ explorePrompt =
+
{_t("Can't see what you’re looking for?")}
+
+ {_t("Explore all public rooms")}
+
+
;
+ } else if (Object.values(this.state.sublists).some(list => list.length > 0)) {
+ const unfilteredLists = RoomListStore.instance.unfilteredLists
+ const unfilteredRooms = unfilteredLists[DefaultTagID.Untagged] || [];
+ const unfilteredHistorical = unfilteredLists[DefaultTagID.Archived] || [];
+ // show a prompt to join/create rooms if the user is in 0 rooms and no historical
+ if (unfilteredRooms.length < 1 && unfilteredHistorical < 1) {
+ explorePrompt =
+
{_t("Use the + to make a new room or explore existing ones below")}
+
+ {_t("Explore all public rooms")}
+
+
;
+ }
+ }
}
const sublists = this.renderSublists();
diff --git a/src/components/views/rooms/RoomSublist.tsx b/src/components/views/rooms/RoomSublist.tsx
index d93de47d6b..b5ae3285b9 100644
--- a/src/components/views/rooms/RoomSublist.tsx
+++ b/src/components/views/rooms/RoomSublist.tsx
@@ -71,6 +71,7 @@ interface IProps {
isMinimized: boolean;
tagId: TagID;
onResize: () => void;
+ showSkeleton?: boolean;
// TODO: Don't use this. It's for community invites, and community invites shouldn't be here.
// You should feel bad if you use this.
@@ -877,6 +878,8 @@ export default class RoomSublist extends React.Component {
);
+ } else if (this.props.showSkeleton && this.state.isExpanded) {
+ content = ;
}
return (
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 1fd3ef8442..d03affa83f 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -403,10 +403,10 @@
"Verify all your sessions to ensure your account & messages are safe": "Verify all your sessions to ensure your account & messages are safe",
"Review": "Review",
"Later": "Later",
+ "Don't miss a reply": "Don't miss a reply",
"Notifications": "Notifications",
- "You are not receiving desktop notifications": "You are not receiving desktop notifications",
- "Enable them now": "Enable them now",
- "Close": "Close",
+ "Enable desktop notifications": "Enable desktop notifications",
+ "Enable": "Enable",
"Your homeserver has exceeded its user limit.": "Your homeserver has exceeded its user limit.",
"Your homeserver has exceeded one of its resource limits.": "Your homeserver has exceeded one of its resource limits.",
"Contact your server admin.": "Contact your server admin.",
@@ -424,9 +424,8 @@
"What's new?": "What's new?",
"What's New": "What's New",
"Update": "Update",
- "Restart": "Restart",
- "Upgrade your %(brand)s": "Upgrade your %(brand)s",
- "A new version of %(brand)s is available!": "A new version of %(brand)s is available!",
+ "Update %(brand)s": "Update %(brand)s",
+ "New version of %(brand)s is available": "New version of %(brand)s is available",
"Guest": "Guest",
"There was an error joining the room": "There was an error joining the room",
"Sorry, your homeserver is too old to participate in this room.": "Sorry, your homeserver is too old to participate in this room.",
@@ -689,7 +688,6 @@
"rooms.": "rooms.",
"Manage": "Manage",
"Securely cache encrypted messages locally for them to appear in search results.": "Securely cache encrypted messages locally for them to appear in search results.",
- "Enable": "Enable",
"%(brand)s is missing some components required for securely caching encrypted messages locally. If you'd like to experiment with this feature, build a custom %(brand)s Desktop with search components added.": "%(brand)s is missing some components required for securely caching encrypted messages locally. If you'd like to experiment with this feature, build a custom %(brand)s Desktop with search components added.",
"%(brand)s can't securely cache encrypted messages locally while running in a web browser. Use %(brand)s Desktop for encrypted messages to appear in search results.": "%(brand)s can't securely cache encrypted messages locally while running in a web browser. Use %(brand)s Desktop for encrypted messages to appear in search results.",
"Connecting to integration manager...": "Connecting to integration manager...",
@@ -872,6 +870,7 @@
"Ban list rules - %(roomName)s": "Ban list rules - %(roomName)s",
"Server rules": "Server rules",
"User rules": "User rules",
+ "Close": "Close",
"You have not ignored anyone.": "You have not ignored anyone.",
"You are currently ignoring:": "You are currently ignoring:",
"You are not subscribed to any lists": "You are not subscribed to any lists",
@@ -1132,6 +1131,7 @@
"Custom Tag": "Custom Tag",
"Can't see what you’re looking for?": "Can't see what you’re looking for?",
"Explore all public rooms": "Explore all public rooms",
+ "Use the + to make a new room or explore existing ones below": "Use the + to make a new room or explore existing ones below",
"%(count)s results|other": "%(count)s results",
"%(count)s results|one": "%(count)s result",
"This room": "This room",
@@ -2053,6 +2053,10 @@
"Community %(groupId)s not found": "Community %(groupId)s not found",
"This homeserver does not support communities": "This homeserver does not support communities",
"Failed to load %(groupId)s": "Failed to load %(groupId)s",
+ "Great, that'll help people know it's you": "Great, that'll help people know it's you",
+ "Add a photo so people know it's you.": "Add a photo so people know it's you.",
+ "Welcome %(name)s": "Welcome %(name)s",
+ "Now, lets help you get started": "Now, lets help you get started",
"Welcome to %(appName)s": "Welcome to %(appName)s",
"Liberate your communication": "Liberate your communication",
"Send a Direct Message": "Send a Direct Message",
diff --git a/src/toasts/DesktopNotificationsToast.ts b/src/toasts/DesktopNotificationsToast.ts
index d8aa7647a3..e10a6d46c6 100644
--- a/src/toasts/DesktopNotificationsToast.ts
+++ b/src/toasts/DesktopNotificationsToast.ts
@@ -29,15 +29,15 @@ const onReject = () => {
const TOAST_KEY = "desktopnotifications";
-export const showToast = () => {
+export const showToast = (fromMessageSend: boolean) => {
ToastStore.sharedInstance().addOrReplaceToast({
key: TOAST_KEY,
- title: _t("Notifications"),
+ title: fromMessageSend ? _t("Don't miss a reply") : _t("Notifications"),
props: {
- description: _t("You are not receiving desktop notifications"),
- acceptLabel: _t("Enable them now"),
+ description: _t("Enable desktop notifications"),
+ acceptLabel: _t("Enable"),
onAccept,
- rejectLabel: _t("Close"),
+ rejectLabel: _t("Dismiss"),
onReject,
},
component: GenericToast,
diff --git a/src/toasts/UpdateToast.tsx b/src/toasts/UpdateToast.tsx
index dfd06cf3a0..eb35c41512 100644
--- a/src/toasts/UpdateToast.tsx
+++ b/src/toasts/UpdateToast.tsx
@@ -74,18 +74,18 @@ export const showToast = (version: string, newVersion: string, releaseNotes?: st
};
} else {
onAccept = installUpdate;
- acceptLabel = _t("Restart");
+ acceptLabel = _t("Update");
}
const brand = SdkConfig.get().brand;
ToastStore.sharedInstance().addOrReplaceToast({
key: TOAST_KEY,
- title: _t("Upgrade your %(brand)s", { brand }),
+ title: _t("Update %(brand)s", { brand }),
props: {
- description: _t("A new version of %(brand)s is available!", { brand }),
+ description: _t("New version of %(brand)s is available", { brand }),
acceptLabel,
onAccept,
- rejectLabel: _t("Later"),
+ rejectLabel: _t("Dismiss"),
onReject,
},
component: GenericToast,