Add a view model for opening a client

This commit is contained in:
Danila Fedorin 2021-08-26 14:13:45 -07:00
parent 820a090a71
commit a781c527fd
3 changed files with 128 additions and 22 deletions

View file

@ -0,0 +1,67 @@
/*
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 "../utils/ViewModel.js";
import {getMatchingPlatforms, selectPlatforms} from "./clients/index.js";
export class OpenDefaultViewModel extends ViewModel {
constructor(options) {
super(options);
const {client, link, openLinkVM, proposedPlatform, webPlatform} = options;
this._client = client;
this._link = link;
this._openLinkVM = openLinkVM;
this._proposedPlatform = proposedPlatform;
this._webPlatform = webPlatform;
}
get name() {
return this._client?.name;
}
get openingDefault() {
return !this._client;
}
get autoRedirect() {
// Only auto-redirect when a preferred client hasn't been set.
return this.openingDefault;
}
get webDeepLink() {
return this._client && this._webPlatform && this._client.getDeepLink(this._webPlatform);
}
close() {
this._openLinkVM.closeDefault();
}
tryOpenLink() {
this._trying = true;
// TODO actually try opening link
this.setTimeout(() => {
if (this.autoRedirect) {
// We're about to be closed so don't
// bother with visual updates.
this.close();
} else {
this._trying = false;
this.emitChange();
}
}, 1000);
this.emitChange();
}
}

View file

@ -22,17 +22,20 @@ import {ServerConsentView} from "./ServerConsentView.js";
export class OpenLinkView extends TemplateView {
render(t, vm) {
return t.div({className: "OpenLinkView card"}, [
t.map(vm => vm.tryingLink, tryingLink => tryingLink ?
t.view(new TryingLinkView(vm)) :
t.mapView(vm => vm.previewViewModel, previewVM => previewVM ?
new ShowLinkView(vm) :
new ServerConsentView(vm.serverConsentViewModel)
),
),
t.mapView(vm => [ vm.openDefaultViewModel, vm.previewViewModel ], ([openDefaultVM, previewVM]) => {
if (openDefaultVM) {
return new TryingLinkView(openDefaultVM)
} else if (previewVM) {
return new ShowLinkView(vm);
} else {
return new ServerConsentView(vm.serverConsentViewModel);
}
}),
]);
}
}
class TryingLinkView extends TemplateView {
render (t, vm) {
return t.div({ className: "OpeningClientView" }, [

View file

@ -18,9 +18,11 @@ import {ViewModel} from "../utils/ViewModel.js";
import {ClientListViewModel} from "./ClientListViewModel.js";
import {ClientViewModel} from "./ClientViewModel.js";
import {PreviewViewModel} from "../preview/PreviewViewModel.js";
import {OpenDefaultViewModel} from "./OpenDefaultViewModel.js";
import {ServerConsentViewModel} from "./ServerConsentViewModel.js";
import {getLabelForLinkKind} from "../Link.js";
import {orderedUnique} from "../utils/unique.js";
import {getMatchingPlatforms, selectPlatforms} from "./clients/index.js";
export class OpenLinkViewModel extends ViewModel {
constructor(options) {
@ -28,12 +30,53 @@ export class OpenLinkViewModel extends ViewModel {
const {clients, link} = options;
this._link = link;
this._clients = clients;
this.openDefaultViewModel = null;
this.serverConsentViewModel = null;
this.previewViewModel = null;
this.clientsViewModel = null;
this.previewLoading = false;
this.tryingLink = false;
this._tryLink();
if (!this._tryOpenDefault()) {
this._activeOpen();
}
}
_tryOpenDefault() {
const client = this._getPreferredClient();
let proposedPlatform = null;
let webPlatform = null;
if (client) {
const matchingPlatforms = getMatchingPlatforms(client, this.platforms);
const selectedPlatforms = selectPlatforms(matchingPlatforms, this.preferences.platform);
if (selectedPlatforms.proposedPlatform !== selectedPlatforms.nativePlatform) {
// Do not auto-open web applications
return false;
}
proposedPlatform = selectedPlatforms.proposedPlatform;
webPlatform = selectedPlatforms.webPlatform;
if (!client.getDeepLink(proposedPlatform, this._link)) {
// Client doesn't support deep links. We can't open it.
return false;
}
}
this.openDefaultViewModel = new OpenDefaultViewModel(this.childOptions({
client,
link: this._link,
openLinkVM: this,
proposedPlatform,
webPlatform,
}));
this.openDefaultViewModel.tryOpenLink();
return true;
}
closeDefault() {
this.openDefaultViewModel = null;
this._activeOpen();
}
_activeOpen() {
if (this.preferences.homeservers === null) {
this._showServerConsent();
} else {
@ -41,18 +84,6 @@ export class OpenLinkViewModel extends ViewModel {
}
}
_tryLink() {
const matrixUrl = this._link.toMatrixUrl()
if (matrixUrl) {
this.tryingLink = true;
this.setTimeout(() => {
this.tryingLink = false;
this.emitChange();
}, 1000);
this.openLink(matrixUrl);
}
}
_showServerConsent() {
let servers = [];
if (this.preferences.homeservers) {
@ -67,11 +98,16 @@ export class OpenLinkViewModel extends ViewModel {
this._showLink();
}
}));
this.emitChange();
}
_getPreferredClient() {
const clientId = this.preferences.clientId || this._link.clientId;
return clientId ? this._clients.find(c => c.id === clientId) : null;
}
async _showLink() {
const clientId = this.preferences.clientId || this._link.clientId;
const preferredClient = clientId ? this._clients.find(c => c.id === clientId) : null;
const preferredClient = this._getPreferredClient();
this.clientsViewModel = new ClientListViewModel(this.childOptions({
clients: this._clients,
link: this._link,