Fix Linux release (#2081)

* Fix Linux release
 - Pin appimage-builder to latest master
 - Add required cmp option to AppImageBuilder.yml
 - Disable intro video on Linux (it breaks onboarding for some reason)

* Auto format

* Fix typecheck
This commit is contained in:
Vítor Vasconcellos 2024-02-13 15:26:19 -03:00 committed by GitHub
parent a18d60aa27
commit 7aae22e83f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
40 changed files with 171 additions and 173 deletions

View file

@ -1 +1 @@
Fork of [tauri-plugin-window-state]( https://github.com/tauri-apps/plugins-workspace/blob/v1/plugins/window-state).
Fork of [tauri-plugin-window-state](https://github.com/tauri-apps/plugins-workspace/blob/v1/plugins/window-state).

View file

@ -109,7 +109,7 @@ function AppInner() {
: Math.max(routerAtIndex.maxIndex, history.index)
};
return [...routers]
return [...routers];
});
});
@ -148,7 +148,7 @@ function AppInner() {
() => ({
setTitle(id, title) {
setTabs((tabs) => {
const tabIndex = tabs.findIndex(t => t.id === id);
const tabIndex = tabs.findIndex((t) => t.id === id);
if (tabIndex === -1) return tabs;
tabs[tabIndex] = { ...tabs[tabIndex]!, title };

View file

@ -10,4 +10,4 @@ globalThis.rspcLinks = [
];
globalThis.onHotReload = (func: () => void) => {
if (import.meta.hot) import.meta.hot.dispose(func);
}
};

View file

@ -1,11 +1,10 @@
import { OperatingSystem, Platform } from '@sd/interface';
import { dialog, invoke, os, shell } from '@tauri-apps/api';
import { confirm } from '@tauri-apps/api/dialog';
import { homeDir } from '@tauri-apps/api/path';
import { open } from '@tauri-apps/api/shell';
// @ts-expect-error: Doesn't have a types package.
import ConsistentHash from 'consistent-hash';
import { OperatingSystem, Platform } from '@sd/interface';
import { commands, events } from './commands';
import { env } from './env';
@ -36,7 +35,6 @@ function constructServerUrl(urlSuffix: string) {
if (!customUriServerUrl)
throw new Error("'window.__SD_CUSTOM_URI_SERVER__' was not injected correctly!");
hr = new ConsistentHash();
customUriServerUrl.forEach((url) => hr.add(url));
}

View file

@ -19,11 +19,7 @@ export function MobileDropdown() {
return (
<Dropdown.Root
button={
<Button
aria-label="mobile-menu"
className="hover:!bg-transparent"
size="icon"
>
<Button aria-label="mobile-menu" className="hover:!bg-transparent" size="icon">
<DotsThreeVertical weight="bold" className="h-6 w-6 " />
</Button>
}

View file

@ -21,7 +21,7 @@ const metroConfig = makeMetroConfig({
resolver: {
...expoDefaultConfig.resolver,
extraNodeModules: {
'react-native-svg': reactSVGPath,
'react-native-svg': reactSVGPath
},
blockList: exclusionList([reactSVGExclude, rspcClientExclude, rspcReactExclude]),
sourceExts: [...expoDefaultConfig.resolver.sourceExts, 'svg'],

View file

@ -67,7 +67,7 @@ const BrowseTags = () => {
return (
<View style={tw`gap-5`}>
<View style={tw`flex-row items-center justify-between w-full px-7`}>
<View style={tw`w-full flex-row items-center justify-between px-7`}>
<Text style={tw`text-lg font-bold text-white`}>Tags</Text>
<View style={tw`flex-row gap-3`}>
<Pressable onPress={() => navigation.navigate('Tags')}>
@ -81,7 +81,7 @@ const BrowseTags = () => {
</Pressable>
<Pressable testID="add-tag" onPress={() => modalRef.current?.present()}>
<View
style={tw`items-center justify-center w-8 h-8 bg-transparent border border-dashed rounded-md border-ink-faint`}
style={tw`h-8 w-8 items-center justify-center rounded-md border border-dashed border-ink-faint bg-transparent`}
>
<Plus weight="bold" size={18} style={tw`text-ink-faint`} />
</View>
@ -96,7 +96,7 @@ const BrowseTags = () => {
style={tw`relative h-auto w-[85.5vw] flex-col items-center justify-center overflow-hidden rounded-md border border-dashed border-sidebar-line p-4`}
>
<Icon name="Tags" size={38} />
<Text style={tw`mt-2 font-medium text-center text-ink-dull`}>
<Text style={tw`mt-2 text-center font-medium text-ink-dull`}>
You have no tags
</Text>
</View>

View file

@ -29,7 +29,7 @@ const CATEGORIES_LIST = [
const Categories = () => {
return (
<View style={tw`relative gap-5`}>
<Text style={tw`text-lg font-bold text-white px-7`}>Library</Text>
<Text style={tw`px-7 text-lg font-bold text-white`}>Library</Text>
<Fade width={30} height="100%" color="mobile-screen">
<ScrollView showsHorizontalScrollIndicator={false} horizontal>
<View style={tw`flex-row gap-2 px-7`}>

View file

@ -10,7 +10,7 @@ import Fade from '../layout/Fade';
const Jobs = () => {
return (
<View style={tw`gap-5`}>
<View style={tw`flex-row items-center justify-between w-full px-7`}>
<View style={tw`w-full flex-row items-center justify-between px-7`}>
<Text style={tw`text-lg font-bold text-white`}>Jobs</Text>
</View>
<Fade color="mobile-screen" height="100%" width={30}>
@ -48,15 +48,15 @@ const Job = ({ progress, message, error }: JobProps) => {
style={tw`h-[170px] w-[310px] flex-col rounded-md border border-app-line/50 bg-app-box/50`}
>
<View
style={tw`flex-row items-center justify-between w-full px-5 py-2 border-b rounded-t-md border-sidebar-line/80 bg-mobile-header/50`}
style={tw`w-full flex-row items-center justify-between rounded-t-md border-b border-sidebar-line/80 bg-mobile-header/50 px-5 py-2`}
>
<View style={tw`flex-row items-center gap-2`}>
<FolderIcon size={36} />
<Text style={tw`font-bold text-white text-md`}>Added Memories</Text>
<Text style={tw`text-md font-bold text-white`}>Added Memories</Text>
</View>
<DotsThreeOutlineVertical weight="fill" size={20} color={tw.color('ink-faint')} />
</View>
<View style={tw`flex-row items-center justify-between flex-1 gap-5 px-5 py-3 mx-auto`}>
<View style={tw`mx-auto flex-1 flex-row items-center justify-between gap-5 px-5 py-3`}>
<AnimatedCircularProgress
size={80}
width={7}

View file

@ -78,8 +78,8 @@ export default function Header({
Platform.OS === 'android' ? 'pt-5' : 'pt-10'
)}
>
<View style={tw`justify-center w-full h-auto pb-5 mx-auto mt-5 px-7`}>
<View style={tw`flex-row items-center justify-between w-full`}>
<View style={tw`mx-auto mt-5 h-auto w-full justify-center px-7 pb-5`}>
<View style={tw`w-full flex-row items-center justify-between`}>
<View style={tw`flex-row items-center gap-5`}>
{navBack && (
<Pressable

View file

@ -11,7 +11,7 @@ export default function Search({ placeholder }: Props) {
const searchStore = getSearchStore();
return (
<View
style={tw`flex flex-row items-center justify-between w-full px-3 mt-4 border rounded-md shadow-sm h-11 border-sidebar-line bg-sidebar-button`}
style={tw`mt-4 flex h-11 w-full flex-row items-center justify-between rounded-md border border-sidebar-line bg-sidebar-button px-3 shadow-sm`}
>
<TextInput
onChangeText={(text) => searchStore.setSearch(text)}

View file

@ -24,10 +24,10 @@ export function SettingsItem(props: SettingsItemProps) {
return (
<Pressable onPress={props.onPress}>
<View style={twStyle(' border-app-line/50 bg-app-box/50', borderRounded, border)}>
<View style={tw`flex-row items-center h-auto`}>
<View style={tw`h-auto flex-row items-center`}>
{props.leftIcon && (
<View
style={tw`items-center justify-center w-8 h-8 ml-4 mr-5 border rounded-full bg-app-input border-app-line`}
style={tw`ml-4 mr-5 h-8 w-8 items-center justify-center rounded-full border border-app-line bg-app-input`}
>
{props.leftIcon({ size: 20, color: tw.color('ink-dull') })}
</View>

View file

@ -49,7 +49,7 @@ module.exports = {
mobile: {
header: `hsla(${DARK_HUE}, 15%, 10%, ${ALPHA})`,
screen: `hsla(${DARK_HUE}, 15%, 12%, ${ALPHA})`,
navtab: `hsla(${DARK_HUE}, 15%, 8%, ${ALPHA})`,
navtab: `hsla(${DARK_HUE}, 15%, 8%, ${ALPHA})`
},
app: {
DEFAULT: `hsla(${DARK_HUE}, 15%, 13%, ${ALPHA})`,
@ -70,7 +70,7 @@ module.exports = {
// menu
menu: `hsla(${DARK_HUE}, 25%, 5%, ${ALPHA})`,
// input
input: `hsla(${DARK_HUE}, 15%, 20%, ${ALPHA})`,
input: `hsla(${DARK_HUE}, 15%, 20%, ${ALPHA})`
},
sidebar: {
box: `hsla(${DARK_HUE}, 15%, 16%, ${ALPHA})`,

View file

@ -8,12 +8,12 @@ module.exports = function (theme) {
extend: {
colors: theme ? COLORS[theme] : COLORS.dark,
fontSize: {
md: '16px',
},
md: '16px'
}
}
},
variants: {
extend: {}
},
}
};
};

View file

@ -1,6 +1,6 @@
import { Themes } from '@sd/client';
import { ComponentType, createElement, forwardRef } from 'react';
import { create } from 'twrnc';
import { Themes } from '@sd/client';
let tw = create(require('../constants/style/tailwind.js')());

View file

@ -92,7 +92,7 @@ const LocationItem: React.FC<LocationItemProps> = ({
return (
<Pressable onPress={onPress}>
<View
style={tw`flex-row justify-between w-full h-auto gap-3 p-2 border rounded-md border-sidebar-line/50 bg-sidebar-box`}
style={tw`h-auto w-full flex-row justify-between gap-3 rounded-md border border-sidebar-line/50 bg-sidebar-box p-2`}
>
<View style={tw`flex-row items-center gap-2`}>
<View style={tw`relative`}>
@ -114,7 +114,7 @@ const LocationItem: React.FC<LocationItemProps> = ({
<View style={tw`flex-row items-center gap-3`}>
<View style={tw`rounded-md bg-app-input p-1.5`}>
<Text
style={tw`text-xs font-bold text-left text-ink-dull`}
style={tw`text-left text-xs font-bold text-ink-dull`}
numberOfLines={1}
>
{`${byteSize(location.size_in_bytes)}`}

View file

@ -29,7 +29,7 @@ export function OnboardingContainer({ children }: React.PropsWithChildren) {
)}
>
<Video
style={tw`w-[700px] h-[700px]`}
style={tw`h-[700px] w-[700px]`}
shouldPlay
onPlaybackStatusUpdate={(status) => {
if (status.isLoaded && status.didJustFinish) {
@ -50,22 +50,22 @@ export function OnboardingContainer({ children }: React.PropsWithChildren) {
<CaretLeft size={24} weight="bold" color="white" />
</Pressable>
)}
<View style={tw`z-10 items-center justify-center flex-1`}>
<View style={tw`z-10 flex-1 items-center justify-center`}>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
keyboardVerticalOffset={bottom}
style={tw`items-center justify-center flex-1 w-full`}
style={tw`w-full flex-1 items-center justify-center`}
>
<MotiView style={tw`items-center justify-center w-full px-4`}>
<MotiView style={tw`w-full items-center justify-center px-4`}>
{children}
</MotiView>
</KeyboardAvoidingView>
<Text style={tw`absolute text-xs bottom-8 text-ink-dull/50`}>
<Text style={tw`absolute bottom-8 text-xs text-ink-dull/50`}>
&copy; {new Date().getFullYear()} Spacedrive Technology Inc.
</Text>
</View>
{/* Bloom */}
<Image source={BloomOne} style={tw`absolute w-screen h-screen top-100 opacity-20`} />
<Image source={BloomOne} style={tw`top-100 absolute h-screen w-screen opacity-20`} />
</View>
);
}
@ -105,7 +105,7 @@ const GetStartedScreen = ({ navigation }: OnboardingStackScreenProps<'GetStarted
{/* Get Started Button */}
<FadeInUpAnimation delay={1200} style={tw`mt-8`}>
<AnimatedButton variant="accent" onPress={() => navigation.push('NewLibrary')}>
<Text style={tw`text-base font-medium text-center text-ink`}>Get Started</Text>
<Text style={tw`text-center text-base font-medium text-ink`}>Get Started</Text>
</AnimatedButton>
</FadeInUpAnimation>
</OnboardingContainer>

View file

@ -38,7 +38,7 @@ const LibraryGeneralSettingsScreen = (_: SettingsStackScreenProps<'LibraryGenera
return (
<View style={tw`gap-4`}>
<View style={tw`px-2 mt-4`}>
<View style={tw`mt-4 px-2`}>
<SettingsTitle>Name</SettingsTitle>
<Controller
name="name"

View file

@ -1,8 +1,8 @@
import { Tag, useCache, useLibraryQuery, useNodes } from '@sd/client';
import { CaretRight, Pen, Trash } from 'phosphor-react-native';
import { useEffect, useRef } from 'react';
import { Animated, FlatList, Text, View } from 'react-native';
import { Swipeable } from 'react-native-gesture-handler';
import { Tag, useCache, useLibraryQuery, useNodes } from '@sd/client';
import { ModalRef } from '~/components/layout/Modal';
import DeleteTagModal from '~/components/modal/confirmModals/DeleteTagModal';
import CreateTagModal from '~/components/modal/tag/CreateTagModal';

View file

@ -1,9 +1,9 @@
import { resetStore } from '@sd/client';
import { proxy, useSnapshot } from 'valtio';
import { proxySet } from 'valtio/utils';
import { resetStore } from '@sd/client';
// TODO: Add "media"
export type ExplorerLayoutMode = 'list' | 'grid' | "media"
export type ExplorerLayoutMode = 'list' | 'grid' | 'media';
export type ExplorerKind = 'Location' | 'Tag' | 'Space';

View file

@ -1,5 +1,4 @@
import { proxy, useSnapshot } from "valtio";
import { proxy, useSnapshot } from 'valtio';
/**
This is subject to change, but the idea is to have a global store for search
@ -13,7 +12,7 @@ const searchStore = proxy({
setSearch: (search: string) => {
searchStore.search = search;
}
})
});
export function useSearchStore() {
return useSnapshot(searchStore);

View file

@ -3,100 +3,87 @@
* If you rename or delete an asset you need to run `npx expo prebuild --clean` to delete them in your android and ios folder as well.
*/
const {
withDangerousMod,
withXcodeProject,
IOSConfig,
} = require("@expo/config-plugins");
const fs = require("fs");
const path = require("path");
const { withDangerousMod, withXcodeProject, IOSConfig } = require('@expo/config-plugins');
const fs = require('fs');
const path = require('path');
// Specify the source directory of your assets
const ASSET_SOURCE_DIR = "assets/rive";
const ASSET_SOURCE_DIR = 'assets/rive';
const IOS_GROUP_NAME = "Rivassets";
const IOS_GROUP_NAME = 'Rivassets';
const withRiveAssets = (config) => {
config = addAndroidResources(config);
config = addIOSResources(config);
return config;
config = addAndroidResources(config);
config = addIOSResources(config);
return config;
};
// Code inspired by https://github.com/rive-app/rive-react-native/issues/185#issuecomment-1593396573
function addAndroidResources(config) {
return withDangerousMod(config, [
"android",
async (config) => {
// Get the path to the Android project directory
const projectRoot = config.modRequest.projectRoot;
return withDangerousMod(config, [
'android',
async (config) => {
// Get the path to the Android project directory
const projectRoot = config.modRequest.projectRoot;
// Get the path to the Android resources directory
const resDir = path.join(
projectRoot,
"android",
"app",
"src",
"main",
"res"
);
// Get the path to the Android resources directory
const resDir = path.join(projectRoot, 'android', 'app', 'src', 'main', 'res');
// Create the 'raw' directory if it doesn't exist
const rawDir = path.join(resDir, "raw");
fs.mkdirSync(rawDir, { recursive: true });
// Create the 'raw' directory if it doesn't exist
const rawDir = path.join(resDir, 'raw');
fs.mkdirSync(rawDir, { recursive: true });
// Get the path to the assets directory
const assetSourcePath = path.join(projectRoot, ASSET_SOURCE_DIR);
// Get the path to the assets directory
const assetSourcePath = path.join(projectRoot, ASSET_SOURCE_DIR);
// Retrieve all files in the assets directory
const assetFiles = fs.readdirSync(assetSourcePath);
// Retrieve all files in the assets directory
const assetFiles = fs.readdirSync(assetSourcePath);
// Move each asset file to the resources 'raw' directory
for (const assetFile of assetFiles) {
const srcAssetPath = path.join(assetSourcePath, assetFile);
const destAssetPath = path.join(rawDir, assetFile);
fs.copyFileSync(srcAssetPath, destAssetPath);
}
// Move each asset file to the resources 'raw' directory
for (const assetFile of assetFiles) {
const srcAssetPath = path.join(assetSourcePath, assetFile);
const destAssetPath = path.join(rawDir, assetFile);
fs.copyFileSync(srcAssetPath, destAssetPath);
}
return config;
},
]);
return config;
}
]);
}
// Code inspired by https://github.com/expo/expo/blob/61f8cf8d4b3cf5f8bf61f346476ebdb4aff40545/packages/expo-font/plugin/src/withFontsIos.ts
function addIOSResources(config) {
return withXcodeProject(config, async (config) => {
const project = config.modResults;
const platformProjectRoot = config.modRequest.platformProjectRoot;
return withXcodeProject(config, async (config) => {
const project = config.modResults;
const platformProjectRoot = config.modRequest.platformProjectRoot;
// Create Assets group in project
IOSConfig.XcodeUtils.ensureGroupRecursively(project, IOS_GROUP_NAME);
// Create Assets group in project
IOSConfig.XcodeUtils.ensureGroupRecursively(project, IOS_GROUP_NAME);
// Get riv filepaths
const projectRoot = config.modRequest.projectRoot;
const assetSourcePath = path.join(projectRoot, ASSET_SOURCE_DIR);
const assetFiles = fs.readdirSync(assetSourcePath);
const assetFilesPaths = assetFiles.map(
(assetFile) => `${assetSourcePath}/${assetFile}`
);
// Get riv filepaths
const projectRoot = config.modRequest.projectRoot;
const assetSourcePath = path.join(projectRoot, ASSET_SOURCE_DIR);
const assetFiles = fs.readdirSync(assetSourcePath);
const assetFilesPaths = assetFiles.map((assetFile) => `${assetSourcePath}/${assetFile}`);
// Add assets to group
addIOSResourceFile(project, platformProjectRoot, assetFilesPaths);
// Add assets to group
addIOSResourceFile(project, platformProjectRoot, assetFilesPaths);
return config;
});
return config;
});
function addIOSResourceFile(project, platformRoot, assetFilesPaths) {
for (const riveFile of assetFilesPaths) {
const riveFilePath = path.relative(platformRoot, riveFile);
IOSConfig.XcodeUtils.addResourceFileToGroup({
filepath: riveFilePath,
groupName: IOS_GROUP_NAME,
project,
isBuildFile: true,
verbose: true,
});
}
}
function addIOSResourceFile(project, platformRoot, assetFilesPaths) {
for (const riveFile of assetFilesPaths) {
const riveFilePath = path.relative(platformRoot, riveFile);
IOSConfig.XcodeUtils.addResourceFileToGroup({
filepath: riveFilePath,
groupName: IOS_GROUP_NAME,
project,
isBuildFile: true,
verbose: true
});
}
}
}
module.exports = withRiveAssets;

View file

@ -1,8 +1,14 @@
import clsx from 'clsx';
import { memo, useMemo } from 'react';
import { byteSize, getItemFilePath, useSelector, type ExplorerItem, useLibraryQuery } from '@sd/client';
import {
byteSize,
getItemFilePath,
useLibraryQuery,
useSelector,
type ExplorerItem
} from '@sd/client';
import { useLocale } from '~/hooks';
import { useExplorerContext } from '../../../Context';
import { ExplorerDraggable } from '../../../ExplorerDraggable';
import { ExplorerDroppable, useExplorerDroppableContext } from '../../../ExplorerDroppable';
@ -110,7 +116,7 @@ const ItemMetadata = () => {
selected={item.selected}
/>
<ItemSize />
{item.data.type === "Label" && <LabelItemCount data={item.data} />}
{item.data.type === 'Label' && <LabelItemCount data={item.data} />}
</ExplorerDraggable>
);
};
@ -148,23 +154,29 @@ const ItemSize = () => {
);
};
function LabelItemCount({data}: {data: Extract<ExplorerItem, {type: "Label"}>}) {
function LabelItemCount({ data }: { data: Extract<ExplorerItem, { type: 'Label' }> }) {
const { t } = useLocale();
const count = useLibraryQuery(["search.objectsCount", {
filters: [{
object: {
labels: {
in: [data.item.id]
const count = useLibraryQuery([
'search.objectsCount',
{
filters: [
{
object: {
labels: {
in: [data.item.id]
}
}
}
}
}]
}])
]
}
]);
if(count.data === undefined) return
return <div className="truncate rounded-md px-1.5 py-[1px] text-center text-tiny text-ink-dull">
{t("item_with_count", {count: count.data})}
</div>
if (count.data === undefined) return;
return (
<div className="truncate rounded-md px-1.5 py-[1px] text-center text-tiny text-ink-dull">
{t('item_with_count', { count: count.data })}
</div>
);
}

View file

@ -38,7 +38,7 @@ const NameCell = memo(({ item, selected }: { item: ExplorerItem; selected: boole
<FileThumb
data={item}
frame
frameClassName={clsx("!border", item.type === "Label" && "!rounded-lg")}
frameClassName={clsx('!border', item.type === 'Label' && '!rounded-lg')}
blackBars
size={35}
className={clsx('mr-2.5', cut && 'opacity-60')}

View file

@ -184,7 +184,7 @@ export const useViewItemDoubleClick = () => {
}
},
[
setSearchParams,
setSearchParams,
explorer.selectedItems,
explorer.settingsStore.openOnDoubleClick,
library.uuid,

View file

@ -1,11 +1,9 @@
import { Plus, X } from '@phosphor-icons/react';
import { useSelector } from '@sd/client';
import { Tooltip } from '@sd/ui';
import clsx from 'clsx';
import { useLayoutEffect, useRef } from 'react';
import useResizeObserver from 'use-resize-observer';
import { useRoutingContext } from '~/RoutingContext';
import { useTabsContext } from '~/TabsContext';
import { useSelector } from '@sd/client';
import { Tooltip } from '@sd/ui';
import {
useKeyMatcher,
useLocale,
@ -13,6 +11,8 @@ import {
useShortcut,
useShowControls
} from '~/hooks';
import { useRoutingContext } from '~/RoutingContext';
import { useTabsContext } from '~/TabsContext';
import { explorerStore } from '../Explorer/store';
import { useTopBarContext } from './Layout';

View file

@ -65,7 +65,7 @@ export function Component() {
center={<SearchBar />}
left={
<div className="flex flex-row items-center gap-2">
<span className="text-sm font-medium truncate">Recents</span>
<span className="truncate text-sm font-medium">Recents</span>
</div>
}
right={<DefaultTopBarOptions />}

View file

@ -84,7 +84,7 @@ export default ({ redirectToSearch }: Props) => {
<Input
ref={searchRef}
placeholder="Search"
className="w-48 mx-2 transition-all duration-200 focus-within:w-60"
className="mx-2 w-48 transition-all duration-200 focus-within:w-60"
size="sm"
value={value}
onChange={(e) => {
@ -98,7 +98,7 @@ export default ({ redirectToSearch }: Props) => {
}}
onFocus={() => search.setSearchBarFocused(true)}
right={
<div className="flex items-center space-x-1 pointer-events-none h-7 opacity-70 group-focus-within:hidden">
<div className="pointer-events-none flex h-7 items-center space-x-1 opacity-70 group-focus-within:hidden">
{
<Shortcut
chars={keybind([ModifierKeys.Control], ['F'])}

View file

@ -19,7 +19,7 @@ function Account() {
return (
<div className="my-2 flex w-full flex-col">
<div className="flex items-center justify-between">
<span className="font-semibold">{t("spacedrive_account")}</span>
<span className="font-semibold">{t('spacedrive_account')}</span>
<Button variant="gray" onClick={auth.logout}>
{t('logout')}
</Button>

View file

@ -23,7 +23,7 @@ export const Component = () => {
<>
<Heading
title={t('backups')}
description={t("backups_description")}
description={t('backups_description')}
rightArea={
<div className="flex flex-row items-center space-x-5">
<Button

View file

@ -3,7 +3,7 @@ import { RouteObject } from 'react-router';
export default [
{ path: 'general', lazy: () => import('./general') },
{ path: 'account', lazy: () => import('./account') },
{ path: 'usage', lazy: () => import('./usage')},
{ path: 'usage', lazy: () => import('./usage') },
{ path: 'appearance', lazy: () => import('./appearance') },
{ path: 'keybindings', lazy: () => import('./keybindings') },
{ path: 'extensions', lazy: () => import('./extensions') },

View file

@ -15,8 +15,8 @@ import Progress from './Progress';
export const Component = () => {
const os = useOperatingSystem(false);
const debugState = useDebugState();
// FIX-ME: Intro video breaks onboarding for the web version
const [showIntro, setShowIntro] = useState(os !== 'browser');
// FIX-ME: Intro video breaks onboarding for the web and Linux versions
const [showIntro, setShowIntro] = useState(os === 'macOS' || os === 'windows');
const ctx = useContextValue();
if (ctx.libraries.isLoading) return null;
@ -46,19 +46,19 @@ export const Component = () => {
</div>
)}
<DragRegion className="z-50 h-9" />
<div className="flex flex-col gap-8 p-10 -mt-5 grow">
<div className="flex flex-col items-center justify-center grow">
<div className="-mt-5 flex grow flex-col gap-8 p-10">
<div className="flex grow flex-col items-center justify-center">
<Outlet />
</div>
<Progress />
</div>
<div className="flex justify-center p-4">
<p className="text-xs opacity-50 text-ink-dull">
<p className="text-xs text-ink-dull opacity-50">
&copy; {new Date().getFullYear()} Spacedrive Technology Inc.
</p>
</div>
<div className="absolute -z-10">
<div className="relative w-screen h-screen">
<div className="relative h-screen w-screen">
<img src={BloomOne} className="absolute h-[2000px] w-[2000px]" />
{/* <img src={BloomThree} className="absolute w-[2000px] h-[2000px] -right-[200px]" /> */}
</div>

View file

@ -388,10 +388,15 @@ body {
}
@keyframes wiggle {
0%, 100% { transform: rotate(-1deg); }
50% { transform: rotate(1deg); }
0%,
100% {
transform: rotate(-1deg);
}
50% {
transform: rotate(1deg);
}
}
.wiggle {
animation: wiggle 200ms infinite;
animation: wiggle 200ms infinite;
}

View file

@ -1,12 +1,3 @@
//@ts-nocheck
// WARNING: Import order matters
window.Prism = window.Prism || {};
Prism.manual = true;
export { highlightElement } from "prismjs";
// Languages
// Do not include default ones: markup, html, xml, svg, mathml, ssml, atom, rss, css, clike, javascript, js
import 'prismjs/components/prism-applescript.js';
@ -58,3 +49,11 @@ import 'prismjs/components/prism-vala.js';
import 'prismjs/components/prism-yaml.js';
import 'prismjs/components/prism-zig.js';
//@ts-nocheck
// WARNING: Import order matters
window.Prism = window.Prism || {};
window.Prism.manual = true;
export { highlightElement } from 'prismjs';

View file

@ -39,7 +39,8 @@ export function getExplorerItemData(data?: ExplorerItem | null): ItemData {
const object = getItemObject(data);
if (object?.kind) itemData.kind = ObjectKind[object?.kind] ?? 'Unknown';
else if(data.type === "NonIndexedPath") itemData.kind = ObjectKind[data.item.kind] ?? 'Unknown';
else if (data.type === 'NonIndexedPath')
itemData.kind = ObjectKind[data.item.kind] ?? 'Unknown';
// Objects only have dateCreated and dateAccessed
itemData.dateCreated = object?.date_created ?? null;

View file

@ -11,8 +11,7 @@ let permits = 0; // A Mutex in JS, lmao
export const getPermits = () => permits;
if ("onHotReload" in globalThis)
globalThis?.onHotReload(() => (permits = 0));
if ('onHotReload' in globalThis) globalThis?.onHotReload(() => (permits = 0));
// A query where the data is streamed in.
// Also basically a subscription with support for React Suspense and proper loading states, invalidation, etc.

View file

@ -11,7 +11,7 @@ export enum ModifierKeys {
NumLock = 'NumLock',
ScrollLock = 'ScrollLock',
Symbol = 'Symbol',
SymbolLock = 'SymbolLock',
SymbolLock = 'SymbolLock'
}
export enum EditingKeys {
@ -20,14 +20,14 @@ export enum EditingKeys {
}
export enum UIKeys {
Escape = 'Escape',
Escape = 'Escape'
}
export enum NavigationKeys {
ArrowUp = 'ArrowUp',
ArrowDown = 'ArrowDown',
ArrowLeft = 'ArrowLeft',
ArrowRight = 'ArrowRight',
ArrowRight = 'ArrowRight'
}
export type OSforKeys = 'macOS' | 'Windows' | 'Other';
@ -54,7 +54,7 @@ export const modifierSymbols: Record<
ArrowUp: { Other: '↑' },
ArrowDown: { Other: '↓' },
ArrowLeft: { Other: '←' },
ArrowRight: { Other: '→' },
ArrowRight: { Other: '→' }
};
export const keySymbols: Record<string, { macOS?: string; Windows?: string; Other: string }> = {

View file

@ -161,5 +161,6 @@ AppDir:
AppImage:
arch: !ENV '${TARGET_APPIMAGE_ARCH}'
comp: xz
sign-key: None
update-information: None

View file

@ -21,6 +21,7 @@ This directory contains the script and recipe to build an AppImage from a Spaced
- Execute the `build_appimage.sh` script inside a `debian:bookworm` container
- Podman: `podman run --rm -v "$(CDPATH='' cd ../.. && pwd -P):/srv" -w /srv debian:bookworm scripts/appimage/build_appimage.sh`
- You may have to run Podman with `podman run --privileged` if you get a permission denied error
- Docker: `docker run --rm -v "$(CDPATH='' cd ../.. && pwd -P):/srv" -w /srv debian:bookworm scripts/appimage/build_appimage.sh`

View file

@ -70,7 +70,7 @@ if ! command -v appimage-builder >/dev/null 2>&1; then
pip3 install wheel setuptools --upgrade
echo 'Install appimage-build in temporary Python virtual environment...'
pip3 install git+https://github.com/AppImageCrafters/appimage-builder.git
pip3 install git+https://github.com/AppImageCrafters/appimage-builder.git@61c8ddde9ef44b85d7444bbe79d80b44a6a5576d
fi
echo 'Running appimage-builder...'