You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			127 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			127 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			TypeScript
		
	
| import { GetNetworkTime } from '../session/apis/snode_api/getNetworkTime';
 | |
| import { FEATURE_RELEASE_TIMESTAMPS } from '../session/constants';
 | |
| import { ConfigurationSync } from '../session/utils/job_runners/jobs/ConfigurationSyncJob';
 | |
| import { assertUnreachable } from '../types/sqlSharedTypes';
 | |
| import { Storage } from './storage';
 | |
| 
 | |
| let isDisappearingMessageFeatureReleased: boolean | undefined;
 | |
| let isUserConfigLibsessionFeatureReleased: boolean | undefined;
 | |
| // TODO DO NOT MERGE Remove export after QA
 | |
| export type FeatureNameTracked = 'disappearing_messages' | 'user_config_libsession';
 | |
| 
 | |
| /**
 | |
|  * This is only intended for testing. Do not call this in production.
 | |
|  */
 | |
| export function resetFeatureReleasedCachedValue() {
 | |
|   isDisappearingMessageFeatureReleased = undefined;
 | |
|   isUserConfigLibsessionFeatureReleased = undefined;
 | |
| }
 | |
| 
 | |
| // eslint-disable-next-line consistent-return
 | |
| function getIsFeatureReleasedCached(featureName: FeatureNameTracked) {
 | |
|   switch (featureName) {
 | |
|     case 'disappearing_messages':
 | |
|       return isDisappearingMessageFeatureReleased;
 | |
|     case 'user_config_libsession':
 | |
|       return isUserConfigLibsessionFeatureReleased;
 | |
|     default:
 | |
|       assertUnreachable(featureName, 'case not handled for getIsFeatureReleasedCached');
 | |
|   }
 | |
| }
 | |
| 
 | |
| function setIsFeatureReleasedCached(featureName: FeatureNameTracked, value: boolean) {
 | |
|   switch (featureName) {
 | |
|     case 'disappearing_messages':
 | |
|       isDisappearingMessageFeatureReleased = value;
 | |
|       break;
 | |
|     case 'user_config_libsession':
 | |
|       isUserConfigLibsessionFeatureReleased = value;
 | |
|       break;
 | |
|     default:
 | |
|       assertUnreachable(featureName, 'case not handled for setIsFeatureReleasedCached');
 | |
|   }
 | |
| }
 | |
| 
 | |
| // eslint-disable-next-line consistent-return
 | |
| function getFeatureReleaseTimestamp(featureName: FeatureNameTracked) {
 | |
|   switch (featureName) {
 | |
|     case 'disappearing_messages':
 | |
|       return FEATURE_RELEASE_TIMESTAMPS.DISAPPEARING_MESSAGES_V2;
 | |
|     case 'user_config_libsession':
 | |
|       return FEATURE_RELEASE_TIMESTAMPS.USER_CONFIG;
 | |
|     default:
 | |
|       assertUnreachable(featureName, 'case not handled for getFeatureReleaseTimestamp');
 | |
|   }
 | |
| }
 | |
| 
 | |
| function featureStorageItemId(featureName: FeatureNameTracked) {
 | |
|   return `featureReleased-${featureName}`;
 | |
| }
 | |
| 
 | |
| export async function getIsFeatureReleased(featureName: FeatureNameTracked): Promise<boolean> {
 | |
|   if (getIsFeatureReleasedCached(featureName) === undefined) {
 | |
|     // read values from db and cache them as it looks like we did not
 | |
|     const oldIsFeatureReleased = Boolean(Storage.get(featureStorageItemId(featureName)));
 | |
|     // values do not exist in the db yet. Let's store false for now in the db and update our cached value.
 | |
|     if (oldIsFeatureReleased === undefined) {
 | |
|       await Storage.put(featureStorageItemId(featureName), false);
 | |
|       setIsFeatureReleasedCached(featureName, false);
 | |
|     } else {
 | |
|       setIsFeatureReleasedCached(featureName, oldIsFeatureReleased);
 | |
|     }
 | |
|   }
 | |
|   return Boolean(getIsFeatureReleasedCached(featureName));
 | |
| }
 | |
| 
 | |
| async function checkIsFeatureReleased(featureName: FeatureNameTracked): Promise<boolean> {
 | |
|   const featureAlreadyReleased = await getIsFeatureReleased(featureName);
 | |
| 
 | |
|   // Is it time to release the feature based on the network timestamp?
 | |
|   if (
 | |
|     !featureAlreadyReleased &&
 | |
|     GetNetworkTime.getNowWithNetworkOffset() >= getFeatureReleaseTimestamp(featureName)
 | |
|   ) {
 | |
|     window.log.info(`[releaseFeature]: It is time to release ${featureName}. Releasing it now`);
 | |
|     await Storage.put(featureStorageItemId(featureName), true);
 | |
|     setIsFeatureReleasedCached(featureName, true);
 | |
|     // trigger a sync right away so our user data is online
 | |
|     await ConfigurationSync.queueNewJobIfNeeded();
 | |
|   }
 | |
| 
 | |
|   const isReleased = Boolean(getIsFeatureReleasedCached(featureName));
 | |
|   // window.log.debug(
 | |
|   //   `[releaseFeature]: "${featureName}" ${isReleased ? 'is released' : 'has not been released yet'}`
 | |
|   // );
 | |
|   return isReleased;
 | |
| }
 | |
| 
 | |
| async function checkIsUserConfigFeatureReleased() {
 | |
|   return checkIsFeatureReleased('user_config_libsession');
 | |
| }
 | |
| 
 | |
| async function checkIsDisappearMessageV2FeatureReleased() {
 | |
|   return (
 | |
|     (await checkIsFeatureReleased('disappearing_messages')) ||
 | |
|     !!process.env.MULTI?.toLocaleLowerCase().includes('disappear_v2')
 | |
|   ); // FIXME to remove after QA
 | |
| }
 | |
| 
 | |
| function isUserConfigFeatureReleasedCached(): boolean {
 | |
|   return !!isUserConfigLibsessionFeatureReleased;
 | |
| }
 | |
| 
 | |
| // NOTE Make sure to call checkIsDisappearMessageV2FeatureReleased at least once and then use this. It's mostly used in components that are rendered where we don't want to do async calls
 | |
| function isDisappearMessageV2FeatureReleasedCached(): boolean {
 | |
|   return (
 | |
|     !!isDisappearingMessageFeatureReleased ||
 | |
|     !!process.env.MULTI?.toLocaleLowerCase().includes('disappear_v2') // FIXME to remove after QA
 | |
|   );
 | |
| }
 | |
| 
 | |
| export const ReleasedFeatures = {
 | |
|   checkIsUserConfigFeatureReleased,
 | |
|   checkIsDisappearMessageV2FeatureReleased,
 | |
|   isUserConfigFeatureReleasedCached,
 | |
|   isDisappearMessageV2FeatureReleasedCached,
 | |
| };
 |