Commit 0f66bd33 authored by Alexandre Lision's avatar Alexandre Lision

chat: add conversation screen

- ability to chat off call
- system notification on incoming msg
- notification in smartlist

Tuleap: #202
Change-Id: Ide10f80f677f23022ad4296a82ae122e69a892cc
parent 57227777
......@@ -111,7 +111,9 @@ SET(ringclient_CONTROLLERS
src/SmartViewVC.mm
src/SmartViewVC.h
src/BrokerVC.mm
src/BrokerVC.h)
src/BrokerVC.h
src/ConversationVC.mm
src/ConversationVC.h)
SET(ringclient_BACKENDS
src/backends/AddressBookBackend.mm
......@@ -133,7 +135,9 @@ SET(ringclient_VIEWS
src/views/ContextualTableCellView.mm
src/views/ContextualTableCellView.h
src/views/IconButton.h
src/views/IconButton.mm)
src/views/IconButton.mm
src/views/IMTableCellView.h
src/views/IMTableCellView.mm)
SET(ringclient_OTHERS
src/main.mm
......@@ -162,7 +166,8 @@ SET(ringclient_XIBS
RingWizard
CertificateWindow
PersonLinker
Broker)
Broker
Conversation)
# Icons
# This part tells CMake where to find and install the file itself
......@@ -174,6 +179,7 @@ SET(ring_ICONS
${CMAKE_CURRENT_SOURCE_DIR}/data/symbol_name.png
${CMAKE_CURRENT_SOURCE_DIR}/data/background_tile.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_accept.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_arrow_back.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_call.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_cancel.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_hangup.png
......@@ -193,6 +199,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_add_participant.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_merge_calls.png
${CMAKE_CURRENT_SOURCE_DIR}/data/default_user_icon.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ancrage.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_send.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/audio.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_person_add.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_persons.png
......
data/dark/ic_action_video.png

321 Bytes | W: | H:

data/dark/ic_action_video.png

224 Bytes | W: | H:

data/dark/ic_action_video.png
data/dark/ic_action_video.png
data/dark/ic_action_video.png
data/dark/ic_action_video.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -22,6 +22,8 @@
#import <qapplication.h>
#import <accountmodel.h>
#import <protocolmodel.h>
#import <media/recordingmodel.h>
#import <media/textrecording.h>
#import <QItemSelectionModel>
#import <account.h>
......@@ -79,13 +81,42 @@
[self showIncomingNotification:call];
}
});
QObject::connect(&Media::RecordingModel::instance(),
&Media::RecordingModel::newTextMessage,
[=](Media::TextRecording* t, ContactMethod* cm) {
BOOL shouldNotify = [[NSUserDefaults standardUserDefaults] boolForKey:Preferences::Notifications];
auto qIdx = t->instantTextMessagingModel()->index(t->instantTextMessagingModel()->rowCount()-1, 0);
// Don't show a notification if we are sending the text OR window already has focus OR user disabled notifications
if(qvariant_cast<Media::Media::Direction>(qIdx.data((int)Media::TextRecording::Role::Direction)) == Media::Media::Direction::OUT
|| self.ringWindowController.window.keyWindow || !shouldNotify)
return;
NSUserNotification* notification = [[NSUserNotification alloc] init];
NSString* localizedTitle = NSLocalizedString(([NSString stringWithFormat:@"Message from %@",
qIdx.data((int)Media::TextRecording::Role::AuthorDisplayname).toString().toNSString()]),
@"Text message notification title");
[notification setTitle:localizedTitle];
[notification setSoundName:NSUserNotificationDefaultSoundName];
[notification setSubtitle:qIdx.data().toString().toNSString()];
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
});
}
- (void) showIncomingNotification:(Call*) call{
NSUserNotification *notification = [[NSUserNotification alloc] init];
notification.title = @"Incoming call", call->peerName();
//notification.informativeText = @"A notification";
notification.soundName = NSUserNotificationDefaultSoundName;
NSString* localizedTitle = NSLocalizedString(([NSString stringWithFormat:@"Incoming call from %@",
call->peerName().toNSString()]),
@"Call notification title");
[notification setTitle:localizedTitle];
[notification setSoundName:NSUserNotificationDefaultSoundName];
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
}
......@@ -99,7 +130,6 @@
- (void) showWizard
{
NSLog(@"Showing wizard");
if(self.wizard == nil) {
self.wizard = [[RingWizardWC alloc] initWithWindowNibName:@"RingWizard"];
}
......
/*
* Copyright (C) 2016 Savoir-faire Linux Inc.
* Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#import <Cocoa/Cocoa.h>
@interface ConversationVC : NSViewController
-(void) initFrame;
-(void) animateIn;
-(IBAction) animateOut:(id)sender;
/**
* Message contained in messageField TextField.
* This is a KVO method to bind the text with the send Button
* if message.length is > 0, button is enabled, otherwise disabled
*/
@property (retain) NSString* message;
@end
This diff is collapsed.
......@@ -28,6 +28,8 @@ class Call;
}
- (void) initFrame;
-(void) initFrame;
-(void) animateIn;
-(void) animateOut;
@end
......@@ -124,7 +124,7 @@
NSButton* a = actionHash[(int) action];
if (a) {
[a setHidden:!(idx.flags() & Qt::ItemIsEnabled)];
[a setState:(idx.data(Qt::CheckStateRole) == Qt::Checked) ? NSOnState : NSOffState];
[a setHighlighted:(idx.data(Qt::CheckStateRole) == Qt::Checked) ? YES : NO];
}
}
......@@ -245,7 +245,6 @@
[=](const QModelIndex &current, const QModelIndex &previous) {
auto call = RecentModel::instance().getActiveCall(current);
if(!current.isValid() || !call) {
[self animateOut];
return;
}
......@@ -258,7 +257,6 @@
[self collapseRightView];
[self updateCall];
[self updateAllActions];
[self animateOut];
});
QObject::connect(CallModel::instance().userActionModel(),
......
......@@ -17,16 +17,24 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#import "RingWindowController.h"
#import <QuartzCore/QuartzCore.h>
//Qt
#import <QItemSelectionModel>
#import <QItemSelection>
//LRC
#import <accountmodel.h>
#import <callmodel.h>
#import <account.h>
#import <call.h>
#import <recentmodel.h>
#import "AppDelegate.h"
#import "Constants.h"
#import "CurrentCallVC.h"
#import "ConversationVC.h"
#import "PreferencesWC.h"
#import "views/NSColor+RingTheme.h"
......@@ -37,7 +45,8 @@
__unsafe_unretained IBOutlet NSTextField *ringIDLabel;
PreferencesWC *preferencesWC;
CurrentCallVC* currentVC;
CurrentCallVC* currentCallVC;
ConversationVC* offlineVC;
}
static NSString* const kPreferencesIdentifier = @"PreferencesIdentifier";
......@@ -46,23 +55,52 @@ static NSString* const kPreferencesIdentifier = @"PreferencesIdentifier";
[super windowDidLoad];
[self.window setMovableByWindowBackground:YES];
currentVC = [[CurrentCallVC alloc] initWithNibName:@"CurrentCall" bundle:nil];
currentCallVC = [[CurrentCallVC alloc] initWithNibName:@"CurrentCall" bundle:nil];
offlineVC = [[ConversationVC alloc] initWithNibName:@"Conversation" bundle:nil];
[callView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[[currentVC view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[[currentCallVC view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[[offlineVC view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[callView addSubview:[currentVC view] positioned:NSWindowAbove relativeTo:nil];
[callView addSubview:[currentCallVC view] positioned:NSWindowAbove relativeTo:nil];
[callView addSubview:[offlineVC view] positioned:NSWindowAbove relativeTo:nil];
[currentVC initFrame];
[currentCallVC initFrame];
[offlineVC initFrame];
// Fresh run, we need to make sure RingID appears
[self updateRingID];
[self connect];
}
- (void) connect
{
// Update Ring ID label based on account model changes
QObject::connect(&AccountModel::instance(),
&AccountModel::dataChanged,
[=] {
[self updateRingID];
});
QObject::connect(RecentModel::instance().selectionModel(),
&QItemSelectionModel::currentChanged,
[=](const QModelIndex &current, const QModelIndex &previous) {
auto call = RecentModel::instance().getActiveCall(current);
if(!current.isValid()) {
[offlineVC animateOut:self];
[currentCallVC animateOut];
return;
}
if (!call) {
[currentCallVC animateOut];
[offlineVC animateIn];
} else {
[currentCallVC animateIn];
[offlineVC animateOut:self];
}
});
}
/**
......
This diff is collapsed.
/*
* Copyright (C) 2016 Savoir-faire Linux Inc.
* Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#import <Cocoa/Cocoa.h>
@interface IMTableCellView : NSTableCellView
@property (nonatomic, strong) IBOutlet NSImageView* photoView;
@property (nonatomic, strong) IBOutlet NSTextView* msgView;
- (void) setup;
- (void) updateWidthConstraint:(CGFloat) newWidth;
@end
/*
* Copyright (C) 2016 Savoir-faire Linux Inc.
* Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#import "IMTableCellView.h"
#import "NSColor+RingTheme.h"
@implementation IMTableCellView
@synthesize msgView;
@synthesize photoView;
- (void) setup
{
if ([self.identifier isEqualToString:@"RightMessageView"]) {
[self.msgView setBackgroundColor:[NSColor ringBlue]];
}
[self.msgView setString:@""];
[self.msgView setAutoresizingMask:NSViewWidthSizable];
[self.msgView setEnabledTextCheckingTypes:NSTextCheckingTypeLink];
[self.msgView setAutomaticLinkDetectionEnabled:YES];
}
- (void) updateWidthConstraint:(CGFloat) newWidth
{
[self.msgView removeConstraints:[self.msgView constraints]];
NSLayoutConstraint* constraint = [NSLayoutConstraint
constraintWithItem:self.msgView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem: nil
attribute:NSLayoutAttributeWidth
multiplier:1.0f
constant:newWidth];
[self.msgView addConstraint:constraint];
}
@end
......@@ -40,53 +40,63 @@
{
[super drawRect:dirtyRect];
NSColor* backgroundColor6;
NSColor* backgroundStrokeColor5;
NSColor* backgroundColor;
NSColor* backgroundStrokeColor;
NSColor* tintColor = [NSColor whiteColor];
if (self.mouseDown || self.state == NSOnState) {
if (self.mouseDown || self.isHighlighted) {
if (self.highlightColor) {
backgroundColor6 = self.highlightColor;
backgroundStrokeColor5 = [self.highlightColor darkenColorByValue:0.1];
backgroundColor = self.highlightColor;
backgroundStrokeColor = [self.highlightColor darkenColorByValue:0.1];
} else {
backgroundColor6 = [self.bgColor darkenColorByValue:0.3];
backgroundStrokeColor5 = [self.bgColor darkenColorByValue:0.4];
backgroundColor = [self.bgColor darkenColorByValue:0.3];
backgroundStrokeColor = [self.bgColor darkenColorByValue:0.4];
}
} else if (!self.isEnabled) {
backgroundColor = [self.bgColor colorWithAlphaComponent:0.7];
backgroundStrokeColor = [self.bgColor colorWithAlphaComponent:0.7];
tintColor = [[NSColor grayColor] colorWithAlphaComponent:0.3];
} else {
backgroundColor6 = self.bgColor;
backgroundStrokeColor5 = [self.bgColor darkenColorByValue:0.1];
backgroundColor = self.bgColor;
backgroundStrokeColor = [self.bgColor darkenColorByValue:0.1];
}
//// Subframes
NSRect group = NSMakeRect(NSMinX(dirtyRect) + floor(NSWidth(dirtyRect) * 0.03333) + 0.5, NSMinY(dirtyRect) + floor(NSHeight(dirtyRect) * 0.03333) + 0.5, floor(NSWidth(dirtyRect) * 0.96667) - floor(NSWidth(dirtyRect) * 0.03333), floor(NSHeight(dirtyRect) * 0.96667) - floor(NSHeight(dirtyRect) * 0.03333));
NSRect group = NSMakeRect(NSMinX(dirtyRect) + floor(NSWidth(dirtyRect) * 0.03333) + 0.5,
NSMinY(dirtyRect) + floor(NSHeight(dirtyRect) * 0.03333) + 0.5,
floor(NSWidth(dirtyRect) * 0.96667) - floor(NSWidth(dirtyRect) * 0.03333),
floor(NSHeight(dirtyRect) * 0.96667) - floor(NSHeight(dirtyRect) * 0.03333));
//// Group
{
//// Oval Drawing
NSBezierPath* ovalPath = [NSBezierPath bezierPathWithRoundedRect:NSMakeRect(NSMinX(group) + floor(NSWidth(group) * 0.00000 + 0.5), NSMinY(group) + floor(NSHeight(group) * 0.00000 + 0.5), floor(NSWidth(group) * 1.00000 + 0.5) - floor(NSWidth(group) * 0.00000 + 0.5), floor(NSHeight(group) * 1.00000 + 0.5) - floor(NSHeight(group) * 0.00000 + 0.5)) xRadius:[self.cornerRadius floatValue] yRadius:[self.cornerRadius floatValue]];
[backgroundColor6 setFill];
NSBezierPath* ovalPath = [NSBezierPath bezierPathWithRoundedRect:
NSMakeRect(NSMinX(group) + floor(NSWidth(group) * 0.00000 + 0.5),
NSMinY(group) + floor(NSHeight(group) * 0.00000 + 0.5),
floor(NSWidth(group) * 1.00000 + 0.5) - floor(NSWidth(group) * 0.00000 + 0.5),
floor(NSHeight(group) * 1.00000 + 0.5) - floor(NSHeight(group) * 0.00000 + 0.5))
xRadius:[self.cornerRadius floatValue] yRadius:[self.cornerRadius floatValue]];
[backgroundColor setFill];
[ovalPath fill];
[backgroundStrokeColor5 setStroke];
[backgroundStrokeColor setStroke];
[ovalPath setLineWidth: 0.5];
[ovalPath stroke];
[NSGraphicsContext saveGraphicsState];
NSBezierPath *path = [NSBezierPath bezierPathWithRect:dirtyRect];
NSBezierPath* path = [NSBezierPath bezierPathWithRect:dirtyRect];
[path addClip];
[self setImagePosition:NSImageOnly];
auto rect2 = NSInsetRect(dirtyRect, self.imageInsets, self.imageInsets);
auto rect = NSInsetRect(dirtyRect, self.imageInsets, self.imageInsets);
[[NSColor image:self.image tintedWithColor:[NSColor whiteColor]]
drawInRect:rect2
[[NSColor image:self.image tintedWithColor:tintColor] drawInRect:rect
fromRect:NSZeroRect
operation:NSCompositeSourceOver
fraction:1.0
respectFlipped:YES
hints:nil];
respectFlipped:YES
hints:nil];
[NSGraphicsContext restoreGraphicsState];
}
......
......@@ -27,6 +27,7 @@
+ (NSColor*) ringDarkBlue;
+ (NSColor*) ringGreyHighlight;
+ (NSColor*) ringGreyLight;
+ (NSColor*) ringDarkGrey;
- (NSColor *)lightenColorByValue:(float)value;
......
......@@ -41,6 +41,11 @@
return [NSColor colorWithCalibratedRed:239/255.0 green:239/255.0 blue:239/255.0 alpha:1.0];
}
+ (NSColor*) ringGreyLight
{
return [NSColor colorWithCalibratedRed:176/255.0 green:176/255.0 blue:176/255.0 alpha:1.0];
}
+ (NSColor*) ringDarkGrey
{
return [NSColor colorWithCalibratedRed:41/255.0 green:41/255.0 blue:41/255.0 alpha:1.0];
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment