blob: e8bbb73ce4a1f87566cee938dc7e754cae9d60a6 [file] [log] [blame]
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -04001/*
Sébastien Blin029ffa82019-01-02 17:43:48 -05002 * Copyright (C) 2015-2019 Savoir-faire Linux Inc.
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -04003 * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
4 * Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21//cocoa
22#import <Quartz/Quartz.h>
Kateryna Kostiuk91b44e32018-09-28 17:08:02 -040023#import <AVFoundation/AVFoundation.h>
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040024
25//Qt
26#import <QSize>
27#import <QtMacExtras/qmacfunctions.h>
28#import <QPixmap>
Kateryna Kostiukc867eb92020-03-08 13:15:17 -040029#import <qstring.h>
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040030
31//LRC
32#import <api/lrc.h>
33#import <api/newaccountmodel.h>
34#import <api/newdevicemodel.h>
35#import <interfaces/pixmapmanipulatori.h>
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040036
37#import "AccSipGeneralVC.h"
38#import "views/NSColor+RingTheme.h"
39#import "views/NSImage+Extensions.h"
Kateryna Kostiuk2f2ef952019-05-07 11:04:41 -040040#import "Constants.h"
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040041
42@interface AccSipGeneralVC ()
43
44@property (unsafe_unretained) IBOutlet NSButton* photoView;
45@property (unsafe_unretained) IBOutlet NSImageView* addProfilePhotoImage;
46@property (unsafe_unretained) IBOutlet NSTextField* displayNameField;
47@property (unsafe_unretained) IBOutlet NSTextField* userNameField;
48@property (unsafe_unretained) IBOutlet NSSecureTextField* passwordField;
49@property (unsafe_unretained) IBOutlet NSTextField* proxyField;
50@property (unsafe_unretained) IBOutlet NSTextField* voicemailField;
51@property (unsafe_unretained) IBOutlet NSTextField* serverField;
52@property (unsafe_unretained) IBOutlet NSButton* removeAccountButton;
53@property (unsafe_unretained) IBOutlet NSButton* editAccountButton;
Kateryna Kostiukc867eb92020-03-08 13:15:17 -040054@property QString selectedAccountID;
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040055
56@end
57
58@implementation AccSipGeneralVC
59
60//Tags for views
61typedef NS_ENUM(NSInteger, TagViews) {
62 DISPLAYNAME = 100
63};
64
65@synthesize accountModel;
66@synthesize delegate;
67@synthesize photoView,addProfilePhotoImage,displayNameField, userNameField, passwordField,proxyField,voicemailField, serverField, removeAccountButton, editAccountButton;
68
69-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil accountmodel:(lrc::api::NewAccountModel*) accountModel
70{
71 if (self = [self initWithNibName: nibNameOrNil bundle:nibBundleOrNil])
72 {
73 self.accountModel= accountModel;
74 }
75 return self;
76}
77
78-(void)viewDidLoad {
79 [super viewDidLoad];
Kateryna Kostiuka8525942018-10-17 14:33:39 -040080 [[self view] setAutoresizingMask: NSViewMinXMargin | NSViewMaxXMargin];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040081 [addProfilePhotoImage setWantsLayer: YES];
82 [self setEditingMode:NO];
83 [self updateView];
84}
85
86- (void)pictureTakerDidEnd:(IKPictureTaker *) picker
87 returnCode:(NSInteger) code
88 contextInfo:(void*) contextInfo
89{
Kateryna Kostiuk256814e2018-09-04 14:47:33 -040090 //do nothing when editing canceled
91 if (code == 0) {
92 return;
93 }
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040094 if (auto outputImage = [picker outputImage]) {
Kateryna Kostiuk14b8aa72020-11-11 10:40:15 -050095 NSData* imageData = [outputImage TIFFRepresentation];
96 NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData: imageData];
97 NSDictionary *properties = [[NSDictionary alloc] init];
98 imageData = [imageRep representationUsingType:NSPNGFileType properties: properties];
99 NSString * dataString = [imageData base64EncodedStringWithOptions:0];
100 self.accountModel->setAvatar(self.selectedAccountID, QString::fromNSString(dataString));
Kateryna Kostiukec0ba5c2020-12-03 16:46:42 -0500101 [self updateAvatar];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400102 } else if(!photoView.image) {
103 [photoView setBordered:YES];
104 [addProfilePhotoImage setHidden:NO];
105 }
106}
107
Kateryna Kostiukec0ba5c2020-12-03 16:46:42 -0500108-(void)updateAvatar {
109 const auto& account = accountModel->getAccountInfo(self.selectedAccountID);
110 @autoreleasepool {
111 NSData *imageData = [[NSData alloc] initWithBase64EncodedString:account.profileInfo.avatar.toNSString() options:NSDataBase64DecodingIgnoreUnknownCharacters];
112 NSImage *image = [[NSImage alloc] initWithData:imageData];
113 if(image) {
114 [photoView setBordered:NO];
115 [photoView setImage: [image roundCorners: image.size.height * 0.5]];
116 [addProfilePhotoImage setHidden:YES];
117 } else {
118 [photoView setImage:nil];
119 [photoView setBordered:YES];
120 [addProfilePhotoImage setHidden:NO];
121 }
122 }
123}
124
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400125#pragma mark - NSTextFieldDelegate methods
126
127- (BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor
128{
129 return YES;
130}
131
132- (IBAction)triggerAdwancedSettings: (NSButton *)sender {
Kateryna Kostiuk034eab32020-11-17 14:59:41 -0500133 [self.view.window makeFirstResponder:nil];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400134 [self.delegate triggerAdvancedOptions];
135}
136
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400137- (void) setSelectedAccount:(const QString&) account {
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400138 self.selectedAccountID = account;
139 [self updateView];
140}
141
142-(void)updateView {
143 const auto& account = accountModel->getAccountInfo(self.selectedAccountID);
Kateryna Kostiukec0ba5c2020-12-03 16:46:42 -0500144 [self updateAvatar];
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400145 NSString* displayName = account.profileInfo.alias.toNSString();
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400146 [displayNameField setStringValue:displayName];
147
148 NSMutableAttributedString *colorTitle = [[NSMutableAttributedString alloc] initWithAttributedString:[removeAccountButton attributedTitle]];
149 NSRange titleRange = NSMakeRange(0, [colorTitle length]);
150 [colorTitle addAttribute:NSForegroundColorAttributeName value:[NSColor errorColor] range:titleRange];
151 [removeAccountButton setAttributedTitle:colorTitle];
152 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400153 [passwordField setStringValue: accountProperties.password.toNSString()];
154 [proxyField setStringValue: accountProperties.routeset.toNSString()];
155 [userNameField setStringValue: accountProperties.username.toNSString()];
156 [serverField setStringValue: accountProperties.hostname.toNSString()];
157 [voicemailField setStringValue: accountProperties.mailbox.toNSString()];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400158 self.accountEnabled = account.enabled;
159}
160
161#pragma mark - Actions
162
163- (IBAction)editPhoto:(id)sender
164{
165 auto pictureTaker = [IKPictureTaker pictureTaker];
Kateryna Kostiukdc563242019-08-19 12:05:54 -0400166#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101400
Kateryna Kostiuk91b44e32018-09-28 17:08:02 -0400167 if (@available(macOS 10.14, *)) {
168 AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
169 if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied)
170 {
171 [pictureTaker setValue:0 forKey:IKPictureTakerAllowsVideoCaptureKey];
172 }
173
174 if(authStatus == AVAuthorizationStatusNotDetermined)
175 {
176 [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
177 if(!granted){
178 [pictureTaker setValue:0 forKey:IKPictureTakerAllowsVideoCaptureKey];
179 }
180 }];
181 }
182 }
Kateryna Kostiukdc563242019-08-19 12:05:54 -0400183#endif
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400184
185 [pictureTaker beginPictureTakerSheetForWindow:[self.view window]
186 withDelegate:self
187 didEndSelector:@selector(pictureTakerDidEnd:returnCode:contextInfo:)
188 contextInfo:nil];
189
190}
191
192- (IBAction)enableAccount: (NSButton *)sender {
193 const auto& account = accountModel->getAccountInfo(self.selectedAccountID);
Kateryna Kostiuk53799642019-07-30 18:21:16 -0400194 self.accountModel->setAccountEnabled(self.selectedAccountID, !account.enabled);
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400195 self.accountEnabled = account.enabled;
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400196}
197
198- (IBAction)removeAccount:(id)sender
199{
200 NSAlert *alert = [[NSAlert alloc] init];
201 [alert addButtonWithTitle:@"OK"];
Kateryna Kostiuk92a30322020-05-08 11:11:52 -0400202 [alert addButtonWithTitle:NSLocalizedString(@"Cancel", @"Button Action")];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400203 [alert setMessageText: NSLocalizedString(@"Remove account",
204 @"Remove account alert title")];
205 [alert setInformativeText:NSLocalizedString(@"By clicking \"OK\" you will remove this account on this device! This action can not be undone. Also, your registered name can be lost.",
206 @"Remove account alert message")];
207
208 if ([alert runModal] == NSAlertFirstButtonReturn) {
209 self.accountModel->removeAccount(self.selectedAccountID);
210 }
211}
212
213- (IBAction)changeEditingMode:(id)sender
214{
215 if([userNameField isEditable]) {
216 [self setEditingMode:NO];
Kateryna Kostiuke2c4e082018-10-22 16:20:22 -0400217 [self saveAccount];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400218 return;
219 }
220 [self setEditingMode:YES];
221}
222
223-(void) setEditingMode:(BOOL) shouldEdit {
224 [userNameField setEditable:shouldEdit];
225 [passwordField setEditable:shouldEdit];
226 [proxyField setEditable:shouldEdit];
227 [voicemailField setEditable:shouldEdit];
228 [serverField setEditable:shouldEdit];
229 [userNameField setDrawsBackground:!shouldEdit];
230 [passwordField setDrawsBackground:!shouldEdit];
231 [proxyField setDrawsBackground:!shouldEdit];
232 [voicemailField setDrawsBackground:!shouldEdit];
233 [serverField setDrawsBackground:!shouldEdit];
234 [userNameField setBezeled:shouldEdit];
235 [passwordField setBezeled:shouldEdit];
236 [proxyField setBezeled:shouldEdit];
237 [voicemailField setBezeled:shouldEdit];
238 [serverField setBezeled:shouldEdit];
239 if(shouldEdit) {
240 [serverField setBezelStyle:NSTextFieldSquareBezel];
241 [userNameField setBezelStyle:NSTextFieldSquareBezel];
242 [passwordField setBezelStyle:NSTextFieldSquareBezel];
243 [proxyField setBezelStyle:NSTextFieldSquareBezel];
244 [voicemailField setBezelStyle:NSTextFieldSquareBezel];
245 [userNameField becomeFirstResponder];
Kateryna Kostiuk92a30322020-05-08 11:11:52 -0400246 [editAccountButton setTitle:NSLocalizedString(@"Done", @"Edit Sip Account Action")];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400247 return;
248 }
Kateryna Kostiuk92a30322020-05-08 11:11:52 -0400249 [editAccountButton setTitle:NSLocalizedString(@"Edit Account", @"Edit Sip Account Action")];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400250 [self.view resignFirstResponder];
251}
252
253-(void) saveAccount {
254 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400255 accountProperties.hostname = QString::fromNSString(serverField.stringValue);
256 accountProperties.password = QString::fromNSString(passwordField.stringValue);
257 accountProperties.username = QString::fromNSString(userNameField.stringValue);
258 accountProperties.routeset = QString::fromNSString(proxyField.stringValue);
259 accountProperties.mailbox = QString::fromNSString(voicemailField.stringValue);
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400260 self.accountModel->setAccountConfig(self.selectedAccountID, accountProperties);
261}
262
263#pragma mark - NSTextFieldDelegate delegate methods
264
Kateryna Kostiuk034eab32020-11-17 14:59:41 -0500265-(void)controlTextDidEndEditing:(NSNotification *)notification
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400266{
Kateryna Kostiuk034eab32020-11-17 14:59:41 -0500267 NSTextField* textField = [notification object];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400268 if (textField.tag != DISPLAYNAME) {
269 return;
270 }
271 NSString* displayName = textField.stringValue;
Kateryna Kostiukc867eb92020-03-08 13:15:17 -0400272 self.accountModel->setAlias(self.selectedAccountID, QString::fromNSString(displayName));
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400273 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
274 self.accountModel->setAccountConfig(self.selectedAccountID, accountProperties);
275}
276
277@end