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

Various fixes #8447

Merged
merged 4 commits into from
Feb 21, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,12 @@ def get_status(self) -> DownloadStatus:
"""
Returns the status of the torrent.
"""
if self.get_error():
return DownloadStatus.STOPPED_ON_ERROR
if self.lt_status:
if self.lt_status.paused:
return DownloadStatus.STOPPED
return DOWNLOAD_STATUS_MAP[self.lt_status.state]
if self.get_error():
return DownloadStatus.STOPPED_ON_ERROR
return DownloadStatus.STOPPED

def get_error(self) -> str | None:
Expand Down
9 changes: 8 additions & 1 deletion src/tribler/core/restapi/file_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,16 @@ async def browse(self, request: web.Request) -> RESTResponse:

# Move up until we find a directory
parent_path = Path(path).resolve()
while not parent_path.is_dir():
while not parent_path.is_dir() and parent_path != parent_path.parent:
parent_path = parent_path.parent

# Did we find an existing directory?
if not parent_path.is_dir() or not parent_path.exists():
return RESTResponse({"error": {
"handled": True,
"message": f"No directory named {parent_path} exists"
}}, status=HTTP_NOT_FOUND)

# Get all files/subdirs
results = []
for file in parent_path.iterdir():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ async def test_readd_download_safe_seeding(self) -> None:
download = Download(TorrentDefNoMetainfo(b"\x01" * 20, b"name", None), None, checkpoint_disabled=True,
config=config)
download.futures["save_resume_data"] = succeed(True)
download_state = DownloadState(download, Mock(state=4, paused=False), None)
download_state = DownloadState(download, Mock(state=4, paused=False, error=None), None)
self.manager.downloads = {b"\x01" * 20: download}
self.manager.config.set("libtorrent/download_defaults/number_hops", 42)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def create_mock_download(self, piece_size: int | None = None, pieces: list[bool]
checkpoint_disabled=True)
download.handle = Mock(is_valid=Mock(return_value=True), file_priorities=Mock(return_value=[0] * 6),
torrent_file=Mock(return_value=download.tdef.torrent_info))
download.lt_status = Mock(state=3, paused=False, pieces=[])
download.lt_status = Mock(state=3, paused=False, error=None, pieces=[])
if piece_size is not None:
self.convert_to_piece_size(download, piece_size)
if pieces is not None:
Expand Down
11 changes: 10 additions & 1 deletion src/tribler/ui/src/dialogs/SelectRemotePath.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,17 @@ export default function SelectRemotePath(props: SelectRemotePathProps & JSX.Intr
const response = await triblerService.browseFiles(dir, showFiles || false);
if (response === undefined) {
toast.error(`${t("ToastErrorBrowseFiles")} ${t("ToastErrorGenNetworkErr")}`);
} else if (isErrorDict(response)) {
} else if (isErrorDict(response) && response.errorCode != 404) {
toast.error(`${t("ToastErrorBrowseFiles")} ${response.error.message}`);
} else if (isErrorDict(response)) {
// If we couldn't get the requested path, browse the default path instead.
let settings = await triblerService.getSettings()
if (settings !== undefined && !isErrorDict(settings)) {
let nextDir = settings.libtorrent.download_defaults.saveas;
if (dir != nextDir) {
reloadPaths(nextDir);
}
}
} else {
setPaths(response.paths);
setCurrentPath(response.current);
Expand Down
20 changes: 16 additions & 4 deletions src/tribler/ui/src/models/download.model.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,29 @@ import { File } from "./file.model";
import { Tracker } from "./tracker.model";


type state = 'ALLOCATING_DISKSPACE' | 'WAITING_FOR_HASHCHECK' | 'HASHCHECKING' | 'DOWNLOADING' |
'SEEDING' | 'STOPPED' | 'STOPPED_ON_ERROR' | 'METADATA' | 'LOADING' | 'EXIT_NODES';
export enum StatusCode {
ALLOCATING_DISKSPACE = 0,
WAITING_FOR_HASHCHECK = 1,
HASHCHECKING = 2,
DOWNLOADING = 3,
SEEDING = 4,
STOPPED = 5,
STOPPED_ON_ERROR = 6,
METADATA = 7,
LOADING = 8,
EXIT_NODES = 9
}

export type Status = keyof typeof StatusCode;

export interface Download {
name: string;
progress: number;
infohash: string;
speed_down: number;
speed_up: number;
status: state;
status_code: number;
status: Status;
status_code: StatusCode;
size: number;
eta: number;
num_peers: number;
Expand Down
9 changes: 6 additions & 3 deletions src/tribler/ui/src/pages/Downloads/Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Peers from "./Peers";
import Trackers from "./Trackers";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
import { Download } from "@/models/download.model";
import { Download, StatusCode } from "@/models/download.model";
import Pieces from "./Pieces";
import { useLayoutEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
Expand Down Expand Up @@ -57,7 +57,10 @@ export default function DownloadDetails({ download }: { download: Download | und
</div>
<div className="flex flex-row">
<div className="basis-1/4">{t('Status')}</div>
<div className="basis-3/4">{capitalize(download.status)}</div>
{download.status_code == StatusCode.STOPPED_ON_ERROR &&
<div className="basis-3/4 text-red-600">Error: {download.error}</div>}
{download.status_code != StatusCode.STOPPED_ON_ERROR &&
<div className="basis-3/4">{capitalize(download.status)}</div>}
</div>
<div className="flex flex-row">
<div className="basis-1/4">{t('Filesize')}</div>
Expand All @@ -79,7 +82,7 @@ export default function DownloadDetails({ download }: { download: Download | und
<TooltipProvider>
<Tooltip>
<TooltipTrigger>
<InfoIcon className="w-4 ml-2"/>
<InfoIcon className="w-4 ml-2" />
</TooltipTrigger>
<TooltipContent>
<span>
Expand Down
4 changes: 2 additions & 2 deletions src/tribler/ui/src/pages/Downloads/Files.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import toast from 'react-hot-toast';
import { ColumnDef, Row } from "@tanstack/react-table";
import { FileTreeItem } from "@/models/file.model";
import { Download } from "@/models/download.model";
import { Download, StatusCode } from "@/models/download.model";
import { Dispatch, MutableRefObject, SetStateAction, useEffect, useMemo, useRef, useState } from "react";
import { isErrorDict } from "@/services/reporting";
import { triblerService } from "@/services/tribler.service";
Expand Down Expand Up @@ -103,7 +103,7 @@ export default function Files({ download }: { download: Download }) {
}, []);

useEffect(() => {
if (download.status_code === 3)
if (download.status_code === StatusCode.DOWNLOADING)
updateFiles(setFiles, download, initialized);
}, [download]);

Expand Down
24 changes: 18 additions & 6 deletions src/tribler/ui/src/pages/Downloads/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ActionButtons, ActionMenu } from "./Actions";
import DownloadDetails from "./Details";
import SimpleTable, { getHeader } from "@/components/ui/simple-table"
import { Download } from "@/models/download.model";
import { Download, StatusCode } from "@/models/download.model";
import { Progress } from "@/components/ui/progress"
import { capitalize, formatBytes, formatDateTime, formatTimeRelative } from "@/lib/utils";
import { isErrorDict } from "@/services/reporting";
Expand Down Expand Up @@ -49,13 +49,23 @@ const downloadColumns: ColumnDef<Download>[] = [
accessorKey: "progress",
header: getHeader('Status'),
cell: ({ row }) => {
let status = `${capitalize(row.original.status.replaceAll("_", " "))} ${(row.original.progress * 100).toFixed(0)}%`
let progress = row.original.progress * 100;
let color = "bg-tribler";

if (row.original.status_code == StatusCode.STOPPED_ON_ERROR) {
status = "Error";
progress = 100;
color = "bg-red-600";
}

return (
<div className="grid">
<div className="col-start-1 row-start-1">
<Progress className="h-5 bg-primary" value={row.original.progress * 100} indicatorColor="bg-tribler" />
<Progress className="h-5 bg-primary" value={progress} indicatorColor={`${color}`} />
</div>
<div className="col-start-1 row-start-1 text-white dark:text-black dark:font-mediumnormal text-center align-middle z-10">
{capitalize(row.original.status.replaceAll("_", " "))} {(row.original.progress * 100).toFixed(0)}%
{status}
</div>
</div>
)
Expand Down Expand Up @@ -100,7 +110,7 @@ const downloadColumns: ColumnDef<Download>[] = [
hide_by_default: true,
},
cell: ({ row }) => {
if (row.original.progress === 1 || row.original.status_code !== 3)
if (row.original.progress === 1 || row.original.status_code !== StatusCode.DOWNLOADING)
return <span>-</span>
return <span>{formatTimeRelative(row.original.eta, false)}</span>
},
Expand Down Expand Up @@ -198,7 +208,8 @@ export default function Downloads({ statusFilter }: { statusFilter: number[] })
<Card className="border-none shadow-none">
<CardHeader className="md:flex-row md:justify-between space-y-0 items-center px-4 py-1.5">
<div className="flex flex-nowrap items-center">
<ActionButtons selectedDownloads={selectedDownloads.filter((d) => d.status !== "LOADING")} />
<ActionButtons selectedDownloads={
selectedDownloads.filter((d) => d.status_code !== StatusCode.LOADING)} />
</div>
<div>
<div className="flex items-center">
Expand Down Expand Up @@ -226,7 +237,8 @@ export default function Downloads({ statusFilter }: { statusFilter: number[] })
selectOnRightClick={true}
/>
</ContextMenuTrigger>
<ActionMenu selectedDownloads={selectedDownloads.filter((d) => d.status !== "LOADING")} />
<ActionMenu selectedDownloads={
selectedDownloads.filter((d) => d.status_code !== StatusCode.LOADING)} />
</ContextMenu>

</Card>
Expand Down
9 changes: 7 additions & 2 deletions src/tribler/ui/src/services/reporting.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import axios, { AxiosError } from "axios";

export interface ErrorDict { [error: string]: {handled: boolean, message: string}; };
export interface ErrorDict {
error: {handled: boolean, message: string},
errorCode?: number
};

export function isErrorDict(object: any): object is ErrorDict {
return (typeof object === 'object') && ('error' in object);
Expand Down Expand Up @@ -38,7 +41,9 @@ export function formatAxiosError(error: Error | AxiosError): ErrorDict | undefin
handleHTTPError(error);
}
// This is some (probably expected) REST API error
return error.response.data;
let errorDict = error.response.data;
errorDict.errorCode = error.status;
return errorDict;
}
// No idea what this is: make it someone else's problem
throw error;
Expand Down
Loading