blob: f0a3d0fc0f1212eeeda330febafeaab1addaa4c8 [file] [log] [blame]
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -04001/*
2 * Copyright (C) 2015-2018 Savoir-faire Linux Inc.
3 * 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>
29
30//LRC
31#import <api/lrc.h>
32#import <api/newaccountmodel.h>
33#import <api/newdevicemodel.h>
34#import <interfaces/pixmapmanipulatori.h>
35#import <globalinstances.h>
36
37#import "AccSipGeneralVC.h"
38#import "views/NSColor+RingTheme.h"
39#import "views/NSImage+Extensions.h"
40
41@interface AccSipGeneralVC ()
42
43@property (unsafe_unretained) IBOutlet NSButton* photoView;
44@property (unsafe_unretained) IBOutlet NSImageView* addProfilePhotoImage;
45@property (unsafe_unretained) IBOutlet NSTextField* displayNameField;
46@property (unsafe_unretained) IBOutlet NSTextField* userNameField;
47@property (unsafe_unretained) IBOutlet NSSecureTextField* passwordField;
48@property (unsafe_unretained) IBOutlet NSTextField* proxyField;
49@property (unsafe_unretained) IBOutlet NSTextField* voicemailField;
50@property (unsafe_unretained) IBOutlet NSTextField* serverField;
51@property (unsafe_unretained) IBOutlet NSButton* removeAccountButton;
52@property (unsafe_unretained) IBOutlet NSButton* editAccountButton;
53@property std::string selectedAccountID;
54
55@end
56
57@implementation AccSipGeneralVC
58
59//Tags for views
60typedef NS_ENUM(NSInteger, TagViews) {
61 DISPLAYNAME = 100
62};
63
64@synthesize accountModel;
65@synthesize delegate;
66@synthesize photoView,addProfilePhotoImage,displayNameField, userNameField, passwordField,proxyField,voicemailField, serverField, removeAccountButton, editAccountButton;
67
68-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil accountmodel:(lrc::api::NewAccountModel*) accountModel
69{
70 if (self = [self initWithNibName: nibNameOrNil bundle:nibBundleOrNil])
71 {
72 self.accountModel= accountModel;
73 }
74 return self;
75}
76
77-(void)viewDidLoad {
78 [super viewDidLoad];
Kateryna Kostiuk3164fb02018-08-28 17:51:43 -040079 [[self view] setAutoresizingMask: NSViewMinXMargin | NSViewMaxXMargin | NSViewHeightSizable];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040080 [photoView setBordered:YES];
81 [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]) {
95 [photoView setBordered:NO];
96 auto image = [picker inputImage];
97 CGFloat newSize = MIN(image.size.height, image.size.width);
98 outputImage = [outputImage cropImageToSize:CGSizeMake(newSize, newSize)];
99 [photoView setImage: [outputImage roundCorners: outputImage.size.height * 0.5]];
100 [addProfilePhotoImage setHidden:YES];
101 auto imageToBytes = QByteArray::fromNSData([outputImage TIFFRepresentation]).toBase64();
102 std::string imageToString = std::string(imageToBytes.constData(), imageToBytes.length());
103 self.accountModel->setAvatar(self.selectedAccountID, imageToString);
104 } else if(!photoView.image) {
105 [photoView setBordered:YES];
106 [addProfilePhotoImage setHidden:NO];
107 }
108}
109
110#pragma mark - NSTextFieldDelegate methods
111
112- (BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor
113{
114 return YES;
115}
116
117- (IBAction)triggerAdwancedSettings: (NSButton *)sender {
118 [self.delegate triggerAdvancedOptions];
119}
120
121- (void) setSelectedAccount:(std::string) account {
122 self.selectedAccountID = account;
123 [self updateView];
124}
125
126-(void)updateView {
127 const auto& account = accountModel->getAccountInfo(self.selectedAccountID);
Kateryna Kostiuk43a79232018-10-18 15:45:18 -0400128 NSData *imageData = [[NSData alloc] initWithBase64EncodedString:@(account.profileInfo.avatar.c_str()) options:NSDataBase64DecodingIgnoreUnknownCharacters];
129 NSImage *image = [[NSImage alloc] initWithData:imageData];
130 if(image) {
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400131 [photoView setBordered:NO];
Kateryna Kostiuk43a79232018-10-18 15:45:18 -0400132 [photoView setImage: [image roundCorners: 350]];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400133 [addProfilePhotoImage setHidden:YES];
134 } else {
135 [photoView setImage:nil];
136 [photoView setBordered:YES];
137 [addProfilePhotoImage setHidden:NO];
138 }
139 NSString* displayName = @(account.profileInfo.alias.c_str());
140 [displayNameField setStringValue:displayName];
141
142 NSMutableAttributedString *colorTitle = [[NSMutableAttributedString alloc] initWithAttributedString:[removeAccountButton attributedTitle]];
143 NSRange titleRange = NSMakeRange(0, [colorTitle length]);
144 [colorTitle addAttribute:NSForegroundColorAttributeName value:[NSColor errorColor] range:titleRange];
145 [removeAccountButton setAttributedTitle:colorTitle];
146 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
147 [passwordField setStringValue: @(accountProperties.password.c_str())];
148 [proxyField setStringValue: @(accountProperties.routeset.c_str())];
149 [userNameField setStringValue: @(accountProperties.username.c_str())];
150 [serverField setStringValue: @(accountProperties.hostname.c_str())];
151 [voicemailField setStringValue: @(accountProperties.mailbox.c_str())];
152 self.accountEnabled = account.enabled;
153}
154
155#pragma mark - Actions
156
157- (IBAction)editPhoto:(id)sender
158{
159 auto pictureTaker = [IKPictureTaker pictureTaker];
Kateryna Kostiuk91b44e32018-09-28 17:08:02 -0400160 if (@available(macOS 10.14, *)) {
161 AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
162 if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied)
163 {
164 [pictureTaker setValue:0 forKey:IKPictureTakerAllowsVideoCaptureKey];
165 }
166
167 if(authStatus == AVAuthorizationStatusNotDetermined)
168 {
169 [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
170 if(!granted){
171 [pictureTaker setValue:0 forKey:IKPictureTakerAllowsVideoCaptureKey];
172 }
173 }];
174 }
175 }
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400176
177 [pictureTaker beginPictureTakerSheetForWindow:[self.view window]
178 withDelegate:self
179 didEndSelector:@selector(pictureTakerDidEnd:returnCode:contextInfo:)
180 contextInfo:nil];
181
182}
183
184- (IBAction)enableAccount: (NSButton *)sender {
185 const auto& account = accountModel->getAccountInfo(self.selectedAccountID);
186 self.accountModel->enableAccount(self.selectedAccountID, !account.enabled);
187 self.accountEnabled = account.enabled;
188 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
189 self.accountModel->setAccountConfig(self.selectedAccountID, accountProperties);
190}
191
192- (IBAction)removeAccount:(id)sender
193{
194 NSAlert *alert = [[NSAlert alloc] init];
195 [alert addButtonWithTitle:@"OK"];
196 [alert addButtonWithTitle:@"Cancel"];
197 [alert setMessageText: NSLocalizedString(@"Remove account",
198 @"Remove account alert title")];
199 [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.",
200 @"Remove account alert message")];
201
202 if ([alert runModal] == NSAlertFirstButtonReturn) {
203 self.accountModel->removeAccount(self.selectedAccountID);
204 }
205}
206
207- (IBAction)changeEditingMode:(id)sender
208{
209 if([userNameField isEditable]) {
210 [self setEditingMode:NO];
211 return;
212 }
213 [self setEditingMode:YES];
214}
215
216-(void) setEditingMode:(BOOL) shouldEdit {
217 [userNameField setEditable:shouldEdit];
218 [passwordField setEditable:shouldEdit];
219 [proxyField setEditable:shouldEdit];
220 [voicemailField setEditable:shouldEdit];
221 [serverField setEditable:shouldEdit];
222 [userNameField setDrawsBackground:!shouldEdit];
223 [passwordField setDrawsBackground:!shouldEdit];
224 [proxyField setDrawsBackground:!shouldEdit];
225 [voicemailField setDrawsBackground:!shouldEdit];
226 [serverField setDrawsBackground:!shouldEdit];
227 [userNameField setBezeled:shouldEdit];
228 [passwordField setBezeled:shouldEdit];
229 [proxyField setBezeled:shouldEdit];
230 [voicemailField setBezeled:shouldEdit];
231 [serverField setBezeled:shouldEdit];
232 if(shouldEdit) {
233 [serverField setBezelStyle:NSTextFieldSquareBezel];
234 [userNameField setBezelStyle:NSTextFieldSquareBezel];
235 [passwordField setBezelStyle:NSTextFieldSquareBezel];
236 [proxyField setBezelStyle:NSTextFieldSquareBezel];
237 [voicemailField setBezelStyle:NSTextFieldSquareBezel];
238 [userNameField becomeFirstResponder];
239 [editAccountButton setTitle:@"Done"];
240 return;
241 }
242 [self saveAccount];
243 [editAccountButton setTitle:@"Edit Account"];
244 [self.view resignFirstResponder];
245}
246
247-(void) saveAccount {
248 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
249 accountProperties.hostname = [serverField.stringValue UTF8String];
250 accountProperties.password = [passwordField.stringValue UTF8String];
251 accountProperties.username = [userNameField.stringValue UTF8String];
252 accountProperties.routeset = [proxyField.stringValue UTF8String];
253 accountProperties.mailbox = [voicemailField.stringValue UTF8String];
254 self.accountModel->setAccountConfig(self.selectedAccountID, accountProperties);
255}
256
257#pragma mark - NSTextFieldDelegate delegate methods
258
259- (void)controlTextDidChange:(NSNotification *)notif
260{
261 NSTextField* textField = [notif object];
262 if (textField.tag != DISPLAYNAME) {
263 return;
264 }
265 NSString* displayName = textField.stringValue;
266
267 [NSObject cancelPreviousPerformRequestsWithTarget:self];
268 self.accountModel->setAlias(self.selectedAccountID, [displayName UTF8String]);
269 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
270 self.accountModel->setAccountConfig(self.selectedAccountID, accountProperties);
271}
272
273@end