Commit 193d7314 authored by Duhoux Pierre-Louis's avatar Duhoux Pierre-Louis

Finish bookmarks page

parent 3da70449
......@@ -758,6 +758,84 @@
"ie_import_defaultcat": {
"message": "Default category to add to imported mangas",
"description": "Placeholder for the input field in import section to specify a category to add on imported mangas"
},
"bookmarks_title": {
"message": "Bookmarks",
"description": "Title of the bookmarks page"
},
"bookmarks_search": {
"message": "Search",
"description": "Placeholder for the search text input on top of the bookmarks page"
},
"bookmarks_number": {
"message": "$1 bookmarks",
"description": "Label to display the total number of bookmarks from a manga in the left panel, $1 is the number of bookmarks"
},
"bookmarks_allmangas": {
"message": "All mangas",
"description": "Title of the first entry from the left panel representing all the mangas"
},
"bookmarks_size_large": {
"message": "Large",
"description": "Size of the bookmarks in list : large"
},
"bookmarks_size_medium": {
"message": "Medium",
"description": "Size of the bookmarks in list : medium"
},
"bookmarks_size_small": {
"message": "Small",
"description": "Size of the bookmarks in list : small"
},
"bookmarks_no_mangas": {
"message": "No mangas have bookmarks",
"description": "Label when no mangas have bookmarks"
},
"bookmarks_no_bookmarks": {
"message": "No bookmarks yet. To bookmark a scan, double click on the scan while reading. Bookmarked scans have a grey border. <br /> To bookmark a chapter, click on the star in the top bar while reading.",
"description": "Label when no bookmarks. Help about how to bookmark a scan and chapter"
},
"bookmarks_no_bookmarks_filter": {
"message": "No bookmarks matching your filters",
"description": "Label when no bookmarks match the filters"
},
"bookmarks_chapter_delete": {
"message": "Delete bookmarked chapter ?",
"description": "Popup title for bookmarked chapter deletion"
},
"bookmarks_scan_delete": {
"message": "Delete bookmarked scan ?",
"description": "Popup title for bookmarked scan deletion"
},
"bookmarks_chapter_delete_text": {
"message": "Are you sure to remove the bookmarked chapter from $1 chapter $2 ?",
"description": "Popup text for bookmarked chapter deletion. $1 is manga name, $2 is chapter name"
},
"bookmarks_scan_delete_text": {
"message": "Are you sure to remove the bookmarked scan from $1 chapter $2, scan $3 ?",
"description": "Popup text for bookmarked chapter deletion. $1 is manga name, $2 is chapter name, $3 is scan name"
},
"bookmarks_chapter_edit": {
"message": "Edit bookmarked chapter ?",
"description": "Popup title for bookmarked chapter edition"
},
"bookmarks_scan_edit": {
"message": "Edit bookmarked scan ?",
"description": "Popup title for bookmarked scan edition"
},
"bookmarks_chapter_edit_text": {
"message": "Update note of bookmarked chapter from $1 chapter $2",
"description": "Popup text for bookmarked chapter edition. $1 is manga name, $2 is chapter name"
},
"bookmarks_scan_edit_text": {
"message": "Update note of bookmarked scan from $1 chapter $2, scan $3",
"description": "Popup text for bookmarked chapter edition. $1 is manga name, $2 is chapter name, $3 is scan name"
},
"bookmarks_edit_note": {
"message": "Note",
"description": "Label of the textarea in bookmark edition"
}
}
......@@ -7,26 +7,25 @@
app
>
<v-card flat>
<v-list two-line>
<v-list two-line v-if="mangas">
<v-list-tile @click="switchAllStates()" avatar ripple>
<v-list-tile-content>
<v-list-tile-title>
All mangas
{{i18n("bookmarks_allmangas")}}
</v-list-tile-title>
<v-list-tile-sub-title class="text--primary">{{ nbBookmarks }} bookmarks</v-list-tile-sub-title>
<v-list-tile-sub-title class="text--primary">{{i18n("bookmarks_number", nbBookmarks)}}
</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-icon
v-if="hasOneUnState()"
color="red darken-2"
@click="switchAllStates()"
>
mdi-eye
</v-icon>
<v-icon
v-else
color="grey lighten-1"
@click="switchAllStates()"
>
mdi-eye-off
</v-icon>
......@@ -39,20 +38,19 @@
<v-list-tile-title>
{{ mg.name }}
</v-list-tile-title>
<v-list-tile-sub-title class="text--primary">{{ mg.nb }} bookmarks</v-list-tile-sub-title>
<v-list-tile-sub-title class="text--primary">{{i18n("bookmarks_number", mg.nb)}}
</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-icon
v-if="!mangasUnSel[mg.key]"
color="red darken-2"
@click="switchMgState(mg)"
>
mdi-eye
</v-icon>
<v-icon
v-else
color="grey lighten-1"
@click="switchMgState(mg)"
>
mdi-eye-off
</v-icon>
......@@ -64,6 +62,7 @@
></v-divider>
</template>
</v-list>
<v-card-text v-else>{{i18n("bookmarks_no_mangas")}}</v-card-text>
</v-card>
</v-navigation-drawer>
<v-toolbar
......@@ -75,22 +74,37 @@
>
<v-toolbar-title style="width: 300px" class="ml-0 pl-3">
<v-toolbar-side-icon @click.stop="drawer = !drawer"></v-toolbar-side-icon>
<v-btn icon large color="white">
<v-btn icon large color="white" class="hidden-sm-and-down">
<v-avatar size="32px" tile>
<img src="/icons/icon_32.png" alt="All Mangas Reader">
</v-avatar>
</v-btn>
<span class="hidden-sm-and-down">Bookmarks</span>
<span>{{i18n("bookmarks_title")}}</span>
</v-toolbar-title>
<v-text-field
flat
solo-inverted
hide-details
prepend-inner-icon="search"
label="Search"
:label="i18n('bookmarks_search')"
class="hidden-sm-and-down"
v-model="search"
></v-text-field>
<v-spacer></v-spacer>
<v-overflow-btn
:items="dropdown_size"
label="Select size"
hide-details
overflow
v-model="size"
class="hidden-md-and-down mr-2"
item-text="text"
item-value="value"
single-line
return-object
solo-inverted
flat
></v-overflow-btn>
<v-btn-toggle v-model="toggle_type" multiple class="transparent">
<v-btn flat>
<v-icon>mdi-image</v-icon>
......@@ -108,7 +122,11 @@
</v-layout>
<v-layout v-else>
<!-- Once loaded -->
<Bookmarks :bookmark-list="displayedBookmarks"/>
<Bookmarks :bookmark-list="displayedBookmarks" :size="size.value" v-if="nbBookmarks > 0 && displayedBookmarks.length > 0"/>
<h2 v-else align-center>
<span v-if="displayedBookmarks.length==0" v-html="i18n('bookmarks_no_bookmarks_filter')"></span>
<span v-else v-html="i18n('bookmarks_no_bookmarks')"></span>
</h2>
</v-layout>
</v-container>
</v-content>
......@@ -121,13 +139,21 @@ import Bookmarks from "../components/Bookmarks";
import * as utils from "../../amr/utils";
import Vue from 'vue';
const sizes = [
{ text: i18n("bookmarks_size_large"), value: 2 },
{ text: i18n("bookmarks_size_medium"), value: 3 },
{ text: i18n("bookmarks_size_small"), value: 4 }
];
export default {
data() {
return {
loaded: false,
drawer: true, /* display left panel by default */
toggle_type: [0,1], /* select both scan and chapter by default */
mangasUnSel: {},
mangasUnSel: {}, /* list of manga state (key is formatMgName(mg.name)) */
search: "",
dropdown_size: sizes,
size: sizes[1],
};
},
computed: {
......@@ -165,8 +191,13 @@ export default {
if (this.mangasUnSel[bmmgname]) return false;
// by search text
let sc = utils.formatMgName(this.search)
let contains = false;
if (utils.formatMgName(bm.name).indexOf(sc) >= 0) contains = true;
else if (utils.formatMgName(bm.note).indexOf(sc) >= 0) contains = true;
else if (utils.formatMgName(bm.chapterName).indexOf(sc) >= 0) contains = true;
return true;
return contains;
});
},
nbBookmarks: function() {
......
<template>
<v-container fluid grid-list-lg>
<gallery :images="scans" :index="curScan" @close="curScan = null" :options="{closeOnSlideClick:true}"></gallery>
<v-layout row wrap>
<v-flex xs12 sm6 lg4 v-for="bm in bookmarkList" :key="bm.key">
<v-flex xs12 sm6 v-bind="getSize()" v-for="bm in bookmarkList" :key="bm.key">
<v-card tile>
<v-card-media v-if="bm.type == 'scan'"
:src="bm.scanUrl"
height="300px"
>
:src="bm.scanUrl"
:height="getHeight()"
@click="setScan(bm)"
class="amr-scan"
>
</v-card-media>
<v-card-title primary-title>
<div>
<div class="headline">{{bm.name}} - {{bm.chapName}}</div>
<span class="grey--text">{{bm.note}}</span>
</div>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn icon @click="openEdit(bm)">
<v-icon>mdi-pencil</v-icon>
</v-btn>
<v-btn icon @click="openDelete(bm)">
<v-icon>mdi-delete</v-icon>
</v-btn>
<v-btn icon @click="openTab(bm)">
<v-icon>mdi-open-in-new</v-icon>
</v-btn>
</v-card-actions>
<v-card-title primary-title class="pt-1">
<div>
<div class="headline">
<img :src="getIcon(bm.mirror)" />
{{bm.name}} - {{bm.chapName}}
</div>
<span class="subtitle grey--text">{{bm.note}}</span>
</div>
</v-card-title>
</v-card>
</v-flex>
</v-layout>
<v-dialog v-model="deleteBookmarkDialog" max-width="290">
<v-card v-if="bmToDelete">
<v-card-title class="headline">{{bmToDelete.type === 'chapter' ? i18n("bookmarks_chapter_delete") : i18n("bookmarks_scan_delete")}}</v-card-title>
<v-card-text>{{bmToDelete.type === 'chapter' ? i18n("bookmarks_chapter_delete_text", bmToDelete.name, bmToDelete.chapName) : i18n("bookmarks_scan_delete_text", bmToDelete.name, bmToDelete.chapName, bmToDelete.scanName)}}</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="red darken-1" flat @click.native="reallyDeleteBm()">{{i18n("button_yes")}}</v-btn>
<v-btn color="grey darken-1" flat @click.native="deleteBookmarkDialog = false">{{i18n("button_no")}}</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog v-model="editBookmarkDialog" max-width="500px">
<v-card v-if="bmToEdit">
<v-card-title>
<span class="headline" v-if="bmToEdit.type === 'chapter'">{{i18n('bookmarks_chapter_edit')}}</span>
<span class="headline" v-else>{{i18n('bookmarks_scan_edit')}}</span>
</v-card-title>
<v-card-text>
<p v-html="bmToEdit.type === 'chapter' ? i18n('bookmarks_chapter_edit_text', bmToEdit.name, bmToEdit.chapName) : i18n('bookmarks_scan_edit_text', bmToEdit.name, bmToEdit.chapName, bmToEdit.scanName)"></p>
<v-container grid-list-md>
<v-layout wrap>
<v-flex xs12>
<v-textarea :label="i18n('bookmarks_edit_note')" v-model="bmToEdit.note"></v-textarea>
</v-flex>
</v-layout>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary darken-1" flat @click.native="editBookmarkDialog = false">{{i18n('button_cancel')}}</v-btn>
<v-btn color="primary darken-1" flat @click.native="reallyEditBm">{{i18n('button_save')}}</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-container>
</template>
<script>
import i18n from "../../amr/i18n";
import VueGallery from "vue-gallery";
import browser from "webextension-polyfill";
export default {
data() {
return {};
return {
deleteBookmarkDialog: false,
bmToDelete: undefined,
editBookmarkDialog: false,
bmToEdit: undefined,
curScan: null
};
},
computed: {
scans: function() {
return this.bookmarkList
.filter(bm => bm.type === "scan")
.map(bm => bm.scanUrl);
}
},
props: ["bookmarkList"],
props: ["bookmarkList", "size"],
name: "Bookmarks",
methods: {
i18n: (message, ...args) => i18n(message, ...args),
getSize: function() {
return this.size === 2
? { [`lg6`]: true }
: this.size === 3 ? { [`lg4`]: true } : { [`lg3`]: true };
},
getHeight: function() {
return this.size === 2
? '500px'
: this.size === 3 ? '300px' : '250px';
},
openDelete(bm) {
this.bmToDelete = bm;
this.deleteBookmarkDialog = true;
},
reallyDeleteBm() {
this.$store.dispatch("deleteBookmark", this.bmToDelete);
this.deleteBookmarkDialog = false;
},
openEdit(bm) {
this.bmToEdit = bm;
this.editBookmarkDialog = true;
},
reallyEditBm() {
this.$store.dispatch("updateBookmarkNote", this.bmToEdit);
this.editBookmarkDialog = false;
},
setScan(bm) {
this.curScan = this.scans.findIndex(sc => sc === bm.scanUrl);
},
openTab(bm) {
browser.runtime.sendMessage({ action: "opentab", url: bm.chapUrl });
},
/**
* Returns mirror icon from its name
*/
getIcon(mirrorname) {
return this.$store.state.mirrors.all.find(mir => mir.mirrorName === mirrorname).mirrorIcon
}
},
components: {
gallery: VueGallery
}
};
</script>
<style>
.subtitle {
font-size: 14px !important;
line-height: 24px !important;
letter-spacing: normal !important;
}
.amr-scan {
cursor: pointer;
}
</style>
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