That fuck shit the fascists are using
at master 169 lines 6.2 kB view raw
1package org.tm.archive.delete; 2 3import android.text.TextUtils; 4 5import androidx.annotation.NonNull; 6import androidx.annotation.Nullable; 7import androidx.lifecycle.LiveData; 8import androidx.lifecycle.MutableLiveData; 9import androidx.lifecycle.Transformations; 10import androidx.lifecycle.ViewModel; 11import androidx.lifecycle.ViewModelProvider; 12 13import com.annimon.stream.Stream; 14import com.google.i18n.phonenumbers.NumberParseException; 15import com.google.i18n.phonenumbers.PhoneNumberUtil; 16import com.google.i18n.phonenumbers.Phonenumber; 17 18import org.tm.archive.keyvalue.SignalStore; 19import org.tm.archive.payments.Balance; 20import org.tm.archive.recipients.Recipient; 21import org.tm.archive.util.DefaultValueLiveData; 22import org.tm.archive.util.SingleLiveEvent; 23import org.whispersystems.signalservice.api.payments.FormatterOptions; 24import org.whispersystems.signalservice.api.payments.Money; 25 26import java.util.List; 27import java.util.Optional; 28 29public class DeleteAccountViewModel extends ViewModel { 30 31 private final DeleteAccountRepository repository; 32 private final List<Country> allCountries; 33 private final LiveData<List<Country>> filteredCountries; 34 private final MutableLiveData<String> regionCode; 35 private final LiveData<String> countryDisplayName; 36 private final MutableLiveData<Long> nationalNumber; 37 private final MutableLiveData<String> query; 38 private final SingleLiveEvent<DeleteAccountEvent> events; 39 private final LiveData<Optional<String>> walletBalance; 40 41 public DeleteAccountViewModel(@NonNull DeleteAccountRepository repository) { 42 this.repository = repository; 43 this.allCountries = repository.getAllCountries(); 44 this.regionCode = new DefaultValueLiveData<>("ZZ"); // PhoneNumberUtil private static final String UNKNOWN_REGION = "ZZ"; 45 this.nationalNumber = new MutableLiveData<>(); 46 this.query = new DefaultValueLiveData<>(""); 47 this.countryDisplayName = Transformations.map(regionCode, repository::getRegionDisplayName); 48 this.filteredCountries = Transformations.map(query, q -> Stream.of(allCountries).filter(country -> isMatch(q, country)).toList()); 49 this.events = new SingleLiveEvent<>(); 50 this.walletBalance = Transformations.map(SignalStore.paymentsValues().liveMobileCoinBalance(), 51 DeleteAccountViewModel::getFormattedWalletBalance); 52 } 53 54 @NonNull LiveData<Optional<String>> getWalletBalance() { 55 return walletBalance; 56 } 57 58 @NonNull LiveData<List<Country>> getFilteredCountries() { 59 return filteredCountries; 60 } 61 62 @NonNull LiveData<String> getCountryDisplayName() { 63 return Transformations.distinctUntilChanged(countryDisplayName); 64 } 65 66 @NonNull LiveData<String> getRegionCode() { 67 return Transformations.distinctUntilChanged(regionCode); 68 } 69 70 @NonNull SingleLiveEvent<DeleteAccountEvent> getEvents() { 71 return events; 72 } 73 74 @Nullable Long getNationalNumber() { 75 return nationalNumber.getValue(); 76 } 77 78 void onQueryChanged(@NonNull String query) { 79 this.query.setValue(query.toLowerCase()); 80 } 81 82 void deleteAccount() { 83 repository.deleteAccount(events::postValue); 84 } 85 86 void submit() { 87 String region = this.regionCode.getValue(); 88 Integer countryCode = region != null ? repository.getRegionCountryCode(region) : null; 89 Long nationalNumber = this.nationalNumber.getValue(); 90 91 if (countryCode == null || countryCode == 0) { 92 events.setValue(DeleteAccountEvent.NoCountryCode.INSTANCE); 93 return; 94 } 95 96 if (nationalNumber == null) { 97 events.setValue(DeleteAccountEvent.NoNationalNumber.INSTANCE); 98 return; 99 } 100 101 Phonenumber.PhoneNumber number = new Phonenumber.PhoneNumber(); 102 number.setCountryCode(countryCode); 103 number.setNationalNumber(nationalNumber); 104 105 if (PhoneNumberUtil.getInstance().isNumberMatch(number, Recipient.self().requireE164()) == PhoneNumberUtil.MatchType.EXACT_MATCH) { 106 events.setValue(DeleteAccountEvent.ConfirmDeletion.INSTANCE); 107 } else { 108 events.setValue(DeleteAccountEvent.NotAMatch.INSTANCE); 109 } 110 } 111 112 void onCountrySelected(int countryCode) { 113 String region = this.regionCode.getValue(); 114 List<String> regions = PhoneNumberUtil.getInstance().getRegionCodesForCountryCode(countryCode); 115 116 if (!regions.contains(region)) { 117 this.regionCode.setValue(PhoneNumberUtil.getInstance().getRegionCodeForCountryCode(countryCode)); 118 } 119 } 120 121 void onRegionSelected(@NonNull String region) { 122 this.regionCode.setValue(region); 123 } 124 125 void setNationalNumber(long nationalNumber) { 126 this.nationalNumber.setValue(nationalNumber); 127 128 try { 129 String phoneNumberRegion = PhoneNumberUtil.getInstance() 130 .getRegionCodeForNumber(PhoneNumberUtil.getInstance().parse(String.valueOf(nationalNumber), 131 regionCode.getValue())); 132 if (phoneNumberRegion != null) { 133 regionCode.setValue(phoneNumberRegion); 134 } 135 } catch (NumberParseException ignored) { 136 } 137 } 138 139 private static @NonNull Optional<String> getFormattedWalletBalance(@NonNull Balance balance) { 140 Money amount = balance.getFullAmount(); 141 if (amount.isPositive()) { 142 return Optional.of(amount.toString(FormatterOptions.defaults())); 143 } else { 144 return Optional.empty(); 145 } 146 } 147 148 private static boolean isMatch(@NonNull String query, @NonNull Country country) { 149 if (TextUtils.isEmpty(query)) { 150 return true; 151 } else { 152 return country.getNormalizedDisplayName().contains(query.toLowerCase()); 153 } 154 } 155 156 public static final class Factory implements ViewModelProvider.Factory { 157 158 private final DeleteAccountRepository repository; 159 160 public Factory(DeleteAccountRepository repository) { 161 this.repository = repository; 162 } 163 164 @Override 165 public @NonNull <T extends ViewModel> T create(@NonNull Class<T> modelClass) { 166 return modelClass.cast(new DeleteAccountViewModel(repository)); 167 } 168 } 169}