Skip to content

Commit

Permalink
iOS Share Extension fix post and dm/gm list (#2659)
Browse files Browse the repository at this point in the history
* MM-14629 DMs and GMs for the iOS extension to match sidebar

* MM-14631 ios extension logging and fix race condition to post after uploading
  • Loading branch information
enahum committed Mar 20, 2019
1 parent 96571c0 commit badaaef
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 34 deletions.
6 changes: 6 additions & 0 deletions ios/Mattermost/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@
#import "RNNotifications.h"
#import <UploadAttachments/UploadAttachments-Swift.h>
#import <UserNotifications/UserNotifications.h>
#import <os/log.h>

@implementation AppDelegate

NSString* const NotificationClearAction = @"clear";

-(void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler {
os_log(OS_LOG_DEFAULT, "Mattermost will attach session from handleEventsForBackgroundURLSession!! identifier=%{public}@", identifier);
[[UploadSession shared] attachSessionWithIdentifier:identifier completionHandler:completionHandler];
os_log(OS_LOG_DEFAULT, "Mattermost session ATTACHED from handleEventsForBackgroundURLSession!! identifier=%{public}@", identifier);
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Expand Down Expand Up @@ -58,6 +61,9 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
[[RCCManager sharedInstance] initBridgeWithBundleURL:jsCodeLocation launchOptions:launchOptions];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error: nil];

os_log(OS_LOG_DEFAULT, "Mattermost started!!");


return YES;
}

Expand Down
146 changes: 117 additions & 29 deletions ios/UploadAttachments/UploadAttachments/StoreManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,16 @@ -(instancetype)init {
-(NSDictionary *)getChannelById:(NSString *)channelId {
NSDictionary *channelsStore = [self.entities objectForKey:@"channels"];
NSDictionary *channels = [channelsStore objectForKey:@"channels"];
NSDictionary *channel = channels[channelId];

for (NSString * key in channels) {
NSDictionary *channel = channels[key];
NSString *channel_id = [channel objectForKey:@"id"];
if ([channel_id isEqualToString:channelId]) {
return channel;
}
}

return nil;
return channel;
}

-(NSDictionary *)getChannelsBySections:(NSString *)forTeamId {
NSDictionary *channelsStore = [self.entities objectForKey:@"channels"];
NSString *currentUserId = [self getCurrentUserId];
NSString *currentChannelId = [self getCurrentChannelId];
NSDictionary *preferences = [self getMyPreferences];
NSDictionary *channels = [channelsStore objectForKey:@"channels"];
NSMutableDictionary *channelsInTeam = [[NSMutableDictionary alloc] init];
NSMutableArray *publicChannels = [[NSMutableArray alloc] init];
Expand All @@ -66,13 +61,17 @@ -(NSDictionary *)getChannelsBySections:(NSString *)forTeamId {
// direct message
NSString *otherUserId = [self getOtherUserIdFromChannel:currentUserId withChannelName:[channel objectForKey:@"name"]];
NSDictionary *otherUser = [self getUserById:otherUserId];
if (otherUser) {
NSNumber *delete_at = [otherUser objectForKey:@"delete_at"] ?: 0;
if (otherUser && [self isDirectChannelVisible:preferences otherUserId:otherUserId] && ![self isAutoClosed:preferences channel:channel currentChannelId:currentChannelId channelArchivedAt:delete_at]) {
[channel setObject:[self displayUserName:otherUser] forKey:@"display_name"];
[directChannels addObject:channel];
}
} else {
[channel setObject:[self completeDirectGroupInfo:key] forKey:@"display_name"];
[directChannels addObject:channel];
NSNumber *delete_at = [channel objectForKey:@"delete_at"] ?: 0;
if ([self isGroupChannelVisible:preferences channelId:key] && ![self isAutoClosed:preferences channel:channel currentChannelId:currentChannelId channelArchivedAt:delete_at]) {
[channel setObject:[self completeDirectGroupInfo:key] forKey:@"display_name"];
[directChannels addObject:channel];
}
}
}
}
Expand All @@ -89,8 +88,6 @@ -(NSDictionary *)getCurrentChannel {
return [self getChannelById:currentChannelId];
}



-(NSString *)getCurrentChannelId {
return [[self.entities objectForKey:@"channels"] objectForKey:@"currentChannelId"];
}
Expand Down Expand Up @@ -236,27 +233,22 @@ -(NSDictionary *)getMyPreferences {
}

-(NSString *)getOtherUserIdFromChannel:(NSString *)currentUserId withChannelName:(NSString *)channelName {
NSArray *ids = [channelName componentsSeparatedByString:@"_"];
if ([ids[0] isEqualToString:currentUserId]) {
return ids[2];
}

return ids[0];
NSArray *ids = [channelName componentsSeparatedByString:@"_"];
NSString *user1 = ids[0];
NSString *user2 = ids[2];
if (user1 != nil && [user1 isEqualToString:currentUserId]) {
return user2;
}

return user1;
}

-(NSDictionary *)getUserById:(NSString *)userId {
NSDictionary *usersStore = [self.entities objectForKey:@"users"];
NSDictionary *users = [usersStore objectForKey:@"profiles"];
NSDictionary *user = [users objectForKey:userId];

for (NSString* key in users) {
NSDictionary *user = [users objectForKey:key];
NSString *user_id = [user objectForKey:@"id"];
if ([user_id isEqualToString:userId]) {
return user;
}
}

return nil;
return user;
}

-(NSString *)getUserFullName:(NSDictionary*) user {
Expand Down Expand Up @@ -300,4 +292,100 @@ -(NSArray *)sortDictArrayByDisplayName:(NSArray *)array {
return [array sortedArrayUsingDescriptors:sortDescriptor];
}

-(BOOL)isAutoClosed:(NSDictionary*)preferences channel:(NSDictionary *)channel currentChannelId:(NSString *)currentChannelId channelArchivedAt:(NSNumber *)channelArchivedAt {
NSNumber *cutoff = [NSNumber numberWithLongLong:([[NSDate date] timeIntervalSince1970] * 1000 - (7 * 24 * 60 * 60 * 1000))];
NSString *channelId = [channel objectForKey:@"id"];

NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.numberStyle = NSNumberFormatterNoStyle;

NSDictionary *viewTimePref = [preferences objectForKey:[NSString stringWithFormat:@"channel_approximate_view_time--%@", channelId]];
NSNumber *viewTime = 0;
if (viewTimePref != nil) {
viewTime = [numberFormatter numberFromString:[viewTimePref objectForKey:@"value"]];
}

if ([viewTime doubleValue] > [cutoff doubleValue]) {
return NO;
}

// If chhannel is archived we cannot post to it
if ([channelArchivedAt doubleValue] > 0.0) {
return YES;
}

NSDictionary *config = [self getConfig];
if (![[config objectForKey:@"CloseUnusedDirectMessages"] isEqualToString:@"true"] || [self isFavoriteChannel:channelId]) {
return NO;
}

NSDictionary *autoClosePref = [preferences objectForKey:@"sidebar_settings--close_unused_direct_messages"];

if (autoClosePref == nil || [[autoClosePref objectForKey:@"value"] isEqualToString:@"after_seven_days"]) {
NSNumber *lastChannelPostAt = [self lastChannelPostActivity:channelId];
if ([lastChannelPostAt doubleValue] > [cutoff doubleValue]) {
return NO;
}

NSDictionary *openTimePref = [preferences objectForKey:[NSString stringWithFormat:@"channel_open_time--%@", channelId]];
NSNumber *openTime = 0;
if (openTimePref != nil) {
openTime = [numberFormatter numberFromString:[openTimePref objectForKey:@"value"]];
}

if ([openTime doubleValue] > [cutoff doubleValue]) {
return NO;
}

NSNumber *lastActivity = [channel objectForKey:@"last_post_at"];
return [lastActivity doubleValue] == 0.0 || [lastActivity doubleValue] < [cutoff doubleValue];
}

return NO;
}

-(BOOL)isFavoriteChannel:(NSString *)channelId {
NSDictionary *preferences = [self getMyPreferences];
NSDictionary *favoritePref = [preferences objectForKey:[NSString stringWithFormat:@"favorite_channel--%@", channelId]];
return favoritePref != nil && [[favoritePref objectForKey:@"value"] isEqualToString:@"true"];
}

-(NSNumber *)lastChannelPostActivity:(NSString *)channelId {
NSDictionary *allPosts = [[self.entities objectForKey:@"posts"] objectForKey:@"posts"];
NSDictionary *postsInChannels = [[self.entities objectForKey:@"posts"] objectForKey:@"postsInChannel"];
NSArray *postInChannel = [postsInChannels objectForKey:channelId];

if (postInChannel != nil && [postInChannel count] > 0) {
NSString *postId = [postInChannel lastObject];
NSDictionary *post = [allPosts objectForKey:postId];
if (post != nil) {
return [post objectForKey:@"create_at"];
}
}

return 0;
}

-(BOOL)isDirectChannelVisible:(NSDictionary *)preferences otherUserId:(NSString *) otherUserId {
NSDictionary *dmPref = [preferences objectForKey:[NSString stringWithFormat:@"direct_channel_show--%@", otherUserId]];
if (dmPref != nil) {
NSString *value = [dmPref objectForKey:@"value"];
if (value != nil) {
return [value isEqualToString:@"true"];
}
}
return NO;
}

-(BOOL)isGroupChannelVisible:(NSDictionary *)preferences channelId:(NSString *) channelId {
NSDictionary *gmPref = [preferences objectForKey:[NSString stringWithFormat:@"group_channel_show--%@", channelId]];
if (gmPref != nil) {
NSString *value = [gmPref objectForKey:@"value"];
if (value != nil) {
return [value isEqualToString:@"true"];
}
}
return NO;
}

@end
34 changes: 29 additions & 5 deletions ios/UploadAttachments/UploadAttachments/UploadSession.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import UIKit
import os.log

@objc @objcMembers public class UploadSession: NSObject, URLSessionDataDelegate {
public class var shared :UploadSession {
Expand Down Expand Up @@ -33,6 +34,11 @@ import UIKit
request.setValue("Bearer \(sessionToken!)", forHTTPHeaderField: "Authorization")
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted)

if #available(iOS 12.0, *) {
os_log(OSLogType.default, "Mattermost will post identifier=%{public}@", identifier)
}

URLSession(configuration: .ephemeral).dataTask(with: request).resume()

UploadSessionManager.shared.removeUploadSessionData(identifier: identifier)
Expand All @@ -42,6 +48,9 @@ import UIKit

public func attachSession(identifier: String, completionHandler: @escaping () -> Void) {
self.completionHandler = completionHandler
if #available(iOS 12.0, *) {
os_log(OSLogType.default, "Mattermost Attached session with completionHandler identifier=%{public}@", identifier)
}
let sessionConfig = URLSessionConfiguration.background(withIdentifier: identifier)
sessionConfig.sharedContainerIdentifier = APP_GROUP_ID
if #available(iOS 11.0, *) {
Expand All @@ -59,9 +68,12 @@ import UIKit
}

self.session = URLSession(configuration: sessionConfig, delegate: self, delegateQueue: nil)
if #available(iOS 12.0, *) {
os_log(OSLogType.default, "Mattermost Session created identifier=%{public}@", identifier)
}
return self.session!
}

public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
// here we should get the file Id and update it in the session
guard let identifier = session.configuration.identifier else {return}
Expand All @@ -74,6 +86,9 @@ import UIKit
UploadSessionManager.shared.appendCompletedUploadToSession(identifier: identifier, fileId: fileId)
}
} catch {
if #available(iOS 12.0, *) {
os_log(OSLogType.default, "Mattermost Failed to receive data identifier=%{public}@ error=%{public}", identifier, error.localizedDescription)
}
print("MMLOG: Failed to get the file upload response %@", error.localizedDescription)
}

Expand All @@ -84,19 +99,28 @@ import UIKit
let identifier = session.configuration.identifier!
guard let sessionData = UploadSessionManager.shared.getUploadSessionData(identifier: identifier) else {return}
if sessionData.fileIds.count == sessionData.totalFiles {
if #available(iOS 12.0, *) {
os_log(OSLogType.default, "Mattermost did complete upload identifier=%{public}@", identifier)
}
ProcessInfo().performExpiringActivity(withReason: "Need to post the message") { (expires) in
self.createPost(identifier: identifier)
self.createPost(identifier: session.configuration.identifier!)
}
}
}
}

public func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
DispatchQueue.main.async {

if #available(iOS 12.0, *) {
os_log(OSLogType.default, "Mattermost urlSessionDidFinishEvents identifier=%{public}@", session.configuration.identifier ?? "no identifier")
}

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(1.0*Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: {
if self.completionHandler != nil {
if #available(iOS 12.0, *) {
os_log(OSLogType.default, "Mattermost CALLED COMPLETIONHANDLER")
}
self.completionHandler!()
}
}
})
}
}

0 comments on commit badaaef

Please sign in to comment.