import { search as emojiSearch } from '../features/emoji/emoji_mart_search_light';
import { tagHistory } from '../settings';
import { useEmoji } from './emojis';
+import resizeImage from '../utils/resize_image';
import { importFetchedAccounts } from './importer';
import { updateTimeline } from './timelines';
import { showAlertForError } from './alerts';
};
};
-const MAX_IMAGE_DIMENSION = 1280;
-
-const dataURLtoBlob = dataURL => {
- const BASE64_MARKER = ';base64,';
-
- if (dataURL.indexOf(BASE64_MARKER) === -1) {
- const parts = dataURL.split(',');
- const contentType = parts[0].split(':')[1];
- const raw = parts[1];
-
- return new Blob([raw], { type: contentType });
- }
-
- const parts = dataURL.split(BASE64_MARKER);
- const contentType = parts[0].split(':')[1];
- const raw = window.atob(parts[1]);
- const rawLength = raw.length;
-
- const uInt8Array = new Uint8Array(rawLength);
-
- for (let i = 0; i < rawLength; ++i) {
- uInt8Array[i] = raw.charCodeAt(i);
- }
-
- return new Blob([uInt8Array], { type: contentType });
-};
-
-const resizeImage = (inputFile, callback) => {
- if (inputFile.type.match(/image.*/) && inputFile.type !== 'image/gif') {
- const reader = new FileReader();
-
- reader.onload = e => {
- const img = new Image();
-
- img.onload = () => {
- const canvas = document.createElement('canvas');
- const { width, height } = img;
-
- let newWidth, newHeight;
-
- if (width < MAX_IMAGE_DIMENSION && height < MAX_IMAGE_DIMENSION) {
- callback(inputFile);
- return;
- }
-
- if (width > height) {
- newHeight = height * MAX_IMAGE_DIMENSION / width;
- newWidth = MAX_IMAGE_DIMENSION;
- } else if (height > width) {
- newWidth = width * MAX_IMAGE_DIMENSION / height;
- newHeight = MAX_IMAGE_DIMENSION;
- } else {
- newWidth = MAX_IMAGE_DIMENSION;
- newHeight = MAX_IMAGE_DIMENSION;
- }
-
- canvas.width = newWidth;
- canvas.height = newHeight;
-
- canvas.getContext('2d').drawImage(img, 0, 0, newWidth, newHeight);
-
- callback(dataURLtoBlob(canvas.toDataURL(inputFile.type)));
- };
-
- img.src = e.target.result;
- };
-
- reader.readAsDataURL(inputFile);
- } else {
- callback(inputFile);
- }
-};
-
export function uploadCompose(files) {
return function (dispatch, getState) {
if (getState().getIn(['compose', 'media_attachments']).size > 3) {
dispatch(uploadComposeRequest());
- resizeImage(files[0], file => {
- let data = new FormData();
+ resizeImage(files[0]).then(file => {
+ const data = new FormData();
data.append('file', file);
- api(getState).post('/api/v1/media', data, {
- onUploadProgress: function (e) {
- dispatch(uploadComposeProgress(e.loaded, e.total));
- },
- }).then(function (response) {
- dispatch(uploadComposeSuccess(response.data));
- }).catch(function (error) {
- dispatch(uploadComposeFail(error));
- });
- });
+ return api(getState).post('/api/v1/media', data, {
+ onUploadProgress: ({ loaded, total }) => dispatch(uploadComposeProgress(loaded, total)),
+ }).then(({ data }) => dispatch(uploadComposeSuccess(data)));
+ }).catch(error => dispatch(uploadComposeFail(error)));
};
};
import api from '../../api';
+import { decode as decodeBase64 } from '../../utils/base64';
import { pushNotificationsSetting } from '../../settings';
import { setBrowserSupport, setSubscription, clearSubscription } from './setter';
import { me } from '../../initial_state';
.replace(/\-/g, '+')
.replace(/_/g, '/');
- const rawData = window.atob(base64);
- const outputArray = new Uint8Array(rawData.length);
-
- for (let i = 0; i < rawData.length; ++i) {
- outputArray[i] = rawData.charCodeAt(i);
- }
- return outputArray;
+ return decodeBase64(base64);
};
const getApplicationServerKey = () => document.querySelector('[name="applicationServerKey"]').getAttribute('content');
import assign from 'object-assign';
import values from 'object.values';
import isNaN from 'is-nan';
+import { decode as decodeBase64 } from './utils/base64';
if (!Array.prototype.includes) {
includes.shim();
if (!Number.isNaN) {
Number.isNaN = isNaN;
}
+
+if (!HTMLCanvasElement.prototype.toBlob) {
+ const BASE64_MARKER = ';base64,';
+
+ Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
+ value(callback, type = 'image/png', quality) {
+ const dataURL = this.toDataURL(type, quality);
+ let data;
+
+ if (dataURL.indexOf(BASE64_MARKER) >= 0) {
+ const [, base64] = dataURL.split(BASE64_MARKER);
+ data = decodeBase64(base64);
+ } else {
+ [, data] = dataURL.split(',');
+ }
+
+ callback(new Blob([data], { type }));
+ },
+ });
+}
function loadPolyfills() {
const needsBasePolyfills = !(
+ Array.prototype.includes &&
+ HTMLCanvasElement.prototype.toBlob &&
window.Intl &&
+ Number.isNaN &&
Object.assign &&
Object.values &&
- Number.isNaN &&
- window.Symbol &&
- Array.prototype.includes
+ window.Symbol
);
// Latest version of Firefox and Safari do not have IntersectionObserver.
--- /dev/null
+import * as base64 from '../base64';
+
+describe('base64', () => {
+ describe('decode', () => {
+ it('returns a uint8 array', () => {
+ const arr = base64.decode('dGVzdA==');
+ expect(arr).toEqual(new Uint8Array([116, 101, 115, 116]));
+ });
+ });
+});
--- /dev/null
+export const decode = base64 => {
+ const rawData = window.atob(base64);
+ const outputArray = new Uint8Array(rawData.length);
+
+ for (let i = 0; i < rawData.length; ++i) {
+ outputArray[i] = rawData.charCodeAt(i);
+ }
+
+ return outputArray;
+};
--- /dev/null
+const MAX_IMAGE_DIMENSION = 1280;
+
+const getImageUrl = inputFile => new Promise((resolve, reject) => {
+ if (window.URL && URL.createObjectURL) {
+ try {
+ resolve(URL.createObjectURL(inputFile));
+ } catch (error) {
+ reject(error);
+ }
+ return;
+ }
+
+ const reader = new FileReader();
+ reader.onerror = (...args) => reject(...args);
+ reader.onload = ({ target }) => resolve(target.result);
+
+ reader.readAsDataURL(inputFile);
+});
+
+const loadImage = inputFile => new Promise((resolve, reject) => {
+ getImageUrl(inputFile).then(url => {
+ const img = new Image();
+
+ img.onerror = (...args) => reject(...args);
+ img.onload = () => resolve(img);
+
+ img.src = url;
+ }).catch(reject);
+});
+
+export default inputFile => new Promise((resolve, reject) => {
+ if (!inputFile.type.match(/image.*/) || inputFile.type === 'image/gif') {
+ resolve(inputFile);
+ return;
+ }
+
+ loadImage(inputFile).then(img => {
+ const canvas = document.createElement('canvas');
+ const { width, height } = img;
+
+ let newWidth, newHeight;
+
+ if (width < MAX_IMAGE_DIMENSION && height < MAX_IMAGE_DIMENSION) {
+ resolve(inputFile);
+ return;
+ }
+
+ if (width > height) {
+ newHeight = height * MAX_IMAGE_DIMENSION / width;
+ newWidth = MAX_IMAGE_DIMENSION;
+ } else if (height > width) {
+ newWidth = width * MAX_IMAGE_DIMENSION / height;
+ newHeight = MAX_IMAGE_DIMENSION;
+ } else {
+ newWidth = MAX_IMAGE_DIMENSION;
+ newHeight = MAX_IMAGE_DIMENSION;
+ }
+
+ canvas.width = newWidth;
+ canvas.height = newHeight;
+
+ canvas.getContext('2d').drawImage(img, 0, 0, newWidth, newHeight);
+
+ canvas.toBlob(resolve, inputFile.type);
+ }).catch(reject);
+});