2022-09-08 00:30:04 -06:00
'use strict' ;
const { ViewModel , ObservableArray } = require ( 'hydrogen-view-sdk' ) ;
const assert = require ( 'matrix-public-archive-shared/lib/assert' ) ;
2022-10-20 01:06:43 -06:00
const ModalViewModel = require ( 'matrix-public-archive-shared/viewmodels/ModalViewModel' ) ;
const HomeserverSelectionModalContentViewModel = require ( 'matrix-public-archive-shared/viewmodels/HomeserverSelectionModalContentViewModel' ) ;
2022-09-08 00:30:04 -06:00
const DEFAULT _SERVER _LIST = [ 'matrix.org' , 'gitter.im' , 'libera.chat' ] ;
2022-10-20 01:06:43 -06:00
const ADDED _HOMESERVERS _LIST _LOCAL _STORAGE _KEY = 'addedHomservers' ;
2022-09-08 00:30:04 -06:00
class RoomDirectoryViewModel extends ViewModel {
constructor ( options ) {
super ( options ) ;
const {
homeserverUrl ,
homeserverName ,
matrixPublicArchiveURLCreator ,
rooms ,
2022-10-20 21:48:00 -06:00
roomFetchError ,
2022-10-21 01:09:26 -06:00
pageSearchParameters ,
2022-09-08 00:30:04 -06:00
nextPaginationToken ,
prevPaginationToken ,
} = options ;
assert ( homeserverUrl ) ;
assert ( homeserverName ) ;
assert ( matrixPublicArchiveURLCreator ) ;
assert ( rooms ) ;
2022-10-20 21:48:00 -06:00
this . _roomFetchError = roomFetchError ;
2022-09-08 00:30:04 -06:00
this . _homeserverUrl = homeserverUrl ;
this . _homeserverName = homeserverName ;
this . _matrixPublicArchiveURLCreator = matrixPublicArchiveURLCreator ;
this . _rooms = new ObservableArray (
rooms . map ( ( room ) => {
return {
roomId : room . room _id ,
canonicalAlias : room . canonical _alias ,
name : room . name ,
mxcAvatarUrl : room . avatar _url ,
homeserverUrlToPullMediaFrom : homeserverUrl ,
numJoinedMembers : room . num _joined _members ,
topic : room . topic ,
archiveRoomUrl : matrixPublicArchiveURLCreator . archiveUrlForRoom ( room . room _id ) ,
} ;
} )
) ;
2022-10-20 21:48:00 -06:00
2022-10-21 01:09:26 -06:00
this . _pageSearchParameters = pageSearchParameters ;
// Default to what the page started with
this . _searchTerm = pageSearchParameters . searchTerm ;
2022-09-08 00:30:04 -06:00
this . _nextPaginationToken = nextPaginationToken ;
this . _prevPaginationToken = prevPaginationToken ;
2022-10-20 01:06:43 -06:00
2022-10-21 01:09:26 -06:00
// 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 ( ) ;
2022-10-20 01:06:43 -06:00
this . _homeserverSelectionModalContentViewModel = new HomeserverSelectionModalContentViewModel ( {
onNewHomeserverAdded : this . onNewHomeserverAdded . bind ( this ) ,
} ) ;
this . homeserverSelectionModalViewModel = new ModalViewModel (
this . childOptions ( {
title : 'Add a new server' ,
contentViewModel : this . _homeserverSelectionModalContentViewModel ,
closeCallback : ( ) => {
const path = this . navigation . pathFrom ( [ ] ) ;
this . navigation . applyPath ( path ) ;
} ,
} )
) ;
this . # setupNavigation ( ) ;
}
# setupNavigation ( ) {
// Make sure the add-server modal open when the URL changes
const handleAddServerNavigationChange = ( ) => {
const shouldShowAddServerModal = ! ! this . navigation . path . get ( 'add-server' ) ? . value ;
this . setShouldShowAddServerModal ( shouldShowAddServerModal ) ;
} ;
const addServer = this . navigation . observe ( 'add-server' ) ;
this . track ( addServer . subscribe ( handleAddServerNavigationChange ) ) ;
// Also handle the case where the URL already includes `#/add-server`
// stuff from page-load
const initialAddServer = addServer . get ( ) ;
handleAddServerNavigationChange ( initialAddServer ) ;
}
setShouldShowAddServerModal ( shouldShowAddServerModal ) {
this . homeserverSelectionModalViewModel . setOpen ( shouldShowAddServerModal ) ;
2022-09-08 00:30:04 -06:00
}
get homeserverUrl ( ) {
return this . _homeserverUrl ;
}
2022-10-20 21:48:00 -06:00
get homeserverName ( ) {
return this . _homeserverName ;
}
2022-09-08 00:30:04 -06:00
get roomDirectoryUrl ( ) {
return this . _matrixPublicArchiveURLCreator . roomDirectoryUrl ( ) ;
}
2022-10-21 01:09:26 -06:00
get pageSearchParameters ( ) {
return this . _pageSearchParameters ;
2022-10-20 21:48:00 -06:00
}
2022-09-15 19:41:55 -06:00
get searchTerm ( ) {
return this . _searchTerm || '' ;
}
setSearchTerm ( newSearchTerm ) {
this . _searchTerm = newSearchTerm ;
this . emitChange ( 'searchTerm' ) ;
}
2022-10-20 01:06:43 -06:00
setHomeserverSelection ( newHomeserver ) {
this . _homeserverSelection = newHomeserver ;
this . emitChange ( 'homeserverSelection' ) ;
}
onHomeserverSelectionAction ( action ) {
if ( action === 'action:add-new-server' ) {
const path = this . navigation . pathFrom ( [ this . navigation . segment ( 'add-server' ) ] ) ;
this . navigation . applyPath ( path ) ;
} else if ( action === 'action:clear-servers' ) {
this . setAddedHomeserversList ( [ ] ) ;
// After clearing the added servers, just fallback to the first one in the available list.
// We don't want people to be stuck on the "Clear servers" option.
this . _homeserverSelection = this . availableHomeserverList [ 0 ] ;
this . emitChange ( 'homeserverSelection' ) ;
} else {
console . warn ( ` Unknown action= ${ action } passed to \` onHomeserverSelectionAction \` ` ) ;
}
}
get homeserverSelection ( ) {
return this . _homeserverSelection ;
}
loadAddedHomserversListFromPersistence ( ) {
if ( window . localStorage ) {
let addedHomeserversFromPersistence = [ ] ;
try {
addedHomeserversFromPersistence = JSON . parse (
window . localStorage . getItem ( ADDED _HOMESERVERS _LIST _LOCAL _STORAGE _KEY )
) ;
} catch ( err ) {
console . warn (
` Resetting \` ${ ADDED _HOMESERVERS _LIST _LOCAL _STORAGE _KEY } \` stored in LocalStorage since we ran into an error parsing what was stored ` ,
err
) ;
this . setAddedHomeserversList ( [ ] ) ;
return ;
}
if ( ! Array . isArray ( addedHomeserversFromPersistence ) ) {
console . warn (
` Resetting \` ${ ADDED _HOMESERVERS _LIST _LOCAL _STORAGE _KEY } \` stored in LocalStorage since it wasn't an array as expected, addedHomeservers= ${ addedHomeserversFromPersistence } `
) ;
this . setAddedHomeserversList ( [ ] ) ;
return ;
}
this . setAddedHomeserversList ( addedHomeserversFromPersistence ) ;
return ;
} else {
console . warn (
` Skipping \` ${ ADDED _HOMESERVERS _LIST _LOCAL _STORAGE _KEY } \` read from LocalStorage since LocalStorage is not available `
) ;
}
}
setAddedHomeserversList ( addedHomeserversList ) {
this . _addedHomeserversList = addedHomeserversList ;
window . localStorage . setItem (
ADDED _HOMESERVERS _LIST _LOCAL _STORAGE _KEY ,
JSON . stringify ( this . _addedHomeserversList )
) ;
2022-10-21 01:09:26 -06:00
// 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 ( ) ;
2022-10-20 01:06:43 -06:00
this . emitChange ( 'addedHomeserversList' ) ;
}
get addedHomeserversList ( ) {
return this . _addedHomeserversList ;
}
onNewHomeserverAdded ( newHomeserver ) {
const addedHomeserversList = this . addedHomeserversList ;
this . setAddedHomeserversList ( addedHomeserversList . concat ( newHomeserver ) ) ;
this . setHomeserverSelection ( newHomeserver ) ;
}
2022-10-20 21:48:00 -06:00
get roomFetchError ( ) {
return this . _roomFetchError ;
}
2022-09-08 00:30:04 -06:00
get nextPageUrl ( ) {
if ( this . _nextPaginationToken ) {
return this . _matrixPublicArchiveURLCreator . roomDirectoryUrl ( {
2022-09-15 19:41:55 -06:00
searchTerm : this . searchTerm ,
2022-09-08 00:30:04 -06:00
paginationToken : this . _nextPaginationToken ,
} ) ;
}
return null ;
}
get prevPageUrl ( ) {
if ( this . _prevPaginationToken ) {
return this . _matrixPublicArchiveURLCreator . roomDirectoryUrl ( {
2022-09-15 19:41:55 -06:00
searchTerm : this . searchTerm ,
2022-09-08 00:30:04 -06:00
paginationToken : this . _prevPaginationToken ,
} ) ;
}
return null ;
}
2022-10-21 01:09:26 -06:00
// 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 ( ) {
2022-09-08 00:30:04 -06:00
// Append the default homeserver to the front
const rawList = [ this . _homeserverName , ... DEFAULT _SERVER _LIST ] ;
2022-10-21 01:09:26 -06:00
// 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 ) ;
}
2022-09-08 00:30:04 -06:00
// Then deduplicate the list
const deduplicatedHomeserverMap = { } ;
rawList . forEach ( ( homeserverName ) => {
deduplicatedHomeserverMap [ homeserverName ] = true ;
} ) ;
const deduplicatedHomeserverList = Object . keys ( deduplicatedHomeserverMap ) ;
2022-10-21 01:09:26 -06:00
this . _availableHomeserverList = deduplicatedHomeserverList ;
this . emit ( 'availableHomeserverList' ) ;
}
get availableHomeserverList ( ) {
return this . _availableHomeserverList ;
2022-09-08 00:30:04 -06:00
}
get rooms ( ) {
return this . _rooms ;
}
}
module . exports = RoomDirectoryViewModel ;