Add dark mode

This commit is contained in:
Sergey 2023-05-01 21:21:47 +00:00
parent 2a60cd29cc
commit 0b406890f9
9 changed files with 3609 additions and 291 deletions

3701
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,7 @@
"dependencies": { "dependencies": {
"axios": "^1.4.0", "axios": "^1.4.0",
"bootstrap": "^4.6.2", "bootstrap": "^4.6.2",
"bootstrap-darkmode": "^0.9.1",
"bootstrap-vue": "^2.23.1", "bootstrap-vue": "^2.23.1",
"core-js": "^3.26.1", "core-js": "^3.26.1",
"idb": "^5.0.8", "idb": "^5.0.8",
@ -30,6 +31,8 @@
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
"eslint": "^6.8.0", "eslint": "^6.8.0",
"eslint-plugin-vue": "^6.2.2", "eslint-plugin-vue": "^6.2.2",
"node-sass": "^8.0.0",
"sass-loader": "^10.4.1",
"vue-template-compiler": "^2.7.14" "vue-template-compiler": "^2.7.14"
}, },
"eslintConfig": { "eslintConfig": {

View File

@ -307,3 +307,7 @@
padding-top: 55px; /* Space for fixed navbar */ padding-top: 55px; /* Space for fixed navbar */
} }
</style> </style>
<style lang="scss">
@import "~bootstrap-darkmode/scss/darktheme";
</style>

View File

@ -1,20 +1,20 @@
<template> <template>
<div class="packet" :class="{'packet-incoming': packet.incoming}"> <div :class="{'packet-incoming': packet.incoming, 'packet-outgoing': !packet.incoming}">
<div>#{{ packet.id }} at {{ dateToText(packet.timestamp) }}, {{ printPacketFlags(packet) }} <div>#{{ packet.id }} at {{ dateToText(packet.timestamp) }}, {{ printPacketFlags(packet) }}
<button @click.prevent="copyRaw" class="btn btn-link">Copy HEX</button> <button @click.prevent="copyRaw" class="btn btn-link">Copy HEX</button>
<button @click.prevent="copyText" class="btn btn-link">Copy text</button> <button @click.prevent="copyText" class="btn btn-link">Copy text</button>
<button @click.prevent="copyPythonBytes" class="btn btn-link">Copy as Python bytes</button> <button @click.prevent="copyPythonBytes" class="btn btn-link">Copy as Python bytes</button>
</div> </div>
<p v-if="!this.$store.state.hexdumpMode" <p v-if="!this.$store.state.hexdumpMode"
class="pt-2 pb-2 mb-3 border-bottom" class="pt-2 pb-2 mb-3"
v-html="stringdata"/> v-html="stringdata"/>
<p v-else <p v-else
class="pt-2 pb-2 mb-3 border-bottom" class="pt-2 pb-2 mb-3"
v-html="hexdata"/> v-html="hexdata"/>
</div> </div>
</template> </template>
<!--suppress JSUnresolvedVariable --> <!--suppress JSUnresolvedVariable, JSDeprecatedSymbols -->
<script> <script>
export default { export default {
name: 'Packet', name: 'Packet',
@ -176,21 +176,19 @@
</script> </script>
<style scoped> <style scoped>
.packet { .packet-outgoing {
background: rgba(224, 246, 255, 0.4); background: var(--response-packet-color);
box-shadow: 0 0 5px 5px rgba(224, 246, 255, 0.4); box-shadow: 0 0 5px 5px var(--response-packet-color);
} }
/*noinspection CssUnusedSymbol*/
.packet-incoming { .packet-incoming {
background: rgba(251, 233, 231, 0.4); background: var(--request-packet-color);
box-shadow: 0 0 5px 5px rgba(251, 233, 231, 0.4); box-shadow: 0 0 5px 5px var(--request-packet-color);
} }
p { p {
font-family: "Ubuntu Mono", "Lucida Console", monospace; font-family: "Ubuntu Mono", "Lucida Console", monospace;
font-size: 100%; font-size: 100%;
color: black;
margin-bottom: 10px; margin-bottom: 10px;
padding-bottom: 5px; padding-bottom: 5px;
word-break: break-word; word-break: break-word;

View File

@ -1,5 +1,6 @@
<template> <template>
<nav class="col-sm-3 d-none d-sm-block bg-light sidebar"> <nav class="col-sm-3 d-none d-sm-block sidebar"
:class="this.$store.state.theme === 'light' ? 'bg-light' : 'bg-dark'">
<div class="m-2"> <div class="m-2">
<button type="button" class="btn btn-sm" <button type="button" class="btn btn-sm"
:title="this.$store.state.pause ? 'Continue' : 'Pause new streams'" :title="this.$store.state.pause ? 'Continue' : 'Pause new streams'"

View File

@ -127,12 +127,15 @@
color: #333; color: #333;
} }
[data-theme=dark] .nav-link {
color: #f8f9fa;
}
/*noinspection CssUnusedSymbol*/ /*noinspection CssUnusedSymbol*/
.nav-link.active { .nav-link.active {
color: #007BFF; color: #007BFF;
} }
/*noinspection CssUnusedSymbol*/
.highlight { .highlight {
background: rgba(220, 53, 69, 0.3); background: rgba(220, 53, 69, 0.3);
box-shadow: 0 0 1px 1px rgba(255, 119, 182, 0.3); box-shadow: 0 0 1px 1px rgba(255, 119, 182, 0.3);
@ -140,7 +143,10 @@
.stream-item { .stream-item {
transition: all .5s; transition: all .5s;
border: 0; box-shadow: 0 24px 3px -25px #4b4e51;
border-bottom: 1px solid rgba(0, 0, 0, 0.1); }
[data-theme=dark] .stream-item {
box-shadow: 0 24px 3px -25px #84898E;
} }
</style> </style>

View File

@ -0,0 +1,127 @@
<template>
<div>
<input
@change="toggleTheme"
id="checkbox"
type="checkbox"
class="switch-checkbox"
/>
<label for="checkbox" class="switch-label">
<span class="checkbox-emoji">🌙</span>
<span class="checkbox-emoji">☀️</span>
<div
class="switch-toggle"
:class="{ 'switch-toggle-checked': chosenTheme === 'dark' }"
></div>
</label>
</div>
</template>
<script>
export default {
mounted() {
this.initTheme();
},
computed: {
chosenTheme: {
get() {
return this.$store.state.theme || this.detectTheme();
},
set(theme) {
this.$store.commit('setTheme', theme);
this.displayTheme(theme);
},
},
},
methods: {
toggleTheme() {
const activeTheme = this.chosenTheme;
if (activeTheme === "light") {
this.chosenTheme = 'dark';
} else {
this.chosenTheme = 'light';
}
console.debug('Toggling theme from ', activeTheme, ' to ', this.chosenTheme);
},
initTheme() {
this.displayTheme(this.chosenTheme);
},
detectTheme() {
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
},
displayTheme(theme) {
document.body.setAttribute('data-theme', theme);
},
},
};
</script>
<style scoped>
.switch-checkbox {
display: none;
}
.switch-label {
align-items: center;
background: var(--button-text-primary-color);
border: calc(var(--button-element-size) * 0.025) solid var(--button-accent-color);
border-radius: var(--button-element-size);
cursor: pointer;
display: flex;
font-size: calc(var(--button-element-size) * 0.3);
height: calc(var(--button-element-size) * 0.35);
position: relative;
padding: calc(var(--button-element-size) * 0.1);
transition: background 0.5s ease;
justify-content: space-between;
width: var(--button-element-size);
z-index: 1;
box-sizing: content-box;
}
.switch-toggle {
position: absolute;
background-color: var(--button-background-color-primary);
border-radius: 50%;
top: calc(var(--button-element-size) * 0.07);
left: calc(var(--button-element-size) * 0.07);
height: calc(var(--button-element-size) * 0.4);
width: calc(var(--button-element-size) * 0.4);
transform: translateX(0);
transition: transform 0.3s ease, background-color 0.5s ease;
}
.switch-toggle-checked {
transform: translateX(calc(var(--button-element-size) * 0.6)) !important;
}
.checkbox-emoji {
color: transparent;
text-shadow: 0 0 0 var(--button-background-color-primary);
}
>>> {
--button-element-size: 3rem;
--button-background-color-primary: #ebebeb;
--button-background-color-secondary: #fafafa;
--button-accent-color: #cacaca;
--button-text-primary-color: #222;
}
[data-theme=dark] * {
--button-background-color-primary: #1e1e1e;
--button-background-color-secondary: #2d2d30;
--button-accent-color: #3f3f3f;
--button-text-primary-color: #ddd;
}
</style>

View File

@ -8,6 +8,8 @@ Vue.use(Vuex);
// noinspection JSUnusedLocalSymbols,JSUnusedGlobalSymbols // noinspection JSUnusedLocalSymbols,JSUnusedGlobalSymbols
export default new Vuex.Store({ export default new Vuex.Store({
state: { state: {
theme: null,
hexdumpBlockSize: 16, hexdumpBlockSize: 16,
hexdumpLineNumberBase: 10, hexdumpLineNumberBase: 10,
pageSize: 25, pageSize: 25,
@ -29,6 +31,7 @@ export default new Vuex.Store({
currentServicesStreamsCount: {}, currentServicesStreamsCount: {},
}, },
mutations: { mutations: {
setTheme: (s, p) => s.theme = p,
setHexdumpBlockSize: (s, p) => s.hexdumpBlockSize = p, setHexdumpBlockSize: (s, p) => s.hexdumpBlockSize = p,
setHexdumpLineNumberBase: (s, p) => s.hexdumpLineNumberBase = p, setHexdumpLineNumberBase: (s, p) => s.hexdumpLineNumberBase = p,
setPageSize: (s, p) => s.pageSize = p, setPageSize: (s, p) => s.pageSize = p,
@ -64,6 +67,7 @@ export default new Vuex.Store({
console.debug('Got mutation:', mutation); console.debug('Got mutation:', mutation);
const mName = mutation?.type; const mName = mutation?.type;
const process = mName !== 'toggleDisplayFavoritesOnly' const process = mName !== 'toggleDisplayFavoritesOnly'
&& mName !== 'setTheme'
&& mName !== 'setServiceModalName' && mName !== 'setServiceModalName'
&& mName !== 'setServiceModalId' && mName !== 'setServiceModalId'
&& mName !== 'togglePause' && mName !== 'togglePause'

View File

@ -1,18 +1,22 @@
<template> <template>
<div> <div>
<p> <p>
<span style="background: rgba(224, 246, 255, 0.4); box-shadow: 0 0 5px 5px rgba(224, 246, 255, 0.4);">Response</span>, <span style="background: var(--request-packet-color); box-shadow: 0 0 3px 3px var(--request-packet-color);">Request</span>,
<span style="background: rgba(251, 233, 231, 0.4); box-shadow: 0 0 5px 5px rgba(251, 233, 231, 0.4);">request</span>. <span style="background: var(--response-packet-color); box-shadow: 0 0 3px 3px var(--response-packet-color);">response</span>.
<ThemeButton class="d-inline float-right" style="margin-top: -0.25rem" />
</p> </p>
<Packet v-for="packet in packets" <Packet v-for="packet in packets"
:key="packet.id" :key="packet.id"
:packet="packet"/> :packet="packet"/>
<infinite-loading @infinite="infiniteLoadingHandler" ref="infiniteLoader"/> <infinite-loading @infinite="infiniteLoadingHandler" ref="infiniteLoader">
<span slot="no-results"></span>
</infinite-loading>
</div> </div>
</template> </template>
<script> <script>
import Packet from '../components/Packet'; import Packet from '../components/Packet';
import ThemeButton from '@/components/ThemeButton.vue';
export default { export default {
name: 'ContentStream', name: 'ContentStream',
@ -77,7 +81,21 @@
}, },
}, },
components: { components: {
ThemeButton,
Packet, Packet,
}, },
}; };
</script> </script>
<style>
:root {
--response-packet-color: rgb(231, 248, 253);
--request-packet-color: rgb(254, 234, 231);
}
:root [data-theme=dark] {
color-scheme: dark;
--response-packet-color: rgb(43, 83, 120);
--request-packet-color: rgb(52, 58, 64);
}
</style>