/* This file is part of the dandelion*. dandelion* is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. dandelion* is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the dandelion*. If not, see . */ package com.github.dfa.diaspora_android.activity; import android.annotation.SuppressLint; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.res.ColorStateList; import android.graphics.Color; import android.graphics.drawable.LayerDrawable; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.support.annotation.NonNull; import android.support.customtabs.CustomTabsSession; import android.support.design.widget.AppBarLayout; import android.support.design.widget.NavigationView; import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.content.ContextCompat; import android.support.v4.content.LocalBroadcastManager; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AlertDialog; import android.support.v7.widget.Toolbar; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.WindowManager; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.data.DiasporaAspect; import com.github.dfa.diaspora_android.data.DiasporaPodList; import com.github.dfa.diaspora_android.data.DiasporaUserProfile; import com.github.dfa.diaspora_android.listener.DiasporaUserProfileChangedListener; import com.github.dfa.diaspora_android.listener.IntellihideToolbarActivityListener; import com.github.dfa.diaspora_android.receiver.OpenExternalLinkReceiver; import com.github.dfa.diaspora_android.receiver.UpdateTitleReceiver; import com.github.dfa.diaspora_android.ui.BadgeDrawable; import com.github.dfa.diaspora_android.ui.PodSelectionDialog; import com.github.dfa.diaspora_android.ui.SearchOrCustomTextDialogCreator; import com.github.dfa.diaspora_android.ui.theme.ThemeHelper; import com.github.dfa.diaspora_android.ui.theme.ThemedActivity; import com.github.dfa.diaspora_android.ui.theme.ThemedAlertDialogBuilder; import com.github.dfa.diaspora_android.ui.theme.ThemedFragment; import com.github.dfa.diaspora_android.util.ActivityUtils; import com.github.dfa.diaspora_android.util.AndroidBug5497Workaround; import com.github.dfa.diaspora_android.util.AppLog; import com.github.dfa.diaspora_android.util.AppSettings; import com.github.dfa.diaspora_android.util.ContextUtils; import com.github.dfa.diaspora_android.util.DiasporaUrlHelper; import com.github.dfa.diaspora_android.web.BrowserFragment; import com.github.dfa.diaspora_android.web.ContextMenuWebView; import com.github.dfa.diaspora_android.web.ProxyHandler; import com.github.dfa.diaspora_android.web.WebHelper; import com.github.dfa.diaspora_android.web.custom_tab.CustomTabActivityHelper; import net.gsantner.opoc.format.markdown.SimpleMarkdownParser; import java.io.IOException; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; public class MainActivity extends ThemedActivity implements NavigationView.OnNavigationItemSelectedListener, DiasporaUserProfileChangedListener, CustomTabActivityHelper.ConnectionCallback, IntellihideToolbarActivityListener, PodSelectionDialog.PodSelectionDialogResultListener { public static final int REQUEST_CODE_ASK_PERMISSIONS = 123; public static final int REQUEST_CODE__ACCESS_EXTERNAL_STORAGE = 124; public static final int INPUT_FILE_REQUEST_CODE_NEW = 1; public static final int INPUT_FILE_REQUEST_CODE_OLD = 2; public static final String ACTION_OPEN_URL = "com.github.dfa.diaspora_android.MainActivity.open_url"; public static final String ACTION_OPEN_EXTERNAL_URL = "com.github.dfa.diaspora_android.MainActivity.open_external_url"; public static final String ACTION_CHANGE_ACCOUNT = "com.github.dfa.diaspora_android.MainActivity.change_account"; public static final String ACTION_CLEAR_CACHE = "com.github.dfa.diaspora_android.MainActivity.clear_cache"; public static final String ACTION_UPDATE_TITLE_FROM_URL = "com.github.dfa.diaspora_android.MainActivity.set_title"; public static final String URL_MESSAGE = "URL_MESSAGE"; public static final String EXTRA_URL = "com.github.dfa.diaspora_android.extra_url"; public static final String CONTENT_HASHTAG = "content://com.github.dfa.diaspora_android.mainactivity/"; private App app; private CustomTabActivityHelper customTabActivityHelper; private AppSettings _appSettings; private DiasporaUrlHelper urls; private DiasporaUserProfile diasporaUserProfile; private final Handler uiHandler = new Handler(); private OpenExternalLinkReceiver brOpenExternalLink; private BroadcastReceiver brSetTitle; private Snackbar snackbarExitApp, snackbarNoInternet, snackbarLastVisitedTimestampInStream; private FragmentManager fm; private CustomTabsSession customTabsSession; /** * UI Bindings */ @BindView(R.id.main__appbar) AppBarLayout appBarLayout; @BindView(R.id.main__topbar) Toolbar toolbarTop; @BindView(R.id.fragment_container) FrameLayout fragmentContainer; @BindView(R.id.main__navigaion_view) NavigationView navView; @BindView(R.id.main__navdrawer) DrawerLayout navDrawer; RelativeLayout navDrawerLayout; LinearLayout navProfilePictureArea; // NavHeader cannot be bound by Butterknife private TextView navheaderTitle; private TextView navheaderDescription; private ImageView navheaderImage; private String textToBeShared; /** * END UI Bindings */ @SuppressLint("SetJavaScriptEnabled") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AppLog.v(this, "onCreate()"); // Pre UI ContextUtils.get().setAppLanguage(AppSettings.get().getLanguage()); if (AppSettings.get().isEditorStatusBarHidden()) { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); } // Bind UI setContentView(R.layout.main__activity); ButterKnife.bind(this); if (AppSettings.get().isEditorStatusBarHidden()) { AndroidBug5497Workaround.assistActivity(this); } app = (App) getApplication(); _appSettings = app.getSettings(); diasporaUserProfile = app.getDiasporaUserProfile(); diasporaUserProfile.setCallbackHandler(uiHandler); diasporaUserProfile.setListener(this); urls = new DiasporaUrlHelper(_appSettings); customTabActivityHelper = new CustomTabActivityHelper(); customTabActivityHelper.setConnectionCallback(this); ProxyHandler.getInstance().updateProxySettings(this); fm = getSupportFragmentManager(); setupUI(); brOpenExternalLink = new OpenExternalLinkReceiver(this); brSetTitle = new UpdateTitleReceiver(app, urls, new UpdateTitleReceiver.TitleCallback() { public void setTitle(String url, int resId) { ThemedFragment top = getTopFragment(); if (top != null && top.getFragmentTag().equals(DiasporaStreamFragment.TAG)) { MainActivity.this.setTitle(resId); showLastVisitedTimestampMessageIfNeeded(url); } } public void setTitle(String url, String title) { ThemedFragment top = getTopFragment(); if (top != null && top.getFragmentTag().equals(DiasporaStreamFragment.TAG)) { MainActivity.this.setTitle(title); } } }); if (!_appSettings.hasPod()) { AppLog.d(this, "We have no pod. Show PodSelectionFragment"); updateNavigationViewEntryVisibilities(); showFragment(getFragment(PodSelectionFragment.TAG)); } else { AppLog.d(this, "Pod found. Handle intents."); //Handle intent Intent intent = getIntent(); if (intent != null && intent.getAction() != null) { handleIntent(intent); } else { openDiasporaUrl(urls.getStreamUrl()); } } // Show first start / update dialog try { if (_appSettings.isAppCurrentVersionFirstStart(true)) { SimpleMarkdownParser smp = SimpleMarkdownParser.get().setDefaultSmpFilter(SimpleMarkdownParser.FILTER_ANDROID_TEXTVIEW); String html = ""; html += smp.parse(getString(R.string.copyright_license_text_official).replace("\n", " \n"), "").getHtml(); html += "


" + getString(R.string.changelog) + "
" + smp.parse(getResources().openRawResource(R.raw.changelog), "", SimpleMarkdownParser.FILTER_ANDROID_TEXTVIEW, SimpleMarkdownParser.FILTER_CHANGELOG).getHtml(); html += "


" + getString(R.string.licenses) + "
" + smp.parse(getResources().openRawResource(R.raw.licenses_3rd_party), "").getHtml(); ActivityUtils _au = new ActivityUtils(this); _au.showDialogWithHtmlTextView(R.string.licenses, html); } } catch (IOException e) { e.printStackTrace(); } } /** * Setup the user interface. Set up both toolbars and initialize the snackbars. * Initialize the navigation drawer and apply intellihide settings. */ private void setupUI() { AppLog.i(this, "setupUI()"); // Setup _toolbar setSupportActionBar(toolbarTop); ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); } setTitle(R.string.app_name); //Setup snackbar snackbarExitApp = Snackbar .make(fragmentContainer, R.string.do_you_want_to_exit, Snackbar.LENGTH_LONG) .setAction(android.R.string.yes, new View.OnClickListener() { public void onClick(View view) { finish(); moveTaskToBack(true); } }); snackbarLastVisitedTimestampInStream = Snackbar.make(fragmentContainer, R.string.jump_to_last_visited_page_in_stream__appspecific, Snackbar.LENGTH_LONG) .setAction(android.R.string.yes, new View.OnClickListener() { public void onClick(View view) { openDiasporaUrl(urls.getStreamWithTimestampUrl(diasporaUserProfile.getLastVisitedPositionInStream())); } }); snackbarNoInternet = Snackbar.make(fragmentContainer, R.string.sorry_need_to_be_connected_to_internet, Snackbar.LENGTH_LONG); // Load app settings setupNavigationSlider(); AppLog.v(this, "UI successfully set up"); } /** * Get an instance of the ThemedFragment with the tag fragmentTag. * If there was no instance so far, create a new one and add it to the FragmentManagers pool. * If there is no Fragment with the corresponding Tag, return the top fragment. * * @param fragmentTag tag * @return corresponding Fragment */ protected ThemedFragment getFragment(String fragmentTag) { ThemedFragment fragment = (ThemedFragment) fm.findFragmentByTag(fragmentTag); if (fragment != null) { return fragment; } else { switch (fragmentTag) { case DiasporaStreamFragment.TAG: DiasporaStreamFragment dsf = new DiasporaStreamFragment(); fm.beginTransaction().add(dsf, fragmentTag).commit(); return dsf; case BrowserFragment.TAG: BrowserFragment bf = new BrowserFragment(); fm.beginTransaction().add(bf, fragmentTag).commit(); return bf; case PodSelectionFragment.TAG: PodSelectionFragment psf = new PodSelectionFragment(); fm.beginTransaction().add(psf, fragmentTag).commit(); return psf; default: AppLog.e(this, "Invalid Fragment Tag: " + fragmentTag + "\nAdd Fragments Tag to getFragment()'s switch case."); return getTopFragment(); } } } /** * Show DiasporaStreamFragment if necessary and load URL url * * @param url URL to load in the DiasporaStreamFragment */ public void openDiasporaUrl(final String url) { AppLog.v(this, "openDiasporaUrl()"); if (url != null && url.startsWith("http://127.0.0.1")) { // This URL seems to be called somehow, but it doesn't make sense ;) toolbarTop.postDelayed(() -> { Intent i = new Intent(ACTION_OPEN_EXTERNAL_URL); i.putExtra(EXTRA_URL, "https://github.com/gsantner/dandelion/blob/master/README.md"); LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i); }, 1000); return; } if (_appSettings.getPod() != null && _appSettings.getPod().getPodUrl() != null && _appSettings.getPod().getPodUrl().getBaseUrl() != null && url.startsWith(_appSettings.getPod().getPodUrl().getBaseUrl()) && !url.startsWith("https://dia.so/")) { DiasporaStreamFragment streamFragment = (DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG); showFragment(streamFragment); showLastVisitedTimestampMessageIfNeeded(url); streamFragment.loadUrl(url); } else { toolbarTop.postDelayed(() -> { Intent i = new Intent(ACTION_OPEN_EXTERNAL_URL); i.putExtra(EXTRA_URL, url); LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i); }, 1000); } } public void showLastVisitedTimestampMessageIfNeeded(String url) { if (url.equals(urls.getStreamUrl()) && diasporaUserProfile.hasLastVisitedTimestampInStream()) { snackbarLastVisitedTimestampInStream.show(); diasporaUserProfile.resetLastVisitedPositionInStream(); } } /** * Show the Fragment fragment in R.id.fragment_container. If the fragment was already visible, do nothing. * * @param fragment Fragment to show */ protected void showFragment(ThemedFragment fragment) { if (PodSelectionFragment.TAG.equals(fragment.getTag())) { Fragment fragment1 = fm.findFragmentByTag(DiasporaStreamFragment.TAG); if (fragment1 != null) { new net.gsantner.opoc.util.ContextUtils(this).restartApp(MainActivity.class); } } AppLog.v(this, "showFragment()"); ThemedFragment currentTop = (ThemedFragment) fm.findFragmentById(R.id.fragment_container); if (currentTop == null || !currentTop.getFragmentTag().equals(fragment.getFragmentTag())) { AppLog.v(this, "Fragment was not visible. Replace it."); fm.beginTransaction().addToBackStack(null).replace(R.id.fragment_container, fragment, fragment.getFragmentTag()).commit(); invalidateOptionsMenu(); setToolbarIntellihide(_appSettings.isIntellihideToolbars() && fragment.isAllowedIntellihide()); } else { AppLog.v(this, "Fragment was already visible. Do nothing."); } } /** * Initialize the navigation slider */ private void setupNavigationSlider() { ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, navDrawer, toolbarTop, R.string.open_navdrawer, R.string.close_navdrawer); navDrawer.addDrawerListener(toggle); toggle.syncState(); //NavigationView navView = ButterKnife.findById(this, R.id.nav_view); navView.setNavigationItemSelectedListener(this); View navHeader = navView.getHeaderView(0); navProfilePictureArea = ButterKnife.findById(navHeader, R.id.nav_profile_picture); navDrawerLayout = ButterKnife.findById(navHeader, R.id.nav_drawer); //Handle clicks on profile picture navProfilePictureArea.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { navDrawer.closeDrawer(GravityCompat.START); if (!_appSettings.getProfileId().equals("")) { openDiasporaUrl(urls.getProfileUrl()); } } }); navheaderTitle = ButterKnife.findById(navHeader, R.id.navheader_title); navheaderDescription = ButterKnife.findById(navHeader, R.id.podselection__podupti_notice); navheaderImage = ButterKnife.findById(navHeader, R.id.navheader_user_image); if (!_appSettings.getName().equals("")) { navheaderTitle.setText(_appSettings.getName()); } if (_appSettings.getPod() != null) { navheaderDescription.setText(_appSettings.getPod().getName()); } String avatarUrl = _appSettings.getAvatarUrl(); if (!avatarUrl.equals("")) { //Display app launcher icon instead of default avatar asset //(Which would by the way not load because of missing pod domain prefix in the url) if (avatarUrl.startsWith("/assets/user/default")) { AppLog.v(this, "Avatar appears to be an asset. Display launcher icon instead (avatarUrl=" + avatarUrl + ")"); navheaderImage.setImageResource(R.drawable.ic_launcher); } else { // Try to load image if (!app.getAvatarImageLoader().loadToImageView(navheaderImage)) { // If not yet loaded, start download AppLog.v(this, "Avatar not cached. Start download: " + avatarUrl); app.getAvatarImageLoader().startImageDownload(navheaderImage, avatarUrl); } } } updateNavigationViewEntryVisibilities(); } protected void updateNavigationViewEntryVisibilities() { Menu navMenu = navView.getMenu(); // Initially show all items visible when logged in navMenu.setGroupVisible(navMenu.findItem(R.id.nav_exit).getGroupId(), true); // Hide by app settings navMenu.findItem(R.id.nav_exit).setVisible(_appSettings.isVisibleInNavExit()); navMenu.findItem(R.id.nav_activities).setVisible(_appSettings.isVisibleInNavActivities()); navMenu.findItem(R.id.nav_aspects).setVisible(_appSettings.isVisibleInNavAspects()); navMenu.findItem(R.id.nav_contacts).setVisible(_appSettings.isVisibleInNavContacts()); navMenu.findItem(R.id.nav_commented).setVisible(_appSettings.isVisibleInNavCommented()); navMenu.findItem(R.id.nav_followed_tags).setVisible(_appSettings.isVisibleInNavFollowed_tags()); navMenu.findItem(R.id.nav_about).setVisible(_appSettings.isVisibleInNavHelp_license()); navMenu.findItem(R.id.nav_liked).setVisible(_appSettings.isVisibleInNavLiked()); navMenu.findItem(R.id.nav_mentions).setVisible(_appSettings.isVisibleInNavMentions()); navMenu.findItem(R.id.nav_profile).setVisible(_appSettings.isVisibleInNavProfile()); navMenu.findItem(R.id.nav_public).setVisible(_appSettings.isVisibleInNavPublic_activities()); navMenu.findItem(R.id.nav_stream).setVisible(true); navMenu.findItem(R.id.nav_statistics).setVisible(_appSettings.isVisibleInNavStatistics()); navMenu.findItem(R.id.nav_reports).setVisible(_appSettings.isVisibleInNavReports()); navMenu.findItem(R.id.nav_toggle_desktop_page).setVisible(_appSettings.isVisibleInNavToggleMobileDesktop()); navMenu.findItem(R.id.nav_product_support).setVisible(_appSettings.isVisibleInNavGsantnerAccount()); // Hide whole group (for logged in use) if no pod was selected if (!_appSettings.hasPod()) { navMenu.setGroupVisible(navMenu.findItem(R.id.nav_exit).getGroupId(), false); } } /** * Open Stream when clicked on top _toolbar AND preference stream shortcut is true * * @param view selected view */ @OnClick(R.id.main__topbar) public void onToolBarClicked(View view) { AppLog.i(this, "onToolBarClicked()"); if (_appSettings.isTopbarStreamShortcutEnabled() && _appSettings.hasPod()) { onNavigationItemSelected(navView.getMenu().findItem(R.id.nav_stream)); } } /** * Forward incoming intents to handleIntent() * * @param intent incoming */ @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); handleIntent(intent); } /** * Handle intents and execute intent specific actions * * @param intent intent to get handled */ private void handleIntent(Intent intent) { AppLog.i(this, "handleIntent()"); if (intent == null) { AppLog.v(this, "Intent was null"); return; } String action = intent.getAction(); String type = intent.getType(); String loadUrl = null; AppLog.v(this, "Action: " + action + " Type: " + type); if (Intent.ACTION_MAIN.equals(action)) { loadUrl = urls.getStreamUrl(); } else if (ACTION_OPEN_URL.equals(action)) { loadUrl = intent.getStringExtra(URL_MESSAGE); } else if (Intent.ACTION_VIEW.equals(action) && intent.getDataString() != null) { Uri data = intent.getData(); if (data != null && data.toString().startsWith(CONTENT_HASHTAG)) { handleHashtag(intent); return; } else { loadUrl = intent.getDataString(); AppLog.v(this, "Intent has a delicious URL for us: " + loadUrl); } } else if (ACTION_CHANGE_ACCOUNT.equals(action)) { AppLog.v(this, "Reset pod data and show PodSelectionFragment"); _appSettings.setPod(null); runOnUiThread(new Runnable() { public void run() { navheaderTitle.setText(R.string.app_name); navheaderDescription.setText(R.string.app_subtitle); navheaderImage.setImageResource(R.drawable.ic_launcher); app.resetPodData(((DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG)).getWebView()); } }); showFragment(getFragment(PodSelectionFragment.TAG)); } else if (ACTION_CLEAR_CACHE.equals(action)) { AppLog.v(this, "Clear WebView cache"); runOnUiThread(new Runnable() { public void run() { ContextMenuWebView wv = ((DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG)).getWebView(); if (wv != null) { wv.clearCache(true); } } }); } else if (Intent.ACTION_SEND.equals(action) && type != null) { switch (type) { case "text/plain": if (intent.hasExtra(Intent.EXTRA_SUBJECT)) { handleSendSubject(intent); } else { handleSendText(intent); } break; case "image/*": handleSendImage(intent); //TODO: Add intent filter to Manifest and implement method break; } } else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) { /* TODO: Implement and add filter to manifest */ return; } else if ("sc_new_post".equals(action)) { openDiasporaUrl(urls.getNewPostUrl()); return; } else if ("sc_activities".equals(action)) { openDiasporaUrl(urls.getActivityUrl()); return; } else if ("sc_contacts".equals(action)) { onNavigationItemSelected(navView.getMenu().findItem(R.id.nav_aspects)); return; } else if ("sc_tags".equals(action)) { onNavigationItemSelected(navView.getMenu().findItem(R.id.nav_followed_tags)); return; } //Catch split screen recreation if (action != null && action.equals(Intent.ACTION_MAIN) && getTopFragment() != null) { return; } if (loadUrl != null) { navDrawer.closeDrawers(); openDiasporaUrl(loadUrl); } } /** * Handle activity results * * @param requestCode reqCode * @param resultCode resCode * @param data data */ @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { AppLog.v(this, "onActivityResult(): " + requestCode); super.onActivityResult(requestCode, resultCode, data); } /** * Return the fragment which is currently displayed in R.id.fragment_container * * @return top fragment or null if there is none displayed */ private ThemedFragment getTopFragment() { return (ThemedFragment) fm.findFragmentById(R.id.fragment_container); } /** * Handle presses on the back button */ @Override public void onBackPressed() { AppLog.v(this, "onBackPressed()"); if (navDrawer.isDrawerOpen(navView)) { navDrawer.closeDrawer(navView); return; } ThemedFragment top = getTopFragment(); if (top != null) { AppLog.v(this, "Top Fragment is not null"); if (!top.onBackPressed()) { AppLog.v(this, "Top Fragment.onBackPressed was false"); AppLog.v(this, "BackStackEntryCount: " + fm.getBackStackEntryCount()); if (fm.getBackStackEntryCount() > 0) { fm.popBackStack(); } else { snackbarExitApp.show(); } return; } else { AppLog.v(this, "Top Fragment.onBackPressed was true"); return; } } if (!snackbarExitApp.isShown()) { snackbarExitApp.show(); } } @Override protected void onStart() { super.onStart(); customTabActivityHelper.bindCustomTabsService(this); } @Override protected void onStop() { super.onStop(); customTabActivityHelper.unbindCustomTabsService(this); } @Override protected void onPause() { AppLog.v(this, "onPause()"); AppLog.v(this, "Unregister BroadcastReceivers"); LocalBroadcastManager.getInstance(this).unregisterReceiver(brSetTitle); LocalBroadcastManager.getInstance(this).unregisterReceiver(brOpenExternalLink); super.onPause(); } @Override protected void onResume() { AppLog.v(this, "onResume()"); super.onResume(); AppLog.v(this, "Register BroadcastReceivers"); LocalBroadcastManager.getInstance(this).registerReceiver(brSetTitle, new IntentFilter(ACTION_UPDATE_TITLE_FROM_URL)); LocalBroadcastManager.getInstance(this).registerReceiver(brOpenExternalLink, new IntentFilter(ACTION_OPEN_EXTERNAL_URL)); invalidateOptionsMenu(); _appSettings = getAppSettings(); if (_appSettings.isRecreateMainActivity()) { recreate(); } setToolbarIntellihide(_appSettings.isIntellihideToolbars()); if (getSupportActionBar() != null) { getSupportActionBar().setDisplayShowTitleEnabled(AppSettings.get().isShowTitleInMainView()); } updateNavigationViewEntryVisibilities(); } /** * Clear and repopulate top and bottom _toolbar. * Also add menu items of the displayed fragment * * @param menu top _toolbar * @return boolean */ @Override public boolean onCreateOptionsMenu(Menu menu) { AppLog.v(this, "onCreateOptionsMenu()"); boolean cache; //Clear the menus menu.clear(); ThemedFragment top = getTopFragment(); if (top != null) { if (!top.getFragmentTag().equals(PodSelectionFragment.TAG)) { cache = _appSettings.isExtendedNotificationsActivated(); getMenuInflater().inflate(R.menu.main__menu_top, menu); menu.findItem(R.id.action_notifications).setVisible(!cache); menu.findItem(R.id.action_notifications_extended).setVisible(cache); } } ContextUtils cu = ContextUtils.get(); final boolean darkBg = cu.get().shouldColorOnTopBeLight(AppSettings.get().getPrimaryColor()); cu.tintMenuItems(menu, true, ContextCompat.getColor(this, darkBg ? R.color.white : R.color.black)); cu.setSubMenuIconsVisiblity(menu, true); return true; } /** * Set the notification and messages counter in the top _toolbar * * @param menu menu * @return boolean */ @Override public boolean onPrepareOptionsMenu(Menu menu) { MenuItem item; updateNavigationViewEntryVisibilities(); if ((item = menu.findItem(R.id.action_notifications)) != null) { LayerDrawable icon = (LayerDrawable) item.getIcon(); BadgeDrawable.setBadgeCount(this, icon, diasporaUserProfile.getNotificationCount()); } if ((item = menu.findItem(R.id.action_conversations)) != null) { LayerDrawable icon = (LayerDrawable) item.getIcon(); BadgeDrawable.setBadgeCount(this, icon, diasporaUserProfile.getUnreadMessagesCount()); } return super.onPrepareOptionsMenu(menu); } /** * Handle clicks on the optionsmenu * * @param item item * @return boolean */ @Override public boolean onOptionsItemSelected(MenuItem item) { AppLog.i(this, "onOptionsItemSelected()"); switch (item.getItemId()) { case R.id.action_notifications: { if (_appSettings.isExtendedNotificationsActivated()) { return true; } //Otherwise we execute the action of action_notifications_all } case R.id.action_notifications_all: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getNotificationsUrl()); return true; } else { snackbarNoInternet.show(); return false; } } case R.id.action_notifications_also_commented: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getSuburlNotificationsAlsoCommentedUrl()); return true; } else { snackbarNoInternet.show(); return false; } } case R.id.action_notifications_comment_on_post: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getSuburlNotificationsCommentOnPostUrl()); return true; } else { snackbarNoInternet.show(); return false; } } case R.id.action_notifications_liked: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getSuburlNotificationsLikedUrl()); return true; } else { snackbarNoInternet.show(); return false; } } case R.id.action_notifications_mentioned: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getSuburlNotificationsMentionedUrl()); return true; } else { snackbarNoInternet.show(); return false; } } case R.id.action_notifications_reshared: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getSuburlNotificationsResharedUrl()); return true; } else { snackbarNoInternet.show(); return false; } } case R.id.action_notifications_started_sharing: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getSuburlNotificationsStartedSharingUrl()); return true; } else { snackbarNoInternet.show(); return false; } } case R.id.action_conversations: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getConversationsUrl()); return true; } else { snackbarNoInternet.show(); return false; } } case R.id.action_compose: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getNewPostUrl()); } else { snackbarNoInternet.show(); } return true; } case R.id.action_search: { if (WebHelper.isOnline(MainActivity.this)) { final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); @SuppressLint("InflateParams") View layout = getLayoutInflater().inflate(R.layout.ui__dialog_search__people_tags, null, false); final EditText input = layout.findViewById(R.id.dialog_search__input); input.setMaxLines(1); input.setSingleLine(true); ThemeHelper.updateEditTextColor(input); final DialogInterface.OnClickListener clickListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int which) { String query = input.getText().toString().trim().replaceAll((which == DialogInterface.BUTTON_NEGATIVE ? "\\*" : "\\#"), ""); if (query.equals("")) { Snackbar.make(fragmentContainer, R.string.please_add_a_name, Snackbar.LENGTH_LONG).show(); } else { openDiasporaUrl(which == DialogInterface.BUTTON_NEGATIVE ? urls.getSearchPeopleUrl(query) : urls.getSearchTagsUrl(query)); } getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); imm.hideSoftInputFromWindow(input.getWindowToken(), 0); } }; final AlertDialog dialog = new ThemedAlertDialogBuilder(this, _appSettings) .setView(layout).setTitle(R.string.search_alert_title) .setCancelable(true) .setPositiveButton(R.string.by_tags, clickListener) .setNegativeButton(R.string.by_people, clickListener) .create(); input.setOnEditorActionListener(new TextView.OnEditorActionListener() { public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_DONE) { dialog.hide(); clickListener.onClick(null, 0); return true; } return false; } }); // Popup keyboard dialog.show(); input.requestFocus(); getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); } else { snackbarNoInternet.show(); } return true; } } return super.onOptionsItemSelected(item); } @Override public void onUserProfileNameChanged(DiasporaUserProfile diasporaUserProfile, String name) { AppLog.i(this, "onUserProfileNameChanged()"); // Update the profile name in the navigation slider navheaderTitle.setText(name); } @Override public void onUserProfileAvatarChanged(DiasporaUserProfile diasporaUserProfile, String avatarUrl) { AppLog.i(this, "onUserProfileAvatarChanged()"); // Update the profile picture in the navigation slider app.getAvatarImageLoader().startImageDownload(navheaderImage, avatarUrl); } /** * Handle hashtag clicks. Open the new-post-url and inject the clicked hashtag into the post-editor * * @param intent intent */ private void handleHashtag(Intent intent) { AppLog.v(this, "handleHashtag()"); try { setSharedTexts(null, intent.getData().toString().split("/")[3]); } catch (Exception e) { AppLog.e(this, e.toString()); } openDiasporaUrl(urls.getNewPostUrl()); } /** * Open the new-post-url and inject text that was shared into the app into the post editors text field * * @param intent shareTextIntent */ private void handleSendText(Intent intent) { AppLog.v(this, "handleSendText()"); try { setSharedTexts(null, intent.getStringExtra(Intent.EXTRA_TEXT)); openDiasporaUrl(urls.getNewPostUrl()); } catch (Exception e) { AppLog.e(this, e.toString()); } } /** * Handle sent text + subject * * @param intent intent */ private void handleSendSubject(Intent intent) { AppLog.v(this, "handleSendSubject()"); try { setSharedTexts(intent.getStringExtra(Intent.EXTRA_SUBJECT), intent.getStringExtra(Intent.EXTRA_TEXT)); openDiasporaUrl(urls.getNewPostUrl()); } catch (Exception e) { AppLog.e(this, e.toString()); } } /** * TODO: MOVE * Set sharedText variable to escaped and formatted subject + body. * If subject is null, only the body will be set. Else the subject will be set as header. * Depending on whether the user has the setting isAppendSharedViaApp set, a reference to * the app will be added at the bottom * * @param sharedSubject post subject or null * @param sharedBody post text */ private void setSharedTexts(String sharedSubject, String sharedBody) { AppLog.i(this, "setSharedTexts()"); String body = WebHelper.replaceUrlWithMarkdown(sharedBody); if (_appSettings.isAppendSharedViaApp()) { AppLog.v(this, "Append app reference to shared text"); body = body + "\n\n" + getString(R.string.shared_via_app); } final String escapedBody = WebHelper.escapeHtmlText(body); if (sharedSubject != null) { AppLog.v(this, "Append subject to shared text"); String escapedSubject = WebHelper.escapeHtmlText(WebHelper.replaceUrlWithMarkdown(sharedSubject)); AppLog.v(this, "Set shared text; Subject: \"" + escapedSubject + "\" Body: \"" + escapedBody + "\""); textToBeShared = "**" + escapedSubject + "** " + escapedBody; } else { AppLog.v(this, "Set shared text; Subject: \"null\" Body: \"" + sharedBody + "\""); textToBeShared = escapedBody; } } /** * Share an image shared to the app via diaspora * * @param intent shareImageIntent */ //TODO: Implement some day private void handleSendImage(Intent intent) { AppLog.i(this, "handleSendImage()"); final Uri imageUri = intent.getParcelableExtra(Intent.EXTRA_STREAM); if (imageUri != null) { AppLog.v(this, "imageUri is not null. Handle shared image"); } else { AppLog.w(this, "imageUri is null. Cannot precede."); } Toast.makeText(this, "Not yet implemented.", Toast.LENGTH_SHORT).show(); } @Override public void onNotificationCountChanged(DiasporaUserProfile diasporaUserProfile, int notificationCount) { AppLog.i(this, "onNotificationCountChanged()"); // Count saved in DiasporaUserProfile // Invalidate the top _toolbar to update the unread messages counter invalidateOptionsMenu(); } @Override public void onUnreadMessageCountChanged(DiasporaUserProfile diasporaUserProfile, int unreadMessageCount) { AppLog.i(this, "onUnreadMessageCountChanged()"); // Count saved in DiasporaUserProfile // Invalidate the top _toolbar to update the unread messages counter invalidateOptionsMenu(); } @Override public void onCustomTabsConnected() { if (customTabsSession == null) { AppLog.i(this, "CustomTabs warmup: " + customTabActivityHelper.warmup(0)); customTabsSession = customTabActivityHelper.getSession(); } } @Override public void onPodSelectionDialogResult(DiasporaPodList.DiasporaPod pod, boolean accepted) { if (accepted) { invalidateOptionsMenu(); navheaderDescription.setText(pod.getName()); } } @Override public void onCustomTabsDisconnected() { } @SuppressWarnings("StatementWithEmptyBody") @Override public boolean onNavigationItemSelected(MenuItem item) { AppLog.v(this, "onNavigationItemsSelected()"); // Handle navigation view item clicks here. switch (item.getItemId()) { case R.id.nav_stream: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getStreamUrl()); } else { snackbarNoInternet.show(); } } break; case R.id.nav_profile: { if (!_appSettings.getProfileId().equals("")) { openDiasporaUrl(urls.getProfileUrl()); } } break; case R.id.nav_followed_tags: { SearchOrCustomTextDialogCreator.showDiasporaTagsDialog(this, arg -> { if (arg.startsWith(SearchOrCustomTextDialogCreator.SPECIAL_PREFIX)) { arg = arg.replace(SearchOrCustomTextDialogCreator.SPECIAL_PREFIX, "").trim(); if (arg.equals(getString(R.string.manage_hashtags))) { openDiasporaUrl(urls.getManageTagsUrl()); } else { openDiasporaUrl(urls.getAllFollowedTagsUrl()); } } else { openDiasporaUrl(urls.getSearchTagsUrl(arg)); } }); } break; case R.id.nav_aspects: { SearchOrCustomTextDialogCreator.showDiasporaAspectsDialog(this, arg -> { if (arg.startsWith(SearchOrCustomTextDialogCreator.SPECIAL_PREFIX)) { arg = arg.replace(SearchOrCustomTextDialogCreator.SPECIAL_PREFIX, "").trim(); if (arg.equals(getString(R.string.manage_your_contact_list))) { openDiasporaUrl(urls.getContactsUrl()); } else if (arg.equals(getString(R.string.nav_profile))) { openDiasporaUrl(urls.getProfileUrl()); } } else { for (DiasporaAspect daspect : _appSettings.getAspects()) { if (arg.equals(daspect.name)) { openDiasporaUrl(urls.getAspectUrl(Long.toString(daspect.id))); break; } } } }); } break; case R.id.nav_contacts: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getContactsUrl()); } else { snackbarNoInternet.show(); } } break; case R.id.nav_activities: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getActivityUrl()); } else { snackbarNoInternet.show(); } } break; case R.id.nav_liked: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getLikedPostsUrl()); } else { snackbarNoInternet.show(); } } break; case R.id.nav_commented: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getCommentedUrl()); } else { snackbarNoInternet.show(); } } break; case R.id.nav_mentions: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getMentionsUrl()); } else { snackbarNoInternet.show(); } } break; case R.id.nav_public: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getPublicUrl()); } else { snackbarNoInternet.show(); } } break; case R.id.nav_reports: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getReportsUrl()); } else { snackbarNoInternet.show(); } } break; case R.id.nav_statistics: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getStatisticsUrl()); } else { snackbarNoInternet.show(); } } break; case R.id.nav_toggle_desktop_page: { openDiasporaUrl(urls.getToggleMobileUrl()); } break; case R.id.nav_product_support: { openDiasporaUrl(urls.getProfileUrl("d1cbdd70095301341e834860008dbc6c")); } break; case R.id.nav_exit: { moveTaskToBack(true); finish(); } break; case R.id.nav_settings: { startActivity(new Intent(this, SettingsActivity.class)); } break; case R.id.nav_about: { startActivity(new Intent(MainActivity.this, AboutActivity.class)); } break; } navDrawer.closeDrawer(GravityCompat.START); return true; } /** * React to results of requestPermission * * @param requestCode resCode * @param permissions requested permissions * @param grantResults granted results */ @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { case REQUEST_CODE__ACCESS_EXTERNAL_STORAGE: if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { AppLog.i(this, "onRequestPermissionsResult: Permission to access external storage granted"); Toast.makeText(this, R.string.permission_granted_try_again, Toast.LENGTH_SHORT).show(); } else { AppLog.w(this, "onRequestPermissionsResult: Permission to access external storage denied"); Toast.makeText(this, R.string.permission_denied, Toast.LENGTH_SHORT).show(); } return; default: super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } /** * Return the string that will be shared into the new-post-editor * * @return String */ public String getTextToBeShared() { return textToBeShared; } /** * Set the string that will be shared into the new-post-editor * * @param textToBeShared text that will be shared into the post-editor */ public void setTextToBeShared(String textToBeShared) { this.textToBeShared = textToBeShared; } @Override protected void applyColorToViews() { ThemeHelper.updateToolbarColor(toolbarTop); navDrawerLayout.setBackgroundColor(_appSettings.getPrimaryColor()); navProfilePictureArea.setBackgroundColor(_appSettings.getPrimaryColor()); if (_appSettings.isAmoledColorMode()) { navView.setItemTextColor(ColorStateList.valueOf(Color.GRAY)); navView.setItemIconTintList(ColorStateList.valueOf(Color.GRAY)); navView.setBackgroundColor(Color.BLACK); navheaderTitle.setTextColor(Color.GRAY); navheaderDescription.setTextColor(Color.DKGRAY); } int popupTheme = ContextUtils.get().shouldColorOnTopBeLight(AppSettings.get().getPrimaryColor()) ? R.style.AppTheme_PopupOverlay_Dark : R.style.AppTheme_PopupOverlay_Light; toolbarTop.setPopupTheme(popupTheme); } public void setToolbarIntellihide(boolean enable) { AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) toolbarTop.getLayoutParams(); if (enable) { AppLog.d(this, "Enable Intellihide"); params.setScrollFlags(toolbarDefaultScrollFlags); } else { AppLog.d(this, "Disable Intellihide"); params.setScrollFlags(0); // clear all scroll flags } appBarLayout.setExpanded(true, true); } }