UNPKG

4.66 kBJavaScriptView Raw
1// @flow
2
3import { NativeEventEmitter, NativeModules } from 'react-native';
4import UUID from 'uuid-js';
5
6const { ExponentFileSystem: FS } = NativeModules;
7
8const normalizeEndingSlash = p => p.replace(/\/*$/, '') + '/';
9
10FS.documentDirectory = normalizeEndingSlash(FS.documentDirectory);
11FS.cacheDirectory = normalizeEndingSlash(FS.cacheDirectory);
12
13export const documentDirectory = FS.documentDirectory;
14export const cacheDirectory = FS.cacheDirectory;
15
16type FileInfo =
17 | {
18 exists: true,
19 uri: string,
20 size: number,
21 modificationTime: number,
22 md5?: string,
23 }
24 | {
25 exists: false,
26 isDirectory: false,
27 };
28
29export function getInfoAsync(fileUri: string, options: { md5?: boolean } = {}): Promise<FileInfo> {
30 return FS.getInfoAsync(fileUri, options);
31}
32
33export function readAsStringAsync(fileUri: string): Promise<string> {
34 return FS.readAsStringAsync(fileUri, {});
35}
36
37export function writeAsStringAsync(fileUri: string, contents: string): Promise<void> {
38 return FS.writeAsStringAsync(fileUri, contents, {});
39}
40
41export function deleteAsync(
42 fileUri: string,
43 options: { idempotent?: boolean } = {}
44): Promise<void> {
45 return FS.deleteAsync(fileUri, options);
46}
47
48export function moveAsync(options: { from: string, to: string }): Promise<void> {
49 return FS.moveAsync(options);
50}
51
52export function copyAsync(options: { from: string, to: string }): Promise<void> {
53 return FS.copyAsync(options);
54}
55
56export function makeDirectoryAsync(
57 fileUri: string,
58 options: { intermediates?: boolean } = {}
59): Promise<void> {
60 return FS.makeDirectoryAsync(fileUri, options);
61}
62
63export function readDirectoryAsync(fileUri: string): Array<string> {
64 return FS.readDirectoryAsync(fileUri, {});
65}
66
67type DownloadOptions = {
68 md5?: boolean,
69 headers?: { [string]: string },
70};
71type DownloadResult = {
72 uri: string,
73 status: number,
74 headers: { [string]: string },
75 md5?: string,
76};
77
78export function downloadAsync(
79 uri: string,
80 fileUri: string,
81 options: DownloadOptions = {}
82): Promise<DownloadResult> {
83 return FS.downloadAsync(uri, fileUri, options);
84}
85
86export function createDownloadResumable(
87 uri: string,
88 fileUri: string,
89 options?: DownloadOptions,
90 callback?: DownloadProgressCallback,
91 resumeData?: string
92) {
93 return new DownloadResumable(uri, fileUri, options, callback, resumeData);
94}
95
96type DownloadProgressCallback = (data: DownloadProgressData) => void;
97type DownloadProgressData = {
98 totalBytesWritten: number,
99 totalBytesExpectedToWrite: number,
100};
101type DownloadPauseState = {
102 url: string,
103 fileUri: string,
104 options: DownloadOptions,
105 resumeData: ?string,
106};
107
108export class DownloadResumable {
109 _uuid: string;
110 _url: string;
111 _fileUri: string;
112 _options: DownloadOptions;
113 _resumeData: ?string;
114 _callback: ?DownloadProgressCallback;
115 _subscription: ?Function;
116 _emitter: NativeEventEmitter;
117
118 constructor(
119 url: string,
120 fileUri: string,
121 options: DownloadOptions = {},
122 callback: ?DownloadProgressCallback,
123 resumeData: ?string
124 ) {
125 this._uuid = UUID.create(4).toString();
126 this._url = url;
127 this._fileUri = fileUri;
128 this._options = options;
129 this._resumeData = resumeData;
130 this._callback = callback;
131 this._subscription = null;
132 this._emitter = new NativeEventEmitter(FS);
133 }
134
135 async downloadAsync(): Promise<?DownloadResult> {
136 this._addSubscription();
137 return await FS.downloadResumableStartAsync(
138 this._url,
139 this._fileUri,
140 this._uuid,
141 this._options,
142 this._resumeData
143 );
144 }
145
146 async pauseAsync(): Promise<DownloadPauseState> {
147 const pauseResult = await FS.downloadResumablePauseAsync(this._uuid);
148 if (pauseResult) {
149 this._resumeData = pauseResult.resumeData;
150 return this.savable();
151 } else {
152 throw new Error('Unable to generate a savable pause state');
153 }
154 }
155
156 async resumeAsync(): Promise<?DownloadResult> {
157 this._addSubscription();
158 return await FS.downloadResumableStartAsync(
159 this._url,
160 this._fileUri,
161 this._uuid,
162 this._options,
163 this._resumeData
164 );
165 }
166
167 savable(): DownloadPauseState {
168 return {
169 url: this._url,
170 fileUri: this._fileUri,
171 options: this._options,
172 resumeData: this._resumeData,
173 };
174 }
175
176 _addSubscription(): void {
177 if (this._subscription) {
178 return;
179 }
180 this._subscription = this._emitter.addListener(
181 'Exponent.downloadProgress',
182 ({ uuid, data }) => {
183 if (uuid === this._uuid) {
184 const callback = this._callback;
185 if (callback) {
186 callback(data);
187 }
188 }
189 }
190 );
191 }
192}