@@ -1,5 +1,8 @@
1+import _get from 'lodash/get';
2+import { compose } from 'lodash/fp';
13import type { Apps } from 'types/store';
24import store from 'stores/store';
5+import { sleep } from 'lib/utils';
36import { api } from 'lib/api';
47import { normalizeId } from 'lib/id';
58
@@ -7,17 +10,26 @@ export function getProvidedApps(patp: string): Promise<any> {
710 return api.scry<any>({ app: 'treaty', path: `/treaties/${patp}` });
811}
912
13+// Unused, use subscription
1014export function getKnownApps(): Promise<any> {
1115 return api.scry<any>({ app: 'treaty', path: `/allies` }).then(processAllies);
1216}
1317
1418export function getApp(ship: string, desk: string): Promise<any> {
15− return api.scry<any>({ app: 'treaty', path: `/treaty/${normalizeId(ship)}/${desk}` });
19+ return getAppByPath(`${normalizeId(ship)}/${desk}`);
1620}
1721
1822// @param path - ship/desk e.g. ~mister-dister-dozzod-dozzod/webterm
19−export function getAppByPath(path: string): Promise<any> {
20− return api.scry<any>({ app: 'treaty', path: `/treaty/${path}` });
23+export async function getAppByPath(path: string, retry: number = 2): Promise<any> {
24+ try {
25+ return await api.scry<any>({ app: 'treaty', path: `/treaty/${path}` });
26+ } catch {
27+ if (retry > 0) {
28+ console.log(`Got error when fetching app: ${path}.\nTrying at most ${retry} more time(s)`);
29+ await sleep(750);
30+ return getAppByPath(path, retry - 1);
31+ }
32+ }
2133}
2234
2335export function getInstalledApps(): Promise<any> {
@@ -30,7 +42,6 @@ export async function sendAllyUpdate(cmd: string, ship: string) {
3042 mark: 'ally-update-0',
3143 json: { [cmd]: normalizeId(ship) },
3244 });
33− // store.refreshKnownApps();
3445 return result;
3546}
3647
@@ -49,7 +60,6 @@ export async function addAllies(ships: string[]) {
4960 results = results.filter(r => r.status === 'fulfilled').map((r) => {
5061 return (r as PromiseFulfilledResult<any>).value;
5162 });
52− store.refreshKnownApps();
5363 return results;
5464}
5565
@@ -60,7 +70,6 @@ export async function delAllies(ships: string[], retry: number = 0) {
6070 results = results.filter(r => r.status === 'fulfilled').map((r) => {
6171 return (r as PromiseFulfilledResult<any>).value;
6272 });
63− store.refreshKnownApps();
6473 return results;
6574}
6675
@@ -73,3 +82,94 @@ export function processAllies(rawPals: any): Apps {
7382 set,
7483 };
7584}
85+
86+export type AllyUpdate = AllyUpdateIni | AllyUpdateAdd | AllyUpdateDel | AllyUpdateNew;
87+
88+export interface AllyUpdateIni {
89+ ini: {
90+ [ship: string]: string[];
91+ }
92+}
93+
94+export interface AllyUpdateNew {
95+ new: {
96+ ship: string;
97+ alliance: string[];
98+ }
99+}
100+
101+export interface AllyUpdateAdd {
102+ add: string;
103+}
104+
105+export interface AllyUpdateDel {
106+ del: string;
107+}
108+
109+export function handleAllyUpdateIni(json: AllyUpdate, apps: Apps): Apps {
110+ const data = _get(json, 'ini', false);
111+ if (data) {
112+ apps = processAllies(json)
113+ }
114+ return apps;
115+};
116+
117+export function handleAllyUpdateNew(json: AllyUpdate, apps: Apps): Apps {
118+ const data = _get(json, 'new', false);
119+ if (data) {
120+ apps = processAllies({
121+ ini: {
122+ ...apps.allies,
123+ [data.ship]: data.alliance,
124+ }
125+ });
126+ }
127+ return apps;
128+};
129+
130+export function handleAllyUpdateAdd(json: AllyUpdate, apps: Apps): Apps {
131+ const data = _get(json, 'add', false);
132+ if (data) {
133+ apps = processAllies({
134+ ini: {
135+ ...apps.allies,
136+ [data]: [],
137+ }
138+ });
139+ }
140+ return apps;
141+};
142+
143+export function handleAllyUpdateDel(json: AllyUpdate, apps: Apps): Apps {
144+ const data = _get(json, 'del', false);
145+ if (data && (data in apps.allies)) {
146+ delete apps.allies[data];
147+ apps = processAllies({
148+ ini: apps.allies,
149+ });
150+ }
151+ return apps;
152+};
153+
154+export function handleAllyUpdateEvent(updateApps) {
155+ return (allyUpdate: AllyUpdate) => {
156+ console.log(`received ally-update: ${Object.keys(allyUpdate)}`);
157+ const reducers = [handleAllyUpdateIni, handleAllyUpdateNew, handleAllyUpdateAdd, handleAllyUpdateDel];
158+ const reducer = compose(reducers.map(r => sta => r(allyUpdate, sta)));
159+ updateApps(reducer);
160+ };
161+}
162+
163+export function subscribeToApps(e: (data: any) => void): Promise<any> {
164+ return api.subscribe({
165+ app: 'treaty',
166+ path: '/allies',
167+ event: handleAllyUpdateEvent(e),
168+ err: () => {
169+ console.error(`Subscription to treaty/all just got "err"`);
170+ },
171+ quit: () => {
172+ console.error(`Subscription to treaty/all just got "quit"`);
173+ }
174+ })
175+}