@amityco/ts-sdk 7.29.1-e932a95f.0 → 7.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/@types/core/events.d.ts +4 -0
- package/dist/@types/core/events.d.ts.map +1 -1
- package/dist/@types/domains/user.d.ts +16 -10
- package/dist/@types/domains/user.d.ts.map +1 -1
- package/dist/client/api/setupLoginSubscriptions.d.ts.map +1 -1
- package/dist/core/events.d.ts +3 -3
- package/dist/core/events.d.ts.map +1 -1
- package/dist/index.cjs.js +384 -136
- package/dist/index.esm.js +384 -136
- package/dist/index.umd.js +2 -2
- package/dist/userRepository/api/flagUser.d.ts.map +1 -1
- package/dist/userRepository/api/isUserFlaggedByMe.d.ts +9 -23
- package/dist/userRepository/api/isUserFlaggedByMe.d.ts.map +1 -1
- package/dist/userRepository/api/unflagUser.d.ts +5 -4
- package/dist/userRepository/api/unflagUser.d.ts.map +1 -1
- package/dist/userRepository/internalApi/getFlagsByMe.d.ts +4 -3
- package/dist/userRepository/internalApi/getFlagsByMe.d.ts.map +1 -1
- package/dist/userRepository/internalApi/tests/getFlagsByMe.test.d.ts +2 -0
- package/dist/userRepository/internalApi/tests/getFlagsByMe.test.d.ts.map +1 -0
- package/dist/userRepository/observers/getUser.d.ts.map +1 -1
- package/dist/userRepository/observers/getUsers/UserLiveCollectionController.d.ts.map +1 -1
- package/dist/userRepository/observers/searchUserByDisplayName/SearchUserLiveCollectionController.d.ts.map +1 -1
- package/dist/userRepository/utils/submitUserReport.d.ts.map +1 -1
- package/dist/userRepository/utils/userFlagByMe.d.ts +68 -0
- package/dist/userRepository/utils/userFlagByMe.d.ts.map +1 -0
- package/dist/utils/bloomFilter.d.ts +8 -3
- package/dist/utils/bloomFilter.d.ts.map +1 -1
- package/dist/utils/linkedObject/userLinkedObject.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -58,7 +58,7 @@ var UserProfileFieldEnum;
|
|
|
58
58
|
* Selects which of the caller's reports `UserRepository.unflagUser` withdraws, sent as the
|
|
59
59
|
* `reportType` query parameter. The four typed members are the backend `reportType` wire
|
|
60
60
|
* values and match `UserReportTypeEnum`. `UNTYPED` selects the typeless (legacy) report,
|
|
61
|
-
* which `
|
|
61
|
+
* which `user.getUserFlagsByMe()` returns as `reportType: null`; it is a selector only, never
|
|
62
62
|
* stored, and the flag endpoint refuses it.
|
|
63
63
|
*/
|
|
64
64
|
var UserReportTypeFilterEnum;
|
|
@@ -343,8 +343,8 @@ var AmityLiveViewerCountMode;
|
|
|
343
343
|
|
|
344
344
|
function getVersion() {
|
|
345
345
|
try {
|
|
346
|
-
// the string ''v7.
|
|
347
|
-
return 'v7.
|
|
346
|
+
// the string ''v7.30.0-esm'' should be replaced by actual value by @rollup/plugin-replace
|
|
347
|
+
return 'v7.30.0-esm';
|
|
348
348
|
}
|
|
349
349
|
catch (error) {
|
|
350
350
|
return '__dev__';
|
|
@@ -1836,15 +1836,64 @@ async function modifyMqttConnection() {
|
|
|
1836
1836
|
}
|
|
1837
1837
|
}
|
|
1838
1838
|
|
|
1839
|
+
class SessionWatcher {
|
|
1840
|
+
constructor() {
|
|
1841
|
+
this._sessionState = "notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */;
|
|
1842
|
+
this._listener = new Map();
|
|
1843
|
+
}
|
|
1844
|
+
onSessionStateChange(callback) {
|
|
1845
|
+
this._listener.set(callback, callback);
|
|
1846
|
+
return () => {
|
|
1847
|
+
this._listener.delete(callback);
|
|
1848
|
+
};
|
|
1849
|
+
}
|
|
1850
|
+
setSessionState(state, reason) {
|
|
1851
|
+
if (this._sessionState === state)
|
|
1852
|
+
return;
|
|
1853
|
+
this._sessionState = state;
|
|
1854
|
+
this._listener.forEach(cb => cb(state, reason));
|
|
1855
|
+
}
|
|
1856
|
+
destroy() {
|
|
1857
|
+
this._listener.clear();
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
let instance$b;
|
|
1861
|
+
var SessionWatcher$1 = {
|
|
1862
|
+
getInstance: () => {
|
|
1863
|
+
if (!instance$b) {
|
|
1864
|
+
instance$b = new SessionWatcher();
|
|
1865
|
+
}
|
|
1866
|
+
return instance$b;
|
|
1867
|
+
},
|
|
1868
|
+
};
|
|
1869
|
+
|
|
1870
|
+
/**
|
|
1871
|
+
* ```js
|
|
1872
|
+
* import { onSessionStateChange } from '@amityco/ts-sdk'
|
|
1873
|
+
* const dispose = onSessionStateChange((state: Amity.SessionStates) => {
|
|
1874
|
+
* // ...
|
|
1875
|
+
* })
|
|
1876
|
+
* ```
|
|
1877
|
+
*
|
|
1878
|
+
* Fired when any {@link Amity.Client} has a session state change
|
|
1879
|
+
*
|
|
1880
|
+
* @param callback The function to call when the event was fired
|
|
1881
|
+
* @returns an {@link Amity.Unsubscriber} function to stop listening
|
|
1882
|
+
*
|
|
1883
|
+
* @category Client Events
|
|
1884
|
+
*/
|
|
1885
|
+
const onSessionStateChange = (callback) => SessionWatcher$1.getInstance().onSessionStateChange(callback);
|
|
1886
|
+
|
|
1839
1887
|
/**
|
|
1840
1888
|
* ```js
|
|
1841
1889
|
* import { getFlagsByMe } from '~/userRepository/internalApi/getFlagsByMe'
|
|
1842
1890
|
* const { isFlagByMe, flags } = await getFlagsByMe('userId')
|
|
1843
1891
|
* ```
|
|
1844
1892
|
*
|
|
1845
|
-
* The v4 read behind `user.getUserFlagsByMe()
|
|
1846
|
-
* `
|
|
1847
|
-
* received. Nothing is filtered, cached or
|
|
1893
|
+
* The v4 read behind `user.getUserFlagsByMe()`, the background confirm of
|
|
1894
|
+
* `user.isFlaggedByMe`, and the deprecated `UserRepository.isUserFlaggedByMe`:
|
|
1895
|
+
* `GET /api/v4/users/:userId/isFlagByMe`, returned as received. Nothing is filtered, cached or
|
|
1896
|
+
* persisted here, and `hashFlag` is not consulted.
|
|
1848
1897
|
* This is the Web counterpart of iOS `ASCUserService.getFlagsByMe` and Android
|
|
1849
1898
|
* `UserRepository.getFlagsByMe`, kept apart from the deprecated public function so the
|
|
1850
1899
|
* user-object read does not change if that function ever does.
|
|
@@ -1905,35 +1954,72 @@ const locationsFor = (value, bits, hashes) => {
|
|
|
1905
1954
|
}
|
|
1906
1955
|
return locations;
|
|
1907
1956
|
};
|
|
1957
|
+
/** Standard or URL-safe base64, padding optional. Anything else is not a filter we can read. */
|
|
1958
|
+
const BASE64 = /^[A-Za-z0-9+/_-]*={0,2}$/;
|
|
1908
1959
|
/**
|
|
1909
|
-
* Whether `value` is probably in the filter. `false` is exact; `true`
|
|
1910
|
-
*
|
|
1911
|
-
*
|
|
1960
|
+
* Whether `value` is probably in the filter. `false` is exact; `true` means "maybe", which may be
|
|
1961
|
+
* a false positive. `null` (the server's value when nobody has flagged the object), a missing
|
|
1962
|
+
* filter or a missing value answer `false`.
|
|
1963
|
+
*
|
|
1964
|
+
* A filter that cannot be read answers `true` ("maybe") and never throws, so the caller asks the
|
|
1965
|
+
* server instead of trusting a "definitely not" it cannot back up (REQ-017): `bits` or `hashes`
|
|
1966
|
+
* not a positive integer, a `hash` that is not base64, or a `hash` shorter than `ceil(bits / 8)`
|
|
1967
|
+
* bytes.
|
|
1912
1968
|
*/
|
|
1913
1969
|
const testBloomFilter = (hashFlag, value) => {
|
|
1914
1970
|
if (!hashFlag || !value)
|
|
1915
1971
|
return false;
|
|
1916
1972
|
const { bits, hashes, hash } = hashFlag;
|
|
1917
|
-
if (!(bits
|
|
1918
|
-
return
|
|
1973
|
+
if (!Number.isInteger(bits) || bits <= 0)
|
|
1974
|
+
return true;
|
|
1975
|
+
if (!Number.isInteger(hashes) || hashes <= 0)
|
|
1976
|
+
return true;
|
|
1977
|
+
if (typeof hash !== 'string' || !BASE64.test(hash))
|
|
1978
|
+
return true;
|
|
1919
1979
|
let buckets;
|
|
1920
1980
|
try {
|
|
1921
1981
|
buckets = toUint8Array(hash);
|
|
1922
1982
|
}
|
|
1923
1983
|
catch (_a) {
|
|
1924
|
-
return
|
|
1984
|
+
return true;
|
|
1925
1985
|
}
|
|
1986
|
+
if (buckets.length < Math.ceil(bits / 8))
|
|
1987
|
+
return true;
|
|
1926
1988
|
const locations = locationsFor(value, bits, hashes);
|
|
1927
1989
|
for (let i = 0; i < locations.length; i += 1) {
|
|
1928
1990
|
const index = Math.floor(locations[i] / 8);
|
|
1929
1991
|
const bit = 1 << locations[i] % 8;
|
|
1930
|
-
if (
|
|
1992
|
+
if ((buckets[index] & bit) === 0)
|
|
1931
1993
|
return false;
|
|
1932
1994
|
}
|
|
1933
1995
|
return true;
|
|
1934
1996
|
};
|
|
1935
1997
|
|
|
1936
|
-
/**
|
|
1998
|
+
/**
|
|
1999
|
+
* Flag state of the current user on a target user, behind `Amity.User.isFlaggedByMe` and
|
|
2000
|
+
* `Amity.User.getUserFlagsByMe()` (`user.check_flag_by_me` v1, REQ-011, REQ-012, REQ-016).
|
|
2001
|
+
*
|
|
2002
|
+
* `hashFlag` is a Bloom filter of reporter ids. "Definitely not" is exact. "Maybe" can be a
|
|
2003
|
+
* false positive caused by other reporters, so the SDK confirms it with the server once per
|
|
2004
|
+
* `hashFlag` value and records the answer in the cache under its own key, never on the user's
|
|
2005
|
+
* cache row (REQ-015). Observers are told through `local.user.flagConfirmed` when a recorded
|
|
2006
|
+
* answer changes what a user object would show.
|
|
2007
|
+
*
|
|
2008
|
+
* Not exported from the public API.
|
|
2009
|
+
*/
|
|
2010
|
+
/** Confirms for the same user are at least this far apart, as Android's `EkoFlag.expired`. */
|
|
2011
|
+
const FLAG_CONFIRM_INTERVAL = 1000;
|
|
2012
|
+
const cacheKey = (userId) => ['userFlagByMe', 'get', userId];
|
|
2013
|
+
const lastConfirmAt = new Map();
|
|
2014
|
+
/**
|
|
2015
|
+
* Bumped by the current user's own flag and unflag. A confirm or exact read that started before
|
|
2016
|
+
* one of them must not record its answer, because the write may have changed it while the
|
|
2017
|
+
* `hashFlag` stayed the same.
|
|
2018
|
+
*/
|
|
2019
|
+
const generations = new Map();
|
|
2020
|
+
const generationOf = (userId) => { var _a; return (_a = generations.get(userId)) !== null && _a !== void 0 ? _a : 0; };
|
|
2021
|
+
const bumpGeneration = (userId) => generations.set(userId, generationOf(userId) + 1);
|
|
2022
|
+
/** The current user's id, or `undefined` when there is no active client. Never throws. */
|
|
1937
2023
|
const currentUserId = () => {
|
|
1938
2024
|
try {
|
|
1939
2025
|
return getActiveClient().userId;
|
|
@@ -1942,43 +2028,223 @@ const currentUserId = () => {
|
|
|
1942
2028
|
return undefined;
|
|
1943
2029
|
}
|
|
1944
2030
|
};
|
|
2031
|
+
const readRecord = (userId) => {
|
|
2032
|
+
var _a;
|
|
2033
|
+
try {
|
|
2034
|
+
return (_a = pullFromCache(cacheKey(userId))) === null || _a === void 0 ? void 0 : _a.data;
|
|
2035
|
+
}
|
|
2036
|
+
catch (_b) {
|
|
2037
|
+
return undefined;
|
|
2038
|
+
}
|
|
2039
|
+
};
|
|
1945
2040
|
/**
|
|
1946
|
-
*
|
|
1947
|
-
*
|
|
1948
|
-
* functions by reference: a fresh closure on every linked object would make two reads of the
|
|
1949
|
-
* same user unequal and re-dispatch snapshots that did not change.
|
|
2041
|
+
* The server's answer recorded for this user and this exact `hashFlag`, or `undefined` when there
|
|
2042
|
+
* is none for the current user. Never throws.
|
|
1950
2043
|
*/
|
|
1951
|
-
const
|
|
2044
|
+
const readConfirmedFlag = (userId, hashFlag) => {
|
|
2045
|
+
const me = currentUserId();
|
|
2046
|
+
if (!me || !hashFlag || typeof hashFlag.hash !== 'string')
|
|
2047
|
+
return undefined;
|
|
2048
|
+
const record = readRecord(userId);
|
|
2049
|
+
if (!record || record.reporterId !== me || record.hash !== hashFlag.hash)
|
|
2050
|
+
return undefined;
|
|
2051
|
+
return record.isFlagByMe;
|
|
2052
|
+
};
|
|
1952
2053
|
/**
|
|
1953
|
-
*
|
|
1954
|
-
*
|
|
1955
|
-
*
|
|
2054
|
+
* The v4 request in flight per user, with the generation it started in. A confirm and an exact
|
|
2055
|
+
* read of the same user share one request; a request that started before the current user's own
|
|
2056
|
+
* flag or unflag is not joined.
|
|
1956
2057
|
*/
|
|
1957
|
-
const
|
|
2058
|
+
const inFlight = new Map();
|
|
2059
|
+
const requestFlagsByMe = (userId) => {
|
|
2060
|
+
const generation = generationOf(userId);
|
|
2061
|
+
const pending = inFlight.get(userId);
|
|
2062
|
+
if (pending && pending.generation === generation)
|
|
2063
|
+
return pending.promise;
|
|
2064
|
+
const promise = getFlagsByMe(userId).finally(() => {
|
|
2065
|
+
var _a;
|
|
2066
|
+
if (((_a = inFlight.get(userId)) === null || _a === void 0 ? void 0 : _a.promise) === promise)
|
|
2067
|
+
inFlight.delete(userId);
|
|
2068
|
+
});
|
|
2069
|
+
inFlight.set(userId, { generation, promise });
|
|
2070
|
+
return promise;
|
|
2071
|
+
};
|
|
2072
|
+
const notifyObservers = (userId) => fireEvent('local.user.flagConfirmed', { userId });
|
|
2073
|
+
/**
|
|
2074
|
+
* Records `isFlagByMe` for `hashFlag`. A "maybe" without a record shows `true`, so observers are
|
|
2075
|
+
* told only when the shown value changes.
|
|
2076
|
+
*/
|
|
2077
|
+
const recordFlag = (userId, hashFlag, isFlagByMe) => {
|
|
1958
2078
|
var _a;
|
|
1959
2079
|
const me = currentUserId();
|
|
1960
|
-
|
|
1961
|
-
|
|
2080
|
+
if (!me || typeof hashFlag.hash !== 'string')
|
|
2081
|
+
return;
|
|
2082
|
+
const shown = (_a = readConfirmedFlag(userId, hashFlag)) !== null && _a !== void 0 ? _a : true;
|
|
2083
|
+
const record = { reporterId: me, hash: hashFlag.hash, isFlagByMe };
|
|
2084
|
+
pushToCache(cacheKey(userId), record);
|
|
2085
|
+
if (shown !== isFlagByMe)
|
|
2086
|
+
notifyObservers(userId);
|
|
2087
|
+
};
|
|
2088
|
+
/**
|
|
2089
|
+
* Starts one background confirm of a "maybe" (REQ-016): at most one in flight per user, and
|
|
2090
|
+
* confirms for the same user at least {@link FLAG_CONFIRM_INTERVAL} apart. A failed confirm
|
|
2091
|
+
* records nothing, surfaces no error, and a later read tries again.
|
|
2092
|
+
*/
|
|
2093
|
+
const confirmFlagByMe = (userId, hashFlag) => {
|
|
2094
|
+
if (inFlight.has(userId))
|
|
2095
|
+
return;
|
|
2096
|
+
const now = Date.now();
|
|
2097
|
+
const last = lastConfirmAt.get(userId);
|
|
2098
|
+
if (last !== undefined && now - last < FLAG_CONFIRM_INTERVAL)
|
|
2099
|
+
return;
|
|
2100
|
+
const me = currentUserId();
|
|
2101
|
+
const generation = generationOf(userId);
|
|
2102
|
+
lastConfirmAt.set(userId, now);
|
|
2103
|
+
requestFlagsByMe(userId)
|
|
2104
|
+
.then(({ isFlagByMe }) => {
|
|
2105
|
+
if (currentUserId() !== me || generationOf(userId) !== generation)
|
|
2106
|
+
return;
|
|
2107
|
+
recordFlag(userId, hashFlag, isFlagByMe);
|
|
2108
|
+
})
|
|
2109
|
+
.catch(() => {
|
|
2110
|
+
// Not an answer: isFlaggedByMe stays true until a later read confirms again.
|
|
2111
|
+
});
|
|
2112
|
+
};
|
|
2113
|
+
/**
|
|
2114
|
+
* The value of `Amity.User.isFlaggedByMe` for a user object whose confirmed answer was captured
|
|
2115
|
+
* (`confirmed`) when the object was linked, so a held object never changes (REQ-014).
|
|
2116
|
+
*
|
|
2117
|
+
* - No current user, `hashFlag: null` or a missing `hashFlag`, or "definitely not": `false`.
|
|
2118
|
+
* - "Maybe" with a confirmed answer: that answer, no request.
|
|
2119
|
+
* - "Maybe" without one: `true`, and one background confirm (REQ-016).
|
|
2120
|
+
*
|
|
2121
|
+
* The linked object declares this as a getter inside an object spread, which the build compiles
|
|
2122
|
+
* to `Object.assign`, so it runs once when the user is linked and the object keeps that value.
|
|
2123
|
+
*/
|
|
2124
|
+
const isFlaggedByMeFor = (user, confirmed) => {
|
|
2125
|
+
const me = currentUserId();
|
|
2126
|
+
if (!me || !user.hashFlag || !testBloomFilter(user.hashFlag, me))
|
|
1962
2127
|
return false;
|
|
1963
|
-
|
|
2128
|
+
if (confirmed !== undefined)
|
|
2129
|
+
return confirmed;
|
|
2130
|
+
confirmFlagByMe(user.userId, user.hashFlag);
|
|
2131
|
+
return true;
|
|
2132
|
+
};
|
|
2133
|
+
const NOT_FLAGGED = { isFlagByMe: false, flags: [] };
|
|
2134
|
+
const isNotOlder = (next, current) => {
|
|
2135
|
+
var _a, _b;
|
|
2136
|
+
const nextAt = Date.parse((_a = next.updatedAt) !== null && _a !== void 0 ? _a : '');
|
|
2137
|
+
const currentAt = Date.parse((_b = current.updatedAt) !== null && _b !== void 0 ? _b : '');
|
|
2138
|
+
return Number.isNaN(nextAt) || Number.isNaN(currentAt) || nextAt >= currentAt;
|
|
2139
|
+
};
|
|
2140
|
+
/**
|
|
2141
|
+
* One `getUserFlagsByMe` closure per userId, remembering the newest user object linked for that
|
|
2142
|
+
* id. Live objects and collections compare snapshots with `isEqual`, which compares functions by
|
|
2143
|
+
* reference, so a fresh closure per linked object would re-dispatch unchanged snapshots
|
|
2144
|
+
* (REQ-015). An older snapshot linked later does not replace a newer one.
|
|
2145
|
+
*/
|
|
2146
|
+
const flagsByMeEntries = new Map();
|
|
2147
|
+
/**
|
|
2148
|
+
* `Amity.User.getUserFlagsByMe()` (REQ-012): `{ isFlagByMe: false, flags: [] }` with no request
|
|
2149
|
+
* when the newest linked user says "not flagged", including a confirmed `false`. Otherwise the
|
|
2150
|
+
* v4 read, returned as is; a confirm already in flight for the user is joined instead of sending
|
|
2151
|
+
* a second request. Its `isFlagByMe` is recorded as the confirmed answer for the
|
|
2152
|
+
* `hashFlag` it was read for; `flags[]` is never stored (REQ-009). A missing `hashFlag` is
|
|
2153
|
+
* unknown, so the server is asked.
|
|
2154
|
+
*/
|
|
2155
|
+
const readFlagsByMe = async (userId) => {
|
|
2156
|
+
var _a, _b;
|
|
2157
|
+
const me = currentUserId();
|
|
2158
|
+
const { hashFlag } = (_b = (_a = flagsByMeEntries.get(userId)) === null || _a === void 0 ? void 0 : _a.latest) !== null && _b !== void 0 ? _b : {};
|
|
2159
|
+
if (me && hashFlag !== undefined) {
|
|
2160
|
+
if (!hashFlag || !testBloomFilter(hashFlag, me))
|
|
2161
|
+
return Object.assign(Object.assign({}, NOT_FLAGGED), { flags: [] });
|
|
2162
|
+
if (readConfirmedFlag(userId, hashFlag) === false)
|
|
2163
|
+
return Object.assign(Object.assign({}, NOT_FLAGGED), { flags: [] });
|
|
2164
|
+
}
|
|
2165
|
+
const generation = generationOf(userId);
|
|
2166
|
+
const result = await requestFlagsByMe(userId);
|
|
2167
|
+
if (hashFlag && currentUserId() === me && generationOf(userId) === generation) {
|
|
2168
|
+
recordFlag(userId, hashFlag, result.isFlagByMe);
|
|
2169
|
+
}
|
|
2170
|
+
return result;
|
|
1964
2171
|
};
|
|
1965
2172
|
const getUserFlagsByMeFor = (user) => {
|
|
1966
2173
|
let entry = flagsByMeEntries.get(user.userId);
|
|
1967
2174
|
if (!entry) {
|
|
1968
|
-
entry = {
|
|
1969
|
-
latest: user,
|
|
1970
|
-
getUserFlagsByMe: async () => {
|
|
1971
|
-
if (knownNotFlaggedByMe(user.userId))
|
|
1972
|
-
return { isFlagByMe: false, flags: [] };
|
|
1973
|
-
return getFlagsByMe(user.userId);
|
|
1974
|
-
},
|
|
1975
|
-
};
|
|
2175
|
+
entry = { latest: user, getUserFlagsByMe: () => readFlagsByMe(user.userId) };
|
|
1976
2176
|
flagsByMeEntries.set(user.userId, entry);
|
|
1977
2177
|
}
|
|
1978
|
-
entry.latest
|
|
2178
|
+
else if (isNotOlder(user, entry.latest)) {
|
|
2179
|
+
entry.latest = user;
|
|
2180
|
+
}
|
|
1979
2181
|
return entry.getUserFlagsByMe;
|
|
1980
2182
|
};
|
|
2183
|
+
/**
|
|
2184
|
+
* The current user's own flag succeeded (REQ-016). Their report may leave `hashFlag` unchanged
|
|
2185
|
+
* when other reporters had already set all of their bits, so the answer is known: record `true`
|
|
2186
|
+
* for the `hashFlag` the response carries, or drop the answer when it carries none.
|
|
2187
|
+
*/
|
|
2188
|
+
const onFlaggedByMe = (user, userId) => {
|
|
2189
|
+
bumpGeneration(userId);
|
|
2190
|
+
if (user === null || user === void 0 ? void 0 : user.hashFlag) {
|
|
2191
|
+
recordFlag(userId, user.hashFlag, true);
|
|
2192
|
+
return;
|
|
2193
|
+
}
|
|
2194
|
+
const dropped = readRecord(userId);
|
|
2195
|
+
dropFromCache(cacheKey(userId), true);
|
|
2196
|
+
if ((dropped === null || dropped === void 0 ? void 0 : dropped.isFlagByMe) === false)
|
|
2197
|
+
notifyObservers(userId);
|
|
2198
|
+
};
|
|
2199
|
+
/**
|
|
2200
|
+
* The current user's own unflag succeeded (`user.unflag` REQ-010, REQ-016). A per-type unflag can
|
|
2201
|
+
* leave other reports in place, so the answer is dropped, never set to `false`; the next "maybe"
|
|
2202
|
+
* is confirmed again.
|
|
2203
|
+
*/
|
|
2204
|
+
const onUnflaggedByMe = (userId) => {
|
|
2205
|
+
bumpGeneration(userId);
|
|
2206
|
+
const dropped = readRecord(userId);
|
|
2207
|
+
dropFromCache(cacheKey(userId), true);
|
|
2208
|
+
if ((dropped === null || dropped === void 0 ? void 0 : dropped.isFlagByMe) === false)
|
|
2209
|
+
notifyObservers(userId);
|
|
2210
|
+
};
|
|
2211
|
+
/** Forgets every in-memory trace of the current user's flag state. Records live in the cache. */
|
|
2212
|
+
const resetUserFlagByMe = () => {
|
|
2213
|
+
flagsByMeEntries.clear();
|
|
2214
|
+
inFlight.clear();
|
|
2215
|
+
lastConfirmAt.clear();
|
|
2216
|
+
generations.clear();
|
|
2217
|
+
};
|
|
2218
|
+
/**
|
|
2219
|
+
* Registered through `setupLoginSubscriptions`. Every confirmed answer belongs to the current
|
|
2220
|
+
* user, so the state is cleared on logout; the records themselves go with the cache, and each
|
|
2221
|
+
* also carries the reporter's id.
|
|
2222
|
+
*/
|
|
2223
|
+
const userFlagByMeOnLoginHandler = () => {
|
|
2224
|
+
const unsubscribe = onSessionStateChange(state => {
|
|
2225
|
+
if (state === "notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */ || state === "terminated" /* Amity.SessionStates.TERMINATED */) {
|
|
2226
|
+
resetUserFlagByMe();
|
|
2227
|
+
}
|
|
2228
|
+
});
|
|
2229
|
+
return () => {
|
|
2230
|
+
unsubscribe();
|
|
2231
|
+
resetUserFlagByMe();
|
|
2232
|
+
};
|
|
2233
|
+
};
|
|
2234
|
+
/**
|
|
2235
|
+
* Called with the cached user when a recorded answer changes what that user would show, so live
|
|
2236
|
+
* objects and live collections deliver it again (REQ-016, delivery).
|
|
2237
|
+
*/
|
|
2238
|
+
const onUserFlagConfirmed = (callback) => createEventSubscriber(getActiveClient(), 'user/onUserFlagConfirmed', 'local.user.flagConfirmed', ({ userId }) => {
|
|
2239
|
+
var _a;
|
|
2240
|
+
const user = (_a = pullFromCache(['user', 'get', userId])) === null || _a === void 0 ? void 0 : _a.data;
|
|
2241
|
+
if (user)
|
|
2242
|
+
callback(user);
|
|
2243
|
+
});
|
|
2244
|
+
|
|
1981
2245
|
const userLinkedObject = (user) => {
|
|
2246
|
+
// Captured now, so a user object the app holds never changes after a confirm (REQ-014).
|
|
2247
|
+
const confirmedFlagByMe = readConfirmedFlag(user.userId, user.hashFlag);
|
|
1982
2248
|
return Object.assign(Object.assign({}, user), { get avatar() {
|
|
1983
2249
|
var _a;
|
|
1984
2250
|
if (!user.avatarFileId)
|
|
@@ -1989,9 +2255,10 @@ const userLinkedObject = (user) => {
|
|
|
1989
2255
|
return avatar;
|
|
1990
2256
|
},
|
|
1991
2257
|
get isFlaggedByMe() {
|
|
1992
|
-
//
|
|
1993
|
-
//
|
|
1994
|
-
|
|
2258
|
+
// Bloom test on this object's hashFlag: "definitely not" is exact and sends nothing.
|
|
2259
|
+
// "Maybe" returns the answer confirmed for this hashFlag, or true while one background
|
|
2260
|
+
// confirm runs (REQ-011, REQ-016). Never throws.
|
|
2261
|
+
return isFlaggedByMeFor(user, confirmedFlagByMe);
|
|
1995
2262
|
},
|
|
1996
2263
|
/* begin_public_function
|
|
1997
2264
|
id: user.get_flags_by_me
|
|
@@ -2263,13 +2530,13 @@ class NetworkActivitiesWatcher {
|
|
|
2263
2530
|
this._listener.clear();
|
|
2264
2531
|
}
|
|
2265
2532
|
}
|
|
2266
|
-
let instance$
|
|
2533
|
+
let instance$a;
|
|
2267
2534
|
var NetworkActivitiesWatcher$1 = {
|
|
2268
2535
|
getInstance: () => {
|
|
2269
|
-
if (!instance$
|
|
2270
|
-
instance$
|
|
2536
|
+
if (!instance$a) {
|
|
2537
|
+
instance$a = new NetworkActivitiesWatcher();
|
|
2271
2538
|
}
|
|
2272
|
-
return instance$
|
|
2539
|
+
return instance$a;
|
|
2273
2540
|
},
|
|
2274
2541
|
};
|
|
2275
2542
|
|
|
@@ -2453,54 +2720,6 @@ const createHttpTransport = (endpoint) => {
|
|
|
2453
2720
|
return instance;
|
|
2454
2721
|
};
|
|
2455
2722
|
|
|
2456
|
-
class SessionWatcher {
|
|
2457
|
-
constructor() {
|
|
2458
|
-
this._sessionState = "notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */;
|
|
2459
|
-
this._listener = new Map();
|
|
2460
|
-
}
|
|
2461
|
-
onSessionStateChange(callback) {
|
|
2462
|
-
this._listener.set(callback, callback);
|
|
2463
|
-
return () => {
|
|
2464
|
-
this._listener.delete(callback);
|
|
2465
|
-
};
|
|
2466
|
-
}
|
|
2467
|
-
setSessionState(state, reason) {
|
|
2468
|
-
if (this._sessionState === state)
|
|
2469
|
-
return;
|
|
2470
|
-
this._sessionState = state;
|
|
2471
|
-
this._listener.forEach(cb => cb(state, reason));
|
|
2472
|
-
}
|
|
2473
|
-
destroy() {
|
|
2474
|
-
this._listener.clear();
|
|
2475
|
-
}
|
|
2476
|
-
}
|
|
2477
|
-
let instance$a;
|
|
2478
|
-
var SessionWatcher$1 = {
|
|
2479
|
-
getInstance: () => {
|
|
2480
|
-
if (!instance$a) {
|
|
2481
|
-
instance$a = new SessionWatcher();
|
|
2482
|
-
}
|
|
2483
|
-
return instance$a;
|
|
2484
|
-
},
|
|
2485
|
-
};
|
|
2486
|
-
|
|
2487
|
-
/**
|
|
2488
|
-
* ```js
|
|
2489
|
-
* import { onSessionStateChange } from '@amityco/ts-sdk'
|
|
2490
|
-
* const dispose = onSessionStateChange((state: Amity.SessionStates) => {
|
|
2491
|
-
* // ...
|
|
2492
|
-
* })
|
|
2493
|
-
* ```
|
|
2494
|
-
*
|
|
2495
|
-
* Fired when any {@link Amity.Client} has a session state change
|
|
2496
|
-
*
|
|
2497
|
-
* @param callback The function to call when the event was fired
|
|
2498
|
-
* @returns an {@link Amity.Unsubscriber} function to stop listening
|
|
2499
|
-
*
|
|
2500
|
-
* @category Client Events
|
|
2501
|
-
*/
|
|
2502
|
-
const onSessionStateChange = (callback) => SessionWatcher$1.getInstance().onSessionStateChange(callback);
|
|
2503
|
-
|
|
2504
2723
|
const TOPICS = {
|
|
2505
2724
|
[AmityAutoSubscription.NETWORK]: [getNetworkTopic],
|
|
2506
2725
|
[AmityAutoSubscription.CHAT]: [
|
|
@@ -8584,7 +8803,7 @@ const setupLoginSubscriptions = (unsubWatcher) => {
|
|
|
8584
8803
|
// NOTE: This is a temporary solution to handle the channel marker when the user is forced to leave
|
|
8585
8804
|
// the channel because currently backend can't handle this, so every time a user is banned from
|
|
8586
8805
|
// a channel or the channel is deleted the channel's unread count will not be reset to zero
|
|
8587
|
-
onChannelDeleted(removeChannelMarkerCache), onChannelMemberBanned(removeChannelMarkerCache), markReadEngineOnLoginHandler(), analyticsEngineOnLoginHandler(), objectResolverEngineOnLoginHandler(), reactionSyncEngineOnLoginHandler(), blockedUserSyncEngineOnLoginHandler(), blockingUserSyncEngineOnLoginHandler(), blockRealtimeOnLoginHandler(), resetAutoSubscriptionsOnLogout(), CursorController.clearOnLogout(), postCommentCountEngineOnLoginHandler(), channelActivityOnLoginHandler());
|
|
8806
|
+
onChannelDeleted(removeChannelMarkerCache), onChannelMemberBanned(removeChannelMarkerCache), markReadEngineOnLoginHandler(), analyticsEngineOnLoginHandler(), objectResolverEngineOnLoginHandler(), reactionSyncEngineOnLoginHandler(), blockedUserSyncEngineOnLoginHandler(), blockingUserSyncEngineOnLoginHandler(), blockRealtimeOnLoginHandler(), resetAutoSubscriptionsOnLogout(), CursorController.clearOnLogout(), postCommentCountEngineOnLoginHandler(), channelActivityOnLoginHandler(), userFlagByMeOnLoginHandler());
|
|
8588
8807
|
if (client.useLegacyUnreadCount) {
|
|
8589
8808
|
subscriptions.push(readReceiptSyncEngineOnLoginHandler());
|
|
8590
8809
|
}
|
|
@@ -13804,7 +14023,7 @@ const getWatchSessionStorage = () => {
|
|
|
13804
14023
|
return storageInstance;
|
|
13805
14024
|
};
|
|
13806
14025
|
|
|
13807
|
-
const privateKey = "
|
|
14026
|
+
const privateKey = "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDHo80SecH7FuF2\nhFYnb+l26/VN8UMLXAQFLnxciNTEwkGVFMpdezlH8rU2HtUJL4RETogbAOLVY0XM\njs6sPn8G1nALmh9qeDpUtVqFOVtBHxEZ910TLOtQiunjqJKO5nWdqZ71EC3OFluR\niGQkO84BiIFbv37ub7xl3S8XarbtKoLcyVpkDHi+1wx1pgCAn6gtBUgckPL5NR8j\nLseabl3HAXQfhTCKo4tmOFM2Dxwl1IUMmIJrJg/aIU/U0tj/1Eoo7mG0JcNWX19l\nW3EecCbi0ncCJOrkUdwlBrcjaMayaX/ubEwyUeTGiLdyc4L3GRLHjyK8xgVNXRMH\nbZWJ2a5NAgMBAAECggEASxuE+35zTFO/XydKgmvIGcWL9FbgMlXb7Vcf0nBoG945\nbiz0NVc2paraIhJXc608xbYF3qLmtAE1MVBI0ORyRdBHNxY024l/6H6SH60Ed+uI\nM4ysp5ourY6Vj+DLwpdRiI9YDjqYAQDIUmhNxJP7XPhOMoZI6st+xZQBM34ic/bv\nAMSJm9OZphSp3+qXVkFZztr2mxD2EZSJJLYxi8BCdgM2qhazalbcJ6zDKHCZWVWm\n8RRxDGldyMb/237JxETzP40tAlzOZDmBAbUgEnurDJ93RVDIE3rbZUshwgeQd18a\nem096mWgvB1AIKYgsTAR3pw+V19YWAjq/glP6fz8wQKBgQD/oQq+ukKF0PRgBeM5\ngeTjSwsdGppQLmf5ndujvoiz/TpdjDEPu6R8kigQr1rG2t4K/yfdZoI8RdmJD1al\n3Q7N9hofooSy4rj6E3txzWZCHJjHad2cnCp/O26HiReGAl7wTcfTmNdiFHhZQzm5\nJBkvWAiwuvQMNfEbnXxw6/vIDwKBgQDH7fX8gsc77JLvAWgp1MaQN/sbqVb6JeT1\nFQfR8E/WFCSmzQBtNzd5KgYuCeelwr/8DyYytvN2BzCYZXp73gI1jF3YlW5jVn74\nOY6TwQ095digwo6Z0yuxopdIOApKgAkL9PRKgNrqAf3NAyMua6lOGifzjDojC3KU\nfylQmxMn4wKBgHp2B9O/H0dEBw5JQ8W0+JX6yWQz7mEjGiR2/1W+XXb8hQ1zr709\nw1r6Gb+EghRpnZ3fBpYGGbYOMFx8wKHM+N6qW3F0ReX8v2juFGE8aRSa5oYBrWzt\nU16Idjbv8hj84cZ1PJmdyvDtpYn9rpWHOZl4rxEbPvbqkIsOMyNVqdT5AoGAOSge\nmwIIU2le2FVeohbibXiToWTYKMuMmURZ5/r72AgKMmWJKbAPe+Q3wBG01/7FRBpQ\noU8Ma0HC8s6QJbliiEyIx9JwrJWd1vkdecBHONrtA4ibm/5zD2WcOllLF+FitLhi\n3qnX6+6F0IaFGFBPJrTzlv0P4dTz/OAdv52V7GECgYEA2TttOKBAqWllgOaZOkql\nLVMJVmgR7s6tLi1+cEP8ZcapV9aRbRzTAKXm4f8AEhtlG9F9kCOvHYCYGi6JaiWJ\nZkHjeex3T+eE6Di6y5Bm/Ift5jtVhJ4jCVwHOKTMej79NPUFTJfv8hCo29haBDv6\nRXFrv+T21KCcw8k3sJeJWWQ=\n-----END PRIVATE KEY-----";
|
|
13808
14027
|
/*
|
|
13809
14028
|
* The crypto algorithm used for importing key and signing string
|
|
13810
14029
|
*/
|
|
@@ -15630,8 +15849,11 @@ const flagUser = async (userId, options) => {
|
|
|
15630
15849
|
if (client.cache) {
|
|
15631
15850
|
ingestInCache(payload);
|
|
15632
15851
|
}
|
|
15852
|
+
const flagged = (_a = payload.users.find(user => user.userId === userId)) !== null && _a !== void 0 ? _a : payload.users[0];
|
|
15853
|
+
// The caller's own report may leave hashFlag unchanged; record that they flagged (REQ-016).
|
|
15854
|
+
onFlaggedByMe(flagged, userId);
|
|
15633
15855
|
fireEvent('user.flagged', data);
|
|
15634
|
-
return userLinkedObject(
|
|
15856
|
+
return userLinkedObject(flagged);
|
|
15635
15857
|
};
|
|
15636
15858
|
/* end_public_function */
|
|
15637
15859
|
|
|
@@ -15651,8 +15873,11 @@ const submitUserReport = async (apiName, userId, body) => {
|
|
|
15651
15873
|
if (client.cache) {
|
|
15652
15874
|
ingestInCache(payload);
|
|
15653
15875
|
}
|
|
15876
|
+
const flagged = (_a = payload.users.find(user => user.userId === userId)) !== null && _a !== void 0 ? _a : payload.users[0];
|
|
15877
|
+
// The caller's own report may leave hashFlag unchanged; record that they flagged (REQ-016).
|
|
15878
|
+
onFlaggedByMe(flagged, userId);
|
|
15654
15879
|
fireEvent('user.flagged', data);
|
|
15655
|
-
return userLinkedObject(
|
|
15880
|
+
return userLinkedObject(flagged);
|
|
15656
15881
|
};
|
|
15657
15882
|
|
|
15658
15883
|
/** Maximum `comment` length, in string length units, after trimming. */
|
|
@@ -15831,14 +16056,15 @@ const flagUserBehavior = async (userId, options) => submitUserReport('flagUserBe
|
|
|
15831
16056
|
* untouched. Withdrawing a report that does not exist succeeds and changes nothing.
|
|
15832
16057
|
*
|
|
15833
16058
|
* The returned user is persisted to the cache, so its `hashFlag` says whether the caller
|
|
15834
|
-
* still
|
|
15835
|
-
* after a per-type withdrawal;
|
|
15836
|
-
* remaining per-type state (`flags`).
|
|
16059
|
+
* may still hold a report on the user. Do not flip a local "flagged by me" flag to `false`
|
|
16060
|
+
* after a per-type withdrawal; observe the user and read `isFlaggedByMe`, or call
|
|
16061
|
+
* `user.getUserFlagsByMe()` for the remaining per-type state (`flags`). The SDK drops the
|
|
16062
|
+
* answer it confirmed for this user, so the next "maybe" is confirmed again.
|
|
15837
16063
|
*
|
|
15838
16064
|
* Sends `DELETE /api/v4/me/flags/:userId`, with `?reportType=<type>` when one is given.
|
|
15839
16065
|
*
|
|
15840
16066
|
* @param userId The ID of the user to unflag
|
|
15841
|
-
* @param options Optional; `reportType` selects a single report to withdraw. For a report that `
|
|
16067
|
+
* @param options Optional; `reportType` selects a single report to withdraw. For a report that `user.getUserFlagsByMe()` lists with `reportType: null`, pass `UserReportTypeFilterEnum.UNTYPED`
|
|
15842
16068
|
* @returns `true` once the server has processed the withdrawal
|
|
15843
16069
|
* @throws {ASCInvalidParameterError} `INVALID_PARAMETERS` when `reportType` is not a `UserReportTypeFilterEnum` value, before any request is made
|
|
15844
16070
|
*
|
|
@@ -15857,6 +16083,8 @@ const unflagUser = async (userId, options) => {
|
|
|
15857
16083
|
if (client.cache) {
|
|
15858
16084
|
ingestInCache(payload);
|
|
15859
16085
|
}
|
|
16086
|
+
// Drop the confirmed answer; never set it to false: other reports may remain (REQ-010).
|
|
16087
|
+
onUnflaggedByMe(userId);
|
|
15860
16088
|
fireEvent('user.unflagged', data);
|
|
15861
16089
|
return !!payload;
|
|
15862
16090
|
};
|
|
@@ -15868,33 +16096,19 @@ const unflagUser = async (userId, options) => {
|
|
|
15868
16096
|
/**
|
|
15869
16097
|
* ```js
|
|
15870
16098
|
* import { UserRepository } from '@amityco/ts-sdk'
|
|
15871
|
-
*
|
|
15872
|
-
* const { isFlagByMe, flags } = await UserRepository.isUserFlaggedByMe('userId')
|
|
15873
|
-
*
|
|
15874
|
-
* // Grey out the report options already used; null marks the typeless report.
|
|
15875
|
-
* const used = new Set(flags.map(flag => flag.reportType))
|
|
16099
|
+
* const isFlagged = await UserRepository.isUserFlaggedByMe(userId)
|
|
15876
16100
|
* ```
|
|
15877
16101
|
*
|
|
15878
|
-
*
|
|
15879
|
-
*
|
|
15880
|
-
* carries `reportType`, `reason`, `comment` and `createdAt`; a field the report does not
|
|
15881
|
-
* have is `null`. `reportType: null` is the typeless (legacy) report, which `unflagUser`
|
|
15882
|
-
* withdraws with `UserReportTypeFilterEnum.UNTYPED`. Only the caller's reports come back.
|
|
15883
|
-
*
|
|
15884
|
-
* This is the only source of per-type state. Nothing is filtered, cached or persisted:
|
|
15885
|
-
* the call reads the server every time and does not consult `hashFlag`, which is a
|
|
15886
|
-
* type-blind bloom filter. Call it again after a flag or unflag when the UI needs the
|
|
15887
|
-
* updated per-type state.
|
|
16102
|
+
* Whether the current user has reported a user. Sends one request per call and caches
|
|
16103
|
+
* nothing.
|
|
15888
16104
|
*
|
|
15889
|
-
*
|
|
15890
|
-
*
|
|
15891
|
-
*
|
|
15892
|
-
*
|
|
15893
|
-
* request-free badge and call `user.getUserFlagsByMe()` for the reports; it skips the request
|
|
15894
|
-
* when the Bloom test says the user is not flagged. This function remains the underlying request.
|
|
16105
|
+
* @deprecated Read `user.isFlaggedByMe` on an {@link Amity.User} for a yes/no hint that
|
|
16106
|
+
* usually needs no request, and call `user.getUserFlagsByMe()` for the exact answer with the
|
|
16107
|
+
* caller's reports by type. Observe the user with `UserRepository.getUser(userId, callback)`
|
|
16108
|
+
* to follow a flag or unflag.
|
|
15895
16109
|
*
|
|
15896
16110
|
* @param userId The ID of the user to check
|
|
15897
|
-
* @returns the
|
|
16111
|
+
* @returns `true` if the current user has reported the user, `false` if not
|
|
15898
16112
|
*
|
|
15899
16113
|
* @category Report API
|
|
15900
16114
|
* @async
|
|
@@ -15902,7 +16116,8 @@ const unflagUser = async (userId, options) => {
|
|
|
15902
16116
|
const isUserFlaggedByMe = async (userId) => {
|
|
15903
16117
|
const client = getActiveClient();
|
|
15904
16118
|
client.log('user/isUserFlaggedByMe', userId);
|
|
15905
|
-
|
|
16119
|
+
const { isFlagByMe } = await getFlagsByMe(userId);
|
|
16120
|
+
return isFlagByMe;
|
|
15906
16121
|
};
|
|
15907
16122
|
/* end_public_function */
|
|
15908
16123
|
|
|
@@ -16141,7 +16356,7 @@ const getUser = (userId, callback) => {
|
|
|
16141
16356
|
const reactor = (response) => {
|
|
16142
16357
|
return callback(Object.assign(Object.assign({}, response), { data: response.data ? LinkedObject.user(response.data) : response.data }));
|
|
16143
16358
|
};
|
|
16144
|
-
|
|
16359
|
+
const unsubscribeUser = liveObject(userId, reactor, 'userId', getUser$1, [
|
|
16145
16360
|
onUserFetched,
|
|
16146
16361
|
onUserUpdated,
|
|
16147
16362
|
onUserDeleted$2,
|
|
@@ -16149,6 +16364,17 @@ const getUser = (userId, callback) => {
|
|
|
16149
16364
|
onUserUnflagged,
|
|
16150
16365
|
onUserFlagCleared,
|
|
16151
16366
|
]);
|
|
16367
|
+
// A confirmed flag answer leaves the cached user row unchanged, so the live object's own
|
|
16368
|
+
// dedupe would drop it. Deliver the re-linked user directly (user.check_flag_by_me REQ-016).
|
|
16369
|
+
const unsubscribeFlag = onUserFlagConfirmed(user => {
|
|
16370
|
+
if (user.userId !== userId)
|
|
16371
|
+
return;
|
|
16372
|
+
callback({ data: LinkedObject.user(user), loading: false, origin: 'event' });
|
|
16373
|
+
});
|
|
16374
|
+
return () => {
|
|
16375
|
+
unsubscribeUser();
|
|
16376
|
+
unsubscribeFlag();
|
|
16377
|
+
};
|
|
16152
16378
|
};
|
|
16153
16379
|
/* end_public_function */
|
|
16154
16380
|
|
|
@@ -16246,13 +16472,24 @@ class UserLiveCollectionController extends LiveCollectionController {
|
|
|
16246
16472
|
this.queryStreamController.appendToQueryStream(response, direction, refresh);
|
|
16247
16473
|
}
|
|
16248
16474
|
startSubscription() {
|
|
16249
|
-
return
|
|
16250
|
-
|
|
16251
|
-
|
|
16252
|
-
|
|
16253
|
-
|
|
16254
|
-
|
|
16255
|
-
|
|
16475
|
+
return [
|
|
16476
|
+
...this.queryStreamController.subscribeRTE([
|
|
16477
|
+
{ fn: onUserDeleted$2, action: EnumUserActions.OnUserDeleted },
|
|
16478
|
+
{ fn: onUserUpdated, action: EnumUserActions.OnUserUpdated },
|
|
16479
|
+
{ fn: onUserFlagged, action: EnumUserActions.OnUserFlagged },
|
|
16480
|
+
{ fn: onUserUnflagged, action: EnumUserActions.OnUserUnflagged },
|
|
16481
|
+
{ fn: onUserFlagCleared, action: EnumUserActions.OnUserFlagCleared },
|
|
16482
|
+
]),
|
|
16483
|
+
// A confirmed flag answer changes isFlaggedByMe on a listed user without changing its
|
|
16484
|
+
// cache row (user.check_flag_by_me REQ-016). Re-link only collections that hold it.
|
|
16485
|
+
onUserFlagConfirmed(user => {
|
|
16486
|
+
var _a;
|
|
16487
|
+
const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
|
|
16488
|
+
if (!(collection === null || collection === void 0 ? void 0 : collection.data.includes(user.userId)))
|
|
16489
|
+
return;
|
|
16490
|
+
this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
|
|
16491
|
+
}),
|
|
16492
|
+
];
|
|
16256
16493
|
}
|
|
16257
16494
|
notifyChange({ origin, loading, error }) {
|
|
16258
16495
|
var _a, _b;
|
|
@@ -16804,13 +17041,24 @@ class SearchUserLiveCollectionController extends LiveCollectionController {
|
|
|
16804
17041
|
this.queryStreamController.appendToQueryStream(response, direction, refresh);
|
|
16805
17042
|
}
|
|
16806
17043
|
startSubscription() {
|
|
16807
|
-
return
|
|
16808
|
-
|
|
16809
|
-
|
|
16810
|
-
|
|
16811
|
-
|
|
16812
|
-
|
|
16813
|
-
|
|
17044
|
+
return [
|
|
17045
|
+
...this.queryStreamController.subscribeRTE([
|
|
17046
|
+
{ fn: onUserDeleted$2, action: EnumUserActions.OnUserDeleted },
|
|
17047
|
+
{ fn: onUserUpdated, action: EnumUserActions.OnUserUpdated },
|
|
17048
|
+
{ fn: onUserFlagged, action: EnumUserActions.OnUserFlagged },
|
|
17049
|
+
{ fn: onUserUnflagged, action: EnumUserActions.OnUserUnflagged },
|
|
17050
|
+
{ fn: onUserFlagCleared, action: EnumUserActions.OnUserFlagCleared },
|
|
17051
|
+
]),
|
|
17052
|
+
// A confirmed flag answer changes isFlaggedByMe on a listed user without changing its
|
|
17053
|
+
// cache row (user.check_flag_by_me REQ-016). Re-link only collections that hold it.
|
|
17054
|
+
onUserFlagConfirmed(user => {
|
|
17055
|
+
var _a;
|
|
17056
|
+
const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
|
|
17057
|
+
if (!(collection === null || collection === void 0 ? void 0 : collection.data.includes(user.userId)))
|
|
17058
|
+
return;
|
|
17059
|
+
this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
|
|
17060
|
+
}),
|
|
17061
|
+
];
|
|
16814
17062
|
}
|
|
16815
17063
|
notifyChange({ origin, loading, error }) {
|
|
16816
17064
|
var _a, _b;
|