diff --git a/src/components/Join.vue b/src/components/Join.vue index 34937d0..62c4055 100644 --- a/src/components/Join.vue +++ b/src/components/Join.vue @@ -90,17 +90,17 @@ - {{ roomId && roomId.startsWith("@") ? $t("join.enter_room_user") : $t("join.enter_room") }} - {{ roomId && roomId.startsWith("@") ? $t("join.join_user") : $t("join.join") }}
{{ loadingMessage }}
-
{{ $t("join.you_have_been_banned") }}
+
{{ $t("join.you_have_been_banned") }}
diff --git a/src/models/user.js b/src/models/user.js deleted file mode 100644 index a9f1870..0000000 --- a/src/models/user.js +++ /dev/null @@ -1,23 +0,0 @@ -export default class User { - constructor(user_id, password, is_guest) { - this.user_id = user_id; - this.password = password; - this.is_guest = is_guest || false - } - - static localPart(user_id) { - if (user_id && user_id.startsWith('@') && user_id.includes(':')) { - const parts = user_id.split(":"); - return parts[0].substring(1); - } - return user_id; - } - - static domainPart(user_id) { - if (user_id && user_id.startsWith('@') && user_id.includes(':')) { - const parts = user_id.split(":"); - return parts[1]; - } - return undefined; - } -} \ No newline at end of file diff --git a/src/models/user.ts b/src/models/user.ts new file mode 100644 index 0000000..018fef6 --- /dev/null +++ b/src/models/user.ts @@ -0,0 +1,27 @@ +export default class User { + user_id: string; + password: string | null; + is_guest: boolean; + + constructor(user_id: string, password: string | null, is_guest?: boolean) { + this.user_id = user_id; + this.password = password; + this.is_guest = is_guest || false; + } + + static localPart(user_id: string | null) { + if (user_id && user_id.startsWith("@") && user_id.includes(":")) { + const parts = user_id.split(":"); + return parts[0].substring(1); + } + return user_id; + } + + static domainPart(user_id: string | null) { + if (user_id && user_id.startsWith("@") && user_id.includes(":")) { + const parts = user_id.split(":"); + return parts[1]; + } + return undefined; + } +} diff --git a/src/services/analytics.service.js b/src/services/analytics.service.ts similarity index 82% rename from src/services/analytics.service.js rename to src/services/analytics.service.ts index ea644d6..4da5018 100644 --- a/src/services/analytics.service.js +++ b/src/services/analytics.service.ts @@ -1,9 +1,23 @@ import cleaninsights from "./cleaninsights.service"; import matomo from "./matomo.service"; +export interface AnalyticsEngine { + event(category: string, action: string); +} + +type AnalyticsEvent = { + category: string; + action: string; +} + export default { install(app) { class AnalyticsServiceClass { + + engines: AnalyticsEngine[]; + cachedEvents: AnalyticsEvent[]; + initialized: boolean; + constructor() { this.engines = []; this.cachedEvents = []; @@ -37,7 +51,7 @@ export default { this.initialized = true; // Handle cached events - this.cachedEvents.forEach(([category, action]) => { + this.cachedEvents.forEach(({category, action}) => { this.event(category, action); }); this.cachedEvents = []; @@ -46,7 +60,7 @@ export default { event(category, action) { if (!this.initialized) { - this.cachedEvents.push([category, action]); + this.cachedEvents.push({category, action}); return; } diff --git a/src/services/matrix.service.js b/src/services/matrix.service.js index be87dce..7870a8b 100644 --- a/src/services/matrix.service.js +++ b/src/services/matrix.service.js @@ -85,19 +85,19 @@ export default { joinedRooms() { return this.rooms.filter((room) => { - return room.selfMembership === "join"; + return room.getMyMembership() === "join"; }); }, invites() { return this.rooms.filter((room) => { - return room.selfMembership === "invite"; + return room.getMyMembership() === "invite"; }); }, joinedAndInvitedRooms() { return this.rooms.filter((room) => { - return room.selfMembership === "join" || room.selfMembership === "invite"; + return room.getMyMembership() === "join" || room.getMyMembership() === "invite"; }); }, }, @@ -313,6 +313,8 @@ export default { store: matrixStore, deviceId: user.device_id, accessToken: user.access_token, + refreshToken: user.refresh_token, + tokenRefreshFunction: this.onSessionRefresh, timelineSupport: true, unstableClientRelationAggregation: true, cryptoStore: cryptoStore @@ -413,7 +415,7 @@ export default { case "m.room.join_rules": { const room = this.matrixClient.getRoom(event.getRoomId()); - if (room && room.getJoinRule() == "private" && room.selfMembership == "invite") { + if (room && room.getJoinRule() == "private" && room.getMyMembership() == "invite") { // We have an invite to a room that's now "private"? This is most probably a deleted DM room. // Reject the invite, i.e. call "leave" on it. this.matrixClient.leave(room.roomId); @@ -451,7 +453,7 @@ export default { }, onRoom(room) { - if (room.selfMembership === "invite") { + if (room.getMyMembership() === "invite") { this.matrixClient .getRoomTags(room.roomId) .then((reply) => { @@ -468,7 +470,7 @@ export default { }, onRoomMyMembership(room) { - if (room.selfMembership === "invite") { + if (room.getMyMembership() === "invite") { // Invitation. Need to call "recalculate" to pick // up room name, not sure why exactly. room.recalculate(); @@ -476,6 +478,28 @@ export default { this.reloadRooms(); }, + onSessionRefresh(refreshToken) { + const now = Date.now(); + return this.matrixClient.refreshToken(refreshToken).then((result) => { + // Store new one! + var user = this.$store.state.auth.user; + user.access_token = result.access_token; + user.refresh_token = result.refresh_token; + user.expires_in_ms = result.expires_in_ms; + this.$store.commit("setUser", user); + + // Return AccessTokens struct + let accesssTokens = { + accessToken: result.access_token, + refreshToken: result.refresh_token + }; + if (result.expires_in_ms) { + accesssTokens.expiry = new Date(now + result.expires_in_ms); + }; + return accesssTokens; + }); + }, + onSessionLoggedOut() { console.log("Logged out!"); if (this.matrixClient) { @@ -517,7 +541,7 @@ export default { // each time! var updatedRooms = this.matrixClient.getVisibleRooms(); updatedRooms = updatedRooms.filter((room) => { - return room.selfMembership && (room.selfMembership == "invite" || room.selfMembership == "join") && room.currentState.getStateEvents(STATE_EVENT_ROOM_DELETED).length == 0; + return room.getMyMembership() && (room.getMyMembership() == "invite" || room.getMyMembership() == "join") && room.currentState.getStateEvents(STATE_EVENT_ROOM_DELETED).length == 0; }); updatedRooms.forEach((room) => { room["avatar"] = room.getAvatarUrl(this.matrixClient.getHomeserverUrl(), 80, 80, "scale", true, this.useAuthedMedia); @@ -567,7 +591,7 @@ export default { var ids = {}; const ret = []; for (const room of this.rooms) { - if (room.selfMembership == "join" && this.getRoomJoinRule(room) == "invite") { + if (room.getMyMembership() == "join" && this.getRoomJoinRule(room) == "invite") { for (const member of room.getJoinedMembers()) { if (member.userId != this.currentUserId && !ids[member.userId]) { ids[member.userId] = member; @@ -842,7 +866,7 @@ export default { }) .then(() => { //console.log("Purge: create timeline"); - return timelineWindow.load(null, 100); + return timelineWindow.load(undefined, 100); }) .then(() => { const getMoreIfAvailable = function _getMoreIfAvailable() { @@ -1234,7 +1258,7 @@ export default { since: response.next_batch, }) .then((response) => { - return _findOrGetMore(client, response); + return _findOrGetMore(client, useAuthedMedia, response); }) .catch((err) => { return Promise.reject("Failed to find room: " + err); diff --git a/src/services/navigation.service.js b/src/services/navigation.service.js deleted file mode 100644 index a03c19f..0000000 --- a/src/services/navigation.service.js +++ /dev/null @@ -1,82 +0,0 @@ -export default { - install(app, router) { - var routes = []; - var nextRoutes = null; - var zeroIndex = undefined; - - router.beforeResolve((to, ignoredfrom, next) => { - if (!zeroIndex) { - routes = [to]; - zeroIndex = window.history.length; - } - next(); - }) - - router.beforeEach((to, from, next) => { - if (nextRoutes) { - console.log("Nav: next routes set, going:", routes, nextRoutes); - routes = nextRoutes; - nextRoutes = null; - if (routes.length > 0) { - console.log("Redirecting to", routes[routes.length - 1]); - next(routes[routes.length - 1]); - return; - } - } - next(); - }) - - const navigationService = { - /*** - * @param mode Mode of operation. -1 = push as root, 0 = replace, 1 = normal push - */ - push(route, mode) { - if (mode === undefined) { - mode = 1; - } - if (mode == -1) { - nextRoutes = [route]; - } else if (mode == 0) { - // Replace - nextRoutes = [...routes]; - nextRoutes.pop(); - nextRoutes.push(route); - } else { - nextRoutes = [...routes]; - nextRoutes.push(route); - } - - const index = nextRoutes.length - routes.length; - const targetIndex = nextRoutes.length - 1; - console.log("Nav - index " + index + " Target " + targetIndex); - if (index < 0) { - console.log("Nav - go " + index); - router.go(index); - } else if (index == 0) { - console.log("Nav - replace"); - routes = nextRoutes; - nextRoutes = null; - router.replace(route).catch((ignoredErr) => {}); - } else { - console.log("Nav - push"); - router.push(route).catch((ignoredErr) => {}); - } - }, - - canPop() { - if (nextRoutes) { - return nextRoutes.length > 1; - } - return routes.length > 1; - }, - - pop() { - routes.pop(); - router.go(-1); - } - } - - app.$navigation = navigationService; - app.config.globalProperties.$navigation = navigationService; - } -} diff --git a/src/services/navigation.service.ts b/src/services/navigation.service.ts new file mode 100644 index 0000000..ea601b3 --- /dev/null +++ b/src/services/navigation.service.ts @@ -0,0 +1,84 @@ +import { RouteLocationNormalizedGeneric, Router } from "vue-router"; + +export default { + install(app, router: Router) { + var routes: RouteLocationNormalizedGeneric[] = []; + var nextRoutes: RouteLocationNormalizedGeneric[] | null = null; + var zeroIndex: number | undefined = undefined; + + router.beforeResolve((to, ignoredfrom, next) => { + if (!zeroIndex) { + routes = [to]; + zeroIndex = window.history.length; + } + next(); + }); + + router.beforeEach((to, from, next) => { + if (nextRoutes) { + console.log("Nav: next routes set, going:", routes, nextRoutes); + routes = nextRoutes; + nextRoutes = null; + if (routes.length > 0) { + console.log("Redirecting to", routes[routes.length - 1]); + next(routes[routes.length - 1]); + return; + } + } + next(); + }); + + const navigationService = { + /*** + * @param mode Mode of operation. -1 = push as root, 0 = replace, 1 = normal push + */ + push(route, mode) { + if (mode === undefined) { + mode = 1; + } + if (mode == -1) { + nextRoutes = [route]; + } else if (mode == 0) { + // Replace + nextRoutes = [...routes]; + nextRoutes.pop(); + nextRoutes.push(route); + } else { + nextRoutes = [...routes]; + nextRoutes.push(route); + } + + const index = nextRoutes.length - routes.length; + const targetIndex = nextRoutes.length - 1; + console.log("Nav - index " + index + " Target " + targetIndex); + if (index < 0) { + console.log("Nav - go " + index); + router.go(index); + } else if (index == 0) { + console.log("Nav - replace"); + routes = nextRoutes; + nextRoutes = null; + router.replace(route).catch((ignoredErr) => {}); + } else { + console.log("Nav - push"); + router.push(route).catch((ignoredErr) => {}); + } + }, + + canPop() { + if (nextRoutes) { + return nextRoutes.length > 1; + } + return routes.length > 1; + }, + + pop() { + routes.pop(); + router.go(-1); + }, + }; + + app.$navigation = navigationService; + app.config.globalProperties.$navigation = navigationService; + }, +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..37f3149 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "strict": true + }, +} \ No newline at end of file