1 /*
2    Main/Home Activity
3 
4    Copyright 2013 Thincast Technologies GmbH, Author: Martin Fleisz
5 
6    This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
7    If a copy of the MPL was not distributed with this file, You can obtain one at
8    http://mozilla.org/MPL/2.0/.
9 */
10 
11 package com.freerdp.freerdpcore.presentation;
12 
13 import android.app.AlertDialog;
14 import android.content.DialogInterface;
15 import android.content.Intent;
16 import android.content.res.Configuration;
17 import android.net.Uri;
18 import android.os.Bundle;
19 import androidx.appcompat.app.AppCompatActivity;
20 import android.text.Editable;
21 import android.text.TextWatcher;
22 import android.util.Log;
23 import android.view.ContextMenu;
24 import android.view.ContextMenu.ContextMenuInfo;
25 import android.view.Menu;
26 import android.view.MenuInflater;
27 import android.view.MenuItem;
28 import android.view.View;
29 import android.view.View.OnClickListener;
30 import android.view.View.OnCreateContextMenuListener;
31 import android.widget.AdapterView;
32 import android.widget.AdapterView.AdapterContextMenuInfo;
33 import android.widget.Button;
34 import android.widget.CheckBox;
35 import android.widget.EditText;
36 import android.widget.ListView;
37 
38 import com.freerdp.freerdpcore.R;
39 import com.freerdp.freerdpcore.application.GlobalApp;
40 import com.freerdp.freerdpcore.domain.BookmarkBase;
41 import com.freerdp.freerdpcore.domain.ConnectionReference;
42 import com.freerdp.freerdpcore.domain.PlaceholderBookmark;
43 import com.freerdp.freerdpcore.domain.QuickConnectBookmark;
44 import com.freerdp.freerdpcore.utils.BookmarkArrayAdapter;
45 import com.freerdp.freerdpcore.utils.SeparatedListAdapter;
46 
47 import java.util.ArrayList;
48 
49 public class HomeActivity extends AppCompatActivity
50 {
51 	private final static String ADD_BOOKMARK_PLACEHOLDER = "add_bookmark";
52 	private static final String TAG = "HomeActivity";
53 	private static final String PARAM_SUPERBAR_TEXT = "superbar_text";
54 	private ListView listViewBookmarks;
55 	private Button clearTextButton;
56 	private EditText superBarEditText;
57 	private BookmarkArrayAdapter manualBookmarkAdapter;
58 	private SeparatedListAdapter separatedListAdapter;
59 	private PlaceholderBookmark addBookmarkPlaceholder;
60 	private String sectionLabelBookmarks;
61 
62 	View mDecor;
63 
onCreate(Bundle savedInstanceState)64 	@Override public void onCreate(Bundle savedInstanceState)
65 	{
66 		setTitle(R.string.title_home);
67 		super.onCreate(savedInstanceState);
68 		setContentView(R.layout.home);
69 
70 		mDecor = getWindow().getDecorView();
71 		mDecor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
72 		                             View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
73 
74 		long heapSize = Runtime.getRuntime().maxMemory();
75 		Log.i(TAG, "Max HeapSize: " + heapSize);
76 		Log.i(TAG, "App data folder: " + getFilesDir().toString());
77 
78 		// load strings
79 		sectionLabelBookmarks = getResources().getString(R.string.section_bookmarks);
80 
81 		// create add bookmark/quick connect bookmark placeholder
82 		addBookmarkPlaceholder = new PlaceholderBookmark();
83 		addBookmarkPlaceholder.setName(ADD_BOOKMARK_PLACEHOLDER);
84 		addBookmarkPlaceholder.setLabel(
85 		    getResources().getString(R.string.list_placeholder_add_bookmark));
86 
87 		// check for passed .rdp file and open it in a new bookmark
88 		Intent caller = getIntent();
89 		Uri callParameter = caller.getData();
90 
91 		if (Intent.ACTION_VIEW.equals(caller.getAction()) && callParameter != null)
92 		{
93 			String refStr = ConnectionReference.getFileReference(callParameter.getPath());
94 			Bundle bundle = new Bundle();
95 			bundle.putString(BookmarkActivity.PARAM_CONNECTION_REFERENCE, refStr);
96 
97 			Intent bookmarkIntent =
98 			    new Intent(this.getApplicationContext(), BookmarkActivity.class);
99 			bookmarkIntent.putExtras(bundle);
100 			startActivity(bookmarkIntent);
101 		}
102 
103 		// load views
104 		clearTextButton = (Button)findViewById(R.id.clear_search_btn);
105 		superBarEditText = (EditText)findViewById(R.id.superBarEditText);
106 
107 		listViewBookmarks = (ListView)findViewById(R.id.listViewBookmarks);
108 
109 		// set listeners for the list view
110 		listViewBookmarks.setOnItemClickListener(new AdapterView.OnItemClickListener() {
111 			public void onItemClick(AdapterView<?> parent, View view, int position, long id)
112 			{
113 				String curSection = separatedListAdapter.getSectionForPosition(position);
114 				Log.v(TAG, "Clicked on item id " + separatedListAdapter.getItemId(position) +
115 				               " in section " + curSection);
116 				if (curSection.equals(sectionLabelBookmarks))
117 				{
118 					String refStr = view.getTag().toString();
119 					if (ConnectionReference.isManualBookmarkReference(refStr) ||
120 					    ConnectionReference.isHostnameReference(refStr))
121 					{
122 						Bundle bundle = new Bundle();
123 						bundle.putString(SessionActivity.PARAM_CONNECTION_REFERENCE, refStr);
124 
125 						Intent sessionIntent = new Intent(view.getContext(), SessionActivity.class);
126 						sessionIntent.putExtras(bundle);
127 						startActivity(sessionIntent);
128 
129 						// clear any search text
130 						superBarEditText.setText("");
131 						superBarEditText.clearFocus();
132 					}
133 					else if (ConnectionReference.isPlaceholderReference(refStr))
134 					{
135 						// is this the add bookmark placeholder?
136 						if (ConnectionReference.getPlaceholder(refStr).equals(
137 						        ADD_BOOKMARK_PLACEHOLDER))
138 						{
139 							Intent bookmarkIntent =
140 							    new Intent(view.getContext(), BookmarkActivity.class);
141 							startActivity(bookmarkIntent);
142 						}
143 					}
144 				}
145 			}
146 		});
147 
148 		listViewBookmarks.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
149 			@Override
150 			public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)
151 			{
152 				// if the selected item is not a session item (tag == null) and not a quick connect
153 				// entry (not a hostname connection reference) inflate the context menu
154 				View itemView = ((AdapterContextMenuInfo)menuInfo).targetView;
155 				String refStr = itemView.getTag() != null ? itemView.getTag().toString() : null;
156 				if (refStr != null && !ConnectionReference.isHostnameReference(refStr) &&
157 				    !ConnectionReference.isPlaceholderReference(refStr))
158 				{
159 					getMenuInflater().inflate(R.menu.bookmark_context_menu, menu);
160 					menu.setHeaderTitle(getResources().getString(R.string.menu_title_bookmark));
161 				}
162 			}
163 		});
164 
165 		superBarEditText.addTextChangedListener(new SuperBarTextWatcher());
166 
167 		clearTextButton.setOnClickListener(new OnClickListener() {
168 			@Override public void onClick(View v)
169 			{
170 				superBarEditText.setText("");
171 			}
172 		});
173 	}
174 
onConfigurationChanged(Configuration newConfig)175 	@Override public void onConfigurationChanged(Configuration newConfig)
176 	{
177 		// ignore orientation/keyboard change
178 		super.onConfigurationChanged(newConfig);
179 		mDecor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
180 		                             View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
181 	}
182 
onSearchRequested()183 	@Override public boolean onSearchRequested()
184 	{
185 		superBarEditText.requestFocus();
186 		return true;
187 	}
188 
onContextItemSelected(MenuItem aItem)189 	@Override public boolean onContextItemSelected(MenuItem aItem)
190 	{
191 
192 		// get connection reference
193 		AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo)aItem.getMenuInfo();
194 		String refStr = menuInfo.targetView.getTag().toString();
195 
196 		// refer to http://tools.android.com/tips/non-constant-fields why we can't use switch/case
197 		// here ..
198 		int itemId = aItem.getItemId();
199 		if (itemId == R.id.bookmark_connect)
200 		{
201 			Bundle bundle = new Bundle();
202 			bundle.putString(SessionActivity.PARAM_CONNECTION_REFERENCE, refStr);
203 			Intent sessionIntent = new Intent(this, SessionActivity.class);
204 			sessionIntent.putExtras(bundle);
205 
206 			startActivity(sessionIntent);
207 			return true;
208 		}
209 		else if (itemId == R.id.bookmark_edit)
210 		{
211 			Bundle bundle = new Bundle();
212 			bundle.putString(BookmarkActivity.PARAM_CONNECTION_REFERENCE, refStr);
213 
214 			Intent bookmarkIntent =
215 			    new Intent(this.getApplicationContext(), BookmarkActivity.class);
216 			bookmarkIntent.putExtras(bundle);
217 			startActivity(bookmarkIntent);
218 			return true;
219 		}
220 		else if (itemId == R.id.bookmark_delete)
221 		{
222 			if (ConnectionReference.isManualBookmarkReference(refStr))
223 			{
224 				long id = ConnectionReference.getManualBookmarkId(refStr);
225 				GlobalApp.getManualBookmarkGateway().delete(id);
226 				manualBookmarkAdapter.remove(id);
227 				separatedListAdapter.notifyDataSetChanged();
228 			}
229 			else
230 			{
231 				assert false;
232 			}
233 
234 			// clear super bar text
235 			superBarEditText.setText("");
236 			return true;
237 		}
238 
239 		return false;
240 	}
241 
onResume()242 	@Override protected void onResume()
243 	{
244 		super.onResume();
245 		Log.v(TAG, "HomeActivity.onResume");
246 
247 		// create bookmark cursor adapter
248 		manualBookmarkAdapter = new BookmarkArrayAdapter(
249 		    this, R.layout.bookmark_list_item, GlobalApp.getManualBookmarkGateway().findAll());
250 
251 		// add add bookmark item to manual adapter
252 		manualBookmarkAdapter.insert(addBookmarkPlaceholder, 0);
253 
254 		// attach all adapters to the separatedListView adapter and assign it to the list view
255 		separatedListAdapter = new SeparatedListAdapter(this);
256 		separatedListAdapter.addSection(sectionLabelBookmarks, manualBookmarkAdapter);
257 		listViewBookmarks.setAdapter(separatedListAdapter);
258 
259 		// if we have a filter text entered cause an update to be caused here
260 		String filter = superBarEditText.getText().toString();
261 		if (filter.length() > 0)
262 			superBarEditText.setText(filter);
263 	}
264 
onPause()265 	@Override protected void onPause()
266 	{
267 		super.onPause();
268 		Log.v(TAG, "HomeActivity.onPause");
269 
270 		// reset adapters
271 		listViewBookmarks.setAdapter(null);
272 		separatedListAdapter = null;
273 		manualBookmarkAdapter = null;
274 	}
275 
onBackPressed()276 	@Override public void onBackPressed()
277 	{
278 		// if back was pressed - ask the user if he really wants to exit
279 		if (ApplicationSettingsActivity.getAskOnExit(this))
280 		{
281 			final CheckBox cb = new CheckBox(this);
282 			cb.setChecked(!ApplicationSettingsActivity.getAskOnExit(this));
283 			cb.setText(R.string.dlg_dont_show_again);
284 
285 			AlertDialog.Builder builder = new AlertDialog.Builder(this);
286 			builder.setTitle(R.string.dlg_title_exit)
287 			    .setMessage(R.string.dlg_msg_exit)
288 			    .setView(cb)
289 			    .setPositiveButton(R.string.yes,
290 			                       new DialogInterface.OnClickListener() {
291 				                       public void onClick(DialogInterface dialog, int which)
292 				                       {
293 					                       finish();
294 				                       }
295 			                       })
296 			    .setNegativeButton(R.string.no,
297 			                       new DialogInterface.OnClickListener() {
298 				                       public void onClick(DialogInterface dialog, int which)
299 				                       {
300 					                       dialog.dismiss();
301 				                       }
302 			                       })
303 			    .create()
304 			    .show();
305 		}
306 		else
307 		{
308 			super.onBackPressed();
309 		}
310 	}
311 
onSaveInstanceState(Bundle outState)312 	@Override protected void onSaveInstanceState(Bundle outState)
313 	{
314 		super.onSaveInstanceState(outState);
315 		outState.putString(PARAM_SUPERBAR_TEXT, superBarEditText.getText().toString());
316 	}
317 
onRestoreInstanceState(Bundle inState)318 	@Override protected void onRestoreInstanceState(Bundle inState)
319 	{
320 		super.onRestoreInstanceState(inState);
321 		superBarEditText.setText(inState.getString(PARAM_SUPERBAR_TEXT));
322 	}
323 
onCreateOptionsMenu(Menu menu)324 	@Override public boolean onCreateOptionsMenu(Menu menu)
325 	{
326 		MenuInflater inflater = getMenuInflater();
327 		inflater.inflate(R.menu.home_menu, menu);
328 		return true;
329 	}
330 
onOptionsItemSelected(MenuItem item)331 	@Override public boolean onOptionsItemSelected(MenuItem item)
332 	{
333 
334 		// refer to http://tools.android.com/tips/non-constant-fields why we can't use switch/case
335 		// here ..
336 		int itemId = item.getItemId();
337 		if (itemId == R.id.newBookmark)
338 		{
339 			Intent bookmarkIntent = new Intent(this, BookmarkActivity.class);
340 			startActivity(bookmarkIntent);
341 		}
342 		else if (itemId == R.id.appSettings)
343 		{
344 			Intent settingsIntent = new Intent(this, ApplicationSettingsActivity.class);
345 			startActivity(settingsIntent);
346 		}
347 		else if (itemId == R.id.help)
348 		{
349 			Intent helpIntent = new Intent(this, HelpActivity.class);
350 			startActivity(helpIntent);
351 		}
352 		else if (itemId == R.id.about)
353 		{
354 			Intent aboutIntent = new Intent(this, AboutActivity.class);
355 			startActivity(aboutIntent);
356 		}
357 
358 		return true;
359 	}
360 
361 	private class SuperBarTextWatcher implements TextWatcher
362 	{
afterTextChanged(Editable s)363 		@Override public void afterTextChanged(Editable s)
364 		{
365 			if (separatedListAdapter != null)
366 			{
367 				String text = s.toString();
368 				if (text.length() > 0)
369 				{
370 					ArrayList<BookmarkBase> computers_list =
371 					    GlobalApp.getQuickConnectHistoryGateway().findHistory(text);
372 					computers_list.addAll(
373 					    GlobalApp.getManualBookmarkGateway().findByLabelOrHostnameLike(text));
374 					manualBookmarkAdapter.replaceItems(computers_list);
375 					QuickConnectBookmark qcBm = new QuickConnectBookmark();
376 					qcBm.setLabel(text);
377 					qcBm.setHostname(text);
378 					manualBookmarkAdapter.insert(qcBm, 0);
379 				}
380 				else
381 				{
382 					manualBookmarkAdapter.replaceItems(
383 					    GlobalApp.getManualBookmarkGateway().findAll());
384 					manualBookmarkAdapter.insert(addBookmarkPlaceholder, 0);
385 				}
386 
387 				separatedListAdapter.notifyDataSetChanged();
388 			}
389 		}
390 
beforeTextChanged(CharSequence s, int start, int count, int after)391 		@Override public void beforeTextChanged(CharSequence s, int start, int count, int after)
392 		{
393 		}
394 
onTextChanged(CharSequence s, int start, int before, int count)395 		@Override public void onTextChanged(CharSequence s, int start, int before, int count)
396 		{
397 		}
398 	}
399 }
400