435 lines
15 KiB
Objective-C
435 lines
15 KiB
Objective-C
#import "StoreManager.h"
|
|
#import "MMMConstants.h"
|
|
|
|
@implementation StoreManager
|
|
+(instancetype)shared {
|
|
static id manager = nil;
|
|
static dispatch_once_t once;
|
|
dispatch_once(&once, ^{
|
|
manager = [[self alloc] init];
|
|
});
|
|
|
|
return manager;
|
|
}
|
|
|
|
-(instancetype)init {
|
|
self = [super init];
|
|
if (self) {
|
|
self.bucket = [[MattermostBucket alloc] init];
|
|
self.keychain = [[MMKeychainManager alloc] init];
|
|
[self getEntities:true];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
#pragma public methods
|
|
|
|
-(NSDictionary *)getChannelById:(NSString *)channelId {
|
|
NSDictionary *channelsStore = [self.entities objectForKey:@"channels"];
|
|
NSDictionary *channels = [channelsStore objectForKey:@"channels"];
|
|
NSDictionary *channel = channels[channelId];
|
|
|
|
return channel;
|
|
}
|
|
|
|
-(NSDictionary *)getChannelsBySections:(NSString *)forTeamId excludeArchived:(BOOL)excludeArchived {
|
|
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];
|
|
NSMutableArray *privateChannels = [[NSMutableArray alloc] init];
|
|
NSMutableArray *directChannels = [[NSMutableArray alloc] init];
|
|
|
|
for (NSString * key in channels) {
|
|
NSMutableDictionary *channel = [[channels objectForKey:key] mutableCopy];
|
|
|
|
NSNumber *deleteAt = [channel objectForKey:@"delete_at"];
|
|
if (excludeArchived && ![deleteAt isEqualToNumber:@0]) {
|
|
continue;
|
|
}
|
|
|
|
NSString *team_id = [channel objectForKey:@"team_id"];
|
|
NSString *channelType = [channel objectForKey:@"type"];
|
|
BOOL isDM = [channelType isEqualToString:@"D"];
|
|
BOOL isGM = [channelType isEqualToString:@"G"];
|
|
BOOL isPublic = [channelType isEqualToString:@"O"];
|
|
BOOL isPrivate = [channelType isEqualToString:@"P"];
|
|
if ([team_id isEqualToString:forTeamId] || isDM || isGM) {
|
|
if (isPublic) {
|
|
// public channel
|
|
[publicChannels addObject:channel];
|
|
} else if (isPrivate) {
|
|
// private channel
|
|
[privateChannels addObject:channel];
|
|
} else if (isDM) {
|
|
// direct message
|
|
NSString *otherUserId = [self getOtherUserIdFromChannel:currentUserId withChannelName:[channel objectForKey:@"name"]];
|
|
NSDictionary *otherUser = [self getUserById:otherUserId];
|
|
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 {
|
|
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];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[channelsInTeam setObject:[self sortDictArrayByDisplayName:publicChannels] forKey:@"public"];
|
|
[channelsInTeam setObject:[self sortDictArrayByDisplayName:privateChannels] forKey:@"private"];
|
|
[channelsInTeam setObject:[self sortDictArrayByDisplayName:directChannels] forKey:@"direct"];
|
|
|
|
return channelsInTeam;
|
|
}
|
|
|
|
-(NSDictionary *)getCurrentChannel {
|
|
NSString *currentChannelId = [self getCurrentChannelId];
|
|
return [self getChannelById:currentChannelId];
|
|
}
|
|
|
|
-(NSString *)getCurrentChannelId {
|
|
return [[self.entities objectForKey:@"channels"] objectForKey:@"currentChannelId"];
|
|
}
|
|
|
|
-(NSString *)getCurrentTeamId {
|
|
return [[self.entities objectForKey:@"teams"] objectForKey:@"currentTeamId"];
|
|
}
|
|
|
|
-(NSString *)getCurrentUserId {
|
|
return [[self.entities objectForKey:@"users"] objectForKey:@"currentUserId"];
|
|
}
|
|
|
|
-(NSDictionary *)getDefaultChannel:(NSString *)forTeamId {
|
|
NSArray *channelsInTeam = [self getChannelsInTeam:forTeamId];
|
|
NSPredicate *filter = [NSPredicate predicateWithFormat:@"name = %@", @"town-square"];
|
|
NSArray *townSquare = [channelsInTeam filteredArrayUsingPredicate:filter];
|
|
if (townSquare != nil && townSquare.count > 0) {
|
|
return townSquare.firstObject;
|
|
}
|
|
|
|
return nil;
|
|
}
|
|
|
|
-(NSDictionary *)getEntities:(BOOL)loadFromFile {
|
|
if (loadFromFile) {
|
|
self.entities = [self.bucket readFromFileAsJSON:@"entities"];
|
|
}
|
|
return self.entities;
|
|
}
|
|
|
|
-(NSArray *)getMyTeams {
|
|
NSDictionary *teamsStore = [self.entities objectForKey:@"teams"];
|
|
NSDictionary *teams = [teamsStore objectForKey:@"teams"];
|
|
NSDictionary *membership = [teamsStore objectForKey:@"myMembers"];
|
|
NSMutableArray *myTeams = [[NSMutableArray alloc] init];
|
|
|
|
for (NSString* key in teams) {
|
|
NSDictionary *member = [membership objectForKey:key];
|
|
NSDictionary *team = [teams objectForKey:key];
|
|
if (member) {
|
|
[myTeams addObject:team];
|
|
}
|
|
}
|
|
|
|
|
|
return [self sortDictArrayByDisplayName:myTeams];
|
|
}
|
|
|
|
-(NSString *)getServerUrl {
|
|
NSDictionary *general = [self.entities objectForKey:@"general"];
|
|
NSDictionary *credentials = [general objectForKey:@"credentials"];
|
|
|
|
if (credentials) {
|
|
return [credentials objectForKey:@"url"];
|
|
}
|
|
|
|
return nil;
|
|
}
|
|
|
|
-(NSString *)getToken {
|
|
NSDictionary *options = @{
|
|
@"accessGroup": APP_GROUP_ID
|
|
};
|
|
NSString* serverUrl = [self getServerUrl];
|
|
|
|
if (serverUrl) {
|
|
NSDictionary *credentials = [self.keychain getInternetCredentialsForServer:[self getServerUrl] withOptions:options];
|
|
|
|
return [credentials objectForKey:@"password"];
|
|
}
|
|
|
|
return nil;
|
|
}
|
|
|
|
-(UInt64)scanValueFromConfig:(NSDictionary *)config key:(NSString *)key {
|
|
NSString *value = [config objectForKey:key];
|
|
NSScanner *scanner = [NSScanner scannerWithString:value];
|
|
unsigned long long convertedValue = 0;
|
|
[scanner scanUnsignedLongLong:&convertedValue];
|
|
return convertedValue;
|
|
}
|
|
|
|
-(UInt64)getMaxImagePixels {
|
|
NSDictionary *config = [self getConfig];
|
|
NSString *key = @"MaxImagePixels";
|
|
if (config != nil && [config objectForKey:key]) {
|
|
return [self scanValueFromConfig:config key:key];
|
|
}
|
|
|
|
return DEFAULT_SERVER_MAX_IMAGE_PIXELS;
|
|
}
|
|
|
|
-(UInt64)getMaxFileSize {
|
|
NSDictionary *config = [self getConfig];
|
|
NSString *key = @"MaxFileSize";
|
|
if (config != nil && [config objectForKey:key]) {
|
|
return [self scanValueFromConfig:config key:key];
|
|
}
|
|
|
|
return DEFAULT_SERVER_MAX_FILE_SIZE;
|
|
}
|
|
|
|
-(UInt64)getMaxPostSize {
|
|
NSDictionary *config = [self getConfig];
|
|
NSString *key = @"MaxPostSize";
|
|
if (config != nil && [config objectForKey:key]) {
|
|
return [self scanValueFromConfig:config key:key];
|
|
}
|
|
|
|
return DEFAULT_SERVER_MAX_POST_SIZE;
|
|
}
|
|
|
|
-(void)updateEntities:(NSString *)content {
|
|
[self.bucket writeToFile:@"entities" content:content];
|
|
}
|
|
|
|
#pragma utilities
|
|
|
|
-(NSString *)completeDirectGroupInfo:(NSString *)channelId {
|
|
NSDictionary *usersStore = [self.entities objectForKey:@"users"];
|
|
NSDictionary *profilesInChannels = [usersStore objectForKey:@"profilesInChannel"];
|
|
NSDictionary *profileIds = [profilesInChannels objectForKey:channelId];
|
|
NSDictionary *channel = [self getChannelById:channelId];
|
|
NSString *currentUserId = [self getCurrentUserId];
|
|
NSMutableArray *result = [[NSMutableArray alloc] init];
|
|
|
|
if (profileIds) {
|
|
for (NSString *key in profileIds) {
|
|
NSDictionary *user = [self getUserById:key];
|
|
NSString *userId = [user objectForKey:@"id"];
|
|
if (![userId isEqualToString:currentUserId]) {
|
|
NSString *fullName = [self getUserFullName:user];
|
|
[result addObject:fullName];
|
|
}
|
|
}
|
|
}
|
|
|
|
if ([result count] != ([profileIds count] - 1)) {
|
|
return [channel objectForKey:@"display_name"];
|
|
}
|
|
|
|
NSArray *sorted = [result sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
|
|
return [sorted componentsJoinedByString:@", "];
|
|
}
|
|
|
|
-(NSString *)displayUserName:(NSDictionary *)user {
|
|
NSString *teammateNameDisplay = [self getTeammateNameDisplaySetting];
|
|
NSString *username = [user objectForKey:@"username"];
|
|
NSString *name;
|
|
|
|
if ([teammateNameDisplay isEqualToString:@"nickname_full_name"]) {
|
|
name = [user objectForKey:@"nickname"] ?: [self getUserFullName:user];
|
|
} else if ([teammateNameDisplay isEqualToString:@"full_name"]) {
|
|
name = [self getUserFullName:user];
|
|
} else {
|
|
name = username;
|
|
}
|
|
|
|
if (!name || [[name stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length] == 0) {
|
|
name = username;
|
|
}
|
|
|
|
return name;
|
|
}
|
|
|
|
-(NSArray *)getChannelsInTeam:(NSString *) teamId {
|
|
NSDictionary *channels = [[self.entities objectForKey:@"channels"] objectForKey:@"channels"];
|
|
NSArray *arr = [channels allValues];
|
|
NSPredicate *filter = [NSPredicate predicateWithFormat:@"team_id = %@", teamId];
|
|
|
|
return [arr filteredArrayUsingPredicate:filter];
|
|
}
|
|
|
|
-(NSDictionary *)getConfig {
|
|
return [[self.entities objectForKey:@"general"] objectForKey:@"config"];
|
|
}
|
|
|
|
-(NSDictionary *)getMyPreferences {
|
|
return [[self.entities objectForKey:@"preferences"] objectForKey:@"myPreferences"];
|
|
}
|
|
|
|
-(NSString *)getOtherUserIdFromChannel:(NSString *)currentUserId withChannelName:(NSString *)channelName {
|
|
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];
|
|
|
|
return user;
|
|
}
|
|
|
|
-(NSString *)getUserFullName:(NSDictionary*) user {
|
|
NSString *fistName = [user objectForKey:@"first_name"];
|
|
NSString *lastName = [user objectForKey:@"last_name"];
|
|
|
|
if (fistName && lastName) {
|
|
return [fistName stringByAppendingFormat:@" %@", lastName];
|
|
} else if (fistName) {
|
|
return fistName;
|
|
} else if (lastName) {
|
|
return lastName;
|
|
}
|
|
|
|
return @"";
|
|
}
|
|
|
|
-(NSString *)getTeammateNameDisplaySetting {
|
|
NSDictionary *config = [self getConfig];
|
|
NSString *teammateNameDisplay = [config objectForKey:@"TeammateNameDisplay"];
|
|
|
|
NSDictionary *preferences = [self getMyPreferences];
|
|
NSString *key = @"display_settings--name_format";
|
|
NSDictionary *displayFormat = [preferences objectForKey:key];
|
|
|
|
if (displayFormat) {
|
|
return [displayFormat objectForKey:@"value"];
|
|
} else if (teammateNameDisplay) {
|
|
return teammateNameDisplay;
|
|
}
|
|
|
|
return @"username";
|
|
}
|
|
|
|
-(NSArray *)sortDictArrayByDisplayName:(NSArray *)array {
|
|
NSSortDescriptor *sd = [[NSSortDescriptor alloc]
|
|
initWithKey:@"display_name"
|
|
ascending:YES
|
|
selector: @selector(localizedCaseInsensitiveCompare:)];
|
|
NSArray *sortDescriptor = [NSArray arrayWithObjects:sd, nil];
|
|
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
|