packer (WIP)

This commit is contained in:
bQUARKz 2026-03-20 05:49:29 +00:00
parent fac421e2ca
commit ae5c03770d
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
3 changed files with 123 additions and 10 deletions

View File

@ -250,6 +250,10 @@ public enum I18n {
ASSETS_RELOCATE_WIZARD_ERROR_TARGET_ALREADY_ASSET("assets.relocateWizard.error.targetAlreadyAsset"), ASSETS_RELOCATE_WIZARD_ERROR_TARGET_ALREADY_ASSET("assets.relocateWizard.error.targetAlreadyAsset"),
ASSETS_RELOCATE_WIZARD_ERROR_TARGET_SAME("assets.relocateWizard.error.targetSame"), ASSETS_RELOCATE_WIZARD_ERROR_TARGET_SAME("assets.relocateWizard.error.targetSame"),
ASSETS_PACK_WIZARD_TITLE("assets.packWizard.title"), ASSETS_PACK_WIZARD_TITLE("assets.packWizard.title"),
ASSETS_PACK_WIZARD_STEP_DEEP_SYNC_TITLE("assets.packWizard.step.deepSync.title"),
ASSETS_PACK_WIZARD_STEP_DEEP_SYNC_DESCRIPTION("assets.packWizard.step.deepSync.description"),
ASSETS_PACK_WIZARD_STEP_DEEP_SYNC_WAITING_TITLE("assets.packWizard.step.deepSyncWaiting.title"),
ASSETS_PACK_WIZARD_STEP_DEEP_SYNC_WAITING_DESCRIPTION("assets.packWizard.step.deepSyncWaiting.description"),
ASSETS_PACK_WIZARD_STEP_SUMMARY_TITLE("assets.packWizard.step.summary.title"), ASSETS_PACK_WIZARD_STEP_SUMMARY_TITLE("assets.packWizard.step.summary.title"),
ASSETS_PACK_WIZARD_STEP_SUMMARY_DESCRIPTION("assets.packWizard.step.summary.description"), ASSETS_PACK_WIZARD_STEP_SUMMARY_DESCRIPTION("assets.packWizard.step.summary.description"),
ASSETS_PACK_WIZARD_STEP_VALIDATION_TITLE("assets.packWizard.step.validation.title"), ASSETS_PACK_WIZARD_STEP_VALIDATION_TITLE("assets.packWizard.step.validation.title"),
@ -263,6 +267,7 @@ public enum I18n {
ASSETS_PACK_WIZARD_BUTTON_CLOSE("assets.packWizard.button.close"), ASSETS_PACK_WIZARD_BUTTON_CLOSE("assets.packWizard.button.close"),
ASSETS_PACK_WIZARD_BUTTON_COPY_FAILURES("assets.packWizard.button.copyFailures"), ASSETS_PACK_WIZARD_BUTTON_COPY_FAILURES("assets.packWizard.button.copyFailures"),
ASSETS_PACK_WIZARD_LOADING_SUMMARY("assets.packWizard.loading.summary"), ASSETS_PACK_WIZARD_LOADING_SUMMARY("assets.packWizard.loading.summary"),
ASSETS_PACK_WIZARD_LOADING_DEEP_SYNC("assets.packWizard.loading.deepSync"),
ASSETS_PACK_WIZARD_LOADING_VALIDATION("assets.packWizard.loading.validation"), ASSETS_PACK_WIZARD_LOADING_VALIDATION("assets.packWizard.loading.validation"),
ASSETS_PACK_WIZARD_LOADING_PACKING("assets.packWizard.loading.packing"), ASSETS_PACK_WIZARD_LOADING_PACKING("assets.packWizard.loading.packing"),
ASSETS_PACK_WIZARD_LABEL_CANONICAL_ARTIFACT("assets.packWizard.label.canonicalArtifact"), ASSETS_PACK_WIZARD_LABEL_CANONICAL_ARTIFACT("assets.packWizard.label.canonicalArtifact"),
@ -285,7 +290,10 @@ public enum I18n {
ASSETS_PACK_WIZARD_VALIDATION_EMPTY("assets.packWizard.validation.empty"), ASSETS_PACK_WIZARD_VALIDATION_EMPTY("assets.packWizard.validation.empty"),
ASSETS_PACK_WIZARD_RESULT_NO_ARTIFACTS("assets.packWizard.result.noArtifacts"), ASSETS_PACK_WIZARD_RESULT_NO_ARTIFACTS("assets.packWizard.result.noArtifacts"),
ASSETS_PACK_WIZARD_RESULT_COPY_FAILURES_HINT("assets.packWizard.result.copyFailuresHint"), ASSETS_PACK_WIZARD_RESULT_COPY_FAILURES_HINT("assets.packWizard.result.copyFailuresHint"),
ASSETS_PACK_WIZARD_DEEP_SYNC_NOTE("assets.packWizard.deepSync.note"),
ASSETS_PACK_WIZARD_DEEP_SYNC_COMPLETED("assets.packWizard.deepSync.completed"),
ASSETS_PACK_WIZARD_ERROR_SUMMARY("assets.packWizard.error.summary"), ASSETS_PACK_WIZARD_ERROR_SUMMARY("assets.packWizard.error.summary"),
ASSETS_PACK_WIZARD_ERROR_DEEP_SYNC("assets.packWizard.error.deepSync"),
ASSETS_PACK_WIZARD_ERROR_VALIDATION("assets.packWizard.error.validation"), ASSETS_PACK_WIZARD_ERROR_VALIDATION("assets.packWizard.error.validation"),
ASSETS_PACK_WIZARD_ERROR_PACK("assets.packWizard.error.pack"), ASSETS_PACK_WIZARD_ERROR_PACK("assets.packWizard.error.pack"),
WORKSPACE_DEBUG("workspace.debug"), WORKSPACE_DEBUG("workspace.debug"),

View File

@ -15,6 +15,8 @@ import javafx.stage.Window;
import p.packer.dtos.PackerEmittedArtifactDTO; import p.packer.dtos.PackerEmittedArtifactDTO;
import p.packer.dtos.PackerPackSummaryAssetDTO; import p.packer.dtos.PackerPackSummaryAssetDTO;
import p.packer.dtos.PackerPackValidationAssetDTO; import p.packer.dtos.PackerPackValidationAssetDTO;
import p.packer.messages.ListAssetsRequest;
import p.packer.messages.ListAssetsResult;
import p.packer.messages.PackWorkspaceRequest; import p.packer.messages.PackWorkspaceRequest;
import p.packer.messages.PackWorkspaceResult; import p.packer.messages.PackWorkspaceResult;
import p.packer.messages.PackWorkspaceSummaryRequest; import p.packer.messages.PackWorkspaceSummaryRequest;
@ -32,6 +34,8 @@ import java.util.Objects;
public final class PackWorkspaceWizard { public final class PackWorkspaceWizard {
private enum Phase { private enum Phase {
DEEP_SYNC_INTRO,
DEEP_SYNC_WAITING,
SUMMARY, SUMMARY,
VALIDATION, VALIDATION,
PACKING, PACKING,
@ -50,7 +54,9 @@ public final class PackWorkspaceWizard {
private final Button closeButton = new Button(); private final Button closeButton = new Button();
private final Button copyFailuresButton = new Button(); private final Button copyFailuresButton = new Button();
private Phase phase = Phase.SUMMARY; private Phase phase = Phase.DEEP_SYNC_INTRO;
private boolean deepSyncRunning;
private boolean deepSyncCompleted;
private boolean loadingSummary; private boolean loadingSummary;
private boolean loadingValidation; private boolean loadingValidation;
private boolean packing; private boolean packing;
@ -68,12 +74,11 @@ public final class PackWorkspaceWizard {
stage.setScene(new Scene(buildRoot(), 760, 560)); stage.setScene(new Scene(buildRoot(), 760, 560));
stage.getScene().getStylesheets().add(Container.theme().getDefaultTheme()); stage.getScene().getStylesheets().add(Container.theme().getDefaultTheme());
stage.setOnCloseRequest(event -> { stage.setOnCloseRequest(event -> {
if (packing) { if (packing || deepSyncRunning) {
event.consume(); event.consume();
} }
}); });
render(); render();
loadSummary();
} }
public static void showAndWait(Window owner, ProjectReference projectReference) { public static void showAndWait(Window owner, ProjectReference projectReference) {
@ -90,9 +95,9 @@ public final class PackWorkspaceWizard {
backButton.getStyleClass().addAll("studio-button", "studio-button-secondary"); backButton.getStyleClass().addAll("studio-button", "studio-button-secondary");
backButton.setOnAction(ignored -> goBack()); backButton.setOnAction(ignored -> goBack());
nextButton.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_BUTTON_VALIDATE)); nextButton.textProperty().bind(Container.i18n().bind(I18n.WIZARD_NEXT));
nextButton.getStyleClass().addAll("studio-button", "studio-button-primary"); nextButton.getStyleClass().addAll("studio-button", "studio-button-primary");
nextButton.setOnAction(ignored -> loadValidation()); nextButton.setOnAction(ignored -> advancePrimaryFlow());
packButton.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_BUTTON_PACK)); packButton.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_BUTTON_PACK));
packButton.getStyleClass().addAll("studio-button", "studio-button-primary"); packButton.getStyleClass().addAll("studio-button", "studio-button-primary");
@ -120,12 +125,19 @@ public final class PackWorkspaceWizard {
} }
private void render() { private void render() {
final boolean busy = loadingSummary || loadingValidation || packing; final boolean busy = deepSyncRunning || loadingSummary || loadingValidation || packing;
backButton.setDisable(busy || phase == Phase.SUMMARY); backButton.setDisable(busy || phase == Phase.DEEP_SYNC_INTRO || phase == Phase.DEEP_SYNC_WAITING);
nextButton.setVisible(phase == Phase.SUMMARY); nextButton.setVisible(phase == Phase.DEEP_SYNC_INTRO
nextButton.setManaged(phase == Phase.SUMMARY); || phase == Phase.DEEP_SYNC_WAITING
nextButton.setDisable(busy || summaryResult == null); || phase == Phase.SUMMARY);
nextButton.setManaged(nextButton.isVisible());
nextButton.setDisable(switch (phase) {
case DEEP_SYNC_INTRO -> busy;
case DEEP_SYNC_WAITING -> deepSyncRunning;
case SUMMARY -> busy || summaryResult == null;
default -> true;
});
packButton.setVisible(phase == Phase.VALIDATION); packButton.setVisible(phase == Phase.VALIDATION);
packButton.setManaged(phase == Phase.VALIDATION); packButton.setManaged(phase == Phase.VALIDATION);
@ -135,6 +147,8 @@ public final class PackWorkspaceWizard {
copyFailuresButton.setManaged(phase == Phase.RESULT); copyFailuresButton.setManaged(phase == Phase.RESULT);
switch (phase) { switch (phase) {
case DEEP_SYNC_INTRO -> renderDeepSyncIntroPhase();
case DEEP_SYNC_WAITING -> renderDeepSyncWaitingPhase();
case SUMMARY -> renderSummaryPhase(); case SUMMARY -> renderSummaryPhase();
case VALIDATION -> renderValidationPhase(); case VALIDATION -> renderValidationPhase();
case PACKING -> renderPackingPhase(); case PACKING -> renderPackingPhase();
@ -142,6 +156,30 @@ public final class PackWorkspaceWizard {
} }
} }
private void renderDeepSyncIntroPhase() {
stepTitle.textProperty().unbind();
stepDescription.textProperty().unbind();
stepTitle.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_STEP_DEEP_SYNC_TITLE));
stepDescription.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_STEP_DEEP_SYNC_DESCRIPTION));
stepBody.getChildren().setAll(
AssetDetailsUiSupport.createSectionMessage(Container.i18n().text(I18n.ASSETS_PACK_WIZARD_DEEP_SYNC_NOTE)));
}
private void renderDeepSyncWaitingPhase() {
stepTitle.textProperty().unbind();
stepDescription.textProperty().unbind();
stepTitle.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_STEP_DEEP_SYNC_WAITING_TITLE));
stepDescription.textProperty().bind(Container.i18n().bind(I18n.ASSETS_PACK_WIZARD_STEP_DEEP_SYNC_WAITING_DESCRIPTION));
if (deepSyncRunning) {
stepBody.getChildren().setAll(createBusyBox(I18n.ASSETS_PACK_WIZARD_LOADING_DEEP_SYNC));
return;
}
final String message = deepSyncCompleted
? Container.i18n().text(I18n.ASSETS_PACK_WIZARD_DEEP_SYNC_COMPLETED)
: Container.i18n().text(I18n.ASSETS_PACK_WIZARD_ERROR_DEEP_SYNC);
stepBody.getChildren().setAll(AssetDetailsUiSupport.createSectionMessage(message));
}
private void renderSummaryPhase() { private void renderSummaryPhase() {
stepTitle.textProperty().unbind(); stepTitle.textProperty().unbind();
stepDescription.textProperty().unbind(); stepDescription.textProperty().unbind();
@ -353,6 +391,65 @@ public final class PackWorkspaceWizard {
} }
} }
private void advancePrimaryFlow() {
switch (phase) {
case DEEP_SYNC_INTRO -> startDeepSync();
case DEEP_SYNC_WAITING -> {
if (deepSyncCompleted) {
phase = Phase.SUMMARY;
feedbackLabel.setText("");
if (summaryResult == null) {
loadSummary();
} else {
render();
}
} else if (!deepSyncRunning) {
startDeepSync();
}
}
case SUMMARY -> loadValidation();
default -> {
}
}
}
private void startDeepSync() {
if (deepSyncRunning) {
return;
}
phase = Phase.DEEP_SYNC_WAITING;
deepSyncRunning = true;
deepSyncCompleted = false;
summaryResult = null;
validationResult = null;
packResult = null;
feedbackLabel.setText("");
render();
Container.backgroundTasks().submit(() -> {
try {
final ListAssetsResult result = Container.packer().workspaceService().listAssets(
new ListAssetsRequest(projectReference.toPackerProjectContext(), true));
Platform.runLater(() -> applyDeepSyncResult(result));
} catch (RuntimeException exception) {
Platform.runLater(() -> applyDeepSyncFailure(exception));
}
});
}
private void applyDeepSyncResult(ListAssetsResult result) {
deepSyncRunning = false;
deepSyncCompleted = result.status() != PackerOperationStatus.FAILED;
feedbackLabel.setText(deepSyncCompleted ? "" : result.summary());
render();
}
private void applyDeepSyncFailure(RuntimeException exception) {
deepSyncRunning = false;
deepSyncCompleted = false;
feedbackLabel.setText(extractMessage(exception, I18n.ASSETS_PACK_WIZARD_ERROR_DEEP_SYNC));
render();
}
private void loadSummary() { private void loadSummary() {
loadingSummary = true; loadingSummary = true;
feedbackLabel.setText(""); feedbackLabel.setText("");

View File

@ -241,6 +241,10 @@ assets.relocateWizard.error.outsideAssets=The planned target root must stay insi
assets.relocateWizard.error.targetAlreadyAsset=The planned target root already contains asset.json. assets.relocateWizard.error.targetAlreadyAsset=The planned target root already contains asset.json.
assets.relocateWizard.error.targetSame=The planned target root must differ from the current asset root. assets.relocateWizard.error.targetSame=The planned target root must differ from the current asset root.
assets.packWizard.title=Pack Workspace assets.packWizard.title=Pack Workspace
assets.packWizard.step.deepSync.title=Prepare Deep Sync
assets.packWizard.step.deepSync.description=Start with a deep sync so the pack wizard reads the latest packer snapshot before validation or packing.
assets.packWizard.step.deepSyncWaiting.title=Deep Sync
assets.packWizard.step.deepSyncWaiting.description=Wait while the packer refreshes the workspace snapshot for this wizard.
assets.packWizard.step.summary.title=Pack Summary assets.packWizard.step.summary.title=Pack Summary
assets.packWizard.step.summary.description=Review the current build set before validating or packing it. assets.packWizard.step.summary.description=Review the current build set before validating or packing it.
assets.packWizard.step.validation.title=Validation assets.packWizard.step.validation.title=Validation
@ -254,6 +258,7 @@ assets.packWizard.button.pack=Pack
assets.packWizard.button.close=Close assets.packWizard.button.close=Close
assets.packWizard.button.copyFailures=Copy Failure Summary assets.packWizard.button.copyFailures=Copy Failure Summary
assets.packWizard.loading.summary=Loading pack summary... assets.packWizard.loading.summary=Loading pack summary...
assets.packWizard.loading.deepSync=Running deep sync...
assets.packWizard.loading.validation=Running pack validation... assets.packWizard.loading.validation=Running pack validation...
assets.packWizard.loading.packing=Packing assets... assets.packWizard.loading.packing=Packing assets...
assets.packWizard.label.canonicalArtifact=Canonical Artifact assets.packWizard.label.canonicalArtifact=Canonical Artifact
@ -276,7 +281,10 @@ assets.packWizard.status.finished=Packing finished
assets.packWizard.validation.empty=No validation entries are currently available. assets.packWizard.validation.empty=No validation entries are currently available.
assets.packWizard.result.noArtifacts=No emitted artifacts were reported. assets.packWizard.result.noArtifacts=No emitted artifacts were reported.
assets.packWizard.result.copyFailuresHint=Failure summary export is reserved for a future iteration. assets.packWizard.result.copyFailuresHint=Failure summary export is reserved for a future iteration.
assets.packWizard.deepSync.note=Next starts a deep sync before the wizard shows the pack summary.
assets.packWizard.deepSync.completed=Deep sync finished. Continue to review the current pack summary.
assets.packWizard.error.summary=Unable to load pack summary. assets.packWizard.error.summary=Unable to load pack summary.
assets.packWizard.error.deepSync=Unable to complete deep sync for the current workspace.
assets.packWizard.error.validation=Unable to validate the current pack set. assets.packWizard.error.validation=Unable to validate the current pack set.
assets.packWizard.error.pack=Unable to pack the current build set. assets.packWizard.error.pack=Unable to pack the current build set.
workspace.debug=Debug workspace.debug=Debug