Merge changes I36bf7b37,Id835f12d,I2861135e,If0ad7302,I91ce3d1e, ...
* changes:
Implement change list for reviewing changes
Make avatar size and text size of UserView configurable
Refactor: Implement avatar/user control as view
Refactor: Implement project/branch/topic/age control as view
Add expandable commit message to abandon and restore screens
Refactor: Implement expandable commit message as view
diff --git a/app/src/main/java/com/google/reviewit/AbandonFragment.java b/app/src/main/java/com/google/reviewit/AbandonFragment.java
index 34625e8..dcc2137 100644
--- a/app/src/main/java/com/google/reviewit/AbandonFragment.java
+++ b/app/src/main/java/com/google/reviewit/AbandonFragment.java
@@ -22,6 +22,7 @@
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.reviewit.app.Change;
+import com.google.reviewit.widget.ExpandableCommitMessageView;
import com.urswolfer.gerrit.client.rest.http.HttpStatusException;
/**
@@ -49,12 +50,14 @@
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- Change change = getApp().getActionHandler().getCurrentChange();
+ Change change = getApp().getSortActionHandler().getCurrentChange();
setTitle(getString(R.string.abandon_change_title, change.info._number));
init(change);
}
private void init(final Change change) {
+ ((ExpandableCommitMessageView)v(R.id.commitMessage)).init(change);
+
v(R.id.abandonButton).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
diff --git a/app/src/main/java/com/google/reviewit/AddReviewerFragment.java b/app/src/main/java/com/google/reviewit/AddReviewerFragment.java
index c53071c..7e25d7f 100644
--- a/app/src/main/java/com/google/reviewit/AddReviewerFragment.java
+++ b/app/src/main/java/com/google/reviewit/AddReviewerFragment.java
@@ -77,7 +77,7 @@
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- Change change = getApp().getActionHandler().getCurrentChange();
+ Change change = getApp().getSortActionHandler().getCurrentChange();
initInputField(change);
try {
displayReviewers(change);
diff --git a/app/src/main/java/com/google/reviewit/BaseFragment.java b/app/src/main/java/com/google/reviewit/BaseFragment.java
index 9babd93..e64d33a 100644
--- a/app/src/main/java/com/google/reviewit/BaseFragment.java
+++ b/app/src/main/java/com/google/reviewit/BaseFragment.java
@@ -31,7 +31,7 @@
import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
-import com.google.reviewit.app.ActionHandler;
+import com.google.reviewit.app.SortActionHandler;
import com.google.reviewit.app.ReviewItApp;
import com.google.reviewit.util.TaskObserver;
import com.google.reviewit.util.WidgetUtil;
@@ -121,8 +121,8 @@
return ((ReviewItApp) getActivity().getApplication());
}
- protected ActionHandler getActionHandler() {
- return getApp().getActionHandler();
+ protected SortActionHandler getSortActionHandler() {
+ return getApp().getSortActionHandler();
}
public void display(
diff --git a/app/src/main/java/com/google/reviewit/DetailedChangeFragment.java b/app/src/main/java/com/google/reviewit/DetailedChangeFragment.java
index f99d812..2991696 100644
--- a/app/src/main/java/com/google/reviewit/DetailedChangeFragment.java
+++ b/app/src/main/java/com/google/reviewit/DetailedChangeFragment.java
@@ -31,7 +31,7 @@
import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.common.FileInfo;
-import com.google.reviewit.app.ActionHandler;
+import com.google.reviewit.app.SortActionHandler;
import com.google.reviewit.app.Change;
import com.google.reviewit.util.ChangeUtil;
import com.google.reviewit.widget.ChangeBox;
@@ -85,7 +85,7 @@
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- Change change = getApp().getActionHandler().getCurrentChange();
+ Change change = getApp().getSortActionHandler().getCurrentChange();
setTitle(getString(R.string.detailed_change_title, change.info._number));
setHasOptionsMenu(true);
init();
@@ -217,7 +217,7 @@
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- ActionHandler actionHandler = getApp().getActionHandler();
+ SortActionHandler actionHandler = getApp().getSortActionHandler();
inflater.inflate(R.menu.menu_detailed_change, menu);
for (int i = 0; i < menu.size(); i++) {
MenuItem item = menu.getItem(i);
@@ -237,7 +237,7 @@
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- ActionHandler actionHandler = getApp().getActionHandler();
+ SortActionHandler actionHandler = getApp().getSortActionHandler();
switch (item.getItemId()) {
case R.id.action_add_reviewer:
display(AddReviewerFragment.create(getClass()));
diff --git a/app/src/main/java/com/google/reviewit/PostReviewFragment.java b/app/src/main/java/com/google/reviewit/PostReviewFragment.java
index 7dc1560..bb431db 100644
--- a/app/src/main/java/com/google/reviewit/PostReviewFragment.java
+++ b/app/src/main/java/com/google/reviewit/PostReviewFragment.java
@@ -26,8 +26,8 @@
import com.google.reviewit.app.Change;
import com.google.reviewit.util.ObservableAsynTask;
import com.google.reviewit.util.TaskObserver;
-import com.google.reviewit.util.WidgetUtil;
import com.google.reviewit.widget.ApprovalsView;
+import com.google.reviewit.widget.ExpandableCommitMessageView;
import com.google.reviewit.widget.VoteView;
import com.urswolfer.gerrit.client.rest.http.HttpStatusException;
@@ -71,36 +71,17 @@
int vote = getArguments().getInt(VOTE);
update(vote);
- Change change = getApp().getActionHandler().getCurrentChange();
+ Change change = getApp().getSortActionHandler().getCurrentChange();
setTitle(getString(R.string.detailed_change_title, change.info._number));
init(change);
- WidgetUtil.setText(v(R.id.subject), change.info.subject);
initLabels(change, vote);
((ApprovalsView) v(R.id.approvals)).displayApprovals(getApp(),
change.info, this);
}
private void init(final Change change) {
- v(R.id.expandCommitMessage).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- setGone(v(R.id.expandCommitMessage));
- setVisible(v(R.id.collapseCommitMessage));
- WidgetUtil.setText(v(R.id.subject),
- change.currentRevision().commit.message);
- }
- });
-
- v(R.id.collapseCommitMessage).setOnClickListener(
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- setGone(v(R.id.collapseCommitMessage));
- setVisible(v(R.id.expandCommitMessage));
- WidgetUtil.setText(v(R.id.subject), change.info.subject);
- }
- });
+ ((ExpandableCommitMessageView)v(R.id.commitMessage)).init(change);
v(R.id.postReviewButton).setOnClickListener(new View.OnClickListener() {
@Override
diff --git a/app/src/main/java/com/google/reviewit/SortSettingFragment.java b/app/src/main/java/com/google/reviewit/QuerySettingsFragment.java
similarity index 97%
rename from app/src/main/java/com/google/reviewit/SortSettingFragment.java
rename to app/src/main/java/com/google/reviewit/QuerySettingsFragment.java
index 5efb057..5ab3f1a 100644
--- a/app/src/main/java/com/google/reviewit/SortSettingFragment.java
+++ b/app/src/main/java/com/google/reviewit/QuerySettingsFragment.java
@@ -25,12 +25,12 @@
import com.google.reviewit.app.ServerConfig;
import com.google.reviewit.util.WidgetUtil;
-public class SortSettingFragment extends BaseFragment {
+public class QuerySettingsFragment extends BaseFragment {
private static final String LABEL_REGEXP = "^[a-zA-Z][a-zA-Z0-9]*$";
@Override
protected @LayoutRes int getLayout() {
- return R.layout.content_sort_settings;
+ return R.layout.content_query_settings;
}
@Override
diff --git a/app/src/main/java/com/google/reviewit/RestoreFragment.java b/app/src/main/java/com/google/reviewit/RestoreFragment.java
index b586d55..45d398a 100644
--- a/app/src/main/java/com/google/reviewit/RestoreFragment.java
+++ b/app/src/main/java/com/google/reviewit/RestoreFragment.java
@@ -22,6 +22,7 @@
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.reviewit.app.Change;
+import com.google.reviewit.widget.ExpandableCommitMessageView;
import com.urswolfer.gerrit.client.rest.http.HttpStatusException;
/**
@@ -49,12 +50,14 @@
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- Change change = getApp().getActionHandler().getCurrentChange();
+ Change change = getApp().getSortActionHandler().getCurrentChange();
setTitle(getString(R.string.restore_change_title, change.info._number));
init(change);
}
private void init(final Change change) {
+ ((ExpandableCommitMessageView)v(R.id.commitMessage)).init(change);
+
v(R.id.restoreButton).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
diff --git a/app/src/main/java/com/google/reviewit/ReviewChangesFragment.java b/app/src/main/java/com/google/reviewit/ReviewChangesFragment.java
index b38f651..5c68c1e 100644
--- a/app/src/main/java/com/google/reviewit/ReviewChangesFragment.java
+++ b/app/src/main/java/com/google/reviewit/ReviewChangesFragment.java
@@ -14,12 +14,184 @@
package com.google.reviewit;
+import android.os.Bundle;
import android.support.annotation.LayoutRes;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.google.gerrit.extensions.restapi.RestApiException;
+import com.google.reviewit.app.Change;
+import com.google.reviewit.app.QueryHandler;
+import com.google.reviewit.util.ObservableAsynTask;
+import com.google.reviewit.util.TaskObserver;
+import com.google.reviewit.widget.ChangeEntry;
+
+import java.util.Collections;
+import java.util.List;
+
+import static com.google.reviewit.util.LayoutUtil.matchAndFixedLayout;
+import static com.google.reviewit.util.WidgetUtil.setGone;
+import static com.google.reviewit.util.WidgetUtil.setInvisible;
+import static com.google.reviewit.util.WidgetUtil.setVisible;
public class ReviewChangesFragment extends BaseFragment {
+ private static final String TAG = ReviewChangesFragment.class.getName();
@Override
protected @LayoutRes int getLayout() {
return R.layout.content_review_changes;
}
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ setHasOptionsMenu(true);
+
+ TaskObserver.enableProgressBar(getWindow());
+ init();
+ display();
+ }
+
+ private void init() {
+ v(R.id.reloadButton).setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ reloadQuery();
+ }
+ });
+
+ // TODO detect when scrolled to the end and automatically load next page
+ }
+
+ private void display() {
+ if (!isOnline()) {
+ setInvisible(v(R.id.progress));
+ setGone(v(R.id.initialProgress));
+ setVisible(v(R.id.statusText, R.id.reloadButton));
+ TextView statusText = tv(R.id.statusText);
+ statusText.setText(getString(R.string.no_network));
+ statusText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 15);
+ return;
+ }
+
+ new ObservableAsynTask<Void, Void, ChangeListData>() {
+ private View progress;
+ private View initialProgress;
+ private View reloadButton;
+ private TextView statusText;
+ private ViewGroup changeList;
+
+ @Override
+ protected void preExecute() {
+ super.preExecute();
+ progress = v(R.id.progress);
+ initialProgress = v(R.id.initialProgress);
+ reloadButton = v(R.id.reloadButton);
+ statusText = tv(R.id.statusText);
+ changeList = vg(R.id.changeList);
+ }
+
+ @Override
+ protected ChangeListData doInBackground(Void... v) {
+ try {
+ QueryHandler queryHandler = getApp().getQueryHandler();
+ if (queryHandler.hasNext()) {
+ return new ChangeListData(queryHandler.next());
+ } else {
+ return new ChangeListData(Collections.<Change>emptyList());
+ }
+ } catch (RestApiException e) {
+ // e.g. server not reachable
+ Log.e(TAG, "Request failed", e);
+ if (e.getCause() != null) {
+ return new ChangeListData(getString(R.string.error_with_cause,
+ e.getMessage(), e.getCause().getMessage()));
+ } else {
+ return new ChangeListData(e.getMessage());
+ }
+ }
+ }
+
+ protected void postExecute(ChangeListData changeListData) {
+ super.postExecute(changeListData);
+
+ if (getActivity() == null) {
+ // user navigated away while we were waiting for the request
+ return;
+ }
+
+ getActivity().invalidateOptionsMenu();
+ setInvisible(progress);
+ setGone(initialProgress, reloadButton);
+
+ if (changeListData.error != null) {
+ statusText.setText(changeListData.error);
+ return;
+ }
+
+ if (!changeListData.changeList.isEmpty()) {
+ setGone(statusText);
+ for (Change change : changeListData.changeList) {
+ ChangeEntry changeEntry = new ChangeEntry(getContext());
+ changeEntry.init(getApp(), change);
+ changeList.addView(changeEntry);
+ addSeparator(changeList);
+ }
+ } else {
+ statusText.setText(getString(R.string.no_changes_match));
+ }
+ }
+ }.execute();
+ }
+
+ private void addSeparator(ViewGroup viewGroup) {
+ View separator = new View(getContext());
+ separator.setLayoutParams(
+ matchAndFixedLayout(widgetUtil.dpToPx(1)));
+ separator.setBackgroundColor(widgetUtil.color(R.color.separator));
+ viewGroup.addView(separator);
+ }
+
+ private void reloadQuery() {
+ getApp().getQueryHandler().reset();
+ display(getClass(), false);
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ inflater.inflate(R.menu.menu_review_changes, menu);
+ super.onCreateOptionsMenu(menu, inflater);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_reload_query:
+ reloadQuery();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ private static class ChangeListData {
+ final List<Change> changeList;
+ final String error;
+
+ ChangeListData(List<Change> changeList) {
+ this.changeList = changeList;
+ this.error = null;
+ }
+
+ ChangeListData(String error) {
+ this.changeList = null;
+ this.error = error;
+ }
+ }
}
diff --git a/app/src/main/java/com/google/reviewit/SettingsFragment.java b/app/src/main/java/com/google/reviewit/SettingsFragment.java
index c81210e..67f0c0f 100644
--- a/app/src/main/java/com/google/reviewit/SettingsFragment.java
+++ b/app/src/main/java/com/google/reviewit/SettingsFragment.java
@@ -41,10 +41,10 @@
}
});
- v(R.id.sortConfig).setOnClickListener(new View.OnClickListener() {
+ v(R.id.queryConfig).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- display(SortSettingFragment.class);
+ display(QuerySettingsFragment.class);
}
});
}
diff --git a/app/src/main/java/com/google/reviewit/SortChangesFragment.java b/app/src/main/java/com/google/reviewit/SortChangesFragment.java
index df116a0..2969891 100644
--- a/app/src/main/java/com/google/reviewit/SortChangesFragment.java
+++ b/app/src/main/java/com/google/reviewit/SortChangesFragment.java
@@ -37,7 +37,7 @@
import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.reviewit.app.ActionHandler;
+import com.google.reviewit.app.SortActionHandler;
import com.google.reviewit.app.Change;
import com.google.reviewit.app.ConfigManager;
import com.google.reviewit.app.QueryConfig;
@@ -74,8 +74,8 @@
setHasOptionsMenu(true);
- if (getActionHandler().hasCurrentChange()) {
- getActionHandler().pushBack();
+ if (getSortActionHandler().hasCurrentChange()) {
+ getSortActionHandler().pushBack();
}
TaskObserver.enableProgressBar(getWindow());
@@ -92,7 +92,7 @@
ConfigManager cfgManager = getApp().getConfigManager();
QueryConfig config = cfgManager.getQueryConfig();
if (!config.isComplete()) {
- display(SortSettingFragment.class);
+ display(QuerySettingsFragment.class);
return;
}
@@ -105,7 +105,7 @@
return;
}
- if (getActionHandler().isQueryNeeded()) {
+ if (getSortActionHandler().isQueryNeeded()) {
if (v(R.id.changeBox) == null) {
setVisible(v(R.id.loadingBox));
setInvisible(v(R.id.progress));
@@ -115,7 +115,7 @@
setVisible(v(R.id.progress));
}
} else {
- Change change = getActionHandler().preview();
+ Change change = getSortActionHandler().preview();
if (change != null) {
ChangeUtil.colorBackground(root, change);
}
@@ -144,7 +144,7 @@
@Override
protected ChangeData doInBackground(Void... v) {
try {
- ActionHandler actionHandler = getActionHandler();
+ SortActionHandler actionHandler = getSortActionHandler();
if (actionHandler.hasNext()) {
Change change = actionHandler.next();
int queueSize = actionHandler.getQueueSize();
@@ -235,16 +235,16 @@
v(R.id.skipButton).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
disableButtons();
- getActionHandler().skip();
- animate(changeBox, ActionHandler.Action.SKIP);
+ getSortActionHandler().skip();
+ animate(changeBox, SortActionHandler.Action.SKIP);
}
});
View.OnClickListener onStarClickListener = new View.OnClickListener() {
public void onClick(View v) {
disableButtons();
- getActionHandler().star();
- animate(changeBox, ActionHandler.Action.STAR);
+ getSortActionHandler().star();
+ animate(changeBox, SortActionHandler.Action.STAR);
}
};
v(R.id.starButton).setOnClickListener(onStarClickListener);
@@ -253,8 +253,8 @@
View.OnClickListener onIgnoreClickListener = new View.OnClickListener() {
public void onClick(View v) {
disableButtons();
- getActionHandler().ignore();
- animate(changeBox, ActionHandler.Action.IGNORE);
+ getSortActionHandler().ignore();
+ animate(changeBox, SortActionHandler.Action.IGNORE);
}
};
v(R.id.ignoreButton).setOnClickListener(onIgnoreClickListener);
@@ -304,7 +304,7 @@
final ViewGroup resultBox = vg(R.id.resultBox);
changeBox.findViewById(R.id.changeBoxUpperPart).setOnTouchListener(
new View.OnTouchListener() {
- private ActionHandler.Action action = ActionHandler.Action.NONE;
+ private SortActionHandler.Action action = SortActionHandler.Action.NONE;
private int x;
private int y;
@@ -330,9 +330,9 @@
if (eventX > (screenCenter + (screenCenter / 2))) {
((GradientDrawable) changeBox.getBackground())
.setColor(widgetUtil.color(R.color.commitMessageStar));
- action = ActionHandler.Action.STAR;
+ action = SortActionHandler.Action.STAR;
} else {
- action = ActionHandler.Action.NONE;
+ action = SortActionHandler.Action.NONE;
((GradientDrawable) changeBox.getBackground())
.setColor(widgetUtil.color(R.color.commitMessage));
}
@@ -342,9 +342,9 @@
if (eventX < (screenCenter / 2)) {
((GradientDrawable) changeBox.getBackground())
.setColor(widgetUtil.color(R.color.commitMessageIgnore));
- action = ActionHandler.Action.IGNORE;
+ action = SortActionHandler.Action.IGNORE;
} else {
- action = ActionHandler.Action.NONE;
+ action = SortActionHandler.Action.NONE;
((GradientDrawable) changeBox.getBackground())
.setColor(widgetUtil.color(R.color.commitMessage));
}
@@ -355,17 +355,17 @@
.setColor(widgetUtil.color(R.color.commitMessage));
switch (action) {
case STAR:
- getActionHandler().star();
+ getSortActionHandler().star();
resultBox.removeView(changeBox);
display();
break;
case IGNORE:
- getActionHandler().ignore();
+ getSortActionHandler().ignore();
resultBox.removeView(changeBox);
display();
break;
case SKIP:
- getActionHandler().skip();
+ getSortActionHandler().skip();
resultBox.removeView(changeBox);
display();
break;
@@ -388,7 +388,7 @@
}
private void animate(
- final View changeBox, final ActionHandler.Action action) {
+ final View changeBox, final SortActionHandler.Action action) {
final ViewGroup resultBox = vg(R.id.resultBox);
Point screenSize = getScreenSize();
final int screenCenter = screenSize.x / 2;
@@ -517,7 +517,7 @@
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- ActionHandler actionHandler = getActionHandler();
+ SortActionHandler actionHandler = getSortActionHandler();
inflater.inflate(R.menu.menu_sort_changes, menu);
for (int i = 0; i < menu.size(); i++) {
MenuItem item = menu.getItem(i);
@@ -574,7 +574,7 @@
}
private void undo() {
- ActionHandler actionHandler = getActionHandler();
+ SortActionHandler actionHandler = getSortActionHandler();
if (!actionHandler.undoPossible()) {
return;
}
@@ -615,17 +615,17 @@
display(SortChangesFragment.class);
}
}
- }.execute(getActionHandler().getCurrentChange());
+ }.execute(getSortActionHandler().getCurrentChange());
}
private void reloadQuery() {
- getActionHandler().reset();
+ getSortActionHandler().reset();
display(getClass(), false);
}
@Override
public boolean onBackPressed() {
- if (getActionHandler().undoPossible()) {
+ if (getSortActionHandler().undoPossible()) {
undo();
return true;
}
diff --git a/app/src/main/java/com/google/reviewit/UnifiedDiffFragment.java b/app/src/main/java/com/google/reviewit/UnifiedDiffFragment.java
index 4db29a2..4a31052 100644
--- a/app/src/main/java/com/google/reviewit/UnifiedDiffFragment.java
+++ b/app/src/main/java/com/google/reviewit/UnifiedDiffFragment.java
@@ -84,7 +84,7 @@
? getArguments().getString(PATH)
: null;
- Change change = getApp().getActionHandler().getCurrentChange();
+ Change change = getApp().getSortActionHandler().getCurrentChange();
checkState(change != null, "Change not set");
Map<String, FileInfo> files = change.currentRevision().files;
root = (ScrollWithHeadingsView) v(R.id.unifiedDiffRoot);
diff --git a/app/src/main/java/com/google/reviewit/app/QueryConfig.java b/app/src/main/java/com/google/reviewit/app/QueryConfig.java
index ea87e08..4759c9d 100644
--- a/app/src/main/java/com/google/reviewit/app/QueryConfig.java
+++ b/app/src/main/java/com/google/reviewit/app/QueryConfig.java
@@ -16,6 +16,9 @@
import com.google.common.base.Strings;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+
public class QueryConfig {
public final String serverId;
public final String query;
@@ -27,6 +30,15 @@
this.label = label;
}
+ public String encodedQuery() {
+ try {
+ // TODO use StandardCharsets.UTF_8.name() with API level 19
+ return URLEncoder.encode(query, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
public boolean isComplete() {
return !Strings.isNullOrEmpty(serverId)
&& !Strings.isNullOrEmpty(query)
diff --git a/app/src/main/java/com/google/reviewit/app/QueryHandler.java b/app/src/main/java/com/google/reviewit/app/QueryHandler.java
new file mode 100644
index 0000000..bdaa6f3
--- /dev/null
+++ b/app/src/main/java/com/google/reviewit/app/QueryHandler.java
@@ -0,0 +1,110 @@
+// Copyright (C) 2016 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.
+
+package com.google.reviewit.app;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.gerrit.extensions.client.ListChangesOption;
+import com.google.gerrit.extensions.common.ChangeInfo;
+import com.google.gerrit.extensions.restapi.RestApiException;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class QueryHandler {
+ /**
+ * Number of changes that should be fetched at once from the server.
+ */
+ private static final int LIMIT_QUERY = 25;
+
+ private final Gerrit gerrit;
+
+ private final LinkedList<Change> result = new LinkedList<>();
+
+ private QueryConfig config;
+
+ /**
+ * Number of changes which should be skipped when querying the next changes
+ * from the server.
+ */
+ private int start = 0;
+
+ private int page = 0;
+
+ /**
+ * Whether there are more changes at the server.
+ */
+ private boolean more = true;
+
+ QueryHandler(ConfigManager cfgManager, Gerrit gerrit) {
+ this.gerrit = gerrit;
+ this.config = cfgManager.getQueryConfig();
+
+ cfgManager.addUpdateListener(new ConfigManager.OnUpdate() {
+ @Override
+ public void onUpdate(QueryConfig cfg) {
+ config = cfg;
+ reset();
+ }
+ });
+ }
+
+ public List<Change> next() throws RestApiException {
+ query();
+ return result.subList(page * LIMIT_QUERY, (page + 1) * LIMIT_QUERY);
+ }
+
+ public boolean hasNext() {
+ return more;
+ }
+
+ private void query() throws RestApiException {
+ result.addAll(Collections2.transform(Collections2.filter(
+ gerrit.api()
+ .changes()
+ .query(config.encodedQuery())
+ .withOption(ListChangesOption.ALL_FILES)
+ .withOption(ListChangesOption.CURRENT_COMMIT)
+ .withOption(ListChangesOption.CURRENT_REVISION)
+ .withOption(ListChangesOption.DETAILED_ACCOUNTS)
+ .withOption(ListChangesOption.DETAILED_LABELS)
+ .withLimit(LIMIT_QUERY)
+ .withStart(start)
+ .get(), new Predicate<ChangeInfo>() {
+ @Override
+ public boolean apply(ChangeInfo changeInfo) {
+ // filter out changes with no revisions
+ return changeInfo.revisions != null;
+ }
+ }), new Function<ChangeInfo, Change>() {
+ @Override
+ public Change apply(ChangeInfo changeInfo) {
+ return new Change(gerrit.api(), changeInfo);
+ }
+ }));
+ start += LIMIT_QUERY;
+ more = !result.isEmpty() && (result.getLast().info._moreChanges != null
+ ? result.getLast().info._moreChanges
+ : false);
+ }
+
+ public void reset() {
+ result.clear();
+ start = 0;
+ more = true;
+ page = 0;
+ }
+}
diff --git a/app/src/main/java/com/google/reviewit/app/ReviewItApp.java b/app/src/main/java/com/google/reviewit/app/ReviewItApp.java
index 10fb519..b2efb88 100644
--- a/app/src/main/java/com/google/reviewit/app/ReviewItApp.java
+++ b/app/src/main/java/com/google/reviewit/app/ReviewItApp.java
@@ -32,7 +32,8 @@
public class ReviewItApp extends Application {
private static final String TAG = ReviewItApp.class.getName();
- private ActionHandler actionHandler;
+ private QueryHandler queryHandler;
+ private SortActionHandler sortActionHandler;
private AvatarCache avatarCache;
private ConfigManager cfgManager;
private ExecutorService executor;
@@ -94,11 +95,18 @@
super.onCreate();
}
- public ActionHandler getActionHandler() {
- if (actionHandler == null) {
- actionHandler = new ActionHandler(getConfigManager(), getGerrit());
+ public QueryHandler getQueryHandler() {
+ if (queryHandler == null) {
+ queryHandler = new QueryHandler(getConfigManager(), getGerrit());
}
- return actionHandler;
+ return queryHandler;
+ }
+
+ public SortActionHandler getSortActionHandler() {
+ if (sortActionHandler == null) {
+ sortActionHandler = new SortActionHandler(getConfigManager(), getGerrit());
+ }
+ return sortActionHandler;
}
public AvatarCache getAvatarCache() {
diff --git a/app/src/main/java/com/google/reviewit/app/ActionHandler.java b/app/src/main/java/com/google/reviewit/app/SortActionHandler.java
similarity index 96%
rename from app/src/main/java/com/google/reviewit/app/ActionHandler.java
rename to app/src/main/java/com/google/reviewit/app/SortActionHandler.java
index c182ea9..2a95b1e 100644
--- a/app/src/main/java/com/google/reviewit/app/ActionHandler.java
+++ b/app/src/main/java/com/google/reviewit/app/SortActionHandler.java
@@ -23,7 +23,7 @@
import java.util.LinkedList;
-public class ActionHandler {
+public class SortActionHandler {
public enum Action {
/**
* Do nothing.
@@ -90,7 +90,7 @@
*/
private boolean more = true;
- ActionHandler(ConfigManager cfgManager, Gerrit gerrit) {
+ SortActionHandler(ConfigManager cfgManager, Gerrit gerrit) {
this.gerrit = gerrit;
this.config = cfgManager.getQueryConfig();
@@ -147,7 +147,7 @@
toProcess.addAll(Collections2.transform(Collections2.filter(
gerrit.api()
.changes()
- .query(encodeQuery(config.query))
+ .query(config.encodedQuery())
.withOption(ListChangesOption.ALL_FILES)
.withOption(ListChangesOption.CURRENT_COMMIT)
.withOption(ListChangesOption.CURRENT_REVISION)
@@ -179,10 +179,6 @@
return toProcess.size() < THRESHOLD_QUEUE && more;
}
- private static String encodeQuery(String query) {
- return query.replaceAll(" ", "+");
- }
-
/**
* Stars the current change.
*/
diff --git a/app/src/main/java/com/google/reviewit/util/LayoutUtil.java b/app/src/main/java/com/google/reviewit/util/LayoutUtil.java
index 907ea6c..ff19c94 100644
--- a/app/src/main/java/com/google/reviewit/util/LayoutUtil.java
+++ b/app/src/main/java/com/google/reviewit/util/LayoutUtil.java
@@ -34,6 +34,11 @@
ViewGroup.LayoutParams.WRAP_CONTENT);
}
+ public static ViewGroup.LayoutParams matchAndFixedLayout(int height) {
+ return new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, height);
+ }
+
public static TableLayout.LayoutParams matchAndWrapTableLayout() {
return new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT,
diff --git a/app/src/main/java/com/google/reviewit/util/WidgetUtil.java b/app/src/main/java/com/google/reviewit/util/WidgetUtil.java
index df03587..6c2b92e 100644
--- a/app/src/main/java/com/google/reviewit/util/WidgetUtil.java
+++ b/app/src/main/java/com/google/reviewit/util/WidgetUtil.java
@@ -118,6 +118,28 @@
return (int) context.getResources().getDimension(id);
}
+ public float toDimension(String value, float defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ try {
+ if (value.endsWith("sp")) {
+ value = value.substring(0, value.length() - 2).trim();
+ return spToPx(Integer.valueOf(value));
+ } else if (value.endsWith("dp")) {
+ value = value.substring(0, value.length() - 2).trim();
+ return dpToPx(Integer.valueOf(value));
+ } else if (value.endsWith("px")) {
+ value = value.substring(0, value.length() - 2).trim();
+ return Integer.valueOf(value);
+ } else {
+ return Integer.valueOf(value);
+ }
+ } catch (NumberFormatException e) {
+ return defaultValue;
+ }
+ }
+
public void setBackgroundColor(View view, @ColorRes int colorId) {
view.setBackgroundColor(color(colorId));
}
diff --git a/app/src/main/java/com/google/reviewit/widget/ChangeBox.java b/app/src/main/java/com/google/reviewit/widget/ChangeBox.java
index bab77d8..dd5288e 100644
--- a/app/src/main/java/com/google/reviewit/widget/ChangeBox.java
+++ b/app/src/main/java/com/google/reviewit/widget/ChangeBox.java
@@ -85,16 +85,11 @@
configureInfo(app);
ChangeInfo info = change.info;
- WidgetUtil.setText(v(R.id.project), info.project);
- WidgetUtil.setText(v(R.id.branch), info.branch);
- WidgetUtil.setText(v(R.id.topic), info.topic);
- WidgetUtil.setText(v(R.id.age),
- FormatUtil.formatDate(getContext(), info.updated));
+ ((ProjectBranchTopicAgeView)v(R.id.projectBranchTopicAge)).init(change);
+ ((UserView)v(R.id.owner)).init(app, info.owner);
WidgetUtil.setText(v(R.id.subject), info.subject);
WidgetUtil.setText(v(R.id.commitMessage),
FormatUtil.formatMessage(change));
- displayAvatar(app, info.owner);
- WidgetUtil.setText(v(R.id.owner), FormatUtil.format(info.owner));
WidgetUtil.setText(v(R.id.patchsets),
FormatUtil.format(change.currentRevision()._number));
setInlineCommentCount(app, change);
@@ -208,10 +203,6 @@
return false;
}
- private void displayAvatar(ReviewItApp app,AccountInfo account) {
- WidgetUtil.displayAvatar(app, account, (ImageView) v(R.id.avatar));
- }
-
private View v(@IdRes int id) {
return findViewById(id);
}
diff --git a/app/src/main/java/com/google/reviewit/widget/ChangeEntry.java b/app/src/main/java/com/google/reviewit/widget/ChangeEntry.java
new file mode 100644
index 0000000..cfd5e37
--- /dev/null
+++ b/app/src/main/java/com/google/reviewit/widget/ChangeEntry.java
@@ -0,0 +1,50 @@
+// Copyright (C) 2016 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.
+
+package com.google.reviewit.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.LinearLayout;
+
+import com.google.gerrit.extensions.common.ChangeInfo;
+import com.google.reviewit.R;
+import com.google.reviewit.app.Change;
+import com.google.reviewit.app.ReviewItApp;
+import com.google.reviewit.util.WidgetUtil;
+
+public class ChangeEntry extends LinearLayout {
+ public ChangeEntry(Context context) {
+ this(context, null, 0);
+ }
+
+ public ChangeEntry(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ChangeEntry(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ inflate(context, R.layout.change_entry, this);
+ }
+
+ public void init(ReviewItApp app, Change change) {
+ ((ProjectBranchTopicAgeView)findViewById(R.id.projectBranchTopicAge))
+ .init(change);
+ ((UserView)findViewById(R.id.owner)).init(app, change.info.owner);
+
+ ChangeInfo info = change.info;
+ WidgetUtil.setText(findViewById(R.id.subject), info.subject);
+ }
+}
diff --git a/app/src/main/java/com/google/reviewit/widget/ExpandableCommitMessageView.java b/app/src/main/java/com/google/reviewit/widget/ExpandableCommitMessageView.java
new file mode 100644
index 0000000..08ffca3
--- /dev/null
+++ b/app/src/main/java/com/google/reviewit/widget/ExpandableCommitMessageView.java
@@ -0,0 +1,69 @@
+// Copyright (C) 2016 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.
+
+package com.google.reviewit.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import com.google.reviewit.R;
+import com.google.reviewit.app.Change;
+import com.google.reviewit.util.WidgetUtil;
+
+import static com.google.reviewit.util.WidgetUtil.setGone;
+import static com.google.reviewit.util.WidgetUtil.setVisible;
+
+public class ExpandableCommitMessageView extends LinearLayout {
+ public ExpandableCommitMessageView(Context context) {
+ this(context, null, 0);
+ }
+
+ public ExpandableCommitMessageView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ExpandableCommitMessageView(
+ Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ inflate(context, R.layout.expandable_commit_message, this);
+ }
+
+ public void init(final Change change) {
+ WidgetUtil.setText(findViewById(R.id.subject), change.info.subject);
+
+ findViewById(R.id.expandCommitMessage).setOnClickListener(
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ setGone(findViewById(R.id.expandCommitMessage));
+ setVisible(findViewById(R.id.collapseCommitMessage));
+ WidgetUtil.setText(findViewById(R.id.subject),
+ change.currentRevision().commit.message);
+ }
+ });
+
+ findViewById(R.id.collapseCommitMessage).setOnClickListener(
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ setGone(findViewById(R.id.collapseCommitMessage));
+ setVisible(findViewById(R.id.expandCommitMessage));
+ WidgetUtil.setText(findViewById(R.id.subject), change.info.subject);
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/com/google/reviewit/widget/MaxFontSizeTextView.java b/app/src/main/java/com/google/reviewit/widget/MaxFontSizeTextView.java
index f9a0920..765621f 100644
--- a/app/src/main/java/com/google/reviewit/widget/MaxFontSizeTextView.java
+++ b/app/src/main/java/com/google/reviewit/widget/MaxFontSizeTextView.java
@@ -24,6 +24,7 @@
import android.widget.TextView;
import com.google.reviewit.R;
+import com.google.reviewit.util.WidgetUtil;
/**
* TextView that automatically sets the font size as large as possible
@@ -46,13 +47,14 @@
public MaxFontSizeTextView(Context context, AttributeSet attrs) {
super(context, attrs);
+ WidgetUtil widgetUtil = new WidgetUtil(context);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.MaxFontSizeTextView, 0, 0);
maxLineLength = a.getInteger(R.styleable
.MaxFontSizeTextView_maxLineLength, 0);
- minTextSize = readAttr(a.getString(
+ minTextSize = widgetUtil.toDimension(a.getString(
R.styleable.MaxFontSizeTextView_minTextSize), MIN_TEXT_SIZE_DEFAULT);
- maxTextSize = readAttr(a.getString(
+ maxTextSize = widgetUtil.toDimension(a.getString(
R.styleable.MaxFontSizeTextView_maxTextSize), MAX_TEXT_SIZE_DEFAULT);
paint = new Paint();
@@ -90,25 +92,6 @@
}
}
- private float readAttr(String attr, float defaultValue) {
- if (attr == null) {
- return defaultValue;
- }
- try {
- if (attr.endsWith("sp")) {
- attr = attr.substring(0, attr.length() - 2).trim();
- return spToPx(Integer.valueOf(attr));
- } else if (attr.endsWith("px")) {
- attr = attr.substring(0, attr.length() - 2).trim();
- return Integer.valueOf(attr);
- } else {
- return Integer.valueOf(attr);
- }
- } catch (NumberFormatException e) {
- return defaultValue;
- }
- }
-
public void setMinTextSize(float minTextSize) {
this.minTextSize = minTextSize;
}
@@ -184,9 +167,4 @@
refitText(getText(), width);
}
}
-
- private int spToPx(int sp) {
- return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
- getResources().getDisplayMetrics());
- }
}
diff --git a/app/src/main/java/com/google/reviewit/widget/ProjectBranchTopicAgeView.java b/app/src/main/java/com/google/reviewit/widget/ProjectBranchTopicAgeView.java
new file mode 100644
index 0000000..12bab21
--- /dev/null
+++ b/app/src/main/java/com/google/reviewit/widget/ProjectBranchTopicAgeView.java
@@ -0,0 +1,54 @@
+// Copyright (C) 2016 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.
+
+package com.google.reviewit.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.LinearLayout;
+
+import com.google.gerrit.extensions.common.ChangeInfo;
+import com.google.reviewit.R;
+import com.google.reviewit.app.Change;
+import com.google.reviewit.util.FormatUtil;
+import com.google.reviewit.util.WidgetUtil;
+
+import static com.google.reviewit.util.WidgetUtil.setVisible;
+
+public class ProjectBranchTopicAgeView extends LinearLayout {
+ public ProjectBranchTopicAgeView(Context context) {
+ this(context, null, 0);
+ }
+
+ public ProjectBranchTopicAgeView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ProjectBranchTopicAgeView(
+ Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ inflate(context, R.layout.project_branch_topic_age, this);
+ }
+
+ public void init(Change change) {
+ ChangeInfo info = change.info;
+ WidgetUtil.setText(findViewById(R.id.project), info.project);
+ WidgetUtil.setText(findViewById(R.id.branch), info.branch);
+ WidgetUtil.setText(findViewById(R.id.topic), info.topic);
+ WidgetUtil.setText(findViewById(R.id.age),
+ FormatUtil.formatDate(getContext(), info.updated));
+
+ }
+}
diff --git a/app/src/main/java/com/google/reviewit/widget/UserView.java b/app/src/main/java/com/google/reviewit/widget/UserView.java
new file mode 100644
index 0000000..23ab47d
--- /dev/null
+++ b/app/src/main/java/com/google/reviewit/widget/UserView.java
@@ -0,0 +1,69 @@
+// Copyright (C) 2016 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.
+
+package com.google.reviewit.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.google.gerrit.extensions.common.AccountInfo;
+import com.google.reviewit.R;
+import com.google.reviewit.app.ReviewItApp;
+import com.google.reviewit.util.FormatUtil;
+import com.google.reviewit.util.WidgetUtil;
+
+public class UserView extends LinearLayout {
+ public UserView(Context context) {
+ this(context, null, 0);
+ }
+
+ public UserView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public UserView(
+ Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ inflate(context, R.layout.user, this);
+
+ WidgetUtil widgetUtil = new WidgetUtil(context);
+ TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
+ R.styleable.UserView, 0, 0);
+ int avatarSize = (int) widgetUtil.toDimension(
+ a.getString(R.styleable.UserView_avatarSize), -1);
+ if (avatarSize > 0) {
+ findViewById(R.id.avatar).setLayoutParams(new LayoutParams(avatarSize,
+ avatarSize));
+ }
+
+ float textSize = widgetUtil.toDimension(
+ a.getString(R.styleable.UserView_textSize), -1);
+ if (textSize > 0) {
+ ((TextView)findViewById(R.id.userName)).setTextSize(
+ TypedValue.COMPLEX_UNIT_PX, textSize);
+ }
+ }
+
+ public void init(ReviewItApp app, AccountInfo account) {
+ WidgetUtil.displayAvatar(app, account,
+ (ImageView) findViewById(R.id.avatar));
+ WidgetUtil.setText(findViewById(R.id.userName), FormatUtil.format(account));
+ }
+}
diff --git a/app/src/main/res/layout/change_box.xml b/app/src/main/res/layout/change_box.xml
index e8eeccf..f802d0e 100644
--- a/app/src/main/res/layout/change_box.xml
+++ b/app/src/main/res/layout/change_box.xml
@@ -29,77 +29,10 @@
android:layout_height="match_parent"
android:layout_weight="1">
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="3dp"
- android:textSize="9sp"
- android:text="@string/project"/>
-
- <TextView
- android:id="@+id/project"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="9sp"/>
- </LinearLayout>
-
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="3dp"
- android:textSize="9sp"
- android:text="@string/branch"/>
-
- <TextView
- android:id="@+id/branch"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="9sp"/>
- </LinearLayout>
-
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="3dp"
- android:textSize="9sp"
- android:text="@string/topic"/>
-
- <TextView
- android:id="@+id/topic"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="9sp"/>
- </LinearLayout>
-
- <TextView
- android:id="@+id/age"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="9sp"/>
- </LinearLayout>
+ <com.google.reviewit.widget.ProjectBranchTopicAgeView
+ android:id="@+id/projectBranchTopicAge"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
<View
android:background="@color/separator"
@@ -143,23 +76,11 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="4dp">
-
- <ImageView
- android:id="@+id/avatar"
- android:layout_width="20dp"
- android:layout_height="20dp"
- android:layout_marginRight="3dp"/>
-
- <TextView
- android:id="@+id/owner"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
- </LinearLayout>
+ <com.google.reviewit.widget.UserView
+ android:id="@+id/owner"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="4dp"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
diff --git a/app/src/main/res/layout/change_entry.xml b/app/src/main/res/layout/change_entry.xml
new file mode 100644
index 0000000..411470d
--- /dev/null
+++ b/app/src/main/res/layout/change_entry.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2016 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. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="3dp"
+ android:paddingTop="3dp"
+ android:paddingRight="3dp"
+ android:paddingBottom="3dp">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1">
+
+ <com.google.reviewit.widget.ProjectBranchTopicAgeView
+ android:id="@+id/projectBranchTopicAge"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+
+ <TextView
+ android:id="@+id/subject"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <com.google.reviewit.widget.UserView
+ android:id="@+id/owner"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:textSize="10sp"
+ app:avatarSize="15dp"/>
+ </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/content_abandon.xml b/app/src/main/res/layout/content_abandon.xml
index da2b061..a1c8b7f 100644
--- a/app/src/main/res/layout/content_abandon.xml
+++ b/app/src/main/res/layout/content_abandon.xml
@@ -14,19 +14,27 @@
See the License for the specific language governing permissions and
limitations under the License. -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- app:layout_behavior="@string/appbar_scrolling_view_behavior">
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior">
+
+ <com.google.reviewit.widget.ExpandableCommitMessageView
+ android:id="@+id/commitMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="7dp"
+ android:background="@drawable/navigation_button_bar"/>
<ScrollView
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin">
<LinearLayout
android:orientation="vertical"
@@ -58,4 +66,4 @@
android:text="@string/abandon"/>
</LinearLayout>
</ScrollView>
-</RelativeLayout>
+</LinearLayout>
diff --git a/app/src/main/res/layout/content_post_review.xml b/app/src/main/res/layout/content_post_review.xml
index 0347ae0..6c2f411 100644
--- a/app/src/main/res/layout/content_post_review.xml
+++ b/app/src/main/res/layout/content_post_review.xml
@@ -32,41 +32,11 @@
<include layout="@layout/progress"/>
- <LinearLayout
+ <com.google.reviewit.widget.ExpandableCommitMessageView
+ android:id="@+id/commitMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingTop="5dp"
- android:orientation="horizontal">
-
- <ImageView
- android:id="@+id/expandCommitMessage"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="-7dp"
- android:clickable="true"
- android:src="@drawable/ic_keyboard_arrow_right_white_36dp"/>
-
- <ImageView
- android:id="@+id/collapseCommitMessage"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="-7dp"
- android:clickable="true"
- android:src="@drawable/ic_keyboard_arrow_down_white_36dp"
- android:visibility="gone"/>
-
- <TextView
- android:id="@+id/subject"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:padding="5dp"
- android:layout_marginBottom="5dp"
- android:layout_marginRight="36dp"
- android:layout_weight="1"
- android:textSize="9sp"
- android:background="@drawable/grey_page_border"
- android:textColor="@color/darkGrey"/>
- </LinearLayout>
+ android:paddingTop="5dp"/>
<LinearLayout
android:layout_width="match_parent"
diff --git a/app/src/main/res/layout/content_sort_settings.xml b/app/src/main/res/layout/content_query_settings.xml
similarity index 100%
rename from app/src/main/res/layout/content_sort_settings.xml
rename to app/src/main/res/layout/content_query_settings.xml
diff --git a/app/src/main/res/layout/content_restore.xml b/app/src/main/res/layout/content_restore.xml
index 5d6e879..e90f9a9 100644
--- a/app/src/main/res/layout/content_restore.xml
+++ b/app/src/main/res/layout/content_restore.xml
@@ -14,19 +14,27 @@
See the License for the specific language governing permissions and
limitations under the License. -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- app:layout_behavior="@string/appbar_scrolling_view_behavior">
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior">
+
+ <com.google.reviewit.widget.ExpandableCommitMessageView
+ android:id="@+id/commitMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="7dp"
+ android:background="@drawable/navigation_button_bar"/>
<ScrollView
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin">
<LinearLayout
android:orientation="vertical"
@@ -58,4 +66,4 @@
android:text="@string/restore"/>
</LinearLayout>
</ScrollView>
-</RelativeLayout>
+</LinearLayout>
diff --git a/app/src/main/res/layout/content_review_changes.xml b/app/src/main/res/layout/content_review_changes.xml
index 456ce76..3851a97 100644
--- a/app/src/main/res/layout/content_review_changes.xml
+++ b/app/src/main/res/layout/content_review_changes.xml
@@ -15,14 +15,47 @@
limitations under the License. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
- <TextView
+ <include layout="@layout/progress"/>
+
+ <ScrollView
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center"
- android:textSize="40sp"
- android:text="TODO"/>
-</LinearLayout>
\ No newline at end of file
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:id="@+id/changeList"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ android:id="@+id/statusText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:layout_marginTop="15dp"
+ android:textSize="24sp"
+ android:text="@string/loading"/>
+
+ <ProgressBar
+ android:id="@+id/initialProgress"
+ android:layout_marginTop="20dp"
+ android:layout_width="match_parent"
+ android:layout_height="150dp"
+ android:indeterminate="true"/>
+
+ <ImageView
+ android:id="@+id/reloadButton"
+ android:layout_width="match_parent"
+ android:layout_height="150dp"
+ android:layout_marginTop="20dp"
+ android:gravity="center_horizontal"
+ android:clickable="true"
+ android:src="@drawable/ic_refresh_black_48dp"
+ android:visibility="gone"/>
+ </LinearLayout>
+ </ScrollView>
+</LinearLayout>
diff --git a/app/src/main/res/layout/content_settings.xml b/app/src/main/res/layout/content_settings.xml
index 41bd70a..78eecf8 100644
--- a/app/src/main/res/layout/content_settings.xml
+++ b/app/src/main/res/layout/content_settings.xml
@@ -49,10 +49,10 @@
android:layout_marginBottom="10dp"/>
<TextView
- android:id="@+id/sortConfig"
+ android:id="@+id/queryConfig"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/sortConfig"
+ android:text="@string/queryConfig"
android:gravity="center_horizontal"
android:textSize="20sp"/>
</LinearLayout>
diff --git a/app/src/main/res/layout/expandable_commit_message.xml b/app/src/main/res/layout/expandable_commit_message.xml
new file mode 100644
index 0000000..dbc2e07
--- /dev/null
+++ b/app/src/main/res/layout/expandable_commit_message.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2016 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. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/expandCommitMessage"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="-7dp"
+ android:clickable="true"
+ android:src="@drawable/ic_keyboard_arrow_right_white_36dp"/>
+
+ <ImageView
+ android:id="@+id/collapseCommitMessage"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="-7dp"
+ android:clickable="true"
+ android:src="@drawable/ic_keyboard_arrow_down_white_36dp"
+ android:visibility="gone"/>
+
+ <TextView
+ android:id="@+id/subject"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="5dp"
+ android:layout_marginBottom="5dp"
+ android:layout_marginRight="36dp"
+ android:layout_weight="1"
+ android:textSize="9sp"
+ android:background="@drawable/grey_page_border"
+ android:textColor="@color/darkGrey"/>
+</LinearLayout>
diff --git a/app/src/main/res/layout/project_branch_topic_age.xml b/app/src/main/res/layout/project_branch_topic_age.xml
new file mode 100644
index 0000000..8c945bf
--- /dev/null
+++ b/app/src/main/res/layout/project_branch_topic_age.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2016 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. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dp"
+ android:textSize="9sp"
+ android:text="@string/project"/>
+
+ <TextView
+ android:id="@+id/project"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="9sp"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dp"
+ android:textSize="9sp"
+ android:text="@string/branch"/>
+
+ <TextView
+ android:id="@+id/branch"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="9sp"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="3dp"
+ android:textSize="9sp"
+ android:text="@string/topic"/>
+
+ <TextView
+ android:id="@+id/topic"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="9sp"/>
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/age"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="9sp"/>
+</LinearLayout>
diff --git a/app/src/main/res/layout/user.xml b/app/src/main/res/layout/user.xml
new file mode 100644
index 0000000..190b04b
--- /dev/null
+++ b/app/src/main/res/layout/user.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2016 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. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <ImageView
+ android:id="@+id/avatar"
+ android:layout_width="20dp"
+ android:layout_height="20dp"
+ android:layout_marginRight="3dp"/>
+
+ <TextView
+ android:id="@+id/userName"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+</LinearLayout>
diff --git a/app/src/main/res/menu/menu_review_changes.xml b/app/src/main/res/menu/menu_review_changes.xml
new file mode 100644
index 0000000..af11e52
--- /dev/null
+++ b/app/src/main/res/menu/menu_review_changes.xml
@@ -0,0 +1,22 @@
+<!-- Copyright (C) 2016 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. -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ <item
+ android:id="@+id/action_reload_query"
+ android:orderInCategory="100"
+ android:title="@string/action_reload_query"
+ app:showAsAction="never"/>
+</menu>
\ No newline at end of file
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
index 662122a..3d6fa8e 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -21,4 +21,9 @@
<attr name="maxLineLength" format="integer"/>
<attr name="ellipsize" format="boolean"/>
</declare-styleable>
+
+ <declare-styleable name="UserView">
+ <attr name="avatarSize" format="string"/>
+ <attr name="textSize" format="string"/>
+ </declare-styleable>
</resources>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 68e7525..c4de3bc 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -40,6 +40,9 @@
<string name="action_restore">Restore...</string>
<string name="action_undo">Undo</string>
+ <!-- ReviewChangesFragment -->
+ <string name="no_changes_match">No changes match the query!</string>
+
<!-- ErrorFragment -->
<string name="title_activity_error">Error</string>
@@ -131,7 +134,7 @@
<!-- SettingsFragment -->
<string name="serverConfig">Server Configuration</string>
- <string name="sortConfig">Sort Configuration</string>
+ <string name="queryConfig">Query Configuration</string>
<string name="add_server">Add Server</string>
<string name="connection_failed">Connection failed: %1$s</string>