@amityco/ts-sdk 7.29.1-e932a95f.0 → 7.30.1-a5f99b06.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/content.d.ts +1 -0
- package/dist/@types/domains/content.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 +447 -138
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +446 -139
- package/dist/index.umd.js +2 -2
- package/dist/userRepository/api/flagUser.d.ts.map +1 -1
- package/dist/userRepository/api/flagUserBehavior.d.ts +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/userRepository/utils/userReport.d.ts +1 -1
- package/dist/utils/bloomFilter.d.ts +8 -3
- package/dist/utils/bloomFilter.d.ts.map +1 -1
- package/dist/utils/contentFlag.d.ts +1 -1
- package/dist/utils/contentFlagReason.d.ts +32 -0
- package/dist/utils/contentFlagReason.d.ts.map +1 -0
- package/dist/utils/linkedObject/userLinkedObject.d.ts.map +1 -1
- package/dist/utils/tests/contentFlagReason.test.d.ts +2 -0
- package/dist/utils/tests/contentFlagReason.test.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -74,7 +74,7 @@ exports.UserProfileFieldEnum = void 0;
|
|
|
74
74
|
* Selects which of the caller's reports `UserRepository.unflagUser` withdraws, sent as the
|
|
75
75
|
* `reportType` query parameter. The four typed members are the backend `reportType` wire
|
|
76
76
|
* values and match `UserReportTypeEnum`. `UNTYPED` selects the typeless (legacy) report,
|
|
77
|
-
* which `
|
|
77
|
+
* which `user.getUserFlagsByMe()` returns as `reportType: null`; it is a selector only, never
|
|
78
78
|
* stored, and the flag endpoint refuses it.
|
|
79
79
|
*/
|
|
80
80
|
exports.UserReportTypeFilterEnum = void 0;
|
|
@@ -161,6 +161,7 @@ const ContentFeedType = Object.freeze({
|
|
|
161
161
|
exports.ContentFlagReasonEnum = void 0;
|
|
162
162
|
(function (ContentFlagReasonEnum) {
|
|
163
163
|
ContentFlagReasonEnum["CommunityGuidelines"] = "Against community guidelines";
|
|
164
|
+
ContentFlagReasonEnum["ChildEndangerment"] = "Child endangerment";
|
|
164
165
|
ContentFlagReasonEnum["HarassmentOrBullying"] = "Harassment or bullying";
|
|
165
166
|
ContentFlagReasonEnum["SelfHarmOrSuicide"] = "Self-harm or suicide";
|
|
166
167
|
ContentFlagReasonEnum["ViolenceOrThreateningContent"] = "Violence or threatening content";
|
|
@@ -359,8 +360,8 @@ exports.AmityLiveViewerCountMode = void 0;
|
|
|
359
360
|
|
|
360
361
|
function getVersion() {
|
|
361
362
|
try {
|
|
362
|
-
// the string ''v7.
|
|
363
|
-
return 'v7.
|
|
363
|
+
// the string ''v7.30.0-cjs'' should be replaced by actual value by @rollup/plugin-replace
|
|
364
|
+
return 'v7.30.0-cjs';
|
|
364
365
|
}
|
|
365
366
|
catch (error) {
|
|
366
367
|
return '__dev__';
|
|
@@ -1852,15 +1853,64 @@ async function modifyMqttConnection() {
|
|
|
1852
1853
|
}
|
|
1853
1854
|
}
|
|
1854
1855
|
|
|
1856
|
+
class SessionWatcher {
|
|
1857
|
+
constructor() {
|
|
1858
|
+
this._sessionState = "notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */;
|
|
1859
|
+
this._listener = new Map();
|
|
1860
|
+
}
|
|
1861
|
+
onSessionStateChange(callback) {
|
|
1862
|
+
this._listener.set(callback, callback);
|
|
1863
|
+
return () => {
|
|
1864
|
+
this._listener.delete(callback);
|
|
1865
|
+
};
|
|
1866
|
+
}
|
|
1867
|
+
setSessionState(state, reason) {
|
|
1868
|
+
if (this._sessionState === state)
|
|
1869
|
+
return;
|
|
1870
|
+
this._sessionState = state;
|
|
1871
|
+
this._listener.forEach(cb => cb(state, reason));
|
|
1872
|
+
}
|
|
1873
|
+
destroy() {
|
|
1874
|
+
this._listener.clear();
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
let instance$b;
|
|
1878
|
+
var SessionWatcher$1 = {
|
|
1879
|
+
getInstance: () => {
|
|
1880
|
+
if (!instance$b) {
|
|
1881
|
+
instance$b = new SessionWatcher();
|
|
1882
|
+
}
|
|
1883
|
+
return instance$b;
|
|
1884
|
+
},
|
|
1885
|
+
};
|
|
1886
|
+
|
|
1887
|
+
/**
|
|
1888
|
+
* ```js
|
|
1889
|
+
* import { onSessionStateChange } from '@amityco/ts-sdk'
|
|
1890
|
+
* const dispose = onSessionStateChange((state: Amity.SessionStates) => {
|
|
1891
|
+
* // ...
|
|
1892
|
+
* })
|
|
1893
|
+
* ```
|
|
1894
|
+
*
|
|
1895
|
+
* Fired when any {@link Amity.Client} has a session state change
|
|
1896
|
+
*
|
|
1897
|
+
* @param callback The function to call when the event was fired
|
|
1898
|
+
* @returns an {@link Amity.Unsubscriber} function to stop listening
|
|
1899
|
+
*
|
|
1900
|
+
* @category Client Events
|
|
1901
|
+
*/
|
|
1902
|
+
const onSessionStateChange = (callback) => SessionWatcher$1.getInstance().onSessionStateChange(callback);
|
|
1903
|
+
|
|
1855
1904
|
/**
|
|
1856
1905
|
* ```js
|
|
1857
1906
|
* import { getFlagsByMe } from '~/userRepository/internalApi/getFlagsByMe'
|
|
1858
1907
|
* const { isFlagByMe, flags } = await getFlagsByMe('userId')
|
|
1859
1908
|
* ```
|
|
1860
1909
|
*
|
|
1861
|
-
* The v4 read behind `user.getUserFlagsByMe()
|
|
1862
|
-
* `
|
|
1863
|
-
* received. Nothing is filtered, cached or
|
|
1910
|
+
* The v4 read behind `user.getUserFlagsByMe()`, the background confirm of
|
|
1911
|
+
* `user.isFlaggedByMe`, and the deprecated `UserRepository.isUserFlaggedByMe`:
|
|
1912
|
+
* `GET /api/v4/users/:userId/isFlagByMe`, returned as received. Nothing is filtered, cached or
|
|
1913
|
+
* persisted here, and `hashFlag` is not consulted.
|
|
1864
1914
|
* This is the Web counterpart of iOS `ASCUserService.getFlagsByMe` and Android
|
|
1865
1915
|
* `UserRepository.getFlagsByMe`, kept apart from the deprecated public function so the
|
|
1866
1916
|
* user-object read does not change if that function ever does.
|
|
@@ -1921,35 +1971,72 @@ const locationsFor = (value, bits, hashes) => {
|
|
|
1921
1971
|
}
|
|
1922
1972
|
return locations;
|
|
1923
1973
|
};
|
|
1974
|
+
/** Standard or URL-safe base64, padding optional. Anything else is not a filter we can read. */
|
|
1975
|
+
const BASE64 = /^[A-Za-z0-9+/_-]*={0,2}$/;
|
|
1924
1976
|
/**
|
|
1925
|
-
* Whether `value` is probably in the filter. `false` is exact; `true`
|
|
1926
|
-
*
|
|
1927
|
-
*
|
|
1977
|
+
* Whether `value` is probably in the filter. `false` is exact; `true` means "maybe", which may be
|
|
1978
|
+
* a false positive. `null` (the server's value when nobody has flagged the object), a missing
|
|
1979
|
+
* filter or a missing value answer `false`.
|
|
1980
|
+
*
|
|
1981
|
+
* A filter that cannot be read answers `true` ("maybe") and never throws, so the caller asks the
|
|
1982
|
+
* server instead of trusting a "definitely not" it cannot back up (REQ-017): `bits` or `hashes`
|
|
1983
|
+
* not a positive integer, a `hash` that is not base64, or a `hash` shorter than `ceil(bits / 8)`
|
|
1984
|
+
* bytes.
|
|
1928
1985
|
*/
|
|
1929
1986
|
const testBloomFilter = (hashFlag, value) => {
|
|
1930
1987
|
if (!hashFlag || !value)
|
|
1931
1988
|
return false;
|
|
1932
1989
|
const { bits, hashes, hash } = hashFlag;
|
|
1933
|
-
if (!(bits
|
|
1934
|
-
return
|
|
1990
|
+
if (!Number.isInteger(bits) || bits <= 0)
|
|
1991
|
+
return true;
|
|
1992
|
+
if (!Number.isInteger(hashes) || hashes <= 0)
|
|
1993
|
+
return true;
|
|
1994
|
+
if (typeof hash !== 'string' || !BASE64.test(hash))
|
|
1995
|
+
return true;
|
|
1935
1996
|
let buckets;
|
|
1936
1997
|
try {
|
|
1937
1998
|
buckets = jsBase64.toUint8Array(hash);
|
|
1938
1999
|
}
|
|
1939
2000
|
catch (_a) {
|
|
1940
|
-
return
|
|
2001
|
+
return true;
|
|
1941
2002
|
}
|
|
2003
|
+
if (buckets.length < Math.ceil(bits / 8))
|
|
2004
|
+
return true;
|
|
1942
2005
|
const locations = locationsFor(value, bits, hashes);
|
|
1943
2006
|
for (let i = 0; i < locations.length; i += 1) {
|
|
1944
2007
|
const index = Math.floor(locations[i] / 8);
|
|
1945
2008
|
const bit = 1 << locations[i] % 8;
|
|
1946
|
-
if (
|
|
2009
|
+
if ((buckets[index] & bit) === 0)
|
|
1947
2010
|
return false;
|
|
1948
2011
|
}
|
|
1949
2012
|
return true;
|
|
1950
2013
|
};
|
|
1951
2014
|
|
|
1952
|
-
/**
|
|
2015
|
+
/**
|
|
2016
|
+
* Flag state of the current user on a target user, behind `Amity.User.isFlaggedByMe` and
|
|
2017
|
+
* `Amity.User.getUserFlagsByMe()` (`user.check_flag_by_me` v1, REQ-011, REQ-012, REQ-016).
|
|
2018
|
+
*
|
|
2019
|
+
* `hashFlag` is a Bloom filter of reporter ids. "Definitely not" is exact. "Maybe" can be a
|
|
2020
|
+
* false positive caused by other reporters, so the SDK confirms it with the server once per
|
|
2021
|
+
* `hashFlag` value and records the answer in the cache under its own key, never on the user's
|
|
2022
|
+
* cache row (REQ-015). Observers are told through `local.user.flagConfirmed` when a recorded
|
|
2023
|
+
* answer changes what a user object would show.
|
|
2024
|
+
*
|
|
2025
|
+
* Not exported from the public API.
|
|
2026
|
+
*/
|
|
2027
|
+
/** Confirms for the same user are at least this far apart, as Android's `EkoFlag.expired`. */
|
|
2028
|
+
const FLAG_CONFIRM_INTERVAL = 1000;
|
|
2029
|
+
const cacheKey = (userId) => ['userFlagByMe', 'get', userId];
|
|
2030
|
+
const lastConfirmAt = new Map();
|
|
2031
|
+
/**
|
|
2032
|
+
* Bumped by the current user's own flag and unflag. A confirm or exact read that started before
|
|
2033
|
+
* one of them must not record its answer, because the write may have changed it while the
|
|
2034
|
+
* `hashFlag` stayed the same.
|
|
2035
|
+
*/
|
|
2036
|
+
const generations = new Map();
|
|
2037
|
+
const generationOf = (userId) => { var _a; return (_a = generations.get(userId)) !== null && _a !== void 0 ? _a : 0; };
|
|
2038
|
+
const bumpGeneration = (userId) => generations.set(userId, generationOf(userId) + 1);
|
|
2039
|
+
/** The current user's id, or `undefined` when there is no active client. Never throws. */
|
|
1953
2040
|
const currentUserId = () => {
|
|
1954
2041
|
try {
|
|
1955
2042
|
return getActiveClient().userId;
|
|
@@ -1958,43 +2045,223 @@ const currentUserId = () => {
|
|
|
1958
2045
|
return undefined;
|
|
1959
2046
|
}
|
|
1960
2047
|
};
|
|
2048
|
+
const readRecord = (userId) => {
|
|
2049
|
+
var _a;
|
|
2050
|
+
try {
|
|
2051
|
+
return (_a = pullFromCache(cacheKey(userId))) === null || _a === void 0 ? void 0 : _a.data;
|
|
2052
|
+
}
|
|
2053
|
+
catch (_b) {
|
|
2054
|
+
return undefined;
|
|
2055
|
+
}
|
|
2056
|
+
};
|
|
1961
2057
|
/**
|
|
1962
|
-
*
|
|
1963
|
-
*
|
|
1964
|
-
* functions by reference: a fresh closure on every linked object would make two reads of the
|
|
1965
|
-
* same user unequal and re-dispatch snapshots that did not change.
|
|
2058
|
+
* The server's answer recorded for this user and this exact `hashFlag`, or `undefined` when there
|
|
2059
|
+
* is none for the current user. Never throws.
|
|
1966
2060
|
*/
|
|
1967
|
-
const
|
|
2061
|
+
const readConfirmedFlag = (userId, hashFlag) => {
|
|
2062
|
+
const me = currentUserId();
|
|
2063
|
+
if (!me || !hashFlag || typeof hashFlag.hash !== 'string')
|
|
2064
|
+
return undefined;
|
|
2065
|
+
const record = readRecord(userId);
|
|
2066
|
+
if (!record || record.reporterId !== me || record.hash !== hashFlag.hash)
|
|
2067
|
+
return undefined;
|
|
2068
|
+
return record.isFlagByMe;
|
|
2069
|
+
};
|
|
1968
2070
|
/**
|
|
1969
|
-
*
|
|
1970
|
-
*
|
|
1971
|
-
*
|
|
2071
|
+
* The v4 request in flight per user, with the generation it started in. A confirm and an exact
|
|
2072
|
+
* read of the same user share one request; a request that started before the current user's own
|
|
2073
|
+
* flag or unflag is not joined.
|
|
1972
2074
|
*/
|
|
1973
|
-
const
|
|
2075
|
+
const inFlight = new Map();
|
|
2076
|
+
const requestFlagsByMe = (userId) => {
|
|
2077
|
+
const generation = generationOf(userId);
|
|
2078
|
+
const pending = inFlight.get(userId);
|
|
2079
|
+
if (pending && pending.generation === generation)
|
|
2080
|
+
return pending.promise;
|
|
2081
|
+
const promise = getFlagsByMe(userId).finally(() => {
|
|
2082
|
+
var _a;
|
|
2083
|
+
if (((_a = inFlight.get(userId)) === null || _a === void 0 ? void 0 : _a.promise) === promise)
|
|
2084
|
+
inFlight.delete(userId);
|
|
2085
|
+
});
|
|
2086
|
+
inFlight.set(userId, { generation, promise });
|
|
2087
|
+
return promise;
|
|
2088
|
+
};
|
|
2089
|
+
const notifyObservers = (userId) => fireEvent('local.user.flagConfirmed', { userId });
|
|
2090
|
+
/**
|
|
2091
|
+
* Records `isFlagByMe` for `hashFlag`. A "maybe" without a record shows `true`, so observers are
|
|
2092
|
+
* told only when the shown value changes.
|
|
2093
|
+
*/
|
|
2094
|
+
const recordFlag = (userId, hashFlag, isFlagByMe) => {
|
|
1974
2095
|
var _a;
|
|
1975
2096
|
const me = currentUserId();
|
|
1976
|
-
|
|
1977
|
-
|
|
2097
|
+
if (!me || typeof hashFlag.hash !== 'string')
|
|
2098
|
+
return;
|
|
2099
|
+
const shown = (_a = readConfirmedFlag(userId, hashFlag)) !== null && _a !== void 0 ? _a : true;
|
|
2100
|
+
const record = { reporterId: me, hash: hashFlag.hash, isFlagByMe };
|
|
2101
|
+
pushToCache(cacheKey(userId), record);
|
|
2102
|
+
if (shown !== isFlagByMe)
|
|
2103
|
+
notifyObservers(userId);
|
|
2104
|
+
};
|
|
2105
|
+
/**
|
|
2106
|
+
* Starts one background confirm of a "maybe" (REQ-016): at most one in flight per user, and
|
|
2107
|
+
* confirms for the same user at least {@link FLAG_CONFIRM_INTERVAL} apart. A failed confirm
|
|
2108
|
+
* records nothing, surfaces no error, and a later read tries again.
|
|
2109
|
+
*/
|
|
2110
|
+
const confirmFlagByMe = (userId, hashFlag) => {
|
|
2111
|
+
if (inFlight.has(userId))
|
|
2112
|
+
return;
|
|
2113
|
+
const now = Date.now();
|
|
2114
|
+
const last = lastConfirmAt.get(userId);
|
|
2115
|
+
if (last !== undefined && now - last < FLAG_CONFIRM_INTERVAL)
|
|
2116
|
+
return;
|
|
2117
|
+
const me = currentUserId();
|
|
2118
|
+
const generation = generationOf(userId);
|
|
2119
|
+
lastConfirmAt.set(userId, now);
|
|
2120
|
+
requestFlagsByMe(userId)
|
|
2121
|
+
.then(({ isFlagByMe }) => {
|
|
2122
|
+
if (currentUserId() !== me || generationOf(userId) !== generation)
|
|
2123
|
+
return;
|
|
2124
|
+
recordFlag(userId, hashFlag, isFlagByMe);
|
|
2125
|
+
})
|
|
2126
|
+
.catch(() => {
|
|
2127
|
+
// Not an answer: isFlaggedByMe stays true until a later read confirms again.
|
|
2128
|
+
});
|
|
2129
|
+
};
|
|
2130
|
+
/**
|
|
2131
|
+
* The value of `Amity.User.isFlaggedByMe` for a user object whose confirmed answer was captured
|
|
2132
|
+
* (`confirmed`) when the object was linked, so a held object never changes (REQ-014).
|
|
2133
|
+
*
|
|
2134
|
+
* - No current user, `hashFlag: null` or a missing `hashFlag`, or "definitely not": `false`.
|
|
2135
|
+
* - "Maybe" with a confirmed answer: that answer, no request.
|
|
2136
|
+
* - "Maybe" without one: `true`, and one background confirm (REQ-016).
|
|
2137
|
+
*
|
|
2138
|
+
* The linked object declares this as a getter inside an object spread, which the build compiles
|
|
2139
|
+
* to `Object.assign`, so it runs once when the user is linked and the object keeps that value.
|
|
2140
|
+
*/
|
|
2141
|
+
const isFlaggedByMeFor = (user, confirmed) => {
|
|
2142
|
+
const me = currentUserId();
|
|
2143
|
+
if (!me || !user.hashFlag || !testBloomFilter(user.hashFlag, me))
|
|
1978
2144
|
return false;
|
|
1979
|
-
|
|
2145
|
+
if (confirmed !== undefined)
|
|
2146
|
+
return confirmed;
|
|
2147
|
+
confirmFlagByMe(user.userId, user.hashFlag);
|
|
2148
|
+
return true;
|
|
2149
|
+
};
|
|
2150
|
+
const NOT_FLAGGED = { isFlagByMe: false, flags: [] };
|
|
2151
|
+
const isNotOlder = (next, current) => {
|
|
2152
|
+
var _a, _b;
|
|
2153
|
+
const nextAt = Date.parse((_a = next.updatedAt) !== null && _a !== void 0 ? _a : '');
|
|
2154
|
+
const currentAt = Date.parse((_b = current.updatedAt) !== null && _b !== void 0 ? _b : '');
|
|
2155
|
+
return Number.isNaN(nextAt) || Number.isNaN(currentAt) || nextAt >= currentAt;
|
|
2156
|
+
};
|
|
2157
|
+
/**
|
|
2158
|
+
* One `getUserFlagsByMe` closure per userId, remembering the newest user object linked for that
|
|
2159
|
+
* id. Live objects and collections compare snapshots with `isEqual`, which compares functions by
|
|
2160
|
+
* reference, so a fresh closure per linked object would re-dispatch unchanged snapshots
|
|
2161
|
+
* (REQ-015). An older snapshot linked later does not replace a newer one.
|
|
2162
|
+
*/
|
|
2163
|
+
const flagsByMeEntries = new Map();
|
|
2164
|
+
/**
|
|
2165
|
+
* `Amity.User.getUserFlagsByMe()` (REQ-012): `{ isFlagByMe: false, flags: [] }` with no request
|
|
2166
|
+
* when the newest linked user says "not flagged", including a confirmed `false`. Otherwise the
|
|
2167
|
+
* v4 read, returned as is; a confirm already in flight for the user is joined instead of sending
|
|
2168
|
+
* a second request. Its `isFlagByMe` is recorded as the confirmed answer for the
|
|
2169
|
+
* `hashFlag` it was read for; `flags[]` is never stored (REQ-009). A missing `hashFlag` is
|
|
2170
|
+
* unknown, so the server is asked.
|
|
2171
|
+
*/
|
|
2172
|
+
const readFlagsByMe = async (userId) => {
|
|
2173
|
+
var _a, _b;
|
|
2174
|
+
const me = currentUserId();
|
|
2175
|
+
const { hashFlag } = (_b = (_a = flagsByMeEntries.get(userId)) === null || _a === void 0 ? void 0 : _a.latest) !== null && _b !== void 0 ? _b : {};
|
|
2176
|
+
if (me && hashFlag !== undefined) {
|
|
2177
|
+
if (!hashFlag || !testBloomFilter(hashFlag, me))
|
|
2178
|
+
return Object.assign(Object.assign({}, NOT_FLAGGED), { flags: [] });
|
|
2179
|
+
if (readConfirmedFlag(userId, hashFlag) === false)
|
|
2180
|
+
return Object.assign(Object.assign({}, NOT_FLAGGED), { flags: [] });
|
|
2181
|
+
}
|
|
2182
|
+
const generation = generationOf(userId);
|
|
2183
|
+
const result = await requestFlagsByMe(userId);
|
|
2184
|
+
if (hashFlag && currentUserId() === me && generationOf(userId) === generation) {
|
|
2185
|
+
recordFlag(userId, hashFlag, result.isFlagByMe);
|
|
2186
|
+
}
|
|
2187
|
+
return result;
|
|
1980
2188
|
};
|
|
1981
2189
|
const getUserFlagsByMeFor = (user) => {
|
|
1982
2190
|
let entry = flagsByMeEntries.get(user.userId);
|
|
1983
2191
|
if (!entry) {
|
|
1984
|
-
entry = {
|
|
1985
|
-
latest: user,
|
|
1986
|
-
getUserFlagsByMe: async () => {
|
|
1987
|
-
if (knownNotFlaggedByMe(user.userId))
|
|
1988
|
-
return { isFlagByMe: false, flags: [] };
|
|
1989
|
-
return getFlagsByMe(user.userId);
|
|
1990
|
-
},
|
|
1991
|
-
};
|
|
2192
|
+
entry = { latest: user, getUserFlagsByMe: () => readFlagsByMe(user.userId) };
|
|
1992
2193
|
flagsByMeEntries.set(user.userId, entry);
|
|
1993
2194
|
}
|
|
1994
|
-
entry.latest
|
|
2195
|
+
else if (isNotOlder(user, entry.latest)) {
|
|
2196
|
+
entry.latest = user;
|
|
2197
|
+
}
|
|
1995
2198
|
return entry.getUserFlagsByMe;
|
|
1996
2199
|
};
|
|
2200
|
+
/**
|
|
2201
|
+
* The current user's own flag succeeded (REQ-016). Their report may leave `hashFlag` unchanged
|
|
2202
|
+
* when other reporters had already set all of their bits, so the answer is known: record `true`
|
|
2203
|
+
* for the `hashFlag` the response carries, or drop the answer when it carries none.
|
|
2204
|
+
*/
|
|
2205
|
+
const onFlaggedByMe = (user, userId) => {
|
|
2206
|
+
bumpGeneration(userId);
|
|
2207
|
+
if (user === null || user === void 0 ? void 0 : user.hashFlag) {
|
|
2208
|
+
recordFlag(userId, user.hashFlag, true);
|
|
2209
|
+
return;
|
|
2210
|
+
}
|
|
2211
|
+
const dropped = readRecord(userId);
|
|
2212
|
+
dropFromCache(cacheKey(userId), true);
|
|
2213
|
+
if ((dropped === null || dropped === void 0 ? void 0 : dropped.isFlagByMe) === false)
|
|
2214
|
+
notifyObservers(userId);
|
|
2215
|
+
};
|
|
2216
|
+
/**
|
|
2217
|
+
* The current user's own unflag succeeded (`user.unflag` REQ-010, REQ-016). A per-type unflag can
|
|
2218
|
+
* leave other reports in place, so the answer is dropped, never set to `false`; the next "maybe"
|
|
2219
|
+
* is confirmed again.
|
|
2220
|
+
*/
|
|
2221
|
+
const onUnflaggedByMe = (userId) => {
|
|
2222
|
+
bumpGeneration(userId);
|
|
2223
|
+
const dropped = readRecord(userId);
|
|
2224
|
+
dropFromCache(cacheKey(userId), true);
|
|
2225
|
+
if ((dropped === null || dropped === void 0 ? void 0 : dropped.isFlagByMe) === false)
|
|
2226
|
+
notifyObservers(userId);
|
|
2227
|
+
};
|
|
2228
|
+
/** Forgets every in-memory trace of the current user's flag state. Records live in the cache. */
|
|
2229
|
+
const resetUserFlagByMe = () => {
|
|
2230
|
+
flagsByMeEntries.clear();
|
|
2231
|
+
inFlight.clear();
|
|
2232
|
+
lastConfirmAt.clear();
|
|
2233
|
+
generations.clear();
|
|
2234
|
+
};
|
|
2235
|
+
/**
|
|
2236
|
+
* Registered through `setupLoginSubscriptions`. Every confirmed answer belongs to the current
|
|
2237
|
+
* user, so the state is cleared on logout; the records themselves go with the cache, and each
|
|
2238
|
+
* also carries the reporter's id.
|
|
2239
|
+
*/
|
|
2240
|
+
const userFlagByMeOnLoginHandler = () => {
|
|
2241
|
+
const unsubscribe = onSessionStateChange(state => {
|
|
2242
|
+
if (state === "notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */ || state === "terminated" /* Amity.SessionStates.TERMINATED */) {
|
|
2243
|
+
resetUserFlagByMe();
|
|
2244
|
+
}
|
|
2245
|
+
});
|
|
2246
|
+
return () => {
|
|
2247
|
+
unsubscribe();
|
|
2248
|
+
resetUserFlagByMe();
|
|
2249
|
+
};
|
|
2250
|
+
};
|
|
2251
|
+
/**
|
|
2252
|
+
* Called with the cached user when a recorded answer changes what that user would show, so live
|
|
2253
|
+
* objects and live collections deliver it again (REQ-016, delivery).
|
|
2254
|
+
*/
|
|
2255
|
+
const onUserFlagConfirmed = (callback) => createEventSubscriber(getActiveClient(), 'user/onUserFlagConfirmed', 'local.user.flagConfirmed', ({ userId }) => {
|
|
2256
|
+
var _a;
|
|
2257
|
+
const user = (_a = pullFromCache(['user', 'get', userId])) === null || _a === void 0 ? void 0 : _a.data;
|
|
2258
|
+
if (user)
|
|
2259
|
+
callback(user);
|
|
2260
|
+
});
|
|
2261
|
+
|
|
1997
2262
|
const userLinkedObject = (user) => {
|
|
2263
|
+
// Captured now, so a user object the app holds never changes after a confirm (REQ-014).
|
|
2264
|
+
const confirmedFlagByMe = readConfirmedFlag(user.userId, user.hashFlag);
|
|
1998
2265
|
return Object.assign(Object.assign({}, user), { get avatar() {
|
|
1999
2266
|
var _a;
|
|
2000
2267
|
if (!user.avatarFileId)
|
|
@@ -2005,9 +2272,10 @@ const userLinkedObject = (user) => {
|
|
|
2005
2272
|
return avatar;
|
|
2006
2273
|
},
|
|
2007
2274
|
get isFlaggedByMe() {
|
|
2008
|
-
//
|
|
2009
|
-
//
|
|
2010
|
-
|
|
2275
|
+
// Bloom test on this object's hashFlag: "definitely not" is exact and sends nothing.
|
|
2276
|
+
// "Maybe" returns the answer confirmed for this hashFlag, or true while one background
|
|
2277
|
+
// confirm runs (REQ-011, REQ-016). Never throws.
|
|
2278
|
+
return isFlaggedByMeFor(user, confirmedFlagByMe);
|
|
2011
2279
|
},
|
|
2012
2280
|
/* begin_public_function
|
|
2013
2281
|
id: user.get_flags_by_me
|
|
@@ -2279,13 +2547,13 @@ class NetworkActivitiesWatcher {
|
|
|
2279
2547
|
this._listener.clear();
|
|
2280
2548
|
}
|
|
2281
2549
|
}
|
|
2282
|
-
let instance$
|
|
2550
|
+
let instance$a;
|
|
2283
2551
|
var NetworkActivitiesWatcher$1 = {
|
|
2284
2552
|
getInstance: () => {
|
|
2285
|
-
if (!instance$
|
|
2286
|
-
instance$
|
|
2553
|
+
if (!instance$a) {
|
|
2554
|
+
instance$a = new NetworkActivitiesWatcher();
|
|
2287
2555
|
}
|
|
2288
|
-
return instance$
|
|
2556
|
+
return instance$a;
|
|
2289
2557
|
},
|
|
2290
2558
|
};
|
|
2291
2559
|
|
|
@@ -2469,54 +2737,6 @@ const createHttpTransport = (endpoint) => {
|
|
|
2469
2737
|
return instance;
|
|
2470
2738
|
};
|
|
2471
2739
|
|
|
2472
|
-
class SessionWatcher {
|
|
2473
|
-
constructor() {
|
|
2474
|
-
this._sessionState = "notLoggedIn" /* Amity.SessionStates.NOT_LOGGED_IN */;
|
|
2475
|
-
this._listener = new Map();
|
|
2476
|
-
}
|
|
2477
|
-
onSessionStateChange(callback) {
|
|
2478
|
-
this._listener.set(callback, callback);
|
|
2479
|
-
return () => {
|
|
2480
|
-
this._listener.delete(callback);
|
|
2481
|
-
};
|
|
2482
|
-
}
|
|
2483
|
-
setSessionState(state, reason) {
|
|
2484
|
-
if (this._sessionState === state)
|
|
2485
|
-
return;
|
|
2486
|
-
this._sessionState = state;
|
|
2487
|
-
this._listener.forEach(cb => cb(state, reason));
|
|
2488
|
-
}
|
|
2489
|
-
destroy() {
|
|
2490
|
-
this._listener.clear();
|
|
2491
|
-
}
|
|
2492
|
-
}
|
|
2493
|
-
let instance$a;
|
|
2494
|
-
var SessionWatcher$1 = {
|
|
2495
|
-
getInstance: () => {
|
|
2496
|
-
if (!instance$a) {
|
|
2497
|
-
instance$a = new SessionWatcher();
|
|
2498
|
-
}
|
|
2499
|
-
return instance$a;
|
|
2500
|
-
},
|
|
2501
|
-
};
|
|
2502
|
-
|
|
2503
|
-
/**
|
|
2504
|
-
* ```js
|
|
2505
|
-
* import { onSessionStateChange } from '@amityco/ts-sdk'
|
|
2506
|
-
* const dispose = onSessionStateChange((state: Amity.SessionStates) => {
|
|
2507
|
-
* // ...
|
|
2508
|
-
* })
|
|
2509
|
-
* ```
|
|
2510
|
-
*
|
|
2511
|
-
* Fired when any {@link Amity.Client} has a session state change
|
|
2512
|
-
*
|
|
2513
|
-
* @param callback The function to call when the event was fired
|
|
2514
|
-
* @returns an {@link Amity.Unsubscriber} function to stop listening
|
|
2515
|
-
*
|
|
2516
|
-
* @category Client Events
|
|
2517
|
-
*/
|
|
2518
|
-
const onSessionStateChange = (callback) => SessionWatcher$1.getInstance().onSessionStateChange(callback);
|
|
2519
|
-
|
|
2520
2740
|
const TOPICS = {
|
|
2521
2741
|
[exports.AmityAutoSubscription.NETWORK]: [getNetworkTopic],
|
|
2522
2742
|
[exports.AmityAutoSubscription.CHAT]: [
|
|
@@ -8584,7 +8804,7 @@ const setupLoginSubscriptions = (unsubWatcher) => {
|
|
|
8584
8804
|
// NOTE: This is a temporary solution to handle the channel marker when the user is forced to leave
|
|
8585
8805
|
// the channel because currently backend can't handle this, so every time a user is banned from
|
|
8586
8806
|
// 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());
|
|
8807
|
+
onChannelDeleted(removeChannelMarkerCache), onChannelMemberBanned(removeChannelMarkerCache), markReadEngineOnLoginHandler(), analyticsEngineOnLoginHandler(), objectResolverEngineOnLoginHandler(), reactionSyncEngineOnLoginHandler(), blockedUserSyncEngineOnLoginHandler(), blockingUserSyncEngineOnLoginHandler(), blockRealtimeOnLoginHandler(), resetAutoSubscriptionsOnLogout(), CursorController.clearOnLogout(), postCommentCountEngineOnLoginHandler(), channelActivityOnLoginHandler(), userFlagByMeOnLoginHandler());
|
|
8588
8808
|
if (client.useLegacyUnreadCount) {
|
|
8589
8809
|
subscriptions.push(readReceiptSyncEngineOnLoginHandler());
|
|
8590
8810
|
}
|
|
@@ -15630,8 +15850,11 @@ const flagUser = async (userId, options) => {
|
|
|
15630
15850
|
if (client.cache) {
|
|
15631
15851
|
ingestInCache(payload);
|
|
15632
15852
|
}
|
|
15853
|
+
const flagged = (_a = payload.users.find(user => user.userId === userId)) !== null && _a !== void 0 ? _a : payload.users[0];
|
|
15854
|
+
// The caller's own report may leave hashFlag unchanged; record that they flagged (REQ-016).
|
|
15855
|
+
onFlaggedByMe(flagged, userId);
|
|
15633
15856
|
fireEvent('user.flagged', data);
|
|
15634
|
-
return userLinkedObject(
|
|
15857
|
+
return userLinkedObject(flagged);
|
|
15635
15858
|
};
|
|
15636
15859
|
/* end_public_function */
|
|
15637
15860
|
|
|
@@ -15651,8 +15874,11 @@ const submitUserReport = async (apiName, userId, body) => {
|
|
|
15651
15874
|
if (client.cache) {
|
|
15652
15875
|
ingestInCache(payload);
|
|
15653
15876
|
}
|
|
15877
|
+
const flagged = (_a = payload.users.find(user => user.userId === userId)) !== null && _a !== void 0 ? _a : payload.users[0];
|
|
15878
|
+
// The caller's own report may leave hashFlag unchanged; record that they flagged (REQ-016).
|
|
15879
|
+
onFlaggedByMe(flagged, userId);
|
|
15654
15880
|
fireEvent('user.flagged', data);
|
|
15655
|
-
return userLinkedObject(
|
|
15881
|
+
return userLinkedObject(flagged);
|
|
15656
15882
|
};
|
|
15657
15883
|
|
|
15658
15884
|
/** Maximum `comment` length, in string length units, after trimming. */
|
|
@@ -15706,7 +15932,7 @@ const toUserProfileReportBody = (options) => {
|
|
|
15706
15932
|
};
|
|
15707
15933
|
/**
|
|
15708
15934
|
* Validates `flagUserBehavior` options and builds its request body. `reason` must be one
|
|
15709
|
-
* of the
|
|
15935
|
+
* of the `ContentFlagReasonEnum` values and is sent as that canonical label;
|
|
15710
15936
|
* `reportType` is always `behavior`.
|
|
15711
15937
|
*
|
|
15712
15938
|
* @throws {ASCInvalidParameterError} `INVALID_PARAMETERS` when the options are malformed
|
|
@@ -15787,7 +16013,7 @@ const flagUserProfile = async (userId, options) => submitUserReport('flagUserPro
|
|
|
15787
16013
|
* })
|
|
15788
16014
|
* ```
|
|
15789
16015
|
*
|
|
15790
|
-
* Reports a user's behavior. `reason` is required and is one of the
|
|
16016
|
+
* Reports a user's behavior. `reason` is required and is one of the
|
|
15791
16017
|
* `ContentFlagReasonEnum` values, sent as its canonical label. Reporter text, including
|
|
15792
16018
|
* the explanation for `Others`, always travels in `comment`; the reason never carries text.
|
|
15793
16019
|
*
|
|
@@ -15831,14 +16057,15 @@ const flagUserBehavior = async (userId, options) => submitUserReport('flagUserBe
|
|
|
15831
16057
|
* untouched. Withdrawing a report that does not exist succeeds and changes nothing.
|
|
15832
16058
|
*
|
|
15833
16059
|
* 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`).
|
|
16060
|
+
* may still hold a report on the user. Do not flip a local "flagged by me" flag to `false`
|
|
16061
|
+
* after a per-type withdrawal; observe the user and read `isFlaggedByMe`, or call
|
|
16062
|
+
* `user.getUserFlagsByMe()` for the remaining per-type state (`flags`). The SDK drops the
|
|
16063
|
+
* answer it confirmed for this user, so the next "maybe" is confirmed again.
|
|
15837
16064
|
*
|
|
15838
16065
|
* Sends `DELETE /api/v4/me/flags/:userId`, with `?reportType=<type>` when one is given.
|
|
15839
16066
|
*
|
|
15840
16067
|
* @param userId The ID of the user to unflag
|
|
15841
|
-
* @param options Optional; `reportType` selects a single report to withdraw. For a report that `
|
|
16068
|
+
* @param options Optional; `reportType` selects a single report to withdraw. For a report that `user.getUserFlagsByMe()` lists with `reportType: null`, pass `UserReportTypeFilterEnum.UNTYPED`
|
|
15842
16069
|
* @returns `true` once the server has processed the withdrawal
|
|
15843
16070
|
* @throws {ASCInvalidParameterError} `INVALID_PARAMETERS` when `reportType` is not a `UserReportTypeFilterEnum` value, before any request is made
|
|
15844
16071
|
*
|
|
@@ -15857,6 +16084,8 @@ const unflagUser = async (userId, options) => {
|
|
|
15857
16084
|
if (client.cache) {
|
|
15858
16085
|
ingestInCache(payload);
|
|
15859
16086
|
}
|
|
16087
|
+
// Drop the confirmed answer; never set it to false: other reports may remain (REQ-010).
|
|
16088
|
+
onUnflaggedByMe(userId);
|
|
15860
16089
|
fireEvent('user.unflagged', data);
|
|
15861
16090
|
return !!payload;
|
|
15862
16091
|
};
|
|
@@ -15868,33 +16097,19 @@ const unflagUser = async (userId, options) => {
|
|
|
15868
16097
|
/**
|
|
15869
16098
|
* ```js
|
|
15870
16099
|
* 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))
|
|
16100
|
+
* const isFlagged = await UserRepository.isUserFlaggedByMe(userId)
|
|
15876
16101
|
* ```
|
|
15877
16102
|
*
|
|
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.
|
|
16103
|
+
* Whether the current user has reported a user. Sends one request per call and caches
|
|
16104
|
+
* nothing.
|
|
15883
16105
|
*
|
|
15884
|
-
*
|
|
15885
|
-
*
|
|
15886
|
-
*
|
|
15887
|
-
*
|
|
15888
|
-
*
|
|
15889
|
-
* Breaking change: earlier versions returned a boolean from the v3 endpoint, which the
|
|
15890
|
-
* backend has deprecated. Read `isFlagByMe` on the result for the same answer.
|
|
15891
|
-
*
|
|
15892
|
-
* @deprecated On an {@link Amity.User} you already hold, read `user.isFlaggedByMe` for a
|
|
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.
|
|
16106
|
+
* @deprecated Read `user.isFlaggedByMe` on an {@link Amity.User} for a yes/no hint that
|
|
16107
|
+
* usually needs no request, and call `user.getUserFlagsByMe()` for the exact answer with the
|
|
16108
|
+
* caller's reports by type. Observe the user with `UserRepository.getUser(userId, callback)`
|
|
16109
|
+
* to follow a flag or unflag.
|
|
15895
16110
|
*
|
|
15896
16111
|
* @param userId The ID of the user to check
|
|
15897
|
-
* @returns the
|
|
16112
|
+
* @returns `true` if the current user has reported the user, `false` if not
|
|
15898
16113
|
*
|
|
15899
16114
|
* @category Report API
|
|
15900
16115
|
* @async
|
|
@@ -15902,7 +16117,8 @@ const unflagUser = async (userId, options) => {
|
|
|
15902
16117
|
const isUserFlaggedByMe = async (userId) => {
|
|
15903
16118
|
const client = getActiveClient();
|
|
15904
16119
|
client.log('user/isUserFlaggedByMe', userId);
|
|
15905
|
-
|
|
16120
|
+
const { isFlagByMe } = await getFlagsByMe(userId);
|
|
16121
|
+
return isFlagByMe;
|
|
15906
16122
|
};
|
|
15907
16123
|
/* end_public_function */
|
|
15908
16124
|
|
|
@@ -16141,7 +16357,7 @@ const getUser = (userId, callback) => {
|
|
|
16141
16357
|
const reactor = (response) => {
|
|
16142
16358
|
return callback(Object.assign(Object.assign({}, response), { data: response.data ? LinkedObject.user(response.data) : response.data }));
|
|
16143
16359
|
};
|
|
16144
|
-
|
|
16360
|
+
const unsubscribeUser = liveObject(userId, reactor, 'userId', getUser$1, [
|
|
16145
16361
|
onUserFetched,
|
|
16146
16362
|
onUserUpdated,
|
|
16147
16363
|
onUserDeleted$2,
|
|
@@ -16149,6 +16365,17 @@ const getUser = (userId, callback) => {
|
|
|
16149
16365
|
onUserUnflagged,
|
|
16150
16366
|
onUserFlagCleared,
|
|
16151
16367
|
]);
|
|
16368
|
+
// A confirmed flag answer leaves the cached user row unchanged, so the live object's own
|
|
16369
|
+
// dedupe would drop it. Deliver the re-linked user directly (user.check_flag_by_me REQ-016).
|
|
16370
|
+
const unsubscribeFlag = onUserFlagConfirmed(user => {
|
|
16371
|
+
if (user.userId !== userId)
|
|
16372
|
+
return;
|
|
16373
|
+
callback({ data: LinkedObject.user(user), loading: false, origin: 'event' });
|
|
16374
|
+
});
|
|
16375
|
+
return () => {
|
|
16376
|
+
unsubscribeUser();
|
|
16377
|
+
unsubscribeFlag();
|
|
16378
|
+
};
|
|
16152
16379
|
};
|
|
16153
16380
|
/* end_public_function */
|
|
16154
16381
|
|
|
@@ -16246,13 +16473,24 @@ class UserLiveCollectionController extends LiveCollectionController {
|
|
|
16246
16473
|
this.queryStreamController.appendToQueryStream(response, direction, refresh);
|
|
16247
16474
|
}
|
|
16248
16475
|
startSubscription() {
|
|
16249
|
-
return
|
|
16250
|
-
|
|
16251
|
-
|
|
16252
|
-
|
|
16253
|
-
|
|
16254
|
-
|
|
16255
|
-
|
|
16476
|
+
return [
|
|
16477
|
+
...this.queryStreamController.subscribeRTE([
|
|
16478
|
+
{ fn: onUserDeleted$2, action: EnumUserActions.OnUserDeleted },
|
|
16479
|
+
{ fn: onUserUpdated, action: EnumUserActions.OnUserUpdated },
|
|
16480
|
+
{ fn: onUserFlagged, action: EnumUserActions.OnUserFlagged },
|
|
16481
|
+
{ fn: onUserUnflagged, action: EnumUserActions.OnUserUnflagged },
|
|
16482
|
+
{ fn: onUserFlagCleared, action: EnumUserActions.OnUserFlagCleared },
|
|
16483
|
+
]),
|
|
16484
|
+
// A confirmed flag answer changes isFlaggedByMe on a listed user without changing its
|
|
16485
|
+
// cache row (user.check_flag_by_me REQ-016). Re-link only collections that hold it.
|
|
16486
|
+
onUserFlagConfirmed(user => {
|
|
16487
|
+
var _a;
|
|
16488
|
+
const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
|
|
16489
|
+
if (!(collection === null || collection === void 0 ? void 0 : collection.data.includes(user.userId)))
|
|
16490
|
+
return;
|
|
16491
|
+
this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
|
|
16492
|
+
}),
|
|
16493
|
+
];
|
|
16256
16494
|
}
|
|
16257
16495
|
notifyChange({ origin, loading, error }) {
|
|
16258
16496
|
var _a, _b;
|
|
@@ -16804,13 +17042,24 @@ class SearchUserLiveCollectionController extends LiveCollectionController {
|
|
|
16804
17042
|
this.queryStreamController.appendToQueryStream(response, direction, refresh);
|
|
16805
17043
|
}
|
|
16806
17044
|
startSubscription() {
|
|
16807
|
-
return
|
|
16808
|
-
|
|
16809
|
-
|
|
16810
|
-
|
|
16811
|
-
|
|
16812
|
-
|
|
16813
|
-
|
|
17045
|
+
return [
|
|
17046
|
+
...this.queryStreamController.subscribeRTE([
|
|
17047
|
+
{ fn: onUserDeleted$2, action: EnumUserActions.OnUserDeleted },
|
|
17048
|
+
{ fn: onUserUpdated, action: EnumUserActions.OnUserUpdated },
|
|
17049
|
+
{ fn: onUserFlagged, action: EnumUserActions.OnUserFlagged },
|
|
17050
|
+
{ fn: onUserUnflagged, action: EnumUserActions.OnUserUnflagged },
|
|
17051
|
+
{ fn: onUserFlagCleared, action: EnumUserActions.OnUserFlagCleared },
|
|
17052
|
+
]),
|
|
17053
|
+
// A confirmed flag answer changes isFlaggedByMe on a listed user without changing its
|
|
17054
|
+
// cache row (user.check_flag_by_me REQ-016). Re-link only collections that hold it.
|
|
17055
|
+
onUserFlagConfirmed(user => {
|
|
17056
|
+
var _a;
|
|
17057
|
+
const collection = (_a = pullFromCache(this.cacheKey)) === null || _a === void 0 ? void 0 : _a.data;
|
|
17058
|
+
if (!(collection === null || collection === void 0 ? void 0 : collection.data.includes(user.userId)))
|
|
17059
|
+
return;
|
|
17060
|
+
this.notifyChange({ origin: "event" /* Amity.LiveDataOrigin.EVENT */, loading: false });
|
|
17061
|
+
}),
|
|
17062
|
+
];
|
|
16814
17063
|
}
|
|
16815
17064
|
notifyChange({ origin, loading, error }) {
|
|
16816
17065
|
var _a, _b;
|
|
@@ -20760,7 +21009,7 @@ const isLegacyContentFlagReason = (input) => input === undefined || typeof input
|
|
|
20760
21009
|
/**
|
|
20761
21010
|
* Validates an `Amity.ContentFlagOptions` argument. Untyped (plain JS) callers can pass
|
|
20762
21011
|
* anything at runtime, so the checks do not trust the declared type: the value must be a
|
|
20763
|
-
* plain object, `reason` must be one of the
|
|
21012
|
+
* plain object, `reason` must be one of the `ContentFlagReasonEnum` values and
|
|
20764
21013
|
* `detail`, when supplied, must be a string (`null` is not a valid supplied detail).
|
|
20765
21014
|
*
|
|
20766
21015
|
* @param apiName used in the error message, e.g. `flagPost`
|
|
@@ -37939,6 +38188,64 @@ class AmityAttachmentProductTags {
|
|
|
37939
38188
|
}
|
|
37940
38189
|
}
|
|
37941
38190
|
|
|
38191
|
+
/**
|
|
38192
|
+
* Stable, cross-platform key per report category. Android and iOS expose the same
|
|
38193
|
+
* keys on `AmityContentFlagReasonType.key`. A UIKit builds its string key from it
|
|
38194
|
+
* (`amity_social_label_report_reason_<key>`), so a released key is never renamed.
|
|
38195
|
+
* The key is not derived from the enum member name on purpose: the existing UIKit
|
|
38196
|
+
* string keys do not follow it (`selling_restricted`, `violence_or_threatening`).
|
|
38197
|
+
*/
|
|
38198
|
+
const CONTENT_FLAG_REASON_KEYS = Object.freeze({
|
|
38199
|
+
[exports.ContentFlagReasonEnum.CommunityGuidelines]: 'community_guidelines',
|
|
38200
|
+
[exports.ContentFlagReasonEnum.ChildEndangerment]: 'child_endangerment',
|
|
38201
|
+
[exports.ContentFlagReasonEnum.HarassmentOrBullying]: 'harassment_or_bullying',
|
|
38202
|
+
[exports.ContentFlagReasonEnum.SelfHarmOrSuicide]: 'self_harm_or_suicide',
|
|
38203
|
+
[exports.ContentFlagReasonEnum.ViolenceOrThreateningContent]: 'violence_or_threatening',
|
|
38204
|
+
[exports.ContentFlagReasonEnum.SellingRestrictedItems]: 'selling_restricted',
|
|
38205
|
+
[exports.ContentFlagReasonEnum.SexualContentOrNudity]: 'sexual_content_or_nudity',
|
|
38206
|
+
[exports.ContentFlagReasonEnum.SpamOrScams]: 'spam_or_scams',
|
|
38207
|
+
[exports.ContentFlagReasonEnum.FalseInformation]: 'false_information',
|
|
38208
|
+
[exports.ContentFlagReasonEnum.Others]: 'others',
|
|
38209
|
+
});
|
|
38210
|
+
/* begin_public_function
|
|
38211
|
+
id: content_flag_reason.get_reasons
|
|
38212
|
+
*/
|
|
38213
|
+
/**
|
|
38214
|
+
* ```js
|
|
38215
|
+
* import { getContentFlagReasons, ContentFlagReasonEnum } from '@amityco/ts-sdk'
|
|
38216
|
+
* const reasons = getContentFlagReasons().filter(r => r !== ContentFlagReasonEnum.Others)
|
|
38217
|
+
* ```
|
|
38218
|
+
*
|
|
38219
|
+
* Returns every report category in display order, with `Others` last. Render a report
|
|
38220
|
+
* picker from this list rather than a copy, so a category added in a later SDK release
|
|
38221
|
+
* appears without a UI change. Each value is also its English default label.
|
|
38222
|
+
*
|
|
38223
|
+
* @returns a new array on every call; mutating it does not affect the SDK
|
|
38224
|
+
*
|
|
38225
|
+
* @category Content Flag
|
|
38226
|
+
*/
|
|
38227
|
+
const getContentFlagReasons = () => Object.values(exports.ContentFlagReasonEnum);
|
|
38228
|
+
/* end_public_function */
|
|
38229
|
+
/* begin_public_function
|
|
38230
|
+
id: content_flag_reason.get_key
|
|
38231
|
+
*/
|
|
38232
|
+
/**
|
|
38233
|
+
* ```js
|
|
38234
|
+
* import { getContentFlagReasonKey, ContentFlagReasonEnum } from '@amityco/ts-sdk'
|
|
38235
|
+
* getContentFlagReasonKey(ContentFlagReasonEnum.ChildEndangerment) // 'child_endangerment'
|
|
38236
|
+
* ```
|
|
38237
|
+
*
|
|
38238
|
+
* Returns the stable, cross-platform key of a report category, for building a
|
|
38239
|
+
* localisation key. Never send the key to the server: flag with the enum value.
|
|
38240
|
+
*
|
|
38241
|
+
* @param reason a `ContentFlagReasonEnum` value
|
|
38242
|
+
* @returns the category's snake_case key
|
|
38243
|
+
*
|
|
38244
|
+
* @category Content Flag
|
|
38245
|
+
*/
|
|
38246
|
+
const getContentFlagReasonKey = (reason) => CONTENT_FLAG_REASON_KEYS[reason];
|
|
38247
|
+
/* end_public_function */
|
|
38248
|
+
|
|
37942
38249
|
exports.API_REGIONS = API_REGIONS;
|
|
37943
38250
|
exports.AdRepository = index$6;
|
|
37944
38251
|
exports.AmityAttachmentProductTags = AmityAttachmentProductTags;
|
|
@@ -38005,6 +38312,8 @@ exports.getChannelTopic = getChannelTopic;
|
|
|
38005
38312
|
exports.getCommentTopic = getCommentTopic;
|
|
38006
38313
|
exports.getCommunityStoriesTopic = getCommunityStoriesTopic;
|
|
38007
38314
|
exports.getCommunityTopic = getCommunityTopic;
|
|
38315
|
+
exports.getContentFlagReasonKey = getContentFlagReasonKey;
|
|
38316
|
+
exports.getContentFlagReasons = getContentFlagReasons;
|
|
38008
38317
|
exports.getLiveReactionTopic = getLiveReactionTopic;
|
|
38009
38318
|
exports.getLiveStreamTopic = getLiveStreamTopic;
|
|
38010
38319
|
exports.getMarkedMessageTopic = getMarkedMessageTopic;
|