Files
spacedrive/interface/app/$libraryId/Explorer/ContextMenu/OpenWith.tsx
Vítor Vasconcellos ea92383b78 Improve file thumbnails and Quick Preview (+ some code clean-up and rust deps update) (#2758)
* Update rspc, prisma-client-rust, axum and tanstack-query
 - Deleted some unused examples and fully commented out frontend code
 - Implement many changes required due to the updates
 - Update most rust dependencies

* Re-enable p2p

* Fix server

* Auto format

* Fix injected script format
 - Update some github actions
 - Update pnpm lock file

* Fix devtools showing up when app opens
 - Fix million complaining about Sparkles component

* Fix sd-server

* Fix and improve thumbnails rendering
 - Fix core always saying a new thumbnail was generated even for files that it skiped thumbnail generation
 - Rewrite FileThumb and improve related components

* Ignore tmp files when running prettier

* Improve FileThumb component performance
 - Rework useExplorerDraggable and useExplorerItemData hooks due to reduce unecessary re-renders

* More fixes for thumb component
 - A couple of minor performance improvements to frontend code

* auto format

* Fix Thumbnail and QuickPreview

* Fix logic for when to show 'fail to load original' error message in QuickPreview
 - Updated prisma-client-rust, libp2p, tauri, tauri-specta, rspc and hyper

* Fix type checking
 - Format scripts

* Add script prettier config

* Fix serde missing feature
 - Use rust-libp2p spacedrive fork again
 - Update rspc

* Autoformat + fix pnpm lock

* Fix thumbnail first load again

* Autoformat

* autoformat

* Fix rust-libp2p fork url again?

* Remove usePathsInfiniteQuery hook

* Update tauri 2.0.6
2024-10-21 15:47:40 +00:00

144 lines
3.4 KiB
TypeScript

import { useQuery } from '@tanstack/react-query';
import { Suspense } from 'react';
import { useLibraryContext } from '@sd/client';
import { toast } from '@sd/ui';
import { Menu } from '~/components/Menu';
import { useLocale } from '~/hooks';
import { OpenWithApplication, Platform, Result, usePlatform } from '~/util/Platform';
import { ConditionalItem } from './ConditionalItem';
import { useContextMenuContext } from './context';
export default new ConditionalItem({
useCondition: () => {
const { selectedFilePaths, selectedEphemeralPaths } = useContextMenuContext();
const {
getFilePathOpenWithApps,
openFilePathWith,
getEphemeralFilesOpenWithApps,
openEphemeralFileWith
} = usePlatform();
if (
!getFilePathOpenWithApps ||
!openFilePathWith ||
!getEphemeralFilesOpenWithApps ||
!openEphemeralFileWith
)
return null;
if (selectedFilePaths.some((p) => p.is_dir) || selectedEphemeralPaths.some((p) => p.is_dir))
return null;
return {
getFilePathOpenWithApps,
openFilePathWith,
getEphemeralFilesOpenWithApps,
openEphemeralFileWith
};
},
Component: ({
getFilePathOpenWithApps,
openFilePathWith,
getEphemeralFilesOpenWithApps,
openEphemeralFileWith
}) => {
const { t } = useLocale();
return (
<Menu.SubMenu label={t('open_with')}>
<Suspense>
<Items
actions={{
getFilePathOpenWithApps,
openFilePathWith,
getEphemeralFilesOpenWithApps,
openEphemeralFileWith
}}
/>
</Suspense>
</Menu.SubMenu>
);
}
});
const Items = ({
actions
}: {
actions: Required<
Pick<
Platform,
| 'getFilePathOpenWithApps'
| 'openFilePathWith'
| 'getEphemeralFilesOpenWithApps'
| 'openEphemeralFileWith'
>
>;
}) => {
const { selectedFilePaths, selectedEphemeralPaths } = useContextMenuContext();
const { library } = useLibraryContext();
const ids = selectedFilePaths.map((obj) => obj.id);
const paths = selectedEphemeralPaths.map((obj) => obj.path);
const { t } = useLocale();
const { data: apps } = useQuery({
queryKey: ['openWith', ids, paths],
queryFn: async () => {
const handleError = (res: Result<OpenWithApplication[], null>) => {
if (res?.status === 'error') {
toast.error('Failed to get applications capable to open file');
if (res.error) console.error(res.error);
return [];
}
return res?.data;
};
return Promise.all([
ids.length > 0
? actions.getFilePathOpenWithApps(library.uuid, ids).then(handleError)
: Promise.resolve([]),
paths.length > 0
? actions.getEphemeralFilesOpenWithApps(paths).then(handleError)
: Promise.resolve([])
])
.then((res) => res.flat())
.then((res) => res.sort((a, b) => a.name.localeCompare(b.name)));
},
initialData: []
});
return (
<>
{apps.length > 0 ? (
apps.map((data, index) => (
<Menu.Item
key={index}
onClick={async () => {
try {
if (ids.length > 0) {
await actions.openFilePathWith(
library.uuid,
ids.map((id) => [id, data.url])
);
}
if (paths.length > 0) {
await actions.openEphemeralFileWith(
paths.map((path) => [path, data.url])
);
}
} catch (e) {
toast.error(t('failed_to_open_file_with', { data: data.url }));
}
}}
>
{data.name}
</Menu.Item>
))
) : (
<p className="w-full text-center text-sm text-gray-400">{t('no_apps_available')}</p>
)}
</>
);
};