diff --git a/frontend/iframe/platform/Navigation.ts b/frontend/iframe/platform/Navigation.ts index bb70bc0..80ba12e 100644 --- a/frontend/iframe/platform/Navigation.ts +++ b/frontend/iframe/platform/Navigation.ts @@ -9,6 +9,7 @@ export enum Section { SessionLoading = "loading", Session = "session", Error = "error", + UnknownRoom = "unknown-room", Redirecting = "redirecting", } diff --git a/frontend/iframe/viewmodels/RootViewModel.ts b/frontend/iframe/viewmodels/RootViewModel.ts index 4e61ae3..52488ff 100644 --- a/frontend/iframe/viewmodels/RootViewModel.ts +++ b/frontend/iframe/viewmodels/RootViewModel.ts @@ -4,6 +4,7 @@ import { LogoutViewModel } from "hydrogen-web/src/domain/LogoutViewModel"; import { SegmentType } from "hydrogen-web/src/domain/navigation"; import { SessionLoadViewModel } from "hydrogen-web/src/domain/SessionLoadViewModel"; import { SessionPickerViewModel } from "hydrogen-web/src/domain/SessionPickerViewModel"; +import { UnknownRoomViewModel } from "hydrogen-web/src/domain/session/room/UnknownRoomViewModel"; import { Options as BaseOptions, ViewModel } from "hydrogen-web/src/domain/ViewModel"; import { Client } from "hydrogen-web/src/matrix/Client.js"; import { HomeServerApi } from "hydrogen-web/src/matrix/net/HomeServerApi"; @@ -22,6 +23,7 @@ export class RootViewModel extends ViewModel { private _sessionPickerViewModel: SessionPickerViewModel | undefined; private _sessionLoadViewModel: SessionLoadViewModel | undefined; private _sessionViewModel: SessionViewModel | undefined; + private _unknownRoomViewModel: UnknownRoomViewModel | undefined; private _pendingClient: Client; private readonly _singleRoomIdOrAlias: string | undefined; private _resolvedSingleRoomId: string | undefined; @@ -46,6 +48,8 @@ export class RootViewModel extends ViewModel { return Section.SessionLoading; } else if (this._sessionViewModel) { return Section.Session; + } else if (this._unknownRoomViewModel) { + return Section.UnknownRoom; } else { return Section.Redirecting; } @@ -71,6 +75,10 @@ export class RootViewModel extends ViewModel { return this._sessionLoadViewModel; } + public get unknownRoomViewModel(): UnknownRoomViewModel | undefined { + return this._unknownRoomViewModel; + } + public get sessionViewModel(): SessionViewModel | undefined { return this._sessionViewModel; } @@ -80,7 +88,7 @@ export class RootViewModel extends ViewModel { } public get singleRoomMode(): boolean { - return !!this._resolvedSingleRoomId; + return !!this._singleRoomIdOrAlias; } public async start() { @@ -101,6 +109,17 @@ export class RootViewModel extends ViewModel { const sessionId = this.navigation.path.get("session")?.value; const loginToken = this.navigation.path.get("sso")?.value; + if (this._singleRoomIdOrAlias && !this._resolvedSingleRoomId) { + try { + this._resolvedSingleRoomId = await this.resolveRoomAlias(this._singleRoomIdOrAlias); + } catch (error) { + // Something went wrong when navigating to the room. + // We swallow the error and fallback to non-single-room mode. + console.warn(error); + this._resolvedSingleRoomId = undefined; + } + } + if (isLogin) { if (this.activeSection !== Section.Login) { this._showLogin(undefined); @@ -118,21 +137,7 @@ export class RootViewModel extends ViewModel { void this._showPicker(); } } else if (sessionId) { - if (this._singleRoomIdOrAlias && !this._resolvedSingleRoomId) { - // We're in single-room mode but haven't resolved the room alias yet. - try { - this._resolvedSingleRoomId = await this.resolveRoomAlias(this._singleRoomIdOrAlias, sessionId); - } catch (error) { - // Something went wrong when navigating to the room. - // We swallow the error and fallback to non-single-room mode. - console.warn(error); - this._resolvedSingleRoomId = undefined; - this.emitChange("singleRoomMode"); - } - } - if (this._resolvedSingleRoomId) { - this.emitChange("singleRoomMode"); this.navigation.push("room", this._resolvedSingleRoomId); } @@ -158,9 +163,14 @@ export class RootViewModel extends ViewModel { } } else { try { - if (!(shouldRestoreLastUrl && this.urlRouter.tryRestoreLastUrl())) { + // don't even try to restore last url when in single room mode + if (this.singleRoomMode || !(shouldRestoreLastUrl && this.urlRouter.tryRestoreLastUrl())) { const sessionInfos = await this.platform.sessionInfoStorage.getAll(); if (sessionInfos.length === 0) { + if (this._resolvedSingleRoomId) { + await this._showUnknownRoom(this._resolvedSingleRoomId); + return; + } this.navigation.push(Section.Login); } else if (sessionInfos.length === 1) { this.navigation.push(Section.Session, sessionInfos[0].id); @@ -169,6 +179,7 @@ export class RootViewModel extends ViewModel { } } } catch (err) { + console.error(err); this._setSection(() => this._error = err); } } @@ -204,6 +215,29 @@ export class RootViewModel extends ViewModel { return response.room_id; } + private async isWorldReadableRoom(roomId: string, sessionId: string): Promise { + const sessionInfo = await this.platform.sessionInfoStorage.get(sessionId); + if (!sessionInfo) { + console.error(`Could not find session for id ${sessionId}`); + return false; + } + + const homeserver = await lookupHomeserver(roomId.split(':')[1], this.platform.request); + const homeserverApi = new HomeServerApi({ + homeserver: homeserver, + request: this.platform.request, + accessToken: sessionInfo.accessToken, + reconnector: this.platform.reconnector, + }); + + return homeserverApi.state(roomId, 'm.room.history_visibility', '').response().then( + response => response.history_visibility === 'world_readable' + ).catch(err => { + console.error(err); + return false; + }); + } + private _showLogin(loginToken: string | undefined) { this._setSection(() => { const options = this.childOptions({ @@ -271,6 +305,29 @@ export class RootViewModel extends ViewModel { }); } + private async _showUnknownRoom(roomId: string) { + const client = new Client(this.platform); + let chosenSession; + + let sessionInfos = await this.platform.sessionInfoStorage.getAll(); + if (sessionInfos.length === 0) { + const homeserver = await lookupHomeserver(roomId.split(':')[1], this.platform.request); + await client.doGuestLogin(homeserver); + } else { + await client.startWithExistingSession(chosenSession.id); + } + + this._setSection(() => { + this._unknownRoomViewModel = new UnknownRoomViewModel(this.childOptions({ + roomIdOrAlias: roomId, + session: client.session, + isWorldReadablePromise: this.isWorldReadableRoom(roomId, client.sessionId), + })); + }); + + this.navigation.push("session", client.sessionId); + } + private _setSection(setter: Function) { // Clear all members the activeSection depends on. this._error = undefined; diff --git a/frontend/iframe/views/RootView.ts b/frontend/iframe/views/RootView.ts index 053c539..571cb61 100644 --- a/frontend/iframe/views/RootView.ts +++ b/frontend/iframe/views/RootView.ts @@ -4,6 +4,7 @@ import { TemplateView } from "hydrogen-web/src/platform/web/ui/general/TemplateV import { LoginView } from "hydrogen-web/src/platform/web/ui/login/LoginView"; import { SessionLoadView } from "hydrogen-web/src/platform/web/ui/login/SessionLoadView"; import { SessionPickerView } from "hydrogen-web/src/platform/web/ui/login/SessionPickerView"; +import { UnknownRoomView } from "hydrogen-web/src/platform/web/ui/session/room/UnknownRoomView"; import { LogoutView } from "hydrogen-web/src/platform/web/ui/LogoutView"; import { Section } from "../platform/Navigation"; import { RootViewModel } from "../viewmodels/RootViewModel"; @@ -36,6 +37,8 @@ export class RootView extends TemplateView { return new StaticView(t => t.p("Redirecting...")); case Section.SessionLoading: return new SessionLoadView(vm.sessionLoadViewModel); + case Section.UnknownRoom: + return new UnknownRoomView(vm.unknownRoomViewModel); case Section.Error: return new StaticView(t => { return t.div({ className: "StatusView" }, [ diff --git a/package.json b/package.json index ee30e74..7d400a5 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "dependencies": { "@wordpress/compose": "^5.17.0", "bs58": "^5.0.0", - "hydrogen-web": "Automattic/hydrogen-web#peeking_unknown_rooms", + "hydrogen-web": "Automattic/hydrogen-web#peeking_with_guest_login", "node-html-parser": "^4.0.0" }, "resolutions": { diff --git a/yarn.lock b/yarn.lock index 8b492ad..1a9ea13 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3801,11 +3801,16 @@ core-js-pure@^3.25.1, core-js-pure@^3.8.1: resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.25.3.tgz#66ac5bfa5754b47fdfd14f3841c5ed21c46db608" integrity sha512-T/7qvgv70MEvRkZ8p6BasLZmOVYKzOaWNBEHAU8FmveCJkl4nko2quqPQOmy6AJIp5MBanhz9no3A94NoRb0XA== -core-js@^3.19.1, core-js@^3.6.5: +core-js@^3.19.1: version "3.25.3" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.25.3.tgz#cbc2be50b5ddfa7981837bd8c41639f27b166593" integrity sha512-y1hvKXmPHvm5B7w4ln1S4uc9eV/O5+iFExSRUimnvIph11uaizFR8LFMdONN8hG3P2pipUfX4Y/fR8rAEtcHcQ== +core-js@^3.6.5: + version "3.29.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.29.0.tgz#0273e142b67761058bcde5615c503c7406b572d6" + integrity sha512-VG23vuEisJNkGl6XQmFJd3rEG/so/CNatqeE+7uZAwTSwFeB/qaO0be8xZYUNWprJ/GIwL8aMt9cj1kvbpTZhg== + core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -4243,9 +4248,9 @@ domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: domelementtype "^2.3.0" dompurify@^2.3.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.4.0.tgz#c9c88390f024c2823332615c9e20a453cf3825dd" - integrity sha512-Be9tbQMZds4a3C6xTmz68NlMfeONA//4dOavl/1rNw50E+/QO0KVpbcU0PcaW0nsQxurXls9ZocqFxk8R2mWEA== + version "2.4.5" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.4.5.tgz#0e89a27601f0bad978f9a924e7a05d5d2cccdd87" + integrity sha512-jggCCd+8Iqp4Tsz0nIvpcb22InKEBrGz5dw3EQJMs8HPJDsKbFIO3STYtAvCfDx26Muevn1MHVI0XxjgFfmiSA== domutils@^2.8.0: version "2.8.0" @@ -5715,9 +5720,9 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -hydrogen-web@Automattic/hydrogen-web#peeking_unknown_rooms: +hydrogen-web@Automattic/hydrogen-web#peeking_with_guest_login: version "0.3.8" - resolved "https://codeload.github.com/Automattic/hydrogen-web/tar.gz/07cce3857a163c17ee68aa86b304bd4430de9bfd" + resolved "https://codeload.github.com/Automattic/hydrogen-web/tar.gz/f95684bfd31bee3487a8ba75938d69e60abd6b07" dependencies: "@matrix-org/olm" "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz" another-json "^0.2.0"