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

@ -7,35 +7,35 @@ const ghostURL = import.meta.env.VITE_API_URL;
export const blogEnabled = !!(ghostURL && ghostKey);
export const api = blogEnabled
? new GhostContentAPI({
url: ghostURL,
key: ghostKey,
version: 'v5.0'
})
: null;
? new GhostContentAPI({
url: ghostURL,
key: ghostKey,
version: 'v5.0'
})
: null;
export async function getPosts() {
if (!api) {
return [];
}
const posts = await api.posts
.browse({
include: ['tags', 'authors']
})
.catch(() => []);
return posts;
if (!api) {
return [];
}
const posts = await api.posts
.browse({
include: ['tags', 'authors']
})
.catch(() => []);
return posts;
}
export async function getPost(slug: string) {
if (!api) {
return null;
}
return await api.posts
.read(
{ slug },
{
include: ['tags', 'authors']
}
)
.catch(() => null);
if (!api) {
return null;
}
return await api.posts
.read(
{ slug },
{
include: ['tags', 'authors']
}
)
.catch(() => null);
}

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,122 +1,122 @@
{
"images": [
{
"idiom": "iphone",
"size": "20x20",
"scale": "2x",
"filename": "App-Icon-20x20@2x.png"
},
{
"idiom": "iphone",
"size": "20x20",
"scale": "3x",
"filename": "App-Icon-20x20@3x.png"
},
{
"idiom": "iphone",
"size": "29x29",
"scale": "1x",
"filename": "App-Icon-29x29@1x.png"
},
{
"idiom": "iphone",
"size": "29x29",
"scale": "2x",
"filename": "App-Icon-29x29@2x.png"
},
{
"idiom": "iphone",
"size": "29x29",
"scale": "3x",
"filename": "App-Icon-29x29@3x.png"
},
{
"idiom": "iphone",
"size": "40x40",
"scale": "2x",
"filename": "App-Icon-40x40@2x.png"
},
{
"idiom": "iphone",
"size": "40x40",
"scale": "3x",
"filename": "App-Icon-40x40@3x.png"
},
{
"idiom": "iphone",
"size": "60x60",
"scale": "2x",
"filename": "App-Icon-60x60@2x.png"
},
{
"idiom": "iphone",
"size": "60x60",
"scale": "3x",
"filename": "App-Icon-60x60@3x.png"
},
{
"idiom": "ipad",
"size": "20x20",
"scale": "1x",
"filename": "App-Icon-20x20@1x.png"
},
{
"idiom": "ipad",
"size": "20x20",
"scale": "2x",
"filename": "App-Icon-20x20@2x.png"
},
{
"idiom": "ipad",
"size": "29x29",
"scale": "1x",
"filename": "App-Icon-29x29@1x.png"
},
{
"idiom": "ipad",
"size": "29x29",
"scale": "2x",
"filename": "App-Icon-29x29@2x.png"
},
{
"idiom": "ipad",
"size": "40x40",
"scale": "1x",
"filename": "App-Icon-40x40@1x.png"
},
{
"idiom": "ipad",
"size": "40x40",
"scale": "2x",
"filename": "App-Icon-40x40@2x.png"
},
{
"idiom": "ipad",
"size": "76x76",
"scale": "1x",
"filename": "App-Icon-76x76@1x.png"
},
{
"idiom": "ipad",
"size": "76x76",
"scale": "2x",
"filename": "App-Icon-76x76@2x.png"
},
{
"idiom": "ipad",
"size": "83.5x83.5",
"scale": "2x",
"filename": "App-Icon-83.5x83.5@2x.png"
},
{
"idiom": "ios-marketing",
"size": "1024x1024",
"scale": "1x",
"filename": "ItunesArtwork@2x.png"
}
],
"info": {
"version": 1,
"author": "expo"
}
"images": [
{
"idiom": "iphone",
"size": "20x20",
"scale": "2x",
"filename": "App-Icon-20x20@2x.png"
},
{
"idiom": "iphone",
"size": "20x20",
"scale": "3x",
"filename": "App-Icon-20x20@3x.png"
},
{
"idiom": "iphone",
"size": "29x29",
"scale": "1x",
"filename": "App-Icon-29x29@1x.png"
},
{
"idiom": "iphone",
"size": "29x29",
"scale": "2x",
"filename": "App-Icon-29x29@2x.png"
},
{
"idiom": "iphone",
"size": "29x29",
"scale": "3x",
"filename": "App-Icon-29x29@3x.png"
},
{
"idiom": "iphone",
"size": "40x40",
"scale": "2x",
"filename": "App-Icon-40x40@2x.png"
},
{
"idiom": "iphone",
"size": "40x40",
"scale": "3x",
"filename": "App-Icon-40x40@3x.png"
},
{
"idiom": "iphone",
"size": "60x60",
"scale": "2x",
"filename": "App-Icon-60x60@2x.png"
},
{
"idiom": "iphone",
"size": "60x60",
"scale": "3x",
"filename": "App-Icon-60x60@3x.png"
},
{
"idiom": "ipad",
"size": "20x20",
"scale": "1x",
"filename": "App-Icon-20x20@1x.png"
},
{
"idiom": "ipad",
"size": "20x20",
"scale": "2x",
"filename": "App-Icon-20x20@2x.png"
},
{
"idiom": "ipad",
"size": "29x29",
"scale": "1x",
"filename": "App-Icon-29x29@1x.png"
},
{
"idiom": "ipad",
"size": "29x29",
"scale": "2x",
"filename": "App-Icon-29x29@2x.png"
},
{
"idiom": "ipad",
"size": "40x40",
"scale": "1x",
"filename": "App-Icon-40x40@1x.png"
},
{
"idiom": "ipad",
"size": "40x40",
"scale": "2x",
"filename": "App-Icon-40x40@2x.png"
},
{
"idiom": "ipad",
"size": "76x76",
"scale": "1x",
"filename": "App-Icon-76x76@1x.png"
},
{
"idiom": "ipad",
"size": "76x76",
"scale": "2x",
"filename": "App-Icon-76x76@2x.png"
},
{
"idiom": "ipad",
"size": "83.5x83.5",
"scale": "2x",
"filename": "App-Icon-83.5x83.5@2x.png"
},
{
"idiom": "ios-marketing",
"size": "1024x1024",
"scale": "1x",
"filename": "ItunesArtwork@2x.png"
}
],
"info": {
"version": 1,
"author": "expo"
}
}

View file

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

View file

@ -1,21 +1,21 @@
{
"images": [
{
"idiom": "universal",
"filename": "image.png",
"scale": "1x"
},
{
"idiom": "universal",
"scale": "2x"
},
{
"idiom": "universal",
"scale": "3x"
}
],
"info": {
"version": 1,
"author": "expo"
}
"images": [
{
"idiom": "universal",
"filename": "image.png",
"scale": "1x"
},
{
"idiom": "universal",
"scale": "2x"
},
{
"idiom": "universal",
"scale": "3x"
}
],
"info": {
"version": 1,
"author": "expo"
}
}

View file

@ -1,21 +1,21 @@
{
"images": [
{
"idiom": "universal",
"filename": "image.png",
"scale": "1x"
},
{
"idiom": "universal",
"scale": "2x"
},
{
"idiom": "universal",
"scale": "3x"
}
],
"info": {
"version": 1,
"author": "expo"
}
"images": [
{
"idiom": "universal",
"filename": "image.png",
"scale": "1x"
},
{
"idiom": "universal",
"scale": "2x"
},
{
"idiom": "universal",
"scale": "3x"
}
],
"info": {
"version": 1,
"author": "expo"
}
}

View file

@ -2,111 +2,358 @@
// This file was generated by [rspc](https://github.com/oscartbeaumont/rspc). Do not edit this file manually.
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> },
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 },
subscriptions:
{ key: "invalidateQuery", input: never, result: InvalidateOperationEvent } |
{ key: "jobs.newThumbnail", input: LibraryArgs<null>, result: string }
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> };
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 };
subscriptions:
| { 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>
<meta charset="utf-8" />
<title>Spacedrive</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<head>
<meta charset="utf-8" />
<title>Spacedrive</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<div id="root"></div>
<script type="module" src="./index.tsx"></script>
</body>
<body>
<div id="root"></div>
<script type="module" src="./index.tsx"></script>
</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"
]
"extends": "../../packages/config/interface.tsconfig.json",
"compilerOptions": {},
"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,49 +29,45 @@ pub fn update_with_timestamp(&self, timestamp: &Timestamp) -> Result<(), String>
```
```javascript
Timestamp.recv = function(msg) {
if (!clock) {
return null;
}
Timestamp.recv = function (msg) {
if (!clock) {
return null;
}
var now = Date.now();
var now = Date.now();
var msg_time = msg.millis();
var msg_time = msg.counter();
var msg_time = msg.millis();
var msg_time = msg.counter();
if (msg_time - now > config.maxDrift) {
throw new Timestamp.ClockDriftError();
}
if (msg_time - now > config.maxDrift) {
throw new Timestamp.ClockDriftError();
}
var last_time = clock.timestamp.millis();
var last_time = clock.timestamp.counter();
var last_time = clock.timestamp.millis();
var last_time = clock.timestamp.counter();
var max_time = Math.max(Math.max(last_time, now), msg_time);
var max_time = Math.max(Math.max(last_time, now), msg_time);
var last_time =
max_time === last_time && lNew === msg_time
? Math.max(last_time, msg_time) + 1
: max_time === last_time
? last_time + 1
: max_time === msg_time
? msg_time + 1
: 0;
var last_time =
max_time === last_time && lNew === msg_time
? Math.max(last_time, msg_time) + 1
: max_time === last_time
? last_time + 1
: max_time === msg_time
? msg_time + 1
: 0;
// 3.
if (max_time - phys > config.maxDrift) {
throw new Timestamp.ClockDriftError();
}
if (last_time > MAX_COUNTER) {
throw new Timestamp.OverflowError();
}
// 3.
if (max_time - phys > config.maxDrift) {
throw new Timestamp.ClockDriftError();
}
if (last_time > MAX_COUNTER) {
throw new Timestamp.OverflowError();
}
clock.timestamp.setMillis(max_time);
clock.timestamp.setCounter(last_time);
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,3 +1,3 @@
{
"recommendations": ["tauri-apps.tauri-vscode", "rust-lang.rust-analyzer"]
"recommendations": ["tauri-apps.tauri-vscode", "rust-lang.rust-analyzer"]
}

View file

@ -1,17 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link rel="icon" type="image/svg+xml" href="/src/assets/logo.svg" />
<title>Tauri + Solid + Typescript App</title>
</head>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link rel="icon" type="image/svg+xml" href="/src/assets/logo.svg" />
<title>Tauri + Solid + Typescript App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script src="/src/index.tsx" type="module"></script>
</body>
<script src="/src/index.tsx" type="module"></script>
</body>
</html>

View file

@ -1,32 +1,32 @@
{
"name": "@sd/sync-example",
"version": "0.0.0",
"description": "",
"scripts": {
"start": "vite",
"dev": "vite",
"build": "vite build",
"serve": "vite preview",
"tauri": "tauri"
},
"license": "MIT",
"devDependencies": {
"@tauri-apps/cli": "^1.1.1",
"@types/babel__core": "^7.1.19",
"@types/node": "^18.8.2",
"autoprefixer": "^10.4.12",
"postcss": "^8.4.17",
"tailwindcss": "^3.1.8",
"typescript": "^4.8.4",
"vite": "^3.1.4",
"vite-plugin-solid": "^2.3.9"
},
"dependencies": {
"@rspc/client": "~0.1.2",
"@rspc/solid": "~0.1.2",
"@rspc/tauri": "~0.1.2",
"@tanstack/solid-query": "4.10.1",
"clsx": "^1.2.1",
"solid-js": "^1.5.7"
}
"name": "@sd/sync-example",
"version": "0.0.0",
"description": "",
"scripts": {
"start": "vite",
"dev": "vite",
"build": "vite build",
"serve": "vite preview",
"tauri": "tauri"
},
"license": "MIT",
"devDependencies": {
"@tauri-apps/cli": "^1.1.1",
"@types/babel__core": "^7.1.19",
"@types/node": "^18.8.2",
"autoprefixer": "^10.4.12",
"postcss": "^8.4.17",
"tailwindcss": "^3.1.8",
"typescript": "^4.8.4",
"vite": "^3.1.4",
"vite-plugin-solid": "^2.3.9"
},
"dependencies": {
"@rspc/client": "~0.1.2",
"@rspc/solid": "~0.1.2",
"@rspc/tauri": "~0.1.2",
"@tanstack/solid-query": "4.10.1",
"clsx": "^1.2.1",
"solid-js": "^1.5.7"
}
}

View file

@ -1,66 +1,66 @@
{
"build": {
"beforeDevCommand": "pnpm dev",
"beforeBuildCommand": "pnpm build",
"devPath": "http://localhost:1420",
"distDir": "../dist",
"withGlobalTauri": false
},
"package": {
"productName": "example",
"version": "0.0.0"
},
"tauri": {
"allowlist": {
"all": true
},
"bundle": {
"active": true,
"category": "DeveloperTool",
"copyright": "",
"deb": {
"depends": []
},
"externalBin": [],
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
],
"identifier": "com.tauri.dev",
"longDescription": "",
"macOS": {
"entitlements": null,
"exceptionDomain": "",
"frameworks": [],
"providerShortName": null,
"signingIdentity": null
},
"resources": [],
"shortDescription": "",
"targets": "all",
"windows": {
"certificateThumbprint": null,
"digestAlgorithm": "sha256",
"timestampUrl": ""
}
},
"security": {
"csp": null
},
"updater": {
"active": false
},
"windows": [
{
"fullscreen": false,
"height": 600,
"resizable": true,
"title": "example",
"width": 800
}
]
}
"build": {
"beforeDevCommand": "pnpm dev",
"beforeBuildCommand": "pnpm build",
"devPath": "http://localhost:1420",
"distDir": "../dist",
"withGlobalTauri": false
},
"package": {
"productName": "example",
"version": "0.0.0"
},
"tauri": {
"allowlist": {
"all": true
},
"bundle": {
"active": true,
"category": "DeveloperTool",
"copyright": "",
"deb": {
"depends": []
},
"externalBin": [],
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
],
"identifier": "com.tauri.dev",
"longDescription": "",
"macOS": {
"entitlements": null,
"exceptionDomain": "",
"frameworks": [],
"providerShortName": null,
"signingIdentity": null
},
"resources": [],
"shortDescription": "",
"targets": "all",
"windows": {
"certificateThumbprint": null,
"digestAlgorithm": "sha256",
"timestampUrl": ""
}
},
"security": {
"csp": null
},
"updater": {
"active": false
},
"windows": [
{
"fullscreen": false,
"height": 600,
"resizable": true,
"title": "example",
"width": 800
}
]
}
}

View file

@ -1,75 +1,69 @@
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", {
onSuccess: () => {
queryClient.invalidateQueries();
},
});
const removeDbs = rspc.createMutation("removeDatabases", {
onSuccess: () => queryClient.invalidateQueries(),
});
const createDb = rspc.createMutation('createDatabase', {
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>
</div>
<ul class="gap-2 flex flex-row flex-wrap">
<For each={dbs.data}>
{(id) => (
<Suspense fallback={null}>
<DatabaseView id={id} />
</Suspense>
)}
</For>
</ul>
</div>
);
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>
</div>
<ul class="gap-2 flex flex-row flex-wrap">
<For each={dbs.data}>
{(id) => (
<Suspense fallback={null}>
<DatabaseView id={id} />
</Suspense>
)}
</For>
</ul>
</div>
);
}
interface DatabaseViewProps {
id: string;
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">
<h1 class="p-2 text-xl font-medium">{props.id}</h1>
<div>
<nav class="space-x-2">
<For each={TABS}>
{(tab) => (
<button
class={clsx(
"px-2 py-1",
tab === currentTab() && "bg-indigo-400"
)}
onClick={() => setCurrentTab(tab)}
>
{tab}
</button>
)}
</For>
</nav>
<div></div>
</div>
</div>
);
return (
<div class="bg-indigo-300 rounded-md min-w-[40rem] flex-1 overflow-hidden">
<h1 class="p-2 text-xl font-medium">{props.id}</h1>
<div>
<nav class="space-x-2">
<For each={TABS}>
{(tab) => (
<button
class={clsx('px-2 py-1', tab === currentTab() && 'bg-indigo-400')}
onClick={() => setCurrentTab(tab)}
>
{tab}
</button>
)}
</For>
</nav>
<div></div>
</div>
</div>
);
}
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

@ -1,15 +1,22 @@
// This file was generated by [rspc](https://github.com/oscartbeaumont/rspc). Do not edit this file manually.
export type Procedures = {
queries:
{ 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
queries:
| { 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;
};
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,17 +1,17 @@
/* @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(
() => (
<rspc.Provider client={rspcClient} queryClient={queryClient}>
<Suspense fallback={null}>
<App />
</Suspense>
</rspc.Provider>
),
document.getElementById("root") as HTMLElement
() => (
<rspc.Provider client={rspcClient} queryClient={queryClient}>
<Suspense fallback={null}>
<App />
</Suspense>
</rspc.Provider>
),
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(),
// Refer to the integration your using for the correct transport.
transport: new TauriTransport()
});
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
suspense: true,
},
},
defaultOptions: {
queries: {
suspense: true
}
}
});
export const rspc = createSolidQueryHooks<Procedures>();

View file

@ -1,15 +1,15 @@
{
"compilerOptions": {
"strict": true,
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"jsx": "preserve",
"jsxImportSource": "solid-js",
"types": ["vite/client"],
"noEmit": true,
"isolatedModules": true
}
"compilerOptions": {
"strict": true,
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"jsx": "preserve",
"jsxImportSource": "solid-js",
"types": ["vite/client"],
"noEmit": true,
"isolatedModules": true
}
}

View file

@ -1,25 +1,25 @@
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()],
// Vite optons tailored for Tauri development and only applied in `tauri dev` or `tauri build`
// prevent vite from obscuring rust errors
clearScreen: false,
// tauri expects a fixed port, fail if that port is not available
server: {
port: 1420,
strictPort: true,
},
// to make use of `TAURI_DEBUG` and other env variables
// https://tauri.studio/v1/api/config#buildconfig.beforedevcommand
envPrefix: ["VITE_", "TAURI_"],
build: {
// Tauri supports es2021
target: ["es2021", "chrome100", "safari13"],
// don't minify for debug builds
minify: !process.env.TAURI_DEBUG ? "esbuild" : false,
// produce sourcemaps for debug builds
sourcemap: !!process.env.TAURI_DEBUG,
},
plugins: [solidPlugin()],
// Vite optons tailored for Tauri development and only applied in `tauri dev` or `tauri build`
// prevent vite from obscuring rust errors
clearScreen: false,
// tauri expects a fixed port, fail if that port is not available
server: {
port: 1420,
strictPort: true
},
// to make use of `TAURI_DEBUG` and other env variables
// https://tauri.studio/v1/api/config#buildconfig.beforedevcommand
envPrefix: ['VITE_', 'TAURI_'],
build: {
// Tauri supports es2021
target: ['es2021', 'chrome100', 'safari13'],
// don't minify for debug builds
minify: !process.env.TAURI_DEBUG ? 'esbuild' : false,
// produce sourcemaps for debug builds
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

@ -18,26 +18,26 @@ 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 |
| Text File | A file that contains human-readable text | 3 |
| Package | A folder that opens an application | 4 |
| Image | An image file | 5 |
| Audio | An audio file | 6 |
| Video | A video file | 7 |
| Archive | A compressed archive of data | 8 |
| Executable | An executable program or application | 9 |
| Alias | A link to another Object | 10 |
| Encrypted Bytes | Raw bytes with self contained metadata | 11 |
| Link | A link to a web page, application or Space | 12 |
| Web Page Archive | A snapshot of a webpage, with HTML, JS, images and screenshot | 13 |
| Widget | A widget is a mini app that can be placed in a Space at various sizes, associated Widget struct required | 14 |
| Album | Albums can only have one level of children, and are associated with the Album struct | 15 |
| 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 |
| Text File | A file that contains human-readable text | 3 |
| Package | A folder that opens an application | 4 |
| Image | An image file | 5 |
| Audio | An audio file | 6 |
| Video | A video file | 7 |
| Archive | A compressed archive of data | 8 |
| Executable | An executable program or application | 9 |
| Alias | A link to another Object | 10 |
| Encrypted Bytes | Raw bytes with self contained metadata | 11 |
| Link | A link to a web page, application or Space | 12 |
| Web Page Archive | A snapshot of a webpage, with HTML, JS, images and screenshot | 13 |
| Widget | A widget is a mini app that can be placed in a Space at various sizes, associated Widget struct required | 14 |
| Album | Albums can only have one level of children, and are associated with the Album struct | 15 |
| Collection | Its like a folder, but appears like a stack of files, designed for burst photos/associated groups of files | 16 |
| Database | A database file | 17 |
| Mesh | A 3D mesh object | 18 |
| Textured Mesh | A 3D mesh object with textures | 19 |
| Entity | A rigged character | 20 |
| Database | A database file | 17 |
| Mesh | A 3D mesh object | 18 |
| Textured Mesh | A 3D mesh object with textures | 19 |
| Entity | A rigged character | 20 |

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

@ -11,30 +11,35 @@ This project uses [Cargo](https://doc.rust-lang.org/cargo/getting-started/instal
## Installation
1. **Clone repo**
```shell
git clone https://github.com/spacedriveapp/spacedrive && cd spacedrive
```
```shell
git clone https://github.com/spacedriveapp/spacedrive && cd spacedrive
```
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.
```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._
```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
```
```shell
pnpm i
```
4. **Run codegen & build required dependencies**
```shell
pnpm prep
```
```shell
pnpm prep
```
## Running apps
@ -53,7 +58,7 @@ To run mobile app
1. Install [Android Studio](https://developer.android.com/studio) for Android and [Xcode](https://apps.apple.com/au/app/xcode/id497799835) for IOS development
2. `./.github/scripts/setup-system.sh mobile`
_The should setup most of the dependencies for the mobile app to build._
_The should setup most of the dependencies for the mobile app to build._
3. You must also ensure you have [NDK 24.0.8215888 and CMake](https://developer.android.com/studio/projects/install-ndk#default-version) in Android Studio
4. `cd apps/mobile && pnpm i` - This is a separate workspace, you need to do this!
5. `pnpm android` - runs on Android Emulator

View file

@ -1,5 +1,5 @@
{
"name": "@sd/docs",
"description": "Allows turborepo to detect our markdown files",
"private": true
"name": "@sd/docs",
"description": "Allows turborepo to detect our markdown files",
"private": true
}

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

@ -2,111 +2,358 @@
// This file was generated by [rspc](https://github.com/oscartbeaumont/rspc). Do not edit this file manually.
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> },
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 },
subscriptions:
{ key: "invalidateQuery", input: never, result: InvalidateOperationEvent } |
{ key: "jobs.newThumbnail", input: LibraryArgs<null>, result: string }
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> };
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 };
subscriptions:
| { 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,96 +1,96 @@
{
"name": "@sd/interface",
"version": "1.0.0",
"license": "GPL-3.0-only",
"private": true,
"main": "src/index.ts",
"exports": {
".": "./src/index.ts",
"./types": "./src/types",
"./assets/*": "./src/assets/*",
"./components/*": "./src/components/*"
},
"scripts": {
"icons": "./scripts/generateSvgImports.mjs",
"lint": "eslint src/**/*.{ts,tsx} && tsc --noEmit"
},
"dependencies": {
"@fontsource/inter": "^4.5.13",
"@headlessui/react": "^1.7.3",
"@heroicons/react": "^2.0.12",
"@radix-ui/react-dialog": "^1.0.0",
"@radix-ui/react-dropdown-menu": "^1.0.0",
"@radix-ui/react-icons": "^1.1.1",
"@radix-ui/react-progress": "^1.0.0",
"@radix-ui/react-slider": "^1.0.0",
"@radix-ui/react-tabs": "^1.0.0",
"@radix-ui/react-toast": "^1.0.0",
"@radix-ui/react-tooltip": "^1.0.0",
"@sd/assets": "workspace:*",
"@sd/client": "workspace:*",
"@sd/ui": "workspace:*",
"@tailwindcss/forms": "^0.5.3",
"@tanstack/react-query": "^4.10.1",
"@tanstack/react-query-devtools": "^4.10.1",
"@tanstack/react-virtual": "3.0.0-beta.18",
"@vitejs/plugin-react": "^2.1.0",
"autoprefixer": "^10.4.12",
"byte-size": "^8.1.0",
"clsx": "^1.2.1",
"date-fns": "^2.29.3",
"dayjs": "^1.11.5",
"immer": "^9.0.15",
"jotai": "^1.8.4",
"lodash": "^4.17.21",
"moment": "^2.29.4",
"phosphor-react": "^1.4.1",
"pretty-bytes": "^6.0.0",
"react": "^18.2.0",
"react-colorful": "^5.6.1",
"react-countup": "^6.3.1",
"react-dom": "^18.2.0",
"react-dropzone": "^14.2.2",
"react-error-boundary": "^3.1.4",
"react-hook-form": "^7.36.1",
"react-hotkeys-hook": "^3.4.7",
"react-json-view": "^1.21.3",
"react-loading-icons": "^1.1.0",
"react-loading-skeleton": "^3.1.0",
"react-portal": "^4.2.2",
"react-query": "^3.39.2",
"react-router": "6.4.2",
"react-router-dom": "6.4.2",
"react-scrollbars-custom": "^4.1.1",
"react-spline": "^1.2.1",
"react-transition-group": "^4.4.5",
"react-virtuoso": "^2.19.1",
"rooks": "^5.14.0",
"tailwindcss": "^3.1.8",
"use-count-up": "^3.0.1",
"use-debounce": "^8.0.4",
"valtio": "^1.7.0",
"valtio-persist": "^1.0.2",
"zod": "^3.19.1",
"zustand": "4.1.1"
},
"devDependencies": {
"@sd/config": "workspace:*",
"@types/babel-core": "^6.25.7",
"@types/byte-size": "^8.1.0",
"@types/lodash": "^4.14.186",
"@types/node": "^18.8.2",
"@types/pretty-bytes": "^5.2.0",
"@types/react": "^18.0.21",
"@types/react-dom": "^18.0.6",
"@types/react-router-dom": "^5.3.3",
"@types/react-table": "^7.7.12",
"@types/react-window": "^1.8.5",
"@types/tailwindcss": "^3.1.0",
"@vitejs/plugin-react": "^1.3.1",
"concurrently": "^7.4.0",
"prettier": "^2.7.1",
"typescript": "^4.8.4",
"vite": "^3.1.4",
"vite-plugin-svgr": "^2.2.1"
}
"name": "@sd/interface",
"version": "1.0.0",
"license": "GPL-3.0-only",
"private": true,
"main": "src/index.ts",
"exports": {
".": "./src/index.ts",
"./types": "./src/types",
"./assets/*": "./src/assets/*",
"./components/*": "./src/components/*"
},
"scripts": {
"icons": "./scripts/generateSvgImports.mjs",
"lint": "eslint src/**/*.{ts,tsx} && tsc --noEmit"
},
"dependencies": {
"@fontsource/inter": "^4.5.13",
"@headlessui/react": "^1.7.3",
"@heroicons/react": "^2.0.12",
"@radix-ui/react-dialog": "^1.0.0",
"@radix-ui/react-dropdown-menu": "^1.0.0",
"@radix-ui/react-icons": "^1.1.1",
"@radix-ui/react-progress": "^1.0.0",
"@radix-ui/react-slider": "^1.0.0",
"@radix-ui/react-tabs": "^1.0.0",
"@radix-ui/react-toast": "^1.0.0",
"@radix-ui/react-tooltip": "^1.0.0",
"@sd/assets": "workspace:*",
"@sd/client": "workspace:*",
"@sd/ui": "workspace:*",
"@tailwindcss/forms": "^0.5.3",
"@tanstack/react-query": "^4.10.1",
"@tanstack/react-query-devtools": "^4.10.1",
"@tanstack/react-virtual": "3.0.0-beta.18",
"@vitejs/plugin-react": "^2.1.0",
"autoprefixer": "^10.4.12",
"byte-size": "^8.1.0",
"clsx": "^1.2.1",
"date-fns": "^2.29.3",
"dayjs": "^1.11.5",
"immer": "^9.0.15",
"jotai": "^1.8.4",
"lodash": "^4.17.21",
"moment": "^2.29.4",
"phosphor-react": "^1.4.1",
"pretty-bytes": "^6.0.0",
"react": "^18.2.0",
"react-colorful": "^5.6.1",
"react-countup": "^6.3.1",
"react-dom": "^18.2.0",
"react-dropzone": "^14.2.2",
"react-error-boundary": "^3.1.4",
"react-hook-form": "^7.36.1",
"react-hotkeys-hook": "^3.4.7",
"react-json-view": "^1.21.3",
"react-loading-icons": "^1.1.0",
"react-loading-skeleton": "^3.1.0",
"react-portal": "^4.2.2",
"react-query": "^3.39.2",
"react-router": "6.4.2",
"react-router-dom": "6.4.2",
"react-scrollbars-custom": "^4.1.1",
"react-spline": "^1.2.1",
"react-transition-group": "^4.4.5",
"react-virtuoso": "^2.19.1",
"rooks": "^5.14.0",
"tailwindcss": "^3.1.8",
"use-count-up": "^3.0.1",
"use-debounce": "^8.0.4",
"valtio": "^1.7.0",
"valtio-persist": "^1.0.2",
"zod": "^3.19.1",
"zustand": "4.1.1"
},
"devDependencies": {
"@sd/config": "workspace:*",
"@types/babel-core": "^6.25.7",
"@types/byte-size": "^8.1.0",
"@types/lodash": "^4.14.186",
"@types/node": "^18.8.2",
"@types/pretty-bytes": "^5.2.0",
"@types/react": "^18.0.21",
"@types/react-dom": "^18.0.6",
"@types/react-router-dom": "^5.3.3",
"@types/react-table": "^7.7.12",
"@types/react-window": "^1.8.5",
"@types/tailwindcss": "^3.1.0",
"@vitejs/plugin-react": "^1.3.1",
"concurrently": "^7.4.0",
"prettier": "^2.7.1",
"typescript": "^4.8.4",
"vite": "^3.1.4",
"vite-plugin-svgr": "^2.2.1"
}
}

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

@ -132,22 +132,22 @@ body {
}
.picker {
position: relative;
position: relative;
}
.swatch {
width: 28px;
height: 28px;
border-radius: 8px;
border: 3px solid #fff;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1), inset 0 0 0 1px rgba(0, 0, 0, 0.1);
cursor: pointer;
width: 28px;
height: 28px;
border-radius: 8px;
border: 3px solid #fff;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1), inset 0 0 0 1px rgba(0, 0, 0, 0.1);
cursor: pointer;
}
.popover {
position: absolute;
top: calc(100% + 2px);
left: 0;
border-radius: 9px;
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
position: absolute;
top: calc(100% + 2px);
left: 0;
border-radius: 9px;
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
}

View file

@ -1,16 +1,14 @@
{
"$schema": "https://turborepo.org/schema.json",
"pipeline": {
"build": {
"outputs": [
"dist/**"
]
},
"lint": {
"outputs": []
},
"dev": {
"cache": false
}
}
"$schema": "https://turborepo.org/schema.json",
"pipeline": {
"build": {
"outputs": ["dist/**"]
},
"lint": {
"outputs": []
},
"dev": {
"cache": false
}
}
}