From bbacfd74db69987c90bfa690b1daa46fa043d9a1 Mon Sep 17 00:00:00 2001 From: YuutaW <17158086+trumeet@users.noreply.github.com> Date: Tue, 25 Dec 2018 18:01:13 -0800 Subject: [PATCH 1/2] fix(app): backward compatibility for Stream apis Signed-off-by: Trumeet <17158086+Trumeet@users.noreply.github.com> --- app/build.gradle | 15 ++++++++++----- .../topic/TopicSubscriptionFragment.java | 5 +++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 0dbd45f..9d813fa 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -91,11 +91,6 @@ dependencies { testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' - implementation 'com.elvishew:xlog:1.6.1' - implementation project(':common') - implementation 'moe.shizuku.preference:preference:3.0.0' - implementation 'moe.shizuku.preference:preference-dialog-android:3.0.0' - implementation 'moe.shizuku.preference:preference-simplemenu:3.0.0' implementation 'com.google.android.material:material:1.1.0-alpha02' def nav_version = "1.0.0-alpha08" implementation "android.arch.navigation:navigation-fragment:$nav_version" @@ -107,4 +102,14 @@ dependencies { implementation 'com.google.android.gms:play-services-oss-licenses:16.0.1' // Fabric implementation 'com.crashlytics.sdk.android:crashlytics:2.9.8' + // Stream support for Java8- + implementation 'com.annimon:stream:1.2.1' + // Preferences + implementation 'moe.shizuku.preference:preference:3.0.0' + implementation 'moe.shizuku.preference:preference-dialog-android:3.0.0' + implementation 'moe.shizuku.preference:preference-simplemenu:3.0.0' + // Logger + implementation 'com.elvishew:xlog:1.6.1' + // Common + implementation project(':common') } diff --git a/app/src/main/java/moe/yuuta/mipushtester/topic/TopicSubscriptionFragment.java b/app/src/main/java/moe/yuuta/mipushtester/topic/TopicSubscriptionFragment.java index 53d3547..2c97e2e 100644 --- a/app/src/main/java/moe/yuuta/mipushtester/topic/TopicSubscriptionFragment.java +++ b/app/src/main/java/moe/yuuta/mipushtester/topic/TopicSubscriptionFragment.java @@ -5,13 +5,14 @@ import android.view.View; import android.view.ViewGroup; +import com.annimon.stream.Collectors; +import com.annimon.stream.Stream; import com.elvishew.xlog.Logger; import com.elvishew.xlog.XLog; import com.google.android.material.snackbar.Snackbar; import com.xiaomi.mipush.sdk.MiPushClient; import java.util.List; -import java.util.stream.Collectors; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -79,7 +80,7 @@ public void onFailure(@NonNull Call> call, @NonNull Throwable t) { private void displayTopicsToUI (List originalList) { List localSubscribedTopics = MiPushClient.getAllTopic(requireContext()); - List list = originalList.stream() + List list = Stream.of(originalList) .peek(topic -> topic.setSubscribed(localSubscribedTopics.contains(topic.getId()))) .collect(Collectors.toList()); DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() { From 295b7f0690de5bd9502ceef43174e0e2b9e5d02e Mon Sep 17 00:00:00 2001 From: YuutaW <17158086+trumeet@users.noreply.github.com> Date: Tue, 25 Dec 2018 19:14:16 -0800 Subject: [PATCH 2/2] feat(app): add multi states view for topics list Signed-off-by: Trumeet <17158086+Trumeet@users.noreply.github.com> --- README.md | 14 +++- .../topic/TopicSubscriptionFragment.java | 39 +++++++-- .../widgets/multi_state/State.java | 56 +++++++++++++ .../layout/fragment_topic_subscription.xml | 45 +++++++---- .../main/res/layout/layout_multi_state.xml | 75 ++++++++++++++++++ .../res/mipmap/illustration_fetal_error.png | Bin 0 -> 88476 bytes .../res/mipmap/illustration_list_is_empty.png | Bin 0 -> 108696 bytes app/src/main/res/values/strings.xml | 4 + 8 files changed, 212 insertions(+), 21 deletions(-) create mode 100644 app/src/main/java/moe/yuuta/mipushtester/widgets/multi_state/State.java create mode 100644 app/src/main/res/layout/layout_multi_state.xml create mode 100644 app/src/main/res/mipmap/illustration_fetal_error.png create mode 100644 app/src/main/res/mipmap/illustration_list_is_empty.png diff --git a/README.md b/README.md index b8b812e..ea058b8 100644 --- a/README.md +++ b/README.md @@ -31,4 +31,16 @@ If your push (message) is not received or display an error, you can feedback [he Don't forget to attach your logs by sharing logs zip (Main → Menu → Share logs) and your steps. # Licenses -GPL v3.0 \ No newline at end of file +## The license for this project +GPL v3.0 +## Licenses for third-party resources +Licenses of libraries are used in Android client is attached into the app, you can go to Main Menu Open Source Licenses to view them. + +Some icons and pictures comes from [icons8.com](https://icons8.com/license), which are free to use for Open Source (Established projects should get the icons for free.) + +Licenses of libraries are used in the server: + +* Vertx - Eclipse Public License 2.0 and Apache License 2.0 +* JUnit - EPL 1.0 +* Mockito - MIT +* Power Mockito - Apache 2.0 \ No newline at end of file diff --git a/app/src/main/java/moe/yuuta/mipushtester/topic/TopicSubscriptionFragment.java b/app/src/main/java/moe/yuuta/mipushtester/topic/TopicSubscriptionFragment.java index 2c97e2e..1dae546 100644 --- a/app/src/main/java/moe/yuuta/mipushtester/topic/TopicSubscriptionFragment.java +++ b/app/src/main/java/moe/yuuta/mipushtester/topic/TopicSubscriptionFragment.java @@ -9,18 +9,21 @@ import com.annimon.stream.Stream; import com.elvishew.xlog.Logger; import com.elvishew.xlog.XLog; -import com.google.android.material.snackbar.Snackbar; import com.xiaomi.mipush.sdk.MiPushClient; import java.util.List; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.databinding.DataBindingUtil; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.RecyclerView; import moe.yuuta.mipushtester.R; import moe.yuuta.mipushtester.api.APIManager; +import moe.yuuta.mipushtester.databinding.FragmentTopicSubscriptionBinding; +import moe.yuuta.mipushtester.widgets.multi_state.State; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; @@ -30,6 +33,7 @@ public class TopicSubscriptionFragment extends Fragment { private TopicListAdapter mAdapter; private Call> mGetTopicListCall; + private State mLoadingState; @Override public void onCreate(@Nullable Bundle savedInstanceState) { @@ -48,20 +52,34 @@ public void onCreate(@Nullable Bundle savedInstanceState) { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - final View view = inflater.inflate(R.layout.fragment_topic_subscription, container, false); - RecyclerView recyclerView = view.findViewById(R.id.recycler_topic); + final FragmentTopicSubscriptionBinding binding = + DataBindingUtil.inflate(inflater, R.layout.fragment_topic_subscription, container, false); + RecyclerView recyclerView = binding.recyclerTopic; recyclerView.setAdapter(mAdapter); - return view; + mLoadingState = new State(); + mLoadingState.onRetryListener = (v -> call()); + binding.setState(mLoadingState); + return binding.getRoot(); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + call(); + } + + private void call () { + if (mGetTopicListCall != null) { + mGetTopicListCall.cancel(); + mGetTopicListCall = null; + } mGetTopicListCall = APIManager.getInstance().getAvailableTopics(); + mLoadingState.showProgress(); mGetTopicListCall.enqueue(new Callback>() { @Override public void onResponse(@NonNull Call> call, @NonNull Response> response) { if (call.isCanceled()) return; + mLoadingState.hideProgress(); if (!response.isSuccessful()) { onFailure(call, new Exception("Unsuccessful code " + response.code())); return; @@ -73,12 +91,23 @@ public void onResponse(@NonNull Call> call, @NonNull Response> call, @NonNull Throwable t) { logger.e("Cannot retain topics", t); if (call.isCanceled()) return; - Snackbar.make(getView(), R.string.error_load_topics, Snackbar.LENGTH_INDEFINITE).show(); + mLoadingState.hideProgress(); + mLoadingState.icon.set(ContextCompat.getDrawable(requireContext(), R.mipmap.illustration_fetal_error)); + mLoadingState.text.set(getString(R.string.error_load_topics)); + mLoadingState.description.set(getString(R.string.error_description_global)); } }); } private void displayTopicsToUI (List originalList) { + if (originalList == null || originalList.size() <= 0) { + mLoadingState.icon.set(ContextCompat.getDrawable(requireContext(), R.mipmap.illustration_list_is_empty)); + mLoadingState.text.set(getString(R.string.topic_empty_title)); + mLoadingState.showRetry.set(false); + mLoadingState.description.set(getString(R.string.topic_empty_description)); + return; + } + mLoadingState.hideAll(); List localSubscribedTopics = MiPushClient.getAllTopic(requireContext()); List list = Stream.of(originalList) .peek(topic -> topic.setSubscribed(localSubscribedTopics.contains(topic.getId()))) diff --git a/app/src/main/java/moe/yuuta/mipushtester/widgets/multi_state/State.java b/app/src/main/java/moe/yuuta/mipushtester/widgets/multi_state/State.java new file mode 100644 index 0000000..f9a0a73 --- /dev/null +++ b/app/src/main/java/moe/yuuta/mipushtester/widgets/multi_state/State.java @@ -0,0 +1,56 @@ +package moe.yuuta.mipushtester.widgets.multi_state; + +import android.graphics.drawable.Drawable; +import android.view.View; + +import androidx.databinding.ObservableBoolean; +import androidx.databinding.ObservableField; + +public class State { + public final ObservableBoolean showProgress; + public final ObservableField icon; + public final ObservableField text; + public final ObservableField description; + public final ObservableBoolean showTitle; + public final ObservableBoolean showIcon; + public final ObservableBoolean showDescription; + public View.OnClickListener onRetryListener; + public final ObservableBoolean showRetry; + public final ObservableField contentDescription; + + public State() { + showProgress = new ObservableBoolean(false); + icon = new ObservableField<>(); + text = new ObservableField<>(); + description = new ObservableField<>(); + showRetry = new ObservableBoolean(false); + showTitle = new ObservableBoolean(true); + showDescription = new ObservableBoolean(true); + contentDescription = new ObservableField<>(); + showIcon = new ObservableBoolean(true); + } + + public void showProgress () { + this.showProgress.set(true); + this.showTitle.set(false); + this.showDescription.set(false); + this.showRetry.set(false); + this.showIcon.set(false); + } + + public void hideProgress () { + this.showProgress.set(false); + this.showTitle.set(true); + this.showDescription.set(true); + this.showRetry.set(true); + this.showIcon.set(true); + } + + public void hideAll () { + this.showProgress.set(false); + this.showTitle.set(false); + this.showDescription.set(false); + this.showRetry.set(false); + this.showIcon.set(false); + } +} diff --git a/app/src/main/res/layout/fragment_topic_subscription.xml b/app/src/main/res/layout/fragment_topic_subscription.xml index 4c45f65..5ec613b 100644 --- a/app/src/main/res/layout/fragment_topic_subscription.xml +++ b/app/src/main/res/layout/fragment_topic_subscription.xml @@ -1,16 +1,31 @@ - - - \ No newline at end of file + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_multi_state.xml b/app/src/main/res/layout/layout_multi_state.xml new file mode 100644 index 0000000..254c744 --- /dev/null +++ b/app/src/main/res/layout/layout_multi_state.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + +