merge duplicate prettier config and format repo with it

This commit is contained in:
Oscar Beaumont 2022-10-07 07:45:15 +08:00
parent fe4da9048a
commit aacdf33216
83 changed files with 1415 additions and 948 deletions

2
.prettierignore Normal file
View file

@ -0,0 +1,2 @@
/target
.build

View file

@ -7,7 +7,7 @@ module.exports = {
bracketSameLine: false,
semi: true,
quoteProps: 'consistent',
importOrder: ['^@sd/interface/(.*)$', '^@sd/client/(.*)$', '^@sd/ui/(.*)$', '^[./]'],
importOrder: ['^[./]', '^@sd/interface/(.*)$', '^@sd/client/(.*)$', '^@sd/ui/(.*)$'],
importOrderSeparation: true,
importOrderSortSpecifiers: true,
plugins: ['@trivago/prettier-plugin-sort-imports']

View file

@ -1,20 +0,0 @@
{
"pluginSearchDirs": [
"."
],
"useTabs": true,
"printWidth": 100,
"singleQuote": true,
"trailingComma": "none",
"bracketSameLine": false,
"semi": true,
"quoteProps": "consistent",
"importOrder": [
"^[./]",
"^@sd/ui/(.*)$",
"^@sd/client/(.*)$",
"^@sd/interface/(.*)$"
],
"importOrderSeparation": true,
"importOrderSortSpecifiers": true
}

View file

@ -109,4 +109,3 @@ This project is using what I'm calling the **"PRRTT"** stack (Prisma, Rust, Reac
- `ios`: A [Swift](https://developer.apple.com/swift/) Native binary (planned).
- `windows`: A [C#](https://docs.microsoft.com/en-us/dotnet/csharp/) Native binary (planned).
- `android`: A [Kotlin](https://kotlinlang.org/) Native binary (planned).

View file

@ -2,13 +2,13 @@ import { Button } from '@sd/ui';
import React from 'react';
import { PageContextBuiltIn } from 'vite-plugin-ssr';
import '@sd/ui/style';
import { Footer } from './components/Footer';
import NavBar from './components/NavBar';
import { PageContextProvider } from './renderer/usePageContext';
import './style.scss';
import '@sd/ui/style';
export default function App({
children,
pageContext

View file

@ -2,8 +2,6 @@ import clsx from 'clsx';
import { useEffect, useState } from 'react';
import { Helmet } from 'react-helmet';
import { ReactComponent as Info } from '@sd/interface/assets/svg/info.svg';
import AppEmbed, { AppEmbedPlaceholder } from '../components/AppEmbed';
import { Bubbles } from '../components/Bubbles';
// import { Bubbles } from '../components/Bubbles';
@ -12,6 +10,8 @@ import NewBanner from '../components/NewBanner';
import { usePageContext } from '../renderer/usePageContext';
import { getWindow } from '../utils';
import { ReactComponent as Info } from '@sd/interface/assets/svg/info.svg';
interface SectionProps {
orientation: 'left' | 'right';
heading?: string;

View file

@ -1,11 +1,11 @@
import { Helmet } from 'react-helmet';
import { ReactComponent as ArrowRight } from '@sd/interface/assets/svg/arrow-right.svg';
import Markdown from '../components/Markdown';
import { TeamMember, TeamMemberProps } from '../components/TeamMember';
import { resolveFilesGlob } from '../utils';
import { ReactComponent as ArrowRight } from '@sd/interface/assets/svg/arrow-right.svg';
const teamImages = resolveFilesGlob(import.meta.globEager('../assets/images/team/*'));
const investorImages = resolveFilesGlob(import.meta.globEager('../assets/images/investors/*'));

View file

@ -139,7 +139,6 @@ html {
background: url('/egg-bloom-two.png') no-repeat center center;
background-size: contain;
}
}
@keyframes bloomBurst {
@ -170,47 +169,48 @@ html {
}
.slot-block {
@apply bg-gray-550 py-3 px-4 border-l-4 border-gray-400 rounded mb-2
@apply bg-gray-550 py-3 px-4 border-l-4 border-gray-400 rounded mb-2;
}
.slot-block.note {
@apply border-yellow-400 bg-yellow-300/20
@apply border-yellow-400 bg-yellow-300/20;
}
.slot-block.info {
@apply border-green-400 bg-green-400/20
@apply border-green-400 bg-green-400/20;
}
.slot-block.warning {
@apply border-red-400 bg-red-400/20
@apply border-red-400 bg-red-400/20;
}
.slot-block-title {
@apply text-white font-bold text-sm m-0 uppercase;
}
.slot-block-content {
@apply my-1 mx-0 mb-0 text-white
@apply my-1 mx-0 mb-0 text-white;
}
.doc-sidebar-button:hover, .doc-sidebar-button.nav-active {
.doc-sidebar-button:hover,
.doc-sidebar-button.nav-active {
&.product {
color:#459EE8;
color: #459ee8;
div {
background-color: #459EE8;
background-color: #459ee8;
}
}
&.developers {
color:#48BB78;
color: #48bb78;
div {
background-color: #48BB78;
background-color: #48bb78;
}
}
&.company {
color:#bb9247;
color: #bb9247;
div {
background-color: #bb9247;
}
}
&.changelog {
color:#8A47BB;
color: #8a47bb;
div {
background-color: #8A47BB;
background-color: #8a47bb;
}
}
}
@ -222,7 +222,6 @@ html {
// #1D054B
// #9A3F8C
.custom-scroll {
-ms-overflow-style: none; /* for Internet Explorer, Edge */
scrollbar-width: none; /* for Firefox */
@ -238,7 +237,6 @@ html {
@apply bg-[#00000006] dark:bg-[#00000030] my-[10px] rounded-[6px];
}
&::-webkit-scrollbar-thumb {
@apply rounded-[6px] bg-gray-300 dark:bg-gray-550 ;
@apply rounded-[6px] bg-gray-300 dark:bg-gray-550;
}
}

View file

@ -1,6 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "expo"
"info": {
"version": 1,
"author": "expo"
}
}

View file

@ -3,110 +3,357 @@
export type Procedures = {
queries:
{ key: "files.readMetadata", input: LibraryArgs<number>, result: null } |
{ key: "getNode", input: never, result: NodeState } |
{ key: "jobs.getHistory", input: LibraryArgs<null>, result: Array<JobReport> } |
{ key: "jobs.getRunning", input: LibraryArgs<null>, result: Array<JobReport> } |
{ key: "library.getStatistics", input: LibraryArgs<null>, result: Statistics } |
{ key: "library.list", input: never, result: Array<LibraryConfigWrapped> } |
{ key: "locations.getById", input: LibraryArgs<number>, result: Location | null } |
{ key: "locations.getExplorerData", input: LibraryArgs<LocationExplorerArgs>, result: ExplorerData } |
{ key: "locations.indexer_rules.get", input: LibraryArgs<number>, result: IndexerRule } |
{ key: "locations.indexer_rules.list", input: LibraryArgs<null>, result: Array<IndexerRule> } |
{ key: "locations.list", input: LibraryArgs<null>, result: Array<{ id: number, pub_id: Array<number>, node_id: number, name: string | null, local_path: string | null, total_capacity: number | null, available_capacity: number | null, filesystem: string | null, disk_type: number | null, is_removable: boolean | null, is_online: boolean, is_archived: boolean, date_created: string, node: Node }> } |
{ key: "tags.get", input: LibraryArgs<number>, result: Tag | null } |
{ key: "tags.getExplorerData", input: LibraryArgs<number>, result: ExplorerData } |
{ key: "tags.getForObject", input: LibraryArgs<number>, result: Array<Tag> } |
{ key: "tags.list", input: LibraryArgs<null>, result: Array<Tag> } |
{ key: "version", input: never, result: string } |
{ key: "volumes.list", input: never, result: Array<Volume> },
| { key: 'files.readMetadata'; input: LibraryArgs<number>; result: null }
| { key: 'getNode'; input: never; result: NodeState }
| { key: 'jobs.getHistory'; input: LibraryArgs<null>; result: Array<JobReport> }
| { key: 'jobs.getRunning'; input: LibraryArgs<null>; result: Array<JobReport> }
| { key: 'library.getStatistics'; input: LibraryArgs<null>; result: Statistics }
| { key: 'library.list'; input: never; result: Array<LibraryConfigWrapped> }
| { key: 'locations.getById'; input: LibraryArgs<number>; result: Location | null }
| {
key: 'locations.getExplorerData';
input: LibraryArgs<LocationExplorerArgs>;
result: ExplorerData;
}
| { key: 'locations.indexer_rules.get'; input: LibraryArgs<number>; result: IndexerRule }
| { key: 'locations.indexer_rules.list'; input: LibraryArgs<null>; result: Array<IndexerRule> }
| {
key: 'locations.list';
input: LibraryArgs<null>;
result: Array<{
id: number;
pub_id: Array<number>;
node_id: number;
name: string | null;
local_path: string | null;
total_capacity: number | null;
available_capacity: number | null;
filesystem: string | null;
disk_type: number | null;
is_removable: boolean | null;
is_online: boolean;
is_archived: boolean;
date_created: string;
node: Node;
}>;
}
| { key: 'tags.get'; input: LibraryArgs<number>; result: Tag | null }
| { key: 'tags.getExplorerData'; input: LibraryArgs<number>; result: ExplorerData }
| { key: 'tags.getForObject'; input: LibraryArgs<number>; result: Array<Tag> }
| { key: 'tags.list'; input: LibraryArgs<null>; result: Array<Tag> }
| { key: 'version'; input: never; result: string }
| { key: 'volumes.list'; input: never; result: Array<Volume> };
mutations:
{ key: "files.delete", input: LibraryArgs<number>, result: null } |
{ key: "files.setFavorite", input: LibraryArgs<SetFavoriteArgs>, result: null } |
{ key: "files.setNote", input: LibraryArgs<SetNoteArgs>, result: null } |
{ key: "jobs.generateThumbsForLocation", input: LibraryArgs<GenerateThumbsForLocationArgs>, result: null } |
{ key: "jobs.identifyUniqueFiles", input: LibraryArgs<IdentifyUniqueFilesArgs>, result: null } |
{ key: "library.create", input: string, result: LibraryConfigWrapped } |
{ key: "library.delete", input: string, result: null } |
{ key: "library.edit", input: EditLibraryArgs, result: null } |
{ key: "locations.create", input: LibraryArgs<LocationCreateArgs>, result: null } |
{ key: "locations.delete", input: LibraryArgs<number>, result: null } |
{ key: "locations.fullRescan", input: LibraryArgs<number>, result: null } |
{ key: "locations.indexer_rules.create", input: LibraryArgs<IndexerRuleCreateArgs>, result: IndexerRule } |
{ key: "locations.indexer_rules.delete", input: LibraryArgs<number>, result: null } |
{ key: "locations.quickRescan", input: LibraryArgs<null>, result: null } |
{ key: "locations.update", input: LibraryArgs<LocationUpdateArgs>, result: null } |
{ key: "tags.assign", input: LibraryArgs<TagAssignArgs>, result: null } |
{ key: "tags.create", input: LibraryArgs<TagCreateArgs>, result: Tag } |
{ key: "tags.delete", input: LibraryArgs<number>, result: null } |
{ key: "tags.update", input: LibraryArgs<TagUpdateArgs>, result: null },
| { key: 'files.delete'; input: LibraryArgs<number>; result: null }
| { key: 'files.setFavorite'; input: LibraryArgs<SetFavoriteArgs>; result: null }
| { key: 'files.setNote'; input: LibraryArgs<SetNoteArgs>; result: null }
| {
key: 'jobs.generateThumbsForLocation';
input: LibraryArgs<GenerateThumbsForLocationArgs>;
result: null;
}
| { key: 'jobs.identifyUniqueFiles'; input: LibraryArgs<IdentifyUniqueFilesArgs>; result: null }
| { key: 'library.create'; input: string; result: LibraryConfigWrapped }
| { key: 'library.delete'; input: string; result: null }
| { key: 'library.edit'; input: EditLibraryArgs; result: null }
| { key: 'locations.create'; input: LibraryArgs<LocationCreateArgs>; result: null }
| { key: 'locations.delete'; input: LibraryArgs<number>; result: null }
| { key: 'locations.fullRescan'; input: LibraryArgs<number>; result: null }
| {
key: 'locations.indexer_rules.create';
input: LibraryArgs<IndexerRuleCreateArgs>;
result: IndexerRule;
}
| { key: 'locations.indexer_rules.delete'; input: LibraryArgs<number>; result: null }
| { key: 'locations.quickRescan'; input: LibraryArgs<null>; result: null }
| { key: 'locations.update'; input: LibraryArgs<LocationUpdateArgs>; result: null }
| { key: 'tags.assign'; input: LibraryArgs<TagAssignArgs>; result: null }
| { key: 'tags.create'; input: LibraryArgs<TagCreateArgs>; result: Tag }
| { key: 'tags.delete'; input: LibraryArgs<number>; result: null }
| { key: 'tags.update'; input: LibraryArgs<TagUpdateArgs>; result: null };
subscriptions:
{ key: "invalidateQuery", input: never, result: InvalidateOperationEvent } |
{ key: "jobs.newThumbnail", input: LibraryArgs<null>, result: string }
| { key: 'invalidateQuery'; input: never; result: InvalidateOperationEvent }
| { key: 'jobs.newThumbnail'; input: LibraryArgs<null>; result: string };
};
export interface ConfigMetadata { version: string | null }
export interface ConfigMetadata {
version: string | null;
}
export interface EditLibraryArgs { id: string, name: string | null, description: string | null }
export interface EditLibraryArgs {
id: string;
name: string | null;
description: string | null;
}
export type ExplorerContext = { type: "Location" } & Location | { type: "Tag" } & Tag
export type ExplorerContext = ({ type: 'Location' } & Location) | ({ type: 'Tag' } & Tag);
export interface ExplorerData { context: ExplorerContext, items: Array<ExplorerItem> }
export interface ExplorerData {
context: ExplorerContext;
items: Array<ExplorerItem>;
}
export type ExplorerItem = { type: "Path" } & { id: number, is_dir: boolean, location_id: number, materialized_path: string, name: string, extension: string | null, object_id: number | null, parent_id: number | null, key_id: number | null, date_created: string, date_modified: string, date_indexed: string, object: Object | null } | { type: "Object" } & { id: number, cas_id: string, integrity_checksum: string | null, name: string | null, extension: string | null, kind: number, size_in_bytes: string, key_id: number | null, hidden: boolean, favorite: boolean, important: boolean, has_thumbnail: boolean, has_thumbstrip: boolean, has_video_preview: boolean, ipfs_id: string | null, note: string | null, date_created: string, date_modified: string, date_indexed: string, file_paths: Array<FilePath> }
export type ExplorerItem =
| ({ type: 'Path' } & {
id: number;
is_dir: boolean;
location_id: number;
materialized_path: string;
name: string;
extension: string | null;
object_id: number | null;
parent_id: number | null;
key_id: number | null;
date_created: string;
date_modified: string;
date_indexed: string;
object: Object | null;
})
| ({ type: 'Object' } & {
id: number;
cas_id: string;
integrity_checksum: string | null;
name: string | null;
extension: string | null;
kind: number;
size_in_bytes: string;
key_id: number | null;
hidden: boolean;
favorite: boolean;
important: boolean;
has_thumbnail: boolean;
has_thumbstrip: boolean;
has_video_preview: boolean;
ipfs_id: string | null;
note: string | null;
date_created: string;
date_modified: string;
date_indexed: string;
file_paths: Array<FilePath>;
});
export interface FilePath { id: number, is_dir: boolean, location_id: number, materialized_path: string, name: string, extension: string | null, object_id: number | null, parent_id: number | null, key_id: number | null, date_created: string, date_modified: string, date_indexed: string }
export interface FilePath {
id: number;
is_dir: boolean;
location_id: number;
materialized_path: string;
name: string;
extension: string | null;
object_id: number | null;
parent_id: number | null;
key_id: number | null;
date_created: string;
date_modified: string;
date_indexed: string;
}
export interface GenerateThumbsForLocationArgs { id: number, path: string }
export interface GenerateThumbsForLocationArgs {
id: number;
path: string;
}
export interface IdentifyUniqueFilesArgs { id: number, path: string }
export interface IdentifyUniqueFilesArgs {
id: number;
path: string;
}
export interface IndexerRule { id: number, kind: number, name: string, parameters: Array<number>, date_created: string, date_modified: string }
export interface IndexerRule {
id: number;
kind: number;
name: string;
parameters: Array<number>;
date_created: string;
date_modified: string;
}
export interface IndexerRuleCreateArgs { kind: RuleKind, name: string, parameters: Array<number> }
export interface IndexerRuleCreateArgs {
kind: RuleKind;
name: string;
parameters: Array<number>;
}
export interface InvalidateOperationEvent { key: string, arg: any }
export interface InvalidateOperationEvent {
key: string;
arg: any;
}
export interface JobReport { id: string, name: string, data: Array<number> | null, metadata: any | null, date_created: string, date_modified: string, status: JobStatus, task_count: number, completed_task_count: number, message: string, seconds_elapsed: number }
export interface JobReport {
id: string;
name: string;
data: Array<number> | null;
metadata: any | null;
date_created: string;
date_modified: string;
status: JobStatus;
task_count: number;
completed_task_count: number;
message: string;
seconds_elapsed: number;
}
export type JobStatus = "Queued" | "Running" | "Completed" | "Canceled" | "Failed" | "Paused"
export type JobStatus = 'Queued' | 'Running' | 'Completed' | 'Canceled' | 'Failed' | 'Paused';
export interface LibraryArgs<T> { library_id: string, arg: T }
export interface LibraryArgs<T> {
library_id: string;
arg: T;
}
export interface LibraryConfig { version: string | null, name: string, description: string }
export interface LibraryConfig {
version: string | null;
name: string;
description: string;
}
export interface LibraryConfigWrapped { uuid: string, config: LibraryConfig }
export interface LibraryConfigWrapped {
uuid: string;
config: LibraryConfig;
}
export interface Location { id: number, pub_id: Array<number>, node_id: number, name: string | null, local_path: string | null, total_capacity: number | null, available_capacity: number | null, filesystem: string | null, disk_type: number | null, is_removable: boolean | null, is_online: boolean, is_archived: boolean, date_created: string }
export interface Location {
id: number;
pub_id: Array<number>;
node_id: number;
name: string | null;
local_path: string | null;
total_capacity: number | null;
available_capacity: number | null;
filesystem: string | null;
disk_type: number | null;
is_removable: boolean | null;
is_online: boolean;
is_archived: boolean;
date_created: string;
}
export interface LocationCreateArgs { path: string, indexer_rules_ids: Array<number> }
export interface LocationCreateArgs {
path: string;
indexer_rules_ids: Array<number>;
}
export interface LocationExplorerArgs { location_id: number, path: string, limit: number, cursor: string | null }
export interface LocationExplorerArgs {
location_id: number;
path: string;
limit: number;
cursor: string | null;
}
export interface LocationUpdateArgs { id: number, name: string | null, indexer_rules_ids: Array<number> }
export interface LocationUpdateArgs {
id: number;
name: string | null;
indexer_rules_ids: Array<number>;
}
export interface Node { id: number, pub_id: Array<number>, name: string, platform: number, version: string | null, last_seen: string, timezone: string | null, date_created: string }
export interface Node {
id: number;
pub_id: Array<number>;
name: string;
platform: number;
version: string | null;
last_seen: string;
timezone: string | null;
date_created: string;
}
export interface NodeConfig { version: string | null, id: string, name: string, p2p_port: number | null }
export interface NodeConfig {
version: string | null;
id: string;
name: string;
p2p_port: number | null;
}
export interface NodeState { version: string | null, id: string, name: string, p2p_port: number | null, data_path: string }
export interface NodeState {
version: string | null;
id: string;
name: string;
p2p_port: number | null;
data_path: string;
}
export interface Object { id: number, cas_id: string, integrity_checksum: string | null, name: string | null, extension: string | null, kind: number, size_in_bytes: string, key_id: number | null, hidden: boolean, favorite: boolean, important: boolean, has_thumbnail: boolean, has_thumbstrip: boolean, has_video_preview: boolean, ipfs_id: string | null, note: string | null, date_created: string, date_modified: string, date_indexed: string }
export interface Object {
id: number;
cas_id: string;
integrity_checksum: string | null;
name: string | null;
extension: string | null;
kind: number;
size_in_bytes: string;
key_id: number | null;
hidden: boolean;
favorite: boolean;
important: boolean;
has_thumbnail: boolean;
has_thumbstrip: boolean;
has_video_preview: boolean;
ipfs_id: string | null;
note: string | null;
date_created: string;
date_modified: string;
date_indexed: string;
}
export type RuleKind = "AcceptFilesByGlob" | "RejectFilesByGlob" | "AcceptIfChildrenDirectoriesArePresent" | "RejectIfChildrenDirectoriesArePresent"
export type RuleKind =
| 'AcceptFilesByGlob'
| 'RejectFilesByGlob'
| 'AcceptIfChildrenDirectoriesArePresent'
| 'RejectIfChildrenDirectoriesArePresent';
export interface SetFavoriteArgs { id: number, favorite: boolean }
export interface SetFavoriteArgs {
id: number;
favorite: boolean;
}
export interface SetNoteArgs { id: number, note: string | null }
export interface SetNoteArgs {
id: number;
note: string | null;
}
export interface Statistics { id: number, date_captured: string, total_object_count: number, library_db_size: string, total_bytes_used: string, total_bytes_capacity: string, total_unique_bytes: string, total_bytes_free: string, preview_media_bytes: string }
export interface Statistics {
id: number;
date_captured: string;
total_object_count: number;
library_db_size: string;
total_bytes_used: string;
total_bytes_capacity: string;
total_unique_bytes: string;
total_bytes_free: string;
preview_media_bytes: string;
}
export interface Tag { id: number, pub_id: Array<number>, name: string | null, color: string | null, total_objects: number | null, redundancy_goal: number | null, date_created: string, date_modified: string }
export interface Tag {
id: number;
pub_id: Array<number>;
name: string | null;
color: string | null;
total_objects: number | null;
redundancy_goal: number | null;
date_created: string;
date_modified: string;
}
export interface TagAssignArgs { object_id: number, tag_id: number, unassign: boolean }
export interface TagAssignArgs {
object_id: number;
tag_id: number;
unassign: boolean;
}
export interface TagCreateArgs { name: string, color: string }
export interface TagCreateArgs {
name: string;
color: string;
}
export interface TagUpdateArgs { id: number, name: string | null, color: string | null }
export interface TagUpdateArgs {
id: number;
name: string | null;
color: string | null;
}
export interface Volume { name: string, mount_point: string, total_capacity: bigint, available_capacity: bigint, is_removable: boolean, disk_type: string | null, file_system: string | null, is_root_filesystem: boolean }
export interface Volume {
name: string;
mount_point: string;
total_capacity: bigint;
available_capacity: bigint;
is_removable: boolean;
disk_type: string | null;
file_system: string | null;
is_root_filesystem: boolean;
}

View file

@ -1,15 +1,13 @@
<!DOCTYPE html>
<html class="dark">
<head>
<head>
<meta charset="utf-8" />
<title>Spacedrive</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
</head>
<body>
<body>
<div id="root"></div>
<script type="module" src="./index.tsx"></script>
</body>
</body>
</html>

View file

@ -1,8 +1,10 @@
import App from './App';
import '@sd/ui/style';
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import '@sd/ui/style';
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
<React.StrictMode>

View file

@ -1,7 +1,5 @@
{
"extends": "../../packages/config/interface.tsconfig.json",
"compilerOptions": {},
"include": [
"src"
]
"include": ["src"]
}

View file

@ -4,7 +4,7 @@ This document outlines the peer to peer protocol used by the Spacedrive desktop
## Concepts
- **Peer** - TODO
- **Peer** - TODO
### P2PManager
@ -34,7 +34,7 @@ To discovery other machines running Spacedrive over your local network, we make
Spacedrive advertise a SRV record that looks like:
_{peer_id}_spacedrive_._udp_.local. 86400 IN SRV 10 5 5223 server.example.com.
_{peer_id}\_spacedrive_._udp_.local. 86400 IN SRV 10 5 5223 server.example.com.
This system will continue to passively discover clients while Spacedrive is running.
@ -58,24 +58,11 @@ TODO
Message::QueryClientAnnouncement(vec![peer_id, peer_id2]);
```
## General Overview
This system is designed on top of the following main technologies:
- [QUIC]() - A tcp-like protocol built on top of UDP. QUIC also supports [TLS 1.3]() for encryption and pro
- [QUIC]() - A tcp-like protocol built on top of UDP. QUIC also supports [TLS 1.3]() for encryption and pro
## Pairing
@ -83,5 +70,5 @@ TODO
# External Resources
- TODO: Magic Wormhole talk
- TODO: Syncthing spec
- TODO: Magic Wormhole talk
- TODO: Syncthing spec

View file

@ -1,4 +1,3 @@
# crdt-rs
Just @brendonovich experimenting with CRDT stuff.

View file

@ -1,5 +1,3 @@
```rust
pub fn update_with_timestamp(&self, timestamp: &Timestamp) -> Result<(), String> {
let mut now = (self.clock)();
@ -31,7 +29,7 @@ pub fn update_with_timestamp(&self, timestamp: &Timestamp) -> Result<(), String>
```
```javascript
Timestamp.recv = function(msg) {
Timestamp.recv = function (msg) {
if (!clock) {
return null;
}
@ -70,10 +68,6 @@ Timestamp.recv = function(msg) {
clock.timestamp.setMillis(max_time);
clock.timestamp.setCounter(last_time);
return new Timestamp(
clock.timestamp.millis(),
clock.timestamp.counter(),
clock.timestamp.node()
);
return new Timestamp(clock.timestamp.millis(), clock.timestamp.counter(), clock.timestamp.node());
};
```

View file

@ -1,26 +1,25 @@
import clsx from "clsx";
import { createSignal, For, JSX, Suspense } from "solid-js";
import { queryClient, rspc } from "./rspc";
import clsx from 'clsx';
import { For, JSX, Suspense, createSignal } from 'solid-js';
import { queryClient, rspc } from './rspc';
export function App() {
const dbs = rspc.createQuery(() => ["dbs"]);
const dbs = rspc.createQuery(() => ['dbs']);
const createDb = rspc.createMutation("createDatabase", {
const createDb = rspc.createMutation('createDatabase', {
onSuccess: () => {
queryClient.invalidateQueries();
},
}
});
const removeDbs = rspc.createMutation("removeDatabases", {
onSuccess: () => queryClient.invalidateQueries(),
const removeDbs = rspc.createMutation('removeDatabases', {
onSuccess: () => queryClient.invalidateQueries()
});
return (
<div class="p-4 space-y-4">
<div class="space-x-4">
<Button onClick={() => createDb.mutate(undefined)}>Add Database</Button>
<Button onClick={() => removeDbs.mutate(undefined)}>
Remove Databases
</Button>
<Button onClick={() => removeDbs.mutate(undefined)}>Remove Databases</Button>
</div>
<ul class="gap-2 flex flex-row flex-wrap">
<For each={dbs.data}>
@ -38,10 +37,10 @@ export function App() {
interface DatabaseViewProps {
id: string;
}
const TABS = ["Tags", "Files", "File Paths", "Messages"];
const TABS = ['Tags', 'Files', 'File Paths', 'Messages'];
function DatabaseView(props: DatabaseViewProps) {
const [currentTab, setCurrentTab] = createSignal<typeof TABS[number]>("Tags");
const [currentTab, setCurrentTab] = createSignal<typeof TABS[number]>('Tags');
return (
<div class="bg-indigo-300 rounded-md min-w-[40rem] flex-1 overflow-hidden">
@ -51,10 +50,7 @@ function DatabaseView(props: DatabaseViewProps) {
<For each={TABS}>
{(tab) => (
<button
class={clsx(
"px-2 py-1",
tab === currentTab() && "bg-indigo-400"
)}
class={clsx('px-2 py-1', tab === currentTab() && 'bg-indigo-400')}
onClick={() => setCurrentTab(tab)}
>
{tab}
@ -69,7 +65,5 @@ function DatabaseView(props: DatabaseViewProps) {
}
function Button(props: JSX.ButtonHTMLAttributes<HTMLButtonElement>) {
return (
<button {...props} class="bg-blue-500 text-white px-2 py-1 rounded-md" />
);
return <button {...props} class="bg-blue-500 text-white px-2 py-1 rounded-md" />;
}

View file

@ -2,14 +2,21 @@
export type Procedures = {
queries:
{ key: "db.tags", input: string, result: Record<string, Tag> } |
{ key: "dbs", input: never, result: Array<string> },
| { key: 'db.tags'; input: string; result: Record<string, Tag> }
| { key: 'dbs'; input: never; result: Array<string> };
mutations:
{ key: "createDatabase", input: never, result: string } |
{ key: "removeDatabases", input: never, result: null },
subscriptions: never
| { key: 'createDatabase'; input: never; result: string }
| { key: 'removeDatabases'; input: never; result: null };
subscriptions: never;
};
export interface Color { red: number, green: number, blue: number }
export interface Color {
red: number;
green: number;
blue: number;
}
export interface Tag { color: Color, name: string }
export interface Tag {
color: Color;
name: string;
}

View file

@ -1,9 +1,9 @@
/* @refresh reload */
import { render, Suspense } from "solid-js/web";
import { Suspense, render } from 'solid-js/web';
import "./index.css";
import { App } from "./App";
import { queryClient, rspc, rspcClient } from "./rspc";
import { App } from './App';
import './index.css';
import { queryClient, rspc, rspcClient } from './rspc';
render(
() => (
@ -13,5 +13,5 @@ render(
</Suspense>
</rspc.Provider>
),
document.getElementById("root") as HTMLElement
document.getElementById('root') as HTMLElement
);

View file

@ -1,22 +1,24 @@
import { QueryClient } from "@tanstack/solid-query";
import { createSolidQueryHooks } from "@rspc/solid";
import { createClient } from "@rspc/client";
import { TauriTransport } from "@rspc/tauri";
import { createClient } from '@rspc/client';
import { createSolidQueryHooks } from '@rspc/solid';
import { TauriTransport } from '@rspc/tauri';
import { QueryClient } from '@tanstack/solid-query';
import type { Procedures } from "./bindings"; // These were the bindings exported from your Rust code!
import type { Procedures } from './bindings';
// These were the bindings exported from your Rust code!
// You must provide the generated types as a generic and create a transport (in this example we are using HTTP Fetch) so that the client knows how to communicate with your API.
export const rspcClient = createClient<Procedures>({
// Refer to the integration your using for the correct transport.
transport: new TauriTransport(),
transport: new TauriTransport()
});
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
suspense: true,
},
},
suspense: true
}
}
});
export const rspc = createSolidQueryHooks<Procedures>();

View file

@ -1,5 +1,5 @@
import { defineConfig } from "vite";
import solidPlugin from "vite-plugin-solid";
import { defineConfig } from 'vite';
import solidPlugin from 'vite-plugin-solid';
export default defineConfig({
plugins: [solidPlugin()],
@ -9,17 +9,17 @@ export default defineConfig({
// tauri expects a fixed port, fail if that port is not available
server: {
port: 1420,
strictPort: true,
strictPort: true
},
// to make use of `TAURI_DEBUG` and other env variables
// https://tauri.studio/v1/api/config#buildconfig.beforedevcommand
envPrefix: ["VITE_", "TAURI_"],
envPrefix: ['VITE_', 'TAURI_'],
build: {
// Tauri supports es2021
target: ["es2021", "chrome100", "safari13"],
target: ['es2021', 'chrome100', 'safari13'],
// don't minify for debug builds
minify: !process.env.TAURI_DEBUG ? "esbuild" : false,
minify: !process.env.TAURI_DEBUG ? 'esbuild' : false,
// produce sourcemaps for debug builds
sourcemap: !!process.env.TAURI_DEBUG,
},
sourcemap: !!process.env.TAURI_DEBUG
}
});

View file

@ -4,13 +4,13 @@
This release has not happened yet, stay tuned...
:::
After __ months of development we are extremely excited to be releasing the first version of Spacedrive as an early public beta.
After \_\_ months of development we are extremely excited to be releasing the first version of Spacedrive as an early public beta.
This is an MVP, and by no means feature complete. Please test out the features listed below and give us feedback via Discord, email or GitHub Issues :D
This release is missing database synchronization between nodes (your devices), for now this renders connecting nodes useless, other than to transfer individual files. But don't worry, its coming very soon!
*Features:*
_Features:_
- Support for Windows, Linux and macOS, iOS and Android.
@ -21,20 +21,20 @@ This release is missing database synchronization between nodes (your devices), f
- Connect multiple [Nodes](../architecture/nodes.md) to a Library via LAN.
- Add [Locations](../architecture/locations.md) to import files into Spacedrive.
- Indexer watch for changes and performs light re-scans.
- Identifier generates checksum and categorizes files into [Objects]()
- Define rules for indexer to ignore certain files or folders.
*Eventually Clouds will be supported and added as Cloud Locations*
_Eventually Clouds will be supported and added as Cloud Locations_
- Browse Locations via the [Explorer](../architecture/explorer.md) and view previews and metadata.
- Viewer options: row/grid item size, gap adjustment, show/hide info.
- Context menu: rename, copy, duplicate, delete, favorite and add tags.
- Multi-select with dedicated context menu options.
- Open with default OS app, in-app viewer (images/text only) or Apple Quicklook
- Automatically identify unique files to discover duplicates, shown in the inspector.
- Generate [Preview Media](../architecture/preview-media.md) for image, video and text.
@ -45,7 +45,7 @@ This release is missing database synchronization between nodes (your devices), f
- Automated Spaces can include files that match criteria.
*Eventually Spaces will be sharable, publically or privately*
_Eventually Spaces will be sharable, publically or privately_
- Create photo [Albums](../architecture/albums.md) and add images.

View file

@ -1,6 +1,7 @@
---
index: 10
---
# Albums
you can put photos here

View file

@ -2,7 +2,6 @@
index: 10
---
# Explorer
using the interface, features

View file

@ -1,6 +1,7 @@
---
index: 1
---
# Libraries
A library is the database that Spacedrive stores all file structures and metadata. It can be synchronized with other [Nodes]()

View file

@ -1,10 +1,9 @@
---
index: 3
---
# Nodes
Nodes are instances of the Spacedrive core running on a device, they are able to connect to each other via a peer-to-peer network. A node is able to run many libraries simultaneously, but must be authorized per-library in order to synchronize.
p2p, connecting nodes, protocols.

View file

@ -19,7 +19,7 @@ Some Objects are purely virtual, meaning they have no Path and are likely only u
## Types of object
| Name | Description | Code |
| ---------------- | ------------------------------------------------------------ | ---- |
| ---------------- | ---------------------------------------------------------------------------------------------------------- | ---- |
| Unknown | A file that can not be identified by the indexer | 0 |
| Document | A known filetype, but without specific support | 1 |
| Folder | A virtual filesystem directory | 2 |

View file

@ -2,7 +2,6 @@
index: 11
---
# Search
Press CTRL+F while on a Spacedrive window to access search.

View file

@ -1,6 +1,7 @@
---
index: 3
---
# Spaces
Spaces are virtual folders that can be shared publicly on the internet, or privately with friends, family and teams. Spaces contain [Objects](/docs/developers/architecture/objects) which can be physically stored on any connected Node, or by Spacedrive as a service. Objects can be organized and presented spatially, with various layouts and variable grid placements. Color theme, icon packs and typography can be customized per Space.

View file

@ -3,4 +3,3 @@ index: 10
---
# Virtual Filesystem

View file

@ -4,23 +4,27 @@ index: 500
---
# JavaScript Client
For developers who want to extend the functionality of Spacedrive, this library allows easy development of [Extensions](), providing full access to Spacedrive's functionality.
### Installation
```shell
$ npm i @spacedrive/client
```
Initialize the Spacedrive client
```ts
import spacedrive from "@spacedrive/client";
spacedrive.start()
```ts
import spacedrive from '@spacedrive/client';
spacedrive.start();
```
Add a location
```ts
const location = await spacedrive.location.create("/Users/jamie/Documents");
const location = await spacedrive.location.create('/Users/jamie/Documents');
location.scan();
```

View file

@ -17,16 +17,21 @@ This project uses [Cargo](https://doc.rust-lang.org/cargo/getting-started/instal
2. **Run setup script**
**For Linux or MacOS users run:**
```shell
./.github/scripts/setup-system.sh
```
This will install FFMPEG and any other required dependencies for Spacedrive to build.
**...or for Windows users run using PowerShell:**
```shell
.\.github\scripts\setup-system.ps1
```
_This will install pnpm, LLVM, FFMPEG and any other required dependencies for Spacedrive to build. Ensure you run it like documented above as it expects it is executed from the root of the repository._
3. **Install dependencies**
```shell
pnpm i

View file

@ -4,4 +4,3 @@ index: 0
---
# Terminology

View file

@ -11,6 +11,7 @@ Locations are places Spacedrive looks for files. You can add Locations from any
Locations can be managed from the settings. The "online" indicator shows if that Location is currently accessible from one of your devices.
## Scanning
When a Location is added it is immediately scanned. The scan happens via several phases.
1. The [Indexer](): directory structure is indexed and saved to your library's database.
@ -28,6 +29,7 @@ There is a button to trigger a full re-scan of this Location. Otherwise the loca
Deleting a location will remove the data from the database permanently.
## Archiving
::: slot warning
This feature is WIP
:::
@ -36,7 +38,9 @@ Locations can be archived, meaning the directory structure is extracted from the
Archives are useful when files have been moved or deleted from a Location, but you want to keep a record of the directory structure of that Location without cluttering the Spacedrive interface. File metadata can optionally be included/excluded from the archive file.
## Dynamic Space
A slider in the Location settings allows you to allocate an amount of GB to use as redundancy for other Locations. The storage space will be filled and emptied dynamically, recent and important files will be copied as priority.
## Encrypted Space
Allocate a portion of this location to be encrypted

View file

@ -11,4 +11,3 @@ It is not possible to connect Nodes yet, please check our [roadmap](/roadmap).
Nodes are instances of Spacedrive, commonly your devices. Currently Spacedrive supports Windows, Linux, Mac, iOS and Android.
These devices can be connected via P2P to directly and securely synchronize and move data.

View file

@ -11,4 +11,5 @@ For the convenience of finding, organizing and sharing files even when you don't
This data is heavily compressed and very portable, you can have multiple libraries and even lock and encrypt them.
## Deleting a Library
A Library can be deleted,

View file

@ -8,7 +8,7 @@
"landing-web": "turbo run dev --parallel --filter=@sd/landing --filter=@sd/web",
"gen:migrations": "cd core && cargo prisma migrate dev",
"gen:prisma": "cd core && cargo prisma generate",
"format": "prettier --config .prettierrc.cli.js --write \"**/*.{ts,tsx,html,scss,json,yml,md}\"",
"format": "prettier --config .prettierrc.js --write \"**/*.{ts,tsx,html,scss,json,yml,md}\"",
"desktop": "pnpm --filter @sd/desktop --",
"web": "pnpm --filter @sd/web -- ",
"landing": "pnpm --filter @sd/landing -- ",

View file

@ -3,110 +3,357 @@
export type Procedures = {
queries:
{ key: "files.readMetadata", input: LibraryArgs<number>, result: null } |
{ key: "getNode", input: never, result: NodeState } |
{ key: "jobs.getHistory", input: LibraryArgs<null>, result: Array<JobReport> } |
{ key: "jobs.getRunning", input: LibraryArgs<null>, result: Array<JobReport> } |
{ key: "library.getStatistics", input: LibraryArgs<null>, result: Statistics } |
{ key: "library.list", input: never, result: Array<LibraryConfigWrapped> } |
{ key: "locations.getById", input: LibraryArgs<number>, result: Location | null } |
{ key: "locations.getExplorerData", input: LibraryArgs<LocationExplorerArgs>, result: ExplorerData } |
{ key: "locations.indexer_rules.get", input: LibraryArgs<number>, result: IndexerRule } |
{ key: "locations.indexer_rules.list", input: LibraryArgs<null>, result: Array<IndexerRule> } |
{ key: "locations.list", input: LibraryArgs<null>, result: Array<{ id: number, pub_id: Array<number>, node_id: number, name: string | null, local_path: string | null, total_capacity: number | null, available_capacity: number | null, filesystem: string | null, disk_type: number | null, is_removable: boolean | null, is_online: boolean, is_archived: boolean, date_created: string, node: Node }> } |
{ key: "tags.get", input: LibraryArgs<number>, result: Tag | null } |
{ key: "tags.getExplorerData", input: LibraryArgs<number>, result: ExplorerData } |
{ key: "tags.getForObject", input: LibraryArgs<number>, result: Array<Tag> } |
{ key: "tags.list", input: LibraryArgs<null>, result: Array<Tag> } |
{ key: "version", input: never, result: string } |
{ key: "volumes.list", input: never, result: Array<Volume> },
| { key: 'files.readMetadata'; input: LibraryArgs<number>; result: null }
| { key: 'getNode'; input: never; result: NodeState }
| { key: 'jobs.getHistory'; input: LibraryArgs<null>; result: Array<JobReport> }
| { key: 'jobs.getRunning'; input: LibraryArgs<null>; result: Array<JobReport> }
| { key: 'library.getStatistics'; input: LibraryArgs<null>; result: Statistics }
| { key: 'library.list'; input: never; result: Array<LibraryConfigWrapped> }
| { key: 'locations.getById'; input: LibraryArgs<number>; result: Location | null }
| {
key: 'locations.getExplorerData';
input: LibraryArgs<LocationExplorerArgs>;
result: ExplorerData;
}
| { key: 'locations.indexer_rules.get'; input: LibraryArgs<number>; result: IndexerRule }
| { key: 'locations.indexer_rules.list'; input: LibraryArgs<null>; result: Array<IndexerRule> }
| {
key: 'locations.list';
input: LibraryArgs<null>;
result: Array<{
id: number;
pub_id: Array<number>;
node_id: number;
name: string | null;
local_path: string | null;
total_capacity: number | null;
available_capacity: number | null;
filesystem: string | null;
disk_type: number | null;
is_removable: boolean | null;
is_online: boolean;
is_archived: boolean;
date_created: string;
node: Node;
}>;
}
| { key: 'tags.get'; input: LibraryArgs<number>; result: Tag | null }
| { key: 'tags.getExplorerData'; input: LibraryArgs<number>; result: ExplorerData }
| { key: 'tags.getForObject'; input: LibraryArgs<number>; result: Array<Tag> }
| { key: 'tags.list'; input: LibraryArgs<null>; result: Array<Tag> }
| { key: 'version'; input: never; result: string }
| { key: 'volumes.list'; input: never; result: Array<Volume> };
mutations:
{ key: "files.delete", input: LibraryArgs<number>, result: null } |
{ key: "files.setFavorite", input: LibraryArgs<SetFavoriteArgs>, result: null } |
{ key: "files.setNote", input: LibraryArgs<SetNoteArgs>, result: null } |
{ key: "jobs.generateThumbsForLocation", input: LibraryArgs<GenerateThumbsForLocationArgs>, result: null } |
{ key: "jobs.identifyUniqueFiles", input: LibraryArgs<IdentifyUniqueFilesArgs>, result: null } |
{ key: "library.create", input: string, result: LibraryConfigWrapped } |
{ key: "library.delete", input: string, result: null } |
{ key: "library.edit", input: EditLibraryArgs, result: null } |
{ key: "locations.create", input: LibraryArgs<LocationCreateArgs>, result: null } |
{ key: "locations.delete", input: LibraryArgs<number>, result: null } |
{ key: "locations.fullRescan", input: LibraryArgs<number>, result: null } |
{ key: "locations.indexer_rules.create", input: LibraryArgs<IndexerRuleCreateArgs>, result: IndexerRule } |
{ key: "locations.indexer_rules.delete", input: LibraryArgs<number>, result: null } |
{ key: "locations.quickRescan", input: LibraryArgs<null>, result: null } |
{ key: "locations.update", input: LibraryArgs<LocationUpdateArgs>, result: null } |
{ key: "tags.assign", input: LibraryArgs<TagAssignArgs>, result: null } |
{ key: "tags.create", input: LibraryArgs<TagCreateArgs>, result: Tag } |
{ key: "tags.delete", input: LibraryArgs<number>, result: null } |
{ key: "tags.update", input: LibraryArgs<TagUpdateArgs>, result: null },
| { key: 'files.delete'; input: LibraryArgs<number>; result: null }
| { key: 'files.setFavorite'; input: LibraryArgs<SetFavoriteArgs>; result: null }
| { key: 'files.setNote'; input: LibraryArgs<SetNoteArgs>; result: null }
| {
key: 'jobs.generateThumbsForLocation';
input: LibraryArgs<GenerateThumbsForLocationArgs>;
result: null;
}
| { key: 'jobs.identifyUniqueFiles'; input: LibraryArgs<IdentifyUniqueFilesArgs>; result: null }
| { key: 'library.create'; input: string; result: LibraryConfigWrapped }
| { key: 'library.delete'; input: string; result: null }
| { key: 'library.edit'; input: EditLibraryArgs; result: null }
| { key: 'locations.create'; input: LibraryArgs<LocationCreateArgs>; result: null }
| { key: 'locations.delete'; input: LibraryArgs<number>; result: null }
| { key: 'locations.fullRescan'; input: LibraryArgs<number>; result: null }
| {
key: 'locations.indexer_rules.create';
input: LibraryArgs<IndexerRuleCreateArgs>;
result: IndexerRule;
}
| { key: 'locations.indexer_rules.delete'; input: LibraryArgs<number>; result: null }
| { key: 'locations.quickRescan'; input: LibraryArgs<null>; result: null }
| { key: 'locations.update'; input: LibraryArgs<LocationUpdateArgs>; result: null }
| { key: 'tags.assign'; input: LibraryArgs<TagAssignArgs>; result: null }
| { key: 'tags.create'; input: LibraryArgs<TagCreateArgs>; result: Tag }
| { key: 'tags.delete'; input: LibraryArgs<number>; result: null }
| { key: 'tags.update'; input: LibraryArgs<TagUpdateArgs>; result: null };
subscriptions:
{ key: "invalidateQuery", input: never, result: InvalidateOperationEvent } |
{ key: "jobs.newThumbnail", input: LibraryArgs<null>, result: string }
| { key: 'invalidateQuery'; input: never; result: InvalidateOperationEvent }
| { key: 'jobs.newThumbnail'; input: LibraryArgs<null>; result: string };
};
export interface ConfigMetadata { version: string | null }
export interface ConfigMetadata {
version: string | null;
}
export interface EditLibraryArgs { id: string, name: string | null, description: string | null }
export interface EditLibraryArgs {
id: string;
name: string | null;
description: string | null;
}
export type ExplorerContext = { type: "Location" } & Location | { type: "Tag" } & Tag
export type ExplorerContext = ({ type: 'Location' } & Location) | ({ type: 'Tag' } & Tag);
export interface ExplorerData { context: ExplorerContext, items: Array<ExplorerItem> }
export interface ExplorerData {
context: ExplorerContext;
items: Array<ExplorerItem>;
}
export type ExplorerItem = { type: "Path" } & { id: number, is_dir: boolean, location_id: number, materialized_path: string, name: string, extension: string | null, object_id: number | null, parent_id: number | null, key_id: number | null, date_created: string, date_modified: string, date_indexed: string, object: Object | null } | { type: "Object" } & { id: number, cas_id: string, integrity_checksum: string | null, name: string | null, extension: string | null, kind: number, size_in_bytes: string, key_id: number | null, hidden: boolean, favorite: boolean, important: boolean, has_thumbnail: boolean, has_thumbstrip: boolean, has_video_preview: boolean, ipfs_id: string | null, note: string | null, date_created: string, date_modified: string, date_indexed: string, file_paths: Array<FilePath> }
export type ExplorerItem =
| ({ type: 'Path' } & {
id: number;
is_dir: boolean;
location_id: number;
materialized_path: string;
name: string;
extension: string | null;
object_id: number | null;
parent_id: number | null;
key_id: number | null;
date_created: string;
date_modified: string;
date_indexed: string;
object: Object | null;
})
| ({ type: 'Object' } & {
id: number;
cas_id: string;
integrity_checksum: string | null;
name: string | null;
extension: string | null;
kind: number;
size_in_bytes: string;
key_id: number | null;
hidden: boolean;
favorite: boolean;
important: boolean;
has_thumbnail: boolean;
has_thumbstrip: boolean;
has_video_preview: boolean;
ipfs_id: string | null;
note: string | null;
date_created: string;
date_modified: string;
date_indexed: string;
file_paths: Array<FilePath>;
});
export interface FilePath { id: number, is_dir: boolean, location_id: number, materialized_path: string, name: string, extension: string | null, object_id: number | null, parent_id: number | null, key_id: number | null, date_created: string, date_modified: string, date_indexed: string }
export interface FilePath {
id: number;
is_dir: boolean;
location_id: number;
materialized_path: string;
name: string;
extension: string | null;
object_id: number | null;
parent_id: number | null;
key_id: number | null;
date_created: string;
date_modified: string;
date_indexed: string;
}
export interface GenerateThumbsForLocationArgs { id: number, path: string }
export interface GenerateThumbsForLocationArgs {
id: number;
path: string;
}
export interface IdentifyUniqueFilesArgs { id: number, path: string }
export interface IdentifyUniqueFilesArgs {
id: number;
path: string;
}
export interface IndexerRule { id: number, kind: number, name: string, parameters: Array<number>, date_created: string, date_modified: string }
export interface IndexerRule {
id: number;
kind: number;
name: string;
parameters: Array<number>;
date_created: string;
date_modified: string;
}
export interface IndexerRuleCreateArgs { kind: RuleKind, name: string, parameters: Array<number> }
export interface IndexerRuleCreateArgs {
kind: RuleKind;
name: string;
parameters: Array<number>;
}
export interface InvalidateOperationEvent { key: string, arg: any }
export interface InvalidateOperationEvent {
key: string;
arg: any;
}
export interface JobReport { id: string, name: string, data: Array<number> | null, metadata: any | null, date_created: string, date_modified: string, status: JobStatus, task_count: number, completed_task_count: number, message: string, seconds_elapsed: number }
export interface JobReport {
id: string;
name: string;
data: Array<number> | null;
metadata: any | null;
date_created: string;
date_modified: string;
status: JobStatus;
task_count: number;
completed_task_count: number;
message: string;
seconds_elapsed: number;
}
export type JobStatus = "Queued" | "Running" | "Completed" | "Canceled" | "Failed" | "Paused"
export type JobStatus = 'Queued' | 'Running' | 'Completed' | 'Canceled' | 'Failed' | 'Paused';
export interface LibraryArgs<T> { library_id: string, arg: T }
export interface LibraryArgs<T> {
library_id: string;
arg: T;
}
export interface LibraryConfig { version: string | null, name: string, description: string }
export interface LibraryConfig {
version: string | null;
name: string;
description: string;
}
export interface LibraryConfigWrapped { uuid: string, config: LibraryConfig }
export interface LibraryConfigWrapped {
uuid: string;
config: LibraryConfig;
}
export interface Location { id: number, pub_id: Array<number>, node_id: number, name: string | null, local_path: string | null, total_capacity: number | null, available_capacity: number | null, filesystem: string | null, disk_type: number | null, is_removable: boolean | null, is_online: boolean, is_archived: boolean, date_created: string }
export interface Location {
id: number;
pub_id: Array<number>;
node_id: number;
name: string | null;
local_path: string | null;
total_capacity: number | null;
available_capacity: number | null;
filesystem: string | null;
disk_type: number | null;
is_removable: boolean | null;
is_online: boolean;
is_archived: boolean;
date_created: string;
}
export interface LocationCreateArgs { path: string, indexer_rules_ids: Array<number> }
export interface LocationCreateArgs {
path: string;
indexer_rules_ids: Array<number>;
}
export interface LocationExplorerArgs { location_id: number, path: string, limit: number, cursor: string | null }
export interface LocationExplorerArgs {
location_id: number;
path: string;
limit: number;
cursor: string | null;
}
export interface LocationUpdateArgs { id: number, name: string | null, indexer_rules_ids: Array<number> }
export interface LocationUpdateArgs {
id: number;
name: string | null;
indexer_rules_ids: Array<number>;
}
export interface Node { id: number, pub_id: Array<number>, name: string, platform: number, version: string | null, last_seen: string, timezone: string | null, date_created: string }
export interface Node {
id: number;
pub_id: Array<number>;
name: string;
platform: number;
version: string | null;
last_seen: string;
timezone: string | null;
date_created: string;
}
export interface NodeConfig { version: string | null, id: string, name: string, p2p_port: number | null }
export interface NodeConfig {
version: string | null;
id: string;
name: string;
p2p_port: number | null;
}
export interface NodeState { version: string | null, id: string, name: string, p2p_port: number | null, data_path: string }
export interface NodeState {
version: string | null;
id: string;
name: string;
p2p_port: number | null;
data_path: string;
}
export interface Object { id: number, cas_id: string, integrity_checksum: string | null, name: string | null, extension: string | null, kind: number, size_in_bytes: string, key_id: number | null, hidden: boolean, favorite: boolean, important: boolean, has_thumbnail: boolean, has_thumbstrip: boolean, has_video_preview: boolean, ipfs_id: string | null, note: string | null, date_created: string, date_modified: string, date_indexed: string }
export interface Object {
id: number;
cas_id: string;
integrity_checksum: string | null;
name: string | null;
extension: string | null;
kind: number;
size_in_bytes: string;
key_id: number | null;
hidden: boolean;
favorite: boolean;
important: boolean;
has_thumbnail: boolean;
has_thumbstrip: boolean;
has_video_preview: boolean;
ipfs_id: string | null;
note: string | null;
date_created: string;
date_modified: string;
date_indexed: string;
}
export type RuleKind = "AcceptFilesByGlob" | "RejectFilesByGlob" | "AcceptIfChildrenDirectoriesArePresent" | "RejectIfChildrenDirectoriesArePresent"
export type RuleKind =
| 'AcceptFilesByGlob'
| 'RejectFilesByGlob'
| 'AcceptIfChildrenDirectoriesArePresent'
| 'RejectIfChildrenDirectoriesArePresent';
export interface SetFavoriteArgs { id: number, favorite: boolean }
export interface SetFavoriteArgs {
id: number;
favorite: boolean;
}
export interface SetNoteArgs { id: number, note: string | null }
export interface SetNoteArgs {
id: number;
note: string | null;
}
export interface Statistics { id: number, date_captured: string, total_object_count: number, library_db_size: string, total_bytes_used: string, total_bytes_capacity: string, total_unique_bytes: string, total_bytes_free: string, preview_media_bytes: string }
export interface Statistics {
id: number;
date_captured: string;
total_object_count: number;
library_db_size: string;
total_bytes_used: string;
total_bytes_capacity: string;
total_unique_bytes: string;
total_bytes_free: string;
preview_media_bytes: string;
}
export interface Tag { id: number, pub_id: Array<number>, name: string | null, color: string | null, total_objects: number | null, redundancy_goal: number | null, date_created: string, date_modified: string }
export interface Tag {
id: number;
pub_id: Array<number>;
name: string | null;
color: string | null;
total_objects: number | null;
redundancy_goal: number | null;
date_created: string;
date_modified: string;
}
export interface TagAssignArgs { object_id: number, tag_id: number, unassign: boolean }
export interface TagAssignArgs {
object_id: number;
tag_id: number;
unassign: boolean;
}
export interface TagCreateArgs { name: string, color: string }
export interface TagCreateArgs {
name: string;
color: string;
}
export interface TagUpdateArgs { id: number, name: string | null, color: string | null }
export interface TagUpdateArgs {
id: number;
name: string | null;
color: string | null;
}
export interface Volume { name: string, mount_point: string, total_capacity: bigint, available_capacity: bigint, is_removable: boolean, disk_type: string | null, file_system: string | null, is_root_filesystem: boolean }
export interface Volume {
name: string;
mount_point: string;
total_capacity: bigint;
available_capacity: bigint;
is_removable: boolean;
disk_type: string | null;
file_system: string | null;
is_root_filesystem: boolean;
}

View file

@ -1,8 +1,9 @@
import { useCurrentLibrary, useInvalidateQuery } from '@sd/client';
import { Suspense, lazy } from 'react';
import { Navigate, Route, Routes } from 'react-router-dom';
import { AppLayout } from './AppLayout';
import { useKeybindHandler } from './hooks/useKeyboardHandler';
import { useCurrentLibrary, useInvalidateQuery } from '@sd/client';
import { lazy, Suspense } from 'react';
import { Navigate, Route, Routes } from 'react-router-dom';
const DebugScreen = lazy(() => import('./screens/Debug'));
const SettingsScreen = lazy(() => import('./screens/settings/Settings'));

View file

@ -1,5 +1,3 @@
import { Folder } from '../icons/Folder';
import { isObject, isPath } from './utils';
import videoSvg from '@sd/assets/svgs/video.svg';
import zipSvg from '@sd/assets/svgs/zip.svg';
import { getExplorerStore, usePlatform } from '@sd/client';
@ -10,6 +8,9 @@ import { useState } from 'react';
import { Suspense, lazy, useMemo } from 'react';
import { useSnapshot } from 'valtio';
import { Folder } from '../icons/Folder';
import { isObject, isPath } from './utils';
interface Props {
data: ExplorerItem;
size: number;

View file

@ -1,11 +1,4 @@
// import types from '../../constants/file-types.json';
import { Tooltip } from '../tooltip/Tooltip';
import FileThumb from './FileThumb';
import { Divider } from './inspector/Divider';
import FavoriteButton from './inspector/FavoriteButton';
import { MetaItem } from './inspector/MetaItem';
import Note from './inspector/Note';
import { isObject } from './utils';
import { ShareIcon } from '@heroicons/react/24/solid';
import { useLibraryQuery } from '@sd/client';
import { ExplorerContext, ExplorerItem } from '@sd/client';
@ -16,6 +9,14 @@ import dayjs from 'dayjs';
import { Link } from 'phosphor-react';
import { useEffect, useState } from 'react';
import { Tooltip } from '../tooltip/Tooltip';
import FileThumb from './FileThumb';
import { Divider } from './inspector/Divider';
import FavoriteButton from './inspector/FavoriteButton';
import { MetaItem } from './inspector/MetaItem';
import Note from './inspector/Note';
import { isObject } from './utils';
interface Props {
context?: ExplorerContext;
data?: ExplorerItem;

View file

@ -1,6 +1,3 @@
import FileItem from './FileItem';
import FileRow from './FileRow';
import { isPath } from './utils';
import { ExplorerLayoutMode, getExplorerStore, useExplorerStore } from '@sd/client';
import { ExplorerContext, ExplorerItem } from '@sd/client';
import { useVirtualizer } from '@tanstack/react-virtual';
@ -8,6 +5,10 @@ import { memo, useCallback, useEffect, useLayoutEffect, useRef, useState } from
import { useSearchParams } from 'react-router-dom';
import { useKey, useOnWindowResize } from 'rooks';
import FileItem from './FileItem';
import FileRow from './FileRow';
import { isPath } from './utils';
const TOP_BAR_HEIGHT = 50;
const GRID_TEXT_AREA_HEIGHT = 25;

View file

@ -2,9 +2,7 @@
"$schema": "https://turborepo.org/schema.json",
"pipeline": {
"build": {
"outputs": [
"dist/**"
]
"outputs": ["dist/**"]
},
"lint": {
"outputs": []