blob: 23d629256ee41cc4bb9e4d1534c9471170cc0532 [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>
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040035
36#import "AccSipGeneralVC.h"
37#import "views/NSColor+RingTheme.h"
38#import "views/NSImage+Extensions.h"
39
40@interface AccSipGeneralVC ()
41
42@property (unsafe_unretained) IBOutlet NSButton* photoView;
43@property (unsafe_unretained) IBOutlet NSImageView* addProfilePhotoImage;
44@property (unsafe_unretained) IBOutlet NSTextField* displayNameField;
45@property (unsafe_unretained) IBOutlet NSTextField* userNameField;
46@property (unsafe_unretained) IBOutlet NSSecureTextField* passwordField;
47@property (unsafe_unretained) IBOutlet NSTextField* proxyField;
48@property (unsafe_unretained) IBOutlet NSTextField* voicemailField;
49@property (unsafe_unretained) IBOutlet NSTextField* serverField;
50@property (unsafe_unretained) IBOutlet NSButton* removeAccountButton;
51@property (unsafe_unretained) IBOutlet NSButton* editAccountButton;
52@property std::string selectedAccountID;
53
54@end
55
56@implementation AccSipGeneralVC
57
58//Tags for views
59typedef NS_ENUM(NSInteger, TagViews) {
60 DISPLAYNAME = 100
61};
62
63@synthesize accountModel;
64@synthesize delegate;
65@synthesize photoView,addProfilePhotoImage,displayNameField, userNameField, passwordField,proxyField,voicemailField, serverField, removeAccountButton, editAccountButton;
66
67-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil accountmodel:(lrc::api::NewAccountModel*) accountModel
68{
69 if (self = [self initWithNibName: nibNameOrNil bundle:nibBundleOrNil])
70 {
71 self.accountModel= accountModel;
72 }
73 return self;
74}
75
76-(void)viewDidLoad {
77 [super viewDidLoad];
Kateryna Kostiuka8525942018-10-17 14:33:39 -040078 [[self view] setAutoresizingMask: NSViewMinXMargin | NSViewMaxXMargin];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040079 [photoView setBordered:YES];
80 [addProfilePhotoImage setWantsLayer: YES];
81 [self setEditingMode:NO];
82 [self updateView];
83}
84
85- (void)pictureTakerDidEnd:(IKPictureTaker *) picker
86 returnCode:(NSInteger) code
87 contextInfo:(void*) contextInfo
88{
Kateryna Kostiuk256814e2018-09-04 14:47:33 -040089 //do nothing when editing canceled
90 if (code == 0) {
91 return;
92 }
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -040093 if (auto outputImage = [picker outputImage]) {
94 [photoView setBordered:NO];
95 auto image = [picker inputImage];
96 CGFloat newSize = MIN(image.size.height, image.size.width);
97 outputImage = [outputImage cropImageToSize:CGSizeMake(newSize, newSize)];
98 [photoView setImage: [outputImage roundCorners: outputImage.size.height * 0.5]];
99 [addProfilePhotoImage setHidden:YES];
100 auto imageToBytes = QByteArray::fromNSData([outputImage TIFFRepresentation]).toBase64();
101 std::string imageToString = std::string(imageToBytes.constData(), imageToBytes.length());
102 self.accountModel->setAvatar(self.selectedAccountID, imageToString);
103 } else if(!photoView.image) {
104 [photoView setBordered:YES];
105 [addProfilePhotoImage setHidden:NO];
106 }
107}
108
109#pragma mark - NSTextFieldDelegate methods
110
111- (BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor
112{
113 return YES;
114}
115
116- (IBAction)triggerAdwancedSettings: (NSButton *)sender {
117 [self.delegate triggerAdvancedOptions];
118}
119
120- (void) setSelectedAccount:(std::string) account {
121 self.selectedAccountID = account;
122 [self updateView];
123}
124
125-(void)updateView {
126 const auto& account = accountModel->getAccountInfo(self.selectedAccountID);
Kateryna Kostiuk43a79232018-10-18 15:45:18 -0400127 NSData *imageData = [[NSData alloc] initWithBase64EncodedString:@(account.profileInfo.avatar.c_str()) options:NSDataBase64DecodingIgnoreUnknownCharacters];
128 NSImage *image = [[NSImage alloc] initWithData:imageData];
129 if(image) {
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400130 [photoView setBordered:NO];
Kateryna Kostiuk43a79232018-10-18 15:45:18 -0400131 [photoView setImage: [image roundCorners: 350]];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400132 [addProfilePhotoImage setHidden:YES];
133 } else {
134 [photoView setImage:nil];
135 [photoView setBordered:YES];
136 [addProfilePhotoImage setHidden:NO];
137 }
138 NSString* displayName = @(account.profileInfo.alias.c_str());
139 [displayNameField setStringValue:displayName];
140
141 NSMutableAttributedString *colorTitle = [[NSMutableAttributedString alloc] initWithAttributedString:[removeAccountButton attributedTitle]];
142 NSRange titleRange = NSMakeRange(0, [colorTitle length]);
143 [colorTitle addAttribute:NSForegroundColorAttributeName value:[NSColor errorColor] range:titleRange];
144 [removeAccountButton setAttributedTitle:colorTitle];
145 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
146 [passwordField setStringValue: @(accountProperties.password.c_str())];
147 [proxyField setStringValue: @(accountProperties.routeset.c_str())];
148 [userNameField setStringValue: @(accountProperties.username.c_str())];
149 [serverField setStringValue: @(accountProperties.hostname.c_str())];
150 [voicemailField setStringValue: @(accountProperties.mailbox.c_str())];
151 self.accountEnabled = account.enabled;
152}
153
154#pragma mark - Actions
155
156- (IBAction)editPhoto:(id)sender
157{
158 auto pictureTaker = [IKPictureTaker pictureTaker];
Kateryna Kostiuk91b44e32018-09-28 17:08:02 -0400159 if (@available(macOS 10.14, *)) {
160 AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
161 if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied)
162 {
163 [pictureTaker setValue:0 forKey:IKPictureTakerAllowsVideoCaptureKey];
164 }
165
166 if(authStatus == AVAuthorizationStatusNotDetermined)
167 {
168 [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
169 if(!granted){
170 [pictureTaker setValue:0 forKey:IKPictureTakerAllowsVideoCaptureKey];
171 }
172 }];
173 }
174 }
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400175
176 [pictureTaker beginPictureTakerSheetForWindow:[self.view window]
177 withDelegate:self
178 didEndSelector:@selector(pictureTakerDidEnd:returnCode:contextInfo:)
179 contextInfo:nil];
180
181}
182
183- (IBAction)enableAccount: (NSButton *)sender {
184 const auto& account = accountModel->getAccountInfo(self.selectedAccountID);
185 self.accountModel->enableAccount(self.selectedAccountID, !account.enabled);
186 self.accountEnabled = account.enabled;
187 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
188 self.accountModel->setAccountConfig(self.selectedAccountID, accountProperties);
189}
190
191- (IBAction)removeAccount:(id)sender
192{
193 NSAlert *alert = [[NSAlert alloc] init];
194 [alert addButtonWithTitle:@"OK"];
195 [alert addButtonWithTitle:@"Cancel"];
196 [alert setMessageText: NSLocalizedString(@"Remove account",
197 @"Remove account alert title")];
198 [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.",
199 @"Remove account alert message")];
200
201 if ([alert runModal] == NSAlertFirstButtonReturn) {
202 self.accountModel->removeAccount(self.selectedAccountID);
203 }
204}
205
206- (IBAction)changeEditingMode:(id)sender
207{
208 if([userNameField isEditable]) {
209 [self setEditingMode:NO];
Kateryna Kostiuke2c4e082018-10-22 16:20:22 -0400210 [self saveAccount];
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400211 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 }
Kateryna Kostiuk1f8c1252018-07-30 18:18:57 -0400242 [editAccountButton setTitle:@"Edit Account"];
243 [self.view resignFirstResponder];
244}
245
246-(void) saveAccount {
247 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
248 accountProperties.hostname = [serverField.stringValue UTF8String];
249 accountProperties.password = [passwordField.stringValue UTF8String];
250 accountProperties.username = [userNameField.stringValue UTF8String];
251 accountProperties.routeset = [proxyField.stringValue UTF8String];
252 accountProperties.mailbox = [voicemailField.stringValue UTF8String];
253 self.accountModel->setAccountConfig(self.selectedAccountID, accountProperties);
254}
255
256#pragma mark - NSTextFieldDelegate delegate methods
257
258- (void)controlTextDidChange:(NSNotification *)notif
259{
260 NSTextField* textField = [notif object];
261 if (textField.tag != DISPLAYNAME) {
262 return;
263 }
264 NSString* displayName = textField.stringValue;
265
266 [NSObject cancelPreviousPerformRequestsWithTarget:self];
267 self.accountModel->setAlias(self.selectedAccountID, [displayName UTF8String]);
268 lrc::api::account::ConfProperties_t accountProperties = self.accountModel->getAccountConfig(self.selectedAccountID);
269 self.accountModel->setAccountConfig(self.selectedAccountID, accountProperties);
270}
271
272@end