Commit 746f376e authored by atraczyk's avatar atraczyk

refactoring: implements per account contacts, trust requests & more

- seperates contacts by account
- implements the trust request API
- introduces localization strings and transifex update mechanism
- adds lodepng to remove windows photobooth png metadata
- changes icons
- adds default colored initial avatars
- changes logo images
- complete overhaul on the ui/ux

Change-Id: I43914ff63a48bb43a6997721773df5029a1650b5
parent 46910037
[main]
host = https://www.transifex.com
[ring.resourcesuwpclientresw]
file_filter = localization/<lang>/Resources.resw
source_file = localization/en-US/Resources.resw
source_lang = en
type = RESX
lang_map = cs_CZ: cs-CZ, da_DK: da-DK, de_DE: de-DE, fa_IR: fa-IR, fr_CA: fr-CA, fr_FR: fr-FR, hi_IN: hi-IN, it_IT: it-IT, nl_NL: nl-NL, pt_BR: pt-BR, ru_RU: ru-RU, sk_SK: sk-SK, sq_AL: sq-AL, zh_CN: zh-CN, zh_TW: zh-TW
......@@ -33,35 +33,30 @@
Margin="24">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center">
<Button x:Name="_aboutBasicButton_"
Content="About"
Margin="0,0,6,0"
BorderThickness="0"
FontSize="12"
Click="_aboutBasicButton__Click"
<Button x:Uid="_aboutBasicButton_"
Margin="0,0,6,0"
BorderThickness="0"
FontSize="12"
Click="_aboutBasicButton__Click"
/>
<Button x:Name="_aboutCreditsButton_"
Content="Credits"
Margin="0,0,6,0"
BorderThickness="0"
FontSize="12"
Click="_aboutCreditsButton__Click"
<Button x:Uid="_aboutCreditsButton_"
Margin="0,0,6,0"
BorderThickness="0"
FontSize="12"
Click="_aboutCreditsButton__Click"
/>
<Button x:Name="_aboutCloseButton_"
Content="Close"
Margin="0,0,6,0"
BorderThickness="0"
FontSize="12"
Click="_aboutCloseButton__Click"
<Button x:Uid="_aboutCloseButton_"
Margin="0,0,6,0"
BorderThickness="0"
FontSize="12"
Click="_aboutCloseButton__Click"
/>
</StackPanel>
<Image x:Name="_welcomeImage_"
Source="Assets\Wide310x150Logo.scale-200.png"
Width="310"
HorizontalAlignment="Center"
Margin="0 10 0 30"
Height="150"/>
Source="Assets\Wide310x150Logo.scale-200.png"
Width="310"
HorizontalAlignment="Center"
Height="150"/>
<Grid x:Name="_aboutNavGrid_">
<Grid.RowDefinitions>
<RowDefinition Height="0"/>
......@@ -72,24 +67,24 @@
VerticalScrollBarVisibility="Hidden">
<StackPanel MaxWidth="500"
Width="310">
<TextBlock Text="Ring version: 2017/2/13"
<TextBlock x:Name="_aboutVersionString_"
TextWrapping="Wrap"
TextAlignment="Justify"
Margin="0,0,0,24"
Margin="0,0,0,24"
FontSize="12"
FontWeight="Bold"
HorizontalAlignment="Center"/>
<TextBlock Text="Release: Beta 2 - Gaston Miron"
<TextBlock x:Uid="_aboutReleaseTitle_"
TextWrapping="Wrap"
TextAlignment="Justify"
FontSize="12"
HorizontalAlignment="Center"/>
<TextBlock Text="The Microsoft Windows Runtime client for Ring."
<TextBlock x:Uid="_aboutReleasePlatform_"
TextWrapping="Wrap"
TextAlignment="Justify"
FontSize="12"
HorizontalAlignment="Center"/>
<TextBlock Text="Ring is a secured and distributed communication software."
<TextBlock x:Uid="_aboutReleaseDescription_"
TextWrapping="Wrap"
TextAlignment="Justify"
FontSize="12"
......@@ -104,29 +99,28 @@
TextAlignment="Justify"
FontSize="10"
HorizontalAlignment="Center"/>
<TextBlock Text="This program comes with absolutely no warranty"
<TextBlock x:Uid="_aboutDisclaimer_"
TextWrapping="Wrap"
TextAlignment="Justify"
FontSize="10"
HorizontalAlignment="Center"/>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center">
<TextBlock Text="See the "
<TextBlock x:Uid="_aboutGPL_0_"
Margin="0,0,4,0"
TextWrapping="Wrap"
TextAlignment="Justify"
FontSize="10"/>
<HyperlinkButton Content="GNU General Public License, version 3 or later"
FontSize="10"
NavigateUri="https://www.gnu.org/licenses/gpl-3.0.en.html">
TextWrapping="Wrap"
TextAlignment="Justify"
FontSize="10"/>
<HyperlinkButton x:Uid="_aboutGPL_1_"
FontSize="10">
<HyperlinkButton.RenderTransform>
<TranslateTransform Y="-6"/>
</HyperlinkButton.RenderTransform>
</HyperlinkButton>
<TextBlock Text=" for details."
TextWrapping="Wrap"
TextAlignment="Justify"
FontSize="10"/>
<TextBlock x:Uid="_aboutGPL_2_"
TextWrapping="Wrap"
TextAlignment="Justify"
FontSize="10"/>
</StackPanel>
</StackPanel>
</ScrollViewer>
......@@ -139,7 +133,7 @@
BorderBrush="Black"
BorderThickness="1">
<StackPanel>
<TextBlock Text="Created by:"
<TextBlock x:Uid="_c_created_by_"
Margin="0,0,0,0"
TextWrapping="Wrap"
TextAlignment="Center"
......@@ -151,7 +145,6 @@
TextAlignment="Center"
FontSize="12"
HorizontalAlignment="Center">
<LineBreak/> Created by:
<LineBreak/> Adrien Béraud
<LineBreak/> Alexandr Sergheev
<LineBreak/> Alexandre Lision
......@@ -166,7 +159,9 @@
<LineBreak/> Emmanuel Lepage-Vallée
<LineBreak/> Frédéric Guimont
<LineBreak/> Guillaume Roguez
<LineBreak/> Hadrien De Sousa
<LineBreak/> Julien Grossholtz
<LineBreak/> Kateryna Kostiuk
<LineBreak/> Loïc Siret
<LineBreak/> Nicolas Jäger
<LineBreak/> Nicolas Reynaud
......@@ -175,13 +170,16 @@
<LineBreak/> Patrick Keroulas
<LineBreak/> Philippe Gorley
<LineBreak/> Romain Bertozzi
<LineBreak/> Sébastien Blin
<LineBreak/> Seva Ivanov
<LineBreak/> Silbino Gonçalves Matado
<LineBreak/> Simon Désaulniers
<LineBreak/> Stepan Salenikovich
<LineBreak/> Simon Zeni
<LineBreak/> Thibault Wittemberg
<LineBreak/>
</TextBlock>
<TextBlock Text="Artwork by:"
<TextBlock x:Uid="_c_artwork_by_"
Margin="0,0,0,0"
TextWrapping="Wrap"
TextAlignment="Center"
......
/**************************************************************************
* Copyright (C) 2016 by Savoir-faire Linux *
* Author: Jger Nicolas <nicolas.jager@savoirfairelinux.com> *
* Author: Traczyk Andreas <andreas.traczyk@savoirfairelinux.com> *
* *
* This program is free software; you can redistribute it and/or modify *
......@@ -27,9 +26,64 @@ using namespace Windows::UI::ViewManagement;
using namespace Windows::UI::Core;
using namespace Windows::UI::Xaml::Controls;
#define BUILD_YEAR_CH0 (__DATE__[ 7])
#define BUILD_YEAR_CH1 (__DATE__[ 8])
#define BUILD_YEAR_CH2 (__DATE__[ 9])
#define BUILD_YEAR_CH3 (__DATE__[10])
#define BUILD_MONTH_IS_JAN (__DATE__[0] == 'J' && __DATE__[1] == 'a' && __DATE__[2] == 'n')
#define BUILD_MONTH_IS_FEB (__DATE__[0] == 'F')
#define BUILD_MONTH_IS_MAR (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'r')
#define BUILD_MONTH_IS_APR (__DATE__[0] == 'A' && __DATE__[1] == 'p')
#define BUILD_MONTH_IS_MAY (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'y')
#define BUILD_MONTH_IS_JUN (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'n')
#define BUILD_MONTH_IS_JUL (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'l')
#define BUILD_MONTH_IS_AUG (__DATE__[0] == 'A' && __DATE__[1] == 'u')
#define BUILD_MONTH_IS_SEP (__DATE__[0] == 'S')
#define BUILD_MONTH_IS_OCT (__DATE__[0] == 'O')
#define BUILD_MONTH_IS_NOV (__DATE__[0] == 'N')
#define BUILD_MONTH_IS_DEC (__DATE__[0] == 'D')
#define BUILD_MONTH_CH0 \
((BUILD_MONTH_IS_OCT || BUILD_MONTH_IS_NOV || BUILD_MONTH_IS_DEC) ? '1' : '0')
#define BUILD_MONTH_CH1 \
( \
(BUILD_MONTH_IS_JAN) ? '1' : \
(BUILD_MONTH_IS_FEB) ? '2' : \
(BUILD_MONTH_IS_MAR) ? '3' : \
(BUILD_MONTH_IS_APR) ? '4' : \
(BUILD_MONTH_IS_MAY) ? '5' : \
(BUILD_MONTH_IS_JUN) ? '6' : \
(BUILD_MONTH_IS_JUL) ? '7' : \
(BUILD_MONTH_IS_AUG) ? '8' : \
(BUILD_MONTH_IS_SEP) ? '9' : \
(BUILD_MONTH_IS_OCT) ? '0' : \
(BUILD_MONTH_IS_NOV) ? '1' : \
(BUILD_MONTH_IS_DEC) ? '2' : \
/* error default */ '?' \
)
#define BUILD_DAY_CH0 ((__DATE__[4] >= '0') ? (__DATE__[4]) : '0')
#define BUILD_DAY_CH1 (__DATE__[ 5])
AboutPage::AboutPage()
{
InitializeComponent();
const char completeVersion[] =
{
BUILD_YEAR_CH0, BUILD_YEAR_CH1, BUILD_YEAR_CH2, BUILD_YEAR_CH3,
'/',
BUILD_MONTH_CH0, BUILD_MONTH_CH1,
'/',
BUILD_DAY_CH0, BUILD_DAY_CH1,
'\0'
};
auto buildDate = std::string(reinterpret_cast<const char*>(completeVersion));
PackageVersion version = Package::Current->Id->Version;
auto buildVersion = version.Major.ToString() + "." + version.Minor.ToString() + "." + version.Build.ToString();
_aboutVersionString_->Text = "Ring version: " + Utils::toPlatformString(buildDate) + " build: " + buildVersion;
};
void RingClientUWP::Views::AboutPage::_aboutBasicButton__Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
......@@ -50,4 +104,4 @@ void RingClientUWP::Views::AboutPage::_aboutCloseButton__Click(Platform::Object^
{
auto rootFrame = dynamic_cast<Windows::UI::Xaml::Controls::Frame^>(Window::Current->Content);
rootFrame->Navigate(Windows::UI::Xaml::Interop::TypeName(MainPage::typeid), true);
}
}
\ No newline at end of file
......@@ -32,7 +32,13 @@ Account::Account(String^ name,
String^ accountType,
String^ accountID,
String^ deviceId,
String^ deviceName,
bool active,
bool upnpState,
bool autoAnswer,
bool dhtPublicInCalls,
bool turnEnabled,
String^ turnAddress,
String^ sipHostname,
String^ sipUsername,
String^ sipPassword)
......@@ -42,11 +48,19 @@ Account::Account(String^ name,
accountType_ = accountType;
accountID_ = accountID;
_deviceId = deviceId;
_deviceName = deviceName;
_active = active;
_upnpState = upnpState;
_autoAnswer = autoAnswer;
_dhtPublicInCalls = dhtPublicInCalls;
_turnEnabled = turnEnabled;
_turnAddress = turnAddress;
_sipHostname = sipHostname;
_sipUsername = sipUsername;
_sipPassword = sipPassword;
_unreadMessages = 0;
_registrationState = RegistrationState::UNKNOWN;
_username = "";
}
void
......@@ -59,4 +73,10 @@ Account::NotifyPropertyChanged(String^ propertyName)
{
PropertyChanged(this, ref new PropertyChangedEventArgs(propertyName));
}));
}
\ No newline at end of file
}
void
Account::raiseNotifyPropertyChanged(String^ propertyName)
{
NotifyPropertyChanged(propertyName);
}
......@@ -30,9 +30,23 @@ ref class Contact;
public ref class Account sealed : public INotifyPropertyChanged
{
public:
Account(String^ name, String^ ringID, String^ accountType, String^ accountID, String^ deviceId, bool upnpState
, String^ sipHostname, String^ sipUsername, String^ sipPassword);
Account(String^ name,
String^ ringID,
String^ accountType,
String^ accountID,
String^ deviceId,
String^ deviceName,
bool active,
bool upnpState,
bool autoAnswer,
bool dhtPublicInCalls,
bool turnEnabled,
String^ turnAddress,
String^ sipHostname,
String^ sipUsername,
String^ sipPassword);
void raiseNotifyPropertyChanged(String^ propertyName);
virtual event PropertyChangedEventHandler^ PropertyChanged;
property String^ name_
......@@ -43,8 +57,51 @@ public:
void set(String^ value) {
alias_ = value;
NotifyPropertyChanged("name_");
NotifyPropertyChanged("_bestName");
}
}
property String^ _username
{
String^ get() {
return username_;
}
void set(String^ value) {
username_ = value;
NotifyPropertyChanged("_username");
NotifyPropertyChanged("_bestName");
}
}
property String^ _bestName {
String^ get() {
String^ bestName;
if (alias_)
bestName = alias_;
return bestName;
}
}
property String^ _bestName2 {
String^ get() {
String^ bestName;
if (accountType_ == "RING" && username_)
bestName += username_;
return bestName;
}
}
property String^ _bestName3 {
String^ get() {
String^ bestName;
if (alias_)
bestName += alias_;
if (accountType_ == "RING" && username_)
bestName += " (" + username_ + ")";
return bestName;
}
}
property String^ ringID_ {
String^ get() {
return ringID__;
......@@ -57,15 +114,16 @@ public:
property String^ accountType_; // refacto : create a enum accountType
property String^ accountID_;
property String^ _deviceId;
property IVector<String^>^ _devicesIdList {
IVector<String^>^ get() {
return devicesIdList_;
}
void set(IVector<String^>^ value) {
devicesIdList_ = value;
}
};
property String^ _deviceName;
property RegistrationState _registrationState;
property bool _active;
property bool _upnpState;
property bool _autoAnswer;
property bool _dhtPublicInCalls;
property bool _turnEnabled;
property String^ _turnAddress;
property String^ _sipHostname;
property String^ _sipUsername
{
......@@ -75,17 +133,35 @@ public:
void set(String^ value) {
sipUsername_ = value;
NotifyPropertyChanged("_sipUsername");
NotifyPropertyChanged("_bestName");
}
}
property unsigned _unreadMessages
{
property unsigned _unreadMessages {
unsigned get() {
return unreadMessages_;
}
void set(unsigned value) {
unreadMessages_ = value;
NotifyPropertyChanged("_unreadMessages");
NotifyPropertyChanged("_allUnread");
}
}
property unsigned _unreadContactRequests {
unsigned get() {
return unreadContactRequests_;
}
void set(unsigned value) {
unreadContactRequests_ = value;
NotifyPropertyChanged("_unreadContactRequests");
NotifyPropertyChanged("_allUnread");
}
}
property unsigned _allUnread {
unsigned get() {
return unreadContactRequests_ + unreadMessages_;
}
}
......@@ -104,13 +180,14 @@ protected:
void NotifyPropertyChanged(String^ propertyName);
private:
IVector<String^>^ devicesIdList_;
IVector<Contact^>^ contactsList_;
String^ alias_;
String^ username_;
String^ ringID__;
String^ sipUsername_;
unsigned unreadMessages_;
unsigned unreadContactRequests_;
};
}
......@@ -33,7 +33,6 @@ AccountListItem::AccountListItem(Account^ a)
{
_account = a;
_editionMode = false;
}
void
......@@ -44,6 +43,13 @@ AccountListItem::NotifyPropertyChanged(String^ propertyName)
CoreDispatcherPriority::High,
ref new DispatchedHandler([this, propertyName]()
{
//MSG_("AccountListItem::NotifyPropertyChanged: " + propertyName);
PropertyChanged(this, ref new PropertyChangedEventArgs(propertyName));
}));
}
\ No newline at end of file
}
void
AccountListItem::raiseNotifyPropertyChanged(String^ propertyName)
{
NotifyPropertyChanged(propertyName);
}
#pragma once
/**************************************************************************
* Copyright (C) 2016 by Savoir-faire Linux *
* Author: Jäger Nicolas <nicolas.jager@savoirfairelinux.com> *
......@@ -17,6 +16,9 @@
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
**************************************************************************/
#pragma once
using namespace Platform;
using namespace Windows::Data::Json;
using namespace Windows::UI::Xaml;
......@@ -26,26 +28,32 @@ using namespace Windows::UI::Xaml::Data;
namespace RingClientUWP
{
namespace Controls {
namespace Controls
{
public ref class AccountListItem sealed : public INotifyPropertyChanged
{
public:
AccountListItem(Account^ a);
void raiseNotifyPropertyChanged(String^ propertyName);
virtual event PropertyChangedEventHandler^ PropertyChanged;
property Account^ _account;
property bool _editionMode;
property bool _disconnected;
property bool _isSelected {
bool get() {
return isSelected_;
}
void set(bool value) {
isSelected_ = value;
if (!_disconnected)
NotifyPropertyChanged("_isSelected");
}
bool get() {
return isSelected_;
}
}
property bool _editionMode;
property bool _disconnected;
protected:
void NotifyPropertyChanged(String^ propertyName);
......
......@@ -42,7 +42,7 @@ AccountListItemsViewModel::AccountListItemsViewModel()
void RingClientUWP::ViewModel::AccountListItemsViewModel::OnaccountAdded(RingClientUWP::Account ^account)
{
auto item = ref new AccountListItem(account);
itemsList_->Append(item);
itemsList_->InsertAt(0, item);
}
......@@ -54,7 +54,8 @@ void RingClientUWP::ViewModel::AccountListItemsViewModel::OnclearAccountsList()
void
AccountListItemsViewModel::updateContactsViewModel()
{
SmartPanelItemsViewModel::instance->update();
SmartPanelItemsViewModel::instance->refreshFilteredItemsList();
SmartPanelItemsViewModel::instance->update(ViewModel::NotifyStrings::notifySmartPanelItem);
}
AccountListItem^
......@@ -67,6 +68,17 @@ RingClientUWP::ViewModel::AccountListItemsViewModel::findItem(String^ accountId)
return nullptr;
}
int
AccountListItemsViewModel::getIndex(String^ accountId)
{
int i;
for (i = 0; i < itemsList_->Size; i++) {
if (itemsList_->GetAt(i)->_account->accountID_ == accountId)
break;
}
return i;
}
void RingClientUWP::ViewModel::AccountListItemsViewModel::removeItem(AccountListItem ^ item)
{
unsigned int index;
......@@ -96,3 +108,25 @@ AccountListItemsViewModel::unreadMessages()
}
return messageCount;
}
int
AccountListItemsViewModel::unreadContactRequests()
{
int unreadContactRequestCount = 0;
for each (auto account in AccountsViewModel::instance->accountsList) {
account->_unreadContactRequests = AccountsViewModel::instance->unreadContactRequests(account->accountID_);
unreadContactRequestCount += account->_unreadContactRequests;
}
return unreadContactRequestCount;
}
void
AccountListItemsViewModel::update(const std::vector<std::string>& properties)
{
for each (AccountListItem^ item in itemsList) {
item->raiseNotifyPropertyChanged("");
for each (std::string prop in properties) {
item->_account->raiseNotifyPropertyChanged(Utils::toPlatformString(prop));
}
}
}
\ No newline at end of file
......@@ -34,6 +34,7 @@ public ref class AccountListItemsViewModel sealed
public:
String^ getSelectedAccountId();
int unreadMessages();
int unreadContactRequests();
internal:
/* singleton */
......@@ -47,26 +48,25 @@ internal:
}
/* functions */
void update(const std::vector<std::string>& properties);
AccountListItem^ findItem(String^ accountId);
int getIndex(String^ accountId);
void removeItem(AccountListItem^ item);
/* properties */
property Vector<AccountListItem^>^ itemsList
{
Vector<AccountListItem^>^ get()
{
Vector<AccountListItem^>^ get() {
return itemsList_;
}
}
property AccountListItem^ _selectedItem
{
AccountListItem^ get()
{
AccountListItem^ get() {
return currentItem_;
}
void set(AccountListItem^ value)
{
void set(AccountListItem^ value) {
if (currentItem_)
currentItem_->_isSelected = false;
currentItem_ = value;
......
This diff is collapsed.
......@@ -34,7 +34,8 @@ delegate void ClearAccountsList();
delegate void ContactAdded(String^, Contact^);
delegate void ContactDeleted(String^, Contact^);
delegate void ContactDataModified(String^, Contact^);
delegate void NewUnreadMessage();
delegate void NewUnreadMessage(Contact^);
delegate void NewUnreadContactRequest();
namespace ViewModel
{
......@@ -42,9 +43,10 @@ namespace ViewModel
public ref class AccountsViewModel sealed
{
public:
void raiseContactAdded(String^ accountId, Contact^ name);
void raiseContactDeleted(String^ accountId, Contact^ name);
void raiseContactDataModified(String^ accountId, Contact^ name);
void raiseContactAdded(String^ accountId, Contact^ contact);
void raiseContactDeleted(String^ accountId, Contact^ contact);
void raiseContactDataModified(String^ accountId, Contact^ contact);
void raiseUnreadContactRequest();
internal:
/* properties */
......@@ -55,21 +57,38 @@ internal:
}
}
property Vector<Account^>^ accountsList
{
Vector<Account^>^ get()
{
property Vector<Account^>^ accountsList {
Vector<Account^>^ get() {
return accountsList_;
}
}
/* functions */
void addRingAccount(std::string& alias, std::string& ringID, std::string& accountID, std::string& deviceId, bool upnpState);
void addSipAccount(std::string& alias, std::string& accountID, std::string& sipHostname, std::string& sipUsername, std::string& sipPassword);
void addRingAccount(std::string& alias,
std::string& ringID,
std::string& accountID,
std::string& deviceId,
std::string& deviceName,
bool active,
bool upnpState,
bool autoAnswer,
bool dhtPublicInCalls,
bool turnEnabled,
std::string& turnAddress);
void addSipAccount( std::string& alias,
std::string& accountID,
bool active,
std::string& sipHostname,
std::string& sipUsername,
std::string& sipPassword);