Better image compression and added prev page thumbnail on edit page

This commit is contained in:
Sagi Dayan 2020-05-24 21:49:18 -04:00
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

View file

@ -8111,6 +8111,9 @@ video {
border-radius: 8px; border-radius: 8px;
background-color: white; } background-color: white; }
.book-thumb.page-preview {
flex-basis: unset; }
.edit-page-controllers { .edit-page-controllers {
border-radius: 15px; border-radius: 15px;
background-color: rgba(134, 134, 134, 0.1); } background-color: rgba(134, 134, 134, 0.1); }

View file

@ -497,6 +497,9 @@ video{
background-color: white; background-color: white;
} }
} }
.book-thumb.page-preview{
flex-basis: unset;
}
.edit-page-controllers{ .edit-page-controllers{
border-radius: 15px; border-radius: 15px;
background-color: rgba(134, 134, 134, 0.1); background-color: rgba(134, 134, 134, 0.1);

View file

@ -86,7 +86,10 @@
<span>Edit</span> <span>Edit</span>
</a> </a>
</li> </li>
<li :class="!editMode ? 'is-active' : ''" @click="editMode=false"> <li
:class="!editMode ? 'is-active' : ''"
@click="currentPage = -7;editMode=false"
>
<a> <a>
<span class="icon is-small"> <span class="icon is-small">
<i class="fa fa-eye" aria-hidden="true"></i> <i class="fa fa-eye" aria-hidden="true"></i>
@ -110,9 +113,9 @@
<div class="page-editor" v-else> <div class="page-editor" v-else>
<div class="columns"> <div class="columns">
<!-- Croppa --> <!-- Croppa -->
<div class="column is-flex"> <div class="column has-text-centered">
<div v-if="pages[currentPage].loaded"> <div v-if="pages[currentPage].loaded">
<h1 class="subtitle">{{pages[currentPage].text}}</h1> <h1 class="subtitle is-3">{{pages[currentPage].text}}</h1>
<croppa <croppa
v-model="pages[currentPage].croppa" v-model="pages[currentPage].croppa"
:prevent-white-space="true" :prevent-white-space="true"
@ -132,17 +135,12 @@
<div <div
class="edit-page-controllers column is-3 is-flex-column is-justify-centered has-text-centered" 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"> <div class="field" v-if="currentPage===0 && pages.length===1">
<label class="label">Page width</label> <label class="label">Page width</label>
<input <input
type="range" type="range"
min="200" :min="DEFAULT_PAGE_WIDTH-50"
max="600" :max="DEFAULT_PAGE_WIDTH"
v-model="bookWidth" v-model="bookWidth"
:disabled="!pages[currentPage].imageLoaded" :disabled="!pages[currentPage].imageLoaded"
/> />
@ -150,7 +148,7 @@
<button <button
type="button" type="button"
class="button is-rounded is-outlined is-small" class="button is-rounded is-outlined is-small"
:disabled="!pages[currentPage].imageLoaded" :disabled="!pages[currentPage].imageLoaded || bookWidth<= DEFAULT_PAGE_WIDTH - 50"
@click="bookWidth-=2" @click="bookWidth-=2"
> >
<i class="fa fa-fw fa-minus"></i> <i class="fa fa-fw fa-minus"></i>
@ -158,19 +156,40 @@
<button <button
type="button" type="button"
class="button is-rounded is-outlined is-small" class="button is-rounded is-outlined is-small"
:disabled="!pages[currentPage].imageLoaded" :disabled="!pages[currentPage].imageLoaded || bookWidth >= DEFAULT_PAGE_WIDTH"
@click="bookWidth+=2" @click="bookWidth+=2"
> >
<i class="fa fa-fw fa-plus"></i> <i class="fa fa-fw fa-plus"></i>
</button> </button>
</div> </div>
</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"> <div class="field" v-if="currentPage===0 && pages.length===1">
<label class="label">Page height</label> <label class="label">Page height</label>
<input <input
type="range" type="range"
min="200" :min="DEFAULT_PAGE_HEIGHT-50"
max="600" :max="DEFAULT_PAGE_HEIGHT"
v-model="bookHeight" v-model="bookHeight"
:disabled="!pages[currentPage].imageLoaded" :disabled="!pages[currentPage].imageLoaded"
/> />
@ -178,7 +197,7 @@
<button <button
type="button" type="button"
class="button is-rounded is-outlined is-small" class="button is-rounded is-outlined is-small"
:disabled="!pages[currentPage].imageLoaded" :disabled="!pages[currentPage].imageLoaded || bookWidth<= DEFAULT_PAGE_HEIGHT - 50"
@click="bookHeight-=2" @click="bookHeight-=2"
> >
<i class="fa fa-fw fa-minus"></i> <i class="fa fa-fw fa-minus"></i>
@ -186,7 +205,7 @@
<button <button
type="button" type="button"
class="button is-rounded is-outlined is-small" class="button is-rounded is-outlined is-small"
:disabled="!pages[currentPage].imageLoaded" :disabled="!pages[currentPage].imageLoaded || bookWidth >= DEFAULT_PAGE_HEIGHT"
@click="bookHeight+=2" @click="bookHeight+=2"
> >
<i class="fa fa-fw fa-plus"></i> <i class="fa fa-fw fa-plus"></i>
@ -238,8 +257,19 @@
<i class="fa fa-fw fa-rotate-right"></i> <i class="fa fa-fw fa-rotate-right"></i>
</button> </button>
</div> </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"> <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 <i class="fa fa-fw fa-trash"></i> Delete Page
</button> </button>
</div> </div>
@ -321,6 +351,13 @@ import { mapGetters, mapActions } from "vuex";
import Flipbook from "../components/flipbook/flipbook.cjs.js"; import Flipbook from "../components/flipbook/flipbook.cjs.js";
import Croppa from "vue-croppa"; import Croppa from "vue-croppa";
import Services from "../../services"; 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 { export default {
name: "EditBook", name: "EditBook",
props: ["editBook"], props: ["editBook"],
@ -344,14 +381,14 @@ export default {
console.log(lastPage, currentPage); console.log(lastPage, currentPage);
if (this.pages[lastPage] && lastPage >= 0) { if (this.pages[lastPage] && lastPage >= 0) {
const imageBlob = await this.pages[lastPage].croppa.promisedBlob( const imageBlob = await this.pages[lastPage].croppa.promisedBlob(
"image/jpg", MIME_TYPE,
0.8 COMPRESSION_RATE
); );
if (imageBlob) { if (imageBlob) {
let url = URL.createObjectURL(imageBlob); let url = URL.createObjectURL(imageBlob);
this.pages[lastPage].base64 = this.pages[ this.pages[lastPage].base64 = this.pages[
lastPage lastPage
].croppa.generateDataUrl("image/jpg", 0.8); ].croppa.generateDataUrl(MIME_TYPE, COMPRESSION_RATE);
this.pages[lastPage].image = url; this.pages[lastPage].image = url;
} }
} }
@ -365,7 +402,7 @@ export default {
}); });
} }
this.pageRotation = 0; this.pageRotation = 0;
this.pageZoom = 500; this.pageZoom = DEFAULT_ZOOM;
return true; return true;
}, },
pageRotation: function(newAngle) { pageRotation: function(newAngle) {
@ -424,6 +461,22 @@ export default {
onCroppaImageLoaded() { onCroppaImageLoaded() {
this.pages[this.currentPage].imageLoaded = true; 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() { async onUploadClicked() {
//TODO: Better validations //TODO: Better validations
if (!this.book.title || !this.book.title.length) { if (!this.book.title || !this.book.title.length) {
@ -448,12 +501,14 @@ export default {
return; return;
} }
this.uploading = true; this.uploading = true;
try {
const resp = await Services.ApiService.uploadBook({ const resp = await Services.ApiService.uploadBook({
title: this.book.title, title: this.book.title,
author: this.book.author, author: this.book.author,
ltr: this.book.ltr, ltr: this.book.ltr,
pages: this.pages.map( 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) { if (resp.code === 0) {
@ -469,6 +524,9 @@ export default {
level: "danger" level: "danger"
}); });
} }
} catch (e) {
console.log(`Error... ${e.message}`);
}
this.uploading = false; this.uploading = false;
}, },
async onAddPageClicked() { async onAddPageClicked() {
@ -489,8 +547,8 @@ export default {
console.log("In else"); console.log("In else");
const nextPage = lastPage + 1; const nextPage = lastPage + 1;
const imageBlob = await this.pages[lastPage].croppa.promisedBlob( const imageBlob = await this.pages[lastPage].croppa.promisedBlob(
"image/jpg", MIME_TYPE,
0.8 COMPRESSION_RATE
); );
if (!imageBlob) { if (!imageBlob) {
this.notify({ this.notify({
@ -501,10 +559,12 @@ export default {
return; return;
} }
let url = URL.createObjectURL(imageBlob); let url = URL.createObjectURL(imageBlob);
this.pages.base64 = this.pages[lastPage].croppa.generateDataUrl( this.pages[lastPage].base64 = this.pages[
"image/jpg", lastPage
0.8 ].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[lastPage].image = url;
this.pages.push({ this.pages.push({
text: `Page ${nextPage}`, text: `Page ${nextPage}`,
@ -566,16 +626,18 @@ export default {
rtl: true rtl: true
}, },
pages: [], pages: [],
bookWidth: 400, bookWidth: DEFAULT_PAGE_WIDTH,
bookHeight: 600, bookHeight: DEFAULT_PAGE_HEIGHT,
previewPages: [], previewPages: [],
editMode: true, editMode: true,
currentPage: -7, currentPage: -7,
flipbookRef: false, flipbookRef: false,
pageRotation: 0, pageRotation: 0,
pageZoom: 500, pageZoom: DEFAULT_ZOOM,
uploading: false, uploading: false,
errors: {} errors: {},
DEFAULT_PAGE_WIDTH,
DEFAULT_PAGE_HEIGHT
}; };
} }
}; };

View file

@ -33,7 +33,7 @@ export default class ApiService {
return (await fetch('/api/v1/client/book/create', options)).json(); return (await fetch('/api/v1/client/book/create', options)).json();
} catch (e) { } catch (e) {
console.error(`uploadBook ERROR: ${e.message}`); console.error(`uploadBook ERROR: ${e.message}`);
return e; throw e;
} }
} }