/*
* Copyright 2011 Azwan Adli Abdullah
*
* 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 com.gh4a.activities;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.Loader;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.view.ActionMode;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import com.gh4a.BaseActivity;
import com.gh4a.Gh4Application;
import com.gh4a.ProgressDialogTask;
import com.gh4a.R;
import com.gh4a.adapter.IssueLabelAdapter;
import com.gh4a.adapter.RootAdapter;
import com.gh4a.loader.LabelListLoader;
import com.gh4a.loader.LoaderCallbacks;
import com.gh4a.loader.LoaderResult;
import com.gh4a.utils.UiUtils;
import com.gh4a.widget.DividerItemDecoration;
import org.eclipse.egit.github.core.Label;
import org.eclipse.egit.github.core.RepositoryId;
import org.eclipse.egit.github.core.service.LabelService;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
public class IssueLabelListActivity extends BaseActivity implements
RootAdapter.OnItemClickListener<IssueLabelAdapter.EditableLabel>, View.OnClickListener {
public static Intent makeIntent(Context context, String repoOwner, String repoName,
boolean fromPullRequest) {
return new Intent(context, IssueLabelListActivity.class)
.putExtra("owner", repoOwner)
.putExtra("repo", repoName)
.putExtra("from_pr", fromPullRequest);
}
private String mRepoOwner;
private String mRepoName;
private boolean mParentIsPullRequest;
private EditActionMode mActionMode;
private IssueLabelAdapter.EditableLabel mAddedLabel;
private FloatingActionButton mFab;
private IssueLabelAdapter mAdapter;
private static final String STATE_KEY_ADDED_LABEL = "added_label";
private static final String STATE_KEY_EDITING_LABEL = "editing_label";
private final LoaderCallbacks<List<Label>> mLabelCallback = new LoaderCallbacks<List<Label>>(this) {
@Override
protected Loader<LoaderResult<List<Label>>> onCreateLoader() {
return new LabelListLoader(IssueLabelListActivity.this, mRepoOwner, mRepoName);
}
@Override
protected void onResultReady(List<Label> result) {
UiUtils.hideImeForView(getCurrentFocus());
mAdapter.clear();
for (Label label : result) {
mAdapter.add(new IssueLabelAdapter.EditableLabel(label));
}
setContentShown(true);
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.generic_list);
setContentShown(false);
ActionBar actionBar = getSupportActionBar();
actionBar.setTitle(R.string.issue_labels);
actionBar.setSubtitle(mRepoOwner + "/" + mRepoName);
actionBar.setDisplayHomeAsUpEnabled(true);
mAdapter = new IssueLabelAdapter(this);
mAdapter.setOnItemClickListener(this);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.addItemDecoration(new DividerItemDecoration(this));
recyclerView.setTag(R.id.FloatingActionButtonScrollEnabled, new Object());
recyclerView.setAdapter(mAdapter);
CoordinatorLayout rootLayout = getRootLayout();
mFab = (FloatingActionButton) getLayoutInflater().inflate(
R.layout.add_fab, rootLayout, false);
mFab.setOnClickListener(this);
rootLayout.addView(mFab);
updateFabVisibility();
getSupportLoaderManager().initLoader(0, null, mLabelCallback);
if (savedInstanceState != null) {
if (savedInstanceState.containsKey(STATE_KEY_ADDED_LABEL)) {
mAddedLabel = (IssueLabelAdapter.EditableLabel)
savedInstanceState.getSerializable(STATE_KEY_EDITING_LABEL);
mAdapter.add(mAddedLabel);
startEditing(mAddedLabel);
} else if (savedInstanceState.containsKey(STATE_KEY_EDITING_LABEL)) {
IssueLabelAdapter.EditableLabel label = (IssueLabelAdapter.EditableLabel)
savedInstanceState.getSerializable(STATE_KEY_EDITING_LABEL);
int count = mAdapter.getCount();
for (int i = 0; i < count; i++) {
IssueLabelAdapter.EditableLabel item = mAdapter.getItem(i);
if (item.getName().equals(label.getName())) {
item.editedName = label.editedName;
item.editedColor = label.editedColor;
startEditing(item);
break;
}
}
}
}
}
@Override
protected void onInitExtras(Bundle extras) {
super.onInitExtras(extras);
mRepoOwner = extras.getString("owner");
mRepoName = extras.getString("repo");
mParentIsPullRequest = extras.getBoolean("from_pr", false);
}
@Override
protected boolean canSwipeToRefresh() {
// swipe-to-refresh doesn't make much sense in the
// interaction model of this activity
return false;
}
@Override
public void onRefresh() {
setContentShown(false);
mAdapter.clear();
forceLoaderReload(0);
super.onRefresh();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mActionMode != null) {
if (mAddedLabel != null) {
outState.putSerializable(STATE_KEY_ADDED_LABEL, mAddedLabel);
} else {
outState.putSerializable(STATE_KEY_EDITING_LABEL, mActionMode.mLabel);
}
}
}
@Override
public void onItemClick(IssueLabelAdapter.EditableLabel item) {
if (mActionMode == null) {
startEditing(item);
}
}
@Override
protected Intent navigateUp() {
return IssueListActivity.makeIntent(this, mRepoOwner, mRepoName, mParentIsPullRequest);
}
@Override
public void onClick(View view) {
if (mActionMode == null) {
mAddedLabel = new IssueLabelAdapter.EditableLabel("dddddd");
mAdapter.add(mAddedLabel);
mAdapter.notifyDataSetChanged();
startEditing(mAddedLabel);
}
}
private void startEditing(IssueLabelAdapter.EditableLabel label) {
mActionMode = new EditActionMode(label);
mAdapter.notifyDataSetChanged();
startSupportActionMode(mActionMode);
updateFabVisibility();
}
private void updateFabVisibility() {
boolean visible = Gh4Application.get().isAuthorized() && mActionMode == null;
mFab.setVisibility(visible ? View.VISIBLE : View.GONE);
}
private final class EditActionMode implements ActionMode.Callback {
private final IssueLabelAdapter.EditableLabel mLabel;
public EditActionMode(IssueLabelAdapter.EditableLabel label) {
mLabel = label;
mLabel.isEditing = true;
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuItem saveItem = menu.add(Menu.NONE, Menu.FIRST, Menu.NONE, R.string.save)
.setIcon(R.drawable.content_save);
MenuItemCompat.setShowAsAction(saveItem, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
if (mLabel != mAddedLabel) {
MenuItem deleteItem = menu.add(Menu.NONE, Menu.FIRST + 1, Menu.NONE, R.string.delete)
.setIcon(R.drawable.content_discard);
MenuItemCompat.setShowAsAction(deleteItem, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
}
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case Menu.FIRST:
if (mLabel == mAddedLabel) {
new AddIssueLabelTask(mLabel.editedName, mLabel.editedColor).schedule();
} else {
new EditIssueLabelTask(mLabel.getName(), mLabel.editedName, mLabel.editedColor)
.schedule();
}
break;
case Menu.FIRST + 1:
new AlertDialog.Builder(IssueLabelListActivity.this)
.setMessage(getString(R.string.issue_dialog_delete_message, mLabel.getName()))
.setPositiveButton(R.string.delete, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
new DeleteIssueLabelTask(mLabel.getName()).schedule();
}
})
.setNegativeButton(R.string.cancel, null)
.show();
break;
default:
break;
}
mode.finish();
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
mLabel.isEditing = false;
if (mLabel == mAddedLabel) {
mAdapter.remove(mLabel);
mAddedLabel = null;
} else {
mLabel.restoreOriginalProperties();
}
mAdapter.notifyDataSetChanged();
updateFabVisibility();
}
}
private class DeleteIssueLabelTask extends ProgressDialogTask<Void> {
private final String mLabelName;
public DeleteIssueLabelTask(String labelName) {
super(IssueLabelListActivity.this, R.string.deleting_msg);
mLabelName = labelName;
}
@Override
protected ProgressDialogTask<Void> clone() {
return new DeleteIssueLabelTask(mLabelName);
}
@Override
protected Void run() throws IOException {
LabelService labelService = (LabelService)
Gh4Application.get().getService(Gh4Application.LABEL_SERVICE);
labelService.deleteLabel(mRepoOwner, mRepoName, URLEncoder.encode(mLabelName, "UTF-8"));
return null;
}
@Override
protected void onSuccess(Void result) {
forceLoaderReload(0);
setResult(RESULT_OK);
}
@Override
protected String getErrorMessage() {
return getContext().getString(R.string.issue_error_delete_label, mLabelName);
}
}
private class EditIssueLabelTask extends ProgressDialogTask<Void> {
private final String mOldLabelName;
private final String mNewLabelName;
private final String mColor;
public EditIssueLabelTask(String oldLabelName, String newLabelName, String color) {
super(IssueLabelListActivity.this, R.string.saving_msg);
mOldLabelName = oldLabelName;
mNewLabelName = newLabelName;
mColor = color;
}
@Override
protected ProgressDialogTask<Void> clone() {
return new EditIssueLabelTask(mOldLabelName, mNewLabelName, mColor);
}
@Override
protected Void run() throws IOException {
LabelService labelService = (LabelService)
Gh4Application.get().getService(Gh4Application.LABEL_SERVICE);
Label label = new Label();
label.setName(mNewLabelName);
label.setColor(mColor);
labelService.editLabel(new RepositoryId(mRepoOwner, mRepoName),
URLEncoder.encode(mOldLabelName, "UTF-8"), label);
return null;
}
@Override
protected void onSuccess(Void result) {
forceLoaderReload(0);
setResult(RESULT_OK);
}
@Override
protected String getErrorMessage() {
return getContext().getString(R.string.issue_error_edit_label, mOldLabelName);
}
}
private class AddIssueLabelTask extends ProgressDialogTask<Void> {
private final String mLabelName;
private final String mColor;
public AddIssueLabelTask(String labelName, String color) {
super(IssueLabelListActivity.this, R.string.saving_msg);
mLabelName = labelName;
mColor = color;
}
@Override
protected ProgressDialogTask<Void> clone() {
return new AddIssueLabelTask(mLabelName, mColor);
}
@Override
protected Void run() throws IOException {
LabelService labelService = (LabelService)
Gh4Application.get().getService(Gh4Application.LABEL_SERVICE);
Label label = new Label();
label.setName(mLabelName);
label.setColor(mColor);
labelService.createLabel(mRepoOwner, mRepoName, label);
return null;
}
@Override
protected void onSuccess(Void result) {
forceLoaderReload(0);
mAddedLabel = null;
setResult(RESULT_OK);
}
@Override
protected String getErrorMessage() {
return getContext().getString(R.string.issue_error_create_label, mLabelName);
}
@Override
protected void onError(Exception e) {
super.onError(e);
mAdapter.remove(mAddedLabel);
mAddedLabel = null;
}
}
}