That fuck shit the fascists are using
1package org.tm.archive.conversation;
2
3import androidx.annotation.NonNull;
4import androidx.lifecycle.LiveData;
5import androidx.lifecycle.MutableLiveData;
6import androidx.lifecycle.ViewModel;
7import androidx.lifecycle.ViewModelProvider;
8
9import org.signal.core.util.ThreadUtil;
10import org.tm.archive.search.MessageResult;
11import org.tm.archive.search.SearchRepository;
12import org.tm.archive.util.Debouncer;
13
14import java.util.Collections;
15import java.util.List;
16
17public class ConversationSearchViewModel extends ViewModel {
18
19 private final SearchRepository searchRepository;
20 private final MutableLiveData<SearchResult> result;
21 private final Debouncer debouncer;
22
23 private boolean firstSearch;
24 private boolean searchOpen;
25 private String activeQuery;
26 private long activeThreadId;
27
28 public ConversationSearchViewModel(@NonNull String noteToSelfTitle) {
29 result = new MutableLiveData<>();
30 debouncer = new Debouncer(500);
31 searchRepository = new SearchRepository(noteToSelfTitle);
32 }
33
34 public @NonNull LiveData<SearchResult> getSearchResults() {
35 return result;
36 }
37
38 public void onQueryUpdated(@NonNull String query, long threadId, boolean forced) {
39 if (firstSearch && query.length() < 2) {
40 result.postValue(new SearchResult(Collections.emptyList(), 0));
41 return;
42 }
43
44 if (query.equals(activeQuery) && !forced) {
45 return;
46 }
47
48 updateQuery(query, threadId);
49 }
50
51 public void onMissingResult() {
52 if (activeQuery != null) {
53 updateQuery(activeQuery, activeThreadId);
54 }
55 }
56
57 public void onMoveUp() {
58 if (result.getValue() == null) {
59 return;
60 }
61
62 debouncer.clear();
63
64 List<MessageResult> messages = result.getValue().getResults();
65 int position = Math.min(result.getValue().getPosition() + 1, messages.size() - 1);
66
67 result.setValue(new SearchResult(messages, position));
68 }
69
70 public void onMoveDown() {
71 if (result.getValue() == null) {
72 return;
73 }
74
75 debouncer.clear();
76
77 List<MessageResult> messages = result.getValue().getResults();
78 int position = Math.max(result.getValue().getPosition() - 1, 0);
79
80 result.setValue(new SearchResult(messages, position));
81 }
82
83
84 public void onSearchOpened() {
85 searchOpen = true;
86 firstSearch = true;
87 }
88
89 public void onSearchClosed() {
90 searchOpen = false;
91 debouncer.clear();
92 }
93
94 private void updateQuery(@NonNull String query, long threadId) {
95 activeQuery = query;
96 activeThreadId = threadId;
97
98 debouncer.publish(() -> {
99 firstSearch = false;
100
101 searchRepository.query(query, threadId, messages -> {
102 ThreadUtil.runOnMain(() -> {
103 if (searchOpen && query.equals(activeQuery)) {
104 result.setValue(new SearchResult(messages, 0));
105 }
106 });
107 });
108 });
109 }
110
111 public static class SearchResult {
112
113 private final List<MessageResult> results;
114 private final int position;
115
116 SearchResult(@NonNull List<MessageResult> results, int position) {
117 this.results = results;
118 this.position = position;
119 }
120
121 public List<MessageResult> getResults() {
122 return results;
123 }
124
125 public int getPosition() {
126 return position;
127 }
128 }
129
130 public static class Factory extends ViewModelProvider.NewInstanceFactory {
131
132 private final String noteToSelfTitle;
133
134 public Factory(@NonNull String noteToSelfTitle) {
135 this.noteToSelfTitle = noteToSelfTitle;
136 }
137
138 @Override
139 public @NonNull <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
140 //noinspection ConstantConditions
141 return modelClass.cast(new ConversationSearchViewModel(noteToSelfTitle));
142 }
143 }
144}