Commit cfe0eba3 authored by Thibault Wittemberg's avatar Thibault Wittemberg

ui: add theming basis

This commit adds Chameleon to theme the app and a custom
theming function to handle MessageBubbles

Change-Id: I58e4d2e30c9e81a444b3a22cef4429d64361426d
parent 799a4cad
......@@ -3,3 +3,4 @@ github "RxSwiftCommunity/RxDataSources" == 1.0.3
github "pkluz/PKHUD"
github "AliSoftware/Reusable" ~> 4.0
github "SwiftyBeaver/SwiftyBeaver"
github "ViccAlexander/Chameleon"
......@@ -3,5 +3,6 @@ github "ReactiveX/RxSwift" "3.5.0"
github "RxSwiftCommunity/RxDataSources" "1.0.4"
github "RxSwiftCommunity/RxRealm" "0.6.0"
github "SwiftyBeaver/SwiftyBeaver" "1.3.0"
github "ViccAlexander/Chameleon" "2.2.0"
github "pkluz/PKHUD" "4.2.3"
github "realm/realm-cocoa" "v2.8.3"
......@@ -93,6 +93,12 @@
04399B151D1C341A00E99CD9 /* libyaml-cpp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 04399AE31D1C341A00E99CD9 /* libyaml-cpp.a */; };
1A1E476D1F0E808500EA9A36 /* Reusable.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1E476C1F0E808500EA9A36 /* Reusable.framework */; };
1A1E476F1F0E894600EA9A36 /* SwiftyBeaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1E476E1F0E894600EA9A36 /* SwiftyBeaver.framework */; };
1A3CA32B1F102BB700283748 /* Chameleon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A3CA32A1F102BB700283748 /* Chameleon.framework */; };
1A3CA32D1F13DA7200283748 /* Chameleon+Ring.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A3CA32C1F13DA7200283748 /* Chameleon+Ring.swift */; };
1A3CA32F1F1400AF00283748 /* MessageCellReceived.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1A3CA32E1F1400AF00283748 /* MessageCellReceived.xib */; };
1A3CA3351F140EB300283748 /* MessableBubble.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A3CA3341F140EB300283748 /* MessableBubble.swift */; };
1A3CA3381F14133300283748 /* MessageCellSent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A3CA3361F14133300283748 /* MessageCellSent.swift */; };
1A3CA3391F14133300283748 /* MessageCellSent.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1A3CA3371F14133300283748 /* MessageCellSent.xib */; };
1A3D28A71F0EB9DB00B524EE /* Bool+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A3D28A61F0EB9DB00B524EE /* Bool+String.swift */; };
1A3D28A91F0EBF0200B524EE /* UIView+Ring.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A3D28A81F0EBF0200B524EE /* UIView+Ring.swift */; };
1A8306331F0EDAA50099D98C /* AccountTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A8306321F0EDAA50099D98C /* AccountTableViewCell.swift */; };
......@@ -145,8 +151,7 @@
56BBC9BF1ED7168400CDAF8B /* SmartlistViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56BBC9BE1ED7168400CDAF8B /* SmartlistViewModel.swift */; };
56BBC9CD1EDC5E7000CDAF8B /* MessageAccessoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56BBC9C71EDC5E7000CDAF8B /* MessageAccessoryView.swift */; };
56BBC9CE1EDC5E7000CDAF8B /* MessageAccessoryView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 56BBC9C81EDC5E7000CDAF8B /* MessageAccessoryView.xib */; };
56BBC9CF1EDC5E7000CDAF8B /* MessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56BBC9C91EDC5E7000CDAF8B /* MessageCell.swift */; };
56BBC9D01EDC5E7000CDAF8B /* MessageCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 56BBC9CA1EDC5E7000CDAF8B /* MessageCell.xib */; };
56BBC9CF1EDC5E7000CDAF8B /* MessageCellReceived.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56BBC9C91EDC5E7000CDAF8B /* MessageCellReceived.swift */; };
56BBC9D21EDC5E7000CDAF8B /* MessageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56BBC9CC1EDC5E7000CDAF8B /* MessageViewModel.swift */; };
56BBC9D41EDC7A6D00CDAF8B /* libargon2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 56BBC9D31EDC7A6D00CDAF8B /* libargon2.a */; };
56BBC9DF1EDDC9D300CDAF8B /* LookupNameResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 56BBC9DE1EDDC9D300CDAF8B /* LookupNameResponse.m */; };
......@@ -274,6 +279,12 @@
04399AE31D1C341A00E99CD9 /* libyaml-cpp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libyaml-cpp.a"; path = "../fat/lib/libyaml-cpp.a"; sourceTree = "<group>"; };
1A1E476C1F0E808500EA9A36 /* Reusable.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Reusable.framework; path = Carthage/Build/iOS/Reusable.framework; sourceTree = "<group>"; };
1A1E476E1F0E894600EA9A36 /* SwiftyBeaver.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftyBeaver.framework; path = Carthage/Build/iOS/SwiftyBeaver.framework; sourceTree = "<group>"; };
1A3CA32A1F102BB700283748 /* Chameleon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Chameleon.framework; path = Carthage/Build/iOS/Chameleon.framework; sourceTree = "<group>"; };
1A3CA32C1F13DA7200283748 /* Chameleon+Ring.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Chameleon+Ring.swift"; sourceTree = "<group>"; };
1A3CA32E1F1400AF00283748 /* MessageCellReceived.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MessageCellReceived.xib; sourceTree = "<group>"; };
1A3CA3341F140EB300283748 /* MessableBubble.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessableBubble.swift; sourceTree = "<group>"; };
1A3CA3361F14133300283748 /* MessageCellSent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageCellSent.swift; sourceTree = "<group>"; };
1A3CA3371F14133300283748 /* MessageCellSent.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MessageCellSent.xib; sourceTree = "<group>"; };
1A3D28A61F0EB9DB00B524EE /* Bool+String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Bool+String.swift"; sourceTree = "<group>"; };
1A3D28A81F0EBF0200B524EE /* UIView+Ring.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Ring.swift"; sourceTree = "<group>"; };
1A8306321F0EDAA50099D98C /* AccountTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountTableViewCell.swift; sourceTree = "<group>"; };
......@@ -332,8 +343,7 @@
56BBC9BE1ED7168400CDAF8B /* SmartlistViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SmartlistViewModel.swift; sourceTree = "<group>"; };
56BBC9C71EDC5E7000CDAF8B /* MessageAccessoryView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageAccessoryView.swift; sourceTree = "<group>"; };
56BBC9C81EDC5E7000CDAF8B /* MessageAccessoryView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MessageAccessoryView.xib; sourceTree = "<group>"; };
56BBC9C91EDC5E7000CDAF8B /* MessageCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageCell.swift; sourceTree = "<group>"; };
56BBC9CA1EDC5E7000CDAF8B /* MessageCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MessageCell.xib; sourceTree = "<group>"; };
56BBC9C91EDC5E7000CDAF8B /* MessageCellReceived.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageCellReceived.swift; sourceTree = "<group>"; };
56BBC9CC1EDC5E7000CDAF8B /* MessageViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageViewModel.swift; sourceTree = "<group>"; };
56BBC9D31EDC7A6D00CDAF8B /* libargon2.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libargon2.a; path = ../fat/lib/libargon2.a; sourceTree = "<group>"; };
56BBC9DD1EDDC9D300CDAF8B /* LookupNameResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LookupNameResponse.h; sourceTree = "<group>"; };
......@@ -346,6 +356,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
1A3CA32B1F102BB700283748 /* Chameleon.framework in Frameworks */,
1A1E476F1F0E894600EA9A36 /* SwiftyBeaver.framework in Frameworks */,
1A1E476D1F0E808500EA9A36 /* Reusable.framework in Frameworks */,
56559B0E1EE8777600BF20E1 /* RxRealm.framework in Frameworks */,
......@@ -467,6 +478,7 @@
02AED8171DD4C4B000F740BA /* Frameworks */ = {
isa = PBXGroup;
children = (
1A3CA32A1F102BB700283748 /* Chameleon.framework */,
1A1E476E1F0E894600EA9A36 /* SwiftyBeaver.framework */,
1A1E476C1F0E808500EA9A36 /* Reusable.framework */,
56559B0D1EE8777600BF20E1 /* RxRealm.framework */,
......@@ -555,6 +567,7 @@
1A3D28A61F0EB9DB00B524EE /* Bool+String.swift */,
1A3D28A81F0EBF0200B524EE /* UIView+Ring.swift */,
1AABA7451F0FE9C000739605 /* UIColor+Ring.swift */,
1A3CA32C1F13DA7200283748 /* Chameleon+Ring.swift */,
);
path = Extensions;
sourceTree = "<group>";
......@@ -782,10 +795,13 @@
children = (
56BBC9C71EDC5E7000CDAF8B /* MessageAccessoryView.swift */,
56BBC9C81EDC5E7000CDAF8B /* MessageAccessoryView.xib */,
56BBC9C91EDC5E7000CDAF8B /* MessageCell.swift */,
56BBC9CA1EDC5E7000CDAF8B /* MessageCell.xib */,
1A3CA32E1F1400AF00283748 /* MessageCellReceived.xib */,
56BBC9C91EDC5E7000CDAF8B /* MessageCellReceived.swift */,
1A3CA3361F14133300283748 /* MessageCellSent.swift */,
1A3CA3371F14133300283748 /* MessageCellSent.xib */,
56BBC9CC1EDC5E7000CDAF8B /* MessageViewModel.swift */,
56BBC9A51ED7151500CDAF8B /* MessageModel.swift */,
1A3CA3341F140EB300283748 /* MessableBubble.swift */,
);
path = Messages;
sourceTree = "<group>";
......@@ -940,8 +956,9 @@
5669A7FE1EA904E4003C7B93 /* TextCell.xib in Resources */,
1ABE07DC1F0D915100D36361 /* Localizable.strings in Resources */,
56BBC9CE1EDC5E7000CDAF8B /* MessageAccessoryView.xib in Resources */,
1A3CA32F1F1400AF00283748 /* MessageCellReceived.xib in Resources */,
1A3CA3391F14133300283748 /* MessageCellSent.xib in Resources */,
04399A031D1C2D9D00E99CD9 /* Images.xcassets in Resources */,
56BBC9D01EDC5E7000CDAF8B /* MessageCell.xib in Resources */,
1ABE07E01F0D91A800D36361 /* Main.storyboard in Resources */,
5669A7FA1EA904AF003C7B93 /* SwitchCell.xib in Resources */,
56BBC9B51ED7156500CDAF8B /* ConversationCell.xib in Resources */,
......@@ -983,6 +1000,7 @@
"$(SRCROOT)/Carthage/Build/iOS/RxRealm.framework",
"$(SRCROOT)/Carthage/Build/iOS/Reusable.framework",
"$(SRCROOT)/Carthage/Build/iOS/SwiftyBeaver.framework",
"$(SRCROOT)/Carthage/Build/iOS/Chameleon.framework",
);
name = "⚙️ Copy Frameworks";
outputPaths = (
......@@ -1036,7 +1054,8 @@
02B22E091DF7585F000358C9 /* DaemonService.swift in Sources */,
0273C3061E0C68B100CF00BA /* CreateRingAccountViewController.swift in Sources */,
56BBC99F1ED714CB00CDAF8B /* MessagesAdapter.mm in Sources */,
56BBC9CF1EDC5E7000CDAF8B /* MessageCell.swift in Sources */,
1A3CA3351F140EB300283748 /* MessableBubble.swift in Sources */,
56BBC9CF1EDC5E7000CDAF8B /* MessageCellReceived.swift in Sources */,
02C9B63F1E1D4E8C00F82F0C /* ServiceEvent.swift in Sources */,
1A3D28A71F0EB9DB00B524EE /* Bool+String.swift in Sources */,
56BBC9D21EDC5E7000CDAF8B /* MessageViewModel.swift in Sources */,
......@@ -1048,6 +1067,7 @@
56559B141EE89E7900BF20E1 /* DeviceModel.swift in Sources */,
56308BA71EA00E5700660275 /* NameRegistrationResponse.m in Sources */,
5628B4211F0C35C8008B1E11 /* WelcomeViewController.swift in Sources */,
1A3CA32D1F13DA7200283748 /* Chameleon+Ring.swift in Sources */,
5628B41C1F0C358D008B1E11 /* AccountDetailsViewController.swift in Sources */,
56AC64E11E80542300EA1AA9 /* TextFieldCell.swift in Sources */,
1ABE07E21F0D924700D36361 /* Strings.swift in Sources */,
......@@ -1056,6 +1076,7 @@
56BBC9BF1ED7168400CDAF8B /* SmartlistViewModel.swift in Sources */,
02B22E011DF755E5000358C9 /* MainTabBarViewController.swift in Sources */,
564C44641E943E1E000F92B1 /* NameRegistrationAdapterDelegate.swift in Sources */,
1A3CA3381F14133300283748 /* MessageCellSent.swift in Sources */,
043999F71D1C2D9D00E99CD9 /* AppDelegate.swift in Sources */,
02B22DFC1DF755BB000358C9 /* AccountModel.swift in Sources */,
56AC64DF1E804ECC00EA1AA9 /* SwitchCell.swift in Sources */,
......
......@@ -23,6 +23,7 @@ import UIKit
import RealmSwift
import SwiftyBeaver
import RxSwift
import Chameleon
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
......@@ -47,6 +48,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
SystemAdapter().registerConfigurationHandler()
self.startDaemon()
Chameleon.setGlobalThemeUsingPrimaryColor(UIColor.ringMain, withSecondaryColor: UIColor.ringSecondary, andContentStyle: .light)
Chameleon.setRingThemeUsingPrimaryColor(UIColor.ringMain, withSecondaryColor: UIColor.ringSecondary, andContentStyle: .light)
self.loadAccounts()
return true
}
......
......@@ -30,3 +30,4 @@
#import "RegistrationResponse.h"
#import "NameRegistrationResponse.h"
#import "MessagesAdapter.h"
#import "Chameleon/Chameleon.h"
......@@ -18,6 +18,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#import "Chameleon/Chameleon-Swift.h"
#import "Ring-Swift.h"
#import "SystemAdapter.h"
......
......@@ -63,6 +63,8 @@ enum L10n {
enum Global {
/// Home
static let homeTabBarTitle = L10n.tr("global.homeTabBarTitle")
/// Me
static let meTabBarTitle = L10n.tr("global.meTabBarTitle")
/// Ok
static let ok = L10n.tr("global.ok")
}
......
......@@ -26,6 +26,7 @@ class ConversationViewController: UIViewController, UITextFieldDelegate {
let disposeBag = DisposeBag()
var viewModel: ConversationViewModel?
var messageViewModels: [MessageViewModel]?
var textFieldShouldEndEditing = false
var bottomOffset: CGFloat = 0
......@@ -92,20 +93,21 @@ class ConversationViewController: UIViewController, UITextFieldDelegate {
}
func setupTableView() {
self.tableView.dataSource = self
self.tableView.estimatedRowHeight = 50
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.separatorStyle = .none
//Register cell
self.tableView.register(cellType: MessageCell.self)
self.tableView.register(cellType: MessageCellSent.self)
self.tableView.register(cellType: MessageCellReceived.self)
//Bind the TableView to the ViewModel
self.viewModel?.messages
.bind(to: tableView.rx.items(cellIdentifier: "MessageCell",
cellType: MessageCell.self)) { _, messageViewModel, cell in
cell.messageLabel.text = messageViewModel.content
cell.bubblePosition = messageViewModel.bubblePosition()
}.disposed(by: disposeBag)
self.viewModel?.messages.subscribe(onNext: { [weak self] (messageViewModels) in
self?.messageViewModels = messageViewModels
self?.tableView.reloadData()
}).disposed(by: self.disposeBag)
//Scroll to bottom when reloaded
self.tableView.rx.methodInvoked(#selector(UITableView.reloadData)).subscribe(onNext: { _ in
......@@ -170,3 +172,28 @@ class ConversationViewController: UIViewController, UITextFieldDelegate {
}
}
extension ConversationViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.messageViewModels?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let messageViewModel = self.messageViewModels?[indexPath.row] {
if messageViewModel.bubblePosition() == .received {
let cell = tableView.dequeueReusableCell(for: indexPath, cellType: MessageCellReceived.self)
cell.messageLabel.text = messageViewModel.content
return cell
}
let cell = tableView.dequeueReusableCell(for: indexPath, cellType: MessageCellSent.self)
cell.messageLabel.text = messageViewModel.content
return cell
}
return tableView.dequeueReusableCell(for: indexPath, cellType: MessageCellSent.self)
}
}
/*
* Copyright (C) 2016 Savoir-faire Linux Inc.
*
* Author: Thibault Wittemberg <thibault.wittemberg@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 Foundation
import Chameleon
extension Chameleon {
static func setRingThemeUsingPrimaryColor (_ primaryColor: UIColor, withSecondaryColor secondaryColor: UIColor, andContentStyle contentStyle: UIContentStyle) {
var contentColor: UIColor
var secondaryContentColor: UIColor
switch contentStyle {
case .contrast:
contentColor = ContrastColorOf(primaryColor, returnFlat: false)
secondaryContentColor = ContrastColorOf(secondaryColor, returnFlat: false)
break
case .light:
contentColor = UIColor.white
secondaryContentColor = UIColor.white
break
case .dark:
contentColor = UIColor.flatBlackColorDark()
secondaryContentColor = UIColor.flatBlackColorDark()
break
}
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).tintColor = UIColor.flatGray()
MessageBubble.appearance().tintColor = secondaryContentColor
MessageBubble.appearance().backgroundColor = secondaryColor
MessageBubble.appearance(whenContainedInInstancesOf: [MessageCellSent.self]).tintColor = contentColor
MessageBubble.appearance(whenContainedInInstancesOf: [MessageCellSent.self]).backgroundColor = primaryColor
UILabel.appearance(whenContainedInInstancesOf: [MessageBubble.self, MessageCellSent.self]).textColor = contentColor
MessageBubble.appearance(whenContainedInInstancesOf: [MessageCellReceived.self]).tintColor = secondaryContentColor
MessageBubble.appearance(whenContainedInInstancesOf: [MessageCellReceived.self]).backgroundColor = secondaryColor
UILabel.appearance(whenContainedInInstancesOf: [MessageBubble.self, MessageCellReceived.self]).textColor = secondaryContentColor
}
}
......@@ -23,9 +23,14 @@ import UIKit
extension UIColor {
static let ringMain = UIColor(colorLiteralRed: 10.0/255.0,
green: 116.0/255.0,
blue: 137.0/255.0,
static let ringMain = UIColor(colorLiteralRed: 58.0/255.0,
green: 192.0/255.0,
blue: 210.0/255.0,
alpha: 1.0)
static let ringSecondary = UIColor(colorLiteralRed: 0.0/255.0,
green: 76.0/255.0,
blue: 96.0/255.0,
alpha: 1.0)
}
......@@ -54,6 +54,6 @@
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
<false/>
</dict>
</plist>
......@@ -25,8 +25,6 @@ class MainTabBarViewController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
UITabBarItem.appearance()
.setTitleTextAttributes( [NSForegroundColorAttributeName: UIColor.ringMain], for: .selected)
}
override func viewDidAppear(_ animated: Bool) {
......
/*
* Copyright (C) 2016 Savoir-faire Linux Inc.
*
* Author: Thibault Wittemberg <thibault.wittemberg@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 Foundation
import UIKit
@IBDesignable
class MessageBubble: UIView {
// just to make the UIView+Ring extension IBDesignable
}
......@@ -21,50 +21,9 @@
import UIKit
import Reusable
enum BubblePosition {
case received
case sent
}
class MessageCell: UITableViewCell, NibReusable {
class MessageCellReceived: UITableViewCell, NibReusable {
@IBOutlet weak var bubble: UIView!
@IBOutlet weak var bubble: MessageBubble!
@IBOutlet weak var messageLabel: UILabel!
@IBOutlet weak var minimumLeadingConstraint: NSLayoutConstraint!
@IBOutlet weak var containerLeadingConstraint: NSLayoutConstraint!
@IBOutlet weak var minimumTrailingConstraint: NSLayoutConstraint!
@IBOutlet weak var containerTrailingConstraint: NSLayoutConstraint!
var bubblePosition = BubblePosition.received {
didSet {
if bubblePosition == .sent {
self.minimumTrailingConstraint.priority = 1
self.containerTrailingConstraint.priority = 999
self.containerLeadingConstraint.priority = 1
self.minimumLeadingConstraint.priority = 999
self.bubble.backgroundColor = UIColor.ringMain
self.messageLabel.textColor = UIColor.white
} else {
self.minimumLeadingConstraint.priority = 1
self.containerLeadingConstraint.priority = 999
self.containerTrailingConstraint.priority = 1
self.minimumTrailingConstraint.priority = 999
self.bubble.backgroundColor = UIColor.lightGray
self.messageLabel.textColor = UIColor.black
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
self.bubblePosition = .received
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
......@@ -11,14 +11,14 @@
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" rowHeight="60" id="KGk-i7-Jjw" customClass="MessageCell" customModule="Ring" customModuleProvider="target">
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" rowHeight="60" id="KGk-i7-Jjw" customClass="MessageCellReceived" customModule="Ring" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="510" height="47"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
<rect key="frame" x="0.0" y="0.0" width="510" height="46.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view clipsSubviews="YES" contentMode="scaleToFill" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="kZJ-Ay-LTR">
<view clipsSubviews="YES" contentMode="scaleToFill" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="kZJ-Ay-LTR" customClass="MessageBubble" customModule="Ring" customModuleProvider="target">
<rect key="frame" x="16" y="8" width="152.5" height="30.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label Label Label Label " lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lyR-7c-S2k">
......@@ -37,8 +37,8 @@
<constraint firstItem="lyR-7c-S2k" firstAttribute="top" secondItem="kZJ-Ay-LTR" secondAttribute="top" constant="4" id="ycc-WI-Jk6"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
<integer key="value" value="5"/>
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
<real key="value" value="4"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
......@@ -54,11 +54,7 @@
</tableViewCellContentView>
<connections>
<outlet property="bubble" destination="kZJ-Ay-LTR" id="hdG-fG-L69"/>
<outlet property="containerLeadingConstraint" destination="nWe-5k-Qpn" id="Ahu-gW-4IY"/>
<outlet property="containerTrailingConstraint" destination="99Y-bR-Ioq" id="JJr-pE-UfA"/>
<outlet property="messageLabel" destination="lyR-7c-S2k" id="hd3-pz-Pwh"/>
<outlet property="minimumLeadingConstraint" destination="Eso-cy-OYs" id="jhV-mE-FMA"/>
<outlet property="minimumTrailingConstraint" destination="TCY-7X-mFs" id="xj3-4A-I9G"/>
</connections>
<point key="canvasLocation" x="-411" y="-132"/>
</tableViewCell>
......
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Silbino Gonçalves Matado <silbino.gmatado@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 UIKit
import Reusable
class MessageCellSent: UITableViewCell, NibReusable {
@IBOutlet weak var bubble: MessageBubble!
@IBOutlet weak var messageLabel: UILabel!
}
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" rowHeight="60" id="KGk-i7-Jjw" customClass="MessageCellSent" customModule="Ring" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="510" height="47"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
<rect key="frame" x="0.0" y="0.0" width="510" height="46.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view clipsSubviews="YES" contentMode="scaleToFill" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="kZJ-Ay-LTR" customClass="MessageBubble" customModule="Ring" customModuleProvider="target">
<rect key="frame" x="341.5" y="8" width="152.5" height="30.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label Label Label Label " lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lyR-7c-S2k">
<rect key="frame" x="8" y="4" width="136.5" height="22.5"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="0.66666666666666663" green="0.66666666666666663" blue="0.66666666666666663" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="30" id="1Kj-UZ-gu7"/>
<constraint firstItem="lyR-7c-S2k" firstAttribute="leading" secondItem="kZJ-Ay-LTR" secondAttribute="leading" constant="8" id="8m5-sR-xnh"/>
<constraint firstAttribute="bottom" secondItem="lyR-7c-S2k" secondAttribute="bottom" constant="4" id="gwN-uX-PWd"/>
<constraint firstAttribute="trailing" secondItem="lyR-7c-S2k" secondAttribute="trailing" constant="8" id="uzV-kG-oGN"/>
<constraint firstItem="lyR-7c-S2k" firstAttribute="top" secondItem="kZJ-Ay-LTR" secondAttribute="top" constant="4" id="ycc-WI-Jk6"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
<real key="value" value="4"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="kZJ-Ay-LTR" secondAttribute="bottom" constant="8" id="1QQ-bu-6Bl"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="kZJ-Ay-LTR" secondAttribute="trailing" priority="1" constant="64" id="99Y-bR-Ioq"/>
<constraint firstItem="kZJ-Ay-LTR" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" priority="1" constant="16" id="Eso-cy-OYs"/>
<constraint firstAttribute="trailing" secondItem="kZJ-Ay-LTR" secondAttribute="trailing" constant="16" id="TCY-7X-mFs"/>
<constraint firstItem="kZJ-Ay-LTR" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="8" id="jhd-A8-c1o"/>
<constraint firstItem="kZJ-Ay-LTR" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="64" id="nWe-5k-Qpn"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property="bubble" destination="kZJ-Ay-LTR" id="hdG-fG-L69"/>
<outlet property="messageLabel" destination="lyR-7c-S2k" id="hd3-pz-Pwh"/>
</connections>
<point key="canvasLocation" x="-411" y="-132"/>
</tableViewCell>
</objects>
</document>
......@@ -20,6 +20,11 @@
import RxSwift
enum BubblePosition {
case received
case sent
}
class MessageViewModel {
fileprivate let accountService = AppDelegate.accountService