Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/subscription pods #580

Merged
merged 5 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
737 changes: 487 additions & 250 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"@emotion/react": "^11.4.1",
"@emotion/styled": "^11.3.0",
"@fairdatasociety/blossom": "^0.5.0",
"@fairdatasociety/fdp-storage": "^0.13.0",
"@fairdatasociety/fdp-storage": "^0.19.0",
"@headlessui/react": "^1.7.14",
"@metamask/sdk": "^0.5.6",
"@types/react-blockies": "^1.4.1",
Expand Down
23 changes: 17 additions & 6 deletions src/api/files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import {
FileItem,
UploadProgressInfo,
} from '@fairdatasociety/fdp-storage';
import { PodShareInfo } from '@fairdatasociety/fdp-storage/dist/pod/types';
import { isSharedPod } from '@utils/pod';
import { formatUrl } from '@utils/url';

interface DownloadFileData {
filename: string;
directory: string;
podName: string;
pod: string | PodShareInfo;
}

interface ShareFileData {
Expand Down Expand Up @@ -54,12 +56,21 @@ export async function downloadFile(
fdp: FdpStorage,
data: DownloadFileData
): Promise<Blob> {
const { pod, directory, filename } = data;
const writePath =
data.directory === 'root' ? '/' : '/' + formatUrl(data.directory) + '/';
const downloadFile = await fdp.file.downloadData(
data.podName,
`${writePath}${data.filename}`
);
data.directory === 'root' ? '/' : '/' + formatUrl(directory) + '/';
const path = `${writePath}${filename}`;
let downloadFile: Uint8Array;

if (isSharedPod(pod)) {
downloadFile = await fdp.file.downloadArbitraryPodData(
pod.podAddress,
pod.password,
path
);
} else {
downloadFile = await fdp.file.downloadData(pod, path);
}

return new Blob([downloadFile]);
}
Expand Down
43 changes: 41 additions & 2 deletions src/api/pod.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { SubItem } from '@data/subscription';
import { DirectoryItem, FdpStorage } from '@fairdatasociety/fdp-storage';
import { PodShareInfo } from '@fairdatasociety/fdp-storage/dist/pod/types';
import { isSharedPod } from '@utils/pod';

export interface GetPodResponse {
pod_name: string[];
Expand All @@ -16,6 +19,35 @@ export async function getPods(fdp: FdpStorage): Promise<GetPodResponse> {
return response as GetPodResponse;
}

export async function getUsersSubItems(
fdp: FdpStorage,
address: string
): Promise<SubItem[]> {
return fdp.dataHub.getAllSubItems(address);
}

export async function getSubscriptionPods(
fdp: FdpStorage,
subItems: SubItem[]
): Promise<PodShareInfo[]> {
const subs: PodShareInfo[] = [];

for (const subItem of subItems) {
try {
const sub = await fdp.personalStorage.openSubscribedPod(
subItem.subHash,
subItem.unlockKeyLocation
);

subs.push(sub);
} catch (error) {
console.warn(String(error));
}
}

return subs;
}

export async function createPod(fdp: FdpStorage, pod_name: string) {
return await fdp.personalStorage.create(pod_name);
}
Expand All @@ -38,8 +70,15 @@ export function getFdpPathByDirectory(directory: string): string {

export async function getFilesAndDirectories(
fdp: FdpStorage,
podName: string,
pod: string | PodShareInfo,
directory: string
): Promise<DirectoryItem> {
return fdp.directory.read(podName, getFdpPathByDirectory(directory), false);
if (isSharedPod(pod)) {
return fdp.directory.readFromShared(
pod,
getFdpPathByDirectory(directory),
false
);
}
return fdp.directory.read(pod, getFdpPathByDirectory(directory), false);
}
53 changes: 35 additions & 18 deletions src/components/Buttons/DriveToggle/DriveToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@ import { FC } from 'react';

interface DriveToggleProps {
activeTab: string;
showSubscribed: boolean;
setActiveTab: (tab: string) => void;
}

const DriveToggle: FC<DriveToggleProps> = ({ activeTab, setActiveTab }) => {
const DriveToggle: FC<DriveToggleProps> = ({
activeTab,
showSubscribed,
setActiveTab,
}) => {
const { intl } = useLocales();

const activeClass =
Expand All @@ -16,24 +21,36 @@ const DriveToggle: FC<DriveToggleProps> = ({ activeTab, setActiveTab }) => {
'font-normal text-color-accents-plum-black dark:text-color-accents-grey-cloud bg-color-shade-dark-4-day dark:bg-color-shade-dark-3-night effect-style-small-button-drop-shadow';

return (
<div className="flex justify-center items-center w-full text-center">
<button
className={`${
activeTab === 'private' ? activeClass : inactiveClass
} flex-grow py-2 px-3 rounded-l`}
onClick={() => setActiveTab('private')}
>
{intl.get('PRIVATE')}
</button>
<div className="flex flex-col justify-center items-center w-full text-center">
<div className="flex">
<button
className={`${
activeTab === 'private' ? activeClass : inactiveClass
} flex-grow py-2 px-3 rounded-l`}
onClick={() => setActiveTab('private')}
>
{intl.get('PRIVATE')}
</button>

<button
className={`${
activeTab === 'shared' ? activeClass : inactiveClass
} flex-grow py-2 px-3 rounded-r`}
onClick={() => setActiveTab('shared')}
>
{intl.get('SHARED')}
</button>
<button
className={`${
activeTab === 'shared' ? activeClass : inactiveClass
} flex-grow py-2 px-3 rounded-r`}
onClick={() => setActiveTab('shared')}
>
{intl.get('SHARED')}
</button>
</div>
{showSubscribed && (
<button
className={`${
activeTab === 'subscribed' ? activeClass : inactiveClass
} flex-grow py-2 px-3 rounded-r`}
onClick={() => setActiveTab('subscribed')}
>
{intl.get('SUBSCRIBED')}
</button>
)}
</div>
);
};
Expand Down
28 changes: 18 additions & 10 deletions src/components/Cards/EmptyDirectoryCard/EmptyDirectoryCard.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import InfoDarkIcon from '@media/UI/info-dark.svg';
import { useLocales } from '@context/LocalesContext';
import { Button } from '@components/Buttons';
import { useContext } from 'react';
import PodContext from '@context/PodContext';
import { isSharedPod } from '@utils/pod';

export interface EmptyDirectoryCardProps {
onUploadClick: () => void;
}

const EmptyDirectoryCard = ({ onUploadClick }: EmptyDirectoryCardProps) => {
const { intl } = useLocales();
const { activePod } = useContext(PodContext);

return (
<div className="flex justify-center items-center w-full pt-10">
Expand All @@ -21,17 +25,21 @@ const EmptyDirectoryCard = ({ onUploadClick }: EmptyDirectoryCardProps) => {
{intl.get('NO_ITEMS')}
</h2>

<p className="mt-2 font-normal text-xs text-color-accents-plum-black dark:text-color-shade-light-2-night text-center">
{intl.get('START_UPLOADING_OR_CREATING_FOLDERS')}
</p>
{!isSharedPod(activePod) && (
<>
<p className="mt-2 font-normal text-xs text-color-accents-plum-black dark:text-color-shade-light-2-night text-center">
{intl.get('START_UPLOADING_OR_CREATING_FOLDERS')}
</p>

<Button
className="mt-4"
variant="tertiary-outlined"
onClick={onUploadClick}
>
{intl.get('UPLOAD')}
</Button>
<Button
className="mt-4"
variant="tertiary-outlined"
onClick={onUploadClick}
>
{intl.get('UPLOAD')}
</Button>
</>
)}
</div>
</div>
</div>
Expand Down
12 changes: 7 additions & 5 deletions src/components/Cards/PodCard/PodCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@ import { useContext } from 'react';
import DriveLightIcon from '@media/UI/drive-active-light.svg';
import DriveDarkIcon from '@media/UI/drive-active-dark.svg';
import shortenString from '@utils/shortenString';
import { PodShareInfo } from '@fairdatasociety/fdp-storage/dist/pod/types';
import { getPodName } from '@utils/pod';

interface PodCardProps {
podName: string;
onClick: (podName: string) => void;
pod: string | PodShareInfo;
onClick: (podName: string | PodShareInfo) => void;
}

export default function PodCard({ podName, onClick }: PodCardProps) {
export default function PodCard({ pod, onClick }: PodCardProps) {
const { theme } = useContext(ThemeContext);

return (
<div
className="w-32 mb-2 py-2 py-8 flex-column cursor-pointer dark:hover:shadow-soft-purple hover:shadow-soft-purple"
onClick={() => onClick(podName)}
onClick={() => onClick(pod)}
>
<span className="flex text-color-accents-grey-lavendar dark:text-color-shade-dark-1-night">
<div className="mx-auto">
Expand All @@ -24,7 +26,7 @@ export default function PodCard({ podName, onClick }: PodCardProps) {
</span>

<h4 className="text-sm px-1 mt-2 overflow-x-hidden font-medium text-center text-color-shade-light-1-day dark:text-color-shade-light-1-night">
{shortenString(podName, 24)}
{shortenString(getPodName(pod), 24)}
</h4>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/Connect/Metamask/MetamaskConnect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const MetamaskConnect = ({ onConnect }: MetamaskConnectProps) => {
const wallet = await decryptWallet(localBasicWallet, password);
const mnemonic = wallet.mnemonic.phrase;
markInviteAsParticipated();
setFdpStorageType('native', network.config);
setFdpStorageType('native', network.ensConfig, network.datahubConfig);
fdpClientRef.current.account.setAccountFromMnemonic(mnemonic);
setIsLoggedIn(true);
setLoginType('metamask');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import UserContext from '@context/UserContext';
import { Network } from '@data/networks';
import { estimateRegistrationPrice, getAccountBalance } from '@utils/ens';
import { sendAmount, switchToNetwork } from '@utils/metamask';
import { BigNumber, utils } from 'ethers';
import { BigNumber, Wallet, utils } from 'ethers';
import { useContext, useEffect, useRef, useState } from 'react';
import InfoLight from '@media/UI/info-light.svg';
import InfoDark from '@media/UI/info-dark.svg';
Expand Down Expand Up @@ -96,7 +96,8 @@ export default function MetamaskCreateAccount({
}

await fdpClientRef.current.account.register(request);
setWallet(fdpClientRef.current.account.wallet);
const wallet = new Wallet(fdpClientRef.current.account.wallet.privateKey);
setWallet(wallet);
setFdpStorageType('native');
setIsLoggedIn(true);
setLoginType('username');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default function MetamaskUsernamePassword({
setLoading(true);
setErrorMessage(null);

setFdpStorageConfig(network.config);
setFdpStorageConfig(network.ensConfig, network.datahubConfig);

const usernameAvailable =
await fdpClientRef.current.account.ens.isUsernameAvailable(username);
Expand Down
9 changes: 8 additions & 1 deletion src/components/DirectoryPath/DirectoryPath.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import PageDownLight from '@media/UI/page-down-light.svg';
import PageDownDark from '@media/UI/page-down-dark.svg';
import { Button } from '@components/Buttons';
import ThemeContext from '@context/ThemeContext';
import { useLocales } from '@context/LocalesContext';

interface DirectoryPathProps {
podName: string;
subscribedPod: boolean;
directory: string;
onDirectorySelect: (newDirectory: string) => void;
onBackToDrive: () => void;
Expand All @@ -19,6 +21,7 @@ const selectableClasses = 'cursor-pointer hover:bg-color-shade-dark-3-day';

const DirectoryPath = ({
podName,
subscribedPod,
directory,
onDirectorySelect,
onBackToDrive,
Expand All @@ -29,6 +32,7 @@ const DirectoryPath = ({
const folders = (directory === 'root' ? '' : directory).split('/');
return [folders, folders.slice(-MAX_FOLDERS)];
}, [directory]);
const { intl } = useLocales();

const offset = folders.length - displayedFolders.length;

Expand All @@ -54,10 +58,13 @@ const DirectoryPath = ({
)}

<span
className={`hidden md:inline ${folderClasses} ${selectableClasses}`}
className={`relative hidden md:inline ${folderClasses} ${selectableClasses}`}
onClick={() => onDirectorySelect('root')}
>
{podName}
{subscribedPod && (
<div className="text-xs">({intl.get('SUBSCRIBED')})</div>
)}
</span>
{offset > 0 && <span className={folderClasses}>&nbsp;/ ...</span>}
{displayedFolders.map((folder, index) => (
Expand Down
Loading
Loading