Commit 3d41282d authored by Duhoux Pierre-Louis's avatar Duhoux Pierre-Louis

Search function coded, need to be improved more

parent 8a1b9024
......@@ -554,6 +554,9 @@
"content_read_reload": {
"message": "Try to reload",
"description": "Message displayed on a scan if it failed to be loaded so the user can try to force its reload"
},
"search_button": {
"message": "Search",
"description": "Button label in search panel"
}
}
\ No newline at end of file
......@@ -4,12 +4,13 @@ import browser from "webextension-polyfill";
import mirrorsImpl from '../amr/mirrors-impl';
import store from '../store';
import * as utils from '../amr/utils';
import storedb from '../amr/storedb';
/** Scripts to inject in pages containing mangas */
const contentScripts = [
'lib/jquery.min.js',
'lib/jquery.scrollTo.min.js',
'lib/jquery.modal.min.js',
'lib/jquery.min.js',
'lib/jquery.scrollTo.min.js',
'lib/jquery.modal.min.js',
'content/back.js'
];
/** CSS to inject in pages containing mangas */
......@@ -37,7 +38,7 @@ class HandleManga {
utils.debug("Read manga " + message.url);
return store.dispatch('readManga', message);
case "getNextChapterImages": //returns list of images for prefetch of next chapter in content script
return this.getChapterImages(message);
return this.getChapterImages(message);
case "markReadTop":
return store.dispatch('markMangaReadTop', message);
case "setDisplayMode":
......@@ -50,9 +51,77 @@ class HandleManga {
case "updateChaptersLists":
// updates all mangas lists (do it in background if called from popup because it requires jQuery)
return store.dispatch("updateChaptersLists");
case "searchList":
return this.searchList(message);
}
}
/**
* Search mangas on a mirror from search phrase
* @param {*} message
*/
async searchList(message) {
return new Promise(async (resolve, reject) => {
let impl = await mirrorsImpl.getImpl(message.mirror);
// check if mirror can list all mangas
if (impl.canListFullMangas) {
// check if mirror list is in local db and filter
let list = storedb.getListOfMangaForMirror(message.mirror)
if (list && list.length > 0) {
// filter entries on search phrase
resolve(this.resultSearchFromArray(
this.filterSearchList(list, message.search),
message.mirror));
} else {
// retrieve from website
let mgs = await this.searchListRemote(message.search, impl);
// store result
storedb.storeListOfMangaForMirror(message.mirror, mgs);
// return filtered results
resolve(this.resultSearchFromArray(
this.filterSearchList(mgs, message.search),
message.mirror));
}
} else {
// let website search
resolve(this.resultSearchFromArray(
await this.searchListRemote(message.search, impl),
message.mirror));
}
});
}
/**
* Convert array of array (standard result from implementation) in proper result
* @param {*} list
* @param {*} mirror
*/
resultSearchFromArray(list, mirror) {
return list.map(arr => {
return {
url: arr[1],
name: arr[0],
mirror: mirror
}
})
}
/**
* Return entries matching the search phrase from a list of results
* @param {*} list
* @param {*} search
*/
filterSearchList(list, search) {
return list.filter(arr => utils.formatMgName(arr[0]).indexOf(utils.formatMgName(search)) !== -1);
}
/**
* Call search function from remote website
*/
async searchListRemote(search, impl) {
return new Promise(async (resolve, reject) => {
impl.getMangaList(search, function (mirrorName, res) {
resolve(res);
});
});
}
/**
* Test if the url matches a mirror implementation.
* If so, inject content script to transform the page and the mirror implementation inside the tab
......
......@@ -43,6 +43,7 @@
</div>
</template>
<script>
import i18n from "../../amr/i18n";
import * as utils from "../utils";
export default {
......@@ -62,6 +63,7 @@ export default {
"delegate-delete"
],
methods: {
i18n: (message, ...args) => i18n(message, ...args),
switchState(cat) {
let nstate = "";
if (cat.state === "include") nstate = "exclude";
......
......@@ -106,8 +106,8 @@
</v-card-title>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" flat @click.native="deleteManga = false">{{i18("button_no")}}</v-btn>
<v-btn color="blue darken-1" flat @click.native="trash()">{{i18("button_yes")}}</v-btn>
<v-btn color="blue darken-1" flat @click.native="deleteManga = false">{{i18n("button_no")}}</v-btn>
<v-btn color="blue darken-1" flat @click.native="trash()">{{i18n("button_yes")}}</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
......@@ -115,6 +115,7 @@
</template>
<script>
import i18n from "../../amr/i18n";
import { mapGetters } from "vuex";
import browser from "webextension-polyfill";
import * as utils from "../utils";
......@@ -189,6 +190,7 @@ export default {
}
},
methods: {
i18n: (message, ...args) => i18n(message, ...args),
/**
* Return the right color for this manga, depending if it updates (you can stop following udates for a manga), if it has unread chapters or not
*/
......
......@@ -63,6 +63,7 @@
</template>
<script>
import i18n from "../../amr/i18n";
import { mapGetters } from "vuex";
import browser from "webextension-polyfill";
import Manga from "./Manga";
......@@ -119,6 +120,7 @@ export default {
}
},
methods: {
i18n: (message, ...args) => i18n(message, ...args),
/**
* Return the right color for this manga, depending if it updates (you can stop following udates for a manga), if it has unread chapters or not
*/
......
......@@ -41,6 +41,7 @@
</div>
</template>
<script>
import i18n from "../../amr/i18n";
import { mapGetters } from "vuex";
import MangaGroup from "./MangaGroup";
import Categories from "./Categories";
......@@ -88,6 +89,7 @@ export default {
name: "MangaList",
components: { MangaGroup, Categories },
methods: {
i18n: (message, ...args) => i18n(message, ...args),
importSamples() {
// we don't do this.$store.dispatch("importSamples"); because to load list of chapters, implementations rely on jQuery, which is not loaded in pages, rely on background page to do so
browser.runtime.sendMessage({ action: "importSamples" });
......
<template>
<v-container fluid>
<v-layout row>
<div class="mirrors-cont">
<SearchMirror v-for="ws in activatedWebsites" :key="ws.mirrorName" :mirror="ws" :search-phrase="search" @add-mangas="addMangas" />
</div>
</v-layout>
<v-layout row>
<v-flex xs4 offset-xs2>
<v-text-field v-model="searchwrite" @keyup.enter="search = searchwrite" />
</v-flex>
<v-flex xs4>
<v-btn color="primary" @click="search = searchwrite" small>{{i18n("search_button")}}</v-btn>
</v-flex>
</v-layout>
<v-layout row>
<v-container fluid>
<v-layout row v-for="res in results" :key="res.url">
{{res.name}} ({{res.mirror}})
</v-layout>
</v-container>
</v-layout>
</v-container>
</template>
<script>
import i18n from "../../amr/i18n";
import SearchMirror from "./SearchMirror";
export default {
data() {
return {
searchwrite: "",
search: "",
results: []
};
},
computed: {
activatedWebsites() {
return this.$store.state.mirrors.all
.filter(mir => mir.activated)
}
},
methods: {
i18n: (message, ...args) => i18n(message, ...args),
addMangas(mgs) {
this.results.push(...mgs);
}
},
name: "Search",
components: { SearchMirror }
}
</script>
<style>
.mirrors-cont {
margin: auto;
}
</style>
<template>
<div class="mirror-search">
<v-progress-circular v-if="searching" indeterminate :width="3" color="primary" class="mirror-progress"></v-progress-circular>
<img :src="mirror.mirrorIcon" :class="'mirror-search-icon ' + (disabled ? 'disabled': '')" @click.stop="disabled = !disabled" />
</div>
</template>
<script>
import browser from "webextension-polyfill";
import i18n from "../../amr/i18n";
export default {
data() {
return {
searching: false, // currently searching
disabled: false // is disabled in search
};
},
props: [
"mirror", // the mirror to search on
"search-phrase", // phrase to search
],
methods: {
i18n: (message, ...args) => i18n(message, ...args),
async search() {
this.searching = true;
let mgs = await browser.runtime.sendMessage({
action: "searchList",
mirror: this.mirror.mirrorName,
search: this.searchPhrase
});
this.$emit("add-mangas", mgs);
this.searching = false;
}
},
watch: {
"searchPhrase": function() {
this.search();
}
},
name: "SearchMirror",
}
</script>
<style>
.mirror-search {
display : inline-block;
margin: 5px;
position:relative;
width: 32px;
height: 32px;
}
.mirror-progress {
position: absolute;
left: 0;
top: 0;
}
.mirror-search-icon {
position: absolute;
top: 8px;
left: 8px;
cursor: pointer;
}
.mirror-search-icon.disabled {
opacity: 0.3;
}
</style>
......@@ -7,7 +7,7 @@
<v-btn icon @click.stop="openOptions()">
<v-icon>mdi-settings</v-icon>
</v-btn>
<v-btn icon @click.stop="bottomSearch = !bottomSearch">
<v-btn icon @click.stop="openSearch()">
<v-icon>mdi-magnify</v-icon>
</v-btn>
<v-menu bottom left>
......@@ -51,25 +51,43 @@
<Options />
</v-card>
</v-dialog>
<v-dialog
v-model="search"
fullscreen
transition="dialog-bottom-transition"
:overlay="false"
scrollable
>
<v-card tile>
<v-toolbar card dark color="primary">
<v-btn icon @click.native="closeSearch()" dark>
<v-icon>close</v-icon>
</v-btn>
<v-toolbar-title>{{i18n("search_title")}}</v-toolbar-title>
</v-toolbar>
<Search />
</v-card>
</v-dialog>
</v-app>
</template>
<script>
import i18n from "../../amr/i18n";
import MangaList from "../components/MangaList";
import Options from "../components/Options";
import Search from "../components/Search";
import PopupResizer from './resizePopup';
export default {
data() {
return {
bottomSearch: false,
bottomOptions: false,
title: "All Mangas Reader",
options: false
options: false,
search: false,
};
},
name: "App",
components: { MangaList, Options },
components: { MangaList, Options, Search },
created() {
// initialize state for store in popup from background
this.$store.dispatch("getStateFromReference", {
......@@ -79,6 +97,7 @@ export default {
});
},
methods: {
i18n: (message, ...args) => i18n(message, ...args),
openOptions() {
this.options = true;
PopupResizer.setHeightToMax();
......@@ -86,6 +105,14 @@ export default {
closeOptions() {
this.options = false;
PopupResizer.setHeightToCurrent();
},
openSearch() {
this.search = true;
PopupResizer.setHeightToMax();
},
closeSearch() {
this.search = false;
PopupResizer.setHeightToCurrent();
}
},
mounted: function () {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment