logo
Hello World!

PatchKit Editor

29 maja 2025 (Updated: 5 lipca 2025)
typescriptreactpatchkit

Zaawansowany edytor WYSIWYG do projektowania interfejsów launcherów z własnym systemem zarządzania stanem, systemem wariantów CSS i intuicyjnymi komponentami UI.

Wcześniej tworzenie własnych launcherów na platformie PatchKit było możliwe jedynie przez Unity lub SDK w Electron'ie, ewentualnie na zamówienie, przez deweloperów PatchKit'a. Pojawił się pomysł webowego edytora WYSIWYG, który mógłby ułatwić tworzenie motywów przez użytkowników, bez potrzeby programowania.

PatchKit Editor to kompleksowe narzędzie do projektowania interfejsów launcherów aplikacji. Projekt przeszedł przez trzy główne etapy rozwoju: prototyp w jQuery, pierwszą implementację w React, oraz całkowicie przepisaną drugą wersję z zaawansowaną architekturą i systemem zarządzania stanem.

React 18, TypeScript, Styled Components, własny system zarządzania stanem

Edytor został zbudowany w React i TypeScript, co zapewnia lepszą kontrolę typów i bardziej przewidywalne zachowanie aplikacji. Wybór React był podyktowany potrzebą stworzenia interaktywnego interfejsu z wieloma komponentami, które muszą reagować na zmiany stanu w czasie rzeczywistym.

Aplikacja wykorzystuje modułową architekturę składającą się z następujących warstw:

Własny, wysokowydajny system zarządzania stanem oparty na useSyncExternalStore z React 18. System pozwala na:

  • Obserwowanie selektorów z precyzyjną subskrypcją
  • Rerenderowanie tylko komponentów subskrybujących konkretne wartości
  • Wsparcie dla złożonych selektorów i aktualizacji funkcyjnych
  • Optymalizację wydajności przy operacjach związanych z pozycją myszki

Struktura komponentów podzielona na kategorie:

  • Layout: Główne kontenery aplikacji (Sidebar, MainContent, Scene)
  • Views: Komponenty interfejsu użytkownika (Properties, TopbarMenu, ContextMenu)
  • Common: Komponenty wielokrotnego użytku (DropdownMenu, KeyboardKey)
  • Launcher: Komponenty renderujące podgląd launchera

Funkcje pomocnicze podzielone tematycznie:

  • LauncherElement: Manipulacja elementami (dodawanie, usuwanie, konwersja CSS)
  • LauncherConfig: Zarządzanie konfiguracją motywów
  • Utils: Funkcje pomocnicze (konwersja nazw, walidacja)

Aplikacja wykorzystuje siedem wyspecjalizowanych store'ów:

  • uiStore: Stan interfejsu użytkownika (wybrane elementy, tryby)
  • sessionStore: Dane sesji użytkownika i autoryzacja
  • mouseStore: Pozycja i stan myszy dla interakcji ze sceną
  • keyboardStore: Stan klawiatury dla skrótów klawiszowych
  • launcherElementsStore: Struktura i właściwości elementów launchera
  • launcherStatesStore: 25+ flag stanu launchera zredukowanych do prostszych stanów
  • launcherWindowStore: Właściwości okna launchera (rozmiar, pozycja)

Pierwszy prototyp stworzyłem w JavaScript i jQuery do obsługi interakcji na scenie. Miał on zaprezentować koncept i pozwolić na podjęcie decyzji o dalszym rozwoju projektu.

Prototyp PatchKit Editor

Faktyczna implementacja została stworzona w React i TypeScript. Wydana została w 2023 roku i była rozwijana przez kolejny rok. Ta wersja dawała duże możliwości, ale nie obsługiwała wszystkich stanów launchera, nie pozwalała na manipulację sceną, edycję wielu elementów naraz i była mało intuicyjna.

Pierwsza wersja PatchKit Editor

Możesz zobaczyć, jak wyglądała ta wersja tutaj: PatchKit Editor v1

Edytor został przepisany od zera i wydany pod koniec 2024 roku. Zaprojektowałem jego nowy wygląd, sposób zarządzania stanem i stylowania elementów. Aktualna wersja wprowadza znaczące ulepszenia w wydajności i funkcjonalności.

Aktualna wersja PatchKit Editor

Możesz zobaczyć, jak wygląda ta wersja tutaj: PatchKit Editor v2

  • Nawigacja: Zoom, pan
  • Narzędzia pozycjonowania:
    • Siatka (grid) z konfigurowalnymi odstępami
    • Snapping do krawędzi i środka elementów
    • Snapping do krawędzi okna aplikacji
    • Wskaźniki dla margin i padding elementów

  • Interfejs: Manipulacja na scenie, w drzewie elementów i skrótami klawiszowymi
  • Wielokrotna selekcja: Jednoczesna edycja wielu elementów
  • Operacje: Kopiowanie, wklejanie, grupowanie, zmiana kolejności

Warianty stanów: Każdy element może mieć różne style dla różnych stanów launchera - podstawowe stany (nie zainstalowana, zainstalowana, aktualizacja dostępna), stany zadań (instalacja, aktualizacja, naprawa w toku), stany błędów (błąd instalacji, brak miejsca na dysku, brak uprawnień) oraz stany aplikacji (uruchomiona, zatrzymana, wymaga naprawy).

Pseudoklasy CSS: Wsparcie dla interaktywnych stanów - :hover (najechanie myszą), :focus (fokus klawiatury), :active (aktywne naciśnięcie).

Color Picker z gradientami:

  • Wsparcie dla HSLA, RGBA, hex
  • Paleta ostatnio użytych kolorów
  • Gradienty liniowe i radialne z wieloma punktami kolorów
  • Parsowanie i generowanie złożonych stringów CSS

Inputy numeryczne:

  • Wsparcie jednostek (px, %)
  • Działania matematyczne w polach
  • Zmiana wartości przez przeciąganie myszką
  • Walidacja zakresu wartości

Dropdown'y z wyszukiwaniem:

  • Filtrowanie opcji w czasie rzeczywistym
  • Wsparcie dla grup opcji
  • Nawigacja klawiaturą

  • Rozmiar okna
  • Stylowanie kontenera

  • Podgląd launchera w różnych stanach
  • Symulacja interakcji użytkownika
  • Testowanie animacji i przejść

  • Obrazy i ikony: Przesyłanie plików, podgląd miniatur, zarządzanie formatami
  • Czcionki: Przeglądanie i dodawanie czcionek z biblioteki Google Fonts
  • Organizacja: Sortowanie w folderach, wyszukiwanie po nazwie, zarządzanie uprawnieniami

  • Undo/Redo: Pełna historia operacji z możliwością cofania
  • Wersje motywów: Automatyczne zapisywanie wersji z możliwością przywrócenia
  • Migracja: Automatyczna konwersja starszych formatów przy imporcie

  • Ochrona przed nieautoryzowanym dostępem
  • Integracja z systemem kont PatchKit
  • Szyfrowanie komunikacji z API

Przy tak dużej aplikacji, zarządzanie stanem jest kluczowe. Przy operacjach na scenie związanych z pozycją myszki, można szybko natknąć się na zbyt dużą liczbę rerenderów, które wywołane kaskadowo spowolnią lub zawieszą aplikację.

Stworzyłem własne rozwiązanie zarządzania stanem wykorzystujące useSyncExternalStore z React 18. System pozwala na:

  • Selektywną subskrypcję: Komponenty subskrybują tylko konkretne części stanu
  • Optymalizację rerenderów: Tylko komponenty używające zmienionych danych są rerenderowane
  • Wsparcie dla złożonych selektorów: Możliwość obserwowania wielu właściwości jednocześnie
  • Funkcyjne aktualizacje: Bezpieczne aktualizacje stanu z wykorzystaniem poprzedniej wartości

Gdybym miał to pisać ponownie, prawdopodobnie zastosowałbym bibliotekę Zustand, która implementuje podobne wzorce.

Motywy utworzone w edytorze są używane w launcherze. Wymagało to stworzenia wspólnej struktury danych dla obu aplikacji. Jest to JSON bazujący na wariantach, które są aplikowane w zależności od flag stanu ustawianych przez launcher.

Struktura pozwala na definiowanie różnych stylów dla różnych stanów:

Warianty stanów: Każdy element może mieć różne style dla różnych kombinacji flag stanu

  • Komponowanie stanów: Wiele wariantów może być aktywnych jednocześnie
  • Generowanie CSS: Na podstawie struktury generowane są klasy CSS i komponenty React
  • Zagnieżdżanie: Elementy mogą być dowolnie zagnieżdżane poprzez właściwość children

Launcher PatchKit wykorzystuje 25+ flag stanu opisujących różne aspekty aplikacji i zadań. Dla uproszczenia interfejsu edytora, flagi te są redukowane do 18 prostszych stanów.

  • Mapowanie stanów: Każdy stan edytora odpowiada konkretnej kombinacji flag launchera
  • Przykłady redukcji:
    • Stan Installation: isAnyTaskInProgress: true, isInstallTaskInProgress: true
    • Stan Updating: isAppInstalled: true, isAppUpdateAvailable: true, isAnyTaskInProgress: true, isUpdateTaskInProgress: true

Ta redukcja pozwala użytkownikom na intuicyjne projektowanie bez konieczności rozumienia złożonej logiki stanów launchera.

System konwersji CSS automatycznie generuje odpowiednie selektory i reguły na podstawie struktury elementów:

  • Normalizacja jednostek: Automatyczne dodawanie px do wartości numerycznych
  • Generowanie selektorów: Tworzenie selektorów CSS dla różnych kombinacji stanów
  • Optymalizacja: Minimalizacja rozmiaru generowanego CSS
  • Wsparcie dla pseudoklas: Automatyczne mapowanie stanów interaktywnych

Wiele stylów CSS wymaga skomplikowanych wartości, ale w edytorze są reprezentowane przez proste kontrolki.

Przykładem są przyciski do pozycjonowania zawartości elementu. Pozwalają na ustawienie kierunku (kolumna/wiersz) i pozycji treści bez konieczności rozumienia flexbox'a.

Pozycjonowanie zawartości elementu

System automatycznie mapuje intuicyjne kontrolki na odpowiednie właściwości CSS:

  • Kierunek: flex-direction: row/column
  • Pozycjonowanie: justify-content, align-items z automatyczną adaptacją do kierunku
  • Inteligentne mapowanie: Właściwości CSS zmieniają znaczenie w zależności od kierunku flexbox'a

Zaawansowany color picker obsługuje tworzenie gradientów z dowolną liczbą punktów kolorów. Komponent automatycznie generuje złożone stringi CSS i parsuje istniejące gradienty.

Funkcjonalności:

  • Gradienty liniowe i radialne

  • Dowolna liczba punktów kolorów

  • Interaktywne pozycjonowanie punktów

  • Podgląd w czasie rzeczywistym

  • Parsowanie istniejących gradientów

    • Przykłady generowanych stylów:
    css
    background: linear-gradient(90deg, #008cff 0%, #ff0000 38%, #00ff47 62%, #00000000 100%);
    
    background: linear-gradient(90deg, #008cff 0%, #ff0000 38%, #00ff47 62%, #00000000 100%);
    
    css
    background: radial-gradient(circle, #008cff 0%, #ff0000 31%, #00ff47 83%, #00000000 100%);
    
    background: radial-gradient(circle, #008cff 0%, #ff0000 31%, #00ff47 83%, #00000000 100%);
    
Color Picker dla gradientów

PatchKit Editor to zaawansowane narzędzie, które przekształciło proces tworzenia launcherów z programistycznego zadania w intuicyjny proces projektowy. Projekt stanowi przykład, jak można zbudować kompleksową aplikację webową z własnym systemem zarządzania stanem, zachowując wysoką wydajność i użyteczność.

  • Własny system zarządzania stanem: Stworzenie wysokowydajnego rozwiązania wykorzystującego najnowsze API React 18.

  • Zaawansowana architektura CSS: Implementacja systemu wariantów pozwalającego na definiowanie stylów dla złożonych kombinacji stanów aplikacji, z automatyczną konwersją do optymalizowanego CSS.

  • Intuicyjny interfejs dla złożonych operacji: Przekształcenie skomplikowanych właściwości CSS (flexbox, gradienty, pozycjonowanie) w proste, wizualne kontrolki dostępne dla użytkowników bez wiedzy technicznej.

  • Skalowalna architektura modułowa: Podział aplikacji na wyspecjalizowane moduły (store'y, komponenty, funkcje) pozwalający na łatwe testowanie, rozszerzanie i utrzymanie kodu.

Ten projekt był dla mnie znaczącym krokiem w rozwoju. Stworzenie tak złożonej aplikacji wymagało wypracowania systematycznego podejścia do architektury oprogramowania i ciągłego uczenia się nowych technologii.

Największą satysfakcję sprawiło mi rozwiązanie problemu wydajności poprzez własny system zarządzania stanem. Zrozumienie, jak React 18 obsługuje concurrent rendering (możliwość przerywania i wznawiania renderowania) i wykorzystanie useSyncExternalStore do stworzenia systemu, który zapewnia spójność danych podczas asynchronicznych operacji renderowania, było fascynującym wyzwaniem. Ten hook gwarantuje, że wszystkie komponenty widzą ten sam stan nawet gdy React przerywa renderowanie dla pilniejszych zadań.

Projekt nauczył mnie również, jak ważne jest projektowanie z myślą o użytkowniku końcowym. Przekształcenie skomplikowanych konceptów programistycznych w intuicyjne narzędzia wizualne wymagało głębokiego zrozumienia zarówno technologii, jak i potrzeb użytkowników.

Uważam ten projekt za kamień milowy w mojej karierze - pierwszy raz stworzyłem aplikację o takiej skali i złożoności, która jest aktywnie używana przez setki użytkowników do tworzenia profesjonalnych interfejsów.

©2025 BatStack