2020-08-05 22:08:55 +05:30
|
|
|
|
/*
|
|
|
|
|
Copyright 2020 Bruno Windels <bruno@windels.cloud>
|
2020-08-17 20:04:25 +05:30
|
|
|
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
2020-08-05 22:08:55 +05:30
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
*/
|
|
|
|
|
|
2020-04-21 00:56:39 +05:30
|
|
|
|
import {TimelineViewModel} from "./timeline/TimelineViewModel.js";
|
2021-08-04 02:32:11 +05:30
|
|
|
|
import {ComposerViewModel} from "./ComposerViewModel.js"
|
2022-02-25 15:52:54 +05:30
|
|
|
|
import {avatarInitials, getIdentifierColorNumber, getAvatarHttpUrl} from "../../avatar";
|
2022-02-14 22:23:59 +05:30
|
|
|
|
import {ViewModel} from "../../ViewModel";
|
2022-02-09 23:32:51 +05:30
|
|
|
|
import {imageToInfo} from "../common.js";
|
2022-04-08 17:49:34 +05:30
|
|
|
|
// TODO: remove fallback so default isn't included in bundle for SDK users that have their custom tileClassForEntry
|
|
|
|
|
// this is a breaking SDK change though to make this option mandatory
|
|
|
|
|
import {tileClassForEntry as defaultTileClassForEntry} from "./timeline/tiles/index";
|
2022-07-26 18:18:03 +05:30
|
|
|
|
import {RoomStatus} from "../../../matrix/room/common";
|
2019-02-28 03:20:08 +05:30
|
|
|
|
|
2020-05-04 22:53:11 +05:30
|
|
|
|
export class RoomViewModel extends ViewModel {
|
|
|
|
|
constructor(options) {
|
|
|
|
|
super(options);
|
2022-04-08 16:22:30 +05:30
|
|
|
|
const {room, tileClassForEntry} = options;
|
2019-02-28 03:20:08 +05:30
|
|
|
|
this._room = room;
|
2019-06-01 21:59:23 +05:30
|
|
|
|
this._timelineVM = null;
|
2022-04-08 17:49:34 +05:30
|
|
|
|
this._tileClassForEntry = tileClassForEntry ?? defaultTileClassForEntry;
|
2022-04-08 16:22:30 +05:30
|
|
|
|
this._tileOptions = undefined;
|
2019-02-28 03:20:08 +05:30
|
|
|
|
this._onRoomChange = this._onRoomChange.bind(this);
|
2019-03-09 05:13:43 +05:30
|
|
|
|
this._timelineError = null;
|
2020-03-31 01:03:04 +05:30
|
|
|
|
this._sendError = null;
|
2021-05-11 16:41:11 +05:30
|
|
|
|
this._composerVM = null;
|
|
|
|
|
if (room.isArchived) {
|
2022-07-07 16:39:45 +05:30
|
|
|
|
this._composerVM = this.track(new ArchivedViewModel(this.childOptions({archivedRoom: room})));
|
2021-05-11 16:41:11 +05:30
|
|
|
|
} else {
|
2022-07-07 16:45:18 +05:30
|
|
|
|
this._recreateComposerOnPowerLevelChange();
|
2021-05-11 16:41:11 +05:30
|
|
|
|
}
|
2020-08-21 15:27:49 +05:30
|
|
|
|
this._clearUnreadTimout = null;
|
2020-10-16 16:32:21 +05:30
|
|
|
|
this._closeUrl = this.urlCreator.urlUntilSegment("session");
|
2020-10-14 18:23:52 +05:30
|
|
|
|
}
|
|
|
|
|
|
2019-06-27 02:44:39 +05:30
|
|
|
|
async load() {
|
2019-02-28 03:20:08 +05:30
|
|
|
|
this._room.on("change", this._onRoomChange);
|
2019-03-09 05:13:43 +05:30
|
|
|
|
try {
|
2021-02-24 15:51:04 +05:30
|
|
|
|
const timeline = await this._room.openTimeline();
|
2022-04-08 16:22:30 +05:30
|
|
|
|
this._tileOptions = this.childOptions({
|
2021-07-20 04:40:35 +05:30
|
|
|
|
roomVM: this,
|
2021-02-24 15:51:04 +05:30
|
|
|
|
timeline,
|
2022-04-08 16:22:30 +05:30
|
|
|
|
tileClassForEntry: this._tileClassForEntry,
|
|
|
|
|
});
|
2021-08-05 22:09:59 +05:30
|
|
|
|
this._timelineVM = this.track(new TimelineViewModel(this.childOptions({
|
2022-04-08 16:22:30 +05:30
|
|
|
|
tileOptions: this._tileOptions,
|
2021-08-05 22:09:59 +05:30
|
|
|
|
timeline,
|
2020-10-19 16:27:21 +05:30
|
|
|
|
})));
|
2020-05-04 22:53:11 +05:30
|
|
|
|
this.emitChange("timelineViewModel");
|
2019-03-09 05:13:43 +05:30
|
|
|
|
} catch (err) {
|
2019-06-02 18:29:30 +05:30
|
|
|
|
console.error(`room.openTimeline(): ${err.message}:\n${err.stack}`);
|
2019-03-09 05:13:43 +05:30
|
|
|
|
this._timelineError = err;
|
2020-05-04 22:53:11 +05:30
|
|
|
|
this.emitChange("error");
|
2019-03-09 05:13:43 +05:30
|
|
|
|
}
|
2020-10-07 16:00:46 +05:30
|
|
|
|
this._clearUnreadAfterDelay();
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-07 16:45:18 +05:30
|
|
|
|
async _recreateComposerOnPowerLevelChange() {
|
2022-07-07 16:39:45 +05:30
|
|
|
|
const powerLevelObservable = await this._room.observePowerLevels();
|
2022-07-07 17:23:23 +05:30
|
|
|
|
const canSendMessage = () => powerLevelObservable.get().canSendType("m.room.message");
|
|
|
|
|
let oldCanSendMessage = canSendMessage();
|
2022-07-07 16:39:45 +05:30
|
|
|
|
const recreateComposer = newCanSendMessage => {
|
|
|
|
|
this._composerVM = this.disposeTracked(this._composerVM);
|
|
|
|
|
if (newCanSendMessage) {
|
|
|
|
|
this._composerVM = this.track(new ComposerViewModel(this));
|
|
|
|
|
}
|
|
|
|
|
else {
|
2022-07-07 18:16:33 +05:30
|
|
|
|
this._composerVM = this.track(new LowerPowerLevelViewModel(this.childOptions()));
|
2022-07-07 16:39:45 +05:30
|
|
|
|
}
|
|
|
|
|
this.emitChange("powerLevelObservable")
|
|
|
|
|
};
|
2022-07-07 17:23:23 +05:30
|
|
|
|
this.track(powerLevelObservable.subscribe(() => {
|
|
|
|
|
const newCanSendMessage = canSendMessage();
|
2022-07-07 16:39:45 +05:30
|
|
|
|
if (oldCanSendMessage !== newCanSendMessage) {
|
|
|
|
|
recreateComposer(newCanSendMessage);
|
|
|
|
|
oldCanSendMessage = newCanSendMessage;
|
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
recreateComposer(oldCanSendMessage);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-07 16:00:46 +05:30
|
|
|
|
async _clearUnreadAfterDelay() {
|
2021-05-11 16:41:11 +05:30
|
|
|
|
if (this._room.isArchived || this._clearUnreadTimout) {
|
2020-10-07 16:00:46 +05:30
|
|
|
|
return;
|
|
|
|
|
}
|
2020-08-21 15:27:49 +05:30
|
|
|
|
this._clearUnreadTimout = this.clock.createTimeout(2000);
|
|
|
|
|
try {
|
|
|
|
|
await this._clearUnreadTimout.elapsed();
|
|
|
|
|
await this._room.clearUnread();
|
2020-10-07 16:00:46 +05:30
|
|
|
|
this._clearUnreadTimout = null;
|
2020-08-21 15:27:49 +05:30
|
|
|
|
} catch (err) {
|
|
|
|
|
if (err.name !== "AbortError") {
|
|
|
|
|
throw err;
|
2021-04-23 21:36:38 +05:30
|
|
|
|
}
|
2020-08-21 15:27:49 +05:30
|
|
|
|
}
|
2019-02-28 03:20:08 +05:30
|
|
|
|
}
|
|
|
|
|
|
2020-10-07 16:00:46 +05:30
|
|
|
|
focus() {
|
|
|
|
|
this._clearUnreadAfterDelay();
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-27 02:44:39 +05:30
|
|
|
|
dispose() {
|
2020-09-10 21:13:01 +05:30
|
|
|
|
super.dispose();
|
2020-10-14 14:56:10 +05:30
|
|
|
|
this._room.off("change", this._onRoomChange);
|
2021-05-11 19:39:58 +05:30
|
|
|
|
if (this._room.isArchived) {
|
|
|
|
|
this._room.release();
|
|
|
|
|
}
|
2020-08-21 15:27:49 +05:30
|
|
|
|
if (this._clearUnreadTimout) {
|
|
|
|
|
this._clearUnreadTimout.abort();
|
|
|
|
|
this._clearUnreadTimout = null;
|
|
|
|
|
}
|
2019-02-28 03:20:08 +05:30
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// room doesn't tell us yet which fields changed,
|
|
|
|
|
// so emit all fields originating from summary
|
|
|
|
|
_onRoomChange() {
|
2022-02-04 15:46:58 +05:30
|
|
|
|
// propagate the update to the child view models so it's bindings can update based on room changes
|
|
|
|
|
this._composerVM.emitChange();
|
2021-05-07 16:41:17 +05:30
|
|
|
|
this.emitChange();
|
2019-02-28 03:20:08 +05:30
|
|
|
|
}
|
|
|
|
|
|
2021-04-21 19:15:51 +05:30
|
|
|
|
get kind() { return "room"; }
|
2021-04-21 19:04:35 +05:30
|
|
|
|
get closeUrl() { return this._closeUrl; }
|
|
|
|
|
get name() { return this._room.name || this.i18n`Empty Room`; }
|
|
|
|
|
get id() { return this._room.id; }
|
|
|
|
|
get timelineViewModel() { return this._timelineVM; }
|
|
|
|
|
get isEncrypted() { return this._room.isEncrypted; }
|
2020-09-11 15:05:53 +05:30
|
|
|
|
|
2019-03-09 05:13:43 +05:30
|
|
|
|
get error() {
|
|
|
|
|
if (this._timelineError) {
|
|
|
|
|
return `Something went wrong loading the timeline: ${this._timelineError.message}`;
|
|
|
|
|
}
|
2020-03-31 01:03:04 +05:30
|
|
|
|
if (this._sendError) {
|
|
|
|
|
return `Something went wrong sending your message: ${this._sendError.message}`;
|
|
|
|
|
}
|
2019-06-16 18:51:20 +05:30
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-20 21:03:08 +05:30
|
|
|
|
get avatarLetter() {
|
2020-08-21 21:44:32 +05:30
|
|
|
|
return avatarInitials(this.name);
|
2019-03-09 05:13:43 +05:30
|
|
|
|
}
|
2019-07-27 14:10:56 +05:30
|
|
|
|
|
2020-08-13 16:11:00 +05:30
|
|
|
|
get avatarColorNumber() {
|
2021-06-29 00:14:27 +05:30
|
|
|
|
return getIdentifierColorNumber(this._room.avatarColorId)
|
2020-08-13 16:11:00 +05:30
|
|
|
|
}
|
2020-08-20 21:03:08 +05:30
|
|
|
|
|
2021-04-28 17:40:54 +05:30
|
|
|
|
avatarUrl(size) {
|
|
|
|
|
return getAvatarHttpUrl(this._room.avatarUrl, size, this.platform, this._room.mediaRepository);
|
2020-08-20 21:03:08 +05:30
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get avatarTitle() {
|
|
|
|
|
return this.name;
|
|
|
|
|
}
|
2021-05-12 17:29:08 +05:30
|
|
|
|
|
|
|
|
|
get canLeave() {
|
|
|
|
|
return this._room.isJoined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
leaveRoom() {
|
|
|
|
|
this._room.leave();
|
|
|
|
|
}
|
2021-05-12 19:08:54 +05:30
|
|
|
|
|
|
|
|
|
get canForget() {
|
|
|
|
|
return this._room.isArchived;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
forgetRoom() {
|
|
|
|
|
this._room.forget();
|
|
|
|
|
}
|
2021-05-18 14:37:46 +05:30
|
|
|
|
|
|
|
|
|
get canRejoin() {
|
|
|
|
|
return this._room.isArchived;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rejoinRoom() {
|
|
|
|
|
this._room.join();
|
|
|
|
|
}
|
2021-08-05 22:35:50 +05:30
|
|
|
|
|
|
|
|
|
_createTile(entry) {
|
2022-04-08 16:22:30 +05:30
|
|
|
|
if (this._tileOptions) {
|
|
|
|
|
const Tile = this._tileOptions.tileClassForEntry(entry);
|
|
|
|
|
if (Tile) {
|
|
|
|
|
return new Tile(entry, this._tileOptions);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-08-05 22:35:50 +05:30
|
|
|
|
}
|
2020-05-05 01:53:43 +05:30
|
|
|
|
|
2022-07-28 12:53:30 +05:30
|
|
|
|
async _processCommandJoin(roomName) {
|
2022-07-27 18:48:32 +05:30
|
|
|
|
try {
|
|
|
|
|
const roomId = await this._options.client.session.joinRoom(roomName);
|
|
|
|
|
const roomStatusObserver = await this._options.client.session.observeRoomStatus(roomId);
|
|
|
|
|
await roomStatusObserver.waitFor(status => status === RoomStatus.Joined);
|
|
|
|
|
this.navigation.push("room", roomId);
|
2022-07-28 13:44:21 +05:30
|
|
|
|
} catch (err) {
|
2022-07-28 13:56:59 +05:30
|
|
|
|
let exc;
|
|
|
|
|
if ((err.statusCode ?? err.status) === 400) {
|
|
|
|
|
exc = new Error(`/join : '${roomName}' was not legal room ID or room alias`);
|
|
|
|
|
} else if ((err.statusCode ?? err.status) === 404 || (err.statusCode ?? err.status) === 502 || err.message == "Internal Server Error") {
|
|
|
|
|
exc = new Error(`/join : room '${roomName}' not found`);
|
|
|
|
|
} else if ((err.statusCode ?? err.status) === 403) {
|
|
|
|
|
exc = new Error(`/join : you're not invited to join '${roomName}'`);
|
2022-07-28 13:44:21 +05:30
|
|
|
|
} else {
|
2022-07-28 13:56:59 +05:30
|
|
|
|
exc = err;
|
2022-07-27 20:12:44 +05:30
|
|
|
|
}
|
2022-07-28 12:53:30 +05:30
|
|
|
|
this._sendError = exc;
|
2022-07-27 20:12:44 +05:30
|
|
|
|
this._timelineError = null;
|
|
|
|
|
this.emitChange("error");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-25 18:52:06 +05:30
|
|
|
|
async _processCommand (message) {
|
2022-07-28 12:53:30 +05:30
|
|
|
|
let msgtype;
|
2022-07-25 18:52:06 +05:30
|
|
|
|
const [commandName, ...args] = message.substring(1).split(" ");
|
|
|
|
|
switch (commandName) {
|
|
|
|
|
case "me":
|
2022-07-26 14:07:05 +05:30
|
|
|
|
message = args.join(" ");
|
2022-07-25 18:52:06 +05:30
|
|
|
|
msgtype = "m.emote";
|
|
|
|
|
break;
|
|
|
|
|
case "join":
|
2022-07-28 12:56:08 +05:30
|
|
|
|
if (args.length === 1) {
|
2022-07-27 18:48:32 +05:30
|
|
|
|
const roomName = args[0];
|
2022-07-27 20:12:44 +05:30
|
|
|
|
await this._processCommandJoin(roomName);
|
2022-07-27 18:48:32 +05:30
|
|
|
|
} else {
|
|
|
|
|
this._sendError = new Error("join syntax: /join <room-id>");
|
|
|
|
|
this._timelineError = null;
|
|
|
|
|
this.emitChange("error");
|
|
|
|
|
}
|
2022-07-25 18:52:06 +05:30
|
|
|
|
break;
|
|
|
|
|
case "shrug":
|
2022-07-26 14:07:05 +05:30
|
|
|
|
message = "¯\\_(ツ)_/¯ " + args.join(" ");
|
2022-07-25 18:52:06 +05:30
|
|
|
|
msgtype = "m.text";
|
|
|
|
|
break;
|
|
|
|
|
case "tableflip":
|
2022-07-29 15:17:47 +05:30
|
|
|
|
message = "(╯°□°)╯︵ ┻━┻ " + args.join(" ");
|
2022-07-25 18:52:06 +05:30
|
|
|
|
msgtype = "m.text";
|
|
|
|
|
break;
|
|
|
|
|
case "unflip":
|
2022-07-29 15:17:47 +05:30
|
|
|
|
message = "┬──┬ ノ( ゜-゜ノ) " + args.join(" ");
|
2022-07-25 18:52:06 +05:30
|
|
|
|
msgtype = "m.text";
|
|
|
|
|
break;
|
|
|
|
|
case "lenny":
|
2022-07-29 15:17:47 +05:30
|
|
|
|
message = "( ͡° ͜ʖ ͡°) " + args.join(" ");
|
2022-07-25 18:52:06 +05:30
|
|
|
|
msgtype = "m.text";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
this._sendError = new Error(`no command name "${commandName}". To send the message instead of executing, please type "/${message}"`);
|
|
|
|
|
this._timelineError = null;
|
|
|
|
|
this.emitChange("error");
|
|
|
|
|
message = undefined;
|
2022-07-21 17:25:23 +05:30
|
|
|
|
}
|
2022-07-22 19:38:53 +05:30
|
|
|
|
return {type: msgtype, message: message};
|
2022-07-21 17:25:23 +05:30
|
|
|
|
}
|
|
|
|
|
|
2021-07-24 03:04:11 +05:30
|
|
|
|
async _sendMessage(message, replyingTo) {
|
2021-05-11 16:41:11 +05:30
|
|
|
|
if (!this._room.isArchived && message) {
|
2022-07-27 20:06:58 +05:30
|
|
|
|
let messinfo = {type : "m.text", message : message};
|
2022-07-25 18:52:06 +05:30
|
|
|
|
if (message.startsWith("//")) {
|
|
|
|
|
messinfo.message = message.substring(1).trim();
|
|
|
|
|
} else if (message.startsWith("/")) {
|
|
|
|
|
messinfo = await this._processCommand(message);
|
|
|
|
|
}
|
2019-09-15 15:53:26 +05:30
|
|
|
|
try {
|
2022-07-27 20:06:58 +05:30
|
|
|
|
const msgtype = messinfo.type;
|
|
|
|
|
const message = messinfo.message;
|
|
|
|
|
if (msgtype && message) {
|
|
|
|
|
if (replyingTo) {
|
|
|
|
|
await replyingTo.reply(msgtype, message);
|
|
|
|
|
} else {
|
|
|
|
|
await this._room.sendEvent("m.room.message", {msgtype, body: message});
|
|
|
|
|
}
|
2021-07-21 01:23:31 +05:30
|
|
|
|
}
|
2019-09-15 15:53:26 +05:30
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error(`room.sendMessage(): ${err.message}:\n${err.stack}`);
|
2020-03-31 01:03:04 +05:30
|
|
|
|
this._sendError = err;
|
|
|
|
|
this._timelineError = null;
|
2020-05-04 22:53:11 +05:30
|
|
|
|
this.emitChange("error");
|
2019-09-15 15:53:26 +05:30
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
2019-07-29 23:24:21 +05:30
|
|
|
|
}
|
2019-09-15 15:53:26 +05:30
|
|
|
|
return false;
|
2019-07-27 14:10:56 +05:30
|
|
|
|
}
|
2020-05-05 01:53:43 +05:30
|
|
|
|
|
2020-11-19 00:37:31 +05:30
|
|
|
|
async _pickAndSendFile() {
|
2020-11-11 15:17:55 +05:30
|
|
|
|
try {
|
2020-11-19 00:37:31 +05:30
|
|
|
|
const file = await this.platform.openFile();
|
|
|
|
|
if (!file) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
return this._sendFile(file);
|
2020-11-11 15:17:55 +05:30
|
|
|
|
} catch (err) {
|
2020-11-19 00:37:31 +05:30
|
|
|
|
console.error(err);
|
2020-11-11 03:06:26 +05:30
|
|
|
|
}
|
2020-11-19 00:37:31 +05:30
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async _sendFile(file) {
|
2020-11-11 03:06:26 +05:30
|
|
|
|
const content = {
|
|
|
|
|
body: file.name,
|
2020-11-13 23:43:35 +05:30
|
|
|
|
msgtype: "m.file"
|
2020-11-11 03:06:26 +05:30
|
|
|
|
};
|
2020-11-13 23:43:35 +05:30
|
|
|
|
await this._room.sendEvent("m.room.message", content, {
|
|
|
|
|
"url": this._room.createAttachment(file.blob, file.name)
|
|
|
|
|
});
|
2020-11-11 03:06:26 +05:30
|
|
|
|
}
|
|
|
|
|
|
2021-03-10 00:05:25 +05:30
|
|
|
|
async _pickAndSendVideo() {
|
|
|
|
|
try {
|
|
|
|
|
if (!this.platform.hasReadPixelPermission()) {
|
|
|
|
|
alert("Please allow canvas image data access, so we can scale your images down.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-03-10 18:13:55 +05:30
|
|
|
|
const file = await this.platform.openFile("video/*");
|
2021-03-10 00:05:25 +05:30
|
|
|
|
if (!file) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!file.blob.mimeType.startsWith("video/")) {
|
|
|
|
|
return this._sendFile(file);
|
|
|
|
|
}
|
2021-03-10 18:13:55 +05:30
|
|
|
|
let video;
|
|
|
|
|
try {
|
|
|
|
|
video = await this.platform.loadVideo(file.blob);
|
|
|
|
|
} catch (err) {
|
|
|
|
|
// TODO: extract platform dependent code from view model
|
|
|
|
|
if (err instanceof window.MediaError && err.code === 4) {
|
|
|
|
|
throw new Error(`this browser does not support videos of type ${file?.blob.mimeType}.`);
|
|
|
|
|
} else {
|
|
|
|
|
throw err;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-03-10 00:05:25 +05:30
|
|
|
|
const content = {
|
|
|
|
|
body: file.name,
|
|
|
|
|
msgtype: "m.video",
|
|
|
|
|
info: videoToInfo(video)
|
|
|
|
|
};
|
|
|
|
|
const attachments = {
|
|
|
|
|
"url": this._room.createAttachment(video.blob, file.name),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const limit = await this.platform.settingsStorage.getInt("sentImageSizeLimit");
|
|
|
|
|
const maxDimension = limit || Math.min(video.maxDimension, 800);
|
|
|
|
|
const thumbnail = await video.scale(maxDimension);
|
|
|
|
|
content.info.thumbnail_info = imageToInfo(thumbnail);
|
|
|
|
|
attachments["info.thumbnail_url"] =
|
|
|
|
|
this._room.createAttachment(thumbnail.blob, file.name);
|
|
|
|
|
await this._room.sendEvent("m.room.message", content, attachments);
|
|
|
|
|
} catch (err) {
|
2021-03-10 18:13:55 +05:30
|
|
|
|
this._sendError = err;
|
2021-03-10 00:05:25 +05:30
|
|
|
|
this.emitChange("error");
|
|
|
|
|
console.error(err.stack);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-19 00:37:31 +05:30
|
|
|
|
async _pickAndSendPicture() {
|
2020-11-13 23:45:03 +05:30
|
|
|
|
try {
|
2020-11-19 00:37:31 +05:30
|
|
|
|
if (!this.platform.hasReadPixelPermission()) {
|
|
|
|
|
alert("Please allow canvas image data access, so we can scale your images down.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const file = await this.platform.openFile("image/*");
|
|
|
|
|
if (!file) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!file.blob.mimeType.startsWith("image/")) {
|
|
|
|
|
return this._sendFile(file);
|
|
|
|
|
}
|
2020-11-20 20:21:16 +05:30
|
|
|
|
let image = await this.platform.loadImage(file.blob);
|
|
|
|
|
const limit = await this.platform.settingsStorage.getInt("sentImageSizeLimit");
|
|
|
|
|
if (limit && image.maxDimension > limit) {
|
2022-02-09 23:32:51 +05:30
|
|
|
|
const scaledImage = await image.scale(limit);
|
|
|
|
|
image.dispose();
|
|
|
|
|
image = scaledImage;
|
2020-11-20 20:21:16 +05:30
|
|
|
|
}
|
2020-11-19 00:37:31 +05:30
|
|
|
|
const content = {
|
|
|
|
|
body: file.name,
|
|
|
|
|
msgtype: "m.image",
|
|
|
|
|
info: imageToInfo(image)
|
|
|
|
|
};
|
|
|
|
|
const attachments = {
|
|
|
|
|
"url": this._room.createAttachment(image.blob, file.name),
|
|
|
|
|
};
|
|
|
|
|
if (image.maxDimension > 600) {
|
|
|
|
|
const thumbnail = await image.scale(400);
|
|
|
|
|
content.info.thumbnail_info = imageToInfo(thumbnail);
|
|
|
|
|
attachments["info.thumbnail_url"] =
|
|
|
|
|
this._room.createAttachment(thumbnail.blob, file.name);
|
|
|
|
|
}
|
|
|
|
|
await this._room.sendEvent("m.room.message", content, attachments);
|
2020-11-13 23:45:03 +05:30
|
|
|
|
} catch (err) {
|
2021-03-10 00:05:25 +05:30
|
|
|
|
this._sendError = err;
|
|
|
|
|
this.emitChange("error");
|
|
|
|
|
console.error(err.stack);
|
2020-11-13 23:45:03 +05:30
|
|
|
|
}
|
|
|
|
|
}
|
2021-05-27 23:57:28 +05:30
|
|
|
|
|
2021-08-06 23:10:25 +05:30
|
|
|
|
get room() {
|
|
|
|
|
return this._room;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-05 01:53:43 +05:30
|
|
|
|
get composerViewModel() {
|
|
|
|
|
return this._composerVM;
|
|
|
|
|
}
|
2021-06-04 23:19:25 +05:30
|
|
|
|
|
2021-06-15 14:30:27 +05:30
|
|
|
|
openDetailsPanel() {
|
2021-06-04 23:19:25 +05:30
|
|
|
|
let path = this.navigation.path.until("room");
|
2021-06-30 14:22:39 +05:30
|
|
|
|
path = path.with(this.navigation.segment("right-panel", true));
|
2021-06-04 23:19:25 +05:30
|
|
|
|
path = path.with(this.navigation.segment("details", true));
|
|
|
|
|
this.navigation.applyPath(path);
|
|
|
|
|
}
|
2021-07-20 04:40:35 +05:30
|
|
|
|
|
2021-07-21 03:52:12 +05:30
|
|
|
|
startReply(entry) {
|
|
|
|
|
if (!this._room.isArchived) {
|
2021-07-22 00:17:52 +05:30
|
|
|
|
this._composerVM.setReplyingTo(entry);
|
2021-07-21 03:52:12 +05:30
|
|
|
|
}
|
2021-07-20 04:40:35 +05:30
|
|
|
|
}
|
2022-07-22 20:04:52 +05:30
|
|
|
|
|
|
|
|
|
dismissError(evt) {
|
|
|
|
|
this._sendError = null;
|
|
|
|
|
this.emitChange("error");
|
|
|
|
|
}
|
2020-05-05 01:53:43 +05:30
|
|
|
|
}
|
|
|
|
|
|
2021-03-10 00:05:25 +05:30
|
|
|
|
function videoToInfo(video) {
|
|
|
|
|
const info = imageToInfo(video);
|
|
|
|
|
info.duration = video.duration;
|
|
|
|
|
return info;
|
|
|
|
|
}
|
2021-05-11 16:41:11 +05:30
|
|
|
|
|
|
|
|
|
class ArchivedViewModel extends ViewModel {
|
|
|
|
|
constructor(options) {
|
|
|
|
|
super(options);
|
|
|
|
|
this._archivedRoom = options.archivedRoom;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get description() {
|
|
|
|
|
if (this._archivedRoom.isKicked) {
|
|
|
|
|
if (this._archivedRoom.kickReason) {
|
|
|
|
|
return this.i18n`You were kicked from the room by ${this._archivedRoom.kickedBy.name} because: ${this._archivedRoom.kickReason}`;
|
|
|
|
|
} else {
|
|
|
|
|
return this.i18n`You were kicked from the room by ${this._archivedRoom.kickedBy.name}.`;
|
|
|
|
|
}
|
|
|
|
|
} else if (this._archivedRoom.isBanned) {
|
|
|
|
|
if (this._archivedRoom.kickReason) {
|
|
|
|
|
return this.i18n`You were banned from the room by ${this._archivedRoom.kickedBy.name} because: ${this._archivedRoom.kickReason}`;
|
|
|
|
|
} else {
|
|
|
|
|
return this.i18n`You were banned from the room by ${this._archivedRoom.kickedBy.name}.`;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return this.i18n`You left this room`;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get kind() {
|
2022-07-07 17:26:43 +05:30
|
|
|
|
return "disabled";
|
2021-05-11 16:41:11 +05:30
|
|
|
|
}
|
2021-05-26 16:40:50 +05:30
|
|
|
|
}
|
2022-07-07 16:39:45 +05:30
|
|
|
|
|
|
|
|
|
class LowerPowerLevelViewModel extends ViewModel {
|
|
|
|
|
get description() {
|
|
|
|
|
return this.i18n`You do not have the powerlevel necessary to send messages`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get kind() {
|
2022-07-07 17:26:43 +05:30
|
|
|
|
return "disabled";
|
2022-07-07 16:39:45 +05:30
|
|
|
|
}
|
|
|
|
|
}
|