Compare commits

...

5 commits

Author SHA1 Message Date
Stefan Hausotte
3063eabfde chore: release 1.6 2026-06-15 19:06:42 +02:00
Stefan Hausotte
a8ce9d1180 ci: make release recipe sed portable across BSD and GNU sed (#83)
`just release` used `sed -i ''`, which is BSD/macOS syntax. In the nix dev
shell GNU sed shadows it and reads `''` as an empty script and the s/.../
expression as a filename, aborting the version bump. Use `-i.bak` plus a
cleanup `rm`, which works on both BSD and GNU sed.

Reviewed-on: https://codeberg.org/secana/Forji/pulls/83
2026-06-15 19:06:16 +02:00
Stefan Hausotte
e36150a2fc ci: add .envrc 2026-06-15 19:02:59 +02:00
Stefan Hausotte
c5893ff638 fix: clearer login error for security-key (passkey) accounts (#82)
Bump ForgejoKit to 0.8.1, which classifies Forgejo's "Basic authorization
is not allowed while having security keys enrolled" 401 as a dedicated
error instead of "Invalid username or password". Accounts with a passkey
or security key now get told to use a personal access token.

Add the new .basicAuthBlockedBySecurityKey case to the session-restore
error mapping (routed through the auth-category path like other 401s).

Closes #78

Reviewed-on: https://codeberg.org/secana/Forji/pulls/82
2026-06-15 18:49:46 +02:00
Stefan Hausotte
64145f50cc fix: make issue/PR description editable in edit form (#80) (#81)
The description row in DescriptionEditorSection is a Button whose label
renders a MarkdownPreview when a body exists. The preview enables text
selection and tappable links, which intercepted the tap inside the Button
label so the editor sheet never opened. Existing issues (with a body)
could therefore not have their description edited; only the empty 'None'
placeholder was tappable.

Disable hit testing on the preview so the tap falls through to the Button.
This fixes IssueEditView, PullRequestEditView, and the create flows, which
all share DescriptionEditorSection.

Extend IssueMutatingUITests to edit an issue description and verify it
persists, closing the coverage gap (the prior test only edited the title).

Closes #80

Reviewed-on: https://codeberg.org/secana/Forji/pulls/81
2026-06-15 14:20:24 +02:00
8 changed files with 76 additions and 19 deletions

1
.envrc Normal file
View file

@ -0,0 +1 @@
use flake

View file

@ -5,6 +5,30 @@ All notable changes to Forji will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.6] - 2026-06-15
### Added
- Shorten the Pull Requests tab to PRs in repository detail (#59)
- Show the overview filter summary only when filters are active (#60)
- Compact notification rows (#55)
- Display and upload image attachments in issues, PRs, and comments
### Changed
- Add a CHANGELOG.md file
### Fixed
- Refresh the merged notifications list when a push notification is opened (#71)
- Render 3-digit shorthand label colors instead of falling back to gray
- Show graceful empty state when repository has issues turned off
- Show graceful empty state when repository has issues turned off
- De-duplicate involved-scope results across pages in single-instance overviews (#70)
- Show graceful empty state when repository has pull requests turned off (#77)
- Make issue/PR description editable in edit form (#80) (#81)
- Clearer login error for security-key (passkey) accounts (#82)
## [1.5] - 2026-06-04
### Added

View file

@ -438,7 +438,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1.5;
CURRENT_PROJECT_VERSION = 1.6;
DEVELOPMENT_TEAM = RVT2M7QTD4;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
@ -454,7 +454,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.5;
MARKETING_VERSION = 1.6;
PRODUCT_BUNDLE_IDENTIFIER = de.hausotte.Forji;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = YES;
@ -474,7 +474,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1.5;
CURRENT_PROJECT_VERSION = 1.6;
DEVELOPMENT_TEAM = RVT2M7QTD4;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
@ -490,7 +490,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.5;
MARKETING_VERSION = 1.6;
PRODUCT_BUNDLE_IDENTIFIER = de.hausotte.Forji;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = YES;
@ -509,11 +509,11 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1.5;
CURRENT_PROJECT_VERSION = 1.6;
DEVELOPMENT_TEAM = RVT2M7QTD4;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 26.2;
MARKETING_VERSION = 1.5;
MARKETING_VERSION = 1.6;
PRODUCT_BUNDLE_IDENTIFIER = de.hausotte.ForjiTests;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = NO;
@ -532,11 +532,11 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1.5;
CURRENT_PROJECT_VERSION = 1.6;
DEVELOPMENT_TEAM = RVT2M7QTD4;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 26.2;
MARKETING_VERSION = 1.5;
MARKETING_VERSION = 1.6;
PRODUCT_BUNDLE_IDENTIFIER = de.hausotte.ForjiTests;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = NO;
@ -554,10 +554,10 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1.5;
CURRENT_PROJECT_VERSION = 1.6;
DEVELOPMENT_TEAM = RVT2M7QTD4;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.5;
MARKETING_VERSION = 1.6;
PRODUCT_BUNDLE_IDENTIFIER = de.hausotte.ForjiUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = NO;
@ -575,10 +575,10 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1.5;
CURRENT_PROJECT_VERSION = 1.6;
DEVELOPMENT_TEAM = RVT2M7QTD4;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.5;
MARKETING_VERSION = 1.6;
PRODUCT_BUNDLE_IDENTIFIER = de.hausotte.ForjiUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = NO;
@ -639,7 +639,7 @@
repositoryURL = "https://codeberg.org/secana/ForgejoKit.git";
requirement = {
kind = exactVersion;
version = 0.8.0;
version = 0.8.1;
};
};
DEC49F6B2F3D00C700E7DD54 /* XCRemoteSwiftPackageReference "textual" */ = {

View file

@ -6,8 +6,8 @@
"kind" : "remoteSourceControl",
"location" : "https://codeberg.org/secana/ForgejoKit.git",
"state" : {
"revision" : "485c147e7f9762c06f51029de47464fb41abc4af",
"version" : "0.8.0"
"revision" : "7675312f5ca302968e267aad632bec4c76414e06",
"version" : "0.8.1"
}
},
{

View file

@ -269,7 +269,7 @@ enum SessionRestoreError: LocalizedError, Equatable {
.invalidServerResponse
case .invalidURL:
.serverNotFound
case .invalidCredentials, .otpRequired, .serverNotFound, .unknownError:
case .invalidCredentials, .otpRequired, .basicAuthBlockedBySecurityKey, .serverNotFound, .unknownError:
fromHTTPErrorCategory(error.httpErrorCategory, statusCode: error.httpStatusCode)
}
}

View file

@ -21,9 +21,14 @@ struct DescriptionEditorSection: View {
MarkdownPreview(text: text)
.font(.subheadline)
.lineLimit(3)
// The preview renders selectable text and tappable links. Inside a
// Button label those intercept the tap, so the editor sheet never
// opens. Disable hit testing so the tap falls through to the Button.
.allowsHitTesting(false)
}
}
.tint(.primary)
.accessibilityIdentifier("description-edit-button")
.sheet(isPresented: $showingEditor) {
DescriptionEditorSheet(text: $text, title: title, onUploadImage: onUploadImage)
}

View file

@ -67,11 +67,36 @@ final class IssueMutatingUITests: ForgejoUITestBase {
editTitleField.tap(withNumberOfTaps: 3, numberOfTouches: 1)
editTitleField.typeText("Edited issue title")
// Edit the description. Tapping the description row must open the editor
// sheet, the regression from issue #80 was that the selectable markdown
// preview swallowed the tap so the sheet never appeared.
let descriptionButton = app.buttons["description-edit-button"]
XCTAssertTrue(descriptionButton.waitForExistence(timeout: 5))
descriptionButton.tap()
let descriptionEditor = app.textViews["markdown-text-editor"]
XCTAssertTrue(
descriptionEditor.waitForExistence(timeout: 5),
"Tapping the description should open the editor sheet",
)
descriptionEditor.tap()
descriptionEditor.typeText("UITESTDESC ")
app.buttons["Done"].tap()
let saveButton = app.buttons["issue-edit-save"]
XCTAssertTrue(saveButton.waitForExistence(timeout: 5))
saveButton.tap()
XCTAssertTrue(app.staticTexts["Edited issue title"].waitForExistence(timeout: 10))
// The edited description must be persisted and rendered in the detail view.
let editedDescription = app.staticTexts.element(
matching: NSPredicate(format: "label CONTAINS %@", "UITESTDESC"),
)
XCTAssertTrue(
editedDescription.waitForExistence(timeout: 10),
"Edited description should appear in the issue detail",
)
// Close and reopen
expandActionMenu()
let toggleButton = app.buttons["issue-toggle-state"]

View file

@ -65,9 +65,11 @@ release new_version:
PREV=$(grep -m1 'MARKETING_VERSION' {{pbxproj}} | sed 's/.*= *//;s/;.*//')
echo "Releasing $PREV -> $NEW"
# 1. Bump the version in the Xcode project.
sed -i '' "s/MARKETING_VERSION = [^;]*/MARKETING_VERSION = $NEW/" {{pbxproj}}
sed -i '' "s/CURRENT_PROJECT_VERSION = [^;]*/CURRENT_PROJECT_VERSION = $NEW/" {{pbxproj}}
# 1. Bump the version in the Xcode project. Use a backup suffix so the -i
# syntax works on both BSD sed (macOS) and GNU sed (nix dev shell).
sed -i.bak "s/MARKETING_VERSION = [^;]*/MARKETING_VERSION = $NEW/" {{pbxproj}}
sed -i.bak "s/CURRENT_PROJECT_VERSION = [^;]*/CURRENT_PROJECT_VERSION = $NEW/" {{pbxproj}}
rm -f {{pbxproj}}.bak
# 2. Generate the changelog section for the new version from the conventional
# commits since the last tag, prepending it under the header.