Skip to content

Commit

Permalink
# Syncing
Browse files Browse the repository at this point in the history
_Creating, editing, and deleting issue and comments._

## GHStore

Creating, edit and deleting issues and comments are accomplished via two methods:

1. The over-arching `save<Class>` methods will add, edit, or delete, according to the current state of the object passed in as an argument.
2. The `delete<Class>` methods delete canceled new objects, then call through to the appropriate `save<Class>` method if necessary.

## LETalk

* Add a `topic` property to return the current issue’s title, regardless of whether the object is an issue or comment.

## GHManagedObject+LETalk

* Implement `plainTitle` method to return the current title including changes.
* Implement `topic` to return the current issue’s title regardless of whether the current talk is an issue or a comment.
  * The default behavior throws an exception and meant to be overridden by subclasses .

## GHManagedObject

* Move dictionary encoding for GitHub keys out of `dictionaryWithValuesForKeys:` into its own method.

## GHComment

* Expose commentID property
* Override `die` method
* Override `topic` method

## GHIssue

* Override `styledTitle` to experiment with delivering a different title for issue than for comments.
* Override `topic` method

## LETalkListController

* Remove the default accessory to save space.
* Set a custom disclosure accessory in an attempt to save space.

## LETalkViewController

* Reload the list on `viewWillAppear:` to ensure current changes are reflected in the table view.
* Enable the `CreateComment` segue.

## LEWorkViewController

* Implement `save` to send the current issue or comment to the server and pop back to the previous table.
* Save changes to the issue title.
* Toggle save and delete on comments based on whether there is a body.
  * If you want to delete the comment, delete the text, and the save button becomes delete.
  * Deleting comments seems to work.
* Toggle save and delete on issues based on whether there is a title set.
  * If you want to delete the issue, delete the title, and the save button becomes delete.
  * Deleting issues does not seem to work. I don’t know why. (Refs #40)
* Ensure the correct segment is selected when edit mode is toggled.
* Add a topic field for editing the current topic.
* When editing an issue, as opposed to a comment, move the topic from the prompt into the topic field.
  * This doesn’t work well and will probably be refactored away (Refs #31)

## iPhone UI

* Add some word bubbles in the table view cells.
* Give the app a nice bluish color to make the bubble pop.
* Adjust the layout to accommodate these changes and fix autolayout conflicts.
  • Loading branch information
ElDragonRojo committed Aug 5, 2013
1 parent efae1b5 commit 4639a75
Show file tree
Hide file tree
Showing 15 changed files with 327 additions and 137 deletions.
35 changes: 25 additions & 10 deletions Lemacs/Base.lproj/Main_iPhone.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
<rect key="frame" x="0.0" y="64" width="320" height="504"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" tag="42" contentMode="scaleToFill" usesAttributedText="YES" translatesAutoresizingMaskIntoConstraints="NO" id="doA-xL-YLh">
<rect key="frame" x="0.0" y="0.0" width="320" height="504"/>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" tag="42" contentMode="scaleToFill" misplaced="YES" usesAttributedText="YES" translatesAutoresizingMaskIntoConstraints="NO" id="doA-xL-YLh">
<rect key="frame" x="0.0" y="30" width="320" height="474"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<attributedString key="attributedText">
Expand All @@ -35,11 +35,23 @@
<outlet property="delegate" destination="LeK-Cl-Emu" id="pao-9o-keO"/>
</connections>
</textView>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" placeholder="Topic (required)" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="JmJ-I8-eTC">
<rect key="frame" x="0.0" y="0.0" width="320" height="30"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocapitalizationType="words" autocorrectionType="yes"/>
<connections>
<outlet property="delegate" destination="LeK-Cl-Emu" id="d8S-hS-Jrx"/>
</connections>
</textField>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="doA-xL-YLh" firstAttribute="top" secondItem="BGJ-tf-hpn" secondAttribute="bottom" id="5Cq-c9-1b9"/>
<constraint firstItem="doA-xL-YLh" firstAttribute="top" secondItem="JmJ-I8-eTC" secondAttribute="bottom" id="1Y8-fk-dDh"/>
<constraint firstItem="JmJ-I8-eTC" firstAttribute="leading" secondItem="A8b-Tl-I0D" secondAttribute="leading" id="ABW-iu-wiB"/>
<constraint firstItem="doA-xL-YLh" firstAttribute="leading" secondItem="A8b-Tl-I0D" secondAttribute="leading" id="D5a-u5-TS7"/>
<constraint firstAttribute="trailing" secondItem="JmJ-I8-eTC" secondAttribute="trailing" id="Ebt-hL-bh0"/>
<constraint firstItem="JmJ-I8-eTC" firstAttribute="top" secondItem="BGJ-tf-hpn" secondAttribute="bottom" id="K2B-p5-wDU"/>
<constraint firstAttribute="bottom" secondItem="doA-xL-YLh" secondAttribute="bottom" id="VQ1-cs-e3Y"/>
<constraint firstItem="doA-xL-YLh" firstAttribute="trailing" secondItem="A8b-Tl-I0D" secondAttribute="trailing" id="uxi-1H-gW1"/>
</constraints>
Expand Down Expand Up @@ -67,6 +79,7 @@
<connections>
<outlet property="segmentedControl" destination="ZTE-GQ-cUX" id="zGS-do-eHe"/>
<outlet property="textView" destination="doA-xL-YLh" id="QJC-Fs-5FY"/>
<outlet property="topicField" destination="JmJ-I8-eTC" id="yud-d0-zZU"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="sa5-wg-BJq" userLabel="First Responder" sceneMemberID="firstResponder"/>
Expand All @@ -79,6 +92,8 @@
<navigationController id="rS3-R9-Ivy" sceneMemberID="viewController">
<navigationBar key="navigationBar" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" id="yXu-0R-QUA">
<autoresizingMask key="autoresizingMask"/>
<color key="backgroundColor" red="0.6945217252" green="0.89304971690000001" blue="0.99937492610000001" alpha="1" colorSpace="calibratedRGB"/>
<color key="barTintColor" red="0.40000000596046448" green="0.80000001192092896" blue="1" alpha="1" colorSpace="calibratedRGB"/>
</navigationBar>
<connections>
<segue destination="pGg-6v-bdr" kind="relationship" relationship="rootViewController" id="RxB-wf-QIq"/>
Expand All @@ -92,16 +107,16 @@
<scene sceneID="lLx-8y-duJ">
<objects>
<tableViewController title="Master" id="57H-Xs-xKD" userLabel="Talk View Controller - Master" customClass="LETalkViewController" sceneMemberID="viewController">
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" rowHeight="150" sectionHeaderHeight="150" sectionFooterHeight="22" id="aIc-pf-KqX">
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" rowHeight="150" sectionHeaderHeight="150" sectionFooterHeight="22" id="aIc-pf-KqX">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="0.6945217252" green="0.89304971690000001" blue="0.99937492610000001" alpha="1" colorSpace="calibratedRGB"/>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="jN8-T7-eV3">
<rect key="frame" x="0.0" y="214" width="320" height="150"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="jN8-T7-eV3" id="16V-xG-3cH">
<rect key="frame" x="0.0" y="0.0" width="287" height="149"/>
<rect key="frame" x="0.0" y="0.0" width="287" height="150"/>
<autoresizingMask key="autoresizingMask"/>
</tableViewCellContentView>
<connections>
Expand Down Expand Up @@ -144,17 +159,17 @@
<scene sceneID="VgW-fR-Quf">
<objects>
<tableViewController title="Master" id="pGg-6v-bdr" userLabel="Talk List Controller - Master" customClass="LETalkListController" sceneMemberID="viewController">
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" rowHeight="100" sectionHeaderHeight="100" sectionFooterHeight="22" id="mLL-gJ-YKr">
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" rowHeight="100" sectionHeaderHeight="100" sectionFooterHeight="22" id="mLL-gJ-YKr">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="backgroundColor" red="0.6945217252" green="0.89304971690000001" blue="0.99937492610000001" alpha="1" colorSpace="calibratedRGB"/>
<gestureRecognizers/>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="d8I-k5-K19">
<rect key="frame" x="0.0" y="164" width="320" height="100"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="d8I-k5-K19" id="PSy-4i-Rat">
<rect key="frame" x="0.0" y="0.0" width="287" height="99"/>
<rect key="frame" x="0.0" y="0.0" width="287" height="100"/>
<autoresizingMask key="autoresizingMask"/>
</tableViewCellContentView>
<connections>
Expand Down Expand Up @@ -212,6 +227,6 @@
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
<inferredMetricsTieBreakers>
<segue reference="nbc-YU-5Aq"/>
<segue reference="s9d-Vw-wBC"/>
</inferredMetricsTieBreakers>
</document>
1 change: 1 addition & 0 deletions Lemacs/GitHub/GHComment.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
+ (instancetype)newCommentInContext:(NSManagedObjectContext *)context;
+ (instancetype)commentNumber:(NSInteger)commentNumber context:(NSManagedObjectContext *)context;

@property (nonatomic) NSInteger commentID;
@property (nonatomic, strong) NSDate *createdDate;
@property (nonatomic, strong) NSString *body, *commentURL;
@property (nonatomic, strong) GHIssue *issue;
Expand Down
24 changes: 23 additions & 1 deletion Lemacs/GitHub/GHComment.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

#import "GHComment.h"
#import "GHIssue.h"
#import "GHStore.h"

@implementation GHComment
Expand Down Expand Up @@ -54,10 +55,31 @@ + (NSString *)indexGitHubKey;

#pragma mark - API

@dynamic body, commentURL, createdDate, issue, user;
@dynamic body, commentID, commentURL, createdDate, issue, user;

@end


@implementation GHComment (Deletion)

- (IBAction)die;
{ // ???: Can we do this? Should we do it after a delay? A request deletion method?
[[GHStore sharedStore] deleteComment:self];
}

@end


@implementation GHComment (LETalk)

- (NSString *)topic;
{
return [self.issue currentValueForKey:kLETalkTitleKey];
}

@end


NSString * const kGHCommentEntityName = @"GHComment";

NSString * const kGHCommentIDGitHubKey = @"id";
Expand Down
35 changes: 35 additions & 0 deletions Lemacs/GitHub/GHIssue.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#import "GHComment.h"
#import "GHStore.h"
#import "GHUser.h"
#import "NSAttributedStringMarkdownParser+GHMarkdown.h"

@implementation GHIssue
Expand Down Expand Up @@ -128,6 +129,40 @@ - (IBAction)die;
@end


@implementation GHIssue (LETalk)

- (NSAttributedString *)styledTitle;
{ // RealName (username) replied in|started topic
if (![self respondsToSelector:@selector(user)])
return nil;

GHUser *user = [self valueForKey:@"user"];

NSDictionary *boldBlackStyle = @{NSFontAttributeName : [UIFont boldSystemFontOfSize:10.0f],
NSForegroundColorAttributeName : [UIColor blackColor]};
NSDictionary *lightGrayStyle = @{NSFontAttributeName : [UIFont systemFontOfSize:10.0f],
NSForegroundColorAttributeName : [UIColor lightGrayColor]};

NSString *name = IsEmpty(user.displayName) ? user.userName : user.displayName;
if (!name)
name = NSLocalizedString(@"You", @"Second person pronoun");

NSMutableAttributedString *styledTitle = [[NSMutableAttributedString alloc] initWithString:name attributes:boldBlackStyle];

NSString *verb = [self isKindOfClass:[GHComment class]] ? NSLocalizedString(@" replied to ", @"reply verb") : NSLocalizedString(@" started ", @"initiate verb");
[styledTitle appendAttributedString:[[NSAttributedString alloc] initWithString:verb attributes:lightGrayStyle]];

return styledTitle;
}

- (NSString *)topic;
{
return [self currentValueForKey:kLETalkTitleKey];
}

@end


NSString * const kGHIssueEntityName = @"GHIssue";

NSString * const kGHIssueClosedGitHubKey = @"state";
Expand Down
10 changes: 5 additions & 5 deletions Lemacs/GitHub/GHManagedObject+LETalk.m
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,6 @@ - (NSAttributedString *)styledBody;
return [[NSAttributedStringMarkdownParser sharedParser] attributedStringFromMarkdownString:NonNil(self.plainBody, @"")];
}

- (NSString *)plainTitle;
{
return [self currentValueForKey:kLETalkTitleKey];
}

- (NSAttributedString *)styledTitle;
{
if (![self respondsToSelector:@selector(user)])
Expand All @@ -87,5 +82,10 @@ - (NSAttributedString *)styledTitle;
return styledTitle;
}

- (NSString *)topic;
{
assert(NO); // Subclasses should override this
return [self currentValueForKey:kLETalkTitleKey];
}

@end
2 changes: 2 additions & 0 deletions Lemacs/GitHub/GHManagedObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
@property (nonatomic, readonly) BOOL needsUpdating;
@property (nonatomic, strong) NSDate *lastUpdated;

- (NSDictionary *)dictionaryWithValuesForGitHubKeys:(NSArray *)keys;

@end


Expand Down
37 changes: 16 additions & 21 deletions Lemacs/GitHub/GHManagedObject.m
Original file line number Diff line number Diff line change
Expand Up @@ -98,27 +98,6 @@ - (void)setValue:(id)value forUndefinedKey:(NSString *)key;
[super setValue:value forUndefinedKey:key];
}

- (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys;
{
if (keys)
return [super dictionaryWithValuesForKeys:keys];

NSDictionary *GitHubKeysToPropertyNames = [[self class] GitHubKeysToPropertyNames];
NSArray *GitHubKeys = GitHubKeysToPropertyNames.allKeys;
__block NSMutableDictionary *GitHubKeysToCurrentValues = [NSMutableDictionary dictionaryWithCapacity:GitHubKeys.count];
GHManagedObject * __weak currentObject = self;
[GitHubKeys enumerateObjectsUsingBlock:^(NSString *GitHubKey, NSUInteger uselessIndex, BOOL *stop) {
if ([GitHubKey isEqualToString:[[currentObject class] indexGitHubKey]])
return;

NSString *propertyName = [[self class] GitHubKeysToPropertyNames][GitHubKey];
id propertyValue = [currentObject currentValueForKey:propertyName];
[GitHubKeysToCurrentValues setValue:propertyValue forKey:GitHubKey];
}];

return [GitHubKeysToCurrentValues copy];
}

- (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;
{
NSDate *modifiedDate = keyedValues[kGHModifiedDatePropertyName];
Expand Down Expand Up @@ -270,6 +249,22 @@ - (BOOL)needsUpdating;
return -[self.lastUpdated timeIntervalSinceNow] > kGHStoreUpdateLimit;
}

- (NSDictionary *)dictionaryWithValuesForGitHubKeys:(NSArray *)keys;
{
__block NSMutableDictionary *GitHubKeysToCurrentValues = [NSMutableDictionary dictionaryWithCapacity:keys.count];
GHManagedObject * __weak currentObject = self;
[keys enumerateObjectsUsingBlock:^(NSString *GitHubKey, NSUInteger uselessIndex, BOOL *stop) {
if ([GitHubKey isEqualToString:[[currentObject class] indexGitHubKey]])
return;

NSString *propertyName = [[self class] GitHubKeysToPropertyNames][GitHubKey];
id propertyValue = [currentObject currentValueForKey:propertyName];
[GitHubKeysToCurrentValues setValue:propertyValue forKey:GitHubKey];
}];

return [GitHubKeysToCurrentValues copy];
}

- (void)setUpRelationship:(NSRelationshipDescription *)relationship withValue:(id)value forKey:(NSString *)key;
{
if (relationship.isToMany)
Expand Down
8 changes: 4 additions & 4 deletions Lemacs/GitHub/GHStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@
- (void)logInWithUsername:(NSString *)username password:(NSString *)password;

// Issues
- (void)addIssue:(GHIssue *)issue;
- (void)deleteIssue:(GHIssue *)issue;
- (void)loadIssues:(BOOL)freshStart;
- (void)loadCommentsForIssue:(GHIssue *)issue;
- (void)loadUser:(GHUser *)user;

// Comments
- (void)addComment:(GHComment *)comment toIssue:(GHIssue *)issue;
// Saving
- (void)deleteComment:(GHComment *)comment;
- (void)deleteIssue:(GHIssue *)issue;
- (void)saveComment:(GHComment *)comment;
- (void)saveIssue:(GHIssue *)issue;

@end
Loading

0 comments on commit 4639a75

Please sign in to comment.