diff --git a/src/views/tinode-web.jsx b/src/views/tinode-web.jsx index 1c95690e..643d5680 100644 --- a/src/views/tinode-web.jsx +++ b/src/views/tinode-web.jsx @@ -800,7 +800,18 @@ class TinodeWeb extends React.Component { // Topic for MessagesView selector. let topicName = hash.path[1] || null; if (topicName != this.state.topicSelected) { - if (!Tinode.topicType(topicName)) { + // A syntactically valid topic name is not enough on its own: mobilePanel='topic-view' only + // ever pairs correctly with MessagesView actually being allowed to render, which requires + // !chapterOneActive (i.e. this.tinode.isAuthenticated()) -- see tinode-web.jsx's render(). + // Without this check, opening (or being redirected/deep-linked to) a #/ URL while + // logged out set mobilePanel to 'topic-view' anyway; on mobile that made *both* the + // SidepanelView gate (`mobilePanel=='sidepanel'`) and the MessagesView gate + // (`!chapterOneActive`) false at once, so neither rendered -- a permanently blank white + // screen (app-container empty, no thrown error) that a hash change alone couldn't recover + // from, only a full reload. Reproduced live: logging out, then setting location.hash to a + // real group's `#/` URL. Falling back to the same "invalid topic" branch already used + // for a malformed name reuses a path already proven safe with topicName=null. + if (!Tinode.topicType(topicName) || !this.tinode.isAuthenticated()) { // Clear invalid topic name and hide messages view on mobile. topicName = null; newState.mobilePanel = 'sidepanel';