├── .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 |
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 | copyToClipboard(value)}
11 | >
12 | {success ? (
13 |
14 | ) : (
15 |
16 | )}
17 |
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 |
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 |
14 | Dismiss
15 |
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 | Error 404
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 |
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 |
20 |
25 |
26 | ) : (
27 |
33 | ⚡ {title}
34 |
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 |
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 |
20 | {!user && (
21 |
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 |
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 | onScreenshotTook(null)}
30 | style={{
31 | backgroundImage: `url(${screenshot})`,
32 | backgroundPosition: 'right bottom',
33 | backgroundSize: 180,
34 | }}
35 | >
36 |
37 |
38 | );
39 | }
40 |
41 | return (
42 |
47 | {isTakingScreenshot ? : }
48 |
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 |
4 |
5 |
6 | Securely Store and Share Your Videos and Images on the Blockchain with DarkSpace .
7 |
8 |
9 |
10 | 
11 | [](https://peerlist.io/sajjad)
12 | 
13 | 
14 | 
15 | [](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 | 
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 |
31 |
32 | Upload a project containg CSS, HTML & JS inside same folder{" "}
33 |
38 | Upload folder or all code files
39 | {" "}
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 |
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 |
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 |
8 |
14 |
15 |
16 |
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 |
37 | Start recycling
38 |
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 | h1>
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 |
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 | {
39 | setActivePage("dashboard");
40 | Router.push("/dashboard");
41 | }}
42 | className={`text-xl w-full lg:w-1/2 h-16 rounded-md bg-gradient-to-r from-pink-500 to-violet-500 transition-all duration-200 px-3.5 py-1.5 font-semibold leading-10 text-white shadow-lg`}
43 | >
44 | Start Upload 🚀
45 |
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 |
28 |
29 |
30 |
31 | {!playerState.isPlaying ? (
32 |
33 | ) : (
34 |
35 | )}
36 |
37 |
38 |
handleVideoProgress(e)}
45 | />
46 |
handleVideoSpeed(e)}
50 | >
51 |
52 | 0.50x
53 |
54 |
55 | 1x
56 |
57 |
58 | 1.25x
59 |
60 |
61 | 2x
62 |
63 |
64 |
65 | {!playerState.isMuted ? (
66 |
67 | ) : (
68 |
69 | )}
70 |
71 |
72 |
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 |
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 |
33 | ) : (
34 |
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 | {/*
39 |
40 | Dashboard
41 | */}
42 | signOut({ redirect: true })}
45 | >
46 |
47 | Logout
48 |
49 |
50 | }
51 | align="end"
52 | openPopover={openPopover}
53 | setOpenPopover={setOpenPopover}
54 | >
55 | setOpenPopover(!openPopover)}
57 | className="flex flex-row w-[100%] h-[100%] items-center justify-center overflow-hidden rounded-full transition-all duration-75 focus:outline-none active:scale-95"
58 | >
59 |
60 |
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 | {
30 | setActivePage("dashboard");
31 | Router.push("/dashboard");
32 | }}
33 | className={`${styles.button} border border-violet-500 hover:border-transparent w-full duration-200 transition-all rounded-md bg-violet-500 px-3.5 py-1.5 text-base font-semibold leading-7 md:leading-9 text-zinc-100 shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white`}
34 | >
35 | Join Now 🚀
36 |
37 |
40 | Learn more →
41 |
42 |
43 |
44 | Completely free to use. No hidden fees.
45 |
46 |
47 |
48 |
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 |
--------------------------------------------------------------------------------