Jelajahi Sumber

Переход на Vue 3, в процессе

Book Pauk 3 tahun lalu
induk
melakukan
88d75fb0d8

+ 3 - 0
build/webpack.base.config.js

@@ -6,6 +6,9 @@ const clientDir = path.resolve(__dirname, '../client');
 
 module.exports = {
     resolve: {
+        alias: {
+            vue: '@vue/compat'
+        },
         fallback: {
             "url": false,
             "path": false,

+ 2 - 0
client/components/App.vue

@@ -77,6 +77,8 @@ class App {
             }
         });
 
+        this.$root.isMobileDevice = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);
+
         // setAppTitle
         this.$root.setAppTitle = this.setAppTitle;
 

+ 14 - 10
client/components/Reader/LoaderPage/LoaderPage.vue

@@ -1,7 +1,7 @@
 <template>
     <div ref="main" class="column no-wrap" style="min-height: 500px">
         <div v-if="mode != 'liberama.top'" class="relative-position">
-            <GithubCorner url="https://github.com/bookpauk/liberama" cornerColor="#1B695F" gitColor="#EBE2C9"></GithubCorner>
+            <GithubCorner url="https://github.com/bookpauk/liberama" corner-color="#1B695F" git-color="#EBE2C9"></GithubCorner>
         </div>
         <div class="col column justify-center items-center no-wrap overflow-hidden" style="min-height: 230px">
             <span class="greeting"><b>{{ title }}</b></span>
@@ -12,13 +12,13 @@
         </div>
 
         <div class="col-auto column justify-start items-center no-wrap overflow-hidden">
-            <q-input ref="input" class="full-width q-px-sm" style="max-width: 700px" outlined dense bg-color="white" v-model="bookUrl" placeholder="URL книги">
-                <template v-slot:append>
-                    <q-btn rounded flat style="width: 40px" icon="la la-check" @click="submitUrl"/>
+            <q-input ref="input" v-model="bookUrl" class="full-width q-px-sm" style="max-width: 700px" outlined dense bg-color="white" placeholder="URL книги">
+                <template #append>
+                    <q-btn rounded flat style="width: 40px" icon="la la-check" @click="submitUrl" />
                 </template>
             </q-input>
 
-            <input type="file" id="file" ref="file" @change="loadFile" style='display: none;'/>
+            <input id="file" ref="file" type="file" style="display: none;" @change="loadFile" />
 
             <div class="q-my-sm"></div>
             <q-btn no-caps dense class="q-px-sm" color="primary" size="13px" @click="loadFileClick">
@@ -58,20 +58,22 @@
 
 <script>
 //-----------------------------------------------------------------------------
-import Vue from 'vue';
-import Component from 'vue-class-component';
+import vueComponent from '../../vueComponent.js';
+
 import GithubCorner from './GithubCorner/GithubCorner.vue';
 
 import PasteTextPage from './PasteTextPage/PasteTextPage.vue';
 import {versionHistory} from '../versionHistory';
 
-export default @Component({
+const componentOptions = {
     components: {
         GithubCorner,
         PasteTextPage,
     },
-})
-class LoaderPage extends Vue {
+};
+class LoaderPage {
+    _options = componentOptions;
+
     bookUrl = null;
     loadPercent = 0;
     pasteTextActive = false;
@@ -190,6 +192,8 @@ class LoaderPage extends Vue {
         return false;
     }
 }
+
+export default vueComponent(LoaderPage);
 //-----------------------------------------------------------------------------
 </script>
 <style scoped>

+ 10 - 7
client/components/Reader/LoaderPage/PasteTextPage/PasteTextPage.vue

@@ -8,27 +8,28 @@
             </span>
         </template>
 
-        <q-input class="q-px-sm" dense borderless v-model="bookTitle" placeholder="Введите название текста"/>
-        <hr/>
+        <q-input v-model="bookTitle" class="q-px-sm" dense borderless placeholder="Введите название текста" />
+        <hr />
         <textarea ref="textArea" class="text" @paste="calcTitle"></textarea>
     </Window>
 </template>
 
 <script>
 //-----------------------------------------------------------------------------
-import Vue from 'vue';
-import Component from 'vue-class-component';
+import vueComponent from '../../../vueComponent.js';
 
 import Window from '../../../share/Window.vue';
 import _ from 'lodash';
 import * as utils from '../../../../share/utils';
 
-export default @Component({
+const componentOptions = {
     components: {
         Window,
     },
-})
-class PasteTextPage extends Vue {
+};
+class PasteTextPage {
+    _options = componentOptions;
+
     bookTitle = '';
 
     created() {
@@ -90,6 +91,8 @@ class PasteTextPage extends Vue {
         return true;
     }
 }
+
+export default vueComponent(PasteTextPage);
 //-----------------------------------------------------------------------------
 </script>
 

+ 6 - 6
client/components/Reader/ProgressPage/ProgressPage.vue

@@ -17,7 +17,7 @@
 
             <div>
                 <span class="text-yellow">{{ text }}</span>
-                <q-icon :style="iconStyle" color="yellow" name="la la-slash" size="20px"/>
+                <q-icon :style="iconStyle" color="yellow" name="la la-slash" size="20px" />
             </div>
         </div>
     </div>
@@ -25,8 +25,8 @@
 
 <script>
 //-----------------------------------------------------------------------------
-import Vue from 'vue';
-import Component from 'vue-class-component';
+import vueComponent from '../../vueComponent.js';
+
 import * as utils from '../../../share/utils';
 
 const ruMessage = {
@@ -42,9 +42,7 @@ const ruMessage = {
     'upload': 'отправка',
 };
 
-export default @Component({
-})
-class ProgressPage extends Vue {
+class ProgressPage {
     text = '';
     totalSteps = 1;
     step = 1;
@@ -96,5 +94,7 @@ class ProgressPage extends Vue {
         return Math.round(((this.step - 1)/this.totalSteps + this.progress/(100*this.totalSteps))*100);
     }
 }
+
+export default vueComponent(ProgressPage);
 //-----------------------------------------------------------------------------
 </script>

+ 15 - 11
client/components/Reader/Reader.vue

@@ -115,7 +115,7 @@
                 ></component>
             </keep-alive>
 
-            <SetPositionPage v-if="setPositionActive" ref="setPositionPage" @set-position-toggle="setPositionToggle" @book-pos-changed="bookPosChanged"></SetPositionPage>
+            <!--SetPositionPage v-if="setPositionActive" ref="setPositionPage" @set-position-toggle="setPositionToggle" @book-pos-changed="bookPosChanged"></SetPositionPage>
             <SearchPage v-show="searchActive" ref="searchPage" 
                 @do-action="doAction"
                 @book-pos-changed="bookPosChanged"
@@ -129,7 +129,7 @@
             <HelpPage v-if="helpActive" ref="helpPage" @do-action="doAction"></HelpPage>
             <ClickMapPage v-show="clickMapActive" ref="clickMapPage"></ClickMapPage>
             <ServerStorage v-show="hidden" ref="serverStorage"></ServerStorage>
-            <ContentsPage v-show="contentsActive" ref="contentsPage" :book-pos="bookPos" :is-visible="contentsActive" @do-action="doAction" @book-pos-changed="bookPosChanged"></ContentsPage>
+            <ContentsPage v-show="contentsActive" ref="contentsPage" :book-pos="bookPos" :is-visible="contentsActive" @do-action="doAction" @book-pos-changed="bookPosChanged"></ContentsPage-->
 
             <ReaderDialogs ref="dialogs" @donate-toggle="donateToggle" @version-history-toggle="versionHistoryToggle"></ReaderDialogs>
         </div>
@@ -138,8 +138,8 @@
 
 <script>
 //-----------------------------------------------------------------------------
-import Vue from 'vue';
-import Component from 'vue-class-component';
+import vueComponent from '../vueComponent.js';
+
 import _ from 'lodash';
 import {Buffer} from 'safe-buffer';
 
@@ -147,7 +147,7 @@ import LoaderPage from './LoaderPage/LoaderPage.vue';
 import TextPage from './TextPage/TextPage.vue';
 import ProgressPage from './ProgressPage/ProgressPage.vue';
 
-import SetPositionPage from './SetPositionPage/SetPositionPage.vue';
+/*import SetPositionPage from './SetPositionPage/SetPositionPage.vue';
 import SearchPage from './SearchPage/SearchPage.vue';
 import CopyTextPage from './CopyTextPage/CopyTextPage.vue';
 import LibsPage from './LibsPage/LibsPage.vue';
@@ -156,7 +156,7 @@ import SettingsPage from './SettingsPage/SettingsPage.vue';
 import HelpPage from './HelpPage/HelpPage.vue';
 import ClickMapPage from './ClickMapPage/ClickMapPage.vue';
 import ServerStorage from './ServerStorage/ServerStorage.vue';
-import ContentsPage from './ContentsPage/ContentsPage.vue';
+import ContentsPage from './ContentsPage/ContentsPage.vue';*/
 
 import ReaderDialogs from './ReaderDialogs/ReaderDialogs.vue';
 
@@ -171,13 +171,13 @@ import miscApi from '../../api/misc';
 import {versionHistory} from './versionHistory';
 import * as utils from '../../share/utils';
 
-export default @Component({
+const componentOptions = {
     components: {
         LoaderPage,
         TextPage,
         ProgressPage,
 
-        SetPositionPage,
+        /*SetPositionPage,
         SearchPage,
         CopyTextPage,
         LibsPage,
@@ -186,7 +186,7 @@ export default @Component({
         HelpPage,
         ClickMapPage,
         ServerStorage,
-        ContentsPage,
+        ContentsPage,*/
 
         ReaderDialogs,
     },
@@ -232,8 +232,10 @@ export default @Component({
                 this.stopScrolling();
         },
     },
-})
-class Reader extends Vue {
+};
+
+class Reader {
+    _options = componentOptions;
     rstore = {};
     loaderActive = false;
     offlineModeActive = false;
@@ -1308,6 +1310,8 @@ class Reader extends Vue {
         return result;
     }
 }
+
+export default vueComponent(Reader);
 //-----------------------------------------------------------------------------
 </script>
 

+ 14 - 7
client/components/Reader/ReaderDialogs/ReaderDialogs.vue

@@ -35,7 +35,9 @@
                 Автор также обращается с просьбой о помощи в распространении 
                 <a href="https://omnireader.ru" target="_blank">ссылки</a>
                 <q-icon class="copy-icon" name="la la-copy" @click="copyLink('https://omnireader.ru')">
-                    <q-tooltip :delay="1000" anchor="top middle" self="center middle" content-style="font-size: 80%">Скопировать</q-tooltip>                    
+                    <q-tooltip :delay="1000" anchor="top middle" self="center middle" content-style="font-size: 80%">
+                        Скопировать
+                    </q-tooltip>                    
                 </q-icon>
                 на читалку через тематические форумы, соцсети, мессенджеры и пр.
                 Чем нас больше, тем легче оставаться на плаву и тем больше мотивации у разработчика, чтобы продолжать работать над проектом.
@@ -47,7 +49,9 @@
 
                 <br><br>
                 <div class="row justify-center">
-                    <q-btn class="q-px-sm" color="primary" dense no-caps rounded @click="openDonate">Помочь проекту</q-btn>
+                    <q-btn class="q-px-sm" color="primary" dense no-caps rounded @click="openDonate">
+                        Помочь проекту
+                    </q-btn>
                 </div>
             </div>
 
@@ -62,14 +66,13 @@
 
 <script>
 //-----------------------------------------------------------------------------
-import Vue from 'vue';
-import Component from 'vue-class-component';
+import vueComponent from '../../vueComponent.js';
 
 import Dialog from '../../share/Dialog.vue';
 import * as utils from '../../../share/utils';
 import {versionHistory} from '../versionHistory';
 
-export default @Component({
+const componentOptions = {
     components: {
         Dialog
     },
@@ -78,8 +81,10 @@ export default @Component({
             this.loadSettings();
         },
     },
-})
-class ReaderDialogs extends Vue {
+};
+class ReaderDialogs {
+    _options = componentOptions;
+
     whatsNewVisible = false;
     whatsNewContent = '';
     donationVisible = false;
@@ -181,6 +186,8 @@ class ReaderDialogs extends Vue {
         return false;
     }
 }
+
+export default vueComponent(ReaderDialogs);
 //-----------------------------------------------------------------------------
 </script>
 

+ 1 - 1
client/components/Reader/SettingsPage/SettingsPage.vue

@@ -200,7 +200,7 @@ class SettingsPage extends Vue {
         this.$watch(
             '$refs.tabs.scrollable',
             (newValue) => {
-                this.tabsScrollable = newValue && !this.$isMobileDevice;
+                this.tabsScrollable = newValue && !this.$root.isMobileDevice;
             }
         );
     }

+ 14 - 14
client/components/Reader/SettingsPage/UserHotKeys/UserHotKeys.vue

@@ -72,7 +72,7 @@ import rstore from '../../../../store/modules/reader';
 
 const UserHotKeysProps = Vue.extend({
     props: {
-        value: Object,
+        modelValue: Object,
         readonly: Boolean,
     }
 });
@@ -82,7 +82,7 @@ export default @Component({
         search: function() {
             this.updateTableData();
         },
-        value: function() {
+        modelValue: function() {
             this.checkCollisions();
             this.updateTableData();
         }
@@ -113,7 +113,7 @@ class UserHotKeys extends UserHotKeysProps {
 
         const search = this.search.toLowerCase();
         const codesIncludeSearch = (action) => {
-            for (const code of this.value[action]) {
+            for (const code of this.modelValue[action]) {
                 if (code.toLowerCase().includes(search))
                     return true;
             }
@@ -131,7 +131,7 @@ class UserHotKeys extends UserHotKeysProps {
 
     checkCollisions() {
         const cols = {};
-        for (const [action, codes] of Object.entries(this.value)) {
+        for (const [action, codes] of Object.entries(this.modelValue)) {
             codes.forEach(code => {
                 if (!cols[code])
                     cols[code] = [];
@@ -158,26 +158,26 @@ class UserHotKeys extends UserHotKeysProps {
     }
 
     removeCode(action, code) {
-        let codes = Array.from(this.value[action]);
+        let codes = Array.from(this.modelValue[action]);
         const index = codes.indexOf(code);
         if (index >= 0) {
             codes.splice(index, 1);
-            const newValue = Object.assign({}, this.value, {[action]: codes});
-            this.$emit('input', newValue);
+            const newValue = Object.assign({}, this.modelValue, {[action]: codes});
+            this.$emit('update:modelValue', newValue);
         }
     }
 
     async addHotKey(action) {
-        if (this.value[action].length >= this.maxCodesLength)
+        if (this.modelValue[action].length >= this.maxCodesLength)
             return;
         try {
             const result = await this.$root.stdDialog.getHotKey(`Добавить сочетание для:<br><b>${rstore.readerActions[action]}</b>`, '');
             if (result) {
-                let codes = Array.from(this.value[action]);
+                let codes = Array.from(this.modelValue[action]);
                 if (codes.indexOf(result) < 0) {
                     codes.push(result);
-                    const newValue = Object.assign({}, this.value, {[action]: codes});
-                    this.$emit('input', newValue);
+                    const newValue = Object.assign({}, this.modelValue, {[action]: codes});
+                    this.$emit('update:modelValue', newValue);
                     this.$nextTick(() => {
                         this.collisionWarning(result);
                     });
@@ -192,8 +192,8 @@ class UserHotKeys extends UserHotKeysProps {
         try {
             if (await this.$root.stdDialog.confirm(`Подтвердите сброс сочетаний клавиш<br>в значения по умолчанию для команды:<br><b>${rstore.readerActions[action]}</b>`, ' ')) {
                 const codes = Array.from(rstore.settingDefaults.userHotKeys[action]);
-                const newValue = Object.assign({}, this.value, {[action]: codes});
-                this.$emit('input', newValue);
+                const newValue = Object.assign({}, this.modelValue, {[action]: codes});
+                this.$emit('update:modelValue', newValue);
             }
         } catch (e) {
             //
@@ -204,7 +204,7 @@ class UserHotKeys extends UserHotKeysProps {
         try {
             if (await this.$root.stdDialog.confirm('Подтвердите сброс сочетаний клавиш<br>для ВСЕХ команд в значения по умолчанию:', ' ')) {
                 const newValue = Object.assign({}, rstore.settingDefaults.userHotKeys);
-                this.$emit('input', newValue);
+                this.$emit('update:modelValue', newValue);
             }
         } catch (e) {
             //

+ 29 - 18
client/components/Reader/TextPage/TextPage.vue

@@ -17,15 +17,22 @@
         <div v-show="showStatusBar" ref="statusBar" class="layout">
             <div v-html="statusBar"></div>
         </div>
-        <div v-show="clickControl" ref="layoutEvents" class="layout events" @mousedown.prevent.stop="onMouseDown" @mouseup.prevent.stop="onMouseUp"
+        <div v-show="clickControl" ref="layoutEvents" class="layout events" 
+            oncontextmenu="return false;"
+            @mousedown.prevent.stop="onMouseDown" @mouseup.prevent.stop="onMouseUp"
             @wheel.prevent.stop="onMouseWheel"
-            @touchstart.stop="onTouchStart" @touchend.stop="onTouchEnd" @touchmove.stop="onTouchMove" @touchcancel.prevent.stop="onTouchCancel"
-            oncontextmenu="return false;">
-            <div v-show="showStatusBar && statusBarClickOpen" v-html="statusBarClickable" @mousedown.prevent.stop @touchstart.stop
-                @click.prevent.stop="onStatusBarClick"></div>
+            @touchstart.stop="onTouchStart" @touchend.stop="onTouchEnd" @touchmove.stop="onTouchMove" @touchcancel.prevent.stop="onTouchCancel"            
+        >
+            <div v-show="showStatusBar && statusBarClickOpen" @mousedown.prevent.stop @touchstart.stop
+                @click.prevent.stop="onStatusBarClick"
+                v-html="statusBarClickable"
+            ></div>
         </div>
-        <div v-show="!clickControl && showStatusBar && statusBarClickOpen" class="layout" v-html="statusBarClickable" @mousedown.prevent.stop @touchstart.stop
-            @click.prevent.stop="onStatusBarClick">
+        <div v-show="!clickControl && showStatusBar && statusBarClickOpen" class="layout" 
+            @mousedown.prevent.stop @touchstart.stop
+            @click.prevent.stop="onStatusBarClick"
+            v-html="statusBarClickable"
+        >
         </div>
         <!-- невидимым делать нельзя (display: none), вовремя не подгружаютя шрифты -->
         <canvas ref="offscreenCanvas" class="layout" style="visibility: hidden"></canvas>
@@ -35,8 +42,8 @@
 
 <script>
 //-----------------------------------------------------------------------------
-import Vue from 'vue';
-import Component from 'vue-class-component';
+import vueComponent from '../../vueComponent.js';
+
 import {loadCSS} from 'fg-loadcss';
 import _ from 'lodash';
 
@@ -51,7 +58,7 @@ import {clickMap} from '../share/clickMap';
 
 const minLayoutWidth = 100;
 
-export default @Component({
+const componentOptions = {
     watch: {
         bookPos: function() {
             this.$emit('book-pos-changed', {bookPos: this.bookPos, bookPosSeen: this.bookPosSeen});
@@ -70,8 +77,10 @@ export default @Component({
             this.updateLayout();
         },
     },
-})
-class TextPage extends Vue {
+};
+class TextPage {
+    _options = componentOptions;
+
     toggleLayout = false;
     showStatusBar = false;
     clickControl = true;
@@ -1036,7 +1045,7 @@ class TextPage extends Vue {
     }
 
     onTouchStart(event) {
-        if (!this.$isMobileDevice)
+        if (!this.$root.isMobileDevice)
             return;
         this.endClickRepeat();
 
@@ -1064,7 +1073,7 @@ class TextPage extends Vue {
     }
 
     onTouchEnd(event) {
-        if (!this.$isMobileDevice)
+        if (!this.$root.isMobileDevice)
             return;
         this.endClickRepeat();
 
@@ -1100,13 +1109,13 @@ class TextPage extends Vue {
     }
 
     onTouchCancel() {
-        if (!this.$isMobileDevice)
+        if (!this.$root.isMobileDevice)
             return;
         this.endClickRepeat();
     }
 
     onMouseDown(event) {
-        if (this.$isMobileDevice)
+        if (this.$root.isMobileDevice)
             return;
         this.endClickRepeat();
         if (event.button == 0) {
@@ -1123,13 +1132,13 @@ class TextPage extends Vue {
     }
 
     onMouseUp() {
-        if (this.$isMobileDevice)
+        if (this.$root.isMobileDevice)
             return;
         this.endClickRepeat();
     }
 
     onMouseWheel(event) {
-        if (this.$isMobileDevice)
+        if (this.$root.isMobileDevice)
             return;
         if (event.deltaY > 0) {
             this.doDown();
@@ -1195,6 +1204,8 @@ class TextPage extends Vue {
    }
 
 }
+
+export default vueComponent(TextPage);
 //-----------------------------------------------------------------------------
 </script>
 <style scoped>

+ 9 - 12
client/components/share/Dialog.vue

@@ -25,26 +25,23 @@
 
 <script>
 //-----------------------------------------------------------------------------
-import Vue from 'vue';
-import Component from 'vue-class-component';
+import vueComponent from '../vueComponent.js';
 
-const DialogProps = Vue.extend({
-    props: {
-        value: Boolean,
-    }
-});
+class Dialog {
+    _props = {
+        modelValue: Boolean,
+    };
 
-export default @Component({
-})
-class Dialog extends DialogProps {
     get active() {
-        return this.value;
+        return this.modelValue;
     }
 
     set active(value) {
-        this.$emit('input', value);
+        this.$emit('update:modelValue', value);
     }
 }
+
+export default vueComponent(Dialog);
 //-----------------------------------------------------------------------------
 </script>
 

+ 33 - 30
client/components/share/NumInput.vue

@@ -1,17 +1,19 @@
 <template>
-    <q-input outlined dense
+    <q-input
         v-model="filteredValue"
+        outlined dense
         input-style="text-align: center"
         class="no-mp"
         :class="(error ? 'error' : '')"
         :disable="disable"
     >
         <slot></slot>
-        <template v-slot:prepend>
-            <q-icon :class="(validate(value - step) ? '' : 'disable')" 
+        <template #prepend>
+            <q-icon
+                v-ripple="validate(value - step)" 
+                :class="(validate(value - step) ? '' : 'disable')" 
                 name="la la-minus-circle" 
                 class="button" 
-                v-ripple="validate(value - step)" 
                 @click="minus"
                 @mousedown.prevent.stop="onMouseDown($event, 'minus')"
                 @mouseup.prevent.stop="onMouseUp"
@@ -21,11 +23,12 @@
                 @touchcancel.prevent.stop="onTouchEnd"
             />
         </template>
-        <template v-slot:append>
-            <q-icon :class="(validate(value + step) ? '' : 'disable')"
+        <template #append>
+            <q-icon
+                v-ripple="validate(value + step)"
+                :class="(validate(value + step) ? '' : 'disable')"
                 name="la la-plus-circle"
                 class="button"
-                v-ripple="validate(value + step)"
                 @click="plus"
                 @mousedown.prevent.stop="onMouseDown($event, 'plus')"
                 @mouseup.prevent.stop="onMouseUp"
@@ -40,43 +43,41 @@
 
 <script>
 //-----------------------------------------------------------------------------
-import Vue from 'vue';
-import Component from 'vue-class-component';
+import vueComponent from '../vueComponent.js';
 
 import * as utils from '../../share/utils';
 
-const NumInputProps = Vue.extend({
-    props: {
-        value: Number,
-        min: { type: Number, default: -Number.MAX_VALUE },
-        max: { type: Number, default: Number.MAX_VALUE },
-        step: { type: Number, default: 1 },
-        digits: { type: Number, default: 0 },
-        disable: Boolean
-    }
-});
-
-export default @Component({
+const componentOptions = {
     watch: {
         filteredValue: function(newValue) {
             if (this.validate(newValue)) {
                 this.error = false;
-                this.$emit('input', this.string2number(newValue));
+                this.$emit('update:modelValue', this.string2number(newValue));
             } else {
                 this.error = true;
             }
         },
-        value: function(newValue) {
+        modelValue: function(newValue) {
             this.filteredValue = newValue;
         },
     }
-})
-class NumInput extends NumInputProps {
+};
+class NumInput {
+    _options = componentOptions;
+    _props = {
+        modelValue: Number,
+        min: { type: Number, default: -Number.MAX_VALUE },
+        max: { type: Number, default: Number.MAX_VALUE },
+        step: { type: Number, default: 1 },
+        digits: { type: Number, default: 0 },
+        disable: Boolean
+    };
+
     filteredValue = 0;
     error = false;
 
     created() {
-        this.filteredValue = this.value;
+        this.filteredValue = this.modelValue;
     }
 
     string2number(value) {
@@ -95,13 +96,13 @@ class NumInput extends NumInputProps {
     }
 
     plus() {
-        const newValue = this.value + this.step;
+        const newValue = this.modelValue + this.step;
         if (this.validate(newValue))
             this.filteredValue = newValue;
     }
 
     minus() {
-        const newValue = this.value - this.step;
+        const newValue = this.modelValue - this.step;
         if (this.validate(newValue))
             this.filteredValue = newValue;
     }
@@ -136,7 +137,7 @@ class NumInput extends NumInputProps {
     }
 
     onTouchStart(event, way) {
-        if (!this.$isMobileDevice)
+        if (!this.$root.isMobileDevice)
             return;
         if (event.touches.length == 1) {
             this.inTouch = true;
@@ -145,12 +146,14 @@ class NumInput extends NumInputProps {
     }
 
     onTouchEnd() {
-        if (!this.$isMobileDevice)
+        if (!this.$root.isMobileDevice)
             return;
         this.inTouch = false;
         this.onMouseUp();
     }
 }
+
+export default vueComponent(NumInput);
 //-----------------------------------------------------------------------------
 </script>
 

+ 20 - 14
client/components/share/Window.vue

@@ -2,11 +2,17 @@
     <div ref="main" class="main xyfit absolute" @click="close" @mouseup="onMouseUp" @mousemove="onMouseMove">
         <div ref="windowBox" class="xyfit absolute flex no-wrap" @click.stop>
             <div ref="window" class="window flexfit column no-wrap">
-                <div ref="header" class="header row justify-end" @mousedown.prevent.stop="onMouseDown"
-                    @touchstart.stop="onTouchStart" @touchend.stop="onTouchEnd" @touchmove.stop="onTouchMove">
+                <div 
+                    ref="header"
+                    class="header row justify-end"
+                    @mousedown.prevent.stop="onMouseDown"
+                    @touchstart.stop="onTouchStart"
+                    @touchend.stop="onTouchEnd"
+                    @touchmove.stop="onTouchMove"
+                >
                     <span class="header-text col"><slot name="header"></slot></span>
                     <slot name="buttons"></slot>
-                    <span class="close-button row justify-center items-center" @mousedown.stop @click="close"><q-icon name="la la-times" size="16px"/></span>
+                    <span class="close-button row justify-center items-center" @mousedown.stop @click="close"><q-icon name="la la-times" size="16px" /></span>
                 </div>
 
                 <slot></slot>
@@ -17,19 +23,17 @@
 
 <script>
 //-----------------------------------------------------------------------------
-import Vue from 'vue';
-import Component from 'vue-class-component';
+import vueComponent from '../vueComponent.js';
 
-export default @Component({
-    props: {
+class Window {
+    _props = {
         height: { type: String, default: '100%' },
         width: { type: String, default: '100%' },
         maxWidth: { type: String, default: '' },
         topShift: { type: Number, default: 0 },
         margin: '',
-    }
-})
-class Window extends Vue {
+    };
+
     init() {
         this.$nextTick(() => {
             this.$refs.main.style.top = 0;
@@ -51,7 +55,7 @@ class Window extends Vue {
     }
 
     onMouseDown(event) {
-        if (this.$isMobileDevice)
+        if (this.$root.isMobileDevice)
             return;
         if (event.button == 0) {
             this.$refs.header.style.cursor = 'move';
@@ -81,7 +85,7 @@ class Window extends Vue {
     }
 
     onTouchStart(event) {
-        if (!this.$isMobileDevice)
+        if (!this.$root.isMobileDevice)
             return;
         if (event.touches.length == 1) {
             const touch = event.touches[0];
@@ -93,7 +97,7 @@ class Window extends Vue {
     }
 
     onTouchMove(event) {
-        if (!this.$isMobileDevice)
+        if (!this.$root.isMobileDevice)
             return;
         if (event.touches.length == 1 && this.moving) {
             const touch = event.touches[0];
@@ -108,7 +112,7 @@ class Window extends Vue {
     }
 
     onTouchEnd() {
-        if (!this.$isMobileDevice)
+        if (!this.$root.isMobileDevice)
             return;
         this.$refs.header.style.cursor = 'default';
         this.moving = false;
@@ -120,6 +124,8 @@ class Window extends Vue {
             this.$emit('close');
     }
 }
+
+export default vueComponent(Window);
 //-----------------------------------------------------------------------------
 </script>
 

+ 1 - 1
client/components/vueComponent.js

@@ -10,7 +10,7 @@ export default function(componentClass) {
         if (['_options', '_props'].includes(prop)) {//meta props
             if (prop === '_options') {
                 const options = obj[prop];
-                for (const optName of ['components', 'watch']) {
+                for (const optName of ['components', 'watch', 'emits']) {
                     if (options[optName]) {
                         comp[optName] = options[optName];
                     }

+ 0 - 4
client/main.js

@@ -3,16 +3,12 @@ import { createApp } from 'vue';
 import router from './router';
 import store from './store';
 import {Quasar, QuasarOptions} from './quasar';
-//import vueSanitize from 'vue-sanitize';
 
 import App from './components/App.vue';
 
-//Vue.prototype.$isMobileDevice = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);
-
 const app = createApp(App);
 app.use(router);
 app.use(store);
 app.use(Quasar, QuasarOptions);
-//app.use(vueSanitize);
 
 app.mount('#app');

+ 1 - 1
client/router.js

@@ -9,7 +9,7 @@ const History = () => import('./components/CardIndex/History/History.vue');
 
 //немедленная загрузка
 //import Reader from './components/Reader/Reader.vue';
-const Reader = () => import('./components/Reader/Reader1.vue');
+const Reader = () => import('./components/Reader/Reader.vue');
 //const ExternalLibs = () => import('./components/ExternalLibs/ExternalLibs.vue');
 
 const Income = () => import('./components/Income/Income.vue');