Эх сурвалжийг харах

Добавлена возможность двигать окна, небольшое облагораживание отображения

Book Pauk 5 жил өмнө
parent
commit
682a044f32

+ 8 - 29
client/components/Reader/CopyTextPage/CopyTextPage.vue

@@ -1,17 +1,13 @@
 <template>
-    <div ref="main" class="main" @click="close">
-        <div class="mainWindow" @click.stop>
-            <Window @close="close">
-                <template slot="header">
-                    Скопировать текст
-                </template>
-
-                <div ref="text" class="text" tabindex="-1">
-                    <div v-html="text"></div>
-                </div>
-            </Window>
+    <Window @close="close">
+        <template slot="header">
+            Скопировать текст
+        </template>
+
+        <div ref="text" class="text" tabindex="-1">
+            <div v-html="text"></div>
         </div>
-    </div>
+    </Window>
 </template>
 
 <script>
@@ -109,23 +105,6 @@ class CopyTextPage extends Vue {
 </script>
 
 <style scoped>
-.main {
-    position: absolute;
-    width: 100%;
-    height: 100%;
-    z-index: 40;
-    display: flex;
-    flex-direction: column;
-    justify-content: center;
-    align-items: center;
-}
-
-.mainWindow {
-    width: 100%;
-    height: 100%;
-    display: flex;
-}
-
 .text {
     flex: 1;
     overflow-wrap: anywhere;

+ 92 - 109
client/components/Reader/RecentBooksPage/RecentBooksPage.vue

@@ -1,101 +1,97 @@
 <template>
-    <div ref="main" class="main" @click="close">
-        <div class="mainWindow" @click.stop>
-            <Window @close="close">
-                <template slot="header">
-                    <span v-show="!loading">Последние {{tableData ? tableData.length : 0}} открытых книг</span>
-                    <span v-show="loading"><i class="el-icon-loading" style="font-size: 30px"></i> <span style="position: relative; top: -5px">Список загружается</span></span>
+    <Window width="600px" ref="window" @close="close">
+        <template slot="header">
+            <span v-show="!loading">Последние {{tableData ? tableData.length : 0}} открытых книг</span>
+            <span v-show="loading"><i class="el-icon-loading" style="font-size: 25px"></i> <span style="position: relative; top: -4px">Список загружается</span></span>
+        </template>
+
+        <el-table
+            :data="tableData"
+            style="width: 100%"
+            size="mini"
+            height="1px"
+            stripe
+            border
+            :default-sort = "{prop: 'touchDateTime', order: 'descending'}"
+            :header-cell-style = "headerCellStyle"
+            :row-key = "rowKey"
+            >
+
+            <el-table-column
+                type="index"
+                width="35px"
+                >
+            </el-table-column>
+            <el-table-column
+                prop="touchDateTime"
+                min-width="90px"
+                sortable
+                >
+                <template slot="header" slot-scope="scope"><!-- eslint-disable-line vue/no-unused-vars -->
+                    <span style="font-size: 90%">Время<br>просм.</span>
+                </template>
+                <template slot-scope="scope"><!-- eslint-disable-line vue/no-unused-vars -->
+                    <div class="desc" @click="loadBook(scope.row.url)">
+                        {{ scope.row.touchDate }}<br>
+                        {{ scope.row.touchTime }}
+                    </div>
+                </template>
+            </el-table-column>
+
+            <el-table-column
+                >
+                <template slot="header" slot-scope="scope"><!-- eslint-disable-line vue/no-unused-vars -->
+                    <!--el-input ref="input"
+                        :value="search" @input="search = $event"
+                        size="mini"
+                        style="margin: 0; padding: 0; vertical-align: bottom; margin-top: 10px"
+                        placeholder="Найти"/-->
+                        <div class="el-input el-input--mini">
+                            <input class="el-input__inner"
+                                ref="input"
+                                placeholder="Найти"
+                                style="margin: 0; vertical-align: bottom; margin-top: 20px; padding: 0 10px 0 10px"
+                                :value="search" @input="search = $event.target.value"
+                            />
+                        </div>
                 </template>
 
-                <el-table
-                    :data="tableData"
-                    style="width: 100%"
-                    size="mini"
-                    height="1px"
-                    stripe
-                    border
-                    :default-sort = "{prop: 'touchDateTime', order: 'descending'}"
-                    :header-cell-style = "headerCellStyle"
-                    :row-key = "rowKey"
+                <el-table-column
+                    min-width="300px"
                     >
-
-                    <el-table-column
-                        type="index"
-                        width="35px"
-                        >
-                    </el-table-column>
-                    <el-table-column
-                        prop="touchDateTime"
-                        min-width="90px"
-                        sortable
-                        >
-                        <template slot="header" slot-scope="scope"><!-- eslint-disable-line vue/no-unused-vars -->
-                            <span style="font-size: 90%">Время<br>просм.</span>
-                        </template>
-                        <template slot-scope="scope"><!-- eslint-disable-line vue/no-unused-vars -->
-                            <div class="desc" @click="loadBook(scope.row.url)">
-                                {{ scope.row.touchDate }}<br>
-                                {{ scope.row.touchTime }}
-                            </div>
-                        </template>
-                    </el-table-column>
-
-                    <el-table-column
-                        >
-                        <template slot="header" slot-scope="scope"><!-- eslint-disable-line vue/no-unused-vars -->
-                            <!--el-input ref="input"
-                                :value="search" @input="search = $event"
-                                size="mini"
-                                style="margin: 0; padding: 0; vertical-align: bottom; margin-top: 10px"
-                                placeholder="Найти"/-->
-                                <div class="el-input el-input--mini">
-                                    <input class="el-input__inner"
-                                        ref="input"
-                                        placeholder="Найти"
-                                        style="margin: 0; padding: 0; vertical-align: bottom; margin-top: 20px; padding: 0 10px 0 10px"
-                                        :value="search" @input="search = $event.target.value"
-                                    />
-                                </div>
-                        </template>
-
-                        <el-table-column
-                            min-width="300px"
-                            >
-                            <template slot-scope="scope">
-                                <div class="desc" @click="loadBook(scope.row.url)">
-                                    <span style="color: green">{{ scope.row.desc.author }}</span><br>
-                                    <span>{{ scope.row.desc.title }}</span>
-                                </div>
-                            </template>
-                        </el-table-column>
-
-                        <el-table-column
-                            min-width="100px"
-                            >
-                            <template slot-scope="scope">
-                                <a v-show="isUrl(scope.row.url)" :href="scope.row.url" target="_blank">Оригинал</a><br>
-                                <a :href="scope.row.path" :download="getFileNameFromPath(scope.row.path)">Скачать FB2</a>
-                            </template>
-                        </el-table-column>
-
-                        <el-table-column
-                            width="60px"
-                            >
-                            <template slot-scope="scope">
-                                <el-button
-                                    size="mini"
-                                    style="width: 30px; padding: 7px 0 7px 0; margin-left: 4px"
-                                    @click="handleDel(scope.row.key)"><i class="el-icon-close"></i>
-                                </el-button>
-                            </template>
-                        </el-table-column>
-
-                    </el-table-column>
-
-                </el-table>
-            </Window>
-        </div>
-    </div>
+                    <template slot-scope="scope">
+                        <div class="desc" @click="loadBook(scope.row.url)">
+                            <span style="color: green">{{ scope.row.desc.author }}</span><br>
+                            <span>{{ scope.row.desc.title }}</span>
+                        </div>
+                    </template>
+                </el-table-column>
+
+                <el-table-column
+                    min-width="100px"
+                    >
+                    <template slot-scope="scope">
+                        <a v-show="isUrl(scope.row.url)" :href="scope.row.url" target="_blank">Оригинал</a><br>
+                        <a :href="scope.row.path" :download="getFileNameFromPath(scope.row.path)">Скачать FB2</a>
+                    </template>
+                </el-table-column>
+
+                <el-table-column
+                    width="60px"
+                    >
+                    <template slot-scope="scope">
+                        <el-button
+                            size="mini"
+                            style="width: 30px; padding: 7px 0 7px 0; margin-left: 4px"
+                            @click="handleDel(scope.row.key)"><i class="el-icon-close"></i>
+                        </el-button>
+                    </template>
+                </el-table-column>
+
+            </el-table-column>
+
+        </el-table>
+    </Window>
 </template>
 
 <script>
@@ -128,6 +124,8 @@ class RecentBooksPage extends Vue {
     }
 
     init() {
+        this.$refs.window.init();
+
         this.$nextTick(() => {
             //this.$refs.input.focus();
         });
@@ -315,21 +313,6 @@ class RecentBooksPage extends Vue {
 </script>
 
 <style scoped>
-.main {
-    position: absolute;
-    width: 100%;
-    height: 100%;
-    z-index: 50;
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-}
-
-.mainWindow {
-    height: 100%;
-    display: flex;
-}
-
 .desc {
     cursor: pointer;
 }

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

@@ -870,7 +870,6 @@ class SettingsPage extends Vue {
 .mainWindow {
     height: 70%;
     display: flex;
-    position: relative;
 }
 
 .text {

+ 6 - 7
client/components/Reader/TextPage/TextPage.vue

@@ -131,7 +131,6 @@ class TextPage extends Vue {
         }, 10);
 
         this.$root.$on('resize', () => {this.$nextTick(this.onResize)});
-        this.mobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);
     }
 
     mounted() {
@@ -1007,7 +1006,7 @@ class TextPage extends Vue {
     }
 
     onTouchStart(event) {
-        if (!this.mobile)
+        if (!this.$isMobileDevice)
             return;
         this.endClickRepeat();
         if (event.touches.length == 1) {
@@ -1023,19 +1022,19 @@ class TextPage extends Vue {
     }
 
     onTouchEnd() {
-        if (!this.mobile)
+        if (!this.$isMobileDevice)
             return;
         this.endClickRepeat();
     }
 
     onTouchCancel() {
-        if (!this.mobile)
+        if (!this.$isMobileDevice)
             return;
         this.endClickRepeat();
     }
 
     onMouseDown(event) {
-        if (this.mobile)
+        if (this.$isMobileDevice)
             return;
         this.endClickRepeat();
         if (event.button == 0) {
@@ -1051,13 +1050,13 @@ class TextPage extends Vue {
     }
 
     onMouseUp() {
-        if (this.mobile)
+        if (this.$isMobileDevice)
             return;
         this.endClickRepeat();
     }
 
     onMouseWheel(event) {
-        if (this.mobile)
+        if (this.$isMobileDevice)
             return;
         if (event.deltaY > 0) {
             this.doDown();

+ 115 - 11
client/components/share/Window.vue

@@ -1,10 +1,15 @@
 <template>
-    <div class="window">
-        <div class="header">
-            <span class="header-text"><slot name="header"></slot></span>
-            <span class="close-button" @click="close"><i class="el-icon-close"></i></span>
+    <div ref="main" class="main" @click="close" @mouseup.prevent.stop="onMouseUp" @mousemove.prevent.stop="onMouseMove">
+        <div ref="windowBox" class="windowBox" @click.stop>
+            <div class="window">
+                <div ref="header" class="header" @mousedown.prevent.stop="onMouseDown"
+                    @touchstart.stop="onTouchStart" @touchend.stop="onTouchEnd" @touchmove.stop="onTouchMove">
+                    <span class="header-text"><slot name="header"></slot></span>
+                    <span class="close-button" @mousedown.stop @click="close"><i class="el-icon-close"></i></span>
+                </div>
+                <slot></slot>
+            </div>
         </div>
-        <slot></slot>
     </div>
 </template>
 
@@ -14,17 +19,112 @@ import Vue from 'vue';
 import Component from 'vue-class-component';
 
 export default @Component({
+    props: {
+        height: { type: String, default: '100%' },
+        width: { type: String, default: '100%' },
+    }
 })
 class Window extends Vue {
-    close() {
-        this.$emit('close');
+    init() {
+        this.$nextTick(() => {
+            this.$refs.windowBox.style.height = this.height;
+            this.$refs.windowBox.style.width = this.width;
+
+            const left = (this.$refs.main.offsetWidth - this.$refs.windowBox.offsetWidth)/2;
+            const top = (this.$refs.main.offsetHeight - this.$refs.windowBox.offsetHeight)/2;
+            this.$refs.windowBox.style.left = (left > 0 ? left : 0) + 'px';
+            this.$refs.windowBox.style.top = (top > 0 ? top : 0) + 'px';
+        });
+    }
+
+    onMouseDown(event) {
+        if (this.$isMobileDevice)
+            return;
+        if (event.button == 0) {
+            this.$refs.header.style.cursor = 'move';
+            this.startX = event.screenX;
+            this.startY = event.screenY;
+            this.moving = true;
+        }
+    }
+
+    onMouseUp(event) {
+        if (event.button == 0) {
+            this.$refs.header.style.cursor = 'default';
+            this.moving = false;
+        }
     }
 
+    onMouseMove(event) {
+        if (this.moving) {
+            const deltaX = event.screenX - this.startX;
+            const deltaY = event.screenY - this.startY;
+            this.startX = event.screenX;
+            this.startY = event.screenY;
+
+            this.$refs.windowBox.style.left = (this.$refs.windowBox.offsetLeft + deltaX) + 'px';
+            this.$refs.windowBox.style.top = (this.$refs.windowBox.offsetTop + deltaY) + 'px';
+        }
+    }
+
+    onTouchStart(event) {
+        if (!this.$isMobileDevice)
+            return;
+        if (event.touches.length == 1) {
+            const touch = event.touches[0];
+            this.$refs.header.style.cursor = 'move';
+            this.startX = touch.screenX;
+            this.startY = touch.screenY;
+            this.moving = true;
+        }
+    }
+
+    onTouchMove(event) {
+        if (!this.$isMobileDevice)
+            return;
+        if (event.touches.length == 1 && this.moving) {
+            const touch = event.touches[0];
+            const deltaX = touch.screenX - this.startX;
+            const deltaY = touch.screenY - this.startY;
+            this.startX = touch.screenX;
+            this.startY = touch.screenY;
+
+            this.$refs.windowBox.style.left = (this.$refs.windowBox.offsetLeft + deltaX) + 'px';
+            this.$refs.windowBox.style.top = (this.$refs.windowBox.offsetTop + deltaY) + 'px';
+        }
+    }
+
+    onTouchEnd() {
+        if (!this.$isMobileDevice)
+            return;
+        this.$refs.header.style.cursor = 'default';
+        this.moving = false;
+    }
+
+
+    close() {
+        if (!this.moving)
+            this.$emit('close');
+    }
 }
 //-----------------------------------------------------------------------------
 </script>
 
 <style scoped>
+.main {
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    z-index: 50;
+}
+
+.windowBox {
+    position: absolute;
+    display: flex;
+    height: 100%;
+    width: 100%;
+}
+
 .window {
     flex: 1;
     display: flex;
@@ -39,9 +139,9 @@ class Window extends Vue {
 .header {
     display: flex;
     justify-content: flex-end;
-    background-color: #e5e7ea;
+    background-color: #59B04F;
     align-items: center;
-    height: 40px;
+    height: 30px;
 }
 
 .header-text {
@@ -54,8 +154,12 @@ class Window extends Vue {
     display: flex;
     justify-content: center;
     align-items: center;
-    width: 40px;
-    height: 40px;
+    width: 30px;
+    height: 30px;
     cursor: pointer;
 }
+
+.close-button:hover {
+    background-color: #69C05F;
+}
 </style>

+ 1 - 0
client/main.js

@@ -6,6 +6,7 @@ import './element';
 
 import App from './components/App.vue';
 //Vue.config.productionTip = false;
+Vue.prototype.$isMobileDevice = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);
 
 new Vue({
     router,