forked from mystiq/hydrogen-web
WIP
This commit is contained in:
parent
41d624a1ae
commit
974f77a71d
11 changed files with 197 additions and 7 deletions
|
@ -125,7 +125,10 @@ export class RootViewModel extends ViewModel {
|
|||
|
||||
_showSession(sessionContainer) {
|
||||
this._setSection(() => {
|
||||
this._sessionViewModel = new SessionViewModel(this.childOptions({sessionContainer}));
|
||||
this._sessionViewModel = new SessionViewModel(this.childOptions({
|
||||
sessionContainer,
|
||||
updateService: this.getOption("updateService")
|
||||
}));
|
||||
this._sessionViewModel.start();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -34,6 +34,11 @@ export class ViewModel extends EventEmitter {
|
|||
return Object.assign({navigation, urlCreator, clock}, explicitOptions);
|
||||
}
|
||||
|
||||
// makes it easier to pass through dependencies of a sub-view model
|
||||
getOption(name) {
|
||||
return this._options[name];
|
||||
}
|
||||
|
||||
track(disposable) {
|
||||
if (!this.disposables) {
|
||||
this.disposables = new Disposables();
|
||||
|
|
|
@ -19,6 +19,7 @@ import {LeftPanelViewModel} from "./leftpanel/LeftPanelViewModel.js";
|
|||
import {RoomViewModel} from "./room/RoomViewModel.js";
|
||||
import {SessionStatusViewModel} from "./SessionStatusViewModel.js";
|
||||
import {RoomGridViewModel} from "./RoomGridViewModel.js";
|
||||
import {SettingsViewModel} from "./SettingsViewModel.js";
|
||||
import {ViewModel} from "../ViewModel.js";
|
||||
|
||||
export class SessionViewModel extends ViewModel {
|
||||
|
@ -34,6 +35,7 @@ export class SessionViewModel extends ViewModel {
|
|||
this._leftPanelViewModel = this.track(new LeftPanelViewModel(this.childOptions({
|
||||
rooms: this._sessionContainer.session.rooms
|
||||
})));
|
||||
this._settingsViewModel = null;
|
||||
this._currentRoomViewModel = null;
|
||||
this._gridViewModel = null;
|
||||
this._setupNavigation();
|
||||
|
@ -53,12 +55,18 @@ export class SessionViewModel extends ViewModel {
|
|||
// this gives us the active room
|
||||
this.track(currentRoomId.subscribe(roomId => {
|
||||
if (!this._gridViewModel) {
|
||||
this._openRoom(roomId);
|
||||
this._updateRoom(roomId);
|
||||
}
|
||||
}));
|
||||
if (currentRoomId.get() && !this._gridViewModel) {
|
||||
this._openRoom(currentRoomId.get());
|
||||
if (!this._gridViewModel) {
|
||||
this._updateRoom(currentRoomId.get());
|
||||
}
|
||||
|
||||
const settings = this.navigation.observe("settings");
|
||||
this.track(settings.subscribe(settingsOpen => {
|
||||
this._updateSettings(settingsOpen);
|
||||
}));
|
||||
this._updateSettings(settings.get());
|
||||
}
|
||||
|
||||
get id() {
|
||||
|
@ -74,6 +82,8 @@ export class SessionViewModel extends ViewModel {
|
|||
return this._currentRoomViewModel.id;
|
||||
} else if (this._gridViewModel) {
|
||||
return "roomgrid";
|
||||
} else if (this._settingsViewModel) {
|
||||
return "settings";
|
||||
}
|
||||
return "placeholder";
|
||||
}
|
||||
|
@ -90,6 +100,10 @@ export class SessionViewModel extends ViewModel {
|
|||
return this._sessionStatusViewModel;
|
||||
}
|
||||
|
||||
get settingsViewModel() {
|
||||
return this._settingsViewModel;
|
||||
}
|
||||
|
||||
get roomList() {
|
||||
return this._roomList;
|
||||
}
|
||||
|
@ -148,7 +162,7 @@ export class SessionViewModel extends ViewModel {
|
|||
return roomVM;
|
||||
}
|
||||
|
||||
_openRoom(roomId) {
|
||||
_updateRoom(roomId) {
|
||||
if (!roomId) {
|
||||
if (this._currentRoomViewModel) {
|
||||
this._currentRoomViewModel = this.disposeTracked(this._currentRoomViewModel);
|
||||
|
@ -167,4 +181,17 @@ export class SessionViewModel extends ViewModel {
|
|||
}
|
||||
this.emitChange("currentRoom");
|
||||
}
|
||||
|
||||
_updateSettings(settingsOpen) {
|
||||
if (this._settingsViewModel) {
|
||||
this._settingsViewModel = this.disposeTracked(this._settingsViewModel);
|
||||
}
|
||||
if (settingsOpen) {
|
||||
this._settingsViewModel = this.track(new SettingsViewModel(this.childOptions({
|
||||
updateService: this.getOption("updateService"),
|
||||
session: this._sessionContainer.session
|
||||
})));
|
||||
}
|
||||
this.emitChange("activeSection");
|
||||
}
|
||||
}
|
||||
|
|
65
src/domain/session/SettingsViewModel.js
Normal file
65
src/domain/session/SettingsViewModel.js
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
Copyright 2020 Bruno Windels <bruno@windels.cloud>
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {ViewModel} from "../ViewModel.js";
|
||||
|
||||
export class SettingsViewModel extends ViewModel {
|
||||
constructor(options) {
|
||||
super(options);
|
||||
this._updateService = options.updateService;
|
||||
this._session = options.session;
|
||||
this._closeUrl = this.urlCreator.urlUntilSegment("session");
|
||||
}
|
||||
|
||||
get closeUrl() {
|
||||
return this._closeUrl;
|
||||
}
|
||||
|
||||
get fingerprintKey() {
|
||||
const key = this._session.fingerprintKey;
|
||||
const partLength = 4;
|
||||
const partCount = Math.ceil(key.length / partLength);
|
||||
let formattedKey = "";
|
||||
for (let i = 0; i < partCount; i += 1) {
|
||||
formattedKey += (formattedKey.length ? " " : "") + key.slice(i * partLength, (i + 1) * partLength);
|
||||
}
|
||||
return formattedKey;
|
||||
}
|
||||
|
||||
get deviceId() {
|
||||
return this._session.deviceId;
|
||||
}
|
||||
|
||||
get userId() {
|
||||
return this._session.userId;
|
||||
}
|
||||
|
||||
get version() {
|
||||
if (this._updateService) {
|
||||
return `${this._updateService.version} (${this._updateService.buildHash})`;
|
||||
}
|
||||
return "development version";
|
||||
}
|
||||
|
||||
checkForUpdate() {
|
||||
this._updateService?.checkForUpdate();
|
||||
}
|
||||
|
||||
get showUpdateButton() {
|
||||
return !!this._updateService;
|
||||
}
|
||||
}
|
|
@ -45,12 +45,17 @@ export class LeftPanelViewModel extends ViewModel {
|
|||
this._currentTileVM = null;
|
||||
this._setupNavigation();
|
||||
this._closeUrl = this.urlCreator.urlForSegment("session");
|
||||
this._settingsUrl = this.urlCreator.urlForSegment("settings");
|
||||
}
|
||||
|
||||
get closeUrl() {
|
||||
return this._closeUrl;
|
||||
}
|
||||
|
||||
get settingsUrl() {
|
||||
return this._settingsUrl;
|
||||
}
|
||||
|
||||
_setupNavigation() {
|
||||
const roomObservable = this.navigation.observe("room");
|
||||
this.track(roomObservable.subscribe(roomId => this._open(roomId)));
|
||||
|
|
|
@ -77,6 +77,18 @@ export class Session {
|
|||
this.needsSessionBackup = new ObservableValue(false);
|
||||
}
|
||||
|
||||
get fingerprintKey() {
|
||||
return this._e2eeAccount?.identityKeys.ed25519;
|
||||
}
|
||||
|
||||
get deviceId() {
|
||||
return this._sessionInfo.deviceId;
|
||||
}
|
||||
|
||||
get userId() {
|
||||
return this._sessionInfo.userId;
|
||||
}
|
||||
|
||||
// called once this._e2eeAccount is assigned
|
||||
_setupEncryption() {
|
||||
console.log("loaded e2ee account with keys", this._e2eeAccount.identityKeys);
|
||||
|
|
3
src/ui/web/css/themes/element/icons/settings.svg
Normal file
3
src/ui/web/css/themes/element/icons/settings.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.3625 9.2875C19.5625 9.8125 20.075 10.1625 20.6375 10.1625C21.3875 10.1625 22 10.775 22 11.525V12.475C22 13.225 21.3875 13.8375 20.6375 13.8375C20.075 13.8375 19.5625 14.1875 19.3625 14.7125C19.346 14.7538 19.3294 14.7958 19.3128 14.838C19.2538 14.9876 19.1932 15.1413 19.125 15.2875C18.8875 15.8 19 16.4 19.4 16.8C19.9375 17.325 19.9375 18.1875 19.4 18.725L18.725 19.4C18.2 19.9375 17.3375 19.9375 16.8 19.4C16.4125 19 15.8 18.8875 15.2875 19.125C15.1 19.2125 14.9125 19.2875 14.7125 19.3625C14.1875 19.5625 13.8375 20.075 13.8375 20.6375C13.8375 21.3875 13.225 22 12.475 22H11.525C10.775 22 10.1625 21.3875 10.1625 20.6375C10.1625 20.075 9.8125 19.5625 9.2875 19.3625C9.24617 19.346 9.20423 19.3294 9.16195 19.3128C9.01243 19.2538 8.85867 19.1932 8.7125 19.125C8.2 18.8875 7.6 19 7.2 19.4C6.675 19.9375 5.8125 19.9375 5.275 19.4L4.6 18.725C4.0625 18.2 4.0625 17.3375 4.6 16.8C5 16.4125 5.1125 15.8 4.875 15.2875C4.7875 15.1 4.7125 14.9125 4.6375 14.7125C4.4375 14.1875 3.925 13.8375 3.3625 13.8375C2.6125 13.8375 2 13.225 2 12.475V11.525C2 10.775 2.6125 10.1625 3.3625 10.1625C3.925 10.1625 4.4375 9.8125 4.6375 9.2875C4.67694 9.16129 4.72634 9.04005 4.77627 8.91751C4.80546 8.84587 4.83483 8.77379 4.8625 8.7C5.1 8.1875 4.9875 7.5875 4.5875 7.1875C4.05 6.6625 4.05 5.8 4.5875 5.2625L5.275 4.6C5.8 4.0625 6.6625 4.0625 7.2 4.6C7.5875 5 8.2 5.1125 8.7125 4.875C8.9 4.7875 9.0875 4.7 9.2875 4.6375C9.8125 4.4375 10.1625 3.925 10.1625 3.3625C10.1625 2.6125 10.775 2 11.525 2H12.475C13.225 2 13.8375 2.6125 13.8375 3.3625C13.8375 3.9375 14.1875 4.4375 14.7125 4.6375C14.7538 4.65403 14.7958 4.67056 14.838 4.68723C14.9876 4.74617 15.1413 4.80679 15.2875 4.875C15.8 5.1125 16.4 5 16.8 4.6C17.325 4.0625 18.1875 4.0625 18.725 4.6L19.4 5.275C19.9375 5.8 19.9375 6.6625 19.4 7.2C19 7.5875 18.8875 8.2 19.125 8.7125C19.2125 8.9 19.2875 9.0875 19.3625 9.2875ZM12 17C9.2375 17 7 14.7625 7 12C7 9.2375 9.2375 7 12 7C14.7625 7 17 9.2375 17 12C17 14.7625 14.7625 17 12 17Z" fill="#8D99A5"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
|
@ -132,12 +132,17 @@ a.button-action {
|
|||
background-repeat: no-repeat;
|
||||
border: none;
|
||||
border-radius: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.button-utility.grid {
|
||||
background-image: url('icons/enable-grid.svg');
|
||||
}
|
||||
|
||||
.button-utility.settings {
|
||||
background-image: url('icons/settings.svg');
|
||||
}
|
||||
|
||||
.button-utility.grid.on {
|
||||
background-image: url('icons/disable-grid.svg');
|
||||
}
|
||||
|
@ -541,3 +546,25 @@ ul.Timeline > li.messageStatus .message-container > p {
|
|||
.GapView > :not(:first-child) {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.Settings {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.Settings .row .label {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.Settings .row.key .content {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.Settings .row {
|
||||
margin: 12px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.Settings .row .label {
|
||||
flex: 0 0 200px;
|
||||
}
|
||||
|
|
|
@ -152,6 +152,14 @@ export class ServiceWorkerHandler {
|
|||
this._registration.update();
|
||||
}
|
||||
|
||||
get version() {
|
||||
return window.HYDROGEN_VERSION;
|
||||
}
|
||||
|
||||
get buildHash() {
|
||||
return window.HYDROGEN_GLOBAL_HASH;
|
||||
}
|
||||
|
||||
async preventConcurrentSessionAccess(sessionId) {
|
||||
return this._sendAndWaitForReply("closeSession", {sessionId});
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@ export class SessionView extends TemplateView {
|
|||
return new RoomGridView(vm.roomGridViewModel);
|
||||
case "placeholder":
|
||||
return new StaticView(t => t.div({className: "room-placeholder"}, t.h2(vm.i18n`Choose a room on the left side.`)));
|
||||
case "settings":
|
||||
return new SettingsView(vm.settingsViewModel);
|
||||
default: //room id
|
||||
return new RoomView(vm.currentRoomViewModel);
|
||||
}
|
||||
|
@ -46,3 +48,35 @@ export class SessionView extends TemplateView {
|
|||
]);
|
||||
}
|
||||
}
|
||||
|
||||
class SettingsView extends TemplateView {
|
||||
render(t, vm) {
|
||||
let version = vm.version;
|
||||
if (vm.showUpdateButton) {
|
||||
version = t.span([
|
||||
vm.version,
|
||||
t.button({onClick: () => vm.checkForUpdate()}, vm.i18n`Check for updates`)
|
||||
]);
|
||||
}
|
||||
|
||||
const row = (label, content, extraClass = "") => {
|
||||
return t.div({className: `row ${extraClass}`}, [
|
||||
t.div({className: "label"}, label),
|
||||
t.div({className: "content"}, content),
|
||||
]);
|
||||
};
|
||||
|
||||
return t.div({className: "Settings"}, [
|
||||
t.div({className: "header"}, [
|
||||
t.a({className: "button-utility close-room", href: vm.closeUrl, title: vm.i18n`Close room`}),
|
||||
t.h2("Settings")
|
||||
]),
|
||||
t.div([
|
||||
row(vm.i18n`User ID`, vm.userId),
|
||||
row(vm.i18n`Session ID`, vm.deviceId),
|
||||
row(vm.i18n`Session key`, vm.fingerprintKey, "key"),
|
||||
row(vm.i18n`Version`, version),
|
||||
])
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ export class LeftPanelView extends TemplateView {
|
|||
vm.i18n`Enable grid layout`;
|
||||
};
|
||||
const utilitiesRow = t.div({className: "utilities"}, [
|
||||
t.a({className: "button-utility close-session", href: vm.closeUrl}),
|
||||
t.a({className: "button-utility close-session", href: vm.closeUrl, "aria-label": vm.i18n`Back to account list`, title: vm.i18n`Back to account list`}),
|
||||
t.view(new FilterField({
|
||||
i18n: vm.i18n,
|
||||
label: vm.i18n`Filter rooms…`,
|
||||
|
@ -75,7 +75,8 @@ export class LeftPanelView extends TemplateView {
|
|||
},
|
||||
title: gridButtonLabel,
|
||||
"aria-label": gridButtonLabel
|
||||
})
|
||||
}),
|
||||
t.a({className: "button-utility settings", href: vm.settingsUrl, "aria-label": vm.i18n`Settings`, title: vm.i18n`Settings`}),
|
||||
]);
|
||||
|
||||
return t.div({className: "LeftPanel"}, [
|
||||
|
|
Loading…
Reference in a new issue