mirror of
https://github.com/Troplo/Colubrina.git
synced 2024-12-25 16:05:14 +11:00
v1.0.13
This commit is contained in:
parent
344fce43ab
commit
e2cb2adff6
22 changed files with 436 additions and 532 deletions
|
@ -4,8 +4,6 @@ let express = require("express")
|
|||
let app = express()
|
||||
let bodyParser = require("body-parser")
|
||||
let os = require("os")
|
||||
const cookieParser = require("cookie-parser")
|
||||
app.use(cookieParser())
|
||||
app.set("trust proxy", true)
|
||||
const socket = require("./lib/socket")
|
||||
const server = require("http").createServer(app)
|
||||
|
@ -45,7 +43,6 @@ app.all("/api/*", (req, res) => {
|
|||
console.log(os.hostname())
|
||||
|
||||
app.use(require("./lib/errorHandler"))
|
||||
|
||||
server.listen(23998, () => {
|
||||
console.log("Initialized")
|
||||
console.log("Listening on port 0.0.0.0:" + 23998)
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
const { User, Theme, Session } = require("../models")
|
||||
const Errors = require("./errors")
|
||||
const { Op } = require("sequelize")
|
||||
module.exports = async function (req, res, next) {
|
||||
try {
|
||||
if (req.header("Authorization") && req.header("Authorization") !== "null") {
|
||||
const token = req.header("Authorization")
|
||||
const session = await Session.findOne({ where: { session: token } })
|
||||
const session = await Session.findOne({
|
||||
where: {
|
||||
session: token,
|
||||
expiredAt: {
|
||||
[Op.gt]: new Date()
|
||||
}
|
||||
}
|
||||
})
|
||||
if (session) {
|
||||
const user = await User.findOne({
|
||||
where: { id: session.userId },
|
||||
|
|
|
@ -1,51 +1,35 @@
|
|||
const { User, Theme, Session } = require("../models")
|
||||
const { Op } = require("sequelize")
|
||||
|
||||
const parseCookie = (str) =>
|
||||
str
|
||||
.split(";")
|
||||
.map((v) => v.split("="))
|
||||
.reduce((acc, v) => {
|
||||
acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim())
|
||||
return acc
|
||||
}, {})
|
||||
module.exports = async function (socket, next) {
|
||||
try {
|
||||
const cookies = parseCookie(socket.handshake.headers.cookie)
|
||||
if (cookies["session"]) {
|
||||
const session = await Session.findOne({
|
||||
where: { session: cookies["session"] }
|
||||
})
|
||||
if (session) {
|
||||
const user = await User.findOne({
|
||||
where: { id: session.userId },
|
||||
attributes: {
|
||||
exclude: ["totp", "password", "emailToken"]
|
||||
},
|
||||
include: [
|
||||
{
|
||||
model: Theme,
|
||||
as: "themeObject"
|
||||
}
|
||||
],
|
||||
raw: true
|
||||
})
|
||||
if (user) {
|
||||
if (user.banned) {
|
||||
socket.user = {
|
||||
id: null,
|
||||
username: "Not Authenticated"
|
||||
}
|
||||
next()
|
||||
} else {
|
||||
socket.user = user
|
||||
next()
|
||||
const token = socket.handshake.auth.token
|
||||
const session = await Session.findOne({
|
||||
where: {
|
||||
session: token,
|
||||
expiredAt: {
|
||||
[Op.gt]: new Date()
|
||||
}
|
||||
}
|
||||
})
|
||||
if (session) {
|
||||
const user = await User.findOne({
|
||||
where: { id: session.userId },
|
||||
attributes: {
|
||||
exclude: ["totp", "compassSession", "password"]
|
||||
},
|
||||
include: [
|
||||
{
|
||||
model: Theme,
|
||||
as: "themeObject"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
socket.user = {
|
||||
id: null,
|
||||
username: "Not Authenticated"
|
||||
}
|
||||
]
|
||||
})
|
||||
if (user) {
|
||||
await user.update({
|
||||
lastSeenAt: new Date().toISOString()
|
||||
})
|
||||
socket.user = user
|
||||
next()
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -45,7 +45,8 @@ let Errors = {
|
|||
401
|
||||
],
|
||||
mailFail: ["There was an error sending the verification email.", 400],
|
||||
invalidToken: ["The token you provided is invalid.", 400]
|
||||
invalidToken: ["The token you provided is invalid.", 400],
|
||||
cannotFriendYourself: ["You cannot friend yourself.", 400]
|
||||
}
|
||||
|
||||
function processErrors(errorName) {
|
||||
|
|
|
@ -122,126 +122,10 @@ module.exports = {
|
|||
socket.emit("unauthorized", {
|
||||
message: "Please reauth."
|
||||
})
|
||||
socket.on("token", async (token) => {
|
||||
const session = await Session.findOne({ where: { session: token } })
|
||||
if (session) {
|
||||
const user = await User.findOne({
|
||||
where: { id: session.userId },
|
||||
attributes: {
|
||||
exclude: ["totp", "password", "emailToken"]
|
||||
},
|
||||
include: [
|
||||
{
|
||||
model: Theme,
|
||||
as: "themeObject"
|
||||
}
|
||||
]
|
||||
})
|
||||
if (user) {
|
||||
socket.user = user
|
||||
socket.join(user.id)
|
||||
socket.emit("authorized")
|
||||
socket.join(user.id)
|
||||
socket.emit("siteState", {
|
||||
release: process.env.RELEASE,
|
||||
notification: process.env.NOTIFICATION,
|
||||
notificationType: process.env.NOTIFICATION_TYPE,
|
||||
latestVersion: require("../../frontend/package.json").version
|
||||
})
|
||||
const friends = await Friend.findAll({
|
||||
where: {
|
||||
userId: user.id,
|
||||
status: "accepted"
|
||||
}
|
||||
})
|
||||
await user.update({
|
||||
status:
|
||||
user.storedStatus === "invisible"
|
||||
? "offline"
|
||||
: user.storedStatus
|
||||
})
|
||||
friends.forEach((friend) => {
|
||||
io.to(friend.friendId).emit("userStatus", {
|
||||
userId: user.id,
|
||||
status:
|
||||
user.storedStatus === "invisible"
|
||||
? "offline"
|
||||
: user.storedStatus
|
||||
})
|
||||
})
|
||||
socket.on("ping", () => {
|
||||
socket.emit("pong")
|
||||
})
|
||||
socket.on("bcBots/deleteMessage", (e) => {
|
||||
if (socket.user.bot) {
|
||||
socket.to(e.userId).emit("deleteMessage", e)
|
||||
} else {
|
||||
socket.emit("bcBots/deleteMessage", {
|
||||
error: "You cannot perform this action."
|
||||
})
|
||||
}
|
||||
})
|
||||
socket.on("idle", async () => {
|
||||
const user = await User.findOne({
|
||||
where: {
|
||||
id: socket.user.id
|
||||
}
|
||||
})
|
||||
if (user.storedStatus === "online") {
|
||||
friends.forEach((friend) => {
|
||||
io.to(friend.friendId).emit("userStatus", {
|
||||
userId: user.id,
|
||||
status: "away"
|
||||
})
|
||||
})
|
||||
io.to(user.id).emit("userStatus", {
|
||||
userId: user.id,
|
||||
status: "away"
|
||||
})
|
||||
await user.update({
|
||||
status: "away"
|
||||
})
|
||||
}
|
||||
})
|
||||
socket.on("online", async () => {
|
||||
const user = await User.findOne({
|
||||
where: {
|
||||
id: socket.user.id
|
||||
}
|
||||
})
|
||||
if (user.storedStatus === "online") {
|
||||
friends.forEach((friend) => {
|
||||
io.to(friend.friendId).emit("userStatus", {
|
||||
userId: user.id,
|
||||
status: "online"
|
||||
})
|
||||
})
|
||||
io.to(user.id).emit("userStatus", {
|
||||
userId: user.id,
|
||||
status: "online"
|
||||
})
|
||||
await user.update({
|
||||
status: "online"
|
||||
})
|
||||
}
|
||||
})
|
||||
socket.on("disconnect", async function () {
|
||||
const clients =
|
||||
io.sockets.adapter.rooms.get(user.id) || new Set()
|
||||
if (!clients.size || clients.size === 0) {
|
||||
friends.forEach((friend) => {
|
||||
io.to(friend.friendId).emit("userStatus", {
|
||||
userId: user.id,
|
||||
status: "offline"
|
||||
})
|
||||
})
|
||||
await user.update({
|
||||
status: "offline"
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
socket.on("token", async () => {
|
||||
socket.emit("unsupported", {
|
||||
message: "This authentication method is unsupported."
|
||||
})
|
||||
})
|
||||
console.log("Unauthenticated user")
|
||||
socket.on("reAuth", async () => {
|
||||
|
|
|
@ -50,6 +50,9 @@ router.post("/", auth, async (req, res, next) => {
|
|||
}
|
||||
})
|
||||
if (user) {
|
||||
if (user.id === req.user.id) {
|
||||
throw Errors.cannotFriendYourself
|
||||
}
|
||||
const friend = await Friend.findOne({
|
||||
where: {
|
||||
userId: req.user.id,
|
||||
|
|
|
@ -133,27 +133,29 @@ router.post("/verify/resend", auth, mailLimiter, async (req, res, next) => {
|
|||
}
|
||||
})
|
||||
|
||||
router.post("/verify/confirm/:token", auth, async (req, res, next) => {
|
||||
router.post("/verify/confirm/:token", async (req, res, next) => {
|
||||
try {
|
||||
const user = await User.findOne({
|
||||
where: {
|
||||
id: req.user.id
|
||||
}
|
||||
})
|
||||
if (process.env.EMAIL_VERIFICATION !== "true") {
|
||||
throw Errors.invalidParameter("Email verification is disabled")
|
||||
}
|
||||
if (!req.params.token) {
|
||||
throw Errors.invalidToken
|
||||
}
|
||||
if (req.params.token !== user.emailToken) {
|
||||
const user = await User.findOne({
|
||||
where: {
|
||||
emailToken: req.params.token,
|
||||
emailVerified: false
|
||||
}
|
||||
})
|
||||
if (user) {
|
||||
await user.update({
|
||||
emailVerified: true,
|
||||
emailToken: null
|
||||
})
|
||||
res.json({ success: true })
|
||||
} else {
|
||||
throw Errors.invalidToken
|
||||
}
|
||||
await user.update({
|
||||
emailVerified: true,
|
||||
emailToken: null
|
||||
})
|
||||
res.json({ success: true })
|
||||
} catch (e) {
|
||||
next(e)
|
||||
}
|
||||
|
@ -198,12 +200,6 @@ router.post("/login", async (req, res, next) => {
|
|||
osVersion: ua.os.version
|
||||
}
|
||||
})
|
||||
res.cookie("session", session.session, {
|
||||
maxAge: 1000 * 60 * 60 * 24 * 365,
|
||||
httpOnly: true,
|
||||
secure: false,
|
||||
sameSite: "strict"
|
||||
})
|
||||
res.json({
|
||||
session: session.session,
|
||||
success: true,
|
||||
|
@ -287,12 +283,6 @@ router.post("/register", limiter, async (req, res, next) => {
|
|||
osVersion: ua.os.version
|
||||
}
|
||||
})
|
||||
res.cookie("session", session.session, {
|
||||
maxAge: 1000 * 60 * 60 * 24 * 365,
|
||||
httpOnly: true,
|
||||
secure: false,
|
||||
sameSite: "strict"
|
||||
})
|
||||
res.json({
|
||||
session: session.session,
|
||||
success: true,
|
||||
|
@ -371,15 +361,6 @@ router.delete("/sessions/:id", auth, async (req, res, next) => {
|
|||
}
|
||||
})
|
||||
|
||||
router.post("/logout", (req, res, next) => {
|
||||
try {
|
||||
res.clearCookie("session")
|
||||
res.sendStatus(204)
|
||||
} catch (e) {
|
||||
next(e)
|
||||
}
|
||||
})
|
||||
|
||||
router.post(
|
||||
"/settings/avatar",
|
||||
auth,
|
||||
|
|
|
@ -1,8 +1,26 @@
|
|||
{
|
||||
"name": "colubrina",
|
||||
"version": "1.0.12",
|
||||
"version": "1.0.13",
|
||||
"private": true,
|
||||
"author": "Troplo <troplo@troplo.com>",
|
||||
"build": {
|
||||
"appId": "com.troplo.colubrina",
|
||||
"win": {
|
||||
"publish": [
|
||||
"github"
|
||||
]
|
||||
},
|
||||
"linux": {
|
||||
"publish": [
|
||||
"github"
|
||||
]
|
||||
},
|
||||
"mac": {
|
||||
"publish": [
|
||||
"github"
|
||||
]
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
|
@ -12,9 +30,11 @@
|
|||
"postinstall": "patch-package && electron-builder install-app-deps",
|
||||
"postuninstall": "electron-builder install-app-deps"
|
||||
},
|
||||
"main": "background.js",
|
||||
"repository": "https://github.com/Troplo/Colubrina",
|
||||
"dependencies": {
|
||||
"@babel/preset-env": "^7.17.10",
|
||||
"@mdi/font": "6.5.95",
|
||||
"@mdi/js": "^6.6.95",
|
||||
"axios": "^0.26.1",
|
||||
"brace": "^0.11.1",
|
||||
|
@ -23,8 +43,6 @@
|
|||
"dayjs": "^1.11.0",
|
||||
"ejs": "^3.1.7",
|
||||
"glob-parent": "^5.1.2",
|
||||
"graphql": "^16.3.0",
|
||||
"graphql-tag": "^2.12.6",
|
||||
"highlight.js": "^11.6.0",
|
||||
"markdown-it": "^13.0.1",
|
||||
"markdown-it-emoji": "git+https://github.com/Troplo/markdown-it-unicode-emoji",
|
||||
|
@ -39,16 +57,13 @@
|
|||
"socket.io-client": "^4.5.1",
|
||||
"twemoji": "^14.0.2",
|
||||
"vue": "^2.6.11",
|
||||
"vue-apollo": "^3.1.0",
|
||||
"vue-axios": "^3.4.1",
|
||||
"vue-chartjs": "^4.0.1",
|
||||
"vue-final-modal": "^2.4.1",
|
||||
"vue-matomo": "^4.1.0",
|
||||
"vue-native-notification": "^1.1.1",
|
||||
"vue-router": "^3.2.0",
|
||||
"vue-sanitize": "^0.2.1",
|
||||
"vue-shortkey": "^3.1.7",
|
||||
"vue-swatches": "^2.1.1",
|
||||
"vue-toastification": "^1.7.14",
|
||||
"vue2-ace-editor": "^0.0.15",
|
||||
"vuetify": "^2.6.4",
|
||||
|
@ -56,7 +71,6 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.16.7",
|
||||
"@mdi/font": "6.5.95",
|
||||
"@vue/cli-plugin-babel": "~4.5.15",
|
||||
"@vue/cli-plugin-eslint": "~4.5.15",
|
||||
"@vue/cli-plugin-pwa": "~4.5.15",
|
||||
|
|
|
@ -437,12 +437,15 @@
|
|||
is limited.
|
||||
</v-alert>
|
||||
</v-container>
|
||||
<router-view
|
||||
:style="
|
||||
'background-color: ' +
|
||||
$vuetify.theme.themes[$vuetify.theme.dark ? 'dark' : 'light'].bg
|
||||
"
|
||||
/>
|
||||
<div @touchstart="touchStart" @touchend="touchEnd">
|
||||
<router-view
|
||||
id="main"
|
||||
:style="
|
||||
'background-color: ' +
|
||||
$vuetify.theme.themes[$vuetify.theme.dark ? 'dark' : 'light'].bg
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</v-main>
|
||||
</v-app>
|
||||
</template>
|
||||
|
@ -451,7 +454,7 @@
|
|||
import AjaxErrorHandler from "@/lib/errorHandler"
|
||||
import { VueFinalModal } from "vue-final-modal"
|
||||
import Header from "@/components/Header"
|
||||
import Vue from "vue"
|
||||
|
||||
export default {
|
||||
name: "App",
|
||||
components: {
|
||||
|
@ -479,7 +482,9 @@ export default {
|
|||
results: [],
|
||||
searchInput: null,
|
||||
themes: [],
|
||||
cssTips: true
|
||||
cssTips: true,
|
||||
touchStartX: null,
|
||||
touchEndX: null
|
||||
}),
|
||||
computed: {
|
||||
creatorJSON: {
|
||||
|
@ -702,6 +707,19 @@ export default {
|
|||
})
|
||||
})
|
||||
},
|
||||
touchEnd(event) {
|
||||
this.touchEndX = event.changedTouches[0].screenX
|
||||
if (this.touchEndX > this.touchStartX) {
|
||||
if (this.touchEndX - this.touchStartX > 100) {
|
||||
this.touchStartX = null
|
||||
this.touchEndX = null
|
||||
this.$store.state.drawer = true
|
||||
}
|
||||
}
|
||||
},
|
||||
touchStart(event) {
|
||||
this.touchStartX = event.changedTouches[0].screenX
|
||||
},
|
||||
setTheme(theme) {
|
||||
const name = theme.id
|
||||
const dark = theme.dark
|
||||
|
@ -728,23 +746,8 @@ export default {
|
|||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
Vue.axios.defaults.headers.common["X-Colubrina"] = true
|
||||
Vue.axios.defaults.headers.common["Authorization"] =
|
||||
localStorage.getItem("session")
|
||||
console.log(localStorage.getItem("instance"))
|
||||
if (process.env.IS_ELECTRON) {
|
||||
this.axios.defaults.baseURL = localStorage.getItem("instance")
|
||||
this.$store.state.baseURL = localStorage.getItem("instance")
|
||||
}
|
||||
if (localStorage.getItem("customHeaders")) {
|
||||
console.log(JSON.parse(localStorage.getItem("customHeaders")))
|
||||
for (let header in JSON.parse(localStorage.getItem("customHeaders"))) {
|
||||
Vue.axios.defaults.headers[header] = JSON.parse(
|
||||
localStorage.getItem("customHeaders")
|
||||
)[header]
|
||||
}
|
||||
}
|
||||
async mounted() {
|
||||
await this.$store.dispatch("doInit")
|
||||
if (this.$vuetify.breakpoint.mobile) {
|
||||
this.$store.state.drawer = false
|
||||
}
|
||||
|
@ -772,7 +775,8 @@ export default {
|
|||
})
|
||||
this.$socket.connect()
|
||||
this.$socket.on("unauthorized", () => {
|
||||
this.$socket.emit("token", localStorage.getItem("session"))
|
||||
console.log("Reauth requested")
|
||||
this.$socket.emit("token", localStorage.getItem("token"))
|
||||
})
|
||||
document.title = this.$route.name
|
||||
? this.$route.name + " - " + this.$store.state.site.name
|
||||
|
@ -780,13 +784,10 @@ export default {
|
|||
this.$store.commit("setLoading", true)
|
||||
this.$vuetify.theme.dark = this.$store.state.user?.theme === "dark" || true
|
||||
this.$store.dispatch("getState")
|
||||
this.getThemes()
|
||||
this.communicationsIdleCheck()
|
||||
this.$store
|
||||
.dispatch("getUserInfo")
|
||||
.then(() => {
|
||||
console.log(window.location.pathname)
|
||||
// check if its /email/confirm/<token>
|
||||
if (
|
||||
!window.location.pathname.includes("/email/confirm/") &&
|
||||
!window.location.pathname.includes("/email/verify") &&
|
||||
|
@ -797,10 +798,10 @@ export default {
|
|||
}
|
||||
})
|
||||
.catch(() => {
|
||||
if (!["/login", "/register"].includes(this.$route.path)) {
|
||||
this.$router.push("/login")
|
||||
}
|
||||
this.$router.push("/login")
|
||||
})
|
||||
this.getThemes()
|
||||
this.communicationsIdleCheck()
|
||||
this.registerSocket()
|
||||
},
|
||||
watch: {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.offset-message {
|
||||
padding-left: 47px;
|
||||
padding-left: 53px;
|
||||
}
|
||||
.message-action-card {
|
||||
position: absolute;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"use strict"
|
||||
|
||||
import { app, protocol, BrowserWindow } from "electron"
|
||||
import { app, protocol, BrowserWindow, screen } from "electron"
|
||||
import { createProtocol } from "vue-cli-plugin-electron-builder/lib"
|
||||
import installExtension, { VUEJS_DEVTOOLS } from "electron-devtools-installer"
|
||||
const isDevelopment = process.env.NODE_ENV !== "production"
|
||||
|
@ -12,15 +12,25 @@ protocol.registerSchemesAsPrivileged([
|
|||
|
||||
async function createWindow() {
|
||||
// Create the browser window.
|
||||
const { bounds } = screen.getDisplayNearestPoint(
|
||||
screen.getCursorScreenPoint()
|
||||
)
|
||||
const height = Math.floor(bounds.height * (2 / 3))
|
||||
const width = Math.floor(bounds.width * (2 / 3))
|
||||
const y = Math.floor(bounds.y + (bounds.height - height) / 2)
|
||||
const x = Math.floor(bounds.x + (bounds.width - width) / 2)
|
||||
const win = new BrowserWindow({
|
||||
width: 1400,
|
||||
height: 1000,
|
||||
width,
|
||||
height,
|
||||
x,
|
||||
y,
|
||||
webPreferences: {
|
||||
// Use pluginOptions.nodeIntegration, leave this alone
|
||||
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
|
||||
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
|
||||
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
|
||||
preload: "window-preload.js",
|
||||
// required for multi-instance support
|
||||
webSecurity: false
|
||||
}
|
||||
})
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
<v-textarea
|
||||
:style="
|
||||
!$vuetify.breakpoint.mobile
|
||||
? 'margin-bottom: 3px'
|
||||
: 'margin-bottom: -17px'
|
||||
? 'margin-bottom: 5px'
|
||||
: 'margin-bottom: 0px'
|
||||
"
|
||||
autofocus
|
||||
label="Type a message"
|
||||
|
|
|
@ -307,7 +307,7 @@
|
|||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
<v-app-bar app color="bg">
|
||||
<v-app-bar app color="dark" elevation="5" style="z-index: 15">
|
||||
<v-app-bar-nav-icon
|
||||
@click.stop="$store.state.drawer = !$store.state.drawer"
|
||||
v-if="$vuetify.breakpoint.mobile || !$store.state.drawer"
|
||||
|
@ -381,10 +381,11 @@
|
|||
</template>
|
||||
</v-app-bar>
|
||||
<v-navigation-drawer
|
||||
color="bg"
|
||||
floating
|
||||
color="dark"
|
||||
app
|
||||
style="max-height: 100%"
|
||||
floating
|
||||
style="max-height: 100%; z-index: 15"
|
||||
class="elevation-5"
|
||||
v-model="$store.state.drawer"
|
||||
:width="$vuetify.breakpoint.mobile ? 270 : 320"
|
||||
>
|
||||
|
@ -414,7 +415,7 @@
|
|||
</template>
|
||||
<template v-else>
|
||||
<v-btn
|
||||
color="toolbar"
|
||||
color="sheet"
|
||||
to="/communications/friends"
|
||||
block
|
||||
class="mb-3 rounded-xl"
|
||||
|
@ -429,12 +430,12 @@
|
|||
solo
|
||||
label="Search..."
|
||||
append-icon="mdi-magnify"
|
||||
background-color="toolbar"
|
||||
background-color="sheet"
|
||||
style="margin-bottom: -18px"
|
||||
elevation="2"
|
||||
v-model="search"
|
||||
></v-text-field>
|
||||
<v-toolbar color="toolbar" class="rounded-xl mb-3" elevation="2">
|
||||
<v-toolbar color="sheet" class="rounded-xl mb-3" elevation="2">
|
||||
<v-toolbar-title class="subtitle-1">
|
||||
CHATS ({{ chats.length }})
|
||||
</v-toolbar-title>
|
||||
|
@ -522,6 +523,7 @@
|
|||
</v-container>
|
||||
<template v-slot:append>
|
||||
<v-card tile color="bg" elevation="0">
|
||||
<v-divider></v-divider>
|
||||
<v-overlay :value="!$store.state.wsConnected" absolute>
|
||||
<v-progress-circular indeterminate size="48"></v-progress-circular>
|
||||
</v-overlay>
|
||||
|
@ -985,7 +987,7 @@ export default {
|
|||
},
|
||||
mounted() {
|
||||
Vue.axios.defaults.headers.common["Authorization"] =
|
||||
localStorage.getItem("session")
|
||||
localStorage.getItem("token")
|
||||
this.searchUsers()
|
||||
this.searchUsersForGroupAdmin()
|
||||
this.$store.dispatch("getChats")
|
||||
|
|
|
@ -37,12 +37,15 @@
|
|||
</v-toolbar>
|
||||
<v-list-item
|
||||
:key="message.keyId"
|
||||
:class="{ 'message-hover': hover }"
|
||||
:class="{
|
||||
'message-hover': hover,
|
||||
'pa-0': $vuetify.breakpoint.mobile
|
||||
}"
|
||||
:id="'message-' + index"
|
||||
@contextmenu="show($event, 'message', message)"
|
||||
:style="lastMessage ? 'margin-bottom: -5px; margin-top: -5px;' : ''"
|
||||
>
|
||||
<v-avatar size="40" class="mr-2" v-if="!lastMessage">
|
||||
<v-avatar size="45" class="mr-2" v-if="!lastMessage">
|
||||
<v-img
|
||||
:src="
|
||||
$store.state.baseURL + '/usercontent/' + message.user.avatar
|
||||
|
@ -124,7 +127,7 @@
|
|||
no-gutters
|
||||
>
|
||||
<v-card
|
||||
elevaion="0"
|
||||
elevation="0"
|
||||
:color="
|
||||
embed.type === 'embed-v1' ? embed.backgroundColor : 'bg'
|
||||
"
|
||||
|
@ -308,7 +311,7 @@
|
|||
:id="'attachment-' + index"
|
||||
:max-width="500"
|
||||
:min-width="!$vuetify.breakpoint.mobile ? 400 : 0"
|
||||
elevaion="0"
|
||||
elevation="0"
|
||||
color="card"
|
||||
>
|
||||
<v-hover
|
||||
|
|
|
@ -69,7 +69,10 @@ Vue.use({
|
|||
{
|
||||
transports: ["websocket", "polling"],
|
||||
headers: {
|
||||
Authorization: localStorage.getItem("session")
|
||||
Authorization: localStorage.getItem("token")
|
||||
},
|
||||
auth: {
|
||||
token: localStorage.getItem("token")
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -25,6 +25,7 @@ function getDirectRecipient(context, item) {
|
|||
}
|
||||
export default new Vuex.Store({
|
||||
state: {
|
||||
desktop: !!process.env.IS_ELECTRON,
|
||||
online: true,
|
||||
selectedChat: null,
|
||||
chats: [],
|
||||
|
@ -142,7 +143,7 @@ export default new Vuex.Store({
|
|||
actions: {
|
||||
getChats(context) {
|
||||
Vue.axios.defaults.headers.common["Authorization"] =
|
||||
localStorage.getItem("session")
|
||||
localStorage.getItem("token")
|
||||
Vue.axios
|
||||
.get("/api/v1/communications")
|
||||
.then((res) => {
|
||||
|
@ -266,7 +267,7 @@ export default new Vuex.Store({
|
|||
checkAuth() {
|
||||
return new Promise((resolve, reject) => {
|
||||
Vue.axios.defaults.headers.common["Authorization"] =
|
||||
localStorage.getItem("session")
|
||||
localStorage.getItem("token")
|
||||
Vue.axios
|
||||
.get("/api/v1/user")
|
||||
.then(() => {
|
||||
|
@ -282,21 +283,13 @@ export default new Vuex.Store({
|
|||
})
|
||||
},
|
||||
logout(context) {
|
||||
Vue.axios
|
||||
.post("/api/v1/user/logout")
|
||||
.then(() => {
|
||||
context.commit("setToken", null)
|
||||
localStorage.removeItem("userCache")
|
||||
localStorage.removeItem("session")
|
||||
Vue.axios.defaults.headers.common["Authorization"] = null
|
||||
context.commit("setUser", {
|
||||
bcUser: null,
|
||||
loggedIn: false
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
Vue.$toast.error("Failed to logout.")
|
||||
})
|
||||
localStorage.removeItem("userCache")
|
||||
localStorage.removeItem("token")
|
||||
Vue.axios.defaults.headers.common["Authorization"] = null
|
||||
context.commit("setUser", {
|
||||
bcUser: null,
|
||||
loggedIn: false
|
||||
})
|
||||
},
|
||||
generateCache() {
|
||||
// todo
|
||||
|
@ -366,38 +359,58 @@ export default new Vuex.Store({
|
|||
}
|
||||
})
|
||||
},
|
||||
getUserInfo(context) {
|
||||
doInit(context) {
|
||||
if (context.state.desktop) {
|
||||
Vue.axios.defaults.baseURL = localStorage.getItem("instance")
|
||||
context.state.baseURL = localStorage.getItem("instance")
|
||||
}
|
||||
Vue.axios.defaults.headers.common["X-Colubrina"] = true
|
||||
Vue.axios.defaults.headers.common["X-Colubrina-Version"] =
|
||||
context.state.versioning.version
|
||||
Vue.axios.defaults.headers.common["Authorization"] =
|
||||
localStorage.getItem("session")
|
||||
return new Promise((resolve, reject) => {
|
||||
localStorage.getItem("token")
|
||||
if (localStorage.getItem("customHeaders")) {
|
||||
for (let header in JSON.parse(localStorage.getItem("customHeaders"))) {
|
||||
Vue.axios.defaults.headers[header] = JSON.parse(
|
||||
localStorage.getItem("customHeaders")
|
||||
)[header]
|
||||
}
|
||||
}
|
||||
},
|
||||
getUserInfo(context) {
|
||||
function setUser(user) {
|
||||
try {
|
||||
const user = JSON.parse(localStorage.getItem("userCache"))
|
||||
if (user?.id) {
|
||||
context.commit("setUser", user)
|
||||
const name = user.themeObject.id
|
||||
const dark = user.themeObject.theme.dark
|
||||
const light = user.themeObject.theme.light
|
||||
if (user.accentColor) {
|
||||
user.themeObject.theme.dark.primary = user.accentColor
|
||||
user.themeObject.theme.light.primary = user.accentColor
|
||||
}
|
||||
Vuetify.framework.theme.themes.dark = dark
|
||||
Vuetify.framework.theme.themes.light = light
|
||||
Vuetify.framework.theme.themes.name = name
|
||||
Vuetify.framework.theme.themes.primaryType =
|
||||
user.themeObject.theme.primaryType
|
||||
const themeElement = document.getElementById("user-theme")
|
||||
if (!themeElement) {
|
||||
const style = document.createElement("style")
|
||||
style.id = "user-theme"
|
||||
style.innerHTML = user.themeObject.theme.css
|
||||
document.head.appendChild(style)
|
||||
}
|
||||
const fontElement = document.getElementById("user-font")
|
||||
if (!fontElement) {
|
||||
const style = document.createElement("style")
|
||||
style.id = "user-font"
|
||||
style.innerHTML = `/* Stop from font breaking CSS code editor */
|
||||
Vue.$socket.emit("connection", {
|
||||
message: true
|
||||
})
|
||||
} catch {
|
||||
console.log("Socket not connected")
|
||||
}
|
||||
localStorage.setItem("userCache", JSON.stringify(user))
|
||||
const name = user.themeObject.id
|
||||
const dark = user.themeObject.theme.dark
|
||||
const light = user.themeObject.theme.light
|
||||
if (user.accentColor) {
|
||||
user.themeObject.theme.dark.primary = user.accentColor
|
||||
user.themeObject.theme.light.primary = user.accentColor
|
||||
}
|
||||
Vuetify.framework.theme.themes.dark = dark
|
||||
Vuetify.framework.theme.themes.light = light
|
||||
Vuetify.framework.theme.themes.name = name
|
||||
Vuetify.framework.theme.themes.primaryType =
|
||||
user.themeObject.theme.primaryType
|
||||
const themeElement = document.getElementById("user-theme")
|
||||
if (!themeElement) {
|
||||
const style = document.createElement("style")
|
||||
style.id = "user-theme"
|
||||
style.innerHTML = user.themeObject.theme.css
|
||||
document.head.appendChild(style)
|
||||
}
|
||||
const fontElement = document.getElementById("user-font")
|
||||
if (!fontElement) {
|
||||
const style = document.createElement("style")
|
||||
style.id = "user-font"
|
||||
style.innerHTML = `/* Stop from font breaking CSS code editor */
|
||||
.ace_editor div {
|
||||
font-family: "JetBrains Mono" !important;
|
||||
}
|
||||
|
@ -406,8 +419,18 @@ div {
|
|||
font-family: "${user.font}", sans-serif;
|
||||
}
|
||||
`
|
||||
document.head.appendChild(style)
|
||||
}
|
||||
document.head.appendChild(style)
|
||||
}
|
||||
context.commit("setLoading", false)
|
||||
context.commit("setUser", user)
|
||||
}
|
||||
Vue.axios.defaults.headers.common["Authorization"] =
|
||||
localStorage.getItem("token")
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const user = JSON.parse(localStorage.getItem("userCache"))
|
||||
if (user?.id) {
|
||||
setUser(user)
|
||||
}
|
||||
} catch {
|
||||
//
|
||||
|
@ -415,94 +438,113 @@ div {
|
|||
Vue.axios
|
||||
.get("/api/v1/user")
|
||||
.then((res) => {
|
||||
context.commit("setUser", res.data)
|
||||
try {
|
||||
Vue.$socket.emit("connection", {
|
||||
message: true
|
||||
})
|
||||
} catch {
|
||||
console.log("Socket not connected")
|
||||
}
|
||||
localStorage.setItem("userCache", JSON.stringify(res.data))
|
||||
const name = res.data.themeObject.id
|
||||
const dark = res.data.themeObject.theme.dark
|
||||
const light = res.data.themeObject.theme.light
|
||||
if (res.data.accentColor) {
|
||||
res.data.themeObject.theme.dark.primary = res.data.accentColor
|
||||
res.data.themeObject.theme.light.primary = res.data.accentColor
|
||||
}
|
||||
Vuetify.framework.theme.themes.dark = dark
|
||||
Vuetify.framework.theme.themes.light = light
|
||||
Vuetify.framework.theme.themes.name = name
|
||||
Vuetify.framework.theme.themes.primaryType =
|
||||
res.data.themeObject.theme.primaryType
|
||||
const themeElement = document.getElementById("user-theme")
|
||||
if (!themeElement) {
|
||||
const style = document.createElement("style")
|
||||
style.id = "user-theme"
|
||||
style.innerHTML = res.data.themeObject.theme.css
|
||||
document.head.appendChild(style)
|
||||
}
|
||||
const fontElement = document.getElementById("user-font")
|
||||
if (!fontElement) {
|
||||
const style = document.createElement("style")
|
||||
style.id = "user-font"
|
||||
style.innerHTML = `/* Stop from font breaking CSS code editor */
|
||||
.ace_editor div {
|
||||
font-family: "JetBrains Mono" !important;
|
||||
}
|
||||
|
||||
div {
|
||||
font-family: "${res.data.font}", sans-serif;
|
||||
}
|
||||
`
|
||||
document.head.appendChild(style)
|
||||
}
|
||||
setUser(res.data)
|
||||
context.commit("setLoading", false)
|
||||
context.commit("setOnline", true)
|
||||
resolve(res.data)
|
||||
})
|
||||
.catch((e) => {
|
||||
if (JSON.parse(localStorage.getItem("userCache"))?.id) {
|
||||
try {
|
||||
const user = JSON.parse(localStorage.getItem("userCache"))
|
||||
const name = user.themeObject.id
|
||||
const dark = user.themeObject.theme.dark
|
||||
const light = user.themeObject.theme.light
|
||||
if (user.accentColor) {
|
||||
user.themeObject.theme.dark.primary = user.accentColor
|
||||
user.themeObject.theme.light.primary = user.accentColor
|
||||
if (user?.id && !e?.response?.data?.errors?.length) {
|
||||
setUser(user)
|
||||
} else {
|
||||
const theme = {
|
||||
id: 1,
|
||||
name: "Colubrina Classic",
|
||||
primaryType: "all",
|
||||
dark: {
|
||||
primary: "#0190ea",
|
||||
secondary: "#757575",
|
||||
accent: "#000000",
|
||||
error: "#ff1744",
|
||||
info: "#2196F3",
|
||||
success: "#4CAF50",
|
||||
warning: "#ff9800",
|
||||
card: "#151515",
|
||||
toolbar: "#191919",
|
||||
sheet: "#181818",
|
||||
text: "#000000",
|
||||
dark: "#151515",
|
||||
bg: "#151515"
|
||||
},
|
||||
light: {
|
||||
primary: "#0190ea",
|
||||
secondary: "#757575",
|
||||
accent: "#000000",
|
||||
error: "#ff1744",
|
||||
info: "#2196F3",
|
||||
success: "#4CAF50",
|
||||
warning: "#ff9800",
|
||||
card: "#f8f8f8",
|
||||
toolbar: "#f8f8f8",
|
||||
sheet: "#f8f8f8",
|
||||
text: "#000000",
|
||||
dark: "#f8f8f8",
|
||||
bg: "#f8f8f8"
|
||||
}
|
||||
}
|
||||
const name = theme.id
|
||||
const dark = theme.dark
|
||||
const light = theme.light
|
||||
Vuetify.framework.theme.themes.dark = dark
|
||||
Vuetify.framework.theme.themes.light = light
|
||||
Vuetify.framework.theme.themes.name = name
|
||||
this.name = name
|
||||
console.log("Failed to load Colubrina Account")
|
||||
context.user = null
|
||||
localStorage.removeItem("userCache")
|
||||
reject(e)
|
||||
}
|
||||
} catch {
|
||||
const theme = {
|
||||
id: 1,
|
||||
name: "Colubrina Classic",
|
||||
primaryType: "all",
|
||||
dark: {
|
||||
primary: "#0190ea",
|
||||
secondary: "#757575",
|
||||
accent: "#000000",
|
||||
error: "#ff1744",
|
||||
info: "#2196F3",
|
||||
success: "#4CAF50",
|
||||
warning: "#ff9800",
|
||||
card: "#151515",
|
||||
toolbar: "#191919",
|
||||
sheet: "#181818",
|
||||
text: "#000000",
|
||||
dark: "#151515",
|
||||
bg: "#151515"
|
||||
},
|
||||
light: {
|
||||
primary: "#0190ea",
|
||||
secondary: "#757575",
|
||||
accent: "#000000",
|
||||
error: "#ff1744",
|
||||
info: "#2196F3",
|
||||
success: "#4CAF50",
|
||||
warning: "#ff9800",
|
||||
card: "#f8f8f8",
|
||||
toolbar: "#f8f8f8",
|
||||
sheet: "#f8f8f8",
|
||||
text: "#000000",
|
||||
dark: "#f8f8f8",
|
||||
bg: "#f8f8f8"
|
||||
}
|
||||
}
|
||||
const name = theme.id
|
||||
const dark = theme.dark
|
||||
const light = theme.light
|
||||
Vuetify.framework.theme.themes.dark = dark
|
||||
Vuetify.framework.theme.themes.light = light
|
||||
Vuetify.framework.theme.themes.name = name
|
||||
Vuetify.framework.theme.themes.primaryType =
|
||||
user.themeObject.theme.primaryType
|
||||
const themeElement = document.getElementById("user-theme")
|
||||
if (!themeElement) {
|
||||
const style = document.createElement("style")
|
||||
style.id = "user-theme"
|
||||
style.innerHTML = user.themeObject.theme.css
|
||||
document.head.appendChild(style)
|
||||
}
|
||||
const fontElement = document.getElementById("user-font")
|
||||
if (!fontElement) {
|
||||
const style = document.createElement("style")
|
||||
style.id = "user-font"
|
||||
style.innerHTML = `/* Stop from font breaking CSS code editor */
|
||||
.ace_editor div {
|
||||
font-family: "JetBrains Mono" !important;
|
||||
}
|
||||
|
||||
div {
|
||||
font-family: "${user.font}", sans-serif;
|
||||
}
|
||||
`
|
||||
document.head.appendChild(style)
|
||||
}
|
||||
context.commit("setLoading", false)
|
||||
context.commit("setUser", user)
|
||||
resolve(user)
|
||||
} else {
|
||||
this.name = name
|
||||
console.log("Failed to load Colubrina Account")
|
||||
localStorage.removeItem("userCache")
|
||||
context.user = null
|
||||
reject(e)
|
||||
}
|
||||
if (!localStorage.getItem("userCache")) {
|
||||
const theme = {
|
||||
id: 1,
|
||||
name: "Colubrina Classic",
|
||||
|
|
|
@ -1,17 +1,11 @@
|
|||
<template>
|
||||
<div id="communications">
|
||||
<v-container fluid>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<router-view
|
||||
v-if="$route.params.id !== 'home'"
|
||||
:chat="selectedChat"
|
||||
:loading="false"
|
||||
:items="$store.state.chats"
|
||||
></router-view>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
<router-view
|
||||
v-if="$route.params.id !== 'home'"
|
||||
:chat="selectedChat"
|
||||
:loading="false"
|
||||
:items="$store.state.chats"
|
||||
></router-view>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -169,8 +169,8 @@
|
|||
<v-row v-if="!loading" @drop="handleDrag" no-gutters>
|
||||
<v-col class="flex-grow-1 flex-shrink-1 pb-0" id="chat-col">
|
||||
<v-card
|
||||
class="d-flex flex-column fill-height rounded-xl"
|
||||
style="overflow: auto; height: calc(100vh - 24px - 40px - 40px)"
|
||||
class="d-flex flex-column fill-height rounded-xl mb-n3"
|
||||
style="overflow: auto; height: calc(100vh - 24px - 40px)"
|
||||
color="card"
|
||||
elevation="0"
|
||||
>
|
||||
|
@ -202,32 +202,30 @@
|
|||
style="display: block; width: 100px; margin: 0 auto"
|
||||
></v-progress-circular>
|
||||
<template v-for="(message, index) in messages">
|
||||
<div :key="'div-' + message.keyId">
|
||||
<Message
|
||||
:key="message.keyId"
|
||||
:message="message"
|
||||
:jump-to-message="jumpToMessage"
|
||||
:edit="edit"
|
||||
:focus-input="focusInput"
|
||||
:replying="setReply"
|
||||
:get-name="getName"
|
||||
:end-edit="endEdit"
|
||||
:auto-scroll="autoScroll"
|
||||
:chat="chat"
|
||||
:index="index"
|
||||
:show="show"
|
||||
:set-image-preview="setImagePreview"
|
||||
:delete-message="deleteMessage"
|
||||
:last-message="
|
||||
messages[index - 1]?.userId === message?.userId &&
|
||||
$date(message.createdAt).diff(
|
||||
messages[index - 1]?.createdAt,
|
||||
'minute'
|
||||
) < 10 &&
|
||||
!message.replyId
|
||||
"
|
||||
></Message>
|
||||
</div>
|
||||
<Message
|
||||
:key="message.keyId"
|
||||
:message="message"
|
||||
:jump-to-message="jumpToMessage"
|
||||
:edit="edit"
|
||||
:focus-input="focusInput"
|
||||
:replying="setReply"
|
||||
:get-name="getName"
|
||||
:end-edit="endEdit"
|
||||
:auto-scroll="autoScroll"
|
||||
:chat="chat"
|
||||
:index="index"
|
||||
:show="show"
|
||||
:set-image-preview="setImagePreview"
|
||||
:delete-message="deleteMessage"
|
||||
:last-message="
|
||||
messages[index - 1]?.userId === message?.userId &&
|
||||
$date(message.createdAt).diff(
|
||||
messages[index - 1]?.createdAt,
|
||||
'minute'
|
||||
) < 10 &&
|
||||
!message.replyId
|
||||
"
|
||||
></Message>
|
||||
<div
|
||||
:key="'div2-' + message.keyId"
|
||||
v-if="message.readReceipts.length"
|
||||
|
@ -277,31 +275,33 @@
|
|||
</template>
|
||||
<v-tooltip top>
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-btn
|
||||
icon
|
||||
small
|
||||
fab
|
||||
width="20"
|
||||
height="20"
|
||||
class="ml-2 mt-2"
|
||||
style="float: right"
|
||||
@click="openUserPanel($store.state.user)"
|
||||
>
|
||||
<v-avatar size="20" v-on="on" color="primary">
|
||||
<img
|
||||
v-if="$store.state.user.avatar"
|
||||
:src="
|
||||
$store.state.baseURL +
|
||||
'/usercontent/' +
|
||||
$store.state.user.avatar
|
||||
"
|
||||
alt="avatar"
|
||||
/>
|
||||
<span v-else>{{
|
||||
$store.state.user.username[0].toUpperCase()
|
||||
}}</span>
|
||||
</v-avatar>
|
||||
</v-btn>
|
||||
<span>
|
||||
<v-btn
|
||||
icon
|
||||
small
|
||||
fab
|
||||
width="20"
|
||||
height="20"
|
||||
class="ml-2 mt-2"
|
||||
style="float: right"
|
||||
@click="openUserPanel($store.state.user)"
|
||||
>
|
||||
<v-avatar size="20" v-on="on" color="primary">
|
||||
<img
|
||||
v-if="$store.state.user.avatar"
|
||||
:src="
|
||||
$store.state.baseURL +
|
||||
'/usercontent/' +
|
||||
$store.state.user.avatar
|
||||
"
|
||||
alt="avatar"
|
||||
/>
|
||||
<span v-else>{{
|
||||
$store.state.user.username[0].toUpperCase()
|
||||
}}</span>
|
||||
</v-avatar>
|
||||
</v-btn>
|
||||
</span>
|
||||
</template>
|
||||
<span>
|
||||
{{ $store.state.user.username }} has read up to this point.
|
||||
|
@ -368,25 +368,18 @@
|
|||
v-model="usersTyping.length"
|
||||
v-if="$vuetify.breakpoint.mobile"
|
||||
>
|
||||
<v-toolbar
|
||||
height="22"
|
||||
color="toolbar"
|
||||
elevation="0"
|
||||
<div
|
||||
style="
|
||||
border-radius: 20px 20px 0 0;
|
||||
cursor: pointer;
|
||||
border-radius: 0 0 20px 20px;
|
||||
position: relative;
|
||||
top: -30px;
|
||||
margin-bottom: -27px;
|
||||
margin-bottom: -22px;
|
||||
"
|
||||
width="100%"
|
||||
v-if="usersTyping.length"
|
||||
>
|
||||
<div>
|
||||
{{ usersTyping.map((user) => getName(user)).join(", ") }}
|
||||
{{ usersTyping.length > 1 ? " are" : " is" }} typing...
|
||||
</div>
|
||||
</v-toolbar>
|
||||
{{ usersTyping.map((user) => getName(user)).join(", ") }}
|
||||
{{ usersTyping.length > 1 ? " are" : " is" }} typing...
|
||||
</div>
|
||||
</v-fade-transition>
|
||||
<CommsInput
|
||||
:chat="chat"
|
||||
|
@ -402,9 +395,9 @@
|
|||
<div
|
||||
style="
|
||||
border-radius: 0 0 20px 20px;
|
||||
position: relative;
|
||||
margin-top: -22px;
|
||||
bottom: -16px;
|
||||
position: absolute;
|
||||
margin-top: -2px;
|
||||
bottom: 1px;
|
||||
"
|
||||
v-if="usersTyping.length"
|
||||
>
|
||||
|
@ -415,14 +408,6 @@
|
|||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
<v-divider
|
||||
vertical
|
||||
style="z-index: 2; padding-right: 3px; padding-left: 3px"
|
||||
v-if="
|
||||
($store.state.userPanel && !$vuetify.breakpoint.mobile) ||
|
||||
($store.state.searchPanel && !$vuetify.breakpoint.mobile)
|
||||
"
|
||||
></v-divider>
|
||||
<v-col
|
||||
cols="3"
|
||||
class=""
|
||||
|
@ -431,7 +416,7 @@
|
|||
>
|
||||
<v-card
|
||||
class="d-flex flex-column fill-height"
|
||||
style="overflow: scroll; height: calc(100vh - 24px - 40px - 40px)"
|
||||
style="overflow: scroll; height: calc(100vh - 24px - 40px)"
|
||||
color="card"
|
||||
elevation="0"
|
||||
>
|
||||
|
@ -484,7 +469,6 @@
|
|||
</v-col>
|
||||
<v-col
|
||||
:cols="$vuetify.breakpoint.xl ? 2 : 3"
|
||||
class="ml-2"
|
||||
id="user-col"
|
||||
v-if="
|
||||
$store.state.userPanel &&
|
||||
|
@ -493,10 +477,10 @@
|
|||
"
|
||||
>
|
||||
<v-card
|
||||
class="d-flex flex-column fill-height rounded-xl"
|
||||
class="d-flex flex-column fill-height rounded-0"
|
||||
elevation="0"
|
||||
style="overflow: scroll; height: calc(100vh - 24px - 40px - 40px)"
|
||||
color="card"
|
||||
style="overflow: scroll; height: calc(100vh - 24px - 40px)"
|
||||
color="sheet"
|
||||
>
|
||||
<v-menu
|
||||
v-model="context.user.value"
|
||||
|
@ -520,7 +504,7 @@
|
|||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
<v-list two-line color="card">
|
||||
<v-list two-line color="sheet">
|
||||
<v-list-item-group class="rounded-xl">
|
||||
<template v-for="item in associations">
|
||||
<v-list-item
|
||||
|
|
|
@ -373,7 +373,8 @@ export default {
|
|||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
async mounted() {
|
||||
await this.$store.dispatch("doInit")
|
||||
this.getFriends()
|
||||
this.getUsers()
|
||||
this.$socket.on("friendRequest", () => {
|
||||
|
|
|
@ -123,7 +123,8 @@ export default {
|
|||
totp: "",
|
||||
totpDialog: false,
|
||||
loading: false,
|
||||
instance: "https://colubrina.troplo.com",
|
||||
instance:
|
||||
localStorage.getItem("instance") || "https://colubrina.troplo.com",
|
||||
customHeaders: {}
|
||||
}
|
||||
},
|
||||
|
@ -149,14 +150,17 @@ export default {
|
|||
})
|
||||
.then(async (res) => {
|
||||
const session =
|
||||
res.data.session || res.data.bcToken || res.data.cookieToken
|
||||
|
||||
localStorage.setItem("session", session)
|
||||
res.data.session ||
|
||||
res.data.token ||
|
||||
res.data.bcToken ||
|
||||
res.data.cookieToken
|
||||
localStorage.setItem("token", session)
|
||||
Vue.axios.defaults.headers.common["Authorization"] = session
|
||||
this.$store.commit("setToken", session)
|
||||
await this.$store.dispatch("getUserInfo")
|
||||
this.$store.dispatch("getChats")
|
||||
this.loading = false
|
||||
this.$socket.auth.token = session
|
||||
this.$socket.disconnect()
|
||||
this.$socket.connect()
|
||||
if (this.isElectron()) {
|
||||
|
@ -204,9 +208,17 @@ export default {
|
|||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.$store.state.user?.id) {
|
||||
this.$router.push("/")
|
||||
}
|
||||
this.$store
|
||||
.dispatch("getUserInfo")
|
||||
.then(() => {
|
||||
this.$router.push("/")
|
||||
})
|
||||
.catch(() => {
|
||||
this.$store.state.user = {
|
||||
bcUser: null,
|
||||
loggedIn: false
|
||||
}
|
||||
})
|
||||
this.testInstance()
|
||||
},
|
||||
watch: {
|
||||
|
|
|
@ -96,7 +96,8 @@ export default {
|
|||
totp: "",
|
||||
totpDialog: false,
|
||||
loading: false,
|
||||
instance: "https://colubrina.troplo.com",
|
||||
instance:
|
||||
localStorage.getItem("instance") || "https://colubrina.troplo.com",
|
||||
instanceString: ""
|
||||
}
|
||||
},
|
||||
|
@ -131,11 +132,18 @@ export default {
|
|||
totp: this.totp
|
||||
})
|
||||
.then(async (res) => {
|
||||
localStorage.setItem("session", res.data.session)
|
||||
Vue.axios.defaults.headers.common["Authorization"] = res.data.session
|
||||
this.$store.commit("setToken", res.data.session)
|
||||
const session =
|
||||
res.data.session ||
|
||||
res.data.token ||
|
||||
res.data.bcToken ||
|
||||
res.data.cookieToken
|
||||
localStorage.setItem("token", session)
|
||||
Vue.axios.defaults.headers.common["Authorization"] = session
|
||||
this.$store.commit("setToken", session)
|
||||
await this.$store.dispatch("getUserInfo")
|
||||
this.$store.dispatch("getChats")
|
||||
this.loading = false
|
||||
this.$socket.auth.token = session
|
||||
this.$socket.disconnect()
|
||||
this.$socket.connect()
|
||||
if (this.isElectron()) {
|
||||
|
@ -169,9 +177,17 @@ export default {
|
|||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.$store.state.user?.id) {
|
||||
this.$router.push("/")
|
||||
}
|
||||
this.$store
|
||||
.dispatch("getUserInfo")
|
||||
.then(() => {
|
||||
this.$router.push("/")
|
||||
})
|
||||
.catch(() => {
|
||||
this.$store.state.user = {
|
||||
bcUser: null,
|
||||
loggedIn: false
|
||||
}
|
||||
})
|
||||
this.testInstance()
|
||||
},
|
||||
watch: {
|
||||
|
|
|
@ -5311,18 +5311,6 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6
|
|||
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
|
||||
integrity sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==
|
||||
|
||||
graphql-tag@^2.12.6:
|
||||
version "2.12.6"
|
||||
resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1"
|
||||
integrity sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==
|
||||
dependencies:
|
||||
tslib "^2.1.0"
|
||||
|
||||
graphql@^16.3.0:
|
||||
version "16.5.0"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.5.0.tgz#41b5c1182eaac7f3d47164fb247f61e4dfb69c85"
|
||||
integrity sha512-qbHgh8Ix+j/qY+a/ZcJnFQ+j8ezakqPiHwPiZhV/3PgGlgf96QMBB5/f2rkiC9sgLoy/xvT6TSiaf2nTHJh5iA==
|
||||
|
||||
gzip-size@^5.0.0:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274"
|
||||
|
@ -9802,11 +9790,6 @@ thread-loader@^2.1.3:
|
|||
loader-utils "^1.1.0"
|
||||
neo-async "^2.6.0"
|
||||
|
||||
throttle-debounce@^2.1.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.3.0.tgz#fd31865e66502071e411817e241465b3e9c372e2"
|
||||
integrity sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ==
|
||||
|
||||
through2-filter@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254"
|
||||
|
@ -10393,15 +10376,6 @@ vm-browserify@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
|
||||
integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
|
||||
|
||||
vue-apollo@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/vue-apollo/-/vue-apollo-3.1.0.tgz#d0370b64f928f488b7ad98177cca8e1a82fa725e"
|
||||
integrity sha512-TkXMpgypbqM/27vKIpWNhL347QRtcu9kWkEmxplPGGMnZb+hSbbIwU07LjQVzFwrLBer0ha9zJP4hIW/fCQDuw==
|
||||
dependencies:
|
||||
chalk "^2.4.2"
|
||||
serialize-javascript "^4.0.0"
|
||||
throttle-debounce "^2.1.0"
|
||||
|
||||
vue-axios@^3.4.1:
|
||||
version "3.4.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-axios/-/vue-axios-3.4.1.tgz#e092ec4060b42e941ea5059df9b8f09058c3eea9"
|
||||
|
@ -10490,11 +10464,6 @@ vue-loader@^15.9.2:
|
|||
vue-hot-reload-api "^2.3.0"
|
||||
vue-style-loader "^4.1.0"
|
||||
|
||||
vue-matomo@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/vue-matomo/-/vue-matomo-4.1.0.tgz#17b513bc8ac60e168bfa8190ad05b3257a3c441e"
|
||||
integrity sha512-y+tdmhY835Ip3EAGfIAgA33+aBYrvRT7fNnBnA7bSM459XpoWXgqJKdbopVpEUrxCPIq8IkuF7g4KqSLc0Fa3w==
|
||||
|
||||
vue-native-notification@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-native-notification/-/vue-native-notification-1.1.1.tgz#8a57950dded83b05b9e261f45bc2e027107eb9cd"
|
||||
|
@ -10528,11 +10497,6 @@ vue-style-loader@^4.1.0, vue-style-loader@^4.1.2:
|
|||
hash-sum "^1.0.2"
|
||||
loader-utils "^1.0.2"
|
||||
|
||||
vue-swatches@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-swatches/-/vue-swatches-2.1.1.tgz#26c467fb7648ff4ee0887aea36d1e03b15032b83"
|
||||
integrity sha512-YugkNbByxMz1dnx1nZyHSL3VSf/TnBH3/NQD+t8JKxPSqUmX87sVGBxjEaqH5IMraOLfVmU0pHCHl2BfXNypQg==
|
||||
|
||||
vue-template-babel-compiler@^1.1.3:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/vue-template-babel-compiler/-/vue-template-babel-compiler-1.2.0.tgz#f77126886e868f64d2acefe5c0ecfd9c323bf943"
|
||||
|
|
Loading…
Reference in a new issue