diff --git a/.github/workflows/deploy-pypi.yml b/.github/workflows/deploy-pypi.yml index 509543c..258a9de 100644 --- a/.github/workflows/deploy-pypi.yml +++ b/.github/workflows/deploy-pypi.yml @@ -122,7 +122,11 @@ jobs: run: | sudo apt update sudo apt install -y libxcb-cursor0 qt6-base-dev patchelf ccache zlib1g-dev + sudo apt install -y flatpak flatpak-builder elfutils patchelf echo "QMAKE=$(which qmake6)" >> $GITHUB_ENV + flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo + flatpak update + flatpak install flathub org.kde.Platform//6.8 org.kde.Sdk//6.8 if [ "$RUNNER_ARCH" == "X64" ]; then linuxdeploy_arch="x86_64" @@ -219,6 +223,8 @@ jobs: Furious-*.zip Furious-*.dmg Furious-*.AppImage + Furious-*.deb + Furious-*.flatpak github-release: name: Upload to GitHub Release diff --git a/.gitignore b/.gitignore index 6df27f7..6b65e63 100644 --- a/.gitignore +++ b/.gitignore @@ -170,6 +170,10 @@ Furious-*/ # Linux app dir AppDir/ +# Linux debian dir +debian/ +# Linux flatpak dir +flatpak/ # zip files *.zip @@ -177,3 +181,7 @@ AppDir/ *.dmg # AppImage files *.AppImage +# deb files +*.deb +# flatpak files +*.flatpak diff --git a/Deploy.py b/Deploy.py index b93853a..8da35d6 100644 --- a/Deploy.py +++ b/Deploy.py @@ -54,6 +54,8 @@ NUITKA_BINARY_VERSION_OPTION = ( f'--product-version={APPLICATION_VERSION} ' ) +PLATFORM_MACHINE_LOWER = PLATFORM_MACHINE.lower() + if PLATFORM == 'Windows': NUITKA_BINARY_VERSION_OPTION += f'--file-description=\"A GUI proxy client based on PySide6. Support Xray-core & hysteria\" ' @@ -118,7 +120,7 @@ if PLATFORM == 'Windows': ARTIFACT_NAME = ( f'{APPLICATION_NAME}-{APPLICATION_VERSION}-' - f'{winVerCompatible}-{PLATFORM_MACHINE.lower()}' + f'{winVerCompatible}-{PLATFORM_MACHINE_LOWER}' ) WIN_UNZIPPED = f'{APPLICATION_NAME}-{APPLICATION_VERSION}-{winVerCompatible}' @@ -135,7 +137,7 @@ elif PLATFORM == 'Darwin': ARTIFACT_NAME = ( f'{APPLICATION_NAME}-{APPLICATION_VERSION}-' - f'{macVerCompatible}-{PLATFORM_MACHINE.lower()}' + f'{macVerCompatible}-{PLATFORM_MACHINE_LOWER}' ) MAC_APP_DIR = ROOT_DIR / 'app' @@ -159,7 +161,7 @@ elif PLATFORM == 'Linux': LINUX_DESKTOP_FILE = f'{APPLICATION_NAME}.desktop' ARTIFACT_NAME = ( - f'{APPLICATION_NAME}-{APPLICATION_VERSION}-linux-{PLATFORM_MACHINE.lower()}' + f'{APPLICATION_NAME}-{APPLICATION_VERSION}-linux-{PLATFORM_MACHINE_LOWER}' ) LINUX_APPIMAGE_FILENAME = f'{ARTIFACT_NAME}.AppImage' @@ -171,6 +173,12 @@ elif PLATFORM == 'Linux': f'--plugin qt ' f'--output appimage' ) + + LINUX_DEBIAN_DIR = ROOT_DIR / 'debian' + LINUX_DEB_FILENAME = f'{ARTIFACT_NAME}.deb' + + LINUX_FLATPAK_DIR = ROOT_DIR / 'flatpak' + LINUX_FLATPAK_FILENAME = f'{ARTIFACT_NAME}.flatpak' else: # Deploy: Not implemented ARTIFACT_NAME = '' @@ -330,6 +338,7 @@ def cleanup(): logger.info(f'remove app dir success') elif PLATFORM == 'Linux': # More cleanup on Linux + # Cleanup AppImage environment try: # Remove artifact os.remove(ROOT_DIR / LINUX_APPIMAGE_FILENAME) @@ -349,6 +358,48 @@ def cleanup(): logger.error(f'remove app dir failed: {ex}') else: logger.info(f'remove app dir success') + + # Cleanup deb environment + try: + # Remove artifact + os.remove(ROOT_DIR / LINUX_DEB_FILENAME) + except Exception as ex: + # Any non-exit exceptions + + logger.error(f'remove artifact failed: {ex}') + else: + logger.info(f'remove artifact success') + + try: + # Remove debian folder + shutil.rmtree(LINUX_DEBIAN_DIR) + except Exception as ex: + # Any non-exit exceptions + + logger.error(f'remove debian dir failed: {ex}') + else: + logger.info(f'remove debian dir success') + + # Cleanup flatpak environment + try: + # Remove artifact + os.remove(ROOT_DIR / LINUX_FLATPAK_FILENAME) + except Exception as ex: + # Any non-exit exceptions + + logger.error(f'remove artifact failed: {ex}') + else: + logger.info(f'remove artifact success') + + try: + # Remove flatpak folder + shutil.rmtree(LINUX_FLATPAK_DIR) + except Exception as ex: + # Any non-exit exceptions + + logger.error(f'remove flatpak dir failed: {ex}') + else: + logger.info(f'remove flatpak dir success') else: # Deploy: Not implemented pass @@ -527,20 +578,23 @@ def main(): LINUX_APP_DIR, ) + DESKTOP_FILE_CONTENT = ( + f'[Desktop Entry]\n' + f'Type=Application\n' + f'Name={APPLICATION_NAME}\n' + f'Exec={APPLICATION_NAME}.bin\n' + f'Icon={iconbase}\n' + f'Terminal=false\n' + f'Categories=Utility\n' + ) + try: with open( LINUX_APP_DIR / LINUX_DESKTOP_FILE, 'w', encoding='utf-8', ) as file: - file.write( - f'[Desktop Entry]\n' - f'Type=Application\n' - f'Name={APPLICATION_NAME}\n' - f'Exec={APPLICATION_NAME}.bin\n' - f'Icon={iconbase}\n' - f'Categories=Utility\n' - ) + file.write(DESKTOP_FILE_CONTENT) except Exception: # Any non-exit exceptions @@ -589,6 +643,322 @@ def main(): logger.info(f'chmod +x success: {LINUX_APPIMAGE_FILENAME}') printStandardStream(result.stdout, result.stderr) + + # Create .deb package + logger.info('generating deb') + + # Prepare package layout + try: + os.makedirs(LINUX_DEBIAN_DIR / 'DEBIAN', exist_ok=True) + os.makedirs(LINUX_DEBIAN_DIR / 'usr' / 'bin', exist_ok=True) + os.makedirs( + LINUX_DEBIAN_DIR / 'usr' / 'share' / APPLICATION_NAME, + exist_ok=True, + ) + os.makedirs( + LINUX_DEBIAN_DIR / 'usr' / 'share' / 'applications', + exist_ok=True, + ) + os.makedirs( + LINUX_DEBIAN_DIR + / 'usr' + / 'share' + / 'icons' + / 'hicolor' + / '512x512' + / 'apps', + exist_ok=True, + ) + except Exception: + # Any non-exit exceptions + + raise + + # Copy output + shutil.copytree( + ROOT_DIR / DEPLOY_DIR_NAME / f'{APPLICATION_NAME}.dist', + LINUX_DEBIAN_DIR / 'usr' / 'share' / APPLICATION_NAME, + dirs_exist_ok=True, + ) + shutil.copy( + ROOT_DIR / 'Icons' / 'png' / f'{iconbase}.png', + LINUX_DEBIAN_DIR + / 'usr' + / 'share' + / 'icons' + / 'hicolor' + / '512x512' + / 'apps', + ) + + # Create launcher script + try: + launcherScript = LINUX_DEBIAN_DIR / 'usr' / 'bin' / APPLICATION_NAME + + with open( + launcherScript, + 'w', + encoding='utf-8', + ) as file: + file.write( + f'#!/bin/bash\n' + f'exec /usr/share/{APPLICATION_NAME}/{APPLICATION_NAME}.bin "$@"\n' + ) + + runExternalCommand( + f'chmod +x {launcherScript}', + shell=True, + check=True, + ) + except Exception: + # Any non-exit exceptions + + raise + + # Create desktop entry file + try: + with open( + LINUX_DEBIAN_DIR + / 'usr' + / 'share' + / 'applications' + / LINUX_DESKTOP_FILE, + 'w', + encoding='utf-8', + ) as file: + file.write(DESKTOP_FILE_CONTENT) + except Exception: + # Any non-exit exceptions + + raise + + # Create control file + try: + if PLATFORM_MACHINE_LOWER == 'x86_64': + arch = 'amd64' + elif PLATFORM_MACHINE_LOWER == 'aarch64': + arch = 'arm64' + else: + raise + + with open( + LINUX_DEBIAN_DIR / 'DEBIAN' / 'control', + 'w', + encoding='utf-8', + ) as file: + file.write( + f'Package: {APPLICATION_NAME}\n' + f'Version: {APPLICATION_VERSION}\n' + f'Section: utils\n' + f'Priority: optional\n' + f'Architecture: {arch}\n' + f'Depends: libc6, libstdc++6, libgl1, libxcb-cursor0, libxcb-xinerama0\n' + f'Maintainer: {APPLICATION_AUTHOR_NAME} <{APPLICATION_AUTHOR_EMAIL}>\n' + f'Description: A GUI proxy client based on PySide6. Support Xray-core & hysteria\n' + f'Homepage: {APPLICATION_ABOUT_PAGE}\n' + ) + except Exception: + # Any non-exit exceptions + + raise + + # Fix permissions + try: + runExternalCommand( + f'find debian -type d -exec chmod 755 {{}} \\;', + shell=True, + check=True, + ) + runExternalCommand( + f'find debian -type f -exec chmod 644 {{}} \\;', + shell=True, + check=True, + ) + runExternalCommand( + f'chmod 755 ' + + (LINUX_DEBIAN_DIR / 'usr' / 'bin' / APPLICATION_NAME).as_posix(), + shell=True, + check=True, + ) + runExternalCommand( + f'chmod 755 ' + + ( + LINUX_DEBIAN_DIR + / 'usr' + / 'share' + / APPLICATION_NAME + / f'{APPLICATION_NAME}.bin' + ).as_posix(), + shell=True, + check=True, + ) + except Exception: + # Any non-exit exceptions + + raise + + try: + runExternalCommand( + f'dpkg-deb --build debian {LINUX_DEB_FILENAME}', + shell=True, + check=True, + ) + except Exception: + # Any non-exit exceptions + + raise + + # Create .flatpak package + logger.info('generating flatpak') + + # Prepare package layout + try: + os.makedirs(LINUX_FLATPAK_DIR / APPLICATION_NAME, exist_ok=True) + except Exception: + # Any non-exit exceptions + + raise + + # Copy output + shutil.copytree( + ROOT_DIR / DEPLOY_DIR_NAME / f'{APPLICATION_NAME}.dist', + LINUX_FLATPAK_DIR / APPLICATION_NAME, + dirs_exist_ok=True, + ) + shutil.copy( + ROOT_DIR / 'Icons' / 'png' / f'{iconbase}.png', + LINUX_FLATPAK_DIR / f'{APPLICATION_FLATPAK_ID}.png', + ) + + # Create flatpak manifest file + try: + with open( + LINUX_FLATPAK_DIR / f'{APPLICATION_FLATPAK_ID}.yml', + 'w', + encoding='utf-8', + ) as file: + file.write( + f'app-id: {APPLICATION_FLATPAK_ID}\n' + f'runtime: org.kde.Platform\n' + f'runtime-version: \"6.8\"\n' + f'sdk: org.kde.Sdk\n' + f'command: {APPLICATION_NAME}\n' + f'\n' + f'finish-args:\n' + f' - --share=ipc\n' + f' - --share=network\n' + f' - --socket=wayland\n' + f' - --socket=fallback-x11\n' + f' - --device=dri\n' + f' - --filesystem=home\n' + f' - --talk-name=org.freedesktop.Flatpak\n' + f'\n' + f'modules:\n' + f' - name: mit-krb5\n' + f' buildsystem: simple\n' + f' sources:\n' + f' - type: archive\n' + f' url: https://kerberos.org/dist/krb5/1.21/krb5-1.21.3.tar.gz\n' + f' sha256: b7a4cd5ead67fb08b980b21abd150ff7217e85ea320c9ed0c6dadd304840ad35\n' + f' build-commands:\n' + f' - cd src && autoreconf -i # Ensure Autotools files are generated\n' + f' - cd src && ./configure --prefix=/app --disable-static --enable-shared\n' + f' - cd src && make -j$(nproc)\n' + f' - cd src && make install\n' + f' - name: {APPLICATION_NAME}\n' + f' buildsystem: simple\n' + f' build-commands:\n' + f' # Script\n' + f' - install -Dm755 {APPLICATION_NAME}.sh /app/bin/{APPLICATION_NAME}\n' + f' # Whole application directory\n' + f' - mkdir -p /app/lib/{APPLICATION_NAME}/\n' + f' - cp -a . /app/lib/{APPLICATION_NAME}/\n' + f' # Desktop + icon\n' + f' - install -Dm644 {APPLICATION_FLATPAK_ID}.desktop /app/share/applications/{APPLICATION_FLATPAK_ID}.desktop\n' + f' - install -Dm644 {APPLICATION_FLATPAK_ID}.png /app/share/icons/hicolor/512x512/apps/{APPLICATION_FLATPAK_ID}.png\n' + f' sources:\n' + f' - type: file\n' + f' path: {APPLICATION_NAME}.sh\n' + f' - type: dir\n' + f' path: {APPLICATION_NAME}\n' + f' - type: file\n' + f' path: {APPLICATION_FLATPAK_ID}.desktop\n' + f' - type: file\n' + f' path: {APPLICATION_FLATPAK_ID}.png\n' + ) + except Exception: + # Any non-exit exceptions + + raise + + # Create desktop entry file + try: + with open( + LINUX_FLATPAK_DIR / f'{APPLICATION_FLATPAK_ID}.desktop', + 'w', + encoding='utf-8', + ) as file: + file.write( + f'[Desktop Entry]\n' + f'Type=Application\n' + f'Name={APPLICATION_NAME}\n' + f'Exec={APPLICATION_NAME}\n' + f'Icon={APPLICATION_FLATPAK_ID}\n' + f'Terminal=false\n' + f'Categories=Utility\n' + ) + except Exception: + # Any non-exit exceptions + + raise + + # Create launcher script + try: + with open( + LINUX_FLATPAK_DIR / f'{APPLICATION_NAME}.sh', + 'w', + encoding='utf-8', + ) as file: + file.write( + f'#!/usr/bin/env bash\n' + f'exec /app/lib/{APPLICATION_NAME}/{APPLICATION_NAME}.bin \"$@\"\n' + ) + except Exception: + # Any non-exit exceptions + + raise + + cwd = os.getcwd() + + try: + os.chdir(LINUX_FLATPAK_DIR) + + runExternalCommand( + f'flatpak-builder build-dir {APPLICATION_FLATPAK_ID}.yml --force-clean', + shell=True, + check=True, + ) + runExternalCommand( + f'flatpak build-export repo build-dir', + shell=True, + check=True, + ) + runExternalCommand( + f'flatpak build-bundle repo {LINUX_FLATPAK_FILENAME} {APPLICATION_FLATPAK_ID}', + shell=True, + check=True, + ) + + shutil.copy( + LINUX_FLATPAK_FILENAME, + ROOT_DIR, + ) + except Exception: + # Any non-exit exceptions + + raise + finally: + os.chdir(cwd) else: # Deploy: Not implemented pass diff --git a/Furious/Core/CoreManager.py b/Furious/Core/CoreManager.py index 017905c..1d8026d 100644 --- a/Furious/Core/CoreManager.py +++ b/Furious/Core/CoreManager.py @@ -21,7 +21,6 @@ from Furious.Frozenlib import * from Furious.Interface import * from Furious.Library import * from Furious.Qt import * -from Furious.Utility import * from Furious.Core.CoreProcessWorker import * from Furious.Core.XrayCore import * from Furious.Core.Hysteria1 import * @@ -30,6 +29,7 @@ from Furious.Core.Tun2socks import * from typing import Callable, Tuple, Union +import os import uuid import logging import tempfile @@ -654,8 +654,13 @@ class CoreManager(Mixins.CleanupOnExit): ) ) + if SystemRuntime.flatpakID(): + tempdir = os.environ.get('TMPDIR') + else: + tempdir = None + with tempfile.NamedTemporaryFile( - mode='w', encoding='utf-8', suffix='.sh', delete=True + mode='w', encoding='utf-8', suffix='.sh', dir=tempdir, delete=True ) as file: content = '\n'.join( filter( diff --git a/Furious/Core/CoreProcessWorker.py b/Furious/Core/CoreProcessWorker.py index 1bb288e..c4c2246 100644 --- a/Furious/Core/CoreProcessWorker.py +++ b/Furious/Core/CoreProcessWorker.py @@ -19,7 +19,6 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Utility import * from PySide6 import QtCore diff --git a/Furious/Core/XrayCore.py b/Furious/Core/XrayCore.py index aa5f70a..0ff6b0e 100644 --- a/Furious/Core/XrayCore.py +++ b/Furious/Core/XrayCore.py @@ -20,7 +20,6 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * from Furious.Library import * -from Furious.Utility import * from Furious.Core.CoreProcessWorker import * from enum import Enum diff --git a/Furious/Frozenlib/Constants.py b/Furious/Frozenlib/Constants.py index 00e5f45..2c8c63f 100644 --- a/Furious/Frozenlib/Constants.py +++ b/Furious/Frozenlib/Constants.py @@ -26,8 +26,11 @@ import platform APPLICATION_NAME = 'Furious' APPLICATION_VERSION = __version__ +APPLICATION_AUTHOR_NAME = 'Loren Eteval' +APPLICATION_AUTHOR_EMAIL = 'loren.eteval@proton.me' APPLICATION_MACOS_SIGNATURE = 'com.Furious' -APPLICATION_REPO_OWNER_NAME = 'LorenEteval' +APPLICATION_FLATPAK_ID = 'com.Furious.Furious' +APPLICATION_REPO_OWNER_NAME = APPLICATION_AUTHOR_NAME.replace(' ', '') APPLICATION_REPO_NAME = 'Furious' APPLICATION_ABOUT_PAGE = ( f'https://github.com/{APPLICATION_REPO_OWNER_NAME}/{APPLICATION_REPO_NAME}' diff --git a/Furious/Utility/StartupOnBoot.py b/Furious/Frozenlib/StartupOnBoot.py similarity index 98% rename from Furious/Utility/StartupOnBoot.py rename to Furious/Frozenlib/StartupOnBoot.py index 7046d51..8fe9e8d 100644 --- a/Furious/Utility/StartupOnBoot.py +++ b/Furious/Frozenlib/StartupOnBoot.py @@ -15,8 +15,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from Furious.Frozenlib import * -from Furious.Utility.SystemRuntime import * +from Furious.Frozenlib.Constants import * +from Furious.Frozenlib.SystemRuntime import * from PySide6 import QtCore diff --git a/Furious/Utility/SystemProxy.py b/Furious/Frozenlib/SystemProxy.py similarity index 96% rename from Furious/Utility/SystemProxy.py rename to Furious/Frozenlib/SystemProxy.py index 332a177..2046719 100644 --- a/Furious/Utility/SystemProxy.py +++ b/Furious/Frozenlib/SystemProxy.py @@ -17,7 +17,11 @@ from __future__ import annotations -from Furious.Frozenlib import * +from Furious.Frozenlib.Constants import * +from Furious.Frozenlib.Enum import * +from Furious.Frozenlib.AppSettings import * +from Furious.Frozenlib.Utility import * +from Furious.Frozenlib.SystemRuntime import * import logging import subprocess @@ -43,9 +47,14 @@ def handleAppSystemProxyMode() -> bool: def linuxProxyConfig(proxy_args, arg0, arg1): + command = 'gsettings' + + if SystemRuntime.flatpakID(): + command = 'flatpak-spawn --host ' + command + runExternalCommand( - [ - 'gsettings', + command.split() + + [ 'set', 'org.gnome.system.' + proxy_args, arg0, diff --git a/Furious/Frozenlib/SystemRoutingTable.py b/Furious/Frozenlib/SystemRoutingTable.py index b99d055..90109c2 100644 --- a/Furious/Frozenlib/SystemRoutingTable.py +++ b/Furious/Frozenlib/SystemRoutingTable.py @@ -19,6 +19,7 @@ from __future__ import annotations from Furious.Frozenlib.Constants import * from Furious.Frozenlib.Utility import * +from Furious.Frozenlib.SystemRuntime import * import re import logging @@ -335,9 +336,14 @@ class SystemRoutingTable: def LinuxFindTUNDevice(deviceName: str) -> bool: assert PLATFORM == 'Linux' + command = 'ip tuntap show' + + if SystemRuntime.flatpakID(): + command = 'flatpak-spawn --host ' + command + try: result = runExternalCommand( - 'ip tuntap show'.split(), + command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, @@ -364,9 +370,14 @@ class SystemRoutingTable: def LinuxDeleteTUNDevice(deviceName: str) -> bool: assert PLATFORM == 'Linux' + command = 'ip tuntap del mode tun dev' + + if SystemRuntime.flatpakID(): + command = 'flatpak-spawn --host ' + command + try: result = runExternalCommand( - 'ip tuntap del mode tun dev'.split() + [deviceName], + command.split() + [deviceName], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, @@ -396,9 +407,14 @@ class SystemRoutingTable: def LinuxExecutePrivilegedScript(filepath, shell='bash') -> bool: assert PLATFORM == 'Linux' + command = 'pkexec' + + if SystemRuntime.flatpakID(): + command = 'flatpak-spawn --host ' + command + try: result = runExternalCommand( - ['pkexec', shell, filepath], + command.split() + [shell, filepath], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, @@ -428,9 +444,14 @@ class SystemRoutingTable: def LinuxGetIpRoute() -> str: assert PLATFORM == 'Linux' + command = 'ip route show' + + if SystemRuntime.flatpakID(): + command = 'flatpak-spawn --host ' + command + try: result = runExternalCommand( - 'ip route show'.split(), + command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, @@ -483,8 +504,13 @@ class SystemRoutingTable: ) if PLATFORM == 'Linux': + command = 'ip route show default' + + if SystemRuntime.flatpakID(): + command = 'flatpak-spawn --host ' + command + result = runExternalCommand( - 'ip route show default'.split(), + command.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, diff --git a/Furious/Utility/SystemRuntime.py b/Furious/Frozenlib/SystemRuntime.py similarity index 90% rename from Furious/Utility/SystemRuntime.py rename to Furious/Frozenlib/SystemRuntime.py index 4e391aa..1d92a08 100644 --- a/Furious/Utility/SystemRuntime.py +++ b/Furious/Frozenlib/SystemRuntime.py @@ -17,7 +17,9 @@ from __future__ import annotations -from Furious.Frozenlib import * +from Furious.Frozenlib.Constants import * +from Furious.Frozenlib.Utility import * +from Furious.Frozenlib.AppSettings import * import os import sys @@ -70,6 +72,16 @@ class SystemRuntime: else: return '' + @staticmethod + def flatpakID() -> str: + if PLATFORM != 'Linux': + return '' + + if 'FLATPAK_ID' in os.environ: + return os.environ['FLATPAK_ID'] + else: + return '' + @staticmethod @functools.lru_cache(None) def isAdmin() -> bool: diff --git a/Furious/Frozenlib/__init__.py b/Furious/Frozenlib/__init__.py index e9f2dfc..31573e3 100644 --- a/Furious/Frozenlib/__init__.py +++ b/Furious/Frozenlib/__init__.py @@ -21,7 +21,10 @@ from .Enum import * from .Globals import * from .Mixins import * from .PySide6Legacy import * +from .StartupOnBoot import * +from .SystemProxy import * from .SystemRoutingTable import * +from .SystemRuntime import * from .Tcping import * from .Utility import * from .Win32Session import * diff --git a/Furious/Qt/DynamicTheme.py b/Furious/Qt/DynamicTheme.py index 1fd5541..28f19ed 100644 --- a/Furious/Qt/DynamicTheme.py +++ b/Furious/Qt/DynamicTheme.py @@ -19,7 +19,6 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Qt.QtGui import * -from Furious.Utility import * __all__ = ['AppHue'] diff --git a/Furious/Qt/QtGui.py b/Furious/Qt/QtGui.py index 50c68a1..e78c5d3 100644 --- a/Furious/Qt/QtGui.py +++ b/Furious/Qt/QtGui.py @@ -17,7 +17,6 @@ from Furious.Frozenlib import * from Furious.Qt.DynamicTranslate import gettext as _ -from Furious.Utility import * from PySide6 import QtCore from PySide6.QtGui import * diff --git a/Furious/TrayActions/Connect.py b/Furious/TrayActions/Connect.py index 128f2dc..1ef08e1 100644 --- a/Furious/TrayActions/Connect.py +++ b/Furious/TrayActions/Connect.py @@ -22,7 +22,6 @@ from Furious.Interface import * from Furious.Library import * from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.Utility import * from Furious.Core import * from Furious.Widget.ConnectProgressBar import ConnectProgressBar diff --git a/Furious/TrayActions/Settings.py b/Furious/TrayActions/Settings.py index d51fde2..6c27d49 100644 --- a/Furious/TrayActions/Settings.py +++ b/Furious/TrayActions/Settings.py @@ -20,7 +20,6 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.Utility import * __all__ = ['SettingsAction'] diff --git a/Furious/Utility/__init__.py b/Furious/Utility/__init__.py index 4b07a40..7af5999 100644 --- a/Furious/Utility/__init__.py +++ b/Furious/Utility/__init__.py @@ -15,7 +15,4 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from .StartupOnBoot import * -from .SystemProxy import * -from .SystemRuntime import * from .AppMainProcess import * diff --git a/Furious/Widget/Application.py b/Furious/Widget/Application.py index 98276d7..c5ef140 100644 --- a/Furious/Widget/Application.py +++ b/Furious/Widget/Application.py @@ -19,7 +19,6 @@ from Furious.Frozenlib import * from Furious.Interface import * from Furious.Qt import gettext as _ from Furious.Library import * -from Furious.Utility import * from Furious.Widget.SystemTrayIcon import * from Furious.Window.AppMainWindow import * from Furious.Window.LogViewerWindow import * @@ -261,6 +260,12 @@ class Application(ApplicationFactory, SingletonApplication): # Xray environment variables os.environ['XRAY_LOCATION_ASSET'] = str(XRAY_ASSET_DIR) + if SystemRuntime.flatpakID(): + # https://github.com/flatpak/flatpak/issues/3438 + os.environ['TMPDIR'] = os.path.join( + os.environ.get('XDG_RUNTIME_DIR'), 'app', APPLICATION_FLATPAK_ID + ) + def addStorage(self): # Protected storage access self._userActivatedItemIndex = Storage.UserActivatedItemIndex() @@ -280,6 +285,9 @@ class Application(ApplicationFactory, SingletonApplication): return backgroudColor.lightness() < 128 def isDarkModeEnabled(self): + if SystemRuntime.flatpakID(): + return self.isDarkMode() + if not SystemRuntime.isAdmin(): return AppSettings.isStateON_('DarkMode') else: @@ -393,6 +401,13 @@ class Application(ApplicationFactory, SingletonApplication): else: logger.info('not running from Linux AppImage') + flatpakId = SystemRuntime.flatpakID() + + if flatpakId: + logger.info(f'running from Linux flatpak: \'{flatpakId}\'') + else: + logger.info('not running from Linux flatpak') + logger.info(f'python version: {PLATFORM_PYTHON_VERSION}') logger.info(f'system version: {sys.version}') logger.info(f'sys.executable: \'{sys.executable}\'') diff --git a/Furious/Widget/GuiTUNSettings.py b/Furious/Widget/GuiTUNSettings.py index 3fdaab0..0f57fab 100644 --- a/Furious/Widget/GuiTUNSettings.py +++ b/Furious/Widget/GuiTUNSettings.py @@ -22,7 +22,6 @@ from Furious.Interface import * from Furious.Library import * from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.Utility import * from PySide6.QtGui import * diff --git a/Furious/Widget/SystemTrayIcon.py b/Furious/Widget/SystemTrayIcon.py index 5b1308b..39499e2 100644 --- a/Furious/Widget/SystemTrayIcon.py +++ b/Furious/Widget/SystemTrayIcon.py @@ -18,7 +18,6 @@ from Furious.Frozenlib import * from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.Utility import * from Furious.TrayActions import * from PySide6 import QtCore diff --git a/Furious/Widget/XrayAssetViewerQListWidget.py b/Furious/Widget/XrayAssetViewerQListWidget.py index 263167e..61ba725 100644 --- a/Furious/Widget/XrayAssetViewerQListWidget.py +++ b/Furious/Widget/XrayAssetViewerQListWidget.py @@ -20,7 +20,6 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.Utility import * from PySide6 import QtCore from PySide6.QtGui import * diff --git a/Furious/Window/AppMainWindow.py b/Furious/Window/AppMainWindow.py index 1379f4f..3d1a1f2 100644 --- a/Furious/Window/AppMainWindow.py +++ b/Furious/Window/AppMainWindow.py @@ -22,7 +22,6 @@ from Furious.Interface import * from Furious.Library import * from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.Utility import * from Furious.Widget.UserServersQTableWidget import * from Furious.Widget.GuiTUNSettings import * from Furious.Window.UserSubsWindow import *