Commit 04cbf6e7 by 段启岩

文章内容初步完成

parent c3c66a25
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="github-markdown.min.css">
<link href="default.min.css" rel="stylesheet"/>
<style>
.article__content {
padding: 0 10px;
}
</style>
</head>
<body>
<div id="Article_Content" class="article__content markdown-body">
</div>
<script src="highlight.js"></script>
<script src="highlightjs-line-numbers.min.js"></script>
<script>
function loadArticleContent(content) {
document.getElementById("Article_Content").innerHTML = content;
hljs.initHighlightingOnLoad();
hljs.initLineNumbersOnLoad();
}
</script>
</body>
</html>
\ No newline at end of file
.hljs{display:block;overflow-x:auto;padding:.5em;background:#F0F0F0}.hljs,.hljs-subst{color:#444}.hljs-comment{color:#888888}.hljs-keyword,.hljs-attribute,.hljs-selector-tag,.hljs-meta-keyword,.hljs-doctag,.hljs-name{font-weight:bold}.hljs-type,.hljs-string,.hljs-number,.hljs-selector-id,.hljs-selector-class,.hljs-quote,.hljs-template-tag,.hljs-deletion{color:#880000}.hljs-title,.hljs-section{color:#880000;font-weight:bold}.hljs-regexp,.hljs-symbol,.hljs-variable,.hljs-template-variable,.hljs-link,.hljs-selector-attr,.hljs-selector-pseudo{color:#BC6060}.hljs-literal{color:#78A960}.hljs-built_in,.hljs-bullet,.hljs-code,.hljs-addition{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta-string{color:#4d99bf}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold}
\ No newline at end of file
!function(e,n){"use strict";function t(e){for(var n=e;n;){if(n.className&&n.className.indexOf("hljs-ln-code")!==-1)return!0;n=n.parentNode}return!1}function r(e){for(var n=e;"TABLE"!==n.nodeName;)n=n.parentNode;return n}function o(e){for(var n=e.toString(),t=e.anchorNode;"TD"!==t.nodeName;)t=t.parentNode;for(var o=e.focusNode;"TD"!==o.nodeName;)o=o.parentNode;var a=parseInt(t.dataset.lineNumber),i=parseInt(o.dataset.lineNumber);if(a!=i){var l=t.textContent,s=o.textContent;if(a>i){var c=a;a=i,i=c,c=l,l=s,s=c}for(;0!==n.indexOf(l);)l=l.slice(1);for(;n.lastIndexOf(s)===-1;)s=s.slice(0,-1);for(var d=l,u=r(t),f=a+1;f<i;++f){var h=m('.{0}[{1}="{2}"]',[b,T,f]),v=u.querySelector(h);d+="\n"+v.textContent}return d+="\n"+s}return n}function a(){var e=n.createElement("style");e.type="text/css",e.innerHTML=m(".{0}{border-collapse:collapse}.{0} td{padding:0}.{1}:before{content:attr({2})}",[N,y,T]),n.getElementsByTagName("head")[0].appendChild(e)}function i(t){"interactive"===n.readyState||"complete"===n.readyState?l(t):e.addEventListener("DOMContentLoaded",function(){l(t)})}function l(t){try{var r=n.querySelectorAll("code.hljs,code.nohighlight");for(var o in r)r.hasOwnProperty(o)&&s(r[o],t)}catch(a){e.console.error("LineNumbers error: ",a)}}function s(e,n){"object"==typeof e&&g(function(){e.innerHTML=d(e,n)})}function c(e,n){if("string"==typeof e){var t=document.createElement("code");return t.innerHTML=e,d(t,n)}}function d(e,n){n=n||{singleLine:!1};var t=n.singleLine?0:1;return f(e),u(e.innerHTML,t)}function u(e,n){var t=v(e);if(""===t[t.length-1].trim()&&t.pop(),t.length>n){for(var r="",o=0,a=t.length;o<a;o++)r+=m('<tr><td class="{0} {1}" {3}="{5}"><div class="{2}" {3}="{5}"></div></td><td class="{0} {4}" {3}="{5}">{6}</td></tr>',[L,j,y,T,b,o+1,t[o].length>0?t[o]:" "]);return m('<table class="{0}">{1}</table>',[N,r])}return e}function f(e){var n=e.childNodes;for(var t in n)if(n.hasOwnProperty(t)){var r=n[t];p(r.textContent)>0&&(r.childNodes.length>0?f(r):h(r.parentNode))}}function h(e){var n=e.className;if(/hljs-/.test(n)){for(var t=v(e.innerHTML),r=0,o="";r<t.length;r++){var a=t[r].length>0?t[r]:" ";o+=m('<span class="{0}">{1}</span>\n',[n,a])}e.innerHTML=o.trim()}}function v(e){return 0===e.length?[]:e.split(x)}function p(e){return(e.trim().match(x)||[]).length}function g(n){e.setTimeout(n,0)}function m(e,n){return e.replace(/\{(\d+)\}/g,function(e,t){return n[t]?n[t]:e})}var N="hljs-ln",L="hljs-ln-line",b="hljs-ln-code",j="hljs-ln-numbers",y="hljs-ln-n",T="data-line-number",x=/\r\n|\r|\n/g;e.hljs?(e.hljs.initLineNumbersOnLoad=i,e.hljs.lineNumbersBlock=s,e.hljs.lineNumbersValue=c,a()):e.console.error("highlight.js not detected!"),document.addEventListener("copy",function(e){var n=window.getSelection();if(t(n.anchorNode)){var r;r=window.navigator.userAgent.indexOf("Edge")!==-1?o(n):n.toString(),e.clipboardData.setData("text/plain",r),e.preventDefault()}})}(window,document);
\ No newline at end of file
......@@ -15,6 +15,7 @@ public class Blog {
private String blogAbstract;
private String cover;
private String originLink;
private String contentHtml;
private String viewPrivileges;
private String allowComment;
private String allowForward;
......
......@@ -24,4 +24,6 @@ public interface IBlogRepository {
void makeCategoriesCache(List<BlogCategory> data);
LiveData<Result<Page<Blog>>> fetchHotBlogList(Integer page, int pageSize);
LiveData<Result<Blog>> getBlog(String blogId);
}
......@@ -53,4 +53,9 @@ public class BlogRepositoryImpl implements IBlogRepository {
public LiveData<Result<Page<Blog>>> fetchHotBlogList(Integer page, int pageSize) {
return blogApiStore.getHotBlogList(page, pageSize);
}
@Override
public LiveData<Result<Blog>> getBlog(String blogId) {
return blogApiStore.getBlog(blogId);
}
}
......@@ -9,6 +9,7 @@ import cn.yunliyunwai.beyondclouds.data.model.BlogCategory;
import cn.yunliyunwai.beyondclouds.data.model.Page;
import cn.yunliyunwai.beyondclouds.data.model.Result;
import retrofit2.http.GET;
import retrofit2.http.Path;
import retrofit2.http.Query;
public interface BlogApiStore {
......@@ -23,4 +24,7 @@ public interface BlogApiStore {
@GET("blog/hots")
LiveData<Result<Page<Blog>>> getHotBlogList( @Query("page") Integer page,
@Query("size") int pageSize);
@GET("blog/{blogId}")
LiveData<Result<Blog>> getBlog(@Path("blogId") String blogId);
}
package cn.yunliyunwai.beyondclouds.ui.blog;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import javax.inject.Inject;
import cn.yunliyunwai.beyondclouds.R;
import cn.yunliyunwai.beyondclouds.base.BaseActivity;
import cn.yunliyunwai.beyondclouds.databinding.ActivityBlogDetailBinding;
import cn.yunliyunwai.beyondclouds.util.ContextUtils;
import cn.yunliyunwai.beyondclouds.util.StatusBarUtils;
import cn.yunliyunwai.beyondclouds.viewmodel.BlogDetailViewModel;
public class BlogDetailActivity extends BaseActivity<BlogDetailViewModel, ActivityBlogDetailBinding> {
public static final String ARG_BLOG_ID = "BLOG_ID";
private String blogId;
@Inject
ViewModelProvider.Factory factory;
......@@ -32,4 +43,49 @@ public class BlogDetailActivity extends BaseActivity<BlogDetailViewModel, Activi
protected ActivityBlogDetailBinding initDataBinding(LayoutInflater inflater) {
return ActivityBlogDetailBinding.inflate(inflater);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
StatusBarUtils.setWindowStatusBarColor(this, R.color.colorStatusBar);
blogId = getIntent().getStringExtra(ARG_BLOG_ID);
initEventListenersAndObservers();
}
private void initEventListenersAndObservers() {
binding.toolBar.setOnLeftIconClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
WebView webView = binding.webViewBlogDetail;
webView.loadUrl("file:///android_asset/pages/article.html");
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
viewModel.webViewPageFinished();
}
});
viewModel.getLoadState().observe(this, new Observer<BlogDetailViewModel.LoadState>() {
@Override
public void onChanged(BlogDetailViewModel.LoadState loadState) {
if (loadState.isLoadComplete()) {
webView.loadUrl("javascript:loadArticleContent(`" + viewModel.getBlog().getContentHtml() + "`)");
}
}
});
viewModel.fetchBlog(blogId);
}
}
......@@ -30,7 +30,7 @@ public class LoginActivity extends BaseActivity<AuthenticationViewModel, Activit
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
overridePendingTransition(R.anim.bottom_enter, R.anim.bottom_exit);
overridePendingTransition(R.anim.bottom_enter, 0);
StatusBarUtils.setWindowStatusBarColor(this, R.color.colorStatusBar);
initEventListener();
}
......@@ -139,4 +139,10 @@ public class LoginActivity extends BaseActivity<AuthenticationViewModel, Activit
binding.setLifecycleOwner(this);
return binding;
}
@Override
public void finish() {
super.finish();
overridePendingTransition(0, R.anim.bottom_exit);
}
}
package cn.yunliyunwai.beyondclouds.viewmodel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModel;
import javax.inject.Inject;
import cn.yunliyunwai.beyondclouds.data.model.Blog;
import cn.yunliyunwai.beyondclouds.data.model.Result;
import cn.yunliyunwai.beyondclouds.data.source.IBlogRepository;
import lombok.Data;
public class BlogDetailViewModel extends ViewModel {
@Data
public static class LoadState {
private boolean dataLoadComplete;
private boolean webViewPageLoadComplete;
public boolean isLoadComplete() {
return dataLoadComplete
&& webViewPageLoadComplete;
}
}
private IBlogRepository blogRepository;
private Blog mBlog;
private MutableLiveData<LoadState> loadState = new MutableLiveData<>();
@Inject
public BlogDetailViewModel() {
public BlogDetailViewModel(IBlogRepository blogRepository) {
this.blogRepository = blogRepository;
loadState.setValue(new LoadState());
}
public Blog getBlog() {
return mBlog;
}
public LiveData<LoadState> getLoadState() {
return loadState;
}
public void fetchBlog(String blogId) {
blogRepository.getBlog(blogId).observeForever(new Observer<Result<Blog>>() {
@Override
public void onChanged(Result<Blog> blogResult) {
if (blogResult.getCode() == 0) {
mBlog = blogResult.getData();
LoadState state = loadState.getValue();
state.setDataLoadComplete(true);
loadState.setValue(state);
}
}
});
}
public void webViewPageFinished() {
LoadState state = loadState.getValue();
state.setWebViewPageLoadComplete(true);
loadState.setValue(state);
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="cn.yunliyunwai.beyondclouds.viewmodel.AuthenticationViewModel.LoginWay" />
<import type="android.text.InputType" />
......@@ -14,5 +15,24 @@
android:layout_height="match_parent"
android:background="@color/colorWhite"
tools:context=".ui.login.LoginActivity">
<cn.yunliyunwai.beyondclouds.view.BeyondToolBar
android:id="@+id/tool_bar"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:leftIcon="@string/icon_back"
app:title="博客详情"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<WebView
android:id="@+id/web_view_blog_detail"
android:overScrollMode="never"
app:layout_constraintTop_toBottomOf="@id/tool_bar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_width="match_parent"
android:layout_height="0dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
\ No newline at end of file
......@@ -11,11 +11,13 @@
android:textColor="@color/colorTextLevel4"
android:layout_marginStart="12dp"
android:layout_marginLeft="12dp"
android:background="@drawable/background_white_touchable"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:gravity="center_vertical|start"
android:layout_width="42dp"
android:layout_height="42dp" />
<TextView
android:id="@+id/txt_title"
......@@ -35,11 +37,12 @@
app:layout_constraintBottom_toBottomOf="parent"
android:textSize="14dp"
android:textColor="@color/colorTextLevel4"
android:background="@null"
android:layout_marginEnd="12dp"
android:layout_marginRight="12dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:background="@drawable/background_white_touchable"
android:gravity="center_vertical|end"
android:layout_width="42dp"
android:layout_height="42dp" />
<View
android:id="@+id/line_bottom"
......
......@@ -15,6 +15,7 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:overScrollMode="never"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none" />
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment