Add a view model for opening a client
This commit is contained in:
parent
820a090a71
commit
a781c527fd
3 changed files with 128 additions and 22 deletions
67
src/open/OpenDefaultViewModel.js
Normal file
67
src/open/OpenDefaultViewModel.js
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,17 +22,20 @@ import {ServerConsentView} from "./ServerConsentView.js";
|
||||||
export class OpenLinkView extends TemplateView {
|
export class OpenLinkView extends TemplateView {
|
||||||
render(t, vm) {
|
render(t, vm) {
|
||||||
return t.div({className: "OpenLinkView card"}, [
|
return t.div({className: "OpenLinkView card"}, [
|
||||||
t.map(vm => vm.tryingLink, tryingLink => tryingLink ?
|
t.mapView(vm => [ vm.openDefaultViewModel, vm.previewViewModel ], ([openDefaultVM, previewVM]) => {
|
||||||
t.view(new TryingLinkView(vm)) :
|
if (openDefaultVM) {
|
||||||
t.mapView(vm => vm.previewViewModel, previewVM => previewVM ?
|
return new TryingLinkView(openDefaultVM)
|
||||||
new ShowLinkView(vm) :
|
} else if (previewVM) {
|
||||||
new ServerConsentView(vm.serverConsentViewModel)
|
return new ShowLinkView(vm);
|
||||||
),
|
} else {
|
||||||
),
|
return new ServerConsentView(vm.serverConsentViewModel);
|
||||||
|
}
|
||||||
|
}),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class TryingLinkView extends TemplateView {
|
class TryingLinkView extends TemplateView {
|
||||||
render (t, vm) {
|
render (t, vm) {
|
||||||
return t.div({ className: "OpeningClientView" }, [
|
return t.div({ className: "OpeningClientView" }, [
|
||||||
|
|
|
@ -18,9 +18,11 @@ import {ViewModel} from "../utils/ViewModel.js";
|
||||||
import {ClientListViewModel} from "./ClientListViewModel.js";
|
import {ClientListViewModel} from "./ClientListViewModel.js";
|
||||||
import {ClientViewModel} from "./ClientViewModel.js";
|
import {ClientViewModel} from "./ClientViewModel.js";
|
||||||
import {PreviewViewModel} from "../preview/PreviewViewModel.js";
|
import {PreviewViewModel} from "../preview/PreviewViewModel.js";
|
||||||
|
import {OpenDefaultViewModel} from "./OpenDefaultViewModel.js";
|
||||||
import {ServerConsentViewModel} from "./ServerConsentViewModel.js";
|
import {ServerConsentViewModel} from "./ServerConsentViewModel.js";
|
||||||
import {getLabelForLinkKind} from "../Link.js";
|
import {getLabelForLinkKind} from "../Link.js";
|
||||||
import {orderedUnique} from "../utils/unique.js";
|
import {orderedUnique} from "../utils/unique.js";
|
||||||
|
import {getMatchingPlatforms, selectPlatforms} from "./clients/index.js";
|
||||||
|
|
||||||
export class OpenLinkViewModel extends ViewModel {
|
export class OpenLinkViewModel extends ViewModel {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
|
@ -28,12 +30,53 @@ export class OpenLinkViewModel extends ViewModel {
|
||||||
const {clients, link} = options;
|
const {clients, link} = options;
|
||||||
this._link = link;
|
this._link = link;
|
||||||
this._clients = clients;
|
this._clients = clients;
|
||||||
|
this.openDefaultViewModel = null;
|
||||||
this.serverConsentViewModel = null;
|
this.serverConsentViewModel = null;
|
||||||
this.previewViewModel = null;
|
this.previewViewModel = null;
|
||||||
this.clientsViewModel = null;
|
this.clientsViewModel = null;
|
||||||
this.previewLoading = false;
|
this.previewLoading = false;
|
||||||
this.tryingLink = 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) {
|
if (this.preferences.homeservers === null) {
|
||||||
this._showServerConsent();
|
this._showServerConsent();
|
||||||
} else {
|
} 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() {
|
_showServerConsent() {
|
||||||
let servers = [];
|
let servers = [];
|
||||||
if (this.preferences.homeservers) {
|
if (this.preferences.homeservers) {
|
||||||
|
@ -67,11 +98,16 @@ export class OpenLinkViewModel extends ViewModel {
|
||||||
this._showLink();
|
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() {
|
async _showLink() {
|
||||||
const clientId = this.preferences.clientId || this._link.clientId;
|
const preferredClient = this._getPreferredClient();
|
||||||
const preferredClient = clientId ? this._clients.find(c => c.id === clientId) : null;
|
|
||||||
this.clientsViewModel = new ClientListViewModel(this.childOptions({
|
this.clientsViewModel = new ClientListViewModel(this.childOptions({
|
||||||
clients: this._clients,
|
clients: this._clients,
|
||||||
link: this._link,
|
link: this._link,
|
||||||
|
|
Loading…
Reference in a new issue