preparing for notifications, added backPress handling for repo folders, added FastHub icon and removed few unused methods.

This commit is contained in:
Kosh 2017-02-19 20:55:04 +08:00
parent 6dd6804da5
commit 88e85ff91e
34 changed files with 408 additions and 47 deletions

View File

@ -93,11 +93,10 @@ dependencies {
compile "com.google.firebase:firebase-analytics:${firebase}"
compile "net.grandcentrix.thirtyinch:thirtyinch:${thirtyinchVersion}"
compile "net.grandcentrix.thirtyinch:thirtyinch-rx:${thirtyinchVersion}"
compile 'com.android.support.constraint:constraint-layout:1.0.0-beta4'
compile 'com.firebase:firebase-jobdispatcher:0.5.2'
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
compile 'de.hdodenhof:circleimageview:2.1.0'
compile 'com.jakewharton:butterknife:8.4.0'
compile 'org.greenrobot:eventbus:3.0.0'
compile 'frankiesardo:icepick:3.1.0'
compile 'it.sephiroth.android.library.bottomnavigation:bottom-navigation:1.0.7'
compile 'pub.devrel:easypermissions:0.2.1'

View File

@ -5,13 +5,14 @@
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:name=".App"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:roundIcon="@mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
@ -117,6 +118,14 @@
</intent-filter>
</activity>
<service
android:name=".provider.tasks.NotificationJobTask"
android:exported="false">
<intent-filter>
<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE"/>
</intent-filter>
</service>
</application>
</manifest>

View File

@ -5,6 +5,7 @@ import android.support.annotation.NonNull;
import com.commonsware.cwac.anddown.AndDown;
import com.fastaccess.helper.TypeFaceHelper;
import com.fastaccess.provider.tasks.NotificationJobTask;
import com.fastaccess.provider.uil.UILProvider;
import com.siimkinks.sqlitemagic.SqliteMagic;
@ -25,13 +26,13 @@ public class App extends Application {
SqliteMagic.init(this);
UILProvider.initUIL(this);
TypeFaceHelper.generateTypeface(this);
NotificationJobTask.scheduleJob(this);//schedule the job for the notifications
}
@NonNull public static App getInstance() {
return instance;
}
@NonNull public AndDown getAndDown() {
if (andDown == null) {
andDown = new AndDown();

View File

@ -0,0 +1,57 @@
package com.fastaccess.data.dao;
import android.os.Parcel;
import android.os.Parcelable;
import com.siimkinks.sqlitemagic.annotation.Column;
import com.siimkinks.sqlitemagic.annotation.Table;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* Created by Kosh on 19 Feb 2017, 6:11 PM
*/
@Getter @Setter @NoArgsConstructor @Table(persistAll = true)
public class NotificationSubjectModel implements Parcelable {
@Column String title;
@Column String url;
@Column String type;
@Column String latestCommentUrl;
@Override public int describeContents() { return 0; }
@Override public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.title);
dest.writeString(this.url);
dest.writeString(this.type);
dest.writeString(this.latestCommentUrl);
dest.writeLong(this.id);
}
protected NotificationSubjectModel(Parcel in) {
this.title = in.readString();
this.url = in.readString();
this.type = in.readString();
this.latestCommentUrl = in.readString();
this.id = in.readLong();
}
public static final Parcelable.Creator<NotificationSubjectModel> CREATOR = new Parcelable.Creator<NotificationSubjectModel>() {
@Override public NotificationSubjectModel createFromParcel(Parcel source) {return new NotificationSubjectModel(source);}
@Override public NotificationSubjectModel[] newArray(int size) {return new NotificationSubjectModel[size];}
};
@Override public String toString() {
return "NotificationSubjectModel{" +
"id=" + id +
", title='" + title + '\'' +
", url='" + url + '\'' +
", type='" + type + '\'' +
", latestCommentUrl='" + latestCommentUrl + '\'' +
'}';
}
}

View File

@ -0,0 +1,99 @@
package com.fastaccess.data.dao;
import android.os.Parcel;
import android.os.Parcelable;
import com.fastaccess.data.dao.types.NotificationReason;
import com.siimkinks.sqlitemagic.Delete;
import com.siimkinks.sqlitemagic.NotificationThreadModelTable;
import com.siimkinks.sqlitemagic.Select;
import com.siimkinks.sqlitemagic.annotation.Column;
import com.siimkinks.sqlitemagic.annotation.Id;
import com.siimkinks.sqlitemagic.annotation.Table;
import java.util.Date;
import java.util.List;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.Setter;
import rx.Completable;
import rx.Observable;
/**
* Created by Kosh on 19 Feb 2017, 6:09 PM
*/
@Getter @Setter @NoArgsConstructor @Table(persistAll = true)
public class NotificationThreadModel implements Parcelable {
@Column @Id(autoIncrement = false) long id;
@Column(onDeleteCascade = true) RepoModel repository;
@Column(onDeleteCascade = true) NotificationSubjectModel subject;
@Column NotificationReason reason;
@Column String url;
@Column boolean unread;
@Column Date updatedAt;
@Column Date lastReadAt;
public Completable save() {
return persist().observe().toCompletable();
}
public static Completable save(@NonNull List<NotificationThreadModel> models) {
return Delete.from(NotificationThreadModelTable.NOTIFICATION_THREAD_MODEL)
.observe()
.toCompletable()
.andThen(persist(models).observe());
}
public static Observable<List<NotificationThreadModel>> getNotifications() {
return Select.from(NotificationThreadModelTable.NOTIFICATION_THREAD_MODEL)
.orderBy(NotificationThreadModelTable.NOTIFICATION_THREAD_MODEL.UPDATED_AT.desc(),
NotificationThreadModelTable.NOTIFICATION_THREAD_MODEL.UNREAD.is(false).desc())
.observe()
.runQuery();
}
@Override public int describeContents() { return 0; }
@Override public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(this.id);
dest.writeParcelable(this.repository, flags);
dest.writeParcelable(this.subject, flags);
dest.writeInt(this.reason == null ? -1 : this.reason.ordinal());
dest.writeString(this.url);
dest.writeValue(this.unread);
dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1);
dest.writeLong(this.lastReadAt != null ? this.lastReadAt.getTime() : -1);
}
protected NotificationThreadModel(Parcel in) {
this.id = in.readLong();
this.repository = in.readParcelable(RepoModel.class.getClassLoader());
this.subject = in.readParcelable(NotificationSubjectModel.class.getClassLoader());
int tmpReason = in.readInt();
this.reason = tmpReason == -1 ? null : NotificationReason.values()[tmpReason];
this.url = in.readString();
this.unread = (Boolean) in.readValue(Boolean.class.getClassLoader());
long tmpUpdatedAt = in.readLong();
this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt);
long tmpLastReadAt = in.readLong();
this.lastReadAt = tmpLastReadAt == -1 ? null : new Date(tmpLastReadAt);
}
public static final Creator<NotificationThreadModel> CREATOR = new Creator<NotificationThreadModel>() {
@Override public NotificationThreadModel createFromParcel(Parcel source) {return new NotificationThreadModel(source);}
@Override public NotificationThreadModel[] newArray(int size) {return new NotificationThreadModel[size];}
};
@Override public String toString() {
return "NotificationThreadModel{" +
"subject=" + subject +
", reason=" + reason +
", unread=" + unread +
'}';
}
}

View File

@ -0,0 +1,23 @@
package com.fastaccess.data.dao.transformer;
import android.support.annotation.NonNull;
import com.fastaccess.data.dao.types.NotificationReason;
import com.siimkinks.sqlitemagic.annotation.transformer.DbValueToObject;
import com.siimkinks.sqlitemagic.annotation.transformer.ObjectToDbValue;
import com.siimkinks.sqlitemagic.annotation.transformer.Transformer;
/**
* Created by Kosh on 11 Feb 2017, 11:43 PM
*/
@Transformer public class NotificatinReasonsTransformer {
@ObjectToDbValue @NonNull public static String objectToDbValue(NotificationReason javaObject) {
return javaObject == null ? NotificationReason.mention.name() : javaObject.name();
}
@DbValueToObject @NonNull public static NotificationReason dbValueToObject(String dbObject) {
return dbObject != null ? NotificationReason.valueOf(dbObject) : NotificationReason.mention;
}
}

View File

@ -0,0 +1,24 @@
package com.fastaccess.data.service;
import com.fastaccess.data.dao.NotificationThreadModel;
import com.fastaccess.data.dao.Pageable;
import retrofit2.Response;
import retrofit2.http.GET;
import retrofit2.http.PATCH;
import retrofit2.http.Path;
import rx.Observable;
/**
* Created by Kosh on 19 Feb 2017, 6:34 PM
*/
public interface NotificationService {
@GET("notifications") Observable<Pageable<NotificationThreadModel>> getNotifications();
@GET("/notifications/threads/{id}")
Observable<NotificationThreadModel> getNotification(@Path("id") String id);
@PATCH("notifications/threads/{id}") Observable<Response<Boolean>> markAsRead(@Path("id") String id);
}

View File

@ -1,10 +1,6 @@
package com.fastaccess.helper;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
@ -18,37 +14,6 @@ import android.view.inputmethod.InputMethodManager;
public class AppHelper {
@SuppressWarnings("deprecation") public static boolean isOnline(@NonNull Context context) {
boolean haveConnectedWifi = false;
boolean haveConnectedMobile = false;
try {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (isM()) {
Network networks = cm.getActiveNetwork();
NetworkInfo netInfo = cm.getNetworkInfo(networks);
haveConnectedWifi = netInfo.getType() == ConnectivityManager.TYPE_WIFI && netInfo.getState().equals(NetworkInfo.State.CONNECTED);
haveConnectedMobile = netInfo.getType() == ConnectivityManager.TYPE_MOBILE && netInfo.getState().equals(NetworkInfo.State.CONNECTED);
} else {
NetworkInfo[] netInfo = cm.getAllNetworkInfo();
for (NetworkInfo ni : netInfo) {
if (ni.getTypeName().equalsIgnoreCase("WIFI")) {
if (ni.isConnected())
haveConnectedWifi = true;
}
if (ni.getTypeName().equalsIgnoreCase("MOBILE")) {
if (ni.isConnected())
haveConnectedMobile = true;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return haveConnectedWifi || haveConnectedMobile;
}
@SuppressWarnings("WeakerAccess") public static boolean isM() {return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;}
public static void hideKeyboard(@NonNull View view) {
InputMethodManager inputManager = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow(view.getWindowToken(), 0);

View File

@ -12,6 +12,7 @@ import com.fastaccess.R;
import com.fastaccess.data.dao.GitHubErrorResponse;
import com.fastaccess.data.service.GistService;
import com.fastaccess.data.service.IssueService;
import com.fastaccess.data.service.NotificationService;
import com.fastaccess.data.service.PullRequestService;
import com.fastaccess.data.service.RepoService;
import com.fastaccess.data.service.SearchService;
@ -162,6 +163,10 @@ public class RestProvider {
return provideRetrofit().create(SearchService.class);
}
@NonNull public static NotificationService getNotificationService() {
return provideRetrofit().create(NotificationService.class);
}
@Nullable public static GitHubErrorResponse getErrorResponse(@NonNull Throwable throwable) {
if (throwable instanceof HttpException) {
ResponseBody body = ((HttpException) throwable).response().errorBody();

View File

@ -0,0 +1,95 @@
package com.fastaccess.provider.tasks;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.NotificationCompat;
import com.annimon.stream.Stream;
import com.fastaccess.R;
import com.fastaccess.data.dao.LoginModel;
import com.fastaccess.data.dao.NotificationThreadModel;
import com.fastaccess.helper.BundleConstant;
import com.fastaccess.helper.Logger;
import com.fastaccess.provider.rest.RestProvider;
import com.firebase.jobdispatcher.Constraint;
import com.firebase.jobdispatcher.FirebaseJobDispatcher;
import com.firebase.jobdispatcher.GooglePlayDriver;
import com.firebase.jobdispatcher.Job;
import com.firebase.jobdispatcher.JobParameters;
import com.firebase.jobdispatcher.JobService;
import com.firebase.jobdispatcher.Lifetime;
import com.firebase.jobdispatcher.RetryStrategy;
import com.firebase.jobdispatcher.Trigger;
import java.util.List;
import rx.schedulers.Schedulers;
/**
* Created by Kosh on 19 Feb 2017, 6:32 PM
*/
public class NotificationJobTask extends JobService {
private final static String EVERY_30_MINS = "every_30_mins";
@Override public boolean onStartJob(JobParameters job) {
if (LoginModel.getUser() != null) {
RestProvider.getNotificationService()
.getNotifications()
.subscribeOn(Schedulers.io())
.subscribe(item -> {
if (item != null) onSave(item.getItems());
}, throwable -> Logger.e(throwable.getMessage()));
}
return false;
}
@Override public boolean onStopJob(JobParameters job) {
return false;
}
public static void scheduleJob(@NonNull Context context) {
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
Job.Builder builder = dispatcher
.newJobBuilder()
.setTag(EVERY_30_MINS)
.setRetryStrategy(RetryStrategy.DEFAULT_LINEAR)
.setLifetime(Lifetime.FOREVER)
.setRecurring(true)
.setConstraints(Constraint.ON_ANY_NETWORK)
.setTrigger(Trigger.executionWindow(10, 30 * 60 /*every 30 seconds*/))
.setService(NotificationJobTask.class);
dispatcher.mustSchedule(builder.build());
}
private void onSave(@Nullable List<NotificationThreadModel> notificationThreadModels) {
if (notificationThreadModels != null) {
NotificationThreadModel.save(notificationThreadModels)
.subscribe(() -> onNotifyUser(notificationThreadModels));
}
}
private void onNotifyUser(@NonNull List<NotificationThreadModel> notificationThreadModels) {
long count = Stream.of(notificationThreadModels)
.filter(NotificationThreadModel::isUnread)
.count();
Logger.e(count, notificationThreadModels);
if (count > 0) {
Context context = getApplicationContext();
Notification notification = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_announcement)
.setContentTitle(context.getString(R.string.notifictions))
.setContentText(context.getString(R.string.unread_notification))
.setNumber((int) count)
.addAction(R.drawable.ic_github, context.getString(R.string.open), PendingIntent.getActivity(context, 0, new Intent(),
PendingIntent.FLAG_UPDATE_CURRENT))
.build();
((NotificationManager) context.getSystemService(NOTIFICATION_SERVICE)).notify(BundleConstant.REQUEST_CODE, notification);
}
}
}

View File

@ -87,6 +87,8 @@ public class MainView extends BaseActivity<MainMvp.View, MainPresenter> implemen
} else if (item.getItemId() == R.id.search) {
startActivity(new Intent(this, SearchView.class));
return true;
} else if (item.getItemId() == R.id.notifications) {
//TODO
}
return super.onOptionsItemSelected(item);
}

View File

@ -0,0 +1,9 @@
package com.fastaccess.ui.modules.notification;
/**
* Created by Kosh on 19 Feb 2017, 7:53 PM
*/
public interface NotificationsMvp {
}

View File

@ -23,6 +23,7 @@ import com.fastaccess.helper.InputHelper;
import com.fastaccess.helper.ParseDateFormat;
import com.fastaccess.helper.TypeFaceHelper;
import com.fastaccess.ui.base.BaseActivity;
import com.fastaccess.ui.modules.repos.code.RepoCodePagerView;
import com.fastaccess.ui.modules.repos.issues.RepoIssuesPagerView;
import com.fastaccess.ui.widgets.AvatarLayout;
import com.fastaccess.ui.widgets.FontTextView;
@ -245,6 +246,21 @@ public class RepoPagerView extends BaseActivity<RepoPagerMvp.View, RepoPagerPres
return super.onOptionsItemSelected(item);
}
@Override public void onBackPressed() {
if (navType == RepoPagerMvp.CODE) {
RepoCodePagerView codePagerView = (RepoCodePagerView) AppHelper.getFragmentByTag(getSupportFragmentManager(), RepoCodePagerView.TAG);
if (codePagerView != null) {
if (codePagerView.canPressBack()) {
super.onBackPressed();
} else {
codePagerView.onBackPressed();
return;
}
}
}
super.onBackPressed();
}
private void showHideFab() {
if (navType == RepoPagerMvp.ISSUES) {
fab.show();

View File

@ -8,7 +8,11 @@ import com.fastaccess.ui.base.mvp.BaseMvp;
interface RepoCodePagerMvp {
interface View extends BaseMvp.FAView {}
interface View extends BaseMvp.FAView {
boolean canPressBack();
void onBackPressed();
}
interface Presenter extends BaseMvp.FAPresenter {}
}

View File

@ -13,6 +13,7 @@ import com.fastaccess.helper.Bundler;
import com.fastaccess.helper.InputHelper;
import com.fastaccess.ui.adapter.FragmentsPagerAdapter;
import com.fastaccess.ui.base.BaseFragment;
import com.fastaccess.ui.modules.repos.code.files.paths.RepoFilePathView;
import com.fastaccess.ui.widgets.ViewPagerView;
import butterknife.BindView;
@ -57,4 +58,17 @@ public class RepoCodePagerView extends BaseFragment<RepoCodePagerMvp.View, RepoC
@NonNull @Override public RepoCodePagerPresenter providePresenter() {
return new RepoCodePagerPresenter();
}
@Override public boolean canPressBack() {
if (pager.getCurrentItem() != 1) return true;
RepoFilePathView pathView = (RepoFilePathView) pager.getAdapter().instantiateItem(pager, 1);
return pathView == null || pathView.canPressBack();
}
@Override public void onBackPressed() {
RepoFilePathView pathView = (RepoFilePathView) pager.getAdapter().instantiateItem(pager, 1);
if (pathView != null) {
pathView.onBackPressed();
}
}
}

View File

@ -24,6 +24,10 @@ interface RepoFilePathMvp {
void onAppendPath(@NonNull RepoFilesModel model);
void onSendData();
boolean canPressBack();
void onBackPressed();
}
interface Presenter extends BaseMvp.FAPresenter,

View File

@ -10,6 +10,7 @@ import com.fastaccess.R;
import com.fastaccess.data.dao.RepoFilesModel;
import com.fastaccess.helper.BundleConstant;
import com.fastaccess.helper.Bundler;
import com.fastaccess.helper.Logger;
import com.fastaccess.ui.adapter.RepoFilePathsAdapter;
import com.fastaccess.ui.base.BaseFragment;
import com.fastaccess.ui.modules.repos.code.files.RepoFilesView;
@ -52,16 +53,17 @@ public class RepoFilePathView extends BaseFragment<RepoFilePathMvp.View, RepoFil
@Override public void onItemClicked(@NonNull RepoFilesModel model, int position) {
if (getRepoFilesView().isRefreshing()) return; // avoid calling for path while the other still loading...
if ((adapter.getItemCount() - 1) > position) {
if ((position + 1) < adapter.getItemCount()) {
adapter.subList(position + 1, adapter.getItemCount());
}
getRepoFilesView().onSetData(getPresenter().getLogin(), getPresenter().getRepoId(), model.getPath());
}
@Override public void onAppendPath(@NonNull RepoFilesModel model) {
adapter.addItem(model);
onShowHideBackBtn();
recycler.scrollToPosition(adapter.getItemCount() - 1); //smoothScrollToPosition(index) hides the recyclerview? WTF GOOGLE.
recycler.scrollToPosition(adapter.getItemCount() - 1); //smoothScrollToPosition(index) hides the recyclerview? MIND-BLOWING??.
getRepoFilesView().onSetData(getPresenter().getLogin(), getPresenter().getRepoId(), model.getPath());
}
@ -69,6 +71,22 @@ public class RepoFilePathView extends BaseFragment<RepoFilePathMvp.View, RepoFil
getRepoFilesView().onSetData(getPresenter().getLogin(), getPresenter().getRepoId(), getPresenter().getPath());
}
@Override public boolean canPressBack() {
return adapter == null || adapter.getItemCount() == 0;
}
@Override public void onBackPressed() {
int position = adapter.getItemCount() > 2 ? adapter.getItemCount() - 2 : adapter.getItemCount() - 1;
Logger.e(position, adapter.getItemCount());
if (position > 0 && position <= adapter.getItemCount()) {
if (position == 1) position = 0;
RepoFilesModel repoFilesModel = adapter.getItem(position);
onItemClicked(repoFilesModel, position);
} else {
onBackClicked();
}
}
@Override protected int fragmentLayout() {
return R.layout.repo_file_layout;
}

View File

@ -120,7 +120,6 @@ public abstract class BaseRecyclerAdapter<M, VH extends BaseViewHolder,
}
public void subList(int fromPosition, int toPosition) {
toPosition = data.size() > toPosition ? toPosition : data.size();
data.subList(fromPosition, toPosition).clear();
notifyItemRangeRemoved(fromPosition, toPosition);
}

View File

@ -1,8 +1,8 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM13,11h-2L11,5h2v6zM13,15h-2v-2h2v2z"/>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.89,2 2,2zM18,16v-5c0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2z"/>
</vector>

View File

@ -2,9 +2,15 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/notifications"
android:icon="@drawable/ic_notifications"
android:title="@string/notifictions"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/search"
android:icon="@drawable/ic_search"
android:title="@string/search"
app:showAsAction="always"/>
app:showAsAction="ifRoom"/>
</menu>

BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@ -141,4 +141,7 @@
<string name="error_creating_issue">Error creating issue.</string>
<string name="create_issue">Create Issue</string>
<string name="error_highlighting_editor">Please un-select highlighting to continue editing.</string>
<string name="notifictions">Notifications</string>
<string name="unread_notification">You have unread notifications</string>
<string name="open">Open</string>
</resources>

BIN
art/web_hi_res_512.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View File

@ -6,7 +6,7 @@ buildscript {
maven { url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' }
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0-beta4'
classpath 'com.android.tools.build:gradle:2.3.0-rc1'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
classpath 'com.google.gms:google-services:3.0.0'
classpath 'me.tatarka:gradle-retrolambda:3.2.4'