Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
115 commits
Select commit Hold shift + click to select a range
6d79fc1
Auto size popup button.
dkocher Sep 15, 2025
69f4bcc
Add annotation.
dkocher Sep 15, 2025
c901f77
Increase padding.
dkocher Sep 15, 2025
372240e
Increase height and add padding in bottom bar.
dkocher Sep 15, 2025
27d071b
Review view layout.
dkocher Sep 15, 2025
737abf6
Use system symbols.
dkocher Sep 15, 2025
1ffd871
Remove fill in symbols.
dkocher Sep 15, 2025
ea368c5
Changes.
dkocher Sep 16, 2025
9091f13
Switch to constraint layout.
dkocher Sep 23, 2025
42abc5c
Use system icons.
dkocher Sep 30, 2025
1633536
Add system icons for menu items.
dkocher Sep 30, 2025
92ef2db
Add implementation to run alerts as popover.
dkocher Oct 5, 2025
ffafa39
Remove URL field.
dkocher Oct 5, 2025
9212849
Use system images.
dkocher Oct 23, 2025
44656c3
Remove custom disclosable view implementation.
dkocher Oct 24, 2025
f756d3b
Switch to constraint layout. Use popover for file details.
dkocher Oct 25, 2025
b57ebe4
Use system image.
dkocher Oct 26, 2025
5909c84
Allow custom positioning rect.
dkocher Oct 26, 2025
449e12e
Auto resize window from constraints.
dkocher Oct 26, 2025
cf1375d
Rename field.
dkocher Oct 26, 2025
5e63a65
Remove toggle.
dkocher Oct 26, 2025
1329295
Remove comment field.
dkocher Oct 26, 2025
cec4ee1
Add keyword.
dkocher Oct 26, 2025
efe6f67
Display bookmark window as popover.
dkocher Oct 26, 2025
1a889e7
Replace with lambda.
dkocher Oct 27, 2025
a7b52fa
Add flag for popover or floating window display.
dkocher Oct 27, 2025
b5fdde3
Switch to constraint layout.
dkocher Oct 27, 2025
a753f33
Hide controls when configuration option not available.
dkocher Oct 27, 2025
980edfb
Move field up.
dkocher Oct 27, 2025
21d3383
Change to local scope.
dkocher Oct 27, 2025
ef17913
Move field up.
dkocher Oct 27, 2025
ac7fb57
Use regular bookmark panel.
dkocher Oct 27, 2025
092ac7d
Localize.
dkocher Oct 27, 2025
9887c8d
Add images for local and server URL.
dkocher Oct 27, 2025
3342561
Move to upper class.
dkocher Oct 28, 2025
ed5387d
Add setter for translating auto resize mask to constraints.
dkocher Oct 29, 2025
331afed
Bookmark editing frame with content view loaded separately.
dkocher Oct 30, 2025
285d0a5
New connection editing frame with content view loaded separately.
dkocher Oct 30, 2025
63ae75d
Allow custom behaviour.
dkocher Oct 30, 2025
954f573
Synchronize access.
dkocher Oct 30, 2025
b6f380b
Move out of window.
dkocher Oct 30, 2025
0c74d27
Remove non-generic controls.
dkocher Oct 31, 2025
7ed96fb
Add options.
dkocher Oct 31, 2025
7b3555a
Default to utility panel.
dkocher Oct 31, 2025
66946f0
Reuse content view to edit bookmark.
dkocher Oct 31, 2025
d8b4727
Implement tabs.
dkocher Oct 31, 2025
db465db
Resize on tab selection change.
dkocher Oct 31, 2025
be1a97d
Rename class.
dkocher Nov 1, 2025
8e8ce5c
Rename outlets.
dkocher Nov 1, 2025
2b2c1e3
Remove custom class in file owner
dkocher Nov 2, 2025
e7ac4cd
Remove custom class in file owner
dkocher Nov 2, 2025
f432f9b
Remove custom class in file owner
dkocher Nov 2, 2025
15b5569
Refactor using inheritance loading both container and content XIB int…
dkocher Nov 2, 2025
fea54f7
Set window title from bookmark.
dkocher Nov 2, 2025
3968872
Make controls regular sized.
dkocher Nov 2, 2025
451fd23
Transparent title bar.
dkocher Nov 2, 2025
408b604
Add "Connect" and "Disconnect" menu items to "Go" menu.
dkocher Nov 3, 2025
a980eb9
Add "Connect" and "Disconnect" menu items to context menu.
dkocher Nov 3, 2025
d5a3080
Updated constraints.
dkocher Nov 3, 2025
b5c0249
Move to upper class.
dkocher Nov 4, 2025
e8776e2
Set ascent colour.
dkocher Nov 4, 2025
be627f6
Javadoc.
dkocher Nov 4, 2025
e0e0243
Do not set application name in window title.
dkocher Nov 4, 2025
c6e4bb4
Extract navigation controller.
dkocher Nov 4, 2025
2672796
Allow annotating methods.
dkocher Nov 4, 2025
3e75575
Extract status controller.
dkocher Nov 4, 2025
d0f41dd
Add type.
dkocher Nov 4, 2025
9f4ee7c
Skip manually setting first responder.
dkocher Nov 4, 2025
2632ceb
Always reload after setting filter.
dkocher Nov 4, 2025
43b1baa
Recalculate key loop after toggling controls.
dkocher Nov 4, 2025
7e55af7
Add NSWindowStyleMask constants.
dkocher Nov 5, 2025
bd184d2
Remove unnecessary variable.
dkocher Nov 5, 2025
6949ae6
Set window title and subtitle depending on selected tab.
dkocher Nov 5, 2025
aae5d10
Formatting.
dkocher Nov 5, 2025
42b60ae
Javadoc.
dkocher Nov 5, 2025
6f9305d
Remove instance variable.
dkocher Nov 5, 2025
783fbfa
Remove custom configuration.
dkocher Nov 5, 2025
abd9b55
Formatting.
dkocher Nov 5, 2025
29f34ad
Explicitly set transparent titlebar.
dkocher Nov 5, 2025
021bc0e
Add observer in constructor to notify collection.
dkocher Nov 6, 2025
6a41c9d
Always create new controller when displayed in popover.
dkocher Nov 6, 2025
2a915da
Revert "Default to utility panel."
dkocher Nov 6, 2025
0f5a5d3
Add constraints.
dkocher Nov 6, 2025
3a40524
Auto configure on username change.
dkocher Nov 6, 2025
a5a2fe7
Use intrinsic size to fix proper resize of popover.
dkocher Nov 6, 2025
fff330c
Switch to icon only default mode for toolbar.
dkocher Nov 6, 2025
dc7069e
Workaround for #17557.
dkocher Nov 6, 2025
88dd386
Javadoc.
dkocher Nov 7, 2025
f08ff7e
Set window level.
dkocher Nov 7, 2025
239a498
Update recommended settings.
dkocher Nov 7, 2025
552fa3b
Add progress indicator in browser view.
dkocher Nov 7, 2025
ce833c0
Register handler to close self.
dkocher Nov 7, 2025
463ddbd
Add constructor.
dkocher Nov 8, 2025
dc59a96
Formatting.
dkocher Nov 8, 2025
7822e8b
Add annotations.
dkocher Nov 9, 2025
261d000
Change implementation for view based table view.
dkocher Nov 10, 2025
e7ac921
Remove default override.
dkocher Sep 9, 2023
9f28018
Fix implementation of menuForEvent to use outline view delgate.
dkocher Aug 13, 2023
af48b7e
Add NSUserInterfaceItemIdentification protocol.
dkocher Nov 11, 2025
9e58644
Forward double action to delegate.
dkocher Nov 11, 2025
1091635
Redundant override.
dkocher Nov 11, 2025
71d1aaa
Remove unnecessary notification.
dkocher Nov 11, 2025
abfda65
Remove custom click handling.
dkocher Nov 11, 2025
d2ea5bb
Add missing type.
dkocher Nov 11, 2025
335be4e
Add missing type.
dkocher Nov 11, 2025
ff42ea0
Set prior notifying listeners.
dkocher Nov 11, 2025
d0e5ae2
Add mappings for layout.
dkocher Nov 12, 2025
1a0ee3d
Delete unused.
dkocher Nov 12, 2025
e40c52a
Update view to use constraints.
dkocher Nov 12, 2025
ac7926d
Update view to use constraints.
dkocher Nov 12, 2025
07083dc
Add generic type.
dkocher Nov 12, 2025
c99273a
Review outlets.
dkocher Nov 12, 2025
e489ecd
Update view to use constraints.
dkocher Nov 12, 2025
1ff5813
Update view to use constraints.
dkocher Nov 12, 2025
d49a46f
Bump version.
dkocher Nov 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* [Feature] Connect with Multi-Bucket Application Keys that grant access to a specific group of buckets within an
account, including the option to limit access based on a single file prefix (
B2) ([#17139](https://trac.cyberduck.io/ticket/17139))
* [Feature] Support for Liquid Glass (macOS) ([#17459](https://trac.cyberduck.io/ticket/17459))
* [Feature] Connect with connection profile obtaining temporary credentials from AWS Security Token Service (STS) by
assuming role with optional Multi-Factor Authentication (MFA) input (
S3) ([#17437](https://trac.cyberduck.io/ticket/17437))
Expand Down
2 changes: 0 additions & 2 deletions Credits.rtf
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@
\cf3 Synapticloop\
\cf0 {\field{\*\fldinst{HYPERLINK "http://zathras.de/"}}{\fldrslt UKCrashReporter}}\
\cf3 M. Uli Kusterer\
\cf0 {\field{\*\fldinst{HYPERLINK "http://www.snoize.com/"}}{\fldrslt SNDisclosableView}}\
\cf3 Kurt Revis\
\cf0 {\field{\*\fldinst{HYPERLINK "https://opensource.apple.com/tarballs/mDNSResponder/"}}{\fldrslt mDNSResponder}}\
\cf3 Apple Inc.\
\cf0 {\field{\*\fldinst{HYPERLINK "https://sparkle-project.org/"}}{\fldrslt Sparkle}}\
Expand Down
168 changes: 140 additions & 28 deletions Cyberduck.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,17 @@
import ch.cyberduck.core.Factory;
import ch.cyberduck.core.FactoryException;

import ch.cyberduck.core.LocaleFactory;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public abstract class BundleController extends ProxyController {
private static final Logger log = LogManager.getLogger(BundleController.class);

protected static final String DEFAULT = LocaleFactory.localizedString("Default");

public static final NSMutableParagraphStyle PARAGRAPH_STYLE_LEFT_ALIGNMENT_TRUNCATE_MIDDLE;
public static final NSMutableParagraphStyle PARAGRAPH_STYLE_LEFT_ALIGNMENT_TRUNCATE_TAIL;
public static final NSMutableParagraphStyle PARAGRAPH_STYLE_RIGHT_ALIGNMENT_TRUNCATE_TAIL;
Expand Down
2 changes: 1 addition & 1 deletion binding/src/main/java/ch/cyberduck/binding/Outlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;

@java.lang.annotation.Target({ElementType.FIELD})
@java.lang.annotation.Target({ElementType.FIELD, ElementType.METHOD})
@java.lang.annotation.Retention(RetentionPolicy.SOURCE)
public @interface Outlet {
}
132 changes: 130 additions & 2 deletions binding/src/main/java/ch/cyberduck/binding/ProxyController.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@

import ch.cyberduck.binding.application.NSAlert;
import ch.cyberduck.binding.application.NSApplication;
import ch.cyberduck.binding.application.NSPopover;
import ch.cyberduck.binding.application.NSView;
import ch.cyberduck.binding.application.NSViewController;
import ch.cyberduck.binding.application.NSWindow;
import ch.cyberduck.binding.application.SheetCallback;
import ch.cyberduck.binding.application.WindowListener;
import ch.cyberduck.binding.foundation.FoundationKitFunctions;
import ch.cyberduck.binding.foundation.NSNotification;
import ch.cyberduck.binding.foundation.NSObject;
import ch.cyberduck.binding.foundation.NSThread;
import ch.cyberduck.core.AbstractController;
import ch.cyberduck.core.threading.DefaultMainAction;
Expand All @@ -28,11 +34,14 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.rococoa.ID;
import org.rococoa.cocoa.foundation.NSRect;
import org.rococoa.cocoa.foundation.NSSize;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

import com.google.common.util.concurrent.Uninterruptibles;

Expand Down Expand Up @@ -153,6 +162,16 @@ public int alert(final SheetController sheet, final AlertRunner runner, final Co
protected static final Set<AlertRunner> alerts
= new HashSet<>();

/**
* @param sheet Controller for alert window
* @param callback Handler invoked after sheet is dismissed with selected option
* @param runner Implementation to display alert window
* @return Selected alert option by user
*/
public int alert(final SheetController sheet, final SheetCallback callback, final AlertRunner runner) {
return this.alert(sheet, callback, runner, new CountDownLatch(1));
}

/**
* Display as sheet attached to window of parent controller
*
Expand All @@ -164,7 +183,9 @@ public int alert(final SheetController sheet, final AlertRunner runner, final Co
*/
public int alert(final SheetController sheet, final SheetCallback callback, final AlertRunner runner, final CountDownLatch signal) {
log.debug("Alert with runner {} and callback {}", runner, callback);
alerts.add(runner);
synchronized(alerts) {
alerts.add(runner);
}
final AtomicInteger option = new AtomicInteger(SheetCallback.CANCEL_OPTION);
final CountDownLatch state = new CountDownLatch(1);
final SheetCallback.DelegatingSheetCallback chain = new SheetCallback.DelegatingSheetCallback(new SheetCallback.ReturnCodeSheetCallback(option), sheet, callback);
Expand All @@ -174,7 +195,11 @@ public void run() {
log.info("Load bundle for alert {}", sheet);
sheet.loadBundle();
runner.alert(sheet.window(), new SheetCallback.DelegatingSheetCallback(new SignalSheetCallback(state),
chain, new SignalSheetCallback(signal), (returncode) -> alerts.remove(runner)));
chain, new SignalSheetCallback(signal), (returncode) -> {
synchronized(alerts) {
alerts.remove(runner);
}
}));
}
}, true);
if(!NSThread.isMainThread()) {
Expand Down Expand Up @@ -310,4 +335,107 @@ public void callback(final int returncode) {
signal.countDown();
}
}

public static final class PopoverAlertRunner extends Proxy implements AlertRunner, AlertRunner.CloseHandler, WindowListener {
private final NSPopover popover = NSPopover.create();
private final NSView positioningView;
private final NSRect positioningRect;
private final SheetController controller;
private final AtomicReference<Proxy> reference = new AtomicReference<>();
private final AtomicInteger option = new AtomicInteger(SheetCallback.CANCEL_OPTION);
private final int behaviour;

public PopoverAlertRunner(final NSView positioningView, final SheetController controller) {
this(positioningView, positioningView.frame(), controller);
}

public PopoverAlertRunner(final NSView positioningView, final SheetController controller, final int behaviour) {
this(positioningView, positioningView.frame(), controller, behaviour);
}

public PopoverAlertRunner(final NSView positioningView, final NSRect positioningRect, final SheetController controller) {
this(positioningView, positioningRect, controller, NSPopover.NSPopoverBehaviorSemitransient);
}

public PopoverAlertRunner(final NSView positioningView, final NSRect positioningRect, final SheetController controller, final int behaviour) {
this.positioningView = positioningView;
this.positioningRect = positioningRect;
this.controller = controller;
this.controller.addHandler(this);
this.behaviour = behaviour;
}

@Override
public void alert(final NSWindow sheet, final SheetCallback callback) {
NSApplication.sharedApplication().activateIgnoringOtherApps(true);
final Proxy proxy = new PopoverDelegate(controller, option, callback);
reference.set(proxy);
popover.setDelegate(proxy.id());
popover.setAnimates(false);
popover.setBehavior(behaviour);
final NSViewController viewController = NSViewController.create();
viewController.setView(sheet.contentView());
popover.setContentViewController(viewController);
popover.showRelativeToRect_ofView_preferredEdge(positioningRect, positioningView,
FoundationKitFunctions.NSRectEdge.NSMinYEdge);
controller.addListener(this);
}

@Override
public void windowDidResize(final NSSize windowFrame) {
log.debug("Resize popover to {}", windowFrame);
popover.setContentSize(controller.view().intrinsicContentSize());
}

@Override
public void closed(final NSWindow sheet, final int returncode) {
option.set(returncode);
popover.performClose(null);
}
}

public static final class PopoverDelegate extends Proxy {
private final SheetController controller;
private final AtomicInteger returncode;
private final SheetCallback callback;

public PopoverDelegate(final SheetController controller, final AtomicInteger returncode, final SheetCallback callback) {
this.controller = controller;
this.returncode = returncode;
this.callback = callback;
}

@Delegate
public void popoverWillClose(final NSNotification notification) {
final NSObject popoverCloseReasonValue = notification.userInfo().objectForKey(NSPopover.NSPopoverCloseReasonKey);
if(popoverCloseReasonValue != null) {
if(NSPopover.NSPopoverCloseReasonValue.NSPopoverCloseReasonStandard.equals(popoverCloseReasonValue.toString())) {
log.debug("Notify {} of return code {}", callback, returncode.get());
// No window close notification for popover
controller.invalidate();
callback.callback(returncode.get());
}
else {
log.debug("Ignore notification {}", notification);
}
}
}

@Delegate
public boolean popoverShouldDetach(final NSPopover popover) {
return true;
}
}

/**
* Adjust frame of subview to match the parent view and attach with translating autoresizing mask into constraints
*
* @param parent Container View
* @param subview Content View
*/
protected void addSubview(final NSView parent, final NSView subview) {
subview.setTranslatesAutoresizingMaskIntoConstraints(true);
subview.setFrame(parent.bounds());
parent.addSubview(subview);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@
public abstract class WindowController extends BundleController implements NSWindow.Delegate {
private static final Logger log = LogManager.getLogger(WindowController.class);

protected static final String DEFAULT = LocaleFactory.localizedString("Default");

protected final Set<WindowListener> listeners
= Collections.synchronizedSet(new HashSet<>());
/**
Expand All @@ -57,11 +55,6 @@ public abstract class WindowController extends BundleController implements NSWin
@Outlet
protected NSWindow window;

/**
* Main content view of window
*/
protected NSView view;

public WindowController() {
super();
}
Expand Down Expand Up @@ -91,10 +84,12 @@ public void removeListener(final WindowListener listener) {

public void setWindow(final NSWindow window) {
this.window = window;
this.view = window.contentView();
this.window.recalculateKeyViewLoop();
this.window.setReleasedWhenClosed(true);
this.window.setDelegate(this.id());
this.window.setLevel(NSWindow.NSWindowLevel.NSNormalWindowLevel);
this.window.setCollectionBehavior(window.collectionBehavior()
| NSWindow.NSWindowCollectionBehavior.NSWindowCollectionBehaviorTransient);
}

public NSWindow window() {
Expand All @@ -103,7 +98,7 @@ public NSWindow window() {

@Override
public NSView view() {
return view;
return window.contentView();
}

/**
Expand Down Expand Up @@ -252,14 +247,14 @@ protected double getMinWindowWidth() {

protected double toolbarHeightForWindow() {
final NSRect windowFrame = NSWindow.contentRectForFrameRect_styleMask(window.frame(), window.styleMask());
return windowFrame.size.height.doubleValue() - view.frame().size.height.doubleValue();
return windowFrame.size.height.doubleValue() - window.contentView().frame().size.height.doubleValue();
}

/**
* @return Minimum size to fit content view of currently selected tab.
*/
protected NSRect getContentRect() {
return view.frame();
return window.contentView().frame();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@
import ch.cyberduck.binding.foundation.NSURL;

import org.rococoa.ID;
import org.rococoa.Selector;
import org.rococoa.cocoa.CGFloat;
import org.rococoa.cocoa.foundation.NSInteger;
import org.rococoa.cocoa.foundation.NSPoint;
import org.rococoa.cocoa.foundation.NSRect;
import org.rococoa.cocoa.foundation.NSUInteger;

/// <i>native declaration : :69</i>
Expand Down Expand Up @@ -260,6 +262,20 @@ public interface Delegate {
*/
public abstract CGFloat rowHeight();

/**
*
* @param enable A Boolean value that indicates whether the table view uses autolayout to calculate the height of rows.
* @since macOS 10.13+
*/
public abstract void setUsesAutomaticRowHeights(boolean enable);

/**
*
* @return A Boolean value that indicates whether the table view uses autolayout to calculate the height of rows.
* @since macOS 10.13+
*/
public abstract boolean usesAutomaticRowHeights();

/**
* If the delegate implements -tableView:heightOfRow:, this method immediately re-tiles the table view using row
* heights it provides.<br> Original signature : <code>void noteHeightOfRowsWithIndexesChanged(NSIndexSet*)</code><br>
Expand Down Expand Up @@ -394,13 +410,13 @@ public interface Delegate {
* Original signature : <code>void setDoubleAction(SEL)</code><br>
* <i>native declaration : :175</i>
*/
public abstract void setDoubleAction(org.rococoa.Selector aSelector);
public abstract void setDoubleAction(Selector aSelector);

/**
* Original signature : <code>SEL doubleAction()</code><br>
* <i>native declaration : :176</i>
*/
public abstract org.rococoa.Selector doubleAction();
public abstract Selector doubleAction();

/**
* Sorting Support<br> The array of sort descriptors is archived. Sort descriptors will persist along with other
Expand Down Expand Up @@ -841,4 +857,14 @@ public void editRow(NSInteger column, NSInteger row, boolean select) {
* <i>from NSDeprecated native declaration : :528</i><br>
* Conversion Error : NSRect
*/

/**
* Returns the rectangle containing the row at the specified index.
*
* @param row Table row
* @return The rectangle containing the row at rowIndex. Returns NSZeroRect if rowIndex lies outside the
* range of valid row indexes for the table view.
*/
public abstract NSRect rectOfRow(NSInteger row);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package ch.cyberduck.binding.application;

/*
* Copyright (c) 2002-2025 iterate GmbH. All rights reserved.
* https://cyberduck.io/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/

public interface NSUserInterfaceItemIdentification {

/**
*
* @return A string that identifies the user interface item.
*/
String identifier();

/**
*
* @param identifier A string that identifies the user interface item.
*/
void setIdentifier(String identifier);
}
Loading