Add polls API requests and PollVotingView.

Signed-off-by: Ivan Sein <ivan@nextcloud.com>
This commit is contained in:
Ivan Sein 2022-07-22 18:55:06 +02:00
Родитель 931b428c96
Коммит e795d33c01
9 изменённых файлов: 404 добавлений и 3 удалений

Просмотреть файл

@ -115,6 +115,10 @@
2C4E758F214B942D003910D5 /* OpenInFirefoxControllerObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C4E758E214B942D003910D5 /* OpenInFirefoxControllerObjC.m */; };
2C5BFBEA28772A9A00E75118 /* NCUnifiedSearchController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C5BFBE928772A9A00E75118 /* NCUnifiedSearchController.swift */; };
2C5BFBED28895E6B00E75118 /* ObjectShareMessageTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C5BFBEC28895E6B00E75118 /* ObjectShareMessageTableViewCell.m */; };
2C5BFBEF288A947900E75118 /* PollVotingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C5BFBEE288A947800E75118 /* PollVotingView.swift */; };
2C5BFBF2288A97D800E75118 /* NCPoll.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C5BFBF1288A97D800E75118 /* NCPoll.m */; };
2C5BFBF3288AA37F00E75118 /* NCPoll.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C5BFBF1288A97D800E75118 /* NCPoll.m */; };
2C5BFBF4288AA37F00E75118 /* NCPoll.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C5BFBF1288A97D800E75118 /* NCPoll.m */; };
2C5E957D227097E0009CA9BE /* NCUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C5E957B227097E0009CA9BE /* NCUtils.m */; };
2C604BD9211988A700D34DCD /* SystemMessageTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C604BD8211988A700D34DCD /* SystemMessageTableViewCell.m */; };
2C62AFAE24C08845007E460A /* ShareExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 2C62AFA324C08845007E460A /* ShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
@ -452,6 +456,9 @@
2C5BFBE928772A9A00E75118 /* NCUnifiedSearchController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCUnifiedSearchController.swift; sourceTree = "<group>"; };
2C5BFBEB28895E6A00E75118 /* ObjectShareMessageTableViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ObjectShareMessageTableViewCell.h; sourceTree = "<group>"; };
2C5BFBEC28895E6B00E75118 /* ObjectShareMessageTableViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ObjectShareMessageTableViewCell.m; sourceTree = "<group>"; };
2C5BFBEE288A947800E75118 /* PollVotingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollVotingView.swift; sourceTree = "<group>"; };
2C5BFBF0288A97D800E75118 /* NCPoll.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NCPoll.h; sourceTree = "<group>"; };
2C5BFBF1288A97D800E75118 /* NCPoll.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NCPoll.m; sourceTree = "<group>"; };
2C5E957B227097E0009CA9BE /* NCUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NCUtils.m; sourceTree = "<group>"; };
2C5E957C227097E0009CA9BE /* NCUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NCUtils.h; sourceTree = "<group>"; };
2C604A2A25E4556E00F23615 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = "<group>"; };
@ -1136,6 +1143,7 @@
2CC32E9027F45AE000BB8C39 /* ReactionsViewCell.swift */,
2CC32E9127F45AE000BB8C39 /* ReactionsViewCell.xib */,
2C44B4D027FF05A000AD1C86 /* ReactionsSummaryView.swift */,
2C5BFBEE288A947800E75118 /* PollVotingView.swift */,
);
name = "Chat views";
sourceTree = "<group>";
@ -1297,6 +1305,8 @@
1FEDE3C4257D439500853F79 /* NCChatFileController.m */,
1F5CDF622584E78900B0026E /* NCChatFileStatus.h */,
1F5CDF632584E78900B0026E /* NCChatFileStatus.m */,
2C5BFBF0288A97D800E75118 /* NCPoll.h */,
2C5BFBF1288A97D800E75118 /* NCPoll.m */,
2CA15543208E41B500CE8EF0 /* NCChatViewController.h */,
2CA15544208E41B500CE8EF0 /* NCChatViewController.m */,
2C43BA7421309A1000B3068A /* NCMessageParameter.h */,
@ -1710,6 +1720,7 @@
2C78EFA91F87EF39008AFA74 /* NBMPeersFlowLayout.m in Sources */,
2C1ABDE5257F883400AEDFB6 /* ABContact.m in Sources */,
2CA1CCDB1F1F6FCA002FE6A2 /* RoomTableViewCell.m in Sources */,
2C5BFBEF288A947900E75118 /* PollVotingView.swift in Sources */,
2CA52AD0267613CB00619610 /* VoiceMessageTableViewCell.m in Sources */,
2C1EF36B25505DCE007C9768 /* NCNavigationController.m in Sources */,
DA755811278EF3EF00A48A1B /* UserSettingsTableViewCell.swift in Sources */,
@ -1821,6 +1832,7 @@
2C4DE9F221F732B40096940D /* NCAudioController.m in Sources */,
2C8A2BC9221F094F00DE6D2C /* DirectoryTableViewController.m in Sources */,
1F61C76B285F65E1004D74D8 /* SimpleTableViewController.swift in Sources */,
2C5BFBF2288A97D800E75118 /* NCPoll.m in Sources */,
2C42ADB420B58E6300296DEA /* NCChatController.m in Sources */,
2C4CDCD026A84AEA0023F403 /* ShareViewController.m in Sources */,
2C4446EC265D25BA00DF1DBC /* NCKeyChainController.m in Sources */,
@ -1884,6 +1896,7 @@
2C62B00924C1BDBD007E460A /* NCAPISessionManager.m in Sources */,
2CC32E9A27F5DADB00BB8C39 /* NCChatReaction.m in Sources */,
2C62AFBB24C1B7B1007E460A /* NCDatabaseManager.m in Sources */,
2C5BFBF4288AA37F00E75118 /* NCPoll.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1902,6 +1915,7 @@
2C4446F4265D51A600DF1DBC /* NCPushNotificationsUtils.m in Sources */,
2CC0019A24A37A7C00A20167 /* UIImageView+Letters.m in Sources */,
2C4446DE2658158000DF1DBC /* NCChatBlock.m in Sources */,
2C5BFBF3288AA37F00E75118 /* NCPoll.m in Sources */,
2C4446D9265814D100DF1DBC /* ServerCapabilities.m in Sources */,
2CC001CE24A37ACA00A20167 /* NCRoom.m in Sources */,
2CC0017324A3795B00A20167 /* NCImageSessionManager.m in Sources */,

Просмотреть файл

@ -24,6 +24,7 @@
#import "AFNetworking.h"
#import "AFImageDownloader.h"
#import "NCPoll.h"
#import "NCRoom.h"
#import "NCUser.h"
@ -67,6 +68,8 @@ typedef void (^GetSharedItemsCompletionBlock)(NSArray *sharedItems, NSInteger la
typedef void (^MessageReactionCompletionBlock)(NSDictionary *reactionsDict, NSError *error, NSInteger statusCode);
typedef void (^PollCompletionBlock)(NCPoll *poll, NSError *error, NSInteger statusCode);
typedef void (^SendSignalingMessagesCompletionBlock)(NSError *error);
typedef void (^PullSignalingMessagesCompletionBlock)(NSDictionary *messages, NSError *error);
typedef void (^GetSignalingSettingsCompletionBlock)(NSDictionary *settings, NSError *error);
@ -118,6 +121,7 @@ extern NSInteger const kReceivedChatMessagesLimit;
- (NSInteger)callAPIVersionForAccount:(TalkAccount *)account;
- (NSInteger)chatAPIVersionForAccount:(TalkAccount *)accounts;
- (NSInteger)reactionsAPIVersionForAccount:(TalkAccount *)account;
- (NSInteger)pollsAPIVersionForAccount:(TalkAccount *)account;
- (NSInteger)signalingAPIVersionForAccount:(TalkAccount *)account;
// Contacts Controller
@ -178,6 +182,12 @@ extern NSInteger const kReceivedChatMessagesLimit;
- (NSURLSessionDataTask *)removeReaction:(NSString *)reaction fromMessage:(NSInteger)messageId inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(MessageReactionCompletionBlock)block;
- (NSURLSessionDataTask *)getReactions:(NSString *)reaction fromMessage:(NSInteger)messageId inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(MessageReactionCompletionBlock)block;
// Polls Controller
- (NSURLSessionDataTask *)createPollWithQuestion:(NSString *)question options:(NSArray *)options resultMode:(NCPollMode)resultMode maxVotes:(NSInteger)maxVotes inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(PollCompletionBlock)block;
- (NSURLSessionDataTask *)getPollWithId:(NSInteger)pollId inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(PollCompletionBlock)block;
- (NSURLSessionDataTask *)voteOnPollWithId:(NSInteger)pollId inRoom:(NSString *)token withOptions:(NSArray *)options forAccount:(TalkAccount *)account withCompletionBlock:(PollCompletionBlock)block;
- (NSURLSessionDataTask *)closePollWithId:(NSInteger)pollId inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(PollCompletionBlock)block;
// Signaling Controller
- (NSURLSessionDataTask *)sendSignalingMessages:(NSString *)messages toRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(SendSignalingMessagesCompletionBlock)block;
- (NSURLSessionDataTask *)pullSignalingMessagesFromRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(PullSignalingMessagesCompletionBlock)block;

Просмотреть файл

@ -156,6 +156,11 @@ NSInteger const kReceivedChatMessagesLimit = 100;
return APIv1;
}
- (NSInteger)pollsAPIVersionForAccount:(TalkAccount *)account
{
return APIv1;
}
- (NSInteger)signalingAPIVersionForAccount:(TalkAccount *)account
{
NSInteger signalingAPIVersion = APIv1;
@ -1506,6 +1511,117 @@ NSInteger const kReceivedChatMessagesLimit = 100;
return task;
}
#pragma mark - Polls Controller
- (NSURLSessionDataTask *)createPollWithQuestion:(NSString *)question options:(NSArray *)options resultMode:(NCPollMode)resultMode maxVotes:(NSInteger)maxVotes inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(PollCompletionBlock)block
{
NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
NSString *endpoint = [NSString stringWithFormat:@"poll/%@", encodedToken];
NSInteger pollsAPIVersion = [self pollsAPIVersionForAccount:account];
NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:pollsAPIVersion forAccount:account];
NSDictionary *parameters = @{@"question" : question,
@"options" : options,
@"resultMode" : @(resultMode),
@"maxVotes" : @(maxVotes)
};
NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSDictionary *pollDict = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
NCPoll *poll = [NCPoll initWithPollDictionary:pollDict];
if (block) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
block(poll, nil, httpResponse.statusCode);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSInteger statusCode = [self getResponseStatusCode:task.response];
[self checkResponseStatusCode:statusCode forAccount:account];
if (block) {
block(nil, error, statusCode);
}
}];
return task;
}
- (NSURLSessionDataTask *)getPollWithId:(NSInteger)pollId inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(PollCompletionBlock)block
{
NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
NSString *endpoint = [NSString stringWithFormat:@"poll/%@/%ld", encodedToken, (long)pollId];
NSInteger pollsAPIVersion = [self pollsAPIVersionForAccount:account];
NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:pollsAPIVersion forAccount:account];
NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSDictionary *pollDict = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
NCPoll *poll = [NCPoll initWithPollDictionary:pollDict];
if (block) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
block(poll, nil, httpResponse.statusCode);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSInteger statusCode = [self getResponseStatusCode:task.response];
[self checkResponseStatusCode:statusCode forAccount:account];
if (block) {
block(nil, error, statusCode);
}
}];
return task;
}
- (NSURLSessionDataTask *)voteOnPollWithId:(NSInteger)pollId inRoom:(NSString *)token withOptions:(NSArray *)options forAccount:(TalkAccount *)account withCompletionBlock:(PollCompletionBlock)block
{
NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
NSString *endpoint = [NSString stringWithFormat:@"poll/%@/%ld", encodedToken, (long)pollId];
NSInteger pollsAPIVersion = [self pollsAPIVersionForAccount:account];
NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:pollsAPIVersion forAccount:account];
NSDictionary *parameters = @{@"optionIds" : options};
NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
NSURLSessionDataTask *task = [apiSessionManager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSDictionary *pollDict = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
NCPoll *poll = [NCPoll initWithPollDictionary:pollDict];
if (block) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
block(poll, nil, httpResponse.statusCode);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSInteger statusCode = [self getResponseStatusCode:task.response];
[self checkResponseStatusCode:statusCode forAccount:account];
if (block) {
block(nil, error, statusCode);
}
}];
return task;
}
- (NSURLSessionDataTask *)closePollWithId:(NSInteger)pollId inRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(PollCompletionBlock)block
{
NSString *encodedToken = [token stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
NSString *endpoint = [NSString stringWithFormat:@"poll/%@/%ld", encodedToken, (long)pollId];
NSInteger pollsAPIVersion = [self pollsAPIVersionForAccount:account];
NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:pollsAPIVersion forAccount:account];
NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
NSURLSessionDataTask *task = [apiSessionManager DELETE:URLString parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSDictionary *pollDict = [[responseObject objectForKey:@"ocs"] objectForKey:@"data"];
NCPoll *poll = [NCPoll initWithPollDictionary:pollDict];
if (block) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
block(poll, nil, httpResponse.statusCode);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSInteger statusCode = [self getResponseStatusCode:task.response];
[self checkResponseStatusCode:statusCode forAccount:account];
if (block) {
block(nil, error, statusCode);
}
}];
return task;
}
#pragma mark - Signaling Controller
- (NSURLSessionDataTask *)sendSignalingMessages:(NSString *)messages toRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(SendSignalingMessagesCompletionBlock)block;

Просмотреть файл

@ -93,7 +93,7 @@ typedef enum NCChatMessageAction {
kNCChatMessageActionAddReaction
} NCChatMessageAction;
@interface NCChatViewController () <UIGestureRecognizerDelegate, UINavigationControllerDelegate, UITextFieldDelegate, UIImagePickerControllerDelegate, UIDocumentPickerDelegate, ShareViewControllerDelegate, ShareConfirmationViewControllerDelegate, FileMessageTableViewCellDelegate, NCChatFileControllerDelegate, QLPreviewControllerDelegate, QLPreviewControllerDataSource, ChatMessageTableViewCellDelegate, ShareLocationViewControllerDelegate, LocationMessageTableViewCellDelegate, VoiceMessageTableViewCellDelegate, AVAudioRecorderDelegate, AVAudioPlayerDelegate, CNContactPickerDelegate>
@interface NCChatViewController () <UIGestureRecognizerDelegate, UINavigationControllerDelegate, UITextFieldDelegate, UIImagePickerControllerDelegate, UIDocumentPickerDelegate, ShareViewControllerDelegate, ShareConfirmationViewControllerDelegate, FileMessageTableViewCellDelegate, NCChatFileControllerDelegate, QLPreviewControllerDelegate, QLPreviewControllerDataSource, ChatMessageTableViewCellDelegate, ShareLocationViewControllerDelegate, LocationMessageTableViewCellDelegate, VoiceMessageTableViewCellDelegate, ObjectShareMessageTableViewCellDelegate, AVAudioRecorderDelegate, AVAudioPlayerDelegate, CNContactPickerDelegate>
@property (nonatomic, strong) NCChatController *chatController;
@property (nonatomic, strong) NCChatTitleView *titleView;
@ -3433,7 +3433,7 @@ NSString * const NCChatViewControllerTalkToUserNotification = @"NCChatViewContro
if (message.poll) {
NSString *pollCellIdentifier = (message.isGroupMessage) ? GroupedObjectShareMessageCellIdentifier : ObjectShareMessageCellIdentifier;
ObjectShareMessageTableViewCell *pollCell = (ObjectShareMessageTableViewCell *)[self.tableView dequeueReusableCellWithIdentifier:pollCellIdentifier];
// locationCell.delegate = self;
pollCell.delegate = self;
[pollCell setupForMessage:message withLastCommonReadMessage:_room.lastCommonReadMessage];
@ -3852,6 +3852,26 @@ NSString * const NCChatViewControllerTalkToUserNotification = @"NCChatViewContro
[self presentViewController:mapNC animated:YES completion:nil];
}
#pragma mark - ObjectShareMessageTableViewCellDelegate
- (void)cellWantsToOpenPoll:(NCMessageParameter *)poll
{
UITableViewStyle style = UITableViewStyleGrouped;
if (@available(iOS 13.0, *)) {
style = UITableViewStyleInsetGrouped;
}
PollVotingView *pollVC = [[PollVotingView alloc] initWithStyle:style];
NCNavigationController *pollNC = [[NCNavigationController alloc] initWithRootViewController:pollVC];
[self presentViewController:pollNC animated:YES completion:nil];
TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount];
[[NCAPIController sharedInstance] getPollWithId:poll.parameterId.integerValue inRoom:_room.token forAccount:activeAccount withCompletionBlock:^(NCPoll *poll, NSError *error, NSInteger statusCode) {
if (!error) {
[pollVC updatePollWithPoll:poll];
}
}];
}
#pragma mark - ChatMessageTableViewCellDelegate
- (void)cellWantsToScrollToMessage:(NCChatMessage *)message {

53
NextcloudTalk/NCPoll.h Normal file
Просмотреть файл

@ -0,0 +1,53 @@
/**
* @copyright Copyright (c) 2022 Ivan Sein <ivan@nextcloud.com>
*
* @author Ivan Sein <ivan@nextcloud.com>
*
* @license GNU GPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#import <Foundation/Foundation.h>
typedef enum NCPollStatus {
NCPollStatusOpen = 0,
NCPollStatusClosed
} NCPollStatus;
typedef enum NCPollMode {
NCPollModePublic = 0,
NCPollModeHidden
} NCPollMode;
@interface NCPoll : NSObject
@property (nonatomic, assign) NSInteger pollId;
@property (nonatomic, strong) NSString *question;
@property (nonatomic, strong) NSArray *options;
@property (nonatomic, strong) NSDictionary *votes;
@property (nonatomic, strong) NSString *actorType;
@property (nonatomic, strong) NSString *actorId;
@property (nonatomic, strong) NSString *actorDisplayName;
@property (nonatomic, assign) NCPollStatus status;
@property (nonatomic, assign) NCPollMode resultMode;
@property (nonatomic, assign) NSInteger maxVotes;
@property (nonatomic, strong) NSArray *votedSelf;
@property (nonatomic, assign) NSInteger numVoters;
@property (nonatomic, strong) NSArray *details;
+ (instancetype)initWithPollDictionary:(NSDictionary *)pollDict;
@end

51
NextcloudTalk/NCPoll.m Normal file
Просмотреть файл

@ -0,0 +1,51 @@
/**
* @copyright Copyright (c) 2022 Ivan Sein <ivan@nextcloud.com>
*
* @author Ivan Sein <ivan@nextcloud.com>
*
* @license GNU GPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#import "NCPoll.h"
@implementation NCPoll
+ (instancetype)initWithPollDictionary:(NSDictionary *)pollDict
{
if (!pollDict || ![pollDict isKindOfClass:[NSDictionary class]]) {
return nil;
}
NCPoll *poll = [[NCPoll alloc] init];
poll.pollId = [[pollDict objectForKey:@"id"] integerValue];
poll.question = [pollDict objectForKey:@"question"];
poll.options = [pollDict objectForKey:@"options"];
poll.votes = [pollDict objectForKey:@"votes"];
poll.actorType = [pollDict objectForKey:@"actorType"];
poll.actorId = [pollDict objectForKey:@"actorId"];
poll.actorDisplayName = [pollDict objectForKey:@"actorDisplayName"];
poll.status = (NCPollStatus)[[pollDict objectForKey:@"status"] integerValue];
poll.resultMode = (NCPollMode)[[pollDict objectForKey:@"resultMode"] integerValue];
poll.maxVotes = [[pollDict objectForKey:@"maxVotes"] integerValue];
poll.votedSelf = [pollDict objectForKey:@"votedSelf"];
poll.numVoters = [[pollDict objectForKey:@"numVoters"] integerValue];
poll.details = [pollDict objectForKey:@"details"];
return poll;
}
@end

Просмотреть файл

@ -38,6 +38,7 @@
#import "NCChatFileController.h"
#import "NCExternalSignalingController.h"
#import "NCNavigationController.h"
#import "NCPoll.h"
#import "NCSettingsController.h"
#import "NCUserDefaults.h"
#import "NCUserInterfaceController.h"

Просмотреть файл

@ -244,7 +244,7 @@
return;
}
if (self.delegate) {
if (self.delegate && self.message.poll) {
[self.delegate cellWantsToOpenPoll:self.objectParameter];
}
}

Просмотреть файл

@ -0,0 +1,136 @@
//
// Copyright (c) 2022 Ivan Sein <ivan@nextcloud.com>
//
// Author Ivan Sein <ivan@nextcloud.com>
//
// GNU GPL version 3 or any later version
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
import UIKit
@objcMembers class PollVotingView: UITableViewController {
enum PollSection: Int {
case kPollSectionQuestion = 0
case kPollSectionOptions
case kPollSectionCount
}
var poll: NCPoll = NCPoll()
var pollBackgroundView: PlaceholderView = PlaceholderView(for: .grouped)
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.setupPollView()
}
required override init(style: UITableView.Style) {
super.init(style: style)
self.setupPollView()
}
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: NCAppBranding.themeTextColor()]
self.navigationController?.navigationBar.tintColor = NCAppBranding.themeTextColor()
self.navigationController?.navigationBar.barTintColor = NCAppBranding.themeColor()
self.navigationController?.navigationBar.isTranslucent = false
self.navigationItem.title = NSLocalizedString("Poll", comment: "")
if #available(iOS 13.0, *) {
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.titleTextAttributes = [.foregroundColor: NCAppBranding.themeTextColor()]
appearance.backgroundColor = NCAppBranding.themeColor()
self.navigationItem.standardAppearance = appearance
self.navigationItem.compactAppearance = appearance
self.navigationItem.scrollEdgeAppearance = appearance
}
pollBackgroundView.placeholderView.isHidden = true
pollBackgroundView.loadingView.startAnimating()
self.tableView.backgroundView = pollBackgroundView
self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(self.cancelButtonPressed))
self.navigationItem.leftBarButtonItem?.tintColor = NCAppBranding.themeTextColor()
}
func cancelButtonPressed() {
self.dismiss(animated: true, completion: nil)
}
func setupPollView() {
self.tableView.dataSource = self
self.tableView.delegate = self
self.tableView.register(UINib(nibName: kShareTableCellNibName, bundle: .main), forCellReuseIdentifier: kShareCellIdentifier)
self.tableView.separatorInset = UIEdgeInsets(top: 0, left: 54, bottom: 0, right: 0)
}
func updatePoll(poll: NCPoll) {
self.poll = poll
pollBackgroundView.loadingView.stopAnimating()
pollBackgroundView.loadingView.isHidden = true
self.tableView.reloadData()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return PollSection.kPollSectionCount.rawValue
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case PollSection.kPollSectionQuestion.rawValue:
return poll.question != nil ? 1 : 0
case PollSection.kPollSectionOptions.rawValue:
return poll.options?.count ?? 0
default:
return 0
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let pollQuestionCellIdentifier = "pollQuestionCellIdentifier"
let pollOptionCellIdentifier = "pollOptionCellIdentifier"
var cell = UITableViewCell()
switch indexPath.section {
case PollSection.kPollSectionQuestion.rawValue:
cell = UITableViewCell(style: .default, reuseIdentifier: pollQuestionCellIdentifier)
cell.textLabel?.text = poll.question
cell.textLabel?.numberOfLines = 4
cell.textLabel?.lineBreakMode = .byWordWrapping
cell.textLabel?.sizeToFit()
cell.imageView?.image = UIImage(named: "poll")?.withRenderingMode(.alwaysTemplate)
cell.imageView?.tintColor = UIColor(red: 0.43, green: 0.43, blue: 0.45, alpha: 1)
case PollSection.kPollSectionOptions.rawValue:
cell = UITableViewCell(style: .value1, reuseIdentifier: pollOptionCellIdentifier)
cell.textLabel?.text = poll.options[indexPath.row] as? String
cell.textLabel?.numberOfLines = 4
cell.textLabel?.lineBreakMode = .byWordWrapping
cell.textLabel?.sizeToFit()
cell.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
default:
break
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
}