Skip to content
Snippets Groups Projects
Commit fc066499 authored by Benjamin Dengler's avatar Benjamin Dengler
Browse files

Initial commit.

parents
No related branches found
No related tags found
No related merge requests found
Showing
with 1403 additions and 0 deletions
package com.bd.gitlab.model;
import java.util.Date;
import com.bd.gitlab.tools.Repository;
public class Project {
private long id;
private String name;
private String description;
private String default_branch;
private User owner;
private boolean is_public;
private String path;
private String path_with_namespace;
private boolean issues_enabled;
private boolean merge_requests_enabled;
private boolean wall_enabled;
private boolean wiki_enabled;
private Date created_at;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getDefaultBranch() {
return default_branch;
}
public void setDefaultBranch(String default_branch) {
this.default_branch = default_branch;
}
public User getOwner() {
return owner;
}
public void setOwner(User owner) {
this.owner = owner;
}
public boolean isPublic() {
return is_public;
}
public void setPublic(boolean is_public) {
this.is_public = is_public;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getPathWithNamespace() {
return path_with_namespace;
}
public void setPathWithNamespace(String path_with_namespace) {
this.path_with_namespace = path_with_namespace;
}
public boolean isIssuesEnabled() {
return issues_enabled;
}
public void setIssuesEnabled(boolean issues_enabled) {
this.issues_enabled = issues_enabled;
}
public boolean isMergeRequestsEnabled() {
return merge_requests_enabled;
}
public void setMergeRequestsEnabled(boolean merge_requests_enabled) {
this.merge_requests_enabled = merge_requests_enabled;
}
public boolean isWallEnabled() {
return wall_enabled;
}
public void setWallEnabled(boolean wall_enabled) {
this.wall_enabled = wall_enabled;
}
public boolean isWikiEnabled() {
return wiki_enabled;
}
public void setWikiEnabled(boolean wiki_enabled) {
this.wiki_enabled = wiki_enabled;
}
public Date getCreatedAt() {
return created_at;
}
public void setCreatedAt(Date created_at) {
this.created_at = created_at;
}
public String toString() {
Group g = getGroup();
if(g != null)
return g.getName() + " / " + name;
if(path_with_namespace != null)
return path_with_namespace.split("/")[0] + " / " + name;
else
return name;
}
public Group getGroup() {
if(Repository.groups == null)
return null;
for(Group g : Repository.groups)
if(g.getPath().equals(this.path_with_namespace.split("/")[0]))
return g;
return null;
}
public boolean equals(Object obj) {
if(obj == null)
return false;
if(obj == this)
return true;
if(!(obj instanceof Project))
return false;
Project rhs = (Project) obj;
return rhs.id == this.id;
}
}
package com.bd.gitlab.model;
import java.util.Date;
public class Session {
public long id;
public String username;
public String email;
public String name;
public String private_token;
public boolean blocked;
public Date created_at;
public String bio;
public String skype;
public String linkedin;
public String twitter;
public boolean dark_scheme;
public long theme_id;
public boolean is_admin;
public boolean can_create_group;
public boolean can_create_team;
public boolean can_create_project;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrivateToken() {
return private_token;
}
public void setPrivateToken(String private_token) {
this.private_token = private_token;
}
public boolean isBlocked() {
return blocked;
}
public void setBlocked(boolean blocked) {
this.blocked = blocked;
}
public Date getCreatedAt() {
return created_at;
}
public void setCreatedAt(Date created_at) {
this.created_at = created_at;
}
public String getBio() {
return bio;
}
public void setBio(String bio) {
this.bio = bio;
}
public String getSkype() {
return skype;
}
public void setSkype(String skype) {
this.skype = skype;
}
public String getLinkedin() {
return linkedin;
}
public void setLinkedin(String linkedin) {
this.linkedin = linkedin;
}
public String getTwitter() {
return twitter;
}
public void setTwitter(String twitter) {
this.twitter = twitter;
}
public boolean isDarkScheme() {
return dark_scheme;
}
public void setDarkScheme(boolean dark_scheme) {
this.dark_scheme = dark_scheme;
}
public long getThemeId() {
return theme_id;
}
public void setThemeId(long theme_id) {
this.theme_id = theme_id;
}
public boolean isIsAdmin() {
return is_admin;
}
public void setIsAdmin(boolean is_admin) {
this.is_admin = is_admin;
}
public boolean isCanCreateGroup() {
return can_create_group;
}
public void setCanCreateGroup(boolean can_create_group) {
this.can_create_group = can_create_group;
}
public boolean isCanCreateTeam() {
return can_create_team;
}
public void setCanCreateTeam(boolean can_create_team) {
this.can_create_team = can_create_team;
}
public boolean isCanCreateProject() {
return can_create_project;
}
public void setCanCreateProject(boolean can_create_project) {
this.can_create_project = can_create_project;
}
}
package com.bd.gitlab.model;
public class TreeItem {
private String name;
private String type;
private long mode;
private String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public long getMode() {
return mode;
}
public void setMode(long mode) {
this.mode = mode;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
package com.bd.gitlab.model;
import java.util.Date;
public class User {
private long id;
private String username;
private String email;
private String avatar_url;
private String name;
private boolean blocked;
private Date created_at;
private int access_level;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public String getAvatarUrl() {
return avatar_url;
}
public void setAvatarUrl(String avatar_url) {
this.avatar_url = avatar_url;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isBlocked() {
return blocked;
}
public void setBlocked(boolean blocked) {
this.blocked = blocked;
}
public Date getCreatedAt() {
return created_at;
}
public void setCreatedAt(Date created_at) {
this.created_at = created_at;
}
public String getAccessLevel(String[] names) {
int temp = access_level / 10 - 1;
if(temp >= 0 && temp < names.length)
return names[temp];
return "";
}
public void setAccessLevel(int access_level) {
this.access_level = access_level;
}
public boolean equals(Object obj) {
if (obj == null)
return false;
if (obj == this)
return true;
if (!(obj instanceof User))
return false;
User rhs = (User) obj;
return rhs.id == id;
}
}
package com.bd.gitlab.tools;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
public class DebugDataHelper {
private static final String TITLE = "Server Error";
private static final String MESSAGE = "Your GitLab Server behaved unexpectedly.\nWould you like to send the developer information so he can fix it?";
private static final String POSITIVE_BUTTON = "OK";
private static final String NEGATIVE_BUTTON = "Cancel";
private static final String SUBJECT = "GitLab Server Error";
private static final String RECIPIENT = "benjamin.dengler@gmail.com";
public static void sendErrorReport(final Context context, final String errorMessage) {
new AlertDialog.Builder(context).setTitle(TITLE).setMessage(MESSAGE).setPositiveButton(POSITIVE_BUTTON, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
openEmail(context, errorMessage);
dialog.dismiss();
}
}).setNegativeButton(NEGATIVE_BUTTON, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).show();
}
private static void openEmail(Context context, String errorMessage) {
Intent sendIntent = new Intent(Intent.ACTION_SEND);
String subject = SUBJECT;
sendIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {RECIPIENT});
sendIntent.putExtra(Intent.EXTRA_TEXT, errorMessage);
sendIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
sendIntent.setType("message/rfc822");
context.startActivity(Intent.createChooser(sendIntent, "Select email client"));
}
}
package com.bd.gitlab.tools;
import java.util.List;
import retrofit.Callback;
import retrofit.client.Response;
import retrofit.http.DELETE;
import retrofit.http.GET;
import retrofit.http.POST;
import retrofit.http.PUT;
import retrofit.http.Path;
import retrofit.http.Query;
import com.bd.gitlab.model.Branch;
import com.bd.gitlab.model.DiffLine;
import com.bd.gitlab.model.DeleteResponse;
import com.bd.gitlab.model.Diff;
import com.bd.gitlab.model.Group;
import com.bd.gitlab.model.Issue;
import com.bd.gitlab.model.Milestone;
import com.bd.gitlab.model.Note;
import com.bd.gitlab.model.Project;
import com.bd.gitlab.model.Session;
import com.bd.gitlab.model.TreeItem;
import com.bd.gitlab.model.User;
public interface GitLabAPI {
/* --- LOGIN --- */
@POST("/session")
void getSessionByUsername(@Query("login") String login, @Query("password") String password, Callback<Session> cb);
@POST("/session")
void getSessionByEmail(@Query("email") String email, @Query("password") String password, Callback<Session> cb);
/* --- MAIN --- */
@GET("/groups?per_page=100")
void getGroups(Callback<List<Group>> cb);
@GET("/users?per_page=100")
void getUsers(Callback<List<User>> cb);
@GET("/projects?per_page=100")
void getProjects(Callback<List<Project>> cb);
/* --- MISC --- */
@GET("/projects/{id}/repository/branches?per_page=100")
void getBranches(@Path("id") long projectId, Callback<List<Branch>> cb);
@GET("/projects/{id}/milestones?per_page=100")
void getMilestones(@Path("id") long projectId, Callback<List<Milestone>> cb);
@GET("/projects/{id}/members?per_page=100")
void getUsersFallback(@Path("id") long projectId, Callback<List<User>> cb);
/* --- COMMITS --- */
@GET("/projects/{id}/repository/commits?per_page=100")
void getCommits(@Path("id") long projectId, @Query("ref_name") String branchName, Callback<List<DiffLine>> cb);
@GET("/projects/{id}/repository/commits/{sha}/diff")
void getCommitDiff(@Path("id") long projectId, @Path("sha") String commitSHA, Callback<List<Diff>> cb);
/* --- ISSUE --- */
@GET("/projects/{id}/issues?per_page=100")
void getIssues(@Path("id") long projectId, Callback<List<Issue>> cb);
@POST("/projects/{id}/issues")
void postIssue(@Path("id") long projectId, @Query("title") String title, @Query("description") String description, Callback<Issue> cb);
@PUT("/projects/{id}/issues/{issue_id}")
void editIssue(@Path("id") long projectId, @Path("issue_id") long issueId, @Query("state_event") String stateEvent, @Query("assignee_id") long assigneeId, @Query("milestone_id") long milestoneId, Callback<Issue> cb);
@GET("/projects/{id}/issues/{issue_id}/notes?per_page=100")
void getIssueNotes(@Path("id") long projectId, @Path("issue_id") long issueId, Callback<List<Note>> cb);
@POST("/projects/{id}/issues/{issue_id}/notes")
void postIssueNote(@Path("id") long projectId, @Path("issue_id") long issueId, @Query("body") String body, Callback<Note> cb);
/* --- FILES --- */
@GET("/projects/{id}/repository/tree?per_page=100")
void getTree(@Path("id") long projectId, @Query("ref_name") String branchName, @Query("path") String path, Callback<List<TreeItem>> cb);
@GET("/projects/{id}/repository/commits/{sha}/blob")
void getBlob(@Path("id") long projectId, @Path("sha") String commitId, @Query("filepath") String path, Callback<Response> cb);
/* --- USER --- */
@GET("/groups/{id}/members?per_page=100")
void getGroupMembers(@Path("id") long groupId, Callback<List<User>> cb);
@POST("/groups/{id}/members")
void addGroupMember(@Path("id") long groupId, @Query("user_id") long userId, @Query("access_level") String accessLevel, Callback<User> cb);
@DELETE("/groups/{id}/members/{user_id}")
void removeGroupMember(@Path("id") long groupId, @Path("user_id") long userId, Callback<DeleteResponse> cb);
}
\ No newline at end of file
package com.bd.gitlab.tools;
import retrofit.RequestInterceptor;
public class GitLabInterceptor implements RequestInterceptor {
@Override
public void intercept(RequestFacade req) {
req.addHeader("PRIVATE-TOKEN", Repository.getPrivateToken());
}
}
package com.bd.gitlab.tools;
import java.lang.reflect.Type;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;
import retrofit.RestAdapter;
import retrofit.converter.GsonConverter;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.preference.PreferenceManager;
import android.util.DisplayMetrics;
import android.view.Surface;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.ListView;
import com.bd.gitlab.adapter.DrawerAdapter;
import com.bd.gitlab.adapter.IssuesAdapter;
import com.bd.gitlab.adapter.UserAdapter;
import com.bd.gitlab.model.Branch;
import com.bd.gitlab.model.DiffLine;
import com.bd.gitlab.model.Group;
import com.bd.gitlab.model.Issue;
import com.bd.gitlab.model.Project;
import com.bd.gitlab.model.TreeItem;
import com.bd.gitlab.model.User;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import org.joda.time.format.ISODateTimeFormat;
public class Repository extends Application {
public static ArrayList<Project> projects;
public static ArrayList<Branch> branches;
public static ArrayList<Group> groups;
public static ArrayList<User> users;
public static Project selectedProject;
public static Branch selectedBranch;
public static Issue selectedIssue;
public static TreeItem selectedFile;
public static User selectedUser;
public static DiffLine selectedCommit;
public static DiffLine newestCommit;
public static DrawerAdapter drawerAdapter;
public static IssuesAdapter issueAdapter;
public static UserAdapter userAdapter;
public static float displayWidth;
private static final String LOGGED_IN = "logged_in";
private static final String SERVER_URL = "server_url";
private static final String PRIVATE_TOKEN = "private_token";
private static final String LAST_PROJECT = "last_project";
private static SharedPreferences preferences;
private static GitLabAPI service;
public static void init(Context context) {
preferences = PreferenceManager.getDefaultSharedPreferences(context);
projects = null;
branches = null;
groups = null;
users = null;
selectedProject = null;
selectedBranch = null;
selectedIssue = null;
selectedFile = null;
selectedUser = null;
newestCommit = null;
drawerAdapter = null;
issueAdapter = null;
userAdapter = null;
}
public static GitLabAPI getService() {
if(getServerUrl().length() < 1) {
Repository.setLoggedIn(false);
Repository.setPrivateToken("");
Repository.setServerUrl("");
service = null;
return null;
}
if(service == null) {
// Configure Gson to handle dates correctly
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
@Override
public Date deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
return ISODateTimeFormat.dateTimeParser().parseDateTime(json.getAsString()).toDate();
}
});
Gson gson = gsonBuilder.create();
RestAdapter restAdapter = new RestAdapter.Builder().setRequestInterceptor(new GitLabInterceptor()).setConverter(new GsonConverter(gson)).setEndpoint(getServerUrl() + "/api/v3").build();
service = restAdapter.create(GitLabAPI.class);
}
return service;
}
public static boolean isLoggedIn() {
return preferences.getBoolean(LOGGED_IN, false);
}
public static void setLoggedIn(boolean loggedIn) {
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(LOGGED_IN, loggedIn);
editor.commit();
}
public static void setServerUrl(String serverUrl) {
SharedPreferences.Editor editor = preferences.edit();
editor.putString(SERVER_URL, serverUrl);
editor.commit();
service = null;
}
public static String getServerUrl() {
return preferences.getString(SERVER_URL, "");
}
public static void setPrivateToken(String privateToken) {
SharedPreferences.Editor editor = preferences.edit();
editor.putString(PRIVATE_TOKEN, privateToken);
editor.commit();
}
public static String getPrivateToken() {
return preferences.getString(PRIVATE_TOKEN, "");
}
public static void setLastProject(String lastProject) {
SharedPreferences.Editor editor = preferences.edit();
editor.putString(LAST_PROJECT, lastProject);
editor.commit();
}
public static String getLastProject() {
return preferences.getString(LAST_PROJECT, "");
}
public static void setListViewSize(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if(listAdapter == null)
return;
int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.AT_MOST);
for(int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
if(listItem instanceof ViewGroup)
listItem.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
listItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
listView.requestLayout();
}
public static int getScreenOrientation(Activity activity) {
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
int height = dm.heightPixels;
int orientation;
// if the device's natural orientation is portrait:
if ((rotation == Surface.ROTATION_0
|| rotation == Surface.ROTATION_180) && height > width ||
(rotation == Surface.ROTATION_90
|| rotation == Surface.ROTATION_270) && width > height) {
switch(rotation) {
case Surface.ROTATION_0:
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
case Surface.ROTATION_90:
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
break;
case Surface.ROTATION_180:
orientation =
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
break;
case Surface.ROTATION_270:
orientation =
ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
break;
default:
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
}
}
// if the device's natural orientation is landscape or if the device
// is square:
else {
switch(rotation) {
case Surface.ROTATION_0:
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
break;
case Surface.ROTATION_90:
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
case Surface.ROTATION_180:
orientation =
ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
break;
case Surface.ROTATION_270:
orientation =
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
break;
default:
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
break;
}
}
return orientation;
}
public static void resetService() {
service = null;
}
}
package com.bd.gitlab.tools;
import java.io.IOException;
import java.util.ArrayList;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import retrofit.RetrofitError;
import retrofit.client.Header;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import com.bd.gitlab.LoginActivity;
import javax.net.ssl.SSLHandshakeException;
public class RetrofitHelper {
private static final String TAG = "GITLAB-NETWORK-ERROR";
public static void printDebugInfo(Context context, RetrofitError error) {
if(error == null)
return;
else if(error.getCause() instanceof SSLHandshakeException && context != null) {
Repository.setLoggedIn(false);
context.startActivity(new Intent(context, LoginActivity.class));
return;
}
String errorMessage = "";
String temp;
temp = "URL: " + error.getUrl();
Log.e(TAG, temp);
errorMessage += temp + "\n";
if(error.getResponse() != null) {
temp = "Status: " + error.getResponse().getStatus() + " - " + error.getResponse().getReason();
Log.e(TAG, temp);
errorMessage += temp + "\n";
ArrayList<Header> headers = new ArrayList<Header>(error.getResponse().getHeaders());
for(Header h : headers) {
temp = "Header: " + h.getName() + " - " + h.getValue();
Log.e(TAG, temp);
errorMessage += temp + "\n";
}
try {
if(error.getResponse().getBody() != null && error.getResponse().getBody().in() != null) {
temp = "Body: " + IOUtils.toString(error.getResponse().getBody().in());
Log.e(TAG, temp);
errorMessage += temp + "\n";
}
}
catch(IOException e) {
e.printStackTrace();
}
}
temp = "Message: " + error.getMessage();
Log.e(TAG, temp);
errorMessage += temp + "\n";
errorMessage += ExceptionUtils.getStackTrace(error);
error.printStackTrace();
//Ask user if he wants to send errorMessage
if(context != null)
DebugDataHelper.sendErrorReport(context, errorMessage);
}
}
package com.bd.gitlab.views;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.Target;
public class CompoundTextView extends TextView implements Target {
public CompoundTextView(Context context) {
super(context);
}
public CompoundTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CompoundTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
setImage(new BitmapDrawable(this.getResources(), bitmap));
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
setImage(errorDrawable);
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
setImage(placeHolderDrawable);
}
private void setImage(Drawable drawable) {
this.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
}
}
package com.bd.gitlab.views;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.bd.gitlab.R;
import com.bd.gitlab.model.Diff;
public class DiffView extends LinearLayout {
private static final int HEADER_BG = Color.rgb(223, 223, 223);
private static final int LINE_BG = Color.rgb(238, 238, 238);
private static final int LINE_BG_ADDED = Color.rgb(204, 255, 204);
private static final int LINE_BG_REMOVED = Color.rgb(255, 204, 204);
private static final int CONTENT_BG = Color.rgb(255, 255, 255);
private static final int CONTENT_BG_ADDED = Color.rgb(204, 255, 221);
private static final int CONTENT_BG_REMOVED = Color.rgb(255, 221, 221);
private static final int CONTENT_BG_COMMENT = Color.rgb(250, 250, 250);
private static final int CONTENT_FONT_COMMENT = Color.rgb(216, 206, 206);
private static final int MARGIN_VIEW_H = 0;
private static final int MARGIN_VIEW_V = 10;
private static final int PADDING_HEADER_H = 0;
private static final int PADDING_HEADER_V = 5;
private static final int PADDING_CONTENT_H = 5;
private static final int PADDING_CONTENT_V = 0;
private Diff diff;
/*
* Superclass constructors
*/
public DiffView(Context context) {
super(context);
}
public DiffView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DiffView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/*
* Custom constructor
*/
public DiffView(Context context, Diff diff) {
this(context);
this.diff = diff;
setOrientation(VERTICAL);
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
params.setMargins(MARGIN_VIEW_H, MARGIN_VIEW_V, MARGIN_VIEW_H, MARGIN_VIEW_V);
setLayoutParams(params);
addView(generateHeader());
ArrayList<Diff.Line> lines = (ArrayList<Diff.Line>) diff.getLines();
for(Diff.Line line : lines)
addView(generateRow(line));
setBackgroundResource(R.drawable.border);
setPadding(1, 1, 1, 1);
}
private LinearLayout generateHeader() {
LinearLayout header = new LinearLayout(getContext());
header.setOrientation(HORIZONTAL);
header.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
header.setBackgroundColor(HEADER_BG);
ImageView icon = new ImageView(getContext());
if(diff.isNewFile())
icon.setImageResource(R.drawable.ic_added);
else if(diff.isDeletedFile())
icon.setImageResource(R.drawable.ic_removed);
else
icon.setImageResource(R.drawable.ic_changed);
icon.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
icon.setPadding(10, 10, 10, 10);
header.addView(icon);
TextView title = new TextView(getContext());
title.setText(diff.getNewPath());
title.setTypeface(title.getTypeface(), Typeface.BOLD);
title.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
title.setPadding(PADDING_HEADER_H, PADDING_HEADER_V, PADDING_HEADER_H, PADDING_HEADER_V);
header.addView(title);
return header;
}
private LinearLayout generateRow(Diff.Line line) {
if(line == null)
return null;
LinearLayout row = new LinearLayout(getContext());
row.setOrientation(HORIZONTAL);
row.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
TextView oldLine = new TextView(getContext());
oldLine.setText(line.oldLine);
oldLine.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
oldLine.setEms(2);
oldLine.setGravity(Gravity.CENTER_HORIZONTAL);
row.addView(oldLine);
TextView newLine = new TextView(getContext());
newLine.setText(line.newLine);
newLine.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
newLine.setEms(2);
newLine.setGravity(Gravity.CENTER_HORIZONTAL);
row.addView(newLine);
TextView content = new TextView(getContext());
content.setText(line.lineContent);
content.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
content.setPadding(PADDING_CONTENT_H, PADDING_CONTENT_V, PADDING_CONTENT_H, PADDING_CONTENT_V);
row.addView(content);
switch(line.lineType) {
case NORMAL:
oldLine.setBackgroundColor(LINE_BG);
newLine.setBackgroundColor(LINE_BG);
content.setBackgroundColor(CONTENT_BG);
break;
case ADDED:
oldLine.setBackgroundColor(LINE_BG_ADDED);
newLine.setBackgroundColor(LINE_BG_ADDED);
content.setBackgroundColor(CONTENT_BG_ADDED);
break;
case REMOVED:
oldLine.setBackgroundColor(LINE_BG_REMOVED);
newLine.setBackgroundColor(LINE_BG_REMOVED);
content.setBackgroundColor(CONTENT_BG_REMOVED);
break;
case COMMENT:
oldLine.setBackgroundColor(LINE_BG);
newLine.setBackgroundColor(LINE_BG);
content.setBackgroundColor(CONTENT_BG_COMMENT);
content.setTextColor(CONTENT_FONT_COMMENT);
content.setGravity(Gravity.CENTER_HORIZONTAL);
break;
}
return row;
}
}
package com.bd.gitlab.views;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.TextView;
public class MarqueeTextView extends TextView {
public MarqueeTextView(Context context) {
super(context);
}
public MarqueeTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MarqueeTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
if(focused)
super.onFocusChanged(true, direction, previouslyFocusedRect);
}
@Override
public void onWindowFocusChanged(boolean focused) {
if(focused)
super.onWindowFocusChanged(true);
}
@Override
public boolean isFocused() {
return true;
}
}
package in.uncod.android.bypass;
import in.uncod.android.bypass.Element.Type;
import android.graphics.Typeface;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.BulletSpan;
import android.text.style.LeadingMarginSpan;
import android.text.style.QuoteSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan;
import android.text.style.TypefaceSpan;
import android.text.style.URLSpan;
public class Bypass {
static {
System.loadLibrary("bypass");
}
private static final float[] HEADER_SIZES = { 1.5f, 1.4f, 1.3f, 1.2f, 1.1f,
1f, };
public CharSequence markdownToSpannable(String markdown) {
Document document = processMarkdown(markdown);
CharSequence[] spans = new CharSequence[document.getElementCount()];
for (int i = 0; i < document.getElementCount(); i++) {
spans[i] = recurseElement(document.getElement(i));
}
return TextUtils.concat(spans);
}
private native Document processMarkdown(String markdown);
private CharSequence recurseElement(Element element) {
CharSequence[] spans = new CharSequence[element.size()];
for (int i = 0; i < element.size(); i++) {
spans[i] = recurseElement(element.children[i]);
}
CharSequence concat = TextUtils.concat(spans);
SpannableStringBuilder builder = new SpannableStringBuilder();
String text = element.getText();
if (element.size() == 0
&& element.getParent() != null
&& element.getParent().getType() != Type.BLOCK_CODE) {
text = text.replace('\n', ' ');
}
if (element.getParent() != null
&& element.getParent().getType() == Type.LIST_ITEM
&& element.getType() == Type.LIST) {
builder.append("\n");
}
if (element.getType() == Type.LIST_ITEM) {
builder.append("\u2022");
}
builder.append(text);
builder.append(concat);
if (element.getType() == Type.LIST && element.getParent() != null) {
} else if (element.getType() == Type.LIST_ITEM) {
if (element.size() > 0 && element.children[element.size()-1].isBlockElement()) {
}
else {
builder.append("\n");
}
} else if (element.isBlockElement()) {
builder.append("\n\n");
}
if (element.getType() == Type.HEADER) {
String levelStr = element.getAttribute("level");
int level = Integer.parseInt(levelStr);
builder.setSpan(new RelativeSizeSpan(HEADER_SIZES[level]), 0,
builder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
builder.setSpan(new StyleSpan(Typeface.BOLD), 0, builder.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (element.getType() == Type.LIST_ITEM
&& element.getParent().getParent() != null) {
LeadingMarginSpan span = new LeadingMarginSpan.Standard(20);
builder.setSpan(span, 0, builder.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (element.getType() == Type.EMPHASIS) {
StyleSpan italicSpan = new StyleSpan(Typeface.ITALIC);
builder.setSpan(italicSpan, 0, builder.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (element.getType() == Type.DOUBLE_EMPHASIS) {
StyleSpan boldSpan = new StyleSpan(Typeface.BOLD);
builder.setSpan(boldSpan, 0, builder.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (element.getType() == Type.TRIPLE_EMPHASIS) {
StyleSpan bolditalicSpan = new StyleSpan(Typeface.BOLD_ITALIC);
builder.setSpan(bolditalicSpan, 0, builder.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (element.getType() == Type.CODE_SPAN) {
TypefaceSpan monoSpan = new TypefaceSpan("monospace");
builder.setSpan(monoSpan, 0, builder.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (element.getType() == Type.LINK) {
URLSpan urlSpan = new URLSpan(element.getAttribute("link"));
builder.setSpan(urlSpan, 0, builder.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (element.getType() == Type.BLOCK_QUOTE) {
QuoteSpan quoteSpan = new QuoteSpan();
builder.setSpan(quoteSpan, 0, builder.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
StyleSpan italicSpan = new StyleSpan(Typeface.ITALIC);
builder.setSpan(italicSpan, 0, builder.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return builder;
}
}
package in.uncod.android.bypass;
public class Document {
Element[] elements;
public Document(Element[] elements) {
this.elements = elements;
}
public int getElementCount() {
return elements.length;
}
public Element getElement(int pos) {
return elements[pos];
}
}
package in.uncod.android.bypass;
import java.util.Map;
import java.util.HashMap;
public class Element {
public enum Type {
// Block Element Types
BLOCK_CODE(0x000),
BLOCK_QUOTE(0x001),
BLOCK_HTML(0x002),
HEADER(0x003),
HRULE(0x004),
LIST(0x005),
LIST_ITEM(0x006),
PARAGRAPH(0x007),
TABLE(0x008),
TABLE_CELL(0x009),
TABLE_ROW(0x00A),
// Span Element Types
AUTOLINK(0x10B),
CODE_SPAN(0x10C),
DOUBLE_EMPHASIS(0x10D),
EMPHASIS(0x10E),
IMAGE(0x10F),
LINEBREAK(0x110),
LINK(0x111),
RAW_HTML_TAG(0x112),
TRIPLE_EMPHASIS(0x113),
TEXT(0x114);
private final int value;
private Type(int value) {
this.value = value;
}
private static final Type[] TypeValues = Type.values();
public static Type fromInteger(int x) {
for (Type type : TypeValues) {
if (type.value == x) {
return type;
}
}
return null;
}
}
String text;
Map<String, String> attributes = new HashMap<String, String>();
Element[] children;
Type type;
Element parent;
int nestLevel = 0;
public Element(String text, int type) {
this.text = text;
this.type = Type.fromInteger(type);
}
public void setParent(Element element) {
this.parent = element;
}
public void setChildren(Element[] children) {
this.children = children;
}
public void addAttribute(String name, String value) {
attributes.put(name, value);
}
public String getAttribute(String name) {
return attributes.get(name);
}
public Element getParent() {
return parent;
}
public String getText() {
return text;
}
public int size() {
if (children != null) {
return children.length;
}
return 0;
}
public Type getType() {
return type;
}
public boolean isBlockElement() {
return (type.value & 0x100) == 0x000;
}
public boolean isSpanElement() {
return (type.value & 0x100) == 0x100;
}
}
app/src/main/res/drawable-hdpi/ic_action_add.png

181 B

app/src/main/res/drawable-hdpi/ic_action_copy.png

227 B

app/src/main/res/drawable-hdpi/ic_action_open.png

715 B

app/src/main/res/drawable-hdpi/ic_action_open_dark.png

822 B

app/src/main/res/drawable-hdpi/ic_action_save.png

318 B

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment