diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000..690ad25
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,35 @@
+module.exports = {
+ "env": {
+ "browser": true,
+ "es6": true
+ },
+ "extends": [
+ "eslint:recommended",
+ "plugin:vue/essential"
+ ],
+ "globals": {
+ "Atomics": "readonly",
+ "SharedArrayBuffer": "readonly"
+ },
+ "parserOptions": {
+ "ecmaVersion": 2018,
+ "sourceType": "module"
+ },
+ "plugins": [
+ "vue"
+ ],
+ "rules": {
+ "indent": [
+ "warn",
+ 2
+ ],
+ "linebreak-style": [
+ "error",
+ "unix"
+ ],
+ "quotes": [
+ "warn",
+ "single"
+ ]
+ }
+}
diff --git a/package.json b/package.json
index cb985ab..8ed94cb 100644
--- a/package.json
+++ b/package.json
@@ -9,47 +9,32 @@
},
"dependencies": {
"@modular-matrix/parse-mxc": "^1.0.1",
+ "@vue-polkadot/vue-identicon": "^0.0.8",
"core-js": "^3.6.5",
+ "jdenticon": "^3.1.0",
"matrix-js-sdk": "^9.1.0",
"sass": "^1.29.0",
- "sass-loader": "^10.1.0",
"v-emoji-picker": "^2.3.1",
"vue": "^2.6.11",
"ws": "^7.3.1"
},
"devDependencies": {
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.0",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
+ "@vue/cli-plugin-pwa": "~4.5.0",
"@vue/cli-service": "~4.5.0",
+ "@vue/compiler-sfc": "^3.0.0",
+ "babel": "^6.23.0",
+ "babel-cli": "^6.18.0",
"babel-eslint": "^10.1.0",
"electron": "^11.0.1",
- "eslint": "^7.14.0",
- "eslint-config-airbnb-base": "^14.2.1",
- "eslint-config-standard": "^16.0.2",
- "eslint-plugin-import": "^2.22.1",
- "eslint-plugin-node": "^11.1.0",
- "eslint-plugin-promise": "^4.2.1",
- "eslint-plugin-vue": "^7.2.0",
+ "eslint": "^6.7.2",
+ "eslint-plugin-vue": "^7.5.0",
+ "node-sass": "^5.0.0",
+ "sass-loader": "^10.1.1",
"vue-router": "^3.4.9",
"vue-template-compiler": "^2.6.11"
- },
- "eslintConfig": {
- "root": true,
- "env": {
- "node": true
- },
- "extends": [
- "plugin:vue/essential",
- "eslint:recommended"
- ],
- "parserOptions": {
- "parser": "babel-eslint"
- },
- "rules": {}
- },
- "browserslist": [
- "> 1%",
- "last 2 versions",
- "not dead"
- ]
+ }
}
diff --git a/src/components/chatInformation.vue b/src/components/chatInformation.vue
index 0fb3f98..7763b4a 100644
--- a/src/components/chatInformation.vue
+++ b/src/components/chatInformation.vue
@@ -6,27 +6,31 @@
{{room.name.substr(0,2)}}
- members:
-
-
+
members:
+
-
and {{room.members.length-20}} other members
+
and {{getMembers().length-20}} other members
-
+
\ No newline at end of file
diff --git a/src/components/timeline.vue b/src/components/timeline.vue
new file mode 100644
index 0000000..92ba28c
--- /dev/null
+++ b/src/components/timeline.vue
@@ -0,0 +1,133 @@
+
+
+
+
{{getDate(timeGroup[0].origin_server_ts)}}
+
+
+
{{getUser(group[0].sender).displayName || group[0].sender}}
+
+
+
+
{{membershipEvents[event.content.membership]}}
+
unknown event
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/topBanner.vue b/src/components/topBanner.vue
index 064a8af..a2e0a26 100644
--- a/src/components/topBanner.vue
+++ b/src/components/topBanner.vue
@@ -1,34 +1,44 @@
-
-
{{session.currentRoom.name.substr(0,2)}}
+
+
-
{{session.currentRoom.name}}
-
{{session.currentRoom.members.length}} members
+
{{room.name}}
+
{{Object.keys(room.currentState.members).length}} members
-
\ No newline at end of file
diff --git a/src/lib/cookieHandler.js b/src/lib/cookieHandler.js
new file mode 100644
index 0000000..fb8bf8e
--- /dev/null
+++ b/src/lib/cookieHandler.js
@@ -0,0 +1,46 @@
+export class cookieHandler {
+ constructor() {
+ this.cookies = {};
+ this.reload();
+ this.expires = undefined;
+ this.SameSite = 'Strict';
+ }
+ getCookies(){
+ return this.cookies;
+ }
+ setCookie(cookies){
+ Object.keys(cookies).forEach(key => {
+ this.cookies[key] = cookies[key];
+ })
+ }
+ parseCookie(string){
+ let cookies = {};
+ string.replace(/ /g, '').split(';').forEach(cookie => {
+ let arr = cookie.split('=');
+ cookies[arr[0]] = arr[1];
+ })
+ return cookies;
+ }
+ reload(){
+ if (document.cookie) this.cookies = this.parseCookie(document.cookie);
+ console.log('cookie loaded')
+ console.log(this.cookies);
+ }
+ store(){
+ Object.keys(this.cookies).forEach(key => {
+ document.cookie = `${key}=${this.cookies[key]}; expires=${this.expires}; SameSite=${this.SameSite}; Secure;`;
+ });
+ console.log('cookie stored');
+ console.log(this.cookies);
+ }
+ toString(cookies = this.cookies){
+ let string = '';
+ Object.keys(cookies).forEach(key => {
+ string += `${key}=${cookies[key]}; `;
+ })
+ return string;
+ }
+ setExpire(days){
+ this.expires = new Date(Date.now() + 86400 * 10000 * days);
+ }
+}
diff --git a/src/lib/getTimeStrings.js b/src/lib/getTimeStrings.js
new file mode 100644
index 0000000..dc13558
--- /dev/null
+++ b/src/lib/getTimeStrings.js
@@ -0,0 +1,10 @@
+export function getTime(time) {
+ let date = new Date(time);
+ return `${date.getHours()}:${(date.getMinutes() < 10) ? '0' : ''}${date.getMinutes()}`;
+}
+
+export function getDate(time) {
+ let months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+ let date = new Date(time);
+ return `${date.getDate()} ${months[date.getMonth()]} ${date.getFullYear()}`;
+}
\ No newline at end of file
diff --git a/src/lib/matrixHandler.js b/src/lib/matrixHandler.js
new file mode 100644
index 0000000..20a209d
--- /dev/null
+++ b/src/lib/matrixHandler.js
@@ -0,0 +1,75 @@
+import matrix from 'matrix-js-sdk';
+
+export class MatrixHandler {
+ constructor(clientDisplayName = 'matrix-chat') {
+ this.clientDisplayName = clientDisplayName;
+ this.accessToken;
+ this.client = undefined;
+ this.rooms = [];
+ this.loading = undefined;
+ this.user = undefined;
+ this.baseUrl = undefined;
+ }
+ login(user, password, baseUrl, onError, callback = ()=>{}){
+ if (this.client){ console.log('there is already an active session'); return; }
+ this.client = new matrix.createClient({
+ baseUrl: baseUrl
+ });
+ this.client.login('m.login.password', {
+ user: user,
+ password: password,
+ initial_device_display_name: this.clientDisplayName,
+ }).then((response) => {
+ if (response.error) {
+ this.logout();
+ console.log(`login error => ${response.error}`);
+ onError(response.error);
+ }
+ if (response.access_token){
+ console.log(`access token => ${response.access_token}`);
+ callback(response.access_token);
+ this.user = user;
+ this.baseUrl = baseUrl;
+ this.startSync()
+ }
+ }).catch(error => {
+ this.logout();
+ console.log(error);
+ onError(error.toString());
+ })
+ }
+ tokenLogin(baseUrl, accessToken, userId){
+ if (this.client){ console.log('there is already an active session'); return; }
+ this.client = new matrix.createClient({baseUrl, accessToken, userId});
+ this.user = userId;
+ this.baseUrl = baseUrl;
+ this.startSync();
+ }
+ logout(){
+ this.client.stopClient();
+ this.client = undefined;
+ }
+ startSync(callback = ()=>{}){
+ this.loading = true;
+ this.client.startClient();
+ this.client.once('sync', (state) => {
+ console.log(state);
+ this.rooms = this.client.getRooms();
+ console.log(this.rooms)
+ this.loading = false;
+ callback();
+ });
+ this.client.on('event', (event) => {
+ if (event.getType() === 'm.room.create') {
+ console.log(event)
+ }
+ })
+ }
+ async sendEvent(msg, roomId){
+ await this.client.sendEvent(roomId, msg.type, msg.content, '').then(() => {
+ console.log('message sent successfully');
+ }).catch((err) => {
+ console.log(`error while sending message => ${err}`);
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/lib/splitArray.js b/src/lib/splitArray.js
new file mode 100644
index 0000000..bf2761c
--- /dev/null
+++ b/src/lib/splitArray.js
@@ -0,0 +1,10 @@
+export default function splitArray(arr, key, get=obj=>obj){
+ let payload = [[]];
+ arr.forEach((obj, i) => {
+ let nextObj = arr[i+1];
+ payload[payload.length-1].push(get(obj));
+ if (!nextObj) return payload;
+ if (key(obj) !== key(nextObj)) payload.push([]);
+ })
+ return payload;
+}
\ No newline at end of file
diff --git a/src/main.js b/src/main.js
index 78d29e5..78856ee 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,81 +1,26 @@
-import Vue from "vue"
-import VueRouter from "vue-router"
-import App from "./App.vue"
-import login from "./views/login.vue"
-import chat from "./views/chat.vue"
-import rooms from "./views/rooms.vue"
+import Vue from 'vue'
+import VueRouter from 'vue-router'
+import App from './App.vue'
+import {router} from './router.js'
+import {MatrixHandler} from './lib/matrixHandler.js'
+import {cookieHandler} from './lib/cookieHandler.js';
-Vue.config.productionTip = false
-Vue.use(VueRouter)
+Vue.config.productionTip = false;
+Vue.use(VueRouter);
-const router = new VueRouter({
- routes: [
- {
- path: "/",
- name: "home",
- component: login
- },
- {
- path: "/login",
- name: "login",
- component: login
- },
- {
- path: "/chat/*",
- name: "chat",
- component: chat
- },
- {
- path: "/rooms/*",
- name: "room",
- component: rooms
- },
- {
- path: "/rooms",
- name: "rooms",
- component: rooms
- }
- ]
-})
+export let matrix = new MatrixHandler();
-let chatroom = {
- name: "open chat",
- user: [],
- username: "you",
- messages: []
-}
-
-export default {
- data(){
- return {
- chatroom: chatroom
- }
- },
- methods: {
- error(msg){
- show_error(msg)
- },
- router(route){router.push(route)}
- }
+let cookie = new cookieHandler().getCookies();
+if (cookie && cookie.baseUrl && cookie.accessToken && cookie.userId) {
+ matrix.tokenLogin(cookie.baseUrl, cookie.accessToken, cookie.userId);
}
new Vue({
- el: "#app",
- router,
- template: "",
- components: {App},
- data(){
- return {
- chatroom: chatroom
- }
- }
-}).$mount("#app")
-
-function element(id){ return document.getElementById(id)}
-function show_error(msg) {
- let error_style = element("errorBox").style
- element("errorMessage").innerText = msg
- error_style.display = "block"
- error_style.animation = "slide-from-left alternate 0.2s"
- setTimeout(() => {error_style.animation = ""}, 200)
-}
\ No newline at end of file
+ el: '#app',
+ router,
+ template: '',
+ components: {App},
+ data() {
+ return {}
+ }
+}).$mount('#app');
diff --git a/src/matrix.js b/src/matrix.js
index f4819df..633cd3c 100644
--- a/src/matrix.js
+++ b/src/matrix.js
@@ -1,8 +1,8 @@
-import matrix from 'matrix-js-sdk';
+/*import matrix from 'matrix-js-sdk';
import main from '@/main.js';
// import Vue from 'vue';
-let client = matrix.createClient({});
+let client = undefined;
let session = {
user: '',
baseUrl: '',
@@ -44,23 +44,12 @@ export default {
data() {
return {
session,
+ client
};
},
methods: {
login() {
- if (session.accessToken !== '') {
- main.methods.error('you are already logged in');
- return;
- } if (session.login.user === '') {
- main.methods.error('username is empty');
- return;
- } if (session.login.password === '') {
- main.methods.error('password is empty');
- return;
- } if (!(session.login.user.includes('@') && session.login.user.includes(':'))) {
- main.methods.error('username is in wrong style');
- return;
- }
+
client = matrix.createClient({
baseUrl: session.login.baseUrl
});
@@ -72,6 +61,7 @@ export default {
document.cookie = `accessToken=${response.access_token}`;
document.cookie = `userId=${session.login.user}`;
document.cookie = `baseUrl=${session.login.baseUrl}`;
+ document.cookie = `SameSite=Strict`;
document.cookie = `expires=${new Date(Date.now() + 86400 * 10 * 1000)}`;
session = {
user: session.login.user,
@@ -86,12 +76,12 @@ export default {
console.log(`login error => ${response.error}`);
}
window.location.href = '/#/rooms/';
- window.location.reload();
+ window.location.reload();*/
/*client.startClient();
client.once('sync', (state) => {
console.log(state);
});*/
- });
+/* });
},
logout(){
document.cookie = `accessToken=`;
@@ -124,7 +114,7 @@ function getCookie(key) {
return cookie ? cookie.split('=')[1] : false;
}
-client.on('event', (event) => {
+/*client.on('event', (event) => {
//console.log(event.getType());
//console.log(event);
if (event.getType() === 'm.room.name') {
@@ -175,4 +165,4 @@ client.on('Room.timeline', (event, room) => {
} else document.getElementById('scrollDown').style.display = 'block';
}
}
-});
+});*/
diff --git a/src/router.js b/src/router.js
new file mode 100644
index 0000000..98f0ff5
--- /dev/null
+++ b/src/router.js
@@ -0,0 +1,34 @@
+import VueRouter from 'vue-router';
+import login from '@/views/login';
+import chat from '@/views/chat';
+import rooms from '@/views/rooms';
+
+export const router = new VueRouter({
+ routes: [
+ {
+ path: '/',
+ name: 'home',
+ component: login
+ },
+ {
+ path: '/login',
+ name: 'login',
+ component: login
+ },
+ {
+ path: '/chat/*',
+ name: 'chat',
+ component: chat
+ },
+ {
+ path: '/rooms/*',
+ name: 'room',
+ component: rooms
+ },
+ {
+ path: '/rooms',
+ name: 'rooms',
+ component: rooms
+ }
+ ]
+})
\ No newline at end of file
diff --git a/src/views/chat.vue b/src/views/chat.vue
index cf64bf5..42f5380 100644
--- a/src/views/chat.vue
+++ b/src/views/chat.vue
@@ -1,103 +1,112 @@
-
-
-
this room is empty
-
-
{{getDate(message.origin_server_ts)}}
-
-
{{message.sender}}
-
-
-
+
+
+
{{loadingStatus}}
+
this room is empty
+
+
-
-
-
+
+
-
+
\ No newline at end of file
diff --git a/src/views/login.vue b/src/views/login.vue
index ecdc93f..726b78e 100644
--- a/src/views/login.vue
+++ b/src/views/login.vue
@@ -1,15 +1,16 @@
[chat]
-
you are already logged in
-
+
@@ -17,7 +18,8 @@
@@ -116,17 +145,13 @@ export default {
left: 20rem;
text-align: center;
}
-.roomImgPlaceholder{
+.roomImg{
position: absolute;
- left: 1rem;
- height: 2rem;
+ left: 0.5rem;
+ height: 3rem;
width: 3rem;
- padding-top: 1rem;
- background-color: #42a7b9;
- border-radius: 1.5rem;
- text-align: center;
}
-.roomImgPlaceholder.small{
+.roomImg.small{
margin-left: calc(50% - 2rem);
}