just a bunch 'o stuff

This commit is contained in:
Jamie
2022-02-20 21:40:57 -08:00
parent 780f89a1a3
commit a85efa13a3
47 changed files with 5839 additions and 153 deletions

View File

@@ -40,6 +40,7 @@
"byte-size": "^8.1.0",
"clsx": "^1.1.1",
"immer": "^9.0.6",
"jotai": "^1.6.0",
"moment": "^2.29.1",
"phosphor-react": "^1.3.1",
"pretty-bytes": "^5.6.0",
@@ -48,11 +49,14 @@
"react-dropzone": "^11.3.4",
"react-error-boundary": "^3.1.3",
"react-hotkeys-hook": "^3.4.4",
"react-portal": "^4.2.1",
"react-router-dom": "^5.2.0",
"react-spline": "^1.2.1",
"react-transition-group": "^4.4.2",
"react-virtuoso": "^2.2.6",
"rooks": "^5.7.1",
"tailwindcss": "^3.0.7",
"ui": "*",
"vite": "^2.4.4",
"vite-plugin-filter-replace": "^0.1.9",
"vite-plugin-react-svg": "^0.2.0",

View File

@@ -14,7 +14,7 @@ fn main() {
let app = app.handle();
let window = app.get_window("main").unwrap();
window.set_shadow(true);
// window.set_shadow(true);
tauri::async_runtime::spawn(async move {
while let Some(event) = core_receiver.recv().await {

View File

@@ -1,29 +1,28 @@
import React, { useEffect, useRef } from 'react';
import React, {useContext, useEffect, useState} from 'react';
import { Route, BrowserRouter as Router, Switch, Redirect } from 'react-router-dom';
import { Sidebar } from './components/file/Sidebar';
import { TopBar } from './components/layout/TopBar';
import { useInputState } from './hooks/useInputState';
import { SettingsScreen } from './screens/Settings';
import { ExplorerScreen } from './screens/Explorer';
import { invoke } from '@tauri-apps/api';
import { DebugGlobalStore } from './Debug';
import { useCoreEvents } from './hooks/useCoreEvents';
import { AppState, useAppState } from './store/global';
import { Modal } from './components/layout/Modal';
import { useKey, useKeyBindings } from 'rooks';
// import { useHotkeys } from 'react-hotkeys-hook';
import { Button } from 'ui';
import { ErrorBoundary, FallbackProps } from 'react-error-boundary';
import { Button } from './components/primitive';
import { useLocationStore, Location } from './store/locations';
import { OverviewScreen } from './screens/Overview';
import { SpacesScreen } from './screens/Spaces';
import {createModal, Modal} from "./components/layout/Modal";
export const SettingsModal = createModal('settings');
function ErrorFallback({ error, resetErrorBoundary }: FallbackProps) {
return (
<div
data-tauri-drag-region
role="alert"
className="flex flex-col items-center justify-center w-screen h-screen p-4 border border-gray-200 rounded-lg dark:border-gray-650 bg-gray-50 dark:bg-gray-350 dark:text-white"
className="flex flex-col items-center justify-center w-screen h-screen p-4 border border-gray-200 rounded-lg dark:border-gray-650 bg-gray-50 dark:bg-gray-950 dark:text-white"
>
<p className="m-3 text-sm font-bold text-gray-400">APP CRASHED</p>
<h1 className="text-2xl font-bold">We're past the event horizon...</h1>
@@ -53,6 +52,7 @@ export default function App() {
// process.exit();
// });
return (
<ErrorBoundary
FallbackComponent={ErrorFallback}
@@ -62,15 +62,15 @@ export default function App() {
>
<Router>
<div className="flex flex-row h-screen overflow-hidden text-gray-900 bg-white border border-gray-200 select-none rounded-xl dark:border-gray-500 dark:text-white dark:bg-gray-650">
<Modal {...SettingsModal}>
<SettingsScreen />
</Modal>
<DebugGlobalStore />
<Sidebar />
<div className="flex flex-col w-full min-h-full">
<TopBar />
<div className="relative flex w-full">
<Switch>
<Route exact path="/">
<Redirect to="/explorer" />
</Route>
<Route path="/overview">
<OverviewScreen />
</Route>
@@ -80,13 +80,11 @@ export default function App() {
<Route path="/explorer">
<ExplorerScreen />
</Route>
<Route path="/settings">
<SettingsScreen />
</Route>
</Switch>
</div>
</div>
<Modal />
</div>
</Router>
</ErrorBoundary>

View File

@@ -106,10 +106,7 @@ export const Sidebar: React.FC<SidebarProps> = (props) => {
<Icon component={CirclesFour} />
Spaces
</SidebarLink>
<SidebarLink to="/explorer">
<Icon component={Folder} />
Explorer
</SidebarLink>
<SidebarLink to="/settings">
<Icon component={MonitorPlay} />
Media
@@ -119,8 +116,8 @@ export const Sidebar: React.FC<SidebarProps> = (props) => {
<Heading>Locations</Heading>
{locations.map((location, index) => {
return (
<div className="flex flex-row items-center">
<SidebarLink className="relative group" key={index} to={`/explorer/${location.name}`}>
<div key={index} className="flex flex-row items-center">
<SidebarLink className="relative group" to={`/explorer/${location.name}`}>
<Icon component={ServerIcon} />
{location.name}
<div className="flex-grow" />

View File

@@ -1,35 +1,42 @@
import { Transition } from '@headlessui/react';
import clsx from 'clsx';
import React, { createContext, useState } from 'react';
import React, {ComponentProps, createContext, useState} from 'react';
import {atom, useAtom, WritableAtom} from "jotai";
import {createPortal} from "react-dom";
export interface ModalProps {
name: string;
open: WritableAtom<boolean, boolean>,
full?: boolean;
}
export interface ModalProps {}
export function createModal(name: string): ModalProps {
return { name, open: atom(true) as WritableAtom<boolean, boolean> }
}
const modalContext = createContext({ open: false });
export const Modal: React.FC<ModalProps> = (props) => {
const [open, setOpen] = useAtom(props.open);
export const Modal = (props: ModalProps) => {
const [open, setOpen] = useState(false);
return (
<div
data-tauri-drag-region
onClick={() => setOpen(false)}
className={clsx(
'transition-opacity w-screen h-screen p-5 absolute t-0 bg-black bg-opacity-30 m-[1px] rounded-lg',
'transition-opacity absolute flex w-full h-full p-5 t-0 bg-black bg-opacity-80 m-[1px] rounded-lg z-50',
{ 'pointer-events-none hidden': !open }
)}
>
<Transition
show={open}
enter="transition-translate ease-in-out duration-200"
enterFrom="-scale-2"
enterTo="scale-0"
leave="transition-translate ease-in-out duration-200"
leaveFrom="scale-0"
leaveTo="-scale-2"
// enter="transition-translate ease-in-out duration-200"
// enterFrom="-scale-2"
// enterTo="scale-0"
// leave="transition-translate ease-in-out duration-200"
// leaveFrom="scale-0"
// leaveTo="-scale-2"
>
<div className="w-full h-full bg-white rounded-lg shadow-xl dark:bg-gray-850">
<h1 className="m-10">hi</h1>
<div className="w-full h-full flex flex-grow bg-white rounded-lg shadow-xl dark:bg-gray-850">
{props.children}
</div>
</Transition>
</div>
);
</div>);
};

View File

@@ -21,6 +21,9 @@ import { appWindow } from '@tauri-apps/api/window';
import { HeartIcon } from '@heroicons/react/solid';
import { invoke } from '@tauri-apps/api';
import { SettingsModal } from '../../App'
import {useAtom} from "jotai";
export interface TopBarProps extends DefaultProps {}
export interface TopBarButtonProps extends ButtonProps {
icon: any;
@@ -51,12 +54,13 @@ const TopBarButton: React.FC<TopBarButtonProps> = ({ icon: Icon, ...props }) =>
};
export const TopBar: React.FC<TopBarProps> = (props) => {
const [settingsOpen, setSettingsOpen] = useAtom(SettingsModal.open)
const [goBack] = useExplorerStore((state) => [state.goBack]);
return (
<>
<div
data-tauri-drag-region
className="flex h-[2.95rem] -mt-0.5 max-w z-50 pl-3 rounded-tr-2xl items-center border-b bg-gray-50 dark:bg-gray-600 border-gray-100 dark:border-gray-800 !bg-opacity-100 backdrop-blur"
className="flex h-[2.95rem] -mt-0.5 max-w z-10 pl-3 rounded-tr-2xl items-center border-b bg-gray-50 dark:bg-gray-600 border-gray-100 dark:border-gray-800 !bg-opacity-100 backdrop-blur"
>
<div className="">
<TopBarButton icon={ChevronLeftIcon} onClick={goBack} />
@@ -92,7 +96,9 @@ export const TopBar: React.FC<TopBarProps> = (props) => {
/>
</div>
</div>
<TopBarButton className="mr-[8px]" icon={CogIcon} />
<TopBarButton onClick={() => {
setSettingsOpen(!settingsOpen);
}} className="mr-[8px]" icon={CogIcon} />
</div>
{/* <div className="h-[1px] flex-shrink-0 max-w bg-gray-200 dark:bg-gray-700" /> */}
</>

View File

@@ -5,6 +5,7 @@ import { invoke } from '@tauri-apps/api';
import { IFile } from '../types';
import { useExplorerStore } from '../store/explorer';
import { Inspector } from '../components/file/Inspector';
import {useParams} from "react-router-dom";
export interface DirectoryResponse {
directory: IFile;
@@ -12,6 +13,9 @@ export interface DirectoryResponse {
}
export const ExplorerScreen: React.FC<{}> = () => {
// let { slug } = useParams();
const [currentDir, tempWatchDir] = useExplorerStore((state) => [
state.currentDir,
state.tempWatchDir
@@ -21,7 +25,6 @@ export const ExplorerScreen: React.FC<{}> = () => {
invoke<DirectoryResponse>('get_files', { path: tempWatchDir }).then((res) => {
console.log({ res });
useExplorerStore.getState().ingestDir(res.directory, res.contents);
invoke('get_thumbs_for_directory', { path: tempWatchDir });
});
}, []);

View File

@@ -8,7 +8,6 @@ import { Checkbox } from '../components/primitive/Checkbox';
import { Dropdown } from '../components/primitive/Dropdown';
import { InputContainer } from '../components/primitive/InputContainer';
import { Shortcut } from '../components/primitive/Shortcut';
import { useInputState } from '../hooks/useInputState';
import { useExplorerStore } from '../store/explorer';
import { useAppState } from '../store/global';
//@ts-ignore
@@ -18,7 +17,7 @@ import { useAppState } from '../store/global';
export const SettingsScreen: React.FC<{}> = () => {
const fileUploader = useRef<HTMLInputElement | null>(null);
const config = useAppState()
const config = useAppState()
const [tempWatchDir, setTempWatchDir] = useExplorerStore((state) => [
state.tempWatchDir,
@@ -51,22 +50,14 @@ const config = useAppState()
<Button
size="sm"
variant="primary"
onClick={() => {
invoke('scan_dir', {
onClick={async () => {
await invoke('scan_dir', {
path: tempWatchDir
});
}}
>
Scan Now
</Button>
<Button
size="sm"
onClick={() => {
invoke('test_scan');
}}
>
Test Scan
</Button>
</div>
<div className="flex flex-row mt-4 space-x-2">

View File

@@ -5,36 +5,36 @@ import { Tag } from '../components/primitive/Tag';
export const SpacesScreen: React.FC<{}> = (props) => {
return (
<div className="flex flex-col w-full h-full px-2 py-5">
<div className="-mt-[1px] space-x-2 ml-1">
<Tag color="red">Videos</Tag>
<Tag color="orange">DSLR Photos</Tag>
<Tag color="yellow">Camera Roll</Tag>
<Tag color="green">NFTs</Tag>
<Tag color="pink">Screenshots</Tag>
<Tag color="blue">Documents</Tag>
<Tag color="purple">Repositories</Tag>
</div>
<div className="flex flex-wrap p-2 my-3 space-x-2 bg-black rounded">
<div className="w-10 h-10 rounded bg-gray-950" />
<div className="w-10 h-10 bg-gray-900 rounded" />
<div className="w-10 h-10 rounded bg-gray-850" />
<div className="w-10 h-10 bg-gray-800 rounded" />
<div className="w-10 h-10 rounded bg-gray-750" />
<div className="w-10 h-10 bg-gray-700 rounded" />
<div className="w-10 h-10 rounded bg-gray-650" />
<div className="w-10 h-10 bg-gray-600 rounded" />
<div className="w-10 h-10 rounded bg-gray-550" />
<div className="w-10 h-10 bg-gray-400 rounded" />
<div className="w-10 h-10 rounded bg-gray-450" />
<div className="w-10 h-10 bg-gray-400 rounded" />
<div className="w-10 h-10 rounded bg-gray-350" />
<div className="w-10 h-10 bg-gray-300 rounded" />
<div className="w-10 h-10 rounded bg-gray-250" />
{/* <div className="w-10 h-10 bg-gray-200 rounded" />
<div className="w-10 h-10 rounded bg-gray-150" />
<div className="w-10 h-10 bg-gray-100 rounded" />
<div className="w-10 h-10 rounded bg-gray-50" /> */}
</div>
{/*<div className="-mt-[1px] space-x-2 ml-1">*/}
{/* <Tag color="red">Videos</Tag>*/}
{/* <Tag color="orange">DSLR Photos</Tag>*/}
{/* <Tag color="yellow">Camera Roll</Tag>*/}
{/* <Tag color="green">NFTs</Tag>*/}
{/* <Tag color="pink">Screenshots</Tag>*/}
{/* <Tag color="blue">Documents</Tag>*/}
{/* <Tag color="purple">Repositories</Tag>*/}
{/*</div>*/}
{/*<div className="flex flex-wrap p-2 my-3 space-x-2 bg-black rounded">*/}
{/* <div className="w-10 h-10 rounded bg-gray-950" />*/}
{/* <div className="w-10 h-10 bg-gray-900 rounded" />*/}
{/* <div className="w-10 h-10 rounded bg-gray-850" />*/}
{/* <div className="w-10 h-10 bg-gray-800 rounded" />*/}
{/* <div className="w-10 h-10 rounded bg-gray-750" />*/}
{/* <div className="w-10 h-10 bg-gray-700 rounded" />*/}
{/* <div className="w-10 h-10 rounded bg-gray-650" />*/}
{/* <div className="w-10 h-10 bg-gray-600 rounded" />*/}
{/* <div className="w-10 h-10 rounded bg-gray-550" />*/}
{/* <div className="w-10 h-10 bg-gray-400 rounded" />*/}
{/* <div className="w-10 h-10 rounded bg-gray-450" />*/}
{/* <div className="w-10 h-10 bg-gray-400 rounded" />*/}
{/* <div className="w-10 h-10 rounded bg-gray-350" />*/}
{/* <div className="w-10 h-10 bg-gray-300 rounded" />*/}
{/* <div className="w-10 h-10 rounded bg-gray-250" />*/}
{/* /!* <div className="w-10 h-10 bg-gray-200 rounded" />*/}
{/* <div className="w-10 h-10 rounded bg-gray-150" />*/}
{/* <div className="w-10 h-10 bg-gray-100 rounded" />*/}
{/* <div className="w-10 h-10 rounded bg-gray-50" /> *!/*/}
{/*</div>*/}
</div>
);
};

View File

@@ -1,5 +1,8 @@
{
"extends": "config/tsconfig/tauri.json",
"include": ["src"],
"exclude": ["node_modules"]
"exclude": ["node_modules"],
"compilerOptions": {
"jsx": "react"
}
}

View File

@@ -1 +1 @@
module.exports = require("config/eslint-preset");
module.exports = require("@calcom/config/eslint-preset");

7
apps/docs/.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
node_modules
.next
.DS_Store
yarn-error.log
dist
examples
packages

1
apps/docs/.nvmrc Normal file
View File

@@ -0,0 +1 @@
14.17

View File

@@ -0,0 +1,2 @@
.next
node_modules

21
apps/docs/LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Shu Ding
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,30 +1,75 @@
## Getting Started
<!-- PROJECT LOGO -->
<div align="right">
<a href="https://github.com/calcom/cal.com">
<img src="https://user-images.githubusercontent.com/8019099/133430653-24422d2a-3c8d-4052-9ad6-0580597151ee.png" alt="Logo">
</a>
<a href="https://cal.com">Website</a>
·
<a href="https://github.com/calcom/docs/issues">Community Support</a>
</div>
First, run the development server:
# Cal.com Documentation
```bash
The official product, support and developer documentation, containing information and guides about using the product as well as support for self-hosted installations. This documentation site runs on [Nextra](https://nextra.vercel.app), so you may refer to their documentation should you need information on anything that isn't covered here.
## Prerequisites
- Git
- Node.js & npm
- Yarn
## Installation
Firstly, clone the repository using Git:
```console
git clone https://github.com/calcom/docs.git
```
Now, you can install the dependencies with yarn:
```console
yarn install
```
## Editing
To create, edit and delete documentation pages, you can simply create markdown (.mdx) files in the `pages/` folder. You can edit Markdown with any text editor, but VS Code and WebStorm have side-by-side previews so you can see your formatted content whilst writing markdown.
You will also need to add it as an entry to the `meta.json` file found in whichever directory that the .mdx file is in.
## Local Development
```console
yarn dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
## Build
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
```console
yarn build
```
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
This command generates static content into the `build` directory and can be served using any static content hosting service.
## Learn More
## How to easily contribute
To learn more about Next.js, take a look at the following resources:
## Existing Page
1. From the documentation's GitHub repository, head to the folder called 'pages' and open it.
2. From here you can view all current pages on the documentation site. Select the page you would like to contribute to.
3. You should now be able to view the page you have selected. Located at the top right of the page will be a pencil icon. Pressing this will bring you up an editor to edit and make changes. You can add formatting using the buttons at the top, which will automatically insert the relevant markdown content needed to style the text.
4. From here make the changes you wish to make.
5. At the bottom of the screen will be a 'Propose Changes' box, fill in all the relevant details such as title and description then press the green 'Propose Changes' button.
6. Your changes have been saved, to submit them for review, located on your screen, press the green 'Create Pull Request' button.
7. Fill in all the relevant details such as title and description and after finalize the submission.
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You have now successfully edited and submitted changes to our documentation site.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Creating a New Page
## Deploy on Vercel
1. From the documentation's GitHub repository, head to the folder called 'pages' and open it.
2. From here you can view all current pages on the documentation site. At the top of your screen press the 'New file' button.
3. You should now be able to view the page you have created. Remember when renaming the document to put .mdx at the end of the file name.
4. From here make the changes you wish to make. Such as creating a title, sub-title and body text.
5. At the bottom of the screen will be a 'Propose Changes' box, fill in all the relevant details such as title and description then press the green 'Propose Changes' button.
6. Your changes have been saved, to submit them for review, located on your screen, press the greem 'Create Pull Request' button.
7. Fill in all the relevant details such as title and description and after finalize the submission.
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
You have now successfully created and submitted changes to our documentation site.

View File

@@ -1,6 +0,0 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

View File

@@ -1,5 +1,8 @@
const withTM = require("next-transpile-modules")(["ui"]);
module.exports = withTM({
reactStrictMode: true,
/* eslint-disable @typescript-eslint/no-var-requires */
const withNextra = require('nextra')({
theme: 'nextra-theme-docs',
themeConfig: './theme.config.js',
unstable_staticImage: true
});
module.exports = withNextra();

View File

@@ -3,23 +3,27 @@
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "next dev --port 3001",
"dev": "next dev --port 6001",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"next": "12.0.3",
"next": "^12.0.9",
"nextra": "^1.1.0",
"nextra-theme-docs": "^2.0.0-beta.5",
"prism-react-renderer": "^1.3.1",
"prismjs": "^1.26.0",
"react": "17.0.2",
"react-dom": "17.0.2",
"ui": "*"
},
"devDependencies": {
"@types/react": "17.0.37",
"config": "*",
"eslint": "7.32.0",
"next-transpile-modules": "9.0.0",
"tsconfig": "*",
"@types/react": "17.0.37",
"typescript": "^4.5.3"
}
}

12
apps/docs/pages/_app.js Normal file
View File

@@ -0,0 +1,12 @@
import 'nextra-theme-docs/style.css';
import './style.css';
import Prism from 'prism-react-renderer/prism';
(typeof global !== 'undefined' ? global : window).Prism = Prism;
require('prismjs/components/prism-typescript');
require('prismjs/components/prism-rust');
export default function Nextra({ Component, pageProps }) {
return <Component {...pageProps} />;
}

View File

@@ -0,0 +1,105 @@
import Callout from 'nextra-theme-docs/callout';
# Ideas
<Callout emoji="👾">
**Space Invaders** is a 1978 shoot 'em up arcade game developed by Tomohiro Nishikado.
</Callout>
> A self hosted, bulletproof, personal cloud.
> Bringing the magic of cloud services like iCloud and google photos to your local devices.
> Dont think in drives.
> A pure rust core brings efficiency and compatibility to complex file management system.
### Architecture
```javascript
import '../styles/fonts.css';
import '../styles/globals.css';
```
```rust
pub enum Action {
SCAN_DIR,
ENCRYPT_FILE,
UPLOAD_FILE,
}
```
- **meta_integrity_hash**<br />
`location + path`<br />
This allows us to quickly assume a file we have already scanned still exists at that location.<br />
_Note: Could potentiallty be replaced by a unique constraint on location+path_
- **sample_byte_integrity_hash**<br />
`100 * 100 byte samples at equal points throughout file`<br />
this is used to find duplicates quickly
- **byte_integrity_hash**<br />
`full byte-to-byte checksum on file contents`<br />
this is used to confirm duplicates
path must be stored so we can handle system delete events and update database accordingly
^ of course but thats a simple query on destructured volume/location/path
duplicate files should have a new File created but it receives no metadata, the parent File, aka the first instance discovered, consumes all metadata and master_file_id determines this link
add deleted_at to File
.spacedrive file can exist in a directory to identify it as something other than a directory, such as a single file with a custom UI
we can also define hard coded enhancements to the visual display of directories based on context
If a new file has the same sampled_byte_integrity hash on the currently loaded volume we check to see if it still exists at that other location. if so, we assign as a duplicate. if not, we count it as a move and update the original File to the new location.
after every file is updated we run a set of checks, or routines.
or a file being updated puts it into a “touched” state queuing it up for inspection routines
database mutations are processed as commits, through an enum of commit types, we take data and commit it to database
wanted state for missing files
sync server uses redis to queue sync chunks
file types are an enum to allow for extended functionality
```rust
pub enum FileType {
File,
RichFile
Directory,
Package,
Alias,
}
pub enum Package {
WebPage,
ThumbnailMedia,
PreviewMedia,
Custom
}
```
### Promotion
_show a pile of drives_
“if this is you, youll know how much of a pain it is to deal with this much data. Were in a world now where independent creatives are the new normal, our data is steadily accumulating but the tooling hasnt caught up yet”
“Cloud services like Google Photos and iCloud have great features, beautiful UI—but youre locked in with a very limited capacity. Many people have multiple cloud accounts each with their own restrictions. Drives that arent backed up, collecting dust and at risk of failure.
“Spacedrive is a beautiful interface to organize and consume an unlimited amount of data, bringing each and every one of your devices together to form your own cloud. Its incredible to see it all come together.
Were in a world now where independent creatives are the new normal, our data is steadily accumulating but the tooling hasnt caught up yet. Cloud services like Google Photos and iCloud have great features, beautiful UI—but youre locked in with a very limited capacity. Many people have multiple cloud accounts, drives that arent backed up and collecting dust, data at risk of loss. I wanted a solution that didnt tie me to any one provider, a photo album shouldnt exist only in my iCloud account, it should be universal and permanent. I believe open source technology is the solution to this, with incredibly an versatile and secure architecture
“a beautiful, intentionally crafted user interface to effortlessly and continually archive your vast wealth of memories, creations, and data. a digital legacy that is will stand the test of time, and be truly yours.”
### Storage Device Presets
To improve index quality these presets can be automatically applied to the indexer to avoid paths and handle individual files by a ruleset uniquely
- Macintosh HD
- Windows C:/
- Linux??
Drop from index button on dropdown

View File

@@ -0,0 +1,3 @@
{
"migrations": "Migrations"
}

View File

@@ -0,0 +1,3 @@
{
"migrations": "Migrations"
}

View File

@@ -0,0 +1,4 @@
{
"migrations": "Migrations"
}

View File

@@ -0,0 +1,18 @@
{
"library": "The Library",
"locations": "Locations",
"search": "Search",
"spaces": "Spaces",
"smart-tags": "Smart Tags",
"sync": "Sync",
"encryption": "Encryption",
"key-manager": "Key Manager",
"albums": "Albums",
"extensions": "Extensions",
"encoder": "Encoder",
"media-viewer": "Media Viewer",
"preview-generation": "Preview Generation",
"statistics": "Statistics",
"timeline": "Timeline",
"workers": "Workers"
}

25
apps/docs/pages/index.mdx Normal file
View File

@@ -0,0 +1,25 @@
import Bleed from 'nextra-theme-docs/bleed';
import Callout from 'nextra-theme-docs/callout';
# SpaceDrive
#### Official Documentation
<Callout emoji="🪐">We're in pre-alpha v0.0.12 [Download Now]()</Callout>
Welcome to the SpaceDrive project documentation. These docs outline the product specification, technical
architecture and development guides.
<Bleed>
![SpaceDrive
UI](https://raw.githubusercontent.com/jamiepine/spacedrive/main/apps/desktop/src/assets/images/spacedrive_screenshot.png?token=GHSAT0AAAAAABRBMCIJMSTTIECISYOUAEU6YQRL3WQ)
</Bleed>
### What is it?
SpaceDrive is an open source virtual filesystem, a personal cloud powered by your everyday devices. Feature-rich benefits of the cloud, only its owned and hosted by you—with security, privacy and ownership as a foundation. SpaceDrive makes it possible to create a **limitless directory** of your digital life that will stand the test of time.
#### A single source of truth, for every file you own.
For each client you install, you'll have another node in your personal network. They all share a single encrypted database and work as a team to perform tasks. Prioritizing peer-to-peer LAN connections but always using end-to-end encryption to synchronize in realtime.
As for UI, it has everything you'd expect from a file explorer and more; a native photo viewer, video and audio player. But also _specific_ support for VODs, git repositories, social media backups, NFTs, screenshots, webpage snapshots, links, notes and more. Community extensions can add support for different filetypes and tailored file viewers.

View File

@@ -1,10 +0,0 @@
import { Button } from "ui";
export default function Docs() {
return (
<div>
<h1>Docs</h1>
<Button />
</div>
);
}

View File

@@ -0,0 +1,4 @@
{
"index": "Home",
"features": "Features"
}

View File

@@ -0,0 +1,7 @@
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans:wght@700&display=swap');h2,
h3,
h4,
h5,
h6 {
font-family: 'Noto Sans', sans-serif;
}

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#292929</TileColor>
</tile>
</msapplication>
</browserconfig>

View File

@@ -0,0 +1,19 @@
{
"name": "SpaceDrive Docs",
"short_name": "SpaceDrive",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#292929",
"background_color": "#292929",
"display": "standalone"
}

32
apps/docs/theme.config.js Normal file
View File

@@ -0,0 +1,32 @@
export default {
github: 'https://github.com/jamiepine/spacedrive',
docsRepositoryBase: 'https://github.com/jamiepine/spacedrive/',
titleSuffix: ' | SpaceDrive',
logo: (
<>
<span className="hidden mr-2 font-extrabold md:inline">SpaceDrive</span>
<span className="hidden font-normal text-gray-600 md:inline">
The Virtual Private Filesystem
</span>
</>
),
search: true,
prevLinks: true,
nextLinks: true,
footer: true,
footerEditLink: 'Edit this page on GitHub',
footerText: <>© {new Date().getFullYear()} Jamie Pine. All rights reserved.</>,
head: (
<>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta httpEquiv="Content-Language" content="en" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="manifest" href="/site.webmanifest" />
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#000000" />
<meta name="msapplication-TileColor" content="#ff0000" />
</>
)
};

View File

@@ -1,5 +0,0 @@
{
"extends": "config/tsconfig/nextjs.json",
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}

3623
apps/docs/yarn.lock Normal file
View File

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "next dev",
"dev": "next dev -p 9003",
"build": "next build",
"start": "next start",
"lint": "next lint"

BIN
packages/core/Cargo.lock generated
View File

Binary file not shown.

View File

@@ -39,8 +39,8 @@ CREATE TABLE IF NOT EXISTS files (
uri TEXT NOT NULL,
is_dir BOOLEAN NOT NULL DEFAULT FALSE,
meta_integrity_hash TEXT NOT NULL UNIQUE ON CONFLICT IGNORE,
sampled_byte_integrity_hash TEXT NOT NULL,
byte_integrity_hash TEXT NOT NULL,
sampled_byte_integrity_hash TEXT,
byte_integrity_hash TEXT,
name TEXT,
extension TEXT,
size_in_bytes TEXT NOT NULL,

View File

@@ -1,2 +1,4 @@
import * as React from "react";
export * from "./Button";
export * from "./primitive";
// export * from "./screens";

View File

@@ -8,6 +8,7 @@
"@types/react": "^17.0.37",
"@types/react-dom": "^17.0.11",
"tsconfig": "*",
"typescript": "^4.5.3"
"typescript": "^4.5.3",
"react": "^17.0.2"
}
}

View File

@@ -1,4 +0,0 @@
import * as React from "react";
export const Button = () => {
return <button>Boop</button>;
};

View File

@@ -0,0 +1,100 @@
import React from 'react';
import { ButtonHTMLAttributes, useState } from 'react';
import { Switch } from '@headlessui/react';
import clsx from 'clsx';
const sizes = {
default: 'py-1 px-3 text-md font-medium',
sm: 'py-1 px-2 text-sm font-medium'
};
const variants = {
default: `
bg-gray-50
shadow-sm
hover:bg-gray-100
active:bg-gray-50
dark:bg-gray-650
dark:hover:bg-gray-600
dark:active:bg-gray-700
dark:active:opacity-80
border-gray-100
hover:border-gray-200
active:border-gray-200
dark:border-gray-600
dark:active:border-gray-600
dark:hover:border-gray-600
text-gray-700
hover:text-gray-900
active:text-gray-600
dark:text-gray-200
dark:active:text-white
dark:hover:text-white
`,
gray: `
bg-gray-100
shadow-sm
hover:bg-gray-200
active:bg-gray-100
dark:bg-gray-800
dark:hover:bg-gray-700
dark:active:bg-gray-700
dark:active:opacity-80
border-gray-200
hover:border-gray-300
active:border-gray-200
dark:border-gray-700
dark:active:border-gray-600
dark:hover:border-gray-600
text-gray-700
hover:text-gray-900
active:text-gray-600
dark:text-gray-200
dark:active:text-white
dark:hover:text-white
`,
primary:
'bg-primary text-white shadow-sm border-primary-600 dark:border-primary-400 active:bg-primary-600 active:border-primary-700 hover:bg-primary-400 hover:border-primary-500',
selected: `bg-gray-100 dark:bg-gray-500
text-black hover:text-black active:text-black dark:hover:text-white dark:text-white
`
};
export type ButtonVariant = keyof typeof variants;
export type ButtonSize = keyof typeof sizes;
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: ButtonVariant;
size?: ButtonSize;
loading?: boolean;
icon?: React.ReactNode;
noPadding?: boolean;
noBorder?: boolean;
pressEffect?: boolean;
justifyLeft?: boolean;
}
export const Button: React.FC<ButtonProps> = ({ loading, ...props }) => {
return (
<button
{...props}
className={clsx(
'flex border rounded-md transition-colors duration-100 cursor-default',
{ 'opacity-5': loading, '!p-1': props.noPadding },
{ 'justify-center': !props.justifyLeft },
sizes[props.size || 'default'],
variants[props.variant || 'default'],
{ 'active:translate-y-[1px]': props.pressEffect },
{ 'border-0': props.noBorder },
props.className
)}
>
{props.children}
</button>
);
};

View File

@@ -0,0 +1 @@
export * from './Button';

1683
yarn.lock
View File

File diff suppressed because it is too large Load Diff