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 authored and dmfs committed Apr 11, 2020
1 parent 08bbda6 commit 5f12777
Show file tree
Hide file tree
Showing 27 changed files with 1,108 additions and 73 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.

7 changes: 7 additions & 0 deletions opentasks/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,14 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
dataBinding {
enabled = true
}
}

dependencies {
implementation project(':opentasks-provider')
implementation project(':opentaskspal')
implementation deps.support_appcompat
implementation deps.support_design
implementation(deps.xml_magic) {
Expand All @@ -81,6 +85,9 @@ dependencies {
implementation deps.datetime
implementation deps.bolts_color
implementation deps.retention_magic
implementation deps.contentpal
implementation 'io.reactivex.rxjava2:rxjava:2.1.5'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'

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

-dontwarn android.databinding.**
-keep class android.databinding.** { *; }
16 changes: 16 additions & 0 deletions opentasks/src/main/java/org/dmfs/tasks/ViewTaskFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@
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.RowDataSubtaskViewParams;
import org.dmfs.tasks.detailsscreen.RowDataSubtasksViewParams;
import org.dmfs.tasks.detailsscreen.SubtasksSource;
import org.dmfs.tasks.detailsscreen.SubtasksView;
import org.dmfs.tasks.model.ContentSet;
import org.dmfs.tasks.model.Model;
import org.dmfs.tasks.model.OnContentChangeListener;
Expand All @@ -74,6 +78,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 @@ -135,6 +141,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 @@ -252,12 +260,14 @@ public void onDestroyView()
mDetailView.setValues(null);
}

mDisposables.dispose();
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
mDisposables = new CompositeDisposable();
mShowFloatingActionButton = !getResources().getBoolean(R.bool.has_two_panes);

mRootView = inflater.inflate(R.layout.fragment_task_view_detail, container, false);
Expand Down Expand Up @@ -442,6 +452,12 @@ private void updateView()
((TextView) mToolBar.findViewById(R.id.toolbar_title)).setText(TaskFieldAdapters.TITLE.get(mContentSet));
}
}

mDisposables.add(new SubtasksSource(mAppContext, mTaskUri, RowDataSubtaskViewParams.SUBTASK_PROJECTION)
.subscribe(subtasks ->
{
new SubtasksView(mContent).update(new RowDataSubtasksViewParams(new ValueColor(mListColor), subtasks));
}));
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright 2018 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 org.dmfs.android.bolts.color.Color;
import org.dmfs.android.contentpal.Projection;
import org.dmfs.android.contentpal.RowDataSnapshot;
import org.dmfs.android.contentpal.projections.Composite;
import org.dmfs.jems.optional.Optional;
import org.dmfs.opentaskspal.readdata.EffectiveDueDate;
import org.dmfs.opentaskspal.readdata.EffectiveTaskColor;
import org.dmfs.opentaskspal.readdata.Id;
import org.dmfs.opentaskspal.readdata.PercentComplete;
import org.dmfs.opentaskspal.readdata.TaskTitle;
import org.dmfs.rfc5545.DateTime;
import org.dmfs.tasks.contract.TaskContract;


/**
* {@link SubtasksView.Params} that reads the data from the given {@link RowDataSnapshot}.
*
* @author Gabor Keszthelyi
*/
public final class RowDataSubtaskViewParams implements SubtaskView.Params
{

/**
* The projection required for this adapter to work.
*/
public static final Projection<TaskContract.Tasks> SUBTASK_PROJECTION = new Composite<>(
Id.PROJECTION,
TaskTitle.PROJECTION,
EffectiveDueDate.PROJECTION,
EffectiveTaskColor.PROJECTION,
PercentComplete.PROJECTION
);

private final RowDataSnapshot<TaskContract.Tasks> mRowDataSnapshot;


public RowDataSubtaskViewParams(RowDataSnapshot<TaskContract.Tasks> rowDataSnapshot)
{
mRowDataSnapshot = rowDataSnapshot;
}


@Override
public Long id()
{
return new Id(mRowDataSnapshot).value();
}


@Override
public Optional<CharSequence> title()
{
return new TaskTitle(mRowDataSnapshot);
}


@Override
public Optional<DateTime> due()
{
return new EffectiveDueDate(mRowDataSnapshot);
}


@Override
public Color color()
{
return new EffectiveTaskColor(mRowDataSnapshot);
}


@Override
public Optional<Integer> percentComplete()
{
return new PercentComplete(mRowDataSnapshot);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2018 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 org.dmfs.android.bolts.color.Color;
import org.dmfs.android.contentpal.RowDataSnapshot;
import org.dmfs.jems.iterable.decorators.Mapped;
import org.dmfs.tasks.contract.TaskContract;


/**
* {@link SubtasksView.Params} that adapts the given {@link RowDataSnapshot}s (and takes the list color).
*
* @author Gabor Keszthelyi
*/
public final class RowDataSubtasksViewParams implements SubtasksView.Params
{
private final Color mTaskListColor;
private final Iterable<RowDataSnapshot<TaskContract.Tasks>> mSubtaskRows;


public RowDataSubtasksViewParams(Color taskListColor, Iterable<RowDataSnapshot<TaskContract.Tasks>> subtaskRows)
{
mTaskListColor = taskListColor;
mSubtaskRows = subtaskRows;
}


@Override
public Color taskListColor()
{
return mTaskListColor;
}


@Override
public Iterable<SubtaskView.Params> subtasks()
{
return new Mapped<>(RowDataSubtaskViewParams::new, mSubtaskRows);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* 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.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;

import org.dmfs.android.bolts.color.Color;
import org.dmfs.jems.optional.Optional;
import org.dmfs.jems.single.combined.Backed;
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;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;


/**
* {@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(
new Backed<>(subtask.title(), getContext().getString(R.string.opentasks_task_details_subtask_untitled)).value());

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()));
});
}
}
Loading

0 comments on commit 5f12777

Please sign in to comment.