Remove some Astrid content provider functionality

pull/618/head
Alex Baker 7 years ago
parent ff3936bf0d
commit 6a440cd91e

@ -152,7 +152,7 @@ public class TaskDaoTests extends DatabaseTestCase {
// try to save task "happy"
Task task = new Task();
task.setTitle("happy");
task.setID(1L);
task.setId(1L);
taskDao.save(task);

@ -1,376 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.provider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.support.test.runner.AndroidJUnit4;
import com.todoroo.andlib.data.Property.IntegerProperty;
import com.todoroo.andlib.data.Property.StringProperty;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.StoreObject;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.test.DatabaseTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.tasks.injection.TestComponent;
import static android.support.test.InstrumentationRegistry.getTargetContext;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotSame;
import static junit.framework.Assert.fail;
@RunWith(AndroidJUnit4.class)
public class Astrid3ProviderTests extends DatabaseTestCase {
String[] PROJECTION = new String[] {
Task.ID.name,
Task.TITLE.name,
};
@Override
public void setUp() {
super.setUp();
// set up database
Astrid3ContentProvider.setDatabaseOverride(database);
}
@Override
protected void inject(TestComponent component) {
component.inject(this);
}
/** Test CRUD over tasks with the ALL ITEMS cursor */
@Test
public void testAllItemsCrud() {
ContentResolver resolver = getTargetContext().getContentResolver();
// fetch all tasks, get nothing
Uri uri = Task.CONTENT_URI;
Cursor cursor = resolver.query(uri, PROJECTION, "1", null, null);
assertEquals(0, cursor.getCount());
cursor.close();
// insert a task
ContentValues values = new ContentValues();
values.put(Task.TITLE.name, "mf doom?");
resolver.insert(uri, values);
// fetch all tasks, get something
cursor = resolver.query(uri, PROJECTION, "1", null, null);
assertEquals(1, cursor.getCount());
cursor.moveToFirst();
assertEquals("mf doom?", cursor.getString(1));
cursor.close();
// update all tasks
values.put(Task.TITLE.name, "mf grimm?");
resolver.update(uri, values, "1", null);
// fetch all tasks, get something
cursor = resolver.query(uri, PROJECTION, "1", null, null);
cursor.moveToFirst();
assertEquals("mf grimm?", cursor.getString(1));
cursor.close();
// delete a task
assertEquals(1, resolver.delete(uri, "1", null));
// fetch all tasks, get nothing
cursor = resolver.query(uri, PROJECTION, null, null, null);
assertEquals(0, cursor.getCount());
cursor.close();
}
/** Test selecting data */
@Test
public void testSelection() {
ContentResolver resolver = getTargetContext().getContentResolver();
Uri uri = Task.CONTENT_URI;
// insert some tasks
ContentValues values = new ContentValues();
values.put(Task.TITLE.name, "tujiko noriko");
values.put(Task.IMPORTANCE.name, Task.IMPORTANCE_MUST_DO);
resolver.insert(uri, values);
values.clear();
values.put(Task.TITLE.name, "miho asahi");
values.put(Task.IMPORTANCE.name, Task.IMPORTANCE_NONE);
resolver.insert(uri, values);
// fetch all tasks with various selection parameters
Cursor cursor = resolver.query(uri, PROJECTION, "1", null, null);
assertEquals(2, cursor.getCount());
cursor.close();
cursor = resolver.query(uri, PROJECTION, null, null, null);
assertEquals(2, cursor.getCount());
cursor.close();
cursor = resolver.query(uri, PROJECTION, Task.IMPORTANCE + "=" +
Task.IMPORTANCE_MUST_DO, null, null);
assertEquals(1, cursor.getCount());
cursor.moveToFirst();
assertEquals("tujiko noriko", cursor.getString(1));
cursor.close();
cursor = resolver.query(uri, PROJECTION, Task.IMPORTANCE + ">" +
Task.IMPORTANCE_MUST_DO, null, null);
assertEquals(1, cursor.getCount());
cursor.moveToFirst();
assertEquals("miho asahi", cursor.getString(1));
cursor.close();
cursor = resolver.query(uri, PROJECTION, Task.IMPORTANCE + "=" +
Task.IMPORTANCE_DO_OR_DIE, null, null);
assertEquals(0, cursor.getCount());
cursor.close();
}
/** Test updating */
@Test
public void testUpdating() {
ContentResolver resolver = getTargetContext().getContentResolver();
// insert some tasks
ContentValues values = new ContentValues();
values.put(Task.TITLE.name, "carlos silva");
values.put(Task.IMPORTANCE.name, Task.IMPORTANCE_SHOULD_DO);
Uri carlosUri = resolver.insert(Task.CONTENT_URI, values);
values.clear();
values.put(Task.TITLE.name, "felix hernandez");
values.put(Task.IMPORTANCE.name, Task.IMPORTANCE_MUST_DO);
resolver.insert(Task.CONTENT_URI, values);
String[] projection = new String[] {
Task.ID.name,
Task.TITLE.name,
Task.IMPORTANCE.name,
};
// test updating with single item URI
Cursor cursor = resolver.query(Task.CONTENT_URI, projection,
Task.TITLE.eq("carlos who?").toString(), null, null);
assertEquals(0, cursor.getCount());
cursor.close();
values.clear();
values.put(Task.TITLE.name, "carlos who?");
assertEquals(1, resolver.update(carlosUri, values, null, null));
cursor = resolver.query(Task.CONTENT_URI, projection, Task.TITLE.eq("carlos who?").toString(), null, null);
assertEquals(1, cursor.getCount());
cursor.close();
// test updating with all items uri
cursor = resolver.query(Task.CONTENT_URI, PROJECTION,
Task.IMPORTANCE.eq(Task.IMPORTANCE_NONE).toString(), null, null);
assertEquals(0, cursor.getCount());
cursor.close();
values.clear();
values.put(Task.IMPORTANCE.name, Task.IMPORTANCE_NONE);
assertEquals(1, resolver.update(Task.CONTENT_URI, values,
Task.IMPORTANCE.eq(Task.IMPORTANCE_SHOULD_DO).toString(), null));
cursor = resolver.query(Task.CONTENT_URI, PROJECTION,
Task.IMPORTANCE.eq(Task.IMPORTANCE_NONE).toString(), null, null);
assertEquals(1, cursor.getCount());
cursor.close();
// test updating with group by uri
try {
Uri groupByUri = Uri.withAppendedPath(Task.CONTENT_URI,
AstridApiConstants.GROUP_BY_URI + Task.TITLE.name);
resolver.update(groupByUri, values, null, null);
fail("Able to update using groupby uri");
} catch (Exception e) {
// expected
}
}
/** Test deleting */
@Test
public void testDeleting() {
ContentResolver resolver = getTargetContext().getContentResolver();
Uri allItemsUri = Task.CONTENT_URI;
// insert some tasks
ContentValues values = new ContentValues();
values.put(Task.TITLE.name, "modest mouse");
values.put(Task.IMPORTANCE.name, Task.IMPORTANCE_DO_OR_DIE);
Uri modestMouse = resolver.insert(allItemsUri, values);
values.clear();
values.put(Task.TITLE.name, "death cab");
values.put(Task.IMPORTANCE.name, Task.IMPORTANCE_MUST_DO);
resolver.insert(allItemsUri, values);
values.clear();
values.put(Task.TITLE.name, "murder city devils");
values.put(Task.IMPORTANCE.name, Task.IMPORTANCE_SHOULD_DO);
resolver.insert(allItemsUri, values);
// test deleting with single URI
Cursor cursor = resolver.query(allItemsUri, PROJECTION, Task.TITLE.name +
" = 'modest mouse'", null, null);
assertEquals(1, cursor.getCount());
cursor.close();
assertEquals(1, resolver.delete(modestMouse, null, null));
cursor = resolver.query(allItemsUri, PROJECTION, Task.TITLE.name +
" = 'modest mouse'", null, null);
assertEquals(0, cursor.getCount());
cursor.close();
// test updating with all items uri
cursor = resolver.query(allItemsUri, PROJECTION, Task.TITLE.name +
" = 'murder city devils'", null, null);
assertEquals(1, cursor.getCount());
cursor.close();
assertEquals(1, resolver.delete(allItemsUri, Task.IMPORTANCE.name +
">" + Task.IMPORTANCE_MUST_DO, null));
cursor = resolver.query(allItemsUri, PROJECTION, Task.TITLE.name +
" = 'murder city devils'", null, null);
assertEquals(0, cursor.getCount());
cursor.close();
// test with group by uri
try {
Uri groupByUri = Uri.withAppendedPath(Task.CONTENT_URI,
AstridApiConstants.GROUP_BY_URI + Task.TITLE.name);
resolver.delete(groupByUri, null, null);
fail("Able to delete using groupby uri");
} catch (Exception e) {
// expected
}
}
/** Test CRUD over SINGLE ITEM uri */
@Test
public void testSingleItemCrud() {
ContentResolver resolver = getTargetContext().getContentResolver();
Uri uri = StoreObject.CONTENT_URI;
ContentValues values = new ContentValues();
values.put(StoreObject.TYPE.name, "rapper");
values.put(StoreObject.ITEM.name, "mf doom?");
Uri firstUri = resolver.insert(uri, values);
values.put(StoreObject.ITEM.name, "gm grimm!");
Uri secondUri = resolver.insert(uri, values);
assertNotSame(firstUri, secondUri);
String[] storeProjection = new String[] {
StoreObject.ITEM.name,
};
Cursor cursor = resolver.query(uri, storeProjection, null, null, null);
assertEquals(2, cursor.getCount());
cursor.close();
cursor = resolver.query(firstUri, storeProjection, null, null, null);
assertEquals(1, cursor.getCount());
cursor.moveToFirst();
assertEquals("mf doom?", cursor.getString(0));
cursor.close();
values.put(StoreObject.ITEM.name, "danger mouse.");
resolver.update(firstUri, values, null, null);
cursor = resolver.query(firstUri, storeProjection, null, null, null);
assertEquals(1, cursor.getCount());
cursor.moveToFirst();
assertEquals("danger mouse.", cursor.getString(0));
cursor.close();
assertEquals(1, resolver.delete(firstUri, null, null));
cursor = resolver.query(uri, storeProjection, null, null, null);
assertEquals(1, cursor.getCount());
cursor.close();
}
/** Test GROUP BY uri */
@Test
public void testGroupByCrud() {
ContentResolver resolver = getTargetContext().getContentResolver();
Uri uri = Task.CONTENT_URI;
ContentValues values = new ContentValues();
values.put(Task.TITLE.name, "catwoman");
resolver.insert(uri, values);
values.put(Task.TITLE.name, "the joker");
resolver.insert(uri, values);
resolver.insert(uri, values);
resolver.insert(uri, values);
values.put(Task.TITLE.name, "deep freeze");
resolver.insert(uri, values);
resolver.insert(uri, values);
Uri groupByUri = Uri.withAppendedPath(Task.CONTENT_URI,
AstridApiConstants.GROUP_BY_URI + Task.TITLE.name);
Cursor cursor = resolver.query(groupByUri, PROJECTION, null, null, Task.TITLE.name);
assertEquals(3, cursor.getCount());
cursor.moveToFirst();
assertEquals("catwoman", cursor.getString(1));
cursor.moveToNext();
assertEquals("deep freeze", cursor.getString(1));
cursor.moveToNext();
assertEquals("the joker", cursor.getString(1));
cursor.close();
// test "group-by" with metadata
IntegerProperty age = new IntegerProperty(Metadata.TABLE, Metadata.VALUE1.name);
StringProperty size = Metadata.VALUE2;
uri = Metadata.CONTENT_URI;
values.clear();
values.put(Metadata.TASK.name, 1);
values.put(Metadata.KEY.name, "sizes");
values.put(age.name, 50);
values.put(size.name, "large");
resolver.insert(uri, values);
values.put(age.name, 40);
values.put(size.name, "large");
resolver.insert(uri, values);
values.put(age.name, 20);
values.put(size.name, "small");
resolver.insert(uri, values);
String[] metadataProjection = new String[] { "AVG(" + age + ")" };
Uri groupBySizeUri = Uri.withAppendedPath(Metadata.CONTENT_URI,
AstridApiConstants.GROUP_BY_URI + size.name);
cursor = resolver.query(groupBySizeUri, metadataProjection, null, null, size.name);
assertEquals(2, cursor.getCount());
cursor.moveToFirst();
assertEquals(45, cursor.getInt(0));
cursor.moveToNext();
assertEquals(20, cursor.getInt(0));
}
}

@ -10,7 +10,6 @@ import com.todoroo.astrid.gtasks.GtasksMetadataServiceTest;
import com.todoroo.astrid.gtasks.GtasksTaskListUpdaterTest;
import com.todoroo.astrid.gtasks.GtasksTaskMovingTest;
import com.todoroo.astrid.model.TaskTest;
import com.todoroo.astrid.provider.Astrid3ProviderTests;
import com.todoroo.astrid.reminders.ReminderServiceTest;
import com.todoroo.astrid.repeats.NewRepeatTests;
import com.todoroo.astrid.repeats.RepeatTaskHelperTest;

@ -65,24 +65,6 @@
<uses-permission android:name="org.tasks.permission.READ_TASKS" />
<!-- for reading data from add-ons or astrid via v3 content provider -->
<permission
android:name="org.tasks.READ"
android:description="@string/read_permission_desc"
android:protectionLevel="normal"
android:label="@string/read_permission_label" />
<uses-permission android:name="org.tasks.READ" />
<!-- for writing data to add-ons or astrid via v3 content provider -->
<permission
android:name="org.tasks.WRITE"
android:description="@string/write_permission_desc"
android:protectionLevel="normal"
android:label="@string/write_permission_label" />
<uses-permission android:name="org.tasks.WRITE" />
<!-- ========================================================== Metadata = -->
<supports-screens
@ -252,24 +234,6 @@
android:grantUriPermissions="true"
android:readPermission="org.tasks.permission.READ_TASKS" />
<provider
android:name="com.todoroo.astrid.provider.Astrid3ContentProvider"
android:authorities="org.tasks"
android:exported="true"
android:multiprocess="true"
android:grantUriPermissions="true"
android:readPermission="org.tasks.READ"
android:writePermission="org.tasks.WRITE" />
<provider
android:name="com.todoroo.astrid.provider.SqlContentProvider"
android:authorities="org.tasks.private"
android:exported="true"
android:multiprocess="true"
android:grantUriPermissions="true"
android:readPermission="org.tasks.READ"
android:writePermission="org.tasks.WRITE" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"

@ -49,9 +49,6 @@ public abstract class AbstractModel implements Parcelable, Cloneable {
/** sentinel for objects without an id */
public static final long NO_ID = 0;
/** prefix for transitories retained in content values */
public static final String RETAIN_TRANSITORY_PREFIX = "retain-trans-"; //$NON-NLS-1$
// --- abstract methods
/** Get the default values for this object */

@ -72,19 +72,6 @@ public class DatabaseDao<TYPE extends AbstractModel> {
return new TodorooCursor<>(modelClass, cursor, query.getFields());
}
/**
* Construct a query with raw SQL
*/
public TodorooCursor<TYPE> rawQuery(String selection, String[] selectionArgs, Property<?>... properties) {
String[] fields = new String[properties.length];
for(int i = 0; i < properties.length; i++) {
fields[i] = properties[i].name;
}
return new TodorooCursor<>(modelClass, database.getDatabase().query(table.name,
fields, selection, selectionArgs, null, null, null),
properties);
}
/**
* Returns object corresponding to the given identifier
* @param properties

@ -5,8 +5,6 @@
*/
package com.todoroo.astrid.api;
import org.tasks.BuildConfig;
/**
* Constants for interfacing with Astrid.
*
@ -14,32 +12,11 @@ import org.tasks.BuildConfig;
*/
public class AstridApiConstants {
// --- General Constants
/**
* Permission for reading tasks and receiving to GET_FILTERS intent
*/
public static final String PERMISSION_READ = BuildConfig.APPLICATION_ID + ".READ";
/**
* Permission for writing and creating tasks
*/
public static final String PERMISSION_WRITE = BuildConfig.APPLICATION_ID + ".WRITE";
/**
* Name of Astrid's publicly readable preference store
*/
public static final String PUBLIC_PREFS = "public";
// --- Content Provider
/**
* URI to append to base content URI for making group-by queries
*/
public static final String GROUP_BY_URI = "/groupby/";
// --- Broadcast Extras
/**
* Extras name for task id
*/

@ -27,7 +27,6 @@ import com.todoroo.astrid.data.TaskAttachment;
import com.todoroo.astrid.data.TaskListMetadata;
import com.todoroo.astrid.data.UserActivity;
import com.todoroo.astrid.provider.Astrid2TaskProvider;
import com.todoroo.astrid.provider.Astrid3ContentProvider;
import org.tasks.analytics.Tracker;
import org.tasks.injection.ApplicationScope;
@ -181,7 +180,6 @@ public class Database {
private void onDatabaseUpdated() {
Astrid2TaskProvider.notifyDatabaseModification(context);
Astrid3ContentProvider.notifyDatabaseModification(context);
}
/**

@ -92,10 +92,6 @@ public class TaskDao {
return dao.toList(Query.select(Task.PROPERTIES).withQueryTemplate(query));
}
public List<Task> rawQuery(String selection, String[] selectionArgs, Property.LongProperty id) {
return dao.rawQuery(selection, selectionArgs, id).toList();
}
/**
* Update all matching a clause to have the values set on template object.
* <p>

@ -7,7 +7,6 @@ package com.todoroo.astrid.data;
import android.content.ContentValues;
import android.net.Uri;
import com.todoroo.andlib.data.AbstractModel;
import com.todoroo.andlib.data.Property;
@ -15,8 +14,6 @@ import com.todoroo.andlib.data.Property.LongProperty;
import com.todoroo.andlib.data.Property.StringProperty;
import com.todoroo.andlib.data.Table;
import org.tasks.BuildConfig;
/**
* Data Model which represents a piece of metadata associated with a task
*
@ -30,10 +27,6 @@ public class Metadata extends AbstractModel {
/** table for this model */
public static final Table TABLE = new Table("metadata", Metadata.class);
/** content uri for this model */
public static final Uri CONTENT_URI = Uri.parse("content://" + BuildConfig.APPLICATION_ID + "/" +
TABLE.name);
// --- properties
/** ID */

@ -7,7 +7,6 @@ package com.todoroo.astrid.data;
import android.content.ContentValues;
import android.net.Uri;
import com.todoroo.andlib.data.AbstractModel;
import com.todoroo.andlib.data.Property;
@ -15,8 +14,6 @@ import com.todoroo.andlib.data.Property.LongProperty;
import com.todoroo.andlib.data.Property.StringProperty;
import com.todoroo.andlib.data.Table;
import org.tasks.BuildConfig;
/**
* Data Model which represents a piece of data unrelated to a task
*
@ -30,10 +27,6 @@ public class StoreObject extends AbstractModel {
/** table for this model */
public static final Table TABLE = new Table("store", StoreObject.class);
/** content uri for this model */
public static final Uri CONTENT_URI = Uri.parse("content://" + BuildConfig.APPLICATION_ID + "/" +
TABLE.name);
// --- properties
/** ID */

@ -7,7 +7,6 @@ package com.todoroo.astrid.data;
import android.content.ContentValues;
import android.net.Uri;
import android.text.TextUtils;
import com.google.ical.values.RRule;
@ -19,7 +18,6 @@ import com.todoroo.andlib.data.Table;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.utility.DateUtilities;
import org.tasks.BuildConfig;
import org.tasks.time.DateTime;
import static org.tasks.date.DateTimeUtils.newDateTime;
@ -37,9 +35,6 @@ public class Task extends RemoteModel {
/** table for this model */
public static final Table TABLE = new Table("tasks", Task.class);
public static final Uri CONTENT_URI = Uri.parse("content://" + BuildConfig.APPLICATION_ID + "/" +
TABLE.name);
// --- properties
/** ID */
@ -572,10 +567,6 @@ public class Task extends RemoteModel {
setValue(CALENDAR_URI, calendarUri);
}
public void setID(Long id) {
setValue(ID, id);
}
public boolean isNotifyModeNonstop() {
return isReminderFlagSet(Task.NOTIFY_MODE_NONSTOP);
}

@ -8,8 +8,6 @@ import com.todoroo.andlib.data.Property.LongProperty;
import com.todoroo.andlib.data.Property.StringProperty;
import com.todoroo.andlib.data.Table;
import org.tasks.BuildConfig;
public class UserActivity extends RemoteModel {
// --- table
@ -17,10 +15,6 @@ public class UserActivity extends RemoteModel {
/** table for this model */
public static final Table TABLE = new Table("userActivity", UserActivity.class);
/** content uri for this model */
public static final Uri CONTENT_URI = Uri.parse("content://" + BuildConfig.APPLICATION_ID + "/" +
TABLE.name);
// --- properties
/** ID */

@ -16,7 +16,6 @@ import android.support.annotation.NonNull;
import com.google.common.base.Joiner;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.core.SortHelper;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
@ -24,8 +23,6 @@ import com.todoroo.astrid.data.TagData;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.tags.TagService;
import org.tasks.analytics.Tracker;
import org.tasks.analytics.Tracking;
import org.tasks.injection.ContentProviderComponent;
import org.tasks.injection.InjectingContentProvider;
import org.tasks.ui.CheckBoxes;
@ -68,9 +65,6 @@ public class Astrid2TaskProvider extends InjectingContentProvider {
private final static String IMPORTANCE = "importance";
private final static String ID = "id";
// fake property for updating that completes a task
private final static String COMPLETED = "completed";
private final static String TAGS_ID = "tags_id";
private static final String[] TASK_FIELD_LIST = new String[] { NAME, IMPORTANCE_COLOR, PREFERRED_DUE_DATE, DEFINITE_DUE_DATE,
@ -86,7 +80,6 @@ public class Astrid2TaskProvider extends InjectingContentProvider {
@Inject Lazy<TagService> tagService;
@Inject Lazy<CheckBoxes> checkBoxes;
@Inject Lazy<TaskDao> taskDao;
@Inject Lazy<Tracker> tracker;
static {
URI_MATCHER.addURI(AUTHORITY, "tasks", URI_TASKS);
@ -195,77 +188,19 @@ public class Astrid2TaskProvider extends InjectingContentProvider {
@Override
public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Cursor cursor;
switch (URI_MATCHER.match(uri)) {
case URI_TASKS:
cursor = getTasks();
break;
case URI_TAGS:
cursor = getTags();
break;
default:
throw new IllegalStateException("Unrecognized URI:" + uri);
}
return cursor;
}
switch (URI_MATCHER.match(uri)) {
case URI_TASKS:
return getTasks();
case URI_TAGS:
return getTags();
default:
throw new IllegalStateException("Unrecognized URI:" + uri);
}
}
@Override
public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {
switch (URI_MATCHER.match(uri)) {
case URI_TASKS:
tracker.get().reportEvent(Tracking.Events.ASTRID_2_CP);
Task task = new Task();
// map values
if(values.containsKey(NAME)) {
task.setTitle(values.getAsString(NAME));
}
if(values.containsKey(PREFERRED_DUE_DATE)) {
task.setDueDate(values.getAsLong(PREFERRED_DUE_DATE));
}
if(values.containsKey(DEFINITE_DUE_DATE)) {
task.setDueDate(values.getAsLong(DEFINITE_DUE_DATE));
}
if(values.containsKey(IMPORTANCE)) {
task.setImportance(values.getAsInteger(IMPORTANCE));
}
if(values.containsKey(COMPLETED)) {
task.setCompletionDate(values.getAsBoolean(COMPLETED) ? DateUtilities.now() : 0);
}
// map selection criteria
String criteria = selection.replace(NAME, Task.TITLE.name).
replace(PREFERRED_DUE_DATE, Task.DUE_DATE.name).
replace(DEFINITE_DUE_DATE, Task.DUE_DATE.name).
replace(IDENTIFIER, Task.ID.name).
replace(ID, Task.ID.name).
replace(IMPORTANCE, Task.IMPORTANCE.name);
return updateBySelection(criteria, selectionArgs, task);
case URI_TAGS:
throw new UnsupportedOperationException("tags updating: not yet");
default:
throw new IllegalStateException("Unrecognized URI:" + uri);
}
}
/**
* Update database based on selection and values
*/
private int updateBySelection(String selection, String[] selectionArgs, Task taskValues) {
List<Task> tasks = taskDao.get().rawQuery(selection, selectionArgs, Task.ID);
for (Task task : tasks) {
taskValues.setID(task.getId());
taskDao.get().save(taskValues);
}
return tasks.size();
throw new UnsupportedOperationException("not supported");
}
public static void notifyDatabaseModification(Context context) {

@ -1,403 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.provider;
import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import com.todoroo.andlib.data.AbstractModel;
import com.todoroo.andlib.data.DatabaseDao;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.dao.RemoteModelDao;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.StoreObject;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.data.UserActivity;
import org.tasks.BuildConfig;
import org.tasks.analytics.Tracker;
import org.tasks.analytics.Tracking;
import org.tasks.injection.ContentProviderComponent;
import org.tasks.injection.InjectingContentProvider;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Set;
import javax.inject.Inject;
import dagger.Lazy;
/**
* Astrid 3 Content Provider. There are two ways to use this content provider:
* <ul>
* <li>access it directly just like any other content provider
* <li>use the DAO classes from the Astrid API library
* </ul>
* <p>
* The following base URI's are supported:
* <ul>
* <li>content://com.todoroo.astrid/tasks - task data ({@link Task})
* <li>content://com.todoroo.astrid/metadata - task metadata ({@link Metadata})
* <li>content://com.todoroo.astrid/store - non-task store data ({@link StoreObject})
* </ul>
* <p>
* Each URI supports the following components:
* <ul>
* <li>/ - operate on all items (insert, delete, update, query)
* <li>/123 - operate on item id #123 (delete, update, query)
* <li>/groupby/title - query with SQL "group by" (query)
* </ul>
* <p>
* If you are writing a third-party application to access this data, you may
* also consider using one of the Api DAO objects like TaskApiDao.
*
* @author Tim Su <tim@todoroo.com>
*
*/
public class Astrid3ContentProvider extends InjectingContentProvider {
/** URI for making a request over all items */
private static final int URI_DIR = 1;
/** URI for making a request over a single item by id */
private static final int URI_ITEM = 2;
/** URI for making a request over all items grouped by some field */
private static final int URI_GROUP = 3;
private static final UriMatcher uriMatcher;
@SuppressLint("StaticFieldLeak")
private static Database databaseOverride;
// --- instance variables
private boolean open;
@Inject Lazy<Database> database;
@Inject Lazy<Tracker> tracker;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
for(Uri uri : new Uri[] { Task.CONTENT_URI, Metadata.CONTENT_URI, StoreObject.CONTENT_URI, UserActivity.CONTENT_URI }) {
String authority = BuildConfig.APPLICATION_ID;
String table = uri.toString();
table = table.substring(table.indexOf('/', 11) + 1);
uriMatcher.addURI(authority, table, URI_DIR);
uriMatcher.addURI(authority, table + "/#", URI_ITEM);
uriMatcher.addURI(authority, table +
AstridApiConstants.GROUP_BY_URI + "*", URI_GROUP);
}
}
public Astrid3ContentProvider() {
setReadPermission(AstridApiConstants.PERMISSION_READ);
setWritePermission(AstridApiConstants.PERMISSION_WRITE);
}
@Override
public String getType(@NonNull Uri uri) {
switch (uriMatcher.match(uri)) {
case URI_DIR:
case URI_GROUP:
return "vnd.android.cursor.dir/vnd.astrid";
case URI_ITEM:
return "vnd.android.cursor/vnd.astrid.item";
default:
throw new IllegalArgumentException("Unsupported URI " + uri + " (" + uriMatcher.match(uri) + ")");
}
}
@Override
protected void inject(ContentProviderComponent component) {
component.inject(this);
}
/* ======================================================================
* ========================================================== helpers ===
* ====================================================================== */
private class UriHelper<TYPE extends AbstractModel> {
/** empty model. used for insert */
public TYPE model;
/** dao */
public DatabaseDao<TYPE> dao;
/** creates from given model */
public boolean create() {
return dao.createNew(model);
}
/** updates from given model */
public void update() {
dao.saveExisting(model);
}
}
private UriHelper<?> generateHelper(Uri uri, boolean populateModel) {
tracker.get().reportEvent(Tracking.Events.ASTRID_3_CP);
final Database db = getDatabase();
if(uri.toString().startsWith(Task.CONTENT_URI.toString())) {
UriHelper<Task> helper = new UriHelper<>();
helper.model = populateModel ? new Task() : null;
helper.dao = new RemoteModelDao<>(db, Task.class);
return helper;
} else if(uri.toString().startsWith(Metadata.CONTENT_URI.toString())) {
UriHelper<Metadata> helper = new UriHelper<>();
helper.model = populateModel ? new Metadata() : null;
helper.dao = new DatabaseDao<>(db, Metadata.class);
return helper;
} else if(uri.toString().startsWith(StoreObject.CONTENT_URI.toString())) {
UriHelper<StoreObject> helper = new UriHelper<>();
helper.model = populateModel ? new StoreObject() : null;
helper.dao = new DatabaseDao<>(db, StoreObject.class);
return helper;
} else if(uri.toString().startsWith(UserActivity.CONTENT_URI.toString())) {
UriHelper<UserActivity> helper = new UriHelper<>();
helper.model = populateModel ? new UserActivity() : null;
helper.dao = new RemoteModelDao<>(db, UserActivity.class);
return helper;
}
throw new UnsupportedOperationException("Unknown URI " + uri);
}
public static void setDatabaseOverride(Database override) {
databaseOverride = override;
}
private Database getDatabase() {
if (!open) {
database.get().openForWriting();
open = true;
}
if(databaseOverride != null) {
return databaseOverride;
}
return database.get();
}
/* ======================================================================
* =========================================================== delete ===
* ====================================================================== */
/**
* Delete from given table
* @return number of rows deleted
*/
@Override
public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
UriHelper<?> helper = generateHelper(uri, false);
switch (uriMatcher.match(uri)) {
// illegal operations
case URI_GROUP:
throw new IllegalArgumentException("Only the / or /# URI is valid"
+ " for deletion.");
// valid operations
case URI_ITEM: {
String itemSelector = String.format("%s = '%s'",
AbstractModel.ID_PROPERTY, uri.getPathSegments().get(1));
if(TextUtils.isEmpty(selection)) {
selection = itemSelector;
} else {
selection = itemSelector + " AND " + selection;
}
}
case URI_DIR:
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri + " (" + uriMatcher.match(uri) + ")");
}
return getDatabase().delete(helper.dao.getTable().name, selection, selectionArgs);
}
/* ======================================================================
* =========================================================== insert ===
* ====================================================================== */
/**
* Insert key/value pairs into given table
*/
@Override
public Uri insert(@NonNull Uri uri, ContentValues values) {
UriHelper<?> helper = generateHelper(uri, true);
switch (uriMatcher.match(uri)) {
// illegal operations
case URI_ITEM:
case URI_GROUP:
throw new IllegalArgumentException("Only the / URI is valid"
+ " for insertion.");
// valid operations
case URI_DIR: {
helper.model.mergeWith(values);
readTransitoriesFromModelContentValues(helper.model);
if(!helper.create()) {
throw new SQLException("Could not insert row into database (constraint failed?)");
}
Uri newUri = ContentUris.withAppendedId(uri, helper.model.getId());
getContext().getContentResolver().notifyChange(newUri, null);
return newUri;
}
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
/* ======================================================================
* =========================================================== update ===
* ====================================================================== */
@Override
public int update(@NonNull Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
UriHelper<?> helper = generateHelper(uri, true);
switch (uriMatcher.match(uri)) {
// illegal operations
case URI_GROUP:
throw new IllegalArgumentException("Only the / or /# URI is valid"
+ " for update.");
// valid operations
case URI_ITEM: {
String itemSelector = String.format("%s = '%s'",
AbstractModel.ID_PROPERTY, uri.getPathSegments().get(1));
if(TextUtils.isEmpty(selection)) {
selection = itemSelector;
} else {
selection = itemSelector + " AND " + selection;
}
}
case URI_DIR:
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri + " (" + uriMatcher.match(uri) + ")");
}
Cursor cursor = query(uri, new String[] { AbstractModel.ID_PROPERTY.name },
selection, selectionArgs, null);
try {
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
long id = cursor.getLong(0);
helper.model.mergeWith(values);
readTransitoriesFromModelContentValues(helper.model);
helper.model.setId(id);
helper.update();
helper.model.clear();
}
getContext().getContentResolver().notifyChange(uri, null);
return cursor.getCount();
} finally {
cursor.close();
}
}
private void readTransitoriesFromModelContentValues(AbstractModel model) {
ContentValues setValues = model.getSetValues();
if (setValues != null) {
Set<Entry<String, Object>> entries = setValues.valueSet();
Set<String> keysToRemove = new HashSet<>();
for (Entry<String, Object> entry: entries) {
String key = entry.getKey();
if (key.startsWith(AbstractModel.RETAIN_TRANSITORY_PREFIX)) {
String newKey = key.substring(AbstractModel.RETAIN_TRANSITORY_PREFIX.length());
Object value = setValues.get(key);
model.putTransitory(newKey, value);
keysToRemove.add(key);
}
}
for (String key : keysToRemove) {
setValues.remove(key);
}
}
}
/* ======================================================================
* ============================================================ query ===
* ====================================================================== */
/**
* Query by task.
* <p>
* Note that the "sortOrder" field actually can be used to append any
* sort of clause to your SQL query as long as it is not also the
* name of a column
*/
@Override
public Cursor query(@NonNull Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
String groupBy = null;
UriHelper<?> helper = generateHelper(uri, false);
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
builder.setTables(helper.dao.getTable().name);
switch (uriMatcher.match(uri)) {
case URI_GROUP:
groupBy = uri.getPathSegments().get(2);
case URI_DIR:
break;
case URI_ITEM:
String itemSelector = String.format("%s = '%s'",
AbstractModel.ID_PROPERTY, uri.getPathSegments().get(1));
builder.appendWhere(itemSelector);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri + " (" + uriMatcher.match(uri) + ")");
}
Cursor cursor = builder.query(getDatabase().getDatabase(), projection, selection, selectionArgs, groupBy, null, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
// --- change listeners
public static void notifyDatabaseModification(Context context) {
ContentResolver cr = context.getContentResolver();
cr.notifyChange(Task.CONTENT_URI, null, false);
}
}

@ -1,134 +0,0 @@
/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.provider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;
import android.support.annotation.NonNull;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.dao.Database;
import org.tasks.BuildConfig;
import org.tasks.analytics.Tracker;
import org.tasks.analytics.Tracking;
import org.tasks.injection.ContentProviderComponent;
import org.tasks.injection.InjectingContentProvider;
import javax.inject.Inject;
import dagger.Lazy;
/**
* Non-public-API SQL content provider.
*
* This provider is dangerous and unsupported, use at your own risk. It allows
* full SQL queries, which means LIMIT and JOIN in queries. Only SELECT is
* currently supported.
*
* @author Tim Su <tim@todoroo.com>
*
*/
public class SqlContentProvider extends InjectingContentProvider {
// --- instance variables
private static final UriMatcher uriMatcher;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(BuildConfig.APPLICATION_ID + ".private",
"sql", 0);
}
private boolean open;
@Inject Lazy<Database> database;
@Inject Lazy<Tracker> tracker;
public SqlContentProvider() {
setReadPermission(AstridApiConstants.PERMISSION_READ);
setWritePermission(AstridApiConstants.PERMISSION_WRITE);
}
@Override
public String getType(@NonNull Uri uri) {
switch (uriMatcher.match(uri)) {
case 0:
return "vnd.android.cursor.dir/vnd.astrid";
default:
throw new IllegalArgumentException("Unsupported URI " + uri + " (" + uriMatcher.match(uri) + ")");
}
}
/* ======================================================================
* =========================================================== delete ===
* ====================================================================== */
/**
* Delete from given table
* @return number of rows deleted
*/
@Override
public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
throw new UnsupportedOperationException("unimplemented");
}
/* ======================================================================
* =========================================================== insert ===
* ====================================================================== */
/**
* Insert key/value pairs into given table
*/
@Override
public Uri insert(@NonNull Uri uri, ContentValues values) {
throw new UnsupportedOperationException("unimplemented");
}
/* ======================================================================
* =========================================================== update ===
* ====================================================================== */
@Override
public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {
throw new UnsupportedOperationException("unimplemented");
}
/* ======================================================================
* ============================================================ query ===
* ====================================================================== */
/**
* Query by task.
* <p>
* Note that the "sortOrder" field actually can be used to append any
* sort of clause to your SQL query as long as it is not also the
* name of a column
*/
@Override
public Cursor query(@NonNull Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
tracker.get().reportEvent(Tracking.Events.ASTRID_SQL_CP);
return getDatabase().rawQuery(selection);
}
private Database getDatabase() {
if (!open) {
database.get().openForWriting();
open = true;
}
return database.get();
}
@Override
protected void inject(ContentProviderComponent component) {
component.inject(this);
}
}

@ -33,10 +33,7 @@ public class Tracking {
RECURRENCE_CUSTOM(R.string.tracking_category_recurrence, R.string.tracking_action_custom),
RECURRENCE_PRESET(R.string.tracking_category_recurrence, R.string.tracking_action_preset),
TASKER_CREATE(R.string.tracking_category_tasker, R.string.tracking_action_task_created),
TASKER_LIST_NOTIFICATION(R.string.tracking_category_tasker, R.string.tracking_action_list_notification),
ASTRID_2_CP(R.string.tracking_category_api, R.string.tracking_action_api_astrid2_update),
ASTRID_3_CP(R.string.tracking_category_api, R.string.tracking_action_api_astrid3),
ASTRID_SQL_CP(R.string.tracking_category_api, R.string.tracking_action_api_astrid_sql);
TASKER_LIST_NOTIFICATION(R.string.tracking_category_tasker, R.string.tracking_action_list_notification);
public final int category;
public final int action;

@ -1,8 +1,6 @@
package org.tasks.injection;
import com.todoroo.astrid.provider.Astrid2TaskProvider;
import com.todoroo.astrid.provider.Astrid3ContentProvider;
import com.todoroo.astrid.provider.SqlContentProvider;
import dagger.Component;
@ -12,9 +10,5 @@ import dagger.Component;
ContentProviderModule.class
})
public interface ContentProviderComponent {
void inject(Astrid3ContentProvider astrid3ContentProvider);
void inject(Astrid2TaskProvider astrid2TaskProvider);
void inject(SqlContentProvider sqlContentProvider);
}

@ -13,7 +13,6 @@
<string name="export_toast_no_tasks">لا يوجد مهام للتصدير.</string>
<string name="import_summary_title"> إستعادة المُلخَّص</string>
<string name="read_permission_label">إذن المهام</string>
<string name="write_permission_label">أخذ التصاريح</string>
<string name="DLG_delete_this_task_question">حذف هذه المهمه؟</string>
<string name="DLG_hour_minutes">الوقت (ساعة : دقيقة)</string>
<string name="DLG_undo">تراجع</string>

@ -24,7 +24,6 @@
<string name="DLG_error_sdcard">Нямате достъп до папка: %s</string>
<string name="DLG_error_sdcard_general">SD картата не може да бъде достъпена!</string>
<string name="read_permission_label">Tasks Разрешение</string>
<string name="write_permission_label">Tasks Разрешение</string>
<string name="discard_confirmation">Сигурни ли сте че искате да отхвърлите промените си?</string>
<string name="keep_editing">Продължаване на редактиране</string>
<string name="DLG_delete_this_task_question">Изтриване на тази задача?</string>

@ -17,7 +17,6 @@
<string name="DLG_error_sdcard">No es pot accedir a la carpeta: %s</string>
<string name="DLG_error_sdcard_general">No s\'ha pogut accedir a la targeta SD.</string>
<string name="read_permission_label">Permís de l\'Tasks</string>
<string name="write_permission_label">Permís de l\'Tasks</string>
<string name="DLG_delete_this_task_question">Voleu suprimir aquesta tasca?</string>
<string name="DLG_hour_minutes">Temps (hores : minuts)</string>
<string name="DLG_undo">Desfés</string>

@ -20,7 +20,6 @@
<string name="DLG_error_sdcard">Chyba v přístupu k adresáři: %s</string>
<string name="DLG_error_sdcard_general">Chyba v přístupu k SD kartě!</string>
<string name="read_permission_label">Tasks Práva</string>
<string name="write_permission_label">Tasks Práva</string>
<string name="DLG_delete_this_task_question">Smazat tento úkol?</string>
<string name="DLG_hour_minutes">Čas (hodin : minut)</string>
<string name="DLG_undo">Vrátit změny</string>

@ -19,7 +19,6 @@
<string name="DLG_error_sdcard">Kan ikke få adgang til mappen: %s</string>
<string name="DLG_error_sdcard_general">Kan ikke få adgang til dig SD-kort!</string>
<string name="read_permission_label">Tasks Tilladelser</string>
<string name="write_permission_label">Tasks Tilladelser</string>
<string name="DLG_delete_this_task_question">Slet denne opgave?</string>
<string name="DLG_hour_minutes">Tid (timer : minutter)</string>
<string name="WID_dateButtonUnset">Tryk for at indstille</string>

@ -19,7 +19,6 @@
<string name="DLG_error_sdcard">Ordner konnte nicht geöffnet werden: %s</string>
<string name="DLG_error_sdcard_general">Auf die SD-Karte konnte nicht zugegriffen werden!</string>
<string name="read_permission_label">Tasks Zugriffsrechte</string>
<string name="write_permission_label">Tasks Zugriffsrechte</string>
<string name="discard_confirmation">Änderungen wirklich verwerfen?</string>
<string name="keep_editing">Weiter bearbeiten</string>
<string name="DLG_delete_this_task_question">Diese Aufgabe löschen?</string>

@ -22,7 +22,6 @@
<string name="DLG_error_sdcard">Δεν υπάρχει πρόσβαση στον φάκελο: %s</string>
<string name="DLG_error_sdcard_general">Δεν υπάρχει πρόσβαση στην SD κάρτα!</string>
<string name="read_permission_label">Άδεια εργασιών</string>
<string name="write_permission_label">Άδεια Εργασιών</string>
<string name="DLG_delete_this_task_question">Διαγραφή εργασίας;</string>
<string name="DLG_hour_minutes">Ώρα (ώρες : λεπτά)</string>
<string name="DLG_undo">Αναίρεση</string>

@ -21,7 +21,6 @@
<string name="DLG_error_sdcard">No se puede acceder a la carpeta: %s</string>
<string name="DLG_error_sdcard_general">¡No se pudo acceder a su tarjeta de memoria SD!</string>
<string name="read_permission_label">Permisos de Tasks</string>
<string name="write_permission_label">Permisos de Tasks</string>
<string name="discard_confirmation">¿Quieres descartar los cambios?</string>
<string name="keep_editing">Seguir editando</string>
<string name="DLG_delete_this_task_question">¿Borrar esta tarea?</string>

@ -24,7 +24,6 @@
<string name="DLG_error_sdcard">Ei pääsyä kansioon: %s</string>
<string name="DLG_error_sdcard_general">Ei pääsyä SD kortillesi!</string>
<string name="read_permission_label">Tasks käyttöoikeus</string>
<string name="write_permission_label">Tasks käyttöoikeus</string>
<string name="discard_confirmation">Oletko varma että haluat hylätä muutokset?</string>
<string name="keep_editing">Jatka muokkausta</string>
<string name="DLG_delete_this_task_question">Poista tämä tehtävä?</string>

@ -21,7 +21,6 @@
<string name="DLG_error_sdcard">Impossible d\'accéder au dossier : %s</string>
<string name="DLG_error_sdcard_general">Impossible d\'accéder à la carte SD !</string>
<string name="read_permission_label">Permissions de Tasks</string>
<string name="write_permission_label">Permissions de Tasks</string>
<string name="discard_confirmation">Êtes-vous sûr de vouloir annuler vos modifications ?</string>
<string name="keep_editing">Continuer l\'édition</string>
<string name="DLG_delete_this_task_question">Supprimer cette tâche ?</string>

@ -21,7 +21,6 @@
<string name="DLG_error_sdcard">No se puede acceder a la carpeta: %s</string>
<string name="DLG_error_sdcard_general">¡No se pudo acceder a su tarjeta de memoria SD!</string>
<string name="read_permission_label">Permisos de Tasks</string>
<string name="write_permission_label">Permisos de Tasks</string>
<string name="discard_confirmation">¿Quieres descartar los cambios?</string>
<string name="keep_editing">Seguir editando</string>
<string name="DLG_delete_this_task_question">¿Borrar esta tarea?</string>

@ -24,7 +24,6 @@
<string name="DLG_error_sdcard">Könyvtár nem elérhető: %s</string>
<string name="DLG_error_sdcard_general">SD kártya nem elérhető</string>
<string name="read_permission_label">Tasks Engedélyek</string>
<string name="write_permission_label">Tasks Engedélyek</string>
<string name="discard_confirmation">Biztosan el akarja vetni a változtatásokat?</string>
<string name="keep_editing">Vissza a szerkesztéshez</string>
<string name="DLG_delete_this_task_question">Feladat törlése?</string>

@ -21,7 +21,6 @@
<string name="DLG_error_sdcard">Impossibile accedere alla cartella: %s</string>
<string name="DLG_error_sdcard_general">Impossibile accedere alla scheda SD!</string>
<string name="read_permission_label">Permessi attività</string>
<string name="write_permission_label">Permessi attività</string>
<string name="discard_confirmation">Sicuro di voler annullare tutte le modifiche?</string>
<string name="keep_editing">Continua modifica</string>
<string name="DLG_delete_this_task_question">Elimino l\'attività?</string>

@ -21,7 +21,6 @@
<string name="DLG_error_sdcard">לא ניתן לגשת לתיקיה: %s</string>
<string name="DLG_error_sdcard_general">לא ניתן לגשת לכרטיס ה־SD שלך!</string>
<string name="read_permission_label">הרשאות אסטריד</string>
<string name="write_permission_label">הרשאות אסטריד</string>
<string name="discard_confirmation">להתעלם מהשינויים ?</string>
<string name="keep_editing">המשך לערוך</string>
<string name="DLG_delete_this_task_question">למחוק משימה זו?</string>

@ -21,7 +21,6 @@
<string name="DLG_error_sdcard">フォルダ %s を開けません</string>
<string name="DLG_error_sdcard_general">SDカードにアクセスできません</string>
<string name="read_permission_label">タスクの読み込み</string>
<string name="write_permission_label">タスクの読み込み</string>
<string name="discard_confirmation">変更を破棄してもよろしいですか?</string>
<string name="keep_editing">編集を続ける</string>
<string name="DLG_delete_this_task_question">このタスクを削除しますか?</string>

@ -24,7 +24,6 @@
<string name="DLG_error_sdcard">폴더에 접근 불가: %s</string>
<string name="DLG_error_sdcard_general">SD 카드에 접근할 수 없습니다!</string>
<string name="read_permission_label">Tasks 권한</string>
<string name="write_permission_label">Tasks 권한</string>
<string name="discard_confirmation">변경 사항을 버리시겠습니까?</string>
<string name="keep_editing">계속 편집</string>
<string name="DLG_delete_this_task_question">이 할일을 삭제할까요?</string>

@ -21,7 +21,6 @@
<string name="DLG_error_sdcard">Nėra prieigos prie aplanko: %s</string>
<string name="DLG_error_sdcard_general">Nėra prieigos prie SD kortelės!</string>
<string name="read_permission_label">Tasks leidimas</string>
<string name="write_permission_label">Tasks leidimas</string>
<string name="discard_confirmation">Ar tikrai norite atmesti pakeitimus?</string>
<string name="keep_editing">Tęsti redagavimą</string>
<string name="DLG_delete_this_task_question">Ištrinti šią užduotį?</string>

@ -17,7 +17,6 @@
<string name="DLG_error_sdcard">Får ikke tilgang til mappen: %s</string>
<string name="DLG_error_sdcard_general">Ditt SD-kort er ikke tilgjengelig!</string>
<string name="read_permission_label">Tasks Tillatelse</string>
<string name="write_permission_label">Tasks Tillatelse</string>
<string name="DLG_delete_this_task_question">Slett denne oppgaven?</string>
<string name="DLG_hour_minutes">Tid (timer : minutter)</string>
<string name="WID_dateButtonUnset">Klikk for å sette</string>

@ -21,7 +21,6 @@
<string name="DLG_error_sdcard">Toegang geweigerd tot map: %s</string>
<string name="DLG_error_sdcard_general">Toegang tot SD-kaart geweigerd!</string>
<string name="read_permission_label">Taak toestemmingen</string>
<string name="write_permission_label">Taak toestemmingen</string>
<string name="discard_confirmation">Weet u zeker dat u de wijzigingen niet wilt opslaan?</string>
<string name="keep_editing">Blijf editen</string>
<string name="DLG_delete_this_task_question">Taak verwijderen?</string>

@ -21,7 +21,6 @@
<string name="DLG_error_sdcard">Brak dostępu do folderu: %s</string>
<string name="DLG_error_sdcard_general">Brak dostępu do Twojej karty SD!</string>
<string name="read_permission_label">Uprawnienia Tasks</string>
<string name="write_permission_label">Zezwolenia Tasks</string>
<string name="discard_confirmation">Czy jesteś pewien, że chcesz porzucić zmiany?</string>
<string name="keep_editing">Kontynuuj edycję</string>
<string name="DLG_delete_this_task_question">Usunąć to zadanie?</string>

@ -20,7 +20,6 @@
<string name="DLG_error_sdcard">Não foi possível acessar a pasta: %s</string>
<string name="DLG_error_sdcard_general">Não foi possível acessar seu cartão SD!</string>
<string name="read_permission_label">Permissões do Tasks</string>
<string name="write_permission_label">Permissões do Tasks</string>
<string name="discard_confirmation">Você tem certeza que deseja descartar suas mudanças?</string>
<string name="keep_editing">Continuar editando</string>
<string name="DLG_delete_this_task_question">Excluir esta tarefa?</string>

@ -23,7 +23,6 @@
<string name="DLG_error_sdcard">Não é possível aceder à pasta: %s</string>
<string name="DLG_error_sdcard_general">Não é possível aceder ao seu cartão SD!</string>
<string name="read_permission_label">Permissões do Tasks</string>
<string name="write_permission_label">Permissões do Tasks</string>
<string name="discard_confirmation">Tem a certeza que deseja descartar as alterações?</string>
<string name="keep_editing">Continuar a editar</string>
<string name="DLG_delete_this_task_question">Remover esta tarefa?</string>

@ -21,7 +21,6 @@
<string name="DLG_error_sdcard">Нет доступа к папке:%s</string>
<string name="DLG_error_sdcard_general">Нет доступа к карте памяти!</string>
<string name="read_permission_label">Разрешения Tasks</string>
<string name="write_permission_label">Разрешения Tasks</string>
<string name="discard_confirmation">Вы действительно хотите отказаться от сделанных изменений?</string>
<string name="keep_editing">Продолжить редактировать</string>
<string name="DLG_delete_this_task_question">Удалить эту задачу?</string>

@ -20,7 +20,6 @@
<string name="DLG_error_sdcard">Chyba v prístupe k súboru: %s</string>
<string name="DLG_error_sdcard_general">Chyba v prístupe k SD karte!</string>
<string name="read_permission_label">Tasks povolenia</string>
<string name="write_permission_label">Tasks povolenia</string>
<string name="DLG_delete_this_task_question">Vymazať túto úlohu?</string>
<string name="DLG_hour_minutes">Čas (hodiny : minúty)</string>
<string name="DLG_undo">Späť</string>

@ -22,7 +22,6 @@
<string name="DLG_error_sdcard">Datoteka:%s ni dostopna</string>
<string name="DLG_error_sdcard_general">Tvoja SD kartica ni dostopna.</string>
<string name="read_permission_label">Dovoljenje Opravkom</string>
<string name="write_permission_label">Dovoljenje Opravkom</string>
<string name="DLG_delete_this_task_question">Zbrišem ta opravek?</string>
<string name="DLG_hour_minutes">Čas (ure : minute)</string>
<string name="DLG_undo">Razveljavi</string>

@ -21,7 +21,6 @@
<string name="DLG_error_sdcard">Mappåtkomst nekad: %s</string>
<string name="DLG_error_sdcard_general">SD-kort ej tillgängligt!</string>
<string name="read_permission_label">Tasks Tillstånd</string>
<string name="write_permission_label">Tasks Tillstånd</string>
<string name="discard_confirmation">Är du säker på att du inte vill spara dina ändringar?</string>
<string name="keep_editing">Fortsätt redigera</string>
<string name="DLG_delete_this_task_question">Radera denna uppgift?</string>

@ -25,7 +25,6 @@
<string name="DLG_error_sdcard">%s dizinine erişilemedi.</string>
<string name="DLG_error_sdcard_general">Hafıza kartına erişemiyorum!</string>
<string name="read_permission_label">Tasks İzni</string>
<string name="write_permission_label">Tasks İzni</string>
<string name="discard_confirmation">Değişikliklerinizi gözden çıkarmak istediğinize emin misiniz?</string>
<string name="keep_editing">Düzenlemeyi sürdür</string>
<string name="DLG_delete_this_task_question">Bu görev silinsin mi?</string>

@ -24,7 +24,6 @@
<string name="DLG_error_sdcard">Немає доступу до папки: %s</string>
<string name="DLG_error_sdcard_general">Немає доступу до карти SD!</string>
<string name="read_permission_label">Дозволи Tasks</string>
<string name="write_permission_label">Дозволи Tasks</string>
<string name="discard_confirmation">Дійсно хочете скасувати ваші зміни?</string>
<string name="keep_editing">Продовжити редагування</string>
<string name="DLG_delete_this_task_question">Видалити цю задачу?</string>

@ -21,7 +21,6 @@
<string name="DLG_error_sdcard">无法开启文件夹:%s</string>
<string name="DLG_error_sdcard_general">无法访问您的 SD 卡!</string>
<string name="read_permission_label">清单小助理权限</string>
<string name="write_permission_label">清单小助理权限</string>
<string name="keep_editing">继续编辑</string>
<string name="DLG_delete_this_task_question">确认删除?</string>
<string name="DLG_hour_minutes">时间(小时:分钟)</string>

@ -19,7 +19,6 @@
<string name="DLG_error_sdcard">無法開啟資料夾: %s</string>
<string name="DLG_error_sdcard_general">無法存取您的SD卡!</string>
<string name="read_permission_label">Tasks 權限</string>
<string name="write_permission_label">Tasks 權限</string>
<string name="DLG_delete_this_task_question">確認刪除?</string>
<string name="DLG_hour_minutes">時間 (小時:分鐘)</string>
<string name="DLG_undo">撤消</string>

@ -13,7 +13,6 @@
<string name="p_date_shortcut_evening">date_shortcut_evening</string>
<string name="p_date_shortcut_night">date_shortcut_night</string>
<string name="write_permission_desc">create new tasks, edit existing tasks</string>
<string name="read_permission_desc">read tasks, display task filters</string>
<!-- ======================================================== REMINDERS == -->
@ -231,7 +230,6 @@
<string name="tracking_category_google_tasks">Gtask</string>
<string name="tracking_category_event">Event</string>
<string name="tracking_category_tasker">Tasker</string>
<string name="tracking_category_api">API</string>
<string name="tracking_action_add">Add</string>
<string name="tracking_action_start">Start</string>
<string name="tracking_action_move">Move</string>
@ -246,9 +244,6 @@
<string name="tracking_action_preset">Preset</string>
<string name="tracking_action_task_created">Task created</string>
<string name="tracking_action_list_notification">List Notification</string>
<string name="tracking_action_api_astrid2_update">2 Update</string>
<string name="tracking_action_api_astrid3">3</string>
<string name="tracking_action_api_astrid_sql">SQL</string>
<string name="tracking_event_night_mode_mismatch">Night Mismatch</string>
<string name="tracking_event_play_services_error">Play Services Error</string>

@ -57,9 +57,6 @@ File %1$s contained %2$s.\n\n
<!-- permission title for READ_TASKS -->
<string name="read_permission_label">Tasks Permission</string>
<!-- permission title for READ_TASKS -->
<string name="write_permission_label">Tasks Permission</string>
<!-- ================================================== Generic Dialogs == -->
<string name="discard_confirmation">Are you sure you want to discard your changes?</string>

Loading…
Cancel
Save