From b8df049b4e555a9c47fc797ee7f97ed9e67bd3a7 Mon Sep 17 00:00:00 2001 From: Marvin <52848568+mleem97@users.noreply.github.com> Date: Fri, 10 Apr 2026 03:56:18 +0200 Subject: [PATCH] feat(homepage): add codeSnippetCaption to localization and integrate snippet component - Added 'codeSnippetCaption' to the English localization file for improved content clarity. - Updated the homepage to include the GregCoreRandomSnippet component, enhancing user engagement with dynamic content. This commit enriches the homepage experience by providing localized captions and integrating a new snippet feature. --- src/components/GregCoreRandomSnippet.tsx | 61 ++++++++++++ src/data/gregCoreSnippets.ts | 118 +++++++++++++++++++++++ src/i18n/homepage/sharedLinks.ts | 1 + src/i18n/homepage/types.ts | 2 + src/pages/index.tsx | 35 +------ 5 files changed, 186 insertions(+), 31 deletions(-) create mode 100644 src/components/GregCoreRandomSnippet.tsx create mode 100644 src/data/gregCoreSnippets.ts diff --git a/src/components/GregCoreRandomSnippet.tsx b/src/components/GregCoreRandomSnippet.tsx new file mode 100644 index 0000000..9ba16b8 --- /dev/null +++ b/src/components/GregCoreRandomSnippet.tsx @@ -0,0 +1,61 @@ +import React, {useMemo} from 'react'; +import BrowserOnly from '@docusaurus/BrowserOnly'; +import {GREG_CORE_SNIPPETS} from '../data/gregCoreSnippets'; + +type Props = { + /** e.g. "Random sample from gregCore" */ + caption: string; +}; + +/** + * Picks one snippet per client mount (stable for that visit; no SSR/CSR mismatch). + */ +function GregCoreRandomSnippetInner({caption}: Props): JSX.Element { + const snippet = useMemo( + () => GREG_CORE_SNIPPETS[Math.floor(Math.random() * GREG_CORE_SNIPPETS.length)], + [], + ); + + return ( +
+
+
+
+
{caption}
+
+ {snippet.title} + · + {snippet.sourcePath} +
+
+
+
+
+
+
+
+
+          {snippet.code.trimEnd()}
+        
+
+
+ ); +} + +export function GregCoreRandomSnippet(props: Props): JSX.Element { + return ( + +
+ Loading code sample… +
+
+ }> + {() => } + + ); +} diff --git a/src/data/gregCoreSnippets.ts b/src/data/gregCoreSnippets.ts new file mode 100644 index 0000000..54905af --- /dev/null +++ b/src/data/gregCoreSnippets.ts @@ -0,0 +1,118 @@ +/** + * Short excerpts from gregCore (gregFramework monorepo) for the homepage. + * Kept in sync conceptually with Core/ and Hooks/ — adjust if APIs move. + */ +export type GregCoreSnippet = { + /** Short title for the card header */ + title: string; + /** Path inside the gregFramework repo */ + sourcePath: string; + code: string; +}; + +export const GREG_CORE_SNIPPETS: readonly GregCoreSnippet[] = [ + { + title: 'GregHookName', + sourcePath: 'gregCore/Core/GregHookName.cs', + code: `public static string Create(GregDomain domain, string action) + => Create(domain, action, null); + +public static string Create(GregDomain domain, string action, string subject) +{ + if (string.IsNullOrWhiteSpace(action)) + throw new ArgumentException("Action ist erforderlich.", nameof(action)); + // → greg.PLAYER.MoneyChanged, greg.EMPLOYEE.Hired, … + var domainPart = DomainToSegment(domain); + // … +}`, + }, + { + title: 'GregDomain', + sourcePath: 'gregCore/Core/GregDomain.cs', + code: `public enum GregDomain +{ + Gameplay, + Player, + Employee, + Customer, + Server, + Rack, + Network, + Power, + Ui, + System +}`, + }, + { + title: 'GregEventDispatcher', + sourcePath: 'gregCore/Core/GregEventDispatcher.cs', + code: `public static void On(string hookName, Action handler) +{ + if (!_handlers.TryGetValue(hookName, out var list)) + _handlers[hookName] = list = new List>(); + list.Add(handler); +} + +public static void Emit(string hookName, object payload = null) +{ + if (!_handlers.TryGetValue(hookName, out var list)) return; + foreach (var handler in list.ToArray()) + try { handler(payload); } + catch (Exception ex) { /* MelonLogger.Warning … */ } +}`, + }, + { + title: 'GregPayload', + sourcePath: 'gregCore/Core/GregPayload.cs', + code: `public static T Get(object payload, string fieldName, T fallback = default) +{ + if (payload == null) return fallback; + try + { + var prop = payload.GetType().GetProperty( + fieldName, + BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase); + if (prop == null) return fallback; + var val = prop.GetValue(payload); + return val is T typed ? typed : fallback; + } + catch { return fallback; } +}`, + }, + { + title: 'Harmony → greg hook', + sourcePath: 'gregCore/Hooks/GregPlayerHooks.cs', + code: `[HarmonyPatch(typeof(Player), nameof(Player.UpdateCoin))] +[HarmonyPostfix] +private static void OnMoneyChanged(Player __instance, float amount, bool withoutSound) +{ + try + { + GregEventDispatcher.Emit( + GregHookName.Create(GregDomain.Player, "MoneyChanged"), + new + { + Amount = amount, + NewBalance = __instance.money, + WithoutSound = withoutSound + }); + } + catch (Exception ex) + { + MelonLogger.Warning($"[gregCore] Hook failed: {ex.Message}"); + } +}`, + }, + { + title: 'Mod subscription', + sourcePath: 'mods/GregShowcaseMod (example)', + code: `GregEventDispatcher.On( + GregHookName.Create(GregDomain.Player, "MoneyChanged"), + payload => + { + var delta = GregPayload.Get(payload, "Amount"); + var balance = GregPayload.Get(payload, "NewBalance"); + MelonLogger.Msg($"Money: {delta:+0.00;-0.00} → {balance}"); + });`, + }, +] as const; diff --git a/src/i18n/homepage/sharedLinks.ts b/src/i18n/homepage/sharedLinks.ts index 28cc282..7905c8d 100644 --- a/src/i18n/homepage/sharedLinks.ts +++ b/src/i18n/homepage/sharedLinks.ts @@ -49,6 +49,7 @@ export const homepageShellEn: Pick< | 'workflowSectionTitle' | 'codeSectionTitle' | 'codeSectionLead' + | 'codeSnippetCaption' | 'ctaDiscordTitle' | 'ctaDiscordLead' | 'ctaDiscordButton' diff --git a/src/i18n/homepage/types.ts b/src/i18n/homepage/types.ts index b17aaa6..b356cee 100644 --- a/src/i18n/homepage/types.ts +++ b/src/i18n/homepage/types.ts @@ -25,6 +25,8 @@ export type HomepageContent = { workflowSectionTitle: string; codeSectionTitle: string; codeSectionLead: string; + /** Homepage #code — random gregCore excerpt */ + codeSnippetCaption: string; ctaDiscordTitle: string; ctaDiscordLead: string; ctaDiscordButton: string; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 63e7c9e..9f36cb4 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -13,6 +13,7 @@ import { FaLifeRing, FaShop, } from 'react-icons/fa6'; +import {GregCoreRandomSnippet} from '../components/GregCoreRandomSnippet'; /** Always resolves to the newest GitHub release (redirect). */ const GREG_MODMANAGER_LATEST = @@ -304,13 +305,13 @@ export default function HomePage(): JSX.Element { check_circle - MelonLoader + Harmony patches with typed hook names + MelonLoader + Harmony: gregCore emits typed greg.* events
  • check_circle - FFM plugins and FMF mods documented beside release metadata + Plugins and mods documented beside release metadata
  • @@ -320,35 +321,7 @@ export default function HomePage(): JSX.Element {
  • -
    -
    -
    -
    -
    -
    -
    -
    -                  using MelonLoader;
    -                  {'\n\n'}
    -                  public{' '}
    -                  sealed{' '}
    -                  class{' '}
    -                  MyMod : MelonMod
    -                  {' {\n'}
    -                  {'  '}
    -                  public{' '}
    -                  override{' '}
    -                  void{' '}
    -                  OnInitializeMelon
    -                  {'() {\n'}
    -                  {'    '}
    -                  
    -                    // gregFramework — attach hooks, log, ship.
    -                  
    -                  {'\n  }\n}'}
    -                
    -
    -
    +