304 lines
11 KiB
Objective-C
304 lines
11 KiB
Objective-C
//
|
|
// SignalsViewController.m
|
|
// Signal
|
|
//
|
|
// Created by Dylan Bourgeois on 27/10/14.
|
|
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
|
//
|
|
|
|
#import "UIUtil.h"
|
|
#import "InboxTableViewCell.h"
|
|
|
|
#import "Environment.h"
|
|
#import "MessagesViewController.h"
|
|
#import "SignalsViewController.h"
|
|
#import "TSStorageManager.h"
|
|
#import "TSDatabaseView.h"
|
|
#import "TSSocketManager.h"
|
|
#import "TSContactThread.h"
|
|
|
|
#import <YapDatabase/YapDatabaseViewChange.h>
|
|
#import "YapDatabaseViewTransaction.h"
|
|
#import "YapDatabaseViewMappings.h"
|
|
#import "YapDatabaseViewConnection.h"
|
|
#import "YapDatabaseFullTextSearch.h"
|
|
#import "YapDatabase.h"
|
|
|
|
#define CELL_HEIGHT 71.0f
|
|
#define HEADER_HEIGHT 44.0f
|
|
|
|
|
|
static NSString *const inboxTableViewCell = @"inBoxTableViewCell";
|
|
static NSString *const kSegueIndentifier = @"showSegue";
|
|
|
|
@interface SignalsViewController ()
|
|
|
|
@property (strong, nonatomic) UILabel * emptyViewLabel;
|
|
@property (nonatomic, strong) YapDatabaseConnection *editingDbConnection;
|
|
@property (nonatomic, strong) YapDatabaseConnection *uiDatabaseConnection;
|
|
@property (nonatomic, strong) YapDatabaseViewMappings *threadMappings;
|
|
|
|
@end
|
|
|
|
@implementation SignalsViewController
|
|
|
|
- (void)awakeFromNib{
|
|
[[Environment getCurrent] setSignalsViewController:self];
|
|
}
|
|
|
|
- (void)viewDidLoad {
|
|
[super viewDidLoad];
|
|
|
|
[self tableViewSetUp];
|
|
|
|
self.editingDbConnection = TSStorageManager.sharedManager.newDatabaseConnection;
|
|
|
|
[self.uiDatabaseConnection beginLongLivedReadTransaction];
|
|
|
|
self.threadMappings = [[YapDatabaseViewMappings alloc] initWithGroups:@[TSInboxGroup]
|
|
view:TSThreadDatabaseViewExtensionName];
|
|
|
|
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction){
|
|
[self.threadMappings updateWithTransaction:transaction];
|
|
}];
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(yapDatabaseModified:)
|
|
name:TSUIDatabaseConnectionDidUpdateNotification
|
|
object:nil];
|
|
}
|
|
|
|
-(void)viewWillAppear:(BOOL)animated
|
|
{
|
|
[super viewWillAppear:animated];
|
|
[self updateTableViewHeader];
|
|
}
|
|
|
|
- (void)didReceiveMemoryWarning {
|
|
[super didReceiveMemoryWarning];
|
|
}
|
|
|
|
|
|
-(void)tableViewSetUp
|
|
{
|
|
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
|
|
}
|
|
|
|
|
|
#pragma mark - Table view data source
|
|
|
|
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
|
return (NSInteger)[self.threadMappings numberOfSections];
|
|
}
|
|
|
|
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
|
return (NSInteger)[self.threadMappings numberOfItemsInSection:(NSUInteger)section];
|
|
}
|
|
|
|
- (InboxTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {
|
|
|
|
InboxTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:inboxTableViewCell];
|
|
TSThread *thread = [self threadForIndexPath:indexPath];
|
|
|
|
if (!cell) {
|
|
cell = [[InboxTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
|
|
reuseIdentifier:inboxTableViewCell];
|
|
cell.delegate = self;
|
|
}
|
|
|
|
[cell configureWithThread:thread];
|
|
[cell configureForState:_inboxArchiveSwitch.selectedSegmentIndex == 0 ? kInboxState : kArchiveState];
|
|
|
|
return cell;
|
|
}
|
|
|
|
- (TSThread*)threadForIndexPath:(NSIndexPath*)indexPath {
|
|
|
|
__block TSThread *thread = nil;
|
|
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
|
thread = [[transaction extension:TSThreadDatabaseViewExtensionName] objectAtIndexPath:indexPath withMappings:self.threadMappings];
|
|
}];
|
|
|
|
return thread;
|
|
}
|
|
|
|
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
|
return CELL_HEIGHT;
|
|
}
|
|
|
|
#pragma mark - HomeFeedTableViewCellDelegate
|
|
|
|
- (void)tableViewCellTappedDelete:(InboxTableViewCell*)cell {
|
|
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
|
|
TSThread *thread = [self threadForIndexPath:indexPath];
|
|
|
|
[self.editingDbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
[thread removeWithTransaction:transaction];
|
|
}];
|
|
}
|
|
|
|
- (void)tableViewCellTappedArchive:(InboxTableViewCell*)cell {
|
|
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
|
|
TSThread *thread = [self threadForIndexPath:indexPath];
|
|
thread.archivalDate = _inboxArchiveSwitch.selectedSegmentIndex == 0 ? [NSDate date] : nil ;
|
|
|
|
[self.editingDbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
|
[thread saveWithTransaction:transaction];
|
|
}];
|
|
}
|
|
|
|
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath{
|
|
[self performSegueWithIdentifier:kSegueIndentifier sender:self];
|
|
[tableView deselectRowAtIndexPath:indexPath animated:NO];
|
|
}
|
|
|
|
#pragma mark - Navigation
|
|
|
|
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
|
|
|
if ([segue.identifier isEqualToString:kSegueIndentifier]){
|
|
MessagesViewController * vc = [segue destinationViewController];
|
|
NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];
|
|
TSThread *thread = [self threadForIndexPath:selectedIndexPath];
|
|
|
|
if (thread) {
|
|
[vc setupWithThread:thread];
|
|
} else if (self.contactIdentifierFromCompose){
|
|
[vc setupWithTSIdentifier:self.contactIdentifierFromCompose];
|
|
self.contactIdentifierFromCompose = nil;
|
|
}
|
|
}
|
|
}
|
|
|
|
#pragma mark - IBAction
|
|
|
|
-(IBAction)segmentDidChange:(id)sender
|
|
{
|
|
switch (_inboxArchiveSwitch.selectedSegmentIndex) {
|
|
case 0:
|
|
self.threadMappings = [[YapDatabaseViewMappings alloc] initWithGroups:@[TSInboxGroup]
|
|
view:TSThreadDatabaseViewExtensionName];
|
|
break;
|
|
|
|
case 1:
|
|
self.threadMappings = [[YapDatabaseViewMappings alloc] initWithGroups:@[TSArchiveGroup]
|
|
view:TSThreadDatabaseViewExtensionName];
|
|
break;
|
|
}
|
|
|
|
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction){
|
|
[self.threadMappings updateWithTransaction:transaction];
|
|
}];
|
|
[self.tableView reloadData];
|
|
[self updateTableViewHeader];
|
|
}
|
|
|
|
#pragma mark Database delegates
|
|
|
|
- (YapDatabaseConnection *)uiDatabaseConnection {
|
|
NSAssert([NSThread isMainThread], @"Must access uiDatabaseConnection on main thread!");
|
|
if (!_uiDatabaseConnection) {
|
|
YapDatabase *database = TSStorageManager.sharedManager.database;
|
|
_uiDatabaseConnection = [database newConnection];
|
|
[_uiDatabaseConnection beginLongLivedReadTransaction];
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(yapDatabaseModified:)
|
|
name:YapDatabaseModifiedNotification
|
|
object:database];
|
|
}
|
|
return _uiDatabaseConnection;
|
|
}
|
|
|
|
- (void)yapDatabaseModified:(NSNotification *)notification {
|
|
NSArray *notifications = [self.uiDatabaseConnection beginLongLivedReadTransaction];
|
|
NSArray *sectionChanges = nil;
|
|
NSArray *rowChanges = nil;
|
|
|
|
[[self.uiDatabaseConnection ext:TSThreadDatabaseViewExtensionName] getSectionChanges:§ionChanges
|
|
rowChanges:&rowChanges
|
|
forNotifications:notifications
|
|
withMappings:self.threadMappings];
|
|
|
|
if ([sectionChanges count] == 0 && [rowChanges count] == 0){
|
|
return;
|
|
}
|
|
|
|
[self.tableView beginUpdates];
|
|
|
|
for (YapDatabaseViewSectionChange *sectionChange in sectionChanges)
|
|
{
|
|
switch (sectionChange.type)
|
|
{
|
|
case YapDatabaseViewChangeDelete :
|
|
{
|
|
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionChange.index]
|
|
withRowAnimation:UITableViewRowAnimationAutomatic];
|
|
break;
|
|
}
|
|
case YapDatabaseViewChangeInsert :
|
|
{
|
|
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionChange.index]
|
|
withRowAnimation:UITableViewRowAnimationAutomatic];
|
|
break;
|
|
}
|
|
case YapDatabaseViewChangeUpdate:
|
|
case YapDatabaseViewChangeMove:
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (YapDatabaseViewRowChange *rowChange in rowChanges)
|
|
{
|
|
switch (rowChange.type)
|
|
{
|
|
case YapDatabaseViewChangeDelete :
|
|
{
|
|
[self.tableView deleteRowsAtIndexPaths:@[ rowChange.indexPath ]
|
|
withRowAnimation:UITableViewRowAnimationAutomatic];
|
|
break;
|
|
}
|
|
case YapDatabaseViewChangeInsert :
|
|
{
|
|
[self.tableView insertRowsAtIndexPaths:@[ rowChange.newIndexPath ]
|
|
withRowAnimation:UITableViewRowAnimationAutomatic];
|
|
break;
|
|
}
|
|
case YapDatabaseViewChangeMove :
|
|
{
|
|
[self.tableView deleteRowsAtIndexPaths:@[ rowChange.indexPath ]
|
|
withRowAnimation:UITableViewRowAnimationAutomatic];
|
|
[self.tableView insertRowsAtIndexPaths:@[ rowChange.newIndexPath ]
|
|
withRowAnimation:UITableViewRowAnimationAutomatic];
|
|
break;
|
|
}
|
|
case YapDatabaseViewChangeUpdate :
|
|
{
|
|
[self.tableView reloadRowsAtIndexPaths:@[ rowChange.indexPath ]
|
|
withRowAnimation:UITableViewRowAnimationNone];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
[self.tableView endUpdates];
|
|
[self updateTableViewHeader];
|
|
}
|
|
|
|
- (void)updateTableViewHeader{
|
|
if ([self.threadMappings numberOfItemsInAllGroups]==0)
|
|
{
|
|
CGRect r = CGRectMake(0, 60, 300, 70);
|
|
_emptyViewLabel = [[UILabel alloc]initWithFrame:r];
|
|
_emptyViewLabel.textColor = [UIColor grayColor];
|
|
_emptyViewLabel.font = [UIFont ows_thinFontWithSize:14.0f];
|
|
_emptyViewLabel.textAlignment = NSTextAlignmentCenter;
|
|
_emptyViewLabel.text = @"You have no messages yet.";
|
|
self.tableView.tableHeaderView = _emptyViewLabel;
|
|
} else {
|
|
_emptyViewLabel = nil;
|
|
self.tableView.tableHeaderView = nil;
|
|
}
|
|
}
|
|
|
|
@end
|