From 62cad676e9beb9d94e8adee6033d7c11c35baf0c Mon Sep 17 00:00:00 2001 From: aleksandar-stefanovic Date: Tue, 31 Jan 2017 17:18:57 +0100 Subject: [PATCH] Add recents files to the document browser The recents mechanism works like this: Every time the file is opened, it saves that file to the shared preferences set, by putting it in the first place, and removing the oldest file from the list, if there are more than 4 recent files. It also adds dynamic App Shortcuts if the device is 7.0 and above. Screenshot: http://imgur.com/a/7kWOl Edited the layout to add a new RecyclerView for recent items, as well as the headers for both the recycler view's. Recent files appear only if in home directory, below app bar and above the file browser. This could be subjected to change in the future. Screenshot of the recents section: http://imgur.com/a/qrqZq Change-Id: I5c99aa26351d9ad2313e18b5b696d04a782e6155 Reviewed-on: https://gerrit.libreoffice.org/33759 Reviewed-by: Christian Lohmaier Tested-by: Christian Lohmaier --- .../res/layout/activity_document_browser.xml | 74 ++++++++-- .../source/res/layout/item_recent_files.xml | 34 +++++ android/source/res/values/strings.xml | 2 + .../libreoffice/ui/LibreOfficeUIActivity.java | 132 +++++++++++++++++- .../libreoffice/ui/RecentFilesAdapter.java | 92 ++++++++++++ 5 files changed, 312 insertions(+), 22 deletions(-) create mode 100644 android/source/res/layout/item_recent_files.xml create mode 100644 android/source/src/java/org/libreoffice/ui/RecentFilesAdapter.java diff --git a/android/source/res/layout/activity_document_browser.xml b/android/source/res/layout/activity_document_browser.xml index 2c1874459b19..a444d6f66b49 100644 --- a/android/source/res/layout/activity_document_browser.xml +++ b/android/source/res/layout/activity_document_browser.xml @@ -22,23 +22,67 @@ android:layout_height="match_parent"> - - + android:layout_height="match_parent"> - - + + + + + + + + + + + + + + + + + + + diff --git a/android/source/res/layout/item_recent_files.xml b/android/source/res/layout/item_recent_files.xml new file mode 100644 index 000000000000..fa966d8b554c --- /dev/null +++ b/android/source/res/layout/item_recent_files.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/android/source/res/values/strings.xml b/android/source/res/values/strings.xml index 5cf731100dd0..f02b4097723a 100644 --- a/android/source/res/values/strings.xml +++ b/android/source/res/values/strings.xml @@ -31,6 +31,8 @@ Sort by Date Preferences fileicon + Recent files + All files EXPLORER_VIEW_TYPE CURRENT_DIRECTORY diff --git a/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java b/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java index 5b79495b0cf1..c842abcc55e2 100644 --- a/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java +++ b/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java @@ -14,11 +14,15 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.content.pm.ShortcutInfo; +import android.content.pm.ShortcutManager; +import android.graphics.drawable.Icon; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; +import android.support.design.widget.NavigationView; import android.support.v4.content.ContextCompat; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBar; @@ -43,10 +47,8 @@ import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ImageView; -import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; -import android.support.design.widget.NavigationView; import org.libreoffice.AboutDialogFragment; import org.libreoffice.LibreOfficeMainActivity; @@ -66,10 +68,12 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; +import java.util.HashSet; import java.util.List; +import java.util.Set; public class LibreOfficeUIActivity extends AppCompatActivity { - private String LOGTAG = LibreOfficeUIActivity.class.getSimpleName(); + private static final String LOGTAG = LibreOfficeUIActivity.class.getSimpleName(); private SharedPreferences prefs; private int filterMode = FileUtilities.ALL; private int viewMode; @@ -85,11 +89,12 @@ public class LibreOfficeUIActivity extends AppCompatActivity { private int currentlySelectedFile; private static final String CURRENT_DIRECTORY_KEY = "CURRENT_DIRECTORY"; - private static final String DOC_PROIVDER_KEY = "CURRENT_DOCUMENT_PROVIDER"; + private static final String DOC_PROVIDER_KEY = "CURRENT_DOCUMENT_PROVIDER"; private static final String FILTER_MODE_KEY = "FILTER_MODE"; public static final String EXPLORER_VIEW_TYPE_KEY = "EXPLORER_VIEW_TYPE"; public static final String EXPLORER_PREFS_KEY = "EXPLORER_PREFS"; public static final String SORT_MODE_KEY = "SORT_MODE"; + private static final String RECENT_DOCUMENTS_KEY = "RECENT_DOCUMENTS"; public static final int GRID_VIEW = 0; public static final int LIST_VIEW = 1; @@ -97,7 +102,8 @@ public class LibreOfficeUIActivity extends AppCompatActivity { private DrawerLayout drawerLayout; private NavigationView navigationDrawer; private ActionBarDrawerToggle drawerToggle; - RecyclerView fileRecyclerView; + private RecyclerView fileRecyclerView; + private RecyclerView recentRecyclerView; private boolean canQuit = false; @@ -151,7 +157,25 @@ public class LibreOfficeUIActivity extends AppCompatActivity { }); } + recentRecyclerView = (RecyclerView) findViewById(R.id.list_recent); + + Set recentFileStrings = prefs.getStringSet(RECENT_DOCUMENTS_KEY, new HashSet()); + + final ArrayList recentFiles = new ArrayList(); + for (String recentFileString : recentFileStrings) { + try { + recentFiles.add(documentProvider.createFromUri(new URI(recentFileString))); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + } + + recentRecyclerView.setLayoutManager(new GridLayoutManager(this, 2)); + recentRecyclerView.setAdapter(new RecentFilesAdapter(this, recentFiles)); + fileRecyclerView = (RecyclerView) findViewById(R.id.file_recycler_view); + //This should be tested because it possibly disables view recycling + fileRecyclerView.setNestedScrollingEnabled(false); openDirectory(currentDirectory); registerForContextMenu(fileRecyclerView); @@ -341,6 +365,18 @@ public class LibreOfficeUIActivity extends AppCompatActivity { if (dir == null) return; + //show recent files if in home directory + if (dir.equals(homeDirectory)) { + recentRecyclerView.setVisibility(View.VISIBLE); + findViewById(R.id.header_browser).setVisibility((View.VISIBLE)); + findViewById(R.id.header_recents).setVisibility((View.VISIBLE)); + + } else { + recentRecyclerView.setVisibility(View.GONE); + findViewById(R.id.header_browser).setVisibility((View.GONE)); + findViewById(R.id.header_recents).setVisibility((View.GONE)); + } + new AsyncTask() { @Override protected Void doInBackground(IFile... dir) { @@ -374,6 +410,7 @@ public class LibreOfficeUIActivity extends AppCompatActivity { } public void open(final IFile document) { + addDocumentToRecents(document); new AsyncTask() { @Override protected File doInBackground(IFile... document) { @@ -640,7 +677,7 @@ public class LibreOfficeUIActivity extends AppCompatActivity { outState.putString(CURRENT_DIRECTORY_KEY, currentDirectory.getUri().toString()); outState.putInt(FILTER_MODE_KEY, filterMode); outState.putInt(EXPLORER_VIEW_TYPE_KEY , viewMode); - outState.putInt(DOC_PROIVDER_KEY, documentProvider.getId()); + outState.putInt(DOC_PROVIDER_KEY, documentProvider.getId()); Log.d(LOGTAG, currentDirectory.toString() + Integer.toString(filterMode) + Integer.toString(viewMode)); //prefs.edit().putInt(EXPLORER_VIEW_TYPE, viewType).commit(); @@ -657,7 +694,7 @@ public class LibreOfficeUIActivity extends AppCompatActivity { if (documentProvider == null) { Log.d(LOGTAG, "onRestoreInstanceState - documentProvider is null"); documentProvider = DocumentProviderFactory.getInstance() - .getProvider(savedInstanceState.getInt(DOC_PROIVDER_KEY)); + .getProvider(savedInstanceState.getInt(DOC_PROVIDER_KEY)); } try { currentDirectory = documentProvider.createFromUri(new URI( @@ -710,6 +747,87 @@ public class LibreOfficeUIActivity extends AppCompatActivity { return (int) (dp * scale + 0.5f); } + private void addDocumentToRecents(IFile iFile) { + String newRecent = iFile.getUri().toString(); + Set recentsSet = prefs.getStringSet(RECENT_DOCUMENTS_KEY, new HashSet()); + + //create array to work with + ArrayList recentsArrayList = new ArrayList(recentsSet); + + //remove string if present, so that it doesn't appear multiple times + recentsSet.remove(newRecent); + + //put the new value in the first place + recentsArrayList.add(0, newRecent); + + + /* + * 4 because the number of recommended items in App Shortcuts is 4, and also + * because it's a good number of recent items in general + */ + final int RECENTS_SIZE = 4; + + while (recentsArrayList.size() > RECENTS_SIZE) { + recentsArrayList.remove(RECENTS_SIZE); + } + + //switch to Set, so that it could be inserted into prefs + recentsSet = new HashSet(recentsArrayList); + + prefs.edit().putStringSet(RECENT_DOCUMENTS_KEY, recentsSet).apply(); + + + //update app shortcuts (7.0 and above) + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1) { + ShortcutManager shortcutManager = getSystemService(ShortcutManager.class); + + //Remove all shortcuts, and apply new ones. + shortcutManager.removeAllDynamicShortcuts(); + + ArrayList shortcuts = new ArrayList(); + for (String pathString : recentsArrayList) { + + //find the appropriate drawable + int drawable = 0; + switch (FileUtilities.getType(pathString)) { + case FileUtilities.DOC: + drawable = R.drawable.writer; + break; + case FileUtilities.CALC: + drawable = R.drawable.calc; + break; + case FileUtilities.DRAWING: + drawable = R.drawable.draw; + break; + case FileUtilities.IMPRESS: + drawable = R.drawable.impress; + break; + } + + File file = new File(pathString); + + //for some reason, getName uses %20 instead of space + String filename = file.getName().replace("%20", " "); + + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.fromFile(file)); + String packageName = this.getApplicationContext().getPackageName(); + ComponentName componentName = new ComponentName(packageName, LibreOfficeMainActivity.class.getName()); + intent.setComponent(componentName); + + ShortcutInfo shortcut = new ShortcutInfo.Builder(this, filename) + .setShortLabel(filename) + .setLongLabel(filename) + .setIcon(Icon.createWithResource(this, drawable)) + .setIntent(intent) + .build(); + + shortcuts.add(shortcut); + } + shortcutManager.setDynamicShortcuts(shortcuts); + } + } + + class ListItemAdapter extends RecyclerView.Adapter { private Activity mActivity; diff --git a/android/source/src/java/org/libreoffice/ui/RecentFilesAdapter.java b/android/source/src/java/org/libreoffice/ui/RecentFilesAdapter.java new file mode 100644 index 000000000000..4ebb9e06328a --- /dev/null +++ b/android/source/src/java/org/libreoffice/ui/RecentFilesAdapter.java @@ -0,0 +1,92 @@ +/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package org.libreoffice.ui; + +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import org.libreoffice.R; +import org.libreoffice.storage.IFile; + +import java.util.List; + +class RecentFilesAdapter extends RecyclerView.Adapter { + + private LibreOfficeUIActivity mActivity; + private List recentFiles; + + RecentFilesAdapter(LibreOfficeUIActivity activity, List recentFiles) { + this.mActivity = activity; + this.recentFiles = recentFiles; + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View item = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_recent_files, parent, false); + return new ViewHolder(item); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + final IFile iFile = recentFiles.get(position); + + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + mActivity.open(iFile); + } + }); + + String filename = iFile.getName(); + + holder.textView.setText(filename); + + int compoundDrawableInt = 0; + + switch (FileUtilities.getType(filename)) { + case FileUtilities.DOC: + compoundDrawableInt = R.drawable.writer; + break; + case FileUtilities.CALC: + compoundDrawableInt = R.drawable.calc; + break; + case FileUtilities.DRAWING: + compoundDrawableInt = R.drawable.draw; + break; + case FileUtilities.IMPRESS: + compoundDrawableInt = R.drawable.impress; + break; + } + holder.imageView.setImageDrawable(ContextCompat.getDrawable(mActivity, compoundDrawableInt)); + } + + @Override + public int getItemCount() { + return recentFiles.size(); + } + + class ViewHolder extends RecyclerView.ViewHolder { + + TextView textView; + ImageView imageView; + + ViewHolder(View itemView) { + super(itemView); + this.textView = (TextView) itemView.findViewById(R.id.textView); + this.imageView = (ImageView) itemView.findViewById(R.id.imageView); + } + } +}