diff --git a/app/src/main/java/com/kidozh/discuzhub/activities/ForumActivity.java b/app/src/main/java/com/kidozh/discuzhub/activities/ForumActivity.java index 93e27517..30671d7b 100644 --- a/app/src/main/java/com/kidozh/discuzhub/activities/ForumActivity.java +++ b/app/src/main/java/com/kidozh/discuzhub/activities/ForumActivity.java @@ -144,8 +144,9 @@ private void configureIntentData(){ private void bindViewModel(){ forumViewModel.totalThreadListMutableLiveData.observe(this, it->{ Map threadTypeMap = null; - if(forumViewModel.displayForumResultMutableLiveData.getValue()!=null){ - threadTypeMap = forumViewModel.displayForumResultMutableLiveData.getValue().forumVariables.threadTypeInfo.idNameMap; + if(forumViewModel.displayForumResultMutableLiveData.getValue()!=null && + forumViewModel.displayForumResultMutableLiveData.getValue().forumVariables.getThreadTypeInfo()!=null){ + threadTypeMap = forumViewModel.displayForumResultMutableLiveData.getValue().forumVariables.getThreadTypeInfo().idNameMap; } adapter.updateListAndType(it, threadTypeMap); @@ -377,9 +378,9 @@ public void onClick(View v) { intent.putExtra(ConstUtils.PASS_BBS_USER_KEY, user); intent.putExtra(ConstUtils.PASS_POST_TYPE, ConstUtils.TYPE_POST_THREAD); if(forumViewModel.displayForumResultMutableLiveData - .getValue().forumVariables.threadTypeInfo != null){ + .getValue().forumVariables.getThreadTypeInfo() != null){ intent.putExtra(ConstUtils.PASS_THREAD_CATEGORY_KEY, (Serializable) forumViewModel.displayForumResultMutableLiveData - .getValue().forumVariables.threadTypeInfo.idNameMap); + .getValue().forumVariables.getThreadTypeInfo().idNameMap); } diff --git a/app/src/main/java/com/kidozh/discuzhub/activities/PublishActivity.java b/app/src/main/java/com/kidozh/discuzhub/activities/PublishActivity.java index 13be34e2..70e70ddf 100644 --- a/app/src/main/java/com/kidozh/discuzhub/activities/PublishActivity.java +++ b/app/src/main/java/com/kidozh/discuzhub/activities/PublishActivity.java @@ -1342,7 +1342,8 @@ protected void onPreExecute() { builder.url(URLUtils.getPostThreadUrl(fid)); } else { - int fidInt = Integer.parseInt(fid); + // int fidInt = Integer.parseInt(fid); + int fidInt = 0; builder.url(URLUtils.getReplyThreadUrl(fidInt,tid)); } diff --git a/app/src/main/java/com/kidozh/discuzhub/activities/ThreadActivity.kt b/app/src/main/java/com/kidozh/discuzhub/activities/ThreadActivity.kt index 7f4aa997..2be412ed 100644 --- a/app/src/main/java/com/kidozh/discuzhub/activities/ThreadActivity.kt +++ b/app/src/main/java/com/kidozh/discuzhub/activities/ThreadActivity.kt @@ -490,9 +490,12 @@ class ThreadActivity : BaseStatusActivity(), OnSmileyPressedInteraction, onFilte //Log.d(TAG,"Thread post result error "+ threadResult.isError()+" "+ threadResult.threadPostVariables.message); val rewriteRule = threadResult.threadPostVariables.rewriteRule - getAndSaveRewriteRule(rewriteRule, UserPreferenceUtils.REWRITE_FORM_DISPLAY_KEY) - getAndSaveRewriteRule(rewriteRule, UserPreferenceUtils.REWRITE_VIEW_THREAD_KEY) - getAndSaveRewriteRule(rewriteRule, UserPreferenceUtils.REWRITE_HOME_SPACE) + if(rewriteRule != null){ + getAndSaveRewriteRule(rewriteRule, UserPreferenceUtils.REWRITE_FORM_DISPLAY_KEY) + getAndSaveRewriteRule(rewriteRule, UserPreferenceUtils.REWRITE_VIEW_THREAD_KEY) + getAndSaveRewriteRule(rewriteRule, UserPreferenceUtils.REWRITE_HOME_SPACE) + } + } }) @@ -698,7 +701,7 @@ class ThreadActivity : BaseStatusActivity(), OnSmileyPressedInteraction, onFilte binding.bbsThreadDetailCommentButton.setOnClickListener(View.OnClickListener { val commentMessage = binding.bbsThreadDetailCommentEditText.text.toString() val captchaString = binding.bbsPostCaptchaEditText.text.toString() - if (needCaptcha() && captchaString.length == 0) { + if (needCaptcha() && captchaString.isEmpty()) { Toasty.warning(applicationContext, getString(R.string.captcha_required), Toast.LENGTH_SHORT).show() return@OnClickListener } @@ -751,9 +754,8 @@ class ThreadActivity : BaseStatusActivity(), OnSmileyPressedInteraction, onFilte Log.d(TAG, "Press string $decodeStr") } - override fun replyToSomeOne(position: Int) { - - val threadCommentInfo = postAdapter.getPosts()[position] + override fun replyToSomeOne(post: Post) { + val threadCommentInfo = post selectedThreadComment = threadCommentInfo binding.bbsThreadDetailReplyChip.text = threadCommentInfo.author binding.bbsThreadDetailReplyChip.visibility = View.VISIBLE @@ -935,124 +937,130 @@ class ThreadActivity : BaseStatusActivity(), OnSmileyPressedInteraction, onFilte // only catch two type : forum_forumdisplay & forum_viewthread // only 8.0+ support reverse copy if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - if (rewriteRules.containsKey("forum_forumdisplay")) { - var rewriteRule = rewriteRules["forum_forumdisplay"] - UserPreferenceUtils.saveRewriteRule(context, discuz, UserPreferenceUtils.REWRITE_FORM_DISPLAY_KEY, rewriteRule) - if (rewriteRule == null || clickedURLPath == null) { - parseURLAndOpen(unescapedURL) - return - } - // match template such as f{fid}-{page} - // crate reverse copy - rewriteRule = rewriteRule.replace("{fid}", "(?\\d+)") - rewriteRule = rewriteRule.replace("{page}", "(?\\d+)") - val pattern = Pattern.compile(rewriteRule) - val matcher = pattern.matcher(clickedURLPath) - if (matcher.find()) { - val fidStr = matcher.group("fid") - val pageStr = matcher.group("page") - // handle it - if (fidStr != null) { - var fid = 0 - fid = try { - fidStr.toInt() - } catch (e: Exception) { - 0 - } - -// int page = Integer.parseInt(pageStr); - val intent = Intent(context, ForumActivity::class.java) - val clickedForum = Forum() - clickedForum.fid = fid - intent.putExtra(ConstUtils.PASS_FORUM_THREAD_KEY, clickedForum) - intent.putExtra(ConstUtils.PASS_BBS_ENTITY_KEY, discuz) - intent.putExtra(ConstUtils.PASS_BBS_USER_KEY, user) - Log.d(TAG, "put base url " + discuz.base_url) - VibrateUtils.vibrateForClick(context) - context.startActivity(intent) + if (rewriteRules != null) { + if (rewriteRules.containsKey("forum_forumdisplay")) { + var rewriteRule = rewriteRules["forum_forumdisplay"] + UserPreferenceUtils.saveRewriteRule(context, discuz, UserPreferenceUtils.REWRITE_FORM_DISPLAY_KEY, rewriteRule) + if (rewriteRule == null || clickedURLPath == null) { + parseURLAndOpen(unescapedURL) return } + // match template such as f{fid}-{page} + // crate reverse copy + rewriteRule = rewriteRule.replace("{fid}", "(?\\d+)") + rewriteRule = rewriteRule.replace("{page}", "(?\\d+)") + val pattern = Pattern.compile(rewriteRule) + val matcher = pattern.matcher(clickedURLPath) + if (matcher.find()) { + val fidStr = matcher.group("fid") + val pageStr = matcher.group("page") + // handle it + if (fidStr != null) { + var fid = 0 + fid = try { + fidStr.toInt() + } catch (e: Exception) { + 0 + } + + // int page = Integer.parseInt(pageStr); + val intent = Intent(context, ForumActivity::class.java) + val clickedForum = Forum() + clickedForum.fid = fid + intent.putExtra(ConstUtils.PASS_FORUM_THREAD_KEY, clickedForum) + intent.putExtra(ConstUtils.PASS_BBS_ENTITY_KEY, discuz) + intent.putExtra(ConstUtils.PASS_BBS_USER_KEY, user) + Log.d(TAG, "put base url " + discuz.base_url) + VibrateUtils.vibrateForClick(context) + context.startActivity(intent) + return + } + } } } - if (rewriteRules.containsKey("forum_viewthread")) { - // match template such as t{tid}-{page}-{prevpage} - var rewriteRule = rewriteRules["forum_viewthread"] - UserPreferenceUtils.saveRewriteRule(context, discuz, UserPreferenceUtils.REWRITE_VIEW_THREAD_KEY, rewriteRule) - if (rewriteRule == null || clickedURLPath == null) { - parseURLAndOpen(unescapedURL) - return - } - // match template such as f{fid}-{page} - // crate reverse copy - rewriteRule = rewriteRule.replace("{tid}", "(?\\d+)") - rewriteRule = rewriteRule.replace("{page}", "(?\\d+)") - rewriteRule = rewriteRule.replace("{prevpage}", "(?\\d+)") - val pattern = Pattern.compile(rewriteRule) - val matcher = pattern.matcher(clickedURLPath) - if (matcher.find()) { - val tidStr = matcher.group("tid") - val pageStr = matcher.group("page") - // handle it - if (tidStr != null) { - val putThreadInfo = Thread() - var tid = 0 - tid = try { - tidStr.toInt() - } catch (e: Exception) { - 0 - } - putThreadInfo.tid = tid - val intent = Intent(context, ThreadActivity::class.java) - intent.putExtra(ConstUtils.PASS_BBS_ENTITY_KEY, discuz) - intent.putExtra(ConstUtils.PASS_BBS_USER_KEY, user) - intent.putExtra(ConstUtils.PASS_THREAD_KEY, putThreadInfo) - intent.putExtra("FID", fid) - intent.putExtra("TID", tid) - intent.putExtra("SUBJECT", url) - VibrateUtils.vibrateForClick(context) - val options = ActivityOptions.makeSceneTransitionAnimation(context as Activity) - val bundle = options.toBundle() - context.startActivity(intent, bundle) + if (rewriteRules != null) { + if (rewriteRules.containsKey("forum_viewthread")) { + // match template such as t{tid}-{page}-{prevpage} + var rewriteRule = rewriteRules["forum_viewthread"] + UserPreferenceUtils.saveRewriteRule(context, discuz, UserPreferenceUtils.REWRITE_VIEW_THREAD_KEY, rewriteRule) + if (rewriteRule == null || clickedURLPath == null) { + parseURLAndOpen(unescapedURL) return } + // match template such as f{fid}-{page} + // crate reverse copy + rewriteRule = rewriteRule.replace("{tid}", "(?\\d+)") + rewriteRule = rewriteRule.replace("{page}", "(?\\d+)") + rewriteRule = rewriteRule.replace("{prevpage}", "(?\\d+)") + val pattern = Pattern.compile(rewriteRule) + val matcher = pattern.matcher(clickedURLPath) + if (matcher.find()) { + val tidStr = matcher.group("tid") + val pageStr = matcher.group("page") + // handle it + if (tidStr != null) { + val putThreadInfo = Thread() + var tid = 0 + tid = try { + tidStr.toInt() + } catch (e: Exception) { + 0 + } + putThreadInfo.tid = tid + val intent = Intent(context, ThreadActivity::class.java) + intent.putExtra(ConstUtils.PASS_BBS_ENTITY_KEY, discuz) + intent.putExtra(ConstUtils.PASS_BBS_USER_KEY, user) + intent.putExtra(ConstUtils.PASS_THREAD_KEY, putThreadInfo) + intent.putExtra("FID", fid) + intent.putExtra("TID", tid) + intent.putExtra("SUBJECT", url) + VibrateUtils.vibrateForClick(context) + val options = ActivityOptions.makeSceneTransitionAnimation(context as Activity) + val bundle = options.toBundle() + context.startActivity(intent, bundle) + return + } + } } } - if (rewriteRules.containsKey("home_space")) { - // match template such as t{tid}-{page}-{prevpage} - var rewriteRule = rewriteRules["home_space"] - Log.d(TAG, "get home space url $rewriteRule") - UserPreferenceUtils.saveRewriteRule(context, discuz, UserPreferenceUtils.REWRITE_HOME_SPACE, rewriteRule) - if (rewriteRule == null || clickedURLPath == null) { - parseURLAndOpen(unescapedURL) - return - } - // match template such as f{fid}-{page} - // crate reverse copy - rewriteRule = rewriteRule.replace("{user}", "(?\\d+)") - rewriteRule = rewriteRule.replace("{value}", "(?\\d+)") - val pattern = Pattern.compile(rewriteRule) - val matcher = pattern.matcher(clickedURLPath) - if (matcher.find()) { - val userString = matcher.group("user") - val uidString = matcher.group("value") - // handle it - if (uidString != null) { - var uid = 0 - uid = try { - uidString.toInt() - } catch (e: Exception) { - 0 - } - val intent = Intent(context, UserProfileActivity::class.java) - intent.putExtra(ConstUtils.PASS_BBS_ENTITY_KEY, discuz) - intent.putExtra(ConstUtils.PASS_BBS_USER_KEY, user) - intent.putExtra("UID", uid) - VibrateUtils.vibrateForClick(context) - val options = ActivityOptions.makeSceneTransitionAnimation(context as Activity) - val bundle = options.toBundle() - context.startActivity(intent, bundle) + if (rewriteRules != null) { + if (rewriteRules.containsKey("home_space")) { + // match template such as t{tid}-{page}-{prevpage} + var rewriteRule = rewriteRules["home_space"] + Log.d(TAG, "get home space url $rewriteRule") + UserPreferenceUtils.saveRewriteRule(context, discuz, UserPreferenceUtils.REWRITE_HOME_SPACE, rewriteRule) + if (rewriteRule == null || clickedURLPath == null) { + parseURLAndOpen(unescapedURL) return } + // match template such as f{fid}-{page} + // crate reverse copy + rewriteRule = rewriteRule.replace("{user}", "(?\\d+)") + rewriteRule = rewriteRule.replace("{value}", "(?\\d+)") + val pattern = Pattern.compile(rewriteRule) + val matcher = pattern.matcher(clickedURLPath) + if (matcher.find()) { + val userString = matcher.group("user") + val uidString = matcher.group("value") + // handle it + if (uidString != null) { + var uid = 0 + uid = try { + uidString.toInt() + } catch (e: Exception) { + 0 + } + val intent = Intent(context, UserProfileActivity::class.java) + intent.putExtra(ConstUtils.PASS_BBS_ENTITY_KEY, discuz) + intent.putExtra(ConstUtils.PASS_BBS_USER_KEY, user) + intent.putExtra("UID", uid) + VibrateUtils.vibrateForClick(context) + val options = ActivityOptions.makeSceneTransitionAnimation(context as Activity) + val bundle = options.toBundle() + context.startActivity(intent, bundle) + return + } + } } } parseURLAndOpen(unescapedURL) diff --git a/app/src/main/java/com/kidozh/discuzhub/activities/ThreadPageActivity.kt b/app/src/main/java/com/kidozh/discuzhub/activities/ThreadPageActivity.kt index 0fb5b65d..b3fe8930 100644 --- a/app/src/main/java/com/kidozh/discuzhub/activities/ThreadPageActivity.kt +++ b/app/src/main/java/com/kidozh/discuzhub/activities/ThreadPageActivity.kt @@ -9,9 +9,7 @@ import android.graphics.drawable.Drawable import android.net.Uri import android.os.Build import android.os.Bundle -import android.text.Html -import android.text.InputType -import android.text.SpannableString +import android.text.* import android.text.method.DigitsKeyListener import android.util.Log import android.view.Menu @@ -20,6 +18,7 @@ import android.view.View import android.widget.* import androidx.core.content.ContextCompat import androidx.core.text.HtmlCompat +import androidx.core.widget.addTextChangedListener import androidx.fragment.app.FragmentStatePagerAdapter import androidx.lifecycle.ViewModelProvider import androidx.preference.PreferenceManager @@ -49,6 +48,7 @@ import okhttp3.Response import java.io.IOException import java.io.InputStream import java.util.regex.Pattern +import kotlin.concurrent.thread class ThreadPageActivity : BaseStatusActivity() , SmileyFragment.OnSmileyPressedInteraction, PostAdapter.onFilterChanged, PostAdapter.onAdapterReply, PostAdapter.OnLinkClicked{ @@ -58,6 +58,7 @@ class ThreadPageActivity : BaseStatusActivity() , SmileyFragment.OnSmileyPressed lateinit var smileyViewModel: SmileyViewModel lateinit var discuz: Discuz var tid = 0 + var fid = 0 lateinit var thread : Thread var forum : Forum? = null lateinit var postAdapter: PostAdapter @@ -80,6 +81,7 @@ class ThreadPageActivity : BaseStatusActivity() , SmileyFragment.OnSmileyPressed configureSmileyHandler() configureSwipeRefreshLayout() bindViewModel() + configureReplyLayout() Log.d(TAG, "start to get thread " + threadViewModel.threadStatusMutableLiveData.value!!.tid) threadViewModel.getThreadDetail(threadViewModel.threadStatusMutableLiveData.value!!) @@ -104,6 +106,7 @@ class ThreadPageActivity : BaseStatusActivity() , SmileyFragment.OnSmileyPressed forum = intent.getParcelableExtra(ConstUtils.PASS_FORUM_THREAD_KEY) val page: Int = intent.getIntExtra(ConstUtils.PASS_PAGE_KEY, 1) tid = thread.tid + fid = intent.getIntExtra("FID", 0) // configure view model threadViewModel.setBBSInfo(discuz, user, forum, thread.tid) @@ -259,6 +262,7 @@ class ThreadPageActivity : BaseStatusActivity() , SmileyFragment.OnSmileyPressed .url(captchaURL) .build() // get first + client = threadViewModel.client client.newCall(captchaRequest).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) {} @@ -312,6 +316,46 @@ class ThreadPageActivity : BaseStatusActivity() , SmileyFragment.OnSmileyPressed } }) + + threadViewModel.replyPostMutableLiveData.observe(this,{ + if(it == null){ + binding.replyPersonContent.visibility = View.GONE + } + else{ + binding.replyPersonContent.visibility = View.VISIBLE + binding.replyPostAuthorChip.text = it.author + binding.replyPostContent.text = it.message + } + }) + + threadViewModel.interactErrorMutableLiveData.observe(this,{ + if(it != null){ + Toasty.error(this, + getString(R.string.discuz_api_message_template, it.key, it.content), + Toast.LENGTH_LONG).show() + } + + }) + + + + threadViewModel.replyResultMutableLiveData.observe(this,{ + if(it?.message != null){ + if (it.message!!.key == "post_reply_succeed") { + Toasty.success(this, + getString(R.string.discuz_api_message_template, it.message!!.key, it.message!!.content), + Toast.LENGTH_LONG).show() + // clear the status + threadViewModel.replyPostMutableLiveData.postValue(null) + binding.replyEdittext.text.clear() + } else { + Toasty.error(this, + getString(R.string.discuz_api_message_template, it.message!!.key, it.message!!.content), + Toast.LENGTH_LONG).show() + } + } + + }) } private fun configureSpinner(){ @@ -359,6 +403,40 @@ class ThreadPageActivity : BaseStatusActivity() , SmileyFragment.OnSmileyPressed } } + private fun configureReplyLayout(){ + binding.replyPostAuthorChip.setOnCloseIconClickListener { + threadViewModel.replyPostMutableLiveData.postValue(null) + } + binding.replyButton.setOnClickListener{ + val replyMessage = binding.replyEdittext.text.toString() + val captcha = binding.captchaEdittext.text.toString() + if(replyMessage.isNotEmpty()){ + threadViewModel.sendReplyRequest(fid,replyMessage,captcha) + } + + } + + binding.replyEdittext.addTextChangedListener(object : TextWatcher{ + 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?) { + val inputString = s.toString(); + binding.replyButton.isEnabled = inputString.isNotEmpty() + } + + }) + + binding.captchaImageview.setOnClickListener { // update it + threadViewModel.secureInfo + } + } + override fun onSmileyPress(str: String, a: Drawable) { val decodeStr = str.replace("/", "") .replace("\\", "") @@ -366,7 +444,7 @@ class ThreadPageActivity : BaseStatusActivity() , SmileyFragment.OnSmileyPressed } - fun invalidateResponse(){ + private fun invalidateResponse(){ // clear spinner for better selection binding.pageSpinner.adapter = null } @@ -379,9 +457,9 @@ class ThreadPageActivity : BaseStatusActivity() , SmileyFragment.OnSmileyPressed } - override fun replyToSomeOne(position: Int) { + override fun replyToSomeOne(post: Post) { // need further notice - + threadViewModel.replyPostMutableLiveData.postValue(post) } private fun parseURLAndOpen(url: String) { @@ -524,124 +602,130 @@ class ThreadPageActivity : BaseStatusActivity() , SmileyFragment.OnSmileyPressed // only catch two type : forum_forumdisplay & forum_viewthread // only 8.0+ support reverse copy if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - if (rewriteRules.containsKey("forum_forumdisplay")) { - var rewriteRule = rewriteRules["forum_forumdisplay"] - UserPreferenceUtils.saveRewriteRule(context, discuz, UserPreferenceUtils.REWRITE_FORM_DISPLAY_KEY, rewriteRule) - if (rewriteRule == null || clickedURLPath == null) { - parseURLAndOpen(unescapedURL) - return - } - // match template such as f{fid}-{page} - // crate reverse copy - rewriteRule = rewriteRule.replace("{fid}", "(?\\d+)") - rewriteRule = rewriteRule.replace("{page}", "(?\\d+)") - val pattern = Pattern.compile(rewriteRule) - val matcher = pattern.matcher(clickedURLPath) - if (matcher.find()) { - val fidStr = matcher.group("fid") - val pageStr = matcher.group("page") - // handle it - if (fidStr != null) { - var fid = 0 - fid = try { - fidStr.toInt() - } catch (e: Exception) { - 0 - } - -// int page = Integer.parseInt(pageStr); - val intent = Intent(context, ForumActivity::class.java) - val clickedForum = Forum() - clickedForum.fid = fid - intent.putExtra(ConstUtils.PASS_FORUM_THREAD_KEY, clickedForum) - intent.putExtra(ConstUtils.PASS_BBS_ENTITY_KEY, discuz) - intent.putExtra(ConstUtils.PASS_BBS_USER_KEY, user) - Log.d(TAG, "put base url " + discuz.base_url) - VibrateUtils.vibrateForClick(context) - context.startActivity(intent) + if (rewriteRules != null) { + if (rewriteRules.containsKey("forum_forumdisplay")) { + var rewriteRule = rewriteRules["forum_forumdisplay"] + UserPreferenceUtils.saveRewriteRule(context, discuz, UserPreferenceUtils.REWRITE_FORM_DISPLAY_KEY, rewriteRule) + if (rewriteRule == null || clickedURLPath == null) { + parseURLAndOpen(unescapedURL) return } + // match template such as f{fid}-{page} + // crate reverse copy + rewriteRule = rewriteRule.replace("{fid}", "(?\\d+)") + rewriteRule = rewriteRule.replace("{page}", "(?\\d+)") + val pattern = Pattern.compile(rewriteRule) + val matcher = pattern.matcher(clickedURLPath) + if (matcher.find()) { + val fidStr = matcher.group("fid") + val pageStr = matcher.group("page") + // handle it + if (fidStr != null) { + var fid = 0 + fid = try { + fidStr.toInt() + } catch (e: Exception) { + 0 + } + + // int page = Integer.parseInt(pageStr); + val intent = Intent(context, ForumActivity::class.java) + val clickedForum = Forum() + clickedForum.fid = fid + intent.putExtra(ConstUtils.PASS_FORUM_THREAD_KEY, clickedForum) + intent.putExtra(ConstUtils.PASS_BBS_ENTITY_KEY, discuz) + intent.putExtra(ConstUtils.PASS_BBS_USER_KEY, user) + Log.d(TAG, "put base url " + discuz.base_url) + VibrateUtils.vibrateForClick(context) + context.startActivity(intent) + return + } + } } } - if (rewriteRules.containsKey("forum_viewthread")) { - // match template such as t{tid}-{page}-{prevpage} - var rewriteRule = rewriteRules["forum_viewthread"] - UserPreferenceUtils.saveRewriteRule(context, discuz, UserPreferenceUtils.REWRITE_VIEW_THREAD_KEY, rewriteRule) - if (rewriteRule == null || clickedURLPath == null) { - parseURLAndOpen(unescapedURL) - return - } - // match template such as f{fid}-{page} - // crate reverse copy - rewriteRule = rewriteRule.replace("{tid}", "(?\\d+)") - rewriteRule = rewriteRule.replace("{page}", "(?\\d+)") - rewriteRule = rewriteRule.replace("{prevpage}", "(?\\d+)") - val pattern = Pattern.compile(rewriteRule) - val matcher = pattern.matcher(clickedURLPath) - if (matcher.find()) { - val tidStr = matcher.group("tid") - val pageStr = matcher.group("page") - // handle it - if (tidStr != null) { - val putThreadInfo = Thread() - var tid = 0 - tid = try { - tidStr.toInt() - } catch (e: Exception) { - 0 - } - putThreadInfo.tid = tid - val intent = Intent(context, ThreadActivity::class.java) - intent.putExtra(ConstUtils.PASS_BBS_ENTITY_KEY, discuz) - intent.putExtra(ConstUtils.PASS_BBS_USER_KEY, user) - intent.putExtra(ConstUtils.PASS_THREAD_KEY, putThreadInfo) - //intent.putExtra("FID", fid) - intent.putExtra("TID", tid) - intent.putExtra("SUBJECT", url) - VibrateUtils.vibrateForClick(context) - val options = ActivityOptions.makeSceneTransitionAnimation(context as Activity) - val bundle = options.toBundle() - context.startActivity(intent, bundle) + if (rewriteRules != null) { + if (rewriteRules.containsKey("forum_viewthread")) { + // match template such as t{tid}-{page}-{prevpage} + var rewriteRule = rewriteRules["forum_viewthread"] + UserPreferenceUtils.saveRewriteRule(context, discuz, UserPreferenceUtils.REWRITE_VIEW_THREAD_KEY, rewriteRule) + if (rewriteRule == null || clickedURLPath == null) { + parseURLAndOpen(unescapedURL) return } + // match template such as f{fid}-{page} + // crate reverse copy + rewriteRule = rewriteRule.replace("{tid}", "(?\\d+)") + rewriteRule = rewriteRule.replace("{page}", "(?\\d+)") + rewriteRule = rewriteRule.replace("{prevpage}", "(?\\d+)") + val pattern = Pattern.compile(rewriteRule) + val matcher = pattern.matcher(clickedURLPath) + if (matcher.find()) { + val tidStr = matcher.group("tid") + val pageStr = matcher.group("page") + // handle it + if (tidStr != null) { + val putThreadInfo = Thread() + var tid = 0 + tid = try { + tidStr.toInt() + } catch (e: Exception) { + 0 + } + putThreadInfo.tid = tid + val intent = Intent(context, ThreadActivity::class.java) + intent.putExtra(ConstUtils.PASS_BBS_ENTITY_KEY, discuz) + intent.putExtra(ConstUtils.PASS_BBS_USER_KEY, user) + intent.putExtra(ConstUtils.PASS_THREAD_KEY, putThreadInfo) + //intent.putExtra("FID", fid) + intent.putExtra("TID", tid) + intent.putExtra("SUBJECT", url) + VibrateUtils.vibrateForClick(context) + val options = ActivityOptions.makeSceneTransitionAnimation(context as Activity) + val bundle = options.toBundle() + context.startActivity(intent, bundle) + return + } + } } } - if (rewriteRules.containsKey("home_space")) { - // match template such as t{tid}-{page}-{prevpage} - var rewriteRule = rewriteRules["home_space"] - Log.d(TAG, "get home space url $rewriteRule") - UserPreferenceUtils.saveRewriteRule(context, discuz, UserPreferenceUtils.REWRITE_HOME_SPACE, rewriteRule) - if (rewriteRule == null || clickedURLPath == null) { - parseURLAndOpen(unescapedURL) - return - } - // match template such as f{fid}-{page} - // crate reverse copy - rewriteRule = rewriteRule.replace("{user}", "(?\\d+)") - rewriteRule = rewriteRule.replace("{value}", "(?\\d+)") - val pattern = Pattern.compile(rewriteRule) - val matcher = pattern.matcher(clickedURLPath) - if (matcher.find()) { - val userString = matcher.group("user") - val uidString = matcher.group("value") - // handle it - if (uidString != null) { - var uid = 0 - uid = try { - uidString.toInt() - } catch (e: Exception) { - 0 - } - val intent = Intent(context, UserProfileActivity::class.java) - intent.putExtra(ConstUtils.PASS_BBS_ENTITY_KEY, discuz) - intent.putExtra(ConstUtils.PASS_BBS_USER_KEY, user) - intent.putExtra("UID", uid) - VibrateUtils.vibrateForClick(context) - val options = ActivityOptions.makeSceneTransitionAnimation(context as Activity) - val bundle = options.toBundle() - context.startActivity(intent, bundle) + if (rewriteRules != null) { + if (rewriteRules.containsKey("home_space")) { + // match template such as t{tid}-{page}-{prevpage} + var rewriteRule = rewriteRules["home_space"] + Log.d(TAG, "get home space url $rewriteRule") + UserPreferenceUtils.saveRewriteRule(context, discuz, UserPreferenceUtils.REWRITE_HOME_SPACE, rewriteRule) + if (rewriteRule == null || clickedURLPath == null) { + parseURLAndOpen(unescapedURL) return } + // match template such as f{fid}-{page} + // crate reverse copy + rewriteRule = rewriteRule.replace("{user}", "(?\\d+)") + rewriteRule = rewriteRule.replace("{value}", "(?\\d+)") + val pattern = Pattern.compile(rewriteRule) + val matcher = pattern.matcher(clickedURLPath) + if (matcher.find()) { + val userString = matcher.group("user") + val uidString = matcher.group("value") + // handle it + if (uidString != null) { + var uid = 0 + uid = try { + uidString.toInt() + } catch (e: Exception) { + 0 + } + val intent = Intent(context, UserProfileActivity::class.java) + intent.putExtra(ConstUtils.PASS_BBS_ENTITY_KEY, discuz) + intent.putExtra(ConstUtils.PASS_BBS_USER_KEY, user) + intent.putExtra("UID", uid) + VibrateUtils.vibrateForClick(context) + val options = ActivityOptions.makeSceneTransitionAnimation(context as Activity) + val bundle = options.toBundle() + context.startActivity(intent, bundle) + return + } + } } } parseURLAndOpen(unescapedURL) diff --git a/app/src/main/java/com/kidozh/discuzhub/adapter/PostAdapter.kt b/app/src/main/java/com/kidozh/discuzhub/adapter/PostAdapter.kt index 2bbd199e..25ad20bc 100644 --- a/app/src/main/java/com/kidozh/discuzhub/adapter/PostAdapter.kt +++ b/app/src/main/java/com/kidozh/discuzhub/adapter/PostAdapter.kt @@ -317,7 +317,7 @@ class PostAdapter(private val bbsInfo: Discuz, private val user: User?, viewThre val bundle = options.toBundle() context.startActivity(intent, bundle) } - holder.mReplyBtn.setOnClickListener { replyListener!!.replyToSomeOne(position) } + holder.mReplyBtn.setOnClickListener { replyListener!!.replyToSomeOne(post) } // advance option if (bbsInfo.apiVersion > 4) { @@ -826,7 +826,7 @@ class PostAdapter(private val bbsInfo: Discuz, private val user: User?, viewThre } interface onAdapterReply { - fun replyToSomeOne(position: Int) + fun replyToSomeOne(post : Post) } interface OnLinkClicked { diff --git a/app/src/main/java/com/kidozh/discuzhub/results/BaseResult.kt b/app/src/main/java/com/kidozh/discuzhub/results/BaseResult.kt index 4badc78c..e4a558a4 100644 --- a/app/src/main/java/com/kidozh/discuzhub/results/BaseResult.kt +++ b/app/src/main/java/com/kidozh/discuzhub/results/BaseResult.kt @@ -3,6 +3,7 @@ package com.kidozh.discuzhub.results import android.text.TextUtils import com.fasterxml.jackson.annotation.JsonIgnoreProperties import com.fasterxml.jackson.annotation.JsonProperty +import com.kidozh.discuzhub.activities.BaseStatusActivity import com.kidozh.discuzhub.entities.ErrorMessage @JsonIgnoreProperties(ignoreUnknown = true) @@ -13,6 +14,17 @@ open class BaseResult { @JsonProperty("Charset") lateinit var Charset: String + fun getCharsetType():Int{ + if (Charset == "GBK") { + return BaseStatusActivity.CHARSET_GBK + } else if (Charset == "BIG5") { + return BaseStatusActivity.CHARSET_BIG5 + } + else{ + return BaseStatusActivity.CHARSET_UTF8 + } + } + @JvmField @JsonIgnoreProperties(ignoreUnknown = true) @JsonProperty("Message") diff --git a/app/src/main/java/com/kidozh/discuzhub/results/ForumResult.java b/app/src/main/java/com/kidozh/discuzhub/results/ForumResult.java deleted file mode 100644 index 8e10d478..00000000 --- a/app/src/main/java/com/kidozh/discuzhub/results/ForumResult.java +++ /dev/null @@ -1,123 +0,0 @@ -package com.kidozh.discuzhub.results; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.kidozh.discuzhub.entities.Forum; -import com.kidozh.discuzhub.entities.Thread; -import com.kidozh.discuzhub.utilities.OneZeroBooleanJsonDeserializer; - -import java.io.IOException; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class ForumResult extends BaseResult { - @JsonProperty("Variables") - public ForumVariables forumVariables; - - @JsonIgnoreProperties(ignoreUnknown = true) - public static class ForumVariables extends VariableResults{ - @JsonProperty("forum") - public Forum forum; - @JsonProperty("group") - public GroupInfo groupInfo; - @JsonProperty("forum_threadlist") - public List forumThreadList; - @JsonProperty("groupiconid") - public Map groupIconId; - @JsonProperty("sublist") - public List subForumLists = new ArrayList<>(); - @JsonFormat(shape = JsonFormat.Shape.STRING) - public int tpp, page; - @JsonProperty("reward_unit") - public String rewardUnit; - @JsonProperty("threadtypes") - public ThreadTypeInfo threadTypeInfo; - - } - - - - public static class GroupInfo implements Serializable{ - @JsonProperty("groupid") - @JsonFormat(shape = JsonFormat.Shape.STRING) - public int groupId; - @JsonProperty("grouptitle") - public String groupTitle; - - } - - @JsonIgnoreProperties(ignoreUnknown = true) - public static class ShortReply implements Serializable { - @JsonFormat(shape = JsonFormat.Shape.STRING) - public int pid; - @JsonFormat(shape = JsonFormat.Shape.STRING) - @JsonProperty("authorid") - public int authorId; - public String author, message; - } - - @JsonIgnoreProperties(ignoreUnknown = true) - public static class SubForumInfo implements Serializable{ - @JsonFormat(shape = JsonFormat.Shape.STRING) - public int fid, threads, posts; - public String name; - @JsonFormat(shape = JsonFormat.Shape.STRING) - @JsonProperty("todayposts") - public int todayPosts; - @JsonProperty("icon") - public String iconURL; - } - - @JsonIgnoreProperties(ignoreUnknown = true) - public static class ThreadTypeInfo implements Serializable{ - @JsonFormat(shape = JsonFormat.Shape.STRING) - @JsonDeserialize(using = OneZeroBooleanJsonDeserializer.class) - @JsonInclude(JsonInclude.Include.NON_NULL) - public boolean required = false, listable = false; - public String prefix; - @JsonProperty("types") - @JsonDeserialize(using = ForumThreadTypeDeserializer.class) - public HashMap idNameMap = new HashMap<>(); - @JsonProperty("icons") - @JsonDeserialize(using = ForumThreadTypeDeserializer.class) - public Map idIconMap= new HashMap<>(); - @JsonProperty("moderators") - @JsonDeserialize(using = ForumThreadTypeDeserializer.class) - public Map idModeratorMap= new HashMap<>(); - - } - - public static class ForumThreadTypeDeserializer extends JsonDeserializer>{ - - @Override - public Map deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { - JsonToken currentToken = p.getCurrentToken(); - if(currentToken.equals(JsonToken.START_OBJECT)) { - ObjectMapper mapper = new ObjectMapper(); - - return mapper.readValue(p, new TypeReference>(){}); - } - else { - return new HashMap<>(); - } - } - } - - public boolean isError(){ - return this.message != null; - } -} diff --git a/app/src/main/java/com/kidozh/discuzhub/results/ForumResult.kt b/app/src/main/java/com/kidozh/discuzhub/results/ForumResult.kt new file mode 100644 index 00000000..a66340db --- /dev/null +++ b/app/src/main/java/com/kidozh/discuzhub/results/ForumResult.kt @@ -0,0 +1,159 @@ +package com.kidozh.discuzhub.results + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import com.kidozh.discuzhub.results.BaseResult +import com.fasterxml.jackson.annotation.JsonProperty +import com.kidozh.discuzhub.results.VariableResults +import com.kidozh.discuzhub.entities.Forum +import com.kidozh.discuzhub.results.ForumResult.SubForumInfo +import com.fasterxml.jackson.annotation.JsonFormat +import com.kidozh.discuzhub.results.ForumResult.ThreadTypeInfo +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.kidozh.discuzhub.utilities.OneZeroBooleanJsonDeserializer +import com.fasterxml.jackson.annotation.JsonInclude +import com.kidozh.discuzhub.results.ForumResult.ForumThreadTypeDeserializer +import com.fasterxml.jackson.databind.JsonDeserializer +import kotlin.Throws +import com.fasterxml.jackson.core.JsonProcessingException +import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.core.JsonToken +import com.fasterxml.jackson.core.type.TypeReference +import com.fasterxml.jackson.databind.DeserializationContext +import com.fasterxml.jackson.databind.ObjectMapper +import com.kidozh.discuzhub.entities.Thread +import java.io.IOException +import java.io.Serializable +import java.util.ArrayList +import java.util.HashMap + +class ForumResult : BaseResult() { + + @JsonProperty("Variables") + lateinit var forumVariables: ForumVariables + + + class ForumVariables : VariableResults() { + + @JsonProperty("forum") + lateinit var forum: Forum + + @JsonProperty("group") + var groupInfo: GroupInfo? = null + + @JsonProperty("forum_threadlist") + lateinit var forumThreadList: List + + @JsonProperty("groupiconid") + var groupIconId: Map? = null + + @JvmField + @JsonProperty("sublist") + var subForumLists: List = ArrayList() + + @JsonFormat(shape = JsonFormat.Shape.STRING) + var tpp = 0 + + @JsonFormat(shape = JsonFormat.Shape.STRING) + var page = 0 + + @JsonProperty("reward_unit") + var rewardUnit: String? = null + + + @JsonProperty("threadtypes") + var threadTypeInfo: ThreadTypeInfo? = null + } + + class GroupInfo : Serializable { + @JsonProperty("groupid") + @JsonFormat(shape = JsonFormat.Shape.STRING) + var groupId = 0 + + @JsonProperty("grouptitle") + var groupTitle: String? = null + } + + @JsonIgnoreProperties(ignoreUnknown = true) + class ShortReply : Serializable { + @JsonFormat(shape = JsonFormat.Shape.STRING) + var pid = 0 + + @JvmField + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JsonProperty("authorid") + var authorId = 0 + + lateinit var author: String + + lateinit var message: String + } + + @JsonIgnoreProperties(ignoreUnknown = true) + class SubForumInfo : Serializable { + @JvmField + @JsonFormat(shape = JsonFormat.Shape.STRING) + var fid = 0 + + @JvmField + @JsonFormat(shape = JsonFormat.Shape.STRING) + var threads = 0 + + @JvmField + @JsonFormat(shape = JsonFormat.Shape.STRING) + var posts = 0 + @JvmField + var name: String? = null + + @JvmField + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JsonProperty("todayposts") + var todayPosts = 0 + + @JsonProperty("icon") + var iconURL: String? = null + } + + @JsonIgnoreProperties(ignoreUnknown = true) + class ThreadTypeInfo : Serializable { + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JsonDeserialize(using = OneZeroBooleanJsonDeserializer::class) + @JsonInclude(JsonInclude.Include.NON_NULL) + var required = false + + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JsonDeserialize(using = OneZeroBooleanJsonDeserializer::class) + @JsonInclude(JsonInclude.Include.NON_NULL) + var listable = false + var prefix: String? = null + + @JvmField + @JsonProperty("types") + @JsonDeserialize(using = ForumThreadTypeDeserializer::class) + var idNameMap = HashMap() + + @JsonProperty("icons") + @JsonDeserialize(using = ForumThreadTypeDeserializer::class) + var idIconMap: Map = HashMap() + + @JsonProperty("moderators") + @JsonDeserialize(using = ForumThreadTypeDeserializer::class) + var idModeratorMap: Map = HashMap() + } + + class ForumThreadTypeDeserializer : JsonDeserializer>() { + @Throws(IOException::class, JsonProcessingException::class) + override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Map { + val currentToken = p.currentToken + return if (currentToken == JsonToken.START_OBJECT) { + val mapper = ObjectMapper() + mapper.readValue>(p, object : TypeReference>() {}) + } else { + HashMap() + } + } + } + + override fun isError(): Boolean { + return message != null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kidozh/discuzhub/results/ThreadResult.kt b/app/src/main/java/com/kidozh/discuzhub/results/ThreadResult.kt index e3f3cf75..41f94ba0 100644 --- a/app/src/main/java/com/kidozh/discuzhub/results/ThreadResult.kt +++ b/app/src/main/java/com/kidozh/discuzhub/results/ThreadResult.kt @@ -58,17 +58,17 @@ class ThreadResult : BaseResult() { var ppp = 0 @JsonProperty("setting_rewriterule") - var rewriteRule: Map = HashMap() + var rewriteRule: Map? = HashMap() @JsonProperty("setting_rewritestatus") @JsonDeserialize(using = SettingRewriteStatusJsonDeserializer::class) - var rewriteList: List = ArrayList() + var rewriteList: List? = ArrayList() @JsonProperty("forum_threadpay") var threadPay: String? = null @JsonProperty("cache_custominfo_postno") - var customPostNoList: List = ArrayList() + var customPostNoList: List? = ArrayList() // for poll @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/app/src/main/java/com/kidozh/discuzhub/results/VariableResults.kt b/app/src/main/java/com/kidozh/discuzhub/results/VariableResults.kt index 7bf57fd0..b0df6b96 100644 --- a/app/src/main/java/com/kidozh/discuzhub/results/VariableResults.kt +++ b/app/src/main/java/com/kidozh/discuzhub/results/VariableResults.kt @@ -18,13 +18,13 @@ open class VariableResults : BaseResult() { @JsonFormat(shape = JsonFormat.Shape.STRING) var groupId = 0 - @JvmField + @JsonProperty("formhash") - var formHash: String? = null + lateinit var formHash: String - @JsonProperty("ismoderator") - @JsonDeserialize(using = OneZeroBooleanJsonDeserializer::class) - var moderator: Boolean? = null +// @JsonProperty("ismoderator") +// @JsonDeserialize(using = OneZeroBooleanJsonDeserializer::class) +// var moderator: Boolean = false @JsonProperty("readaccess") var readAccess = 0 diff --git a/app/src/main/java/com/kidozh/discuzhub/services/DiscuzApiService.java b/app/src/main/java/com/kidozh/discuzhub/services/DiscuzApiService.java index 52d4b059..bea8ece2 100644 --- a/app/src/main/java/com/kidozh/discuzhub/services/DiscuzApiService.java +++ b/app/src/main/java/com/kidozh/discuzhub/services/DiscuzApiService.java @@ -181,5 +181,13 @@ Call myThreadResult( @Query("page") int page ); + @FormUrlEncoded + @POST(DISCUZ_API_PATH+"?version=4&module=sendreply&action=reply&replysubmit=yes") + Call replyThread( + @Query("fid") int fid, + @Query("tid") int tid, + @FieldMap HashMap options + ); + } diff --git a/app/src/main/java/com/kidozh/discuzhub/utilities/OneZeroBooleanJsonDeserializer.java b/app/src/main/java/com/kidozh/discuzhub/utilities/OneZeroBooleanJsonDeserializer.java index ac6a62c6..02e2d4ec 100644 --- a/app/src/main/java/com/kidozh/discuzhub/utilities/OneZeroBooleanJsonDeserializer.java +++ b/app/src/main/java/com/kidozh/discuzhub/utilities/OneZeroBooleanJsonDeserializer.java @@ -27,6 +27,7 @@ public Boolean deserialize(JsonParser p, DeserializationContext ctxt) throws IOE } else if (currentToken.equals(JsonToken.VALUE_NULL)) { return Boolean.FALSE; } + return Boolean.TRUE; } } diff --git a/app/src/main/java/com/kidozh/discuzhub/viewModels/ForumViewModel.kt b/app/src/main/java/com/kidozh/discuzhub/viewModels/ForumViewModel.kt index 5505c317..f9bdf33a 100644 --- a/app/src/main/java/com/kidozh/discuzhub/viewModels/ForumViewModel.kt +++ b/app/src/main/java/com/kidozh/discuzhub/viewModels/ForumViewModel.kt @@ -111,9 +111,9 @@ class ForumViewModel(application: Application) : AndroidViewModel(application) { override fun onResponse(call: Call, response: Response) { // clear status if page == 1 if (response.isSuccessful && response.body() != null) { - val forumResult = response.body() + val forumResult = response.body() as ForumResult displayForumResultMutableLiveData.postValue(forumResult) - Log.d(TAG, "Get forum thread size " + forumResult!!.forumVariables.forumThreadList.size) + // for list display val threadList = forumResult.forumVariables.forumThreadList diff --git a/app/src/main/java/com/kidozh/discuzhub/viewModels/ThreadViewModel.kt b/app/src/main/java/com/kidozh/discuzhub/viewModels/ThreadViewModel.kt index fe107b2b..96e95a9b 100644 --- a/app/src/main/java/com/kidozh/discuzhub/viewModels/ThreadViewModel.kt +++ b/app/src/main/java/com/kidozh/discuzhub/viewModels/ThreadViewModel.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import com.kidozh.discuzhub.R +import com.kidozh.discuzhub.activities.BaseStatusActivity import com.kidozh.discuzhub.daos.FavoriteThreadDao import com.kidozh.discuzhub.database.FavoriteThreadDatabase import com.kidozh.discuzhub.entities.* @@ -17,11 +18,16 @@ import com.kidozh.discuzhub.utilities.NetworkUtils import com.kidozh.discuzhub.utilities.URLUtils import com.kidozh.discuzhub.utilities.UserPreferenceUtils import com.kidozh.discuzhub.utilities.bbsParseUtils.DetailedThreadInfo +import okhttp3.FormBody import okhttp3.OkHttpClient import retrofit2.Call import retrofit2.Callback import retrofit2.Response +import java.net.URLEncoder +import java.text.DateFormat +import java.util.* import kotlin.collections.ArrayList +import kotlin.collections.HashMap class ThreadViewModel(application: Application) : AndroidViewModel(application) { private val TAG = ThreadViewModel::class.java.simpleName @@ -49,7 +55,11 @@ class ThreadViewModel(application: Application) : AndroidViewModel(application) var interactErrorMutableLiveData = MutableLiveData(null) var threadPriceInfoMutableLiveData = MutableLiveData(null) var buyThreadResultMutableLiveData = MutableLiveData(null) + var replyResultMutableLiveData = MutableLiveData(null) var dao: FavoriteThreadDao + + var replyPostMutableLiveData: MutableLiveData = MutableLiveData(null) + fun setBBSInfo(bbsInfo: Discuz, user: User?, forum: Forum?, tid: Int) { this.bbsInfo = bbsInfo this.user = user @@ -62,11 +72,11 @@ class ThreadViewModel(application: Application) : AndroidViewModel(application) isFavoriteThreadMutableLiveData = dao.isFavoriteItem(bbsInfo.id, user?.getUid() ?: 0, tid, "tid") - if(user == null){ - favoriteThreadLiveData = dao.getFavoriteItemByTid(bbsInfo.id, 0, tid, "tid") + favoriteThreadLiveData = if(user == null){ + dao.getFavoriteItemByTid(bbsInfo.id, 0, tid, "tid") } else{ - favoriteThreadLiveData = dao.getFavoriteItemByTid(bbsInfo.id, user.getUid(), tid, "tid") + dao.getFavoriteItemByTid(bbsInfo.id, user.getUid(), tid, "tid") } } @@ -118,9 +128,7 @@ class ThreadViewModel(application: Application) : AndroidViewModel(application) var detailedThreadInfo: DetailedThreadInfo? = null threadPostResultMutableLiveData.postValue(threadResult) // update formhash first - if (threadResult.threadPostVariables.formHash != null) { - formHash.postValue(threadResult.threadPostVariables.formHash) - } + formHash.postValue(threadResult.threadPostVariables.formHash) // update user bbsPersonInfoMutableLiveData.postValue(threadResult.threadPostVariables.userBriefInfo) // parse detailed info @@ -331,56 +339,183 @@ class ThreadViewModel(application: Application) : AndroidViewModel(application) } } dao = FavoriteThreadDatabase.getInstance(getApplication()).dao - if(favoriteThreadActionResultCall != null){ - favoriteThreadActionResultCall.enqueue(object :Callback{ - override fun onResponse(call: Call, response: Response) { - if (response.isSuccessful && response.body() != null) { - val result = response.body() as ApiMessageActionResult - val key = result.message?.key + favoriteThreadActionResultCall?.enqueue(object :Callback{ + override fun onResponse(call: Call, response: Response) { + if (response.isSuccessful && response.body() != null) { + val result = response.body() as ApiMessageActionResult + val key = result.message?.key + Thread{ + if (favorite && key == "favorite_do_success") { + dao.insert(favoriteThread) + } else if (!favorite && key == "do_success") { + dao.delete(favoriteThread) + dao.delete(bbsInfo.id, if (user != null) user!!.getUid() else 0, favoriteThread.idKey, "tid") + } + }.start() + + } else { + MessageResult().apply { + content = getApplication().getString(R.string.network_failed) + key = response.code().toString() + } + if(favorite){ Thread{ - if (favorite && key == "favorite_do_success") { - dao.insert(favoriteThread) - } else if (!favorite && key == "do_success") { - dao.delete(favoriteThread) - dao.delete(bbsInfo.id, if (user != null) user!!.getUid() else 0, favoriteThread.idKey, "tid") - } else { - - } + dao.delete(bbsInfo.id, if (user != null) user!!.getUid() else 0, favoriteThread.idKey, "tid") + dao.insert(favoriteThread) + }.start() + + } else{ + // clear potential + Thread{ + dao.delete(bbsInfo.id, if (user != null) user!!.getUid() else 0, favoriteThread.idKey, "tid") }.start() } - else { - MessageResult().apply { - content = getApplication().getString(R.string.network_failed) - key = response.code().toString() - } - if(favorite){ - Thread{ - dao.delete(bbsInfo.id, if (user != null) user!!.getUid() else 0, favoriteThread.idKey, "tid") - dao.insert(favoriteThread) - }.start() - } - else{ - // clear potential - Thread{ - dao.delete(bbsInfo.id, if (user != null) user!!.getUid() else 0, favoriteThread.idKey, "tid") - }.start() + } - } - } + } + override fun onFailure(call: Call, t: Throwable) { - } + } - override fun onFailure(call: Call, t: Throwable) { + }) + } + + private fun needCaptcha(): Boolean { + return !(secureInfoResultMutableLiveData.value == null || secureInfoResultMutableLiveData.value!!.secureVariables == null) + } + + fun sendReplyRequest(fid: Int,message: String, captcha: String){ + Log.d(TAG, "Get message $message Captcha $captcha") + val replyPost : Post? = replyPostMutableLiveData.value + if(threadPostResultMutableLiveData.value == null){ + return + } + val result = threadPostResultMutableLiveData.value as ThreadResult + // preparing forum parameters + val formHash: String = result.threadPostVariables.formHash + val now = Date() + val formBody: HashMap = HashMap() + formBody["usesig"] = "1" + formBody["subject"] = "" + formBody["tid"] = tid.toString() + formBody["posttime"] = (now.time / 1000 - 1).toString() + formBody["formhash"] = formHash + // encoding the charset for discuz encoding + val charsetType = result.getCharsetType() + when (charsetType) { + BaseStatusActivity.CHARSET_GBK -> { + formBody["message"] = URLEncoder.encode(message, "GBK") + + } + BaseStatusActivity.CHARSET_BIG5 -> { + formBody["message"] = URLEncoder.encode(message, "BIG5") + } + else -> { + formBody["message"] = message + } + } + // captcha verification + if (needCaptcha()) { + val secureInfoResult = secureInfoResultMutableLiveData.value as SecureInfoResult + formBody["seccodehash"] = secureInfoResult.secureVariables.secHash + if(replyPost==null){ + // it's a post + formBody["seccodemodid"] = "forum::viewthread" + } + else{ + formBody["seccodemodid"] = "forum::post" + } + + Log.d(TAG,"Need captcha and the seccodeHash "+secureInfoResult.secureVariables.secHash) + + + when (charsetType) { + BaseStatusActivity.CHARSET_GBK -> { + formBody["seccodeverify"] = URLEncoder.encode(captcha, "GBK") + } + BaseStatusActivity.CHARSET_BIG5 -> { + formBody["seccodeverify"] = URLEncoder.encode(captcha, "BIG5") + } + else -> { + formBody["seccodeverify"] = captcha } + } + } + if(replyPost != null){ + // reply to someone + formBody.put("handlekey", "reply") + formBody.put("reppid", replyPost.pid.toString()) + formBody.put("reppost", replyPost.pid.toString()) + val df = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.FULL, Locale.getDefault()) + val publishAtString = df.format(replyPost.publishAt) + val MAX_CHAR_LENGTH = 300 + val trimEnd = MAX_CHAR_LENGTH.coerceAtMost(replyPost.message.length) + var replyMessage = replyPost.message.substring(0, trimEnd) + if (replyPost.message.length > MAX_CHAR_LENGTH) { + replyMessage += "..." + } + val noticeAuthorMsg = replyPost.message + + val noticeMsgTrimString = getApplication().getString(R.string.bbs_reply_notice_author_string, + URLUtils.getReplyPostURLInLabel(replyPost.pid, tid), + replyPost.author, + publishAtString, + replyMessage + ) + when (charsetType) { + BaseStatusActivity.CHARSET_GBK -> { + formBody["message"] = URLEncoder.encode(message, "GBK") + formBody["noticeauthormsg"] = URLEncoder.encode(noticeAuthorMsg, "GBK") + formBody["noticetrimstr"] = URLEncoder.encode(noticeMsgTrimString, "GBK") + + } + BaseStatusActivity.CHARSET_BIG5 -> { + formBody["message"] = URLEncoder.encode(message, "BIG5") + formBody["noticeauthormsg"] = URLEncoder.encode(noticeAuthorMsg, "BIG5") + formBody["noticetrimstr"] = URLEncoder.encode(noticeMsgTrimString, "BIG5") + } + else -> { + formBody["message"] = message + formBody["noticeauthormsg"] = noticeAuthorMsg + formBody["noticetrimstr"] = noticeMsgTrimString + } + } - }) } + // start to send information + val retrofit = NetworkUtils.getRetrofitInstance(bbsInfo.base_url, client) + val service = retrofit.create(DiscuzApiService::class.java) + val call = service.replyThread(fid,tid,formBody) + call.enqueue(object :Callback{ + override fun onResponse(call: Call, response: Response) { + if(response.isSuccessful && response.body() != null){ + val result = response.body() as ApiMessageActionResult + replyResultMutableLiveData.postValue(result) + } + else{ + interactErrorMutableLiveData.postValue(ErrorMessage(response.code().toString(), + getApplication().getString(R.string.discuz_network_unsuccessful, + response.message() + ) + )) + } + } + + override fun onFailure(call: Call, t: Throwable) { + interactErrorMutableLiveData.postValue(ErrorMessage(getApplication().getString(R.string.discuz_network_failure_template), + if (t.localizedMessage == null) t.toString() else t.localizedMessage)) + } + + }) + + + } init { diff --git a/app/src/main/res/layout/activity_thread_page.xml b/app/src/main/res/layout/activity_thread_page.xml index 168bf657..5ea5ec7b 100644 --- a/app/src/main/res/layout/activity_thread_page.xml +++ b/app/src/main/res/layout/activity_thread_page.xml @@ -94,7 +94,6 @@ android:id="@+id/reply_layout" android:layout_width="match_parent" android:layout_height="wrap_content" - android:visibility="gone" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"> @@ -171,6 +170,7 @@ android:id="@+id/reply_button" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:enabled="false" android:text="@string/bbs_thread_comment" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" @@ -202,6 +202,8 @@ android:id="@+id/captcha_imageview" android:layout_width="64dp" android:layout_height="0dp" + android:clickable="true" + android:hapticFeedbackEnabled="true" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent"