import { Data } from '../data/data' ;
import { commitConversationAndRefreshWrapper } from '../models/conversation' ;
import { PubKey } from '../session/types' ;
import { Storage } from './storage' ;
const BLOCKED_NUMBERS_ID = 'blocked' ;
export class BlockedNumberController {
private static loaded : boolean = false ;
private static blockedNumbers : Set < string > = new Set ( ) ;
/ * *
* Check if a device is blocked synchronously .
* This will only check against the memory cache on if a device is blocked , it is recommended to pass in the primary device pub key .
*
* Make sure ` load() ` has been called before this function so that the correct blocked state is returned .
*
* @param number The device .
* /
public static isBlocked ( device : string | PubKey ) : boolean {
// This function is not `async` because the old `isBlocked` function in js was also not async.
// To convert it means we'll have to re-wire all our UI components to work with async.
const stringValue = device instanceof PubKey ? device.key : device.toLowerCase ( ) ;
return this . blockedNumbers . has ( stringValue ) ;
}
/ * *
* Block a user or group , by pubkey
*
* @param user The user to block .
* /
public static async block ( user : string | PubKey ) : Promise < void > {
// The reason we add all linked device to block number set instead of checking if any device of a user is in the `isBlocked` function because
// `isBlocked` is used synchronously in the code. To check if any device is blocked needs it to be async, which would mean all calls to `isBlocked` will also need to be async and so on
// This is too much of a hassle at the moment as some UI code will have to be migrated to work with this async call.
await this . load ( ) ;
const toBlock = PubKey . cast ( user ) ;
if ( ! this . blockedNumbers . has ( toBlock . key ) ) {
this . blockedNumbers . add ( toBlock . key ) ;
await this . saveToDB ( BLOCKED_NUMBERS_ID , this . blockedNumbers ) ;
await commitConversationAndRefreshWrapper ( toBlock . key ) ;
}
}
/ * *
* Unblock all these users .
* This will only unblock the primary device of the user .
*
* @param user The user to unblock .
* /
public static async unblockAll ( users : Array < string > ) : Promise < void > {
await this . load ( ) ;
let changes = false ;
users . forEach ( user = > {
const toUnblock = PubKey . cast ( user ) ;
if ( this . blockedNumbers . has ( toUnblock . key ) ) {
this . blockedNumbers . delete ( toUnblock . key ) ;
changes = true ;
}
} ) ;
for ( let index = 0 ; index < users . length ; index ++ ) {
const user = users [ index ] ;
try {
// eslint-disable-next-line no-await-in-loop
await commitConversationAndRefreshWrapper ( user ) ;
} catch ( e ) {
window . log . warn (
'failed to SessionUtilContact.insertContactFromDBIntoWrapperAndRefresh with: ' ,
user
) ;
}
}
if ( changes ) {
await this . saveToDB ( BLOCKED_NUMBERS_ID , this . blockedNumbers ) ;
}
}
public static async setBlocked ( user : string | PubKey , blocked : boolean ) : Promise < void > {
if ( blocked ) {
return BlockedNumberController . block ( user ) ;
}
return BlockedNumberController . unblockAll ( [ PubKey . cast ( user ) . key ] ) ;
}
public static getBlockedNumbers ( ) : Array < string > {
return [ . . . this . blockedNumbers ] ;
}
// ---- DB
public static async load() {
if ( ! this . loaded ) {
this . blockedNumbers = await this . getNumbersFromDB ( BLOCKED_NUMBERS_ID ) ;
this . loaded = true ;
}
}
public static reset() {
this . loaded = false ;
this . blockedNumbers = new Set ( ) ;
}
private static async getNumbersFromDB ( id : string ) : Promise < Set < string > > {
const data = await Data . getItemById ( id ) ;
if ( ! data || ! data . value ) {
return new Set ( ) ;
}
return new Set ( data . value ) ;
}
private static async saveToDB ( id : string , numbers : Set < string > ) : Promise < void > {
await Storage . put ( id , [ . . . numbers ] ) ;
}
}