mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-02 10:03:28 +00:00
merge duplicate prettier config and format repo with it
This commit is contained in:
parent
fe4da9048a
commit
aacdf33216
2
.prettierignore
Normal file
2
.prettierignore
Normal file
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
.build
|
|
@ -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']
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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).
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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/*'));
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ html {
|
|||
&.bloom-one {
|
||||
@apply left-0 -ml-[300px];
|
||||
background: url('/bloom-one.png') no-repeat center center;
|
||||
background-size: contain;
|
||||
background-size: contain;
|
||||
animation-delay: 300ms;
|
||||
}
|
||||
&.bloom-two {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "expo"
|
||||
}
|
||||
"info": {
|
||||
"version": 1,
|
||||
"author": "expo"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
{
|
||||
"extends": "../../packages/config/interface.tsconfig.json",
|
||||
"compilerOptions": {},
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
"extends": "../../packages/config/interface.tsconfig.json",
|
||||
"compilerOptions": {},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# FFMPEG Thumbnailer RS
|
||||
|
||||
Rust implementation of a thumbnail generation for video files using ffmpeg.
|
||||
Rust implementation of a thumbnail generation for video files using ffmpeg.
|
||||
Based on https://github.com/dirkvdb/ffmpegthumbnailer
|
||||
|
||||
For now only implements the minimum API for Spacedrive needs. PRs are welcome
|
||||
|
@ -32,8 +32,8 @@ async fn main() -> Result<(), ThumbnailerError> {
|
|||
.with_film_strip(false)
|
||||
.quality(80.0)?
|
||||
.build();
|
||||
|
||||
|
||||
thumbnailer.process("input.mp4", "output.webp").await
|
||||
}
|
||||
|
||||
```
|
||||
```
|
||||
|
|
|
@ -6,4 +6,4 @@ This is the P2P library which powers Spacedrive's P2P functionality.
|
|||
|
||||
```bash
|
||||
RUST_LOG="p2p=debug" cargo run -p server
|
||||
```
|
||||
```
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -9,4 +9,4 @@ TODO: Write some docs
|
|||
```bash
|
||||
cargo run -p tunnel --bin generate-env
|
||||
cargo run -p tunnel
|
||||
```
|
||||
```
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# crdt-rs
|
||||
|
||||
Just @brendonovich experimenting with CRDT stuff.
|
||||
|
||||
|
|
|
@ -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());
|
||||
};
|
||||
```
|
||||
|
|
2
crates/sync/example/.vscode/extensions.json
vendored
2
crates/sync/example/.vscode/extensions.json
vendored
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"recommendations": ["tauri-apps.tauri-vscode", "rust-lang.rust-analyzer"]
|
||||
"recommendations": ["tauri-apps.tauri-vscode", "rust-lang.rust-analyzer"]
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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" />;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
@ -67,4 +67,4 @@ This release is missing database synchronization between nodes (your devices), f
|
|||
|
||||
- Update installer.
|
||||
|
||||
- Optional crash reporting.
|
||||
- Optional crash reporting.
|
||||
|
|
|
@ -74,4 +74,4 @@ limit any of our or your liabilities in any way that is not permitted under appl
|
|||
exclude any of our or your liabilities that may not be excluded under applicable law.
|
||||
The limitations and prohibitions of liability set in this Section and elsewhere in this disclaimer: (a) are subject to the preceding paragraph; and (b) govern all liabilities arising under the disclaimer, including liabilities arising in contract, in tort, and for breach of statutory duty.
|
||||
|
||||
As long as the website and the information and services on the website are provided free of charge, we will not be liable for any loss or damage of any nature.
|
||||
As long as the website and the information and services on the website are provided free of charge, we will not be liable for any loss or damage of any nature.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
index: 10
|
||||
---
|
||||
# Albums
|
||||
|
||||
you can put photos here
|
||||
# Albums
|
||||
|
||||
you can put photos here
|
||||
|
|
|
@ -4,4 +4,4 @@ index: 4
|
|||
|
||||
# Database
|
||||
|
||||
prisma client rust, sqlite, migrations, backup
|
||||
prisma client rust, sqlite, migrations, backup
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
index: 10
|
||||
---
|
||||
|
||||
|
||||
# Explorer
|
||||
|
||||
using the interface, features
|
||||
using the interface, features
|
||||
|
|
|
@ -4,4 +4,4 @@ index: 10
|
|||
|
||||
# Extensions
|
||||
|
||||
extended functionality of Spacedrive
|
||||
extended functionality of Spacedrive
|
||||
|
|
|
@ -4,4 +4,4 @@ index: 10
|
|||
|
||||
# Jobs
|
||||
|
||||
jobs are computation tasks performed by nodes in a Spacedrive network, they can be created by any node and performed by any or all nodes.
|
||||
jobs are computation tasks performed by nodes in a Spacedrive network, they can be created by any node and performed by any or all nodes.
|
||||
|
|
|
@ -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]()
|
||||
A library is the database that Spacedrive stores all file structures and metadata. It can be synchronized with other [Nodes]()
|
||||
|
|
|
@ -4,4 +4,4 @@ index: 10
|
|||
|
||||
# Locations
|
||||
|
||||
indexing, identifying, watching, .spacedrive folder, online/offline
|
||||
indexing, identifying, watching, .spacedrive folder, online/offline
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -7,8 +7,8 @@ new: true
|
|||
# Objects
|
||||
|
||||
Objects are files discovered on your devices and drives, but can also be virtual, existing only within Spacedrive.
|
||||
|
||||
All metadata associated with files in Spacedrive is linked to the Object for that file.
|
||||
|
||||
All metadata associated with files in Spacedrive is linked to the Object for that file.
|
||||
|
||||
If two or more files are discovered that are identical, they are linked to the same Object in Spacedrive.
|
||||
|
||||
|
@ -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 |
|
||||
|
|
|
@ -9,4 +9,4 @@ Spacedrive generates compressed preview media for images, videos and text files.
|
|||
|
||||
Preview media is stored in the Node's data folder in a single directory. Images are stored as WEBP format with their CAS id as the name.
|
||||
|
||||
ffmpeg, syncing, security
|
||||
ffmpeg, syncing, security
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
index: 11
|
||||
---
|
||||
|
||||
|
||||
# Search
|
||||
|
||||
Press CTRL+F while on a Spacedrive window to access search.
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
---
|
||||
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.
|
||||
|
||||
Objects can be added to a Space manually, or by matching a defined ruleset, similar to Tags.
|
||||
|
||||
Spacedrive comes with pre-defined Spaces, such as: photos, videos, screenshots, documents, .
|
||||
Spacedrive comes with pre-defined Spaces, such as: photos, videos, screenshots, documents, .
|
||||
|
|
|
@ -6,4 +6,4 @@ index: 13
|
|||
|
||||
Spacedrive heavily incentivize using tags to organize files efficiently by giving them more functionality and easier ways to apply them, individually and in bulk.
|
||||
|
||||
ways to add tags, tag automation
|
||||
ways to add tags, tag automation
|
||||
|
|
|
@ -3,4 +3,3 @@ index: 10
|
|||
---
|
||||
|
||||
# Virtual Filesystem
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
---
|
||||
index: 10
|
||||
---
|
||||
---
|
||||
|
|
|
@ -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();
|
||||
```
|
||||
```
|
||||
|
|
|
@ -6,37 +6,42 @@ index: 1
|
|||
|
||||
To get started contributing to Spacedrive, follow this guide carefully.
|
||||
|
||||
This project uses [Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) and [pnpm](https://pnpm.io/installation).
|
||||
This project uses [Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) and [pnpm](https://pnpm.io/installation).
|
||||
|
||||
## Installation
|
||||
## 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
|
||||
```
|
||||
|
||||
## Running apps
|
||||
```shell
|
||||
pnpm prep
|
||||
```
|
||||
|
||||
## Running apps
|
||||
|
||||
- **Desktop:** `pnpm desktop dev`
|
||||
- **Landing:** `pnpm landing dev`
|
||||
|
@ -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
|
||||
|
@ -65,4 +70,4 @@ To run mobile app
|
|||
If you are having issues ensure you are using the following versions of Rust and Node:
|
||||
|
||||
- Rust version: **1.64.0**
|
||||
- Node version: **17**
|
||||
- Node version: **17**
|
||||
|
|
|
@ -6,4 +6,4 @@ index: 0
|
|||
|
||||
```rust
|
||||
pub struct DeveloperDocumentation;
|
||||
```
|
||||
```
|
||||
|
|
|
@ -3,4 +3,4 @@ name: Open Source
|
|||
index: 10
|
||||
---
|
||||
|
||||
# Open Source
|
||||
# Open Source
|
||||
|
|
|
@ -3,4 +3,4 @@ name: Tech Stack
|
|||
index: 10
|
||||
---
|
||||
|
||||
# Tech Stack
|
||||
# Tech Stack
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
# Features
|
||||
# Features
|
||||
|
|
|
@ -7,7 +7,7 @@ index: 0
|
|||
|
||||
Spacedrive is a cross-platform file manager. It connects your devices together to help you organize files from anywhere.
|
||||
|
||||
Beyond being an opinionated, swiss army knife file explorer, Spacedrive is a personal database. It identifies your files uniquely, understanding more file types than any operating system.
|
||||
Beyond being an opinionated, swiss army knife file explorer, Spacedrive is a personal database. It identifies your files uniquely, understanding more file types than any operating system.
|
||||
|
||||
Create photo albums that you'll never loose, effortlessly catalogue terabytes of video, move files between devices dynamically to optimize space and redundancy, generate preview media for easy viewing, automate security and encryption—the list goes on.
|
||||
|
||||
|
|
|
@ -7,4 +7,4 @@ index: 0
|
|||
|
||||
::: slot note Note
|
||||
Spacedrive is not yet released, these docs are a work in progress. Check out our [roadmap](/roadmap) to see a timeline leading to release!
|
||||
:::
|
||||
:::
|
||||
|
|
|
@ -4,4 +4,3 @@ index: 0
|
|||
---
|
||||
|
||||
# Terminology
|
||||
|
||||
|
|
|
@ -11,15 +11,16 @@ 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.
|
||||
2. The [Identifier](): metadata is extracted and unique identifiers generated.
|
||||
3. The [Thumbnailer](): compressed previews are generated for all media and text files.
|
||||
|
||||
If any one of these jobs fail or the application is closed, the state is saved and it will resume when the app is relaunched.
|
||||
If any one of these jobs fail or the application is closed, the state is saved and it will resume when the app is relaunched.
|
||||
|
||||
::: slot info
|
||||
::: slot info
|
||||
If you wish to pause or cancel these jobs you can do so from the [Job Manager]()
|
||||
:::
|
||||
|
||||
|
@ -28,7 +29,8 @@ 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
|
||||
|
||||
::: slot warning
|
||||
This feature is WIP
|
||||
:::
|
||||
Locations can be archived, meaning the directory structure is extracted from the Spacedrive database and preserved as a standalone database file. This file can be opened by Spacedrive in the [Database]() view.
|
||||
|
@ -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
|
||||
|
||||
Allocate a portion of this location to be encrypted
|
||||
|
|
|
@ -4,11 +4,10 @@ index: 6
|
|||
|
||||
# Connecting Nodes
|
||||
|
||||
::: slot note WIP
|
||||
::: slot note WIP
|
||||
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.
|
||||
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.
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
index: 11
|
||||
---
|
||||
|
||||
# Converting Files
|
||||
# Converting Files
|
||||
|
|
|
@ -4,4 +4,4 @@ index: 7
|
|||
|
||||
# Creating Spaces
|
||||
|
||||
Spaces are virtual folders, they can contain files from various locations.
|
||||
Spaces are virtual folders, they can contain files from various locations.
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
index: 9
|
||||
---
|
||||
|
||||
# Discover Duplicates
|
||||
# Discover Duplicates
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
index: 10
|
||||
---
|
||||
|
||||
# File Viewer
|
||||
# File Viewer
|
||||
|
|
|
@ -4,4 +4,4 @@ index: 7
|
|||
|
||||
# Generate Thumbnails
|
||||
|
||||
![image](/thumbnails.webp)
|
||||
![image](/thumbnails.webp)
|
||||
|
|
|
@ -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,
|
||||
|
||||
A Library can be deleted,
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
index: 8
|
||||
---
|
||||
|
||||
# Managing Jobs
|
||||
# Managing Jobs
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
---
|
||||
index: 9
|
||||
---
|
||||
---
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
index: 12
|
||||
---
|
||||
|
||||
# Photo Albums
|
||||
# Photo Albums
|
||||
|
|
|
@ -1 +1 @@
|
|||
# Privacy
|
||||
# Privacy
|
||||
|
|
|
@ -1 +1 @@
|
|||
# Security
|
||||
# Security
|
||||
|
|
|
@ -11,4 +11,4 @@ pre-push:
|
|||
run: pnpm eslint {staged_files}
|
||||
markdown-link-check:
|
||||
glob: '*.md'
|
||||
run: pnpm markdown-link-check {staged_files}
|
||||
run: pnpm markdown-link-check {staged_files}
|
||||
|
|
|
@ -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 -- ",
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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'));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
26
turbo.json
26
turbo.json
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue