Ver código fonte

Начало работы над ContentsPage

Book Pauk 4 anos atrás
pai
commit
e095c3318b

+ 48 - 0
client/components/Reader/ContentsPage/ContentsPage.vue

@@ -0,0 +1,48 @@
+<template>
+    <Window width="600px" ref="window" @close="close">
+        <template slot="header">
+        </template>
+
+    </Window>
+</template>
+
+<script>
+//-----------------------------------------------------------------------------
+import Vue from 'vue';
+import Component from 'vue-class-component';
+//import _ from 'lodash';
+
+import Window from '../../share/Window.vue';
+//import * as utils from '../../../share/utils';
+
+export default @Component({
+    components: {
+        Window,
+    },
+    watch: {
+    },
+})
+class ContentsPage extends Vue {
+    created() {
+    }
+
+    init() {
+        this.$refs.window.init();
+    }
+
+    close() {
+        this.$emit('do-action', {action: 'contents'});
+    }
+
+    keyHook(event) {
+        if (!this.$root.stdDialog.active && event.type == 'keydown' && event.key == 'Escape') {
+            this.close();
+        }
+        return true;
+    }
+}
+//-----------------------------------------------------------------------------
+</script>
+
+<style scoped>
+</style>

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

@@ -48,6 +48,10 @@
                         <q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%">{{ rstore.readerActions['refresh'] }}</q-tooltip>
                     </button>
                     <div class="space"></div>
+                    <button ref="contents" v-show="showToolButton['contents']" class="tool-button" :class="buttonActiveClass('contents')" @click="buttonClick('contents')" v-ripple>
+                        <q-icon name="la la-list" size="32px"/>
+                        <q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%">{{ rstore.readerActions['contents'] }}</q-tooltip>
+                    </button>
                     <button ref="libs" v-show="mode == 'liberama.top' && showToolButton['libs']" class="tool-button" :class="buttonActiveClass('libs')" @click="buttonClick('libs')" v-ripple>
                         <q-icon name="la la-sitemap" size="32px"/>
                         <q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%">{{ rstore.readerActions['libs'] }}</q-tooltip>
@@ -89,12 +93,13 @@
                 @stop-text-search="stopTextSearch">
             </SearchPage>
             <CopyTextPage v-if="copyTextActive" ref="copyTextPage" @do-action="doAction"></CopyTextPage>
-            <LibsPage v-show="libsActive" ref="libsPage" @load-book="loadBook" @libs-close="libsClose" @do-action="doAction"></LibsPage>
+            <LibsPage v-show="hidden" ref="libsPage" @load-book="loadBook" @libs-close="libsClose" @do-action="doAction"></LibsPage>
             <RecentBooksPage v-show="recentBooksActive" ref="recentBooksPage" @load-book="loadBook" @recent-books-close="recentBooksClose"></RecentBooksPage>
             <SettingsPage v-show="settingsActive" ref="settingsPage" @do-action="doAction"></SettingsPage>
             <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="contentsPageActive" ref="contentsPage" @do-action="doAction"></ContentsPage>
 
             <ReaderDialogs ref="dialogs" @donate-toggle="donateToggle" @version-history-toggle="versionHistoryToggle"></ReaderDialogs>
         </div>
@@ -121,6 +126,8 @@ 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 ReaderDialogs from './ReaderDialogs/ReaderDialogs.vue';
 
 import bookManager from './share/bookManager';
@@ -143,6 +150,8 @@ export default @Component({
         HelpPage,
         ClickMapPage,
         ServerStorage,
+        ContentsPage,
+
         ReaderDialogs,
     },
     watch: {
@@ -200,6 +209,7 @@ class Reader extends Vue {
     settingsActive = false;
     helpActive = false;
     clickMapActive = false;
+    contentsPageActive = false;
 
     bookPos = null;
     allowUrlParamBookPos = false;
@@ -490,6 +500,7 @@ class Reader extends Vue {
         this.stopScrolling();
         this.stopSearch();
         this.helpActive = false;
+        this.contentsPageActive = false;
     }
 
     loaderToggle() {
@@ -603,6 +614,17 @@ class Reader extends Vue {
         }
     }
 
+    contentsPageToggle() {
+        this.contentsPageActive = !this.contentsPageActive;
+        if (this.contentsPageActive) {
+            this.closeAllWindows();
+            this.$refs.contentsPage.init();
+            this.contentsPageActive = true;
+        } else {
+            this.contentsPageActive = false;
+        }
+    }
+
     libsClose() {
         if (this.libsActive)
             this.libsToogle();
@@ -707,6 +729,7 @@ class Reader extends Vue {
             case 'copyText':
             case 'splitToPara':
             case 'refresh':
+            case 'contents':
             case 'libs':
             case 'recentBooks':
             case 'offlineMode':
@@ -735,6 +758,7 @@ class Reader extends Vue {
                 case 'scrolling':
                 case 'search':
                 case 'copyText':
+                case 'contents':
                     classResult = classDisabled;
                     break;
                 case 'splitToPara':
@@ -1026,6 +1050,9 @@ class Reader extends Vue {
             case 'refresh':
                 this.refreshBook();
                 break;
+            case 'contents':
+                this.contentsPageToggle();
+                break;
             case 'libs':
                 this.libsToogle();
                 break;
@@ -1125,6 +1152,9 @@ class Reader extends Vue {
             if (!result && this.copyTextActive)
                 result = this.$refs.copyTextPage.keyHook(event);
 
+            if (!result && this.contentsPageActive)
+                result = this.$refs.contentsPage.keyHook(event);
+
             if (!result && this.$refs.page && this.$refs.page.keyHook)
                 result = this.$refs.page.keyHook(event);
 

+ 18 - 0
client/components/Reader/share/BookParser.js

@@ -46,11 +46,17 @@ export default class BookParser {
         let isFirstSection = true;
         let isFirstTitlePara = false;
 
+        //изображения
         this.binary = {};
         let binaryId = '';
         let binaryType = '';
         let dimPromises = [];
 
+        //оглавление
+        this.contents = [];//[{paraIndex: <number>, subtitles: [{paraIndex: <number>}, ... ]}, ... ]
+        let curTitle = {paraIndex: -1, subtitles: []};
+        let curSubtitle = {paraIndex: -1};
+
         let paraIndex = -1;
         let paraOffset = 0;
         let para = []; /*array of
@@ -129,6 +135,7 @@ export default class BookParser {
                 return;
             }
 
+            const prevParaIndex = paraIndex;
             let p = para[paraIndex];
             paraOffset -= p.length;
             //добавление пустых (addEmptyParagraphs) параграфов перед текущим
@@ -143,6 +150,11 @@ export default class BookParser {
                 p.offset = paraOffset;
                 para[paraIndex] = p;
 
+                if (curTitle.paraIndex == prevParaIndex)
+                    curTitle.paraIndex = paraIndex;
+                if (curSubtitle.paraIndex == prevParaIndex)
+                    curSubtitle.paraIndex = paraIndex;
+
                 //уберем начальный пробел
                 p.length = 0;
                 p.text = p.text.substr(1);
@@ -205,6 +217,9 @@ export default class BookParser {
                     isFirstTitlePara = true;
                     bold = true;
                     center = true;
+
+                    curTitle = {paraIndex, subtitles: []};
+                    this.contents.push(curTitle);
                 }
 
                 if (tag == 'section') {
@@ -231,6 +246,9 @@ export default class BookParser {
                     isFirstTitlePara = true;
                     bold = true;
                     center = true;
+
+                    curSubtitle = {paraIndex};
+                    curTitle.subtitles.push(curSubtitle);
                 }
 
                 if (tag == 'epigraph') {

+ 4 - 1
client/store/modules/reader.js

@@ -15,6 +15,7 @@ const readerActions = {
     'splitToPara': 'Обновить с разбиением на параграфы',
     'refresh': 'Принудительно обновить книгу',
     'offlineMode': 'Автономный режим (без интернета)',
+    'contents': 'Оглавление/закладки',
     'libs': 'Библиотека',
     'recentBooks': 'Открыть недавние',
     'switchToolbar': 'Показать/скрыть панель управления',
@@ -42,6 +43,7 @@ const toolButtons = [
     {name: 'copyText',    show: false},
     {name: 'splitToPara', show: false},
     {name: 'refresh',     show: true},
+    {name: 'contents',    show: true},
     {name: 'libs',        show: true},
     {name: 'recentBooks', show: true},
     {name: 'offlineMode', show: false},
@@ -61,9 +63,10 @@ const hotKeys = [
     {name: 'copyText', codes: ['Ctrl+C']},
     {name: 'splitToPara', codes: ['Shift+R']},
     {name: 'refresh', codes: ['R']},
-    {name: 'offlineMode', codes: ['O']},
+    {name: 'contents', codes: ['C']},
     {name: 'libs', codes: ['L']},
     {name: 'recentBooks', codes: ['X']},
+    {name: 'offlineMode', codes: ['O']},
 
     {name: 'switchToolbar', codes: ['Tab', 'Q']},
     {name: 'bookBegin', codes: ['Home']},