FreeRDP
Loading...
Searching...
No Matches
BookmarkViewModel.java
1/*
2 * ViewModel for BookmarkActivity — handles asynchronous data loading and saving, keeping database
3 * and file I/O off the main thread.
4 */
5
6package com.freerdp.freerdpcore.presentation;
7
8import android.app.Application;
9import android.content.SharedPreferences;
10import android.os.Bundle;
11import android.util.Log;
12
13import androidx.annotation.NonNull;
14import androidx.lifecycle.AndroidViewModel;
15import androidx.lifecycle.LiveData;
16import androidx.lifecycle.MutableLiveData;
17
18import com.freerdp.freerdpcore.data.AppDatabase;
19import com.freerdp.freerdpcore.data.HistoryDatabase;
20import com.freerdp.freerdpcore.domain.BookmarkBase;
21import com.freerdp.freerdpcore.domain.ConnectionReference;
22import com.freerdp.freerdpcore.services.ManualBookmarkGateway;
23import com.freerdp.freerdpcore.services.QuickConnectHistoryGateway;
24import com.freerdp.freerdpcore.utils.RDPFileParser;
25
26import java.io.File;
27import java.io.IOException;
28import java.util.concurrent.ExecutorService;
29import java.util.concurrent.Executors;
30
31public class BookmarkViewModel extends AndroidViewModel
32{
33 private static final String TAG = "BookmarkViewModel";
34
35 // LiveData for observing state changes from the Activity
36 private final MutableLiveData<BookmarkBase> bookmarkLiveData = new MutableLiveData<>();
37 private final MutableLiveData<Boolean> saveCompleteEvent = new MutableLiveData<>();
38
39 private boolean settingsChanged = false;
40 private boolean newBookmark = false;
41
42 // Single-thread executor handles Room DB and File parsing off the UI thread
43 private final ExecutorService executor = Executors.newSingleThreadExecutor();
44
45 private final ManualBookmarkGateway manualBookmarkGateway;
46 private final QuickConnectHistoryGateway quickConnectHistoryGateway;
47
48 public BookmarkViewModel(@NonNull Application application)
49 {
50 super(application);
51 manualBookmarkGateway =
52 new ManualBookmarkGateway(AppDatabase.getInstance(application).bookmarkDao());
53 quickConnectHistoryGateway =
54 new QuickConnectHistoryGateway(HistoryDatabase.getInstance(application).historyDao());
55 }
56
57 public LiveData<BookmarkBase> getBookmarkLiveData()
58 {
59 return bookmarkLiveData;
60 }
61
62 public LiveData<Boolean> getSaveCompleteEvent()
63 {
64 return saveCompleteEvent;
65 }
66
67 public BookmarkBase getBookmark()
68 {
69 return bookmarkLiveData.getValue();
70 }
71
72 public boolean isSettingsChanged()
73 {
74 return settingsChanged;
75 }
76
77 public void setSettingsChanged(boolean changed)
78 {
79 settingsChanged = changed;
80 }
81
82 public boolean isNewBookmark()
83 {
84 return newBookmark;
85 }
86
87 public void setNewBookmark(boolean isNew)
88 {
89 newBookmark = isNew;
90 }
91
92 // -------------------------------------------------------------------------
93 // Async Operations
94 // -------------------------------------------------------------------------
95
96 public void loadBookmark(Bundle bundle, SharedPreferences prefs)
97 {
98 if (bookmarkLiveData.getValue() != null)
99 return;
100
101 executor.execute(() -> {
102 BookmarkBase bookmark = null;
103 boolean isNew = false;
104
105 if (bundle != null && bundle.containsKey(BookmarkActivity.PARAM_CONNECTION_REFERENCE))
106 {
107 String refStr = bundle.getString(BookmarkActivity.PARAM_CONNECTION_REFERENCE);
108
109 if (ConnectionReference.isBookmarkReference(refStr))
110 {
111 bookmark =
112 manualBookmarkGateway.findById(ConnectionReference.getBookmarkId(refStr));
113 isNew = false;
114 }
115 else if (ConnectionReference.isHostnameReference(refStr))
116 {
117 bookmark = new BookmarkBase();
118 bookmark.setLabel(ConnectionReference.getHostname(refStr));
119 bookmark.setHostname(ConnectionReference.getHostname(refStr));
120 isNew = true;
121 }
122 else if (ConnectionReference.isFileReference(refStr))
123 {
124 String file = ConnectionReference.getFile(refStr);
125 bookmark = new BookmarkBase();
126 bookmark.setLabel(file);
127 try
128 {
129 RDPFileParser rdpFile = new RDPFileParser(file);
130 updateBookmarkFromFile(bookmark, rdpFile);
131 bookmark.setLabel(new File(file).getName());
132 isNew = true;
133 }
134 catch (IOException e)
135 {
136 Log.e(TAG, "Failed reading RDP file", e);
137 }
138 }
139 }
140
141 if (bookmark == null)
142 {
143 bookmark = new BookmarkBase();
144 }
145
146 this.newBookmark = isNew;
147 this.settingsChanged = false;
148
149 // Clear TEMP SharedPreferences and write fresh data BEFORE posting to UI
150 prefs.edit().clear().apply();
151 bookmark.writeToSharedPreferences(prefs);
152
153 // Notify Activity that loading is complete on the Main Thread
154 bookmarkLiveData.postValue(bookmark);
155 });
156 }
157
158 public void saveBookmark(SharedPreferences prefs)
159 {
160 BookmarkBase bookmark = getBookmark();
161 if (bookmark == null)
162 return;
163
164 executor.execute(() -> {
165 bookmark.readFromSharedPreferences(prefs);
166
167 if (bookmark.getType() == BookmarkBase.TYPE_MANUAL)
168 {
169 quickConnectHistoryGateway.removeHistoryItem(bookmark.getHostname());
170
171 if (bookmark.getId() > 0)
172 {
173 manualBookmarkGateway.update(bookmark);
174 }
175 else
176 {
177 manualBookmarkGateway.insert(bookmark);
178 }
179 }
180
181 // Notify Activity to close
182 saveCompleteEvent.postValue(true);
183 });
184 }
185
186 private void updateBookmarkFromFile(BookmarkBase bookmark, RDPFileParser rdpFile)
187 {
188 String s;
189 Integer i;
190
191 s = rdpFile.getString("full address");
192 if (s != null)
193 {
194 if (s.lastIndexOf(":") > s.lastIndexOf("]"))
195 {
196 try
197 {
198 bookmark.setPort(Integer.parseInt(s.substring(s.lastIndexOf(":") + 1)));
199 }
200 catch (NumberFormatException e)
201 {
202 Log.e(TAG, "Malformed address");
203 }
204 s = s.substring(0, s.lastIndexOf(":"));
205 }
206 if (s.startsWith("[") && s.endsWith("]"))
207 s = s.substring(1, s.length() - 1);
208 bookmark.setHostname(s);
209 }
210
211 i = rdpFile.getInteger("server port");
212 if (i != null)
213 bookmark.setPort(i);
214
215 s = rdpFile.getString("username");
216 if (s != null)
217 bookmark.setUsername(s);
218
219 s = rdpFile.getString("domain");
220 if (s != null)
221 bookmark.setDomain(s);
222
223 i = rdpFile.getInteger("connect to console");
224 if (i != null)
225 bookmark.getAdvancedSettings().setConsoleMode(i == 1);
226 }
227
228 @Override protected void onCleared()
229 {
230 super.onCleared();
231 executor.shutdown(); // Clean up threads when ViewModel dies
232 }
233}