From a7b5d10d21f8d34e20e46cabd072ba617d4e9bdd Mon Sep 17 00:00:00 2001 From: fdx Date: Mon, 30 Jul 2018 16:01:42 +0800 Subject: [PATCH] 1. optimise login captcha display 2. refactor topic detail view code by divide all list to 2 lists. 3. remove diff for topic detail page --- app/build.gradle | 6 +- app/src/main/AndroidManifest.xml | 1 - app/src/main/java/im/fdx/v2ex/MyApp.kt | 20 ++- .../main/java/im/fdx/v2ex/model/BaseModel.kt | 5 +- .../main/java/im/fdx/v2ex/network/Parser.kt | 8 +- .../main/java/im/fdx/v2ex/ui/LoginActivity.kt | 2 + .../java/im/fdx/v2ex/ui/SettingsActivity.kt | 4 +- .../im/fdx/v2ex/ui/details/DetailsActivity.kt | 38 ++--- .../im/fdx/v2ex/ui/details/DetailsAdapter.kt | 134 ++++++++++-------- .../ui/details/{ReplyModel.kt => Reply.kt} | 18 +-- .../java/im/fdx/v2ex/ui/main/MainActivity.kt | 32 ++--- .../im/fdx/v2ex/ui/main/MyDiffCallback.kt | 12 +- .../java/im/fdx/v2ex/ui/node/NodeActivity.kt | 4 +- .../java/im/fdx/v2ex/utils/extensions/Hint.kt | 11 ++ app/src/main/java/im/fdx/v2ex/view/Popup.kt | 4 +- app/src/main/res/layout/activity_login.xml | 1 + app/src/main/res/layout/item_verify_code.xml | 11 +- build.gradle | 2 +- 18 files changed, 156 insertions(+), 157 deletions(-) rename app/src/main/java/im/fdx/v2ex/ui/details/{ReplyModel.kt => Reply.kt} (69%) diff --git a/app/build.gradle b/app/build.gradle index 12d0a1c8..20f0f9a3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,8 +12,8 @@ android { applicationId "im.fdx.v2ex" minSdkVersion 21 targetSdkVersion 28 - versionCode 24 - versionName "2.3.0" + versionCode 25 + versionName "2.3.2" } lintOptions { checkReleaseBuilds false @@ -23,7 +23,7 @@ android { googlePlay { Properties prop = getSignConfig() - if (prop != null&&false) { + if (prop != null) { keyAlias prop['keyAlias'] keyPassword prop['keyPassword'] storeFile file(prop['storeFile']) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ca70cafb..43e29e25 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -89,7 +89,6 @@ LogLevel.ALL else -> LogLevel.NONE diff --git a/app/src/main/java/im/fdx/v2ex/model/BaseModel.kt b/app/src/main/java/im/fdx/v2ex/model/BaseModel.kt index 4900e0c5..82a2efc8 100644 --- a/app/src/main/java/im/fdx/v2ex/model/BaseModel.kt +++ b/app/src/main/java/im/fdx/v2ex/model/BaseModel.kt @@ -5,6 +5,5 @@ import android.os.Parcelable /** * Created by fdx on 2017/3/18. */ -abstract class BaseModel : Parcelable { - -} +@Deprecated("没有用处") +abstract class BaseModel : Parcelable diff --git a/app/src/main/java/im/fdx/v2ex/network/Parser.kt b/app/src/main/java/im/fdx/v2ex/network/Parser.kt index ad878ad4..bad1ee6a 100644 --- a/app/src/main/java/im/fdx/v2ex/network/Parser.kt +++ b/app/src/main/java/im/fdx/v2ex/network/Parser.kt @@ -1,7 +1,7 @@ package im.fdx.v2ex.network import im.fdx.v2ex.model.NotificationModel -import im.fdx.v2ex.ui.details.ReplyModel +import im.fdx.v2ex.ui.details.Reply import im.fdx.v2ex.ui.main.Comment import im.fdx.v2ex.ui.main.Topic import im.fdx.v2ex.ui.member.Member @@ -256,9 +256,9 @@ class Parser(private val htmlStr: String) { return nodeModels } - fun getReplies(): ArrayList { + fun getReplies(): ArrayList { - val replyModels = ArrayList() + val replyModels = ArrayList() val items = doc.getElementsByAttributeValueStarting("id", "r_") for (item in items) { @@ -266,7 +266,7 @@ class Parser(private val htmlStr: String) { //
val id = item.id().substring(2) - val replyModel = ReplyModel() + val replyModel = Reply() val memberModel = Member() val avatar = item.getElementsByClass("avatar").attr("src") val username = item.getElementsByTag("strong").first().getElementsByAttributeValueStarting("href", "/member/").first().text() diff --git a/app/src/main/java/im/fdx/v2ex/ui/LoginActivity.kt b/app/src/main/java/im/fdx/v2ex/ui/LoginActivity.kt index 0fda6840..4ca879e2 100644 --- a/app/src/main/java/im/fdx/v2ex/ui/LoginActivity.kt +++ b/app/src/main/java/im/fdx/v2ex/ui/LoginActivity.kt @@ -21,6 +21,7 @@ import im.fdx.v2ex.network.NetManager.SIGN_IN_URL import im.fdx.v2ex.pref import im.fdx.v2ex.utils.Keys import im.fdx.v2ex.utils.extensions.logd +import im.fdx.v2ex.utils.extensions.setStatusBarColor import im.fdx.v2ex.utils.extensions.setUpToolbar import kotlinx.android.synthetic.main.activity_login.* import kotlinx.android.synthetic.main.item_verify_code.* @@ -51,6 +52,7 @@ class LoginActivity : BaseActivity() { setContentView(R.layout.activity_login) setUpToolbar() + setStatusBarColor(R.color.primary) progressBar = findViewById(R.id.pb_login) val usernamePref = pref.getString("username", "") diff --git a/app/src/main/java/im/fdx/v2ex/ui/SettingsActivity.kt b/app/src/main/java/im/fdx/v2ex/ui/SettingsActivity.kt index 0811f8d0..ede4c9c5 100644 --- a/app/src/main/java/im/fdx/v2ex/ui/SettingsActivity.kt +++ b/app/src/main/java/im/fdx/v2ex/ui/SettingsActivity.kt @@ -52,7 +52,7 @@ class SettingsActivity : AppCompatActivity() { sharedPreferences = PreferenceManager.getDefaultSharedPreferences(activity) jobSchedule = activity?.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler when { - MyApp.get().isLogin() -> { + MyApp.get().isLogin -> { addPreferencesFromResource(R.xml.preference_login) findPreference("group_user").title = sharedPreferences.getString("username", getString(R.string.user)) @@ -70,7 +70,7 @@ class SettingsActivity : AppCompatActivity() { activity!!.finish() activity!!.toast("已退出登录") } - .setNegativeButton(R.string.cancel) { dialogInterface, i -> + .setNegativeButton(R.string.cancel) { _, _ -> } .show() diff --git a/app/src/main/java/im/fdx/v2ex/ui/details/DetailsActivity.kt b/app/src/main/java/im/fdx/v2ex/ui/details/DetailsActivity.kt index 3b48e323..9ad812a9 100644 --- a/app/src/main/java/im/fdx/v2ex/ui/details/DetailsActivity.kt +++ b/app/src/main/java/im/fdx/v2ex/ui/details/DetailsActivity.kt @@ -22,7 +22,6 @@ import android.widget.TextView import com.elvishew.xlog.XLog import im.fdx.v2ex.MyApp import im.fdx.v2ex.R -import im.fdx.v2ex.model.BaseModel import im.fdx.v2ex.network.* import im.fdx.v2ex.network.NetManager.dealError import im.fdx.v2ex.ui.BaseActivity @@ -36,14 +35,11 @@ import kotlinx.android.synthetic.main.footer_reply.* import okhttp3.* import org.jetbrains.anko.share import org.jetbrains.anko.toast -import org.jsoup.nodes.Element import java.io.IOException -import java.util.regex.Pattern class DetailsActivity : BaseActivity() { private lateinit var mAdapter: DetailsAdapter - // private val mAllContent = mutableListOf() private var mMenu: Menu? = null private lateinit var tvToolbar: TextView @@ -80,7 +76,7 @@ class DetailsActivity : BaseActivity() { } else if (intent.action == "im.fdx.v2ex.reply") { logd("MSG_GET LocalBroadCast") token = intent.getStringExtra("token") - val rm = intent.getParcelableArrayListExtra("replies") + val rm = intent.getParcelableArrayListExtra("replies") mAdapter.addItems(rm) if (intent.getBooleanExtra("bottom", false)) { detail_recycler_view.scrollToPosition(mAdapter.itemCount - 1) @@ -112,7 +108,7 @@ class DetailsActivity : BaseActivity() { filter.addAction(Keys.ACTION_LOGOUT) filter.addAction("im.fdx.v2ex.reply") LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter) - setFootView(MyApp.get().isLogin()) + setFootView(MyApp.get().isLogin) setUpToolbar() tvToolbar = findViewById(R.id.tv_toolbar) @@ -121,7 +117,6 @@ class DetailsActivity : BaseActivity() { //// 这个Scroll 到顶部的bug,是focus的原因,focus会让系统自动滚动 val mLayoutManager = LinearLayoutManager(this) detail_recycler_view.layoutManager = mLayoutManager - detail_recycler_view.smoothScrollToPosition(POSITION_START) detail_recycler_view.addOnScrollListener(object : RecyclerView.OnScrollListener() { private var currentPosition = 0 @@ -166,7 +161,7 @@ class DetailsActivity : BaseActivity() { override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {} override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {} - override fun afterTextChanged(s: Editable) = if (s.isNullOrEmpty()) { + override fun afterTextChanged(s: Editable) = if (s.isEmpty()) { iv_send.isClickable = false iv_send.imageTintList = null } else { @@ -200,7 +195,7 @@ class DetailsActivity : BaseActivity() { data != null -> data.pathSegments[1] intent.getParcelableExtra("model") != null -> { val topicModel = intent.getParcelableExtra("model") - mAdapter.mAllList.add(0, topicModel) + mAdapter.topic[0] = topicModel mAdapter.notifyDataSetChanged() topicModel.id } @@ -244,7 +239,7 @@ class DetailsActivity : BaseActivity() { topicHeader = parser.parseResponseToTopic(topicId) val repliesFirstPage = parser.getReplies() - if (MyApp.get().isLogin()) { + if (MyApp.get().isLogin) { token = parser.getVerifyCode() if (token == null) { @@ -271,11 +266,6 @@ class DetailsActivity : BaseActivity() { once = parser.getOnceNum() } - val mAllContent = mutableListOf() - mAllContent.clear() - mAllContent.add(0, topicHeader!!) - mAllContent.addAll(repliesFirstPage) - XLog.tag("DetailsActivity").d("got page 1 , next is more page") val totalPage = parser.getPageValue()[1] // [2,3] @@ -283,7 +273,7 @@ class DetailsActivity : BaseActivity() { currentPage = parser.getPageValue()[0] runOnUiThread { swipe_details.isRefreshing = false - mAdapter.updateItems(mAllContent) + mAdapter.updateItems(topicHeader!!, repliesFirstPage) if (totalPage == 1 && scrollToBottom) { detail_recycler_view.scrollToPosition(mAdapter.itemCount - 1) } @@ -297,12 +287,6 @@ class DetailsActivity : BaseActivity() { }) } - private fun parseIsFavored(body: Element): Boolean { - val p = Pattern.compile("un(?=favorite/topic/\\d{1,10}\\?t=)") - val matcher = p.matcher(body.outerHtml()) - return matcher.find() - } - private fun getMoreRepliesByOrder(totalPage: Int, scrollToBottom: Boolean) { val intentGetMoreReply = Intent(this@DetailsActivity, MoreReplyService::class.java) intentGetMoreReply.action = "im.fdx.v2ex.get.other.more" @@ -310,7 +294,7 @@ class DetailsActivity : BaseActivity() { intentGetMoreReply.putExtra("topic_id", mTopicId) intentGetMoreReply.putExtra("bottom", scrollToBottom) startService(intentGetMoreReply) - XLog.tag("DetailsActivity").d("yes I startIntentService") + logd("yes I startIntentService") } @@ -328,7 +312,7 @@ class DetailsActivity : BaseActivity() { override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.menu_details, menu) - if (MyApp.get().isLogin()) { + if (MyApp.get().isLogin) { menu.findItem(R.id.menu_favor).isVisible = true menu.findItem(R.id.menu_reply)?.isVisible = true } else { @@ -354,11 +338,11 @@ class DetailsActivity : BaseActivity() { swipe_details.isRefreshing = true getRepliesPageOne(mTopicId, false) } - R.id.menu_item_share -> share("来自V2EX的帖子:${(mAdapter.mAllList[0] as Topic).title} \n" + - " ${NetManager.HTTPS_V2EX_BASE}/t/${(mAdapter.mAllList[0] as Topic).id}") + R.id.menu_item_share -> share("来自V2EX的帖子:${(mAdapter.topic[0]).title} \n" + + " ${NetManager.HTTPS_V2EX_BASE}/t/${mAdapter.topic[0].id}") R.id.menu_item_open_in_browser -> { - val topicId = (mAdapter.mAllList[0] as Topic).id + val topicId = mAdapter.topic[0].id val url = NetManager.HTTPS_V2EX_BASE + "/t/" + topicId val uri = Uri.parse(url) val intent = Intent(Intent.ACTION_VIEW, uri) diff --git a/app/src/main/java/im/fdx/v2ex/ui/details/DetailsAdapter.kt b/app/src/main/java/im/fdx/v2ex/ui/details/DetailsAdapter.kt index 993bbbe6..86968569 100644 --- a/app/src/main/java/im/fdx/v2ex/ui/details/DetailsAdapter.kt +++ b/app/src/main/java/im/fdx/v2ex/ui/details/DetailsAdapter.kt @@ -6,13 +6,11 @@ import android.content.ClipData import android.content.ClipboardManager import android.content.Context import android.support.v4.content.ContextCompat -import android.support.v7.util.DiffUtil import android.support.v7.widget.RecyclerView import android.text.Spannable import android.text.SpannableString import android.text.style.ForegroundColorSpan import android.view.LayoutInflater -import android.view.MenuItem import android.view.View import android.view.ViewGroup import android.view.inputmethod.InputMethodManager @@ -22,10 +20,9 @@ import android.widget.TextView import com.elvishew.xlog.XLog import im.fdx.v2ex.MyApp import im.fdx.v2ex.R -import im.fdx.v2ex.model.BaseModel import im.fdx.v2ex.network.HttpHelper import im.fdx.v2ex.network.NetManager -import im.fdx.v2ex.ui.main.MyDiffCallback +import im.fdx.v2ex.pref import im.fdx.v2ex.ui.main.Topic import im.fdx.v2ex.ui.main.TopicsRVAdapter import im.fdx.v2ex.ui.member.MemberActivity @@ -34,6 +31,7 @@ import im.fdx.v2ex.utils.TimeUtil import im.fdx.v2ex.utils.extensions.getPair import im.fdx.v2ex.utils.extensions.load import im.fdx.v2ex.utils.extensions.logd +import im.fdx.v2ex.utils.extensions.showLoginHint import im.fdx.v2ex.view.GoodTextView import im.fdx.v2ex.view.Popup import kotlinx.android.extensions.LayoutContainer @@ -49,10 +47,14 @@ import java.io.IOException * todo 把 allList 分离 */ class DetailsAdapter(private val mContext: Context, - private val callback: DetailsAdapter.AdapterCallback, - val mAllList: MutableList = mutableListOf()) - : RecyclerView.Adapter() { - internal var verifyCode: String? = null + private val callback: DetailsAdapter.AdapterCallback +) : RecyclerView.Adapter() { + + var verifyCode: String? = null + + val topic: MutableList = MutableList(1) { Topic() } + val replies: MutableList = mutableListOf() + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder = when (viewType) { @@ -67,9 +69,9 @@ class DetailsAdapter(private val mContext: Context, when (getItemViewType(position)) { TYPE_HEADER -> { + val topic = this.topic[0] val mainHolder = holder as TopicWithCommentsViewHolder - val topic = mAllList[position] as Topic mainHolder.tvTitle.text = topic.title mainHolder.tvTitle.maxLines = 4 mainHolder.tvContent.isSelected = true @@ -111,37 +113,38 @@ class DetailsAdapter(private val mContext: Context, } TYPE_ITEM -> { val itemVH = holder as ItemViewHolder - val replyItem = mAllList[position] as ReplyModel - replyItem.isLouzu = replyItem.member?.username == (mAllList[0] as Topic).member?.username + val replyItem = replies[position - topic.size] + replyItem.isLouzu = replyItem.member?.username == (topic[0]).member?.username if (position == itemCount - 1) { itemVH.divider.visibility = View.GONE } - if (MyApp.get().isLogin()) { - (mContext as Activity).registerForContextMenu(itemVH.itemView) - itemVH.itemView.setOnCreateContextMenuListener { menu, _, _ -> - val menuInflater = mContext.menuInflater - menuInflater.inflate(R.menu.menu_reply, menu) + (mContext as Activity).registerForContextMenu(itemVH.itemView) - val menuListener = MenuItem.OnMenuItemClickListener { item -> - when (item.itemId) { - R.id.menu_reply -> reply(replyItem, position) - R.id.menu_thank -> thank(replyItem, itemVH) - R.id.menu_copy -> copyText(replyItem) - } - false - } + itemVH.itemView.setOnCreateContextMenuListener { menu, _, _ -> + val menuInflater = mContext.menuInflater + menuInflater.inflate(R.menu.menu_reply, menu) - menu.findItem(R.id.menu_reply).setOnMenuItemClickListener(menuListener) - menu.findItem(R.id.menu_thank).setOnMenuItemClickListener(menuListener) - menu.findItem(R.id.menu_copy).setOnMenuItemClickListener(menuListener) + menu.findItem(R.id.menu_reply).setOnMenuItemClickListener { + reply(replyItem, position) + true + } + menu.findItem(R.id.menu_thank).setOnMenuItemClickListener { + thank(replyItem, itemVH) + true + } + menu.findItem(R.id.menu_copy).setOnMenuItemClickListener { + copyText(replyItem.content) + true } - itemVH.iv_thanks.setOnClickListener { thank(replyItem, itemVH) } - itemVH.tv_thanks.setOnClickListener { thank(replyItem, itemVH) } - itemVH.iv_reply.setOnClickListener { reply(replyItem, position) } } + itemVH.iv_thanks.setOnClickListener { thank(replyItem, itemVH) } + itemVH.tv_thanks.setOnClickListener { thank(replyItem, itemVH) } + itemVH.iv_reply.setOnClickListener { reply(replyItem, position) } + + XLog.i(replyItem.content_rendered) itemVH.tv_reply_time.text = TimeUtil.getRelativeTime(replyItem.created) itemVH.tv_replier.text = replyItem.member?.username @@ -152,7 +155,7 @@ class DetailsAdapter(private val mContext: Context, itemVH.iv_reply_avatar.setOnClickListener { mContext.startActivity(Keys.KEY_USERNAME to replyItem.member!!.username) } - if (replyItem.member?.username == (mAllList[0] as Topic).member?.username) { + if (replyItem.member?.username == topic[0].member?.username) { itemVH.tv_louzu.visibility = View.VISIBLE } else { itemVH.tv_louzu.visibility = View.GONE @@ -171,16 +174,16 @@ class DetailsAdapter(private val mContext: Context, val username = url.split("/").last() var index = replyItem.content.getPair(username) if (index <= 0 || index > position) { //5 - mAllList.forEachIndexed { i, baseModel -> - if (i in 1 until position && (baseModel as ReplyModel).member?.username == username) { - index = i + replies.forEachIndexed { i, r -> + if (i in 0 until position && r.member?.username == username) { + index = i + 1 } } } if (index <= 0 || index > position) { return } - Popup(mContext).show(v, mAllList[index] as ReplyModel, index, View.OnClickListener { + Popup(mContext).show(v, replies[index], index, View.OnClickListener { callback.onMethodCallback(-1, index) }) } @@ -190,14 +193,22 @@ class DetailsAdapter(private val mContext: Context, } } - private fun copyText(replyItem: ReplyModel) { - XLog.d("I click menu copy") + private fun copyText(content: String) { + logd("I click menu copy") val manager = mContext.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - manager.primaryClip = ClipData.newPlainText("item", replyItem.content) + manager.primaryClip = ClipData.newPlainText("item", content) + mContext.toast("评论已复制") } - private fun thank(replyItem: ReplyModel, itemVH: ItemViewHolder): Boolean { - XLog.tag(TAG).d("hehe" + verifyCode) + private fun thank(replyItem: Reply, itemVH: ItemViewHolder): Boolean { + logd("token: $verifyCode") + + val editText: EditText = (mContext as Activity).findViewById(R.id.et_post_reply) + if (!MyApp.get().isLogin) { + mContext.showLoginHint(editText) + return false + } + if (verifyCode == null) { return true } @@ -215,7 +226,7 @@ class DetailsAdapter(private val mContext: Context, override fun onResponse(call: Call, response: Response) { if (response.code() == 200) { - (mContext as Activity).runOnUiThread { + mContext.runOnUiThread { mContext.toast("感谢成功") replyItem.thanks = replyItem.thanks + 1 itemVH.tv_thanks.text = (replyItem.thanks).toString() @@ -232,10 +243,16 @@ class DetailsAdapter(private val mContext: Context, return false } - private fun reply(replyItem: ReplyModel, position: Int) { + private fun reply(replyItem: Reply, position: Int) { + val editText: EditText = (mContext as Activity).findViewById(R.id.et_post_reply) + if (!MyApp.get().isLogin) { + mContext.showLoginHint(editText) + return + } + val text = "@${replyItem.member!!.username} " + - if (MyApp.get().mPrefs.getBoolean("pref_add_row", false)) "#$position " else "" + if (pref.getBoolean("pref_add_row", false)) "#$position " else "" if (!editText.text.toString().contains(text)) { val spanString = SpannableString(text) val span = ForegroundColorSpan(ContextCompat.getColor(mContext, R.color.primary)) @@ -248,7 +265,7 @@ class DetailsAdapter(private val mContext: Context, imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT) } - override fun getItemCount() = mAllList.size + 1 + override fun getItemCount() = topic.size + replies.size + 1 override fun getItemViewType(position: Int) = when { position == 0 && itemCount > 1 -> TYPE_HEADER @@ -256,30 +273,22 @@ class DetailsAdapter(private val mContext: Context, else -> TYPE_ITEM } - fun updateItems(newItems: List) { - if (mAllList.isEmpty()) { - mAllList.addAll(newItems) - notifyDataSetChanged() - } else { - val diffResult = DiffUtil.calculateDiff(MyDiffCallback(mAllList, newItems)) - mAllList.clear() - mAllList.addAll(newItems) - diffResult.dispatchUpdatesTo(this) - } + fun updateItems(topics: Topic, replies: List) { + this.topic.clear() + this.replies.clear() + this.topic.add(topics) + this.replies.addAll(replies) + notifyDataSetChanged() } - fun addItems(newItems: List) { - val old = mAllList.toList() - mAllList.addAll(newItems) - val diffResult = DiffUtil.calculateDiff(MyDiffCallback(old, mAllList)) - diffResult.dispatchUpdatesTo(this) + fun addItems(replies: List) { + this.replies.addAll(replies) + notifyDataSetChanged() } //我重用了MainAdapter中的MainViewHolder - class ItemViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView), LayoutContainer { - - } + class ItemViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView), LayoutContainer class TopicWithCommentsViewHolder(itemView: View) : TopicsRVAdapter.MainViewHolder(itemView) { internal var ll: LinearLayout = itemView.findViewById(R.id.ll_comments) @@ -301,7 +310,6 @@ class DetailsAdapter(private val mContext: Context, } companion object { - private val TAG = DetailsAdapter::class.java.simpleName private const val TYPE_HEADER = 0 private const val TYPE_ITEM = 1 private const val TYPE_FOOTER = 2 diff --git a/app/src/main/java/im/fdx/v2ex/ui/details/ReplyModel.kt b/app/src/main/java/im/fdx/v2ex/ui/details/Reply.kt similarity index 69% rename from app/src/main/java/im/fdx/v2ex/ui/details/ReplyModel.kt rename to app/src/main/java/im/fdx/v2ex/ui/details/Reply.kt index dc163648..b6d61b6b 100644 --- a/app/src/main/java/im/fdx/v2ex/ui/details/ReplyModel.kt +++ b/app/src/main/java/im/fdx/v2ex/ui/details/Reply.kt @@ -29,15 +29,15 @@ import kotlinx.android.parcel.Parcelize // } @Parcelize -data class ReplyModel(var id: String = "", - var content: String = "", - var content_rendered: String = "", - var thanks: Int = 0, - var created: Long = 0, - var isThanked: Boolean = false, - var member: Member? = null, - var isLouzu: Boolean = false +data class Reply(var id: String = "", + var content: String = "", + var content_rendered: String = "", + var thanks: Int = 0, + var created: Long = 0, + var isThanked: Boolean = false, + var member: Member? = null, + var isLouzu: Boolean = false ) : BaseModel(), Parcelable { - override fun toString() = "ReplyModel{content='$content_rendered}" + override fun toString() = "Reply{content='$content_rendered}" } diff --git a/app/src/main/java/im/fdx/v2ex/ui/main/MainActivity.kt b/app/src/main/java/im/fdx/v2ex/ui/main/MainActivity.kt index 88a86ef9..76503d5b 100644 --- a/app/src/main/java/im/fdx/v2ex/ui/main/MainActivity.kt +++ b/app/src/main/java/im/fdx/v2ex/ui/main/MainActivity.kt @@ -12,7 +12,6 @@ import android.graphics.Color import android.graphics.drawable.Icon import android.os.Build import android.os.Bundle -import android.preference.PreferenceManager import android.support.design.widget.FloatingActionButton import android.support.design.widget.NavigationView import android.support.design.widget.TabLayout @@ -38,6 +37,7 @@ import im.fdx.v2ex.network.NetManager.DAILY_CHECK import im.fdx.v2ex.network.NetManager.HTTPS_V2EX_BASE import im.fdx.v2ex.network.Parser import im.fdx.v2ex.network.vCall +import im.fdx.v2ex.pref import im.fdx.v2ex.ui.* import im.fdx.v2ex.ui.favor.FavorActivity import im.fdx.v2ex.ui.member.MemberActivity @@ -56,7 +56,6 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList private lateinit var mDrawer: DrawerLayout private lateinit var navigationView: NavigationView - private lateinit var sharedPreferences: SharedPreferences private lateinit var mViewPager: ViewPager private lateinit var fab: FloatingActionButton @@ -86,7 +85,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList mAdapter?.initFragment() mAdapter?.notifyDataSetChanged() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { - shortcutManager?.addDynamicShortcuts(listOfNotNull(createTopicInfo)) + shortcutManager?.addDynamicShortcuts(listOfNotNull(createTopicInfo)) } } Keys.ACTION_LOGOUT -> { @@ -150,23 +149,22 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList fab.setOnClickListener { startActivity(Intent(this@MainActivity, NewTopicActivity::class.java)) } val ivMode = navigationView.getHeaderView(0).findViewById(R.id.iv_night_mode) - sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) ivMode.setOnClickListener { - if (sharedPreferences.getBoolean("NIGHT_MODE", false)) { + if (pref.getBoolean("NIGHT_MODE", false)) { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) - sharedPreferences.edit().putBoolean("NIGHT_MODE", false).apply() + pref.edit().putBoolean("NIGHT_MODE", false).apply() recreate() } else { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) - sharedPreferences.edit().putBoolean("NIGHT_MODE", true).apply() + pref.edit().putBoolean("NIGHT_MODE", true).apply() recreate() } } - if (MyApp.get().isLogin()) { + if (MyApp.get().isLogin) { showNavIcon(true) - val username = sharedPreferences.getString(Keys.KEY_USERNAME, "") - val avatar = sharedPreferences.getString(Keys.KEY_AVATAR, "") + val username = pref.getString(Keys.KEY_USERNAME, "") + val avatar = pref.getString(Keys.KEY_AVATAR, "") logd("$username//// $avatar") if (!username.isNullOrEmpty() && !avatar.isNullOrEmpty()) { setUserInfo(username, avatar) @@ -214,26 +212,26 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList .setIcon(Icon.createWithResource(this, R.drawable.ic_shortcut_create)) .build() when { - MyApp.get().isLogin() -> shortcutManager?.addDynamicShortcuts(listOfNotNull(createTopicInfo)) + MyApp.get().isLogin -> shortcutManager?.addDynamicShortcuts(listOfNotNull(createTopicInfo)) else -> shortcutManager?.removeDynamicShortcuts(shortcutIds) } } } private fun startGetNotification() { - if (MyApp.get().isLogin() && isOpenMessage) { + if (MyApp.get().isLogin && isOpenMessage) { val mJobScheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler val builder = JobInfo.Builder(JOB_ID_GET_NOTIFICATION, ComponentName(MyApp.get().packageName, MyJobSchedule::class.java.name)) - val timeSec = sharedPreferences.getString("pref_msg_period", "30").toInt() + val timeSec = pref.getString("pref_msg_period", "30").toInt() builder.setPeriodic((timeSec * 1000).toLong()) mJobScheduler.schedule(builder.build()) } } private fun stopGetNotification() { - if (MyApp.get().isLogin() && isOpenMessage && !isBackground) { + if (MyApp.get().isLogin && isOpenMessage && !isBackground) { val mJobScheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler mJobScheduler.cancel(JOB_ID_GET_NOTIFICATION) } @@ -279,7 +277,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList override fun onPrepareOptionsMenu(menu: Menu): Boolean { - if (MyApp.get().isLogin()) { + if (MyApp.get().isLogin) { menu.findItem(R.id.menu_login).isVisible = false menu.findItem(R.id.menu_notification).isVisible = true } else { @@ -417,9 +415,9 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList } private val isBackground: Boolean - get() = sharedPreferences.getBoolean("pref_background_msg", false) + get() = pref.getBoolean("pref_background_msg", false) private val isOpenMessage: Boolean - get() = sharedPreferences.getBoolean("pref_msg", true) + get() = pref.getBoolean("pref_msg", true) } diff --git a/app/src/main/java/im/fdx/v2ex/ui/main/MyDiffCallback.kt b/app/src/main/java/im/fdx/v2ex/ui/main/MyDiffCallback.kt index 40717f8b..f7cdb038 100644 --- a/app/src/main/java/im/fdx/v2ex/ui/main/MyDiffCallback.kt +++ b/app/src/main/java/im/fdx/v2ex/ui/main/MyDiffCallback.kt @@ -2,7 +2,7 @@ package im.fdx.v2ex.ui.main import android.support.v7.util.DiffUtil import im.fdx.v2ex.model.BaseModel -import im.fdx.v2ex.ui.details.ReplyModel +import im.fdx.v2ex.ui.details.Reply /** * Created by fdx on 2017/7/11. @@ -14,8 +14,8 @@ class MyDiffCallback(private val oldList: List, private val newList: if (oldList[oldItemPosition] is Topic && newList[newItemPosition] is Topic) { return (oldList[oldItemPosition] as Topic).id == (newList[newItemPosition] as Topic).id - } else if (oldList[oldItemPosition] is ReplyModel && newList[newItemPosition] is ReplyModel) - return (oldList[oldItemPosition] as ReplyModel).id == (newList[newItemPosition] as ReplyModel).id + } else if (oldList[oldItemPosition] is Reply && newList[newItemPosition] is Reply) + return (oldList[oldItemPosition] as Reply).id == (newList[newItemPosition] as Reply).id else return false } @@ -30,9 +30,9 @@ class MyDiffCallback(private val oldList: List, private val newList: if (oldList[oldItemPosition] is Topic && newList[newItemPosition] is Topic) { return (oldList[oldItemPosition] as Topic).replies == (newList[newItemPosition] as Topic).replies && (oldList[oldItemPosition] as Topic).content_rendered == (newList[newItemPosition] as Topic).content_rendered - } else if (oldList[oldItemPosition] is ReplyModel && newList[newItemPosition] is ReplyModel) - return (oldList[oldItemPosition] as ReplyModel).thanks == (newList[newItemPosition] as ReplyModel).thanks && - (oldList[oldItemPosition] as ReplyModel).isThanked == (newList[newItemPosition] as ReplyModel).isThanked + } else if (oldList[oldItemPosition] is Reply && newList[newItemPosition] is Reply) + return (oldList[oldItemPosition] as Reply).thanks == (newList[newItemPosition] as Reply).thanks && + (oldList[oldItemPosition] as Reply).isThanked == (newList[newItemPosition] as Reply).isThanked else return false } diff --git a/app/src/main/java/im/fdx/v2ex/ui/node/NodeActivity.kt b/app/src/main/java/im/fdx/v2ex/ui/node/NodeActivity.kt index de49d747..5edffa2b 100644 --- a/app/src/main/java/im/fdx/v2ex/ui/node/NodeActivity.kt +++ b/app/src/main/java/im/fdx/v2ex/ui/node/NodeActivity.kt @@ -91,7 +91,7 @@ class NodeActivity : BaseActivity() { fab_node.setOnClickListener { startActivity(Keys.KEY_NODE_NAME to nodeName) } - if (!MyApp.get().isLogin()) fab_node.hide() + if (!MyApp.get().isLogin) fab_node.hide() nodeName = when { intent.data != null -> intent.data.pathSegments[1] @@ -110,7 +110,7 @@ class NodeActivity : BaseActivity() { override fun onCreateOptionsMenu(menu: Menu?): Boolean { menuInflater.inflate(R.menu.menu_node, menu) mMenu = menu!! - if (!MyApp.get().isLogin()) { + if (!MyApp.get().isLogin) { menu.findItem(R.id.menu_follow)?.isVisible = false } return true diff --git a/app/src/main/java/im/fdx/v2ex/utils/extensions/Hint.kt b/app/src/main/java/im/fdx/v2ex/utils/extensions/Hint.kt index 9a385859..5bbab5bf 100644 --- a/app/src/main/java/im/fdx/v2ex/utils/extensions/Hint.kt +++ b/app/src/main/java/im/fdx/v2ex/utils/extensions/Hint.kt @@ -2,9 +2,13 @@ package im.fdx.v2ex.utils.extensions import android.app.Activity import android.content.Context +import android.support.design.widget.Snackbar import android.support.v4.widget.SwipeRefreshLayout +import android.view.View import com.elvishew.xlog.XLog import im.fdx.v2ex.R +import im.fdx.v2ex.ui.LoginActivity +import org.jetbrains.anko.startActivity import org.jetbrains.anko.toast /** @@ -45,4 +49,11 @@ fun Any.logw(msg: Any?) { fun Any.loge(msg: Any?) { XLog.tag("v+" + this::class.java.simpleName).e(msg) +} + + +fun Activity.showLoginHint(view: View) { + Snackbar.make(view, "您还未登录,请登录后再试", Snackbar.LENGTH_LONG).setAction("登录") { + startActivity() + }.show() } \ No newline at end of file diff --git a/app/src/main/java/im/fdx/v2ex/view/Popup.kt b/app/src/main/java/im/fdx/v2ex/view/Popup.kt index 4db04e92..da114d96 100644 --- a/app/src/main/java/im/fdx/v2ex/view/Popup.kt +++ b/app/src/main/java/im/fdx/v2ex/view/Popup.kt @@ -11,7 +11,7 @@ import android.view.ViewGroup import android.widget.PopupWindow import im.fdx.v2ex.R import im.fdx.v2ex.ui.details.DetailsAdapter -import im.fdx.v2ex.ui.details.ReplyModel +import im.fdx.v2ex.ui.details.Reply import im.fdx.v2ex.utils.TimeUtil import im.fdx.v2ex.utils.extensions.load import kotlinx.android.synthetic.main.item_reply_view.* @@ -34,7 +34,7 @@ class Popup(mActivity: Context) { @SuppressLint("SetTextI18n") - fun show(v: View, data: ReplyModel, position: Int, clickListener: View.OnClickListener) { + fun show(v: View, data: Reply, position: Int, clickListener: View.OnClickListener) { popupWindow.width = v.width val hd = DetailsAdapter.ItemViewHolder(contentView) diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 122971b2..23333c94 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -12,6 +12,7 @@ android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="@style/AppTheme.AppBarOverlay" + app:titleTextColor="@color/white" app:contentInsetStartWithNavigation="0dp" app:popupTheme="@style/AppTheme.PopupOverlay"> diff --git a/app/src/main/res/layout/item_verify_code.xml b/app/src/main/res/layout/item_verify_code.xml index 4a8cef5f..4e7fdcde 100644 --- a/app/src/main/res/layout/item_verify_code.xml +++ b/app/src/main/res/layout/item_verify_code.xml @@ -8,12 +8,10 @@ android:layout_marginBottom="@dimen/margin_between_log_in_item" android:layout_marginTop="@dimen/margin_between_log_in_item"> - + android:textColor="@color/white" /> + tools:background="@color/black54" />