Optionally scale images when sending
Default is "scale". Currently scales image so that longest side is 640px.
This commit is contained in:
parent
91dfb0bc8e
commit
5276a46afa
4 changed files with 331 additions and 83 deletions
97
package-lock.json
generated
97
package-lock.json
generated
|
|
@ -1,18 +1,21 @@
|
||||||
{
|
{
|
||||||
"name": "keanuapp-weblite",
|
"name": "keanuapp-weblite",
|
||||||
"version": "0.1.4",
|
"version": "0.1.5",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.5",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"aes-js": "^3.1.2",
|
"aes-js": "^3.1.2",
|
||||||
"axios": "^0.21.0",
|
"axios": "^0.21.0",
|
||||||
"clean-insights-sdk": "^2.4.1",
|
"clean-insights-sdk": "^2.4.1",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
|
"data-uri-to-buffer": "^3.0.1",
|
||||||
"dayjs": "^1.10.3",
|
"dayjs": "^1.10.3",
|
||||||
"fix-webm-duration": "^1.0.0",
|
"fix-webm-duration": "^1.0.0",
|
||||||
|
"image-resize": "^1.1.5",
|
||||||
|
"image-size": "^1.0.0",
|
||||||
"intersection-observer": "^0.11.0",
|
"intersection-observer": "^0.11.0",
|
||||||
"js-sha256": "^0.9.0",
|
"js-sha256": "^0.9.0",
|
||||||
"json-web-key": "^0.4.0",
|
"json-web-key": "^0.4.0",
|
||||||
|
|
@ -21,6 +24,7 @@
|
||||||
"matrix-js-sdk": "^9.4.1",
|
"matrix-js-sdk": "^9.4.1",
|
||||||
"md-gum-polyfill": "^1.0.0",
|
"md-gum-polyfill": "^1.0.0",
|
||||||
"olm": "https://packages.matrix.org/npm/olm/olm-3.2.1.tgz",
|
"olm": "https://packages.matrix.org/npm/olm/olm-3.2.1.tgz",
|
||||||
|
"pretty-bytes": "^5.6.0",
|
||||||
"qrcode": "^1.4.4",
|
"qrcode": "^1.4.4",
|
||||||
"raw-loader": "^4.0.2",
|
"raw-loader": "^4.0.2",
|
||||||
"recordrtc": "^5.6.2",
|
"recordrtc": "^5.6.2",
|
||||||
|
|
@ -4820,6 +4824,14 @@
|
||||||
"node": ">=0.10"
|
"node": ">=0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/data-uri-to-buffer": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/dayjs": {
|
"node_modules/dayjs": {
|
||||||
"version": "1.10.4",
|
"version": "1.10.4",
|
||||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.4.tgz",
|
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.4.tgz",
|
||||||
|
|
@ -7319,6 +7331,28 @@
|
||||||
"node": ">= 4"
|
"node": ">= 4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/image-resize": {
|
||||||
|
"version": "1.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/image-resize/-/image-resize-1.1.5.tgz",
|
||||||
|
"integrity": "sha512-oLSSXVzAmjhwSe36cGNmaSAid8xEXADlS6k+hXqXij3SMPhf9zUI6g3dHuNDV9nVmaD4jja36+k5PWmOiuI1wg==",
|
||||||
|
"dependencies": {
|
||||||
|
"jquery": "^3.4.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/image-size": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-JLJ6OwBfO1KcA+TvJT+v8gbE6iWbj24LyDNFgFEN0lzegn6cC6a/p3NIDaepMsJjQjlUWqIC7wJv8lBFxPNjcw==",
|
||||||
|
"dependencies": {
|
||||||
|
"queue": "6.0.2"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"image-size": "bin/image-size.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/import-cwd": {
|
"node_modules/import-cwd": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
|
||||||
|
|
@ -8167,8 +8201,7 @@
|
||||||
"node_modules/jquery": {
|
"node_modules/jquery": {
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
|
||||||
"integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==",
|
"integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/js-message": {
|
"node_modules/js-message": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
|
|
@ -10782,6 +10815,17 @@
|
||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pretty-bytes": {
|
||||||
|
"version": "5.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
|
||||||
|
"integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/pretty-error": {
|
"node_modules/pretty-error": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz",
|
||||||
|
|
@ -11093,6 +11137,14 @@
|
||||||
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
|
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/queue": {
|
||||||
|
"version": "6.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
|
||||||
|
"integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "~2.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/randombytes": {
|
"node_modules/randombytes": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||||
|
|
@ -19479,6 +19531,11 @@
|
||||||
"assert-plus": "^1.0.0"
|
"assert-plus": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"data-uri-to-buffer": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og=="
|
||||||
|
},
|
||||||
"dayjs": {
|
"dayjs": {
|
||||||
"version": "1.10.4",
|
"version": "1.10.4",
|
||||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.4.tgz",
|
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.4.tgz",
|
||||||
|
|
@ -21454,6 +21511,22 @@
|
||||||
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
|
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"image-resize": {
|
||||||
|
"version": "1.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/image-resize/-/image-resize-1.1.5.tgz",
|
||||||
|
"integrity": "sha512-oLSSXVzAmjhwSe36cGNmaSAid8xEXADlS6k+hXqXij3SMPhf9zUI6g3dHuNDV9nVmaD4jja36+k5PWmOiuI1wg==",
|
||||||
|
"requires": {
|
||||||
|
"jquery": "^3.4.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"image-size": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-JLJ6OwBfO1KcA+TvJT+v8gbE6iWbj24LyDNFgFEN0lzegn6cC6a/p3NIDaepMsJjQjlUWqIC7wJv8lBFxPNjcw==",
|
||||||
|
"requires": {
|
||||||
|
"queue": "6.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"import-cwd": {
|
"import-cwd": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
|
||||||
|
|
@ -22075,8 +22148,7 @@
|
||||||
"jquery": {
|
"jquery": {
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
|
||||||
"integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==",
|
"integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"js-message": {
|
"js-message": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
|
|
@ -24229,6 +24301,11 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"pretty-bytes": {
|
||||||
|
"version": "5.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
|
||||||
|
"integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg=="
|
||||||
|
},
|
||||||
"pretty-error": {
|
"pretty-error": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz",
|
||||||
|
|
@ -24486,6 +24563,14 @@
|
||||||
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
|
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"queue": {
|
||||||
|
"version": "6.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
|
||||||
|
"integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
|
||||||
|
"requires": {
|
||||||
|
"inherits": "~2.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"randombytes": {
|
"randombytes": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,11 @@
|
||||||
"axios": "^0.21.0",
|
"axios": "^0.21.0",
|
||||||
"clean-insights-sdk": "^2.4.1",
|
"clean-insights-sdk": "^2.4.1",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
|
"data-uri-to-buffer": "^3.0.1",
|
||||||
"dayjs": "^1.10.3",
|
"dayjs": "^1.10.3",
|
||||||
"fix-webm-duration": "^1.0.0",
|
"fix-webm-duration": "^1.0.0",
|
||||||
|
"image-resize": "^1.1.5",
|
||||||
|
"image-size": "^1.0.0",
|
||||||
"intersection-observer": "^0.11.0",
|
"intersection-observer": "^0.11.0",
|
||||||
"js-sha256": "^0.9.0",
|
"js-sha256": "^0.9.0",
|
||||||
"json-web-key": "^0.4.0",
|
"json-web-key": "^0.4.0",
|
||||||
|
|
@ -22,6 +25,7 @@
|
||||||
"matrix-js-sdk": "^9.4.1",
|
"matrix-js-sdk": "^9.4.1",
|
||||||
"md-gum-polyfill": "^1.0.0",
|
"md-gum-polyfill": "^1.0.0",
|
||||||
"olm": "https://packages.matrix.org/npm/olm/olm-3.2.1.tgz",
|
"olm": "https://packages.matrix.org/npm/olm/olm-3.2.1.tgz",
|
||||||
|
"pretty-bytes": "^5.6.0",
|
||||||
"qrcode": "^1.4.4",
|
"qrcode": "^1.4.4",
|
||||||
"raw-loader": "^4.0.2",
|
"raw-loader": "^4.0.2",
|
||||||
"recordrtc": "^5.6.2",
|
"recordrtc": "^5.6.2",
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,10 @@
|
||||||
ref="messageOperations"
|
ref="messageOperations"
|
||||||
:style="opStyle"
|
:style="opStyle"
|
||||||
:emojis="recentEmojis"
|
:emojis="recentEmojis"
|
||||||
v-on:close="showContextMenu = false;showContextMenuAnchor = null;"
|
v-on:close="
|
||||||
|
showContextMenu = false;
|
||||||
|
showContextMenuAnchor = null;
|
||||||
|
"
|
||||||
v-if="selectedEvent && showContextMenu"
|
v-if="selectedEvent && showContextMenu"
|
||||||
v-on:addreaction="addReaction"
|
v-on:addreaction="addReaction"
|
||||||
v-on:addquickreaction="addQuickReaction"
|
v-on:addquickreaction="addQuickReaction"
|
||||||
|
|
@ -33,7 +36,10 @@
|
||||||
<avatar-operations
|
<avatar-operations
|
||||||
ref="avatarOperations"
|
ref="avatarOperations"
|
||||||
:style="avatarOpStyle"
|
:style="avatarOpStyle"
|
||||||
v-on:close="showAvatarMenu = false;showAvatarMenuAnchor = null;"
|
v-on:close="
|
||||||
|
showAvatarMenu = false;
|
||||||
|
showAvatarMenuAnchor = null;
|
||||||
|
"
|
||||||
v-on:start-private-chat="startPrivateChat($event)"
|
v-on:start-private-chat="startPrivateChat($event)"
|
||||||
v-if="selectedEvent && showAvatarMenu"
|
v-if="selectedEvent && showAvatarMenu"
|
||||||
:room="room"
|
:room="room"
|
||||||
|
|
@ -47,7 +53,10 @@
|
||||||
@notify="handleChatContainerResize"
|
@notify="handleChatContainerResize"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<CreatedRoomWelcomeHeader v-if="showCreatedRoomWelcomeHeader" v-on:close="closeCreateRoomWelcomeHeader" />
|
<CreatedRoomWelcomeHeader
|
||||||
|
v-if="showCreatedRoomWelcomeHeader"
|
||||||
|
v-on:close="closeCreateRoomWelcomeHeader"
|
||||||
|
/>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-for="(event, index) in events"
|
v-for="(event, index) in events"
|
||||||
|
|
@ -208,17 +217,20 @@
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-col v-if="config.useShortCodeStickers" class="input-area-button text-center flex-grow-0 flex-shrink-1">
|
<v-col
|
||||||
<v-btn
|
v-if="config.useShortCodeStickers"
|
||||||
v-if="!showRecorder"
|
class="input-area-button text-center flex-grow-0 flex-shrink-1"
|
||||||
icon
|
>
|
||||||
large
|
<v-btn
|
||||||
color="black"
|
v-if="!showRecorder"
|
||||||
@click="showStickerPicker"
|
icon
|
||||||
:disabled="attachButtonDisabled"
|
large
|
||||||
>
|
color="black"
|
||||||
<v-icon large>face</v-icon>
|
@click="showStickerPicker"
|
||||||
</v-btn>
|
:disabled="attachButtonDisabled"
|
||||||
|
>
|
||||||
|
<v-icon large>face</v-icon>
|
||||||
|
</v-btn>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-col class="input-area-button text-center flex-grow-0 flex-shrink-1">
|
<v-col class="input-area-button text-center flex-grow-0 flex-shrink-1">
|
||||||
|
|
@ -254,16 +266,52 @@
|
||||||
</v-container>
|
</v-container>
|
||||||
|
|
||||||
<div v-if="currentImageInputPath">
|
<div v-if="currentImageInputPath">
|
||||||
<v-dialog v-model="currentImageInputPath" class="ma-0 pa-0" width="50%">
|
<v-dialog v-model="currentImageInputPath" class="ma-0 pa-0" :width="$vuetify.breakpoint.smAndUp ? '50%' : '85%'">
|
||||||
<v-card class="ma-0 pa-0">
|
<v-card class="ma-0 pa-0">
|
||||||
<v-card-text class="ma-0 pa-0">
|
<v-card-text class="ma-0 pa-2">
|
||||||
<v-img
|
<v-img
|
||||||
v-if="currentImageInput"
|
v-if="currentImageInput && currentImageInput.image"
|
||||||
:aspect-ratio="1"
|
:aspect-ratio="1"
|
||||||
:src="currentImageInput"
|
:src="currentImageInput.image"
|
||||||
contain
|
contain
|
||||||
style="max-height: 50vh"
|
style="max-height: 50vh; background-color: #e2e2e2"
|
||||||
/>
|
/>
|
||||||
|
<div>
|
||||||
|
file: {{ currentImageInputPath.name }}
|
||||||
|
<span
|
||||||
|
v-if="
|
||||||
|
currentImageInput &&
|
||||||
|
currentImageInput.scaled &&
|
||||||
|
currentImageInput.useScaled
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ currentImageInput.scaledDimensions.width }} x
|
||||||
|
{{ currentImageInput.scaledDimensions.height }}</span
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-else-if="currentImageInput && currentImageInput.dimensions"
|
||||||
|
>
|
||||||
|
{{ currentImageInput.dimensions.width }} x
|
||||||
|
{{ currentImageInput.dimensions.height }}</span
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-if="
|
||||||
|
currentImageInput &&
|
||||||
|
currentImageInput.scaled &&
|
||||||
|
currentImageInput.useScaled
|
||||||
|
"
|
||||||
|
>
|
||||||
|
({{ formatBytes(currentImageInput.scaledSize) }})</span
|
||||||
|
>
|
||||||
|
<span v-else>
|
||||||
|
({{ formatBytes(currentImageInputPath.size) }})</span
|
||||||
|
>
|
||||||
|
<v-switch
|
||||||
|
v-if="currentImageInput && currentImageInput.scaled"
|
||||||
|
label="Scale image"
|
||||||
|
v-model="currentImageInput.useScaled"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div v-if="currentSendError">{{ currentSendError }}</div>
|
<div v-if="currentSendError">{{ currentSendError }}</div>
|
||||||
<div v-else>{{ currentSendProgress }}</div>
|
<div v-else>{{ currentSendProgress }}</div>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
|
|
@ -286,22 +334,33 @@
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MessageOperationsBottomSheet ref="messageOperationsSheet" xv-show="showEmojiPicker">
|
<MessageOperationsBottomSheet
|
||||||
|
ref="messageOperationsSheet"
|
||||||
|
xv-show="showEmojiPicker"
|
||||||
|
>
|
||||||
<MessageOperationsPicker
|
<MessageOperationsPicker
|
||||||
v-on:close="showEmojiPicker = false"
|
v-on:close="showEmojiPicker = false"
|
||||||
v-if="selectedEvent"
|
v-if="selectedEvent"
|
||||||
v-on:addreaction="addReaction"
|
v-on:addreaction="addReaction"
|
||||||
v-on:addquickreaction="addQuickReaction"
|
v-on:addquickreaction="addQuickReaction"
|
||||||
v-on:addreply="addReply(selectedEvent)"
|
v-on:addreply="addReply(selectedEvent)"
|
||||||
v-on:edit="edit(selectedEvent)"
|
v-on:edit="edit(selectedEvent)"
|
||||||
v-on:redact="redact(selectedEvent)"
|
v-on:redact="redact(selectedEvent)"
|
||||||
v-on:download="download(selectedEvent)"
|
v-on:download="download(selectedEvent)"
|
||||||
:event="selectedEvent"
|
:event="selectedEvent"
|
||||||
/>
|
/>
|
||||||
<VEmojiPicker ref="emojiPicker" style="width: 100%" @select="emojiSelected" />
|
<VEmojiPicker
|
||||||
|
ref="emojiPicker"
|
||||||
|
style="width: 100%"
|
||||||
|
@select="emojiSelected"
|
||||||
|
/>
|
||||||
</MessageOperationsBottomSheet>
|
</MessageOperationsBottomSheet>
|
||||||
|
|
||||||
<StickerPickerBottomSheet ref="stickerPickerSheet" style="z-index:10" v-on:selectSticker="sendSticker" />
|
<StickerPickerBottomSheet
|
||||||
|
ref="stickerPickerSheet"
|
||||||
|
style="z-index: 10"
|
||||||
|
v-on:selectSticker="sendSticker"
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- "NOT ALLOWED FOR GUEST ACCOUNTS" dialog -->
|
<!-- "NOT ALLOWED FOR GUEST ACCOUNTS" dialog -->
|
||||||
<v-dialog v-model="showNotAllowedForGuests" class="ma-0 pa-0" width="50%">
|
<v-dialog v-model="showNotAllowedForGuests" class="ma-0 pa-0" width="50%">
|
||||||
|
|
@ -324,7 +383,7 @@
|
||||||
<v-container
|
<v-container
|
||||||
fluid
|
fluid
|
||||||
fill-height
|
fill-height
|
||||||
style="position: absolute;background-color:rgba(0,0,0,0.2)"
|
style="position: absolute; background-color: rgba(0, 0, 0, 0.2)"
|
||||||
v-if="!initialLoadDone || loading"
|
v-if="!initialLoadDone || loading"
|
||||||
>
|
>
|
||||||
<v-row align="center" justify="center">
|
<v-row align="center" justify="center">
|
||||||
|
|
@ -342,6 +401,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import Vue from "vue";
|
||||||
import { TimelineWindow, EventTimeline } from "matrix-js-sdk";
|
import { TimelineWindow, EventTimeline } from "matrix-js-sdk";
|
||||||
import MessageIncomingText from "./messages/MessageIncomingText";
|
import MessageIncomingText from "./messages/MessageIncomingText";
|
||||||
import MessageIncomingFile from "./messages/MessageIncomingFile";
|
import MessageIncomingFile from "./messages/MessageIncomingFile";
|
||||||
|
|
@ -373,14 +433,18 @@ import ChatHeader from "./ChatHeader";
|
||||||
import VoiceRecorder from "./VoiceRecorder";
|
import VoiceRecorder from "./VoiceRecorder";
|
||||||
import RoomInfoBottomSheet from "./RoomInfoBottomSheet";
|
import RoomInfoBottomSheet from "./RoomInfoBottomSheet";
|
||||||
import CreatedRoomWelcomeHeader from "./CreatedRoomWelcomeHeader";
|
import CreatedRoomWelcomeHeader from "./CreatedRoomWelcomeHeader";
|
||||||
import MessageOperationsBottomSheet from './MessageOperationsBottomSheet';
|
import MessageOperationsBottomSheet from "./MessageOperationsBottomSheet";
|
||||||
import stickers from '../plugins/stickers';
|
import stickers from "../plugins/stickers";
|
||||||
import StickerPickerBottomSheet from './StickerPickerBottomSheet';
|
import StickerPickerBottomSheet from "./StickerPickerBottomSheet";
|
||||||
import BottomSheet from './BottomSheet.vue';
|
import BottomSheet from "./BottomSheet.vue";
|
||||||
import config from "../assets/config";
|
import config from "../assets/config";
|
||||||
|
import ImageResize from "image-resize";
|
||||||
|
const sizeOf = require("image-size");
|
||||||
|
const dataUriToBuffer = require("data-uri-to-buffer");
|
||||||
|
const prettyBytes = require("pretty-bytes");
|
||||||
|
|
||||||
const READ_RECEIPT_TIMEOUT = 5000; /* How long a message must have been visible before the read marker is updated */
|
const READ_RECEIPT_TIMEOUT = 5000; /* How long a message must have been visible before the read marker is updated */
|
||||||
const WINDOW_BUFFER_SIZE = 0.3 /** Relative window height of when we start paginating. Always keep this much loaded before and after our scroll position! */
|
const WINDOW_BUFFER_SIZE = 0.3; /** Relative window height of when we start paginating. Always keep this much loaded before and after our scroll position! */
|
||||||
|
|
||||||
// from https://kirbysayshi.com/2013/08/19/maintaining-scroll-position-knockoutjs-list.html
|
// from https://kirbysayshi.com/2013/08/19/maintaining-scroll-position-knockoutjs-list.html
|
||||||
function ScrollPosition(node) {
|
function ScrollPosition(node) {
|
||||||
|
|
@ -448,14 +512,14 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
config: config,
|
config: config,
|
||||||
events: [],
|
events: [],
|
||||||
currentInput: "",
|
currentInput: "",
|
||||||
typingMembers: [],
|
typingMembers: [],
|
||||||
timelineWindow: null,
|
timelineWindow: null,
|
||||||
|
|
||||||
/** true if we are currently paginating */
|
/** true if we are currently paginating */
|
||||||
timelineWindowPaginating: false,
|
timelineWindowPaginating: false,
|
||||||
|
|
||||||
scrollPosition: null,
|
scrollPosition: null,
|
||||||
|
|
@ -504,7 +568,7 @@ export default {
|
||||||
showCreatedRoomWelcomeHeader: false,
|
showCreatedRoomWelcomeHeader: false,
|
||||||
|
|
||||||
/** An array of recent emojis. Used in the "message operations" popup. */
|
/** An array of recent emojis. Used in the "message operations" popup. */
|
||||||
recentEmojis: []
|
recentEmojis: [],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -627,7 +691,7 @@ export default {
|
||||||
},
|
},
|
||||||
debugging() {
|
debugging() {
|
||||||
return (window.location.host || "").startsWith("localhost");
|
return (window.location.host || "").startsWith("localhost");
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
|
|
@ -679,13 +743,18 @@ export default {
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onRoomJoined(initialEventId) {
|
onRoomJoined(initialEventId) {
|
||||||
|
|
||||||
// Was this room just created (by you)? Show a small info header in
|
// Was this room just created (by you)? Show a small info header in
|
||||||
// that case!
|
// that case!
|
||||||
const createEvent = this.room.currentState.getStateEvents("m.room.create","");
|
const createEvent = this.room.currentState.getStateEvents(
|
||||||
|
"m.room.create",
|
||||||
|
""
|
||||||
|
);
|
||||||
if (createEvent) {
|
if (createEvent) {
|
||||||
const creatorId = createEvent.getContent().creator;
|
const creatorId = createEvent.getContent().creator;
|
||||||
if (creatorId == this.$matrix.currentUserId && createEvent.getLocalAge() < (5 * 60000) /* 5 minutes */) {
|
if (
|
||||||
|
creatorId == this.$matrix.currentUserId &&
|
||||||
|
createEvent.getLocalAge() < 5 * 60000 /* 5 minutes */
|
||||||
|
) {
|
||||||
this.showCreatedRoomWelcomeHeader = true;
|
this.showCreatedRoomWelcomeHeader = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -713,7 +782,8 @@ export default {
|
||||||
const getMoreIfNeeded = function _getMoreIfNeeded() {
|
const getMoreIfNeeded = function _getMoreIfNeeded() {
|
||||||
const container = self.$refs.chatContainer;
|
const container = self.$refs.chatContainer;
|
||||||
if (
|
if (
|
||||||
container.scrollHeight <= (1 + 2 * WINDOW_BUFFER_SIZE) * container.clientHeight &&
|
container.scrollHeight <=
|
||||||
|
(1 + 2 * WINDOW_BUFFER_SIZE) * container.clientHeight &&
|
||||||
self.timelineWindow &&
|
self.timelineWindow &&
|
||||||
self.timelineWindow.canPaginate(EventTimeline.BACKWARDS)
|
self.timelineWindow.canPaginate(EventTimeline.BACKWARDS)
|
||||||
) {
|
) {
|
||||||
|
|
@ -770,20 +840,27 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
scrollToEndOfTimeline() {
|
scrollToEndOfTimeline() {
|
||||||
if (this.timelineWindow && this.timelineWindow.canPaginate(EventTimeline.FORWARDS)) {
|
if (
|
||||||
|
this.timelineWindow &&
|
||||||
|
this.timelineWindow.canPaginate(EventTimeline.FORWARDS)
|
||||||
|
) {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
// Instead of paging though ALL history, just reload a timeline at the live marker...
|
// Instead of paging though ALL history, just reload a timeline at the live marker...
|
||||||
var timelineWindow = new TimelineWindow(this.$matrix.matrixClient, this.room.getUnfilteredTimelineSet(), {});
|
var timelineWindow = new TimelineWindow(
|
||||||
const self = this;
|
this.$matrix.matrixClient,
|
||||||
timelineWindow
|
this.room.getUnfilteredTimelineSet(),
|
||||||
.load(null, 20)
|
{}
|
||||||
.then(() => {
|
);
|
||||||
self.timelineWindow = timelineWindow;
|
const self = this;
|
||||||
self.events = self.timelineWindow.getEvents();
|
timelineWindow
|
||||||
})
|
.load(null, 20)
|
||||||
.finally(() => {
|
.then(() => {
|
||||||
this.loading = false;
|
self.timelineWindow = timelineWindow;
|
||||||
});
|
self.events = self.timelineWindow.getEvents();
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// Can't paginate, just scroll to bottom of window!
|
// Can't paginate, just scroll to bottom of window!
|
||||||
this.smoothScrollToEnd();
|
this.smoothScrollToEnd();
|
||||||
|
|
@ -876,7 +953,11 @@ export default {
|
||||||
if (event.getSender() != this.$matrix.currentUserId) {
|
if (event.getSender() != this.$matrix.currentUserId) {
|
||||||
if (event.getContent().msgtype == "m.image") {
|
if (event.getContent().msgtype == "m.image") {
|
||||||
// For SVG, make downloadable
|
// For SVG, make downloadable
|
||||||
if (event.getContent().info && event.getContent().info.mimetype && event.getContent().info.mimetype.startsWith("image/svg")) {
|
if (
|
||||||
|
event.getContent().info &&
|
||||||
|
event.getContent().info.mimetype &&
|
||||||
|
event.getContent().info.mimetype.startsWith("image/svg")
|
||||||
|
) {
|
||||||
return MessageIncomingFile;
|
return MessageIncomingFile;
|
||||||
}
|
}
|
||||||
return MessageIncomingImage;
|
return MessageIncomingImage;
|
||||||
|
|
@ -893,7 +974,11 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
if (event.getContent().msgtype == "m.image") {
|
if (event.getContent().msgtype == "m.image") {
|
||||||
// For SVG, make downloadable
|
// For SVG, make downloadable
|
||||||
if (event.getContent().info && event.getContent().info.mimetype && event.getContent().info.mimetype.startsWith("image/svg")) {
|
if (
|
||||||
|
event.getContent().info &&
|
||||||
|
event.getContent().info.mimetype &&
|
||||||
|
event.getContent().info.mimetype.startsWith("image/svg")
|
||||||
|
) {
|
||||||
return MessageOutgoingImage;
|
return MessageOutgoingImage;
|
||||||
}
|
}
|
||||||
return MessageOutgoingImage;
|
return MessageOutgoingImage;
|
||||||
|
|
@ -945,14 +1030,18 @@ export default {
|
||||||
// Scrolled to top
|
// Scrolled to top
|
||||||
this.handleScrolledToTop();
|
this.handleScrolledToTop();
|
||||||
} else if (
|
} else if (
|
||||||
container.scrollHeight - container.scrollTop.toFixed(0) - container.clientHeight <= bufferHeight
|
container.scrollHeight -
|
||||||
|
container.scrollTop.toFixed(0) -
|
||||||
|
container.clientHeight <=
|
||||||
|
bufferHeight
|
||||||
) {
|
) {
|
||||||
this.handleScrolledToBottom(false);
|
this.handleScrolledToBottom(false);
|
||||||
}
|
}
|
||||||
this.showScrollToEnd =
|
this.showScrollToEnd =
|
||||||
container.scrollHeight - container.scrollTop.toFixed(0) >
|
container.scrollHeight - container.scrollTop.toFixed(0) >
|
||||||
container.clientHeight || (this.timelineWindow &&
|
container.clientHeight ||
|
||||||
this.timelineWindow.canPaginate(EventTimeline.FORWARDS));
|
(this.timelineWindow &&
|
||||||
|
this.timelineWindow.canPaginate(EventTimeline.FORWARDS));
|
||||||
|
|
||||||
this.restartRRTimer();
|
this.restartRRTimer();
|
||||||
},
|
},
|
||||||
|
|
@ -1046,16 +1135,68 @@ export default {
|
||||||
if (event.target.files && event.target.files[0]) {
|
if (event.target.files && event.target.files[0]) {
|
||||||
var reader = new FileReader();
|
var reader = new FileReader();
|
||||||
reader.onload = (e) => {
|
reader.onload = (e) => {
|
||||||
|
const file = event.target.files[0];
|
||||||
this.currentSendShowSendButton = true;
|
this.currentSendShowSendButton = true;
|
||||||
this.currentImageInput = e.target.result;
|
if (file.type.startsWith("image/")) {
|
||||||
this.currentImageInputPath = event.target.files[0];
|
this.currentImageInput = {
|
||||||
|
image: e.target.result,
|
||||||
|
dimensions: null,
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
this.currentImageInput.dimensions = sizeOf(
|
||||||
|
dataUriToBuffer(e.target.result)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Need to resize?
|
||||||
|
const w = this.currentImageInput.dimensions.width;
|
||||||
|
const h = this.currentImageInput.dimensions.height;
|
||||||
|
if (w > 640 || h > 640) {
|
||||||
|
var aspect = w / h;
|
||||||
|
var newWidth = parseInt((w > h ? 640 : 640 * aspect).toFixed());
|
||||||
|
var newHeight = parseInt(
|
||||||
|
(w > h ? 640 / aspect : 640).toFixed()
|
||||||
|
);
|
||||||
|
var imageResize = new ImageResize({
|
||||||
|
format: "png",
|
||||||
|
width: newWidth,
|
||||||
|
height: newHeight,
|
||||||
|
outputType: "blob",
|
||||||
|
});
|
||||||
|
imageResize
|
||||||
|
.play(event.target)
|
||||||
|
.then((img) => {
|
||||||
|
Vue.set(
|
||||||
|
this.currentImageInput,
|
||||||
|
"scaled",
|
||||||
|
new File([img], file.name, {
|
||||||
|
type: img.type,
|
||||||
|
lastModified: Date.now(),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
Vue.set(this.currentImageInput, "useScaled", true);
|
||||||
|
Vue.set(this.currentImageInput, "scaledSize", img.size);
|
||||||
|
Vue.set(this.currentImageInput, "scaledDimensions", {
|
||||||
|
width: newWidth,
|
||||||
|
height: newHeight,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error("Resize failed:", err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to get image dimensions: " + error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(this.currentImageInput);
|
||||||
|
this.currentImageInputPath = file;
|
||||||
};
|
};
|
||||||
reader.readAsDataURL(event.target.files[0]);
|
reader.readAsDataURL(event.target.files[0]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
showStickerPicker() {
|
showStickerPicker() {
|
||||||
this.$refs.stickerPickerSheet.open();
|
this.$refs.stickerPickerSheet.open();
|
||||||
},
|
},
|
||||||
|
|
||||||
onUploadProgress(p) {
|
onUploadProgress(p) {
|
||||||
|
|
@ -1068,12 +1209,22 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
sendAttachment(withText) {
|
sendAttachment(withText) {
|
||||||
|
this.$refs.attachment.value = null;
|
||||||
if (this.currentImageInputPath) {
|
if (this.currentImageInputPath) {
|
||||||
|
var inputFile = this.currentImageInputPath;
|
||||||
|
if (
|
||||||
|
this.currentImageInput &&
|
||||||
|
this.currentImageInput.scaled &&
|
||||||
|
this.currentImageInput.useScaled
|
||||||
|
) {
|
||||||
|
// Send scaled version of image instead!
|
||||||
|
inputFile = this.currentImageInput.scaled;
|
||||||
|
}
|
||||||
this.currentSendProgress = null;
|
this.currentSendProgress = null;
|
||||||
this.currentSendOperation = util.sendImage(
|
this.currentSendOperation = util.sendImage(
|
||||||
this.$matrix.matrixClient,
|
this.$matrix.matrixClient,
|
||||||
this.roomId,
|
this.roomId,
|
||||||
this.currentImageInputPath,
|
inputFile,
|
||||||
this.onUploadProgress
|
this.onUploadProgress
|
||||||
);
|
);
|
||||||
this.currentSendOperation
|
this.currentSendOperation
|
||||||
|
|
@ -1095,6 +1246,7 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
cancelSendAttachment() {
|
cancelSendAttachment() {
|
||||||
|
this.$refs.attachment.value = null;
|
||||||
if (this.currentSendOperation) {
|
if (this.currentSendOperation) {
|
||||||
this.currentSendOperation.reject("Canceled");
|
this.currentSendOperation.reject("Canceled");
|
||||||
}
|
}
|
||||||
|
|
@ -1195,7 +1347,7 @@ export default {
|
||||||
showMoreMessageOperations(e) {
|
showMoreMessageOperations(e) {
|
||||||
this.addReaction(e);
|
this.addReaction(e);
|
||||||
},
|
},
|
||||||
|
|
||||||
addReaction(e) {
|
addReaction(e) {
|
||||||
const event = e.event;
|
const event = e.event;
|
||||||
// Store the event we are reacting to, so that we know where to
|
// Store the event we are reacting to, so that we know where to
|
||||||
|
|
@ -1306,21 +1458,26 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
startPrivateChat(e) {
|
startPrivateChat(e) {
|
||||||
this.$matrix.getOrCreatePrivateChat(e.event.getSender())
|
this.$matrix
|
||||||
.then(room => {
|
.getOrCreatePrivateChat(e.event.getSender())
|
||||||
|
.then((room) => {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$navigation.push(
|
this.$navigation.push(
|
||||||
{
|
{
|
||||||
name: "Chat",
|
name: "Chat",
|
||||||
params: { roomId: util.sanitizeRoomId(room.getCanonicalAlias() || room.roomId) },
|
params: {
|
||||||
|
roomId: util.sanitizeRoomId(
|
||||||
|
room.getCanonicalAlias() || room.roomId
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
-1
|
-1
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch((err) => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
closeContextMenusIfOpen(e) {
|
closeContextMenusIfOpen(e) {
|
||||||
|
|
@ -1466,8 +1623,11 @@ export default {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.recentEmojis = [];
|
this.recentEmojis = [];
|
||||||
}
|
},
|
||||||
|
|
||||||
|
formatBytes(bytes) {
|
||||||
|
return prettyBytes(bytes);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -562,7 +562,6 @@ export default {
|
||||||
//
|
//
|
||||||
const createRoomOptions = {
|
const createRoomOptions = {
|
||||||
visibility: "private", // Not listed!
|
visibility: "private", // Not listed!
|
||||||
//name: this.roomName,
|
|
||||||
preset: "private_chat",
|
preset: "private_chat",
|
||||||
initial_state: [
|
initial_state: [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue