Skip to content

Commit ccf4341

Browse files
committed
Merge branch 'dev'
2 parents e61a815 + ddeb616 commit ccf4341

File tree

4 files changed

+129
-60
lines changed

4 files changed

+129
-60
lines changed

seafile/SeafActionsManager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ NS_ASSUME_NONNULL_BEGIN
6565

6666
+ (void)entryAction:(SeafBase *)entry inEncryptedRepo:(BOOL)encrypted inTargetVC:(UIViewController *)targetVC fromView:(UIView *)view actionBlock:(ActionType)block;
6767

68-
+ (void)exportByActivityView:(NSArray <NSURL *> *)urls item:(UIBarButtonItem * _Nullable)barButtonItem targerVC:(UIViewController *)targetVC;
68+
+ (void)exportByActivityView:(NSArray <NSURL *> *)urls item:(id _Nullable)item targerVC:(UIViewController *)targetVC;
6969

7070
@end
7171

seafile/SeafActionsManager.m

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
// Copyright © 2018 Seafile. All rights reserved.
77
//
88

9+
#import <UIKit/UIKit.h>
910
#import "SeafActionsManager.h"
1011
#import "SeafRepos.h"
1112
#import "SeafFile.h"
1213
#import "SeafWechatHelper.h"
1314
#import "SeafActionSheet.h"
1415
#import "Debug.h"
1516
#import "SVProgressHUD.h"
17+
#import "SeafGlobal.h"
1618

1719
@implementation SeafActionsManager
1820

@@ -86,18 +88,27 @@ + (void)directoryAction:(SeafDir*)directory photos:(NSArray *)photos inTargetVC:
8688
[actionSheet showFromView:item];
8789
}
8890

89-
+ (void)exportByActivityView:(NSArray <NSURL *> *)urls item:(UIBarButtonItem *)barButtonItem targerVC:(UIViewController *)targetVC {
91+
+ (void)exportByActivityView:(NSArray <NSURL *> *)urls item:(id)item targerVC:(UIViewController *)targetVC {
9092
UIActivityViewController *controller = [[UIActivityViewController alloc] initWithActivityItems:urls applicationActivities:nil];
9193
controller.completionWithItemsHandler = ^(UIActivityType __nullable activityType, BOOL completed, NSArray * __nullable returnedItems, NSError * __nullable activityError) {
9294
Debug("activityType=%@ completed=%d, returnedItems=%@, activityError=%@", activityType, completed, returnedItems, activityError);
9395
if ([UIActivityTypeSaveToCameraRoll isEqualToString:activityType]) {
9496
[self savedToPhotoAlbumWithError:activityError];
9597
}
9698
};
97-
if (barButtonItem) {
98-
controller.popoverPresentationController.barButtonItem = barButtonItem;
99+
100+
if (IsIpad()) {
101+
UIPopoverPresentationController *popover = controller.popoverPresentationController;
102+
if (targetVC.view.window) {
103+
popover.sourceView = targetVC.view.window;
104+
popover.sourceRect = CGRectMake(CGRectGetMidX(targetVC.view.window.bounds), CGRectGetMidY(targetVC.view.window.bounds), 0, 0);
105+
} else {
106+
popover.sourceView = targetVC.view;
107+
popover.sourceRect = CGRectMake(CGRectGetMidX(targetVC.view.bounds), CGRectGetMidY(targetVC.view.bounds), 0, 0);
108+
}
109+
popover.permittedArrowDirections = 0;
99110
}
100-
111+
101112
[targetVC presentViewController:controller animated:true completion:nil];
102113
}
103114

seafile/SeafCustomInputAlertViewController.m

Lines changed: 68 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ @interface SeafCustomInputAlertViewController () <UITextFieldDelegate>
1717

1818
// For keyboard-aware animation
1919
@property (nonatomic, strong) NSLayoutConstraint *alertViewBottomConstraint;
20+
@property (nonatomic, strong) NSLayoutConstraint *alertViewCenterYConstraint; // Center Y constraint for iPad keyboard adjustments
2021
@property (nonatomic, assign) BOOL isBeingDismissedProgrammatically;
2122
@property (nonatomic, strong) id finalCompletionHandler; // To store either confirm or cancel block
2223

@@ -155,12 +156,15 @@ - (void)viewDidLoad {
155156

156157
if (IsIpad()) {
157158
self.view.backgroundColor = [UIColor clearColor]; // The form sheet content is alertView
158-
self.preferredContentSize = CGSizeMake(450, 240); // Set preferredContentSize BEFORE setupViews/setupConstraints
159+
self.preferredContentSize = CGSizeMake(450, 800); // Increase default height to avoid clipping
159160

160161
[self setupViews]; // alertView needs to be created
161162
[self setupConstraints]; // alertView needs to be constrained
162163
self.alertView.alpha = 1.0; // Visible by default for form sheet
163164
// Estimate height: title(20) + space(20) + field(40) + space(25) + button(44) + padding(30+30) = 209. Let's use 240.
165+
166+
// Register for keyboard notifications so we can move the alert if it would be covered.
167+
[self registerForKeyboardNotifications];
164168
} else {
165169
[self setupViews];
166170
[self setupConstraints]; // Constraints are set up here
@@ -189,15 +193,11 @@ - (void)viewWillAppear:(BOOL)animated {
189193

190194
- (void)viewWillDisappear:(BOOL)animated {
191195
[super viewWillDisappear:animated];
192-
if (!IsIpad()) {
193-
[self unregisterForKeyboardNotifications];
194-
}
196+
[self unregisterForKeyboardNotifications];
195197
}
196198

197199
- (void)dealloc {
198-
if (!IsIpad()) {
199-
[self unregisterForKeyboardNotifications]; // Just in case
200-
}
200+
[self unregisterForKeyboardNotifications]; // Ensure removed for all device types
201201
}
202202

203203
- (void)setupViews {
@@ -222,13 +222,13 @@ - (void)setupViews {
222222
- (void)setupConstraints {
223223
// alertView constraints (leading/trailing for full width, bottom constraint for vertical positioning)
224224
if (IsIpad()) {
225-
// Center alertView and set its size based on preferredContentSize
225+
// Keep a reference to the center-Y constraint so we can move the alert when the keyboard shows up.
226+
self.alertViewCenterYConstraint = [self.alertView.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor];
226227
[NSLayoutConstraint activateConstraints:@[
227228
[self.alertView.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor],
228-
[self.alertView.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor],
229-
[self.alertView.widthAnchor constraintEqualToConstant:self.preferredContentSize.width],
230-
[self.alertView.heightAnchor constraintEqualToConstant:self.preferredContentSize.height]
231-
]];
229+
self.alertViewCenterYConstraint,
230+
[self.alertView.widthAnchor constraintEqualToConstant:self.preferredContentSize.width]
231+
]]; // Do not fix height so it can expand with content
232232
} else {
233233
self.alertViewBottomConstraint = [self.alertView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor constant:kInitialOffScreenBottomConstant];
234234
[NSLayoutConstraint activateConstraints:@[ // Full width, bottom constraint set above for iPhone
@@ -292,55 +292,70 @@ - (void)unregisterForKeyboardNotifications {
292292
}
293293

294294
- (void)keyboardWillShow:(NSNotification *)notification {
295-
if (IsIpad()) return; // Only for iPhone
296295
NSDictionary *userInfo = notification.userInfo;
297-
CGRect keyboardFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
296+
CGRect keyboardFrameInScreen = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
297+
CGRect keyboardFrame = [self.view convertRect:keyboardFrameInScreen fromView:nil];
298298
NSTimeInterval animationDuration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
299-
UIViewAnimationCurve animationCurve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
300-
301-
self.alertViewBottomConstraint.constant = -keyboardFrame.size.height;
302-
303-
[UIView animateWithDuration:animationDuration
304-
delay:0.0
305-
options:(animationCurve << 16) | UIViewAnimationOptionBeginFromCurrentState
306-
animations:^{
307-
self.alertView.alpha = 1.0;
308-
self.backgroundDimmingView.alpha = 1.0;
309-
[self.view layoutIfNeeded];
310-
} completion:nil];
299+
UIViewAnimationOptions options = (([userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue]) << 16) | UIViewAnimationOptionBeginFromCurrentState;
300+
301+
if (IsIpad()) {
302+
// Move the alert view up by 30% of the keyboard height so it stays visible
303+
CGFloat keyboardHeight = keyboardFrame.size.height;
304+
self.alertViewCenterYConstraint.constant = -keyboardHeight * 0.3; // leave smaller gap
305+
306+
[UIView animateWithDuration:animationDuration delay:0.0 options:options animations:^{
307+
[self.view layoutIfNeeded];
308+
} completion:nil];
309+
} else {
310+
self.alertViewBottomConstraint.constant = -keyboardFrame.size.height;
311+
[UIView animateWithDuration:animationDuration
312+
delay:0.0
313+
options:options
314+
animations:^{
315+
self.alertView.alpha = 1.0;
316+
self.backgroundDimmingView.alpha = 1.0;
317+
[self.view layoutIfNeeded];
318+
} completion:nil];
319+
}
311320
}
312321

313322
- (void)keyboardWillHide:(NSNotification *)notification {
314-
if (IsIpad()) return; // Only for iPhone
315323
NSDictionary *userInfo = notification.userInfo;
316324
NSTimeInterval animationDuration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
317-
UIViewAnimationCurve animationCurve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
318-
319-
self.alertViewBottomConstraint.constant = kInitialOffScreenBottomConstant;
320-
321-
[UIView animateWithDuration:animationDuration
322-
delay:0.0
323-
options:(animationCurve << 16) | UIViewAnimationOptionBeginFromCurrentState
324-
animations:^{
325-
self.alertView.alpha = 0.0;
326-
self.backgroundDimmingView.alpha = 0.0;
327-
[self.view layoutIfNeeded];
328-
} completion:^(BOOL finished) {
329-
if (self.isBeingDismissedProgrammatically) {
330-
[self dismissViewControllerAnimated:NO completion:^{
331-
if (self.finalCompletionHandler) {
332-
// Check which handler it is (void vs void(^)(NSString*))
333-
if (self.cancelHandler == self.finalCompletionHandler && [self.finalCompletionHandler respondsToSelector:@selector(description)]) { // crude check for block type
334-
((void(^)(void))self.finalCompletionHandler)();
335-
} else if (self.completionHandler == self.finalCompletionHandler && [self.finalCompletionHandler respondsToSelector:@selector(description)]) {
336-
((void(^)(NSString *))self.finalCompletionHandler)(self.inputTextField.text);
325+
UIViewAnimationOptions options = (([userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue]) << 16) | UIViewAnimationOptionBeginFromCurrentState;
326+
327+
if (IsIpad()) {
328+
self.alertViewCenterYConstraint.constant = 0; // Reset back to center
329+
[UIView animateWithDuration:animationDuration delay:0.0 options:options animations:^{
330+
[self.view layoutIfNeeded];
331+
} completion:nil];
332+
} else {
333+
self.alertViewBottomConstraint.constant = kInitialOffScreenBottomConstant;
334+
335+
[UIView animateWithDuration:animationDuration
336+
delay:0.0
337+
options:options
338+
animations:^{
339+
self.alertView.alpha = 0.0;
340+
self.backgroundDimmingView.alpha = 0.0;
341+
[self.view layoutIfNeeded];
342+
} completion:^(BOOL finished) {
343+
if (self.isBeingDismissedProgrammatically) {
344+
[self dismissViewControllerAnimated:NO completion:^{
345+
if (self.finalCompletionHandler) {
346+
// Determine which handler to call
347+
if (self.cancelHandler == self.finalCompletionHandler) {
348+
((void(^)(void))self.finalCompletionHandler)();
349+
} else if (self.completionHandler == self.finalCompletionHandler) {
350+
((void(^)(NSString *))self.finalCompletionHandler)(self.inputTextField.text);
351+
}
337352
}
338-
}
339-
self.isBeingDismissedProgrammatically = NO;
340-
self.finalCompletionHandler = nil;
341-
}];
342-
}
343-
}];
353+
self.isBeingDismissedProgrammatically = NO;
354+
self.finalCompletionHandler = nil;
355+
}];
356+
}
357+
}];
358+
}
344359
}
345360

346361
#pragma mark - Actions

seafile/SeafDetailViewController.m

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,9 @@ - (void)viewWillLayoutSubviews
477477
toolbarHeight + safeAreaBottom); // Include safe area in height
478478
self.toolbarView.frame = toolbarFrame;
479479

480+
// Recalculate buttons layout for new width
481+
[self layoutToolbarButtons];
482+
480483
// Ensure toolbar always stays on top layer
481484
[self.view bringSubviewToFront:self.toolbarView];
482485
}
@@ -1088,8 +1091,9 @@ - (void)setupToolbar {
10881091
// Set icon to gray
10891092
UIImage *grayImage = [self imageWithTintColor:[UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0] image:resizedImage];
10901093
[btn setImage:grayImage forState:UIControlStateNormal];
1091-
// Slightly adjust icon position in button
1092-
btn.imageEdgeInsets = UIEdgeInsetsMake(3.0, 0, -3.0, 0); // Adjust margins to fit smaller height
1094+
// Vertically center icon inside the button
1095+
CGFloat verticalOffset = (toolbarH - iconSize)/2.0;
1096+
btn.imageEdgeInsets = UIEdgeInsetsMake(verticalOffset, 0, verticalOffset, 0);
10931097
}
10941098

10951099
// Set button label and event
@@ -1098,6 +1102,9 @@ - (void)setupToolbar {
10981102
[self.toolbarView addSubview:btn];
10991103
}
11001104

1105+
// Initial layout calculation
1106+
[self layoutToolbarButtons];
1107+
11011108
// Ensure toolbar stays on top layer
11021109
[self.view bringSubviewToFront:self.toolbarView];
11031110
}
@@ -1177,12 +1184,48 @@ - (void)updateToolbarButtons {
11771184
}
11781185

11791186
[btn setImage:finalImage forState:UIControlStateNormal];
1187+
// Vertically center icon again in case of state change
1188+
CGFloat toolbarH = 36.0f;
1189+
CGFloat verticalOffset = (toolbarH - iconSize)/2.0f;
1190+
btn.imageEdgeInsets = UIEdgeInsetsMake(verticalOffset, 0, verticalOffset, 0);
11801191
}
11811192
}
11821193
}
11831194
}
11841195
}
11851196

1197+
// New helper method: layout toolbar buttons to fit current width
1198+
- (void)layoutToolbarButtons {
1199+
if (!self.toolbarView) return;
1200+
// Determine the design height we used when creating buttons
1201+
CGFloat toolbarHeight = 36.0f; // Must be in sync with setupToolbar
1202+
1203+
// Safe-area bottom is already included in toolbarView height, but the buttons themselves
1204+
// should stay in the top part (outside the safe-area region).
1205+
// Therefore, keep button height equal to toolbarHeight, starting at y = 0.
1206+
NSUInteger buttonCount = 0;
1207+
for (UIView *v in self.toolbarView.subviews) {
1208+
if ([v isKindOfClass:[UIButton class]]) buttonCount += 1;
1209+
}
1210+
if (buttonCount == 0) return;
1211+
1212+
CGFloat totalWidth = self.toolbarView.bounds.size.width;
1213+
CGFloat itemWidth = totalWidth / buttonCount;
1214+
1215+
// Re-position each button according to its tag order (tags were assigned 0,1,2 when created).
1216+
for (UIView *v in self.toolbarView.subviews) {
1217+
if (![v isKindOfClass:[UIButton class]]) continue;
1218+
UIButton *btn = (UIButton *)v;
1219+
NSInteger index = btn.tag; // 0,1,2
1220+
CGRect frame = CGRectMake(index * itemWidth, 0, itemWidth, toolbarHeight);
1221+
btn.frame = frame;
1222+
// Ensure icon remains vertically centered after layout change
1223+
CGFloat iconSize = 20.0f;
1224+
CGFloat verticalOffset = (toolbarHeight - iconSize)/2.0f;
1225+
btn.imageEdgeInsets = UIEdgeInsetsMake(verticalOffset, 0, verticalOffset, 0);
1226+
}
1227+
}
1228+
11861229
// Set the preview item and refresh the view.
11871230
- (void)setPreViewItem:(id<SeafPreView>)item master:(UIViewController<SeafDentryDelegate> *)c
11881231
{

0 commit comments

Comments
 (0)