That fuck shit the fascists are using
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}