Removed app list fragments from old 3 tab layout.
This commit is contained in:
		
							parent
							
								
									6f80fbd945
								
							
						
					
					
						commit
						65afc83b16
					
				@ -1,240 +0,0 @@
 | 
			
		||||
package org.fdroid.fdroid.views.fragments;
 | 
			
		||||
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.database.Cursor;
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
import android.os.Build;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.support.annotation.Nullable;
 | 
			
		||||
import android.support.v4.app.ActivityOptionsCompat;
 | 
			
		||||
import android.support.v4.app.ListFragment;
 | 
			
		||||
import android.support.v4.app.LoaderManager;
 | 
			
		||||
import android.support.v4.content.CursorLoader;
 | 
			
		||||
import android.support.v4.content.Loader;
 | 
			
		||||
import android.support.v4.util.Pair;
 | 
			
		||||
import android.text.TextUtils;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.widget.AdapterView;
 | 
			
		||||
import android.widget.TextView;
 | 
			
		||||
 | 
			
		||||
import org.fdroid.fdroid.AppDetails;
 | 
			
		||||
import org.fdroid.fdroid.AppDetails2;
 | 
			
		||||
import org.fdroid.fdroid.Preferences;
 | 
			
		||||
import org.fdroid.fdroid.R;
 | 
			
		||||
import org.fdroid.fdroid.UpdateService;
 | 
			
		||||
import org.fdroid.fdroid.Utils;
 | 
			
		||||
import org.fdroid.fdroid.data.App;
 | 
			
		||||
import org.fdroid.fdroid.data.Schema.AppMetadataTable;
 | 
			
		||||
import org.fdroid.fdroid.views.AppListAdapter;
 | 
			
		||||
 | 
			
		||||
public abstract class AppListFragment extends ListFragment implements
 | 
			
		||||
        AdapterView.OnItemClickListener,
 | 
			
		||||
        AdapterView.OnItemLongClickListener,
 | 
			
		||||
        Preferences.ChangeListener,
 | 
			
		||||
        LoaderManager.LoaderCallbacks<Cursor> {
 | 
			
		||||
 | 
			
		||||
    private static final String TAG = "AppListFragment";
 | 
			
		||||
 | 
			
		||||
    private static final int REQUEST_APPDETAILS = 0;
 | 
			
		||||
 | 
			
		||||
    private static final String[] APP_PROJECTION = {
 | 
			
		||||
            AppMetadataTable.Cols._ID, // Required for cursor loader to work.
 | 
			
		||||
            AppMetadataTable.Cols.Package.PACKAGE_NAME,
 | 
			
		||||
            AppMetadataTable.Cols.NAME,
 | 
			
		||||
            AppMetadataTable.Cols.SUMMARY,
 | 
			
		||||
            AppMetadataTable.Cols.IS_COMPATIBLE,
 | 
			
		||||
            AppMetadataTable.Cols.LICENSE,
 | 
			
		||||
            AppMetadataTable.Cols.ICON,
 | 
			
		||||
            AppMetadataTable.Cols.ICON_URL,
 | 
			
		||||
            AppMetadataTable.Cols.InstalledApp.VERSION_CODE,
 | 
			
		||||
            AppMetadataTable.Cols.InstalledApp.VERSION_NAME,
 | 
			
		||||
            AppMetadataTable.Cols.SuggestedApk.VERSION_NAME,
 | 
			
		||||
            AppMetadataTable.Cols.SUGGESTED_VERSION_CODE,
 | 
			
		||||
            AppMetadataTable.Cols.REQUIREMENTS, // Needed for filtering apps that require root.
 | 
			
		||||
            AppMetadataTable.Cols.ANTI_FEATURES, // Needed for filtering apps that require anti-features.
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    private static final String APP_SORT = AppMetadataTable.Cols.NAME;
 | 
			
		||||
 | 
			
		||||
    private AppListAdapter appAdapter;
 | 
			
		||||
 | 
			
		||||
    @Nullable private String searchQuery;
 | 
			
		||||
 | 
			
		||||
    protected abstract AppListAdapter getAppListAdapter();
 | 
			
		||||
 | 
			
		||||
    protected abstract String getFromTitle();
 | 
			
		||||
 | 
			
		||||
    protected abstract Uri getDataUri();
 | 
			
		||||
 | 
			
		||||
    protected abstract Uri getDataUri(String query);
 | 
			
		||||
 | 
			
		||||
    protected abstract int getEmptyMessage();
 | 
			
		||||
 | 
			
		||||
    protected abstract int getNoSearchResultsMessage();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Subclasses can choose to do different things based on when a user begins searching.
 | 
			
		||||
     * For example, the "Available" tab chooses to hide its category spinner to make it clear
 | 
			
		||||
     * that it is searching all apps, not the current category.
 | 
			
		||||
     * NOTE: This will get called <em>multiple</em> times, every time the user changes the
 | 
			
		||||
     * search query.
 | 
			
		||||
     */
 | 
			
		||||
    void onSearch() {
 | 
			
		||||
        // Do nothing by default.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Alerts the child class that the user is no longer performing a search.
 | 
			
		||||
     * This is triggered every time the search query is blank.
 | 
			
		||||
     *
 | 
			
		||||
     * @see AppListFragment#onSearch()
 | 
			
		||||
     */
 | 
			
		||||
    protected void onSearchStopped() {
 | 
			
		||||
        // Do nothing by default.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Utility function to set empty view text which should be different
 | 
			
		||||
     * depending on whether search is active or not.
 | 
			
		||||
     */
 | 
			
		||||
    private void setEmptyText(int resId) {
 | 
			
		||||
        ((TextView) getListView().getEmptyView()).setText(resId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onActivityCreated(Bundle savedInstanceState) {
 | 
			
		||||
        super.onActivityCreated(savedInstanceState);
 | 
			
		||||
 | 
			
		||||
        // Can't do this in the onCreate view, because "onCreateView" which
 | 
			
		||||
        // returns the list view is "called between onCreate and
 | 
			
		||||
        // onActivityCreated" according to the docs.
 | 
			
		||||
        getListView().setOnItemClickListener(this);
 | 
			
		||||
        getListView().setOnItemLongClickListener(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onResume() {
 | 
			
		||||
        super.onResume();
 | 
			
		||||
 | 
			
		||||
        //Starts a new or restarts an existing Loader in this manager
 | 
			
		||||
        getLoaderManager().initLoader(0, null, this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onCreate(Bundle savedInstanceState) {
 | 
			
		||||
        super.onCreate(savedInstanceState);
 | 
			
		||||
 | 
			
		||||
        appAdapter = getAppListAdapter();
 | 
			
		||||
 | 
			
		||||
        if (appAdapter.getCount() == 0) {
 | 
			
		||||
            updateEmptyRepos();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        setListAdapter(appAdapter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The first time the app is run, we will have an empty app list.
 | 
			
		||||
     * If this is the case, we will attempt to update with the default repo.
 | 
			
		||||
     * However, if we have tried this at least once, then don't try to do
 | 
			
		||||
     * it automatically again, because the repos or internet connection may
 | 
			
		||||
     * be bad.
 | 
			
		||||
     */
 | 
			
		||||
    private boolean updateEmptyRepos() {
 | 
			
		||||
        Preferences prefs = Preferences.get();
 | 
			
		||||
        if (!prefs.hasTriedEmptyUpdate()) {
 | 
			
		||||
            Utils.debugLog(TAG, "Empty app list, and we haven't done an update yet. Forcing repo update.");
 | 
			
		||||
            prefs.setTriedEmptyUpdate(true);
 | 
			
		||||
            UpdateService.updateNow(getActivity());
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        Utils.debugLog(TAG, "Empty app list, but it looks like we've had an update previously. Will not force repo update.");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
 | 
			
		||||
        showItemDetails(view, position, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
 | 
			
		||||
        showItemDetails(view, position, true);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void showItemDetails(View view, int position, boolean useNewDetailsActivity) {
 | 
			
		||||
        // Cursor is null in the swap list when touching the first item.
 | 
			
		||||
        Cursor cursor = (Cursor) getListView().getItemAtPosition(position);
 | 
			
		||||
        if (cursor != null) {
 | 
			
		||||
            final App app = new App(cursor);
 | 
			
		||||
            Intent intent = getAppDetailsIntent(useNewDetailsActivity);
 | 
			
		||||
            intent.putExtra(AppDetails2.EXTRA_APPID, app.packageName);
 | 
			
		||||
            intent.putExtra(AppDetails.EXTRA_FROM, getFromTitle());
 | 
			
		||||
            if (Build.VERSION.SDK_INT >= 21) {
 | 
			
		||||
                Pair<View, String> iconTransitionPair = Pair.create(view.findViewById(R.id.icon),
 | 
			
		||||
                        getString(R.string.transition_app_item_icon));
 | 
			
		||||
                Bundle bundle = ActivityOptionsCompat
 | 
			
		||||
                        .makeSceneTransitionAnimation(getActivity(),
 | 
			
		||||
                                iconTransitionPair)
 | 
			
		||||
                        .toBundle();
 | 
			
		||||
                startActivityForResult(intent, REQUEST_APPDETAILS, bundle);
 | 
			
		||||
            } else {
 | 
			
		||||
                startActivityForResult(intent, REQUEST_APPDETAILS);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Intent getAppDetailsIntent(boolean useNewDetailsActivity) {
 | 
			
		||||
        return new Intent(getActivity(), useNewDetailsActivity ? AppDetails2.class : AppDetails.class);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onPreferenceChange() {
 | 
			
		||||
        getAppListAdapter().notifyDataSetChanged();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
 | 
			
		||||
        appAdapter.swapCursor(data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onLoaderReset(Loader<Cursor> loader) {
 | 
			
		||||
        appAdapter.swapCursor(null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
 | 
			
		||||
        Uri uri = updateSearchStatus() ? getDataUri(searchQuery) : getDataUri();
 | 
			
		||||
        return new CursorLoader(
 | 
			
		||||
                getActivity(), uri, APP_PROJECTION, null, null, APP_SORT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Notifies the subclass via {@link AppListFragment#onSearch()} and {@link AppListFragment#onSearchStopped()}
 | 
			
		||||
     * about whether or not a search is taking place and changes empty message
 | 
			
		||||
     * appropriately.
 | 
			
		||||
     *
 | 
			
		||||
     * @return True if a user is searching.
 | 
			
		||||
     */
 | 
			
		||||
    private boolean updateSearchStatus() {
 | 
			
		||||
        if (TextUtils.isEmpty(searchQuery)) {
 | 
			
		||||
            onSearchStopped();
 | 
			
		||||
            setEmptyText(getEmptyMessage());
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        onSearch();
 | 
			
		||||
        setEmptyText(getNoSearchResultsMessage());
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void updateSearchQuery(@Nullable String query) {
 | 
			
		||||
        if (!TextUtils.equals(query, searchQuery)) {
 | 
			
		||||
            searchQuery = query;
 | 
			
		||||
            if (isAdded()) {
 | 
			
		||||
                getLoaderManager().restartLoader(0, null, this);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,253 +0,0 @@
 | 
			
		||||
package org.fdroid.fdroid.views.fragments;
 | 
			
		||||
 | 
			
		||||
import android.app.Activity;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.SharedPreferences;
 | 
			
		||||
import android.content.res.Resources;
 | 
			
		||||
import android.database.ContentObserver;
 | 
			
		||||
import android.database.Cursor;
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
import android.os.AsyncTask;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.os.Handler;
 | 
			
		||||
import android.os.Looper;
 | 
			
		||||
import android.support.annotation.Nullable;
 | 
			
		||||
import android.support.v4.app.LoaderManager;
 | 
			
		||||
import android.view.LayoutInflater;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.view.ViewGroup;
 | 
			
		||||
import android.widget.AdapterView;
 | 
			
		||||
import android.widget.ArrayAdapter;
 | 
			
		||||
import android.widget.Spinner;
 | 
			
		||||
 | 
			
		||||
import org.fdroid.fdroid.Preferences;
 | 
			
		||||
import org.fdroid.fdroid.R;
 | 
			
		||||
import org.fdroid.fdroid.Utils;
 | 
			
		||||
import org.fdroid.fdroid.compat.ArrayAdapterCompat;
 | 
			
		||||
import org.fdroid.fdroid.compat.CursorAdapterCompat;
 | 
			
		||||
import org.fdroid.fdroid.data.AppProvider;
 | 
			
		||||
import org.fdroid.fdroid.data.CategoryProvider;
 | 
			
		||||
import org.fdroid.fdroid.views.AppListAdapter;
 | 
			
		||||
import org.fdroid.fdroid.views.AvailableAppListAdapter;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
public class AvailableAppsFragment extends AppListFragment implements
 | 
			
		||||
        LoaderManager.LoaderCallbacks<Cursor> {
 | 
			
		||||
 | 
			
		||||
    private static final String TAG = "AvailableAppsFragment";
 | 
			
		||||
 | 
			
		||||
    private static final String PREFERENCES_FILE = "CategorySpinnerPosition";
 | 
			
		||||
    private static final String CATEGORY_KEY = "Selection";
 | 
			
		||||
    private static String defaultCategory;
 | 
			
		||||
 | 
			
		||||
    private List<String> categories;
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    private View categoryWrapper;
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    private Spinner categorySpinner;
 | 
			
		||||
    private String currentCategory;
 | 
			
		||||
    private AppListAdapter adapter;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected String getFromTitle() {
 | 
			
		||||
        return getString(R.string.tab_available_apps);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected AppListAdapter getAppListAdapter() {
 | 
			
		||||
        if (adapter == null) {
 | 
			
		||||
            final AppListAdapter a = AvailableAppListAdapter.create(getActivity(), null, CursorAdapterCompat.FLAG_AUTO_REQUERY);
 | 
			
		||||
            Preferences.get().registerUpdateHistoryListener(new Preferences.ChangeListener() {
 | 
			
		||||
                @Override
 | 
			
		||||
                public void onPreferenceChange() {
 | 
			
		||||
                    a.notifyDataSetChanged();
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            adapter = a;
 | 
			
		||||
        }
 | 
			
		||||
        return adapter;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private class CategoryObserver extends ContentObserver {
 | 
			
		||||
 | 
			
		||||
        private final ArrayAdapter<String> adapter;
 | 
			
		||||
 | 
			
		||||
        CategoryObserver(ArrayAdapter<String> adapter) {
 | 
			
		||||
            // Using Looper.getMainLooper() ensures that the onChange method is run on the main thread.
 | 
			
		||||
            super(new Handler(Looper.getMainLooper()));
 | 
			
		||||
            this.adapter = adapter;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onChange(boolean selfChange) {
 | 
			
		||||
            final Activity activity = getActivity();
 | 
			
		||||
            if (!isAdded() || adapter == null || activity == null) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Because onChange is always invoked on the main thread (see constructor), we want to
 | 
			
		||||
            // run the database query on a background thread. Afterwards, the UI is updated
 | 
			
		||||
            // on a foreground thread.
 | 
			
		||||
            new AsyncTask<Void, Void, List<String>>() {
 | 
			
		||||
                @Override
 | 
			
		||||
                protected List<String> doInBackground(Void... params) {
 | 
			
		||||
                    return CategoryProvider.Helper.categories(activity);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
                protected void onPostExecute(List<String> loadedCategories) {
 | 
			
		||||
                    adapter.clear();
 | 
			
		||||
                    categories = loadedCategories;
 | 
			
		||||
                    ArrayAdapterCompat.addAll(adapter, translateCategories(activity, loadedCategories));
 | 
			
		||||
                }
 | 
			
		||||
            }.execute();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onChange(boolean selfChange, Uri uri) {
 | 
			
		||||
            onChange(selfChange);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Attempt to translate category names with fallback to default name if no translation available
 | 
			
		||||
     */
 | 
			
		||||
    private static List<String> translateCategories(Context context, List<String> categories) {
 | 
			
		||||
        List<String> translatedCategories = new ArrayList<>(categories.size());
 | 
			
		||||
        Resources res = context.getResources();
 | 
			
		||||
        String pkgName = context.getPackageName();
 | 
			
		||||
        for (String category : categories) {
 | 
			
		||||
            String resId = category.replace(" & ", "_").replace(" ", "_").replace("'", "");
 | 
			
		||||
            int id = res.getIdentifier("category_" + resId, "string", pkgName);
 | 
			
		||||
            translatedCategories.add(id == 0 ? category : context.getString(id));
 | 
			
		||||
        }
 | 
			
		||||
        return translatedCategories;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Spinner setupCategorySpinner(Spinner spinner) {
 | 
			
		||||
 | 
			
		||||
        categorySpinner = spinner;
 | 
			
		||||
        categorySpinner.setId(R.id.category_spinner);
 | 
			
		||||
 | 
			
		||||
        categories = CategoryProvider.Helper.categories(getActivity());
 | 
			
		||||
 | 
			
		||||
        ArrayAdapter<String> adapter = new ArrayAdapter<>(
 | 
			
		||||
                getActivity(), android.R.layout.simple_spinner_item, translateCategories(getActivity(), categories));
 | 
			
		||||
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
 | 
			
		||||
        categorySpinner.setAdapter(adapter);
 | 
			
		||||
 | 
			
		||||
        getActivity().getContentResolver().registerContentObserver(
 | 
			
		||||
                AppProvider.getContentUri(), false, new CategoryObserver(adapter));
 | 
			
		||||
 | 
			
		||||
        categorySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
 | 
			
		||||
                getListView().setSelection(0);
 | 
			
		||||
                setCurrentCategory(categories.get(pos));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onNothingSelected(AdapterView<?> parent) {
 | 
			
		||||
                setCurrentCategory(null);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        return categorySpinner;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
 | 
			
		||||
        View view = inflater.inflate(R.layout.available_app_list, container, false);
 | 
			
		||||
 | 
			
		||||
        categoryWrapper = view.findViewById(R.id.category_wrapper);
 | 
			
		||||
        setupCategorySpinner((Spinner) view.findViewById(R.id.category_spinner));
 | 
			
		||||
        defaultCategory = CategoryProvider.Helper.getCategoryWhatsNew(getActivity());
 | 
			
		||||
 | 
			
		||||
        return view;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected Uri getDataUri() {
 | 
			
		||||
        if (currentCategory == null || currentCategory.equals(CategoryProvider.Helper.getCategoryAll(getActivity()))) {
 | 
			
		||||
            return AppProvider.getContentUri();
 | 
			
		||||
        }
 | 
			
		||||
        if (currentCategory.equals(CategoryProvider.Helper.getCategoryRecentlyUpdated(getActivity()))) {
 | 
			
		||||
            return AppProvider.getRecentlyUpdatedUri();
 | 
			
		||||
        }
 | 
			
		||||
        if (currentCategory.equals(CategoryProvider.Helper.getCategoryWhatsNew(getActivity()))) {
 | 
			
		||||
            // Removed this feature in the new UI. this fragment will be gone soon so not implementing it again.
 | 
			
		||||
            // return AppProvider.getNewlyAddedUri();
 | 
			
		||||
            return AppProvider.getRecentlyUpdatedUri();
 | 
			
		||||
        }
 | 
			
		||||
        return AppProvider.getCategoryUri(currentCategory);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected Uri getDataUri(String query) {
 | 
			
		||||
        return AppProvider.getSearchUri(query, null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected int getEmptyMessage() {
 | 
			
		||||
        return R.string.empty_available_app_list;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected int getNoSearchResultsMessage() {
 | 
			
		||||
        return R.string.empty_search_available_app_list;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void setCurrentCategory(String category) {
 | 
			
		||||
        currentCategory = category;
 | 
			
		||||
        Utils.debugLog(TAG, "Category '" + currentCategory + "' selected.");
 | 
			
		||||
        getLoaderManager().restartLoader(0, null, this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onResume() {
 | 
			
		||||
        /* restore the saved Category Spinner position */
 | 
			
		||||
        Activity activity = getActivity();
 | 
			
		||||
        SharedPreferences p = activity.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE);
 | 
			
		||||
        currentCategory = p.getString(CATEGORY_KEY, defaultCategory);
 | 
			
		||||
 | 
			
		||||
        if (categorySpinner != null) {
 | 
			
		||||
            for (int i = 0; i < categorySpinner.getCount(); i++) {
 | 
			
		||||
                if (currentCategory.equals(categorySpinner.getItemAtPosition(i).toString())) {
 | 
			
		||||
                    categorySpinner.setSelection(i);
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        setCurrentCategory(currentCategory);
 | 
			
		||||
        super.onResume();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onPause() {
 | 
			
		||||
        super.onPause();
 | 
			
		||||
        /* store the Category Spinner position for when we come back */
 | 
			
		||||
        SharedPreferences p = getActivity().getSharedPreferences(PREFERENCES_FILE,
 | 
			
		||||
                Context.MODE_PRIVATE);
 | 
			
		||||
        SharedPreferences.Editor e = p.edit();
 | 
			
		||||
        e.putString(CATEGORY_KEY, currentCategory);
 | 
			
		||||
        e.apply();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void onSearch() {
 | 
			
		||||
        if (categoryWrapper != null) {
 | 
			
		||||
            categoryWrapper.setVisibility(View.GONE);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void onSearchStopped() {
 | 
			
		||||
        if (categoryWrapper != null) {
 | 
			
		||||
            categoryWrapper.setVisibility(View.VISIBLE);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,52 +0,0 @@
 | 
			
		||||
package org.fdroid.fdroid.views.fragments;
 | 
			
		||||
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.view.LayoutInflater;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.view.ViewGroup;
 | 
			
		||||
 | 
			
		||||
import org.fdroid.fdroid.R;
 | 
			
		||||
import org.fdroid.fdroid.compat.CursorAdapterCompat;
 | 
			
		||||
import org.fdroid.fdroid.data.AppProvider;
 | 
			
		||||
import org.fdroid.fdroid.views.AppListAdapter;
 | 
			
		||||
import org.fdroid.fdroid.views.CanUpdateAppListAdapter;
 | 
			
		||||
 | 
			
		||||
public class CanUpdateAppsFragment extends AppListFragment {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected AppListAdapter getAppListAdapter() {
 | 
			
		||||
        return CanUpdateAppListAdapter.create(getActivity(), null, CursorAdapterCompat.FLAG_AUTO_REQUERY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected String getFromTitle() {
 | 
			
		||||
        return getString(R.string.tab_updates);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected Uri getDataUri() {
 | 
			
		||||
        return AppProvider.getCanUpdateUri();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected Uri getDataUri(String query) {
 | 
			
		||||
        return AppProvider.getSearchCanUpdateUri(query);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected int getEmptyMessage() {
 | 
			
		||||
        return R.string.empty_can_update_app_list;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected int getNoSearchResultsMessage() {
 | 
			
		||||
        return R.string.empty_search_can_update_app_list;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
 | 
			
		||||
        return inflater.inflate(R.layout.can_update_app_list, container, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -1,52 +0,0 @@
 | 
			
		||||
package org.fdroid.fdroid.views.fragments;
 | 
			
		||||
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.view.LayoutInflater;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.view.ViewGroup;
 | 
			
		||||
 | 
			
		||||
import org.fdroid.fdroid.R;
 | 
			
		||||
import org.fdroid.fdroid.compat.CursorAdapterCompat;
 | 
			
		||||
import org.fdroid.fdroid.data.AppProvider;
 | 
			
		||||
import org.fdroid.fdroid.views.AppListAdapter;
 | 
			
		||||
import org.fdroid.fdroid.views.InstalledAppListAdapter;
 | 
			
		||||
 | 
			
		||||
public class InstalledAppsFragment extends AppListFragment {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected AppListAdapter getAppListAdapter() {
 | 
			
		||||
        return InstalledAppListAdapter.create(getActivity(), null, CursorAdapterCompat.FLAG_AUTO_REQUERY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected String getFromTitle() {
 | 
			
		||||
        return getString(R.string.tab_installed_apps);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected Uri getDataUri() {
 | 
			
		||||
        return AppProvider.getInstalledUri();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected Uri getDataUri(String query) {
 | 
			
		||||
        return AppProvider.getSearchInstalledUri(query);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected int getEmptyMessage() {
 | 
			
		||||
        return R.string.empty_installed_app_list;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected int getNoSearchResultsMessage() {
 | 
			
		||||
        return R.string.empty_search_installed_app_list;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
 | 
			
		||||
        return inflater.inflate(R.layout.installed_app_list, container, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -1,104 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:tools="http://schemas.android.com/tools"
 | 
			
		||||
    android:orientation="horizontal"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="?attr/listPreferredItemHeight"
 | 
			
		||||
    android:paddingLeft="?attr/listPreferredItemPaddingLeft"
 | 
			
		||||
    android:paddingStart="?attr/listPreferredItemPaddingLeft"
 | 
			
		||||
    android:paddingRight="?attr/listPreferredItemPaddingRight"
 | 
			
		||||
    android:paddingEnd="?attr/listPreferredItemPaddingRight"
 | 
			
		||||
    android:baselineAligned="false"
 | 
			
		||||
    >
 | 
			
		||||
 | 
			
		||||
    <ImageView
 | 
			
		||||
        android:id="@+id/icon"
 | 
			
		||||
        android:contentDescription="@string/app_icon"
 | 
			
		||||
        android:layout_width="48dip"
 | 
			
		||||
        android:layout_height="48dip"
 | 
			
		||||
        android:layout_gravity="center_vertical"
 | 
			
		||||
        android:scaleType="fitCenter"
 | 
			
		||||
        tools:src="@drawable/ic_launcher"
 | 
			
		||||
        android:transitionName="@string/transition_app_item_icon" />
 | 
			
		||||
 | 
			
		||||
    <LinearLayout
 | 
			
		||||
        android:orientation="vertical"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:layout_gravity="center_vertical"
 | 
			
		||||
        android:baselineAligned="false">
 | 
			
		||||
 | 
			
		||||
        <LinearLayout
 | 
			
		||||
            android:orientation="horizontal"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:baselineAligned="false">
 | 
			
		||||
 | 
			
		||||
            <TextView android:id="@+id/name"
 | 
			
		||||
                android:textSize="16sp"
 | 
			
		||||
                android:maxLines="1"
 | 
			
		||||
                android:ellipsize="end"
 | 
			
		||||
                android:layout_width="wrap_content"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:paddingStart="?attr/listPreferredItemPaddingLeft"
 | 
			
		||||
                android:paddingEnd="?attr/listPreferredItemPaddingRight"
 | 
			
		||||
                android:layout_gravity="center_vertical"
 | 
			
		||||
                android:gravity="start"
 | 
			
		||||
                android:textAlignment="viewStart"
 | 
			
		||||
                tools:text="F-Droid" />
 | 
			
		||||
 | 
			
		||||
            <TextView android:id="@+id/status"
 | 
			
		||||
                android:textSize="14sp"
 | 
			
		||||
                android:maxLines="1"
 | 
			
		||||
                android:ellipsize="end"
 | 
			
		||||
                android:layout_weight="1"
 | 
			
		||||
                android:layout_width="0dp"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:layout_gravity="center_vertical"
 | 
			
		||||
                android:gravity="end"
 | 
			
		||||
                android:textAlignment="viewEnd"
 | 
			
		||||
                tools:text="Installed" />
 | 
			
		||||
 | 
			
		||||
        </LinearLayout>
 | 
			
		||||
 | 
			
		||||
        <LinearLayout
 | 
			
		||||
            android:orientation="horizontal"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:baselineAligned="false">
 | 
			
		||||
 | 
			
		||||
            <TextView android:id="@+id/summary"
 | 
			
		||||
                android:textSize="14sp"
 | 
			
		||||
                android:textColor="?android:attr/textColorSecondary"
 | 
			
		||||
                android:singleLine="true"
 | 
			
		||||
                android:ellipsize="end"
 | 
			
		||||
                android:layout_weight="1"
 | 
			
		||||
                android:layout_width="wrap_content"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:layout_gravity="center_vertical"
 | 
			
		||||
                android:paddingLeft="?attr/listPreferredItemPaddingLeft"
 | 
			
		||||
                android:paddingStart="?attr/listPreferredItemPaddingLeft"
 | 
			
		||||
                android:paddingRight="?attr/listPreferredItemPaddingRight"
 | 
			
		||||
                android:paddingEnd="?attr/listPreferredItemPaddingRight"
 | 
			
		||||
                android:gravity="start"
 | 
			
		||||
                android:textAlignment="viewStart"
 | 
			
		||||
                tools:text="Application manager" />
 | 
			
		||||
 | 
			
		||||
            <TextView android:id="@+id/license"
 | 
			
		||||
                android:textSize="14sp"
 | 
			
		||||
                android:textColor="?android:attr/textColorSecondary"
 | 
			
		||||
                android:singleLine="true"
 | 
			
		||||
                android:ellipsize="end"
 | 
			
		||||
                android:layout_weight="0"
 | 
			
		||||
                android:layout_width="wrap_content"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:layout_gravity="center_vertical"
 | 
			
		||||
                android:gravity="end"
 | 
			
		||||
                android:textAlignment="viewEnd"
 | 
			
		||||
                tools:text="GPLv3+" />
 | 
			
		||||
 | 
			
		||||
        </LinearLayout>
 | 
			
		||||
 | 
			
		||||
    </LinearLayout>
 | 
			
		||||
 | 
			
		||||
</LinearLayout>
 | 
			
		||||
@ -1,104 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:tools="http://schemas.android.com/tools"
 | 
			
		||||
    android:orientation="horizontal"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="?attr/listPreferredItemHeight"
 | 
			
		||||
    android:paddingLeft="?attr/listPreferredItemPaddingLeft"
 | 
			
		||||
    android:paddingStart="?attr/listPreferredItemPaddingLeft"
 | 
			
		||||
    android:paddingRight="?attr/listPreferredItemPaddingRight"
 | 
			
		||||
    android:paddingEnd="?attr/listPreferredItemPaddingRight"
 | 
			
		||||
    android:baselineAligned="false">
 | 
			
		||||
 | 
			
		||||
    <ImageView
 | 
			
		||||
        android:id="@+id/icon"
 | 
			
		||||
        android:contentDescription="@string/app_icon"
 | 
			
		||||
        android:layout_width="48dip"
 | 
			
		||||
        android:layout_height="48dip"
 | 
			
		||||
        android:layout_gravity="center_vertical"
 | 
			
		||||
        android:scaleType="fitCenter"
 | 
			
		||||
        tools:src="@drawable/ic_launcher" />
 | 
			
		||||
 | 
			
		||||
    <LinearLayout
 | 
			
		||||
        android:orientation="vertical"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:layout_gravity="center_vertical"
 | 
			
		||||
        android:baselineAligned="false">
 | 
			
		||||
 | 
			
		||||
        <LinearLayout
 | 
			
		||||
            android:orientation="horizontal"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:baselineAligned="false">
 | 
			
		||||
 | 
			
		||||
            <TextView android:id="@+id/name"
 | 
			
		||||
                android:textSize="16sp"
 | 
			
		||||
                android:maxLines="1"
 | 
			
		||||
                android:ellipsize="end"
 | 
			
		||||
                android:layout_width="wrap_content"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:paddingLeft="?attr/listPreferredItemPaddingLeft"
 | 
			
		||||
                android:paddingStart="?attr/listPreferredItemPaddingLeft"
 | 
			
		||||
                android:paddingRight="?attr/listPreferredItemPaddingRight"
 | 
			
		||||
                android:paddingEnd="?attr/listPreferredItemPaddingRight"
 | 
			
		||||
                android:layout_gravity="center_vertical"
 | 
			
		||||
                android:gravity="start"
 | 
			
		||||
                android:textAlignment="viewStart"
 | 
			
		||||
                tools:text="F-Droid" />
 | 
			
		||||
 | 
			
		||||
            <TextView android:id="@+id/status"
 | 
			
		||||
                android:textSize="14sp"
 | 
			
		||||
                android:maxLines="1"
 | 
			
		||||
                android:ellipsize="end"
 | 
			
		||||
                android:layout_weight="1"
 | 
			
		||||
                android:layout_width="0dp"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:layout_gravity="center_vertical"
 | 
			
		||||
                android:gravity="end"
 | 
			
		||||
                android:textAlignment="viewEnd"
 | 
			
		||||
                tools:text="Installed" />
 | 
			
		||||
 | 
			
		||||
        </LinearLayout>
 | 
			
		||||
 | 
			
		||||
        <LinearLayout
 | 
			
		||||
            android:orientation="horizontal"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:baselineAligned="false">
 | 
			
		||||
 | 
			
		||||
            <TextView android:id="@+id/summary"
 | 
			
		||||
                android:textSize="14sp"
 | 
			
		||||
                android:textColor="?android:attr/textColorSecondary"
 | 
			
		||||
                android:singleLine="true"
 | 
			
		||||
                android:ellipsize="end"
 | 
			
		||||
                android:layout_weight="1"
 | 
			
		||||
                android:layout_width="wrap_content"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:layout_gravity="center_vertical"
 | 
			
		||||
                android:paddingLeft="?attr/listPreferredItemPaddingLeft"
 | 
			
		||||
                android:paddingStart="?attr/listPreferredItemPaddingLeft"
 | 
			
		||||
                android:paddingRight="?attr/listPreferredItemPaddingRight"
 | 
			
		||||
                android:paddingEnd="?attr/listPreferredItemPaddingRight"
 | 
			
		||||
                android:gravity="start"
 | 
			
		||||
                android:textAlignment="viewStart"
 | 
			
		||||
                tools:text="Application manager" />
 | 
			
		||||
 | 
			
		||||
            <TextView android:id="@+id/license"
 | 
			
		||||
                android:textSize="14sp"
 | 
			
		||||
                android:textColor="?android:attr/textColorSecondary"
 | 
			
		||||
                android:singleLine="true"
 | 
			
		||||
                android:ellipsize="end"
 | 
			
		||||
                android:layout_weight="0"
 | 
			
		||||
                android:layout_width="wrap_content"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:layout_gravity="center_vertical"
 | 
			
		||||
                android:gravity="end"
 | 
			
		||||
                android:textAlignment="viewEnd"
 | 
			
		||||
                tools:text="GPLv3+" />
 | 
			
		||||
 | 
			
		||||
        </LinearLayout>
 | 
			
		||||
 | 
			
		||||
    </LinearLayout>
 | 
			
		||||
 | 
			
		||||
</LinearLayout>
 | 
			
		||||
@ -1,38 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<RelativeLayout
 | 
			
		||||
    xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="match_parent">
 | 
			
		||||
 | 
			
		||||
    <RelativeLayout
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:id="@+id/category_wrapper"
 | 
			
		||||
        android:layout_alignParentTop="true">
 | 
			
		||||
 | 
			
		||||
        <Spinner
 | 
			
		||||
            android:id="@+id/category_spinner"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="48dp"
 | 
			
		||||
            android:layout_marginLeft="8dp"
 | 
			
		||||
            android:layout_marginRight="8dp"
 | 
			
		||||
            android:paddingBottom="1dp" />
 | 
			
		||||
 | 
			
		||||
        <View
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="2dp"
 | 
			
		||||
            android:layout_alignBottom="@id/category_spinner"
 | 
			
		||||
            android:background="@color/fdroid_green" />
 | 
			
		||||
 | 
			
		||||
    </RelativeLayout>
 | 
			
		||||
 | 
			
		||||
    <ListView
 | 
			
		||||
        style="@style/AppList"
 | 
			
		||||
        android:layout_below="@id/category_wrapper" />
 | 
			
		||||
 | 
			
		||||
    <TextView
 | 
			
		||||
        style="@style/AppListEmptyText"
 | 
			
		||||
        android:layout_below="@id/category_wrapper"
 | 
			
		||||
        android:text="@string/empty_available_app_list" />
 | 
			
		||||
 | 
			
		||||
</RelativeLayout>
 | 
			
		||||
@ -1,14 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<RelativeLayout
 | 
			
		||||
    xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="match_parent">
 | 
			
		||||
 | 
			
		||||
    <ListView
 | 
			
		||||
        style="@style/AppList" />
 | 
			
		||||
 | 
			
		||||
    <TextView
 | 
			
		||||
        style="@style/AppListEmptyText"
 | 
			
		||||
        android:text="@string/empty_can_update_app_list" />
 | 
			
		||||
 | 
			
		||||
</RelativeLayout>
 | 
			
		||||
@ -1,14 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<RelativeLayout
 | 
			
		||||
    xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="match_parent">
 | 
			
		||||
 | 
			
		||||
    <ListView
 | 
			
		||||
        style="@style/AppList" />
 | 
			
		||||
 | 
			
		||||
    <TextView
 | 
			
		||||
        style="@style/AppListEmptyText"
 | 
			
		||||
        android:text="@string/empty_installed_app_list" />
 | 
			
		||||
 | 
			
		||||
</RelativeLayout>
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user