Skip to content
Open
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
4 changes: 2 additions & 2 deletions backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ map $http_origin $cors_origin {

# Define CORS headers once to avoid duplication
map $request_method $cors_allow_headers {
default "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,swarm-postage-batch-id,swarm-pin,swarm-deferred-upload,registry-address,swarm-collection,x-upload-signed-message,x-uploader-address,x-file-name,x-message-content,Swarm-Index-Document,Swarm-Error-Document,swarm-tag,x-upload-session-token,x-multi-file-upload";
OPTIONS "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,swarm-postage-batch-id,swarm-pin,swarm-deferred-upload,registry-address,swarm-collection,x-upload-signed-message,x-uploader-address,x-file-name,x-message-content,Swarm-Index-Document,Swarm-Error-Document,swarm-tag,x-upload-session-token,x-multi-file-upload";
default "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,swarm-postage-batch-id,swarm-pin,swarm-deferred-upload,registry-address,swarm-collection,x-upload-signed-message,x-uploader-address,x-file-name,x-message-content,Swarm-Index-Document,Swarm-Error-Document,swarm-tag,x-upload-session-token,x-multi-file-upload,swarm-redundancy-level";
OPTIONS "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,swarm-postage-batch-id,swarm-pin,swarm-deferred-upload,registry-address,swarm-collection,x-upload-signed-message,x-uploader-address,x-file-name,x-message-content,Swarm-Index-Document,Swarm-Error-Document,swarm-tag,x-upload-session-token,x-multi-file-upload,swarm-redundancy-level";
}

map $request_method $cors_expose_headers {
Expand Down
2 changes: 2 additions & 0 deletions backend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ const verifySignature = async (req, res, next) => {
const messageContent = req.headers['x-message-content'];
const sessionToken = req.headers['x-upload-session-token']; // New header for session token
const isMultiFileUpload = req.headers['x-multi-file-upload'] === 'true'; // New header to indicate multi-file upload
const redundancyLevel = req.headers['swarm-redundancy-level']; // Erasure coding level

console.log('Headers received:', {
signedMessage: signedMessage ? 'exists' : 'missing',
Expand All @@ -95,6 +96,7 @@ const verifySignature = async (req, res, next) => {
messageContent,
sessionToken: sessionToken ? 'exists' : 'missing',
isMultiFileUpload,
redundancyLevel: redundancyLevel || 'not set',
});

// Check for existing session first (for multi-file uploads)
Expand Down
68 changes: 68 additions & 0 deletions src/app/components/ErasureCodingDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from 'react';
import CustomDropdown, { DropdownOption } from './CustomDropdown';

interface ErasureCodingDropdownProps {
selectedLevel: number;
onLevelChange: (level: number) => void;
disabled?: boolean;
className?: string;
}

const ErasureCodingDropdown: React.FC<ErasureCodingDropdownProps> = ({
selectedLevel,
onLevelChange,
disabled = false,
className = '',
}) => {
// Define erasure coding options with icons and descriptions
const erasureCodingOptions: DropdownOption[] = [
{
value: 0,
label: 'None (Default)',
icon: '🔓',
description: 'No erasure coding - standard storage',
},
{
value: 1,
label: 'Medium',
icon: '🛡️',
description: 'Basic protection - ~25% more storage',
},
{
value: 2,
label: 'Strong',
icon: '🔒',
description: 'Enhanced protection - ~50% more storage',
},
{
value: 3,
label: 'Insane',
icon: '🔐',
description: 'High protection - ~100% more storage',
},
{
value: 4,
label: 'Paranoid',
icon: '🏰',
description: 'Maximum protection - ~200% more storage',
},
];

const handleSelect = (value: string | number) => {
onLevelChange(Number(value));
};

return (
<CustomDropdown
options={erasureCodingOptions}
selectedValue={selectedLevel}
onSelect={handleSelect}
placeholder="Select erasure coding level..."
disabled={disabled}
className={className}
showIcons={true}
/>
);
};

export default ErasureCodingDropdown;
17 changes: 14 additions & 3 deletions src/app/components/FileUploadUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export interface FileUploadParams {
serveUncompressed: boolean;
isTarFile: boolean;
isWebpageUpload: boolean;
redundancyLevel?: number;
isFolderUpload?: boolean;
setUploadProgress: (progress: number) => void;
setStatusMessage: (status: ExecutionStatus) => void;
Expand Down Expand Up @@ -56,6 +57,7 @@ export interface MultiFileUploadParams {
beeApiUrl: string;
serveUncompressed: boolean;
isWebpageUpload: boolean;
>>>>>>> origin/main
setUploadProgress: (progress: number) => void;
setStatusMessage: (status: ExecutionStatus) => void;
setIsDistributing: (isDistributing: boolean) => void;
Expand Down Expand Up @@ -136,9 +138,10 @@ export const handleFileUpload = async (params: FileUploadParams): Promise<string
beeApiUrl,
serveUncompressed,
isTarFile,
isWebpageUpload,
isFolderUpload = false,
setUploadProgress,
isWebpageUpload,
redundancyLevel = 0,
isFolderUpload = false,
setUploadProgress,
setStatusMessage,
setIsDistributing,
setUploadStep,
Expand Down Expand Up @@ -337,6 +340,11 @@ export const handleFileUpload = async (params: FileUploadParams): Promise<string
'swarm-collection': serveUncompressed && (isTarFile || isArchive) ? 'true' : 'false',
};

// Add erasure coding redundancy level if specified
if (redundancyLevel > 0) {
baseHeaders['swarm-redundancy-level'] = redundancyLevel.toString();
}

if (!isLocalhost) {
baseHeaders['x-upload-signed-message'] = signedMessage;
baseHeaders['x-uploader-address'] = address as string;
Expand Down Expand Up @@ -606,6 +614,9 @@ export const handleMultiFileUpload = async (
baseHeaders['Swarm-Error-Document'] = 'error.html';
}

// Add erasure coding redundancy level if specified (for multi-file uploads, use level 0 by default)
// Note: Multi-file uploads don't currently support redundancy level selection

if (!isLocalhost) {
// For multi-file uploads, add session-related headers
baseHeaders['x-multi-file-upload'] = 'true';
Expand Down
38 changes: 38 additions & 0 deletions src/app/components/SwapComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import UploadHistorySection from './UploadHistorySection';
import SearchableChainDropdown from './SearchableChainDropdown';
import SearchableTokenDropdown from './SearchableTokenDropdown';
import StorageStampsDropdown from './StorageStampsDropdown';
import ErasureCodingDropdown from './ErasureCodingDropdown';
import StorageDurationDropdown from './StorageDurationDropdown';

import {
Expand Down Expand Up @@ -108,6 +109,7 @@ const SwapComponent: React.FC = () => {
const [nodeAddress, setNodeAddress] = useState<string>(DEFAULT_NODE_ADDRESS);
const [isWebpageUpload, setIsWebpageUpload] = useState(false);
const [isTarFile, setIsTarFile] = useState(false);
const [redundancyLevel, setRedundancyLevel] = useState<number>(0);
const [isFolderUpload, setIsFolderUpload] = useState(false);
const [showHelp, setShowHelp] = useState(false);
const [totalUsdAmount, setTotalUsdAmount] = useState<string | null>(null);
Expand Down Expand Up @@ -1232,6 +1234,7 @@ const SwapComponent: React.FC = () => {
serveUncompressed,
isTarFile,
isWebpageUpload,
redundancyLevel,
isFolderUpload,
setUploadProgress,
setStatusMessage,
Expand Down Expand Up @@ -1899,6 +1902,22 @@ const SwapComponent: React.FC = () => {
</div>
)}

{!isMultipleFiles && isTarFile && (
<div className={styles.checkboxWrapper}>
<input
type="checkbox"
id="webpage-upload"
checked={isWebpageUpload}
onChange={e => setIsWebpageUpload(e.target.checked)}
className={styles.checkbox}
disabled={uploadStep === 'uploading'}
/>
<label htmlFor="webpage-upload" className={styles.checkboxLabel}>
Upload as webpage
</label>
</div>
)}

{!isMultipleFiles && selectedFile?.name.toLowerCase().endsWith('.zip') && (
<div className={styles.checkboxWrapper}>
<input
Expand All @@ -1921,6 +1940,25 @@ const SwapComponent: React.FC = () => {
</div>
)}

{!isMultipleFiles && selectedFile && (
<div className={styles.dropdownWrapper}>
<label className={styles.dropdownLabel}>
Erasure Coding
<span
className={styles.tooltip}
title="Erasure coding provides data protection against loss. Higher levels use more storage space but offer better protection against chunk unavailability."
>
?
</span>
</label>
<ErasureCodingDropdown
selectedLevel={redundancyLevel}
onLevelChange={setRedundancyLevel}
disabled={uploadStep === 'uploading'}
/>
</div>
)}

<button
onClick={handleFileUpload}
disabled={
Expand Down
39 changes: 39 additions & 0 deletions src/app/components/css/SwapComponent.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,45 @@
accent-color: #ff7a00;
}

.dropdownWrapper {
display: flex;
flex-direction: column;
gap: 8px;
margin-bottom: 16px;
}

.dropdownLabel {
display: flex;
align-items: center;
gap: 6px;
font-size: 14px;
font-weight: 500;
color: #ffffff;
}

.tooltip {
cursor: help;
font-size: 12px;
font-weight: bold;
color: #8b949e;
background: none;
border: 1px solid #8b949e;
border-radius: 50%;
width: 16px;
height: 16px;
display: inline-flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
line-height: 1;
}

.tooltip:hover {
color: #ff7a00;
border-color: #ff7a00;
background-color: rgba(255, 122, 0, 0.1);
}

.checkboxLabel {
font-size: 14px;
color: #8b949e;
Expand Down
Loading