diff --git a/app/src/main/java/com/stardust/scriptdroid/network/UserService.java b/app/src/main/java/com/stardust/scriptdroid/network/UserService.java index 890ff7f4..2ffeb0b6 100644 --- a/app/src/main/java/com/stardust/scriptdroid/network/UserService.java +++ b/app/src/main/java/com/stardust/scriptdroid/network/UserService.java @@ -2,12 +2,14 @@ package com.stardust.scriptdroid.network; import com.jakewharton.retrofit2.adapter.rxjava2.HttpException; import com.stardust.scriptdroid.network.api.UserApi; +import com.stardust.scriptdroid.network.entity.notification.Notification; +import com.stardust.scriptdroid.network.entity.notification.NotificationResponse; import com.stardust.scriptdroid.network.entity.user.User; import com.stardust.util.Objects; import org.greenrobot.eventbus.EventBus; -import java.util.Collections; +import java.util.List; import io.reactivex.Observable; import io.reactivex.schedulers.Schedulers; @@ -21,7 +23,6 @@ import retrofit2.Retrofit; public class UserService { - public static class LoginStateChange { private final boolean mOnline; @@ -116,4 +117,13 @@ public class UserService { .doOnNext(this::setUser) .doOnError(error -> setUser(null)); } + + + public Observable> getNotifications() { + return NodeBB.getInstance().getRetrofit() + .create(UserApi.class) + .getNotifitions() + .map(NotificationResponse::getNotifications); + } + } diff --git a/app/src/main/java/com/stardust/scriptdroid/network/api/UserApi.java b/app/src/main/java/com/stardust/scriptdroid/network/api/UserApi.java index 4c55c16e..ba43bee4 100644 --- a/app/src/main/java/com/stardust/scriptdroid/network/api/UserApi.java +++ b/app/src/main/java/com/stardust/scriptdroid/network/api/UserApi.java @@ -1,5 +1,6 @@ package com.stardust.scriptdroid.network.api; +import com.stardust.scriptdroid.network.entity.notification.NotificationResponse; import com.stardust.scriptdroid.network.entity.user.User; import java.util.Map; @@ -33,4 +34,7 @@ public interface UserApi { @POST("/logout") Observable logout(@HeaderMap Map csrfToken); + + @GET("/api/notifications") + Observable getNotifitions(); } diff --git a/app/src/main/java/com/stardust/scriptdroid/network/entity/notification/Notification.java b/app/src/main/java/com/stardust/scriptdroid/network/entity/notification/Notification.java new file mode 100644 index 00000000..5d896d32 --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/network/entity/notification/Notification.java @@ -0,0 +1,134 @@ +package com.stardust.scriptdroid.network.entity.notification; + +import com.stardust.scriptdroid.network.entity.user.User; + +public class Notification { + + private boolean read; + private String mergeId; + private String importance; + private String nid; + private String type; + private String path; + private String readClass; + private String datetime; + private String from; + private String bodyShort; + private String datetimeISO; + private User user; + + public void setRead(boolean read) { + this.read = read; + } + + public boolean isRead() { + return read; + } + + public void setMergeId(String mergeId) { + this.mergeId = mergeId; + } + + public String getMergeId() { + return mergeId; + } + + public void setImportance(String importance) { + this.importance = importance; + } + + public String getImportance() { + return importance; + } + + public void setNid(String nid) { + this.nid = nid; + } + + public String getNid() { + return nid; + } + + public void setType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public void setPath(String path) { + this.path = path; + } + + public String getPath() { + return path; + } + + public void setReadClass(String readClass) { + this.readClass = readClass; + } + + public String getReadClass() { + return readClass; + } + + public void setDatetime(String datetime) { + this.datetime = datetime; + } + + public String getDatetime() { + return datetime; + } + + public void setFrom(String from) { + this.from = from; + } + + public String getFrom() { + return from; + } + + public void setBodyShort(String bodyShort) { + this.bodyShort = bodyShort; + } + + public String getBodyShort() { + return bodyShort; + } + + public void setDatetimeISO(String datetimeISO) { + this.datetimeISO = datetimeISO; + } + + public String getDatetimeISO() { + return datetimeISO; + } + + public void setUser(User user) { + this.user = user; + } + + public User getUser() { + return user; + } + + @Override + public String toString() { + return + "Notification{" + + "read = '" + read + '\'' + + ",mergeId = '" + mergeId + '\'' + + ",importance = '" + importance + '\'' + + ",nid = '" + nid + '\'' + + ",type = '" + type + '\'' + + ",path = '" + path + '\'' + + ",readClass = '" + readClass + '\'' + + ",datetime = '" + datetime + '\'' + + ",from = '" + from + '\'' + + ",bodyShort = '" + bodyShort + '\'' + + ",datetimeISO = '" + datetimeISO + '\'' + + ",user = '" + user + '\'' + + "}"; + } +} diff --git a/app/src/main/java/com/stardust/scriptdroid/network/entity/notification/NotificationResponse.java b/app/src/main/java/com/stardust/scriptdroid/network/entity/notification/NotificationResponse.java new file mode 100644 index 00000000..e6463918 --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/network/entity/notification/NotificationResponse.java @@ -0,0 +1,25 @@ +package com.stardust.scriptdroid.network.entity.notification; + +import java.util.List; + +public class NotificationResponse { + + private List notifications; + + public void setNotifications(List notifications) { + this.notifications = notifications; + } + + public List getNotifications() { + return notifications; + } + + + @Override + public String toString() { + return + "NotificationResponse{" + + "notifications = '" + notifications + '\'' + + "}"; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java index 4611ac81..315e6b15 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/MainActivity.java @@ -62,6 +62,10 @@ import java.util.Arrays; @EActivity(R.layout.activity_main) public class MainActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHost, BackPressedHandler.HostActivity { + public static class DrawerOpenEvent { + static DrawerOpenEvent SINGLETON = new DrawerOpenEvent(); + } + private static final String LOG_TAG = "MainActivity"; @ViewById(R.id.drawer_layout) @@ -100,6 +104,12 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); registerBackPressHandlers(); ThemeColorManager.addViewBackground(findViewById(R.id.app_bar)); + mDrawerLayout.addDrawerListener(new DrawerLayout.SimpleDrawerListener() { + @Override + public void onDrawerOpened(View drawerView) { + EventBus.getDefault().post(DrawerOpenEvent.SINGLETON); + } + }); } private void showAnnunciationIfNeeded() { diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/CommunityDrawerMenu.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/CommunityDrawerMenu.java index c6cc4648..210eca24 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/CommunityDrawerMenu.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/CommunityDrawerMenu.java @@ -2,6 +2,7 @@ package com.stardust.scriptdroid.ui.main.drawer; import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.network.UserService; +import com.stardust.scriptdroid.network.entity.notification.Notification; import com.stardust.scriptdroid.ui.main.community.CommunityFragment; import org.greenrobot.eventbus.EventBus; @@ -10,7 +11,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import io.reactivex.Observable; +import io.reactivex.ObservableSource; import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Function; import io.reactivex.schedulers.Schedulers; /** @@ -21,10 +25,11 @@ public class CommunityDrawerMenu { private DrawerMenuItem mUnreadItem = new DrawerMenuItem(R.drawable.community_inbox, R.string.text_community_unread, this::showUnread); private DrawerMenuItem mLogoutItem = new DrawerMenuItem(R.drawable.ic_exit_to_app_black_24dp, R.string.text_logout, this::logout); - + private DrawerMenuItem mNotificationItem = new DrawerMenuItem(R.drawable.ic_ali_notification, R.string.text_notification, this::showNotifications); private List mDrawerMenuItems = new ArrayList<>(Arrays.asList( new DrawerMenuGroup(R.string.text_community), + mNotificationItem, new DrawerMenuItem(R.drawable.community_list, R.string.text_community_category, this::showCategories), mUnreadItem, new DrawerMenuItem(R.drawable.community_time, R.string.text_community_recent, this::showRecent), @@ -34,9 +39,11 @@ public class CommunityDrawerMenu { )); private boolean mShown = false; + private DrawerMenuAdapter mMenuAdapter; public void showCommunityMenu(DrawerMenuAdapter adapter) { + mMenuAdapter = adapter; mShown = true; List items = adapter.getDrawerMenuItems(); if (items.get(0) == mDrawerMenuItems.get(0)) { @@ -49,21 +56,44 @@ public class CommunityDrawerMenu { refreshUserStatus(adapter); } + private void refreshUserStatus(DrawerMenuAdapter adapter) { UserService.getInstance().refreshOnlineStatus() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(online -> setUserOnlineStatus(adapter, online)); + .subscribe(online -> { + setUserOnlineStatus(adapter, online); + if (online) { + refreshNotificationCount(adapter); + } + }); + + } + + public void refreshNotificationCount(DrawerMenuAdapter adapter) { + UserService.getInstance().getNotifications() + .flatMap(Observable::fromIterable) + .filter(n -> !n.isRead()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .count() + .subscribe(count -> setNotificationCount(adapter, count)); + } + + private void setNotificationCount(DrawerMenuAdapter adapter, long count) { + mNotificationItem.setNotificationCount((int) count); + adapter.notifyItemChanged(mNotificationItem); } public void setUserOnlineStatus(DrawerMenuAdapter adapter, boolean online) { if (online) { + addItem(adapter, R.string.text_community, mNotificationItem); addItem(adapter, R.string.text_community_category, mUnreadItem); addItem(adapter, R.string.text_community_tags, mLogoutItem); - } else { removeItem(adapter, R.string.text_community_unread); removeItem(adapter, R.string.text_logout); + removeItem(adapter, R.string.text_notification); } } @@ -80,6 +110,7 @@ public class CommunityDrawerMenu { break; } } + } private void removeItem(DrawerMenuAdapter adapter, int title) { @@ -94,6 +125,7 @@ public class CommunityDrawerMenu { } } + public void hideCommunityMenu(DrawerMenuAdapter adapter) { List items = adapter.getDrawerMenuItems(); mShown = false; @@ -111,6 +143,11 @@ public class CommunityDrawerMenu { } } + private void showNotifications(DrawerMenuItemViewHolder holder) { + EventBus.getDefault().post(new CommunityFragment.LoadUrl("/notifications")); + setNotificationCount(mMenuAdapter, 0); + } + private void showCategories(DrawerMenuItemViewHolder holder) { EventBus.getDefault().post(new CommunityFragment.LoadUrl("/categories")); } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerFragment.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerFragment.java index 90749cfb..454442df 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerFragment.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerFragment.java @@ -35,6 +35,7 @@ import com.stardust.scriptdroid.network.api.UserApi; import com.stardust.scriptdroid.network.entity.user.User; import com.stardust.scriptdroid.network.entity.VersionInfo; import com.stardust.scriptdroid.tool.SimpleObserver; +import com.stardust.scriptdroid.ui.main.MainActivity; import com.stardust.scriptdroid.ui.main.community.CommunityFragment; import com.stardust.scriptdroid.ui.user.LoginActivity_; import com.stardust.scriptdroid.ui.settings.SettingsActivity; @@ -403,6 +404,13 @@ public class DrawerFragment extends android.support.v4.app.Fragment { } + @Subscribe(threadMode = ThreadMode.MAIN) + public void onDrawerOpen(MainActivity.DrawerOpenEvent event) { + if (mCommunityDrawerMenu.isShown()) { + mCommunityDrawerMenu.refreshNotificationCount(mDrawerMenuAdapter); + } + } + private void showStableModePromptIfNeeded() { new NotAskAgainDialog.Builder(getContext(), "DrawerFragment.stable_mode") .title(R.string.text_stable_mode) diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerMenuItem.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerMenuItem.java index 9a9b9f4d..eeae49f8 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerMenuItem.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerMenuItem.java @@ -18,6 +18,7 @@ public class DrawerMenuItem { private Action mAction; private boolean mSwitchChecked; private boolean mOnProgress; + private int mNotificationCount; public DrawerMenuItem(int icon, int title, Action action) { mIcon = icon; @@ -36,6 +37,14 @@ public class DrawerMenuItem { mSwitchEnabled = true; } + public int getNotificationCount() { + return mNotificationCount; + } + + public void setNotificationCount(int notificationCount) { + mNotificationCount = notificationCount; + } + public int getIcon() { return mIcon; } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerMenuItemViewHolder.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerMenuItemViewHolder.java index 3207a1ee..0fbf9c8d 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerMenuItemViewHolder.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/drawer/DrawerMenuItemViewHolder.java @@ -37,6 +37,10 @@ public class DrawerMenuItemViewHolder extends BindableViewHolder @BindView(R.id.title) TextView mTitle; + + @BindView(R.id.notifications) + TextView mNotifications; + private boolean mAntiShake; private long mLastClickMillis; private DrawerMenuItem mDrawerMenuItem; @@ -62,6 +66,16 @@ public class DrawerMenuItemViewHolder extends BindableViewHolder mAntiShake = item.antiShake(); setSwitch(item); setProgress(item.isProgress()); + setNotifications(item.getNotificationCount()); + } + + private void setNotifications(int notificationCount) { + if (notificationCount == 0) { + mNotifications.setVisibility(View.GONE); + } else { + mNotifications.setVisibility(View.VISIBLE); + mNotifications.setText(String.valueOf(notificationCount)); + } } private void setSwitch(DrawerMenuItem item) { diff --git a/app/src/main/res/layout/drawer_menu_item.xml b/app/src/main/res/layout/drawer_menu_item.xml index 1c7a09ae..f655f3a2 100644 --- a/app/src/main/res/layout/drawer_menu_item.xml +++ b/app/src/main/res/layout/drawer_menu_item.xml @@ -1,15 +1,18 @@ - + - + + + android:visibility="gone" + tools:visibility="visible"/> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 394a67e6..66c32ed7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -349,4 +349,5 @@ 预览 字体大小: %d 正则表达式不能向前查找 + 通知