From 9904a70f656ba52fbdf1c8a809e7cd6f23158275 Mon Sep 17 00:00:00 2001 From: Kosh Date: Sun, 26 Feb 2017 21:26:57 +0800 Subject: [PATCH] displaying guides on some places of the app and updated readme of what the project made of. --- README.md | 25 +++++++++++- app/build.gradle | 1 + app/src/main/java/com/fastaccess/App.java | 8 ++++ .../com/fastaccess/helper/PrefGetter.java | 35 +++++++++++++++++ .../fastaccess/ui/modules/feeds/FeedsMvp.java | 4 +- .../ui/modules/feeds/FeedsView.java | 30 ++++++++++++++ .../ui/modules/repos/RepoPagerView.java | 39 +++++++++++++++++++ .../repos/code/files/RepoFilesView.java | 20 ++++++++++ .../code/files/paths/RepoFilePathView.java | 6 +++ .../repos/code/releases/RepoReleasesView.java | 18 +++++++++ .../details/comments/IssueCommentsView.java | 18 +++++++++ .../recyclerview/BaseRecyclerAdapter.java | 24 ++++++++++++ app/src/main/res/values/strings.xml | 12 ++++++ 13 files changed, 238 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f44358f4..9b4eaeba 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ![Logo](https://github.com/k0shk0sh/FastHub/blob/master/art/feature_graphic.png?raw=true "Logo") -**FastHub** is yet another open source GitHub client app but unlike any other app, FastHub built from ground up. +**FastHub** is yet another **open source** GitHub client app but unlike any other app, FastHub built from ground up. @@ -26,6 +26,29 @@ - Receive notifications. - Loads more... + +# FastHub made of: + +- Min SDK(21) but Appcompat is used all the way. +- MVP architecture'd using Thirtyinch lib for the edibility of maintaining and following one structure throughout the project. +- Lambda expressions because __you know why__. +- RxJava & RxAndroid for Retrofit & Background threads. +- Retrofit for consuming rest api. +- SqliteMagic for offline mode. +- Stream API for dealing with iterations. +- JobScheduler using Firebase JobDispatcher for notifications service. +- ButterKnife for views binding. +- Icepick for saving instance of objects. +- Lombok for (getters/setters). +- BottomNavigationView for `Fragments` navigation. +- UIL for image loading. +- AndDown for comments markdown highlighting. +- Alerter for displaying error/success messages. +- CircleImageView for avatar images. +- MatrialTagPrompt for displying guides throughout the app. +- Firebase analytics, crash reporting, ads & messaging. (analytics & messaging not yet implemented.) +- The mighty Android support libs. + # Contribution You love FastHub? You want new features or bug fixes? Please contribute to the project either by creating PR or submitting an issue ticket. diff --git a/app/build.gradle b/app/build.gradle index cd04be17..9ece2d77 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -117,6 +117,7 @@ dependencies { compile 'com.annimon:stream:1.1.4' compile 'com.commonsware.cwac:anddown:0.3.0' compile 'com.tapadoo.android:alerter:1.0.1' + compile 'uk.co.samuelwall:material-tap-target-prompt:1.9.2' apt 'org.projectlombok:lombok:1.12.6' apt 'frankiesardo:icepick-processor:3.1.0' apt 'com.jakewharton:butterknife-compiler:8.4.0' diff --git a/app/src/main/java/com/fastaccess/App.java b/app/src/main/java/com/fastaccess/App.java index 0af7a6a9..8d1fa535 100644 --- a/app/src/main/java/com/fastaccess/App.java +++ b/app/src/main/java/com/fastaccess/App.java @@ -2,6 +2,7 @@ package com.fastaccess; import android.app.Application; import android.support.annotation.NonNull; +import android.util.Log; import com.commonsware.cwac.anddown.AndDown; import com.fastaccess.helper.TypeFaceHelper; @@ -27,6 +28,13 @@ public class App extends Application { UILProvider.initUIL(this); TypeFaceHelper.generateTypeface(this); NotificationJobTask.scheduleJob(this);//schedule the job for the notifications + if (BuildConfig.DEBUG) { + Thread.setDefaultUncaughtExceptionHandler((paramThread, paramThrowable) -> { + Log.e("Crash", paramThrowable.getMessage(), paramThrowable); + System.exit(2); + }); + } + } @NonNull public static App getInstance() { diff --git a/app/src/main/java/com/fastaccess/helper/PrefGetter.java b/app/src/main/java/com/fastaccess/helper/PrefGetter.java index a05399b4..9a46744d 100644 --- a/app/src/main/java/com/fastaccess/helper/PrefGetter.java +++ b/app/src/main/java/com/fastaccess/helper/PrefGetter.java @@ -9,6 +9,11 @@ import android.support.annotation.NonNull; public class PrefGetter { private static final String ADS = "enable_ads"; private static final String TOKEN = "token"; + private static final String USER_ICON_GUIDE = "user_icon_guide"; + private static final String RELEASE_GUIDE = "release_guide"; + private static final String FILE_OPTION_GUIDE = "file_option_guide"; + private static final String COMMENTS_GUIDE = "comments_guide"; + private static final String REPO_GUIDE = "repo_guide"; public static void setToken(@NonNull String token) { PrefHelper.set(TOKEN, token); @@ -29,4 +34,34 @@ public class PrefGetter { public static void clear() { PrefHelper.clearPrefs(); } + + public static boolean isUserIconGuideShowed() { + boolean isShowed = PrefHelper.getBoolean(USER_ICON_GUIDE); + PrefHelper.set(USER_ICON_GUIDE, true); + return isShowed; + } + + public static boolean isReleaseHintShow() { + boolean isShowed = PrefHelper.getBoolean(RELEASE_GUIDE); + PrefHelper.set(RELEASE_GUIDE, true); + return isShowed; + } + + public static boolean isFileOptionHintShow() { + boolean isShowed = PrefHelper.getBoolean(FILE_OPTION_GUIDE); + PrefHelper.set(FILE_OPTION_GUIDE, true); + return isShowed; + } + + public static boolean isCommentHintShowed() { + boolean isShowed = PrefHelper.getBoolean(COMMENTS_GUIDE); + PrefHelper.set(COMMENTS_GUIDE, true); + return isShowed; + } + + public static boolean isRepoGuideShowed() { + boolean isShowed = PrefHelper.getBoolean(REPO_GUIDE); + PrefHelper.set(REPO_GUIDE, true); + return isShowed; + } } diff --git a/app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsMvp.java b/app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsMvp.java index bde47d59..e4915812 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsMvp.java +++ b/app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsMvp.java @@ -8,6 +8,7 @@ import com.fastaccess.data.dao.SimpleUrlsModel; import com.fastaccess.provider.rest.loadmore.OnLoadMore; import com.fastaccess.ui.base.mvp.BaseMvp; import com.fastaccess.ui.widgets.dialog.ListDialogView; +import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; import java.util.ArrayList; @@ -18,7 +19,8 @@ import java.util.ArrayList; interface FeedsMvp { interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, - android.view.View.OnClickListener, ListDialogView.onSimpleItemSelection { + android.view.View.OnClickListener, ListDialogView.onSimpleItemSelection, + BaseRecyclerAdapter.GuideListener { void onNotifyAdapter(); diff --git a/app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsView.java b/app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsView.java index 75dc383c..394f8fec 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsView.java +++ b/app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsView.java @@ -6,11 +6,14 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.StringRes; import android.support.v4.widget.SwipeRefreshLayout; +import android.view.MotionEvent; import android.view.View; import com.fastaccess.R; +import com.fastaccess.data.dao.EventsModel; import com.fastaccess.data.dao.SimpleUrlsModel; import com.fastaccess.helper.Logger; +import com.fastaccess.helper.PrefGetter; import com.fastaccess.provider.rest.loadmore.OnLoadMore; import com.fastaccess.provider.scheme.SchemeParser; import com.fastaccess.ui.adapter.FeedsAdapter; @@ -22,6 +25,7 @@ import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; import java.util.ArrayList; import butterknife.BindView; +import uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt; /** * Created by Kosh on 11 Nov 2016, 12:36 PM @@ -50,6 +54,7 @@ public class FeedsView extends BaseFragment imple refresh.setOnRefreshListener(this); recycler.setEmptyView(stateLayout, refresh); adapter = new FeedsAdapter(getPresenter().getEvents()); + adapter.setGuideListener(this); adapter.setListener(getPresenter()); getLoadMore().setCurrent_page(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); recycler.setAdapter(adapter); @@ -113,4 +118,29 @@ public class FeedsView extends BaseFragment imple @Override public void onItemSelected(SimpleUrlsModel item) { SchemeParser.launchUri(getContext(), Uri.parse(item.getItem())); } + + @Override public void onShowGuide(@NonNull View itemView, @NonNull EventsModel model) { + if (!PrefGetter.isUserIconGuideShowed()) { + new MaterialTapTargetPrompt.Builder(getActivity()) + .setTarget(itemView.findViewById(R.id.avatarLayout)) + .setPrimaryText(R.string.users) + .setSecondaryText(R.string.avatar_click_hint) + .setOnHidePromptListener(new MaterialTapTargetPrompt.OnHidePromptListener() { + @Override public void onHidePrompt(MotionEvent event, boolean tappedTarget) { + + } + + @Override public void onHidePromptComplete() { + new MaterialTapTargetPrompt.Builder(getActivity()) + .setTarget(itemView) + .setPrimaryText(R.string.fork) + .setSecondaryText(R.string.feeds_fork_hint) + .setCaptureTouchEventOutsidePrompt(true) + .show(); + } + }) + .setCaptureTouchEventOutsidePrompt(true) + .show(); + } + } } diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/RepoPagerView.java b/app/src/main/java/com/fastaccess/ui/modules/repos/RepoPagerView.java index 5f2bcd56..2ac9c4d2 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/RepoPagerView.java +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/RepoPagerView.java @@ -10,6 +10,7 @@ import android.support.annotation.NonNull; import android.support.design.widget.FloatingActionButton; import android.view.Menu; import android.view.MenuItem; +import android.view.MotionEvent; import android.view.View; import com.fastaccess.R; @@ -21,6 +22,7 @@ import com.fastaccess.helper.BundleConstant; import com.fastaccess.helper.Bundler; import com.fastaccess.helper.InputHelper; import com.fastaccess.helper.ParseDateFormat; +import com.fastaccess.helper.PrefGetter; import com.fastaccess.helper.TypeFaceHelper; import com.fastaccess.ui.base.BaseActivity; import com.fastaccess.ui.modules.repos.code.RepoCodePagerView; @@ -37,6 +39,7 @@ import butterknife.OnClick; import hugo.weaving.DebugLog; import icepick.State; import it.sephiroth.android.library.bottomnavigation.BottomNavigation; +import uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt; /** * Created by Kosh on 09 Dec 2016, 4:17 PM @@ -176,6 +179,42 @@ public class RepoPagerView extends BaseActivity + new MaterialTapTargetPrompt.Builder(getActivity()) + .setTarget(itemView.findViewById(R.id.menu)) + .setPrimaryText(R.string.options) + .setSecondaryText(R.string.click_file_option_hint) + .setCaptureTouchEventOutsidePrompt(true) + .show()); + adapter.notifyDataSetChanged();// call it notify the adapter to show the guide immediately. + } + } + } + @Override public void showProgress(@StringRes int resId) { refresh.setRefreshing(true); stateLayout.showProgress(); diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/paths/RepoFilePathView.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/paths/RepoFilePathView.java index 29437c8f..b0eeebbd 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/paths/RepoFilePathView.java +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/paths/RepoFilePathView.java @@ -104,6 +104,12 @@ public class RepoFilePathView extends BaseFragment + new MaterialTapTargetPrompt.Builder(getActivity()) + .setTarget(itemView.findViewById(R.id.download)) + .setPrimaryText(R.string.download) + .setSecondaryText(R.string.click_here_to_download_release_hint) + .setCaptureTouchEventOutsidePrompt(true) + .show()); + adapter.notifyDataSetChanged();// call it notify the adapter to show the guide immediately. + } + } + } + @NonNull @Override public RepoReleasesPresenter providePresenter() { return new RepoReleasesPresenter(); } diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/comments/IssueCommentsView.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/comments/IssueCommentsView.java index 0cd3b926..f2ff9280 100644 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/comments/IssueCommentsView.java +++ b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/comments/IssueCommentsView.java @@ -13,6 +13,7 @@ import com.fastaccess.data.dao.CommentsModel; import com.fastaccess.data.dao.UserModel; import com.fastaccess.helper.BundleConstant; import com.fastaccess.helper.Bundler; +import com.fastaccess.helper.PrefGetter; import com.fastaccess.provider.rest.loadmore.OnLoadMore; import com.fastaccess.ui.adapter.CommentsAdapter; import com.fastaccess.ui.base.BaseFragment; @@ -23,6 +24,7 @@ import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; import butterknife.BindView; import retrofit2.Response; +import uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt; /** * Created by Kosh on 11 Nov 2016, 12:36 PM @@ -175,4 +177,20 @@ public class IssueCommentsView extends BaseFragment + new MaterialTapTargetPrompt.Builder(getActivity()) + .setTarget(itemView.findViewById(R.id.menu)) + .setPrimaryText(R.string.comment) + .setSecondaryText(R.string.comment_hint) + .setCaptureTouchEventOutsidePrompt(true) + .show()); + adapter.notifyDataSetChanged(); + } + } + } } diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseRecyclerAdapter.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseRecyclerAdapter.java index 9ba9ef82..06dc8581 100644 --- a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseRecyclerAdapter.java +++ b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseRecyclerAdapter.java @@ -3,6 +3,7 @@ package com.fastaccess.ui.widgets.recyclerview; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; +import android.view.View; import android.view.ViewGroup; import com.fastaccess.helper.AnimHelper; @@ -16,10 +17,16 @@ import java.util.List; public abstract class BaseRecyclerAdapter> extends RecyclerView.Adapter { + public interface GuideListener { + void onShowGuide(@NonNull View itemView, @NonNull M model); + } + @NonNull private List data; @Nullable private P listener; private int lastKnowingPosition = -1; private boolean enableAnimation = true; + private boolean showedGuide; + private GuideListener guideListener; public BaseRecyclerAdapter() { this(new ArrayList<>()); @@ -57,12 +64,21 @@ public abstract class BaseRecyclerAdapter lastKnowingPosition) { AnimHelper.startBeatsAnimation(holder.itemView); @@ -145,4 +161,12 @@ public abstract class BaseRecyclerAdapterError Deleting Comment Delete Comments + Comment Issue Merge Pull Request @@ -160,4 +161,15 @@ Password Login Gist Description + Whenever there is a User avatar, you can click it to open the User\'s Profile + Long click on Fork event to choose to open either Original Repo or the Forked Repo. + Click here to download releases. + Options + Click here to download File or share a Directory. + Single tap to tag a user or to edit the comment if you are the author.\nLong press if you are the author of the + comment to delete it. + Click here to star/unstar repo. + Watch + Click here to watch/unwatch repo. + Click here to fork repo.