Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor to always replace task details fragments instead of updating… #630

Merged
merged 1 commit into from
Sep 25, 2018

Conversation

lemonboston
Copy link
Contributor

@lemonboston lemonboston commented Jan 11, 2018

… them when new task is selected. #624


@dmfs It took some time to get everything correctly working here but it looks good now for me.

There is a field in TaskListActivity now to save the last used color, so it can be used while the selected task is loaded. It is useful upon starting up the app and after rotation.

EmptyTaskFragment also has a hint color now, so we don't change back the color to primary after a deletion but keep it as it was for that task.

ViewTaskFragment can be further simplified after these changes, I've created a separate ticket for that: #628

This pull request should fix #609 and #525, too.

I've created 3 new classes for reading arguments from Bundle here, in order to read the color argument. They help now, but the plan would be to remove and replace them once the full solution from boxed-bolts is available, since that approach is much better and more general.

Uri taskUri = ContentUris.withAppendedId(Tasks.getContentUri(mAuthority), selectTaskId);
// TODO For now we get the id of the task, not the instance, once we support recurrence we'll have to change that, use instance URI that time
Uri taskUri = ContentUris.withAppendedId(Tasks.getContentUri(mAuthority), (long) TaskFieldAdapters.TASK_ID.get(cursor));
// TODO Should we use TASK_COLOR? (That's not in the projection.)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, TASK_COLOR should be used as some sort of secondary color, like on a banner, badge or additional color bar.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, good to know. I've updated the parameter names to refer to the task list color.

@lemonboston
Copy link
Contributor Author

@dmfs I've made the color args mandatory for the Fragments as discussed on Slack. It allowed to remove classes, simplify the code.

I've kept Conditional and OptionalNonTransparentIntColor they seem okay for me, but that usage could be replaced with a ternary operator, let me know if you would prefer that.

@lemonboston
Copy link
Contributor Author

I've changed my mind about those 2 classes, not worth adding and maintaining them for a single if, so I've removed them.

@dmfs
Copy link
Owner

dmfs commented Jan 15, 2018

On tablets it looks a bit strange that the details view is faded while the main app bar just changes instantly. For now it's ok but we should think of something to improve this later on.
I mean when you switch to a task with a different color.

@dmfs
Copy link
Owner

dmfs commented Jan 15, 2018

I like that the app bar stays with the color of the last task when you delete it, instead of going back to the primary color.

@dmfs
Copy link
Owner

dmfs commented Jan 15, 2018

Rotating on a small tablet still doesn't work properly.

Steps to reproduce:

  • open a task in portrait mode, the details should show up full screen
  • rotate to landscape

Expected result:

  • same task is opened in the details pane

Actual result:

  • a different task is opened in the details pane

Similarly (and probably related)

  • select a task in landscape mode
  • rotate to portrait (the list view shows up)
  • rotate back to landscape

Expected result:

  • the same task is selected

Actual result:

  • a different task is selected

@@ -65,7 +67,7 @@ protected void onCreate(Bundle savedInstanceState)

if (savedInstanceState == null)
{
ViewTaskFragment fragment = ViewTaskFragment.newInstance(getIntent().getData());
ViewTaskFragment fragment = ViewTaskFragment.newInstance(getIntent().getData(), new PrimaryColor(this));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about passing this color to the activity as well? On my device I see the primary color briefly when opening a task, we could avoid that by passing the color to the ViewTaskActivity. Just make sure you tolerate the absence of the color in case it's called by an external app.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added color as an optional extra to ViewTaskActivity.

@lemonboston
Copy link
Contributor Author

Strange, I couldn't reproduce the first case you described, that works as expected for me. I had also tested this.
And for the second case, for me the empty fragment is shown when turning back to landscape. With correct color, so that is saved, but the selected task is not.

I compared with master, I see it works correctly there, and that the selected task item is highlighted in portrait mode as well.

I am going to look into this.

@dmfs
Copy link
Owner

dmfs commented Jan 16, 2018

Make sure you create multiple tasks and select one of the latter ones.

@lemonboston
Copy link
Contributor Author

lemonboston commented Jan 16, 2018

I've pushed a branch named mx/624-investigation which add some logs on top of this branch.
Here are the logs from the Nexus 7 Android 8.0 emulator, for the following action:

  • clean install, 3 tasks created with quick add dialog (in landscape mode)
  • select the last one (the log starts here)
  • rotate once
  • rotate again
01-16 17:48:26.723 7738-7738/org.dmfs.tasks D/Investigator: [main] TaskListActivity@4b9ca7a.onItemSelected() | uri = content://org.dmfs.tasks/tasks/3 | color = -15042873 | force = true | pos = 0
                                                                at org.dmfs.tasks.TaskListFragment.selectChildView(TaskListFragment.java:513)
                                                                at org.dmfs.tasks.TaskListFragment.access$000(TaskListFragment.java:87)
                                                                at org.dmfs.tasks.TaskListFragment$1.onChildClick(TaskListFragment.java:154)
                                                                at android.widget.ExpandableListView.handleItemClick(ExpandableListView.java:714)
                                                                at android.widget.ExpandableListView.performItemClick(ExpandableListView.java:653)
01-16 17:48:26.763 7738-7738/org.dmfs.tasks D/Investigator: [main] TaskListActivity@4b9ca7a.replaceTaskDetailsFragment() | fragment = ViewTaskFragment{184c577}
                                                                at org.dmfs.tasks.TaskListActivity.onItemSelected(TaskListActivity.java:410)
                                                                at org.dmfs.tasks.TaskListFragment.selectChildView(TaskListFragment.java:513)
                                                                at org.dmfs.tasks.TaskListFragment.access$000(TaskListFragment.java:87)
                                                                at org.dmfs.tasks.TaskListFragment$1.onChildClick(TaskListFragment.java:154)
01-16 17:48:53.911 7738-7738/org.dmfs.tasks D/Investigator: [main] TaskListActivity@9999c9.onCreate() | selectedUri = null | color = -15042873 | savedState = Bundle[{android:viewHierarchyState=Bundle[{android:views={16908290=android.view.AbsSavedState$1@ac589f4, 2131296261=android.view.View$BaseSavedState@cdc451d, 2131296272=android.view.View$BaseSavedState@8467392, 2131296284=android.view.View$BaseSavedState@221e163, 2131296352=android.view.AbsSavedState$1@ac589f4, 2131296398=FragmentPager.SavedState{ab5160 position=0}, 2131296452=HorizontalScrollView.SavedState{bfd1619 scrollPosition=0}, 2131296455=android.view.View$BaseSavedState@7d436de, 2131296510=android.support.v7.widget.Toolbar$SavedState@bc730bf}, android:focusedViewId=16908298}], android:support:fragments=android.support.v4.app.FragmentManagerState@764238c, mCurrentPageId=0, mLastUsedColor=-15042873, @android:autofillResetNeeded=true, mShouldShowDetails=true, mShouldSwitchToDetail=false, mSelectedTaskUri=null, android:lastAutofillId=1073741874, android:sessionId=623073871}]
01-16 17:48:54.600 7738-7738/org.dmfs.tasks D/Investigator: [main] TaskListActivity@9999c9.onItemSelected() | uri = content://org.dmfs.tasks/tasks/3 | color = -15042873 | force = false | pos = 0
                                                                at org.dmfs.tasks.TaskListFragment.selectChildView(TaskListFragment.java:513)
                                                                at org.dmfs.tasks.TaskListFragment.access$000(TaskListFragment.java:87)
                                                                at org.dmfs.tasks.TaskListFragment$7.run(TaskListFragment.java:911)
                                                                at android.os.Handler.handleCallback(Handler.java:789)
                                                                at android.os.Handler.dispatchMessage(Handler.java:98)
01-16 17:49:24.418 7738-7738/org.dmfs.tasks D/Investigator: [main] TaskListActivity@8b64b62.onCreate() | selectedUri = null | color = -15042873 | savedState = Bundle[{android:viewHierarchyState=Bundle[{android:views={16908290=android.view.AbsSavedState$1@ac589f4, 2131296261=android.view.View$BaseSavedState@c4a481a, 2131296272=android.view.View$BaseSavedState@bb4cf4b, 2131296352=android.view.AbsSavedState$1@ac589f4, 2131296398=FragmentPager.SavedState{2274d28 position=0}, 2131296452=HorizontalScrollView.SavedState{92e3a41 scrollPosition=0}, 2131296510=android.support.v7.widget.Toolbar$SavedState@db4cbe6}, android:focusedViewId=16908298}], android:support:fragments=android.support.v4.app.FragmentManagerState@5ff1527, mCurrentPageId=0, mLastUsedColor=-15042873, @android:autofillResetNeeded=true, mShouldShowDetails=false, mShouldSwitchToDetail=false, mSelectedTaskUri=null, android:lastAutofillId=1073741874}]
01-16 17:49:24.419 7738-7738/org.dmfs.tasks D/Investigator: [main] TaskListActivity@8b64b62.replaceTaskDetailsFragment() | fragment = EmptyTaskFragment{93813d4}
                                                                at org.dmfs.tasks.TaskListActivity.onCreate(TaskListActivity.java:234)
                                                                at android.app.Activity.performCreate(Activity.java:6975)
                                                                at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
                                                                at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
01-16 17:49:25.040 7738-7738/org.dmfs.tasks D/Investigator: [main] TaskListActivity@8b64b62.onItemSelected() | uri = content://org.dmfs.tasks/tasks/3 | color = -15042873 | force = false | pos = 0
                                                                at org.dmfs.tasks.TaskListFragment.selectChildView(TaskListFragment.java:513)
                                                                at org.dmfs.tasks.TaskListFragment.access$000(TaskListFragment.java:87)
                                                                at org.dmfs.tasks.TaskListFragment$7.run(TaskListFragment.java:911)
                                                                at android.os.Handler.handleCallback(Handler.java:789)
                                                                at android.os.Handler.dispatchMessage(Handler.java:98)
01-16 17:49:25.043 7738-7738/org.dmfs.tasks D/Investigator: [main] TaskListActivity@8b64b62.replaceTaskDetailsFragment() | fragment = ViewTaskFragment{ff03f0b}
                                                                at org.dmfs.tasks.TaskListActivity.onItemSelected(TaskListActivity.java:410)
                                                                at org.dmfs.tasks.TaskListFragment.selectChildView(TaskListFragment.java:513)
                                                                at org.dmfs.tasks.TaskListFragment.access$000(TaskListFragment.java:87)
                                                                at org.dmfs.tasks.TaskListFragment$7.run(TaskListFragment.java:911)

@lemonboston lemonboston force-pushed the mx/624-task-details-fragment-replace branch from 041d5d3 to f2d9d6c Compare January 16, 2018 21:15
@lemonboston
Copy link
Contributor Author

I've found the bug for the task list item selection highlight - TaskListFragment had the twoPane variable as fragment argument, so it kept its value after rotation. And the highlighting is based on that.
I've changed it to simply read the has_two_pane bool resource which I suppose we should use at all places.
Ready for checking again.

@lemonboston
Copy link
Contributor Author

lemonboston commented Jan 18, 2018

I've added two more changes today, to fix issues on small tablet:
-- fix the case when selected item in landscape mode is deleted by swiping it out - it now replaces the fragment with EmptyTaskFragment and the list is shown after rotation
-- fix the case of missing selection highlight when rotating to landscape, also fixing to keep the correct task selected

Note that some of the issues we've encountered are already present in master version.
I've added bugs: #640, #641, #642

#642 should be partially fixed here.

The behaviour for showing the details in portrait mode is still not perfect:
it works if we don't change selection in landscape mode, but if we do, then the list is shown after rotating back to portrait.
But as I saw on master, this doesn't work at all there, even without changing selection.
So for this case that still doesn't work, we could add a low priority bug.

Ready for check again.

@dmfs
Copy link
Owner

dmfs commented Jan 18, 2018

It's expected behavior that the list is shown when you select a new task in landscape mode and rotate to portrait mode.

@dmfs
Copy link
Owner

dmfs commented Jan 18, 2018

The latest version crashes for me when adding a task in single pane mode:

01-18 22:03:52.175  4629  4629 E AndroidRuntime: Process: org.dmfs.tasks, PID: 4629
01-18 22:03:52.175  4629  4629 E AndroidRuntime: java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference
01-18 22:03:52.175  4629  4629 E AndroidRuntime: 	at org.dmfs.tasks.model.adapters.ColorFieldAdapter.get(ColorFieldAdapter.java:93)
01-18 22:03:52.175  4629  4629 E AndroidRuntime: 	at org.dmfs.tasks.EditTaskFragment.saveAndExit(EditTaskFragment.java:798)
01-18 22:03:52.175  4629  4629 E AndroidRuntime: 	at org.dmfs.tasks.EditTaskFragment.onOptionsItemSelected(EditTaskFragment.java:539)
01-18 22:03:52.175  4629  4629 E AndroidRuntime: 	at android.support.v4.app.Fragment.performOptionsItemSelected(Fragment.java:2379)
01-18 22:03:52.175  4629  4629 E AndroidRuntime: 	at android.support.v4.app.FragmentManagerImpl.dispatchOptionsItemSelected(FragmentManager.java:3133)
01-18 22:03:52.175  4629  4629 E AndroidRuntime: 	at android.support.v4.app.FragmentController.dispatchOptionsItemSelected(FragmentController.java:344)
01-18 22:03:52.175  4629  4629 E AndroidRuntime: 	at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:414)
01-18 22:03:52.175  4629  4629 E AndroidRuntime: 	at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:195)
01-18 22:03:52.175  4629  4629 E AndroidRuntime: 	at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:113)
01-18 22:03:52.175  4629  4629 E AndroidRuntime: 	at android.support.v7.app.AppCompatDelegateImplV9.onMenuItemSelected(AppCompatDelegateImplV9.java:679)
01-18 22:03:52.175  4629  4629 E AndroidRuntime: 	at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:822)
01-18 22:03:52.175  4629  4629 E AndroidRuntime: 	at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:156)
01-18 22:03:52.175  4629  4629 E AndroidRuntime: 	at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:969)

@dmfs
Copy link
Owner

dmfs commented Jan 18, 2018

crashes in two-pane mode as well

activity.startActivity(new Intent("android.intent.action.VIEW", mTaskUri));
activity.startActivity(
new Intent(Intent.ACTION_VIEW, mTaskUri)
.putExtra(ViewTaskActivity.EXTRA_COLOR, TaskFieldAdapters.LIST_COLOR.get(mValues)));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't work and causes the aforementioned crash because mValues doesn't contain the list color at this point. If the task is new, mValues has been created from scratch and not been loaded from the database, so it doesn't contain the list color yet.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a field called mListColor which holds the color of the currently selected list.

@dmfs
Copy link
Owner

dmfs commented Jan 18, 2018

Another crash when deleting a task in two-pane mode

01-18 22:27:15.716  4404  4905 E AndroidRuntime: Process: org.dmfs.tasks, PID: 4404
01-18 22:27:15.716  4404  4905 E AndroidRuntime: java.lang.RuntimeException: An error occurred while executing doInBackground()
01-18 22:27:15.716  4404  4905 E AndroidRuntime: 	at android.os.AsyncTask$3.done(AsyncTask.java:353)
01-18 22:27:15.716  4404  4905 E AndroidRuntime: 	at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
01-18 22:27:15.716  4404  4905 E AndroidRuntime: 	at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
01-18 22:27:15.716  4404  4905 E AndroidRuntime: 	at java.util.concurrent.FutureTask.run(FutureTask.java:271)
01-18 22:27:15.716  4404  4905 E AndroidRuntime: 	at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
01-18 22:27:15.716  4404  4905 E AndroidRuntime: 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
01-18 22:27:15.716  4404  4905 E AndroidRuntime: 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
01-18 22:27:15.716  4404  4905 E AndroidRuntime: 	at java.lang.Thread.run(Thread.java:764)
01-18 22:27:15.716  4404  4905 E AndroidRuntime: Caused by: java.lang.NullPointerException: uri
01-18 22:27:15.716  4404  4905 E AndroidRuntime: 	at com.android.internal.util.Preconditions.checkNotNull(Preconditions.java:128)
01-18 22:27:15.716  4404  4905 E AndroidRuntime: 	at android.content.ContentResolver.query(ContentResolver.java:737)
01-18 22:27:15.716  4404  4905 E AndroidRuntime: 	at android.content.ContentResolver.query(ContentResolver.java:704)
01-18 22:27:15.716  4404  4905 E AndroidRuntime: 	at android.content.ContentResolver.query(ContentResolver.java:662)
01-18 22:27:15.716  4404  4905 E AndroidRuntime: 	at org.dmfs.tasks.utils.AsyncContentLoader.doInBackground(AsyncContentLoader.java:76)
01-18 22:27:15.716  4404  4905 E AndroidRuntime: 	at org.dmfs.tasks.utils.AsyncContentLoader.doInBackground(AsyncContentLoader.java:34)
01-18 22:27:15.716  4404  4905 E AndroidRuntime: 	at android.os.AsyncTask$2.call(AsyncTask.java:333)
01-18 22:27:15.716  4404  4905 E AndroidRuntime: 	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
01-18 22:27:15.716  4404  4905 E AndroidRuntime: 	... 4 more

@lemonboston
Copy link
Contributor Author

I've fixed the first crash about the color.

I couldn't reproduce the 2nd one when deleting a task. I tried to figure it out from the stacktrace what may cause that and applied a speculative fix.
If you remember or can reproduce it, could you please describe the steps?

Ready for check again.

@dmfs
Copy link
Owner

dmfs commented Jan 29, 2018

This is still not working correctly. Try on a phone:

  • open task editor
  • enter title
  • save
  • press back to return to the list
  • rotate the device

Expected behavior

The list is still shown

Actual behavior

The just closed details view is shown

@dmfs
Copy link
Owner

dmfs commented Jan 29, 2018

I'll look into that.

… them when new task is selected. #624

Potential fix for the mysterious bugs on certain emulators.

Fix task list item selection highlight issue by changing the twopane flag from being a TaskListFragment extra to just being read from the bool resource.

Fix issue on small tablet, rotating to portrait not opening up task again.

Fix issue when deleting a task and rotating.

Fix the case when selected item is deleted by swiping it out in two pane mode.

Fix the case when previously select task was shown incorrectly.

Fix crash related to color when a new task is created with the editor.

Compare task uri in ViewTaskFragment.Callback#onTaskDeleted() as well just to be sure. Rename callback methods, move implementations next to each other.

Speculative fix for the crash when a task was deleted.
@dmfs dmfs force-pushed the mx/624-task-details-fragment-replace branch from b311605 to 329cf7e Compare September 25, 2018 09:37
@dmfs dmfs merged commit cef62e0 into master Sep 25, 2018
@dmfs dmfs deleted the mx/624-task-details-fragment-replace branch September 25, 2018 21:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Play Store report: NPE in showFloatingActionButton
2 participants