This commit is contained in:
Jack Hadrill 2022-03-20 17:41:43 +00:00
parent c6fb1528ea
commit ee532dfd30
8 changed files with 169 additions and 7 deletions

38
.drone.yml Normal file
View File

@ -0,0 +1,38 @@
kind: pipeline
type: docker
name: build
steps:
- name: install
image: node:lts-alpine
commands:
- apk add git
- npm install
- name: build
image: node:lts-alpine
commands:
- npm run build
depends_on:
- install
- name: publish
image: alpine
depends_on:
- build
when:
branch:
- master
environment:
USERNAME:
from_secret: ftp_username
PASSWORD:
from_secret: ftp_password
APIKEY:
from_secret: api_key
commands:
- apk --no-cache add lftp curl
- cd dist
- 'curl -X DELETE -H "AccessKey: $PASSWORD" https://storage.bunnycdn.com/mercuryapp/'
- 'lftp -e "mirror -P 10 -R" -u $USERNAME,$PASSWORD storage.bunnycdn.com'
- 'curl -X POST -H "AccessKey: $APIKEY" https://bunnycdn.com/api/pullzone/733874/purgeCache --data ""'

27
package-lock.json generated
View File

@ -17,6 +17,7 @@
"reconnecting-websocket": "^4.4.0", "reconnecting-websocket": "^4.4.0",
"romulus-js": "git+https://git.jacknet.io/TerribleCodeClub/romulus-js.git", "romulus-js": "git+https://git.jacknet.io/TerribleCodeClub/romulus-js.git",
"uuid": "^8.3.2", "uuid": "^8.3.2",
"vanilla-picker": "^2.12.1",
"vue": "^3.2.25", "vue": "^3.2.25",
"vue-router": "^4.0.14" "vue-router": "^4.0.14"
}, },
@ -46,6 +47,11 @@
"url": "https://opencollective.com/popperjs" "url": "https://opencollective.com/popperjs"
} }
}, },
"node_modules/@sphinxxxx/color-conversion": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@sphinxxxx/color-conversion/-/color-conversion-2.2.2.tgz",
"integrity": "sha512-XExJS3cLqgrmNBIP3bBw6+1oQ1ksGjFh0+oClDKFYpCCqx/hlqwWO5KO/S63fzUo67SxI9dMrF0y5T/Ey7h8Zw=="
},
"node_modules/@types/color": { "node_modules/@types/color": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.3.tgz", "resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.3.tgz",
@ -878,6 +884,14 @@
"uuid": "dist/bin/uuid" "uuid": "dist/bin/uuid"
} }
}, },
"node_modules/vanilla-picker": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/vanilla-picker/-/vanilla-picker-2.12.1.tgz",
"integrity": "sha512-2qrEP9VYylKXbyzXKsbu2dferBTvqnlsr29XjHwFE+/MEp0VNj6oEUESLDtKZ7DWzGdSv1x/+ujqFZF+KsO3cg==",
"dependencies": {
"@sphinxxxx/color-conversion": "^2.2.2"
}
},
"node_modules/vite": { "node_modules/vite": {
"version": "2.8.6", "version": "2.8.6",
"resolved": "https://registry.npmjs.org/vite/-/vite-2.8.6.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-2.8.6.tgz",
@ -954,6 +968,11 @@
"integrity": "sha512-q/ytXxO5NKvyT37pmisQAItCFqA7FD/vNb8dgaJy3/630Fsc+Mz9/9f2SziBoIZ30TJooXyTwZmhi1zjXmObYg==", "integrity": "sha512-q/ytXxO5NKvyT37pmisQAItCFqA7FD/vNb8dgaJy3/630Fsc+Mz9/9f2SziBoIZ30TJooXyTwZmhi1zjXmObYg==",
"peer": true "peer": true
}, },
"@sphinxxxx/color-conversion": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@sphinxxxx/color-conversion/-/color-conversion-2.2.2.tgz",
"integrity": "sha512-XExJS3cLqgrmNBIP3bBw6+1oQ1ksGjFh0+oClDKFYpCCqx/hlqwWO5KO/S63fzUo67SxI9dMrF0y5T/Ey7h8Zw=="
},
"@types/color": { "@types/color": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.3.tgz", "resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.3.tgz",
@ -1479,6 +1498,14 @@
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
}, },
"vanilla-picker": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/vanilla-picker/-/vanilla-picker-2.12.1.tgz",
"integrity": "sha512-2qrEP9VYylKXbyzXKsbu2dferBTvqnlsr29XjHwFE+/MEp0VNj6oEUESLDtKZ7DWzGdSv1x/+ujqFZF+KsO3cg==",
"requires": {
"@sphinxxxx/color-conversion": "^2.2.2"
}
},
"vite": { "vite": {
"version": "2.8.6", "version": "2.8.6",
"resolved": "https://registry.npmjs.org/vite/-/vite-2.8.6.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-2.8.6.tgz",

View File

@ -17,6 +17,7 @@
"reconnecting-websocket": "^4.4.0", "reconnecting-websocket": "^4.4.0",
"romulus-js": "git+https://git.jacknet.io/TerribleCodeClub/romulus-js.git", "romulus-js": "git+https://git.jacknet.io/TerribleCodeClub/romulus-js.git",
"uuid": "^8.3.2", "uuid": "^8.3.2",
"vanilla-picker": "^2.12.1",
"vue": "^3.2.25", "vue": "^3.2.25",
"vue-router": "^4.0.14" "vue-router": "^4.0.14"
}, },

View File

@ -0,0 +1,62 @@
<template>
<div ref="picker" id="picker" class="btn"><div class="label">Set username color</div></div>
</template>
<script setup>
import Color from 'color';
import Picker from 'vanilla-picker'
import { inject, onMounted, ref } from 'vue';
import { useUserStore } from '../../stores/userStore';
const requestUserData = inject('requestUserData')
const userStore = useUserStore()
const self = userStore.getSelf()
const picker = ref(null)
const usernameColor = ref(Color())
const bootstrapPrimaryColor = getComputedStyle(document.documentElement).getPropertyValue('--bs-primary')
onMounted(() => {
const p = new Picker(picker.value)
p.setOptions({
alpha: false,
color: self.color.hex() ?? bootstrapPrimaryColor
})
picker.value.style.backgroundColor = self.color.hex() ?? bootstrapPrimaryColor
p.onChange = function(color) {
picker.value.style.backgroundColor = color.rgbaString
}
p.onOpen = function(color) {
usernameColor.value = Color(color.hex)
}
p.onDone = function(color) {
usernameColor.value = Color(color.hex)
picker.value.style.backgroundColor = color.rgbaString
userStore.setColor(-1, Color(color.hex))
requestUserData()
}
p.onClose = function(color) {
picker.value.style.backgroundColor = usernameColor.value.hex()
}
})
</script>
<style>
#picker .label {
background: inherit;
background-clip: text;
color: transparent;
filter: invert(1) grayscale(1) contrast(9);
}
</style>

View File

@ -8,5 +8,13 @@ import { computed } from 'vue'
const props = defineProps(['user']) const props = defineProps(['user'])
const user = props.user const user = props.user
const color = computed(() => { return user.color?.hex() ?? '#6c757d' }) const bootstrapSecondaryColor = getComputedStyle(document.documentElement).getPropertyValue('--bs-secondary')
const color = computed(() => { return user.color?.hex() ?? bootstrapSecondaryColor })
</script> </script>
<style scoped>
span:hover {
color: white !important;
}
</style>

View File

@ -5,6 +5,7 @@ import { useUserStore } from '../stores/userStore'
import { useMessageStore } from '../stores/messageStore' import { useMessageStore } from '../stores/messageStore'
import { useChannelStore } from '../stores/channelStore' import { useChannelStore } from '../stores/channelStore'
import { decrypt } from 'romulus-js' import { decrypt } from 'romulus-js'
import { provide } from 'vue'
const CLIENT_ID = 'Mercury' const CLIENT_ID = 'Mercury'
const SUBSCRIBED_MESSAGE_TYPES = [MessageTypes.Basic, MessageTypes.UserDataRequest, MessageTypes.UserDataResponse] const SUBSCRIBED_MESSAGE_TYPES = [MessageTypes.Basic, MessageTypes.UserDataRequest, MessageTypes.UserDataResponse]
@ -105,6 +106,8 @@ export default {
}) })
} }
app.provide('requestUserData', requestUserData)
// Keepalive timeout. // Keepalive timeout.
var timeout = setInterval(() => { var timeout = setInterval(() => {
ws.send(packers[MessageTypes.Keepalive]()) ws.send(packers[MessageTypes.Keepalive]())

View File

@ -5,11 +5,11 @@
<template v-slot:title>Welcome to Mercury!</template> <template v-slot:title>Welcome to Mercury!</template>
<template v-slot:content> <template v-slot:content>
<div class="d-flex flex-column text-center align-items-center px-5 overflow-hidden"> <div class="d-flex flex-column text-center align-items-center px-5 overflow-hidden">
<img class="animate__animated animate__rotateIn py-5 w-25" id="logo" src="../assets/logo-light.png" /> <img class="animate__animated animate__rollIn py-5 w-25" id="logo" src="../assets/logo-light.png" />
<h1 class="animate__animated animate__fadeInDown animate__delay-1s"> <h1 class="animate__animated animate__zoomIn">
Mercury is a web-based BENNC client. Mercury is a web-based BENNC client.
</h1> </h1>
<h2 class="animate__animated animate__fadeInDown animate__delay-2s"> <h2 class="animate__animated animate__zoomIn">
Go to <router-link :to="{ name: 'Settings' }" class="text-muted"><i class="bi bi-gear-fill"></i> Settings</router-link> to configure your client. Go to <router-link :to="{ name: 'Settings' }" class="text-muted"><i class="bi bi-gear-fill"></i> Settings</router-link> to configure your client.
</h2> </h2>
</div> </div>
@ -26,10 +26,10 @@ import Content from '../components/Content.vue'
#logo { #logo {
filter: invert(80%); filter: invert(80%);
} }
h1 { /* h1 {
--animate-delay: 0.5s; --animate-delay: 0.5s;
} }
h2 { h2 {
--animate-delay: 0.5s; --animate-delay: 0.5s;
} } */
</style> </style>

View File

@ -3,8 +3,16 @@
<Content> <Content>
<template v-slot:title>Settings</template> <template v-slot:title>Settings</template>
<template v-slot:content> <template v-slot:content>
<h3>User</h3>
<div class="mb-5">
<div class="input-group mb-3">
<input @keyup.enter="saveUsername" v-model="username" type="text" class="form-control" placeholder="Username" aria-label="Username">
<button @click="saveUsername" class="btn btn-primary" type="button">Save</button>
</div>
<ColorPicker></ColorPicker>
</div>
<h3>Channels</h3> <h3>Channels</h3>
<table class="table"> <table class="table mb-5">
<thead> <thead>
<th scope="col">Name</th> <th scope="col">Name</th>
<th scope="col">Key</th> <th scope="col">Key</th>
@ -38,8 +46,23 @@ import { useChannelStore } from '../stores/channelStore'
import Key from '../components/common/Key.vue' import Key from '../components/common/Key.vue'
import Sidebar from '../components/Sidebar.vue' import Sidebar from '../components/Sidebar.vue'
import Content from '../components/Content.vue' import Content from '../components/Content.vue'
import ColorPicker from '../components/settings/ColorPicker.vue';
import { inject, ref } from 'vue';
import { useUserStore } from '../stores/userStore';
const channelStore = useChannelStore() const channelStore = useChannelStore()
const userStore = useUserStore()
const requestUserData = inject('requestUserData')
const self = userStore.getSelf()
const username = ref('')
username.value = self.name
function saveUsername() {
userStore.setName(-1, username.value)
requestUserData()
}
</script> </script>
<style scope> <style scope>