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;
background-color: white; }
.book-thumb.page-preview {
flex-basis: unset; }
.edit-page-controllers {
border-radius: 15px;
background-color: rgba(134, 134, 134, 0.1); }

View file

@ -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);

View file

@ -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
};
}
};

View file

@ -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;
}
}