From feca8bc6a9691cab36d7ab9a7a51df17e3df9a24 Mon Sep 17 00:00:00 2001 From: Egbert Bouman Date: Wed, 19 Jun 2024 18:04:30 +0200 Subject: [PATCH 1/7] Removed unused dependencies --- requirements.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index b455843c82..e50a57f64e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,3 @@ pillow pony pystray pywin32;sys_platform=="win32" - -PyQt5 -numpy -pyqtgraph From a772a273fa43f267a053f4f6da08ed72b355336b Mon Sep 17 00:00:00 2001 From: Egbert Bouman Date: Wed, 19 Jun 2024 18:04:55 +0200 Subject: [PATCH 2/7] Update ruff.toml --- .ruff.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ruff.toml b/.ruff.toml index 0dcbf37424..0b513515eb 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -81,7 +81,7 @@ exclude = [ "build", "dist", "node_modules", - "src/tribler/gui", + "src/tribler/ui", "venv", ] From 209364fd4edfd200a79dd5beee00b34c62927469 Mon Sep 17 00:00:00 2001 From: Egbert Bouman Date: Wed, 17 Jul 2024 12:25:45 +0200 Subject: [PATCH 3/7] Fix Windows build --- build/win/build.py | 14 ++++++++------ build/win/makedist_win.bat | 7 +++++++ src/run_tribler.py | 3 ++- src/tribler/core/restapi/file_endpoint.py | 8 +++++--- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/build/win/build.py b/build/win/build.py index 3efc4cdbe9..b0f990fd1f 100644 --- a/build/win/build.py +++ b/build/win/build.py @@ -43,20 +43,20 @@ def get_freeze_build_options(): included_packages = [ "aiohttp_apispec", "pkg_resources", - "pyqtgraph", "requests", "tribler.core", - "tribler.gui", "libtorrent", "ssl", ] # These files will be included in the build included_files = [ - ("src/tribler/gui/qt_resources", "qt_resources"), - ("src/tribler/gui/images", "images"), + ("src/tribler/ui/public", "lib/tribler/ui/public"), + ("src/tribler/ui/dist", "lib/tribler/ui/dist"), + ("src/tribler/core", "tribler_source/tribler/core"), - ("src/tribler/gui", "tribler_source/tribler/gui"), + ("src/tribler/ui/public", "tribler_source/tribler/ui/public"), + ("src/tribler/ui/dist", "tribler_source/tribler/ui/dist"), ("build/win/resources", "tribler_source/resources"), ] @@ -70,7 +70,9 @@ def get_freeze_build_options(): '_tkinter', 'tkinter', 'Tkinter', - 'matplotlib' + 'matplotlib', + 'numpy', + 'tribler.ui' ] _setup_options = { diff --git a/build/win/makedist_win.bat b/build/win/makedist_win.bat index 0cbe2f2202..4cc22b965e 100644 --- a/build/win/makedist_win.bat +++ b/build/win/makedist_win.bat @@ -36,6 +36,13 @@ if defined VENV ( call python3 -m pip install --upgrade pip call python3 -m pip install --upgrade -r requirements-build.txt +REM ----- Build UI +pushd . +cd src/tribler/ui/ +call npm install +call npm run build +popd + REM ----- Build REM Arno: When adding files here, make sure tribler.nsi actually diff --git a/src/run_tribler.py b/src/run_tribler.py index d73773121a..9200e6eb7f 100644 --- a/src/run_tribler.py +++ b/src/run_tribler.py @@ -12,6 +12,7 @@ from pathlib import Path import pystray +import tribler from PIL import Image from tribler.core.session import Session from tribler.tribler_config import TriblerConfigManager @@ -85,7 +86,7 @@ async def main() -> None: session = Session(config) await session.start() - image_path = Path(__file__).absolute() / "../tribler/ui/public/tribler.png" + image_path = Path(tribler.__file__).parent / "ui/public/tribler.png" image = Image.open(image_path.resolve()) url = f"http://localhost:{session.rest_manager.get_api_port()}/ui/#/downloads/all?key={config.get('api/key')}" menu = (pystray.MenuItem('Open', lambda: webbrowser.open_new_tab(url)), diff --git a/src/tribler/core/restapi/file_endpoint.py b/src/tribler/core/restapi/file_endpoint.py index dfba471945..a8d8b5b6c6 100644 --- a/src/tribler/core/restapi/file_endpoint.py +++ b/src/tribler/core/restapi/file_endpoint.py @@ -1,13 +1,15 @@ import contextlib import logging -import sys +import platform from pathlib import Path -import win32api from aiohttp import web from tribler.core.restapi.rest_endpoint import HTTP_NOT_FOUND, RESTEndpoint, RESTResponse +if platform.system() == 'Windows': + import win32api + class FileEndpoint(RESTEndpoint): """ @@ -33,7 +35,7 @@ async def browse(self, request: web.Request) -> RESTResponse: show_files = request.query.get('files') == "1" # Deal with getting the drives on Windows - if path == "/" and sys.platform == 'win32': + if path == "/" and platform.system() == 'Windows': paths = [] for drive in win32api.GetLogicalDriveStrings().split("\000"): if not drive: From 7f720a2365c72bb86f456847aacbd5bc11258841 Mon Sep 17 00:00:00 2001 From: Egbert Bouman Date: Wed, 24 Jul 2024 18:44:30 +0200 Subject: [PATCH 4/7] Fix Debian build --- build/debian/makedist_debian.sh | 7 +++++++ build/win/build.py | 7 +++++++ src/tribler/ui/package.json | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/build/debian/makedist_debian.sh b/build/debian/makedist_debian.sh index 2fe7e562f2..70e7f884a0 100755 --- a/build/debian/makedist_debian.sh +++ b/build/debian/makedist_debian.sh @@ -29,6 +29,13 @@ python3 -m pip install --upgrade -r requirements-build.txt python3 ./build/update_version.py -r . python3 ./build/debian/update_metainfo.py -r . +# ----- Build UI +pushd . +cd src/tribler/ui/ +npm install +npm run build +popd + # ----- Build binaries echo Building Tribler using Cx_Freeze python3 setup.py build diff --git a/build/win/build.py b/build/win/build.py index b0f990fd1f..d4b5c80a65 100644 --- a/build/win/build.py +++ b/build/win/build.py @@ -25,6 +25,7 @@ and the appropriate function is called based on the command line arguments. """ import sys +import platform def get_wheel_build_options(): @@ -49,6 +50,9 @@ def get_freeze_build_options(): "ssl", ] + if platform.system() != 'Windows': + included_packages.append("gi") + # These files will be included in the build included_files = [ ("src/tribler/ui/public", "lib/tribler/ui/public"), @@ -84,6 +88,9 @@ def get_freeze_build_options(): 'build_exe': 'dist/tribler' } } + if platform.system() == 'Linux': + _setup_options["build_exe"]["bin_includes"] = "libffi.so" + app_name = "Tribler" if sys.platform != "linux" else "tribler" app_script = "src/tribler/run.py" diff --git a/src/tribler/ui/package.json b/src/tribler/ui/package.json index 55a5784f88..a04fefe26c 100644 --- a/src/tribler/ui/package.json +++ b/src/tribler/ui/package.json @@ -1,7 +1,7 @@ { "name": "tribler-webui", "private": true, - "version": "0.1", + "version": "0.1.0", "type": "module", "scripts": { "dev": "vite", From 700e8502fb7fd1c354c09a624faa792dd0e4ca1b Mon Sep 17 00:00:00 2001 From: Egbert Bouman Date: Thu, 25 Jul 2024 13:53:56 +0200 Subject: [PATCH 5/7] Fix Mac build --- build/mac/makedist_macos.sh | 9 +++++++++ tribler.spec | 31 +++---------------------------- 2 files changed, 12 insertions(+), 28 deletions(-) diff --git a/build/mac/makedist_macos.sh b/build/mac/makedist_macos.sh index 6d13af940e..46727beda0 100755 --- a/build/mac/makedist_macos.sh +++ b/build/mac/makedist_macos.sh @@ -17,6 +17,15 @@ python3 -m venv "${BUILD_ENV}" python3 -m pip install --upgrade pip python3 -m pip install --upgrade -r requirements-build.txt +# ----- Build UI + +pushd . +cd src/tribler/ui/ +npm install +npm run build +rm -rf node_modules +popd + # ----- Build pyinstaller tribler.spec --log-level="${LOG_LEVEL}" diff --git a/tribler.spec b/tribler.spec index c0d12855e5..f5fc58e432 100644 --- a/tribler.spec +++ b/tribler.spec @@ -30,17 +30,12 @@ show_console = os.environ.get('SHOW_CONSOLE', 'false') == 'true' if sys.platform == 'darwin': show_console = True -widget_files = [] -for file in os.listdir(os.path.join(src_dir, "tribler", "gui", "widgets")): - if file.endswith(".py"): - widget_files.append('tribler.gui.widgets.%s' % file[:-3]) - data_to_copy = [ - (os.path.join(src_dir, "tribler", "gui", "qt_resources"), 'qt_resources'), - (os.path.join(src_dir, "tribler", "gui", "images"), 'images'), (os.path.join(src_dir, "tribler", "core"), 'tribler_source/tribler/core'), - (os.path.join(src_dir, "tribler", "gui"), 'tribler_source/tribler/gui'), + (os.path.join(src_dir, "tribler", "ui", "public"), 'tribler_source/tribler/ui/public'), + (os.path.join(src_dir, "tribler", "ui", "dist"), 'tribler_source/tribler/ui/dist'), (os.path.join(root_dir, "build", "win", "resources"), 'tribler_source/resources'), + (os.path.dirname(aiohttp_apispec.__file__), 'aiohttp_apispec') ] @@ -65,10 +60,6 @@ ttf_path = os.path.join("/usr", "share", "fonts", "truetype", "noto", "NotoColor if sys.platform.startswith('linux') and os.path.exists(ttf_path): data_to_copy += [(ttf_path, 'fonts')] -# fixes ZeroDivisionError in pyqtgraph\graphicsItems\ButtonItem.py -# https://issueexplorer.com/issue/pyqtgraph/pyqtgraph/1811 -data_to_copy += collect_data_files("pyqtgraph", includes=["**/*.ui", "**/*.png", "**/*.svg"]) - excluded_libs = ['wx', 'PyQt4', 'FixTk', 'tcl', 'tk', '_tkinter', 'tkinter', 'Tkinter', 'matplotlib'] # Pony dependencies; each packages need to be added separatedly; added as hidden import @@ -85,18 +76,12 @@ hiddenimports = [ # 'pkg_resources.py2_warn', # Workaround PyInstaller & SetupTools, https://github.com/pypa/setuptools/issues/1963 'pyaes', 'pydantic', - 'pyqtgraph', - 'pyqtgraph.graphicsItems.PlotItem.plotConfigTemplate_pyqt5', - 'pyqtgraph.graphicsItems.ViewBox.axisCtrlTemplate_pyqt5', - 'pyqtgraph.imageview.ImageViewTemplate_pyqt5', - 'PyQt5.QtTest', 'requests', 'scrypt', '_scrypt', 'sqlalchemy', 'sqlalchemy.ext.baked', 'sqlalchemy.ext.declarative', 'tribler.core.logger.logger_streams', 'typing_extensions', ] -hiddenimports += widget_files hiddenimports += pony_deps hiddenimports += [x for member in known_components.__dict__.values() for x in getattr(member, "hiddenimports", set())] @@ -109,10 +94,6 @@ if sys.platform.startswith('linux'): # https://github.com/pyinstaller/pyinstaller/issues/5359 hiddenimports += collect_submodules('pydantic') -# fixes ZeroDivisionError in pyqtgraph\graphicsItems\ButtonItem.py -# https://issueexplorer.com/issue/pyqtgraph/pyqtgraph/1811 -hiddenimports += collect_submodules("pyqtgraph", filter=lambda name: "Template" in name) - sys.modules['FixTk'] = None a = Analysis(['src/run_tribler.py'], pathex=[''], @@ -164,9 +145,3 @@ app = BUNDLE(coll, # Replace the Info.plist file on MacOS if sys.platform == 'darwin': shutil.copy('build/mac/resources/Info.plist', 'dist/Tribler.app/Contents/Info.plist') - -# On Windows 10, we have to make sure that qwindows.dll is in the right path -if sys.platform == 'win32': - shutil.copytree(os.path.join('dist', 'tribler', 'PyQt5', 'Qt', 'plugins', 'platforms'), - os.path.join('dist', 'tribler', 'platforms')) - From b820bfdf2c11f546c3721e8211e5d5ea6a55e7a5 Mon Sep 17 00:00:00 2001 From: Egbert Bouman Date: Thu, 1 Aug 2024 10:19:38 +0200 Subject: [PATCH 6/7] Fix aiohttp>=v3.10.0 compatibility --- src/tribler/core/socks5/aiohttp_connector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tribler/core/socks5/aiohttp_connector.py b/src/tribler/core/socks5/aiohttp_connector.py index 7a3b00b396..af33e3e2db 100644 --- a/src/tribler/core/socks5/aiohttp_connector.py +++ b/src/tribler/core/socks5/aiohttp_connector.py @@ -46,12 +46,12 @@ def __init__(self, proxy_addr: tuple, **kwargs) -> None: async def _wrap_create_connection(self, # type: ignore[override] protocol_factory: Callable[[], Socks5ClientUDPConnection], - host: str, port: int, **kwargs) -> tuple[BaseTransport, Socks5ClientUDPConnection]: """ Create a transport and its associated connection. """ client = Socks5Client(self.proxy_addr, lambda *_: None) + host, port = kwargs.pop("addr_infos")[0][-1] if "timeout" in kwargs and hasattr(kwargs["timeout"], "sock_connect"): await wait_for(client.connect_tcp((host, port)), timeout=kwargs["timeout"].sock_connect) From b2fa912e9e7caa66e6a10dbedd2643832f218013 Mon Sep 17 00:00:00 2001 From: Egbert Bouman Date: Thu, 1 Aug 2024 10:27:15 +0200 Subject: [PATCH 7/7] Remove duplicate search results --- src/tribler/ui/src/pages/Search/index.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tribler/ui/src/pages/Search/index.tsx b/src/tribler/ui/src/pages/Search/index.tsx index 6dc014eaee..3f3ddbcf29 100644 --- a/src/tribler/ui/src/pages/Search/index.tsx +++ b/src/tribler/ui/src/pages/Search/index.tsx @@ -3,7 +3,7 @@ import { useEffect, useState } from "react"; import { triblerService } from "@/services/tribler.service"; import { Torrent } from "@/models/torrent.model"; import { ColumnDef } from "@tanstack/react-table"; -import { categoryIcon, formatBytes, formatTimeAgo, getMagnetLink } from "@/lib/utils"; +import { categoryIcon, filterDuplicates, formatBytes, formatTimeAgo, getMagnetLink } from "@/lib/utils"; import SaveAs from "@/dialogs/SaveAs"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; import { useSearchParams } from "react-router-dom"; @@ -69,7 +69,8 @@ export default function Search() { useEffect(() => { const searchTorrents = async () => { if (!query) return; - setTorrents((await triblerService.searchTorrentsLocal(query, true))); + const localResults = await triblerService.searchTorrentsLocal(query, true); + setTorrents(filterDuplicates(localResults, 'infohash')); const remoteQuery = await triblerService.searchTorrentsRemote(query, true); setRequest(remoteQuery.request_uuid); }