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)}}
{{room.name}}
-
{{room.members.length}} members
+
{{getMembers().length}} members
-

members:

-
- +

members:

+
+
-
{{member.content.displayname?member.content.displayname:member.sender}}
-
+
{{getUser(member).displayName || member}}
+
{{getStatus(getUser(member))}}
-

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 @@ + + + + + \ 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 @@ - \ 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 @@ - + \ 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 @@