forked from sagi/seepur
Better image compression and added prev page thumbnail on edit page
This commit is contained in:
parent
31f01a2850
commit
2bf05c4690
8 changed files with 125 additions and 57 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -8111,6 +8111,9 @@ video {
|
|||
border-radius: 8px;
|
||||
background-color: white; }
|
||||
|
||||
.book-thumb.page-preview {
|
||||
flex-basis: unset; }
|
||||
|
||||
.edit-page-controllers {
|
||||
border-radius: 15px;
|
||||
background-color: rgba(134, 134, 134, 0.1); }
|
||||
|
|
|
@ -497,6 +497,9 @@ video{
|
|||
background-color: white;
|
||||
}
|
||||
}
|
||||
.book-thumb.page-preview{
|
||||
flex-basis: unset;
|
||||
}
|
||||
.edit-page-controllers{
|
||||
border-radius: 15px;
|
||||
background-color: rgba(134, 134, 134, 0.1);
|
||||
|
|
|
@ -86,7 +86,10 @@
|
|||
<span>Edit</span>
|
||||
</a>
|
||||
</li>
|
||||
<li :class="!editMode ? 'is-active' : ''" @click="editMode=false">
|
||||
<li
|
||||
:class="!editMode ? 'is-active' : ''"
|
||||
@click="currentPage = -7;editMode=false"
|
||||
>
|
||||
<a>
|
||||
<span class="icon is-small">
|
||||
<i class="fa fa-eye" aria-hidden="true"></i>
|
||||
|
@ -110,9 +113,9 @@
|
|||
<div class="page-editor" v-else>
|
||||
<div class="columns">
|
||||
<!-- Croppa -->
|
||||
<div class="column is-flex">
|
||||
<div class="column has-text-centered">
|
||||
<div v-if="pages[currentPage].loaded">
|
||||
<h1 class="subtitle">{{pages[currentPage].text}}</h1>
|
||||
<h1 class="subtitle is-3">{{pages[currentPage].text}}</h1>
|
||||
<croppa
|
||||
v-model="pages[currentPage].croppa"
|
||||
:prevent-white-space="true"
|
||||
|
@ -132,17 +135,12 @@
|
|||
<div
|
||||
class="edit-page-controllers column is-3 is-flex-column is-justify-centered has-text-centered"
|
||||
>
|
||||
<div class="change-image">
|
||||
<button class="button" @click="pages[currentPage].croppa.chooseFile()">
|
||||
<i class="fa fa-fw fa-refresh"></i> Change Image
|
||||
</button>
|
||||
</div>
|
||||
<div class="field" v-if="currentPage===0 && pages.length===1">
|
||||
<label class="label">Page width</label>
|
||||
<input
|
||||
type="range"
|
||||
min="200"
|
||||
max="600"
|
||||
:min="DEFAULT_PAGE_WIDTH-50"
|
||||
:max="DEFAULT_PAGE_WIDTH"
|
||||
v-model="bookWidth"
|
||||
:disabled="!pages[currentPage].imageLoaded"
|
||||
/>
|
||||
|
@ -150,7 +148,7 @@
|
|||
<button
|
||||
type="button"
|
||||
class="button is-rounded is-outlined is-small"
|
||||
:disabled="!pages[currentPage].imageLoaded"
|
||||
:disabled="!pages[currentPage].imageLoaded || bookWidth<= DEFAULT_PAGE_WIDTH - 50"
|
||||
@click="bookWidth-=2"
|
||||
>
|
||||
<i class="fa fa-fw fa-minus"></i>
|
||||
|
@ -158,19 +156,40 @@
|
|||
<button
|
||||
type="button"
|
||||
class="button is-rounded is-outlined is-small"
|
||||
:disabled="!pages[currentPage].imageLoaded"
|
||||
:disabled="!pages[currentPage].imageLoaded || bookWidth >= DEFAULT_PAGE_WIDTH"
|
||||
@click="bookWidth+=2"
|
||||
>
|
||||
<i class="fa fa-fw fa-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="prev-page-preview" v-else>
|
||||
<div
|
||||
class="is-flex is-justify-centered"
|
||||
v-if="pages[currentPage - 1] && pages[currentPage - 1].base64"
|
||||
>
|
||||
<div class="book-thumb page-preview">
|
||||
<div class="book-text">
|
||||
<div>Previouse Page</div>
|
||||
</div>
|
||||
<div class="book-cover">
|
||||
<img
|
||||
:src="pages[currentPage - 1] ? pages[currentPage - 1].base64: ''"
|
||||
/>
|
||||
</div>
|
||||
<div class="book-text">
|
||||
<div>{{pages[currentPage - 1].text}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="is-fullwidth-container" />
|
||||
<div class="field" v-if="currentPage===0 && pages.length===1">
|
||||
<label class="label">Page height</label>
|
||||
<input
|
||||
type="range"
|
||||
min="200"
|
||||
max="600"
|
||||
:min="DEFAULT_PAGE_HEIGHT-50"
|
||||
:max="DEFAULT_PAGE_HEIGHT"
|
||||
v-model="bookHeight"
|
||||
:disabled="!pages[currentPage].imageLoaded"
|
||||
/>
|
||||
|
@ -178,7 +197,7 @@
|
|||
<button
|
||||
type="button"
|
||||
class="button is-rounded is-outlined is-small"
|
||||
:disabled="!pages[currentPage].imageLoaded"
|
||||
:disabled="!pages[currentPage].imageLoaded || bookWidth<= DEFAULT_PAGE_HEIGHT - 50"
|
||||
@click="bookHeight-=2"
|
||||
>
|
||||
<i class="fa fa-fw fa-minus"></i>
|
||||
|
@ -186,7 +205,7 @@
|
|||
<button
|
||||
type="button"
|
||||
class="button is-rounded is-outlined is-small"
|
||||
:disabled="!pages[currentPage].imageLoaded"
|
||||
:disabled="!pages[currentPage].imageLoaded || bookWidth >= DEFAULT_PAGE_HEIGHT"
|
||||
@click="bookHeight+=2"
|
||||
>
|
||||
<i class="fa fa-fw fa-plus"></i>
|
||||
|
@ -238,8 +257,19 @@
|
|||
<i class="fa fa-fw fa-rotate-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="change-image">
|
||||
<button
|
||||
class="button is-fullwidth-container"
|
||||
@click="pages[currentPage].croppa.chooseFile()"
|
||||
>
|
||||
<i class="fa fa-fw fa-refresh"></i> Change Image
|
||||
</button>
|
||||
</div>
|
||||
<div class="remove-image" v-if="currentPage === pages.length-1">
|
||||
<button class="button is-danger" @click="deleteLastPage()">
|
||||
<button
|
||||
class="button is-danger is-fullwidth-container"
|
||||
@click="deleteLastPage()"
|
||||
>
|
||||
<i class="fa fa-fw fa-trash"></i> Delete Page
|
||||
</button>
|
||||
</div>
|
||||
|
@ -321,6 +351,13 @@ import { mapGetters, mapActions } from "vuex";
|
|||
import Flipbook from "../components/flipbook/flipbook.cjs.js";
|
||||
import Croppa from "vue-croppa";
|
||||
import Services from "../../services";
|
||||
|
||||
const DEFAULT_PAGE_WIDTH = 350;
|
||||
const DEFAULT_PAGE_HEIGHT = 350;
|
||||
|
||||
const DEFAULT_ZOOM = 500;
|
||||
const MIME_TYPE = "image/jpeg";
|
||||
const COMPRESSION_RATE = 0.4;
|
||||
export default {
|
||||
name: "EditBook",
|
||||
props: ["editBook"],
|
||||
|
@ -344,14 +381,14 @@ export default {
|
|||
console.log(lastPage, currentPage);
|
||||
if (this.pages[lastPage] && lastPage >= 0) {
|
||||
const imageBlob = await this.pages[lastPage].croppa.promisedBlob(
|
||||
"image/jpg",
|
||||
0.8
|
||||
MIME_TYPE,
|
||||
COMPRESSION_RATE
|
||||
);
|
||||
if (imageBlob) {
|
||||
let url = URL.createObjectURL(imageBlob);
|
||||
this.pages[lastPage].base64 = this.pages[
|
||||
lastPage
|
||||
].croppa.generateDataUrl("image/jpg", 0.8);
|
||||
].croppa.generateDataUrl(MIME_TYPE, COMPRESSION_RATE);
|
||||
this.pages[lastPage].image = url;
|
||||
}
|
||||
}
|
||||
|
@ -365,7 +402,7 @@ export default {
|
|||
});
|
||||
}
|
||||
this.pageRotation = 0;
|
||||
this.pageZoom = 500;
|
||||
this.pageZoom = DEFAULT_ZOOM;
|
||||
return true;
|
||||
},
|
||||
pageRotation: function(newAngle) {
|
||||
|
@ -424,6 +461,22 @@ export default {
|
|||
onCroppaImageLoaded() {
|
||||
this.pages[this.currentPage].imageLoaded = true;
|
||||
},
|
||||
async promiseAllProgress(
|
||||
promises: Promise<any>[],
|
||||
callback: (done: number, total: number) => void
|
||||
): Promise<any> {
|
||||
let counter = 0;
|
||||
callback(counter, promises.length);
|
||||
for (let i = 0; i < promises.length; i++) {
|
||||
const promise = promises[i];
|
||||
promise.then(async val => {
|
||||
counter++;
|
||||
callback(counter, promises.length);
|
||||
return val;
|
||||
});
|
||||
}
|
||||
return Promise.all(promises);
|
||||
},
|
||||
async onUploadClicked() {
|
||||
//TODO: Better validations
|
||||
if (!this.book.title || !this.book.title.length) {
|
||||
|
@ -448,12 +501,14 @@ export default {
|
|||
return;
|
||||
}
|
||||
this.uploading = true;
|
||||
try {
|
||||
const resp = await Services.ApiService.uploadBook({
|
||||
title: this.book.title,
|
||||
author: this.book.author,
|
||||
ltr: this.book.ltr,
|
||||
pages: this.pages.map(
|
||||
p => p.base64 || p.croppa.generateDataUrl("image/jpg", 0.7)
|
||||
p =>
|
||||
p.base64 || p.croppa.generateDataUrl(MIME_TYPE, COMPRESSION_RATE)
|
||||
)
|
||||
});
|
||||
if (resp.code === 0) {
|
||||
|
@ -469,6 +524,9 @@ export default {
|
|||
level: "danger"
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(`Error... ${e.message}`);
|
||||
}
|
||||
this.uploading = false;
|
||||
},
|
||||
async onAddPageClicked() {
|
||||
|
@ -489,8 +547,8 @@ export default {
|
|||
console.log("In else");
|
||||
const nextPage = lastPage + 1;
|
||||
const imageBlob = await this.pages[lastPage].croppa.promisedBlob(
|
||||
"image/jpg",
|
||||
0.8
|
||||
MIME_TYPE,
|
||||
COMPRESSION_RATE
|
||||
);
|
||||
if (!imageBlob) {
|
||||
this.notify({
|
||||
|
@ -501,10 +559,12 @@ export default {
|
|||
return;
|
||||
}
|
||||
let url = URL.createObjectURL(imageBlob);
|
||||
this.pages.base64 = this.pages[lastPage].croppa.generateDataUrl(
|
||||
"image/jpg",
|
||||
0.8
|
||||
);
|
||||
this.pages[lastPage].base64 = this.pages[
|
||||
lastPage
|
||||
].croppa.generateDataUrl(MIME_TYPE, COMPRESSION_RATE);
|
||||
const c01 = this.pages[lastPage].croppa.generateDataUrl(MIME_TYPE, 0.1);
|
||||
console.log(`COMPRESSION_RATE: ${this.pages[lastPage].base64.length}`);
|
||||
console.log(`0.1: ${c01.length}`);
|
||||
this.pages[lastPage].image = url;
|
||||
this.pages.push({
|
||||
text: `Page ${nextPage}`,
|
||||
|
@ -566,16 +626,18 @@ export default {
|
|||
rtl: true
|
||||
},
|
||||
pages: [],
|
||||
bookWidth: 400,
|
||||
bookHeight: 600,
|
||||
bookWidth: DEFAULT_PAGE_WIDTH,
|
||||
bookHeight: DEFAULT_PAGE_HEIGHT,
|
||||
previewPages: [],
|
||||
editMode: true,
|
||||
currentPage: -7,
|
||||
flipbookRef: false,
|
||||
pageRotation: 0,
|
||||
pageZoom: 500,
|
||||
pageZoom: DEFAULT_ZOOM,
|
||||
uploading: false,
|
||||
errors: {}
|
||||
errors: {},
|
||||
DEFAULT_PAGE_WIDTH,
|
||||
DEFAULT_PAGE_HEIGHT
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
@ -33,7 +33,7 @@ export default class ApiService {
|
|||
return (await fetch('/api/v1/client/book/create', options)).json();
|
||||
} catch (e) {
|
||||
console.error(`uploadBook ERROR: ${e.message}`);
|
||||
return e;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue