-
Notifications
You must be signed in to change notification settings - Fork 132
/
DefaultChannelSupport.ts
154 lines (130 loc) · 6.35 KB
/
DefaultChannelSupport.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import { Channel, ContextHandler, Listener, PrivateChannel, ChannelSelector, EventHandler } from "@kite9/fdc3-standard";
import { Messaging } from "../Messaging";
import { ChannelSupport } from "./ChannelSupport";
import { DefaultPrivateChannel } from "./DefaultPrivateChannel";
import { DefaultChannel } from "./DefaultChannel";
import { DefaultContextListener } from "../listeners/DefaultContextListener";
import { BrowserTypes } from "@kite9/fdc3-schema";
import { FollowingContextListener } from "../listeners/FollowingContextListener";
import { EventListener } from "../listeners/EventListener";
type ChannelDetail = BrowserTypes.Channel
type GetUserChannelsRequest = BrowserTypes.GetUserChannelsRequest
type GetUserChannelsResponse = BrowserTypes.GetUserChannelsResponse
type GetOrCreateChannelResponse = BrowserTypes.GetOrCreateChannelResponse
type GetOrCreateChannelRequest = BrowserTypes.GetOrCreateChannelRequest
type CreatePrivateChannelRequest = BrowserTypes.CreatePrivateChannelRequest
type CreatePrivateChannelResponse = BrowserTypes.CreatePrivateChannelResponse
type JoinUserChannelResponse = BrowserTypes.JoinUserChannelResponse
type JoinUserChannelRequest = BrowserTypes.JoinUserChannelRequest
type GetCurrentChannelResponse = BrowserTypes.GetCurrentChannelResponse
type GetCurrentChannelRequest = BrowserTypes.GetCurrentChannelRequest
type LeaveCurrentChannelRequest = BrowserTypes.LeaveCurrentChannelRequest
type LeaveCurrentChannelResponse = BrowserTypes.LeaveCurrentChannelResponse
export class DefaultChannelSupport implements ChannelSupport {
readonly messaging: Messaging
readonly channelSelector: ChannelSelector
protected userChannels: Channel[] | null = null
private followingListeners: FollowingContextListener[] = []
constructor(messaging: Messaging, channelSelector: ChannelSelector) {
this.messaging = messaging;
this.channelSelector = channelSelector
this.channelSelector.setChannelChangeCallback((channelId: string | null) => {
if (channelId == null) {
this.leaveUserChannel()
} else {
this.joinUserChannel(channelId)
}
})
this.addChannelChangedEventHandler((e) => {
this.channelSelector.updateChannel(e.details.newChannelId, this.userChannels ?? [])
})
}
async addChannelChangedEventHandler(handler: EventHandler): Promise<Listener> {
const listener = new EventListener(this.messaging, "channelChangedEvent", handler)
await listener.register()
return listener
}
async getUserChannel(): Promise<Channel | null> {
const response = await this.messaging.exchange<GetCurrentChannelResponse>({
meta: this.messaging.createMeta(),
type: 'getCurrentChannelRequest',
payload: {}
} as GetCurrentChannelRequest, 'getCurrentChannelResponse')
if (response.payload?.channel?.id) {
return new DefaultChannel(this.messaging, response.payload.channel.id, "user", response.payload.channel.displayMetadata)
} else {
return null
}
}
async getUserChannels(): Promise<Channel[]> {
if (!this.userChannels) {
const response = await this.messaging.exchange<GetUserChannelsResponse>({
meta: this.messaging.createMeta(),
type: 'getUserChannelsRequest',
payload: {}
} as GetUserChannelsRequest, 'getUserChannelsResponse')
const channels: ChannelDetail[] = response.payload.userChannels ?? []
this.userChannels = channels.map(c => new DefaultChannel(this.messaging, c.id, "user", c.displayMetadata));
}
return this.userChannels
}
async getOrCreate(id: string): Promise<Channel> {
const response = await this.messaging.exchange<GetOrCreateChannelResponse>({
meta: this.messaging.createMeta(),
type: 'getOrCreateChannelRequest',
payload: {
channelId: id
}
} as GetOrCreateChannelRequest,
'getOrCreateChannelResponse')
const out = new DefaultChannel(this.messaging, id, "app", response.payload.channel?.displayMetadata!!)
return out
}
async createPrivateChannel(): Promise<PrivateChannel> {
const response = await this.messaging.exchange<CreatePrivateChannelResponse>({
meta: this.messaging.createMeta(),
type: 'createPrivateChannelRequest',
payload: {}
} as CreatePrivateChannelRequest,
'createPrivateChannelResponse')
return new DefaultPrivateChannel(this.messaging, response.payload?.privateChannel?.id!!)
}
async leaveUserChannel(): Promise<void> {
await this.messaging.exchange<LeaveCurrentChannelResponse>({
meta: this.messaging.createMeta(),
type: 'leaveCurrentChannelRequest',
payload: {}
} as LeaveCurrentChannelRequest,
'leaveCurrentChannelResponse')
this.channelSelector.updateChannel(null, this.userChannels ?? [])
this.followingListeners.forEach(l => l.changeChannel(null))
}
async joinUserChannel(id: string) {
await this.messaging.exchange<JoinUserChannelResponse>({
meta: this.messaging.createMeta(),
type: 'joinUserChannelRequest',
payload: {
channelId: id
}
} as JoinUserChannelRequest,
'joinUserChannelResponse')
this.channelSelector.updateChannel(id, this.userChannels ?? [])
for (const l of this.followingListeners) {
await l.changeChannel(new DefaultChannel(this.messaging, id, "user"))
}
}
async addContextListener(handler: ContextHandler, type: string | null): Promise<Listener> {
const _container = this
class UnsubscribingDefaultContextListener extends DefaultContextListener {
async unsubscribe(): Promise<void> {
super.unsubscribe()
_container.followingListeners = _container.followingListeners.filter(l => l != this)
}
}
const currentChannelId = (await this.getUserChannel())?.id ?? null
const listener = new UnsubscribingDefaultContextListener(this.messaging, currentChannelId, type, handler)
this.followingListeners.push(listener)
await listener.register()
return listener
}
}