Skip to content

Feature. Quick View: Show history of file #573

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 53 additions & 69 deletions GitUp/Application/Document.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
#import "AuthenticationWindowController.h"

#import <GitUpKit/GitUpKit.h>
// Move to GitUpKit?
#import "QuickViewModel.h"

#import <GitUpKit/XLFacilityMacros.h>

#define kWindowModeString_Map @"map"
Expand Down Expand Up @@ -59,7 +62,20 @@ typedef NS_ENUM(NSInteger, NavigationAction) {
kNavigationAction_Previous
};

@interface Document () <NSToolbarDelegate, NSTextFieldDelegate, GCLiveRepositoryDelegate, GIWindowControllerDelegate, GIMapViewControllerDelegate, GISnapshotListViewControllerDelegate, GIUnifiedReflogViewControllerDelegate, GICommitListViewControllerDelegate, GICommitRewriterViewControllerDelegate, GICommitSplitterViewControllerDelegate, GIConflictResolverViewControllerDelegate>
@interface Document () <
NSToolbarDelegate,
NSTextFieldDelegate,
GCLiveRepositoryDelegate,
GIWindowControllerDelegate,
GIMapViewControllerDelegate,
GISnapshotListViewControllerDelegate,
GIUnifiedReflogViewControllerDelegate,
GICommitListViewControllerDelegate,
GICommitRewriterViewControllerDelegate,
GICommitSplitterViewControllerDelegate,
GIConflictResolverViewControllerDelegate,
GIQuickViewControllerDelegate
>
@property(nonatomic, strong) AuthenticationWindowController* authenticationWindowController;
@property(nonatomic) IBOutlet GICustomToolbarItem* navigateItem;
@property(nonatomic) IBOutlet GICustomToolbarItem* titleItem;
Expand Down Expand Up @@ -108,7 +124,7 @@ @implementation Document {
GIUnifiedReflogViewController* _unifiedReflogViewController;
GICommitListViewController* _searchResultsViewController;
GICommitListViewController* _ancestorsViewController;
GIQuickViewController* _quickViewController;
GIQuickViewControllerWithCommitsList* _quickViewController;
GIDiffViewController* _diffViewController;
GICommitRewriterViewController* _commitRewriterViewController;
GICommitSplitterViewController* _commitSplitterViewController;
Expand All @@ -121,10 +137,7 @@ @implementation Document {
NSDateFormatter* _dateFormatter;
CALayer* _fixedSnapshotLayer;
CALayer* _animatingSnapshotLayer;
NSMutableArray* _quickViewCommits;
GCHistoryWalker* _quickViewAncestors;
GCHistoryWalker* _quickViewDescendants;
NSUInteger _quickViewIndex;
QuickViewModel* _quickViewModel;
BOOL _searchReady;
BOOL _preventSelectionLoopback;
NSResponder* _savedFirstResponder;
Expand Down Expand Up @@ -360,7 +373,9 @@ - (void)windowControllerDidLoadNib:(NSWindowController*)windowController {
_searchResultsViewController.emptyLabel = NSLocalizedString(@"No Results", nil);
[_searchControllerView replaceWithView:_searchResultsViewController.view];

_quickViewController = [[GIQuickViewController alloc] initWithRepository:_repository];
_quickViewModel = [[QuickViewModel alloc] initWithRepository:_repository];
_quickViewController = [[GIQuickViewControllerWithCommitsList alloc] initWithRepository:_repository];
_quickViewController.delegate = self;
NSTabViewItem* quickItem = [_mainTabView tabViewItemAtIndex:[_mainTabView indexOfTabViewItemWithIdentifier:kWindowModeString_Map_QuickView]];
quickItem.view = _quickViewController.view;

Expand Down Expand Up @@ -929,90 +944,47 @@ - (void)_hideHelp:(BOOL)open {

#pragma mark - QuickView

- (void)_loadMoreAncestors {
if (![_quickViewAncestors iterateWithCommitBlock:^(GCHistoryCommit* commit, BOOL* stop) {
[_quickViewCommits addObject:commit];
}]) {
_quickViewAncestors = nil;
}
}

- (void)_loadMoreDescendants {
if (![_quickViewDescendants iterateWithCommitBlock:^(GCHistoryCommit* commit, BOOL* stop) {
[_quickViewCommits insertObject:commit atIndex:0];
_quickViewIndex += 1; // We insert commits before the index too!
}]) {
_quickViewDescendants = nil;
}
}

- (void)_enterQuickViewWithHistoryCommit:(GCHistoryCommit*)commit commitList:(NSArray*)commitList {
[_repository suspendHistoryUpdates]; // We don't want the the history to change while in QuickView because of the walkers

_quickViewCommits = [[NSMutableArray alloc] init];
if (commitList) {
[_quickViewCommits addObjectsFromArray:commitList];
_quickViewIndex = [_quickViewCommits indexOfObjectIdenticalTo:commit];
XLOG_DEBUG_CHECK(_quickViewIndex != NSNotFound);
} else {
[_quickViewCommits addObject:commit];
_quickViewIndex = 0;
_quickViewAncestors = [_repository.history walkerForAncestorsOfCommits:@[ commit ]];
[self _loadMoreAncestors];
_quickViewDescendants = [_repository.history walkerForDescendantsOfCommits:@[ commit ]];
[self _loadMoreDescendants];
}

_quickViewController.commit = commit;

[self _setWindowMode:kWindowModeString_Map_QuickView];
__weak typeof(self) weakSelf = self;
[_quickViewModel enterWithHistoryCommit:commit commitList:commitList onResult:^(GCHistoryCommit * _Nonnull theCommit, NSArray * _Nullable theList) {
_quickViewController.commit = commit;
_quickViewController.list = commitList;
[weakSelf _updateToolBar];
[weakSelf _setWindowMode:kWindowModeString_Map_QuickView];
}];
}

- (BOOL)_hasPreviousQuickView {
return (_quickViewIndex + 1 < _quickViewCommits.count);
return _quickViewModel.hasPrevious;
}

- (void)_previousQuickView {
_quickViewIndex += 1;
GCHistoryCommit* commit = _quickViewCommits[_quickViewIndex];
- (void)_selectQuickViewCommit:(GCHistoryCommit *)commit {
_quickViewController.commit = commit;
if (_searchView.superview) {
_searchResultsViewController.selectedCommit = commit;
} else {
[_mapViewController selectCommit:commit];
}
if (_quickViewIndex == _quickViewCommits.count - 1) {
[self _loadMoreAncestors];
}

[self _updateToolBar];
}

- (void)_previousQuickView {
[_quickViewModel moveBackward];
[self _selectQuickViewCommit:_quickViewModel.currentCommit];
}

- (BOOL)_hasNextQuickView {
return (_quickViewIndex > 0);
return _quickViewModel.hasNext;
}

- (void)_nextQuickView {
_quickViewIndex -= 1;
GCHistoryCommit* commit = _quickViewCommits[_quickViewIndex];
_quickViewController.commit = commit;
if (_searchView.superview) {
_searchResultsViewController.selectedCommit = commit;
} else {
[_mapViewController selectCommit:commit];
}
if (_quickViewIndex == 0) {
[self _loadMoreDescendants];
}
[self _updateToolBar];
[_quickViewModel moveForward];
[self _selectQuickViewCommit:_quickViewModel.currentCommit];
}

- (void)_exitQuickView {
_quickViewCommits = nil;
_quickViewAncestors = nil;
_quickViewDescendants = nil;

[_repository resumeHistoryUpdates];

[_quickViewModel exit];
[self _setWindowMode:kWindowModeString_Map];
}

Expand Down Expand Up @@ -1464,6 +1436,18 @@ - (void)unifiedReflogViewController:(GIUnifiedReflogViewController*)controller d
[self toggleReflog:nil];
}

#pragma mark - GIQuickViewControllerDelegate
- (void)quickViewWantsToShowSelectedCommitsList:(NSArray<GCHistoryCommit *> *)commitsList selectedCommit:(GCHistoryCommit *)commit {
[self _enterQuickViewWithHistoryCommit:commit commitList:commitsList];
}

- (void)quickViewDidSelectCommit:(GCHistoryCommit *)commit commitsList:(NSArray<GCHistoryCommit *> *)commitsList {
// update quickViewModel.
// and toolbar.
_quickViewModel.selectedCommit = commit;
[self _selectQuickViewCommit:_quickViewModel.selectedCommit];
}

#pragma mark - GICommitListViewControllerDelegate

- (void)commitListViewControllerDidChangeSelection:(GICommitListViewController*)controller {
Expand Down
32 changes: 32 additions & 0 deletions GitUp/Application/QuickViewModel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// QuickViewModel.h
// Application
//
// Created by Dmitry Lobanov on 15/09/2019.
//

#import <Foundation/Foundation.h>
@import GitUpKit;

NS_ASSUME_NONNULL_BEGIN

@interface QuickViewModel : NSObject
- (instancetype)initWithRepository:(GCLiveRepository *)repository;

// Checking
@property (assign, nonatomic, readonly) BOOL hasPrevious;
@property (assign, nonatomic, readonly) BOOL hasNext;
@property (assign, nonatomic, readonly) BOOL hasPaging;

// Moving
- (void)moveBackward;
- (void)moveForward;

// States
- (void)enterWithHistoryCommit:(GCHistoryCommit *)commit commitList:(NSArray *)commitList onResult:(void(^)(GCHistoryCommit *, NSArray * _Nullable))result;
- (void)exit;
@property (strong, nonatomic, readonly) GCHistoryCommit *currentCommit;
@property (strong, nonatomic, readwrite) GCHistoryCommit *selectedCommit;
@end

NS_ASSUME_NONNULL_END
151 changes: 151 additions & 0 deletions GitUp/Application/QuickViewModel.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
//
// QuickViewModel.m
// Application
//
// Created by Dmitry Lobanov on 15/09/2019.
//

@import GitUpKit;
#import <GitUpKit/XLFacilityMacros.h>
#import "QuickViewModel.h"

@interface QuickViewModel ()

@property (weak, nonatomic) GCLiveRepository *repository;

@property (assign, nonatomic) NSUInteger index;
@property (strong, nonatomic) NSMutableArray *commits;

@property (strong, nonatomic) GCHistoryWalker *ancestors;
@property (strong, nonatomic) GCHistoryWalker *descendants;

#pragma mark - Protected
- (void)loadMoreAncestors;
- (void)loadMoreDescendants;
@end

@implementation QuickViewModel

#pragma mark - Initialization
- (instancetype)initWithRepository:(GCLiveRepository *)repository {
if ((self = [super init])) {
self.repository = repository;
}
return self;
}

#pragma mark - Loading
- (void)loadMoreAncestors {
if (![_ancestors iterateWithCommitBlock:^(GCHistoryCommit* commit, BOOL* stop) {
[_commits addObject:commit];
}]) {
_ancestors = nil;
}
}

- (void)loadMoreDescendants {
if (![_descendants iterateWithCommitBlock:^(GCHistoryCommit* commit, BOOL* stop) {
[_commits insertObject:commit atIndex:0];
_index += 1; // We insert commits before the index too!
}]) {
_descendants = nil;
}
}

#pragma mark - Checking
- (BOOL)hasPrevious {
return _index + 1 < _commits.count;
}

- (BOOL)hasNext {
return _index > 0;
}

- (BOOL)hasPaging {
return _commits != nil;
}

// TODO: Rename them appropriately.
// Blowing mind.
Comment on lines +68 to +69
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an actual TODO?

Copy link
Contributor Author

@lolgear lolgear Jul 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I added a note about it.

If we move backward, then, we should increase index. (And load Ancestors)
If we move forward, then, we should decrease index. (And load Descendants)

If these statements are logically correct, then, we could keep current API.
Otherwise, we need to rethink it.

// Moving backward means moving to the end of array. ( or back to origin )
// Moving forward means moving to the beginning of array. ( or to recent commits )
// Also, these checks for end of array should be done __after__ increment or decrement of index.
#pragma mark - Moving
- (void)moveBackward {
_index += 1;
if (_index == _commits.count - 1) {
[self loadMoreAncestors];
}
}

- (void)moveForward {
_index -= 1;
if (_index == 0) {
[self loadMoreDescendants];
}
}

#pragma mark - State
- (void)enterWithHistoryCommit:(GCHistoryCommit *)commit commitList:(NSArray *)commitList onResult:(void(^)(GCHistoryCommit *, NSArray * _Nullable))result {

// actually, we need to cleanup state if we reenter this function.
[self exit];

[_repository suspendHistoryUpdates]; // We don't want the the history to change while in QuickView because of the walkers

_commits = [NSMutableArray new];
if (commitList) {
[_commits addObjectsFromArray:commitList];
_index = [_commits indexOfObjectIdenticalTo:commit];
if (result) {
result(commit, commitList);
}
XLOG_DEBUG_CHECK(_index != NSNotFound);
}
else {
[_commits addObject:commit];
_index = 0;
_ancestors = [_repository.history walkerForAncestorsOfCommits:@[ commit ]];
[self loadMoreAncestors];
_descendants = [_repository.history walkerForDescendantsOfCommits:@[ commit ]];
[self loadMoreDescendants];
if (result) {
result(commit, nil);
}
}
}

- (void)cleanup {
_commits = nil;
_ancestors = nil;
_descendants = nil;
}

- (void)exit {
[self cleanup];
// resume history updates for repository.
if ([_repository areHistoryUpdatesSuspended]) {
[_repository resumeHistoryUpdates];
}
}

- (GCHistoryCommit *)currentCommit {
return _commits[_index];
}

- (void)setSelectedCommit:(GCHistoryCommit *)selectedCommit {
NSUInteger index = [_commits indexOfObjectIdenticalTo:selectedCommit];
if (index == NSNotFound) {
// set index to zero.
_index = 0;
}
else {
_index = index;
}
}

- (GCHistoryCommit *)selectedCommit {
return self.currentCommit;
}

@end
Loading