mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-04 11:03:27 +00:00
Format existing code with new conventions
This commit is contained in:
parent
0b7a7c05d1
commit
f5e0666d11
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
@ -43,7 +43,7 @@ body:
|
|||
id: info
|
||||
attributes:
|
||||
label: Platform and versions
|
||||
description: "Please include the output of `pnpm --version && cargo --version && rustc --version` along with information about your Operating System such as version and/or specific distribution if revelant."
|
||||
description: 'Please include the output of `pnpm --version && cargo --version && rustc --version` along with information about your Operating System such as version and/or specific distribution if revelant.'
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
|
|
3
.github/pull_request_template.md
vendored
3
.github/pull_request_template.md
vendored
|
@ -1,10 +1,9 @@
|
|||
<!-- Put any information about this PR up here -->
|
||||
|
||||
|
||||
|
||||
<!-- Which issue does this PR close? -->
|
||||
<!-- If this PR does not have a corresponding issue,
|
||||
make sure one gets created before you create this PR.
|
||||
You can create a bug report or feature request at
|
||||
https://github.com/spacedriveapp/spacedrive/issues/new/choose -->
|
||||
|
||||
Closes #(issue)
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
{
|
||||
"plugins": ["@trivago/prettier-plugin-sort-imports"],
|
||||
"useTabs": true,
|
||||
"printWidth": 100,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"jsxBracketSameLine": false,
|
||||
"bracketSameLine": false,
|
||||
"semi": true,
|
||||
"quoteProps": "consistent",
|
||||
"importOrder": [
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
hard_tabs = true
|
||||
tab_spaces = 4
|
||||
match_block_trailing_comma = true
|
||||
max_width = 90
|
||||
newline_style = "Unix"
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
@ -18,23 +17,23 @@ diverse, inclusive, and healthy community.
|
|||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
- Demonstrating empathy and kindness toward other people
|
||||
- Being respectful of differing opinions, viewpoints, and experiences
|
||||
- Giving and gracefully accepting constructive feedback
|
||||
- Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
- Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
- The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
- Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
- Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
@ -120,14 +119,14 @@ version 2.0, available at
|
|||
[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
|
||||
|
||||
Community Impact Guidelines were inspired by
|
||||
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
||||
[Mozilla's code of conduct enforcement ladder][mozilla coc].
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available
|
||||
[https://www.contributor-covenant.org/faq][faq]. Translations are available
|
||||
at [https://www.contributor-covenant.org/translations][translations].
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
|
||||
[Mozilla CoC]: https://github.com/mozilla/diversity
|
||||
[FAQ]: https://www.contributor-covenant.org/faq
|
||||
[mozilla coc]: https://github.com/mozilla/diversity
|
||||
[faq]: https://www.contributor-covenant.org/faq
|
||||
[translations]: https://www.contributor-covenant.org/translations
|
||||
|
|
|
@ -61,10 +61,11 @@ If you are having issues ensure you are using the following versions of Rust and
|
|||
### Pull Request
|
||||
|
||||
When you're finished with the changes, create a pull request, also known as a PR.
|
||||
|
||||
- Fill the "Ready for review" template so that we can review your PR. This template helps reviewers understand your changes as well as the purpose of your pull request.
|
||||
- Don't forget to [link PR to issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) if you are solving one.
|
||||
- Enable the checkbox to [allow maintainer edits](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/allowing-changes-to-a-pull-request-branch-created-from-a-fork) so the branch can be updated for a merge.
|
||||
Once you submit your PR, a team member will review your proposal. We may ask questions or request for additional information.
|
||||
Once you submit your PR, a team member will review your proposal. We may ask questions or request for additional information.
|
||||
- We may ask for changes to be made before a PR can be merged, either using [suggested changes](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/incorporating-feedback-in-your-pull-request) or pull request comments. You can apply suggested changes directly through the UI. You can make any other changes in your fork, then commit them to your branch.
|
||||
- As you update your PR and apply changes, mark each conversation as [resolved](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request#resolving-conversations).
|
||||
- If you run into any merge issues, checkout this [git tutorial](https://lab.github.com/githubtraining/managing-merge-conflicts) to help you resolve merge conflicts and other issues.
|
||||
|
|
|
@ -38,7 +38,6 @@ Organize files across many devices in one place. From cloud services to offline
|
|||
|
||||
For independent creatives, hoarders and those that want to own their digital footprint. Spacedrive provides a file management experience like no other, and it's completely free.
|
||||
|
||||
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/spacedriveapp/.github/main/profile/app.png" alt="Logo">
|
||||
<br />
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
max_width = 100
|
||||
hard_tabs = false
|
||||
tab_spaces = 2
|
||||
hard_tabs = true
|
||||
newline_style = "Auto"
|
||||
use_small_heuristics = "Default"
|
||||
reorder_imports = true
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
// import Spacedrive interface
|
||||
import SpacedriveInterface, { Platform } from '@sd/interface';
|
||||
import { listen, Event } from '@tauri-apps/api/event';
|
||||
// import types from Spacedrive core (TODO: re-export from client would be cleaner)
|
||||
import { ClientCommand, ClientQuery, CoreEvent } from '@sd/core';
|
||||
// import Spacedrive JS client
|
||||
import { BaseTransport } from '@sd/client';
|
||||
// import types from Spacedrive core (TODO: re-export from client would be cleaner)
|
||||
import { ClientCommand, ClientQuery, CoreEvent } from '@sd/core';
|
||||
// import Spacedrive interface
|
||||
import SpacedriveInterface, { Platform } from '@sd/interface';
|
||||
// import tauri apis
|
||||
import { dialog, invoke, os, shell } from '@tauri-apps/api';
|
||||
import { Event, listen } from '@tauri-apps/api/event';
|
||||
import { convertFileSrc } from '@tauri-apps/api/tauri';
|
||||
import '@sd/ui/style';
|
||||
import { appWindow } from '@tauri-apps/api/window';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import '@sd/ui/style';
|
||||
|
||||
// bind state to core via Tauri
|
||||
class Transport extends BaseTransport {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { defineConfig } from 'vite';
|
||||
import svg from 'vite-plugin-svgr';
|
||||
|
||||
import { name, version } from './package.json';
|
||||
import svg from "vite-plugin-svgr"
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
|
|
|
@ -28,12 +28,12 @@
|
|||
* --syntax-cursor-line: hsla(220, 100%, 80%, 0.04);
|
||||
*/
|
||||
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
code[class*='language-'],
|
||||
pre[class*='language-'] {
|
||||
background: hsl(220, 9%, 6%);
|
||||
color: hsl(220, 14%, 71%);
|
||||
text-shadow: 0 1px rgba(0, 0, 0, 0.3);
|
||||
font-family: "Fira Code", "Fira Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace;
|
||||
font-family: 'Fira Code', 'Fira Mono', Menlo, Consolas, 'DejaVu Sans Mono', monospace;
|
||||
direction: ltr;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
|
@ -47,394 +47,397 @@
|
|||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Selection */
|
||||
code[class*="language-"]::-moz-selection,
|
||||
code[class*="language-"] *::-moz-selection,
|
||||
pre[class*="language-"] *::-moz-selection {
|
||||
/* Selection */
|
||||
code[class*='language-']::-moz-selection,
|
||||
code[class*='language-'] *::-moz-selection,
|
||||
pre[class*='language-'] *::-moz-selection {
|
||||
background: hsl(220, 13%, 28%);
|
||||
color: inherit;
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
code[class*="language-"]::selection,
|
||||
code[class*="language-"] *::selection,
|
||||
pre[class*="language-"] *::selection {
|
||||
code[class*='language-']::selection,
|
||||
code[class*='language-'] *::selection,
|
||||
pre[class*='language-'] *::selection {
|
||||
background: hsl(220, 13%, 28%);
|
||||
color: inherit;
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
pre[class*="language-"] {
|
||||
/* Code blocks */
|
||||
pre[class*='language-'] {
|
||||
padding: 1em;
|
||||
margin: 0.5em 0;
|
||||
overflow: auto;
|
||||
border-radius: 0.3em;
|
||||
}
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
:not(pre) > code[class*="language-"] {
|
||||
/* Inline code */
|
||||
:not(pre) > code[class*='language-'] {
|
||||
padding: 0.2em 0.3em;
|
||||
border-radius: 0.3em;
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print */
|
||||
@media print {
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
/* Print */
|
||||
@media print {
|
||||
code[class*='language-'],
|
||||
pre[class*='language-'] {
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
.token.cdata {
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
.token.cdata {
|
||||
color: hsl(220, 10%, 40%);
|
||||
}
|
||||
}
|
||||
|
||||
.token.doctype,
|
||||
.token.punctuation,
|
||||
.token.entity {
|
||||
.token.doctype,
|
||||
.token.punctuation,
|
||||
.token.entity {
|
||||
color: hsl(220, 14%, 71%);
|
||||
}
|
||||
}
|
||||
|
||||
.token.attr-name,
|
||||
.token.class-name,
|
||||
.token.boolean,
|
||||
.token.constant,
|
||||
.token.number,
|
||||
.token.atrule {
|
||||
.token.attr-name,
|
||||
.token.class-name,
|
||||
.token.boolean,
|
||||
.token.constant,
|
||||
.token.number,
|
||||
.token.atrule {
|
||||
color: hsl(29, 54%, 61%);
|
||||
}
|
||||
}
|
||||
|
||||
.token.keyword {
|
||||
.token.keyword {
|
||||
color: hsl(286, 60%, 67%);
|
||||
}
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.symbol,
|
||||
.token.deleted,
|
||||
.token.important {
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.symbol,
|
||||
.token.deleted,
|
||||
.token.important {
|
||||
color: hsl(355, 65%, 65%);
|
||||
}
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.builtin,
|
||||
.token.inserted,
|
||||
.token.regex,
|
||||
.token.attr-value,
|
||||
.token.attr-value > .token.punctuation {
|
||||
.token.selector,
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.builtin,
|
||||
.token.inserted,
|
||||
.token.regex,
|
||||
.token.attr-value,
|
||||
.token.attr-value > .token.punctuation {
|
||||
color: hsl(95, 38%, 62%);
|
||||
}
|
||||
}
|
||||
|
||||
.token.variable,
|
||||
.token.operator,
|
||||
.token.function {
|
||||
.token.variable,
|
||||
.token.operator,
|
||||
.token.function {
|
||||
color: hsl(207, 82%, 66%);
|
||||
}
|
||||
}
|
||||
|
||||
.token.url {
|
||||
.token.url {
|
||||
color: hsl(187, 47%, 55%);
|
||||
}
|
||||
}
|
||||
|
||||
/* HTML overrides */
|
||||
.token.attr-value > .token.punctuation.attr-equals,
|
||||
.token.special-attr > .token.attr-value > .token.value.css {
|
||||
/* HTML overrides */
|
||||
.token.attr-value > .token.punctuation.attr-equals,
|
||||
.token.special-attr > .token.attr-value > .token.value.css {
|
||||
color: hsl(220, 14%, 71%);
|
||||
}
|
||||
}
|
||||
|
||||
/* CSS overrides */
|
||||
.language-css .token.selector {
|
||||
/* CSS overrides */
|
||||
.language-css .token.selector {
|
||||
color: hsl(355, 65%, 65%);
|
||||
}
|
||||
}
|
||||
|
||||
.language-css .token.property {
|
||||
.language-css .token.property {
|
||||
color: hsl(220, 14%, 71%);
|
||||
}
|
||||
}
|
||||
|
||||
.language-css .token.function,
|
||||
.language-css .token.url > .token.function {
|
||||
.language-css .token.function,
|
||||
.language-css .token.url > .token.function {
|
||||
color: hsl(187, 47%, 55%);
|
||||
}
|
||||
}
|
||||
|
||||
.language-css .token.url > .token.string.url {
|
||||
.language-css .token.url > .token.string.url {
|
||||
color: hsl(95, 38%, 62%);
|
||||
}
|
||||
}
|
||||
|
||||
.language-css .token.important,
|
||||
.language-css .token.atrule .token.rule {
|
||||
.language-css .token.important,
|
||||
.language-css .token.atrule .token.rule {
|
||||
color: hsl(286, 60%, 67%);
|
||||
}
|
||||
}
|
||||
|
||||
/* JS overrides */
|
||||
.language-javascript .token.operator {
|
||||
/* JS overrides */
|
||||
.language-javascript .token.operator {
|
||||
color: hsl(286, 60%, 67%);
|
||||
}
|
||||
}
|
||||
|
||||
.language-javascript .token.template-string > .token.interpolation > .token.interpolation-punctuation.punctuation {
|
||||
.language-javascript
|
||||
.token.template-string
|
||||
> .token.interpolation
|
||||
> .token.interpolation-punctuation.punctuation {
|
||||
color: hsl(5, 48%, 51%);
|
||||
}
|
||||
}
|
||||
|
||||
/* JSON overrides */
|
||||
.language-json .token.operator {
|
||||
/* JSON overrides */
|
||||
.language-json .token.operator {
|
||||
color: hsl(220, 14%, 71%);
|
||||
}
|
||||
}
|
||||
|
||||
.language-json .token.null.keyword {
|
||||
.language-json .token.null.keyword {
|
||||
color: hsl(29, 54%, 61%);
|
||||
}
|
||||
}
|
||||
|
||||
/* MD overrides */
|
||||
.language-markdown .token.url,
|
||||
.language-markdown .token.url > .token.operator,
|
||||
.language-markdown .token.url-reference.url > .token.string {
|
||||
/* MD overrides */
|
||||
.language-markdown .token.url,
|
||||
.language-markdown .token.url > .token.operator,
|
||||
.language-markdown .token.url-reference.url > .token.string {
|
||||
color: hsl(220, 14%, 71%);
|
||||
}
|
||||
}
|
||||
|
||||
.language-markdown .token.url > .token.content {
|
||||
.language-markdown .token.url > .token.content {
|
||||
color: hsl(207, 82%, 66%);
|
||||
}
|
||||
}
|
||||
|
||||
.language-markdown .token.url > .token.url,
|
||||
.language-markdown .token.url-reference.url {
|
||||
.language-markdown .token.url > .token.url,
|
||||
.language-markdown .token.url-reference.url {
|
||||
color: hsl(187, 47%, 55%);
|
||||
}
|
||||
}
|
||||
|
||||
.language-markdown .token.blockquote.punctuation,
|
||||
.language-markdown .token.hr.punctuation {
|
||||
.language-markdown .token.blockquote.punctuation,
|
||||
.language-markdown .token.hr.punctuation {
|
||||
color: hsl(220, 10%, 40%);
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
|
||||
.language-markdown .token.code-snippet {
|
||||
.language-markdown .token.code-snippet {
|
||||
color: hsl(95, 38%, 62%);
|
||||
}
|
||||
}
|
||||
|
||||
.language-markdown .token.bold .token.content {
|
||||
.language-markdown .token.bold .token.content {
|
||||
color: hsl(29, 54%, 61%);
|
||||
}
|
||||
}
|
||||
|
||||
.language-markdown .token.italic .token.content {
|
||||
.language-markdown .token.italic .token.content {
|
||||
color: hsl(286, 60%, 67%);
|
||||
}
|
||||
}
|
||||
|
||||
.language-markdown .token.strike .token.content,
|
||||
.language-markdown .token.strike .token.punctuation,
|
||||
.language-markdown .token.list.punctuation,
|
||||
.language-markdown .token.title.important > .token.punctuation {
|
||||
.language-markdown .token.strike .token.content,
|
||||
.language-markdown .token.strike .token.punctuation,
|
||||
.language-markdown .token.list.punctuation,
|
||||
.language-markdown .token.title.important > .token.punctuation {
|
||||
color: hsl(355, 65%, 65%);
|
||||
}
|
||||
}
|
||||
|
||||
/* General */
|
||||
.token.bold {
|
||||
/* General */
|
||||
.token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.italic {
|
||||
.token.comment,
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
.token.entity {
|
||||
cursor: help;
|
||||
}
|
||||
}
|
||||
|
||||
.token.namespace {
|
||||
.token.namespace {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
/* Plugin overrides */
|
||||
/* Selectors should have higher specificity than those in the plugins' default stylesheets */
|
||||
/* Plugin overrides */
|
||||
/* Selectors should have higher specificity than those in the plugins' default stylesheets */
|
||||
|
||||
/* Show Invisibles plugin overrides */
|
||||
.token.token.tab:not(:empty):before,
|
||||
.token.token.cr:before,
|
||||
.token.token.lf:before,
|
||||
.token.token.space:before {
|
||||
/* Show Invisibles plugin overrides */
|
||||
.token.token.tab:not(:empty):before,
|
||||
.token.token.cr:before,
|
||||
.token.token.lf:before,
|
||||
.token.token.space:before {
|
||||
color: hsla(220, 14%, 71%, 0.15);
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Toolbar plugin overrides */
|
||||
/* Space out all buttons and move them away from the right edge of the code block */
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item {
|
||||
/* Toolbar plugin overrides */
|
||||
/* Space out all buttons and move them away from the right edge of the code block */
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item {
|
||||
margin-right: 0.4em;
|
||||
}
|
||||
}
|
||||
|
||||
/* Styling the buttons */
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > button,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > a,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > span {
|
||||
/* Styling the buttons */
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > button,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > a,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > span {
|
||||
background: hsl(220, 13%, 26%);
|
||||
color: hsl(220, 9%, 55%);
|
||||
padding: 0.1em 0.4em;
|
||||
border-radius: 0.3em;
|
||||
}
|
||||
}
|
||||
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:hover,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:focus,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:hover,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:focus,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:hover,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:focus {
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:hover,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:focus,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:hover,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:focus,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:hover,
|
||||
div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:focus {
|
||||
background: hsl(220, 13%, 28%);
|
||||
color: hsl(220, 14%, 71%);
|
||||
}
|
||||
}
|
||||
|
||||
/* Line Highlight plugin overrides */
|
||||
/* The highlighted line itself */
|
||||
.line-highlight.line-highlight {
|
||||
/* Line Highlight plugin overrides */
|
||||
/* The highlighted line itself */
|
||||
.line-highlight.line-highlight {
|
||||
background: hsla(220, 100%, 80%, 0.04);
|
||||
}
|
||||
}
|
||||
|
||||
/* Default line numbers in Line Highlight plugin */
|
||||
.line-highlight.line-highlight:before,
|
||||
.line-highlight.line-highlight[data-end]:after {
|
||||
/* Default line numbers in Line Highlight plugin */
|
||||
.line-highlight.line-highlight:before,
|
||||
.line-highlight.line-highlight[data-end]:after {
|
||||
background: hsl(220, 13%, 26%);
|
||||
color: hsl(220, 14%, 71%);
|
||||
padding: 0.1em 0.6em;
|
||||
border-radius: 0.3em;
|
||||
box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.2); /* same as Toolbar plugin default */
|
||||
}
|
||||
}
|
||||
|
||||
/* Hovering over a linkable line number (in the gutter area) */
|
||||
/* Requires Line Numbers plugin as well */
|
||||
pre[id].linkable-line-numbers.linkable-line-numbers span.line-numbers-rows > span:hover:before {
|
||||
/* Hovering over a linkable line number (in the gutter area) */
|
||||
/* Requires Line Numbers plugin as well */
|
||||
pre[id].linkable-line-numbers.linkable-line-numbers span.line-numbers-rows > span:hover:before {
|
||||
background-color: hsla(220, 100%, 80%, 0.04);
|
||||
}
|
||||
}
|
||||
|
||||
/* Line Numbers and Command Line plugins overrides */
|
||||
/* Line separating gutter from coding area */
|
||||
.line-numbers.line-numbers .line-numbers-rows,
|
||||
.command-line .command-line-prompt {
|
||||
/* Line Numbers and Command Line plugins overrides */
|
||||
/* Line separating gutter from coding area */
|
||||
.line-numbers.line-numbers .line-numbers-rows,
|
||||
.command-line .command-line-prompt {
|
||||
border-right-color: hsla(220, 14%, 71%, 0.15);
|
||||
}
|
||||
}
|
||||
|
||||
/* Stuff in the gutter */
|
||||
.line-numbers .line-numbers-rows > span:before,
|
||||
.command-line .command-line-prompt > span:before {
|
||||
/* Stuff in the gutter */
|
||||
.line-numbers .line-numbers-rows > span:before,
|
||||
.command-line .command-line-prompt > span:before {
|
||||
color: hsl(220, 14%, 45%);
|
||||
}
|
||||
}
|
||||
|
||||
/* Match Braces plugin overrides */
|
||||
/* Note: Outline colour is inherited from the braces */
|
||||
.rainbow-braces .token.token.punctuation.brace-level-1,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-5,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-9 {
|
||||
/* Match Braces plugin overrides */
|
||||
/* Note: Outline colour is inherited from the braces */
|
||||
.rainbow-braces .token.token.punctuation.brace-level-1,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-5,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-9 {
|
||||
color: hsl(355, 65%, 65%);
|
||||
}
|
||||
}
|
||||
|
||||
.rainbow-braces .token.token.punctuation.brace-level-2,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-6,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-10 {
|
||||
.rainbow-braces .token.token.punctuation.brace-level-2,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-6,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-10 {
|
||||
color: hsl(95, 38%, 62%);
|
||||
}
|
||||
}
|
||||
|
||||
.rainbow-braces .token.token.punctuation.brace-level-3,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-7,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-11 {
|
||||
.rainbow-braces .token.token.punctuation.brace-level-3,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-7,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-11 {
|
||||
color: hsl(207, 82%, 66%);
|
||||
}
|
||||
}
|
||||
|
||||
.rainbow-braces .token.token.punctuation.brace-level-4,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-8,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-12 {
|
||||
.rainbow-braces .token.token.punctuation.brace-level-4,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-8,
|
||||
.rainbow-braces .token.token.punctuation.brace-level-12 {
|
||||
color: hsl(286, 60%, 67%);
|
||||
}
|
||||
}
|
||||
|
||||
/* Diff Highlight plugin overrides */
|
||||
/* Taken from https://github.com/atom/github/blob/master/styles/variables.less */
|
||||
pre.diff-highlight > code .token.token.deleted:not(.prefix),
|
||||
pre > code.diff-highlight .token.token.deleted:not(.prefix) {
|
||||
/* Diff Highlight plugin overrides */
|
||||
/* Taken from https://github.com/atom/github/blob/master/styles/variables.less */
|
||||
pre.diff-highlight > code .token.token.deleted:not(.prefix),
|
||||
pre > code.diff-highlight .token.token.deleted:not(.prefix) {
|
||||
background-color: hsla(353, 100%, 66%, 0.15);
|
||||
}
|
||||
}
|
||||
|
||||
pre.diff-highlight > code .token.token.deleted:not(.prefix)::-moz-selection,
|
||||
pre.diff-highlight > code .token.token.deleted:not(.prefix) *::-moz-selection,
|
||||
pre > code.diff-highlight .token.token.deleted:not(.prefix)::-moz-selection,
|
||||
pre > code.diff-highlight .token.token.deleted:not(.prefix) *::-moz-selection {
|
||||
pre.diff-highlight > code .token.token.deleted:not(.prefix)::-moz-selection,
|
||||
pre.diff-highlight > code .token.token.deleted:not(.prefix) *::-moz-selection,
|
||||
pre > code.diff-highlight .token.token.deleted:not(.prefix)::-moz-selection,
|
||||
pre > code.diff-highlight .token.token.deleted:not(.prefix) *::-moz-selection {
|
||||
background-color: hsla(353, 95%, 66%, 0.25);
|
||||
}
|
||||
}
|
||||
|
||||
pre.diff-highlight > code .token.token.deleted:not(.prefix)::selection,
|
||||
pre.diff-highlight > code .token.token.deleted:not(.prefix) *::selection,
|
||||
pre > code.diff-highlight .token.token.deleted:not(.prefix)::selection,
|
||||
pre > code.diff-highlight .token.token.deleted:not(.prefix) *::selection {
|
||||
pre.diff-highlight > code .token.token.deleted:not(.prefix)::selection,
|
||||
pre.diff-highlight > code .token.token.deleted:not(.prefix) *::selection,
|
||||
pre > code.diff-highlight .token.token.deleted:not(.prefix)::selection,
|
||||
pre > code.diff-highlight .token.token.deleted:not(.prefix) *::selection {
|
||||
background-color: hsla(353, 95%, 66%, 0.25);
|
||||
}
|
||||
}
|
||||
|
||||
pre.diff-highlight > code .token.token.inserted:not(.prefix),
|
||||
pre > code.diff-highlight .token.token.inserted:not(.prefix) {
|
||||
pre.diff-highlight > code .token.token.inserted:not(.prefix),
|
||||
pre > code.diff-highlight .token.token.inserted:not(.prefix) {
|
||||
background-color: hsla(137, 100%, 55%, 0.15);
|
||||
}
|
||||
}
|
||||
|
||||
pre.diff-highlight > code .token.token.inserted:not(.prefix)::-moz-selection,
|
||||
pre.diff-highlight > code .token.token.inserted:not(.prefix) *::-moz-selection,
|
||||
pre > code.diff-highlight .token.token.inserted:not(.prefix)::-moz-selection,
|
||||
pre > code.diff-highlight .token.token.inserted:not(.prefix) *::-moz-selection {
|
||||
pre.diff-highlight > code .token.token.inserted:not(.prefix)::-moz-selection,
|
||||
pre.diff-highlight > code .token.token.inserted:not(.prefix) *::-moz-selection,
|
||||
pre > code.diff-highlight .token.token.inserted:not(.prefix)::-moz-selection,
|
||||
pre > code.diff-highlight .token.token.inserted:not(.prefix) *::-moz-selection {
|
||||
background-color: hsla(135, 73%, 55%, 0.25);
|
||||
}
|
||||
}
|
||||
|
||||
pre.diff-highlight > code .token.token.inserted:not(.prefix)::selection,
|
||||
pre.diff-highlight > code .token.token.inserted:not(.prefix) *::selection,
|
||||
pre > code.diff-highlight .token.token.inserted:not(.prefix)::selection,
|
||||
pre > code.diff-highlight .token.token.inserted:not(.prefix) *::selection {
|
||||
pre.diff-highlight > code .token.token.inserted:not(.prefix)::selection,
|
||||
pre.diff-highlight > code .token.token.inserted:not(.prefix) *::selection,
|
||||
pre > code.diff-highlight .token.token.inserted:not(.prefix)::selection,
|
||||
pre > code.diff-highlight .token.token.inserted:not(.prefix) *::selection {
|
||||
background-color: hsla(135, 73%, 55%, 0.25);
|
||||
}
|
||||
}
|
||||
|
||||
/* Previewers plugin overrides */
|
||||
/* Based on https://github.com/atom-community/atom-ide-datatip/blob/master/styles/atom-ide-datatips.less and https://github.com/atom/atom/blob/master/packages/one-dark-ui */
|
||||
/* Border around popup */
|
||||
.prism-previewer.prism-previewer:before,
|
||||
.prism-previewer-gradient.prism-previewer-gradient div {
|
||||
/* Previewers plugin overrides */
|
||||
/* Based on https://github.com/atom-community/atom-ide-datatip/blob/master/styles/atom-ide-datatips.less and https://github.com/atom/atom/blob/master/packages/one-dark-ui */
|
||||
/* Border around popup */
|
||||
.prism-previewer.prism-previewer:before,
|
||||
.prism-previewer-gradient.prism-previewer-gradient div {
|
||||
border-color: hsl(224, 13%, 17%);
|
||||
}
|
||||
}
|
||||
|
||||
/* Angle and time should remain as circles and are hence not included */
|
||||
.prism-previewer-color.prism-previewer-color:before,
|
||||
.prism-previewer-gradient.prism-previewer-gradient div,
|
||||
.prism-previewer-easing.prism-previewer-easing:before {
|
||||
/* Angle and time should remain as circles and are hence not included */
|
||||
.prism-previewer-color.prism-previewer-color:before,
|
||||
.prism-previewer-gradient.prism-previewer-gradient div,
|
||||
.prism-previewer-easing.prism-previewer-easing:before {
|
||||
border-radius: 0.3em;
|
||||
}
|
||||
}
|
||||
|
||||
/* Triangles pointing to the code */
|
||||
.prism-previewer.prism-previewer:after {
|
||||
/* Triangles pointing to the code */
|
||||
.prism-previewer.prism-previewer:after {
|
||||
border-top-color: hsl(224, 13%, 17%);
|
||||
}
|
||||
}
|
||||
|
||||
.prism-previewer-flipped.prism-previewer-flipped.after {
|
||||
.prism-previewer-flipped.prism-previewer-flipped.after {
|
||||
border-bottom-color: hsl(224, 13%, 17%);
|
||||
}
|
||||
}
|
||||
|
||||
/* Background colour within the popup */
|
||||
.prism-previewer-angle.prism-previewer-angle:before,
|
||||
.prism-previewer-time.prism-previewer-time:before,
|
||||
.prism-previewer-easing.prism-previewer-easing {
|
||||
/* Background colour within the popup */
|
||||
.prism-previewer-angle.prism-previewer-angle:before,
|
||||
.prism-previewer-time.prism-previewer-time:before,
|
||||
.prism-previewer-easing.prism-previewer-easing {
|
||||
background: hsl(219, 13%, 22%);
|
||||
}
|
||||
}
|
||||
|
||||
/* For angle, this is the positive area (eg. 90deg will display one quadrant in this colour) */
|
||||
/* For time, this is the alternate colour */
|
||||
.prism-previewer-angle.prism-previewer-angle circle,
|
||||
.prism-previewer-time.prism-previewer-time circle {
|
||||
/* For angle, this is the positive area (eg. 90deg will display one quadrant in this colour) */
|
||||
/* For time, this is the alternate colour */
|
||||
.prism-previewer-angle.prism-previewer-angle circle,
|
||||
.prism-previewer-time.prism-previewer-time circle {
|
||||
stroke: hsl(220, 14%, 71%);
|
||||
stroke-opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Stroke colours of the handle, direction point, and vector itself */
|
||||
.prism-previewer-easing.prism-previewer-easing circle,
|
||||
.prism-previewer-easing.prism-previewer-easing path,
|
||||
.prism-previewer-easing.prism-previewer-easing line {
|
||||
/* Stroke colours of the handle, direction point, and vector itself */
|
||||
.prism-previewer-easing.prism-previewer-easing circle,
|
||||
.prism-previewer-easing.prism-previewer-easing path,
|
||||
.prism-previewer-easing.prism-previewer-easing line {
|
||||
stroke: hsl(220, 14%, 71%);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill colour of the handle */
|
||||
.prism-previewer-easing.prism-previewer-easing circle {
|
||||
/* Fill colour of the handle */
|
||||
.prism-previewer-easing.prism-previewer-easing circle {
|
||||
fill: transparent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import React from 'react';
|
||||
import { ReactComponent as AppLogo } from '../assets/app-logo.svg';
|
||||
import {
|
||||
Twitter,
|
||||
Discord,
|
||||
Instagram,
|
||||
Github,
|
||||
Instagram,
|
||||
Opencollective,
|
||||
Twitch
|
||||
Twitch,
|
||||
Twitter
|
||||
} from '@icons-pack/react-simple-icons';
|
||||
import React from 'react';
|
||||
|
||||
import { ReactComponent as AppLogo } from '../assets/app-logo.svg';
|
||||
|
||||
function FooterLink(props: { children: string | JSX.Element; link: string }) {
|
||||
return (
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useEffect } from 'react';
|
||||
|
||||
import Prism from 'prismjs';
|
||||
import 'prismjs/components/prism-rust';
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
import '../atom-one.css';
|
||||
|
||||
interface MarkdownPageProps {
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
import { Button, Dropdown } from '@sd/ui';
|
||||
import clsx from 'clsx';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Link, List, MapPin, Question } from 'phosphor-react';
|
||||
import { ReactComponent as AppLogo } from '../assets/app-logo.svg';
|
||||
import { Discord, Github } from '@icons-pack/react-simple-icons';
|
||||
import {
|
||||
ClockIcon,
|
||||
CogIcon,
|
||||
|
@ -12,6 +6,13 @@ import {
|
|||
MapIcon,
|
||||
QuestionMarkCircleIcon
|
||||
} from '@heroicons/react/solid';
|
||||
import { Discord, Github } from '@icons-pack/react-simple-icons';
|
||||
import { Button, Dropdown } from '@sd/ui';
|
||||
import clsx from 'clsx';
|
||||
import { Link, List, MapPin, Question } from 'phosphor-react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { ReactComponent as AppLogo } from '../assets/app-logo.svg';
|
||||
|
||||
function NavLink(props: { link?: string; children: string }) {
|
||||
return (
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import { Button } from '@sd/ui';
|
||||
import React, { Suspense } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { BrowserRouter as Router, useRoutes } from 'react-router-dom';
|
||||
|
||||
import routes from '~react-pages';
|
||||
import NavBar from './components/NavBar';
|
||||
import { Footer } from './components/Footer';
|
||||
|
||||
import '@sd/ui/style';
|
||||
|
||||
import { Footer } from './components/Footer';
|
||||
import NavBar from './components/NavBar';
|
||||
import './style.scss';
|
||||
import { Button } from '@sd/ui';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import Markdown from '../components/Markdown';
|
||||
import React from 'react';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { Button } from '@sd/ui';
|
||||
import { SmileyXEyes } from 'phosphor-react';
|
||||
import React from 'react';
|
||||
import { Helmet } from 'react-helmet';
|
||||
|
||||
import Markdown from '../components/Markdown';
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import Markdown from '../components/Markdown';
|
||||
import React from 'react';
|
||||
import { ReactComponent as Content } from '~/docs/changelog/index.md';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { ReactComponent as Content } from '~/docs/changelog/index.md';
|
||||
|
||||
import Markdown from '../components/Markdown';
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import Markdown from '../../../components/Markdown';
|
||||
import React from 'react';
|
||||
import { ReactComponent as Content } from '~/docs/architecture/distributed-data-sync.md';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { ReactComponent as Content } from '~/docs/architecture/distributed-data-sync.md';
|
||||
|
||||
import Markdown from '../../../components/Markdown';
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import Markdown from '../components/Markdown';
|
||||
import React from 'react';
|
||||
import { ReactComponent as Content } from '~/docs/product/faq.md';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { ReactComponent as Content } from '~/docs/product/faq.md';
|
||||
|
||||
import Markdown from '../components/Markdown';
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { Button } from '@sd/ui';
|
||||
import { Bubbles } from '../components/Bubbles';
|
||||
|
||||
import NavBar from '../components/NavBar';
|
||||
import { Footer } from '../components/Footer';
|
||||
import { Apple, Github, Linux, Windows } from '@icons-pack/react-simple-icons';
|
||||
import { useState } from 'react';
|
||||
import { Button } from '@sd/ui';
|
||||
import clsx from 'clsx';
|
||||
import React, { useEffect } from 'react';
|
||||
import { useState } from 'react';
|
||||
|
||||
import AppEmbed from '../components/AppEmbed';
|
||||
import { Bubbles } from '../components/Bubbles';
|
||||
import { Footer } from '../components/Footer';
|
||||
import NavBar from '../components/NavBar';
|
||||
|
||||
interface SectionProps {
|
||||
orientation: 'left' | 'right';
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import Markdown from '../components/Markdown';
|
||||
import React from 'react';
|
||||
import { ReactComponent as Content } from '~/docs/product/roadmap.md';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { ReactComponent as Content } from '~/docs/product/roadmap.md';
|
||||
|
||||
import { ReactComponent as Folder } from '../../../../packages/interface/src/assets/svg/folder.svg';
|
||||
import Markdown from '../components/Markdown';
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import Markdown from '../components/Markdown';
|
||||
import React from 'react';
|
||||
import { ReactComponent as Content } from '~/docs/product/credits.md';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { ReactComponent as Content } from '~/docs/product/credits.md';
|
||||
|
||||
import Markdown from '../components/Markdown';
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import pages from 'vite-plugin-pages';
|
||||
import { defineConfig } from 'vite';
|
||||
import md, { Mode } from 'vite-plugin-markdown';
|
||||
import pages from 'vite-plugin-pages';
|
||||
import svg from 'vite-plugin-svgr';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import React, { useEffect } from 'react';
|
||||
|
||||
import SpacedriveInterface from '@sd/interface';
|
||||
import { ClientCommand, ClientQuery, CoreEvent } from '@sd/core';
|
||||
import { BaseTransport } from '@sd/client';
|
||||
import { ClientCommand, ClientQuery, CoreEvent } from '@sd/core';
|
||||
import SpacedriveInterface from '@sd/interface';
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
const websocket = new WebSocket(import.meta.env.VITE_SDSERVER_BASE_URL || 'ws://localhost:8080/ws');
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import App from './App';
|
||||
|
||||
import '@sd/ui/style';
|
||||
|
||||
import App from './App';
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { defineConfig } from 'vite';
|
||||
import svg from 'vite-plugin-svgr';
|
||||
import tsconfigPaths from 'vite-plugin-tsconfig-paths';
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
max_width = 100
|
||||
hard_tabs = false
|
||||
tab_spaces = 2
|
||||
hard_tabs = true
|
||||
newline_style = "Unix"
|
||||
use_small_heuristics = "Default"
|
||||
reorder_imports = true
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
import type { Platform } from "./Platform";
|
||||
import type { Platform } from './Platform';
|
||||
|
||||
export interface Client { uuid: string, name: string, platform: Platform, tcp_address: string, last_seen: string, last_synchronized: string, }
|
||||
export interface Client {
|
||||
uuid: string;
|
||||
name: string;
|
||||
platform: Platform;
|
||||
tcp_address: string;
|
||||
last_seen: string;
|
||||
last_synchronized: string;
|
||||
}
|
||||
|
|
|
@ -1,2 +1,14 @@
|
|||
|
||||
export type ClientCommand = { key: "FileRead", params: { id: number, } } | { key: "FileDelete", params: { id: number, } } | { key: "LibDelete", params: { id: number, } } | { key: "TagCreate", params: { name: string, color: string, } } | { key: "TagUpdate", params: { name: string, color: string, } } | { key: "TagAssign", params: { file_id: number, tag_id: number, } } | { key: "TagDelete", params: { id: number, } } | { key: "LocCreate", params: { path: string, } } | { key: "LocUpdate", params: { id: number, name: string | null, } } | { key: "LocDelete", params: { id: number, } } | { key: "SysVolumeUnmount", params: { id: number, } } | { key: "GenerateThumbsForLocation", params: { id: number, path: string, } } | { key: "IdentifyUniqueFiles" };
|
||||
export type ClientCommand =
|
||||
| { key: 'FileRead'; params: { id: number } }
|
||||
| { key: 'FileDelete'; params: { id: number } }
|
||||
| { key: 'LibDelete'; params: { id: number } }
|
||||
| { key: 'TagCreate'; params: { name: string; color: string } }
|
||||
| { key: 'TagUpdate'; params: { name: string; color: string } }
|
||||
| { key: 'TagAssign'; params: { file_id: number; tag_id: number } }
|
||||
| { key: 'TagDelete'; params: { id: number } }
|
||||
| { key: 'LocCreate'; params: { path: string } }
|
||||
| { key: 'LocUpdate'; params: { id: number; name: string | null } }
|
||||
| { key: 'LocDelete'; params: { id: number } }
|
||||
| { key: 'SysVolumeUnmount'; params: { id: number } }
|
||||
| { key: 'GenerateThumbsForLocation'; params: { id: number; path: string } }
|
||||
| { key: 'IdentifyUniqueFiles' };
|
||||
|
|
|
@ -1,2 +1,10 @@
|
|||
|
||||
export type ClientQuery = { key: "ClientGetState" } | { key: "SysGetVolumes" } | { key: "LibGetTags" } | { key: "JobGetRunning" } | { key: "JobGetHistory" } | { key: "SysGetLocations" } | { key: "SysGetLocation", params: { id: number, } } | { key: "LibGetExplorerDir", params: { location_id: number, path: string, limit: number, } } | { key: "GetLibraryStatistics" };
|
||||
export type ClientQuery =
|
||||
| { key: 'ClientGetState' }
|
||||
| { key: 'SysGetVolumes' }
|
||||
| { key: 'LibGetTags' }
|
||||
| { key: 'JobGetRunning' }
|
||||
| { key: 'JobGetHistory' }
|
||||
| { key: 'SysGetLocations' }
|
||||
| { key: 'SysGetLocation'; params: { id: number } }
|
||||
| { key: 'LibGetExplorerDir'; params: { location_id: number; path: string; limit: number } }
|
||||
| { key: 'GetLibraryStatistics' };
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
import type { LibraryState } from "./LibraryState";
|
||||
import type { LibraryState } from './LibraryState';
|
||||
|
||||
export interface ClientState { client_uuid: string, client_id: number, client_name: string, data_path: string, tcp_port: number, libraries: Array<LibraryState>, current_library_uuid: string, }
|
||||
export interface ClientState {
|
||||
client_uuid: string;
|
||||
client_id: number;
|
||||
client_name: string;
|
||||
data_path: string;
|
||||
tcp_port: number;
|
||||
libraries: Array<LibraryState>;
|
||||
current_library_uuid: string;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
import type { ClientQuery } from "./ClientQuery";
|
||||
import type { CoreResource } from "./CoreResource";
|
||||
import type { ClientQuery } from './ClientQuery';
|
||||
import type { CoreResource } from './CoreResource';
|
||||
|
||||
export type CoreEvent = { key: "InvalidateQuery", data: ClientQuery } | { key: "InvalidateQueryDebounced", data: ClientQuery } | { key: "InvalidateResource", data: CoreResource } | { key: "NewThumbnail", data: { cas_id: string, } } | { key: "Log", data: { message: string, } } | { key: "DatabaseDisconnected", data: { reason: string | null, } };
|
||||
export type CoreEvent =
|
||||
| { key: 'InvalidateQuery'; data: ClientQuery }
|
||||
| { key: 'InvalidateQueryDebounced'; data: ClientQuery }
|
||||
| { key: 'InvalidateResource'; data: CoreResource }
|
||||
| { key: 'NewThumbnail'; data: { cas_id: string } }
|
||||
| { key: 'Log'; data: { message: string } }
|
||||
| { key: 'DatabaseDisconnected'; data: { reason: string | null } };
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
import type { File } from "./File";
|
||||
import type { JobReport } from "./JobReport";
|
||||
import type { LocationResource } from "./LocationResource";
|
||||
import type { File } from './File';
|
||||
import type { JobReport } from './JobReport';
|
||||
import type { LocationResource } from './LocationResource';
|
||||
|
||||
export type CoreResource = "Client" | "Library" | { Location: LocationResource } | { File: File } | { Job: JobReport } | "Tag";
|
||||
export type CoreResource =
|
||||
| 'Client'
|
||||
| 'Library'
|
||||
| { Location: LocationResource }
|
||||
| { File: File }
|
||||
| { Job: JobReport }
|
||||
| 'Tag';
|
||||
|
|
|
@ -1,8 +1,18 @@
|
|||
import type { ClientState } from "./ClientState";
|
||||
import type { DirectoryWithContents } from "./DirectoryWithContents";
|
||||
import type { JobReport } from "./JobReport";
|
||||
import type { LocationResource } from "./LocationResource";
|
||||
import type { Statistics } from "./Statistics";
|
||||
import type { Volume } from "./Volume";
|
||||
import type { ClientState } from './ClientState';
|
||||
import type { DirectoryWithContents } from './DirectoryWithContents';
|
||||
import type { JobReport } from './JobReport';
|
||||
import type { LocationResource } from './LocationResource';
|
||||
import type { Statistics } from './Statistics';
|
||||
import type { Volume } from './Volume';
|
||||
|
||||
export type CoreResponse = { key: "Success", data: null } | { key: "SysGetVolumes", data: Array<Volume> } | { key: "SysGetLocation", data: LocationResource } | { key: "SysGetLocations", data: Array<LocationResource> } | { key: "LibGetExplorerDir", data: DirectoryWithContents } | { key: "ClientGetState", data: ClientState } | { key: "LocCreate", data: LocationResource } | { key: "JobGetRunning", data: Array<JobReport> } | { key: "JobGetHistory", data: Array<JobReport> } | { key: "GetLibraryStatistics", data: Statistics };
|
||||
export type CoreResponse =
|
||||
| { key: 'Success'; data: null }
|
||||
| { key: 'SysGetVolumes'; data: Array<Volume> }
|
||||
| { key: 'SysGetLocation'; data: LocationResource }
|
||||
| { key: 'SysGetLocations'; data: Array<LocationResource> }
|
||||
| { key: 'LibGetExplorerDir'; data: DirectoryWithContents }
|
||||
| { key: 'ClientGetState'; data: ClientState }
|
||||
| { key: 'LocCreate'; data: LocationResource }
|
||||
| { key: 'JobGetRunning'; data: Array<JobReport> }
|
||||
| { key: 'JobGetHistory'; data: Array<JobReport> }
|
||||
| { key: 'GetLibraryStatistics'; data: Statistics };
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import type { FilePath } from "./FilePath";
|
||||
import type { FilePath } from './FilePath';
|
||||
|
||||
export interface DirectoryWithContents { directory: FilePath, contents: Array<FilePath>, }
|
||||
export interface DirectoryWithContents {
|
||||
directory: FilePath;
|
||||
contents: Array<FilePath>;
|
||||
}
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
|
||||
export type EncryptionAlgorithm = "None" | "AES128" | "AES192" | "AES256";
|
||||
export type EncryptionAlgorithm = 'None' | 'AES128' | 'AES192' | 'AES256';
|
||||
|
|
|
@ -1,5 +1,24 @@
|
|||
import type { EncryptionAlgorithm } from "./EncryptionAlgorithm";
|
||||
import type { FileKind } from "./FileKind";
|
||||
import type { FilePath } from "./FilePath";
|
||||
import type { EncryptionAlgorithm } from './EncryptionAlgorithm';
|
||||
import type { FileKind } from './FileKind';
|
||||
import type { FilePath } from './FilePath';
|
||||
|
||||
export interface File { id: number, cas_id: string, integrity_checksum: string | null, size_in_bytes: string, kind: FileKind, hidden: boolean, favorite: boolean, important: boolean, has_thumbnail: boolean, has_thumbstrip: boolean, has_video_preview: boolean, encryption: EncryptionAlgorithm, ipfs_id: string | null, comment: string | null, date_created: string, date_modified: string, date_indexed: string, paths: Array<FilePath>, }
|
||||
export interface File {
|
||||
id: number;
|
||||
cas_id: string;
|
||||
integrity_checksum: string | null;
|
||||
size_in_bytes: string;
|
||||
kind: FileKind;
|
||||
hidden: boolean;
|
||||
favorite: boolean;
|
||||
important: boolean;
|
||||
has_thumbnail: boolean;
|
||||
has_thumbstrip: boolean;
|
||||
has_video_preview: boolean;
|
||||
encryption: EncryptionAlgorithm;
|
||||
ipfs_id: string | null;
|
||||
comment: string | null;
|
||||
date_created: string;
|
||||
date_modified: string;
|
||||
date_indexed: string;
|
||||
paths: Array<FilePath>;
|
||||
}
|
||||
|
|
|
@ -1,2 +1,10 @@
|
|||
|
||||
export type FileKind = "Unknown" | "Directory" | "Package" | "Archive" | "Image" | "Video" | "Audio" | "Plaintext" | "Alias";
|
||||
export type FileKind =
|
||||
| 'Unknown'
|
||||
| 'Directory'
|
||||
| 'Package'
|
||||
| 'Archive'
|
||||
| 'Image'
|
||||
| 'Video'
|
||||
| 'Audio'
|
||||
| 'Plaintext'
|
||||
| 'Alias';
|
||||
|
|
|
@ -1,2 +1,16 @@
|
|||
|
||||
export interface FilePath { id: number, is_dir: boolean, location_id: number, materialized_path: string, name: string, extension: string | null, file_id: number | null, parent_id: number | null, temp_cas_id: string | null, has_local_thumbnail: boolean, date_created: string, date_modified: string, date_indexed: string, permissions: string | null, }
|
||||
export interface FilePath {
|
||||
id: number;
|
||||
is_dir: boolean;
|
||||
location_id: number;
|
||||
materialized_path: string;
|
||||
name: string;
|
||||
extension: string | null;
|
||||
file_id: number | null;
|
||||
parent_id: number | null;
|
||||
temp_cas_id: string | null;
|
||||
has_local_thumbnail: boolean;
|
||||
date_created: string;
|
||||
date_modified: string;
|
||||
date_indexed: string;
|
||||
permissions: string | null;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
import type { JobStatus } from "./JobStatus";
|
||||
import type { JobStatus } from './JobStatus';
|
||||
|
||||
export interface JobReport { id: string, date_created: string, date_modified: string, status: JobStatus, task_count: number, completed_task_count: number, message: string, seconds_elapsed: string, }
|
||||
export interface JobReport {
|
||||
id: string;
|
||||
date_created: string;
|
||||
date_modified: string;
|
||||
status: JobStatus;
|
||||
task_count: number;
|
||||
completed_task_count: number;
|
||||
message: string;
|
||||
seconds_elapsed: string;
|
||||
}
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
|
||||
export type JobStatus = "Queued" | "Running" | "Completed" | "Canceled" | "Failed";
|
||||
export type JobStatus = 'Queued' | 'Running' | 'Completed' | 'Canceled' | 'Failed';
|
||||
|
|
|
@ -1,2 +1,6 @@
|
|||
|
||||
export interface LibraryState { library_uuid: string, library_id: number, library_path: string, offline: boolean, }
|
||||
export interface LibraryState {
|
||||
library_uuid: string;
|
||||
library_id: number;
|
||||
library_path: string;
|
||||
offline: boolean;
|
||||
}
|
||||
|
|
|
@ -1,2 +1,10 @@
|
|||
|
||||
export interface LocationResource { id: number, name: string | null, path: string | null, total_capacity: number | null, available_capacity: number | null, is_removable: boolean | null, is_online: boolean, date_created: string, }
|
||||
export interface LocationResource {
|
||||
id: number;
|
||||
name: string | null;
|
||||
path: string | null;
|
||||
total_capacity: number | null;
|
||||
available_capacity: number | null;
|
||||
is_removable: boolean | null;
|
||||
is_online: boolean;
|
||||
date_created: string;
|
||||
}
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
|
||||
export type Platform = "Unknown" | "Windows" | "MacOS" | "Linux" | "IOS" | "Android";
|
||||
export type Platform = 'Unknown' | 'Windows' | 'MacOS' | 'Linux' | 'IOS' | 'Android';
|
||||
|
|
|
@ -1,2 +1,9 @@
|
|||
|
||||
export interface Statistics { total_file_count: number, total_bytes_used: string, total_bytes_capacity: string, total_bytes_free: string, total_unique_bytes: string, preview_media_bytes: string, library_db_size: string, }
|
||||
export interface Statistics {
|
||||
total_file_count: number;
|
||||
total_bytes_used: string;
|
||||
total_bytes_capacity: string;
|
||||
total_bytes_free: string;
|
||||
total_unique_bytes: string;
|
||||
preview_media_bytes: string;
|
||||
library_db_size: string;
|
||||
}
|
||||
|
|
|
@ -1,2 +1,10 @@
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,9 @@ pub async fn run_migrations(ctx: &CoreContext) -> Result<()> {
|
|||
};
|
||||
|
||||
let value: Vec<serde_json::Value> = client
|
||||
._query_raw("SELECT name FROM sqlite_master WHERE type='table' AND name='_migrations'")
|
||||
._query_raw(
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name='_migrations'",
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
|
|
@ -51,7 +51,10 @@ impl Job for ThumbnailJob {
|
|||
tokio::task::spawn_blocking(move || {
|
||||
ctx.progress(vec![
|
||||
JobReportUpdate::TaskCount(image_files.len()),
|
||||
JobReportUpdate::Message(format!("Preparing to process {} files", image_files.len())),
|
||||
JobReportUpdate::Message(format!(
|
||||
"Preparing to process {} files",
|
||||
image_files.len()
|
||||
)),
|
||||
]);
|
||||
|
||||
for (i, image_file) in image_files.iter().enumerate() {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -2,13 +2,13 @@ use crate::job::jobs::JobReportUpdate;
|
|||
use crate::{
|
||||
file::FileError,
|
||||
job::{jobs::Job, worker::WorkerContext},
|
||||
prisma::{file_path},
|
||||
prisma::file_path,
|
||||
CoreContext,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use futures::executor::block_on;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use prisma_client_rust::Direction;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct FileCreated {
|
||||
|
@ -88,7 +88,10 @@ impl Job for FileIdentifierJob {
|
|||
|
||||
let remaining = count_orphan_file_paths(&ctx.core_ctx).await?;
|
||||
|
||||
println!("Finished with {} files remaining because your code is bad.", remaining);
|
||||
println!(
|
||||
"Finished with {} files remaining because your code is bad.",
|
||||
remaining
|
||||
);
|
||||
|
||||
// if remaining > 0 {
|
||||
// ctx.core_ctx.spawn_job(Box::new(FileIdentifierJob));
|
||||
|
|
|
@ -135,8 +135,7 @@ impl JobReport {
|
|||
}
|
||||
pub async fn create(&self, ctx: &CoreContext) -> Result<(), JobError> {
|
||||
let config = state::client::get();
|
||||
ctx
|
||||
.database
|
||||
ctx.database
|
||||
.job()
|
||||
.create(
|
||||
job::id::set(self.id.clone()),
|
||||
|
@ -149,8 +148,7 @@ impl JobReport {
|
|||
Ok(())
|
||||
}
|
||||
pub async fn update(&self, ctx: &CoreContext) -> Result<(), JobError> {
|
||||
ctx
|
||||
.database
|
||||
ctx.database
|
||||
.job()
|
||||
.find_unique(job::id::equals(self.id.clone()))
|
||||
.update(vec![
|
||||
|
|
|
@ -29,8 +29,7 @@ pub struct WorkerContext {
|
|||
|
||||
impl WorkerContext {
|
||||
pub fn progress(&self, updates: Vec<JobReportUpdate>) {
|
||||
self
|
||||
.sender
|
||||
self.sender
|
||||
.send(WorkerEvent::Progressed(updates))
|
||||
.unwrap_or(());
|
||||
}
|
||||
|
@ -147,7 +146,8 @@ impl Worker {
|
|||
worker.job_report.task_count = task_count as i32;
|
||||
}
|
||||
JobReportUpdate::CompletedTaskCount(completed_task_count) => {
|
||||
worker.job_report.completed_task_count = completed_task_count as i32;
|
||||
worker.job_report.completed_task_count =
|
||||
completed_task_count as i32;
|
||||
}
|
||||
JobReportUpdate::Message(message) => {
|
||||
worker.job_report.message = message;
|
||||
|
@ -157,8 +157,7 @@ impl Worker {
|
|||
}
|
||||
}
|
||||
}
|
||||
ctx
|
||||
.emit(CoreEvent::InvalidateQueryDebounced(
|
||||
ctx.emit(CoreEvent::InvalidateQueryDebounced(
|
||||
ClientQuery::JobGetRunning,
|
||||
))
|
||||
.await;
|
||||
|
@ -167,11 +166,9 @@ impl Worker {
|
|||
worker.job_report.status = JobStatus::Completed;
|
||||
worker.job_report.update(&ctx).await.unwrap_or(());
|
||||
|
||||
ctx
|
||||
.emit(CoreEvent::InvalidateQuery(ClientQuery::JobGetRunning))
|
||||
ctx.emit(CoreEvent::InvalidateQuery(ClientQuery::JobGetRunning))
|
||||
.await;
|
||||
ctx
|
||||
.emit(CoreEvent::InvalidateQuery(ClientQuery::JobGetHistory))
|
||||
ctx.emit(CoreEvent::InvalidateQuery(ClientQuery::JobGetHistory))
|
||||
.await;
|
||||
break;
|
||||
}
|
||||
|
@ -179,8 +176,7 @@ impl Worker {
|
|||
worker.job_report.status = JobStatus::Failed;
|
||||
worker.job_report.update(&ctx).await.unwrap_or(());
|
||||
|
||||
ctx
|
||||
.emit(CoreEvent::InvalidateQuery(ClientQuery::JobGetHistory))
|
||||
ctx.emit(CoreEvent::InvalidateQuery(ClientQuery::JobGetHistory))
|
||||
.await;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -47,8 +47,7 @@ impl CoreController {
|
|||
pub async fn query(&self, query: ClientQuery) -> Result<CoreResponse, CoreError> {
|
||||
// a one time use channel to send and await a response
|
||||
let (sender, recv) = oneshot::channel();
|
||||
self
|
||||
.query_sender
|
||||
self.query_sender
|
||||
.send(ReturnableMessage {
|
||||
data: query,
|
||||
return_sender: sender,
|
||||
|
@ -60,8 +59,7 @@ impl CoreController {
|
|||
|
||||
pub async fn command(&self, command: ClientCommand) -> Result<CoreResponse, CoreError> {
|
||||
let (sender, recv) = oneshot::channel();
|
||||
self
|
||||
.command_sender
|
||||
self.command_sender
|
||||
.send(ReturnableMessage {
|
||||
data: command,
|
||||
return_sender: sender,
|
||||
|
@ -87,8 +85,7 @@ pub struct CoreContext {
|
|||
|
||||
impl CoreContext {
|
||||
pub fn spawn_job(&self, job: Box<dyn Job>) {
|
||||
self
|
||||
.internal_sender
|
||||
self.internal_sender
|
||||
.send(InternalEvent::JobIngest(job))
|
||||
.unwrap_or_else(|e| {
|
||||
println!("Failed to spawn job. {:?}", e);
|
||||
|
@ -227,7 +224,9 @@ impl Core {
|
|||
} else {
|
||||
for library in self.state.libraries.iter() {
|
||||
// init database for library
|
||||
match library::loader::load(&ctx, &library.library_path, &library.library_uuid).await {
|
||||
match library::loader::load(&ctx, &library.library_path, &library.library_uuid)
|
||||
.await
|
||||
{
|
||||
Ok(library) => println!("Loaded library: {:?}", library),
|
||||
Err(e) => println!("Error loading library: {:?}", e),
|
||||
}
|
||||
|
@ -313,12 +312,16 @@ impl Core {
|
|||
file::explorer::open::open_dir(&ctx, &location_id, &path).await?,
|
||||
),
|
||||
ClientQuery::LibGetTags => todo!(),
|
||||
ClientQuery::JobGetRunning => CoreResponse::JobGetRunning(self.jobs.get_running().await),
|
||||
// TODO: FIX THIS
|
||||
ClientQuery::JobGetHistory => CoreResponse::JobGetHistory(Jobs::get_history(&ctx).await?),
|
||||
ClientQuery::GetLibraryStatistics => {
|
||||
CoreResponse::GetLibraryStatistics(library::statistics::Statistics::calculate(&ctx).await?)
|
||||
ClientQuery::JobGetRunning => {
|
||||
CoreResponse::JobGetRunning(self.jobs.get_running().await)
|
||||
}
|
||||
// TODO: FIX THIS
|
||||
ClientQuery::JobGetHistory => {
|
||||
CoreResponse::JobGetHistory(Jobs::get_history(&ctx).await?)
|
||||
}
|
||||
ClientQuery::GetLibraryStatistics => CoreResponse::GetLibraryStatistics(
|
||||
library::statistics::Statistics::calculate(&ctx).await?,
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -3,7 +3,8 @@ use futures::{channel::mpsc, SinkExt};
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{
|
||||
crdt::PoMethod, examples::tag::TagCreate, CrdtCtx, FakeCoreContext, PropertyOperation, SyncMethod,
|
||||
crdt::PoMethod, examples::tag::TagCreate, CrdtCtx, FakeCoreContext, PropertyOperation,
|
||||
SyncMethod,
|
||||
};
|
||||
|
||||
pub struct SyncEngine {
|
||||
|
|
|
@ -50,7 +50,8 @@ static DOTFILE_NAME: &str = ".spacedrive";
|
|||
// - accessible on from the local filesystem
|
||||
// - already exists in the database
|
||||
pub async fn check_location(path: &str) -> Result<DotSpacedrive, LocationError> {
|
||||
let dotfile: DotSpacedrive = match fs::File::open(format!("{}/{}", path.clone(), DOTFILE_NAME)) {
|
||||
let dotfile: DotSpacedrive = match fs::File::open(format!("{}/{}", path.clone(), DOTFILE_NAME))
|
||||
{
|
||||
Ok(file) => serde_json::from_reader(file).unwrap_or(DotSpacedrive::default()),
|
||||
Err(e) => return Err(LocationError::DotfileReadFailure(e)),
|
||||
};
|
||||
|
@ -158,7 +159,9 @@ pub async fn create_location(ctx: &CoreContext, path: &str) -> Result<LocationRe
|
|||
.create(
|
||||
location::pub_id::set(uuid.to_string()),
|
||||
vec![
|
||||
location::name::set(Some(p.file_name().unwrap().to_string_lossy().to_string())),
|
||||
location::name::set(Some(
|
||||
p.file_name().unwrap().to_string_lossy().to_string(),
|
||||
)),
|
||||
location::is_online::set(true),
|
||||
location::local_path::set(Some(path.to_string())),
|
||||
],
|
||||
|
@ -189,8 +192,7 @@ pub async fn create_location(ctx: &CoreContext, path: &str) -> Result<LocationRe
|
|||
Err(e) => Err(LocationError::DotfileWriteFailure(e, path.to_string()))?,
|
||||
}
|
||||
|
||||
ctx
|
||||
.emit(CoreEvent::InvalidateQuery(ClientQuery::SysGetLocations))
|
||||
ctx.emit(CoreEvent::InvalidateQuery(ClientQuery::SysGetLocations))
|
||||
.await;
|
||||
|
||||
location
|
||||
|
|
|
@ -75,8 +75,8 @@ impl Volume {
|
|||
let mut name = disk.name().to_str().unwrap_or("Volume").to_string();
|
||||
let is_removable = disk.is_removable();
|
||||
|
||||
let file_system =
|
||||
String::from_utf8(disk.file_system().to_vec()).unwrap_or_else(|_| "Err".to_string());
|
||||
let file_system = String::from_utf8(disk.file_system().to_vec())
|
||||
.unwrap_or_else(|_| "Err".to_string());
|
||||
|
||||
let disk_type = match disk.type_() {
|
||||
sysinfo::DiskType::SSD => "SSD".to_string(),
|
||||
|
@ -84,7 +84,8 @@ impl Volume {
|
|||
_ => "Removable Disk".to_string(),
|
||||
};
|
||||
|
||||
if cfg!(target_os = "macos") && mount_point == "/" || mount_point == "/System/Volumes/Data"
|
||||
if cfg!(target_os = "macos") && mount_point == "/"
|
||||
|| mount_point == "/System/Volumes/Data"
|
||||
{
|
||||
name = "Macintosh HD".to_string();
|
||||
mount_point = "/".to_string();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
# Core view
|
||||
|
||||
The primary screen in the Spacedrive app is of your entire virtual network, every "core" is a device under your full command. It is presented in a large panel list view, featuring bold visuals and quick interactions with your fleet.
|
||||
|
||||
Recent files, recent locations and settings are part of these panels, that can be customized at will.
|
||||
|
|
|
@ -1,22 +1,26 @@
|
|||
# Roadmap
|
||||
|
||||
**Complete (Still Testing):**
|
||||
|
||||
- **File discovery** - Scan devices, drives and cloud accounts to build a directory of all files with metadata.
|
||||
- **Preview generation** - Auto generate lower resolution stand-ins for image and video.
|
||||
- **Statistics** - Total capacity, index size, preview media size, free space etc.
|
||||
|
||||
**In progress:**
|
||||
|
||||
- **File Explorer** - Browse online/offline storage locations, view files with metadata, perform basic CRUD.
|
||||
- **Realtime synchronization** - Data index synchronized in realtime between devices, prioritizing peer-to-peer LAN connections (WiFi sync).
|
||||
- **Self hosted** - Spacedrive can be deployed as a service, behaving as just another device powering your personal cloud.
|
||||
|
||||
**To be developed (MVP):**
|
||||
|
||||
- **Photos** - Photo and video albums similar to Apple/Google photos.
|
||||
- **Search** - Deep search into your filesystem with a keybind, including offline locations.
|
||||
- **Tags** - Define routines on custom tags to automate workflows, easily tag files individually, in bulk and automatically via rules.
|
||||
- **Extensions** - Build tools on top of Spacedrive, extend functionality and integrate third party services. Extension directory on [spacedrive.com/extensions](/extensions).
|
||||
|
||||
**To be developed (Post-MVP):**
|
||||
|
||||
- **Spacedrive Cloud** - We'll host an always-on cloud device for you, with pay-as-you-go plans for storage.
|
||||
- **Cloud integration** - Index & backup to Apple Photos, Google Drive, Dropbox, OneDrive & Mega + easy API for the community to add more.
|
||||
- **Encrypted vault(s)** - Effortlessly manage & encrypt sensitive files, built on top of VeraCrypt. Encrypt individual files or create flexible-size vaults.
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"db:migrate": "pnpm core prisma migrate dev",
|
||||
"db:gen": "pnpm core prisma generate",
|
||||
"lint": "turbo run lint",
|
||||
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
|
||||
"format": "prettier --write \"**/*.{ts,tsx,html,scss,json,yml,md}\"",
|
||||
"desktop": "pnpm --filter @sd/desktop --",
|
||||
"mobile": "pnpm --filter @sd/mobile -- ",
|
||||
"web": "pnpm --filter @sd/web -- ",
|
||||
|
@ -23,6 +23,7 @@
|
|||
"typecheck": "pnpm -r exec tsc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@trivago/prettier-plugin-sort-imports": "^3.2.0",
|
||||
"prettier": "^2.6.2",
|
||||
"turbo": "^1.2.4"
|
||||
},
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { ClientCommand, ClientQuery, CoreResponse } from '@sd/core';
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import {
|
||||
useMutation,
|
||||
useQuery,
|
||||
UseMutationOptions,
|
||||
UseQueryOptions,
|
||||
UseQueryResult,
|
||||
UseMutationOptions
|
||||
useMutation,
|
||||
useQuery
|
||||
} from 'react-query';
|
||||
|
||||
// global var to store the transport TODO: not global :D
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { useQuery } from 'react-query';
|
||||
import { useState } from 'react';
|
||||
import { useFileExplorerState } from './state';
|
||||
import { useQuery } from 'react-query';
|
||||
|
||||
import { useBridgeCommand, useBridgeQuery } from '../bridge';
|
||||
import { useFileExplorerState } from './state';
|
||||
|
||||
// this hook initializes the explorer state and queries the core
|
||||
export function useFileExplorer(initialPath = '/', initialLocation: number | null = null) {
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
"zustand": "^3.7.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@trivago/prettier-plugin-sort-imports": "^3.2.0",
|
||||
"@types/babel-core": "^6.25.7",
|
||||
"@types/byte-size": "^8.1.0",
|
||||
"@types/lodash": "^4.14.182",
|
||||
|
|
|
@ -4,8 +4,11 @@ import ProgressBar from '../primitive/ProgressBar';
|
|||
import { Transition } from '@headlessui/react';
|
||||
import clsx from 'clsx';
|
||||
|
||||
const MiddleTruncatedText = ({ children, ...props }: DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>) => {
|
||||
const text = children?.toString() ?? "";
|
||||
const MiddleTruncatedText = ({
|
||||
children,
|
||||
...props
|
||||
}: DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>) => {
|
||||
const text = children?.toString() ?? '';
|
||||
const first = text.substring(0, text.length / 2);
|
||||
const last = text.substring(first.length);
|
||||
|
||||
|
@ -16,11 +19,29 @@ const MiddleTruncatedText = ({ children, ...props }: DetailedHTMLProps<HTMLAttri
|
|||
|
||||
return (
|
||||
<div className="whitespace-nowrap overflow-hidden w-full">
|
||||
<span {...props} style={{ maxWidth: `calc(100% - (1em * ${endWidth}))`, minWidth: startWidth }} className={clsx(props?.className, "text-ellipsis inline-block align-bottom whitespace-nowrap overflow-hidden")}>{first}</span>
|
||||
<span {...props} style={{ maxWidth: `calc(100% - (1em * ${startWidth}))`, direction: "rtl" }} className={clsx(props?.className, "inline-block align-bottom whitespace-nowrap overflow-hidden")}>{last}</span>
|
||||
<span
|
||||
{...props}
|
||||
style={{ maxWidth: `calc(100% - (1em * ${endWidth}))`, minWidth: startWidth }}
|
||||
className={clsx(
|
||||
props?.className,
|
||||
'text-ellipsis inline-block align-bottom whitespace-nowrap overflow-hidden'
|
||||
)}
|
||||
>
|
||||
{first}
|
||||
</span>
|
||||
<span
|
||||
{...props}
|
||||
style={{ maxWidth: `calc(100% - (1em * ${startWidth}))`, direction: 'rtl' }}
|
||||
className={clsx(
|
||||
props?.className,
|
||||
'inline-block align-bottom whitespace-nowrap overflow-hidden'
|
||||
)}
|
||||
>
|
||||
{last}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default function RunningJobsWidget() {
|
||||
const { data: jobs } = useBridgeQuery('JobGetRunning');
|
||||
|
@ -39,7 +60,9 @@ export default function RunningJobsWidget() {
|
|||
>
|
||||
<div key={job.id} className="flex flex-col px-2 pt-1.5 pb-2 bg-gray-700 rounded">
|
||||
{/* <span className="mb-0.5 text-tiny font-bold text-gray-400">{job.status} Job</span> */}
|
||||
<MiddleTruncatedText className="mb-1.5 text-gray-450 text-tiny">{job.message}</MiddleTruncatedText>
|
||||
<MiddleTruncatedText className="mb-1.5 text-gray-450 text-tiny">
|
||||
{job.message}
|
||||
</MiddleTruncatedText>
|
||||
<ProgressBar value={job.completed_task_count} total={job.task_count} />
|
||||
</div>
|
||||
</Transition>
|
||||
|
|
|
@ -32,7 +32,6 @@ const Heading: React.FC<{ className?: string; children: string }> = ({ children,
|
|||
export const SettingsScreen: React.FC<{}> = () => {
|
||||
return (
|
||||
<div className="flex flex-row w-full">
|
||||
|
||||
<div className="h-full border-r border-gray-100 w-60 dark:border-gray-550">
|
||||
<div data-tauri-drag-region className="w-full h-7" />
|
||||
<div className="p-5 pt-0">
|
||||
|
|
|
@ -3,7 +3,9 @@ button {
|
|||
@apply cursor-default;
|
||||
}
|
||||
|
||||
body { font-family: "InterVariable", sans-serif; }
|
||||
body {
|
||||
font-family: 'InterVariable', sans-serif;
|
||||
}
|
||||
|
||||
.no-scrollbar {
|
||||
-ms-overflow-style: none; /* for Internet Explorer, Edge */
|
||||
|
@ -51,14 +53,13 @@ body { font-family: "InterVariable", sans-serif; }
|
|||
width: 8px;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
@apply bg-transparent rounded-[6px] my-[10px]
|
||||
@apply bg-transparent rounded-[6px] my-[10px];
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
@apply rounded-[6px] bg-gray-300 dark:bg-gray-550;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
|
@ -98,7 +99,6 @@ body { font-family: "InterVariable", sans-serif; }
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
.dialog-overlay[data-state='open'] {
|
||||
animation: fadeIn 200ms ease-out forwards;
|
||||
}
|
||||
|
@ -106,8 +106,8 @@ body { font-family: "InterVariable", sans-serif; }
|
|||
animation: fadeIn 200ms ease-out forwards;
|
||||
}
|
||||
.dialog-content[data-state='open'] {
|
||||
-webkit-animation: slide-top 0.3s cubic-bezier(0.215, 0.610, 0.355, 1.000) both;
|
||||
animation: slide-top 0.3s cubic-bezier(0.215, 0.610, 0.355, 1.000) both;
|
||||
-webkit-animation: slide-top 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) both;
|
||||
animation: slide-top 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) both;
|
||||
}
|
||||
.dialog-content[data-state='closed'] {
|
||||
animation: bounceDown 100ms ease-in forwards;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
import React from 'react';
|
||||
|
||||
const sizes = {
|
||||
default: 'py-1 px-3 text-md font-medium',
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React from 'react';
|
||||
import { Menu } from '@headlessui/react';
|
||||
import { ChevronDownIcon } from '@heroicons/react/solid';
|
||||
import clsx from 'clsx';
|
||||
import React from 'react';
|
||||
|
||||
import { Button } from './Button';
|
||||
|
||||
type Section = {
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
background-position: center;
|
||||
}
|
||||
|
||||
|
||||
.fade-in-image {
|
||||
animation: fadeIn 1s;
|
||||
-webkit-animation: fadeIn 1s;
|
||||
|
@ -34,26 +33,46 @@
|
|||
-ms-animation: fadeIn 1s;
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
0% {opacity:0;}
|
||||
100% {opacity:1;}
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes fadeIn {
|
||||
0% {opacity:0;}
|
||||
100% {opacity:1;}
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes fadeIn {
|
||||
0% {opacity:0;}
|
||||
100% {opacity:1;}
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@-o-keyframes fadeIn {
|
||||
0% {opacity:0;}
|
||||
100% {opacity:1;}
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@-ms-keyframes fadeIn {
|
||||
0% {opacity:0;}
|
||||
100% {opacity:1;}
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,12 +4,14 @@ importers:
|
|||
|
||||
.:
|
||||
specifiers:
|
||||
'@trivago/prettier-plugin-sort-imports': ^3.2.0
|
||||
prettier: ^2.6.2
|
||||
turbo: ^1.2.4
|
||||
zustand: ^3.7.2
|
||||
dependencies:
|
||||
zustand: 3.7.2
|
||||
devDependencies:
|
||||
'@trivago/prettier-plugin-sort-imports': 3.2.0_prettier@2.6.2
|
||||
prettier: 2.6.2
|
||||
turbo: 1.2.4
|
||||
|
||||
|
@ -2178,7 +2180,6 @@ packages:
|
|||
|
||||
/@types/prop-types/15.7.5:
|
||||
resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
|
||||
dev: true
|
||||
|
||||
/@types/qs/6.9.7:
|
||||
resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==}
|
||||
|
@ -2239,7 +2240,6 @@ packages:
|
|||
'@types/prop-types': 15.7.5
|
||||
'@types/scheduler': 0.16.2
|
||||
csstype: 3.0.11
|
||||
dev: true
|
||||
|
||||
/@types/responselike/1.0.0:
|
||||
resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==}
|
||||
|
@ -2249,7 +2249,6 @@ packages:
|
|||
|
||||
/@types/scheduler/0.16.2:
|
||||
resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==}
|
||||
dev: true
|
||||
|
||||
/@types/serve-static/1.13.10:
|
||||
resolution: {integrity: sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==}
|
||||
|
|
Loading…
Reference in a new issue