Skip to content

Commit a677255

Browse files
committed
feat: merge set profileUpdatedAt to the set actions
1 parent d46e344 commit a677255

File tree

10 files changed

+80
-110
lines changed

10 files changed

+80
-110
lines changed

include/contacts_config.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ class ContactsConfigWrapper : public ConfigBaseImpl,
2020
Napi::Value get(const Napi::CallbackInfo& info);
2121
Napi::Value getAll(const Napi::CallbackInfo& info);
2222
void set(const Napi::CallbackInfo& info);
23-
Napi::Value setProfileUpdatedSeconds(const Napi::CallbackInfo& info);
2423
Napi::Value erase(const Napi::CallbackInfo& info);
2524
};
2625

include/groups/meta_group_wrapper.hpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ class MetaGroupWrapper : public Napi::ObjectWrap<MetaGroupWrapper> {
6262
Napi::Value memberGetOrConstruct(const Napi::CallbackInfo& info);
6363
Napi::Value memberConstructAndSet(const Napi::CallbackInfo& info);
6464

65-
void memberSetNameTruncated(const Napi::CallbackInfo& info);
6665
void memberSetInviteFailed(const Napi::CallbackInfo& info);
6766
void memberSetInviteSent(const Napi::CallbackInfo& info);
6867
void memberSetInviteNotSent(const Napi::CallbackInfo& info);
@@ -71,8 +70,7 @@ class MetaGroupWrapper : public Napi::ObjectWrap<MetaGroupWrapper> {
7170
void memberSetPromotionSent(const Napi::CallbackInfo& info);
7271
void memberSetPromotionFailed(const Napi::CallbackInfo& info);
7372
void memberSetPromotionAccepted(const Napi::CallbackInfo& info);
74-
void memberSetProfilePicture(const Napi::CallbackInfo& info);
75-
void memberSetProfileUpdatedSeconds(const Napi::CallbackInfo& info);
73+
void memberSetProfileDetails(const Napi::CallbackInfo& info);
7674
Napi::Value memberResetAllSendingState(const Napi::CallbackInfo& info);
7775
void memberSetSupplement(const Napi::CallbackInfo& info);
7876
Napi::Value memberEraseAndRekey(const Napi::CallbackInfo& info);

include/utilities.hpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,21 @@ std::optional<bool> maybeNonemptyBoolean(Napi::Value x, const std::string& ident
6363
std::optional<std::chrono::sys_seconds> maybeNonemptySysSeconds(
6464
Napi::Value x, const std::string& identifier);
6565

66+
std::chrono::sys_seconds toCppSysSeconds(Napi::Value x, const std::string& identifier);
67+
6668
bool toCppBoolean(Napi::Value x, const std::string& identifier);
6769

68-
// If the object is null/undef/empty returns nullopt, otherwise if a String returns a std::string of
69-
// the value. Throws if something else.
70+
// If the object is null/undef/empty returns nullopt, otherwise if a String returns a
71+
// std::string of the value. Throws if something else.
7072
std::optional<std::string> maybeNonemptyString(Napi::Value x, const std::string& identifier);
7173

7274
// If the object is null/undef/empty returns nullopt, otherwise if a Uint8Array returns a
7375
// std::vector<unsigned char> of the value. Throws if something else.
7476
std::optional<std::vector<unsigned char>> maybeNonemptyBuffer(
7577
Napi::Value x, const std::string& identifier);
7678

77-
// Implementation struct of toJs(); we add specializations of this for any C++ types we want to be
78-
// able to convert into JS types.
79+
// Implementation struct of toJs(); we add specializations of this for any C++ types we want to
80+
// be able to convert into JS types.
7981
template <typename T, typename SFINAE = void>
8082
struct toJs_impl {
8183
// If this gets instantiated it means we're missing a specialization and so fail to compile:
@@ -219,8 +221,8 @@ static Napi::Array get_all_impl(const Napi::CallbackInfo& info, size_t size, It
219221
});
220222
}
221223

222-
// Wraps a string in an optional<string_view> which will be nullopt if the input string is empty.
223-
// This is particularly useful with `toJs` to convert empty strings into Null.
224+
// Wraps a string in an optional<string_view> which will be nullopt if the input string is
225+
// empty. This is particularly useful with `toJs` to convert empty strings into Null.
224226
inline std::optional<std::string_view> maybe_string(std::string_view val) {
225227
if (val.empty())
226228
return std::nullopt;
@@ -258,8 +260,8 @@ auto wrapResult(const Napi::Env& env, Call&& call) {
258260
}
259261
}
260262

261-
// Similar to wrapResult(), but a small shortcut to allow passing `info` instead of `info.Env()` as
262-
// the first argument.
263+
// Similar to wrapResult(), but a small shortcut to allow passing `info` instead of `info.Env()`
264+
// as the first argument.
263265
template <typename Call>
264266
auto wrapResult(const Napi::CallbackInfo& info, Call&& call) {
265267
return wrapResult(info.Env(), std::forward<Call>(call));

src/contacts_config.cpp

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@ void ContactsConfigWrapper::Init(Napi::Env env, Napi::Object exports) {
6565
InstanceMethod("get", &ContactsConfigWrapper::get),
6666
InstanceMethod("getAll", &ContactsConfigWrapper::getAll),
6767
InstanceMethod("set", &ContactsConfigWrapper::set),
68-
InstanceMethod(
69-
"setProfileUpdatedSeconds",
70-
&ContactsConfigWrapper::setProfileUpdatedSeconds),
7168
InstanceMethod("erase", &ContactsConfigWrapper::erase),
7269

7370
});
@@ -127,8 +124,6 @@ void ContactsConfigWrapper::set(const Napi::CallbackInfo& info) {
127124
// created time)
128125
contact.created = unix_timestamp_now();
129126

130-
if (auto name = maybeNonemptyString(obj.Get("name"), "contacts.set name"))
131-
contact.set_name(std::move(*name));
132127
if (auto nickname = maybeNonemptyString(obj.Get("nickname"), "contacts.set nickname"))
133128
contact.set_nickname(std::move(*nickname));
134129
else
@@ -144,40 +139,27 @@ void ContactsConfigWrapper::set(const Napi::CallbackInfo& info) {
144139
toCppString(obj.Get("expirationMode"), "contacts.set expirationMode"));
145140
contact.exp_timer = std::chrono::seconds{toCppInteger(
146141
obj.Get("expirationTimerSeconds"), "contacts.set expirationTimerSeconds")};
147-
if (auto pic = obj.Get("profilePicture"); !pic.IsUndefined())
148-
contact.profile_picture = profile_pic_from_object(pic);
149-
else
150-
contact.profile_picture.clear();
151-
// if no profile picture are given from the JS side,
152-
// reset that user profile picture
153142

154-
config.set(contact);
155-
});
156-
}
143+
auto newProfileUpdateSeconds = toCppSysSeconds(
144+
obj.Get("profileUpdatedSeconds"), "contacts.set, profileUpdatedSeconds");
157145

158-
Napi::Value ContactsConfigWrapper::setProfileUpdatedSeconds(const Napi::CallbackInfo& info) {
159-
return wrapResult(info, [&] {
160-
assertInfoLength(info, 1);
146+
// if the saved profile info is older than the new one, update it and the profile fields
147+
// provided
148+
if (contact.profile_updated < newProfileUpdateSeconds) {
149+
contact.profile_updated = newProfileUpdateSeconds;
161150

162-
auto arg = info[0];
163-
assertIsObject(arg);
164-
auto obj = arg.As<Napi::Object>();
151+
if (auto name = maybeNonemptyString(obj.Get("name"), "contacts.set name"))
152+
contact.set_name(std::move(*name));
165153

166-
if (obj.IsEmpty())
167-
throw std::invalid_argument("setProfileUpdatedSeconds received empty");
168-
169-
auto sessionID = toCppString(obj.Get("id"), "contacts.setProfileUpdatedSeconds, id");
170-
auto contact = config.get(sessionID);
171-
172-
auto seconds = maybeNonemptySysSeconds(
173-
obj.Get("profileUpdatedSeconds"),
174-
"contacts.setProfileUpdatedSeconds, profileUpdatedSeconds");
175-
if (contact && seconds) {
176-
config.set_profile_updated(sessionID, seconds.value());
177-
config.set(*contact);
178-
return true;
154+
// if no profile picture are given from the JS side,
155+
// reset that user profile picture
156+
if (auto pic = obj.Get("profilePicture"); !pic.IsUndefined())
157+
contact.profile_picture = profile_pic_from_object(pic);
158+
else
159+
contact.profile_picture.clear();
179160
}
180-
return false;
161+
162+
config.set(contact);
181163
});
182164
}
183165

src/groups/meta_group_wrapper.cpp

Lines changed: 15 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,6 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) {
111111
InstanceMethod(
112112
"membersMarkPendingRemoval",
113113
&MetaGroupWrapper::membersMarkPendingRemoval),
114-
InstanceMethod(
115-
"memberSetNameTruncated", &MetaGroupWrapper::memberSetNameTruncated),
116114
InstanceMethod("memberSetSupplement", &MetaGroupWrapper::memberSetSupplement),
117115
InstanceMethod("memberSetInviteSent", &MetaGroupWrapper::memberSetInviteSent),
118116
InstanceMethod(
@@ -131,10 +129,7 @@ void MetaGroupWrapper::Init(Napi::Env env, Napi::Object exports) {
131129
"memberSetPromotionAccepted",
132130
&MetaGroupWrapper::memberSetPromotionAccepted),
133131
InstanceMethod(
134-
"memberSetProfilePicture", &MetaGroupWrapper::memberSetProfilePicture),
135-
InstanceMethod(
136-
"memberSetProfileUpdatedSeconds",
137-
&MetaGroupWrapper::memberSetProfileUpdatedSeconds),
132+
"memberSetProfileDetails", &MetaGroupWrapper::memberSetProfileDetails),
138133
InstanceMethod(
139134
"memberResetAllSendingState",
140135
&MetaGroupWrapper::memberResetAllSendingState),
@@ -523,21 +518,6 @@ Napi::Value MetaGroupWrapper::memberConstructAndSet(const Napi::CallbackInfo& in
523518
});
524519
}
525520

526-
void MetaGroupWrapper::memberSetNameTruncated(const Napi::CallbackInfo& info) {
527-
wrapExceptions(info, [&] {
528-
assertIsString(info[0]);
529-
assertIsString(info[1]);
530-
531-
auto pubkeyHex = toCppString(info[0], "memberSetNameTruncated pubkeyHex");
532-
auto newName = toCppString(info[1], "memberSetNameTruncated newName");
533-
auto m = this->meta_group->members->get(pubkeyHex);
534-
if (m) {
535-
m->set_name(newName);
536-
this->meta_group->members->set(*m);
537-
}
538-
});
539-
}
540-
541521
void MetaGroupWrapper::memberSetSupplement(const Napi::CallbackInfo& info) {
542522
wrapExceptions(info, [&] {
543523
assertIsString(info[0]);
@@ -656,35 +636,30 @@ void MetaGroupWrapper::memberSetPromotionAccepted(const Napi::CallbackInfo& info
656636
});
657637
}
658638

659-
void MetaGroupWrapper::memberSetProfilePicture(const Napi::CallbackInfo& info) {
639+
void MetaGroupWrapper::memberSetProfileDetails(const Napi::CallbackInfo& info) {
660640
wrapExceptions(info, [&] {
661641
assertInfoLength(info, 2);
662642
assertIsString(info[0]);
663643
assertIsObject(info[1]);
664644

665-
auto pubkeyHex = toCppString(info[0], "memberSetProfilePicture");
666-
auto profilePicture = profile_pic_from_object(info[1]);
645+
auto pubkeyHex = toCppString(info[0], "memberSetProfileDetails");
667646

668647
auto m = this->meta_group->members->get(pubkeyHex);
669-
if (m) {
670-
m->profile_picture = profilePicture;
671-
this->meta_group->members->set(*m);
672-
}
673-
});
674-
}
648+
auto argsAsObj = info[1].As<Napi::Object>();
649+
auto updatedAtSeconds =
650+
toCppSysSeconds(argsAsObj.Get("profileUpdatedSeconds"), "memberSetProfileDetails");
675651

676-
void MetaGroupWrapper::memberSetProfileUpdatedSeconds(const Napi::CallbackInfo& info) {
677-
wrapExceptions(info, [&] {
678-
assertInfoLength(info, 2);
679-
assertIsString(info[0]);
680-
assertIsObject(info[1]);
652+
// if the profile details provided are more recent that the ones saved, update them
653+
if (m && updatedAtSeconds > m->profile_updated) {
654+
m->profile_updated = updatedAtSeconds;
655+
656+
auto profilePicture = profile_pic_from_object(argsAsObj.Get("profilePicture"));
657+
m->profile_picture = profilePicture;
681658

682-
auto pubkeyHex = toCppString(info[0], "memberSetProfiUpdatedSeconds");
683-
auto updatedAtSeconds = maybeNonemptySysSeconds(info[1], "memberSetProfiUpdatedSeconds");
659+
// this will truncate silently if the name is too long
660+
auto newName = toCppString(argsAsObj.Get("name"), "memberSetProfileDetails newName");
661+
m->set_name_truncated(newName);
684662

685-
auto m = this->meta_group->members->get(pubkeyHex);
686-
if (m) {
687-
m->profile_updated = updatedAtSeconds.value();
688663
this->meta_group->members->set(*m);
689664
}
690665
});

src/utilities.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,18 @@ std::optional<std::chrono::sys_seconds> maybeNonemptySysSeconds(
149149
return std::chrono::sys_seconds{std::chrono::seconds{num}};
150150
}
151151

152-
throw std::invalid_argument{"maybeNonemptyTime with invalid type, called from " + identifier};
152+
throw std::invalid_argument{
153+
"maybeNonemptySysSeconds with invalid type, called from " + identifier};
154+
}
155+
156+
std::chrono::sys_seconds toCppSysSeconds(Napi::Value x, const std::string& identifier) {
157+
158+
if (x.IsNumber()) {
159+
auto num = x.As<Napi::Number>().Int64Value();
160+
return std::chrono::sys_seconds{std::chrono::seconds{num}};
161+
}
162+
163+
throw std::invalid_argument{"toCppSysSeconds with invalid type, called from " + identifier};
153164
}
154165

155166
std::optional<session::config::profile_pic> maybeNonemptyProfilePic(

types/groups/groupmembers.d.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ declare module 'libsession_util_nodejs' {
8787
memberGetAllPendingRemovals: () => Array<GroupMemberGet>;
8888

8989
// setters
90-
memberSetNameTruncated: (pubkeyHex: PubkeyType, newName: string) => void;
9190

9291
/**
9392
* A member's invite state defaults to invite-not-sent.
@@ -117,8 +116,14 @@ declare module 'libsession_util_nodejs' {
117116
/** Called when the member accepted the promotion */
118117
memberSetPromotionAccepted: (pubkeyHex: PubkeyType) => void;
119118

120-
memberSetProfilePicture: (pubkeyHex: PubkeyType, profilePicture: ProfilePicture) => void;
121-
memberSetProfileUpdatedSeconds: (pubkeyHex: PubkeyType, profileUpdatedSeconds: number) => void;
119+
memberSetProfileDetails: (
120+
pubkeyHex: PubkeyType,
121+
profileDetails: {
122+
profileUpdatedSeconds: number;
123+
name: string;
124+
profilePicture: ProfilePicture;
125+
}
126+
) => void;
122127
memberResetAllSendingState: () => boolean;
123128
memberSetSupplement: (pubkeyHex: PubkeyType) => void;
124129
membersMarkPendingRemoval: (members: Array<PubkeyType>, withMessages: boolean) => void;

types/groups/metagroup.d.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ declare module 'libsession_util_nodejs' {
9797
public memberGetAll: MetaGroupWrapper['memberGetAll'];
9898
public memberGetAllPendingRemovals: MetaGroupWrapper['memberGetAllPendingRemovals'];
9999
public memberSetInviteAccepted: MetaGroupWrapper['memberSetInviteAccepted'];
100-
public memberSetNameTruncated: MetaGroupWrapper['memberSetNameTruncated'];
101100
public memberSetPromoted: MetaGroupWrapper['memberSetPromoted'];
102101
public memberSetPromotionAccepted: MetaGroupWrapper['memberSetPromotionAccepted'];
103102
public memberSetPromotionSent: MetaGroupWrapper['memberSetPromotionSent'];
@@ -107,8 +106,7 @@ declare module 'libsession_util_nodejs' {
107106
public memberSetInviteFailed: MetaGroupWrapper['memberSetInviteFailed'];
108107
public memberEraseAndRekey: MetaGroupWrapper['memberEraseAndRekey'];
109108
public membersMarkPendingRemoval: MetaGroupWrapper['membersMarkPendingRemoval'];
110-
public memberSetProfilePicture: MetaGroupWrapper['memberSetProfilePicture'];
111-
public memberSetProfileUpdatedSeconds: MetaGroupWrapper['memberSetProfileUpdatedSeconds'];
109+
public memberSetProfileDetails: MetaGroupWrapper['memberSetProfileDetails'];
112110
public memberResetAllSendingState: MetaGroupWrapper['memberResetAllSendingState'];
113111
public memberSetSupplement: MetaGroupWrapper['memberSetSupplement'];
114112

@@ -149,7 +147,6 @@ declare module 'libsession_util_nodejs' {
149147
| MakeActionCall<MetaGroupWrapper, 'memberGetAll'>
150148
| MakeActionCall<MetaGroupWrapper, 'memberGetAllPendingRemovals'>
151149
| MakeActionCall<MetaGroupWrapper, 'memberSetInviteAccepted'>
152-
| MakeActionCall<MetaGroupWrapper, 'memberSetNameTruncated'>
153150
| MakeActionCall<MetaGroupWrapper, 'memberSetPromoted'>
154151
| MakeActionCall<MetaGroupWrapper, 'memberSetPromotionFailed'>
155152
| MakeActionCall<MetaGroupWrapper, 'memberSetPromotionSent'>
@@ -159,8 +156,7 @@ declare module 'libsession_util_nodejs' {
159156
| MakeActionCall<MetaGroupWrapper, 'memberSetInviteFailed'>
160157
| MakeActionCall<MetaGroupWrapper, 'memberEraseAndRekey'>
161158
| MakeActionCall<MetaGroupWrapper, 'membersMarkPendingRemoval'>
162-
| MakeActionCall<MetaGroupWrapper, 'memberSetProfilePicture'>
163-
| MakeActionCall<MetaGroupWrapper, 'memberSetProfileUpdatedSeconds'>
159+
| MakeActionCall<MetaGroupWrapper, 'memberSetProfileDetails'>
164160
| MakeActionCall<MetaGroupWrapper, 'memberResetAllSendingState'>
165161
| MakeActionCall<MetaGroupWrapper, 'memberSetSupplement'>
166162

types/user/contacts.d.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@ declare module 'libsession_util_nodejs' {
1010
init: (secretKey: Uint8Array, dump: Uint8Array | null) => void;
1111
/** This function is used to free wrappers from memory only */
1212
free: () => void;
13-
get: (pubkeyHex: string) => ContactInfo | null;
13+
get: (pubkeyHex: string) => ContactInfoGet | null;
1414
set: (contact: ContactInfoSet) => void;
15-
setProfileUpdatedSeconds: (pubkeyHex: string, profileUpdatedSeconds: number) => void;
16-
getAll: () => Array<ContactInfo>;
15+
getAll: () => Array<ContactInfoGet>;
1716
erase: (pubkeyHex: string) => void;
1817
};
1918

@@ -27,15 +26,25 @@ declare module 'libsession_util_nodejs' {
2726

2827
type ContactInfoShared = WithPriority & {
2928
id: string;
30-
name?: string;
3129
nickname?: string;
32-
profilePicture?: ProfilePicture;
3330
/**
3431
* Can only be set the first time a contact is created, a new change won't override the value in the wrapper.
3532
*/
3633
createdAtSeconds: number;
3734
expirationMode?: DisappearingMessageConversationModeType;
3835
expirationTimerSeconds?: number;
36+
/**
37+
* A name & profile pic change won't be applied unless this value is more recent than the currently saved one.
38+
*/
39+
profileUpdatedSeconds: number;
40+
/**
41+
* see `profileUpdatedSeconds` for more info.
42+
*/
43+
name?: string;
44+
/**
45+
* see `profileUpdatedSeconds` for more info.
46+
*/
47+
profilePicture?: ProfilePicture;
3948
};
4049

4150
export type ContactInfoSet = ContactInfoShared & {
@@ -44,22 +53,16 @@ declare module 'libsession_util_nodejs' {
4453
blocked?: boolean;
4554
};
4655

47-
export type ContactInfo = ContactInfoShared & {
56+
export type ContactInfoGet = ContactInfoShared & {
4857
approved: boolean;
4958
approvedMe: boolean;
5059
blocked: boolean;
51-
/**
52-
* This should be bumped whenever the contact profile is updated through
53-
* `setProfileUpdatedSeconds`.
54-
*/
55-
profileUpdatedSeconds: number;
5660
};
5761

5862
export class ContactsConfigWrapperNode extends BaseConfigWrapperNode {
5963
constructor(secretKey: Uint8Array, dump: Uint8Array | null);
6064
public get: ContactsWrapper['get'];
6165
public set: ContactsWrapper['set'];
62-
public setProfileUpdatedSeconds: ContactsWrapper['setProfileUpdatedSeconds'];
6366
public getAll: ContactsWrapper['getAll'];
6467
public erase: ContactsWrapper['erase'];
6568
}
@@ -69,7 +72,6 @@ declare module 'libsession_util_nodejs' {
6972
| MakeActionCall<ContactsWrapper, 'free'>
7073
| MakeActionCall<ContactsWrapper, 'get'>
7174
| MakeActionCall<ContactsWrapper, 'set'>
72-
| MakeActionCall<ContactsWrapper, 'setProfileUpdatedSeconds'>
7375
| MakeActionCall<ContactsWrapper, 'getAll'>
7476
| MakeActionCall<ContactsWrapper, 'erase'>;
7577
}

0 commit comments

Comments
 (0)