diff --git a/package-lock.json b/package-lock.json index 672eabb..79105a3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,9 +21,9 @@ "@opentelemetry/semantic-conventions": "^1.3.1", "dompurify": "^2.3.9", "express": "^4.17.2", - "hydrogen-view-sdk": "npm:@mlm/hydrogen-view-sdk@^0.19.0-scratch", + "hydrogen-view-sdk": "npm:@mlm/hydrogen-view-sdk@^0.20.0-scratch", "json5": "^2.2.1", - "linkedom": "^0.14.1", + "linkedom": "^0.14.17", "matrix-public-archive-shared": "file:./shared/", "nconf": "^0.11.3", "node-fetch": "^2.6.7", @@ -2216,7 +2216,8 @@ }, "node_modules/boolbase": { "version": "1.0.0", - "license": "ISC" + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, "node_modules/boxen": { "version": "5.1.2", @@ -2552,13 +2553,14 @@ } }, "node_modules/css-select": { - "version": "4.2.1", - "license": "BSD-2-Clause", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", "dependencies": { "boolbase": "^1.0.0", - "css-what": "^5.1.0", - "domhandler": "^4.3.0", - "domutils": "^2.8.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", "nth-check": "^2.0.1" }, "funding": { @@ -2566,8 +2568,9 @@ } }, "node_modules/css-what": { - "version": "5.1.0", - "license": "BSD-2-Clause", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", "engines": { "node": ">= 6" }, @@ -2664,32 +2667,35 @@ } }, "node_modules/dom-serializer": { - "version": "1.3.2", - "license": "MIT", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" }, "funding": { "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, "node_modules/domelementtype": { - "version": "2.2.0", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/fb55" } - ], - "license": "BSD-2-Clause" + ] }, "node_modules/domhandler": { - "version": "4.3.0", - "license": "BSD-2-Clause", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dependencies": { - "domelementtype": "^2.2.0" + "domelementtype": "^2.3.0" }, "engines": { "node": ">= 4" @@ -2703,12 +2709,13 @@ "license": "(MPL-2.0 OR Apache-2.0)" }, "node_modules/domutils": { - "version": "2.8.0", - "license": "BSD-2-Clause", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", + "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.1" }, "funding": { "url": "https://github.com/fb55/domutils?sponsor=1" @@ -2763,8 +2770,12 @@ } }, "node_modules/entities": { - "version": "2.2.0", - "license": "BSD-2-Clause", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "engines": { + "node": ">=0.12" + }, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -3590,7 +3601,9 @@ "license": "MIT" }, "node_modules/htmlparser2": { - "version": "7.2.0", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", + "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", { @@ -3598,22 +3611,11 @@ "url": "https://github.com/sponsors/fb55" } ], - "license": "MIT", "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.2", - "domutils": "^2.8.0", - "entities": "^3.0.1" - } - }, - "node_modules/htmlparser2/node_modules/entities": { - "version": "3.0.1", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "entities": "^4.3.0" } }, "node_modules/http-cache-semantics": { @@ -3637,9 +3639,9 @@ }, "node_modules/hydrogen-view-sdk": { "name": "@mlm/hydrogen-view-sdk", - "version": "0.19.0-scratch", - "resolved": "https://registry.npmjs.org/@mlm/hydrogen-view-sdk/-/hydrogen-view-sdk-0.19.0-scratch.tgz", - "integrity": "sha512-wpb6DAnayXO2Xcb9tHS13JGXgF/kOnqEuSxYdQisxJPDnYDrcqwX7LHTw/yhPvfNKLSv5UpWr7DrMAN1xEhwOg==", + "version": "0.20.0-scratch", + "resolved": "https://registry.npmjs.org/@mlm/hydrogen-view-sdk/-/hydrogen-view-sdk-0.20.0-scratch.tgz", + "integrity": "sha512-5WktCwE3b8BgQ2ICx37c91hWrFJbAg+rUU1DTFeT/sFpRP+USqBHfz5IDrd4EcgZk7/FiMpV1lzpsJ5Wfip1NQ==", "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", @@ -4017,13 +4019,14 @@ "license": "MIT" }, "node_modules/linkedom": { - "version": "0.14.1", - "license": "ISC", + "version": "0.14.17", + "resolved": "https://registry.npmjs.org/linkedom/-/linkedom-0.14.17.tgz", + "integrity": "sha512-PD6GQKvZ4s6Ai4/WkpyHc8MhiZdCz4hWmMOWJk+MO3/kl1QvPUbo4nQWS9+VHO7lRBk1ucIa9ONS9qzCUcBAmQ==", "dependencies": { - "css-select": "^4.2.1", + "css-select": "^5.1.0", "cssom": "^0.5.0", "html-escaper": "^3.0.3", - "htmlparser2": "^7.2.0", + "htmlparser2": "^8.0.1", "uhyphen": "^0.1.0" } }, @@ -4449,8 +4452,9 @@ } }, "node_modules/nth-check": { - "version": "2.0.1", - "license": "BSD-2-Clause", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dependencies": { "boolbase": "^1.0.0" }, @@ -7181,7 +7185,9 @@ } }, "boolbase": { - "version": "1.0.0" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, "boxen": { "version": "5.1.2", @@ -7386,17 +7392,21 @@ "dev": true }, "css-select": { - "version": "4.2.1", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", "requires": { "boolbase": "^1.0.0", - "css-what": "^5.1.0", - "domhandler": "^4.3.0", - "domutils": "^2.8.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "css-what": { - "version": "5.1.0" + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" }, "cssom": { "version": "0.5.0" @@ -7451,31 +7461,39 @@ } }, "dom-serializer": { - "version": "1.3.2", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" } }, "domelementtype": { - "version": "2.2.0" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" }, "domhandler": { - "version": "4.3.0", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "requires": { - "domelementtype": "^2.2.0" + "domelementtype": "^2.3.0" } }, "dompurify": { "version": "2.3.9" }, "domutils": { - "version": "2.8.0", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", + "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.1" } }, "dot-prop": { @@ -7514,7 +7532,9 @@ } }, "entities": { - "version": "2.2.0" + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==" }, "error": { "version": "7.0.2", @@ -8043,17 +8063,14 @@ "version": "3.0.3" }, "htmlparser2": { - "version": "7.2.0", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", + "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.2", - "domutils": "^2.8.0", - "entities": "^3.0.1" - }, - "dependencies": { - "entities": { - "version": "3.0.1" - } + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "entities": "^4.3.0" } }, "http-cache-semantics": { @@ -8071,9 +8088,9 @@ } }, "hydrogen-view-sdk": { - "version": "npm:@mlm/hydrogen-view-sdk@0.19.0-scratch", - "resolved": "https://registry.npmjs.org/@mlm/hydrogen-view-sdk/-/hydrogen-view-sdk-0.19.0-scratch.tgz", - "integrity": "sha512-wpb6DAnayXO2Xcb9tHS13JGXgF/kOnqEuSxYdQisxJPDnYDrcqwX7LHTw/yhPvfNKLSv5UpWr7DrMAN1xEhwOg==", + "version": "npm:@mlm/hydrogen-view-sdk@0.20.0-scratch", + "resolved": "https://registry.npmjs.org/@mlm/hydrogen-view-sdk/-/hydrogen-view-sdk-0.20.0-scratch.tgz", + "integrity": "sha512-5WktCwE3b8BgQ2ICx37c91hWrFJbAg+rUU1DTFeT/sFpRP+USqBHfz5IDrd4EcgZk7/FiMpV1lzpsJ5Wfip1NQ==", "requires": { "@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", @@ -8302,12 +8319,14 @@ } }, "linkedom": { - "version": "0.14.1", + "version": "0.14.17", + "resolved": "https://registry.npmjs.org/linkedom/-/linkedom-0.14.17.tgz", + "integrity": "sha512-PD6GQKvZ4s6Ai4/WkpyHc8MhiZdCz4hWmMOWJk+MO3/kl1QvPUbo4nQWS9+VHO7lRBk1ucIa9ONS9qzCUcBAmQ==", "requires": { - "css-select": "^4.2.1", + "css-select": "^5.1.0", "cssom": "^0.5.0", "html-escaper": "^3.0.3", - "htmlparser2": "^7.2.0", + "htmlparser2": "^8.0.1", "uhyphen": "^0.1.0" } }, @@ -8557,7 +8576,9 @@ "dev": true }, "nth-check": { - "version": "2.0.1", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "requires": { "boolbase": "^1.0.0" } diff --git a/package.json b/package.json index 466cd19..26701a6 100644 --- a/package.json +++ b/package.json @@ -47,9 +47,9 @@ "@opentelemetry/semantic-conventions": "^1.3.1", "dompurify": "^2.3.9", "express": "^4.17.2", - "hydrogen-view-sdk": "npm:@mlm/hydrogen-view-sdk@^0.19.0-scratch", + "hydrogen-view-sdk": "npm:@mlm/hydrogen-view-sdk@^0.20.0-scratch", "json5": "^2.2.1", - "linkedom": "^0.14.1", + "linkedom": "^0.14.17", "matrix-public-archive-shared": "file:./shared/", "nconf": "^0.11.3", "node-fetch": "^2.6.7", diff --git a/server/routes/room-directory-routes.js b/server/routes/room-directory-routes.js index eb86701..cc81a08 100644 --- a/server/routes/room-directory-routes.js +++ b/server/routes/room-directory-routes.js @@ -73,8 +73,8 @@ router.get( : null, nextPaginationToken, prevPaginationToken, - searchParameters: { - homeserver, + pageSearchParameters: { + homeserver: homeserver || matrixServerName, searchTerm, paginationToken, limit, diff --git a/shared/room-directory-vm-render-script.js b/shared/room-directory-vm-render-script.js index b9df7a4..1e65c6b 100644 --- a/shared/room-directory-vm-render-script.js +++ b/shared/room-directory-vm-render-script.js @@ -20,7 +20,7 @@ assert(rooms); const roomFetchError = window.matrixPublicArchiveContext.roomFetchError; const nextPaginationToken = window.matrixPublicArchiveContext.nextPaginationToken; const prevPaginationToken = window.matrixPublicArchiveContext.prevPaginationToken; -const searchParameters = window.matrixPublicArchiveContext.searchParameters; +const pageSearchParameters = window.matrixPublicArchiveContext.pageSearchParameters; const config = window.matrixPublicArchiveContext.config; assert(config); assert(config.matrixServerUrl); @@ -80,11 +80,10 @@ async function mountHydrogen() { matrixPublicArchiveURLCreator, rooms, roomFetchError, - searchParameters, + pageSearchParameters, nextPaginationToken, prevPaginationToken, }); - roomDirectoryViewModel.loadAddedHomserversListFromPersistence(); const view = new RoomDirectoryView(roomDirectoryViewModel); diff --git a/shared/viewmodels/RoomDirectoryViewModel.js b/shared/viewmodels/RoomDirectoryViewModel.js index 4c848a4..491e393 100644 --- a/shared/viewmodels/RoomDirectoryViewModel.js +++ b/shared/viewmodels/RoomDirectoryViewModel.js @@ -20,7 +20,7 @@ class RoomDirectoryViewModel extends ViewModel { matrixPublicArchiveURLCreator, rooms, roomFetchError, - searchParameters, + pageSearchParameters, nextPaginationToken, prevPaginationToken, } = options; @@ -49,13 +49,19 @@ class RoomDirectoryViewModel extends ViewModel { }) ); - this._searchParameters = searchParameters; - this._searchTerm = searchParameters.searchTerm; - this._addedHomeserversList = []; + this._pageSearchParameters = pageSearchParameters; + // Default to what the page started with + this._searchTerm = pageSearchParameters.searchTerm; this._nextPaginationToken = nextPaginationToken; this._prevPaginationToken = prevPaginationToken; - this._homeserverSelection = this.availableHomeserverList[0]; + // The default selected homeserver should be the one according to the page or the first one in the list + this._homeserverSelection = pageSearchParameters.homeserver || this._availableHomeserverList[0]; + // The homeservers that the user added themselves (pulled from LocalStorage) + this._addedHomeserversList = []; + this.loadAddedHomserversListFromPersistence(); + // The default list of homeservers to select from + this._calculateAvailableHomeserverList(); this._homeserverSelectionModalContentViewModel = new HomeserverSelectionModalContentViewModel({ onNewHomeserverAdded: this.onNewHomeserverAdded.bind(this), @@ -105,8 +111,8 @@ class RoomDirectoryViewModel extends ViewModel { return this._matrixPublicArchiveURLCreator.roomDirectoryUrl(); } - get searchParameters() { - return this._searchParameters; + get pageSearchParameters() { + return this._pageSearchParameters; } get searchTerm() { @@ -181,6 +187,12 @@ class RoomDirectoryViewModel extends ViewModel { ADDED_HOMESERVERS_LIST_LOCAL_STORAGE_KEY, JSON.stringify(this._addedHomeserversList) ); + + // If the added homeserver list changes, make sure the default page selected + // homeserver is still somewhere in the list. If it's no longer in the added + // homeserver list, we will put it in the default available list. + this._calculateAvailableHomeserverList(); + this.emitChange('addedHomeserversList'); } @@ -220,10 +232,23 @@ class RoomDirectoryViewModel extends ViewModel { return null; } - get availableHomeserverList() { + // The default list of available homeservers to select from. Deduplicates the the + // homeserver we're pulling from and the `DEFAULT_SERVER_LIST`. Also makes sure that + // the page selected homeserver is either in our default available list or in the + // added servers list. + _calculateAvailableHomeserverList() { // Append the default homeserver to the front const rawList = [this._homeserverName, ...DEFAULT_SERVER_LIST]; + // Make sure the page selected homeserver is in the list somewhere + if ( + this.homeserverSelection && + !rawList.includes(this.homeserverSelection) && + !this._addedHomeserversList.includes(this.homeserverSelection) + ) { + rawList.unshift(this.homeserverSelection); + } + // Then deduplicate the list const deduplicatedHomeserverMap = {}; rawList.forEach((homeserverName) => { @@ -231,7 +256,12 @@ class RoomDirectoryViewModel extends ViewModel { }); const deduplicatedHomeserverList = Object.keys(deduplicatedHomeserverMap); - return deduplicatedHomeserverList; + this._availableHomeserverList = deduplicatedHomeserverList; + this.emit('availableHomeserverList'); + } + + get availableHomeserverList() { + return this._availableHomeserverList; } get rooms() { diff --git a/shared/views/RoomDirectoryView.js b/shared/views/RoomDirectoryView.js index ea81607..bf4d627 100644 --- a/shared/views/RoomDirectoryView.js +++ b/shared/views/RoomDirectoryView.js @@ -28,14 +28,11 @@ class RoomDirectoryView extends TemplateView { } ); - const availableHomeserverOptionElements = vm.availableHomeserverList.map((homeserverName) => { - return t.option({ value: homeserverName }, homeserverName); - }); - const homeserverSelectElement = t.select( { className: 'RoomDirectoryView_homeserverSelector', name: 'homeserver', + 'data-testid': 'homeserver-select', onInput: (event) => { const optionValue = event.target.value; if (optionValue.startsWith('action:')) { @@ -51,13 +48,37 @@ class RoomDirectoryView extends TemplateView { }, }, [ - ...availableHomeserverOptionElements, + t.map( + (vm) => vm.availableHomeserverList, + (_, t, vm) => { + const availableHomeserverOptionElements = vm.availableHomeserverList.map( + (homeserverName) => { + return t.option( + { value: homeserverName, selected: vm.homeserverSelection === homeserverName }, + homeserverName + ); + } + ); + let availableHomeserversOptGroup = text(''); + if (availableHomeserverOptionElements.length > 0) { + availableHomeserversOptGroup = t.optgroup( + { label: 'Defaults' }, + availableHomeserverOptionElements + ); + } + + return availableHomeserversOptGroup; + } + ), t.map( (vm) => vm.addedHomeserversList, (_, t, vm) => { const addedHomeserverOptionElements = vm.addedHomeserversList.map((homeserverName) => { - return t.option({ value: homeserverName }, homeserverName); + return t.option( + { value: homeserverName, selected: vm.homeserverSelection === homeserverName }, + homeserverName + ); }); let addedHomeserversOptGroup = text(''); @@ -153,12 +174,31 @@ class RoomDirectoryView extends TemplateView { const pickedActionOption = homeserverSelection.startsWith('action:'); const isInitialization = oldHomeserverSelection === undefined; if (!pickedActionOption && !isInitialization) { - // Submit the page with the new homeserver selection to get results + // Clear the hash out before we submit the form so it doesn't come back from + // the dead after the page loads. Normally, the hash would go away in the + // modal close callback but this races with it and sometimes we beat it. + const path = vm.navigation.pathFrom([]); + vm.navigation.applyPath(path); + // Submit the page with the new homeserver selection to get results. headerForm.submit(); } } ); + // Also update the selection whenever the lists change around + t.mapSideEffect( + (vm) => vm.availableHomeserverList, + () => { + homeserverSelectElement.value = vm.homeserverSelection; + } + ); + t.mapSideEffect( + (vm) => vm.addedHomeserversList, + () => { + homeserverSelectElement.value = vm.homeserverSelection; + } + ); + return t.div( { className: { @@ -168,13 +208,14 @@ class RoomDirectoryView extends TemplateView { [ t.header({ className: 'RoomDirectoryView_header' }, [headerForm]), t.main({ className: 'RoomDirectoryView_mainContent' }, [ + // Display a nice error section when we failed to fetch rooms from the room directory t.if( (vm) => vm.roomFetchError, (t, vm) => { return t.section({ className: 'RoomDirectoryView_roomListError' }, [ t.h3('❗ Unable to fetch rooms from room directory'), t.p({}, [ - `This may be a temporary problem with the homeserver where the room directory lives (${vm.searchParameters.homeserver}) or the homeserver that the archive is pulling from (${vm.homeserverName}). You can try adjusting your search term or select a different homeserver to look at. If this problem persists, please open a `, + `This may be a temporary problem with the homeserver where the room directory lives (${vm.pageSearchParameters.homeserver}) or the homeserver that the archive is pulling from (${vm.homeserverName}). You can try adjusting your search term or select a different homeserver to look at. If this problem persists, please open a `, t.a( { href: 'https://github.com/matrix-org/matrix-public-archive/issues/new' }, 'bug report' @@ -198,7 +239,7 @@ class RoomDirectoryView extends TemplateView { t.p({}, `The error occured with these search paramers:`), t.pre( { className: 'RoomDirectoryView_codeBlock' }, - t.code({}, JSON.stringify(vm.searchParameters, null, 2)) + t.code({}, JSON.stringify(vm.pageSearchParameters, null, 2)) ), t.details({}, [ t.summary({}, 'Why are we showing so many details?'), @@ -239,6 +280,7 @@ class RoomDirectoryView extends TemplateView { ]); } ), + // Otherwise, display the rooms that we fetched t.view(roomList), t.div({ className: 'RoomDirectoryView_paginationButtonCombo' }, [ t.a( diff --git a/test/e2e-tests.js b/test/e2e-tests.js index dace4b4..86fbf72 100644 --- a/test/e2e-tests.js +++ b/test/e2e-tests.js @@ -700,6 +700,15 @@ describe('matrix-public-archive', () => { const roomDirectoryWithSearchPageHtml = await fetchEndpointAsText(archiveUrl); const domWithSearch = parseHTML(roomDirectoryWithSearchPageHtml); + // Make sure the `?homserver` is selected in the homeserver selector `