Skip to content

Commit 1d72bd3

Browse files
committed
feat: add debug option to test messageInfo pro features
1 parent 3e6fb35 commit 1d72bd3

File tree

24 files changed

+171
-130
lines changed

24 files changed

+171
-130
lines changed

preload.js

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,16 @@ window.sessionFeatureFlags = {
6868
proAvailable: !isEmpty(process.env.SESSION_PRO),
6969
mockCurrentUserHasPro: !isEmpty(process.env.SESSION_USER_HAS_PRO),
7070
mockOthersHavePro: !isEmpty(process.env.SESSION_OTHERS_HAVE_PRO),
71+
mockMessageProFeatures: [],
7172
// Note: some stuff are init when the app starts, so fsTTL30s should only be set from the env itself (before app starts)
7273
fsTTL30s: !isEmpty(process.env.FILE_SERVER_TTL_30S),
73-
debug: {
74-
debugLogging: !isEmpty(process.env.SESSION_DEBUG),
75-
debugLibsessionDumps: !isEmpty(process.env.SESSION_DEBUG_LIBSESSION_DUMPS),
76-
debugBuiltSnodeRequests: !isEmpty(process.env.SESSION_DEBUG_BUILT_SNODE_REQUEST),
77-
debugSwarmPolling: !isEmpty(process.env.SESSION_DEBUG_SWARM_POLLING),
78-
debugServerRequests: false,
79-
debugNonSnodeRequests: false,
80-
debugOnionRequests: false,
81-
},
74+
debugLogging: !isEmpty(process.env.SESSION_DEBUG),
75+
debugLibsessionDumps: !isEmpty(process.env.SESSION_DEBUG_LIBSESSION_DUMPS),
76+
debugBuiltSnodeRequests: !isEmpty(process.env.SESSION_DEBUG_BUILT_SNODE_REQUEST),
77+
debugSwarmPolling: !isEmpty(process.env.SESSION_DEBUG_SWARM_POLLING),
78+
debugServerRequests: false,
79+
debugNonSnodeRequests: false,
80+
debugOnionRequests: false,
8281
};
8382

8483
window.versionInfo = {

ts/components/conversation/right-panel/overlay/message-info/components/MessageInfo.tsx

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
useMessageReceivedAt,
1111
useMessageSender,
1212
useMessageSenderIsAdmin,
13-
useMessageSentWithProFeat,
13+
useMessageSentWithProFeatures,
1414
useMessageServerId,
1515
useMessageServerTimestamp,
1616
useMessageTimestamp,
@@ -34,13 +34,11 @@ import { tr } from '../../../../../../localization/localeTools';
3434
import { Localizer } from '../../../../../basic/Localizer';
3535
import { LucideIcon } from '../../../../../icon/LucideIcon';
3636
import { LUCIDE_ICONS_UNICODE } from '../../../../../icon/lucide';
37-
import {
38-
ProFeatures,
39-
useProBadgeOnClickCb,
40-
} from '../../../../../menuAndSettingsHooks/useProBadgeOnClickCb';
37+
import { useProBadgeOnClickCb } from '../../../../../menuAndSettingsHooks/useProBadgeOnClickCb';
4138
import { useCurrentUserHasPro } from '../../../../../../hooks/useHasPro';
4239
import { ProIconButton } from '../../../../../buttons/ProButton';
4340
import { assertUnreachable } from '../../../../../../types/sqlSharedTypes';
41+
import { ProMessageFeature } from '../../../../../../models/proMessageFeature';
4442

4543
export const MessageInfoLabel = styled.label<{ color?: string }>`
4644
font-size: var(--font-size-lg);
@@ -159,13 +157,13 @@ const StyledProFeaturesContainer = styled.div`
159157
gap: var(--margins-xs);
160158
`;
161159

162-
function proFeatureToTrKey(proFeature: ProFeatures) {
160+
function proFeatureToTrKey(proFeature: ProMessageFeature) {
163161
switch (proFeature) {
164-
case ProFeatures.PRO_BADGE:
162+
case ProMessageFeature.PRO_BADGE:
165163
return 'proBadge' as const;
166-
case ProFeatures.PRO_INCREASED_MESSAGE_LENGTH:
164+
case ProMessageFeature.PRO_INCREASED_MESSAGE_LENGTH:
167165
return 'proIncreasedMessageLengthFeature' as const;
168-
case ProFeatures.PRO_ANIMATED_DISPLAY_PICTURE:
166+
case ProMessageFeature.PRO_ANIMATED_DISPLAY_PICTURE:
169167
return 'proAnimatedDisplayPictureFeature' as const;
170168
default:
171169
assertUnreachable(proFeature, 'ProFeatureToTrKey: unknown case');
@@ -176,7 +174,7 @@ function proFeatureToTrKey(proFeature: ProFeatures) {
176174
function ProMessageFeaturesDetails({ messageId }: { messageId: string }) {
177175
const currentUserHasPro = useCurrentUserHasPro();
178176

179-
const messageSentWithProFeat = useMessageSentWithProFeat(messageId);
177+
const messageSentWithProFeat = useMessageSentWithProFeatures(messageId);
180178

181179
const showPro = useProBadgeOnClickCb({
182180
context: 'message-info-sent-with-pro',

ts/components/dialog/debug/FeatureFlags.tsx

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
import { isBoolean } from 'lodash';
1+
import { isArray, isBoolean } from 'lodash';
22
import type { SessionFlagsKeys } from '../../../state/ducks/types/releasedFeaturesReduxTypes';
33
import { Flex } from '../../basic/Flex';
44
import { SessionToggle } from '../../basic/SessionToggle';
55
import { HintText, SpacerSM, SpacerXS } from '../../basic/Text';
66
import { DEBUG_FEATURE_FLAGS } from './constants';
77
import { ConvoHub } from '../../../session/conversations';
88
import { isDebugMode } from '../../../shared/env_vars';
9+
import { ProMessageFeature } from '../../../models/proMessageFeature';
910

1011
type FeatureFlagToggleType = {
1112
forceUpdate: () => void;
@@ -104,25 +105,48 @@ export const FeatureFlags = ({
104105
return null;
105106
}
106107

107-
if (!isBoolean(value)) {
108+
if (isBoolean(value)) {
109+
return <FlagToggle forceUpdate={forceUpdate} flag={flag} value={value} />;
110+
}
111+
if (isArray(value) && flag === 'mockMessageProFeatures') {
112+
const rotateMsgProFeat = () => {
113+
if (value.length === 0) {
114+
window.sessionFeatureFlags.mockMessageProFeatures = [ProMessageFeature.PRO_BADGE];
115+
} else if (value.length === 1) {
116+
if (value[0] === ProMessageFeature.PRO_BADGE) {
117+
window.sessionFeatureFlags.mockMessageProFeatures = [
118+
ProMessageFeature.PRO_ANIMATED_DISPLAY_PICTURE,
119+
];
120+
} else if (value[0] === ProMessageFeature.PRO_ANIMATED_DISPLAY_PICTURE) {
121+
window.sessionFeatureFlags.mockMessageProFeatures = [
122+
ProMessageFeature.PRO_INCREASED_MESSAGE_LENGTH,
123+
];
124+
} else if (value[0] === ProMessageFeature.PRO_INCREASED_MESSAGE_LENGTH) {
125+
window.sessionFeatureFlags.mockMessageProFeatures = [
126+
ProMessageFeature.PRO_BADGE,
127+
ProMessageFeature.PRO_ANIMATED_DISPLAY_PICTURE,
128+
ProMessageFeature.PRO_INCREASED_MESSAGE_LENGTH,
129+
];
130+
}
131+
} else if (value.length === 3) {
132+
window.sessionFeatureFlags.mockMessageProFeatures = [];
133+
}
134+
forceUpdate();
135+
};
108136
return (
109-
<>
110-
<h3>{flag}</h3>
111-
{Object.entries(value).map(([k, v]: [string, FlagValues]) => {
112-
const nestedFlag = k as SessionFlagsKeys;
113-
return (
114-
<FlagToggle
115-
flag={nestedFlag}
116-
value={v}
117-
parentFlag={flag}
118-
forceUpdate={forceUpdate}
119-
/>
120-
);
121-
})}
122-
</>
137+
<Flex
138+
$container={true}
139+
$alignItems="center"
140+
$flexDirection="row"
141+
style={{ cursor: 'pointer', gap: 'var(--margins-xs)' }}
142+
onClick={rotateMsgProFeat}
143+
>
144+
<div>{flag}</div>
145+
<pre style={{ overflow: 'hidden' }}>{JSON.stringify(value)}</pre>
146+
</Flex>
123147
);
124148
}
125-
return <FlagToggle forceUpdate={forceUpdate} flag={flag} value={value} />;
149+
throw new Error('Feature flag is not a boolean or array');
126150
})}
127151
<SpacerSM />
128152
</Flex>

ts/components/menuAndSettingsHooks/useProBadgeOnClickCb.tsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useIsProAvailable } from '../../hooks/useIsProAvailable';
2+
import { ProMessageFeature } from '../../models/proMessageFeature';
23
import { assertUnreachable } from '../../types/sqlSharedTypes';
34
import type { ContactNameContext } from '../conversation/ContactName/ContactNameContext';
45
import {
@@ -7,7 +8,7 @@ import {
78
} from '../dialog/SessionProInfoModal';
89

910
type WithUserHasPro = { userHasPro: boolean };
10-
type WithMessageSentWithProFeat = { messageSentWithProFeat: Array<ProFeatures> | null };
11+
type WithMessageSentWithProFeat = { messageSentWithProFeat: Array<ProMessageFeature> | null };
1112
type WithCurrentUserHasPro = { currentUserHasPro: boolean };
1213

1314
type WithIsMe = { isMe: boolean };
@@ -61,18 +62,12 @@ const contactNameContextNoShow: Array<ContactNameContext> = [
6162
'message-search-result',
6263
];
6364

64-
export enum ProFeatures {
65-
PRO_BADGE = 'pro-badge',
66-
PRO_INCREASED_MESSAGE_LENGTH = 'pro-increased-message-length',
67-
PRO_ANIMATED_DISPLAY_PICTURE = 'pro-animated-display-picture',
68-
}
69-
70-
function proFeatureToVariant(proFeature: ProFeatures): SessionProInfoVariant {
65+
function proFeatureToVariant(proFeature: ProMessageFeature): SessionProInfoVariant {
7166
switch (proFeature) {
72-
case ProFeatures.PRO_INCREASED_MESSAGE_LENGTH:
67+
case ProMessageFeature.PRO_INCREASED_MESSAGE_LENGTH:
7368
return SessionProInfoVariant.MESSAGE_CHARACTER_LIMIT;
74-
case ProFeatures.PRO_BADGE:
75-
case ProFeatures.PRO_ANIMATED_DISPLAY_PICTURE:
69+
case ProMessageFeature.PRO_BADGE:
70+
case ProMessageFeature.PRO_ANIMATED_DISPLAY_PICTURE:
7671
return SessionProInfoVariant.GENERIC;
7772
default:
7873
assertUnreachable(proFeature, 'ProFeatureToVariant: unknown case');

ts/models/message.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ import { Model } from './models';
9696
import { ReduxOnionSelectors } from '../state/selectors/onions';
9797
import { tStrippedWithObj, tr, tStripped } from '../localization/localeTools';
9898
import type { QuotedAttachmentType } from '../components/conversation/message/message-content/quote/Quote';
99+
import { isProMessageFeature, ProMessageFeature } from './proMessageFeature';
99100

100101
// tslint:disable: cyclomatic-complexity
101102

@@ -600,6 +601,7 @@ export class MessageModel extends Model<MessageAttributes> {
600601

601602
const attachments = this.get('attachments') || [];
602603
const isTrustedForAttachmentDownload = this.isTrustedForAttachmentDownload();
604+
const proFeatures = this.getProFeatures();
603605
const body = this.get('body');
604606
const props: PropsForMessageWithoutConvoProps = {
605607
id: this.id,
@@ -639,6 +641,9 @@ export class MessageModel extends Model<MessageAttributes> {
639641
if (isTrustedForAttachmentDownload) {
640642
props.isTrustedForAttachmentDownload = isTrustedForAttachmentDownload;
641643
}
644+
if (proFeatures.length) {
645+
props.proFeatures = proFeatures;
646+
}
642647
const isUnread = this.isUnread();
643648
if (isUnread) {
644649
props.isUnread = isUnread;
@@ -1249,6 +1254,16 @@ export class MessageModel extends Model<MessageAttributes> {
12491254
}
12501255
}
12511256

1257+
private getProFeatures(): Array<ProMessageFeature> {
1258+
const proFeatures = this.get('proFeatures');
1259+
1260+
if (!proFeatures?.length) {
1261+
return [];
1262+
}
1263+
1264+
return proFeatures.filter(isProMessageFeature);
1265+
}
1266+
12521267
private dispatchMessageUpdate() {
12531268
updatesToDispatch.set(this.id, this.getMessageModelProps());
12541269
throttledAllMessagesDispatch();

ts/models/messageType.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
InteractionNotificationType,
1616
} from '../state/ducks/types';
1717
import type { SignalService } from '../protobuf';
18+
import type { ProMessageFeature } from './proMessageFeature';
1819

1920
export type MessageModelType = 'incoming' | 'outgoing';
2021

@@ -102,12 +103,17 @@ type SharedMessageAttributes = {
102103
interactionNotification?: InteractionNotificationType;
103104
};
104105

106+
/**
107+
* Attributes that can be optional or not depending on if the message was already constructed or not.
108+
*/
105109
type NotSharedMessageAttributes = {
106110
/**
107-
* The local if of this message (i.e. an id only used locally).
111+
* The local id of this message (i.e. an id only used locally).
108112
* Added on commit() if unset before that
109113
*/
110114
id: string;
115+
direction: MessageModelType;
116+
111117
/** in seconds, 0 means no expiration */
112118
expireTimer: number;
113119
/** when the expireTimer above started to count, in milliseconds */
@@ -138,7 +144,8 @@ type NotSharedMessageAttributes = {
138144
*/
139145
synced: boolean;
140146
sync: boolean;
141-
direction: MessageModelType;
147+
148+
proFeatures?: Array<ProMessageFeature>;
142149
};
143150

144151
export type MessageAttributes = SharedMessageAttributes & NotSharedMessageAttributes;

ts/models/proMessageFeature.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* An enum of the pro features that a message can have.
3+
*/
4+
export enum ProMessageFeature {
5+
PRO_BADGE = 'pro-badge',
6+
PRO_INCREASED_MESSAGE_LENGTH = 'pro-increased-message-length',
7+
PRO_ANIMATED_DISPLAY_PICTURE = 'pro-animated-display-picture',
8+
}
9+
10+
const proFeatureValues = Object.values(ProMessageFeature);
11+
12+
export function isProMessageFeature(feature: string): feature is ProMessageFeature {
13+
return proFeatureValues.includes(feature as ProMessageFeature);
14+
}

ts/receiver/configMessage.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ async function mergeUserConfigsWithIncomingUpdates(
123123

124124
const variant = LibSessionUtil.userNamespaceToVariant(namespace);
125125

126-
if (window.sessionFeatureFlags.debug.debugLibsessionDumps) {
126+
if (window.sessionFeatureFlags.debugLibsessionDumps) {
127127
await printDumpForDebug(
128128
`printDumpsForDebugging: before merge of ${toMerge.length}, ${variant}:`,
129129
variant
@@ -142,7 +142,7 @@ async function mergeUserConfigsWithIncomingUpdates(
142142
`${variant}: needsPush:${needsPush} needsDump:${needsDump}; mergedCount:${hashesMerged.length} `
143143
);
144144

145-
if (window.sessionFeatureFlags.debug.debugLibsessionDumps) {
145+
if (window.sessionFeatureFlags.debugLibsessionDumps) {
146146
await printDumpForDebug(`printDumpsForDebugging: after merge of ${variant}:`, variant);
147147
}
148148
const incomingConfResult: IncomingUserResult = {

ts/session/apis/file_server_api/FileServerApi.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export const downloadFileFromFileServer = async (
108108
}
109109

110110
const urlToGet = `${POST_GET_FILE_ENDPOINT}/${fileId}`;
111-
if (window.sessionFeatureFlags?.debug.debugServerRequests) {
111+
if (window.sessionFeatureFlags?.debugServerRequests) {
112112
window.log.info(`about to try to download fsv2: "${urlToGet}"`);
113113
}
114114

@@ -120,7 +120,7 @@ export const downloadFileFromFileServer = async (
120120
throwError: true,
121121
timeoutMs: 30 * DURATION.SECONDS, // longer time for file download
122122
});
123-
if (window.sessionFeatureFlags?.debug.debugServerRequests) {
123+
if (window.sessionFeatureFlags?.debugServerRequests) {
124124
window.log.info(`download fsv2: "${urlToGet} got result:`, JSON.stringify(result));
125125
}
126126
if (!result) {

ts/session/apis/network_api/NetworkApi.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export default class NetworkApi {
103103
}
104104

105105
private async makeRequest(request: Awaited<ReturnType<typeof this.getRequestParams>>) {
106-
if (window.sessionFeatureFlags?.debug.debugServerRequests) {
106+
if (window.sessionFeatureFlags?.debugServerRequests) {
107107
window.log.info(`[network api] ${request.endpoint}\nrequest:`, JSON.stringify(request));
108108
}
109109
const controller = new AbortController();
@@ -115,7 +115,7 @@ export default class NetworkApi {
115115

116116
const response = this.handleOnionResponse(result, request.endpoint);
117117

118-
if (window.sessionFeatureFlags?.debug.debugServerRequests) {
118+
if (window.sessionFeatureFlags?.debugServerRequests) {
119119
window.log.info(`[network api] ${request.endpoint}\nresponse:`, JSON.stringify(response));
120120
}
121121

@@ -134,7 +134,7 @@ export default class NetworkApi {
134134
};
135135

136136
if (!batchGlobalIsSuccess(result) || !result?.body) {
137-
if (window.sessionFeatureFlags?.debug.debugServerRequests) {
137+
if (window.sessionFeatureFlags?.debugServerRequests) {
138138
window.log.error(
139139
`[network api] ${endpoint}: failed with status ${parseBatchGlobalStatusCode(result)} ${JSON.stringify(result)} `
140140
);
@@ -154,7 +154,7 @@ export default class NetworkApi {
154154
// #region API calls
155155

156156
async getValidateHeaders(): Promise<ValidateHeaderResponse> {
157-
if (window.sessionFeatureFlags?.debug.debugServerRequests) {
157+
if (window.sessionFeatureFlags?.debugServerRequests) {
158158
window.log.info('[network api] /validate/headers: about to try to validate headers');
159159
}
160160

@@ -168,7 +168,7 @@ export default class NetworkApi {
168168
}
169169

170170
async getInfo(): Promise<InfoResponse | null> {
171-
if (window.sessionFeatureFlags?.debug.debugServerRequests) {
171+
if (window.sessionFeatureFlags?.debugServerRequests) {
172172
window.log.info(`[network api] /info: about to try to get info`);
173173
}
174174

0 commit comments

Comments
 (0)