├── .eslintrc.json ├── .babelrc ├── public ├── favicon.ico ├── og-image.jpg ├── assets │ ├── file.png │ ├── logo.png │ ├── hero-02.png │ ├── thirdweb.png │ ├── blank-profile.png │ ├── hero-geometry.webp │ ├── Lesson_01_RowList_04.png │ ├── cloud-upload-regular-240.png │ ├── menu.svg │ ├── type.svg │ ├── host-icon.svg │ ├── info-seyfdesigner.svg │ ├── video-icon.svg │ ├── vertical-menu.svg │ ├── profile.svg │ ├── google.svg │ ├── image-icon.svg │ ├── logo.svg │ ├── thought.svg │ ├── apple.svg │ ├── index.js │ ├── copy-seyfdesigner.svg │ ├── ethereum.svg │ ├── logout.svg │ ├── delete-seyfdesigner.svg │ ├── search.svg │ ├── moon.svg │ ├── dashboard.svg │ ├── share-seyfdesigner.svg │ ├── github.svg │ ├── logo2.svg │ ├── search-seyfdesigner.svg │ ├── payment.svg │ ├── menu-seyfdesigner.svg │ ├── host-seyfdesigner.svg │ ├── folder-seyfdesigner.svg │ ├── idea.svg │ ├── turbo.svg │ ├── heart-seyfdesigner.svg │ ├── secure.svg │ ├── clock-seyfdesigner.svg │ ├── home-seyfdesigner.svg │ ├── rock-seyfdesigner.svg │ ├── plus-seyfdesigner.svg │ ├── sun.svg │ ├── video-seyfdesigner.svg │ ├── ethereum.org.svg │ ├── url-seyfdesigner.svg │ ├── filecoin.svg │ ├── logout-seyfdesigner.svg │ ├── withdraw.svg │ ├── money.svg │ ├── image-seyfdesigner.svg │ ├── thirdweb.svg │ ├── download-seyfdesigner.svg │ ├── star-seyfdesigner.svg │ ├── upload-seyfdesigner.svg │ ├── user-seyfdesigner.svg │ └── create-campaign.svg ├── icon-192x192.png ├── icon-256x256.png ├── icon-384x384.png ├── icon-512x512.png └── manifest.json ├── postcss.config.js ├── pages ├── api │ ├── status │ │ └── index.js │ ├── fetch │ │ ├── stats.js │ │ └── publicfiles.js │ └── auth │ │ └── [...nextauth].js ├── _document.js ├── dashboard │ ├── index.js │ ├── files.js │ ├── photos.js │ ├── videos.js │ └── recent.js ├── docs.js ├── 404.js └── about.js ├── components ├── HeaderSection.js ├── UserFileCard.js ├── widgetForm │ ├── steps │ │ ├── FeedbackContentStep.js │ │ ├── FeedbackSuccessStep.js │ │ └── FeedbackTypeStep.js │ ├── ScreenshotButton.js │ └── index.js ├── Loading.js ├── LucideIcons.js ├── CloseButton.js ├── icons │ ├── index.tsx │ ├── loading-dots.tsx │ └── loading-dots.module.css ├── FeatureCard.js ├── CountBox.js ├── CardBox.js ├── StatsCard.js ├── ui │ ├── copy-button.jsx │ ├── avatar.jsx │ └── toast.jsx ├── LadyLoader.js ├── Widget.js ├── Snackbar.js ├── CustomButton.js ├── Loader.js ├── shared │ ├── Popover.tsx │ └── Leaflet.tsx ├── FileCardSkeleton.js ├── LogoWall.js ├── index.js ├── GithubBadge.js ├── DisplayFiles.js ├── FolderUpload.js ├── ProfileCard.js ├── confirmModal.js ├── GlobalStat.js ├── GetStarted.js ├── VideoPlayer.js ├── Sidebar.js ├── layout │ └── UserDropdown.tsx ├── Footer.js └── CtaSection.js ├── lib ├── utils.ts ├── hooks │ ├── useOnlineStatus.js │ ├── useScroll.js │ ├── useCopyToClipboard.js │ ├── useEventListener.js │ ├── useWindowSize.js │ └── useVideoPlayer.js └── constants.ts ├── turbo.json ├── .env.local.example ├── styles ├── Button.module.css ├── Logowall.module.css ├── Video.module.css ├── globals.css ├── Home.module.css └── Ladyloader.module.css ├── assets ├── Icons │ ├── MenuIcon.jsx │ ├── ClockIcon.jsx │ ├── LinkLogo.jsx │ ├── LeftFaceArrow.jsx │ ├── GoogleLogo.jsx │ ├── DarkspaceLogo.jsx │ ├── LogoutIcon.jsx │ ├── SearchIcon.jsx │ ├── FolderIcon.jsx │ ├── HomeIcon.jsx │ ├── VideoIcon.jsx │ ├── HostIcon.jsx │ ├── DetailIcon.jsx │ ├── DownloadIcon.jsx │ ├── UploadIcon.jsx │ ├── OpenEyeIcon.jsx │ ├── ImageIcon.jsx │ ├── CopyIcon.jsx │ ├── UserIcon.jsx │ ├── LinkIcon.jsx │ ├── TrashIcon.jsx │ ├── AppleLogo.jsx │ ├── GithubLogo.jsx │ ├── DiscordLogo.jsx │ ├── CloseEyeIcon.jsx │ ├── WalletIcon.jsx │ ├── UsersIcon.jsx │ └── index.js └── index.js ├── next.config.js ├── .gitignore ├── middleware.js ├── tailwind.config.js ├── constants └── index.js ├── README.md ├── package.json └── utils └── index.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["next/babel"], 3 | "plugins": [] 4 | } 5 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Darkrove/darkspace/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/og-image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Darkrove/darkspace/HEAD/public/og-image.jpg -------------------------------------------------------------------------------- /public/assets/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Darkrove/darkspace/HEAD/public/assets/file.png -------------------------------------------------------------------------------- /public/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Darkrove/darkspace/HEAD/public/assets/logo.png -------------------------------------------------------------------------------- /public/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Darkrove/darkspace/HEAD/public/icon-192x192.png -------------------------------------------------------------------------------- /public/icon-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Darkrove/darkspace/HEAD/public/icon-256x256.png -------------------------------------------------------------------------------- /public/icon-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Darkrove/darkspace/HEAD/public/icon-384x384.png -------------------------------------------------------------------------------- /public/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Darkrove/darkspace/HEAD/public/icon-512x512.png -------------------------------------------------------------------------------- /public/assets/hero-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Darkrove/darkspace/HEAD/public/assets/hero-02.png -------------------------------------------------------------------------------- /public/assets/thirdweb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Darkrove/darkspace/HEAD/public/assets/thirdweb.png -------------------------------------------------------------------------------- /public/assets/blank-profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Darkrove/darkspace/HEAD/public/assets/blank-profile.png -------------------------------------------------------------------------------- /public/assets/hero-geometry.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Darkrove/darkspace/HEAD/public/assets/hero-geometry.webp -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /public/assets/Lesson_01_RowList_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Darkrove/darkspace/HEAD/public/assets/Lesson_01_RowList_04.png -------------------------------------------------------------------------------- /public/assets/cloud-upload-regular-240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Darkrove/darkspace/HEAD/public/assets/cloud-upload-regular-240.png -------------------------------------------------------------------------------- /pages/api/status/index.js: -------------------------------------------------------------------------------- 1 | export default function handler(req, res) { 2 | res.status(200).json({ platform: 'vercel', status: "successfull", env: "production" }) 3 | } -------------------------------------------------------------------------------- /components/HeaderSection.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const HeaderSection = () => { 4 | return
HeaderSection
; 5 | }; 6 | 7 | export default HeaderSection; 8 | -------------------------------------------------------------------------------- /components/UserFileCard.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const UserFileCard = () => { 4 | return ( 5 |
UserFileCard
6 | ) 7 | } 8 | 9 | export default UserFileCard -------------------------------------------------------------------------------- /lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { ClassValue, clsx } from 'clsx' 2 | import { twMerge } from 'tailwind-merge' 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "pipeline": { 4 | "build": { 5 | "outputs": [".next/**"] 6 | }, 7 | "lint": {} 8 | } 9 | } -------------------------------------------------------------------------------- /public/assets/menu.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /components/widgetForm/steps/FeedbackContentStep.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const FeedbackContentStep = () => { 4 | return ( 5 |
FeedbackContentStep
6 | ) 7 | } 8 | 9 | export default FeedbackContentStep -------------------------------------------------------------------------------- /components/widgetForm/steps/FeedbackSuccessStep.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const FeedbackSuccessStep = () => { 4 | return ( 5 |
FeedbackSuccessStep
6 | ) 7 | } 8 | 9 | export default FeedbackSuccessStep -------------------------------------------------------------------------------- /components/Loading.js: -------------------------------------------------------------------------------- 1 | import { CircleNotch } from "phosphor-react"; 2 | 3 | export function Loading() { 4 | return ( 5 |
6 | 7 |
8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /public/assets/type.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.env.local.example: -------------------------------------------------------------------------------- 1 | CONTRACT = 2 | 3 | NEXT_PUBLIC_GITHUB_ID= 4 | NEXT_PUBLIC_GITHUB_SECRET= 5 | 6 | NEXT_PUBLIC_GOOGLE_ID= 7 | NEXT_PUBLIC_GOOGLE_SECRET= 8 | 9 | NEXT_PUBLIC_DISCORD_ID= 10 | NEXT_PUBLIC_DISCORD_SECRET= 11 | 12 | NEXT_PUBLIC_PRODUCTION_URL= 13 | NEXT_PUBLIC_DEVELOPMENT_URL= 14 | 15 | NEXTAUTH_URL= 16 | NEXTAUTH_SECRET= 17 | 18 | NEXT_PUBLIC_STORAGE_API= -------------------------------------------------------------------------------- /components/LucideIcons.js: -------------------------------------------------------------------------------- 1 | import { ChevronLeft, ChevronRight, Moon, Sun, Laptop, CheckCircle, Download, X, Network, User } from 'lucide-react' 2 | 3 | export const Icons = { 4 | ChevronLeft, 5 | ChevronRight, 6 | Sun, 7 | Moon, 8 | Laptop, 9 | CheckCircle, 10 | Download, 11 | X, 12 | Network, 13 | User 14 | } 15 | 16 | export default Icons -------------------------------------------------------------------------------- /public/assets/host-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/CloseButton.js: -------------------------------------------------------------------------------- 1 | import { Popover } from '@headlessui/react'; 2 | import { X } from "phosphor-react"; 3 | 4 | export function CloseButton() { 5 | return ( 6 | 10 | 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /lib/hooks/useOnlineStatus.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react" 2 | import useEventListener from "./useEventListener" 3 | 4 | export default function useOnlineStatus() { 5 | const [online, setOnline] = useState(global.navigator?.onLine) 6 | 7 | useEventListener("online", () => setOnline(global.navigator?.onLine)) 8 | useEventListener("offline", () => setOnline(global.navigator?.onLine)) 9 | 10 | return online 11 | } -------------------------------------------------------------------------------- /components/icons/index.tsx: -------------------------------------------------------------------------------- 1 | export { default as LoadingDots } from "./loading-dots"; 2 | // export { default as LoadingCircle } from "./loading-circle"; 3 | // export { default as LoadingSpinner } from "./loading-spinner"; 4 | // export { default as ExpandingArrow } from "./expanding-arrow"; 5 | // export { default as Github } from "./github"; 6 | // export { default as Twitter } from "./twitter"; 7 | // export { default as Google } from "./google"; -------------------------------------------------------------------------------- /public/assets/info-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/icons/loading-dots.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styles from "./loading-dots.module.css"; 3 | 4 | const LoadingDots = ({ color = "#000" }: { color?: string }) => { 5 | return ( 6 | 7 | 8 | 9 | 10 | 11 | ); 12 | }; 13 | 14 | export default LoadingDots; -------------------------------------------------------------------------------- /lib/constants.ts: -------------------------------------------------------------------------------- 1 | export const FADE_IN_ANIMATION_SETTINGS = { 2 | initial: { opacity: 0 }, 3 | animate: { opacity: 1 }, 4 | transition: { duration: 0.2 }, 5 | }; 6 | 7 | export const FADE_DOWN_ANIMATION_VARIANTS = { 8 | hidden: { opacity: 0, y: -10 }, 9 | show: { opacity: 1, y: 0, transition: { type: "spring" } }, 10 | }; 11 | 12 | export const FADE_UP_ANIMATION_VARIANTS = { 13 | hidden: { opacity: 0, y: 10 }, 14 | show: { opacity: 1, y: 0, transition: { type: "spring" } }, 15 | }; 16 | -------------------------------------------------------------------------------- /public/assets/video-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/assets/vertical-menu.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/assets/profile.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /lib/hooks/useScroll.js: -------------------------------------------------------------------------------- 1 | import { useCallback, useEffect, useState } from "react"; 2 | 3 | export default function useScroll(threshold) { 4 | const [scrolled, setScrolled] = useState(false); 5 | 6 | const onScroll = useCallback(() => { 7 | setScrolled(window.pageYOffset > threshold); 8 | }, [threshold]); 9 | 10 | useEffect(() => { 11 | window.addEventListener("scroll", onScroll); 12 | return () => window.removeEventListener("scroll", onScroll); 13 | }, [onScroll]); 14 | 15 | return scrolled; 16 | } 17 | -------------------------------------------------------------------------------- /public/assets/google.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /components/FeatureCard.js: -------------------------------------------------------------------------------- 1 | import React, { Children } from "react"; 2 | 3 | const Feature = ({ title, description, icon }) => { 4 | return ( 5 | <> 6 |
7 | {icon} 8 | 9 |

{title}

10 | 11 |

{description}

12 |
13 | 14 | ); 15 | }; 16 | 17 | export default Feature; 18 | -------------------------------------------------------------------------------- /styles/Button.module.css: -------------------------------------------------------------------------------- 1 | .button:hover { 2 | background-image: linear-gradient(to right, rgb(250, 82, 82), rgb(250, 82, 82) 16.65%, rgb(190, 75, 219) 16.65%, rgb(190, 75, 219) 33.3%, rgb(76, 110, 245) 33.3%, rgb(76, 110, 245) 49.95%, rgb(64, 192, 87) 49.95%, rgb(64, 192, 87) 66.6%, rgb(250, 176, 5) 66.6%, rgb(250, 176, 5) 83.25%, rgb(253, 126, 20) 83.25%, rgb(253, 126, 20) 100%, rgb(250, 82, 82) 100%); 3 | animation: 2s linear dance6123 infinite; 4 | } 5 | 6 | @keyframes dance6123 { 7 | to { 8 | background-position: 200px; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /components/CountBox.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const CountBox = ({ title, value }) => { 4 | return ( 5 |
6 |

7 | {value} 8 |

9 |

10 | {title} 11 |

12 |
13 | ); 14 | }; 15 | 16 | export default CountBox; 17 | -------------------------------------------------------------------------------- /pages/_document.js: -------------------------------------------------------------------------------- 1 | import Document, { Html, Head, Main, NextScript } from "next/document"; 2 | 3 | class MyDocument extends Document { 4 | render() { 5 | return ( 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | ); 18 | } 19 | } 20 | 21 | export default MyDocument 22 | -------------------------------------------------------------------------------- /lib/hooks/useCopyToClipboard.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react" 2 | import copy from "copy-to-clipboard" 3 | 4 | export default function useCopyToClipboard() { 5 | const [value, setValue] = useState() 6 | const [success, setSuccess] = useState('') 7 | 8 | useEffect(() => { 9 | setTimeout(() => setSuccess(''), 5000) 10 | }, [success]) 11 | 12 | const copyToClipboard = (text, options) => { 13 | const result = copy(text, options) 14 | if (result) setValue(text) 15 | setSuccess(result) 16 | } 17 | 18 | return [copyToClipboard, { value, success }] 19 | } -------------------------------------------------------------------------------- /components/CardBox.js: -------------------------------------------------------------------------------- 1 | import CopyButton from "./ui/copy-button" 2 | 3 | const CardBox = ({ copyIcon, value, title }) => { 4 | return ( 5 |
6 |
7 |

{title}

8 | {copyIcon && ( 9 | 10 | )} 11 |
12 |

{value || "-"}

13 |
14 | ); 15 | }; 16 | 17 | export default CardBox; 18 | -------------------------------------------------------------------------------- /lib/hooks/useEventListener.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from "react" 2 | 3 | export default function useEventListener( 4 | eventType, 5 | callback, 6 | element = global.window 7 | ) { 8 | const callbackRef = useRef(callback) 9 | 10 | useEffect(() => { 11 | callbackRef.current = callback 12 | }, [callback]) 13 | 14 | useEffect(() => { 15 | if (element == null) return 16 | const handler = e => callbackRef.current(e) 17 | element.addEventListener(eventType, handler) 18 | 19 | return () => element.removeEventListener(eventType, handler) 20 | }, [eventType, element]) 21 | } -------------------------------------------------------------------------------- /public/assets/image-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/Icons/MenuIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const MenuIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 14 | 19 | 20 | ) 21 | 22 | export default MenuIcon -------------------------------------------------------------------------------- /public/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /assets/Icons/ClockIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const ClockIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 14 | 19 | 20 | ) 21 | 22 | export default ClockIcon -------------------------------------------------------------------------------- /assets/Icons/LinkLogo.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | const LinkLogo = ({ 3 | fill = "currentColor", 4 | filled, 5 | size, 6 | height, 7 | width, 8 | label, 9 | ...props 10 | }) => ( 11 | 24 | 25 | 26 | ); 27 | export default LinkLogo; 28 | -------------------------------------------------------------------------------- /assets/Icons/LeftFaceArrow.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | const LeftFaceArrow = ({ 3 | fill = "currentColor", 4 | filled, 5 | size, 6 | height, 7 | width, 8 | label, 9 | ...props 10 | }) => ( 11 | 18 | 25 | 26 | ); 27 | export default LeftFaceArrow; 28 | -------------------------------------------------------------------------------- /components/StatsCard.js: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | 3 | const Statistic = ({ icon, count, title }) => { 4 | return ( 5 |
6 |
7 | icon 14 |
15 |
{count}
16 |

{title}

17 |
18 | ); 19 | }; 20 | 21 | export default Statistic; 22 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const withPWA = require("next-pwa")({ 3 | dest: "public", 4 | disable: process.env.NODE_ENV === 'development', 5 | register: true, 6 | skipWaiting: true, 7 | }); 8 | const nextConfig = { 9 | reactStrictMode: true, 10 | basePath: "", 11 | images: { 12 | domains: [ 13 | "kitwind.io", 14 | "cdn.discordapp.com", 15 | "avatars.githubusercontent.com", 16 | "lh3.googleusercontent.com", 17 | "ipfs.io", 18 | "gateway.ipfs.io", 19 | "cloudflare-ipfs.com", 20 | "gateway.pinata.cloud", 21 | "ipfs.eternum.io", 22 | "dweb.link", 23 | ], 24 | }, 25 | }; 26 | 27 | module.exports = withPWA(nextConfig); 28 | -------------------------------------------------------------------------------- /assets/Icons/GoogleLogo.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | const GoogleLogo = ({ 3 | fill = "currentColor", 4 | filled, 5 | size, 6 | height, 7 | width, 8 | label, 9 | ...props 10 | }) => ( 11 | 18 | 22 | 23 | ); 24 | export default GoogleLogo; 25 | -------------------------------------------------------------------------------- /public/assets/thought.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /assets/Icons/DarkspaceLogo.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | const DarkspaceLogo = ({ 3 | fill = "currentColor", 4 | filled, 5 | size, 6 | height, 7 | width, 8 | label, 9 | ...props 10 | }) => ( 11 | 19 | 20 | 21 | 22 | 23 | ); 24 | export default DarkspaceLogo; 25 | -------------------------------------------------------------------------------- /assets/Icons/LogoutIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const LogoutIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 14 | 19 | 20 | ) 21 | 22 | export default LogoutIcon -------------------------------------------------------------------------------- /assets/Icons/SearchIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const SearchIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 15 | 19 | 23 | 24 | ) 25 | 26 | export default SearchIcon -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env.local 30 | .env.development.local 31 | .env.test.local 32 | .env.production.local 33 | 34 | # vercel 35 | .vercel 36 | 37 | # pwa 38 | **/public/sw.js 39 | **/public/sw.js.map 40 | **/public/workbox-*.js 41 | **/public/workbox-*.js.map 42 | **/public/worker-*.js 43 | **/public/worker-*.js.map 44 | 45 | 46 | # turbo 47 | .turbo -------------------------------------------------------------------------------- /components/icons/loading-dots.module.css: -------------------------------------------------------------------------------- 1 | .loading { 2 | display: inline-flex; 3 | align-items: center; 4 | } 5 | 6 | .loading .spacer { 7 | margin-right: 2px; 8 | } 9 | 10 | .loading span { 11 | animation-name: blink; 12 | animation-duration: 1.4s; 13 | animation-iteration-count: infinite; 14 | animation-fill-mode: both; 15 | width: 5px; 16 | height: 5px; 17 | border-radius: 50%; 18 | display: inline-block; 19 | margin: 0 1px; 20 | } 21 | 22 | .loading span:nth-of-type(2) { 23 | animation-delay: 0.2s; 24 | } 25 | 26 | .loading span:nth-of-type(3) { 27 | animation-delay: 0.4s; 28 | } 29 | 30 | @keyframes blink { 31 | 0% { 32 | opacity: 0.2; 33 | } 34 | 20% { 35 | opacity: 1; 36 | } 37 | 100% { 38 | opacity: 0.2; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /components/ui/copy-button.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import useCopyToClipboard from "../../lib/hooks/useCopyToClipboard"; 3 | import { Copy, Checks } from "phosphor-react" 4 | 5 | const CopyButton = ({ value }) => { 6 | const [copyToClipboard, { success }] = useCopyToClipboard(); 7 | return ( 8 | 18 | ) 19 | } 20 | 21 | export default CopyButton -------------------------------------------------------------------------------- /assets/Icons/FolderIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const FolderIcon = ({ fill = "currentColor", ...props }) => ( 4 | 11 | 16 | 17 | ); 18 | 19 | export default FolderIcon; 20 | -------------------------------------------------------------------------------- /public/assets/apple.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/assets/index.js: -------------------------------------------------------------------------------- 1 | import createCampaign from './create-campaign.svg'; 2 | import dashboard from './dashboard.svg'; 3 | import logo from './logo.svg'; 4 | import logout from './logout.svg'; 5 | import payment from './payment.svg'; 6 | import profile from './profile.svg'; 7 | import sun from './sun.svg'; 8 | import withdraw from './withdraw.svg'; 9 | import tagType from './type.svg'; 10 | import search from './search.svg'; 11 | import menu from './menu.svg'; 12 | import money from './money.svg'; 13 | import loader from './loader.svg'; 14 | import thirdweb from './thirdweb.png'; 15 | 16 | export default { 17 | tagType, 18 | createCampaign, 19 | dashboard, 20 | logo, 21 | logout, 22 | payment, 23 | profile, 24 | sun, 25 | withdraw, 26 | search, 27 | menu, 28 | money, 29 | loader, 30 | thirdweb, 31 | }; 32 | -------------------------------------------------------------------------------- /assets/Icons/HomeIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const HomeIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 14 | 19 | 20 | ) 21 | 22 | export default HomeIcon -------------------------------------------------------------------------------- /assets/Icons/VideoIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const VideoIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 14 | 19 | 20 | ) 21 | 22 | export default VideoIcon -------------------------------------------------------------------------------- /public/assets/copy-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/LadyLoader.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styles from "../styles/Ladyloader.module.css"; 3 | 4 | const LadyLoader = () => { 5 | return ( 6 |
7 |
8 | 9 | 10 | 11 |
12 | 13 |
14 |
15 | 16 | 17 | 18 |
19 |
20 | 21 |
22 | 23 | 24 | 25 |
26 |
27 | ); 28 | }; 29 | 30 | export default LadyLoader; 31 | -------------------------------------------------------------------------------- /public/assets/ethereum.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /assets/Icons/HostIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const HostIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 14 | 19 | 20 | ) 21 | 22 | export default HostIcon -------------------------------------------------------------------------------- /components/Widget.js: -------------------------------------------------------------------------------- 1 | 2 | import { ChatTeardropDots } from 'phosphor-react'; 3 | 4 | import { Popover } from "@headlessui/react"; 5 | import { WidgetForm } from "./widgetForm"; 6 | 7 | export default function Widget() { 8 | 9 | return ( 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Feedback 21 | 22 | 23 | 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /assets/Icons/DetailIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const DetailIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 14 | 19 | 20 | ) 21 | 22 | export default DetailIcon -------------------------------------------------------------------------------- /public/assets/logout.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /assets/Icons/DownloadIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const DownloadIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 14 | 19 | 20 | ) 21 | 22 | export default DownloadIcon -------------------------------------------------------------------------------- /components/Snackbar.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const Snackbar = () => { 4 | return ( 5 |
6 |
7 |
8 | Success 9 | 10 | Vitae nulla eligendi dignissimos culpa doloribus. 11 | 12 |
13 | 16 |
17 |
18 | ); 19 | }; 20 | 21 | export default Snackbar; 22 | -------------------------------------------------------------------------------- /components/ui/avatar.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import * as Avatar from '@radix-ui/react-avatar'; 3 | import { cn } from '../../lib/utils' 4 | 5 | const Profile = ({ image, name, className, ...props }) => { 6 | const fallback = name 7 | ?.split(" ") 8 | .map((word) => word[0]) 9 | .join("").toUpperCase(); 10 | 11 | return ( 12 | 13 | 18 | 19 | {fallback} 20 | 21 | 22 | ) 23 | } 24 | 25 | export default Profile -------------------------------------------------------------------------------- /assets/Icons/UploadIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const UploadIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 14 | 19 | 20 | ) 21 | 22 | export default UploadIcon -------------------------------------------------------------------------------- /pages/dashboard/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { getServerSession } from "next-auth/next"; 3 | import useSWR from "swr"; 4 | 5 | import { authOptions } from "../api/auth/[...nextauth]"; 6 | import { useStateContext } from "../../context"; 7 | import { DisplayFiles } from "../../components"; 8 | 9 | const Home = () => { 10 | const { address } = useStateContext(); 11 | 12 | const fetcher = (url) => fetch(url).then((res) => res.json()); 13 | 14 | const { data, error, isLoading } = useSWR( 15 | "/api/fetch/publicfiles", 16 | fetcher 17 | ); 18 | 19 | return ( 20 |
21 | 29 |
30 | ); 31 | }; 32 | 33 | export default Home; -------------------------------------------------------------------------------- /pages/docs.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const docs = () => { 4 | return ( 5 |
6 |
7 |

8 | Comming Soon ⏱ 9 |

10 |

11 | Stay Tuned 🔔 for more updates, and star ⭐ this repo on {" "} 12 | github {" "}. 17 |

18 |
19 |
20 | ) 21 | } 22 | 23 | export default docs -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "theme_color": "#8b5cf6", 3 | "background_color": "#18181b", 4 | "display": "standalone", 5 | "scope": "/", 6 | "start_url": "/", 7 | "name": "DarkSpace", 8 | "short_name": "DarkSpace", 9 | "description": "The Next Generation of Secure and Decentralized Data Storage", 10 | "icons": [ 11 | { 12 | "src": "/icon-192x192.png", 13 | "sizes": "192x192", 14 | "type": "image/png" 15 | }, 16 | { 17 | "src": "/icon-256x256.png", 18 | "sizes": "256x256", 19 | "type": "image/png" 20 | }, 21 | { 22 | "src": "/icon-384x384.png", 23 | "sizes": "384x384", 24 | "type": "image/png" 25 | }, 26 | { 27 | "src": "/icon-512x512.png", 28 | "sizes": "512x512", 29 | "type": "image/png" 30 | } 31 | ] 32 | } -------------------------------------------------------------------------------- /assets/Icons/OpenEyeIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const OpenEyeIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 14 | 19 | 20 | ) 21 | 22 | export default OpenEyeIcon -------------------------------------------------------------------------------- /assets/Icons/ImageIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const ImageIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 14 | 19 | 20 | ) 21 | 22 | export default ImageIcon -------------------------------------------------------------------------------- /pages/dashboard/files.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import { getServerSession } from "next-auth/next"; 3 | import useSWR from "swr"; 4 | 5 | import { authOptions } from "../api/auth/[...nextauth]"; 6 | import { useStateContext } from "../../context"; 7 | import { DisplayFiles } from "../../components"; 8 | 9 | const Files = () => { 10 | const { address, contract, getUserFiles } = useStateContext(); 11 | 12 | const fetchFiles = async () => { 13 | const data = await getUserFiles(); 14 | return data; 15 | }; 16 | const { data, error, isLoading } = useSWR(["userFiles"], fetchFiles); 17 | 18 | return ( 19 |
20 | file.type !== "directory").reverse()} 25 | address={address} 26 | user={true} 27 | /> 28 |
29 | ); 30 | }; 31 | 32 | export default Files; -------------------------------------------------------------------------------- /public/assets/delete-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/Icons/CopyIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const CopyIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 14 | 19 | 20 | ) 21 | 22 | export default CopyIcon -------------------------------------------------------------------------------- /assets/Icons/UserIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const UserIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 14 | 19 | 20 | ) 21 | 22 | export default UserIcon -------------------------------------------------------------------------------- /public/assets/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /assets/Icons/LinkIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const LinkIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 14 | 19 | 20 | ) 21 | export default LinkIcon -------------------------------------------------------------------------------- /pages/dashboard/photos.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import { getServerSession } from "next-auth/next"; 3 | import useSWR from "swr"; 4 | 5 | import { authOptions } from "../api/auth/[...nextauth]"; 6 | import { useStateContext } from "../../context"; 7 | import { DisplayFiles } from "../../components"; 8 | 9 | const Photos = () => { 10 | const { address, contract, getUserFiles } = useStateContext(); 11 | 12 | const fetchFiles = async () => { 13 | const data = await getUserFiles(); 14 | return data; 15 | }; 16 | 17 | const { data, error, isLoading } = useSWR(["userFiles"], fetchFiles); 18 | 19 | return ( 20 |
21 | file.type.split("/")[0] === "image") 27 | .reverse()} 28 | address={address} 29 | user={true} 30 | /> 31 |
32 | ); 33 | }; 34 | 35 | export default Photos; -------------------------------------------------------------------------------- /pages/dashboard/videos.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import { getServerSession } from "next-auth/next"; 3 | import useSWR from "swr"; 4 | 5 | import { authOptions } from "../api/auth/[...nextauth]"; 6 | import { useStateContext } from "../../context"; 7 | import { DisplayFiles } from "../../components"; 8 | 9 | const Videos = () => { 10 | const { address, contract, getUserFiles } = useStateContext(); 11 | 12 | const fetchFiles = async () => { 13 | const data = await getUserFiles(); 14 | return data; 15 | }; 16 | 17 | const { data, error, isLoading } = useSWR(["userFiles"], fetchFiles); 18 | 19 | return ( 20 |
21 | file.type.split("/")[0] === "video") 27 | .reverse()} 28 | address={address} 29 | user={true} 30 | /> 31 |
32 | ); 33 | }; 34 | 35 | export default Videos; 36 | -------------------------------------------------------------------------------- /public/assets/moon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /pages/api/fetch/stats.js: -------------------------------------------------------------------------------- 1 | import { Sepolia } from "@thirdweb-dev/chains"; 2 | import { ThirdwebSDK } from "@thirdweb-dev/sdk"; 3 | import { formatBytes } from "../../../utils"; 4 | 5 | const fetch = async () => { 6 | const sdk = new ThirdwebSDK(Sepolia, { 7 | secretKey: process.env.THIRDWEB_SECRET, 8 | }); 9 | const contract = await sdk.getContract(process.env.CONTRACT); 10 | const data = await contract.call("getFiles"); 11 | if (data.length > 0) { 12 | const storage = data.reduce( 13 | (total, f) => (total + f.fileSize.toNumber()), 0 14 | ) 15 | const files = data.reduce( 16 | (total, f) => (total + 1), 0 17 | ) 18 | 19 | const stats = { 20 | size: storage, 21 | filecount: files 22 | } 23 | 24 | return stats; 25 | } else { 26 | return null; 27 | } 28 | }; 29 | 30 | export default async function handler(req, res) { 31 | const data = await fetch(); 32 | console.log(data) 33 | res.status(200).json(data); 34 | } 35 | -------------------------------------------------------------------------------- /public/assets/dashboard.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /assets/Icons/TrashIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const TrashIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 14 | 19 | 20 | ) 21 | 22 | export default TrashIcon -------------------------------------------------------------------------------- /pages/404.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Link from "next/link"; 3 | 4 | const ErrorPage = () => { 5 | return ( 6 |
7 |
8 |
9 |

10 | Error404 11 |

12 |

13 | Sorry, we couldn't find this page. 14 |

15 |

16 | But dont worry, you can find plenty of other things on our homepage. 17 |

18 | 22 | Back to homepage 23 | 24 |
25 |
26 |
27 | ); 28 | }; 29 | 30 | export default ErrorPage; 31 | -------------------------------------------------------------------------------- /lib/hooks/useWindowSize.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | export default function useWindowSize() { 4 | const [windowSize, setWindowSize] = useState({ 5 | width: undefined, 6 | height: undefined, 7 | }); 8 | 9 | useEffect(() => { 10 | // Handler to call on window resize 11 | function handleResize() { 12 | // Set window width/height to state 13 | setWindowSize({ 14 | width: window.innerWidth, 15 | height: window.innerHeight, 16 | }); 17 | } 18 | 19 | // Add event listener 20 | window.addEventListener("resize", handleResize); 21 | 22 | // Call handler right away so state gets updated with initial window size 23 | handleResize(); 24 | 25 | // Remove event listener on cleanup 26 | return () => window.removeEventListener("resize", handleResize); 27 | }, []); // Empty array ensures that effect is only run on mount 28 | 29 | return { 30 | windowSize, 31 | isMobile: typeof windowSize?.width === "number" && windowSize?.width < 768, 32 | isDesktop: 33 | typeof windowSize?.width === "number" && windowSize?.width >= 768, 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /public/assets/share-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/assets/github.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/assets/logo2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /public/assets/search-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /pages/api/fetch/publicfiles.js: -------------------------------------------------------------------------------- 1 | import { Sepolia } from "@thirdweb-dev/chains"; 2 | import { ThirdwebSDK } from "@thirdweb-dev/sdk"; 3 | import { unpadString } from "../../../utils"; 4 | 5 | const fetch = async () => { 6 | const sdk = new ThirdwebSDK(Sepolia, { 7 | secretKey: process.env.THIRDWEB_SECRET, 8 | }); 9 | const contract = await sdk.getContract(process.env.CONTRACT); 10 | const data = await contract.call("getPublicFiles"); 11 | if (data.length > 0) { 12 | const parsedFiles = data.map((file, i) => ({ 13 | owner: file.owner, 14 | username: unpadString(file.username), 15 | profile: file.profile, 16 | name: unpadString(file.fileName), 17 | type: unpadString(file.fileType), 18 | size: file.fileSize.toNumber(), 19 | hash: file.fileHash, 20 | uploadTime: file.fileUploadTime.toNumber(), 21 | pid: file.id.toNumber(), 22 | status: file.fileStatus, 23 | })); 24 | // console.warn(parsedFiles) 25 | return parsedFiles.filter((file) => file.hash !== ""); 26 | } else { 27 | return null; 28 | } 29 | }; 30 | 31 | export default async function handler(req, res) { 32 | const data = await fetch(); 33 | // console.log(data) 34 | res.status(200).json(data.reverse()); 35 | } 36 | -------------------------------------------------------------------------------- /public/assets/payment.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /components/widgetForm/steps/FeedbackTypeStep.js: -------------------------------------------------------------------------------- 1 | import Image from "next/image" 2 | import React from "react" 3 | import { feedbackTypes } from '..'; 4 | import { CloseButton } from '../../CloseButton'; 5 | 6 | 7 | export default function FeedbackTypeStep({ onFeedbackTypeChanged }) { 8 | return ( 9 | <> 10 |
11 | 12 | Leave your feedback 13 | 14 | 15 |
16 | 17 |
18 | {Object.entries(feedbackTypes).map(([key, value]) => { 19 | return ( 20 | 28 | {value.image.alt} 29 | {value.title} 30 | 31 | ); 32 | })} 33 |
34 | 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /public/assets/menu-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /middleware.js: -------------------------------------------------------------------------------- 1 | import { getToken } from "next-auth/jwt" 2 | import { withAuth } from "next-auth/middleware" 3 | import { NextResponse } from "next/server" 4 | 5 | 6 | export default withAuth( 7 | async function middleware(req) { 8 | const pathname = req.nextUrl.pathname 9 | const token = await getToken({ req }) 10 | const isAuth = !!token 11 | const isAuthPage = pathname.startsWith("/signin") 12 | const sensitveRoutes = ['/dashboard', '/dashboard/profile', '/dashboard/files', 13 | '/dashboard/host', '/dashboard/photos', '/dashboard/recent', 14 | '/dashboard/uploadmedia', '/dashboard/video', '/dashboard/show', '/dashboard/show/[slug]'] 15 | if (isAuthPage) { 16 | if (isAuth) { 17 | return NextResponse.redirect(new URL('/dashboard', req.url)) 18 | } 19 | return null 20 | } 21 | 22 | if (!isAuth && sensitveRoutes.some((route) => pathname.startsWith(route))) { 23 | return NextResponse.redirect(new URL('/signin', req.url)) 24 | } 25 | }, { 26 | callbacks: { 27 | async authorized() { 28 | return true 29 | } 30 | } 31 | } 32 | ) 33 | 34 | export const config = { 35 | matcher: ['/', '/signin', '/dashboard/:path*'] 36 | } -------------------------------------------------------------------------------- /components/CustomButton.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const CustomButton = ({ 4 | btnType, 5 | title, 6 | handleClick, 7 | styles, 8 | status, 9 | disabled, 10 | }) => { 11 | return ( 12 | <> 13 | {status ? ( 14 | 26 | ) : ( 27 | 35 | )} 36 | 37 | ); 38 | }; 39 | export default CustomButton; 40 | -------------------------------------------------------------------------------- /assets/Icons/AppleLogo.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | const AppleLogo = ({ 3 | fill = "currentColor", 4 | filled, 5 | size, 6 | height, 7 | width, 8 | label, 9 | ...props 10 | }) => ( 11 | 20 | 21 | 25 | 26 | 27 | ); 28 | export default AppleLogo; 29 | -------------------------------------------------------------------------------- /components/Loader.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Balancer from "react-wrap-balancer"; 3 | 4 | const Loader = ({ message, subMessage, isTransacting }) => { 5 | return ( 6 |
7 |
8 |
9 |
10 | 11 | {message} 12 | 13 | 14 | {subMessage} 15 | 16 | {isTransacting && ( 17 | 23 | VIEW ON ETHERSCAN 24 | 25 | )} 26 |
27 |
28 |
29 | ); 30 | }; 31 | 32 | export default Loader; 33 | -------------------------------------------------------------------------------- /assets/Icons/GithubLogo.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | const GithubLogo = ({ 3 | fill = "currentColor", 4 | filled, 5 | size, 6 | height, 7 | width, 8 | label, 9 | ...props 10 | }) => ( 11 | 18 | 23 | 24 | ); 25 | export default GithubLogo; 26 | -------------------------------------------------------------------------------- /public/assets/host-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/assets/folder-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | "./app/**/*.{js,ts,jsx,tsx}", 5 | "./pages/**/*.{js,ts,jsx,tsx}", 6 | "./components/**/*.{js,ts,jsx,tsx}", 7 | "node_modules/preline/dist/*.js", 8 | ], 9 | theme: { 10 | extend: { 11 | fontFamily: { 12 | epilogue: ['Epilogue', 'sans-serif'], 13 | }, 14 | boxShadow: { 15 | secondary: '10px 10px 20px rgba(2, 2, 2, 0.25)', 16 | }, 17 | colors: { 18 | toast: { 19 | '50': '#FFF6DF', 20 | '100': '#fdf7f1', 21 | '200': '#F8EEDB', 22 | '300': '#ebbf99', 23 | '400': '#dea373', 24 | '500': '#ce864f', 25 | '600': '#A1724E', 26 | '700': '#8c501c', 27 | '800': '#5c340f', 28 | '900': '#482307', 29 | }, 30 | }, 31 | container: { 32 | center: true, 33 | }, 34 | skeletonScreen: { 35 | DEFAULT: { 36 | baseColor: '#8d8d8f', 37 | movingColor: 'linear-gradient(to right, transparent 0%, #9f9fa1 50%, transparent 100%)', 38 | duration: '1s', 39 | timing: 'linear', 40 | }, 41 | }, 42 | }, 43 | }, 44 | darkMode: 'class', 45 | plugins: [ 46 | require('preline/plugin'), 47 | require('@gradin/tailwindcss-skeleton-screen'), 48 | ], 49 | } 50 | -------------------------------------------------------------------------------- /assets/Icons/DiscordLogo.jsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | const DiscordLogo = ({ 3 | fill = "currentColor", 4 | filled, 5 | size, 6 | height, 7 | width, 8 | label, 9 | ...props 10 | }) => ( 11 | 19 | 23 | 24 | ); 25 | export default DiscordLogo; 26 | -------------------------------------------------------------------------------- /components/shared/Popover.tsx: -------------------------------------------------------------------------------- 1 | import React, { Dispatch, SetStateAction, ReactNode, useRef } from "react"; 2 | import * as PopoverPrimitive from "@radix-ui/react-popover"; 3 | import useWindowSize from "../../lib/hooks/useWindowSize"; 4 | import Leaflet from "./Leaflet"; 5 | 6 | export default function Popover({ 7 | children, 8 | content, 9 | align = "center", 10 | openPopover, 11 | setOpenPopover, 12 | }: { 13 | children: ReactNode; 14 | content: ReactNode | string; 15 | align?: "center" | "start" | "end"; 16 | openPopover: boolean; 17 | setOpenPopover: Dispatch>; 18 | }) { 19 | const { isMobile, isDesktop } = useWindowSize(); 20 | return ( 21 | <> 22 | {isMobile && children} 23 | {openPopover && isMobile && ( 24 | {content} 25 | )} 26 | {isDesktop && ( 27 | 28 | 29 | {children} 30 | 31 | 36 | {content} 37 | 38 | 39 | )} 40 | 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /assets/Icons/CloseEyeIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const CloseEyeIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 14 | 19 | 20 | ) 21 | 22 | export default CloseEyeIcon -------------------------------------------------------------------------------- /assets/Icons/WalletIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const WalletIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 15 | 19 | 23 | 27 | 28 | ) 29 | 30 | export default WalletIcon -------------------------------------------------------------------------------- /public/assets/idea.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /assets/Icons/UsersIcon.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const UsersIcon = ({ 4 | fill = "currentColor", 5 | ...props 6 | }) => ( 7 | 14 | 19 | 20 | ) 21 | 22 | export default UsersIcon -------------------------------------------------------------------------------- /public/assets/turbo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /public/assets/heart-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/Logowall.module.css: -------------------------------------------------------------------------------- 1 | 2 | .app { 3 | min-width: 100vw; 4 | display: flex; 5 | align-items: center; 6 | justify-content: center; 7 | flex-direction: column; 8 | } 9 | 10 | .tag_list { 11 | width: 60rem; 12 | max-width: 90vw; 13 | display: flex; 14 | flex-shrink: 0; 15 | flex-direction: column; 16 | gap: 1rem 0; 17 | position: relative; 18 | padding: 1.5rem 0; 19 | overflow: hidden; 20 | } 21 | 22 | .inner { 23 | display: flex; 24 | width: fit-content; 25 | animation-name: loop; 26 | animation-timing-function: linear; 27 | animation-iteration-count: infinite; 28 | animation-direction: var(--direction); 29 | animation-duration: var(--duration); 30 | } 31 | 32 | .tag { 33 | display: flex; 34 | align-items: center; 35 | gap: 0 0.2rem; 36 | color: #e2e8f0; 37 | font-size: 0.9rem; 38 | background-color: #334155; 39 | border-radius: 0.4rem; 40 | padding: 0.7rem 1rem; 41 | margin-right: 1rem; 42 | box-shadow: 0 0.1rem 0.2rem rgb(0 0 0 / 20%), 0 0.1rem 0.5rem rgb(0 0 0 / 30%), 43 | 0 0.2rem 1.5rem rgb(0 0 0 / 40%); 44 | } 45 | 46 | .span { 47 | font-size: 1.2rem; 48 | color: #64748b; 49 | } 50 | 51 | .fade { 52 | pointer-events: none; 53 | background: linear-gradient( 54 | 90deg, 55 | #1e293b, 56 | transparent 30%, 57 | transparent 70%, 58 | #1e293b 59 | ); 60 | position: absolute; 61 | inset: 0; 62 | } 63 | 64 | @keyframes loop { 65 | 0% { 66 | transform: translateX(0); 67 | } 68 | 100% { 69 | transform: translateX(-50%); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /public/assets/secure.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /public/assets/clock-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /assets/Icons/index.js: -------------------------------------------------------------------------------- 1 | export { default as AppleLogo } from "./AppleLogo" 2 | export { default as GoogleLogo } from "./GoogleLogo" 3 | export { default as GithubLogo } from "./GithubLogo" 4 | export { default as DarkspaceLogo } from "./DarkspaceLogo" 5 | export { default as DarkspaceLogoFull } from "./DarkspaceLogoFull" 6 | export { default as LinkLogo } from "./LinkLogo" 7 | export { default as LeftFaceArrow } from "./LeftFaceArrow" 8 | export { default as DiscordLogo } from "./DiscordLogo" 9 | export { default as UserIcon } from "./UserIcon" 10 | export { default as LogoutIcon } from "./LogoutIcon" 11 | export { default as ClockIcon } from "./ClockIcon" 12 | export { default as CopyIcon } from "./CopyIcon" 13 | export { default as DetailIcon } from "./DetailIcon" 14 | export { default as FolderIcon } from "./FolderIcon" 15 | export { default as HomeIcon } from "./HomeIcon" 16 | export { default as HostIcon } from "./HostIcon" 17 | export { default as ImageIcon } from "./ImageIcon" 18 | export { default as LinkIcon } from "./LinkIcon" 19 | export { default as DownloadIcon } from "./DownloadIcon" 20 | export { default as SearchIcon } from "./SearchIcon" 21 | export { default as UploadIcon } from "./UploadIcon" 22 | export { default as VideoIcon } from "./VideoIcon" 23 | export { default as MenuIcon } from "./MenuIcon" 24 | export { default as UsersIcon } from "./UsersIcon" 25 | export { default as TrashIcon } from "./TrashIcon" 26 | export { default as OpenEyeIcon } from "./OpenEyeIcon" 27 | export { default as CloseEyeIcon } from "./CloseEyeIcon" 28 | export { default as WalletIcon } from "./WalletIcon" -------------------------------------------------------------------------------- /components/FileCardSkeleton.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const FileCardSkeleton = ({ user }) => { 4 | return ( 5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | {!user && ( 21 |
22 |
23 |
24 |
25 | )} 26 |
27 |
28 |
29 | ); 30 | }; 31 | 32 | export default FileCardSkeleton; 33 | -------------------------------------------------------------------------------- /public/assets/home-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /components/LogoWall.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Image from "next/image"; 3 | import Balancer from "react-wrap-balancer"; 4 | 5 | const Logo = ({ src, description }) => { 6 | return ( 7 |
8 | {description 16 |
17 | ); 18 | }; 19 | 20 | const LogoWall = () => { 21 | return ( 22 |
23 |
24 |
25 |

26 | Powered by web3 technologies 27 |

28 |
29 |
30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 |
38 |
39 |
40 |
41 | ); 42 | }; 43 | 44 | export default LogoWall; 45 | -------------------------------------------------------------------------------- /constants/index.js: -------------------------------------------------------------------------------- 1 | import { upload, dashboard, folder, host, rocket, profile, image, video, clock } from '../assets'; 2 | import { HomeIcon, HostIcon, ImageIcon, VideoIcon, FolderIcon, ClockIcon, UploadIcon, UserIcon } from "../assets/Icons" 3 | 4 | export const navlinks = [ 5 | { 6 | name: 'dashboard', 7 | tip: 'Home', 8 | imgUrl: dashboard, 9 | link: '/dashboard', 10 | icon: 11 | }, 12 | { 13 | name: 'host', 14 | tip: 'Hosting', 15 | imgUrl: rocket, 16 | link: '/dashboard/host', 17 | icon: 18 | }, 19 | { 20 | name: 'upload media', 21 | tip: 'Upload', 22 | imgUrl: upload, 23 | link: '/dashboard/uploadmedia', 24 | icon: 25 | }, 26 | { 27 | name: 'files', 28 | tip: 'Files', 29 | imgUrl: folder, 30 | link: '/dashboard/files', 31 | icon: 32 | }, 33 | { 34 | name: 'videos', 35 | tip: 'Videos', 36 | imgUrl: video, 37 | link: '/dashboard/videos', 38 | icon: 39 | }, 40 | { 41 | name: 'photos', 42 | tip: 'Photos', 43 | imgUrl: image, 44 | link: '/dashboard/photos', 45 | icon: 46 | }, 47 | { 48 | name: 'recent', 49 | tip: 'Recent', 50 | imgUrl: clock, 51 | link: '/dashboard/recent', 52 | icon: 53 | }, 54 | { 55 | name: 'profile', 56 | tip: 'Profile', 57 | imgUrl: profile, 58 | link: '/dashboard/profile', 59 | icon: 60 | }, 61 | ]; -------------------------------------------------------------------------------- /public/assets/rock-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /components/widgetForm/ScreenshotButton.js: -------------------------------------------------------------------------------- 1 | // import html2canvas from 'html2canvas'; 2 | import { Camera, Trash } from 'phosphor-react'; 3 | import { useState } from 'react'; 4 | import { Loading } from '../Loading'; 5 | 6 | 7 | 8 | export function ScreenshotButton({ 9 | screenshot, 10 | onScreenshotTook, 11 | }) { 12 | const [isTakingScreenshot, setIsTakingScreenshot] = useState(false); 13 | 14 | async function handleTakeScreenshot() { 15 | setIsTakingScreenshot(true); 16 | // const canvas = await html2canvas(document.querySelector('html')!); 17 | // const base64image = canvas.toDataURL('image/png'); 18 | 19 | // onScreenshotTook(base64image); 20 | 21 | setIsTakingScreenshot(false); 22 | } 23 | 24 | if (screenshot) { 25 | return ( 26 | 38 | ); 39 | } 40 | 41 | return ( 42 | 49 | ); 50 | } 51 | -------------------------------------------------------------------------------- /public/assets/plus-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /components/index.js: -------------------------------------------------------------------------------- 1 | export { default as Sidebar } from "./Sidebar"; 2 | export { default as Navbar } from "./Navbar"; 3 | export { default as CustomButton } from "./CustomButton"; 4 | export { default as FormField } from "./FormField"; 5 | export { default as Loader } from "./Loader"; 6 | export { default as DisplayFiles } from "./DisplayFiles"; 7 | export { default as FileCard } from "./FileCard"; 8 | export { default as MediaModal } from "./MediaModal"; 9 | export { default as UserFileCard } from "./UserFileCard"; 10 | export { default as ToolTip } from "./ToolTip"; 11 | export { default as HomeNavbar } from "./HomeNavbar"; 12 | export { default as FolderUpload } from "./FolderUpload"; 13 | export { default as DisplayTable } from "./DisplayTable"; 14 | export { default as Snackbar } from "./Snackbar"; 15 | export { default as StatsCard } from "./StatsCard"; 16 | export { default as ProfileCard } from "./ProfileCard"; 17 | export { default as Stats } from "./Stats"; 18 | export { default as Header } from "./Header"; 19 | export { default as CountBox } from "./CountBox"; 20 | export { default as CardBox } from "./CardBox"; 21 | export { default as FileCardSkeleton } from "./FileCardSkeleton"; 22 | export { default as UserDropdown } from "./layout/UserDropdown"; 23 | export { default as CtaSection } from "./CtaSection"; 24 | export { default as VideoPlayer } from "./VideoPlayer"; 25 | export { default as LadyLoader } from "./LadyLoader"; 26 | export { default as LogoWall } from "./LogoWall"; 27 | export { default as FeatureCard } from "./FeatureCard"; 28 | export { default as GetStarted } from "./GetStarted"; 29 | export { default as Footer } from "./Footer"; 30 | export { default as Widget } from "./Widget"; 31 | export { default as GlobalStat } from "./GlobalStat"; -------------------------------------------------------------------------------- /components/GithubBadge.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import useSWR from "swr"; 3 | 4 | const GithubBadge = () => { 5 | 6 | const fetcher = (url) => fetch(url).then((res) => res.json()); 7 | 8 | const { data, error, isLoading } = useSWR( 9 | "https://api.github.com/repos/Darkrove/darkspace", 10 | fetcher 11 | ); 12 | 13 | return ( 14 |
15 | 21 | 26 | 27 | Star on Github 28 | {data.stargazers_count} 29 |
30 | ); 31 | }; 32 | 33 | 34 | export default GithubBadge; -------------------------------------------------------------------------------- /public/assets/sun.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | logo-full 4 | 5 |

6 |

Securely Store and Share Your Videos and Images on the Blockchain with DarkSpace.

7 | 8 |
9 | 10 | ![Stars](https://img.shields.io/github/stars/darkrove/darkspace?logo=dbt&color=%239988B6&style=for-the-badge&logoColor=white) 11 | [![Perrlist](https://img.shields.io/badge/PEERLIST-SAJJAD-orange?logo=scribd&logoColor=white&style=for-the-badge)](https://peerlist.io/sajjad) 12 | ![Codesize](https://img.shields.io/github/languages/code-size/darkrove/darkspace?logo=nextdotjs&logoColor=white&style=for-the-badge) 13 | ![License](https://img.shields.io/github/license/darkrove/darkspace?style=for-the-badge&logo=cmake&logoColor=white) 14 | ![Lastcommit](https://img.shields.io/github/last-commit/darkrove/darkspace?color=%23F213A4&style=for-the-badge&logo=quicktime&logoColot=white) 15 | [![Coffee](https://img.shields.io/badge/BUY%20ME%20A%20COFEE-BUY-%2357bcad?logo=buymeacoffee&logoColor=white&style=for-the-badge)](https://www.buymeacoffee.com/sajjadshaikh) 16 | 17 |
18 | 19 | ## 🛠 Tech Stack 20 | 21 | - [Next.js](https://nextjs.org/) - frontend / backend 22 | - [Tailwind](https://tailwindcss.com/) - styling 23 | - [RedixUI](https://www.radix-ui.com/) - components 24 | - [Thirdweb](https://thirdweb.com/) - web3 development framework 25 | - [IPFS](https://ipfs.io/) - p2p network 26 | - [Goerli](https://goerli.etherscan.io/) - blockchain test network 27 | 28 | ## ⚡ How it works? 29 | 30 | ![Frame 11](https://user-images.githubusercontent.com/53792139/218177211-cc70d8d2-a80c-423e-9b95-8af95e1f65c7.png) 31 | -------------------------------------------------------------------------------- /public/assets/video-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /components/DisplayFiles.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { FileCard, FileCardSkeleton } from "./"; 4 | 5 | const DisplayFiles = ({ 6 | children, 7 | title, 8 | subtitle, 9 | isLoading, 10 | files, 11 | address, 12 | user, 13 | style, 14 | error, 15 | }) => { 16 | const showStatus = () => { 17 | if (!address && !isLoading && user) { 18 | return ( 19 |

20 | Please connect your wallet!! 21 |

22 | ); 23 | } else if (!isLoading && files?.length === 0) { 24 | return ( 25 |

26 | Oops!! nothing to show 😬 27 |

28 | ); 29 | } 30 | }; 31 | 32 | return ( 33 |
34 |
35 |

36 | {title} 37 |

38 |

39 | {subtitle} ({files ? files?.length : "0"}) 40 |

41 |
42 | {isLoading && ( 43 |
44 | {[0, 1, 2, 3].map((id) => ( 45 | 46 | ))} 47 |
48 | )} 49 | {showStatus()} 50 |
51 | {!isLoading && 52 | files?.length > 0 && 53 | files 54 | .slice(0) 55 | .map((file, id) => ( 56 | 57 | ))} 58 |
59 | {children} 60 |
61 | ); 62 | }; 63 | 64 | export default DisplayFiles; 65 | -------------------------------------------------------------------------------- /public/assets/ethereum.org.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /public/assets/url-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/assets/filecoin.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /public/assets/logout-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/Video.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | justify-content: center; 4 | align-items: center; 5 | height: 100vh; 6 | } 7 | 8 | .video { 9 | width: 100%; 10 | } 11 | 12 | .videowrapper { 13 | width: 100%; 14 | position: relative; 15 | display: flex; 16 | justify-content: center; 17 | overflow: hidden; 18 | border-radius: 10px; 19 | } 20 | 21 | .videowrapper:hover .controls { 22 | transform: translateY(0%); 23 | } 24 | 25 | .controls { 26 | display: flex; 27 | align-items: center; 28 | justify-content: space-evenly; 29 | position: absolute; 30 | bottom: 30px; 31 | padding: 14px; 32 | width: 100%; 33 | max-width: 500px; 34 | flex-wrap: wrap; 35 | background: rgba(255, 255, 255, 0.25); 36 | box-shadow: 0 8px 32px 0 rgba(255, 255, 255, 0.1); 37 | backdrop-filter: blur(4px); 38 | -webkit-backdrop-filter: blur(4px); 39 | border-radius: 10px; 40 | border: 1px solid rgba(255, 255, 255, 0.18); 41 | transform: translateY(130%); 42 | transition: all 0.3s ease-in-out; 43 | } 44 | 45 | .btn { 46 | background: none; 47 | border: none; 48 | outline: none; 49 | cursor: pointer; 50 | } 51 | 52 | .btn { 53 | background-color: none; 54 | color: white; 55 | } 56 | 57 | .range { 58 | background: rgba(255, 255, 255, 0.2); 59 | border-radius: 20px; 60 | height: 4px; 61 | width: 350px; 62 | } 63 | 64 | .range::-webkit-slider-thumb { 65 | -webkit-appearance: none !important; 66 | cursor: pointer; 67 | height: 6px; 68 | } 69 | 70 | .range::-moz-range-progress { 71 | background: white; 72 | } 73 | 74 | .velocity { 75 | appearance: none; 76 | background: none; 77 | color: white; 78 | outline: none; 79 | border: none; 80 | text-align: center; 81 | font-size: 16px; 82 | } 83 | 84 | .mutebtn { 85 | background: none; 86 | border: none; 87 | outline: none; 88 | cursor: pointer; 89 | } 90 | 91 | .mutebtn { 92 | background-color: none; 93 | color: white; 94 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "darkspace-beta", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint", 10 | "export": "next export", 11 | "deploy": "next build && next export && npx thirdweb@latest upload out" 12 | }, 13 | "dependencies": { 14 | "@headlessui/react": "^1.7.12", 15 | "@heroicons/react": "^2.0.14", 16 | "@preline/dropdown": "^1.3.0", 17 | "@radix-ui/colors": "^0.1.8", 18 | "@radix-ui/react-avatar": "^1.0.2", 19 | "@radix-ui/react-popover": "^1.0.3", 20 | "@rajesh896/video-thumbnails-generator": "^2.3.9", 21 | "@thirdweb-dev/react": "^3.14.40", 22 | "@thirdweb-dev/sdk": "^3.10.59", 23 | "@thirdweb-dev/storage": "^1.0.6", 24 | "@vercel/analytics": "^0.1.8", 25 | "clsx": "^1.2.1", 26 | "daisyui": "^2.46.0", 27 | "date-fns": "^2.29.3", 28 | "dateformat": "^5.0.3", 29 | "deployment-badge": "^1.1.0", 30 | "ethers": "^5.7.2", 31 | "framer-motion": "^8.5.3", 32 | "lucide-react": "^0.107.0", 33 | "next": "^13.1.2", 34 | "next-auth": "^4.18.7", 35 | "next-pwa": "^5.6.0", 36 | "next-seo": "^5.15.0", 37 | "nextjs-progressbar": "^0.0.16", 38 | "nft.storage": "^7.0.0", 39 | "phosphor-react": "^1.4.1", 40 | "preline": "^1.7.0", 41 | "react": "^18.2", 42 | "react-dom": "^18.2", 43 | "react-hot-toast": "^2.4.0", 44 | "react-icons": "^4.7.1", 45 | "react-query": "^3.39.3", 46 | "react-wrap-balancer": "^0.4.0", 47 | "swr": "^2.0.3", 48 | "tailwind-merge": "^1.10.0", 49 | "web3": "^1.8.1" 50 | }, 51 | "devDependencies": { 52 | "@gradin/tailwindcss-skeleton-screen": "^1.0.2", 53 | "@types/react": "^18.0.27", 54 | "autoprefixer": "^10.4.13", 55 | "eslint": "8.11.0", 56 | "eslint-config-next": "^13", 57 | "postcss": "^8.4.20", 58 | "tailwindcss": "^3.2.4" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /assets/index.js: -------------------------------------------------------------------------------- 1 | const dashboard = '/assets/home-seyfdesigner.svg'; 2 | const logo = '/assets/logo.svg'; 3 | const logout = '/assets/logout-seyfdesigner.svg'; 4 | const folder = '/assets/folder-seyfdesigner.svg'; 5 | const profile = '/assets/user-seyfdesigner.svg'; 6 | const sun = '/assets/sun.svg'; 7 | const upload = '/assets/upload-seyfdesigner.svg'; 8 | const video = '/assets/video-seyfdesigner.svg'; 9 | const clock = '/assets/clock-seyfdesigner.svg'; 10 | const search = '/assets/search-seyfdesigner.svg'; 11 | const menu = '/assets/menu-seyfdesigner.svg'; 12 | const image = '/assets/image-seyfdesigner.svg'; 13 | const loader = '/assets/loader.svg'; 14 | const userProfile = '/assets/blank-profile.png'; 15 | const secure = '/assets/secure.svg'; 16 | const verticalMenu = '/assets/vertical-menu.svg'; 17 | const videoIcon = '/assets/video-icon.svg'; 18 | const imageIcon = '/assets/image-icon.svg'; 19 | const hostIcon = '/assets/host-icon.svg'; 20 | const host = '/assets/host-seyfdesigner.svg'; 21 | const rocket = '/assets/rock-seyfdesigner.svg'; 22 | const download = '/assets/download-seyfdesigner.svg'; 23 | const url = '/assets/url-seyfdesigner.svg'; 24 | const link = '/assets/link-seyfdesigner.svg'; 25 | const copy = '/assets/copy-seyfdesigner.svg'; 26 | const info = '/assets/info-seyfdesigner.svg'; 27 | const share = '/assets/share-seyfdesigner.svg'; 28 | const remove = '/assets/delete-seyfdesigner.svg'; 29 | const ethereum = '/assets/ethereum.org.svg'; 30 | const heroLogo = '/assets/hero-geometry.webp'; 31 | 32 | export { 33 | clock, 34 | verticalMenu, 35 | upload, 36 | dashboard, 37 | logo, 38 | logout, 39 | folder, 40 | profile, 41 | sun, 42 | video, 43 | search, 44 | menu, 45 | image, 46 | loader, 47 | userProfile, 48 | secure, 49 | videoIcon, 50 | imageIcon, 51 | hostIcon, 52 | host, 53 | rocket, 54 | download, 55 | url, 56 | link, 57 | share, 58 | copy, 59 | info, 60 | remove, 61 | ethereum, 62 | heroLogo 63 | }; 64 | -------------------------------------------------------------------------------- /components/FolderUpload.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Image from "next/image"; 3 | 4 | const folderUpload = ({ isActive, handleChange }) => { 5 | return ( 6 |
7 |
8 |
9 |
14 | 22 |
23 |
24 | illustration 31 |

32 | Upload a project containg CSS, HTML & JS inside same folder{" "} 33 | {" "} 40 |

41 |
42 |
43 |
44 |
45 |
46 | ); 47 | }; 48 | 49 | export default folderUpload; 50 | -------------------------------------------------------------------------------- /lib/hooks/useVideoPlayer.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | 3 | const useVideoPlayer = (videoElement) => { 4 | const [playerState, setPlayerState] = useState({ 5 | isPlaying: false, 6 | progress: 0, 7 | speed: 1, 8 | isMuted: false, 9 | }); 10 | 11 | const togglePlay = () => { 12 | setPlayerState({ 13 | ...playerState, 14 | isPlaying: !playerState.isPlaying, 15 | }); 16 | }; 17 | 18 | useEffect(() => { 19 | playerState.isPlaying 20 | ? videoElement.current.play() 21 | : videoElement.current.pause(); 22 | }, [playerState.isPlaying, videoElement]); 23 | 24 | const handleOnTimeUpdate = () => { 25 | const progress = (videoElement.current.currentTime / videoElement.current.duration) * 100; 26 | setPlayerState({ 27 | ...playerState, 28 | progress, 29 | }); 30 | }; 31 | 32 | const handleVideoProgress = (event) => { 33 | const manualChange = Number(event.target.value); 34 | videoElement.current.currentTime = (videoElement.current.duration / 100) * manualChange; 35 | setPlayerState({ 36 | ...playerState, 37 | progress: manualChange, 38 | }); 39 | }; 40 | 41 | const handleVideoSpeed = (event) => { 42 | const speed = Number(event.target.value); 43 | videoElement.current.playbackRate = speed; 44 | setPlayerState({ 45 | ...playerState, 46 | speed, 47 | }); 48 | }; 49 | 50 | const toggleMute = () => { 51 | setPlayerState({ 52 | ...playerState, 53 | isMuted: !playerState.isMuted, 54 | }); 55 | }; 56 | 57 | useEffect(() => { 58 | playerState.isMuted 59 | ? (videoElement.current.muted = true) 60 | : (videoElement.current.muted = false); 61 | }, [playerState.isMuted, videoElement]); 62 | 63 | return { 64 | playerState, 65 | togglePlay, 66 | handleOnTimeUpdate, 67 | handleVideoProgress, 68 | handleVideoSpeed, 69 | toggleMute, 70 | }; 71 | }; 72 | 73 | export default useVideoPlayer; -------------------------------------------------------------------------------- /public/assets/withdraw.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /public/assets/money.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /components/ProfileCard.js: -------------------------------------------------------------------------------- 1 | import React, { useState, ueEffect } from "react"; 2 | import Image from "next/image"; 3 | 4 | import { GoogleLogo, GithubLogo, DiscordLogo } from "../assets/Icons" 5 | import Profile from "./ui/avatar"; 6 | import { capitalizeFirstLetter } from "../utils"; 7 | import useOnlineStatus from "../lib/hooks/useOnlineStatus" 8 | import clsx from 'clsx'; 9 | 10 | export default function ProfileCard({ host, user }) { 11 | const status = useOnlineStatus() 12 | return ( 13 |
14 |
15 |

24 | {host === 'github' && }{" "} 25 | {host === 'google' && }{" "} 26 | {host === 'discord' && }{" "} 27 | 28 | {user?.email} 29 |

30 |
31 |

32 | {capitalizeFirstLetter(user?.name)} 33 |

34 |
35 |
36 |
37 | {/* {user?.name} */} 44 | 45 |
46 |
47 | ); 48 | } -------------------------------------------------------------------------------- /public/assets/image-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /components/ui/toast.jsx: -------------------------------------------------------------------------------- 1 | import { Icons } from '../LucideIcons.js' 2 | import { cn } from '../../lib/utils' 3 | 4 | import * as React from 'react' 5 | import hotToast, { Toaster as HotToaster } from 'react-hot-toast' 6 | 7 | export const Toaster = HotToaster 8 | 9 | export function Toast({ visible, className, ...props }) { 10 | return ( 11 |
19 | ) 20 | } 21 | 22 | Toast.Icon = function ToastIcon({ name, className, ...props }) { 23 | const Icon = Icons[name] 24 | 25 | if (!Icon) { 26 | return null 27 | } 28 | 29 | return ( 30 |
31 | 32 |
33 | ) 34 | } 35 | 36 | Toast.Title = function ToastTitle({ className, ...props }) { 37 | return

38 | } 39 | 40 | Toast.Description = function ToastDescription({ 41 | className, 42 | ...props 43 | }) { 44 | return

45 | } 46 | 47 | export function toast(opts) { 48 | const { icon, title, message, type = 'default', duration = 3000 } = opts 49 | 50 | return hotToast.custom( 51 | ({ visible }) => ( 52 | 58 |

59 | 60 |
61 | {title} 62 | {message && {message}} 63 |
64 |
65 | 66 | 67 | 68 | ), 69 | { duration } 70 | ) 71 | } -------------------------------------------------------------------------------- /styles/globals.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Epilogue:wght@400;500;600;700&display=swap"); 2 | @import "@radix-ui/colors/blackA.css"; 3 | @import "@radix-ui/colors/violet.css"; 4 | 5 | @tailwind base; 6 | @tailwind components; 7 | @tailwind utilities; 8 | 9 | body { 10 | @apply text-white/70 bg-zinc-900 relative; 11 | } 12 | body::before { 13 | width: 100%; 14 | height: 100%; 15 | content: ""; 16 | position: fixed; 17 | background: radial-gradient( 18 | 75.61% 75.61% at 50% 24.39%, 19 | rgba(133, 19, 179, 0.596) 0%, 20 | rgba(107, 9, 146, 0) 100% 21 | ); 22 | z-index: -1; 23 | } 24 | 25 | * { 26 | -webkit-tap-highlight-color: transparent; 27 | } 28 | 29 | .linear-gradient { 30 | background: linear-gradient( 31 | 179.14deg, 32 | rgba(32, 18, 63, 0) -7.14%, 33 | #000000 87.01% 34 | ); 35 | } 36 | 37 | input[type="date"]::-webkit-calendar-picker-indicator { 38 | cursor: pointer; 39 | filter: invert(0.8); 40 | } 41 | 42 | .card { 43 | @apply bg-white/5 backdrop-blur-lg border border-white/10 rounded-xl; 44 | } 45 | 46 | .loader-pulse { 47 | @apply bg-violet-500; 48 | width: 64px; 49 | height: 64px; 50 | border-radius: 50%; 51 | animation: load-pulse 0.85s infinite linear; 52 | } 53 | 54 | @keyframes load-pulse { 55 | 0% { 56 | transform: scale(0.15); 57 | opacity: 0; 58 | } 59 | 60 | 50% { 61 | opacity: 1; 62 | } 63 | 64 | 100% { 65 | transform: scale(1); 66 | opacity: 0; 67 | } 68 | } 69 | 70 | .gridcard { 71 | background-color: #18181b; 72 | opacity: 1; 73 | background-image: radial-gradient(#cc23ff 0.65px, transparent 0.65px), 74 | radial-gradient(#cc23ff 0.65px, #18181b 0.65px); 75 | background-size: 26px 26px; 76 | background-position: 0 0, 13px 13px; 77 | } 78 | 79 | .AvatarRoot { 80 | display: inline-flex; 81 | align-items: center; 82 | justify-content: center; 83 | vertical-align: middle; 84 | overflow: hidden; 85 | user-select: none; 86 | background-color: var(--blackA3); 87 | } 88 | 89 | .AvatarImage { 90 | width: 100%; 91 | height: 100%; 92 | object-fit: cover; 93 | } 94 | 95 | .AvatarFallback { 96 | color: white; 97 | font-size: 15px; 98 | line-height: 1; 99 | font-weight: 500; 100 | } 101 | -------------------------------------------------------------------------------- /public/assets/thirdweb.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /components/widgetForm/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { CloseButton } from '../CloseButton'; 3 | 4 | import FeedbackTypeStep from './steps/FeedbackTypeStep'; 5 | import FeedbackContentStep from './steps/FeedbackContentStep'; 6 | import FeedbackSuccessStep from './steps/FeedbackSuccessStep'; 7 | 8 | const bugImageUrl = '/assets/bug.svg'; 9 | const ideiaImageUrl = '/assets/idea.svg'; 10 | const thoughtImageUrl = '/assets/thought.svg'; 11 | 12 | export const feedbackTypes = { 13 | BUG: { 14 | title: 'Problems', 15 | image: { 16 | source: bugImageUrl, 17 | alt: 'Image of Bug', 18 | }, 19 | form: "https://forms.gle/j4wyUGUq9CgmEZKX9", 20 | }, 21 | IDEA: { 22 | title: 'Idea', 23 | image: { 24 | source: ideiaImageUrl, 25 | alt: 'Image of Lamp', 26 | }, 27 | form: "https://forms.gle/VnaU8h9wVfQa9EdR8", 28 | }, 29 | OTHER: { 30 | title: 'Other', 31 | image: { 32 | source: thoughtImageUrl, 33 | alt: 'Imagem of Thought', 34 | }, 35 | form: "https://forms.gle/Vab3EW3ATFup7TFd6", 36 | }, 37 | }; 38 | 39 | // export type FeedbackType = keyof typeof feedbackTypes; 40 | 41 | export function WidgetForm() { 42 | const [feedbackType, setFeedbackType] = useState(null); 43 | const [feedbackSent, setFeedbackSent] = useState(false); 44 | 45 | function handleRestartFeedback() { 46 | setFeedbackSent(false); 47 | setFeedbackType(null); 48 | } 49 | 50 | return ( 51 |
52 | {feedbackSent ? ( 53 | 54 | ) : ( 55 | <> 56 | {!feedbackType ? ( 57 | 58 | ) : ( 59 | setFeedbackSent(true)} 63 | /> 64 | )} 65 | 66 | )} 67 | 68 |
69 | Made with 💜 by{' '} 70 | Darkspace 71 |
72 |
73 | ); 74 | } 75 | -------------------------------------------------------------------------------- /styles/Home.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | padding: 0 2rem; 3 | } 4 | 5 | .main { 6 | min-height: 100vh; 7 | padding: 4rem 0; 8 | flex: 1; 9 | display: flex; 10 | flex-direction: column; 11 | justify-content: center; 12 | align-items: center; 13 | } 14 | 15 | .title a { 16 | color: #f213a4; 17 | text-decoration: none; 18 | } 19 | 20 | .title a:hover, 21 | .title a:focus, 22 | .title a:active { 23 | text-decoration: underline; 24 | } 25 | 26 | .title { 27 | margin: 0; 28 | line-height: 1.15; 29 | font-size: 4rem; 30 | } 31 | 32 | .title, 33 | .description { 34 | text-align: center; 35 | } 36 | 37 | .connect { 38 | margin-bottom: 2rem; 39 | width: 230px; 40 | } 41 | 42 | .description { 43 | margin-top: 3rem; 44 | margin-bottom: 2rem; 45 | line-height: 1.5; 46 | font-size: 1.5rem; 47 | } 48 | 49 | .code { 50 | background: #fafafa; 51 | border-radius: 5px; 52 | padding: 0.75rem; 53 | font-size: 1.1rem; 54 | font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, 55 | Bitstream Vera Sans Mono, Courier New, monospace; 56 | } 57 | 58 | .grid { 59 | display: flex; 60 | align-items: center; 61 | justify-content: center; 62 | flex-wrap: wrap; 63 | max-width: 1200px; 64 | } 65 | 66 | .card { 67 | background-color: #1b2129; 68 | margin: 1rem; 69 | padding: 1.5rem; 70 | text-align: left; 71 | color: inherit; 72 | text-decoration: none; 73 | border: 1px solid #eaeaea; 74 | border-radius: 10px; 75 | transition: color 0.15s ease, border-color 0.15s ease; 76 | max-width: 350px; 77 | } 78 | 79 | .card:hover, 80 | .card:focus, 81 | .card:active { 82 | background-color: #272c34; 83 | color: #0ea5e9; 84 | border-color: #0ea5e9; 85 | } 86 | 87 | .card h2 { 88 | margin: 0 0 1rem 0; 89 | font-size: 1.5rem; 90 | } 91 | 92 | .card p { 93 | margin: 0; 94 | font-size: 1.25rem; 95 | line-height: 1.5; 96 | } 97 | 98 | .logo { 99 | height: 1em; 100 | margin-left: 0.5rem; 101 | } 102 | 103 | @media (max-width: 600px) { 104 | .grid { 105 | width: 100%; 106 | flex-direction: column; 107 | } 108 | } 109 | 110 | .card, 111 | .footer { 112 | border-color: #222; 113 | } 114 | .code { 115 | background: #111; 116 | } 117 | .logo img { 118 | filter: invert(1); 119 | } 120 | -------------------------------------------------------------------------------- /components/confirmModal.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const confirmModal = () => { 4 | return ( 5 |
6 |
7 | 17 | 22 | 23 | 24 | 25 | 26 |

27 | Quis vel eros donec ac odio tempor. 28 |

29 |

30 | Tempora ipsa quod magnam non, dolores nemo optio. Praesentium soluta 31 | maiores non itaque aliquam sint. 32 |

33 | 39 |
40 |
41 | ); 42 | }; 43 | 44 | export default confirmModal; 45 | -------------------------------------------------------------------------------- /components/GlobalStat.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Balancer from "react-wrap-balancer"; 3 | import useSWR from "swr"; 4 | import { formatBytes } from '../utils'; 5 | 6 | const GlobalStat = () => { 7 | const fetcher = (url) => fetch(url).then((res) => res.json()); 8 | const { data, error, isLoading } = useSWR( 9 | "/api/fetch/stats", 10 | fetcher 11 | ); 12 | return ( 13 |
14 |
15 |
16 |

17 | Highlight 18 | 19 | 20 | Important highlights about darkspace activity 🚀 21 | 22 |

23 |
24 |
25 |
26 |

27 | Total Files 28 |

29 |

{data ? data.filecount : 0}

30 |
31 |
32 |
33 |
34 |

35 | Total Uploads 36 |

37 |

{data ? formatBytes(data.size) : "00 MB"}

38 |
39 |
40 |
41 |
42 |
43 |
44 | ) 45 | } 46 | 47 | export default GlobalStat -------------------------------------------------------------------------------- /components/GetStarted.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Balancer from "react-wrap-balancer"; 3 | import Router from "next/router"; 4 | 5 | import { DarkspaceLogo } from "../assets/Icons"; 6 | import { useStateContext } from "../context"; 7 | 8 | const GetStarted = () => { 9 | const { activePage, setActivePage } = useStateContext(); 10 | return ( 11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | 23 |
24 |
25 |
26 |
27 |

28 | Get Started now 29 |

30 |

31 | 32 | The future of storage is here. Start owning your data and 33 | experience the power of blockchain technology. 34 | 35 |

36 |
37 | 46 |
47 |
48 |
49 |
50 |
51 | ); 52 | }; 53 | 54 | export default GetStarted; 55 | -------------------------------------------------------------------------------- /pages/api/auth/[...nextauth].js: -------------------------------------------------------------------------------- 1 | import NextAuth, { NextAuthOptions } from "next-auth"; 2 | import DiscordProvider from "next-auth/providers/discord" 3 | import GithubProvider from "next-auth/providers/github"; 4 | import GoogleProvider from "next-auth/providers/google"; 5 | 6 | function getGoogleCredentials() { 7 | const clientId = process.env.NEXT_PUBLIC_GOOGLE_ID 8 | const clientSecret = process.env.NEXT_PUBLIC_GOOGLE_SECRET 9 | 10 | if (!clientId || clientId.length === 0) { 11 | throw new Error("Missing ClientId for Google credentials"); 12 | } 13 | if(!clientSecret || clientSecret.length === 0) { 14 | throw new Error("Missing ClientSecret for Google credentials"); 15 | } 16 | return { clientId, clientSecret }; 17 | } 18 | 19 | function getGithubCredentials() { 20 | const clientId = process.env.NEXT_PUBLIC_GITHUB_ID 21 | const clientSecret = process.env.NEXT_PUBLIC_GITHUB_SECRET 22 | 23 | if (!clientId || clientId.length === 0) { 24 | throw new Error("Missing ClientId for Github credentials"); 25 | } 26 | if(!clientSecret || clientSecret.length === 0) { 27 | throw new Error("Missing ClientSecret for Github credentials"); 28 | } 29 | return { clientId, clientSecret }; 30 | } 31 | 32 | function getDiscordCredentials() { 33 | const clientId = process.env.NEXT_PUBLIC_DISCORD_ID 34 | const clientSecret = process.env.NEXT_PUBLIC_DISCORD_SECRET 35 | 36 | if (!clientId || clientId.length === 0) { 37 | throw new Error("Missing ClientId for Discord credentials"); 38 | } 39 | if(!clientSecret || clientSecret.length === 0) { 40 | throw new Error("Missing ClientSecret for Discord credentials"); 41 | } 42 | return { clientId, clientSecret }; 43 | } 44 | 45 | export const authOptions = { 46 | pages: { 47 | signIn: '/signin', 48 | }, 49 | providers: [ 50 | DiscordProvider({ 51 | clientId: getDiscordCredentials().clientId, 52 | clientSecret: getDiscordCredentials().clientSecret, 53 | }), 54 | GithubProvider({ 55 | clientId: getGithubCredentials().clientId, 56 | clientSecret: getGithubCredentials().clientSecret, 57 | }), 58 | GoogleProvider({ 59 | clientId: getGoogleCredentials().clientId, 60 | clientSecret: getGoogleCredentials().clientSecret, 61 | }), 62 | ], 63 | theme: { 64 | colorScheme: "dark", 65 | }, 66 | callbacks: { 67 | async jwt({ token }) { 68 | token.userRole = "admin"; 69 | return token; 70 | }, 71 | }, 72 | }; 73 | 74 | export default NextAuth(authOptions); 75 | -------------------------------------------------------------------------------- /public/assets/download-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /components/VideoPlayer.js: -------------------------------------------------------------------------------- 1 | import React, { useRef } from "react"; 2 | import { FaPlay, FaPause, FaVolumeUp, FaVolumeMute } from "react-icons/fa"; 3 | 4 | import styles from "../styles/Video.module.css"; 5 | import useVideoPlayer from "../lib/hooks/useVideoPlayer"; 6 | 7 | const VideoPlayer = (props) => { 8 | const { src, style } = props; 9 | const videoElement = useRef(null); 10 | const { 11 | playerState, 12 | togglePlay, 13 | handleOnTimeUpdate, 14 | handleVideoProgress, 15 | handleVideoSpeed, 16 | toggleMute, 17 | } = useVideoPlayer(videoElement); 18 | return ( 19 |
20 |
21 |
73 |
74 | ); 75 | }; 76 | 77 | export default VideoPlayer; 78 | -------------------------------------------------------------------------------- /components/shared/Leaflet.tsx: -------------------------------------------------------------------------------- 1 | import React, { 2 | useEffect, 3 | useRef, 4 | ReactNode, 5 | Dispatch, 6 | SetStateAction, 7 | } from "react"; 8 | import { AnimatePresence, motion, useAnimation } from "framer-motion"; 9 | 10 | export default function Leaflet({ 11 | setShow, 12 | children, 13 | }: { 14 | setShow: Dispatch>; 15 | children: ReactNode; 16 | }) { 17 | const leafletRef = useRef(null); 18 | const controls = useAnimation(); 19 | const transitionProps = { type: "spring", stiffness: 500, damping: 30 }; 20 | useEffect(() => { 21 | controls.start({ 22 | y: 20, 23 | transition: transitionProps, 24 | }); 25 | // eslint-disable-next-line react-hooks/exhaustive-deps 26 | }, []); 27 | 28 | async function handleDragEnd(_: any, info: any) { 29 | const offset = info.offset.y; 30 | const velocity = info.velocity.y; 31 | const height = leafletRef.current?.getBoundingClientRect().height || 0; 32 | if (offset > height / 2 || velocity > 800) { 33 | await controls.start({ y: "100%", transition: transitionProps }); 34 | setShow(false); 35 | } else { 36 | controls.start({ y: 0, transition: transitionProps }); 37 | } 38 | } 39 | 40 | return ( 41 | 42 | 56 |
59 |
60 |
61 |
62 | {children} 63 | 64 | setShow(false)} 71 | /> 72 | 73 | ); 74 | } 75 | -------------------------------------------------------------------------------- /public/assets/star-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/assets/upload-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/assets/user-seyfdesigner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /components/Sidebar.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Link from "next/link"; 3 | import Image from "next/image"; 4 | import { useRouter } from "next/router"; 5 | import { useSession } from "next-auth/react"; 6 | 7 | import { navlinks } from "../constants"; 8 | import { sun } from "../assets"; 9 | import { useStateContext } from "../context"; 10 | import { ToolTip } from "./"; 11 | import { DarkspaceLogo } from "../assets/Icons"; 12 | 13 | const Icon = ({ styles, name, imgUrl, activePage, disabled, handleClick }) => ( 14 |
24 | {!activePage ? ( 25 | logo 33 | ) : ( 34 | logo 44 | )} 45 |
46 | ); 47 | 48 | const Sidebar = () => { 49 | const { activePage, setActivePage } = useStateContext(); 50 | const router = useRouter(); 51 | 52 | return ( 53 |
54 | setActivePage("dashboard")} 56 | href="/dashboard" 57 | className="w-[48px] h-[48px] rounded-[10px] bg-white/5 flex justify-center items-center" 58 | > 59 | 60 | 61 | 62 |
63 |
64 | {navlinks.map((link) => ( 65 | 66 | { 71 | if (!link.disabled) { 72 | setActivePage(link.name); 73 | router.push(link.link); 74 | } 75 | }} 76 | /> 77 | 78 | ))} 79 |
80 | {/* */} 81 |
82 |
83 | ); 84 | }; 85 | 86 | export default Sidebar; 87 | -------------------------------------------------------------------------------- /components/layout/UserDropdown.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { signOut, useSession } from "next-auth/react"; 3 | import Link from "next/link"; 4 | import Image from "next/image"; 5 | import { motion } from "framer-motion"; 6 | 7 | import { UserIcon, LogoutIcon } from "../../assets/Icons"; 8 | import Profile from "../ui/avatar"; 9 | import Popover from "../shared/Popover"; 10 | import { FADE_IN_ANIMATION_SETTINGS } from "../../lib/constants"; 11 | 12 | export default function UserDropdown({ onProfileClick }) { 13 | const { data: session } = useSession(); 14 | const { name, email, image } = session?.user || {}; 15 | const [openPopover, setOpenPopover] = useState(false); 16 | 17 | if (!email) return null; 18 | 19 | return ( 20 | 24 | 27 | 32 | 33 |

Profile

34 | 35 | {/* */} 42 | 49 |
50 | } 51 | align="end" 52 | openPopover={openPopover} 53 | setOpenPopover={setOpenPopover} 54 | > 55 | 61 | 62 | 63 | ); 64 | } 65 | -------------------------------------------------------------------------------- /pages/dashboard/recent.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import Link from "next/link"; 3 | import { getServerSession } from "next-auth/next"; 4 | import useSWR from "swr"; 5 | 6 | import { authOptions } from "../api/auth/[...nextauth]"; 7 | import { useStateContext } from "../../context"; 8 | import { LeftFaceArrow } from "../../assets/Icons"; 9 | import { DisplayFiles } from "../../components"; 10 | 11 | const Recent = () => { 12 | const { address, contract, setActivePage, getUserFiles } = useStateContext(); 13 | 14 | const fetchFiles = async () => { 15 | const data = await getUserFiles(); 16 | return data 17 | }; 18 | 19 | const { data, error, isLoading } = useSWR(["userFiles"], fetchFiles); 20 | 21 | return ( 22 |
23 | file.type.split("/")[0] === "image") 29 | .reverse() 30 | .slice(0, 4)} 31 | address={address} 32 | user={true} 33 | > 34 | {address && 35 | data?.filter((file) => file.type.split("/")[0] === "image").length > 36 | 0 ? ( 37 | setActivePage("photos")} 40 | rel="noreferrer" 41 | className="flex group gap-2 mt-[10px] items-center duration-200 text-zinc-500 cursor-pointer no-underline hover:text-zinc-400" 42 | > 43 | See Others{" "} 44 | 45 | 46 | 47 | 48 | ) : null} 49 | 50 | file.type.split("/")[0] === "video") 56 | .reverse() 57 | .slice(0, 4)} 58 | address={address} 59 | user={true} 60 | style="mt-[20px]" 61 | > 62 | {address && 63 | data?.filter((file) => file.type.split("/")[0] === "video").length > 64 | 0 ? ( 65 | setActivePage("videoss")} 68 | rel="noreferrer" 69 | className="flex group gap-2 mt-[10px] items-center duration-200 text-zinc-500 cursor-pointer no-underline hover:text-zinc-400" 70 | > 71 | See Others{" "} 72 | 73 | 74 | 75 | 76 | ) : null} 77 | 78 |
79 | ); 80 | }; 81 | 82 | export default Recent; -------------------------------------------------------------------------------- /components/Footer.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { FaGithub, FaInstagram, FaDiscord, FaTwitter } from "react-icons/fa"; 3 | import { SiHashnode } from "react-icons/si"; 4 | 5 | import { DarkspaceLogoFull } from "../assets/Icons"; 6 | 7 | const SocialIcon = ({ icon, title, link }) => { 8 | return ( 9 |
  • 10 | 16 | {title} 17 | {icon} 18 | 19 |
  • 20 | ); 21 | }; 22 | 23 | const Footer = () => { 24 | return ( 25 |
    29 |
    30 |
    31 |
    32 | 33 |
    34 | 35 |

    36 | The Next Generation of Secure and Decentralized Data Storage: 37 | DarkSpace 38 |

    39 |
    40 | 41 |
    42 |

    43 | Copyright © 2023. All rights reserved. 44 |

    45 | 46 |
      47 | } 49 | title="github" 50 | link="https://github.com/Darkrove/darkspace" 51 | /> 52 | } 54 | title="instagram" 55 | link="https://www.instagram.com/sajjadshaikh.io/" 56 | /> 57 | } 59 | title="twitter" 60 | link="https://twitter.com/sajjads72619701" 61 | /> 62 | } 64 | title="discord" 65 | link="https://discord.gg/Ftg4SY7NEj" 66 | /> 67 | } 69 | title="hashnode" 70 | link="https://hashnode.com/@darkrove" 71 | /> 72 |
    73 |
    74 |
    75 |
    76 | ); 77 | }; 78 | 79 | export default Footer; 80 | -------------------------------------------------------------------------------- /components/CtaSection.js: -------------------------------------------------------------------------------- 1 | import Balancer from "react-wrap-balancer"; 2 | import Router from "next/router"; 3 | import Image from "next/image"; 4 | 5 | import { useStateContext } from "../context"; 6 | import styles from "../styles/Button.module.css"; 7 | 8 | export default function CtaSection() { 9 | const { activePage, setActivePage } = useStateContext(); 10 | return ( 11 |
    12 |
    13 |
    14 |
    15 |

    16 | 17 | Securely Store and Share Your Videos and Images on the 18 | Blockchain with DarkSpace 19 | 20 |

    21 |

    22 | 23 | Dive and Experience the power of decentralization and never 24 | worry about your stuff being lost or snooped. 25 | 26 |

    27 |
    28 | 37 | 42 |
    43 |

    44 | Completely free to use. No hidden fees. 45 |

    46 |
    47 |
    48 | hero image 55 |
    56 |
    57 |
    58 |
    59 | ); 60 | } 61 | -------------------------------------------------------------------------------- /public/assets/create-campaign.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /pages/about.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import useSWR from "swr"; 3 | 4 | const about = () => { 5 | const fetcher = (url) => fetch(url).then((res) => res.json()); 6 | 7 | // eslint-disable-next-line react-hooks/rules-of-hooks 8 | const { data, error, isLoading } = useSWR( 9 | "https://api.github.com/repos/Darkrove/darkspace", 10 | fetcher 11 | ); 12 | return ( 13 |
    14 |
    15 |

    16 | Open Source Project 🔮 17 |

    18 |

    19 | The source code of this project is available on {" "} 20 | github {" "} 25 | for you to review, modify and you can also contribute to this project if you want to by 26 | forking 📌 this repo and making pull requests. 27 |

    28 |
    29 | 35 | 40 | 41 | Star on Github 42 | {data?.stargazers_count} 43 |
    44 |
    45 |
    46 | ) 47 | } 48 | 49 | export default about 50 | -------------------------------------------------------------------------------- /utils/index.js: -------------------------------------------------------------------------------- 1 | import Web3 from "web3" 2 | import { intlFormatDistance } from "date-fns" 3 | import { intlFormat } from "date-fns" 4 | import dateFormat from "dateformat" 5 | 6 | const web3 = new Web3(); 7 | 8 | export const checkIfImage = (url, callback) => { 9 | const img = new Image(); 10 | img.src = url; 11 | 12 | if (img.complete) callback(true); 13 | 14 | img.onload = () => callback(true); 15 | img.onerror = () => callback(false); 16 | }; 17 | 18 | export const shortenAddress = (address) => { 19 | return `${address?.slice(0, 10)}...${address?.slice(address?.length - 8)}`; 20 | }; 21 | 22 | export const formatBytes = (bytes, decimals = 2) => { 23 | if (!+bytes) return "0 Bytes"; 24 | 25 | const k = 1024; 26 | const dm = decimals < 0 ? 0 : decimals; 27 | const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; 28 | 29 | const i = Math.floor(Math.log(bytes) / Math.log(k)); 30 | 31 | return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`; 32 | }; 33 | 34 | export const formatDate = (epoch) => { 35 | const uploadDate = new Date(epoch * 1000); 36 | // const currentDate = new Date(); 37 | // let dateDiff = intlFormatDistance(new Date(uploadDate.getFullYear(), uploadDate.getMonth()+1, uploadDate.getDate(), uploadDate.getHours(), uploadDate.getMinutes(), uploadDate.getSeconds()), 38 | // new Date(currentDate.getFullYear(), currentDate.getMonth()+1, currentDate.getDate(), currentDate.getHours(), currentDate.getMinutes(), currentDate.getSeconds())) 39 | // let dateStr = uploadDate.getFullYear() + "/" + (uploadDate.getMonth() + 1) + "/" + uploadDate.getDate() + " " + uploadDate.getHours() + ":" + uploadDate.getMinutes() + ":" + uploadDate.getSeconds() 40 | // let date = intlFormat(new Date(uploadDate.getFullYear(), uploadDate.getMonth(), uploadDate.getDate(), uploadDate.getHours(), uploadDate.getMinutes(), uploadDate.getSeconds()), { 41 | // year: 'numeric', 42 | // month: 'numeric', 43 | // day: 'numeric', 44 | // hour: 'numeric', 45 | // }) 46 | const now = new Date(uploadDate.getFullYear(), uploadDate.getMonth(), uploadDate.getDate(), uploadDate.getHours(), uploadDate.getMinutes(), uploadDate.getSeconds()) 47 | const date = dateFormat(now, "mmm d, yyyy, h:MM TT"); 48 | return date.toString() 49 | } 50 | 51 | export const formatLongDate = (epoch) => { 52 | const uploadDate = new Date(epoch * 1000) 53 | const now = new Date(uploadDate.getFullYear(), uploadDate.getMonth(), uploadDate.getDate(), uploadDate.getHours(), uploadDate.getMinutes(), uploadDate.getSeconds()) 54 | const date = dateFormat(now, "dddd, mmmm dS, yyyy, h:MM:ss TT"); 55 | return date.toString() 56 | } 57 | 58 | export const padString = (str) => { 59 | let res = web3.utils.fromAscii(str) 60 | while (res.length < 66) { 61 | res += '0'; 62 | } 63 | return res; 64 | }; 65 | 66 | export const unpadString = (str) => { 67 | let res = web3.utils.toAscii(str) 68 | return res.replace(/\0/g, '') 69 | } 70 | 71 | export const capitalizeFirstLetter = (string) => { 72 | if (string) { 73 | return string[0].toUpperCase() + string.slice(1).toLowerCase(); 74 | } else { 75 | return "Nan" 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /styles/Ladyloader.module.css: -------------------------------------------------------------------------------- 1 | .loader { 2 | --path: #2f3545; 3 | --dot: #5628ee; 4 | --duration: 3s; 5 | width: 44px; 6 | height: 44px; 7 | position: relative; 8 | } 9 | 10 | .loader:before { 11 | content: ""; 12 | width: 6px; 13 | height: 6px; 14 | border-radius: 50%; 15 | position: absolute; 16 | display: block; 17 | background: var(--dot); 18 | top: 37px; 19 | left: 19px; 20 | transform: translate(-18px, -18px); 21 | animation: dotRect var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86) 22 | infinite; 23 | } 24 | 25 | .loader svg { 26 | display: block; 27 | width: 100%; 28 | height: 100%; 29 | } 30 | 31 | .loader svg rect, 32 | .loader svg polygon, 33 | .loader svg circle { 34 | fill: none; 35 | stroke: var(--path); 36 | stroke-width: 10px; 37 | stroke-linejoin: round; 38 | stroke-linecap: round; 39 | } 40 | 41 | .loader svg polygon { 42 | stroke-dasharray: 145 76 145 76; 43 | stroke-dashoffset: 0; 44 | animation: pathTriangle var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86) 45 | infinite; 46 | } 47 | 48 | .loader svg rect { 49 | stroke-dasharray: 192 64 192 64; 50 | stroke-dashoffset: 0; 51 | animation: pathRect 3s cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite; 52 | } 53 | 54 | .loader svg circle { 55 | stroke-dasharray: 150 50 150 50; 56 | stroke-dashoffset: 75; 57 | animation: pathCircle var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86) 58 | infinite; 59 | } 60 | 61 | .loader.triangle { 62 | width: 48px; 63 | } 64 | 65 | .loader.triangle:before { 66 | left: 21px; 67 | transform: translate(-10px, -18px); 68 | animation: dotTriangle var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86) 69 | infinite; 70 | } 71 | 72 | @keyframes pathTriangle { 73 | 33% { 74 | stroke-dashoffset: 74; 75 | } 76 | 77 | 66% { 78 | stroke-dashoffset: 147; 79 | } 80 | 81 | 100% { 82 | stroke-dashoffset: 221; 83 | } 84 | } 85 | 86 | @keyframes dotTriangle { 87 | 33% { 88 | transform: translate(0, 0); 89 | } 90 | 91 | 66% { 92 | transform: translate(10px, -18px); 93 | } 94 | 95 | 100% { 96 | transform: translate(-10px, -18px); 97 | } 98 | } 99 | 100 | @keyframes pathRect { 101 | 25% { 102 | stroke-dashoffset: 64; 103 | } 104 | 105 | 50% { 106 | stroke-dashoffset: 128; 107 | } 108 | 109 | 75% { 110 | stroke-dashoffset: 192; 111 | } 112 | 113 | 100% { 114 | stroke-dashoffset: 256; 115 | } 116 | } 117 | 118 | @keyframes dotRect { 119 | 25% { 120 | transform: translate(0, 0); 121 | } 122 | 123 | 50% { 124 | transform: translate(18px, -18px); 125 | } 126 | 127 | 75% { 128 | transform: translate(0, -36px); 129 | } 130 | 131 | 100% { 132 | transform: translate(-18px, -18px); 133 | } 134 | } 135 | 136 | @keyframes pathCircle { 137 | 25% { 138 | stroke-dashoffset: 125; 139 | } 140 | 141 | 50% { 142 | stroke-dashoffset: 175; 143 | } 144 | 145 | 75% { 146 | stroke-dashoffset: 225; 147 | } 148 | 149 | 100% { 150 | stroke-dashoffset: 275; 151 | } 152 | } 153 | 154 | .loader { 155 | display: inline-block; 156 | margin: 0 16px; 157 | } 158 | --------------------------------------------------------------------------------