Skip to content

Commit

Permalink
add live notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
Roman Abendroth committed Nov 10, 2023
1 parent 062cf63 commit decc9f7
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 40 deletions.
2 changes: 1 addition & 1 deletion rules/firestore.rules
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ service cloud.firestore {

match /notifications/{notificationId} {
allow read: if isAuthenticated();
allow write: if false;
allow write: if isAuthenticated();
allow create: if false;
allow update: if false;
}
Expand Down
48 changes: 12 additions & 36 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<script lang="ts" context="module">
import type { Readable } from "svelte/store";
type FirebaseStoreData = {
app: FirebaseApp | null;
auth: Auth | null;
app: FirebaseApp;
};
export type FirebaseStore = Readable<FirebaseStoreData>;
Expand All @@ -17,54 +18,29 @@
import {
browserSessionPersistence,
getAuth,
onAuthStateChanged,
onIdTokenChanged,
signOut,
type Auth,
type Unsubscribe
} from 'firebase/auth';
import Cookies from 'js-cookie';
import { onDestroy, setContext } from 'svelte';
import { Icon, Plus } from 'svelte-hero-icons';
import { readonly, writable, type Readable, type Writable } from 'svelte/store';
import { goto } from '$app/navigation';
import { readonly, writable, type Writable } from 'svelte/store';
import { enhance } from '$app/forms';
import type { Auth } from 'firebase/auth';
const subscriptions: Unsubscribe[] = [];
const app = initializeApp(config);
const firebaseStore: Writable<FirebaseStoreData> = writable({
app: null,
auth: null
app,
});
setContext('firebase', readonly(firebaseStore));
let auth: Auth;
if (browser) {
// Initialize Firebase
const app = initializeApp(config);
const auth = getAuth(app);
auth = getAuth(app);
auth.setPersistence(browserSessionPersistence).catch(console.error);
subscriptions.push(
onAuthStateChanged(auth, () => {
firebaseStore.set({
app,
auth
});
})
);
subscriptions.push(
onIdTokenChanged(auth, (user) => {
user
?.getIdToken()
.then((token) => Cookies.set('idToken', token, {expires: 1 / 24, sameSite: 'Strict'}))
.catch(console.error);
})
);
}
setContext('firebase', readonly(firebaseStore));
let isLoggingOut = false;
onDestroy(() => {
Expand All @@ -80,7 +56,7 @@
<li><strong>Plant Care Assistant</strong></li>
</ul>
<ul>
{#if $firebaseStore.auth?.currentUser}
{#if auth?.currentUser}
<li>
<a href="/app/create-plant" role="button" class="outline"
>
Expand All @@ -92,7 +68,7 @@
<form method="POST" action="/login?/logout" use:enhance={async () => {
isLoggingOut = true;
try {
await signOut($firebaseStore.auth)
await signOut(auth)
} catch(e) {
console.error(e)
} finally {
Expand Down
59 changes: 58 additions & 1 deletion src/routes/app/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,48 @@
import { getContext } from 'svelte';
import type { FirebaseStore } from '../+layout.svelte';
import PlantCard from '$lib/components/PlantCard.svelte';
import { BellAlert, Icon } from "svelte-hero-icons";
import { onSnapshot, getFirestore, query, collection, where, Timestamp } from "firebase/firestore";
import type { FirebaseApp } from "firebase/app";
import { browser } from "$app/environment";
import { getAuth, onAuthStateChanged } from "firebase/auth";
const firebase = getContext<FirebaseStore>('firebase');
export let data;
$: user = $firebase.auth?.currentUser;
const auth = getAuth($firebase.app!);
$: user = auth.currentUser;
$: notification = "";
$: hasNotification = notification !== "";
if (browser) {
onAuthStateChanged(auth, (user) => {
if (user) {
const firebaseApp: FirebaseApp = $firebase.app!;
const firestore = getFirestore(firebaseApp);
const q = query(
collection(firestore, "notifications"),
where("owner", "==", user.uid),
where("createdAt", ">=", Timestamp.fromDate(new Date()))
);
onSnapshot(
q,
(querySnapshot) => {
querySnapshot.forEach((doc) => {
console.log("notification");
console.log(doc.data());
notification = doc.data().message;
});
});
}
});
}
function resetNotification() {
notification = "";
}
</script>

{#if !user}
Expand All @@ -23,6 +59,13 @@
{#each data.plants as plant}
<PlantCard {plant} />
{/each}
{#if hasNotification}
<div class="notification">
<Icon src={BellAlert} width={20} />
<span>{notification}</span>
<button on:click={resetNotification}>X</button>
</div>
{/if}
</div>
{/if}

Expand All @@ -45,4 +88,18 @@
hgroup {
margin-bottom: 0;
}
.notification {
display: flex;
align-items: center;
justify-content: center;
background-color: var(--color-primary);
color: var(--color-primary-contrast);
padding: 1rem;
border-radius: 0.5rem;
position: fixed;
bottom: 1rem;
right: 1rem;
z-index: 100;
}
</style>
6 changes: 4 additions & 2 deletions src/routes/login/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { signInWithEmailAndPassword } from 'firebase/auth';
import { getAuth, signInWithEmailAndPassword } from 'firebase/auth';
import { enhance } from '$app/forms';
import { getContext } from 'svelte';
import { fade } from 'svelte/transition';
Expand All @@ -11,6 +11,8 @@
message: null as null | string
};
const auth = getAuth($firebase.app);
let busy = false;
</script>

Expand All @@ -27,7 +29,7 @@
const password = formData.get("password");

try {
const userCred = await signInWithEmailAndPassword($firebase.auth, email, password)
const userCred = await signInWithEmailAndPassword(auth, email, password)
const token = await userCred.user.getIdToken();
formData.set("idToken", token);
} catch(e) {
Expand Down

0 comments on commit decc9f7

Please sign in to comment.