crop the image and store online and in settings
This commit is contained in:
45
package-lock.json
generated
45
package-lock.json
generated
@@ -59,6 +59,7 @@
|
||||
"vue": "^3.4.21",
|
||||
"vue-axios": "^3.5.2",
|
||||
"vue-facing-decorator": "^3.0.4",
|
||||
"vue-picture-cropper": "^0.7.0",
|
||||
"vue-qrcode-reader": "^5.5.3",
|
||||
"vue-router": "^4.3.0",
|
||||
"web-did-resolver": "^2.0.27"
|
||||
@@ -2369,6 +2370,14 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@bassist/utils": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@bassist/utils/-/utils-0.4.0.tgz",
|
||||
"integrity": "sha512-aoFTl0jUjm8/tDZodP41wnEkvB+C5O9NFCuYN/ztL6jSUSsuBkXq90/1ifBm1XhV/zySHgLYlU1+tgo3XtQ+nA==",
|
||||
"dependencies": {
|
||||
"@withtypes/mime": "^0.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@bitauth/libauth": {
|
||||
"version": "1.19.1",
|
||||
"license": "MIT",
|
||||
@@ -9696,6 +9705,25 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@withtypes/mime": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@withtypes/mime/-/mime-0.1.2.tgz",
|
||||
"integrity": "sha512-PB9BfZGzwblUONJY0LiOwsHCA6uV3DIPj/w9ReekdHxPOl0VdUFgI5s4avKycuuq9Gf5Nz2ZPA2O36GAUzlMPA==",
|
||||
"dependencies": {
|
||||
"mime": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@withtypes/mime/node_modules/mime": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
|
||||
"integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
|
||||
"bin": {
|
||||
"mime": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@xmldom/xmldom": {
|
||||
"version": "0.7.13",
|
||||
"license": "MIT",
|
||||
@@ -11439,6 +11467,11 @@
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/cropperjs": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.6.1.tgz",
|
||||
"integrity": "sha512-F4wsi+XkDHCOMrHMYjrTEE4QBOrsHHN5/2VsVAaRq8P7E5z7xQpT75S+f/9WikmBEailas3+yo+6zPIomW+NOA=="
|
||||
},
|
||||
"node_modules/cross-fetch": {
|
||||
"version": "4.0.0",
|
||||
"license": "MIT",
|
||||
@@ -21419,6 +21452,18 @@
|
||||
"vue": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-picture-cropper": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-picture-cropper/-/vue-picture-cropper-0.7.0.tgz",
|
||||
"integrity": "sha512-NF7+Dgso6d0GB16E5d/BbrcTIHm1VWz8dS3IjLhoBl+ZeC+yDA46CyJphQuO32SisaPmrKHN8VbiE2LgAfhnkQ==",
|
||||
"dependencies": {
|
||||
"@bassist/utils": "^0.4.0",
|
||||
"cropperjs": "^1.6.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": ">=3.2.13"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-qrcode-reader": {
|
||||
"version": "5.5.3",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"dev": "vite",
|
||||
"serve": "vite preview",
|
||||
"build": "VITE_GIT_HASH=`git log -1 --pretty=format:%h` vite build",
|
||||
"lint": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src",
|
||||
"lint": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src",
|
||||
"lint-fix": "eslint --ext .js,.ts,.vue --ignore-path .gitignore --fix src",
|
||||
"prebuild": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src && node sw_combine.js"
|
||||
},
|
||||
@@ -62,6 +62,7 @@
|
||||
"vue": "^3.4.21",
|
||||
"vue-axios": "^3.5.2",
|
||||
"vue-facing-decorator": "^3.0.4",
|
||||
"vue-picture-cropper": "^0.7.0",
|
||||
"vue-qrcode-reader": "^5.5.3",
|
||||
"vue-router": "^4.3.0",
|
||||
"web-did-resolver": "^2.0.27"
|
||||
|
||||
@@ -20,28 +20,54 @@
|
||||
</div>
|
||||
|
||||
<div v-if="uploading" class="flex justify-center">
|
||||
<fa icon="spinner" class="fa-spin fa-3x text-center block" />
|
||||
<fa
|
||||
icon="spinner"
|
||||
class="fa-spin fa-3x text-center block px-12 py-12"
|
||||
/>
|
||||
</div>
|
||||
<div v-else-if="blob">
|
||||
<div
|
||||
class="flex justify-center gap-2 absolute bottom-[1rem] left-[1rem] right-[1rem] bg-black/50 px-4 py-2"
|
||||
>
|
||||
<div v-if="crop">
|
||||
<VuePictureCropper
|
||||
:boxStyle="{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
backgroundColor: '#f8f8f8',
|
||||
margin: 'auto',
|
||||
}"
|
||||
:img="URL.createObjectURL(blob)"
|
||||
:options="{
|
||||
viewMode: 1,
|
||||
dragMode: 'crop',
|
||||
aspectRatio: 9 / 9,
|
||||
}"
|
||||
/>
|
||||
<!-- This gives a round cropper.
|
||||
:presetMode="{
|
||||
mode: 'round',
|
||||
}"
|
||||
-->
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="flex justify-center">
|
||||
<img :src="URL.createObjectURL(blob)" class="mt-2 rounded" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="absolute bottom-[1rem] left-[1rem] px-2 py-1">
|
||||
<button
|
||||
@click="uploadImage"
|
||||
class="bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white font-bold py-2 px-4 rounded-md"
|
||||
class="bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white py-1 px-2 rounded-md"
|
||||
>
|
||||
<span>Upload</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="absolute bottom-[1rem] right-[1rem] px-2 py-1">
|
||||
<button
|
||||
@click="retryImage"
|
||||
class="bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white font-bold py-2 px-4 rounded-md"
|
||||
class="bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white py-1 px-2 rounded-md"
|
||||
>
|
||||
<span>Retry</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex justify-center">
|
||||
<img :src="URL.createObjectURL(blob)" class="mt-2 rounded" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-else ref="cameraContainer">
|
||||
<!--
|
||||
@@ -92,6 +118,7 @@
|
||||
import axios from "axios";
|
||||
import Camera from "simple-vue-camera";
|
||||
import { Component, Vue } from "vue-facing-decorator";
|
||||
import VuePictureCropper, { cropper } from "vue-picture-cropper";
|
||||
|
||||
import { DEFAULT_IMAGE_API_SERVER, NotificationIface } from "@/constants/app";
|
||||
import { getIdentity } from "@/libs/util";
|
||||
@@ -99,13 +126,14 @@ import { db } from "@/db/index";
|
||||
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
|
||||
import { accessToken } from "@/libs/crypto";
|
||||
|
||||
@Component({ components: { Camera } })
|
||||
@Component({ components: { Camera, VuePictureCropper } })
|
||||
export default class GiftedPhotoDialog extends Vue {
|
||||
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
||||
|
||||
activeDeviceNumber = 0;
|
||||
activeDid = "";
|
||||
blob: Blob | null = null;
|
||||
crop: boolean;
|
||||
mirror = false;
|
||||
numDevices = 0;
|
||||
setImage: (arg: string) => void = () => {};
|
||||
@@ -134,8 +162,9 @@ export default class GiftedPhotoDialog extends Vue {
|
||||
}
|
||||
}
|
||||
|
||||
open(setImageFn: (arg: string) => void) {
|
||||
open(setImageFn: (arg: string) => void, crop?: boolean) {
|
||||
this.visible = true;
|
||||
this.crop = !!crop;
|
||||
const bottomNav = document.querySelector("#QuickNav") as HTMLElement;
|
||||
if (bottomNav) {
|
||||
bottomNav.style.display = "none";
|
||||
@@ -274,6 +303,11 @@ export default class GiftedPhotoDialog extends Vue {
|
||||
|
||||
async uploadImage() {
|
||||
this.uploading = true;
|
||||
|
||||
if (this.crop) {
|
||||
this.blob = await cropper?.getBlob();
|
||||
}
|
||||
|
||||
const identifier = await getIdentity(this.activeDid);
|
||||
const token = await accessToken(identifier);
|
||||
const headers = {
|
||||
|
||||
@@ -611,7 +611,7 @@ export default class AccountViewView extends Vue {
|
||||
isRegistered = false;
|
||||
isSubscribed = false;
|
||||
notificationMaybeChanged = false;
|
||||
profileImageUrl: string | null = null;
|
||||
profileImageUrl?: string;
|
||||
publicHex = "";
|
||||
publicBase64 = "";
|
||||
webPushServer = "";
|
||||
@@ -684,6 +684,7 @@ export default class AccountViewView extends Vue {
|
||||
(settings?.firstName || "") +
|
||||
(settings?.lastName ? ` ${settings.lastName}` : ""); // pre v 0.1.3
|
||||
this.isRegistered = !!settings?.isRegistered;
|
||||
this.profileImageUrl = settings?.profileImageUrl as string;
|
||||
this.showContactGives = !!settings?.showContactGivesInline;
|
||||
this.showShortcutBvc = !!settings?.showShortcutBvc;
|
||||
this.warnIfProdServer = !!settings?.warnIfProdServer;
|
||||
@@ -1289,10 +1290,14 @@ export default class AccountViewView extends Vue {
|
||||
}
|
||||
|
||||
openPhotoDialog() {
|
||||
(this.$refs.photoDialog as GiftedPhotoDialog).open((imgUrl) => {
|
||||
(this.$refs.photoDialog as GiftedPhotoDialog).open(async (imgUrl) => {
|
||||
await db.open();
|
||||
db.settings.update(MASTER_SETTINGS_KEY, {
|
||||
profileImageUrl: imgUrl,
|
||||
});
|
||||
this.profileImageUrl = imgUrl;
|
||||
console.log("Got image URL:", imgUrl);
|
||||
});
|
||||
//console.log("Got image URL:", imgUrl);
|
||||
}, true);
|
||||
}
|
||||
|
||||
confirmDeleteImage() {
|
||||
|
||||
Reference in New Issue
Block a user