Skip to content

Commit 06e6d7f

Browse files
authored
Merge pull request #7 from codediodeio/tk2217-master
Tk2217 master - Add support for Firebase Storage
2 parents b6ade27 + abfb528 commit 06e6d7f

File tree

6 files changed

+385
-7
lines changed

6 files changed

+385
-7
lines changed

README.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,3 +436,84 @@ Slot Props & Events:
436436
```
437437

438438
Note: Each data item in the collection contains the document data AND fields for the `id` and `ref` (DocumentReference).
439+
440+
### `<StorageRef>`
441+
442+
Retrives a downloadURL and metada from Firebase storage.
443+
444+
Props:
445+
446+
- *path (required)* to file in storage i.e `images/mountain.jpg` or a [Reference](https://firebase.google.com/docs/reference/js/firebase.storage.Reference)
447+
- *meta* include metadata with file. Default `false`.
448+
- *startWith* start with a default URL. Pass an object like `{ url: someURL }`
449+
450+
Slots:
451+
452+
- *default slot* shown when downloadURL is available.
453+
- *loading* shown when waiting for response.
454+
- *fallback* shown when error occurs.
455+
456+
457+
Slot Props & Events:
458+
459+
- *downloadURL* url to resource
460+
- *metadata* file metadata
461+
- *ref* Storage Reference for direct access
462+
463+
```html
464+
<StorageRef {path} let:downloadURL let:ref meta let:metadata>
465+
466+
<img src={downloadURL} />
467+
468+
<div slot="loading">
469+
Loading...
470+
</div>
471+
472+
<div slot="fallback">
473+
Error
474+
</div>
475+
476+
</StorageRef>
477+
```
478+
479+
### `<UploadTask>`
480+
481+
Creates an [UploadTask](https://firebase.google.com/docs/reference/js/firebase.storage.UploadTask) that transmits a file to Firebase storage.
482+
483+
Props:
484+
485+
- *path (required)* to upload to i.e "images/mountain.jpg" or a [Reference](https://firebase.google.com/docs/reference/js/firebase.storage.Reference)
486+
- *file* file to upload as a `File` object `Blob` or `Unit8Array`.
487+
-
488+
489+
Slots:
490+
491+
- *default slot* shown while task is created.
492+
- *complete* shown when task state is `success` and url is available.
493+
- *fallback* shown when error occurs or upload is cancelled.
494+
495+
496+
Slot Props & Events:
497+
498+
- *snapshot* snapshot of upload, useful for monitoring progress.
499+
- *task* Firebase upload task. Use it to pause, resume, and cancel. `task.pause()`
500+
- *downLoadURL* url to uploaded file.
501+
502+
503+
```html
504+
<UploadTask {file} {path} let:task let:snapshot let:downloadURL={url}>
505+
506+
Uploading your file...
507+
508+
Progress: {(snapshot.bytesTransferred / snapshot.totalBytes) * 100} %
509+
510+
<div slot="complete">
511+
Success! Download here {url}
512+
</div>
513+
514+
<div slot="fallback">
515+
Error or canceled
516+
</div>
517+
518+
</UploadTask>
519+
```

example/src/App.svelte

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
export let name;
33
import { writable } from "svelte/store";
44
import { onMount } from "svelte";
5-
import { FirebaseApp, Doc, Collection, User } from "sveltefire";
5+
import { FirebaseApp, Doc, Collection, User, UploadTask, StorageRef } from "sveltefire";
66
77
import firebase from "firebase/app";
88
import "firebase/firestore";
99
import "firebase/auth";
10+
import "firebase/storage";
1011
import "firebase/performance"; // Optional
1112
import "firebase/analytics"; // Optional
1213
@@ -28,6 +29,8 @@
2829
let eventData = {};
2930
let eventRef = {};
3031
32+
let readyToUpload = false;
33+
3134
function onData(e) {
3235
eventData = e.detail.data;
3336
}
@@ -61,14 +64,18 @@
6164
</script>
6265

6366
<style>
64-
67+
h1 {
68+
border-bottom: 1px dashed rgb(185, 185, 185);
69+
}
6570
</style>
6671

6772
<FirebaseApp {firebase} on:initializeApp={useEmulator} perf analytics>
6873

69-
<h1>Firebase Ready {appName}</h1>
74+
<h1>FirebaseApp</h1>
75+
76+
<p>Firebase Ready {appName}</p>
7077

71-
<h1>User Login</h1>
78+
<h1>User</h1>
7279
<User let:user let:auth>
7380

7481
<div slot="signed-out">
@@ -82,7 +89,7 @@
8289
UID: {user.uid}
8390
<button on:click={() => auth.signOut()}>Sign Out</button>
8491

85-
<h2>Firestore</h2>
92+
<h1>Firestore</h1>
8693

8794
<Doc path={`posts/first-post`} let:data={post} let:ref={postRef} log>
8895
<div slot="loading">Loading...</div>
@@ -176,7 +183,7 @@
176183
</Doc>
177184

178185

179-
<h2>Events</h2>
186+
<h3>Events</h3>
180187

181188
<p>Path: {eventRef.path}</p>
182189
<p>Event Data: {eventData && eventData.title}</p>
@@ -185,4 +192,43 @@
185192
</button>
186193

187194
<Doc path={'posts/event-post'} on:data={onData} on:ref={onRef} />
195+
196+
197+
198+
199+
<h1>Storage</h1>
200+
201+
<button on:click={(e) => readyToUpload = true }>Start Upload</button>
202+
203+
{#if readyToUpload}
204+
205+
<h3>UploadTask:</h3>
206+
207+
<UploadTask path={'myfile.txt'} file={new File(['hello world'], 'filename')} let:task let:snapshot let:downloadURL>
208+
209+
Progress {(snapshot.bytesTransferred / snapshot.totalBytes) * 100} <br>
210+
State {snapshot.state}
211+
212+
<button on:click={() => task.pause()}>Pause</button>
213+
214+
<div slot="complete">DownloadURL: {downloadURL}</div>
215+
216+
</UploadTask>
217+
218+
{/if}
219+
220+
221+
<h3>File</h3>
222+
223+
<StorageRef path={'myfile.txt'} meta let:metadata let:downloadURL>
224+
225+
URL: {downloadURL} <br>
226+
Meta: {JSON.stringify(metadata)}
227+
228+
<div slot="loading">Loading file...</div>
229+
</StorageRef>
230+
231+
188232
</FirebaseApp>
233+
234+
<div style="height: 500px"></div>

src/StorageRef.svelte

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<script>
2+
export let path = "";
3+
export let log = false;
4+
export let traceId = "";
5+
export let startWith = undefined;
6+
export let url = true;
7+
export let meta = false;
8+
9+
import { onDestroy, onMount, createEventDispatcher } from "svelte";
10+
import { fileDownloadStore } from "./storage";
11+
12+
const opts = {
13+
startWith,
14+
traceId,
15+
log,
16+
meta,
17+
url,
18+
};
19+
20+
let store = fileDownloadStore(path, opts);
21+
22+
const dispatch = createEventDispatcher();
23+
24+
let unsub;
25+
26+
// Props changed
27+
$: {
28+
if (unsub) {
29+
// Unsub and create new store
30+
unsub();
31+
store = fileDownloadStore(path, opts);
32+
dispatch("ref", { ref: store.ref });
33+
}
34+
35+
unsub = store.subscribe(result => {
36+
if (result) {
37+
dispatch("storageResult", {
38+
downloadURL: result[0],
39+
metadata: result[1],
40+
});
41+
}
42+
43+
});
44+
}
45+
46+
onMount(() => dispatch("ref", { ref: store.ref }));
47+
onDestroy(() => unsub());
48+
</script>
49+
50+
<slot name="before" />
51+
52+
{#if $store}
53+
<slot
54+
downloadURL={$store && $store.url}
55+
metadata={$store && $store.metadata}
56+
ref={store.ref}
57+
error={store.error} />
58+
{:else if store.loading}
59+
<slot name="loading" />
60+
{:else}
61+
<slot name="fallback" />
62+
{/if}
63+
64+
<slot name="after" />

src/UploadTask.svelte

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<script>
2+
export let path;
3+
export let file;
4+
export let log = false;
5+
export let traceId = "";
6+
7+
import { onDestroy, onMount, createEventDispatcher } from "svelte";
8+
import { uploadTaskStore } from "./storage";
9+
10+
const opts = {
11+
traceId,
12+
log,
13+
}
14+
15+
let store = uploadTaskStore(path, file, opts);
16+
17+
const dispatch = createEventDispatcher();
18+
19+
let unsub;
20+
21+
// Props changed
22+
$: {
23+
if (unsub) {
24+
// Unsub and create new store
25+
unsub();
26+
store = uploadTaskStore(path, file, opts);
27+
dispatch("ref", { ref: store.ref });
28+
}
29+
30+
unsub = store.subscribe(snapshot => {
31+
dispatch("snapshot", {
32+
snapshot
33+
});
34+
});
35+
}
36+
37+
onMount(() => dispatch("ref", { ref: store.ref }))
38+
onDestroy(() => unsub());
39+
</script>
40+
41+
<slot name="before" />
42+
43+
{#if $store}
44+
<slot
45+
snapshot={$store}
46+
ref={store.ref}
47+
task={store.task}
48+
downloadURL={store.downloadURL}
49+
error={store.error} />
50+
{:else}
51+
<slot name="fallback" />
52+
{/if}
53+
54+
{#if store.downloadURL}
55+
<slot name="complete" />
56+
{/if}
57+
58+
<slot name="after" />

src/index.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import Doc from './Doc.svelte';
44
import Collection from './Collection.svelte';
55
import { userStore } from './auth';
66
import { docStore, collectionStore } from './firestore';
7-
7+
import { fileDownloadStore, uploadTaskStore } from './storage';
8+
import StorageRef from './StorageRef.svelte';
9+
import UploadTask from './UploadTask.svelte';
810

911
export {
1012
FirebaseApp,
@@ -14,4 +16,8 @@ export {
1416
userStore,
1517
docStore,
1618
collectionStore,
19+
fileDownloadStore,
20+
uploadTaskStore,
21+
StorageRef,
22+
UploadTask,
1723
}

0 commit comments

Comments
 (0)