This commit is contained in:
Christopher Beckmann 2017-10-26 13:25:53 +02:00
commit 2159c59c3e
5 changed files with 1 additions and 573 deletions

View file

@ -24,18 +24,6 @@
android:value="org.secuso.privacyfriendlybreakreminder.activities.TimerActivity" />
</activity>
<receiver
android:name=".widget.AppWidget"
android:label="Resizable Widget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/app_widget2x1_info" />
</receiver>
<activity
android:name=".activities.SplashActivity"
android:theme="@style/SplashTheme"

View file

@ -30,7 +30,7 @@ public class HelpActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_help);
//addPreferencesFromResource(R.xml.pref_help);
}
}

View file

@ -1,109 +0,0 @@
package org.secuso.privacyfriendlybreakreminder.activities.helper;
import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.widget.Toolbar;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls
* to be used with AppCompat.
*/
public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
private AppCompatDelegate mDelegate;
@Override
protected void onCreate(Bundle savedInstanceState) {
getDelegate().installViewFactory();
getDelegate().onCreate(savedInstanceState);
super.onCreate(savedInstanceState);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
getDelegate().onPostCreate(savedInstanceState);
}
public ActionBar getSupportActionBar() {
return getDelegate().getSupportActionBar();
}
public void setSupportActionBar(@Nullable Toolbar toolbar) {
getDelegate().setSupportActionBar(toolbar);
}
@Override
public MenuInflater getMenuInflater() {
return getDelegate().getMenuInflater();
}
@Override
public void setContentView(@LayoutRes int layoutResID) {
getDelegate().setContentView(layoutResID);
}
@Override
public void setContentView(View view) {
getDelegate().setContentView(view);
}
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
getDelegate().setContentView(view, params);
}
@Override
public void addContentView(View view, ViewGroup.LayoutParams params) {
getDelegate().addContentView(view, params);
}
@Override
protected void onPostResume() {
super.onPostResume();
getDelegate().onPostResume();
}
@Override
protected void onTitleChanged(CharSequence title, int color) {
super.onTitleChanged(title, color);
getDelegate().setTitle(title);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
getDelegate().onConfigurationChanged(newConfig);
}
@Override
protected void onStop() {
super.onStop();
getDelegate().onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
getDelegate().onDestroy();
}
public void invalidateOptionsMenu() {
getDelegate().invalidateOptionsMenu();
}
private AppCompatDelegate getDelegate() {
if (mDelegate == null) {
mDelegate = AppCompatDelegate.create(this, null);
}
return mDelegate;
}
}

View file

@ -1,75 +0,0 @@
package org.secuso.privacyfriendlybreakreminder.activities.helper;
/*
* The MIT License (MIT)
*
* Copyright (c) 2014 Matthieu Harlé
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import android.database.Cursor;
import android.widget.Filter;
/**
* Taken from: https://gist.github.com/Shywim/127f207e7248fe48400b
*/
public class CursorFilter extends Filter {
CursorFilterClient mClient;
interface CursorFilterClient {
CharSequence convertToString(Cursor cursor);
Cursor runQueryOnBackgroundThread(CharSequence constraint);
Cursor getCursor();
void changeCursor(Cursor cursor);
}
CursorFilter(CursorFilterClient client) {
mClient = client;
}
@Override
public CharSequence convertResultToString(Object resultValue) {
return mClient.convertToString((Cursor) resultValue);
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
Cursor cursor = mClient.runQueryOnBackgroundThread(constraint);
FilterResults results = new FilterResults();
if (cursor != null) {
results.count = cursor.getCount();
results.values = cursor;
} else {
results.count = 0;
results.values = null;
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
Cursor oldCursor = mClient.getCursor();
if (results.values != null && results.values != oldCursor) {
mClient.changeCursor((Cursor) results.values);
}
}
}

View file

@ -1,376 +0,0 @@
package org.secuso.privacyfriendlybreakreminder.activities.helper;
/*
* Copyright (C) 2014 skyfish.jy@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/*
* The MIT License (MIT)
*
* Copyright (c) 2014 Matthieu Harlé
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.CursorJoiner;
import android.database.DataSetObserver;
import android.os.Handler;
import android.provider.BaseColumns;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.widget.Filter;
import android.widget.FilterQueryProvider;
import android.widget.Filterable;
/**
* Provide a {@link android.support.v7.widget.RecyclerView.Adapter} implementation with cursor
* support.
*
* Child classes only need to implement {@link #onCreateViewHolder(android.view.ViewGroup, int)} and
* {@link #onBindViewHolder(RecyclerView.ViewHolder, Cursor)}.
*
* This class does not implement deprecated fields and methods from CursorAdapter! Incidentally,
* only {@link android.widget.CursorAdapter#FLAG_REGISTER_CONTENT_OBSERVER} is available, so the
* flag is implied, and only the Adapter behavior using this flag has been ported.
*
* @param <VH> {@inheritDoc}
*
* @see android.support.v7.widget.RecyclerView.Adapter
* @see android.widget.CursorAdapter
* @see Filterable
* @see CursorFilter.CursorFilterClient
*/
public abstract class CursorRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> implements CursorFilter.CursorFilterClient, Filterable {
protected Context mContext;
private Cursor mCursor;
private boolean mDataValid;
private int mRowIdColumn;
private DataSetObserver mDataSetObserver;
private ChangeObserver mChangeObserver;
private CursorFilter mCursorFilter;
private FilterQueryProvider mFilterQueryProvider;
private boolean mUseIndividualNotifies;
private String mIdIdentifier = "_id";
public CursorRecyclerViewAdapter(Context context, Cursor cursor, String idIdentifier) {
this(context, null);
this.setIdIdentifier(idIdentifier);
this.changeCursor(cursor);
}
public CursorRecyclerViewAdapter(Context context, Cursor cursor) {
mContext = context;
mCursor = cursor;
mDataValid = cursor != null;
mRowIdColumn = mDataValid ? mCursor.getColumnIndex(mIdIdentifier) : -1;
mDataSetObserver = new NotifyingDataSetObserver();
mChangeObserver = new ChangeObserver();
if (mDataValid) {
if (mChangeObserver != null) cursor.registerContentObserver(mChangeObserver);
if (mDataSetObserver != null) cursor.registerDataSetObserver(mDataSetObserver);
}
}
public void setIdIdentifier(String identifier) {
mIdIdentifier = TextUtils.isEmpty(identifier) ?
"_id" :
identifier;
}
public Cursor getCursor() {
return mCursor;
}
@Override
public int getItemCount() {
if (mDataValid && mCursor != null) {
return mCursor.getCount();
}
return 0;
}
@Override
public long getItemId(int position) {
if (mDataValid && mCursor != null && mCursor.moveToPosition(position)) {
return mCursor.getLong(mRowIdColumn);
}
return 0;
}
@Override
public void setHasStableIds(boolean hasStableIds) {
super.setHasStableIds(hasStableIds);
}
public abstract void onBindViewHolder(VH viewHolder, Cursor cursor);
@Override
public void onBindViewHolder(VH viewHolder, int position) {
if (!mDataValid) {
throw new IllegalStateException("this should only be called when the cursor is valid");
}
if (!mCursor.moveToPosition(position)) {
throw new IllegalStateException("couldn't move cursor to position " + position);
}
onBindViewHolder(viewHolder, mCursor);
}
/**
* Change the underlying cursor to a new cursor. If there is an existing cursor it will be
* closed.
*/
public void changeCursor(Cursor cursor) {
Cursor old = swapCursor(cursor);
if (old != null) {
old.close();
}
}
/**
* Swap in a new Cursor, returning the old Cursor. Unlike
* {@link #changeCursor(Cursor)}, the returned old Cursor is <em>not</em>
* closed.
*/
public Cursor swapCursor(Cursor newCursor) {
if (newCursor == mCursor) {
return null;
}
// unregister observers on old cursor
final Cursor oldCursor = mCursor;
if (oldCursor != null) {
if (mChangeObserver != null) oldCursor.unregisterContentObserver(mChangeObserver);
if (mDataSetObserver != null) oldCursor.unregisterDataSetObserver(mDataSetObserver);
}
// register observers on the new cursor
mCursor = newCursor;
if (mCursor != null) {
if (mChangeObserver != null) newCursor.registerContentObserver(mChangeObserver);
if (mDataSetObserver != null) newCursor.registerDataSetObserver(mDataSetObserver);
mRowIdColumn = newCursor.getColumnIndexOrThrow(mIdIdentifier);
mDataValid = true;
} else {
mRowIdColumn = -1;
mDataValid = false;
}
// notify that Dataset has Changed
boolean notifyDataChanged = true;
// check if we can get better notifies
if(mUseIndividualNotifies && oldCursor != null && newCursor != null && !oldCursor.isClosed() && !newCursor.isClosed()) {
notifyDataChanged = notifyItems(oldCursor, newCursor);
}
if(notifyDataChanged) {
notifyDataSetChanged();
}
return oldCursor;
}
public void setUseIndividualNotifies(boolean use) {
mUseIndividualNotifies = use;
}
/**
* Compares the two cursors and calls notifyChanged on every item that changed.
* @param oldCursor
* @param newCursor
* @return
*/
private boolean notifyItems(Cursor oldCursor, Cursor newCursor) {
String[] columns = new String[] { BaseColumns._ID };
CursorJoiner joiner = new CursorJoiner(oldCursor, columns, newCursor, columns);
for (CursorJoiner.Result res : joiner) {
switch (res) {
case LEFT:
notifyItemRemoved(newCursor.getPosition());
break;
case RIGHT:
notifyItemInserted(newCursor.getPosition());
break;
case BOTH:
// for(int i = 0; i < newCursor.getColumnCount(); i++) {
// if(!oldCursor.getString(i).equals(newCursor.getString(i))) {
// notifyItemChanged(newCursor.getPosition());
// }
// }
if (getRowHash(oldCursor) != getRowHash(newCursor)) {
notifyItemChanged(newCursor.getPosition());
}
break;
}
}
return false;
}
private int getRowHash(Cursor cursor) {
StringBuilder result = new StringBuilder("row");
for (int i = 0; i < cursor.getColumnCount(); i++) {
result.append(cursor.getString(i));
}
return result.toString().hashCode();
}
/**
* <p>Converts the cursor into a CharSequence. Subclasses should override this
* method to convert their results. The default implementation returns an
* empty String for null values or the default String representation of
* the value.</p>
*
* @param cursor the cursor to convert to a CharSequence
* @return a CharSequence representing the value
*/
public CharSequence convertToString(Cursor cursor) {
return cursor == null ? "" : cursor.toString();
}
/**
* Runs a query with the specified constraint. This query is requested
* by the filter attached to this adapter.
*
* The query is provided by a
* {@link FilterQueryProvider}.
* If no provider is specified, the current cursor is not filtered and returned.
*
* After this method returns the resulting cursor is passed to {@link #changeCursor(Cursor)}
* and the previous cursor is closed.
*
* This method is always executed on a background thread, not on the
* application's main thread (or UI thread.)
*
* Contract: when constraint is null or empty, the original results,
* prior to any filtering, must be returned.
*
* @param constraint the constraint with which the query must be filtered
*
* @return a Cursor representing the results of the new query
*
* @see #getFilter()
* @see #getFilterQueryProvider()
* @see #setFilterQueryProvider(FilterQueryProvider)
*/
public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
if (mFilterQueryProvider != null) {
return mFilterQueryProvider.runQuery(constraint);
}
return mCursor;
}
public Filter getFilter() {
if (mCursorFilter == null) {
mCursorFilter = new CursorFilter(this);
}
return mCursorFilter;
}
/**
* Returns the query filter provider used for filtering. When the
* provider is null, no filtering occurs.
*
* @return the current filter query provider or null if it does not exist
*
* @see #setFilterQueryProvider(FilterQueryProvider)
* @see #runQueryOnBackgroundThread(CharSequence)
*/
public FilterQueryProvider getFilterQueryProvider() {
return mFilterQueryProvider;
}
/**
* Sets the query filter provider used to filter the current Cursor.
* The provider's
* {@link FilterQueryProvider#runQuery(CharSequence)}
* method is invoked when filtering is requested by a client of
* this adapter.
*
* @param filterQueryProvider the filter query provider or null to remove it
*
* @see #getFilterQueryProvider()
* @see #runQueryOnBackgroundThread(CharSequence)
*/
public void setFilterQueryProvider(FilterQueryProvider filterQueryProvider) {
mFilterQueryProvider = filterQueryProvider;
}
/**
* Called when the {@link ContentObserver} on the cursor receives a change notification.
* Can be implemented by sub-class.
*
* @see ContentObserver#onChange(boolean)
*/
protected void onContentChanged() {
}
private class ChangeObserver extends ContentObserver {
public ChangeObserver() {
super(new Handler());
}
@Override
public boolean deliverSelfNotifications() {
return true;
}
@Override
public void onChange(boolean selfChange) {
onContentChanged();
}
}
private class NotifyingDataSetObserver extends DataSetObserver {
private final String TAG = NotifyingDataSetObserver.class.getSimpleName();
@Override
public void onChanged() {
super.onChanged();
mDataValid = true;
notifyDataSetChanged();
}
@Override
public void onInvalidated() {
super.onInvalidated();
mDataValid = false;
notifyDataSetChanged();
//There is no notifyDataSetInvalidated() method in RecyclerView.Adapter
}
}
}