Various improvements. All over, improvements.

pull/14/head
Tim Su 14 years ago
parent 8314bb97f7
commit 34ee32f5dd

@ -255,9 +255,10 @@
<activity android:name="com.todoroo.astrid.rmilk.MilkLoginActivity"
android:theme="@style/Theme" />
<activity android:name="com.todoroo.astrid.rmilk.MilkPreferences"
android:icon="@drawable/ic_menu_rmilk"
android:label="@string/rmilk_MPr_header">
<intent-filter>
<action android:name="com.todoroo.astrid.SETTINGS" />
<action android:name="com.todoroo.astrid.TASK_LIST_MENU" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>

@ -49,6 +49,12 @@ public abstract class SynchronizationProvider {
*/
abstract protected void initiate(Context context);
/**
* @param context
* @return title of notification
*/
abstract protected String getNotificationTitle(Context context);
/**
* Push variables from given task to the remote server.
*
@ -103,6 +109,7 @@ public abstract class SynchronizationProvider {
private final Notification notification;
private PendingIntent notificationIntent;
private String notificationTitle;
public SynchronizationProvider() {
DependencyInjectionService.getInstance().inject(this);
@ -111,10 +118,12 @@ public abstract class SynchronizationProvider {
int icon = android.R.drawable.stat_notify_sync;
long when = System.currentTimeMillis();
notification = new Notification(icon, null, when);
notification.flags |= Notification.FLAG_ONGOING_EVENT;
}
public void synchronize(final Context context) {
// display notification
notificationTitle = getNotificationTitle(context);
notificationIntent = PendingIntent.getActivity(context, 0, new Intent(), 0);
postUpdate(context, context.getString(R.string.SyP_progress_starting));
final NotificationManager nm = new NotificationManager.AndroidNotificationManager(context);
@ -149,7 +158,7 @@ public abstract class SynchronizationProvider {
*/
protected void postUpdate(Context context, String string) {
notification.setLatestEventInfo(context,
context.getString(R.string.rmilk_notification_title), string, notificationIntent);
notificationTitle, string, notificationIntent);
}
// --- synchronization logic

@ -4,7 +4,7 @@
<booleanAttribute key="ch.zork.quicklaunch" value="true"/>
<stringAttribute key="ch.zork.quicklaunch.icon" value="14.gif"/>
<intAttribute key="ch.zork.quicklaunch.index" value="0"/>
<stringAttribute key="ch.zork.quicklaunch.mode" value="run"/>
<stringAttribute key="ch.zork.quicklaunch.mode" value="debug"/>
<intAttribute key="com.android.ide.eclipse.adt.action" value="0"/>
<stringAttribute key="com.android.ide.eclipse.adt.avd" value="android-22"/>
<stringAttribute key="com.android.ide.eclipse.adt.commandline" value="-scale 0.7"/>

@ -77,10 +77,14 @@ public class AndroidUtilities {
*
* @param context
* @param intent
* @param request request code. if negative, no request.
*/
public static void startExternalIntent(Context context, Intent intent) {
public static void startExternalIntent(Context context, Intent intent, int request) {
try {
context.startActivity(intent);
if(request > -1 && context instanceof Activity)
((Activity)context).startActivityForResult(intent, request);
else
context.startActivity(intent);
} catch (SecurityException e) {
ExceptionHelper helper = new ExceptionHelper();
helper.exceptionService.displayAndReportError(context,

@ -3,7 +3,6 @@
*/
package com.todoroo.andlib.widget;
import android.content.Intent;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
@ -11,7 +10,6 @@ import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.preference.RingtonePreference;
import android.preference.Preference.OnPreferenceChangeListener;
@ -40,10 +38,6 @@ abstract public class TodorooPreferences extends PreferenceActivity {
addPreferencesFromResource(getPreferenceResource());
DependencyInjectionService.getInstance().inject(this);
PreferenceScreen screen = getPreferenceScreen();
initializePreference(screen);
}
protected void initializePreference(Preference preference) {
@ -76,8 +70,11 @@ abstract public class TodorooPreferences extends PreferenceActivity {
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
initializePreference(getPreferenceScreen());
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus) {
initializePreference(getPreferenceScreen());
}
}
}

@ -2,7 +2,6 @@ package com.todoroo.astrid.reminders;
import java.util.Date;
import android.app.Activity;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@ -15,8 +14,6 @@ import android.net.Uri;
import android.util.Log;
import com.timsu.astrid.R;
import com.timsu.astrid.data.task.TaskIdentifier;
import com.timsu.astrid.utilities.Constants;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService;
@ -27,6 +24,7 @@ import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.model.Task;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.utility.Constants;
import com.todoroo.astrid.utility.Preferences;
public class Notifications extends BroadcastReceiver {
@ -88,13 +86,6 @@ public class Notifications extends BroadcastReceiver {
// --- notification creation
/** Clear notifications associated with this application */
public static void clearAllNotifications(Context context, TaskIdentifier taskId) {
NotificationManager nm = (NotificationManager)
context.getSystemService(Activity.NOTIFICATION_SERVICE);
nm.cancel((int)taskId.getId());
}
/** @return a random reminder string */
static String getRandomReminder(String[] reminders) {
int next = ReminderService.random.nextInt(reminders.length);

@ -9,8 +9,6 @@ import android.graphics.Color;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.view.View;
import android.view.ViewGroup.OnHierarchyChangeListener;
import android.widget.ListView;
import com.timsu.astrid.R;
import com.todoroo.andlib.service.Autowired;
@ -60,16 +58,6 @@ public class MilkPreferences extends TodorooPreferences {
r.getStringArray(R.array.rmilk_MPr_interval_entries)[index]));
}
// shortcut
else if (r.getString(R.string.rmilk_MPr_shortcut_key).equals(
preference.getKey())) {
if ((Boolean) value) {
preference.setSummary(R.string.rmilk_MPr_shortcut_desc_enabled);
} else {
preference.setSummary(R.string.rmilk_MPr_shortcut_desc_disabled);
}
}
// status
else if (r.getString(R.string.rmilk_MPr_status_key).equals(preference.getKey())) {
boolean loggedIn = Utilities.isLoggedIn();
@ -94,7 +82,7 @@ public class MilkPreferences extends TodorooPreferences {
DateUtilities.getDateWithTimeFormat(MilkPreferences.this).
format(new Date(Utilities.getLastAttemptedSyncDate())));
if(Utilities.getLastSyncDate() > 0) {
subtitle = r.getString(R.string.rmilk_status_success,
subtitle = r.getString(R.string.rmilk_status_failed_subtitle,
DateUtilities.getDateWithTimeFormat(MilkPreferences.this).
format(new Date(Utilities.getLastSyncDate())));
}
@ -107,25 +95,27 @@ public class MilkPreferences extends TodorooPreferences {
return true;
}
});
} else {
} else if(Utilities.getLastSyncDate() > 0) {
status = r.getString(R.string.rmilk_status_success,
DateUtilities.getDateWithTimeFormat(MilkPreferences.this).
format(new Date(Utilities.getLastSyncDate())));
statusColor = Color.rgb(0, 100, 0);
} else {
status = r.getString(R.string.rmilk_status_never);
statusColor = Color.rgb(0, 0, 100);
preference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference p) {
new RTMSyncProvider().synchronize(MilkPreferences.this);
return true;
}
});
}
preference.setTitle(status);
preference.setSummary(subtitle);
final int statusColorSetting = statusColor;
getListView().setOnHierarchyChangeListener(new OnHierarchyChangeListener() {
public void onChildViewRemoved(View arg0, View arg1) {
//
}
public void onChildViewAdded(View parent, View child) {
if(((ListView)parent).getChildCount() == 2) {
child.setBackgroundColor(statusColorSetting);
}
}
});
View view = findViewById(R.id.status);
if(view != null)
view.setBackgroundColor(statusColor);
}
// sync button

@ -126,7 +126,8 @@ public final class MilkDataService {
return taskDao.query(Query.select(Task.ID).where(Criterion.none));
return
taskDao.query(Query.select(properties).join(METADATA_JOIN).
where(Task.MODIFICATION_DATE.gt(lastSyncDate)));
where(Criterion.and(MetadataCriteria.withKey(METADATA_KEY),
Task.MODIFICATION_DATE.gt(lastSyncDate))));
}
/**
@ -137,7 +138,7 @@ public final class MilkDataService {
if(task.getId() != Task.NO_ID)
return;
TodorooCursor<Task> cursor = taskDao.query(Query.select(Task.ID).
join(METADATA_JOIN).where(Criterion.and(LIST_ID.eq(task.getValue(LIST_ID)),
join(METADATA_JOIN).where(Criterion.and(MetadataCriteria.withKey(METADATA_KEY),
TASK_SERIES_ID.eq(task.getValue(TASK_SERIES_ID)),
TASK_ID.eq(task.getValue(TASK_ID)))));
try {
@ -296,7 +297,7 @@ public final class MilkDataService {
MilkList model = new MilkList();
MilkList inbox = null;
for(Map.Entry<String, RtmList> list : lists.getLists().entrySet()) {
if(list.getValue().isSmart())
if(list.getValue().isSmart() || "All Tasks".equals(list.getValue().getName())) //$NON-NLS-1$
continue;
model.setValue(MilkList.ID, Long.parseLong(list.getValue().getId()));
model.setValue(MilkList.NAME, list.getValue().getName());

@ -263,7 +263,12 @@ public class RTMSyncProvider extends SynchronizationProvider {
}
SyncData syncData = populateSyncData(remoteChanges);
synchronizeTasks(syncData);
try {
synchronizeTasks(syncData);
} finally {
syncData.localCreated.close();
syncData.localUpdated.close();
}
Utilities.recordSuccessfulSync();
@ -279,6 +284,11 @@ public class RTMSyncProvider extends SynchronizationProvider {
// ------------------------------------------------------- helper methods
// ----------------------------------------------------------------------
@Override
protected String getNotificationTitle(Context context) {
return context.getString(R.string.rmilk_notification_title);
}
/**
* Populate SyncData data structure
*/
@ -447,6 +457,8 @@ public class RTMSyncProvider extends SynchronizationProvider {
@Override
protected Task read(Task task) throws IOException {
if(task.getValue(MilkDataService.TASK_SERIES_ID) == 0)
throw new ServiceInternalException("Tried to read an invalid task"); //$NON-NLS-1$
RtmTaskSeries rtmTask = rtmService.tasks_getTask(Long.toString(task.getValue(MilkDataService.TASK_SERIES_ID)),
task.getValue(Task.TITLE));
if(rtmTask != null)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2006 The Android Open Source Project
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.
-->
<!-- Layout for a visually child-like Preference in a PreferenceActivity. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/status"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:paddingRight="?android:attr/scrollbarSize">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:layout_marginRight="6dip"
android:layout_marginTop="6dip"
android:layout_marginBottom="6dip"
android:layout_weight="1">
<TextView android:id="@+android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceLarge"
android:ellipsize="marquee"
android:fadingEdge="horizontal" />
<TextView android:id="@+android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
android:layout_alignLeft="@android:id/title"
android:textAppearance="?android:attr/textAppearanceSmall"
android:maxLines="2"
android:textColor="?android:attr/textColorSecondary" />
</RelativeLayout>
<!-- Preference should place its actual preference widget here. -->
<LinearLayout android:id="@+android:id/widget_frame"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:orientation="vertical" />
</LinearLayout>

@ -57,7 +57,11 @@
<!-- Status: success (%s -> last sync date) -->
<string name="rmilk_status_success">Last Sync: %s</string>
<!-- Status: error (%s -> last attempted sync date) -->
<string name="rmilk_status_failed">Sync Failed On: %s</string>
<string name="rmilk_status_failed">Failed On: %s</string>
<!-- Status: error subtitle (%s -> last successful sync date) -->
<string name="rmilk_status_failed_subtitle">Last Successful Sync: %s</string>
<!-- Status: never sync'd -->
<string name="rmilk_status_never">Never Synchronized!</string>
<!-- Options Group Label -->
<string name="rmilk_MPr_group_options">Options</string>
@ -71,15 +75,6 @@
<!-- Preference Key (do not translate) -->
<string name="rmilk_MPr_interval_key">rmilk_interval</string>
<!-- Shortcut Title -->
<string name="rmilk_MPr_shortcut_title">Main Menu Shortcut</string>
<!-- Shortcut Description (enabled) -->
<string name="rmilk_MPr_shortcut_desc_enabled">Shortcut will be shown in main menu</string>
<!-- Shortcut Description (disabled) -->
<string name="rmilk_MPr_shortcut_desc_disabled">Shortcut will be hidden in main menu</string>
<!-- Preference Key (do not translate) -->
<string name="rmilk_MPr_shortcut_key">rmilk_shortcut</string>
<!-- Background Wifi Title -->
<string name="rmilk_MPr_bgwifi_title">Wifi Only Setting</string>
<!-- Background Wifi Description (enabled) -->
@ -123,23 +118,10 @@ Error Message: %s
<!-- ======================== Synchronization ========================== -->
<!-- generic sync constants -->
<string name="rmilk_error">Sync Error! Sorry for the inconvenience! Error:</string>
<string name="rmilk_uptodate">Sync: Up to date!</string>
<string name="rmilk_result_title">%s Results</string>
<string name="rmilk_result_local">Summary - Astrid Tasks:</string>
<string name="rmilk_result_remote">Summary - Remote Server:</string>
<string name="rmilk_result_created">Created: %d</string>
<string name="rmilk_result_updated">Updated: %d</string>
<string name="rmilk_result_deleted">Deleted: %d</string>
<string name="rmilk_result_merged">Merged: %d</string>
<!-- rmilk-specific constants -->
<string name="rmilk_notification_title">Astrid: Remember the Milk</string>
<string name="rmilk_forget_confirm">Log out / clear synchronization data?</string>
<string name="rmilk_last_sync">Last Sync Date: %s</string>
<string name="rmilk_last_auto_sync">Last AutoSync Attempt: %s</string>
<string name="rmilk_date_never">never</string>
<string name="rmilk_ioerror">Connection Error! Check your Internet connection,
or maybe RTM servers (status.rememberthemilk.com), for possible solutions.</string>

@ -6,6 +6,7 @@
android:title="@string/rmilk_MPr_group_status">
<Preference
android:layout="@layout/rmilk_status_preference"
android:key="@string/rmilk_MPr_status_key"
android:textSize="24sp"
android:gravity="center"/>
@ -21,10 +22,6 @@
android:entryValues="@array/rmilk_MPr_interval_values"
android:title="@string/rmilk_MPr_interval_title" />
<CheckBoxPreference
android:key="@string/rmilk_MPr_shortcut_key"
android:title="@string/rmilk_MPr_shortcut_title" />
</PreferenceCategory>
<PreferenceCategory

@ -0,0 +1,93 @@
/*
* ASTRID: Android's Simple Task Recording Dashboard
*
* Copyright (c) 2009 Tim Su
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.todoroo.astrid.activity;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.os.Bundle;
import com.todoroo.andlib.sql.QueryTemplate;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.astrid.api.Filter;
/**
* This activity is launched when a user opens up a notification from the
* tray. It launches the appropriate activity based on the passed in parameters.
*
* @author timsu
*
*/
public class ShortcutActivity extends Activity {
// --- constants
/** token for passing a {@link Filter}'s title through extras */
public static final String TOKEN_FILTER_TITLE = "title"; //$NON-NLS-1$
/** token for passing a {@link Filter}'s sql through extras */
public static final String TOKEN_FILTER_SQL = "sql"; //$NON-NLS-1$
/** token for passing a {@link Filter}'s values for new tasks through extras */
public static final String TOKEN_FILTER_VALUES = "v4nt"; //$NON-NLS-1$
/** token for passing a {@link Filter}'s values for new tasks through extras (keys) */
public static final String TOKEN_FILTER_VALUES_KEYS = "v4ntk"; //$NON-NLS-1$
/** token for passing a {@link Filter}'s values for new tasks through extras (values) */
public static final String TOKEN_FILTER_VALUES_VALUES = "v4ntv"; //$NON-NLS-1$
// --- implementation
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
launchTaskList(getIntent());
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
launchTaskList(intent);
}
private void launchTaskList(Intent intent) {
Bundle extras = intent.getExtras();
if(extras != null && extras.containsKey(TOKEN_FILTER_SQL)) {
// launched from desktop shortcut, must create a fake filter
String title = extras.getString(TOKEN_FILTER_TITLE);
String sql = extras.getString(TOKEN_FILTER_SQL);
ContentValues values = null;
if(extras.containsKey(TOKEN_FILTER_VALUES))
values = AndroidUtilities.contentValuesFromString(extras.getString(TOKEN_FILTER_VALUES));
Filter filter = new Filter("", title, new QueryTemplate(), values); //$NON-NLS-1$
filter.sqlQuery = sql;
Intent taskListIntent = new Intent(this, TaskListActivity.class);
taskListIntent.putExtra(TaskListActivity.TOKEN_FILTER, filter);
startActivity(taskListIntent);
}
finish();
}
}

@ -82,6 +82,7 @@ public class TaskListActivity extends ListActivity implements OnScrollListener {
public static final int ACTIVITY_EDIT_TASK = 0;
public static final int ACTIVITY_SETTINGS = 1;
public static final int ACTIVITY_PLUGINS = 2;
public static final int ACTIVITY_MENU_EXTERNAL = 3;
// --- menu codes
@ -238,7 +239,7 @@ public class TaskListActivity extends ListActivity implements OnScrollListener {
Task task = ((ViewHolder)view.getTag()).task;
task.setValue(Task.IMPORTANCE, importance);
taskService.save(task, false);
taskAdapter.setFieldContentsAndVisibility(view, task);
taskAdapter.setFieldContentsAndVisibility(view);
}
return false;
@ -394,15 +395,17 @@ public class TaskListActivity extends ListActivity implements OnScrollListener {
}
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
loadTaskListContent(true);
taskService.cleanup();
if(requestCode == ACTIVITY_EDIT_TASK && resultCode != TaskEditActivity.RESULT_CODE_DISCARDED)
loadTaskListContent(true);
else if(requestCode == ACTIVITY_SETTINGS)
loadTaskListContent(true);
}
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
@ -447,6 +450,7 @@ public class TaskListActivity extends ListActivity implements OnScrollListener {
if(requery) {
taskCursor.requery();
taskAdapter.notifyDataSetChanged();
taskAdapter.flushDetailCache();
}
startManagingCursor(taskCursor);
@ -628,7 +632,7 @@ public class TaskListActivity extends ListActivity implements OnScrollListener {
// context menu items
case CONTEXT_MENU_ADDON_INTENT_ID: {
intent = item.getIntent();
AndroidUtilities.startExternalIntent(this, intent);
AndroidUtilities.startExternalIntent(this, intent, ACTIVITY_MENU_EXTERNAL);
return true;
}

@ -161,7 +161,7 @@ public class TaskAdapter extends CursorAdapter {
Task actionItem = ((ViewHolder)view.getTag()).task;
actionItem.readFromCursor(cursor);
setFieldContentsAndVisibility(view, actionItem);
setFieldContentsAndVisibility(view);
setTaskAppearance(view, actionItem.isCompleted());
}
@ -191,9 +191,10 @@ public class TaskAdapter extends CursorAdapter {
}
/** Helper method to set the contents and visibility of each field */
public void setFieldContentsAndVisibility(View view, Task task) {
public synchronized void setFieldContentsAndVisibility(View view) {
Resources r = activity.getResources();
ViewHolder viewHolder = (ViewHolder)view.getTag();
Task task = viewHolder.task;
// name
final TextView nameView = viewHolder.nameView; {
@ -269,6 +270,13 @@ public class TaskAdapter extends CursorAdapter {
}
}
/**
* Called to tell the cache to be cleared
*/
public void flushDetailCache() {
detailCache.clear();
}
/**
* Respond to a request to add details for a task
*

Loading…
Cancel
Save