diff --git a/package-lock.json b/package-lock.json
index 9a3e164..0715aeb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,6 +12,7 @@
"bits-ui": "^0.21.7",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
+ "dotenv": "^16.4.5",
"drag-drop-touch": "^1.3.1",
"firebase": "^10.11.1",
"firebase-admin": "^12.1.0",
@@ -2808,6 +2809,17 @@
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
},
+ "node_modules/dotenv": {
+ "version": "16.4.5",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
+ "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
"node_modules/drag-drop-touch": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/drag-drop-touch/-/drag-drop-touch-1.3.1.tgz",
diff --git a/package.json b/package.json
index ba71c69..a3056f9 100644
--- a/package.json
+++ b/package.json
@@ -32,6 +32,7 @@
"bits-ui": "^0.21.7",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
+ "dotenv": "^16.4.5",
"drag-drop-touch": "^1.3.1",
"firebase": "^10.11.1",
"firebase-admin": "^12.1.0",
diff --git a/src/lib/components/Myerror.svelte b/src/lib/components/Myerror.svelte
new file mode 100644
index 0000000..90be279
--- /dev/null
+++ b/src/lib/components/Myerror.svelte
@@ -0,0 +1,10 @@
+
+
+
403
+The Profile of @{username} is not public!
+
+
+

+
diff --git a/src/lib/firebase.ts b/src/lib/firebase.ts
new file mode 100644
index 0000000..4001218
--- /dev/null
+++ b/src/lib/firebase.ts
@@ -0,0 +1,101 @@
+// Import the functions you need from the SDKs you need
+import { initializeApp } from "firebase/app";
+import { doc, getFirestore, onSnapshot } from "firebase/firestore";
+import { getAuth, onAuthStateChanged, type User } from "firebase/auth";
+import { getStorage } from "firebase/storage";
+import { writable, type Readable, derived } from "svelte/store";
+import { env } from "$env/dynamic/public";
+
+// TODO: Add SDKs for Firebase products that you want to use
+// https://firebase.google.com/docs/web/setup#available-libraries
+// Your web app's Firebase configuration
+const firebaseConfig = {
+
+ apiKey: env.PUBLIC_API_KEY,
+ authDomain: env.PUBLIC_AUTH_DOMAIN ,
+ projectId: env.PUBLIC_PROJECT_ID,
+ storageBucket: env.PUBLIC_STORAGE_BUCKET,
+ messagingSenderId: env.PUBLIC_MESSAGING_SENDER_ID,
+ appId: env.PUBLIC_APP_ID,
+
+};
+
+// Initialize Firebase
+const app = initializeApp(firebaseConfig);
+
+export const db = getFirestore();
+export const auth = getAuth();
+export const storage = getStorage();
+
+/**
+ * @returns a store with the current firebase user
+ */
+
+function userStore() {
+ let unsubscribe: () => void;
+
+ if (!auth || !globalThis.window) {
+ console.warn("Auth is not initialized or not in browser");
+ const { subscribe } = writable(null);
+ return {
+ subscribe,
+ };
+ }
+
+ const { subscribe } = writable(auth?.currentUser ?? null, (set) => {
+ unsubscribe = onAuthStateChanged(auth, (user) => {
+ set(user);
+ });
+
+ return () => unsubscribe();
+ });
+
+ return {
+ subscribe,
+ };
+}
+
+export const user = userStore();
+
+/**
+ * @param {string} path document path or reference
+ * @returns a store with realtime updates on document data
+ */
+export function docStore(path: string) {
+ let unsubscribe: () => void;
+
+ const docRef = doc(db, path);
+
+ const { subscribe } = writable(null, (set) => {
+ unsubscribe = onSnapshot(docRef, (snapshot) => {
+ set((snapshot.data() as T) ?? null);
+ });
+
+ return () => unsubscribe();
+ });
+
+ return {
+ subscribe,
+ ref: docRef,
+ id: docRef.id,
+ };
+}
+
+interface UserData {
+ username: string;
+ bio: string;
+ photoURL: string;
+ links: any[];
+ published: boolean;
+}
+
+export const userData: Readable = derived(
+ user,
+ ($user, set) => {
+ if ($user) {
+ return docStore(`users/${$user.uid}`).subscribe(set);
+ } else {
+ set(null);
+ }
+ },
+);
diff --git a/src/routes/[username]/+page.svelte b/src/routes/[username]/+page.svelte
index 6eed820..06701d4 100644
--- a/src/routes/[username]/+page.svelte
+++ b/src/routes/[username]/+page.svelte
@@ -9,8 +9,10 @@
} from "firebase/auth";
import { goto } from "$app/navigation";
import { toasts, ToastContainer, FlatToast } from "svelte-toasts";
+ import Myerror from "$lib/components/Myerror.svelte"
export let data: PageData;
+
async function signInWithGoogle() {
const provider = new GoogleAuthProvider();
const user = await signInWithPopup(auth, provider);
@@ -36,6 +38,10 @@
navigator.clipboard.writeText(copytext)
showToast()
}
+
+
+ let unpublished = data.published
+ let username = data.username
@@ -47,6 +53,11 @@
+{#if unpublished && data.username != $userData?.username}
+
+
+
+{:else}
@{data.username}
@@ -102,3 +113,4 @@
>
{/if}
+{/if}
diff --git a/src/routes/[username]/+page.ts b/src/routes/[username]/+page.ts
index 76332dc..03aba59 100644
--- a/src/routes/[username]/+page.ts
+++ b/src/routes/[username]/+page.ts
@@ -1,6 +1,6 @@
import { collection, getDocs, limit, query, where } from 'firebase/firestore';
import type { PageLoad } from './$types';
-import { db, userData } from '$lib/firebase';
+import { db, userData} from '$lib/firebase';
import { error } from '@sveltejs/kit';
export const load = (async ({ params }) => {
@@ -20,14 +20,11 @@ export const load = (async ({ params }) => {
throw error(404, "that user does not exists")
}
- if (!data.published) {
- throw error(403, `The Profile of @${data.username} is not public!`)
- }
-
return {
username: data.username,
photoURL: data.photoURL,
bio: data.bio,
links: data.links ?? [],
+ published: Boolean
}
}) satisfies PageLoad;
diff --git a/static/403.png b/static/403.png
new file mode 100644
index 0000000..4788a28
Binary files /dev/null and b/static/403.png differ
diff --git a/tailwind.config.js b/tailwind.config.js
index bbc0447..86e170b 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -2,67 +2,67 @@ import { fontFamily } from "tailwindcss/defaultTheme";
/** @type {import('tailwindcss').Config} */
const config = {
- darkMode: ["class"],
- content: ["./src/**/*.{html,js,svelte,ts}"],
- plugins: [require("daisyui")],
- daisyui: {
- themes: ["dark"],
+ darkMode: ["class"],
+ content: ["./src/**/*.{html,js,svelte,ts}"],
+ plugins: [require("daisyui")],
+ daisyui: {
+ themes: ["dark"],
+ },
+ safelist: ["dark"],
+ theme: {
+ container: {
+ center: true,
+ padding: "2rem",
+ screens: {
+ "2xl": "1400px",
+ },
},
- safelist: ["dark"],
- theme: {
- container: {
- center: true,
- padding: "2rem",
- screens: {
- "2xl": "1400px"
- }
- },
- extend: {
- colors: {
- border: "hsl(var(--border) / )",
- input: "hsl(var(--input) / )",
- ring: "hsl(var(--ring) / )",
- background: "hsl(var(--background) / )",
- foreground: "hsl(var(--foreground) / )",
- primary: {
- DEFAULT: "hsl(var(--primary) / )",
- foreground: "hsl(var(--primary-foreground) / )"
- },
- secondary: {
- DEFAULT: "hsl(var(--secondary) / )",
- foreground: "hsl(var(--secondary-foreground) / )"
- },
- destructive: {
- DEFAULT: "hsl(var(--destructive) / )",
- foreground: "hsl(var(--destructive-foreground) / )"
- },
- muted: {
- DEFAULT: "hsl(var(--muted) / )",
- foreground: "hsl(var(--muted-foreground) / )"
- },
- accent: {
- DEFAULT: "hsl(var(--accent) / )",
- foreground: "hsl(var(--accent-foreground) / )"
- },
- popover: {
- DEFAULT: "hsl(var(--popover) / )",
- foreground: "hsl(var(--popover-foreground) / )"
- },
- card: {
- DEFAULT: "hsl(var(--card) / )",
- foreground: "hsl(var(--card-foreground) / )"
- }
- },
- borderRadius: {
- lg: "var(--radius)",
- md: "calc(var(--radius) - 2px)",
- sm: "calc(var(--radius) - 4px)"
- },
- fontFamily: {
- sans: [...fontFamily.sans]
- }
- }
- },
+ extend: {
+ colors: {
+ border: "hsl(var(--border) / )",
+ input: "hsl(var(--input) / )",
+ ring: "hsl(var(--ring) / )",
+ background: "hsl(var(--background) / )",
+ foreground: "hsl(var(--foreground) / )",
+ primary: {
+ DEFAULT: "hsl(var(--primary) / )",
+ foreground: "hsl(var(--primary-foreground) / )",
+ },
+ secondary: {
+ DEFAULT: "hsl(var(--secondary) / )",
+ foreground: "hsl(var(--secondary-foreground) / )",
+ },
+ destructive: {
+ DEFAULT: "hsl(var(--destructive) / )",
+ foreground: "hsl(var(--destructive-foreground) / )",
+ },
+ muted: {
+ DEFAULT: "hsl(var(--muted) / )",
+ foreground: "hsl(var(--muted-foreground) / )",
+ },
+ accent: {
+ DEFAULT: "hsl(var(--accent) / )",
+ foreground: "hsl(var(--accent-foreground) / )",
+ },
+ popover: {
+ DEFAULT: "hsl(var(--popover) / )",
+ foreground: "hsl(var(--popover-foreground) / )",
+ },
+ card: {
+ DEFAULT: "hsl(var(--card) / )",
+ foreground: "hsl(var(--card-foreground) / )",
+ },
+ },
+ borderRadius: {
+ lg: "var(--radius)",
+ md: "calc(var(--radius) - 2px)",
+ sm: "calc(var(--radius) - 4px)",
+ },
+ fontFamily: {
+ sans: [...fontFamily.sans],
+ },
+ },
+ },
};
export default config;