Skip to content

Commit 3f28b9c

Browse files
committed
Implement local file support and enhance key combinations.
- Add support for opening local JSON/YAML files with `Shortcut+L` in the File menu. - Update accelerators to improve usability (`Shortcut+O` for Swagger JSON URL). - Extend the macOS packaging script with optional GitHub Release upload logic via `gh`. - Broaden native image configuration to include additional JavaFX input handling. - Substantially update resource configuration.
1 parent e5f49ea commit 3f28b9c

File tree

6 files changed

+1342
-7
lines changed

6 files changed

+1342
-7
lines changed

build-macos-arm64.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ set -euo pipefail
1010
# Requirements:
1111
# - The native image should already be built at target/gluonfx/aarch64-darwin/swaggerific.app
1212
# - pkgbuild and productbuild must be available (macOS only)
13+
#
14+
# Optional: After packaging, this script uploads the tar.gz to the GitHub
15+
# release tagged "latest_macos" using GitHub CLI (`gh`). Keep it simple.
16+
# Requirements for upload: `gh` installed and authenticated (`gh auth login`).
1317

1418
ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
1519
TARGET_DIR="$ROOT_DIR/target/gluonfx/aarch64-darwin"
@@ -19,6 +23,10 @@ STAGING_DIR="$ROOT_DIR/staging"
1923
IDENTIFIER="io.github.ozkanpakdil.swaggerific"
2024
APP_ICON_PNG="$ROOT_DIR/src/main/resources/applogo.png"
2125

26+
# --- Simple, fixed upload target ---
27+
GITHUB_REPO="ozkanpakdil/swaggerific"
28+
RELEASE_TAG="latest_macos"
29+
2230
# Obtain project version from Maven (falls back to 0.0.0 if unavailable)
2331
VERSION="$(./mvnw -q -DforceStdout help:evaluate -Dexpression=project.version 2>/dev/null || echo 0.0.0)"
2432
if [[ -z "$VERSION" || "$VERSION" == *"["* ]]; then
@@ -102,3 +110,23 @@ echo "Done. Artifacts:"
102110
echo " - $STAGING_DIR/$ARCHIVE_NAME"
103111
echo " - $STAGING_DIR/$PKG_NAME"
104112
echo " - $STAGING_DIR/$INSTALLER_NAME"
113+
114+
# ------------------------
115+
# Simple upload to GitHub Release (latest_macos)
116+
# ------------------------
117+
ARCHIVE_PATH="$STAGING_DIR/$ARCHIVE_NAME"
118+
if command -v gh >/dev/null 2>&1; then
119+
echo "Uploading $ARCHIVE_PATH to https://github.com/$GITHUB_REPO/releases/tag/$RELEASE_TAG ..."
120+
# Ensure release exists (no frills); if it doesn't, print a hint and skip
121+
if gh release view "$RELEASE_TAG" --repo "$GITHUB_REPO" >/dev/null 2>&1; then
122+
gh release upload "$RELEASE_TAG" "$ARCHIVE_PATH" --repo "$GITHUB_REPO" --clobber
123+
echo "Upload complete."
124+
else
125+
echo "Release tag '$RELEASE_TAG' does not exist on $GITHUB_REPO. Create it first, then re-run."
126+
echo "Hint: gh release create $RELEASE_TAG -t \"latest macOS\" -n \"Automated macOS build\" --repo $GITHUB_REPO"
127+
fi
128+
else
129+
echo "GitHub CLI (gh) not found. To upload manually run:"
130+
echo " gh auth login"
131+
echo " gh release upload $RELEASE_TAG $ARCHIVE_PATH --repo $GITHUB_REPO --clobber"
132+
fi

src/main/java/io/github/ozkanpakdil/swaggerific/ui/MainController.java

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,107 @@ public void menuFileOpenSwagger(ActionEvent ignoredActionEvent) {
378378
});
379379
}
380380

381+
/**
382+
* Opens a local Swagger/OpenAPI JSON file and populates the tree.
383+
*/
384+
@DisableWindow
385+
public void menuFileOpenLocal(ActionEvent ignoredActionEvent) {
386+
javafx.stage.FileChooser chooser = new javafx.stage.FileChooser();
387+
chooser.setTitle("Open Swagger/OpenAPI JSON");
388+
chooser.getExtensionFilters().addAll(
389+
new javafx.stage.FileChooser.ExtensionFilter("JSON Files", "*.json"),
390+
new javafx.stage.FileChooser.ExtensionFilter("All Files", "*.*")
391+
);
392+
File file = chooser.showOpenDialog(mainBox.getScene().getWindow());
393+
if (file == null) return;
394+
395+
setIsOnloading();
396+
new Thread(() -> {
397+
try {
398+
String jsonContent = Files.readString(file.toPath());
399+
400+
if (StringUtils.isBlank(jsonContent)) {
401+
throw new RuntimeException("Selected file is empty");
402+
}
403+
404+
// Parse
405+
jsonRoot = Json.mapper().readTree(jsonContent);
406+
jsonModal = Json.mapper().readValue(jsonContent, SwaggerModal.class);
407+
408+
if (StringUtils.isAllBlank(jsonModal.getSwagger(), jsonModal.getOpenapi())) {
409+
throw new RuntimeException("File content is not a recognized Swagger/OpenAPI document");
410+
}
411+
412+
// Base URL target is unknown for local files; leave empty so user can edit full URL later
413+
urlTarget = "";
414+
415+
// Build a new root
416+
TreeItem<String> newRoot = new TreeItem<>("base root");
417+
418+
if (!StringUtils.isBlank(jsonModal.getSwagger())) { // Swagger 2.0 JSON
419+
jsonModal.getTags().forEach(tag1 -> {
420+
TreeItem<String> tag = new TreeItem<>();
421+
tag.setValue(tag1.getName());
422+
jsonModal.getPaths().forEach((path1, pathItem) -> {
423+
if (path1.contains(tag1.getName())) {
424+
TreeItem<String> path = new TreeItem<>();
425+
path.setValue(path1);
426+
tag.getChildren().add(path);
427+
returnTreeItemsForTheMethod(pathItem, path.getChildren(), path1);
428+
}
429+
});
430+
newRoot.getChildren().add(tag);
431+
});
432+
} else { // OpenAPI 3+
433+
jsonModal.getPaths().forEach((path, pathItem) -> {
434+
String[] pathParts = (!path.startsWith("/")) ?
435+
path.split("/") :
436+
path.substring(1).split("/");
437+
TreeItem<String> currentItem = newRoot;
438+
439+
for (String part : pathParts) {
440+
Optional<TreeItem<String>> existingItem = currentItem.getChildren().stream()
441+
.filter(item -> part.equals(item.getValue()))
442+
.findFirst();
443+
if (existingItem.isPresent()) {
444+
currentItem = existingItem.get();
445+
} else {
446+
TreeItem<String> newItem = new TreeItem<>(part);
447+
currentItem.getChildren().add(newItem);
448+
currentItem = newItem;
449+
}
450+
}
451+
452+
TreeItem<String> finalCurrentItem = currentItem;
453+
pathItem.readOperationsMap().forEach((method, operation) -> {
454+
TreeItemOperationLeaf operationLeaf = TreeItemOperationLeaf.builder()
455+
.uri(urlTarget + path)
456+
.methodParameters(operation.getParameters())
457+
.build();
458+
operationLeaf.setValue(method.name());
459+
finalCurrentItem.getChildren().add(operationLeaf);
460+
});
461+
});
462+
}
463+
464+
Platform.runLater(() -> {
465+
treeFilter = new TreeFilter();
466+
txtFilterTree.setText("");
467+
treeItemRoot = newRoot;
468+
treePaths.setRoot(treeItemRoot);
469+
treePaths.setShowRoot(false);
470+
});
471+
} catch (Exception e) {
472+
Platform.runLater(() -> {
473+
log.error("Error opening Swagger file", e);
474+
showAlert("Error", "Failed to open Swagger file", e.getMessage());
475+
});
476+
} finally {
477+
Platform.runLater(this::setIsOffloading);
478+
}
479+
}).start();
480+
}
481+
381482
// Test helper: open swagger URL without UI dialog
382483
public void openSwaggerForTest(String urlSwaggerJson) {
383484
setIsOnloading();

src/main/java/io/github/ozkanpakdil/swaggerific/ui/MenuController.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ public void menuFileOpenSwagger(ActionEvent event) {
1111
mainController.menuFileOpenSwagger(event);
1212
}
1313

14+
public void menuFileOpenLocal(ActionEvent event) {
15+
mainController.menuFileOpenLocal(event);
16+
}
17+
1418
public void openDebugConsole() {
1519
mainController.flipDebugConsole();
1620
}

src/main/resources/META-INF/native-image/reflect-config.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,6 +1316,10 @@
13161316
"queryAllPublicConstructors":true,
13171317
"methods":[{"name":"<init>","parameterTypes":["javafx.scene.input.KeyCode","javafx.scene.input.KeyCombination$ModifierValue","javafx.scene.input.KeyCombination$ModifierValue","javafx.scene.input.KeyCombination$ModifierValue","javafx.scene.input.KeyCombination$ModifierValue","javafx.scene.input.KeyCombination$ModifierValue"] }]
13181318
},
1319+
{
1320+
"name":"javafx.scene.input.KeyCombination",
1321+
"methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }]
1322+
},
13191323
{
13201324
"name":"javafx.scene.input.KeyCombination$ModifierValue",
13211325
"methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }]

src/main/resources/META-INF/native-image/resource-config.json

Lines changed: 1201 additions & 1 deletion
Large diffs are not rendered by default.

src/main/resources/io/github/ozkanpakdil/swaggerific/menu-bar.fxml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@
55
xmlns:fx="http://javafx.com/fxml/1"
66
fx:controller="io.github.ozkanpakdil.swaggerific.ui.MenuController">
77
<Menu text="_File">
8-
<MenuItem onAction="#menuFileOpenSwagger" text="Open Swagger JSON URL">
9-
<accelerator>
10-
<KeyCodeCombination alt="UP" code="O" control="DOWN" meta="UP" shift="UP" shortcut="UP"/>
11-
</accelerator>
12-
</MenuItem>
13-
<MenuItem text="Open"/>
8+
<!-- Open local file (JSON/YAML) -->
9+
<MenuItem text="Open" onAction="#menuFileOpenLocal" accelerator="Shortcut+L"/>
10+
<!-- Open Swagger/OpenAPI from URL -->
11+
<MenuItem onAction="#menuFileOpenSwagger" text="Open Swagger JSON URL" accelerator="Shortcut+O"/>
1412
<MenuItem text="Save"/>
1513
<MenuItem text="Save As"/>
1614
<MenuItem text="Enable Debug Window" onAction="#openDebugConsole">

0 commit comments

Comments
 (0)