Merge branch 'dev'

This commit is contained in:
Iain Learmonth 2021-12-14 12:09:34 +00:00
commit 44b8c2ef73
8 changed files with 1045 additions and 950 deletions

1
.npmrc Normal file
View file

@ -0,0 +1 @@
@matrix-org:registry=https://gitlab.matrix.org/api/v4/projects/27/packages/npm/

138
package-lock.json generated
View file

@ -1,6 +1,6 @@
{ {
"name": "keanuapp-weblite", "name": "keanuapp-weblite",
"version": "0.1.16", "version": "0.1.19",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -1248,6 +1248,11 @@
} }
} }
}, },
"@matrix-org/olm": {
"version": "3.2.8",
"resolved": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz",
"integrity": "sha1-jVNjbQReF3biouxmE+VzMN2c6FY="
},
"@mrmlnc/readdir-enhanced": { "@mrmlnc/readdir-enhanced": {
"version": "2.2.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
@ -1836,6 +1841,17 @@
"color-convert": "^2.0.1" "color-convert": "^2.0.1"
} }
}, },
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"optional": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"cliui": { "cliui": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
@ -1868,6 +1884,13 @@
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true "dev": true
}, },
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"optional": true
},
"is-fullwidth-code-point": { "is-fullwidth-code-point": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
@ -1903,6 +1926,28 @@
"ansi-regex": "^5.0.0" "ansi-regex": "^5.0.0"
} }
}, },
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"optional": true,
"requires": {
"has-flag": "^4.0.0"
}
},
"vue-loader-v16": {
"version": "npm:vue-loader@16.8.3",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
"integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
"dev": true,
"optional": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
}
},
"wrap-ansi": { "wrap-ansi": {
"version": "6.2.0", "version": "6.2.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
@ -2731,9 +2776,9 @@
} }
}, },
"base-x": { "base-x": {
"version": "3.0.8", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz",
"integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==",
"requires": { "requires": {
"safe-buffer": "^5.0.1" "safe-buffer": "^5.0.1"
} }
@ -7971,9 +8016,9 @@
"integrity": "sha512-wRJtOo1v1ch+gN8PRsj0IGJznk+kQ8mz13ds/nuhLI+Qyf/931ZlRpd92oq0IRPpZIb+bhX8pRjzIVdcPDKmiQ==" "integrity": "sha512-wRJtOo1v1ch+gN8PRsj0IGJznk+kQ8mz13ds/nuhLI+Qyf/931ZlRpd92oq0IRPpZIb+bhX8pRjzIVdcPDKmiQ=="
}, },
"matrix-js-sdk": { "matrix-js-sdk": {
"version": "12.4.1", "version": "15.2.0",
"resolved": "https://registry.npmjs.org/matrix-js-sdk/-/matrix-js-sdk-12.4.1.tgz", "resolved": "https://registry.npmjs.org/matrix-js-sdk/-/matrix-js-sdk-15.2.0.tgz",
"integrity": "sha512-C9aSGX9e4GoCm0Rli+iGBXmcnRxnwETw7MvgNcSBfPaLHOMZi/wz4YOV7HEZK8R+OXuDrDYyglncWSJkkoDpAQ==", "integrity": "sha512-jZOM8Fn86oNvU3zVQcc+JTKKrtYq4ADN6rPZs4Mwxj/X/GDP+2YIP5176GtviF0GM6VO1dcnPZY73ykl8DayjA==",
"requires": { "requires": {
"@babel/runtime": "^7.12.5", "@babel/runtime": "^7.12.5",
"another-json": "^0.2.0", "another-json": "^0.2.0",
@ -8706,10 +8751,6 @@
"integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
"dev": true "dev": true
}, },
"olm": {
"version": "https://packages.matrix.org/npm/olm/olm-3.2.1.tgz",
"integrity": "sha512-B87bTpGIGieuV2FNauChjjQtVltwTGagQFoHm+3Dcse4amKAAGJB/I54dnP/JtbHZ+RYVoApM2OQ46Z4VH6eNg=="
},
"on-finished": { "on-finished": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
@ -10760,9 +10801,9 @@
} }
}, },
"qs": { "qs": {
"version": "6.10.1", "version": "6.10.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.2.tgz",
"integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", "integrity": "sha512-mSIdjzqznWgfd4pMii7sHtaYF8rx8861hBO80SraY5GT0XQibWZWJSid0avzHGkDIZLImux2S5mXO0Hfct2QCw==",
"requires": { "requires": {
"side-channel": "^1.0.4" "side-channel": "^1.0.4"
} }
@ -13230,75 +13271,6 @@
} }
} }
}, },
"vue-loader-v16": {
"version": "npm:vue-loader@16.5.0",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.5.0.tgz",
"integrity": "sha512-WXh+7AgFxGTgb5QAkQtFeUcHNIEq3PGVQ8WskY5ZiFbWBkOwcCPRs4w/2tVyTbh2q6TVRlO3xfvIukUtjsu62A==",
"dev": true,
"optional": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"optional": true,
"requires": {
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"optional": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"optional": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"optional": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"optional": true
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"optional": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"vue-property-decorator": { "vue-property-decorator": {
"version": "9.1.2", "version": "9.1.2",
"resolved": "https://registry.npmjs.org/vue-property-decorator/-/vue-property-decorator-9.1.2.tgz", "resolved": "https://registry.npmjs.org/vue-property-decorator/-/vue-property-decorator-9.1.2.tgz",

View file

@ -1,6 +1,6 @@
{ {
"name": "keanuapp-weblite", "name": "keanuapp-weblite",
"version": "0.1.19", "version": "0.1.21",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "serve": "vue-cli-service serve",
@ -9,6 +9,7 @@
"create-sticker-config": "node ./create_sticker_config.js $1" "create-sticker-config": "node ./create_sticker_config.js $1"
}, },
"dependencies": { "dependencies": {
"@matrix-org/olm": "^3.2.8",
"aes-js": "^3.1.2", "aes-js": "^3.1.2",
"axios": "^0.21.0", "axios": "^0.21.0",
"clean-insights-sdk": "^2.4", "clean-insights-sdk": "^2.4",
@ -23,9 +24,8 @@
"json-web-key": "^0.4.0", "json-web-key": "^0.4.0",
"linkifyjs": "3.0.0-beta.3", "linkifyjs": "3.0.0-beta.3",
"material-design-icons-iconfont": "^6.1", "material-design-icons-iconfont": "^6.1",
"matrix-js-sdk": "^12.4", "matrix-js-sdk": "^15.2.0",
"md-gum-polyfill": "^1.0.0", "md-gum-polyfill": "^1.0.0",
"olm": "https://packages.matrix.org/npm/olm/olm-3.2.1.tgz",
"pretty-bytes": "^5.6.0", "pretty-bytes": "^5.6.0",
"qrcode": "^1.4.4", "qrcode": "^1.4.4",
"raw-loader": "^4.0.2", "raw-loader": "^4.0.2",

View file

@ -1,6 +1,6 @@
{ {
"name": "keanuapp-weblite", "name": "keanuapp-weblite",
"version": "0.1.18", "version": "0.1.20",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "serve": "vue-cli-service serve",
@ -9,6 +9,7 @@
"create-sticker-config": "node ./create_sticker_config.js $1" "create-sticker-config": "node ./create_sticker_config.js $1"
}, },
"dependencies": { "dependencies": {
"@matrix-org/olm": "^3.2.8",
"aes-js": "^3.1.2", "aes-js": "^3.1.2",
"axios": "^0.21.0", "axios": "^0.21.0",
"clean-insights-sdk": "^2.4", "clean-insights-sdk": "^2.4",
@ -23,9 +24,8 @@
"json-web-key": "^0.4.0", "json-web-key": "^0.4.0",
"linkifyjs": "3.0.0-beta.3", "linkifyjs": "3.0.0-beta.3",
"material-design-icons-iconfont": "^6.1", "material-design-icons-iconfont": "^6.1",
"matrix-js-sdk": "^12.4", "matrix-js-sdk": "^15.2.0",
"md-gum-polyfill": "^1.0.0", "md-gum-polyfill": "^1.0.0",
"olm": "https://packages.matrix.org/npm/olm/olm-3.2.1.tgz",
"pretty-bytes": "^5.6.0", "pretty-bytes": "^5.6.0",
"qrcode": "^1.4.4", "qrcode": "^1.4.4",
"raw-loader": "^4.0.2", "raw-loader": "^4.0.2",

Binary file not shown.

View file

@ -12,6 +12,10 @@ export default {
for (const key of Object.keys(json)) { for (const key of Object.keys(json)) {
Vue.set(config, key, json[key]); Vue.set(config, key, json[key]);
} }
// If default server is not set, default to current server address
if (!json.defaultServer) {
Vue.set(config, "defaultServer", window.location.origin);
}
}); });
Vue.prototype.$config = config; Vue.prototype.$config = config;
} }

View file

@ -1,4 +1,5 @@
global.Olm = require("olm"); import olm from "@matrix-org/olm/olm";
global.Olm = olm;
import sdk from "matrix-js-sdk"; import sdk from "matrix-js-sdk";
import { TimelineWindow, EventTimeline } from "matrix-js-sdk"; import { TimelineWindow, EventTimeline } from "matrix-js-sdk";
import util from "../plugins/utils"; import util from "../plugins/utils";
@ -10,7 +11,7 @@ const LocalStorageCryptoStore = require("matrix-js-sdk/lib/crypto/store/localSto
export default { export default {
install(Vue, options) { install(Vue, options) {
if (!options || !options.store) { if (!options || !options.store) {
throw new Error('Please initialise plugin with a Vuex store.') throw new Error("Please initialise plugin with a Vuex store.");
} }
// Set User-Agent headers. // Set User-Agent headers.
@ -36,8 +37,8 @@ export default {
userDisplayName: null, userDisplayName: null,
userAvatar: null, userAvatar: null,
currentRoom: null, currentRoom: null,
notificationCount: 0 notificationCount: 0,
} };
}, },
mounted() { mounted() {
console.log("Matrix service mounted"); console.log("Matrix service mounted");
@ -53,13 +54,13 @@ export default {
}, },
currentUserId() { currentUserId() {
const user = this.currentUser || {} const user = this.currentUser || {};
return user.user_id; return user.user_id;
}, },
currentUserDisplayName() { currentUserDisplayName() {
if (this.ready) { if (this.ready) {
const user = this.matrixClient.getUser(this.currentUserId) || {} const user = this.matrixClient.getUser(this.currentUserId) || {};
return this.userDisplayName || user.displayName; return this.userDisplayName || user.displayName;
} }
return null; return null;
@ -74,16 +75,16 @@ export default {
}, },
joinedRooms() { joinedRooms() {
return this.rooms.filter(room => { return this.rooms.filter((room) => {
return room.selfMembership === 'join' return room.selfMembership === "join";
}); });
}, },
invites() { invites() {
return this.rooms.filter(room => { return this.rooms.filter((room) => {
return room.selfMembership === 'invite' return room.selfMembership === "invite";
}); });
} },
}, },
watch: { watch: {
@ -91,7 +92,7 @@ export default {
immediate: true, immediate: true,
handler(roomId) { handler(roomId) {
this.currentRoom = this.getRoom(roomId); this.currentRoom = this.getRoom(roomId);
} },
}, },
}, },
@ -101,7 +102,9 @@ export default {
return new LocalStorageCryptoStore(this.$store.getters.storage); return new LocalStorageCryptoStore(this.$store.getters.storage);
}, },
login(user) { login(user) {
const tempMatrixClient = sdk.createClient(User.homeServerUrl(user.home_server)); const tempMatrixClient = sdk.createClient(
User.homeServerUrl(user.home_server)
);
var promiseLogin; var promiseLogin;
const self = this; const self = this;
@ -119,7 +122,7 @@ export default {
promiseLogin = tempMatrixClient promiseLogin = tempMatrixClient
.register(user, pass, null, { .register(user, pass, null, {
type: "m.login.dummy", type: "m.login.dummy",
initial_device_display_name: this.$config.appName initial_device_display_name: this.$config.appName,
}) })
.then((response) => { .then((response) => {
console.log("Response", response); console.log("Response", response);
@ -129,9 +132,14 @@ export default {
u.is_guest = true; u.is_guest = true;
this.$store.commit("setUser", u); this.$store.commit("setUser", u);
return u; return u;
}) });
} else { } else {
var data = { user: User.localPart(user.user_id), password: user.password, type: "m.login.password", initial_device_display_name: this.$config.appName }; var data = {
user: User.localPart(user.user_id),
password: user.password,
type: "m.login.password",
initial_device_display_name: this.$config.appName,
};
if (user.device_id) { if (user.device_id) {
data.device_id = user.device_id; data.device_id = user.device_id;
} }
@ -146,11 +154,10 @@ export default {
u.home_server = tempMatrixClient.baseUrl; // Don't use deprecated field from response. u.home_server = tempMatrixClient.baseUrl; // Don't use deprecated field from response.
this.$store.commit("setUser", u); this.$store.commit("setUser", u);
return u; return u;
}) });
} }
return promiseLogin return promiseLogin.then((user) => {
.then((user) => {
return self.getMatrixClient(user); return self.getMatrixClient(user);
}); });
}, },
@ -175,15 +182,14 @@ export default {
this.removeMatrixClientListeners(this.matrixClient); this.removeMatrixClientListeners(this.matrixClient);
this.matrixClient.stopClient(); this.matrixClient.stopClient();
this.matrixClient.clearStores().then(() => { this.matrixClient.clearStores().then(() => {
this.clearCryptoStore() this.clearCryptoStore();
}) });
this.matrixClient = null; this.matrixClient = null;
this.matrixClientReady = false; this.matrixClientReady = false;
} else { } else {
this.clearCryptoStore(); this.clearCryptoStore();
} }
this.$store.commit("setUser", null); this.$store.commit("setUser", null);
this.$store.commit("setCurrentRoomId", null); this.$store.commit("setCurrentRoomId", null);
this.rooms = []; this.rooms = [];
@ -196,16 +202,17 @@ export default {
initClient() { initClient() {
this.reloadRooms(); this.reloadRooms();
this.matrixClientReady = true; this.matrixClientReady = true;
this.matrixClient.emit('Matrix.initialized', this.matrixClient); this.matrixClient.emit("Matrix.initialized", this.matrixClient);
this.matrixClient.getProfileInfo(this.currentUserId) this.matrixClient
.then(info => { .getProfileInfo(this.currentUserId)
.then((info) => {
console.log("Got user profile: " + JSON.stringify(info)); console.log("Got user profile: " + JSON.stringify(info));
this.userDisplayName = info.displayname; this.userDisplayName = info.displayname;
this.userAvatar = info.avatar_url; this.userAvatar = info.avatar_url;
}) })
.catch(err => { .catch((err) => {
console.log("Failed to get user profile: ", err); console.log("Failed to get user profile: ", err);
}) });
}, },
getMatrixClient(user) { getMatrixClient(user) {
@ -215,13 +222,13 @@ export default {
if (this.matrixClientReady) { if (this.matrixClientReady) {
return new Promise((resolve, ignoredreject) => { return new Promise((resolve, ignoredreject) => {
resolve(user); resolve(user);
}) });
} else if (this.matrixClient) { } else if (this.matrixClient) {
return new Promise((resolve, ignoredreject) => { return new Promise((resolve, ignoredreject) => {
this.matrixClient.once('Matrix.initialized', (ignoredclient) => { this.matrixClient.once("Matrix.initialized", (ignoredclient) => {
resolve(user); resolve(user);
}); });
}) });
} }
const matrixStore = new sdk.MemoryStore(this.$store.getters.storage); const matrixStore = new sdk.MemoryStore(this.$store.getters.storage);
@ -244,7 +251,7 @@ export default {
timelineSupport: true, timelineSupport: true,
unstableClientRelationAggregation: true, unstableClientRelationAggregation: true,
//useAuthorizationHeader: true //useAuthorizationHeader: true
} };
this.matrixClient = sdk.createClient(opts); this.matrixClient = sdk.createClient(opts);
// if (user.is_guest) { // if (user.is_guest) {
// this.matrixClient.setGuest(true); // this.matrixClient.setGuest(true);
@ -259,23 +266,24 @@ export default {
this.matrixClient.startClient(); this.matrixClient.startClient();
return this.matrixClient; return this.matrixClient;
}) })
.then(matrixClient => { .then((matrixClient) => {
if (matrixClient.isInitialSyncComplete()) { if (matrixClient.isInitialSyncComplete()) {
console.log("Initial sync done already!"); console.log("Initial sync done already!");
return matrixClient; return matrixClient;
} else { } else {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
matrixClient.once( matrixClient.once("sync", function(
"sync", state,
function (state, ignoredprevState, ignoredres) { ignoredprevState,
ignoredres
) {
console.log(state); // state will be 'PREPARED' when the client is ready to use console.log(state); // state will be 'PREPARED' when the client is ready to use
if (state == "PREPARED") { if (state == "PREPARED") {
resolve(matrixClient); resolve(matrixClient);
} else if (state == "ERROR") { } else if (state == "ERROR") {
reject("Error syncing"); reject("Error syncing");
} }
} });
)
}); });
} }
}) })
@ -283,7 +291,7 @@ export default {
// Ready to use! Start by loading rooms. // Ready to use! Start by loading rooms.
this.initClient(); this.initClient();
return user; return user;
}) });
}, },
/** /**
@ -296,7 +304,11 @@ export default {
if (this.ready) { if (this.ready) {
return Promise.resolve(this.currentUser); return Promise.resolve(this.currentUser);
} }
return this.$store.dispatch("login", this.currentUser || new User(this.$config.defaultServer, "", "", true)); return this.$store.dispatch(
"login",
this.currentUser ||
new User(this.$config.defaultServer, "", "", true)
);
}, },
addMatrixClientListeners(client) { addMatrixClientListeners(client) {
@ -319,7 +331,8 @@ export default {
onEvent(event) { onEvent(event) {
switch (event.getType()) { switch (event.getType()) {
case "m.room.topic": { case "m.room.topic":
{
const room = this.matrixClient.getRoom(event.getRoomId()); const room = this.matrixClient.getRoom(event.getRoomId());
if (room) { if (room) {
Vue.set(room, "topic", event.getContent().topic); Vue.set(room, "topic", event.getContent().topic);
@ -327,20 +340,45 @@ export default {
} }
break; break;
case "m.room.avatar": { case "m.room.avatar":
{
const room = this.matrixClient.getRoom(event.getRoomId()); const room = this.matrixClient.getRoom(event.getRoomId());
if (room) { if (room) {
Vue.set(room, "avatar", room.getAvatarUrl(this.matrixClient.getHomeserverUrl(), 80, 80, "scale", true)); Vue.set(
room,
"avatar",
room.getAvatarUrl(
this.matrixClient.getHomeserverUrl(),
80,
80,
"scale",
true
)
);
} }
} }
break; break;
case "m.room.member": { case "m.room.member":
if (this.currentRoom && event.getRoomId() == this.currentRoom.roomId) { // Don't use this.currentRoomId, may be an alias. We need the real id! {
if (event.getContent().membership == "leave" && (event.getPrevContent() || {}).membership == "join" && event.getStateKey() == this.currentUserId && event.getSender() != this.currentUserId) { if (
this.currentRoom &&
event.getRoomId() == this.currentRoom.roomId
) {
// Don't use this.currentRoomId, may be an alias. We need the real id!
if (
event.getContent().membership == "leave" &&
(event.getPrevContent() || {}).membership == "join" &&
event.getStateKey() == this.currentUserId &&
event.getSender() != this.currentUserId
) {
// We were kicked // We were kicked
const wasPurged = (event.getContent().reason == "Room Deleted"); const wasPurged =
this.$navigation.push({ name: "Goodbye", params: { roomWasPurged: wasPurged } }, -1); event.getContent().reason == "Room Deleted";
this.$navigation.push(
{ name: "Goodbye", params: { roomWasPurged: wasPurged } },
-1
);
} }
} }
} }
@ -395,12 +433,25 @@ export default {
// TODO - do incremental update instead of replacing the whole array // TODO - do incremental update instead of replacing the whole array
// each time! // each time!
var updatedRooms = this.matrixClient.getVisibleRooms(); var updatedRooms = this.matrixClient.getVisibleRooms();
updatedRooms = updatedRooms.filter(room => { updatedRooms = updatedRooms.filter((room) => {
return room.selfMembership && (room.selfMembership == "invite" || room.selfMembership == "join"); return (
room.selfMembership &&
(room.selfMembership == "invite" || room.selfMembership == "join")
);
}); });
updatedRooms.forEach(room => { updatedRooms.forEach((room) => {
if (!room.avatar) { if (!room.avatar) {
Vue.set(room, "avatar", room.getAvatarUrl(this.matrixClient.getHomeserverUrl(), 80, 80, "scale", true)); Vue.set(
room,
"avatar",
room.getAvatarUrl(
this.matrixClient.getHomeserverUrl(),
80,
80,
"scale",
true
)
);
} }
}); });
console.log("Reload rooms", updatedRooms); console.log("Reload rooms", updatedRooms);
@ -423,7 +474,7 @@ export default {
var room = null; var room = null;
if (this.matrixClient) { if (this.matrixClient) {
const visibleRooms = this.matrixClient.getRooms(); const visibleRooms = this.matrixClient.getRooms();
room = visibleRooms.find(room => { room = visibleRooms.find((room) => {
if (roomId.startsWith("#")) { if (roomId.startsWith("#")) {
return room.getCanonicalAlias() == roomId; return room.getCanonicalAlias() == roomId;
} }
@ -440,9 +491,15 @@ export default {
var ids = {}; var ids = {};
const ret = []; const ret = [];
for (const room of this.rooms) { for (const room of this.rooms) {
if (room.selfMembership == 'join' && this.getRoomJoinRule(room) == 'invite') { if (
room.selfMembership == "join" &&
this.getRoomJoinRule(room) == "invite"
) {
for (const member of room.getJoinedMembers()) { for (const member of room.getJoinedMembers()) {
if (member.userId != this.currentUserId && !ids[member.userId]) { if (
member.userId != this.currentUserId &&
!ids[member.userId]
) {
ids[member.userId] = member; ids[member.userId] = member;
ret.push(member); ret.push(member);
} }
@ -474,20 +531,22 @@ export default {
"m.room.history_visibility", "m.room.history_visibility",
"" ""
); );
return historyVisibility && historyVisibility.getContent().history_visibility; return (
historyVisibility &&
historyVisibility.getContent().history_visibility
);
} }
return null; return null;
}, },
leaveRoom(roomId) { leaveRoom(roomId) {
return this.matrixClient.leave(roomId, undefined) return this.matrixClient.leave(roomId, undefined).then(() => {
.then(() => { this.rooms = this.rooms.filter((room) => {
this.rooms = this.rooms.filter(room => {
room.roomId != roomId; room.roomId != roomId;
}); });
this.matrixClient.store.removeRoom(roomId); this.matrixClient.store.removeRoom(roomId);
//this.matrixClient.forget(roomId, true, undefined); //this.matrixClient.forget(roomId, true, undefined);
}) });
}, },
/** /**
@ -516,8 +575,9 @@ export default {
const self = this; const self = this;
//console.log("Purge: set invite only"); //console.log("Purge: set invite only");
statusCallback(this.$t('room.purge_set_room_state')); statusCallback(this.$t("room.purge_set_room_state"));
this.matrixClient.sendStateEvent( this.matrixClient
.sendStateEvent(
roomId, roomId,
"m.room.join_rules", "m.room.join_rules",
{ join_rule: "invite" }, { join_rule: "invite" },
@ -534,18 +594,21 @@ export default {
}) })
.then(() => { .then(() => {
//console.log("Purge: set history visibility to 'joined'"); //console.log("Purge: set history visibility to 'joined'");
return this.matrixClient.sendStateEvent(roomId, "m.room.history_visibility", { return this.matrixClient.sendStateEvent(
roomId,
"m.room.history_visibility",
{
history_visibility: "joined", history_visibility: "joined",
}); }
);
}) })
.then(() => { .then(() => {
//console.log("Purge: create timeline"); //console.log("Purge: create timeline");
return timelineWindow.load(null, 100) return timelineWindow.load(null, 100);
}) })
.then(() => { .then(() => {
const getMoreIfAvailable = function _getMoreIfAvailable() { const getMoreIfAvailable = function _getMoreIfAvailable() {
if (timelineWindow.canPaginate(EventTimeline.BACKWARDS) if (timelineWindow.canPaginate(EventTimeline.BACKWARDS)) {
) {
//console.log("Purge: page back"); //console.log("Purge: page back");
return timelineWindow return timelineWindow
.paginate(EventTimeline.BACKWARDS, 100, true, 5) .paginate(EventTimeline.BACKWARDS, 100, true, 5)
@ -560,36 +623,53 @@ export default {
}) })
.then(() => { .then(() => {
//console.log("Purge: redact events"); //console.log("Purge: redact events");
statusCallback(this.$t('room.purge_redacting_events')); statusCallback(this.$t("room.purge_redacting_events"));
// First ignore unknown device errors // First ignore unknown device errors
this.matrixClient.setGlobalErrorOnUnknownDevices(false); this.matrixClient.setGlobalErrorOnUnknownDevices(false);
var redactionPromises = []; var redactionPromises = [];
timelineWindow.getEvents().forEach(event => { timelineWindow.getEvents().forEach((event) => {
if (!event.isRedacted() && !event.isRedaction() && !event.isState()) { if (
!event.isRedacted() &&
!event.isRedaction() &&
!event.isState()
) {
// Redact! // Redact!
redactionPromises.push(this.matrixClient.redactEvent(event.getRoomId(), event.getId())); redactionPromises.push(
this.matrixClient.redactEvent(
event.getRoomId(),
event.getId()
)
);
} }
}); });
return Promise.all(redactionPromises); return Promise.all(redactionPromises);
}) })
.then(() => { .then(() => {
//console.log("Purge: kick members"); //console.log("Purge: kick members");
statusCallback(this.$t('room.purge_removing_members')); statusCallback(this.$t("room.purge_removing_members"));
var joined = room.getMembersWithMembership("join"); var joined = room.getMembersWithMembership("join");
var invited = room.getMembersWithMembership("invite"); var invited = room.getMembersWithMembership("invite");
var members = joined.concat(invited); var members = joined.concat(invited);
var kickPromises = []; var kickPromises = [];
members.forEach(member => { members.forEach((member) => {
if (member.userId != self.currentUserId) { if (member.userId != self.currentUserId) {
kickPromises.push(this.matrixClient.kick(roomId, member.userId, "Room Deleted")); kickPromises.push(
this.matrixClient.kick(
roomId,
member.userId,
"Room Deleted"
)
);
} }
}); });
return Promise.all(kickPromises); return Promise.all(kickPromises);
}) })
.then(() => { .then(() => {
statusCallback(null); statusCallback(null);
this.matrixClient.setGlobalErrorOnUnknownDevices(oldGlobalErrorSetting); this.matrixClient.setGlobalErrorOnUnknownDevices(
oldGlobalErrorSetting
);
return this.leaveRoom(roomId); return this.leaveRoom(roomId);
}) })
.then(() => { .then(() => {
@ -597,10 +677,12 @@ export default {
}) })
.catch((err) => { .catch((err) => {
console.error("Error purging room", err); console.error("Error purging room", err);
this.matrixClient.setGlobalErrorOnUnknownDevices(oldGlobalErrorSetting); this.matrixClient.setGlobalErrorOnUnknownDevices(
oldGlobalErrorSetting
);
reject(err); reject(err);
}); });
}) });
}, },
/** /**
@ -661,7 +743,7 @@ export default {
.catch((error) => { .catch((error) => {
reject(error); reject(error);
}); });
}) });
}, },
/** /**
@ -670,11 +752,22 @@ export default {
* @param {*} userId * @param {*} userId
*/ */
isDirectRoomWith(room, userId) { isDirectRoomWith(room, userId) {
if (room.selfMembership == "join" && room.getInvitedAndJoinedMemberCount() == 2) { if (
room.selfMembership == "join" &&
room.getInvitedAndJoinedMemberCount() == 2
) {
// Is the other member the one we are looking for? // Is the other member the one we are looking for?
if (room.getMembersWithMembership("join").some(item => item.userId == userId)) { if (
room
.getMembersWithMembership("join")
.some((item) => item.userId == userId)
) {
return true; return true;
} else if (room.getMembersWithMembership("invite").some(item => item.userId == userId)) { } else if (
room
.getMembersWithMembership("invite")
.some((item) => item.userId == userId)
) {
return true; return true;
} }
} }
@ -696,9 +789,9 @@ export default {
setPassword(oldPassword, newPassword) { setPassword(oldPassword, newPassword) {
if (this.matrixClient && this.currentUser) { if (this.matrixClient && this.currentUser) {
const authDict = { const authDict = {
type: 'm.login.password', type: "m.login.password",
identifier: { identifier: {
type: 'm.id.user', type: "m.id.user",
user: this.currentUser.user_id, user: this.currentUser.user_id,
}, },
// TODO: Remove `user` once servers support proper UIA // TODO: Remove `user` once servers support proper UIA
@ -707,7 +800,8 @@ export default {
password: oldPassword, password: oldPassword,
}; };
const self = this; const self = this;
return this.matrixClient.setPassword(authDict, newPassword) return this.matrixClient
.setPassword(authDict, newPassword)
.then(() => { .then(() => {
// Forget password and remove the 'is_guest' flag, we are now a "real" user! // Forget password and remove the 'is_guest' flag, we are now a "real" user!
self.currentUser.password = undefined; self.currentUser.password = undefined;
@ -716,7 +810,7 @@ export default {
}) })
.then(() => { .then(() => {
return true; return true;
}) });
} }
return Promise.resolve(false); return Promise.resolve(false);
}, },
@ -730,7 +824,7 @@ export default {
return Promise.reject("Invalid parameters"); return Promise.reject("Invalid parameters");
} }
const parts = roomId.split(':'); const parts = roomId.split(":");
if (parts.length != 2) { if (parts.length != 2) {
return Promise.reject("Unknown room server"); return Promise.reject("Unknown room server");
} }
@ -740,9 +834,11 @@ export default {
if (this.matrixClient) { if (this.matrixClient) {
clientPromise = this.getMatrixClient().then(() => { clientPromise = this.getMatrixClient().then(() => {
return this.matrixClient; return this.matrixClient;
}) });
} else { } else {
const tempMatrixClient = sdk.createClient(this.$config.defaultServer); const tempMatrixClient = sdk.createClient(
this.$config.defaultServer
);
var tempUserString = this.$store.state.tempuser; var tempUserString = this.$store.state.tempuser;
var tempUser = null; var tempUser = null;
if (tempUserString) { if (tempUserString) {
@ -759,7 +855,7 @@ export default {
clientPromise = tempMatrixClient clientPromise = tempMatrixClient
.register(user, pass, null, { .register(user, pass, null, {
type: "m.login.dummy", type: "m.login.dummy",
initial_device_display_name: this.$config.appName initial_device_display_name: this.$config.appName,
}) })
.then((response) => { .then((response) => {
console.log("Response", response); console.log("Response", response);
@ -771,25 +867,30 @@ export default {
} }
// Get an access token // Get an access token
clientPromise = clientPromise.then(user => { clientPromise = clientPromise.then((user) => {
var data = { user: User.localPart(user.user_id), password: user.password, type: "m.login.password", initial_device_display_name: this.$config.appName }; var data = {
user: User.localPart(user.user_id),
password: user.password,
type: "m.login.password",
initial_device_display_name: this.$config.appName,
};
if (user.device_id) { if (user.device_id) {
data.device_id = user.device_id; data.device_id = user.device_id;
} }
return tempMatrixClient.login("m.login.password", data) return tempMatrixClient.login("m.login.password", data);
}) });
// Then login // Then login
// //
// Create a slimmed down client, without crypto. This one is // Create a slimmed down client, without crypto. This one is
// Only used to get public room info from. // Only used to get public room info from.
clientPromise = clientPromise.then(user => { clientPromise = clientPromise.then((user) => {
var opts = { var opts = {
baseUrl: this.$config.defaultServer, baseUrl: this.$config.defaultServer,
userId: user.user_id, userId: user.user_id,
accessToken: user.access_token, accessToken: user.access_token,
timelineSupport: false, timelineSupport: false,
} };
var matrixClient = sdk.createClient(opts); var matrixClient = sdk.createClient(opts);
matrixClient.startClient(); matrixClient.startClient();
return matrixClient; return matrixClient;
@ -798,19 +899,33 @@ export default {
const findOrGetMore = function _findOrGetMore(client, response) { const findOrGetMore = function _findOrGetMore(client, response) {
for (var room of response.chunk) { for (var room of response.chunk) {
if ((roomId.startsWith("#") && room.canonical_alias == roomId) || (roomId.startsWith("!") && room.room_id == roomId)) { if (
(roomId.startsWith("#") && room.canonical_alias == roomId) ||
(roomId.startsWith("!") && room.room_id == roomId)
) {
if (room.avatar_url) { if (room.avatar_url) {
room.avatar = client.mxcUrlToHttp(room.avatar_url, 80, 80, 'scale', true); room.avatar = client.mxcUrlToHttp(
room.avatar_url,
80,
80,
"scale",
true
);
} }
return Promise.resolve(room); return Promise.resolve(room);
} }
} }
if (response.next_batch) { if (response.next_batch) {
return client.publicRooms({ server: server, limit: 1000, since: response.next_batch }) return client
.then(response => { .publicRooms({
server: server,
limit: 1000,
since: response.next_batch,
})
.then((response) => {
return _findOrGetMore(client, response); return _findOrGetMore(client, response);
}) })
.catch(err => { .catch((err) => {
return Promise.reject("Failed to find room: " + err); return Promise.reject("Failed to find room: " + err);
}); });
} else { } else {
@ -820,31 +935,32 @@ export default {
var matrixClient; var matrixClient;
return clientPromise return clientPromise
.then(client => { .then((client) => {
matrixClient = client; matrixClient = client;
return matrixClient.publicRooms({ server: server, limit: 1000 }) return matrixClient.publicRooms({ server: server, limit: 1000 });
}) })
.then(response => { .then((response) => {
return findOrGetMore(matrixClient, response); return findOrGetMore(matrixClient, response);
}) })
.catch(err => { .catch((err) => {
return Promise.reject("Failed to find room: " + err); return Promise.reject("Failed to find room: " + err);
}); });
}, },
updateNotificationCount() { updateNotificationCount() {
var count = 0; var count = 0;
this.rooms.forEach(room => { this.rooms.forEach((room) => {
count += room.getUnreadNotificationCount('total') || 0; count += room.getUnreadNotificationCount("total") || 0;
}); });
this.notificationCount = count; this.notificationCount = count;
} },
},
});
} sdk.setCryptoStoreFactory(
}) matrixService.createCryptoStore.bind(matrixService)
);
sdk.setCryptoStoreFactory(matrixService.createCryptoStore.bind(matrixService));
Vue.prototype.$matrix = matrixService; Vue.prototype.$matrix = matrixService;
} },
} };

View file

@ -1,33 +1,35 @@
const CopyWebpackPlugin = require('copy-webpack-plugin') const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = { module.exports = {
"transpileDependencies": [ transpileDependencies: ["vuetify"],
"vuetify"
],
publicPath: process.env.NODE_ENV === 'production' publicPath: process.env.NODE_ENV === "production" ? "./" : "./",
? './'
: './',
chainWebpack: config => { chainWebpack: (config) => {
config.plugin('html').tap(args => { config.plugin("html").tap((args) => {
var c = require("./src/assets/config.json"); var c = require("./src/assets/config.json");
args[0].title = c.appName; args[0].title = c.appName;
return args; return args;
}) });
}, },
configureWebpack: { configureWebpack: {
devtool: 'source-map', devtool: "source-map",
plugins: [ plugins: [
new CopyWebpackPlugin([{ new CopyWebpackPlugin([
{
from: "./src/assets/config.json", from: "./src/assets/config.json",
to: "./", to: "./",
}]) },
] {
from: "./node_modules/@matrix-org/olm/olm.wasm",
to: "./js/olm.wasm",
},
]),
],
}, },
devServer: { devServer: {
//https: true //https: true,
}, },
} };