Skip to content

Commit

Permalink
sdk(sync-agent): don't treat Myself model as special (#894)
Browse files Browse the repository at this point in the history
Previously, the Myself model was extending a Member model, which
required some special treatment to avoid creating it twice.

Now, the `Myself` model is wrapping a Member with some set actions,
removing the cognitive overhead when changing the `Members` model, since
we dont need to keep the special myself case in mind when doing changes.
  • Loading branch information
miguel-nascimento authored Aug 28, 2024
1 parent edc1994 commit 06fb5a3
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 68 deletions.
2 changes: 1 addition & 1 deletion packages/react-sdk/src/useDisplayName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ObservableConfig, useObservable } from './useObservable'
import { type ActionConfig, useAction } from './internals/useAction'

export const useDisplayName = (
member: Member,
member: Member | Myself,
config?: ObservableConfig.FromObservable<MemberDisplayName>,
) => {
const { data, ...rest } = useObservable(member?.observables.displayName, config)
Expand Down
2 changes: 1 addition & 1 deletion packages/react-sdk/src/useEnsAddress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ObservableConfig, useObservable } from './useObservable'
import { type ActionConfig, useAction } from './internals/useAction'

export const useEnsAddress = (
member: Member,
member: Member | Myself,
config?: ObservableConfig.FromObservable<MemberEnsAddress>,
) => {
const { data, ...rest } = useObservable(member?.observables.ensAddress, config)
Expand Down
5 changes: 4 additions & 1 deletion packages/react-sdk/src/useNft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import type { Member, MemberNft, Myself } from '@river-build/sdk'
import { ObservableConfig, useObservable } from './useObservable'
import { type ActionConfig, useAction } from './internals/useAction'

export const useNft = (member: Member, config?: ObservableConfig.FromObservable<MemberNft>) => {
export const useNft = (
member: Member | Myself,
config?: ObservableConfig.FromObservable<MemberNft>,
) => {
const { data, ...rest } = useObservable(member?.observables.nft, config)
return {
...data,
Expand Down
2 changes: 1 addition & 1 deletion packages/react-sdk/src/useUsername.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ObservableConfig, useObservable } from './useObservable'
import { type ActionConfig, useAction } from './internals/useAction'

export const useUsername = (
member: Member,
member: Member | Myself,
config?: ObservableConfig.FromObservable<MemberUsername>,
) => {
const { data, ...rest } = useObservable(member?.observables.username, config)
Expand Down
90 changes: 31 additions & 59 deletions packages/sdk/src/sync-agent/members/members.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,18 @@ export class Members extends PersistedObservable<MembersModel> {
})
}

// Lazy loading the myself object, so we dont create unneeded e.g: if we're not in the stream yet
// but we create it if we want to access it
get myself() {
if (this._myself) return this._myself
this._myself = new Myself(this.data.id, this.riverConnection, this.store)
this._myself.onStreamInitialized(this.data.id)
return this._myself
if (this._myself) {
return this._myself
}
const member = this.get(this.riverConnection.userId)
const my = new Myself(member, this.data.id, this.riverConnection)
this._myself = my
return my
}

get(userId: string) {
check(isUserId(userId), 'invalid user id')
if (userId === this.riverConnection.userId) {
return this.myself
}
// Its possible to get a member that its not in the userIds array, if the user left the stream for example
// We can get a member that left, to get the last snapshot of the member
if (!this.members[userId]) {
Expand Down Expand Up @@ -98,16 +96,14 @@ export class Members extends PersistedObservable<MembersModel> {
(member) => member.userId,
)
for (const userId of userIds) {
if (userId !== this.riverConnection.userId) {
if (!this.members[userId]) {
this.members[userId] = new Member(
userId,
streamId,
this.riverConnection,
this.store,
)
this.members[userId].onStreamInitialized(streamId)
}
if (!this.members[userId]) {
this.members[userId] = new Member(
userId,
streamId,
this.riverConnection,
this.store,
)
this.members[userId].onStreamInitialized(streamId)
}
}
this.setData({ initialized: true, userIds })
Expand All @@ -130,52 +126,28 @@ export class Members extends PersistedObservable<MembersModel> {
private onMemberJoin = (streamId: string, userId: string): void => {
if (streamId !== this.data.id) return
this.setData({ userIds: [...this.data.userIds, userId] })
if (userId === this.riverConnection.userId) {
if (!this._myself) {
this._myself = new Myself(streamId, this.riverConnection, this.store)
this._myself.onStreamInitialized(streamId)
}
} else {
if (!this.members[userId]) {
this.members[userId] = new Member(
userId,
streamId,
this.riverConnection,
this.store,
)
this.members[userId].onStreamInitialized(streamId)
this.members[userId].observables.membership.onStreamMembershipUpdated(
streamId,
userId,
MembershipOp.SO_JOIN,
)
}
if (!this.members[userId]) {
this.members[userId] = new Member(userId, streamId, this.riverConnection, this.store)
this.members[userId].onStreamInitialized(streamId)
this.members[userId].observables.membership.onStreamMembershipUpdated(
streamId,
userId,
MembershipOp.SO_JOIN,
)
}
}

private onMemberInvite = (streamId: string, userId: string): void => {
if (streamId !== this.data.id) return
this.setData({ userIds: [...this.data.userIds, userId] })
if (userId === this.riverConnection.userId) {
if (!this._myself) {
this._myself = new Myself(streamId, this.riverConnection, this.store)
this._myself.onStreamInitialized(streamId)
}
} else {
if (!this.members[userId]) {
this.members[userId] = new Member(
userId,
streamId,
this.riverConnection,
this.store,
)
this.members[userId].onStreamInitialized(streamId)
this.members[userId].observables.membership.onStreamMembershipUpdated(
streamId,
userId,
MembershipOp.SO_INVITE,
)
}
if (!this.members[userId]) {
this.members[userId] = new Member(userId, streamId, this.riverConnection, this.store)
this.members[userId].onStreamInitialized(streamId)
this.members[userId].observables.membership.onStreamMembershipUpdated(
streamId,
userId,
MembershipOp.SO_INVITE,
)
}
}

Expand Down
30 changes: 25 additions & 5 deletions packages/sdk/src/sync-agent/members/models/myself.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,37 @@
import type { Address } from '@river-build/web3'
import type { Store } from '../../../store/store'
import type { RiverConnection } from '../../river-connection/riverConnection'
import { type NftModel } from './metadata/nft'
import { addressFromUserId } from '../../../id'
import { Member } from './member'

export class Myself extends Member {
export class Myself {
observables: Member['observables']
constructor(
private streamId: string,
public member: Member,
protected streamId: string,
protected riverConnection: RiverConnection,
store: Store,
) {
super(riverConnection.userId, streamId, riverConnection, store)
this.observables = member.observables
}

get username() {
return this.member.username
}

get displayName() {
return this.member.displayName
}

get ensAddress() {
return this.member.ensAddress
}

get nft() {
return this.member.nft
}

get membership() {
return this.member.membership
}

async setUsername(username: string) {
Expand Down

0 comments on commit 06fb5a3

Please sign in to comment.