Skip to content
This repository has been archived by the owner on Jan 29, 2019. It is now read-only.

Commit

Permalink
feat: improving XHR adapter
Browse files Browse the repository at this point in the history
  • Loading branch information
alexsasharegan committed Feb 17, 2018
1 parent 9c4f1b6 commit 82baf15
Show file tree
Hide file tree
Showing 10 changed files with 474 additions and 369 deletions.
336 changes: 181 additions & 155 deletions package-lock.json

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,22 @@
},
"dependencies": {},
"devDependencies": {
"@types/jest": "^22.1.1",
"@types/jest": "^22.1.3",
"cross-env": "^5.1.3",
"jest": "^22.2.1",
"jest": "^22.3.0",
"lodash": "^4.17.5",
"postcss": "^6.0.17",
"postcss": "^6.0.18",
"rimraf": "^2.6.2",
"rollup": "^0.55.3",
"rollup": "^0.56.1",
"rollup-plugin-postcss": "^1.2.8",
"rollup-plugin-typescript": "^0.8.1",
"rollup-plugin-typescript2": "^0.11.0",
"rollup-plugin-typescript2": "^0.11.1",
"rollup-plugin-uglify": "^3.0.0",
"rollup-plugin-vue": "^3.0.0",
"standard-version": "^4.3.0",
"ts-jest": "^22.0.3",
"typescript": "^2.7.1",
"uglify-js": "^3.3.10",
"ts-jest": "^22.0.4",
"typescript": "^2.7.2",
"uglify-js": "^3.3.11",
"vue": "^2.5.13",
"vue-template-compiler": "^2.5.13"
},
Expand Down
4 changes: 2 additions & 2 deletions src/classes/VTransmitFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export class VTransmitFile {
}

set dataUrl(value) {
// Use non-enumerable data url to avoid copying around large datasets
// Use non-enumerable data url to avoid copying around large data sets
Object.defineProperty(this, "_dataUrl", {
value,
enumerable: false,
Expand All @@ -110,6 +110,6 @@ export class VTransmitFile {
}

static idFactory() {
return uniqueId("v-transmit-file-");
return uniqueId("vt_");
}
}
3 changes: 1 addition & 2 deletions src/classes/VTransmitUploadContext.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import VueTransmit from "../components/VueTransmit.vue";
import { VTransmitFile } from "./VTransmitFile";
import { UploadStatuses, VTransmitEvents } from "../core/utils";
import { UploadStatuses } from "../core/utils";

export class VTransmitUploadContext {
public Statuses = UploadStatuses;
public Events = VTransmitEvents;
public props: AnyObject;

constructor(public vtransmit: VueTransmit) {
Expand Down
119 changes: 62 additions & 57 deletions src/components/VueTransmit.vue
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,13 @@ import {
UploadStatuses,
VTransmitEvents as Events,
round,
expectNever,
ErrType,
} from "../core/utils";
import { VTransmitFile } from "../classes/VTransmitFile";
import { VTransmitUploadContext } from "../classes/VTransmitUploadContext";
import { XHRUploadAdapter } from "../upload-adapters/xhr";
import { UploaderInterface, UploadReject } from "../core/interfaces";
import { UploaderInterface } from "../core/interfaces";
type FileSystemEntry = WebKitFileEntry | WebKitDirectoryEntry;
Expand Down Expand Up @@ -665,25 +667,24 @@ export default Vue.extend({
imgEl.src = imageUrl;
},
processQueue(): void {
const processingLength = this.uploadingFiles.length;
const len_uploading = this.uploadingFiles.length;
if (
processingLength >= this.maxConcurrentUploads ||
len_uploading >= this.maxConcurrentUploads ||
this.queuedFiles.length === 0
) {
return;
}
const queuedFiles = [...this.queuedFiles];
if (this.uploadMultiple) {
return this.processFiles(
queuedFiles.slice(0, this.maxConcurrentUploads - processingLength)
this.queuedFiles.slice(0, this.maxConcurrentUploads - len_uploading)
);
}
let i = processingLength;
let i = len_uploading;
let file: VTransmitFile | undefined;
for (; i < this.maxConcurrentUploads; i++) {
if ((file = queuedFiles.shift())) {
if ((file = this.queuedFiles.shift())) {
this.processFile(file);
}
}
Expand Down Expand Up @@ -739,26 +740,27 @@ export default Vue.extend({
this.uploadFiles([file]);
},
uploadFiles(files: VTransmitFile[]): void {
this.transport
.uploadFiles(files)
.then(response => this.uploadFinished(files, response))
.catch((err: UploadReject) => {
switch (err.event) {
case Events.Timeout:
this.handleTimeout(files, err.message, err.data);
break;
case Events.Error:
default:
this.errorProcessing(files, err.message, err.data);
break;
}
});
this.transport.uploadFiles(files).then(result => {
if (result.ok) {
return this.uploadFinished(files, result.data);
}
switch (result.err.type) {
case ErrType.Any:
this.errorProcessing(files, result.err.message, result.err.data);
break;
case ErrType.Timeout:
this.handleTimeout(files, result.err.message, result.err.data);
break;
default:
expectNever(result.err.type, "unmatched error case");
break;
}
});
},
handleTimeout(
files: VTransmitFile[],
message: string,
data: AnyObject
): void {
handleTimeout(files: VTransmitFile[], message: string, data: any): void {
let f: VTransmitFile;
for (f of files) {
f.status = UploadStatuses.Timeout;
Expand Down Expand Up @@ -809,11 +811,7 @@ export default Vue.extend({
this.processQueue();
}
},
errorProcessing(
files: VTransmitFile[],
message: string,
data: AnyObject = {}
) {
errorProcessing(files: VTransmitFile[], message: string, data?: any) {
for (const file of files) {
file.status = UploadStatuses.Error;
file.endProgress();
Expand All @@ -834,34 +832,41 @@ export default Vue.extend({
if (!acceptedFileTypes.length) {
return true;
}
const mimeType = file.type;
const baseMimeType = mimeType.replace(/\/.*$/, "");
const mime_type = file.type;
const base_type = mime_type.slice(0, mime_type.indexOf("/"));
let valid_type: string;
// Return true on the first condition match,
// otherwise exhaust all conditions and return false.
for (let i = 0; i < acceptedFileTypes.length; i++) {
const validType = acceptedFileTypes[i];
if (validType.charAt(0) === ".") {
for (valid_type of acceptedFileTypes) {
switch (true) {
// Handle extension validation
// Ensure extension exists at the end of the filename.
if (
file.name
.toLowerCase()
.indexOf(
validType.toLowerCase(),
file.name.length - validType.length
) !== -1
) {
return true;
}
} else if (/\/\*$/.test(validType)) {
// Handle globbed mimetype validation ("image/*")
if (baseMimeType === validType.replace(/\/.*$/, "")) {
return true;
}
} else {
if (mimeType === validType) {
return true;
}
case valid_type.charAt(0) == ".":
// Ensure extension exists at the end of the filename.
if (
file.name
.toLowerCase()
.indexOf(
valid_type.toLowerCase(),
file.name.length - valid_type.length
) !== -1
) {
return true;
}
break;
// Handle globs ("image/*")
case valid_type.slice(-2) == "/*":
if (base_type === valid_type.slice(0, -2)) {
return true;
}
break;
// Match mimetype exact
default:
if (mime_type == valid_type) {
return true;
}
break;
}
}
Expand Down Expand Up @@ -979,7 +984,7 @@ export default Vue.extend({
if (webkitIsFile(entry)) {
entry.file(
<any>((file: File) => {
if (this.ignoreHiddenFiles && /^\./.test(file.name)) {
if (this.ignoreHiddenFiles && file.name.charAt(0) == ".") {
return;
}
(file as any).fullPath = `${path}/${file.name}`;
Expand Down
29 changes: 18 additions & 11 deletions src/core/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,36 @@
import { VTransmitFile } from "../classes/VTransmitFile";
import { VTransmitUploadContext } from "../classes/VTransmitUploadContext";
import { VTransmitEvents } from "../core/utils";
import { ErrType } from "../core/utils";

export interface UploaderConstructor {
export interface UploaderConstructor<T = any> {
new (
context: VTransmitUploadContext,
options: { [key: string]: any }
): UploaderInterface;
): UploaderInterface<T>;
}

export interface UploaderInterface {
export interface UploaderInterface<T = any> {
/**
* Given a file, cancel it's underlying transport
* and return a list of affected files
* (since files can be grouped in transport).
*/
cancelUpload(file: VTransmitFile): VTransmitFile[];
uploadFiles(files: VTransmitFile[]): Promise<UploadResolve>;
uploadFiles(files: VTransmitFile[]): Promise<UploadResult<T>>;
}

export type UploadResolve = {
[key: string]: any;
};
export type UploadReject = {
event: VTransmitEvents;
export type UploadResult<T> =
| {
readonly ok: true;
data: T;
}
| {
readonly ok: false;
err: UploadErr;
};

export type UploadErr = {
type: ErrType;
message: string;
data: AnyObject;
data: any;
};
9 changes: 9 additions & 0 deletions src/core/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ export function scaleW(ratio: number, height: number): number {
return height * ratio;
}

export function expectNever(_: never, msg: string): never {
throw new Error(msg);
}

export enum UploadStatuses {
None = "",
Added = "added",
Expand All @@ -52,6 +56,11 @@ export enum UploadStatuses {
Success = "success",
}

export enum ErrType {
Any,
Timeout,
}

export enum VTransmitEvents {
Initialize = "initialize",
AddedFile = "added-file",
Expand Down
Loading

0 comments on commit 82baf15

Please sign in to comment.