commit
224ab2672a
3 changed files with 150 additions and 11 deletions
|
@ -23,6 +23,7 @@ import {imageToInfo} from "../common.js";
|
||||||
// TODO: remove fallback so default isn't included in bundle for SDK users that have their custom tileClassForEntry
|
// 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
|
// this is a breaking SDK change though to make this option mandatory
|
||||||
import {tileClassForEntry as defaultTileClassForEntry} from "./timeline/tiles/index";
|
import {tileClassForEntry as defaultTileClassForEntry} from "./timeline/tiles/index";
|
||||||
|
import {RoomStatus} from "../../../matrix/room/common";
|
||||||
|
|
||||||
export class RoomViewModel extends ViewModel {
|
export class RoomViewModel extends ViewModel {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
|
@ -197,19 +198,90 @@ export class RoomViewModel extends ViewModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _processCommandJoin(roomName) {
|
||||||
|
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);
|
||||||
|
} catch (err) {
|
||||||
|
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}'`);
|
||||||
|
} else {
|
||||||
|
exc = err;
|
||||||
|
}
|
||||||
|
this._sendError = exc;
|
||||||
|
this._timelineError = null;
|
||||||
|
this.emitChange("error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async _processCommand (message) {
|
||||||
|
let msgtype;
|
||||||
|
const [commandName, ...args] = message.substring(1).split(" ");
|
||||||
|
switch (commandName) {
|
||||||
|
case "me":
|
||||||
|
message = args.join(" ");
|
||||||
|
msgtype = "m.emote";
|
||||||
|
break;
|
||||||
|
case "join":
|
||||||
|
if (args.length === 1) {
|
||||||
|
const roomName = args[0];
|
||||||
|
await this._processCommandJoin(roomName);
|
||||||
|
} else {
|
||||||
|
this._sendError = new Error("join syntax: /join <room-id>");
|
||||||
|
this._timelineError = null;
|
||||||
|
this.emitChange("error");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "shrug":
|
||||||
|
message = "¯\\_(ツ)_/¯ " + args.join(" ");
|
||||||
|
msgtype = "m.text";
|
||||||
|
break;
|
||||||
|
case "tableflip":
|
||||||
|
message = "(╯°□°)╯︵ ┻━┻ " + args.join(" ");
|
||||||
|
msgtype = "m.text";
|
||||||
|
break;
|
||||||
|
case "unflip":
|
||||||
|
message = "┬──┬ ノ( ゜-゜ノ) " + args.join(" ");
|
||||||
|
msgtype = "m.text";
|
||||||
|
break;
|
||||||
|
case "lenny":
|
||||||
|
message = "( ͡° ͜ʖ ͡°) " + args.join(" ");
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
return {type: msgtype, message: message};
|
||||||
|
}
|
||||||
|
|
||||||
async _sendMessage(message, replyingTo) {
|
async _sendMessage(message, replyingTo) {
|
||||||
if (!this._room.isArchived && message) {
|
if (!this._room.isArchived && message) {
|
||||||
try {
|
let messinfo = {type : "m.text", message : message};
|
||||||
let msgtype = "m.text";
|
if (message.startsWith("//")) {
|
||||||
if (message.startsWith("/me ")) {
|
messinfo.message = message.substring(1).trim();
|
||||||
message = message.substr(4).trim();
|
} else if (message.startsWith("/")) {
|
||||||
msgtype = "m.emote";
|
messinfo = await this._processCommand(message);
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
const msgtype = messinfo.type;
|
||||||
|
const message = messinfo.message;
|
||||||
|
if (msgtype && message) {
|
||||||
if (replyingTo) {
|
if (replyingTo) {
|
||||||
await replyingTo.reply(msgtype, message);
|
await replyingTo.reply(msgtype, message);
|
||||||
} else {
|
} else {
|
||||||
await this._room.sendEvent("m.room.message", {msgtype, body: message});
|
await this._room.sendEvent("m.room.message", {msgtype, body: message});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`room.sendMessage(): ${err.message}:\n${err.stack}`);
|
console.error(`room.sendMessage(): ${err.message}:\n${err.stack}`);
|
||||||
this._sendError = err;
|
this._sendError = err;
|
||||||
|
@ -353,6 +425,11 @@ export class RoomViewModel extends ViewModel {
|
||||||
this._composerVM.setReplyingTo(entry);
|
this._composerVM.setReplyingTo(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dismissError(evt) {
|
||||||
|
this._sendError = null;
|
||||||
|
this.emitChange("error");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function videoToInfo(video) {
|
function videoToInfo(video) {
|
||||||
|
|
|
@ -521,6 +521,62 @@ a {
|
||||||
|
|
||||||
.RoomView_error {
|
.RoomView_error {
|
||||||
color: var(--error-color);
|
color: var(--error-color);
|
||||||
|
background : #efefef;
|
||||||
|
height : 0px;
|
||||||
|
font-weight : bold;
|
||||||
|
transition : 0.25s all ease-out;
|
||||||
|
padding-right : 20px;
|
||||||
|
padding-left : 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RoomView_error div{
|
||||||
|
overflow : hidden;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
position : relative;
|
||||||
|
display : flex;
|
||||||
|
align-items : center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RoomView_error:not(:empty) {
|
||||||
|
height : auto;
|
||||||
|
padding-top : 20px;
|
||||||
|
padding-bottom : 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RoomView_error p {
|
||||||
|
position : relative;
|
||||||
|
display : block;
|
||||||
|
width : 100%;
|
||||||
|
height : auto;
|
||||||
|
margin : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RoomView_error button {
|
||||||
|
width : 40px;
|
||||||
|
padding-top : 20px;
|
||||||
|
padding-bottom : 20px;
|
||||||
|
background : none;
|
||||||
|
border : none;
|
||||||
|
position : relative;
|
||||||
|
border-radius : 5px;
|
||||||
|
transition: 0.1s all ease-out;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RoomView_error button:hover {
|
||||||
|
background : #cfcfcf;
|
||||||
|
}
|
||||||
|
|
||||||
|
.RoomView_error button:before {
|
||||||
|
content:"\274c";
|
||||||
|
position : absolute;
|
||||||
|
top : 15px;
|
||||||
|
left: 9px;
|
||||||
|
width : 20px;
|
||||||
|
height : 10px;
|
||||||
|
font-size : 10px;
|
||||||
|
align-self : middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.MessageComposer_replyPreview .Timeline_message {
|
.MessageComposer_replyPreview .Timeline_message {
|
||||||
|
|
|
@ -46,7 +46,13 @@ export class RoomView extends TemplateView {
|
||||||
})
|
})
|
||||||
]),
|
]),
|
||||||
t.div({className: "RoomView_body"}, [
|
t.div({className: "RoomView_body"}, [
|
||||||
t.div({className: "RoomView_error"}, vm => vm.error),
|
t.div({className: "RoomView_error"}, [
|
||||||
|
t.if(vm => vm.error, t => t.div(
|
||||||
|
[
|
||||||
|
t.p({}, vm => vm.error),
|
||||||
|
t.button({ className: "RoomView_error_closerButton", onClick: evt => vm.dismissError(evt) })
|
||||||
|
])
|
||||||
|
)]),
|
||||||
t.mapView(vm => vm.timelineViewModel, timelineViewModel => {
|
t.mapView(vm => vm.timelineViewModel, timelineViewModel => {
|
||||||
return timelineViewModel ?
|
return timelineViewModel ?
|
||||||
new TimelineView(timelineViewModel, this._viewClassForTile) :
|
new TimelineView(timelineViewModel, this._viewClassForTile) :
|
||||||
|
|
Reference in a new issue