Skip to content

Commit

Permalink
Show subtasks on details view. #442
Browse files Browse the repository at this point in the history
  • Loading branch information
Gabor Keszthelyi committed Dec 21, 2017
1 parent 62e6af8 commit 0da7e7d
Show file tree
Hide file tree
Showing 27 changed files with 1,009 additions and 70 deletions.
1 change: 1 addition & 0 deletions .idea/dictionaries/dictionary.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions opentasks-provider/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ dependencies {
exclude module: 'jems'
}
androidTestImplementation 'com.android.support:support-annotations:' + SUPPORT_LIBRARY_VERSION
androidTestImplementation 'com.android.support.test:runner:0.5'
androidTestImplementation 'com.android.support.test:rules:0.5'
androidTestImplementation 'com.android.support.test:runner:' + ANDROID_TEST_RUNNER_VERSION
androidTestImplementation 'com.android.support.test:rules:' + ANDROID_TEST_RUNNER_VERSION
testImplementation 'org.robolectric:robolectric:' + ROBOLECTRIC_VERSION
testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:2.10.0'
Expand Down
9 changes: 9 additions & 0 deletions opentasks/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,14 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
dataBinding {
enabled = true
}
}

dependencies {
implementation project(':opentasks-provider')
implementation project(':opentaskspal')
implementation 'com.android.support:appcompat-v7:' + SUPPORT_LIBRARY_VERSION
implementation 'com.android.support:design:' + SUPPORT_LIBRARY_VERSION
implementation('org.dmfs:android-xml-magic:0.1.1') {
Expand All @@ -66,6 +70,11 @@ dependencies {
implementation 'org.dmfs:jems:' + JEMS_VERSION
implementation 'org.dmfs:rfc5545-datetime:' + RFC5545_DATETIME_VERSION
implementation 'com.github.dmfs.bolts:color-bolts:' + BOLTS_VERSION
implementation('com.github.dmfs.contentpal:contentpal:' + CONTENTPAL_VERSION) {
exclude module: 'jems'
}
implementation 'io.reactivex.rxjava2:rxjava:2.1.5'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'

testImplementation 'junit:junit:4.12'
testImplementation 'org.robolectric:robolectric:3.5.1'
Expand Down
5 changes: 4 additions & 1 deletion opentasks/proguard.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,7 @@
java.lang.String TAG;
@org.dmfs.android.retentionmagic.annotations.* <fields>;
private long mId;
}
}

-dontwarn android.databinding.**
-keep class android.databinding.** { *; }
25 changes: 16 additions & 9 deletions opentasks/src/main/java/org/dmfs/tasks/ViewTaskFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,13 @@
import android.view.animation.AlphaAnimation;
import android.widget.TextView;

import org.dmfs.android.bolts.color.colors.ValueColor;
import org.dmfs.android.bolts.color.elementary.ValueColor;
import org.dmfs.android.retentionmagic.SupportFragment;
import org.dmfs.android.retentionmagic.annotations.Parameter;
import org.dmfs.android.retentionmagic.annotations.Retain;
import org.dmfs.tasks.contract.TaskContract.Tasks;
import org.dmfs.tasks.detailsscreen.SubtasksView;
import org.dmfs.tasks.detailsscreen.SubtasksViewParamsSource;
import org.dmfs.tasks.model.ContentSet;
import org.dmfs.tasks.model.Model;
import org.dmfs.tasks.model.OnContentChangeListener;
Expand All @@ -70,6 +72,8 @@
import java.util.HashSet;
import java.util.Set;

import io.reactivex.disposables.CompositeDisposable;


/**
* A fragment representing a single Task detail screen. This fragment is either contained in a {@link TaskListActivity} in two-pane mode (on tablets) or in a
Expand Down Expand Up @@ -130,6 +134,8 @@ public class ViewTaskFragment extends SupportFragment
*/
private TaskView mDetailView;

private CompositeDisposable mDisposables;

private int mListColor;
private int mOldStatus = -1;
private boolean mPinned = false;
Expand Down Expand Up @@ -207,14 +213,6 @@ public static ViewTaskFragment newInstance(Uri uri)
}


/**
* Mandatory empty constructor for the fragment manager to instantiate the fragment (e.g. upon screen orientation changes).
*/
public ViewTaskFragment()
{
}


@Override
public void onCreate(Bundle savedInstanceState)
{
Expand Down Expand Up @@ -265,6 +263,7 @@ public void onDestroyView()
mDetailView.setValues(null);
}

mDisposables.dispose();
}


Expand Down Expand Up @@ -319,6 +318,8 @@ else if (mTaskUri != null)
loadUri(uri);
}

mDisposables = new CompositeDisposable();

return mRootView;
}

Expand Down Expand Up @@ -715,6 +716,12 @@ public void onContentLoaded(ContentSet contentSet)
postUpdateView();
}
}

mDisposables.add(new SubtasksViewParamsSource(mAppContext, mTaskUri, new ValueColor(mListColor))
.subscribe(subtaskViewParams ->
{
new SubtasksView(mContent).update(subtaskViewParams);
}));
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright 2017 dmfs GmbH
*
* 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.
*/

package org.dmfs.tasks.detailsscreen;

import android.content.Context;
import android.content.Intent;
import android.databinding.DataBindingUtil;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;

import org.dmfs.android.bolts.color.Color;
import org.dmfs.optional.Optional;
import org.dmfs.rfc5545.DateTime;
import org.dmfs.tasks.R;
import org.dmfs.tasks.databinding.OpentasksViewItemTaskDetailsSubtaskBinding;
import org.dmfs.tasks.readdata.TaskContentUri;
import org.dmfs.tasks.utils.DateFormatter;
import org.dmfs.tasks.utils.DateFormatter.DateFormatContext;
import org.dmfs.tasks.widget.ProgressBackgroundView;
import org.dmfs.tasks.widget.SmartView;


/**
* {@link View} for showing a subtask on the details screen.
*
* @author Gabor Keszthelyi
*/
public final class SubtaskView extends FrameLayout implements SmartView<SubtaskView.Params>
{

public interface Params // i.e. fields of the subtask
{
Long id();

Optional<CharSequence> title();

Optional<DateTime> due();

Color color();

Optional<Integer> percentComplete();
}


public SubtaskView(@NonNull Context context, @Nullable AttributeSet attrs)
{
super(context, attrs);
}


@Override
public void update(Params subtask)
{
OpentasksViewItemTaskDetailsSubtaskBinding views = DataBindingUtil.bind(this);

views.opentasksTaskDetailsSubtaskTitle.setText(subtask.title().value(getContext().getString(R.string.opentasks_task_details_subtask_untitled)));

if (subtask.due().isPresent())
{
views.opentasksTaskDetailsSubtaskDue.setText(
new DateFormatter(getContext()).format(subtask.due().value(), DateTime.now(), DateFormatContext.LIST_VIEW));
}

views.opentasksTaskDetailsSubtaskListRibbon.setBackgroundColor(subtask.color().argb());

new ProgressBackgroundView(views.opentasksTaskDetailsSubtaskProgressBackground)
.update(subtask.percentComplete());

views.getRoot().setOnClickListener((v) ->
{
Context ctx = v.getContext();
// TODO Use BasicTaskDetailsUi class when #589 is merged
ctx.startActivity(new Intent(Intent.ACTION_VIEW, new TaskContentUri(subtask.id(), ctx).value()));
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Copyright 2017 dmfs GmbH
*
* 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.
*/

package org.dmfs.tasks.detailsscreen;

import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.TextView;

import org.dmfs.android.bolts.color.Color;
import org.dmfs.tasks.R;
import org.dmfs.tasks.widget.PopulateableViewGroup;
import org.dmfs.tasks.widget.SmartView;
import org.dmfs.tasks.widget.UpdatedSmartViews;


/**
* {@link SmartView} for the subtasks section of the task details screen.
*
* @author Gabor Keszthelyi
*/
public final class SubtasksView implements SmartView<SubtasksView.Params>
{
public interface Params
{
Color taskListColor();

Iterable<SubtaskView.Params> subtasks();
}


private final ViewGroup mContentView;


public SubtasksView(ViewGroup contentView)
{
mContentView = contentView;
}


@Override
public void update(SubtasksView.Params params)
{
if (!params.subtasks().iterator().hasNext())
{
// Don't show the subtasks UI section if there are no subtasks
return;
}

LayoutInflater inflater = LayoutInflater.from(mContentView.getContext());

inflater.inflate(R.layout.opentasks_view_item_divider, mContentView);

TextView sectionHeader = (TextView) inflater.inflate(R.layout.opentasks_view_item_task_details_subtitles_section_header, null);
sectionHeader.setTextColor(new Darkened(params.taskListColor()).argb());
mContentView.addView(sectionHeader);

new PopulateableViewGroup<SubtaskView>(mContentView)
.populate(new UpdatedSmartViews<>(params.subtasks(), inflater, R.layout.opentasks_view_item_task_details_subtask));
}


// TODO Remove when #522 is merged, use the version from there
private static final class Darkened implements Color
{
private final Color mOriginal;


private Darkened(Color original)
{
mOriginal = original;
}


@Override
public int argb()
{
float[] hsv = new float[3];
android.graphics.Color.colorToHSV(mOriginal.argb(), hsv);
hsv[2] = hsv[2] * 0.75f;
return android.graphics.Color.HSVToColor(hsv);
}
}
}
Loading

0 comments on commit 0da7e7d

Please sign in to comment.