Merge branch 'develop' into remove-updater

This commit is contained in:
Sefa Eyeoglu 2022-12-14 23:22:27 +01:00
commit 849b92665e
No known key found for this signature in database
GPG Key ID: C10411294912A422
251 changed files with 20746 additions and 1271 deletions

View File

@ -15,6 +15,9 @@ on:
SPARKLE_ED25519_KEY: SPARKLE_ED25519_KEY:
description: Private key for signing Sparkle updates description: Private key for signing Sparkle updates
required: false required: false
CACHIX_AUTH_TOKEN:
description: Private token for authenticating against Cachix cache
required: false
jobs: jobs:
build: build:
@ -35,17 +38,11 @@ jobs:
qt_tools: '' qt_tools: ''
- os: windows-2022 - os: windows-2022
name: "Windows-Legacy" name: "Windows-MinGW-w64"
msystem: clang32
qt_ver: 5
- os: windows-2022
name: "Windows"
msystem: clang64 msystem: clang64
qt_ver: 6
- os: windows-2022 - os: windows-2022
name: "Windows-Legacy-MSVC" name: "Windows-MSVC-Legacy"
msystem: '' msystem: ''
architecture: 'win32' architecture: 'win32'
vcvars_arch: 'amd64_x86' vcvars_arch: 'amd64_x86'
@ -64,7 +61,19 @@ jobs:
qt_ver: 6 qt_ver: 6
qt_host: windows qt_host: windows
qt_arch: '' qt_arch: ''
qt_version: '6.4.1' qt_version: '6.4.0'
qt_modules: 'qt5compat qtimageformats'
qt_tools: ''
- os: windows-2022
name: "Windows-MSVC-arm64"
msystem: ''
architecture: 'arm64'
vcvars_arch: 'amd64_arm64'
qt_ver: 6
qt_host: windows
qt_arch: 'win64_msvc2019_arm64'
qt_version: '6.4.0'
qt_modules: 'qt5compat qtimageformats' qt_modules: 'qt5compat qtimageformats'
qt_tools: '' qt_tools: ''
@ -120,12 +129,12 @@ jobs:
cmake:p cmake:p
extra-cmake-modules:p extra-cmake-modules:p
ninja:p ninja:p
qt${{ matrix.qt_ver }}-base:p qt6-base:p
qt${{ matrix.qt_ver }}-svg:p qt6-svg:p
qt${{ matrix.qt_ver }}-imageformats:p qt6-imageformats:p
quazip-qt${{ matrix.qt_ver }}:p quazip-qt6:p
ccache:p ccache:p
${{ matrix.qt_ver == 6 && 'qt6-5compat:p' || '' }} qt6-5compat:p
- name: Force newer ccache - name: Force newer ccache
if: runner.os == 'Windows' && matrix.msystem == '' && inputs.build_type == 'Debug' if: runner.os == 'Windows' && matrix.msystem == '' && inputs.build_type == 'Debug'
@ -136,7 +145,7 @@ jobs:
if: (runner.os != 'Windows' || matrix.msystem == '') && inputs.build_type == 'Debug' if: (runner.os != 'Windows' || matrix.msystem == '') && inputs.build_type == 'Debug'
uses: hendrikmuhs/ccache-action@v1.2.5 uses: hendrikmuhs/ccache-action@v1.2.5
with: with:
key: ${{ matrix.os }}-qt${{ matrix.qt_ver }} key: ${{ matrix.os }}-qt${{ matrix.qt_ver }}-${{ matrix.architecture }}
- name: Setup ccache (Windows MinGW-w64) - name: Setup ccache (Windows MinGW-w64)
if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug' if: runner.os == 'Windows' && matrix.msystem != '' && inputs.build_type == 'Debug'
@ -159,9 +168,9 @@ jobs:
uses: actions/cache@v3.0.11 uses: actions/cache@v3.0.11
with: with:
path: '${{ github.workspace }}\.ccache' path: '${{ github.workspace }}\.ccache'
key: ${{ matrix.os }}-qt${{ matrix.qt_ver }} key: ${{ matrix.os }}-mingw-w64
restore-keys: | restore-keys: |
${{ matrix.os }}-qt${{ matrix.qt_ver }} ${{ matrix.os }}-mingw-w64
- name: Set short version - name: Set short version
shell: bash shell: bash
@ -185,8 +194,23 @@ jobs:
if: runner.os == 'Linux' && matrix.qt_ver != 6 if: runner.os == 'Linux' && matrix.qt_ver != 6
run: | run: |
sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5 sudo apt-get -y install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5core5a libqt5network5 libqt5gui5
- name: Install Qt (macOS, AppImage & Windows MSVC) - name: Install host Qt (Windows MSVC arm64)
if: runner.os == 'Windows' && matrix.architecture == 'arm64'
uses: jurplel/install-qt-action@v3
with:
version: ${{ matrix.qt_version }}
host: 'windows'
target: 'desktop'
arch: ''
modules: ${{ matrix.qt_modules }}
tools: ${{ matrix.qt_tools }}
cache: ${{ inputs.is_qt_cached }}
cache-key-prefix: host-qt-arm64-windows
dir: ${{ github.workspace }}\HostQt
set-env: false
- name: Install Qt (macOS, Linux, Qt 6 & Windows MSVC)
if: runner.os == 'Linux' && matrix.qt_ver == 6 || runner.os == 'macOS' || (runner.os == 'Windows' && matrix.msystem == '') if: runner.os == 'Linux' && matrix.qt_ver == 6 || runner.os == 'macOS' || (runner.os == 'Windows' && matrix.msystem == '')
uses: jurplel/install-qt-action@v3 uses: jurplel/install-qt-action@v3
with: with:
@ -198,6 +222,13 @@ jobs:
tools: ${{ matrix.qt_tools }} tools: ${{ matrix.qt_tools }}
cache: ${{ inputs.is_qt_cached }} cache: ${{ inputs.is_qt_cached }}
- name: Install MSVC (Windows MSVC)
if: runner.os == 'Windows' && matrix.msystem == ''
uses: ilammy/msvc-dev-cmd@v1
with:
vsversion: 2022
arch: ${{ matrix.vcvars_arch }}
- name: Prepare AppImage (Linux) - name: Prepare AppImage (Linux)
if: runner.os == 'Linux' && matrix.qt_ver != 5 if: runner.os == 'Linux' && matrix.qt_ver != 5
run: | run: |
@ -207,6 +238,11 @@ jobs:
${{ github.workspace }}/.github/scripts/prepare_JREs.sh ${{ github.workspace }}/.github/scripts/prepare_JREs.sh
- name: Add QT_HOST_PATH var (Windows MSVC arm64)
if: runner.os == 'Windows' && matrix.architecture == 'arm64'
run: |
echo "QT_HOST_PATH=${{ github.workspace }}\HostQt\Qt\${{ matrix.qt_version }}\msvc2019_64" >> $env:GITHUB_ENV
## ##
# CONFIGURE # CONFIGURE
## ##
@ -225,12 +261,12 @@ jobs:
if: runner.os == 'Windows' && matrix.msystem != '' if: runner.os == 'Windows' && matrix.msystem != ''
shell: msys2 {0} shell: msys2 {0}
run: | run: |
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -G Ninja cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DCMAKE_C_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DCMAKE_CXX_COMPILER_LAUNCHER=${{ env.CCACHE_VAR }} -DLauncher_QT_VERSION_MAJOR=6 -DCMAKE_OBJDUMP=/mingw64/bin/objdump.exe -G Ninja
- name: Configure CMake (Windows MSVC) - name: Configure CMake (Windows MSVC)
if: runner.os == 'Windows' && matrix.msystem == '' if: runner.os == 'Windows' && matrix.msystem == ''
run: | run: |
cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} cmake -S . -B ${{ env.BUILD_DIR }} -DCMAKE_INSTALL_PREFIX=${{ env.INSTALL_DIR }} -DCMAKE_BUILD_TYPE=${{ inputs.build_type }} -DENABLE_LTO=ON -DLauncher_BUILD_PLATFORM=${{ matrix.name }} -DLauncher_QT_VERSION_MAJOR=${{ matrix.qt_ver }} -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreadedDLL" -A${{ matrix.architecture}} -DLauncher_FORCE_BUNDLED_LIBS=ON
# https://github.com/ccache/ccache/wiki/MS-Visual-Studio (I coudn't figure out the compiler prefix) # https://github.com/ccache/ccache/wiki/MS-Visual-Studio (I coudn't figure out the compiler prefix)
if ("${{ env.CCACHE_VAR }}") if ("${{ env.CCACHE_VAR }}")
{ {
@ -283,7 +319,7 @@ jobs:
ctest -E "^example64|example$" --test-dir build --output-on-failure ctest -E "^example64|example$" --test-dir build --output-on-failure
- name: Test (Windows MSVC) - name: Test (Windows MSVC)
if: runner.os == 'Windows' && matrix.msystem == '' if: runner.os == 'Windows' && matrix.msystem == '' && matrix.architecture != 'arm64'
run: | run: |
ctest -E "^example64|example$" --test-dir build --output-on-failure -C ${{ inputs.build_type }} ctest -E "^example64|example$" --test-dir build --output-on-failure -C ${{ inputs.build_type }}
@ -321,23 +357,12 @@ jobs:
EOF EOF
fi fi
- name: Add VC Enviroment Variables
if: runner.os == 'Windows' && matrix.msystem == ''
uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{ matrix.vcvars_arch }}
- name: Package (Windows MinGW-w64) - name: Package (Windows MinGW-w64)
if: runner.os == 'Windows' && matrix.msystem != '' if: runner.os == 'Windows' && matrix.msystem != ''
shell: msys2 {0} shell: msys2 {0}
run: | run: |
cmake --install ${{ env.BUILD_DIR }} cmake --install ${{ env.BUILD_DIR }}
cd ${{ env.INSTALL_DIR }}
if [ "${{ matrix.qt_ver }}" == "5" ]; then
cp /clang32/bin/libcrypto-1_1.dll /clang32/bin/libssl-1_1.dll ./
fi
- name: Package (Windows MSVC) - name: Package (Windows MSVC)
if: runner.os == 'Windows' && matrix.msystem == '' if: runner.os == 'Windows' && matrix.msystem == ''
run: | run: |
@ -526,3 +551,33 @@ jobs:
bundle: "Prism Launcher.flatpak" bundle: "Prism Launcher.flatpak"
manifest-path: flatpak/org.prismlauncher.PrismLauncher.yml manifest-path: flatpak/org.prismlauncher.PrismLauncher.yml
cache-key: flatpak-${{ github.sha }}-x86_64 cache-key: flatpak-${{ github.sha }}-x86_64
nix:
runs-on: ubuntu-latest
strategy:
matrix:
package:
- prismlauncher
- prismlauncher-qt5
steps:
- name: Clone repository
if: inputs.build_type == 'Debug'
uses: actions/checkout@v3
with:
submodules: 'true'
- name: Install nix
if: inputs.build_type == 'Debug'
uses: cachix/install-nix-action@v18
with:
install_url: https://nixos.org/nix/install
extra_nix_config: |
auto-optimise-store = true
experimental-features = nix-command flakes
- uses: cachix/cachix-action@v12
if: inputs.build_type == 'Debug'
with:
name: prismlauncher
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- name: Build
if: inputs.build_type == 'Debug'
run: nix build .#${{ matrix.package }} --print-build-logs

View File

@ -8,7 +8,6 @@ on:
- '**.md' - '**.md'
- '**/LICENSE' - '**/LICENSE'
- 'flake.lock' - 'flake.lock'
- '**.nix'
- 'packages/**' - 'packages/**'
- '.github/ISSUE_TEMPLATE/**' - '.github/ISSUE_TEMPLATE/**'
- '.markdownlint**' - '.markdownlint**'
@ -17,7 +16,6 @@ on:
- '**.md' - '**.md'
- '**/LICENSE' - '**/LICENSE'
- 'flake.lock' - 'flake.lock'
- '**.nix'
- 'packages/**' - 'packages/**'
- '.github/ISSUE_TEMPLATE/**' - '.github/ISSUE_TEMPLATE/**'
- '.markdownlint**' - '.markdownlint**'
@ -33,3 +31,4 @@ jobs:
is_qt_cached: true is_qt_cached: true
secrets: secrets:
SPARKLE_ED25519_KEY: ${{ secrets.SPARKLE_ED25519_KEY }} SPARKLE_ED25519_KEY: ${{ secrets.SPARKLE_ED25519_KEY }}
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}

View File

@ -46,15 +46,26 @@ jobs:
tar -czf PrismLauncher-${{ env.VERSION }}.tar.gz PrismLauncher-${{ env.VERSION }} tar -czf PrismLauncher-${{ env.VERSION }}.tar.gz PrismLauncher-${{ env.VERSION }}
for d in PrismLauncher-Windows-*; do for d in PrismLauncher-Windows-MSVC*; do
cd "${d}" || continue cd "${d}" || continue
MSVC="$(echo -n ${d} | grep -o MSVC || true)"
LEGACY="$(echo -n ${d} | grep -o Legacy || true)" LEGACY="$(echo -n ${d} | grep -o Legacy || true)"
ARM64="$(echo -n ${d} | grep -o arm64 || true)"
INST="$(echo -n ${d} | grep -o Setup || true)" INST="$(echo -n ${d} | grep -o Setup || true)"
PORT="$(echo -n ${d} | grep -o Portable || true)" PORT="$(echo -n ${d} | grep -o Portable || true)"
NAME="PrismLauncher-Windows" NAME="PrismLauncher-Windows-MSVC"
test -z "${MSVC}" && NAME="${NAME}-MinGW" || NAME="${NAME}-MSVC"
test -z "${LEGACY}" || NAME="${NAME}-Legacy" test -z "${LEGACY}" || NAME="${NAME}-Legacy"
test -z "${ARM64}" || NAME="${NAME}-arm64"
test -z "${PORT}" || NAME="${NAME}-Portable"
test -z "${INST}" || mv PrismLauncher-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe
test -n "${INST}" || zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" *
cd ..
done
for d in PrismLauncher-Windows-MinGW-w64*; do
cd "${d}" || continue
INST="$(echo -n ${d} | grep -o Setup || true)"
PORT="$(echo -n ${d} | grep -o Portable || true)"
NAME="PrismLauncher-Windows-MinGW-w64"
test -z "${PORT}" || NAME="${NAME}-Portable" test -z "${PORT}" || NAME="${NAME}-Portable"
test -z "${INST}" || mv PrismLauncher-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe test -z "${INST}" || mv PrismLauncher-*.exe ../${NAME}-Setup-${{ env.VERSION }}.exe
test -n "${INST}" || zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" * test -n "${INST}" || zip -r -9 "../${NAME}-${{ env.VERSION }}.zip" *
@ -77,15 +88,15 @@ jobs:
PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage PrismLauncher-Linux-${{ env.VERSION }}-x86_64.AppImage
PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz PrismLauncher-Linux-Qt6-${{ env.VERSION }}.tar.gz
PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz PrismLauncher-Linux-Qt6-Portable-${{ env.VERSION }}.tar.gz
PrismLauncher-Windows-MinGW-Legacy-${{ env.VERSION }}.zip PrismLauncher-Windows-MinGW-w64-${{ env.VERSION }}.zip
PrismLauncher-Windows-MinGW-Legacy-Portable-${{ env.VERSION }}.zip PrismLauncher-Windows-MinGW-w64-Portable-${{ env.VERSION }}.zip
PrismLauncher-Windows-MinGW-Legacy-Setup-${{ env.VERSION }}.exe PrismLauncher-Windows-MinGW-w64-Setup-${{ env.VERSION }}.exe
PrismLauncher-Windows-MinGW-${{ env.VERSION }}.zip
PrismLauncher-Windows-MinGW-Portable-${{ env.VERSION }}.zip
PrismLauncher-Windows-MinGW-Setup-${{ env.VERSION }}.exe
PrismLauncher-Windows-MSVC-Legacy-${{ env.VERSION }}.zip PrismLauncher-Windows-MSVC-Legacy-${{ env.VERSION }}.zip
PrismLauncher-Windows-MSVC-Legacy-Portable-${{ env.VERSION }}.zip PrismLauncher-Windows-MSVC-Legacy-Portable-${{ env.VERSION }}.zip
PrismLauncher-Windows-MSVC-Legacy-Setup-${{ env.VERSION }}.exe PrismLauncher-Windows-MSVC-Legacy-Setup-${{ env.VERSION }}.exe
PrismLauncher-Windows-MSVC-arm64-${{ env.VERSION }}.zip
PrismLauncher-Windows-MSVC-arm64-Portable-${{ env.VERSION }}.zip
PrismLauncher-Windows-MSVC-arm64-Setup-${{ env.VERSION }}.exe
PrismLauncher-Windows-MSVC-${{ env.VERSION }}.zip PrismLauncher-Windows-MSVC-${{ env.VERSION }}.zip
PrismLauncher-Windows-MSVC-Portable-${{ env.VERSION }}.zip PrismLauncher-Windows-MSVC-Portable-${{ env.VERSION }}.zip
PrismLauncher-Windows-MSVC-Setup-${{ env.VERSION }}.exe PrismLauncher-Windows-MSVC-Setup-${{ env.VERSION }}.exe

View File

@ -129,7 +129,7 @@ set(Launcher_NEWS_OPEN_URL "https://prismlauncher.org/news" CACHE STRING "URL th
set(Launcher_HELP_URL "https://prismlauncher.org/wiki/help-pages/%1" CACHE STRING "URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help") set(Launcher_HELP_URL "https://prismlauncher.org/wiki/help-pages/%1" CACHE STRING "URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help")
######## Set version numbers ######## ######## Set version numbers ########
set(Launcher_VERSION_MAJOR 6) set(Launcher_VERSION_MAJOR 7)
set(Launcher_VERSION_MINOR 0) set(Launcher_VERSION_MINOR 0)
set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}") set(Launcher_VERSION_NAME "${Launcher_VERSION_MAJOR}.${Launcher_VERSION_MINOR}")
@ -221,7 +221,7 @@ if(Launcher_QT_VERSION_MAJOR EQUAL 5)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUNICODE -D_UNICODE") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUNICODE -D_UNICODE")
elseif(Launcher_QT_VERSION_MAJOR EQUAL 6) elseif(Launcher_QT_VERSION_MAJOR EQUAL 6)
set(QT_VERSION_MAJOR 6) set(QT_VERSION_MAJOR 6)
find_package(Qt6 REQUIRED COMPONENTS Core Widgets Concurrent Network Test Xml Core5Compat) find_package(Qt6 REQUIRED COMPONENTS Core CoreTools Widgets Concurrent Network Test Xml Core5Compat)
list(APPEND Launcher_QT_LIBS Qt6::Core5Compat) list(APPEND Launcher_QT_LIBS Qt6::Core5Compat)
if(NOT Launcher_FORCE_BUNDLED_LIBS) if(NOT Launcher_FORCE_BUNDLED_LIBS)
@ -235,12 +235,16 @@ else()
message(FATAL_ERROR "Qt version ${Launcher_QT_VERSION_MAJOR} is not supported") message(FATAL_ERROR "Qt version ${Launcher_QT_VERSION_MAJOR} is not supported")
endif() endif()
include(ECMQueryQt) if(Launcher_QT_VERSION_MAJOR EQUAL 5)
ecm_query_qt(QT_PLUGINS_DIR QT_INSTALL_PLUGINS) include(ECMQueryQt)
ecm_query_qt(QT_LIBS_DIR QT_INSTALL_LIBS) ecm_query_qt(QT_PLUGINS_DIR QT_INSTALL_PLUGINS)
ecm_query_qt(QT_LIBEXECS_DIR QT_INSTALL_LIBEXECS) ecm_query_qt(QT_LIBS_DIR QT_INSTALL_LIBS)
ecm_query_qt(QT_DATA_DIR QT_HOST_DATA) ecm_query_qt(QT_LIBEXECS_DIR QT_INSTALL_LIBEXECS)
set(QT_MKSPECS_DIR ${QT_DATA_DIR}/mkspecs) else()
set(QT_PLUGINS_DIR ${QT${QT_VERSION_MAJOR}_INSTALL_PREFIX}/${QT${QT_VERSION_MAJOR}_INSTALL_PLUGINS})
set(QT_LIBS_DIR ${QT${QT_VERSION_MAJOR}_INSTALL_PREFIX}/${QT${QT_VERSION_MAJOR}_INSTALL_LIBS})
set(QT_LIBEXECS_DIR ${QT${QT_VERSION_MAJOR}_INSTALL_PREFIX}/${QT${QT_VERSION_MAJOR}_INSTALL_LIBEXECS})
endif()
# NOTE: Qt 6 already sets this by default # NOTE: Qt 6 already sets this by default
if (Qt5_POSITION_INDEPENDENT_CODE) if (Qt5_POSITION_INDEPENDENT_CODE)
@ -368,11 +372,11 @@ if(NOT ZLIB_FOUND)
set(SKIP_INSTALL_ALL ON) set(SKIP_INSTALL_ALL ON)
add_subdirectory(libraries/zlib EXCLUDE_FROM_ALL) add_subdirectory(libraries/zlib EXCLUDE_FROM_ALL)
set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib" "${CMAKE_CURRENT_BINARY_DIR}/libraries/zlib") set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libraries/zlib" "${CMAKE_CURRENT_BINARY_DIR}/libraries/zlib" CACHE STRING "")
set_target_properties(zlibstatic PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIR}") set_target_properties(zlibstatic PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${ZLIB_INCLUDE_DIR}")
add_library(ZLIB::ZLIB ALIAS zlibstatic) add_library(ZLIB::ZLIB ALIAS zlibstatic)
set(ZLIB_LIBRARY ZLIB::ZLIB) set(ZLIB_LIBRARY ZLIB::ZLIB CACHE STRING "zlib library name")
set(ZLIB_FOUND true)
find_package(ZLIB REQUIRED) find_package(ZLIB REQUIRED)
else() else()
message(STATUS "Using system zlib") message(STATUS "Using system zlib")

View File

@ -415,3 +415,28 @@
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library. If not, see <http://www.gnu.org/licenses/>. License along with this library. If not, see <http://www.gnu.org/licenses/>.
## Oxygen Icons
The Oxygen Icon Theme
Copyright (C) 2007 Nuno Pinheiro <nuno@oxygen-icons.org>
Copyright (C) 2007 David Vignoni <david@icon-king.com>
Copyright (C) 2007 David Miller <miller@oxygen-icons.org>
Copyright (C) 2007 Johann Ollivier Lapeyre <johann@oxygen-icons.org>
Copyright (C) 2007 Kenneth Wimer <kwwii@bootsplash.org>
Copyright (C) 2007 Riccardo Iaconelli <riccardo@oxygen-icons.org>
and others
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library. If not, see <http://www.gnu.org/licenses/>.

View File

@ -161,6 +161,8 @@ class Config {
QString MODRINTH_STAGING_URL = "https://staging-api.modrinth.com/v2"; QString MODRINTH_STAGING_URL = "https://staging-api.modrinth.com/v2";
QString MODRINTH_PROD_URL = "https://api.modrinth.com/v2"; QString MODRINTH_PROD_URL = "https://api.modrinth.com/v2";
QString FLAME_BASE_URL = "https://api.curseforge.com/v1";
QString versionString() const; QString versionString() const;
/** /**
* \brief Converts the Version to a string. * \brief Converts the Version to a string.

View File

@ -23,8 +23,8 @@
pkgs = forAllSystems (system: nixpkgs.legacyPackages.${system}); pkgs = forAllSystems (system: nixpkgs.legacyPackages.${system});
packagesFn = pkgs: rec { packagesFn = pkgs: rec {
prismlauncher = pkgs.libsForQt5.callPackage ./nix { inherit version self libnbtplusplus tomlplusplus; }; prismlauncher-qt5 = pkgs.libsForQt5.callPackage ./nix { inherit version self libnbtplusplus tomlplusplus; };
prismlauncher-qt6 = pkgs.qt6Packages.callPackage ./nix { inherit version self libnbtplusplus tomlplusplus; }; prismlauncher = pkgs.qt6Packages.callPackage ./nix { inherit version self libnbtplusplus tomlplusplus; };
}; };
in in
{ {

View File

@ -97,6 +97,7 @@
#include <QIcon> #include <QIcon>
#include "InstanceList.h" #include "InstanceList.h"
#include "MTPixmapCache.h"
#include <minecraft/auth/AccountList.h> #include <minecraft/auth/AccountList.h>
#include "icons/IconList.h" #include "icons/IconList.h"
@ -125,6 +126,7 @@
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
#include <dlfcn.h> #include <dlfcn.h>
#include "gamemode_client.h" #include "gamemode_client.h"
#include "MangoHud.h"
#endif #endif
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
@ -145,6 +147,8 @@
static const QLatin1String liveCheckFile("live.check"); static const QLatin1String liveCheckFile("live.check");
PixmapCache* PixmapCache::s_instance = nullptr;
namespace { namespace {
void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) void appDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{ {
@ -654,6 +658,9 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
m_globalSettingsProvider->addPage<AccountListPage>(); m_globalSettingsProvider->addPage<AccountListPage>();
m_globalSettingsProvider->addPage<APIPage>(); m_globalSettingsProvider->addPage<APIPage>();
} }
PixmapCache::setInstance(new PixmapCache(this));
qDebug() << "<> Settings loaded."; qDebug() << "<> Settings loaded.";
} }
@ -876,13 +883,13 @@ bool Application::createSetupWizard()
return false; return false;
} }
bool Application::event(QEvent* event) { bool Application::event(QEvent* event)
{
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
if (event->type() == QEvent::ApplicationStateChange) { if (event->type() == QEvent::ApplicationStateChange) {
auto ev = static_cast<QApplicationStateChangeEvent*>(event); auto ev = static_cast<QApplicationStateChangeEvent*>(event);
if (m_prevAppState == Qt::ApplicationActive if (m_prevAppState == Qt::ApplicationActive && ev->applicationState() == Qt::ApplicationActive) {
&& ev->applicationState() == Qt::ApplicationActive) {
emit clickedOnDock(); emit clickedOnDock();
} }
m_prevAppState = ev->applicationState(); m_prevAppState = ev->applicationState();
@ -1480,17 +1487,8 @@ void Application::updateCapabilities()
if (gamemode_query_status() >= 0) if (gamemode_query_status() >= 0)
m_capabilities |= SupportsGameMode; m_capabilities |= SupportsGameMode;
{ if (!MangoHud::getLibraryString().isEmpty())
void *dummy = dlopen("libMangoHud_dlsym.so", RTLD_LAZY); m_capabilities |= SupportsMangoHud;
// try normal variant as well
if (dummy == NULL)
dummy = dlopen("libMangoHud.so", RTLD_LAZY);
if (dummy != NULL) {
dlclose(dummy);
m_capabilities |= SupportsMangoHud;
}
}
#endif #endif
} }

View File

@ -89,7 +89,18 @@ set(CORE_SOURCES
# Time # Time
MMCTime.h MMCTime.h
MMCTime.cpp MMCTime.cpp
MTPixmapCache.h
) )
if (UNIX AND NOT CYGWIN AND NOT APPLE)
set(CORE_SOURCES
${CORE_SOURCES}
# MangoHud
MangoHud.h
MangoHud.cpp
)
endif()
set(PATHMATCHER_SOURCES set(PATHMATCHER_SOURCES
# Path matchers # Path matchers
@ -672,6 +683,8 @@ SET(LAUNCHER_SOURCES
ui/pages/instance/GameOptionsPage.h ui/pages/instance/GameOptionsPage.h
ui/pages/instance/VersionPage.cpp ui/pages/instance/VersionPage.cpp
ui/pages/instance/VersionPage.h ui/pages/instance/VersionPage.h
ui/pages/instance/ManagedPackPage.cpp
ui/pages/instance/ManagedPackPage.h
ui/pages/instance/TexturePackPage.h ui/pages/instance/TexturePackPage.h
ui/pages/instance/ResourcePackPage.h ui/pages/instance/ResourcePackPage.h
ui/pages/instance/ShaderPackPage.h ui/pages/instance/ShaderPackPage.h
@ -788,6 +801,8 @@ SET(LAUNCHER_SOURCES
ui/dialogs/ExportInstanceDialog.h ui/dialogs/ExportInstanceDialog.h
ui/dialogs/IconPickerDialog.cpp ui/dialogs/IconPickerDialog.cpp
ui/dialogs/IconPickerDialog.h ui/dialogs/IconPickerDialog.h
ui/dialogs/ImportResourcePackDialog.cpp
ui/dialogs/ImportResourcePackDialog.h
ui/dialogs/LoginDialog.cpp ui/dialogs/LoginDialog.cpp
ui/dialogs/LoginDialog.h ui/dialogs/LoginDialog.h
ui/dialogs/MSALoginDialog.cpp ui/dialogs/MSALoginDialog.cpp
@ -907,6 +922,7 @@ qt_wrap_ui(LAUNCHER_UI
ui/pages/instance/OtherLogsPage.ui ui/pages/instance/OtherLogsPage.ui
ui/pages/instance/InstanceSettingsPage.ui ui/pages/instance/InstanceSettingsPage.ui
ui/pages/instance/VersionPage.ui ui/pages/instance/VersionPage.ui
ui/pages/instance/ManagedPackPage.ui
ui/pages/instance/WorldListPage.ui ui/pages/instance/WorldListPage.ui
ui/pages/instance/ScreenshotsPage.ui ui/pages/instance/ScreenshotsPage.ui
ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui ui/pages/modplatform/atlauncher/AtlOptionalModDialog.ui
@ -933,6 +949,7 @@ qt_wrap_ui(LAUNCHER_UI
ui/dialogs/SkinUploadDialog.ui ui/dialogs/SkinUploadDialog.ui
ui/dialogs/ExportInstanceDialog.ui ui/dialogs/ExportInstanceDialog.ui
ui/dialogs/IconPickerDialog.ui ui/dialogs/IconPickerDialog.ui
ui/dialogs/ImportResourcePackDialog.ui
ui/dialogs/MSALoginDialog.ui ui/dialogs/MSALoginDialog.ui
ui/dialogs/OfflineLoginDialog.ui ui/dialogs/OfflineLoginDialog.ui
ui/dialogs/AboutDialog.ui ui/dialogs/AboutDialog.ui

View File

@ -49,6 +49,7 @@
#include "StringUtils.h" #include "StringUtils.h"
#if defined Q_OS_WIN32 #if defined Q_OS_WIN32
#define WIN32_LEAN_AND_MEAN
#include <objbase.h> #include <objbase.h>
#include <objidl.h> #include <objidl.h>
#include <shlguid.h> #include <shlguid.h>
@ -188,6 +189,8 @@ bool copy::operator()(const QString& offset, bool dryRun)
qDebug() << "Source file:" << src_path; qDebug() << "Source file:" << src_path;
qDebug() << "Destination file:" << dst_path; qDebug() << "Destination file:" << dst_path;
} }
m_copied++;
emit fileCopied(relative_dst_path);
}; };
// We can't use copy_opts::recursive because we need to take into account the // We can't use copy_opts::recursive because we need to take into account the
@ -341,12 +344,35 @@ QString getDesktopDir()
} }
// Cross-platform Shortcut creation // Cross-platform Shortcut creation
bool createShortCut(QString location, QString dest, QStringList args, QString name, QString icon) bool createShortcut(QString destination, QString target, QStringList args, QString name, QString icon)
{ {
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) #if defined(Q_OS_MACOS)
location = PathCombine(location, name + ".desktop"); destination += ".command";
QFile f(location); QFile f(destination);
f.open(QIODevice::WriteOnly | QIODevice::Text);
QTextStream stream(&f);
QString argstring;
if (!args.empty())
argstring = " \"" + args.join("\" \"") + "\"";
stream << "#!/bin/bash"
<< "\n";
stream << "\""
<< target
<< "\" "
<< argstring
<< "\n";
stream.flush();
f.close();
f.setPermissions(f.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeGroup | QFileDevice::ExeOther);
return true;
#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
QFile f(destination);
f.open(QIODevice::WriteOnly | QIODevice::Text); f.open(QIODevice::WriteOnly | QIODevice::Text);
QTextStream stream(&f); QTextStream stream(&f);
@ -358,10 +384,12 @@ bool createShortCut(QString location, QString dest, QStringList args, QString na
<< "\n"; << "\n";
stream << "Type=Application" stream << "Type=Application"
<< "\n"; << "\n";
stream << "TryExec=" << dest.toLocal8Bit() << "\n"; stream << "Exec=\"" << target.toLocal8Bit() << "\"" << argstring.toLocal8Bit() << "\n";
stream << "Exec=" << dest.toLocal8Bit() << argstring.toLocal8Bit() << "\n";
stream << "Name=" << name.toLocal8Bit() << "\n"; stream << "Name=" << name.toLocal8Bit() << "\n";
stream << "Icon=" << icon.toLocal8Bit() << "\n"; if (!icon.isEmpty())
{
stream << "Icon=" << icon.toLocal8Bit() << "\n";
}
stream.flush(); stream.flush();
f.close(); f.close();
@ -369,25 +397,132 @@ bool createShortCut(QString location, QString dest, QStringList args, QString na
f.setPermissions(f.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeGroup | QFileDevice::ExeOther); f.setPermissions(f.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeGroup | QFileDevice::ExeOther);
return true; return true;
#elif defined Q_OS_WIN #elif defined(Q_OS_WIN)
// TODO: Fix QFileInfo targetInfo(target);
// QFile file(PathCombine(location, name + ".lnk"));
// WCHAR *file_w;
// WCHAR *dest_w;
// WCHAR *args_w;
// file.fileName().toWCharArray(file_w);
// dest.toWCharArray(dest_w);
// QString argStr; if (!targetInfo.exists())
// for (int i = 0; i < args.count(); i++) {
// { qWarning() << "Target file does not exist!";
// argStr.append(args[i]); return false;
// argStr.append(" "); }
// }
// argStr.toWCharArray(args_w);
// return SUCCEEDED(CreateLink(file_w, dest_w, args_w)); target = targetInfo.absoluteFilePath();
return false;
if (target.length() >= MAX_PATH)
{
qWarning() << "Target file path is too long!";
return false;
}
if (!icon.isEmpty() && icon.length() >= MAX_PATH)
{
qWarning() << "Icon path is too long!";
return false;
}
destination += ".lnk";
if (destination.length() >= MAX_PATH)
{
qWarning() << "Destination path is too long!";
return false;
}
QString argStr;
int argCount = args.count();
for (int i = 0; i < argCount; i++)
{
if (args[i].contains(' '))
{
argStr.append('"').append(args[i]).append('"');
}
else
{
argStr.append(args[i]);
}
if (i < argCount - 1)
{
argStr.append(" ");
}
}
if (argStr.length() >= MAX_PATH)
{
qWarning() << "Arguments string is too long!";
return false;
}
HRESULT hres;
// ...yes, you need to initialize the entire COM stack just to make a shortcut
hres = CoInitialize(nullptr);
if (FAILED(hres))
{
qWarning() << "Failed to initialize COM!";
return false;
}
WCHAR wsz[MAX_PATH];
IShellLink* psl;
// create an IShellLink instance - this stores the shortcut's attributes
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
if (SUCCEEDED(hres))
{
wmemset(wsz, 0, MAX_PATH);
target.toWCharArray(wsz);
psl->SetPath(wsz);
wmemset(wsz, 0, MAX_PATH);
argStr.toWCharArray(wsz);
psl->SetArguments(wsz);
wmemset(wsz, 0, MAX_PATH);
targetInfo.absolutePath().toWCharArray(wsz);
psl->SetWorkingDirectory(wsz); // "Starts in" attribute
if (!icon.isEmpty())
{
wmemset(wsz, 0, MAX_PATH);
icon.toWCharArray(wsz);
psl->SetIconLocation(wsz, 0);
}
// query an IPersistFile interface from our IShellLink instance
// this is the interface that will actually let us save the shortcut to disk!
IPersistFile* ppf;
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres))
{
wmemset(wsz, 0, MAX_PATH);
destination.toWCharArray(wsz);
hres = ppf->Save(wsz, TRUE);
if (FAILED(hres))
{
qWarning() << "IPresistFile->Save() failed";
qWarning() << "hres = " << hres;
}
ppf->Release();
}
else
{
qWarning() << "Failed to query IPersistFile interface from IShellLink instance";
qWarning() << "hres = " << hres;
}
psl->Release();
}
else
{
qWarning() << "Failed to create IShellLink instance";
qWarning() << "hres = " << hres;
}
// go away COM, nobody likes you
CoUninitialize();
return SUCCEEDED(hres);
#else #else
qWarning("Desktop Shortcuts not supported on your platform!"); qWarning("Desktop Shortcuts not supported on your platform!");
return false; return false;

View File

@ -172,4 +172,9 @@ QString getDesktopDir();
// Overrides one folder with the contents of another, preserving items exclusive to the first folder // Overrides one folder with the contents of another, preserving items exclusive to the first folder
// Equivalent to doing QDir::rename, but allowing for overrides // Equivalent to doing QDir::rename, but allowing for overrides
bool overrideFolder(QString overwritten_path, QString override_path); bool overrideFolder(QString overwritten_path, QString override_path);
/**
* Creates a shortcut to the specified target file at the specified destination path.
*/
bool createShortcut(QString destination, QString target, QStringList args, QString name, QString icon);
} }

View File

@ -25,10 +25,10 @@ void InstanceCopyTask::executeTask()
{ {
setStatus(tr("Copying instance %1").arg(m_origInstance->name())); setStatus(tr("Copying instance %1").arg(m_origInstance->name()));
FS::copy folderCopy(m_origInstance->instanceRoot(), m_stagingPath); m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [this]{
folderCopy.followSymlinks(false).matcher(m_matcher.get()); FS::copy folderCopy(m_origInstance->instanceRoot(), m_stagingPath);
folderCopy.followSymlinks(false).matcher(m_matcher.get());
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [&folderCopy]{
return folderCopy(); return folderCopy();
}); });
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &InstanceCopyTask::copyFinished); connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &InstanceCopyTask::copyFinished);

View File

@ -25,9 +25,13 @@ void InstanceCreationTask::executeTask()
return; return;
qWarning() << "Instance creation failed!"; qWarning() << "Instance creation failed!";
if (!m_error_message.isEmpty()) if (!m_error_message.isEmpty()) {
qWarning() << "Reason: " << m_error_message; qWarning() << "Reason: " << m_error_message;
emitFailed(tr("Error while creating new instance.")); emitFailed(tr("Error while creating new instance:\n%1").arg(m_error_message));
} else {
emitFailed(tr("Error while creating new instance."));
}
return; return;
} }

View File

@ -55,11 +55,9 @@
#include <quazip/quazipdir.h> #include <quazip/quazipdir.h>
InstanceImportTask::InstanceImportTask(const QUrl sourceUrl, QWidget* parent) InstanceImportTask::InstanceImportTask(const QUrl sourceUrl, QWidget* parent, QMap<QString, QString>&& extra_info)
{ : m_sourceUrl(sourceUrl), m_extra_info(extra_info), m_parent(parent)
m_sourceUrl = sourceUrl; {}
m_parent = parent;
}
bool InstanceImportTask::abort() bool InstanceImportTask::abort()
{ {
@ -164,18 +162,14 @@ void InstanceImportTask::processZipPack()
} }
else else
{ {
QString mmcRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "instance.cfg"); QStringList paths_to_ignore { "overrides/" };
QString flameRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "manifest.json");
if (!mmcRoot.isNull()) if (QString mmcRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "instance.cfg", paths_to_ignore); !mmcRoot.isNull()) {
{
// process as MultiMC instance/pack // process as MultiMC instance/pack
qDebug() << "MultiMC:" << mmcRoot; qDebug() << "MultiMC:" << mmcRoot;
root = mmcRoot; root = mmcRoot;
m_modpackType = ModpackType::MultiMC; m_modpackType = ModpackType::MultiMC;
} } else if (QString flameRoot = MMCZip::findFolderOfFileInZip(m_packZip.get(), "manifest.json", paths_to_ignore); !flameRoot.isNull()) {
else if(!flameRoot.isNull())
{
// process as Flame pack // process as Flame pack
qDebug() << "Flame:" << flameRoot; qDebug() << "Flame:" << flameRoot;
root = flameRoot; root = flameRoot;
@ -263,14 +257,28 @@ void InstanceImportTask::extractAborted()
void InstanceImportTask::processFlame() void InstanceImportTask::processFlame()
{ {
auto* inst_creation_task = new FlameCreationTask(m_stagingPath, m_globalSettings, m_parent); auto pack_id_it = m_extra_info.constFind("pack_id");
Q_ASSERT(pack_id_it != m_extra_info.constEnd());
auto pack_id = pack_id_it.value();
auto pack_version_id_it = m_extra_info.constFind("pack_version_id");
Q_ASSERT(pack_version_id_it != m_extra_info.constEnd());
auto pack_version_id = pack_version_id_it.value();
QString original_instance_id;
auto original_instance_id_it = m_extra_info.constFind("original_instance_id");
if (original_instance_id_it != m_extra_info.constEnd())
original_instance_id = original_instance_id_it.value();
auto* inst_creation_task = new FlameCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id);
inst_creation_task->setName(*this); inst_creation_task->setName(*this);
inst_creation_task->setIcon(m_instIcon); inst_creation_task->setIcon(m_instIcon);
inst_creation_task->setGroup(m_instGroup); inst_creation_task->setGroup(m_instGroup);
inst_creation_task->setConfirmUpdate(shouldConfirmUpdate());
connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] { connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] {
setOverride(inst_creation_task->shouldOverride()); setOverride(inst_creation_task->shouldOverride(), inst_creation_task->originalInstanceID());
emitSucceeded(); emitSucceeded();
}); });
connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed); connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed);
@ -327,14 +335,29 @@ void InstanceImportTask::processMultiMC()
void InstanceImportTask::processModrinth() void InstanceImportTask::processModrinth()
{ {
auto* inst_creation_task = new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, m_sourceUrl.toString()); auto pack_id_it = m_extra_info.constFind("pack_id");
Q_ASSERT(pack_id_it != m_extra_info.constEnd());
auto pack_id = pack_id_it.value();
QString pack_version_id;
auto pack_version_id_it = m_extra_info.constFind("pack_version_id");
if (pack_version_id_it != m_extra_info.constEnd())
pack_version_id = pack_version_id_it.value();
QString original_instance_id;
auto original_instance_id_it = m_extra_info.constFind("original_instance_id");
if (original_instance_id_it != m_extra_info.constEnd())
original_instance_id = original_instance_id_it.value();
auto* inst_creation_task = new ModrinthCreationTask(m_stagingPath, m_globalSettings, m_parent, pack_id, pack_version_id, original_instance_id);
inst_creation_task->setName(*this); inst_creation_task->setName(*this);
inst_creation_task->setIcon(m_instIcon); inst_creation_task->setIcon(m_instIcon);
inst_creation_task->setGroup(m_instGroup); inst_creation_task->setGroup(m_instGroup);
inst_creation_task->setConfirmUpdate(shouldConfirmUpdate());
connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] { connect(inst_creation_task, &Task::succeeded, this, [this, inst_creation_task] {
setOverride(inst_creation_task->shouldOverride()); setOverride(inst_creation_task->shouldOverride(), inst_creation_task->originalInstanceID());
emitSucceeded(); emitSucceeded();
}); });
connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed); connect(inst_creation_task, &Task::failed, this, &InstanceImportTask::emitFailed);

View File

@ -56,7 +56,7 @@ class InstanceImportTask : public InstanceTask
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit InstanceImportTask(const QUrl sourceUrl, QWidget* parent = nullptr); explicit InstanceImportTask(const QUrl sourceUrl, QWidget* parent = nullptr, QMap<QString, QString>&& extra_info = {});
bool abort() override; bool abort() override;
const QVector<Flame::File> &getBlockedFiles() const const QVector<Flame::File> &getBlockedFiles() const
@ -101,6 +101,10 @@ private: /* data */
Modrinth, Modrinth,
} m_modpackType = ModpackType::Unknown; } m_modpackType = ModpackType::Unknown;
// Extra info we might need, that's available before, but can't be derived from
// the source URL / the resource it points to alone.
QMap<QString, QString> m_extra_info;
//FIXME: nuke //FIXME: nuke
QWidget* m_parent; QWidget* m_parent;
}; };

View File

@ -816,7 +816,7 @@ class InstanceStaging : public Task {
void childSucceded() void childSucceded()
{ {
unsigned sleepTime = backoff(); unsigned sleepTime = backoff();
if (m_parent->commitStagedInstance(m_stagingPath, m_instance_name, m_groupName, m_child->shouldOverride())) if (m_parent->commitStagedInstance(m_stagingPath, m_instance_name, m_groupName, *m_child.get()))
{ {
emitSucceeded(); emitSucceeded();
return; return;
@ -880,25 +880,22 @@ QString InstanceList::getStagedInstancePath()
return path; return path;
} }
bool InstanceList::commitStagedInstance(const QString& path, InstanceName const& instanceName, const QString& groupName, bool should_override) bool InstanceList::commitStagedInstance(const QString& path, InstanceName const& instanceName, const QString& groupName, InstanceTask const& commiting)
{ {
QDir dir; QDir dir;
QString instID; QString instID;
InstancePtr inst; InstancePtr inst;
auto should_override = commiting.shouldOverride();
if (should_override) { if (should_override) {
// This is to avoid problems when the instance folder gets manually renamed instID = commiting.originalInstanceID();
if ((inst = getInstanceByManagedName(instanceName.originalName()))) {
instID = QFileInfo(inst->instanceRoot()).fileName();
} else if ((inst = getInstanceByManagedName(instanceName.modifiedName()))) {
instID = QFileInfo(inst->instanceRoot()).fileName();
} else {
instID = FS::RemoveInvalidFilenameChars(instanceName.modifiedName(), '-');
}
} else { } else {
instID = FS::DirNameFromString(instanceName.modifiedName(), m_instDir); instID = FS::DirNameFromString(instanceName.modifiedName(), m_instDir);
} }
Q_ASSERT(!instID.isEmpty());
{ {
WatchLock lock(m_watcher, m_instDir); WatchLock lock(m_watcher, m_instDir);
QString destination = FS::PathCombine(m_instDir, instID); QString destination = FS::PathCombine(m_instDir, instID);

View File

@ -133,7 +133,7 @@ public:
* should_override is used when another similar instance already exists, and we want to override it * should_override is used when another similar instance already exists, and we want to override it
* - for instance, when updating it. * - for instance, when updating it.
*/ */
bool commitStagedInstance(const QString& keyPath, const InstanceName& instanceName, const QString& groupName, bool should_override); bool commitStagedInstance(const QString& keyPath, const InstanceName& instanceName, const QString& groupName, const InstanceTask&);
/** /**
* Destroy a previously created staging area given by @keyPath - used when creation fails. * Destroy a previously created staging area given by @keyPath - used when creation fails.

View File

@ -5,6 +5,7 @@
#include "ui/pages/BasePageProvider.h" #include "ui/pages/BasePageProvider.h"
#include "ui/pages/instance/LogPage.h" #include "ui/pages/instance/LogPage.h"
#include "ui/pages/instance/VersionPage.h" #include "ui/pages/instance/VersionPage.h"
#include "ui/pages/instance/ManagedPackPage.h"
#include "ui/pages/instance/ModFolderPage.h" #include "ui/pages/instance/ModFolderPage.h"
#include "ui/pages/instance/ResourcePackPage.h" #include "ui/pages/instance/ResourcePackPage.h"
#include "ui/pages/instance/TexturePackPage.h" #include "ui/pages/instance/TexturePackPage.h"
@ -33,6 +34,7 @@ public:
values.append(new LogPage(inst)); values.append(new LogPage(inst));
std::shared_ptr<MinecraftInstance> onesix = std::dynamic_pointer_cast<MinecraftInstance>(inst); std::shared_ptr<MinecraftInstance> onesix = std::dynamic_pointer_cast<MinecraftInstance>(inst);
values.append(new VersionPage(onesix.get())); values.append(new VersionPage(onesix.get()));
values.append(ManagedPackPage::createPage(onesix.get()));
auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList()); auto modsPage = new ModFolderPage(onesix.get(), onesix->loaderModList());
modsPage->setFilter("%1 (*.zip *.jar *.litemod)"); modsPage->setFilter("%1 (*.zip *.jar *.litemod)");
values.append(modsPage); values.append(modsPage);

View File

@ -18,6 +18,29 @@ InstanceNameChange askForChangingInstanceName(QWidget* parent, const QString& ol
return InstanceNameChange::ShouldKeep; return InstanceNameChange::ShouldKeep;
} }
ShouldUpdate askIfShouldUpdate(QWidget *parent, QString original_version_name)
{
auto info = CustomMessageBox::selectable(
parent, QObject::tr("Similar modpack was found!"),
QObject::tr("One or more of your instances are from this same modpack%1. Do you want to create a "
"separate instance, or update the existing one?\n\nNOTE: Make sure you made a backup of your important instance data before "
"updating, as worlds can be corrupted and some configuration may be lost (due to pack overrides).")
.arg(original_version_name),
QMessageBox::Information, QMessageBox::Ok | QMessageBox::Reset | QMessageBox::Abort);
info->setButtonText(QMessageBox::Ok, QObject::tr("Update existing instance"));
info->setButtonText(QMessageBox::Abort, QObject::tr("Create new instance"));
info->setButtonText(QMessageBox::Reset, QObject::tr("Cancel"));
info->exec();
if (info->clickedButton() == info->button(QMessageBox::Ok))
return ShouldUpdate::Update;
if (info->clickedButton() == info->button(QMessageBox::Abort))
return ShouldUpdate::SkipUpdating;
return ShouldUpdate::Cancel;
}
QString InstanceName::name() const QString InstanceName::name() const
{ {
if (!m_modified_name.isEmpty()) if (!m_modified_name.isEmpty())

View File

@ -6,6 +6,8 @@
/* Helpers */ /* Helpers */
enum class InstanceNameChange { ShouldChange, ShouldKeep }; enum class InstanceNameChange { ShouldChange, ShouldKeep };
[[nodiscard]] InstanceNameChange askForChangingInstanceName(QWidget* parent, const QString& old_name, const QString& new_name); [[nodiscard]] InstanceNameChange askForChangingInstanceName(QWidget* parent, const QString& old_name, const QString& new_name);
enum class ShouldUpdate { Update, SkipUpdating, Cancel };
[[nodiscard]] ShouldUpdate askIfShouldUpdate(QWidget* parent, QString original_version_name);
struct InstanceName { struct InstanceName {
public: public:
@ -42,10 +44,20 @@ class InstanceTask : public Task, public InstanceName {
void setGroup(const QString& group) { m_instGroup = group; } void setGroup(const QString& group) { m_instGroup = group; }
QString group() const { return m_instGroup; } QString group() const { return m_instGroup; }
[[nodiscard]] bool shouldConfirmUpdate() const { return m_confirm_update; }
void setConfirmUpdate(bool confirm) { m_confirm_update = confirm; }
bool shouldOverride() const { return m_override_existing; } bool shouldOverride() const { return m_override_existing; }
[[nodiscard]] QString originalInstanceID() const { return m_original_instance_id; };
protected: protected:
void setOverride(bool override) { m_override_existing = override; } void setOverride(bool override, QString instance_id_to_override = {})
{
m_override_existing = override;
if (!instance_id_to_override.isEmpty())
m_original_instance_id = instance_id_to_override;
}
protected: /* data */ protected: /* data */
SettingsObjectPtr m_globalSettings; SettingsObjectPtr m_globalSettings;
@ -54,4 +66,7 @@ class InstanceTask : public Task, public InstanceName {
QString m_stagingPath; QString m_stagingPath;
bool m_override_existing = false; bool m_override_existing = false;
bool m_confirm_update = true;
QString m_original_instance_id;
}; };

View File

@ -28,11 +28,11 @@ QString Time::prettifyDuration(int64_t duration) {
int days = (int) (duration / 24); int days = (int) (duration / 24);
if((hours == 0)&&(days == 0)) if((hours == 0)&&(days == 0))
{ {
return QObject::tr("%1m %2s").arg(minutes).arg(seconds); return QObject::tr("%1min %2s").arg(minutes).arg(seconds);
} }
if (days == 0) if (days == 0)
{ {
return QObject::tr("%1h %2m").arg(hours).arg(minutes); return QObject::tr("%1h %2min").arg(hours).arg(minutes);
} }
return QObject::tr("%1d %2h %3m").arg(days).arg(hours).arg(minutes); return QObject::tr("%1d %2h %3min").arg(days).arg(hours).arg(minutes);
} }

View File

@ -39,6 +39,7 @@
#include "MMCZip.h" #include "MMCZip.h"
#include "FileSystem.h" #include "FileSystem.h"
#include <QCoreApplication>
#include <QDebug> #include <QDebug>
// ours // ours
@ -228,23 +229,27 @@ bool MMCZip::createModdedJar(QString sourceJarPath, QString targetJarPath, const
} }
// ours // ours
QString MMCZip::findFolderOfFileInZip(QuaZip * zip, const QString & what, const QString &root) QString MMCZip::findFolderOfFileInZip(QuaZip* zip, const QString& what, const QStringList& ignore_paths, const QString& root)
{ {
QuaZipDir rootDir(zip, root); QuaZipDir rootDir(zip, root);
for(auto fileName: rootDir.entryList(QDir::Files)) for (auto&& fileName : rootDir.entryList(QDir::Files)) {
{ if (fileName == what)
if(fileName == what)
return root; return root;
QCoreApplication::processEvents();
} }
for(auto fileName: rootDir.entryList(QDir::Dirs))
{ // Recurse the search to non-ignored subfolders
QString result = findFolderOfFileInZip(zip, what, root + fileName); for (auto&& fileName : rootDir.entryList(QDir::Dirs)) {
if(!result.isEmpty()) if (ignore_paths.contains(fileName))
{ continue;
QString result = findFolderOfFileInZip(zip, what, ignore_paths, root + fileName);
if (!result.isEmpty())
return result; return result;
}
} }
return QString();
return {};
} }
// ours // ours

View File

@ -80,9 +80,11 @@ namespace MMCZip
/** /**
* Find a single file in archive by file name (not path) * Find a single file in archive by file name (not path)
* *
* \param ignore_paths paths to skip when recursing the search
*
* \return the path prefix where the file is * \return the path prefix where the file is
*/ */
QString findFolderOfFileInZip(QuaZip * zip, const QString & what, const QString &root = QString("")); QString findFolderOfFileInZip(QuaZip * zip, const QString & what, const QStringList& ignore_paths = {}, const QString &root = QString(""));
/** /**
* Find a multiple files of the same name in archive by file name * Find a multiple files of the same name in archive by file name

95
launcher/MTPixmapCache.h Normal file
View File

@ -0,0 +1,95 @@
#pragma once
#include <QCoreApplication>
#include <QPixmapCache>
#include <QThread>
#define GET_TYPE() \
Qt::ConnectionType type; \
if (QThread::currentThread() != QCoreApplication::instance()->thread()) \
type = Qt::BlockingQueuedConnection; \
else \
type = Qt::DirectConnection;
#define DEFINE_FUNC_NO_PARAM(NAME, RET_TYPE) \
static RET_TYPE NAME() \
{ \
RET_TYPE ret; \
GET_TYPE() \
QMetaObject::invokeMethod(s_instance, "_" #NAME, type, Q_RETURN_ARG(RET_TYPE, ret)); \
return ret; \
}
#define DEFINE_FUNC_ONE_PARAM(NAME, RET_TYPE, PARAM_1_TYPE) \
static RET_TYPE NAME(PARAM_1_TYPE p1) \
{ \
RET_TYPE ret; \
GET_TYPE() \
QMetaObject::invokeMethod(s_instance, "_" #NAME, type, Q_RETURN_ARG(RET_TYPE, ret), Q_ARG(PARAM_1_TYPE, p1)); \
return ret; \
}
#define DEFINE_FUNC_TWO_PARAM(NAME, RET_TYPE, PARAM_1_TYPE, PARAM_2_TYPE) \
static RET_TYPE NAME(PARAM_1_TYPE p1, PARAM_2_TYPE p2) \
{ \
RET_TYPE ret; \
GET_TYPE() \
QMetaObject::invokeMethod(s_instance, "_" #NAME, type, Q_RETURN_ARG(RET_TYPE, ret), Q_ARG(PARAM_1_TYPE, p1), \
Q_ARG(PARAM_2_TYPE, p2)); \
return ret; \
}
/** A wrapper around QPixmapCache with thread affinity with the main thread.
*/
class PixmapCache final : public QObject {
Q_OBJECT
public:
PixmapCache(QObject* parent) : QObject(parent) {}
~PixmapCache() override = default;
static PixmapCache& instance() { return *s_instance; }
static void setInstance(PixmapCache* i) { s_instance = i; }
public:
DEFINE_FUNC_NO_PARAM(cacheLimit, int)
DEFINE_FUNC_NO_PARAM(clear, bool)
DEFINE_FUNC_TWO_PARAM(find, bool, const QString&, QPixmap*)
DEFINE_FUNC_TWO_PARAM(find, bool, const QPixmapCache::Key&, QPixmap*)
DEFINE_FUNC_TWO_PARAM(insert, bool, const QString&, const QPixmap&)
DEFINE_FUNC_ONE_PARAM(insert, QPixmapCache::Key, const QPixmap&)
DEFINE_FUNC_ONE_PARAM(remove, bool, const QString&)
DEFINE_FUNC_ONE_PARAM(remove, bool, const QPixmapCache::Key&)
DEFINE_FUNC_TWO_PARAM(replace, bool, const QPixmapCache::Key&, const QPixmap&)
DEFINE_FUNC_ONE_PARAM(setCacheLimit, bool, int)
// NOTE: Every function returns something non-void to simplify the macros.
private slots:
int _cacheLimit() { return QPixmapCache::cacheLimit(); }
bool _clear()
{
QPixmapCache::clear();
return true;
}
bool _find(const QString& key, QPixmap* pixmap) { return QPixmapCache::find(key, pixmap); }
bool _find(const QPixmapCache::Key& key, QPixmap* pixmap) { return QPixmapCache::find(key, pixmap); }
bool _insert(const QString& key, const QPixmap& pixmap) { return QPixmapCache::insert(key, pixmap); }
QPixmapCache::Key _insert(const QPixmap& pixmap) { return QPixmapCache::insert(pixmap); }
bool _remove(const QString& key)
{
QPixmapCache::remove(key);
return true;
}
bool _remove(const QPixmapCache::Key& key)
{
QPixmapCache::remove(key);
return true;
}
bool _replace(const QPixmapCache::Key& key, const QPixmap& pixmap) { return QPixmapCache::replace(key, pixmap); }
bool _setCacheLimit(int n)
{
QPixmapCache::setCacheLimit(n);
return true;
}
private:
static PixmapCache* s_instance;
};

90
launcher/MangoHud.cpp Normal file
View File

@ -0,0 +1,90 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* PrismLauncher - Minecraft Launcher
* Copyright (C) 2022 Jan Drögehoff <sentrycraft123@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <QStringList>
#include <QDir>
#include <QString>
#include <QtGlobal>
#include "MangoHud.h"
#include "FileSystem.h"
#include "Json.h"
namespace MangoHud {
QString getLibraryString()
{
/*
* Check for vulkan layers in this order:
*
* $VK_LAYER_PATH
* $XDG_DATA_DIRS (/usr/local/share/:/usr/share/)
* $XDG_DATA_HOME (~/.local/share)
* /etc
* $XDG_CONFIG_DIRS (/etc/xdg)
* $XDG_CONFIG_HOME (~/.config)
*/
QStringList vkLayerList;
{
QString home = QDir::homePath();
QString vkLayerPath = qEnvironmentVariable("VK_LAYER_PATH");
if (!vkLayerPath.isEmpty()) {
vkLayerList << vkLayerPath;
}
QStringList xdgDataDirs = qEnvironmentVariable("XDG_DATA_DIRS", "/usr/local/share/:/usr/share/").split(QLatin1String(":"));
for (QString dir : xdgDataDirs) {
vkLayerList << FS::PathCombine(dir, "vulkan", "implicit_layer.d");
}
QString xdgDataHome = qEnvironmentVariable("XDG_DATA_HOME");
if (xdgDataHome.isEmpty()) {
xdgDataHome = FS::PathCombine(home, ".local", "share");
}
vkLayerList << FS::PathCombine(xdgDataHome, "vulkan", "implicit_layer.d");
vkLayerList << "/etc";
QStringList xdgConfigDirs = qEnvironmentVariable("XDG_CONFIG_DIRS", "/etc/xdg").split(QLatin1String(":"));
for (QString dir : xdgConfigDirs) {
vkLayerList << FS::PathCombine(dir, "vulkan", "implicit_layer.d");
}
QString xdgConfigHome = qEnvironmentVariable("XDG_CONFIG_HOME");
if (xdgConfigHome.isEmpty()) {
xdgConfigHome = FS::PathCombine(home, ".config");
}
vkLayerList << FS::PathCombine(xdgConfigHome, "vulkan", "implicit_layer.d");
}
for (QString vkLayer : vkLayerList) {
QString filePath = FS::PathCombine(vkLayer, "MangoHud.json");
if (!QFile::exists(filePath))
continue;
auto conf = Json::requireDocument(filePath, vkLayer);
auto confObject = Json::requireObject(conf, vkLayer);
auto layer = Json::ensureObject(confObject, "layer");
return Json::ensureString(layer, "library_path");
}
return QString();
}
} // namespace MangoHud

27
launcher/MangoHud.h Normal file
View File

@ -0,0 +1,27 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* PrismLauncher - Minecraft Launcher
* Copyright (C) 2022 Jan Drögehoff <sentrycraft123@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <QString>
#include <QStringList>
namespace MangoHud {
QString getLibraryString();
}

View File

@ -354,15 +354,18 @@ const MMCIcon *IconList::icon(const QString &key) const
bool IconList::deleteIcon(const QString &key) bool IconList::deleteIcon(const QString &key)
{ {
int iconIdx = getIconIndex(key); if (!iconFileExists(key))
if (iconIdx == -1)
return false; return false;
auto &iconEntry = icons[iconIdx];
if (iconEntry.has(IconType::FileBased)) return QFile::remove(icon(key)->getFilePath());
{ }
return QFile::remove(iconEntry.m_images[IconType::FileBased].filename);
} bool IconList::trashIcon(const QString &key)
return false; {
if (!iconFileExists(key))
return false;
return FS::trash(icon(key)->getFilePath(), nullptr);
} }
bool IconList::addThemeIcon(const QString& key) bool IconList::addThemeIcon(const QString& key)

View File

@ -52,6 +52,7 @@ public:
bool addIcon(const QString &key, const QString &name, const QString &path, const IconType type); bool addIcon(const QString &key, const QString &name, const QString &path, const IconType type);
void saveIcon(const QString &key, const QString &path, const char * format) const; void saveIcon(const QString &key, const QString &path, const char * format) const;
bool deleteIcon(const QString &key); bool deleteIcon(const QString &key);
bool trashIcon(const QString &key);
bool iconFileExists(const QString &key) const; bool iconFileExists(const QString &key) const;
void installIcons(const QStringList &iconFiles); void installIcons(const QStringList &iconFiles);

View File

@ -10,7 +10,7 @@ typedef std::shared_ptr<Agent> AgentPtr;
class Agent { class Agent {
public: public:
Agent(LibraryPtr library, QString &argument) Agent(LibraryPtr library, const QString &argument)
{ {
m_library = library; m_library = library;
m_argument = argument; m_argument = argument;

View File

@ -88,6 +88,10 @@
#include "minecraft/gameoptions/GameOptions.h" #include "minecraft/gameoptions/GameOptions.h"
#include "minecraft/update/FoldersTask.h" #include "minecraft/update/FoldersTask.h"
#ifdef Q_OS_LINUX
#include "MangoHud.h"
#endif
#define IBUS "@im=ibus" #define IBUS "@im=ibus"
// all of this because keeping things compatible with deprecated old settings // all of this because keeping things compatible with deprecated old settings
@ -482,9 +486,22 @@ QProcessEnvironment MinecraftInstance::createLaunchEnvironment()
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
if (settings()->get("EnableMangoHud").toBool() && APPLICATION->capabilities() & Application::SupportsMangoHud) if (settings()->get("EnableMangoHud").toBool() && APPLICATION->capabilities() & Application::SupportsMangoHud)
{ {
auto preload = env.value("LD_PRELOAD", "") + ":libMangoHud_dlsym.so:libMangoHud.so";
env.insert("LD_PRELOAD", preload); auto preloadList = env.value("LD_PRELOAD").split(QLatin1String(":"));
auto libPaths = env.value("LD_LIBRARY_PATH").split(QLatin1String(":"));
auto mangoHudLibString = MangoHud::getLibraryString();
if (!mangoHudLibString.isEmpty())
{
QFileInfo mangoHudLib(mangoHudLibString);
// dlsym variant is only needed for OpenGL and not included in the vulkan layer
preloadList << "libMangoHud_dlsym.so" << mangoHudLib.fileName();
libPaths << mangoHudLib.absolutePath();
}
env.insert("LD_PRELOAD", preloadList.join(QLatin1String(":")));
env.insert("LD_LIBRARY_PATH", libPaths.join(QLatin1String(":")));
env.insert("MANGOHUD", "1"); env.insert("MANGOHUD", "1");
} }
@ -1110,8 +1127,6 @@ std::shared_ptr<ResourcePackFolderModel> MinecraftInstance::resourcePackList() c
if (!m_resource_pack_list) if (!m_resource_pack_list)
{ {
m_resource_pack_list.reset(new ResourcePackFolderModel(resourcePacksDir())); m_resource_pack_list.reset(new ResourcePackFolderModel(resourcePacksDir()));
m_resource_pack_list->enableInteraction(!isRunning());
connect(this, &BaseInstance::runningStatusChanged, m_resource_pack_list.get(), &ResourcePackFolderModel::disableInteraction);
} }
return m_resource_pack_list; return m_resource_pack_list;
} }
@ -1121,8 +1136,6 @@ std::shared_ptr<TexturePackFolderModel> MinecraftInstance::texturePackList() con
if (!m_texture_pack_list) if (!m_texture_pack_list)
{ {
m_texture_pack_list.reset(new TexturePackFolderModel(texturePacksDir())); m_texture_pack_list.reset(new TexturePackFolderModel(texturePacksDir()));
m_texture_pack_list->disableInteraction(isRunning());
connect(this, &BaseInstance::runningStatusChanged, m_texture_pack_list.get(), &ModFolderModel::disableInteraction);
} }
return m_texture_pack_list; return m_texture_pack_list;
} }
@ -1132,8 +1145,6 @@ std::shared_ptr<ShaderPackFolderModel> MinecraftInstance::shaderPackList() const
if (!m_shader_pack_list) if (!m_shader_pack_list)
{ {
m_shader_pack_list.reset(new ShaderPackFolderModel(shaderPacksDir())); m_shader_pack_list.reset(new ShaderPackFolderModel(shaderPacksDir()));
m_shader_pack_list->disableInteraction(isRunning());
connect(this, &BaseInstance::runningStatusChanged, m_shader_pack_list.get(), &ModFolderModel::disableInteraction);
} }
return m_shader_pack_list; return m_shader_pack_list;
} }

View File

@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
/* /*
* PolyMC - Minecraft Launcher * Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -47,7 +48,6 @@
#include "Exception.h" #include "Exception.h"
#include "minecraft/OneSixVersionFormat.h" #include "minecraft/OneSixVersionFormat.h"
#include "FileSystem.h" #include "FileSystem.h"
#include "meta/Index.h"
#include "minecraft/MinecraftInstance.h" #include "minecraft/MinecraftInstance.h"
#include "Json.h" #include "Json.h"
@ -55,7 +55,6 @@
#include "PackProfile_p.h" #include "PackProfile_p.h"
#include "ComponentUpdateTask.h" #include "ComponentUpdateTask.h"
#include "Application.h"
#include "modplatform/ModAPI.h" #include "modplatform/ModAPI.h"
static const QMap<QString, ModAPI::ModLoaderType> modloaderMapping{ static const QMap<QString, ModAPI::ModLoaderType> modloaderMapping{
@ -738,6 +737,11 @@ void PackProfile::installCustomJar(QString selectedFile)
installCustomJar_internal(selectedFile); installCustomJar_internal(selectedFile);
} }
void PackProfile::installAgents(QStringList selectedFiles)
{
installAgents_internal(selectedFiles);
}
bool PackProfile::installEmpty(const QString& uid, const QString& name) bool PackProfile::installEmpty(const QString& uid, const QString& name)
{ {
QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches"); QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
@ -832,18 +836,14 @@ bool PackProfile::installJarMods_internal(QStringList filepaths)
for(auto filepath:filepaths) for(auto filepath:filepaths)
{ {
QFileInfo sourceInfo(filepath); QFileInfo sourceInfo(filepath);
auto uuid = QUuid::createUuid(); QString id = QUuid::createUuid().toString(QUuid::WithoutBraces);
QString id = uuid.toString().remove('{').remove('}');
QString target_filename = id + ".jar"; QString target_filename = id + ".jar";
QString target_id = "org.multimc.jarmod." + id; QString target_id = "custom.jarmod." + id;
QString target_name = sourceInfo.completeBaseName() + " (jar mod)"; QString target_name = sourceInfo.completeBaseName() + " (jar mod)";
QString finalPath = FS::PathCombine(d->m_instance->jarModsDir(), target_filename); QString finalPath = FS::PathCombine(d->m_instance->jarModsDir(), target_filename);
QFileInfo targetInfo(finalPath); QFileInfo targetInfo(finalPath);
if(targetInfo.exists()) Q_ASSERT(!targetInfo.exists());
{
return false;
}
if (!QFile::copy(sourceInfo.absoluteFilePath(),QFileInfo(finalPath).absoluteFilePath())) if (!QFile::copy(sourceInfo.absoluteFilePath(),QFileInfo(finalPath).absoluteFilePath()))
{ {
@ -852,7 +852,7 @@ bool PackProfile::installJarMods_internal(QStringList filepaths)
auto f = std::make_shared<VersionFile>(); auto f = std::make_shared<VersionFile>();
auto jarMod = std::make_shared<Library>(); auto jarMod = std::make_shared<Library>();
jarMod->setRawName(GradleSpecifier("org.multimc.jarmods:" + id + ":1")); jarMod->setRawName(GradleSpecifier("custom.jarmods:" + id + ":1"));
jarMod->setFilename(target_filename); jarMod->setFilename(target_filename);
jarMod->setDisplayName(sourceInfo.completeBaseName()); jarMod->setDisplayName(sourceInfo.completeBaseName());
jarMod->setHint("local"); jarMod->setHint("local");
@ -892,7 +892,7 @@ bool PackProfile::installCustomJar_internal(QString filepath)
return false; return false;
} }
auto specifier = GradleSpecifier("org.multimc:customjar:1"); auto specifier = GradleSpecifier("custom:customjar:1");
QFileInfo sourceInfo(filepath); QFileInfo sourceInfo(filepath);
QString target_filename = specifier.getFileName(); QString target_filename = specifier.getFileName();
QString target_id = specifier.artifactId(); QString target_id = specifier.artifactId();
@ -939,6 +939,64 @@ bool PackProfile::installCustomJar_internal(QString filepath)
return true; return true;
} }
bool PackProfile::installAgents_internal(QStringList filepaths)
{
// FIXME code duplication
const QString patchDir = FS::PathCombine(d->m_instance->instanceRoot(), "patches");
if (!FS::ensureFolderPathExists(patchDir))
return false;
const QString libDir = d->m_instance->getLocalLibraryPath();
if (!FS::ensureFolderPathExists(libDir))
return false;
for (const QString& source : filepaths) {
const QFileInfo sourceInfo(source);
const QString id = QUuid::createUuid().toString(QUuid::WithoutBraces);
const QString targetBaseName = id + ".jar";
const QString targetId = "custom.agent." + id;
const QString targetName = sourceInfo.completeBaseName() + " (agent)";
const QString target = FS::PathCombine(d->m_instance->getLocalLibraryPath(), targetBaseName);
const QFileInfo targetInfo(target);
Q_ASSERT(!targetInfo.exists());
if (!QFile::copy(source, target))
return false;
auto versionFile = std::make_shared<VersionFile>();
auto agent = std::make_shared<Library>();
agent->setRawName("custom.agents:" + id + ":1");
agent->setFilename(targetBaseName);
agent->setDisplayName(sourceInfo.completeBaseName());
agent->setHint("local");
versionFile->agents.append(std::make_shared<Agent>(agent, QString()));
versionFile->name = targetName;
versionFile->uid = targetId;
QFile patchFile(FS::PathCombine(patchDir, targetId + ".json"));
if (!patchFile.open(QFile::WriteOnly)) {
qCritical() << "Error opening" << patchFile.fileName() << "for reading:" << patchFile.errorString();
return false;
}
patchFile.write(OneSixVersionFormat::versionFileToJson(versionFile).toJson());
patchFile.close();
appendComponent(new Component(this, versionFile->uid, versionFile));
}
scheduleSave();
invalidateLaunchProfile();
return true;
}
std::shared_ptr<LaunchProfile> PackProfile::getProfile() const std::shared_ptr<LaunchProfile> PackProfile::getProfile() const
{ {
if(!d->m_profile) if(!d->m_profile)

View File

@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
/* /*
* PolyMC - Minecraft Launcher * Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* Copyright (C) 2022 TheKodeToad <TheKodeToad@proton.me>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -85,6 +86,9 @@ public:
/// install a jar/zip as a replacement for the main jar /// install a jar/zip as a replacement for the main jar
void installCustomJar(QString selectedFile); void installCustomJar(QString selectedFile);
/// install Java agent files
void installAgents(QStringList selectedFiles);
enum MoveDirection { MoveUp, MoveDown }; enum MoveDirection { MoveUp, MoveDown };
/// move component file # up or down the list /// move component file # up or down the list
void move(const int index, const MoveDirection direction); void move(const int index, const MoveDirection direction);
@ -167,6 +171,7 @@ private:
bool load(); bool load();
bool installJarMods_internal(QStringList filepaths); bool installJarMods_internal(QStringList filepaths);
bool installCustomJar_internal(QString filepath); bool installCustomJar_internal(QString filepath);
bool installAgents_internal(QStringList filepaths);
bool removeComponent_internal(ComponentPtr patch); bool removeComponent_internal(ComponentPtr patch);
private: /* data */ private: /* data */

View File

@ -1,9 +1,11 @@
#include "ResourcePack.h" #include "ResourcePack.h"
#include <QCoreApplication>
#include <QDebug> #include <QDebug>
#include <QMap> #include <QMap>
#include <QRegularExpression> #include <QRegularExpression>
#include "MTPixmapCache.h"
#include "Version.h" #include "Version.h"
#include "minecraft/mod/tasks/LocalResourcePackParseTask.h" #include "minecraft/mod/tasks/LocalResourcePackParseTask.h"
@ -15,7 +17,7 @@ static const QMap<int, std::pair<Version, Version>> s_pack_format_versions = {
{ 3, { Version("1.11"), Version("1.12.2") } }, { 4, { Version("1.13"), Version("1.14.4") } }, { 3, { Version("1.11"), Version("1.12.2") } }, { 4, { Version("1.13"), Version("1.14.4") } },
{ 5, { Version("1.15"), Version("1.16.1") } }, { 6, { Version("1.16.2"), Version("1.16.5") } }, { 5, { Version("1.15"), Version("1.16.1") } }, { 6, { Version("1.16.2"), Version("1.16.5") } },
{ 7, { Version("1.17"), Version("1.17.1") } }, { 8, { Version("1.18"), Version("1.18.2") } }, { 7, { Version("1.17"), Version("1.17.1") } }, { 8, { Version("1.18"), Version("1.18.2") } },
{ 9, { Version("1.19"), Version("1.19.2") } }, { 9, { Version("1.19"), Version("1.19.2") } }, { 11, { Version("1.19.3"), Version("1.19.3") } },
}; };
void ResourcePack::setPackFormat(int new_format_id) void ResourcePack::setPackFormat(int new_format_id)
@ -43,16 +45,22 @@ void ResourcePack::setImage(QImage new_image)
Q_ASSERT(!new_image.isNull()); Q_ASSERT(!new_image.isNull());
if (m_pack_image_cache_key.key.isValid()) if (m_pack_image_cache_key.key.isValid())
QPixmapCache::remove(m_pack_image_cache_key.key); PixmapCache::instance().remove(m_pack_image_cache_key.key);
m_pack_image_cache_key.key = QPixmapCache::insert(QPixmap::fromImage(new_image)); m_pack_image_cache_key.key = PixmapCache::instance().insert(QPixmap::fromImage(new_image));
m_pack_image_cache_key.was_ever_used = true; m_pack_image_cache_key.was_ever_used = true;
// This can happen if the pixmap is too big to fit in the cache :c
if (!m_pack_image_cache_key.key.isValid()) {
qWarning() << "Could not insert a image cache entry! Ignoring it.";
m_pack_image_cache_key.was_ever_used = false;
}
} }
QPixmap ResourcePack::image(QSize size) QPixmap ResourcePack::image(QSize size)
{ {
QPixmap cached_image; QPixmap cached_image;
if (QPixmapCache::find(m_pack_image_cache_key.key, &cached_image)) { if (PixmapCache::instance().find(m_pack_image_cache_key.key, &cached_image)) {
if (size.isNull()) if (size.isNull())
return cached_image; return cached_image;
return cached_image.scaled(size); return cached_image.scaled(size);
@ -114,3 +122,8 @@ bool ResourcePack::applyFilter(QRegularExpression filter) const
return Resource::applyFilter(filter); return Resource::applyFilter(filter);
} }
bool ResourcePack::valid() const
{
return m_pack_format != 0;
}

View File

@ -42,6 +42,8 @@ class ResourcePack : public Resource {
/** Thread-safe. */ /** Thread-safe. */
void setImage(QImage new_image); void setImage(QImage new_image);
bool valid() const override;
[[nodiscard]] auto compare(Resource const& other, SortType type) const -> std::pair<int, bool> override; [[nodiscard]] auto compare(Resource const& other, SortType type) const -> std::pair<int, bool> override;
[[nodiscard]] bool applyFilter(QRegularExpression filter) const override; [[nodiscard]] bool applyFilter(QRegularExpression filter) const override;

View File

@ -62,3 +62,8 @@ QPixmap TexturePack::image(QSize size)
TexturePackUtils::process(*this); TexturePackUtils::process(*this);
return image(size); return image(size);
} }
bool TexturePack::valid() const
{
return m_description != nullptr;
}

View File

@ -48,6 +48,8 @@ class TexturePack : public Resource {
/** Thread-safe. */ /** Thread-safe. */
void setImage(QImage new_image); void setImage(QImage new_image);
bool valid() const override;
protected: protected:
mutable QMutex m_data_lock; mutable QMutex m_data_lock;

View File

@ -28,14 +28,14 @@
namespace ResourcePackUtils { namespace ResourcePackUtils {
bool process(ResourcePack& pack) bool process(ResourcePack& pack, ProcessingLevel level)
{ {
switch (pack.type()) { switch (pack.type()) {
case ResourceType::FOLDER: case ResourceType::FOLDER:
ResourcePackUtils::processFolder(pack); ResourcePackUtils::processFolder(pack, level);
return true; return true;
case ResourceType::ZIPFILE: case ResourceType::ZIPFILE:
ResourcePackUtils::processZIP(pack); ResourcePackUtils::processZIP(pack, level);
return true; return true;
default: default:
qWarning() << "Invalid type for resource pack parse task!"; qWarning() << "Invalid type for resource pack parse task!";
@ -43,7 +43,7 @@ bool process(ResourcePack& pack)
} }
} }
void processFolder(ResourcePack& pack) void processFolder(ResourcePack& pack, ProcessingLevel level)
{ {
Q_ASSERT(pack.type() == ResourceType::FOLDER); Q_ASSERT(pack.type() == ResourceType::FOLDER);
@ -60,6 +60,9 @@ void processFolder(ResourcePack& pack)
mcmeta_file.close(); mcmeta_file.close();
} }
if (level == ProcessingLevel::BasicInfoOnly)
return;
QFileInfo image_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.png")); QFileInfo image_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.png"));
if (image_file_info.isFile()) { if (image_file_info.isFile()) {
QFile mcmeta_file(image_file_info.filePath()); QFile mcmeta_file(image_file_info.filePath());
@ -74,7 +77,7 @@ void processFolder(ResourcePack& pack)
} }
} }
void processZIP(ResourcePack& pack) void processZIP(ResourcePack& pack, ProcessingLevel level)
{ {
Q_ASSERT(pack.type() == ResourceType::ZIPFILE); Q_ASSERT(pack.type() == ResourceType::ZIPFILE);
@ -98,6 +101,11 @@ void processZIP(ResourcePack& pack)
file.close(); file.close();
} }
if (level == ProcessingLevel::BasicInfoOnly) {
zip.close();
return;
}
if (zip.setCurrentFile("pack.png")) { if (zip.setCurrentFile("pack.png")) {
if (!file.open(QIODevice::ReadOnly)) { if (!file.open(QIODevice::ReadOnly)) {
qCritical() << "Failed to open file in zip."; qCritical() << "Failed to open file in zip.";
@ -138,6 +146,13 @@ void processPackPNG(ResourcePack& pack, QByteArray&& raw_data)
qWarning() << "Failed to parse pack.png."; qWarning() << "Failed to parse pack.png.";
} }
} }
bool validate(QFileInfo file)
{
ResourcePack rp{ file };
return ResourcePackUtils::process(rp, ProcessingLevel::BasicInfoOnly) && rp.valid();
}
} // namespace ResourcePackUtils } // namespace ResourcePackUtils
LocalResourcePackParseTask::LocalResourcePackParseTask(int token, ResourcePack& rp) LocalResourcePackParseTask::LocalResourcePackParseTask(int token, ResourcePack& rp)
@ -152,8 +167,6 @@ bool LocalResourcePackParseTask::abort()
void LocalResourcePackParseTask::executeTask() void LocalResourcePackParseTask::executeTask()
{ {
Q_ASSERT(m_resource_pack.valid());
if (!ResourcePackUtils::process(m_resource_pack)) if (!ResourcePackUtils::process(m_resource_pack))
return; return;

View File

@ -26,13 +26,19 @@
#include "tasks/Task.h" #include "tasks/Task.h"
namespace ResourcePackUtils { namespace ResourcePackUtils {
bool process(ResourcePack& pack);
void processZIP(ResourcePack& pack); enum class ProcessingLevel { Full, BasicInfoOnly };
void processFolder(ResourcePack& pack);
bool process(ResourcePack& pack, ProcessingLevel level = ProcessingLevel::Full);
void processZIP(ResourcePack& pack, ProcessingLevel level = ProcessingLevel::Full);
void processFolder(ResourcePack& pack, ProcessingLevel level = ProcessingLevel::Full);
void processMCMeta(ResourcePack& pack, QByteArray&& raw_data); void processMCMeta(ResourcePack& pack, QByteArray&& raw_data);
void processPackPNG(ResourcePack& pack, QByteArray&& raw_data); void processPackPNG(ResourcePack& pack, QByteArray&& raw_data);
/** Checks whether a file is valid as a resource pack or not. */
bool validate(QFileInfo file);
} // namespace ResourcePackUtils } // namespace ResourcePackUtils
class LocalResourcePackParseTask : public Task { class LocalResourcePackParseTask : public Task {

View File

@ -28,14 +28,14 @@
namespace TexturePackUtils { namespace TexturePackUtils {
bool process(TexturePack& pack) bool process(TexturePack& pack, ProcessingLevel level)
{ {
switch (pack.type()) { switch (pack.type()) {
case ResourceType::FOLDER: case ResourceType::FOLDER:
TexturePackUtils::processFolder(pack); TexturePackUtils::processFolder(pack, level);
return true; return true;
case ResourceType::ZIPFILE: case ResourceType::ZIPFILE:
TexturePackUtils::processZIP(pack); TexturePackUtils::processZIP(pack, level);
return true; return true;
default: default:
qWarning() << "Invalid type for resource pack parse task!"; qWarning() << "Invalid type for resource pack parse task!";
@ -43,7 +43,7 @@ bool process(TexturePack& pack)
} }
} }
void processFolder(TexturePack& pack) void processFolder(TexturePack& pack, ProcessingLevel level)
{ {
Q_ASSERT(pack.type() == ResourceType::FOLDER); Q_ASSERT(pack.type() == ResourceType::FOLDER);
@ -60,6 +60,9 @@ void processFolder(TexturePack& pack)
mcmeta_file.close(); mcmeta_file.close();
} }
if (level == ProcessingLevel::BasicInfoOnly)
return;
QFileInfo image_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.png")); QFileInfo image_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.png"));
if (image_file_info.isFile()) { if (image_file_info.isFile()) {
QFile mcmeta_file(image_file_info.filePath()); QFile mcmeta_file(image_file_info.filePath());
@ -74,7 +77,7 @@ void processFolder(TexturePack& pack)
} }
} }
void processZIP(TexturePack& pack) void processZIP(TexturePack& pack, ProcessingLevel level)
{ {
Q_ASSERT(pack.type() == ResourceType::ZIPFILE); Q_ASSERT(pack.type() == ResourceType::ZIPFILE);
@ -98,6 +101,11 @@ void processZIP(TexturePack& pack)
file.close(); file.close();
} }
if (level == ProcessingLevel::BasicInfoOnly) {
zip.close();
return;
}
if (zip.setCurrentFile("pack.png")) { if (zip.setCurrentFile("pack.png")) {
if (!file.open(QIODevice::ReadOnly)) { if (!file.open(QIODevice::ReadOnly)) {
qCritical() << "Failed to open file in zip."; qCritical() << "Failed to open file in zip.";
@ -129,6 +137,13 @@ void processPackPNG(TexturePack& pack, QByteArray&& raw_data)
qWarning() << "Failed to parse pack.png."; qWarning() << "Failed to parse pack.png.";
} }
} }
bool validate(QFileInfo file)
{
TexturePack rp{ file };
return TexturePackUtils::process(rp, ProcessingLevel::BasicInfoOnly) && rp.valid();
}
} // namespace TexturePackUtils } // namespace TexturePackUtils
LocalTexturePackParseTask::LocalTexturePackParseTask(int token, TexturePack& rp) LocalTexturePackParseTask::LocalTexturePackParseTask(int token, TexturePack& rp)
@ -143,8 +158,6 @@ bool LocalTexturePackParseTask::abort()
void LocalTexturePackParseTask::executeTask() void LocalTexturePackParseTask::executeTask()
{ {
Q_ASSERT(m_texture_pack.valid());
if (!TexturePackUtils::process(m_texture_pack)) if (!TexturePackUtils::process(m_texture_pack))
return; return;

View File

@ -27,13 +27,19 @@
#include "tasks/Task.h" #include "tasks/Task.h"
namespace TexturePackUtils { namespace TexturePackUtils {
bool process(TexturePack& pack);
void processZIP(TexturePack& pack); enum class ProcessingLevel { Full, BasicInfoOnly };
void processFolder(TexturePack& pack);
bool process(TexturePack& pack, ProcessingLevel level = ProcessingLevel::Full);
void processZIP(TexturePack& pack, ProcessingLevel level = ProcessingLevel::Full);
void processFolder(TexturePack& pack, ProcessingLevel level = ProcessingLevel::Full);
void processPackTXT(TexturePack& pack, QByteArray&& raw_data); void processPackTXT(TexturePack& pack, QByteArray&& raw_data);
void processPackPNG(TexturePack& pack, QByteArray&& raw_data); void processPackPNG(TexturePack& pack, QByteArray&& raw_data);
/** Checks whether a file is valid as a texture pack or not. */
bool validate(QFileInfo file);
} // namespace TexturePackUtils } // namespace TexturePackUtils
class LocalTexturePackParseTask : public Task { class LocalTexturePackParseTask : public Task {

View File

@ -12,7 +12,7 @@ LibrariesTask::LibrariesTask(MinecraftInstance * inst)
void LibrariesTask::executeTask() void LibrariesTask::executeTask()
{ {
setStatus(tr("Getting the library files from Mojang...")); setStatus(tr("Downloading required library files..."));
qDebug() << m_inst->name() << ": downloading libraries"; qDebug() << m_inst->name() << ": downloading libraries";
MinecraftInstance *inst = (MinecraftInstance *)m_inst; MinecraftInstance *inst = (MinecraftInstance *)m_inst;

View File

@ -42,12 +42,25 @@ void Flame::FileResolvingTask::executeTask()
void Flame::FileResolvingTask::netJobFinished() void Flame::FileResolvingTask::netJobFinished()
{ {
setProgress(1, 3); setProgress(1, 3);
int index = 0;
// job to check modrinth for blocked projects // job to check modrinth for blocked projects
m_checkJob = new NetJob("Modrinth check", m_network); m_checkJob = new NetJob("Modrinth check", m_network);
blockedProjects = QMap<File *,QByteArray *>(); blockedProjects = QMap<File *,QByteArray *>();
auto doc = Json::requireDocument(*result);
auto array = Json::requireArray(doc.object()["data"]); QJsonDocument doc;
QJsonArray array;
try {
doc = Json::requireDocument(*result);
array = Json::requireArray(doc.object()["data"]);
} catch (Json::JsonException& e) {
qCritical() << "Non-JSON data returned from the CF API";
qCritical() << e.cause();
emitFailed(tr("Invalid data returned from the API."));
return;
}
for (QJsonValueRef file : array) { for (QJsonValueRef file : array) {
auto fileid = Json::requireInteger(Json::requireObject(file)["id"]); auto fileid = Json::requireInteger(Json::requireObject(file)["id"]);
auto& out = m_toProcess.files[fileid]; auto& out = m_toProcess.files[fileid];
@ -68,7 +81,6 @@ void Flame::FileResolvingTask::netJobFinished()
blockedProjects.insert(&out, output); blockedProjects.insert(&out, output);
} }
} }
index++;
} }
connect(m_checkJob.get(), &NetJob::finished, this, &Flame::FileResolvingTask::modrinthCheckFinished); connect(m_checkJob.get(), &NetJob::finished, this, &Flame::FileResolvingTask::modrinthCheckFinished);

View File

@ -1,3 +1,38 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* Copyright 2013-2021 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "FlameInstanceCreationTask.h" #include "FlameInstanceCreationTask.h"
#include "modplatform/flame/FlameAPI.h" #include "modplatform/flame/FlameAPI.h"
@ -46,13 +81,19 @@ bool FlameCreationTask::updateInstance()
auto instance_list = APPLICATION->instances(); auto instance_list = APPLICATION->instances();
// FIXME: How to handle situations when there's more than one install already for a given modpack? // FIXME: How to handle situations when there's more than one install already for a given modpack?
auto inst = instance_list->getInstanceByManagedName(originalName()); InstancePtr inst;
if (auto original_id = originalInstanceID(); !original_id.isEmpty()) {
inst = instance_list->getInstanceById(original_id);
Q_ASSERT(inst);
} else {
inst = instance_list->getInstanceByManagedName(originalName());
if (!inst) { if (!inst) {
inst = instance_list->getInstanceById(originalName()); inst = instance_list->getInstanceById(originalName());
if (!inst) if (!inst)
return false; return false;
}
} }
QString index_path(FS::PathCombine(m_stagingPath, "manifest.json")); QString index_path(FS::PathCombine(m_stagingPath, "manifest.json"));
@ -67,24 +108,14 @@ bool FlameCreationTask::updateInstance()
auto version_id = inst->getManagedPackVersionName(); auto version_id = inst->getManagedPackVersionName();
auto version_str = !version_id.isEmpty() ? tr(" (version %1)").arg(version_id) : ""; auto version_str = !version_id.isEmpty() ? tr(" (version %1)").arg(version_id) : "";
auto info = CustomMessageBox::selectable( if (shouldConfirmUpdate()) {
m_parent, tr("Similar modpack was found!"), auto should_update = askIfShouldUpdate(m_parent, version_str);
tr("One or more of your instances are from this same modpack%1. Do you want to create a " if (should_update == ShouldUpdate::SkipUpdating)
"separate instance, or update the existing one?\n\nNOTE: Make sure you made a backup of your important instance data before " return false;
"updating, as worlds can be corrupted and some configuration may be lost (due to pack overrides).") if (should_update == ShouldUpdate::Cancel) {
.arg(version_str), QMessageBox::Information, QMessageBox::Ok | QMessageBox::Reset | QMessageBox::Abort); m_abort = true;
info->setButtonText(QMessageBox::Ok, tr("Update existing instance")); return false;
info->setButtonText(QMessageBox::Abort, tr("Create new instance")); }
info->setButtonText(QMessageBox::Reset, tr("Cancel"));
info->exec();
if (info->clickedButton() == info->button(QMessageBox::Abort))
return false;
if (info->clickedButton() == info->button(QMessageBox::Reset)) {
m_abort = true;
return false;
} }
QDir old_inst_dir(inst->instanceRoot()); QDir old_inst_dir(inst->instanceRoot());
@ -197,10 +228,10 @@ bool FlameCreationTask::updateInstance()
m_process_update_file_info_job = nullptr; m_process_update_file_info_job = nullptr;
} else { } else {
// We don't have an old index file, so we may duplicate stuff! // We don't have an old index file, so we may duplicate stuff!
auto dialog = CustomMessageBox::selectable(m_parent, auto dialog = CustomMessageBox::selectable(m_parent, tr("No index file."),
tr("No index file."), tr("We couldn't find a suitable index file for the older version. This may cause some "
tr("We couldn't find a suitable index file for the older version. This may cause some of the files to be duplicated. Do you want to continue?"), "of the files to be duplicated. Do you want to continue?"),
QMessageBox::Warning, QMessageBox::Ok | QMessageBox::Cancel); QMessageBox::Warning, QMessageBox::Ok | QMessageBox::Cancel);
if (dialog->exec() == QDialog::DialogCode::Rejected) { if (dialog->exec() == QDialog::DialogCode::Rejected) {
m_abort = true; m_abort = true;
@ -208,7 +239,7 @@ bool FlameCreationTask::updateInstance()
} }
} }
setOverride(true); setOverride(true, inst->id());
qDebug() << "Will override instance!"; qDebug() << "Will override instance!";
m_instance = inst; m_instance = inst;
@ -330,7 +361,7 @@ bool FlameCreationTask::createInstance()
FS::deletePath(jarmodsPath); FS::deletePath(jarmodsPath);
} }
instance.setManagedPack("flame", {}, m_pack.name, {}, m_pack.version); instance.setManagedPack("flame", m_managed_id, m_pack.name, m_managed_version_id, m_pack.version);
instance.setName(name()); instance.setName(name());
m_mod_id_resolver = new Flame::FileResolvingTask(APPLICATION->network(), m_pack); m_mod_id_resolver = new Flame::FileResolvingTask(APPLICATION->network(), m_pack);
@ -338,6 +369,7 @@ bool FlameCreationTask::createInstance()
connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::failed, [&](QString reason) { connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::failed, [&](QString reason) {
m_mod_id_resolver.reset(); m_mod_id_resolver.reset();
setError(tr("Unable to resolve mod IDs:\n") + reason); setError(tr("Unable to resolve mod IDs:\n") + reason);
loop.quit();
}); });
connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::progress, this, &FlameCreationTask::setProgress); connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::progress, this, &FlameCreationTask::setProgress);
connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::status, this, &FlameCreationTask::setStatus); connect(m_mod_id_resolver.get(), &Flame::FileResolvingTask::status, this, &FlameCreationTask::setStatus);
@ -353,14 +385,6 @@ bool FlameCreationTask::createInstance()
setAbortable(false); setAbortable(false);
auto inst = m_instance.value(); auto inst = m_instance.value();
// Only change the name if it didn't use a custom name, so that the previous custom name
// is preserved, but if we're using the original one, we update the version string.
// NOTE: This needs to come before the copyManagedPack call!
if (inst->name().contains(inst->getManagedPackVersionName())) {
if (askForChangingInstanceName(m_parent, inst->name(), instance.name()) == InstanceNameChange::ShouldChange)
inst->setName(instance.name());
}
inst->copyManagedPack(instance); inst->copyManagedPack(instance);
} }
@ -376,13 +400,13 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop)
auto anyBlocked = false; auto anyBlocked = false;
for (const auto& result : results.files.values()) { for (const auto& result : results.files.values()) {
if (!result.resolved || result.url.isEmpty()) { if (!result.resolved || result.url.isEmpty()) {
BlockedMod blocked_mod; BlockedMod blocked_mod;
blocked_mod.name = result.fileName; blocked_mod.name = result.fileName;
blocked_mod.websiteUrl = result.websiteUrl; blocked_mod.websiteUrl = result.websiteUrl;
blocked_mod.hash = result.hash; blocked_mod.hash = result.hash;
blocked_mod.matched = false; blocked_mod.matched = false;
blocked_mod.localPath = ""; blocked_mod.localPath = "";
blocked_mod.targetFolder = result.targetFolder;
blocked_mods.append(blocked_mod); blocked_mods.append(blocked_mod);
@ -392,14 +416,14 @@ void FlameCreationTask::idResolverSucceeded(QEventLoop& loop)
if (anyBlocked) { if (anyBlocked) {
qWarning() << "Blocked mods found, displaying mod list"; qWarning() << "Blocked mods found, displaying mod list";
auto message_dialog = new BlockedModsDialog(m_parent, tr("Blocked mods found"), BlockedModsDialog message_dialog(m_parent, tr("Blocked mods found"),
tr("The following files are not available for download in third party launchers.<br/>" tr("The following files are not available for download in third party launchers.<br/>"
"You will need to manually download them and add them to the instance."), "You will need to manually download them and add them to the instance."),
blocked_mods); blocked_mods);
message_dialog->setModal(true); message_dialog.setModal(true);
if (message_dialog->exec()) { if (message_dialog.exec()) {
qDebug() << "Post dialog blocked mods list: " << blocked_mods; qDebug() << "Post dialog blocked mods list: " << blocked_mods;
copyBlockedMods(blocked_mods); copyBlockedMods(blocked_mods);
setupDownloadJob(loop); setupDownloadJob(loop);
@ -428,7 +452,7 @@ void FlameCreationTask::copyBlockedMods(QList<BlockedMod> const& blocked_mods)
continue; continue;
} }
auto dest_path = FS::PathCombine(m_stagingPath, "minecraft", "mods", mod.name); auto dest_path = FS::PathCombine(m_stagingPath, "minecraft", mod.targetFolder, mod.name);
setStatus(tr("Copying Blocked Mods (%1 out of %2 are done)").arg(QString::number(i), QString::number(total))); setStatus(tr("Copying Blocked Mods (%1 out of %2 are done)").arg(QString::number(i), QString::number(total)));
@ -483,9 +507,7 @@ void FlameCreationTask::setupDownloadJob(QEventLoop& loop)
} }
m_mod_id_resolver.reset(); m_mod_id_resolver.reset();
connect(m_files_job.get(), &NetJob::succeeded, this, [&]() { connect(m_files_job.get(), &NetJob::succeeded, this, [&]() { m_files_job.reset(); });
m_files_job.reset();
});
connect(m_files_job.get(), &NetJob::failed, [&](QString reason) { connect(m_files_job.get(), &NetJob::failed, [&](QString reason) {
m_files_job.reset(); m_files_job.reset();
setError(reason); setError(reason);

View File

@ -1,3 +1,38 @@
// SPDX-License-Identifier: GPL-3.0-only
/*
* Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This file incorporates work covered by the following copyright and
* permission notice:
*
* Copyright 2013-2021 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once #pragma once
#include "InstanceCreationTask.h" #include "InstanceCreationTask.h"
@ -16,11 +51,21 @@ class FlameCreationTask final : public InstanceCreationTask {
Q_OBJECT Q_OBJECT
public: public:
FlameCreationTask(const QString& staging_path, SettingsObjectPtr global_settings, QWidget* parent) FlameCreationTask(const QString& staging_path,
: InstanceCreationTask(), m_parent(parent) SettingsObjectPtr global_settings,
QWidget* parent,
QString id,
QString version_id,
QString original_instance_id = {})
: InstanceCreationTask()
, m_parent(parent)
, m_managed_id(std::move(id))
, m_managed_version_id(std::move(version_id))
{ {
setStagingPath(staging_path); setStagingPath(staging_path);
setParentSettings(global_settings); setParentSettings(global_settings);
m_original_instance_id = std::move(original_instance_id);
} }
bool abort() override; bool abort() override;
@ -43,5 +88,7 @@ class FlameCreationTask final : public InstanceCreationTask {
NetJob* m_process_update_file_info_job = nullptr; NetJob* m_process_update_file_info_job = nullptr;
NetJob::Ptr m_files_job = nullptr; NetJob::Ptr m_files_job = nullptr;
QString m_managed_id, m_managed_version_id;
std::optional<InstancePtr> m_instance; std::optional<InstancePtr> m_instance;
}; };

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
/* /*
* PolyMC - Minecraft Launcher * Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 flowln <flowlnlnln@gmail.com> * Copyright (C) 2022 flowln <flowlnlnln@gmail.com>
* Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org> * Copyright (c) 2022 Jamie Mansfield <jmansfield@cadixdev.org>
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
@ -189,13 +189,13 @@ void PackInstallTask::onResolveModsSucceeded()
// First check for blocked mods // First check for blocked mods
if (!results_file.resolved || results_file.url.isEmpty()) { if (!results_file.resolved || results_file.url.isEmpty()) {
BlockedMod blocked_mod; BlockedMod blocked_mod;
blocked_mod.name = local_file.name; blocked_mod.name = local_file.name;
blocked_mod.websiteUrl = results_file.websiteUrl; blocked_mod.websiteUrl = results_file.websiteUrl;
blocked_mod.hash = results_file.hash; blocked_mod.hash = results_file.hash;
blocked_mod.matched = false; blocked_mod.matched = false;
blocked_mod.localPath = ""; blocked_mod.localPath = "";
blocked_mod.targetFolder = results_file.targetFolder;
m_blocked_mods.append(blocked_mod); m_blocked_mods.append(blocked_mod);
@ -210,12 +210,14 @@ void PackInstallTask::onResolveModsSucceeded()
if (anyBlocked) { if (anyBlocked) {
qDebug() << "Blocked files found, displaying file list"; qDebug() << "Blocked files found, displaying file list";
auto message_dialog = new BlockedModsDialog(m_parent, tr("Blocked files found"), BlockedModsDialog message_dialog(m_parent, tr("Blocked files found"),
tr("The following files are not available for download in third party launchers.<br/>" tr("The following files are not available for download in third party launchers.<br/>"
"You will need to manually download them and add them to the instance."), "You will need to manually download them and add them to the instance."),
m_blocked_mods); m_blocked_mods);
if (message_dialog->exec() == QDialog::Accepted) { message_dialog.setModal(true);
if (message_dialog.exec() == QDialog::Accepted) {
qDebug() << "Post dialog blocked mods list: " << m_blocked_mods; qDebug() << "Post dialog blocked mods list: " << m_blocked_mods;
createInstance(); createInstance();
} else { } else {
@ -365,7 +367,7 @@ void PackInstallTask::copyBlockedMods()
continue; continue;
} }
auto dest_path = FS::PathCombine(m_stagingPath, ".minecraft", "mods", mod.name); auto dest_path = FS::PathCombine(m_stagingPath, ".minecraft", mod.targetFolder, mod.name);
setStatus(tr("Copying Blocked Mods (%1 out of %2 are done)").arg(QString::number(i), QString::number(total))); setStatus(tr("Copying Blocked Mods (%1 out of %2 are done)").arg(QString::number(i), QString::number(total)));

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
/* /*
* PolyMC - Minecraft Launcher * Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 flowln <flowlnlnln@gmail.com> * Copyright (C) 2022 flowln <flowlnlnln@gmail.com>
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
* *

View File

@ -33,13 +33,19 @@ bool ModrinthCreationTask::updateInstance()
auto instance_list = APPLICATION->instances(); auto instance_list = APPLICATION->instances();
// FIXME: How to handle situations when there's more than one install already for a given modpack? // FIXME: How to handle situations when there's more than one install already for a given modpack?
auto inst = instance_list->getInstanceByManagedName(originalName()); InstancePtr inst;
if (auto original_id = originalInstanceID(); !original_id.isEmpty()) {
inst = instance_list->getInstanceById(original_id);
Q_ASSERT(inst);
} else {
inst = instance_list->getInstanceByManagedName(originalName());
if (!inst) { if (!inst) {
inst = instance_list->getInstanceById(originalName()); inst = instance_list->getInstanceById(originalName());
if (!inst) if (!inst)
return false; return false;
}
} }
QString index_path = FS::PathCombine(m_stagingPath, "modrinth.index.json"); QString index_path = FS::PathCombine(m_stagingPath, "modrinth.index.json");
@ -49,25 +55,14 @@ bool ModrinthCreationTask::updateInstance()
auto version_name = inst->getManagedPackVersionName(); auto version_name = inst->getManagedPackVersionName();
auto version_str = !version_name.isEmpty() ? tr(" (version %1)").arg(version_name) : ""; auto version_str = !version_name.isEmpty() ? tr(" (version %1)").arg(version_name) : "";
auto info = CustomMessageBox::selectable( if (shouldConfirmUpdate()) {
m_parent, tr("Similar modpack was found!"), auto should_update = askIfShouldUpdate(m_parent, version_str);
tr("One or more of your instances are from this same modpack%1. Do you want to create a " if (should_update == ShouldUpdate::SkipUpdating)
"separate instance, or update the existing one?\n\nNOTE: Make sure you made a backup of your important instance data before " return false;
"updating, as worlds can be corrupted and some configuration may be lost (due to pack overrides).") if (should_update == ShouldUpdate::Cancel) {
.arg(version_str), m_abort = true;
QMessageBox::Information, QMessageBox::Ok | QMessageBox::Reset | QMessageBox::Abort); return false;
info->setButtonText(QMessageBox::Ok, tr("Create new instance")); }
info->setButtonText(QMessageBox::Abort, tr("Update existing instance"));
info->setButtonText(QMessageBox::Reset, tr("Cancel"));
info->exec();
if (info->clickedButton() == info->button(QMessageBox::Ok))
return false;
if (info->clickedButton() == info->button(QMessageBox::Reset)) {
m_abort = true;
return false;
} }
// Remove repeated files, we don't need to download them! // Remove repeated files, we don't need to download them!
@ -149,7 +144,7 @@ bool ModrinthCreationTask::updateInstance()
} }
setOverride(true); setOverride(true, inst->id());
qDebug() << "Will override instance!"; qDebug() << "Will override instance!";
m_instance = inst; m_instance = inst;
@ -222,7 +217,7 @@ bool ModrinthCreationTask::createInstance()
instance.setIconKey("modrinth"); instance.setIconKey("modrinth");
} }
instance.setManagedPack("modrinth", getManagedPackID(), m_managed_name, m_managed_version_id, version()); instance.setManagedPack("modrinth", m_managed_id, m_managed_name, m_managed_version_id, version());
instance.setName(name()); instance.setName(name());
instance.saveNow(); instance.saveNow();
@ -295,7 +290,8 @@ bool ModrinthCreationTask::parseManifest(const QString& index_path, std::vector<
} }
if (set_managed_info) { if (set_managed_info) {
m_managed_version_id = Json::ensureString(obj, "versionId", {}, "Managed ID"); if (m_managed_version_id.isEmpty())
m_managed_version_id = Json::ensureString(obj, "versionId", {}, "Managed ID");
m_managed_name = Json::ensureString(obj, "name", {}, "Managed Name"); m_managed_name = Json::ensureString(obj, "name", {}, "Managed Name");
} }
@ -395,13 +391,3 @@ bool ModrinthCreationTask::parseManifest(const QString& index_path, std::vector<
return true; return true;
} }
QString ModrinthCreationTask::getManagedPackID() const
{
if (!m_source_url.isEmpty()) {
QRegularExpression regex(R"(data\/(.*)\/versions)");
return regex.match(m_source_url).captured(1);
}
return {};
}

View File

@ -14,11 +14,21 @@ class ModrinthCreationTask final : public InstanceCreationTask {
Q_OBJECT Q_OBJECT
public: public:
ModrinthCreationTask(QString staging_path, SettingsObjectPtr global_settings, QWidget* parent, QString source_url = {}) ModrinthCreationTask(QString staging_path,
: InstanceCreationTask(), m_parent(parent), m_source_url(std::move(source_url)) SettingsObjectPtr global_settings,
QWidget* parent,
QString id,
QString version_id = {},
QString original_instance_id = {})
: InstanceCreationTask()
, m_parent(parent)
, m_managed_id(std::move(id))
, m_managed_version_id(std::move(version_id))
{ {
setStagingPath(staging_path); setStagingPath(staging_path);
setParentSettings(global_settings); setParentSettings(global_settings);
m_original_instance_id = std::move(original_instance_id);
} }
bool abort() override; bool abort() override;
@ -28,14 +38,12 @@ class ModrinthCreationTask final : public InstanceCreationTask {
private: private:
bool parseManifest(const QString&, std::vector<Modrinth::File>&, bool set_managed_info = true, bool show_optional_dialog = true); bool parseManifest(const QString&, std::vector<Modrinth::File>&, bool set_managed_info = true, bool show_optional_dialog = true);
QString getManagedPackID() const;
private: private:
QWidget* m_parent = nullptr; QWidget* m_parent = nullptr;
QString minecraftVersion, fabricVersion, quiltVersion, forgeVersion; QString minecraftVersion, fabricVersion, quiltVersion, forgeVersion;
QString m_managed_id, m_managed_version_id, m_managed_name; QString m_managed_id, m_managed_version_id, m_managed_name;
QString m_source_url;
std::vector<Modrinth::File> m_files; std::vector<Modrinth::File> m_files;
NetJob::Ptr m_files_job; NetJob::Ptr m_files_job;

View File

@ -128,6 +128,7 @@ auto loadIndexedVersion(QJsonObject &obj) -> ModpackVersion
file.name = Json::requireString(obj, "name"); file.name = Json::requireString(obj, "name");
file.version = Json::requireString(obj, "version_number"); file.version = Json::requireString(obj, "version_number");
file.changelog = Json::ensureString(obj, "changelog");
file.id = Json::requireString(obj, "id"); file.id = Json::requireString(obj, "id");
file.project_id = Json::requireString(obj, "project_id"); file.project_id = Json::requireString(obj, "project_id");

View File

@ -80,6 +80,7 @@ struct ModpackExtra {
struct ModpackVersion { struct ModpackVersion {
QString name; QString name;
QString version; QString version;
QString changelog;
QString id; QString id;
QString project_id; QString project_id;

View File

@ -39,5 +39,6 @@
<file>scalable/export.svg</file> <file>scalable/export.svg</file>
<file>scalable/rename.svg</file> <file>scalable/rename.svg</file>
<file>scalable/launch.svg</file> <file>scalable/launch.svg</file>
<file>scalable/shortcut.svg</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<rect fill="none" width="24" height="24"/>
<g id="_x35__1_">
<g>
<path fill="#585858" d="M9.5,9.5C9.8,9.5,10,9.2,10,9l0-2.4l7.6,7.3c0.2,0.2,0.5,0.2,0.7,0c0.2-0.2,0.2-0.5,0-0.7L10.8,6L13,6
c0.3,0,0.5-0.2,0.5-0.5S13.3,5,13,5H9.5C9.2,5,9,5.2,9,5.5V9C9,9.2,9.2,9.5,9.5,9.5z M21,5h-5.5v1H21c0.5,0,1,0.5,1,1l0,10
c0,0.5-0.4,1-1,1l-10,0c-0.5,0-1-0.5-1-1v-5.5H9V17c0,1.1,1.1,2,2.2,2H21c1.1,0,2-0.9,2-2V7.2C23,6.1,22.1,5,21,5z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 886 B

View File

@ -19,6 +19,7 @@
<file>scalable/loadermods.svg</file> <file>scalable/loadermods.svg</file>
<file>scalable/log.svg</file> <file>scalable/log.svg</file>
<file>scalable/minecraft.svg</file> <file>scalable/minecraft.svg</file>
<file>scalable/matrix.svg</file>
<file>scalable/new.svg</file> <file>scalable/new.svg</file>
<file>scalable/news.svg</file> <file>scalable/news.svg</file>
<file>scalable/notes.svg</file> <file>scalable/notes.svg</file>
@ -27,6 +28,7 @@
<file>scalable/refresh.svg</file> <file>scalable/refresh.svg</file>
<file>scalable/resourcepacks.svg</file> <file>scalable/resourcepacks.svg</file>
<file>scalable/shaderpacks.svg</file> <file>scalable/shaderpacks.svg</file>
<file>scalable/shortcut.svg</file>
<file>scalable/screenshots.svg</file> <file>scalable/screenshots.svg</file>
<file>scalable/settings.svg</file> <file>scalable/settings.svg</file>
<file>scalable/status-bad.svg</file> <file>scalable/status-bad.svg</file>
@ -39,5 +41,6 @@
<file>scalable/export.svg</file> <file>scalable/export.svg</file>
<file>scalable/rename.svg</file> <file>scalable/rename.svg</file>
<file>scalable/launch.svg</file> <file>scalable/launch.svg</file>
<file>scalable/server.svg</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 127.14 96.36"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="图层_2" data-name="图层 2"><g id="Discord_Logos" data-name="Discord Logos"><g id="Discord_Logo_-_Large_-_White" data-name="Discord Logo - Large - White"><path class="cls-1" d="M107.7,8.07A105.15,105.15,0,0,0,81.47,0a72.06,72.06,0,0,0-3.36,6.83A97.68,97.68,0,0,0,49,6.83,72.37,72.37,0,0,0,45.64,0,105.89,105.89,0,0,0,19.39,8.09C2.79,32.65-1.71,56.6.54,80.21h0A105.73,105.73,0,0,0,32.71,96.36,77.7,77.7,0,0,0,39.6,85.25a68.42,68.42,0,0,1-10.85-5.18c.91-.66,1.8-1.34,2.66-2a75.57,75.57,0,0,0,64.32,0c.87.71,1.76,1.39,2.66,2a68.68,68.68,0,0,1-10.87,5.19,77,77,0,0,0,6.89,11.1A105.25,105.25,0,0,0,126.6,80.22h0C129.24,52.84,122.09,29.11,107.7,8.07ZM42.45,65.69C36.18,65.69,31,60,31,53s5-12.74,11.43-12.74S54,46,53.89,53,48.84,65.69,42.45,65.69Zm42.24,0C78.41,65.69,73.25,60,73.25,53s5-12.74,11.44-12.74S96.23,46,96.12,53,91.08,65.69,84.69,65.69Z"/></g></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 127.14 96.36"><defs><style>.cls-1{fill:#eff0f1;}</style></defs><g id="图层_2" data-name="图层 2"><g id="Discord_Logos" data-name="Discord Logos"><g id="Discord_Logo_-_Large_-_White" data-name="Discord Logo - Large - White"><path class="cls-1" d="M107.7,8.07A105.15,105.15,0,0,0,81.47,0a72.06,72.06,0,0,0-3.36,6.83A97.68,97.68,0,0,0,49,6.83,72.37,72.37,0,0,0,45.64,0,105.89,105.89,0,0,0,19.39,8.09C2.79,32.65-1.71,56.6.54,80.21h0A105.73,105.73,0,0,0,32.71,96.36,77.7,77.7,0,0,0,39.6,85.25a68.42,68.42,0,0,1-10.85-5.18c.91-.66,1.8-1.34,2.66-2a75.57,75.57,0,0,0,64.32,0c.87.71,1.76,1.39,2.66,2a68.68,68.68,0,0,1-10.87,5.19,77,77,0,0,0,6.89,11.1A105.25,105.25,0,0,0,126.6,80.22h0C129.24,52.84,122.09,29.11,107.7,8.07ZM42.45,65.69C36.18,65.69,31,60,31,53s5-12.74,11.43-12.74S54,46,53.89,53,48.84,65.69,42.45,65.69Zm42.24,0C78.41,65.69,73.25,60,73.25,53s5-12.74,11.44-12.74S96.23,46,96.12,53,91.08,65.69,84.69,65.69Z"/></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 985 B

After

Width:  |  Height:  |  Size: 988 B

View File

@ -1,18 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs <defs id="defs3051">
id="defs3051"> <style type="text/css" id="current-color-scheme">
<style
type="text/css"
id="current-color-scheme">
.ColorScheme-Text { .ColorScheme-Text {
color:#eff0f1; color:#eff0f1;
} }
</style> </style>
</defs> </defs>
<path <path style="fill:currentColor;fill-opacity:1;stroke:none"
style="fill:currentColor;fill-opacity:1;stroke:none" d="M 3 2 L 3 14 L 8 14 L 8 13 L 4 13 L 4 3 L 9 3 L 9 6 L 12 6 L 12 9 L 13 9 L 13 6 L 13 5 L 10 2 L 9 2 L 3 2 z M 10 9 L 10 11 L 8 11 L 8 12 L 10 12 L 10 14 L 11 14 L 11 12 L 13 12 L 13 11 L 11 11 L 11 9 L 10 9 z "
d="M 4 4 L 4 28 L 17 28 L 17 27 L 5 27 L 5 14 L 10 14 L 13 11 L 27 11 L 27 17 L 28 17 L 28 7 L 18 7 L 15 4 L 4 4 z M 22 17 L 22 22 L 17 22 L 17 23 L 22 23 L 22 28 L 23 28 L 23 23 L 28 23 L 28 22 L 23 22 L 23 17 L 22 17 z "
id="path99"
class="ColorScheme-Text" class="ColorScheme-Text"
/> />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 597 B

After

Width:  |  Height:  |  Size: 546 B

View File

@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#eff0f1;
}
</style>
</defs>
<path
style="fill:currentColor"
d="m 2,2 0,3 0,1 0,1 0,3 0,1 0,3 12,0 0,-3 0,-1 0,-3 0,-1 0,-1 0,-3 z m 9,1 2,0 0,1 -2,0 z M 3,6 13,6 13,7 3,7 Z m 8,2 2,0 0,1 -2,0 z m -8,2 10,0 0,1 -10,0 z m 8,2 2,0 0,1 -2,0 z"
class="ColorScheme-Text"/>
</svg>

After

Width:  |  Height:  |  Size: 495 B

View File

@ -0,0 +1,18 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#eff0f1;
}
</style>
</defs>
<g
transform="translate(-3,-1033.3622)">
<path
style="fill:currentColor;fill-opacity:1;stroke:none"
d="M 4,7 C 3.4459904,7 3,7.4459904 3,8 l 0,6 c 0,0.55401 0.4459904,1 1,1 l 5,0 c 0.55401,0 1,-0.44599 1,-1 l 0,-1 2,0 0,1 c 0,0.554 0.44599,1 1,1 l 5,0 c 0.55401,0 1,-0.446 1,-1 L 19,8 C 19,7.446 18.55401,7 18,7 l -5,0 c -0.55401,0 -1,0.446 -1,1 l 0,1 -2,0 0,-1 C 10,7.4459904 9.55401,7 9,7 Z M 4,8 7,8 9,8 9,9 C 8.4459904,9 8,9.4459904 8,10 l 0,2 c 0,0.55401 0.4459904,1 1,1 l 0,1 -2,0 -3,0 z m 9,0 3,0 2,0 0,6 -2,0 -3,0 0,-1 c 0.55401,0 1,-0.44599 1,-1 l 0,-2 C 14,9.4459904 13.55401,9 13,9 Z m -4,2 4,0 0,2 -4,0 z"
transform="translate(0,1030.3622)"
id="rect4161"
class="ColorScheme-Text" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 976 B

View File

@ -19,6 +19,7 @@
<file>scalable/loadermods.svg</file> <file>scalable/loadermods.svg</file>
<file>scalable/log.svg</file> <file>scalable/log.svg</file>
<file>scalable/minecraft.svg</file> <file>scalable/minecraft.svg</file>
<file>scalable/matrix.svg</file>
<file>scalable/new.svg</file> <file>scalable/new.svg</file>
<file>scalable/news.svg</file> <file>scalable/news.svg</file>
<file>scalable/notes.svg</file> <file>scalable/notes.svg</file>
@ -27,6 +28,7 @@
<file>scalable/refresh.svg</file> <file>scalable/refresh.svg</file>
<file>scalable/resourcepacks.svg</file> <file>scalable/resourcepacks.svg</file>
<file>scalable/shaderpacks.svg</file> <file>scalable/shaderpacks.svg</file>
<file>scalable/shortcut.svg</file>
<file>scalable/screenshots.svg</file> <file>scalable/screenshots.svg</file>
<file>scalable/settings.svg</file> <file>scalable/settings.svg</file>
<file>scalable/status-bad.svg</file> <file>scalable/status-bad.svg</file>
@ -39,5 +41,6 @@
<file>scalable/export.svg</file> <file>scalable/export.svg</file>
<file>scalable/rename.svg</file> <file>scalable/rename.svg</file>
<file>scalable/launch.svg</file> <file>scalable/launch.svg</file>
<file>scalable/server.svg</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -1 +1 @@
<svg width="8" height="8" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3 3.5v.25h-.5V6h3V3.75H5V3.5h-.75v.25h-.5V3.5H3Zm-.25.5h2.5v1.75h-2.5V4Z" fill="#EFF0F1"/><path d="M1 1v6h6l-.25-.25h-5.5V3.5H2.5l.75-.75h3.5v4L7 7V1.75H4.5L3.75 1H1Z" fill="#EFF0F1"/></svg> <svg width="8" height="8" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3 3.5v.25h-.5V6h3V3.75H5V3.5h-.75v.25h-.5V3.5H3Zm-.25.5h2.5v1.75h-2.5V4Z" fill="#232629"/><path d="M1 1v6h6l-.25-.25h-5.5V3.5H2.5l.75-.75h3.5v4L7 7V1.75H4.5L3.75 1H1Z" fill="#232629"/></svg>

Before

Width:  |  Height:  |  Size: 273 B

After

Width:  |  Height:  |  Size: 273 B

View File

@ -1 +1 @@
<svg width="8" height="8" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3.167 2.46v.208H2.75v1.875h2.5V2.668h-.417V2.46h-.625v.208h-.416V2.46h-.625Zm-.209.417h2.084v1.458H2.958V2.877Z" fill="#EFF0F1"/><path d="M1.5 1v6h5V1h-5Zm1.5.5h2a1 1 0 0 1 1 1V3a.5.5 0 1 0 0 1v1l-.5.5h-3L2 5V4a.5.5 0 1 0 0-1v-.5a1 1 0 0 1 1-1ZM2 6h2v.5H2V6Zm3 0h1v.5H5V6Z" fill="#EFF0F1"/></svg> <svg width="8" height="8" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3.167 2.46v.208H2.75v1.875h2.5V2.668h-.417V2.46h-.625v.208h-.416V2.46h-.625Zm-.209.417h2.084v1.458H2.958V2.877Z" fill="#232629"/><path d="M1.5 1v6h5V1h-5Zm1.5.5h2a1 1 0 0 1 1 1V3a.5.5 0 1 0 0 1v1l-.5.5h-3L2 5V4a.5.5 0 1 0 0-1v-.5a1 1 0 0 1 1-1ZM2 6h2v.5H2V6Zm3 0h1v.5H5V6Z" fill="#232629"/></svg>

Before

Width:  |  Height:  |  Size: 379 B

After

Width:  |  Height:  |  Size: 379 B

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 127.14 96.36"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="图层_2" data-name="图层 2"><g id="Discord_Logos" data-name="Discord Logos"><g id="Discord_Logo_-_Large_-_White" data-name="Discord Logo - Large - White"><path class="cls-1" d="M107.7,8.07A105.15,105.15,0,0,0,81.47,0a72.06,72.06,0,0,0-3.36,6.83A97.68,97.68,0,0,0,49,6.83,72.37,72.37,0,0,0,45.64,0,105.89,105.89,0,0,0,19.39,8.09C2.79,32.65-1.71,56.6.54,80.21h0A105.73,105.73,0,0,0,32.71,96.36,77.7,77.7,0,0,0,39.6,85.25a68.42,68.42,0,0,1-10.85-5.18c.91-.66,1.8-1.34,2.66-2a75.57,75.57,0,0,0,64.32,0c.87.71,1.76,1.39,2.66,2a68.68,68.68,0,0,1-10.87,5.19,77,77,0,0,0,6.89,11.1A105.25,105.25,0,0,0,126.6,80.22h0C129.24,52.84,122.09,29.11,107.7,8.07ZM42.45,65.69C36.18,65.69,31,60,31,53s5-12.74,11.43-12.74S54,46,53.89,53,48.84,65.69,42.45,65.69Zm42.24,0C78.41,65.69,73.25,60,73.25,53s5-12.74,11.44-12.74S96.23,46,96.12,53,91.08,65.69,84.69,65.69Z"/></g></g></g></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 127.14 96.36"><defs><style>.cls-1{fill:#232629;}</style></defs><g id="图层_2" data-name="图层 2"><g id="Discord_Logos" data-name="Discord Logos"><g id="Discord_Logo_-_Large_-_White" data-name="Discord Logo - Large - White"><path class="cls-1" d="M107.7,8.07A105.15,105.15,0,0,0,81.47,0a72.06,72.06,0,0,0-3.36,6.83A97.68,97.68,0,0,0,49,6.83,72.37,72.37,0,0,0,45.64,0,105.89,105.89,0,0,0,19.39,8.09C2.79,32.65-1.71,56.6.54,80.21h0A105.73,105.73,0,0,0,32.71,96.36,77.7,77.7,0,0,0,39.6,85.25a68.42,68.42,0,0,1-10.85-5.18c.91-.66,1.8-1.34,2.66-2a75.57,75.57,0,0,0,64.32,0c.87.71,1.76,1.39,2.66,2a68.68,68.68,0,0,1-10.87,5.19,77,77,0,0,0,6.89,11.1A105.25,105.25,0,0,0,126.6,80.22h0C129.24,52.84,122.09,29.11,107.7,8.07ZM42.45,65.69C36.18,65.69,31,60,31,53s5-12.74,11.43-12.74S54,46,53.89,53,48.84,65.69,42.45,65.69Zm42.24,0C78.41,65.69,73.25,60,73.25,53s5-12.74,11.44-12.74S96.23,46,96.12,53,91.08,65.69,84.69,65.69Z"/></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 985 B

After

Width:  |  Height:  |  Size: 988 B

View File

@ -1 +1 @@
<svg width="8" height="8" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M2 1.5V2H1v4.5h6V2H6v-.5H4.5V2h-1v-.5H2Zm-.5 1h5V6h-5V2.5Z" fill="#EFF0F1"/><path d="M3.93 4.37s-.19-.364-.183-.63c.005-.19.434-.378.603-.651.168-.273-.022-.54-.022-.54s.043.197-.07.4c-.112.203-.525.322-.686.672-.16.35.357.75.357.75Z" fill="#EFF0F1"/><path d="M4.637 3.264s-.645.246-.645.525c0 .28.175.372.203.463.028.091-.049.245-.049.245s.252-.175.21-.378c-.042-.203-.238-.267-.126-.47.075-.136.407-.385.407-.385Z" fill="#EFF0F1"/><path d="M3.859 4.741c.595-.021.812-.209.812-.209-.385.105-1.407.098-1.415.021-.006-.077.316-.14.316-.14s-.505 0-.546.126c-.043.126.238.223.833.202ZM4.72 5.036s.583-.124.526-.44c-.07-.386-.477-.169-.477-.169s.288 0 .316.175c.028.175-.364.434-.364.434ZM4.434 4.868s-.147.038-.364.063c-.292.033-.645.007-.673-.042-.028-.05.05-.077.05-.077-.35.084-.16.23.251.26.352.023.876-.106.876-.106l-.14-.098ZM3.53 5.174s-.159.004-.168.088c-.01.084.098.159.49.182.392.024.668-.107.668-.107l-.178-.107s-.112.023-.285.046c-.173.024-.527-.018-.541-.051-.014-.032.014-.051.014-.051Z" fill="#EFF0F1"/><path d="M5.057 5.552c.06-.065-.019-.117-.019-.117s.028.033-.009.07c-.037.037-.378.13-.924.158-.546.028-1.14-.05-1.159-.121-.018-.07.304-.126.304-.126-.037.005-.485.014-.5.136-.013.12.197.22 1.037.22.84 0 1.21-.155 1.27-.22Z" fill="#EFF0F1"/><path d="M4.73 5.828c-.368.074-1.489.027-1.489.027s.728.173 1.56.029c.397-.07.42-.262.42-.262s-.122.13-.49.206Z" fill="#EFF0F1"/></svg> <svg width="8" height="8" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M2 1.5V2H1v4.5h6V2H6v-.5H4.5V2h-1v-.5H2Zm-.5 1h5V6h-5V2.5Z" fill="#232629"/><path d="M3.93 4.37s-.19-.364-.183-.63c.005-.19.434-.378.603-.651.168-.273-.022-.54-.022-.54s.043.197-.07.4c-.112.203-.525.322-.686.672-.16.35.357.75.357.75Z" fill="#232629"/><path d="M4.637 3.264s-.645.246-.645.525c0 .28.175.372.203.463.028.091-.049.245-.049.245s.252-.175.21-.378c-.042-.203-.238-.267-.126-.47.075-.136.407-.385.407-.385Z" fill="#232629"/><path d="M3.859 4.741c.595-.021.812-.209.812-.209-.385.105-1.407.098-1.415.021-.006-.077.316-.14.316-.14s-.505 0-.546.126c-.043.126.238.223.833.202ZM4.72 5.036s.583-.124.526-.44c-.07-.386-.477-.169-.477-.169s.288 0 .316.175c.028.175-.364.434-.364.434ZM4.434 4.868s-.147.038-.364.063c-.292.033-.645.007-.673-.042-.028-.05.05-.077.05-.077-.35.084-.16.23.251.26.352.023.876-.106.876-.106l-.14-.098ZM3.53 5.174s-.159.004-.168.088c-.01.084.098.159.49.182.392.024.668-.107.668-.107l-.178-.107s-.112.023-.285.046c-.173.024-.527-.018-.541-.051-.014-.032.014-.051.014-.051Z" fill="#232629"/><path d="M5.057 5.552c.06-.065-.019-.117-.019-.117s.028.033-.009.07c-.037.037-.378.13-.924.158-.546.028-1.14-.05-1.159-.121-.018-.07.304-.126.304-.126-.037.005-.485.014-.5.136-.013.12.197.22 1.037.22.84 0 1.21-.155 1.27-.22Z" fill="#232629"/><path d="M4.73 5.828c-.368.074-1.489.027-1.489.027s.728.173 1.56.029c.397-.07.42-.262.42-.262s-.122.13-.49.206Z" fill="#232629"/></svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,18 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs <defs id="defs3051">
id="defs3051"> <style type="text/css" id="current-color-scheme">
<style
type="text/css"
id="current-color-scheme">
.ColorScheme-Text { .ColorScheme-Text {
color:#232629; color:#232629;
} }
</style> </style>
</defs> </defs>
<path <path style="fill:currentColor;fill-opacity:1;stroke:none"
style="fill:currentColor;fill-opacity:1;stroke:none" d="M 3 2 L 3 14 L 8 14 L 8 13 L 4 13 L 4 3 L 9 3 L 9 6 L 12 6 L 12 9 L 13 9 L 13 6 L 13 5 L 10 2 L 9 2 L 3 2 z M 10 9 L 10 11 L 8 11 L 8 12 L 10 12 L 10 14 L 11 14 L 11 12 L 13 12 L 13 11 L 11 11 L 11 9 L 10 9 z "
d="M 4 4 L 4 28 L 17 28 L 17 27 L 5 27 L 5 14 L 10 14 L 13 11 L 27 11 L 27 17 L 28 17 L 28 7 L 18 7 L 15 4 L 4 4 z M 22 17 L 22 22 L 17 22 L 17 23 L 22 23 L 22 28 L 23 28 L 23 23 L 28 23 L 28 22 L 23 22 L 23 17 L 22 17 z "
id="path99"
class="ColorScheme-Text" class="ColorScheme-Text"
/> />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 597 B

After

Width:  |  Height:  |  Size: 546 B

View File

@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#232629;
}
</style>
</defs>
<path
style="fill:currentColor"
d="m 2,2 0,3 0,1 0,1 0,3 0,1 0,3 12,0 0,-3 0,-1 0,-3 0,-1 0,-1 0,-3 z m 9,1 2,0 0,1 -2,0 z M 3,6 13,6 13,7 3,7 Z m 8,2 2,0 0,1 -2,0 z m -8,2 10,0 0,1 -10,0 z m 8,2 2,0 0,1 -2,0 z"
class="ColorScheme-Text"/>
</svg>

After

Width:  |  Height:  |  Size: 495 B

View File

@ -0,0 +1,18 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs id="defs3051">
<style type="text/css" id="current-color-scheme">
.ColorScheme-Text {
color:#232629;
}
</style>
</defs>
<g
transform="translate(-3,-1033.3622)">
<path
style="fill:currentColor;fill-opacity:1;stroke:none"
d="M 4,7 C 3.4459904,7 3,7.4459904 3,8 l 0,6 c 0,0.55401 0.4459904,1 1,1 l 5,0 c 0.55401,0 1,-0.44599 1,-1 l 0,-1 2,0 0,1 c 0,0.554 0.44599,1 1,1 l 5,0 c 0.55401,0 1,-0.446 1,-1 L 19,8 C 19,7.446 18.55401,7 18,7 l -5,0 c -0.55401,0 -1,0.446 -1,1 l 0,1 -2,0 0,-1 C 10,7.4459904 9.55401,7 9,7 Z M 4,8 7,8 9,8 9,9 C 8.4459904,9 8,9.4459904 8,10 l 0,2 c 0,0.55401 0.4459904,1 1,1 l 0,1 -2,0 -3,0 z m 9,0 3,0 2,0 0,6 -2,0 -3,0 0,-1 c 0.55401,0 1,-0.44599 1,-1 l 0,-2 C 14,9.4459904 13.55401,9 13,9 Z m -4,2 4,0 0,2 -4,0 z"
transform="translate(0,1030.3622)"
id="rect4161"
class="ColorScheme-Text" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 976 B

View File

@ -35,6 +35,7 @@
<file>scalable/screenshot-placeholder.svg</file> <file>scalable/screenshot-placeholder.svg</file>
<file>scalable/screenshots.svg</file> <file>scalable/screenshots.svg</file>
<file>scalable/settings.svg</file> <file>scalable/settings.svg</file>
<file>scalable/shortcut.svg</file>
<file>scalable/star.svg</file> <file>scalable/star.svg</file>
<file>scalable/status-bad.svg</file> <file>scalable/status-bad.svg</file>
<file>scalable/status-good.svg</file> <file>scalable/status-good.svg</file>
@ -46,6 +47,7 @@
<file>scalable/tag.svg</file> <file>scalable/tag.svg</file>
<file>scalable/export.svg</file> <file>scalable/export.svg</file>
<file>scalable/rename.svg</file> <file>scalable/rename.svg</file>
<file>scalable/server.svg</file>
<file>scalable/launch.svg</file> <file>scalable/launch.svg</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="24px"
viewBox="0 0 24 24"
width="24px"
fill="#000000"
version="1.1"
id="svg136"
sodipodi:docname="server.svg"
inkscape:version="1.2.1 (9c6d41e4, 2022-07-14)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs140" />
<sodipodi:namedview
id="namedview138"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="42.791667"
inkscape:cx="12.222006"
inkscape:cy="12.257059"
inkscape:window-width="1748"
inkscape:window-height="1161"
inkscape:window-x="9"
inkscape:window-y="33"
inkscape:window-maximized="0"
inkscape:current-layer="svg136" />
<path
d="M0 0h24v24H0V0z"
fill="none"
id="path132" />
<path
d="M19 15v4H5v-4h14m1-2H4c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1-1v-6c0-.55-.45-1-1-1zM7 18.5c-.82 0-1.5-.67-1.5-1.5s.68-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM19 5v4H5V5h14m1-2H4c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1zM7 8.5c-.82 0-1.5-.67-1.5-1.5S6.18 5.5 7 5.5s1.5.68 1.5 1.5S7.83 8.5 7 8.5z"
id="path134"
style="fill:#757575;fill-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,3 @@
<svg fill="#757575" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M5 21q-.825 0-1.413-.587Q3 19.825 3 19V5q0-.825.587-1.413Q4.175 3 5 3h7v2H5v14h14v-7h2v7q0 .825-.587 1.413Q19.825 21 19 21Zm4.7-5.3-1.4-1.4L17.6 5H14V3h7v7h-2V6.4Z"/>
</svg>

After

Width:  |  Height:  |  Size: 286 B

View File

@ -35,6 +35,7 @@
<file>scalable/screenshot-placeholder.svg</file> <file>scalable/screenshot-placeholder.svg</file>
<file>scalable/screenshots.svg</file> <file>scalable/screenshots.svg</file>
<file>scalable/settings.svg</file> <file>scalable/settings.svg</file>
<file>scalable/shortcut.svg</file>
<file>scalable/star.svg</file> <file>scalable/star.svg</file>
<file>scalable/status-bad.svg</file> <file>scalable/status-bad.svg</file>
<file>scalable/status-good.svg</file> <file>scalable/status-good.svg</file>
@ -47,5 +48,6 @@
<file>scalable/rename.svg</file> <file>scalable/rename.svg</file>
<file>scalable/tag.svg</file> <file>scalable/tag.svg</file>
<file>scalable/launch.svg</file> <file>scalable/launch.svg</file>
<file>scalable/server.svg</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z"/> <path d="M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 321 B

After

Width:  |  Height:  |  Size: 322 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M16,13C15.71,13 15.38,13 15.03,13.05C16.19,13.89 17,15 17,16.5V19H23V16.5C23,14.17 18.33,13 16,13M8,13C5.67,13 1,14.17 1,16.5V19H15V16.5C15,14.17 10.33,13 8,13M8,11A3,3 0 0,0 11,8A3,3 0 0,0 8,5A3,3 0 0,0 5,8A3,3 0 0,0 8,11M16,11A3,3 0 0,0 19,8A3,3 0 0,0 16,5A3,3 0 0,0 13,8A3,3 0 0,0 16,11Z"/> <path d="M16,13C15.71,13 15.38,13 15.03,13.05C16.19,13.89 17,15 17,16.5V19H23V16.5C23,14.17 18.33,13 16,13M8,13C5.67,13 1,14.17 1,16.5V19H15V16.5C15,14.17 10.33,13 8,13M8,11A3,3 0 0,0 11,8A3,3 0 0,0 8,5A3,3 0 0,0 5,8A3,3 0 0,0 8,11M16,11A3,3 0 0,0 19,8A3,3 0 0,0 16,5A3,3 0 0,0 13,8A3,3 0 0,0 16,11Z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 412 B

After

Width:  |  Height:  |  Size: 413 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49 0-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z"/> <path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49 0-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 496 B

After

Width:  |  Height:  |  Size: 497 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M12,8L10.67,8.09C9.81,7.07 7.4,4.5 5,4.5C5,4.5 3.03,7.46 4.96,11.41C4.41,12.24 4.07,12.67 4,13.66L2.07,13.95L2.28,14.93L4.04,14.67L4.18,15.38L2.61,16.32L3.08,17.21L4.53,16.32C5.68,18.76 8.59,20 12,20C15.41,20 18.32,18.76 19.47,16.32L20.92,17.21L21.39,16.32L19.82,15.38L19.96,14.67L21.72,14.93L21.93,13.95L20,13.66C19.93,12.67 19.59,12.24 19.04,11.41C20.97,7.46 19,4.5 19,4.5C16.6,4.5 14.19,7.07 13.33,8.09L12,8M9,11A1,1 0 0,1 10,12A1,1 0 0,1 9,13A1,1 0 0,1 8,12A1,1 0 0,1 9,11M15,11A1,1 0 0,1 16,12A1,1 0 0,1 15,13A1,1 0 0,1 14,12A1,1 0 0,1 15,11M11,14H13L12.3,15.39C12.5,16.03 13.06,16.5 13.75,16.5A1.5,1.5 0 0,0 15.25,15H15.75A2,2 0 0,1 13.75,17C13,17 12.35,16.59 12,16V16H12C11.65,16.59 11,17 10.25,17A2,2 0 0,1 8.25,15H8.75A1.5,1.5 0 0,0 10.25,16.5C10.94,16.5 11.5,16.03 11.7,15.39L11,14Z"/> <path d="M12,8L10.67,8.09C9.81,7.07 7.4,4.5 5,4.5C5,4.5 3.03,7.46 4.96,11.41C4.41,12.24 4.07,12.67 4,13.66L2.07,13.95L2.28,14.93L4.04,14.67L4.18,15.38L2.61,16.32L3.08,17.21L4.53,16.32C5.68,18.76 8.59,20 12,20C15.41,20 18.32,18.76 19.47,16.32L20.92,17.21L21.39,16.32L19.82,15.38L19.96,14.67L21.72,14.93L21.93,13.95L20,13.66C19.93,12.67 19.59,12.24 19.04,11.41C20.97,7.46 19,4.5 19,4.5C16.6,4.5 14.19,7.07 13.33,8.09L12,8M9,11A1,1 0 0,1 10,12A1,1 0 0,1 9,13A1,1 0 0,1 8,12A1,1 0 0,1 9,11M15,11A1,1 0 0,1 16,12A1,1 0 0,1 15,13A1,1 0 0,1 14,12A1,1 0 0,1 15,11M11,14H13L12.3,15.39C12.5,16.03 13.06,16.5 13.75,16.5A1.5,1.5 0 0,0 15.25,15H15.75A2,2 0 0,1 13.75,17C13,17 12.35,16.59 12,16V16H12C11.65,16.59 11,17 10.25,17A2,2 0 0,1 8.25,15H8.75A1.5,1.5 0 0,0 10.25,16.5C10.94,16.5 11.5,16.03 11.7,15.39L11,14Z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 914 B

After

Width:  |  Height:  |  Size: 915 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M20 6h-8l-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-2.06 11L15 15.28 12.06 17l.78-3.33-2.59-2.24 3.41-.29L15 8l1.34 3.14 3.41.29-2.59 2.24.78 3.33z"/> <path d="M20 6h-8l-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-2.06 11L15 15.28 12.06 17l.78-3.33-2.59-2.24 3.41-.29L15 8l1.34 3.14 3.41.29-2.59 2.24.78 3.33z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 303 B

After

Width:  |  Height:  |  Size: 304 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M21 10.12h-6.78l2.74-2.82c-2.73-2.7-7.15-2.8-9.88-.1-2.73 2.71-2.73 7.08 0 9.79 2.73 2.71 7.15 2.71 9.88 0C18.32 15.65 19 14.08 19 12.1h2c0 1.98-.88 4.55-2.64 6.29-3.51 3.48-9.21 3.48-12.72 0-3.5-3.47-3.53-9.11-.02-12.58 3.51-3.47 9.14-3.47 12.65 0L21 3v7.12zM12.5 8v4.25l3.5 2.08-.72 1.21L11 13V8h1.5z"/> <path d="M21 10.12h-6.78l2.74-2.82c-2.73-2.7-7.15-2.8-9.88-.1-2.73 2.71-2.73 7.08 0 9.79 2.73 2.71 7.15 2.71 9.88 0C18.32 15.65 19 14.08 19 12.1h2c0 1.98-.88 4.55-2.64 6.29-3.51 3.48-9.21 3.48-12.72 0-3.5-3.47-3.53-9.11-.02-12.58 3.51-3.47 9.14-3.47 12.65 0L21 3v7.12zM12.5 8v4.25l3.5 2.08-.72 1.21L11 13V8h1.5z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 424 B

After

Width:  |  Height:  |  Size: 425 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9h-4v4h-2v-4H9V9h4V5h2v4h4v2z"/> <path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9h-4v4h-2v-4H9V9h4V5h2v4h4v2z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 265 B

After

Width:  |  Height:  |  Size: 266 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M22,12A10,10,0,1,1,12,2,10,10,0,0,1,22,12ZM12,4a8,8,0,1,0,8,8A8,8,0,0,0,12,4Zm4.23,14-1.12-4.82,3.73-3.23-4.92-.42L12,5,10.08,9.54,5.16,10l3.73,3.23L7.77,18,12,15.45,16.23,18"/> <path d="M22,12A10,10,0,1,1,12,2,10,10,0,0,1,22,12ZM12,4a8,8,0,1,0,8,8A8,8,0,0,0,12,4Zm4.23,14-1.12-4.82,3.73-3.23-4.92-.42L12,5,10.08,9.54,5.16,10l3.73,3.23L7.77,18,12,15.45,16.23,18"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 296 B

After

Width:  |  Height:  |  Size: 297 B

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg <svg
fill="#D8DEE9" fill="#eeeeee"
height="24" height="24"
viewBox="0 0 24 24" viewBox="0 0 24 24"
width="24" width="24"

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" version="1.1" id="svg4" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" version="1.1" id="svg4" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<defs id="defs8"/> <defs id="defs8"/>
<path id="path5145" style="fill:#D8DEE9;fill-opacity:1;stroke:none;stroke-width:1.4;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none" d="M 7.1074219 0.96484375 L 7.1074219 2.7304688 L 2.6132812 2.7304688 L 2.6132812 4.4960938 L 21.386719 4.4960938 L 21.386719 2.7304688 L 16.892578 2.7304688 L 16.892578 0.96484375 L 7.1074219 0.96484375 z M 5.0058594 6.0839844 L 5.0058594 22.859375 L 18.994141 22.859375 L 18.994141 6.0839844 L 5.0058594 6.0839844 z M 7.9160156 9.0605469 L 10.193359 9.0605469 L 10.193359 19.882812 L 7.9160156 19.882812 L 7.9160156 9.0605469 z M 13.804688 9.0605469 L 16.085938 9.0605469 L 16.085938 19.882812 L 13.804688 19.882812 L 13.804688 9.0605469 z "/> <path id="path5145" style="fill:#eeeeee;fill-opacity:1;stroke:none;stroke-width:1.4;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none" d="M 7.1074219 0.96484375 L 7.1074219 2.7304688 L 2.6132812 2.7304688 L 2.6132812 4.4960938 L 21.386719 4.4960938 L 21.386719 2.7304688 L 16.892578 2.7304688 L 16.892578 0.96484375 L 7.1074219 0.96484375 z M 5.0058594 6.0839844 L 5.0058594 22.859375 L 18.994141 22.859375 L 18.994141 6.0839844 L 5.0058594 6.0839844 z M 7.9160156 9.0605469 L 10.193359 9.0605469 L 10.193359 19.882812 L 7.9160156 19.882812 L 7.9160156 9.0605469 z M 13.804688 9.0605469 L 16.085938 9.0605469 L 16.085938 19.882812 L 13.804688 19.882812 L 13.804688 9.0605469 z "/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 943 B

After

Width:  |  Height:  |  Size: 944 B

View File

@ -1,4 +1,4 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M10.14,11.63a1.15,1.15,0,1,0,1,1.14A1.1,1.1,0,0,0,10.14,11.63Zm3.75,0a1.15,1.15,0,1,0,1,1.14A1.1,1.1,0,0,0,13.89,11.63Z"/> <path d="M10.14,11.63a1.15,1.15,0,1,0,1,1.14A1.1,1.1,0,0,0,10.14,11.63Zm3.75,0a1.15,1.15,0,1,0,1,1.14A1.1,1.1,0,0,0,13.89,11.63Z"/>
<path d="M18.89,3H5.11A2.11,2.11,0,0,0,3,5.12V19a2.11,2.11,0,0,0,2.11,2.12H16.77l-.55-1.9,1.32,1.22,1.24,1.15,2.21,2V5.12A2.11,2.11,0,0,0,18.89,3Zm-4,13.43s-.37-.44-.68-.83a3.25,3.25,0,0,0,1.86-1.22,5.89,5.89,0,0,1-1.18.61,6.77,6.77,0,0,1-1.49.44,7.21,7.21,0,0,1-2.66,0A8.63,8.63,0,0,1,9.25,15a6,6,0,0,1-.75-.35l-.09-.05,0,0-.29-.17a3.2,3.2,0,0,0,1.8,1.21l-.69.85a3.73,3.73,0,0,1-3.14-1.56,13.77,13.77,0,0,1,1.48-6,5.09,5.09,0,0,1,2.89-1.08l.1.12A6.94,6.94,0,0,0,7.82,9.26s.23-.12.61-.3a7.72,7.72,0,0,1,2.33-.65l.17,0a8.7,8.7,0,0,1,2.08,0,8.38,8.38,0,0,1,3.1,1A6.85,6.85,0,0,0,13.55,8l.14-.16a5.09,5.09,0,0,1,2.89,1.08,13.77,13.77,0,0,1,1.48,6A3.76,3.76,0,0,1,14.92,16.43Z"/> <path d="M18.89,3H5.11A2.11,2.11,0,0,0,3,5.12V19a2.11,2.11,0,0,0,2.11,2.12H16.77l-.55-1.9,1.32,1.22,1.24,1.15,2.21,2V5.12A2.11,2.11,0,0,0,18.89,3Zm-4,13.43s-.37-.44-.68-.83a3.25,3.25,0,0,0,1.86-1.22,5.89,5.89,0,0,1-1.18.61,6.77,6.77,0,0,1-1.49.44,7.21,7.21,0,0,1-2.66,0A8.63,8.63,0,0,1,9.25,15a6,6,0,0,1-.75-.35l-.09-.05,0,0-.29-.17a3.2,3.2,0,0,0,1.8,1.21l-.69.85a3.73,3.73,0,0,1-3.14-1.56,13.77,13.77,0,0,1,1.48-6,5.09,5.09,0,0,1,2.89-1.08l.1.12A6.94,6.94,0,0,0,7.82,9.26s.23-.12.61-.3a7.72,7.72,0,0,1,2.33-.65l.17,0a8.7,8.7,0,0,1,2.08,0,8.38,8.38,0,0,1,3.1,1A6.85,6.85,0,0,0,13.55,8l.14-.16a5.09,5.09,0,0,1,2.89,1.08,13.77,13.77,0,0,1,1.48,6A3.76,3.76,0,0,1,14.92,16.43Z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 921 B

After

Width:  |  Height:  |  Size: 922 B

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" version="1.1" id="svg4" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" version="1.1" id="svg4" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<defs id="defs8"/> <defs id="defs8"/>
<path id="path2" d="M 4 4 C 2.9000011 4 2.0097656 4.9000011 2.0097656 6 L 2 18 C 2 19.099999 2.9000011 20 4 20 L 20 20 C 21.099999 20 22 19.099999 22 18 L 22 8 C 22 6.9000011 21.099999 6 20 6 L 12 6 L 10 4 L 4 4 z M 12.537109 9.9082031 L 13.185547 10.298828 L 17.554688 12.929688 L 13.185547 15.5625 L 12.537109 15.953125 L 11.755859 14.65625 L 12.404297 14.265625 L 13.349609 13.695312 L 6.4453125 13.695312 L 6.4453125 12.166016 L 13.351562 12.166016 L 12.404297 11.595703 L 11.755859 11.205078 L 12.537109 9.9082031 z "/> <path id="path2" d="M 4 4 C 2.9000011 4 2.0097656 4.9000011 2.0097656 6 L 2 18 C 2 19.099999 2.9000011 20 4 20 L 20 20 C 21.099999 20 22 19.099999 22 18 L 22 8 C 22 6.9000011 21.099999 6 20 6 L 12 6 L 10 4 L 4 4 z M 12.537109 9.9082031 L 13.185547 10.298828 L 17.554688 12.929688 L 13.185547 15.5625 L 12.537109 15.953125 L 11.755859 14.65625 L 12.404297 14.265625 L 13.349609 13.695312 L 6.4453125 13.695312 L 6.4453125 12.166016 L 13.351562 12.166016 L 12.404297 11.595703 L 11.755859 11.205078 L 12.537109 9.9082031 z "/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 771 B

After

Width:  |  Height:  |  Size: 772 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M22.7,19L13.6,9.9C14.5,7.6 14,4.9 12.1,3C10.1,1 7.1,0.6 4.7,1.7L9,6L6,9L1.6,4.7C0.4,7.1 0.9,10.1 2.9,12.1C4.8,14 7.5,14.5 9.8,13.6L18.9,22.7C19.3,23.1 19.9,23.1 20.3,22.7L22.6,20.4C23.1,20 23.1,19.3 22.7,19Z"/> <path d="M22.7,19L13.6,9.9C14.5,7.6 14,4.9 12.1,3C10.1,1 7.1,0.6 4.7,1.7L9,6L6,9L1.6,4.7C0.4,7.1 0.9,10.1 2.9,12.1C4.8,14 7.5,14.5 9.8,13.6L18.9,22.7C19.3,23.1 19.9,23.1 20.3,22.7L22.6,20.4C23.1,20 23.1,19.3 22.7,19Z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 329 B

After

Width:  |  Height:  |  Size: 330 B

View File

@ -10,7 +10,7 @@
width="24" width="24"
viewBox="0 0 24 24" viewBox="0 0 24 24"
height="24" height="24"
fill="#D8DEE9"> fill="#eeeeee">
<path <path
d="m 15.07,11.25 -0.9,0.92 C 13.45,12.89 13,13.5 13,15 h -2 v -0.5 c 0,-1.11 0.45,-2.11 1.17,-2.83 l 1.24,-1.26 C 13.78,10.049999 14,9.549999 14,9 14,7.89 13.100001,7 12,7 A 2,2 0 0 0 10,9 H 7.9999995 A 4,4 0 0 1 12,5 4,4 0 0 1 16,9 c 0,0.879999 -0.36,1.67 -0.93,2.25 M 13,19 h -2 v -2 h 2 M 12,2 A 10,10 0 0 0 1.9999995,12 10,10 0 0 0 12,22 10,10 0 0 0 22,12 C 22,6.47 17.5,2 12,2 Z" d="m 15.07,11.25 -0.9,0.92 C 13.45,12.89 13,13.5 13,15 h -2 v -0.5 c 0,-1.11 0.45,-2.11 1.17,-2.83 l 1.24,-1.26 C 13.78,10.049999 14,9.549999 14,9 14,7.89 13.100001,7 12,7 A 2,2 0 0 0 10,9 H 7.9999995 A 4,4 0 0 1 12,5 4,4 0 0 1 16,9 c 0,0.879999 -0.36,1.67 -0.93,2.25 M 13,19 h -2 v -2 h 2 M 12,2 A 10,10 0 0 0 1.9999995,12 10,10 0 0 0 12,22 10,10 0 0 0 22,12 C 22,6.47 17.5,2 12,2 Z"
id="path817" /> id="path817" />

Before

Width:  |  Height:  |  Size: 818 B

After

Width:  |  Height:  |  Size: 818 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z"/> <path d="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M2,21H20V19H2M20,8H18V5h2m0-2H4V13a4,4,0,0,0,4,4h6a4,4,0,0,0,4-4V10h2a2,2,0,0,0,2-2V5A2,2,0,0,0,20,3ZM11,4.43l1.62,3.29,3.63.53-2.63,2.56.62,3.62L11,12.72,7.75,14.43l.62-3.62L5.74,8.25l3.63-.53Z"/> <path d="M2,21H20V19H2M20,8H18V5h2m0-2H4V13a4,4,0,0,0,4,4h6a4,4,0,0,0,4-4V10h2a2,2,0,0,0,2-2V5A2,2,0,0,0,20,3ZM11,4.43l1.62,3.29,3.63.53-2.63,2.56.62,3.62L11,12.72,7.75,14.43l.62-3.62L5.74,8.25l3.63-.53Z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 316 B

After

Width:  |  Height:  |  Size: 317 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M2,21H20V19H2M20,8H18V5H20M20,3H4V13A4,4 0 0,0 8,17H14A4,4 0 0,0 18,13V10H20A2,2 0 0,0 22,8V5C22,3.89 21.1,3 20,3Z"/> <path d="M2,21H20V19H2M20,8H18V5H20M20,3H4V13A4,4 0 0,0 8,17H14A4,4 0 0,0 18,13V10H20A2,2 0 0,0 22,8V5C22,3.89 21.1,3 20,3Z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 236 B

After

Width:  |  Height:  |  Size: 237 B

View File

@ -7,7 +7,7 @@
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
fill="#D8DEE9" fill="#eeeeee"
height="24" height="24"
viewBox="0 0 24 24" viewBox="0 0 24 24"
width="24" width="24"

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg <svg
fill="#D8DEE9" fill="#eeeeee"
height="48" height="48"
width="48" width="48"
version="1.1" version="1.1"

Before

Width:  |  Height:  |  Size: 385 B

After

Width:  |  Height:  |  Size: 385 B

View File

@ -1,2 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<svg width="24" height="24" fill="#D8DEE9" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m20 4h-16v16h16zm0 18h-16c-1.1046 0-2-0.89543-2-2v-16c0-1.1046 0.89543-2 2-2h16c1.1046 0 2 0.89543 2 2v16c0 1.1046-0.89543 2-2 2z"/><path d="m7.2 18c-0.225 0-0.45-0.075-0.6-0.15-0.375-0.225-0.6-0.6-0.6-1.05v-9.6c0-0.45 0.225-0.825 0.6-1.05 0.225-0.15 0.375-0.15 0.6-0.15 0.15 0 0.375 0.075 0.525 0.15l9.6 4.8c0.375 0.225 0.675 0.6 0.675 1.05 0 0.45-0.225 0.9-0.675 1.05l-9.6 4.8c-0.15 0.075-0.375 0.15-0.525 0.15z" clip-rule="evenodd" fill="#D8DEE9" fill-rule="evenodd" stroke-width=".99999"/></svg> <svg width="24" height="24" fill="#eeeeee" version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m20 4h-16v16h16zm0 18h-16c-1.1046 0-2-0.89543-2-2v-16c0-1.1046 0.89543-2 2-2h16c1.1046 0 2 0.89543 2 2v16c0 1.1046-0.89543 2-2 2z"/><path d="m7.2 18c-0.225 0-0.45-0.075-0.6-0.15-0.375-0.225-0.6-0.6-0.6-1.05v-9.6c0-0.45 0.225-0.825 0.6-1.05 0.225-0.15 0.375-0.15 0.6-0.15 0.15 0 0.375 0.075 0.525 0.15l9.6 4.8c0.375 0.225 0.675 0.6 0.675 1.05 0 0.45-0.225 0.9-0.675 1.05l-9.6 4.8c-0.15 0.075-0.375 0.15-0.525 0.15z" clip-rule="evenodd" fill="#eeeeee" fill-rule="evenodd" stroke-width=".99999"/></svg>

Before

Width:  |  Height:  |  Size: 660 B

After

Width:  |  Height:  |  Size: 660 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M16.23,18l-1.12-4.82,3.73-3.23-4.92-.42L12,5,10.08,9.54,5.16,10l3.73,3.23L7.77,18,12,15.45,16.23,18M20,4H4V20H20Zm0,18H4a2,2,0,0,1-2-2V4A2,2,0,0,1,4,2H20a2,2,0,0,1,2,2V20A2,2,0,0,1,20,22Z"/> <path d="M16.23,18l-1.12-4.82,3.73-3.23-4.92-.42L12,5,10.08,9.54,5.16,10l3.73,3.23L7.77,18,12,15.45,16.23,18M20,4H4V20H20Zm0,18H4a2,2,0,0,1-2-2V4A2,2,0,0,1,4,2H20a2,2,0,0,1,2,2V20A2,2,0,0,1,20,22Z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 309 B

After

Width:  |  Height:  |  Size: 310 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/> <path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 248 B

After

Width:  |  Height:  |  Size: 249 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M21,16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V7.5C3,7.12 3.21,6.79 3.53,6.62L11.43,2.18C11.59,2.06 11.79,2 12,2C12.21,2 12.41,2.06 12.57,2.18L20.47,6.62C20.79,6.79 21,7.12 21,7.5V16.5M12,4.15L6.04,7.5L12,10.85L17.96,7.5L12,4.15M5,15.91L11,19.29V12.58L5,9.21V15.91M19,15.91V9.21L13,12.58V19.29L19,15.91Z"/> <path d="M21,16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V7.5C3,7.12 3.21,6.79 3.53,6.62L11.43,2.18C11.59,2.06 11.79,2 12,2C12.21,2 12.41,2.06 12.57,2.18L20.47,6.62C20.79,6.79 21,7.12 21,7.5V16.5M12,4.15L6.04,7.5L12,10.85L17.96,7.5L12,4.15M5,15.91L11,19.29V12.58L5,9.21V15.91M19,15.91V9.21L13,12.58V19.29L19,15.91Z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 529 B

After

Width:  |  Height:  |  Size: 530 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M0,2A2,2,0,0,1,2,0H22a2,2,0,0,1,2,2V8L22,8V6H20V8H18v2H16V8H14V6H12V8H10V6H8v4H6V8H4V6H2V8H0ZM0,22a2,2,0,0,0,2,2H22a2,2,0,0,0,2-2V10H22V22H2V10H0Zm18.71-3.29a3.83,3.83,0,0,0-5.41-5.41L12,14.59l-1.29-1.29a3.83,3.83,0,1,0,0,5.41L12,17.41l1.29,1.29a3.83,3.83,0,0,0,5.41,0Zm-4-4a1.83,1.83,0,1,1,0,2.59L13.41,16Zm-5.41,0L10.59,16,9.29,17.29a1.83,1.83,0,1,1,0-2.59Z"/> <path d="M0,2A2,2,0,0,1,2,0H22a2,2,0,0,1,2,2V8L22,8V6H20V8H18v2H16V8H14V6H12V8H10V6H8v4H6V8H4V6H2V8H0ZM0,22a2,2,0,0,0,2,2H22a2,2,0,0,0,2-2V10H22V22H2V10H0Zm18.71-3.29a3.83,3.83,0,0,0-5.41-5.41L12,14.59l-1.29-1.29a3.83,3.83,0,1,0,0,5.41L12,17.41l1.29,1.29a3.83,3.83,0,0,0,5.41,0Zm-4-4a1.83,1.83,0,1,1,0,2.59L13.41,16Zm-5.41,0L10.59,16,9.29,17.29a1.83,1.83,0,1,1,0-2.59Z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 481 B

After

Width:  |  Height:  |  Size: 482 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"/> <path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 235 B

After

Width:  |  Height:  |  Size: 236 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M20,11H4V8H20M20,15H13V13H20M20,19H13V17H20M11,19H4V13H11M20.33,4.67L18.67,3L17,4.67L15.33,3L13.67,4.67L12,3L10.33,4.67L8.67,3L7,4.67L5.33,3L3.67,4.67L2,3V19A2,2 0 0,0 4,21H20A2,2 0 0,0 22,19V3L20.33,4.67Z"/> <path d="M20,11H4V8H20M20,15H13V13H20M20,19H13V17H20M11,19H4V13H11M20.33,4.67L18.67,3L17,4.67L15.33,3L13.67,4.67L12,3L10.33,4.67L8.67,3L7,4.67L5.33,3L3.67,4.67L2,3V19A2,2 0 0,0 4,21H20A2,2 0 0,0 22,19V3L20.33,4.67Z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 327 B

After

Width:  |  Height:  |  Size: 328 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M14,17H7V15H14M17,13H7V11H17M17,9H7V7H17M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3Z"/> <path d="M14,17H7V15H14M17,13H7V11H17M17,9H7V7H17M19,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3Z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 247 B

After

Width:  |  Height:  |  Size: 248 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M5.12,5l.81-1h12l.94,1m1.67.23L19.15,3.55A1.45,1.45,0,0,0,18,3H6a1.49,1.49,0,0,0-1.16.55L3.46,5.23A1.92,1.92,0,0,0,3,6.5V19a2,2,0,0,0,2,2H19a2,2,0,0,0,2-2V6.5A1.92,1.92,0,0,0,20.54,5.23Z"/> <path d="M5.12,5l.81-1h12l.94,1m1.67.23L19.15,3.55A1.45,1.45,0,0,0,18,3H6a1.49,1.49,0,0,0-1.16.55L3.46,5.23A1.92,1.92,0,0,0,3,6.5V19a2,2,0,0,0,2,2H19a2,2,0,0,0,2-2V6.5A1.92,1.92,0,0,0,20.54,5.23Z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 308 B

After

Width:  |  Height:  |  Size: 309 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M12,3h0a9,9,0,0,0-9,9v9H5.09V12a6.91,6.91,0,1,1,7.23,6.9,5.9,5.9,0,0,1-2.59-.47v-3A4.13,4.13,0,1,0,7.85,12v9H12A9,9,0,1,0,12,3Zm0,15.91h0Z"/> <path d="M12,3h0a9,9,0,0,0-9,9v9H5.09V12a6.91,6.91,0,1,1,7.23,6.9,5.9,5.9,0,0,1-2.59-.47v-3A4.13,4.13,0,1,0,7.85,12v9H12A9,9,0,1,0,12,3Zm0,15.91h0Z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 260 B

After

Width:  |  Height:  |  Size: 261 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M22 4v-.5C22 2.12 20.88 1 19.5 1S17 2.12 17 3.5V4c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h5c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zm-.8 0h-3.4v-.5c0-.94.76-1.7 1.7-1.7s1.7.76 1.7 1.7V4zm-2.28 8c.04.33.08.66.08 1 0 2.08-.8 3.97-2.1 5.39-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H7v-2h2c.55 0 1-.45 1-1V8h2c1.1 0 2-.9 2-2V3.46c-.95-.3-1.95-.46-3-.46C5.48 3 1 7.48 1 13s4.48 10 10 10 10-4.48 10-10c0-.34-.02-.67-.05-1h-2.03zM10 20.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L8 16v1c0 1.1.9 2 2 2v1.93z"/> <path d="M22 4v-.5C22 2.12 20.88 1 19.5 1S17 2.12 17 3.5V4c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h5c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zm-.8 0h-3.4v-.5c0-.94.76-1.7 1.7-1.7s1.7.76 1.7 1.7V4zm-2.28 8c.04.33.08.66.08 1 0 2.08-.8 3.97-2.1 5.39-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H7v-2h2c.55 0 1-.45 1-1V8h2c1.1 0 2-.9 2-2V3.46c-.95-.3-1.95-.46-3-.46C5.48 3 1 7.48 1 13s4.48 10 10 10 10-4.48 10-10c0-.34-.02-.67-.05-1h-2.03zM10 20.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L8 16v1c0 1.1.9 2 2 2v1.93z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 618 B

After

Width:  |  Height:  |  Size: 619 B

View File

@ -1,3 +1,3 @@
<svg fill="#D8DEE9" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"> <svg fill="#eeeeee" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M8.75,5.5v7.15H10.7V18.5l4.55-7.8h-2.6l2.6-5.2ZM20,4H4V20H20Zm0,18H4a2,2,0,0,1-2-2V4A2,2,0,0,1,4,2H20a2,2,0,0,1,2,2V20A2,2,0,0,1,20,22Z"/> <path d="M8.75,5.5v7.15H10.7V18.5l4.55-7.8h-2.6l2.6-5.2ZM20,4H4V20H20Zm0,18H4a2,2,0,0,1-2-2V4A2,2,0,0,1,4,2H20a2,2,0,0,1,2,2V20A2,2,0,0,1,20,22Z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 257 B

After

Width:  |  Height:  |  Size: 258 B

Some files were not shown because too many files have changed in this diff Show More