perf(vite): chunk webcams, locales and large libraries (#1578)
This commit is contained in:
parent
817efba0d8
commit
32122348b3
1284
package-lock.json
generated
1284
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
18
package.json
18
package.json
@ -34,8 +34,6 @@
|
|||||||
"@jaames/iro": "^5.5.2",
|
"@jaames/iro": "^5.5.2",
|
||||||
"@lezer/highlight": "^1.0.0",
|
"@lezer/highlight": "^1.0.0",
|
||||||
"@sindarius/gcodeviewer": "^3.2.2",
|
"@sindarius/gcodeviewer": "^3.2.2",
|
||||||
"@types/node": "^18.0.0",
|
|
||||||
"@types/overlayscrollbars": "^1.12.1",
|
|
||||||
"@uiw/codemirror-theme-vscode": "^4.19.11",
|
"@uiw/codemirror-theme-vscode": "^4.19.11",
|
||||||
"axios": "^0.27.0",
|
"axios": "^0.27.0",
|
||||||
"codemirror": "^6.0.1",
|
"codemirror": "^6.0.1",
|
||||||
@ -45,12 +43,12 @@
|
|||||||
"echarts-gl": "^2.0.8",
|
"echarts-gl": "^2.0.8",
|
||||||
"hls.js": "^1.3.3",
|
"hls.js": "^1.3.3",
|
||||||
"jmuxer": "^2.0.5",
|
"jmuxer": "^2.0.5",
|
||||||
"js-sha256": "^0.9.0",
|
"js-sha256": "^0.10.0",
|
||||||
"lodash.kebabcase": "^4.1.1",
|
"lodash.kebabcase": "^4.1.1",
|
||||||
"lodash.throttle": "^4.1.1",
|
"lodash.throttle": "^4.1.1",
|
||||||
"overlayscrollbars": "^1.13.1",
|
"overlayscrollbars": "^1.13.1",
|
||||||
"overlayscrollbars-vue": "^0.2.2",
|
"overlayscrollbars-vue": "^0.2.2",
|
||||||
"regenerator-runtime": "^0.13.9",
|
"regenerator-runtime": "^0.14.0",
|
||||||
"resize-observer-polyfill": "^1.5.1",
|
"resize-observer-polyfill": "^1.5.1",
|
||||||
"semver": "^7.5.2",
|
"semver": "^7.5.2",
|
||||||
"typed_janus_js": "^1.0.14",
|
"typed_janus_js": "^1.0.14",
|
||||||
@ -76,8 +74,10 @@
|
|||||||
"@types/jmuxer": "^2.0.3",
|
"@types/jmuxer": "^2.0.3",
|
||||||
"@types/lodash.kebabcase": "^4.1.6",
|
"@types/lodash.kebabcase": "^4.1.6",
|
||||||
"@types/lodash.throttle": "^4.1.6",
|
"@types/lodash.throttle": "^4.1.6",
|
||||||
|
"@types/node": "^20.0.0",
|
||||||
|
"@types/overlayscrollbars": "^1.12.1",
|
||||||
"@types/semver": "^7.3.8",
|
"@types/semver": "^7.3.8",
|
||||||
"@types/uuid": "^8.3.1",
|
"@types/uuid": "^9.0.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||||
"@typescript-eslint/parser": "^6.0.0",
|
"@typescript-eslint/parser": "^6.0.0",
|
||||||
"@vue/eslint-config-typescript": "^12.0.0",
|
"@vue/eslint-config-typescript": "^12.0.0",
|
||||||
@ -87,13 +87,15 @@
|
|||||||
"eslint-config-prettier": "^9.0.0",
|
"eslint-config-prettier": "^9.0.0",
|
||||||
"eslint-plugin-jsonc": "^2.2.1",
|
"eslint-plugin-jsonc": "^2.2.1",
|
||||||
"eslint-plugin-vue": "^9.0.0",
|
"eslint-plugin-vue": "^9.0.0",
|
||||||
|
"postcss": "^8.4.31",
|
||||||
|
"postcss-nesting": "^12.0.1",
|
||||||
"prettier": "^3.0.0",
|
"prettier": "^3.0.0",
|
||||||
"sass": "~1.32",
|
"sass": "~1.32",
|
||||||
"start-server-and-test": "^1.14.0",
|
"start-server-and-test": "^2.0.0",
|
||||||
"typescript": "^4.5.5",
|
"typescript": "^4.5.5",
|
||||||
"unplugin-vue-components": "^0.22.12",
|
"unplugin-vue-components": "^0.22.12",
|
||||||
"vite": "^3.2.7",
|
"vite": "^4.4.9",
|
||||||
"vite-plugin-checker": "^0.5.0",
|
"vite-plugin-checker": "^0.6.0",
|
||||||
"vite-plugin-package-version": "^1.0.2",
|
"vite-plugin-package-version": "^1.0.2",
|
||||||
"vite-plugin-pwa": "^0.16.4",
|
"vite-plugin-pwa": "^0.16.4",
|
||||||
"vite-plugin-vue2": "^2.0.1",
|
"vite-plugin-vue2": "^2.0.1",
|
||||||
|
13
src/App.vue
13
src/App.vue
@ -40,6 +40,7 @@ import TheUploadSnackbar from '@/components/TheUploadSnackbar.vue'
|
|||||||
import TheManualProbeDialog from '@/components/dialogs/TheManualProbeDialog.vue'
|
import TheManualProbeDialog from '@/components/dialogs/TheManualProbeDialog.vue'
|
||||||
import TheBedScrewsDialog from '@/components/dialogs/TheBedScrewsDialog.vue'
|
import TheBedScrewsDialog from '@/components/dialogs/TheBedScrewsDialog.vue'
|
||||||
import TheScrewsTiltAdjustDialog from '@/components/dialogs/TheScrewsTiltAdjustDialog.vue'
|
import TheScrewsTiltAdjustDialog from '@/components/dialogs/TheScrewsTiltAdjustDialog.vue'
|
||||||
|
import { setAndLoadLocale } from './plugins/i18n'
|
||||||
|
|
||||||
Component.registerHooks(['metaInfo'])
|
Component.registerHooks(['metaInfo'])
|
||||||
|
|
||||||
@ -162,8 +163,8 @@ export default class App extends Mixins(BaseMixin) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Watch('language')
|
@Watch('language')
|
||||||
languageChanged(newVal: string): void {
|
async languageChanged(newVal: string): Promise<void> {
|
||||||
this.$i18n.locale = newVal
|
await setAndLoadLocale(newVal)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Watch('customStylesheet')
|
@Watch('customStylesheet')
|
||||||
@ -310,10 +311,10 @@ export default class App extends Mixins(BaseMixin) {
|
|||||||
<style>
|
<style>
|
||||||
@import './assets/styles/fonts.css';
|
@import './assets/styles/fonts.css';
|
||||||
@import './assets/styles/toastr.css';
|
@import './assets/styles/toastr.css';
|
||||||
@import './assets/styles/page.scss';
|
@import './assets/styles/page.css';
|
||||||
@import './assets/styles/sidebar.scss';
|
@import './assets/styles/sidebar.css';
|
||||||
@import './assets/styles/utils.scss';
|
@import './assets/styles/utils.css';
|
||||||
@import './assets/styles/updateManager.scss';
|
@import './assets/styles/updateManager.css';
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--app-height: 100%;
|
--app-height: 100%;
|
||||||
|
@ -1,12 +1,3 @@
|
|||||||
@mixin no-select {
|
|
||||||
-webkit-touch-callout: none;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-khtml-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-select-none {
|
.user-select-none {
|
||||||
-webkit-touch-callout: none;
|
-webkit-touch-callout: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
@ -124,7 +124,7 @@ export default class CommandHelpModal extends Mixins(BaseMixin) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
.command-help-content {
|
.command-help-content {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
|
||||||
|
@ -341,7 +341,7 @@ export default class TheEditor extends Mixins(BaseMixin) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
::v-deep .ͼ1 .cm-panel.cm-search *:focus:not(.focus-visible) {
|
::v-deep .ͼ1 .cm-panel.cm-search *:focus:not(.focus-visible) {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<style scoped lang="scss"></style>
|
<style scoped></style>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :class="'consoleTable ' + (isMini ? 'mini' : '')">
|
<div :class="'consoleTable ' + (isMini ? 'mini' : '')">
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<style scoped lang="scss">
|
<style scoped>
|
||||||
.consoleTableRow {
|
.consoleTableRow {
|
||||||
font-family: 'Roboto Mono', monospace;
|
font-family: 'Roboto Mono', monospace;
|
||||||
font-size: 0.95em;
|
font-size: 0.95em;
|
||||||
|
@ -173,4 +173,4 @@ export default class TheBedScrewsDialog extends Mixins(BaseMixin, ControlMixin)
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style scoped></style>
|
||||||
|
@ -181,7 +181,7 @@ export default class TheManualProbeDialog extends Mixins(BaseMixin) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
.v-btn-toggle {
|
.v-btn-toggle {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
@ -274,7 +274,7 @@ export default class ExtruderControlPanel extends Mixins(BaseMixin, ExtruderMixi
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
._btn-group {
|
._btn-group {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
@ -49,14 +49,13 @@ export default class ExtruderControlPanel extends Mixins(BaseMixin, ControlMixin
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
._btn-group {
|
._btn-group {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.v-btn {
|
.v-btn {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
@ -116,7 +116,7 @@ export default class GitCommitsList extends Mixins(BaseMixin) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
.groupedCommits {
|
.groupedCommits {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ export default class GitCommitsListDayCommit extends Mixins(BaseMixin) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
li.commit {
|
li.commit {
|
||||||
border-color: rgb(48, 54, 61);
|
border-color: rgb(48, 54, 61);
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<style lang="scss" scoped></style>
|
<style scoped></style>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<panel
|
<panel
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<style lang="scss" scoped></style>
|
<style scoped></style>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="['printing', 'paused'].includes(printer_state) && printing_objects.length">
|
<div v-if="['printing', 'paused'].includes(printer_state) && printing_objects.length">
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<style lang="scss" scoped></style>
|
<style scoped></style>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<style lang="scss" scoped></style>
|
<style scoped></style>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
svg {
|
svg {
|
||||||
//background: rgba(200, 200, 200);
|
|
||||||
border: 2px solid #888;
|
border: 2px solid #888;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ export default class StatusPanelJobqueue extends Mixins(BaseMixin) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
.filesJobqueue {
|
.filesJobqueue {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
@ -275,7 +275,7 @@ export default class StatusPanelJobqueueEntry extends Mixins(BaseMixin) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
.filesJobqueue {
|
.filesJobqueue {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<style lang="scss" scoped></style>
|
<style scoped></style>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<style lang="scss" scoped></style>
|
<style scoped></style>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<style lang="scss" scoped></style>
|
<style scoped></style>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-card-text class="pa-0">
|
<v-card-text class="pa-0">
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<style lang="scss" scoped></style>
|
<style scoped></style>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-card-text class="pa-0">
|
<v-card-text class="pa-0">
|
||||||
|
@ -223,7 +223,7 @@ export default class StatusPanelPrintstatusThumbnail extends Mixins(BaseMixin) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
.statusPanel-big-thumbnail {
|
.statusPanel-big-thumbnail {
|
||||||
transition: height 0.25s ease-out;
|
transition: height 0.25s ease-out;
|
||||||
}
|
}
|
||||||
|
@ -397,7 +397,7 @@ export default class StatusPanel extends Mixins(BaseMixin) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
._border-radius {
|
._border-radius {
|
||||||
border-bottom-left-radius: inherit;
|
border-bottom-left-radius: inherit;
|
||||||
border-bottom-right-radius: inherit;
|
border-bottom-right-radius: inherit;
|
||||||
|
@ -155,7 +155,7 @@ export default class TemperaturePanelList extends Mixins(BaseMixin) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
.temperature-panel-table th,
|
.temperature-panel-table th,
|
||||||
.temperature-panel-table ::v-deep td {
|
.temperature-panel-table ::v-deep td {
|
||||||
padding-top: 5px !important;
|
padding-top: 5px !important;
|
||||||
|
@ -273,7 +273,7 @@ export default class TemperaturePanelListItem extends Mixins(BaseMixin) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
::v-deep .v-icon._no-focus-style:focus::after {
|
::v-deep .v-icon._no-focus-style:focus::after {
|
||||||
opacity: 0 !important;
|
opacity: 0 !important;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ export default class TemperaturePanelListItemNevermore extends Mixins(BaseMixin)
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
::v-deep .v-icon._no-focus-style:focus::after {
|
::v-deep .v-icon._no-focus-style:focus::after {
|
||||||
opacity: 0 !important;
|
opacity: 0 !important;
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ export default class TemperaturePanelPresets extends Mixins(BaseMixin) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
._preset-title {
|
._preset-title {
|
||||||
font-size: 0.8125rem;
|
font-size: 0.8125rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
.btnHomeAxis {
|
.btnHomeAxis {
|
||||||
width: 36px;
|
width: 36px;
|
||||||
min-width: 36px !important;
|
min-width: 36px !important;
|
||||||
|
@ -706,7 +706,7 @@ export default class CircleControl extends Mixins(BaseMixin, ControlMixin) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
svg {
|
svg {
|
||||||
max-height: 350px;
|
max-height: 350px;
|
||||||
min-height: 275px;
|
min-height: 275px;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
.btnMinWidthAuto {
|
.btnMinWidthAuto {
|
||||||
min-width: auto !important;
|
min-width: auto !important;
|
||||||
}
|
}
|
||||||
|
@ -267,7 +267,7 @@ export default class ZoffsetControl extends Mixins(BaseMixin) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
.v-btn-toggle {
|
.v-btn-toggle {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,25 @@ export default class SettingsGeneralTab extends Mixins(BaseMixin, SettingsGenera
|
|||||||
mdiHelpCircle = mdiHelpCircle
|
mdiHelpCircle = mdiHelpCircle
|
||||||
mdiCloseThick = mdiCloseThick
|
mdiCloseThick = mdiCloseThick
|
||||||
|
|
||||||
|
availableLanguages: { text: string; value: string }[] = []
|
||||||
|
|
||||||
|
async created() {
|
||||||
|
const locales = import.meta.glob<string>('../../locales/*.json', { import: 'title' })
|
||||||
|
const languages: { text: string; value: string }[] = []
|
||||||
|
|
||||||
|
for (const file in locales) {
|
||||||
|
const langKey = file.slice(file.lastIndexOf('.') - 2, file.lastIndexOf('.'))
|
||||||
|
const title = await locales[file]()
|
||||||
|
|
||||||
|
languages.push({
|
||||||
|
text: title,
|
||||||
|
value: langKey,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.availableLanguages = languages
|
||||||
|
}
|
||||||
|
|
||||||
get printerName() {
|
get printerName() {
|
||||||
return this.$store.state.gui.general.printername
|
return this.$store.state.gui.general.printername
|
||||||
}
|
}
|
||||||
@ -98,22 +117,6 @@ export default class SettingsGeneralTab extends Mixins(BaseMixin, SettingsGenera
|
|||||||
this.$store.dispatch('gui/saveSetting', { name: 'general.language', value: newVal })
|
this.$store.dispatch('gui/saveSetting', { name: 'general.language', value: newVal })
|
||||||
}
|
}
|
||||||
|
|
||||||
get availableLanguages() {
|
|
||||||
const locales = import.meta.glob('../../locales/*.json', { eager: true }) as { [key: string]: any }
|
|
||||||
const languages: { text: string; value: string }[] = []
|
|
||||||
|
|
||||||
Object.keys(locales).map((file: string) => {
|
|
||||||
const langKey = file.slice(file.lastIndexOf('.') - 2, file.lastIndexOf('.'))
|
|
||||||
|
|
||||||
languages.push({
|
|
||||||
text: locales[file].title,
|
|
||||||
value: langKey,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
return languages
|
|
||||||
}
|
|
||||||
|
|
||||||
get dateFormat() {
|
get dateFormat() {
|
||||||
return this.$store.state.gui.general.dateFormat
|
return this.$store.state.gui.general.dateFormat
|
||||||
}
|
}
|
||||||
|
@ -78,4 +78,4 @@ export default class SettingsMiscellaneousTab extends Mixins(BaseMixin) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style scoped></style>
|
||||||
|
@ -233,4 +233,4 @@ export default class SettingsMiscellaneousTabLightGroups extends Mixins(BaseMixi
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style scoped></style>
|
||||||
|
@ -464,4 +464,4 @@ export default class SettingsMiscellaneousTabLightPresets extends Mixins(BaseMix
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style scoped></style>
|
||||||
|
@ -322,7 +322,7 @@ export default class WebcamForm extends Mixins(BaseMixin, WebcamMixin) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
::v-deep ._transition svg {
|
::v-deep ._transition svg {
|
||||||
transition: transform 500ms;
|
transition: transform 500ms;
|
||||||
}
|
}
|
||||||
|
@ -70,4 +70,4 @@ export default class WebcamListEntry extends Mixins(BaseMixin, WebcamMixin) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style scoped></style>
|
||||||
|
@ -83,7 +83,7 @@ export default class Panel extends Mixins(BaseMixin) {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
.expanded header.v-toolbar {
|
.expanded header.v-toolbar {
|
||||||
border-bottom-left-radius: 4px;
|
border-bottom-left-radius: 4px;
|
||||||
border-bottom-right-radius: 4px;
|
border-bottom-right-radius: 4px;
|
||||||
@ -107,7 +107,7 @@ export default class Panel extends Mixins(BaseMixin) {
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="scss">
|
<style>
|
||||||
.v-card.panel .v-toolbar__content {
|
.v-card.panel .v-toolbar__content {
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
.btn-collapsible > * {
|
.btn-collapsible > * {
|
||||||
will-change: transform;
|
will-change: transform;
|
||||||
transition: transform 500ms;
|
transition: transform 500ms;
|
||||||
|
@ -1,31 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<template v-if="service === 'mjpegstreamer'">
|
<template v-if="service === 'mjpegstreamer'">
|
||||||
<mjpegstreamer :cam-settings="webcam" :show-fps="showFps" :printer-url="printerUrl" />
|
<mjpegstreamer-async :cam-settings="webcam" :show-fps="showFps" :printer-url="printerUrl" />
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="service === 'mjpegstreamer-adaptive'">
|
<template v-else-if="service === 'mjpegstreamer-adaptive'">
|
||||||
<mjpegstreamer-adaptive :cam-settings="webcam" :show-fps="showFps" :printer-url="printerUrl" />
|
<mjpegstreamer-adaptive-async :cam-settings="webcam" :show-fps="showFps" :printer-url="printerUrl" />
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="service === 'uv4l-mjpeg'">
|
<template v-else-if="service === 'uv4l-mjpeg'">
|
||||||
<uv4l-mjpeg :cam-settings="webcam" :printer-url="printerUrl" />
|
<uv4l-mjpeg-async :cam-settings="webcam" :printer-url="printerUrl" />
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="service === 'ipstream'">
|
<template v-else-if="service === 'ipstream'">
|
||||||
<ipstreamer :cam-settings="webcam" :printer-url="printerUrl" />
|
<ipstreamer-async :cam-settings="webcam" :printer-url="printerUrl" />
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="service === 'hlsstream'">
|
<template v-else-if="service === 'hlsstream'">
|
||||||
<hlsstreamer :cam-settings="webcam" :printer-url="printerUrl" />
|
<hlsstreamer-async :cam-settings="webcam" :printer-url="printerUrl" />
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="service === 'jmuxer-stream'">
|
<template v-else-if="service === 'jmuxer-stream'">
|
||||||
<j-muxer-stream :cam-settings="webcam" :printer-url="printerUrl" />
|
<j-muxer-stream-async :cam-settings="webcam" :printer-url="printerUrl" />
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="service === 'webrtc-camerastreamer'">
|
<template v-else-if="service === 'webrtc-camerastreamer'">
|
||||||
<webrtc-camera-streamer :cam-settings="webcam" :printer-url="printerUrl" />
|
<webrtc-camera-streamer-async :cam-settings="webcam" :printer-url="printerUrl" />
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="service === 'webrtc-janus'">
|
<template v-else-if="service === 'webrtc-janus'">
|
||||||
<janus-streamer :cam-settings="webcam" :printer-url="printerUrl" />
|
<janus-streamer-async :cam-settings="webcam" :printer-url="printerUrl" />
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="service === 'webrtc-mediamtx'">
|
<template v-else-if="service === 'webrtc-mediamtx'">
|
||||||
<webrtc-media-m-t-x :cam-settings="webcam" :printer-url="printerUrl" />
|
<webrtc-media-m-t-x-async :cam-settings="webcam" :printer-url="printerUrl" />
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<p class="text-center py-3 font-italic">{{ $t('Panels.WebcamPanel.UnknownWebcamService') }}</p>
|
<p class="text-center py-3 font-italic">{{ $t('Panels.WebcamPanel.UnknownWebcamService') }}</p>
|
||||||
@ -38,18 +38,19 @@ import Component from 'vue-class-component'
|
|||||||
import { Mixins, Prop } from 'vue-property-decorator'
|
import { Mixins, Prop } from 'vue-property-decorator'
|
||||||
import BaseMixin from '@/components/mixins/base'
|
import BaseMixin from '@/components/mixins/base'
|
||||||
import { GuiWebcamStateWebcam } from '@/store/gui/webcams/types'
|
import { GuiWebcamStateWebcam } from '@/store/gui/webcams/types'
|
||||||
|
import { DynamicCamLoader } from '@/components/webcams/streamers/DynamicCamLoader'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
Hlsstreamer: () => import('@/components/webcams/Hlsstreamer.vue'),
|
HlsstreamerAsync: DynamicCamLoader('Hlsstreamer'),
|
||||||
Ipstreamer: () => import('@/components/webcams/Ipstreamer.vue'),
|
IpstreamerAsync: DynamicCamLoader('Ipstreamer'),
|
||||||
JanusStreamer: () => import('@/components/webcams/JanusStreamer.vue'),
|
JanusStreamerAsync: DynamicCamLoader('JanusStreamer'),
|
||||||
JMuxerStream: () => import('@/components/webcams/JMuxerStream.vue'),
|
JMuxerStreamAsync: DynamicCamLoader('JMuxerStream'),
|
||||||
Mjpegstreamer: () => import('@/components/webcams/Mjpegstreamer.vue'),
|
MjpegstreamerAsync: DynamicCamLoader('Mjpegstreamer'),
|
||||||
MjpegstreamerAdaptive: () => import('@/components/webcams/MjpegstreamerAdaptive.vue'),
|
MjpegstreamerAdaptiveAsync: DynamicCamLoader('MjpegstreamerAdaptive'),
|
||||||
Uv4lMjpeg: () => import('@/components/webcams/Uv4lMjpeg.vue'),
|
Uv4lMjpegAsync: DynamicCamLoader('Uv4lMjpeg'),
|
||||||
WebrtcCameraStreamer: () => import('@/components/webcams/WebrtcCameraStreamer.vue'),
|
WebrtcCameraStreamerAsync: DynamicCamLoader('WebrtcCameraStreamer'),
|
||||||
WebrtcMediaMTX: () => import('@/components/webcams/WebrtcMediaMTX.vue'),
|
WebrtcMediaMTXAsync: DynamicCamLoader('WebrtcMediaMTX'),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
export default class WebcamWrapperItem extends Mixins(BaseMixin) {
|
export default class WebcamWrapperItem extends Mixins(BaseMixin) {
|
||||||
|
39
src/components/webcams/streamers/DynamicCamLoader.ts
Normal file
39
src/components/webcams/streamers/DynamicCamLoader.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
|
||||||
|
type StreamerTypes =
|
||||||
|
| 'Hlsstreamer'
|
||||||
|
| 'Ipstreamer'
|
||||||
|
| 'JanusStreamer'
|
||||||
|
| 'JMuxerStream'
|
||||||
|
| 'Mjpegstreamer'
|
||||||
|
| 'MjpegstreamerAdaptive'
|
||||||
|
| 'Uv4lMjpeg'
|
||||||
|
| 'WebrtcCameraStreamer'
|
||||||
|
| 'WebrtcMediaMTX'
|
||||||
|
|
||||||
|
function getDynamicCamImport(componentName: StreamerTypes) {
|
||||||
|
// split each webcam streamer into its own chunk
|
||||||
|
switch (componentName) {
|
||||||
|
case 'Hlsstreamer':
|
||||||
|
return () => import('@/components/webcams/streamers/Hlsstreamer.vue')
|
||||||
|
case 'Ipstreamer':
|
||||||
|
return () => import('@/components/webcams/streamers/Ipstreamer.vue')
|
||||||
|
case 'JanusStreamer':
|
||||||
|
return () => import('@/components/webcams/streamers/JanusStreamer.vue')
|
||||||
|
case 'JMuxerStream':
|
||||||
|
return () => import('@/components/webcams/streamers/JMuxerStream.vue')
|
||||||
|
case 'Mjpegstreamer':
|
||||||
|
return () => import('@/components/webcams/streamers/Mjpegstreamer.vue')
|
||||||
|
case 'MjpegstreamerAdaptive':
|
||||||
|
return () => import('@/components/webcams/streamers/MjpegstreamerAdaptive.vue')
|
||||||
|
case 'Uv4lMjpeg':
|
||||||
|
return () => import('@/components/webcams/streamers/Uv4lMjpeg.vue')
|
||||||
|
case 'WebrtcCameraStreamer':
|
||||||
|
return () => import('@/components/webcams/streamers/WebrtcCameraStreamer.vue')
|
||||||
|
case 'WebrtcMediaMTX':
|
||||||
|
return () => import('@/components/webcams/streamers/WebrtcMediaMTX.vue')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DynamicCamLoader = (componentName: StreamerTypes) =>
|
||||||
|
Vue.component(componentName, getDynamicCamImport(componentName))
|
86
src/main.ts
86
src/main.ts
@ -1,41 +1,53 @@
|
|||||||
import 'core-js/stable' // polyfills for older browsers
|
|
||||||
import 'regenerator-runtime' // async polyfill used by the gcodeviewer
|
import 'regenerator-runtime' // async polyfill used by the gcodeviewer
|
||||||
import 'resize-observer-polyfill' // polyfill needed by the responsive class detection
|
import 'resize-observer-polyfill' // polyfill needed by the responsive class detection
|
||||||
|
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import App from '@/App.vue'
|
import App from '@/App.vue'
|
||||||
import vuetify from '@/plugins/vuetify'
|
import vuetify from '@/plugins/vuetify'
|
||||||
import i18n from '@/plugins/i18n'
|
import i18n, { setAndLoadLocale } from '@/plugins/i18n'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
import router from '@/plugins/router'
|
import router from '@/plugins/router'
|
||||||
import { WebSocketPlugin } from '@/plugins/webSocketClient'
|
import { WebSocketPlugin } from '@/plugins/webSocketClient'
|
||||||
|
|
||||||
Vue.config.productionTip = false
|
|
||||||
|
|
||||||
// vue-observe-visibility
|
// vue-observe-visibility
|
||||||
import { ObserveVisibility } from 'vue-observe-visibility'
|
import { ObserveVisibility } from 'vue-observe-visibility'
|
||||||
Vue.directive('observe-visibility', ObserveVisibility)
|
|
||||||
|
|
||||||
//vue-meta
|
//vue-meta
|
||||||
import VueMeta from 'vue-meta'
|
import VueMeta from 'vue-meta'
|
||||||
Vue.use(VueMeta)
|
|
||||||
|
|
||||||
//vue-load-image
|
//vue-load-image
|
||||||
import VueLoadImage from 'vue-load-image'
|
import VueLoadImage from 'vue-load-image'
|
||||||
Vue.component('VueLoadImage', VueLoadImage)
|
|
||||||
|
|
||||||
//vue-toast-notifications
|
//vue-toast-notifications
|
||||||
import VueToast from 'vue-toast-notification'
|
import VueToast from 'vue-toast-notification'
|
||||||
import 'vue-toast-notification/dist/theme-sugar.css'
|
import 'vue-toast-notification/dist/theme-sugar.css'
|
||||||
|
//overlayerscrollbars-vue
|
||||||
|
import { OverlayScrollbarsPlugin } from 'overlayscrollbars-vue'
|
||||||
|
import 'overlayscrollbars/css/OverlayScrollbars.css'
|
||||||
|
// Directives
|
||||||
|
import './directives/longpress'
|
||||||
|
import './directives/responsive-class'
|
||||||
|
|
||||||
|
// Echarts
|
||||||
|
import ECharts from 'vue-echarts'
|
||||||
|
import { use } from 'echarts/core'
|
||||||
|
|
||||||
|
// import ECharts modules manually to reduce bundle size
|
||||||
|
import { SVGRenderer } from 'echarts/renderers'
|
||||||
|
import { BarChart, LineChart, PieChart } from 'echarts/charts'
|
||||||
|
import { DatasetComponent, GridComponent, LegendComponent, TooltipComponent } from 'echarts/components'
|
||||||
|
// vue-resize
|
||||||
|
import 'vue-resize/dist/vue-resize.css'
|
||||||
|
// @ts-ignore
|
||||||
|
import VueResize from 'vue-resize'
|
||||||
|
|
||||||
|
Vue.config.productionTip = false
|
||||||
|
|
||||||
|
Vue.directive('observe-visibility', ObserveVisibility)
|
||||||
|
|
||||||
|
Vue.use(VueMeta)
|
||||||
|
|
||||||
|
Vue.component('VueLoadImage', VueLoadImage)
|
||||||
|
|
||||||
Vue.use(VueToast, {
|
Vue.use(VueToast, {
|
||||||
duration: 3000,
|
duration: 3000,
|
||||||
})
|
})
|
||||||
|
|
||||||
//overlayerscrollbars-vue
|
|
||||||
import { OverlayScrollbarsPlugin } from 'overlayscrollbars-vue'
|
|
||||||
import 'overlayscrollbars/css/OverlayScrollbars.css'
|
|
||||||
|
|
||||||
const isSafari = navigator.userAgent.includes('Safari') && navigator.userAgent.search('Chrome') === -1
|
const isSafari = navigator.userAgent.includes('Safari') && navigator.userAgent.search('Chrome') === -1
|
||||||
const isTouch = 'ontouchstart' in window || (navigator.maxTouchPoints > 0 && navigator.maxTouchPoints !== 256)
|
const isTouch = 'ontouchstart' in window || (navigator.maxTouchPoints > 0 && navigator.maxTouchPoints !== 256)
|
||||||
Vue.use(OverlayScrollbarsPlugin, {
|
Vue.use(OverlayScrollbarsPlugin, {
|
||||||
@ -46,41 +58,27 @@ Vue.use(OverlayScrollbarsPlugin, {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
// Directives
|
|
||||||
import './directives/longpress'
|
|
||||||
import './directives/responsive-class'
|
|
||||||
|
|
||||||
// Echarts
|
|
||||||
import ECharts from 'vue-echarts'
|
|
||||||
import { use } from 'echarts/core'
|
|
||||||
|
|
||||||
// import ECharts modules manually to reduce bundle size
|
|
||||||
import { SVGRenderer } from 'echarts/renderers'
|
|
||||||
import { LineChart, BarChart, PieChart } from 'echarts/charts'
|
|
||||||
import { GridComponent, LegendComponent, TooltipComponent, DatasetComponent } from 'echarts/components'
|
|
||||||
|
|
||||||
use([SVGRenderer, LineChart, BarChart, LegendComponent, PieChart, DatasetComponent, GridComponent, TooltipComponent])
|
use([SVGRenderer, LineChart, BarChart, LegendComponent, PieChart, DatasetComponent, GridComponent, TooltipComponent])
|
||||||
Vue.component('EChart', ECharts)
|
Vue.component('EChart', ECharts)
|
||||||
|
|
||||||
// vue-resize
|
|
||||||
import 'vue-resize/dist/vue-resize.css'
|
|
||||||
// @ts-ignore
|
|
||||||
import VueResize from 'vue-resize'
|
|
||||||
Vue.use(VueResize)
|
Vue.use(VueResize)
|
||||||
|
|
||||||
const initLoad = async () => {
|
const initLoad = async () => {
|
||||||
//load config.json
|
try {
|
||||||
await fetch('/config.json')
|
//load config.json
|
||||||
.then((res) => res.json())
|
const res = await fetch('/config.json')
|
||||||
.then(async (file) => {
|
const file = (await res.json()) as Record<string, unknown>
|
||||||
window.console.debug('Loaded config.json')
|
|
||||||
|
|
||||||
await store.dispatch('importConfigJson', file)
|
window.console.debug('Loaded config.json')
|
||||||
if ('defaultLocale' in file) i18n.locale = file.defaultLocale
|
|
||||||
})
|
await store.dispatch('importConfigJson', file)
|
||||||
.catch(() => {
|
if ('defaultLocale' in file) {
|
||||||
window.console.error('config.json not found or cannot be decoded!')
|
await setAndLoadLocale(file.defaultLocale as string)
|
||||||
})
|
}
|
||||||
|
} catch (e) {
|
||||||
|
window.console.error('Failed to load config.json')
|
||||||
|
window.console.error(e)
|
||||||
|
}
|
||||||
|
|
||||||
const url = store.getters['socket/getWebsocketUrl']
|
const url = store.getters['socket/getWebsocketUrl']
|
||||||
Vue.use(WebSocketPlugin, { url, store })
|
Vue.use(WebSocketPlugin, { url, store })
|
||||||
|
@ -2,23 +2,21 @@ import Vue from 'vue'
|
|||||||
import VueI18n from 'vue-i18n'
|
import VueI18n from 'vue-i18n'
|
||||||
Vue.use(VueI18n)
|
Vue.use(VueI18n)
|
||||||
|
|
||||||
function loadLocaleMessages() {
|
import defaultLocale from '../locales/en.json'
|
||||||
const locales = import.meta.globEager('../locales/*.json')
|
|
||||||
const messages: any = {}
|
|
||||||
|
|
||||||
for (const file in locales) {
|
const locale = (import.meta.env.VUE_APP_I18N_LOCALE as string) || 'en'
|
||||||
const langKey = file.slice(file.lastIndexOf('.') - 2, file.lastIndexOf('.'))
|
|
||||||
|
|
||||||
if (langKey && langKey.length > 1) {
|
const i18n = new VueI18n({
|
||||||
messages[langKey] = JSON.parse(JSON.stringify(locales[file]))
|
locale,
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return messages
|
|
||||||
}
|
|
||||||
|
|
||||||
export default new VueI18n({
|
|
||||||
locale: (import.meta.env.VUE_APP_I18N_LOCALE as string) || 'en',
|
|
||||||
fallbackLocale: (import.meta.env.VUE_APP_I18N_FALLBACK_LOCALE as string) || 'en',
|
fallbackLocale: (import.meta.env.VUE_APP_I18N_FALLBACK_LOCALE as string) || 'en',
|
||||||
messages: loadLocaleMessages(),
|
messages: { en: defaultLocale },
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export default i18n
|
||||||
|
|
||||||
|
export async function setAndLoadLocale(lang: string) {
|
||||||
|
const locales = await import(`../locales/${lang}.json`)
|
||||||
|
i18n.setLocaleMessage(lang, locales)
|
||||||
|
i18n.locale = lang
|
||||||
|
return locales
|
||||||
|
}
|
||||||
|
@ -76,17 +76,35 @@ export default defineConfig({
|
|||||||
resolvers: [VuetifyResolver()],
|
resolvers: [VuetifyResolver()],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|
||||||
css: {
|
css: {
|
||||||
preprocessorOptions: {
|
postcss: {
|
||||||
css: { charset: false },
|
plugins: [require('postcss-nesting')()],
|
||||||
scss: {
|
|
||||||
quietDeps: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
build: {
|
build: {
|
||||||
target: 'safari12',
|
target: 'safari12',
|
||||||
|
rollupOptions: {
|
||||||
|
output: {
|
||||||
|
manualChunks: (id: string) => {
|
||||||
|
if (id.includes('node_modules')) {
|
||||||
|
// split codemirror into its own chunk
|
||||||
|
if (id.includes('/codemirror/') || id.includes('/@codemirror/')) {
|
||||||
|
return 'codemirror'
|
||||||
|
}
|
||||||
|
|
||||||
|
// split these libs into their own chunks
|
||||||
|
const chunkedLibs = ['vuetify', 'echarts', 'overlayscrollbars']
|
||||||
|
for (const lib of chunkedLibs) {
|
||||||
|
if (id.includes(`/node_modules/${lib}/`)) {
|
||||||
|
return lib.replace('.js', '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
envPrefix: 'VUE_',
|
envPrefix: 'VUE_',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user