Browse Source

1.重写学习详情页面
2.使用EXO播放视频
3.使用vue-office和pptxjs预览文档
4.本地编写js并使用原生webview加载
5.完善文档预览的生命周期

JaycePC 11 months ago
parent
commit
bf66474350
48 changed files with 18666 additions and 315 deletions
  1. 16 17
      HttpCoreLibrary/build.gradle
  2. 9 10
      RcCore/build.gradle
  3. 1 1
      RcCore/src/main/java/com/rc/core/ui/activity/RcRefreshActivity.kt
  4. 1 1
      RcCore/src/main/java/com/rc/core/util/EscapeUnescape.java
  5. 35 39
      app/build.gradle
  6. 9 4
      app/src/main/AndroidManifest.xml
  7. 159 0
      app/src/main/assets/web/index.html
  8. 1 0
      app/src/main/assets/web/js-preview-lib/docx.css
  9. 1 0
      app/src/main/assets/web/js-preview-lib/docx.umd.js
  10. 762 0
      app/src/main/assets/web/js-preview-lib/excel.css
  11. 43 0
      app/src/main/assets/web/js-preview-lib/excel.umd.js
  12. 1 0
      app/src/main/assets/web/js-preview-lib/pdf.umd.js
  13. 10 0
      app/src/main/assets/web/js-preview-lib/vconsole.min.js
  14. 2 0
      app/src/main/assets/web/pptx-js-1.21.1/css/nv.d3.min.css
  15. 161 0
      app/src/main/assets/web/pptx-js-1.21.1/css/pptxjs.css
  16. 5 0
      app/src/main/assets/web/pptx-js-1.21.1/js/d3.min.js
  17. 872 0
      app/src/main/assets/web/pptx-js-1.21.1/js/dingbat.js
  18. 517 0
      app/src/main/assets/web/pptx-js-1.21.1/js/divs2slides.js
  19. 12 0
      app/src/main/assets/web/pptx-js-1.21.1/js/divs2slides.min.js
  20. 455 0
      app/src/main/assets/web/pptx-js-1.21.1/js/filereader.js
  21. 5 0
      app/src/main/assets/web/pptx-js-1.21.1/js/jquery-1.11.3.min.js
  22. 10 0
      app/src/main/assets/web/pptx-js-1.21.1/js/jquery.fullscreen-min.js
  23. 14 0
      app/src/main/assets/web/pptx-js-1.21.1/js/jszip.min.js
  24. 10 0
      app/src/main/assets/web/pptx-js-1.21.1/js/nv.d3.min.js
  25. 14104 0
      app/src/main/assets/web/pptx-js-1.21.1/js/pptxjs.js
  26. 10 0
      app/src/main/assets/web/pptx-js-1.21.1/js/pptxjs.min.js
  27. 2 3
      app/src/main/java/com/dlc/exam/ExamApp.kt
  28. 2 2
      app/src/main/java/com/dlc/exam/ui/MainActivity.kt
  29. 1 1
      app/src/main/java/com/dlc/exam/ui/exam/MockExamActivity.kt
  30. 44 12
      app/src/main/java/com/dlc/exam/ui/learn/CourseChapterActivity.kt
  31. 9 6
      app/src/main/java/com/dlc/exam/ui/learn/LearnCompletedDialog.kt
  32. 169 31
      app/src/main/java/com/dlc/exam/ui/learn/LearnDetailActivity.kt
  33. 232 0
      app/src/main/java/com/dlc/exam/ui/learn/LearnDetailExoActivity.java
  34. 368 0
      app/src/main/java/com/dlc/exam/ui/learn/LearnDetailWebActivity.java
  35. 2 2
      app/src/main/java/com/dlc/exam/ui/learn/test/ClassTestRecordActivity.kt
  36. 3 3
      app/src/main/java/com/dlc/exam/ui/me/PersonalCenterActivity.kt
  37. 139 139
      app/src/main/java/com/dlc/exam/ui/widget/ExamJzvdStd.kt
  38. 57 0
      app/src/main/java/com/dlc/exam/ui/widget/JsInterface.java
  39. 40 0
      app/src/main/java/com/dlc/exam/ui/widget/MessageEvent.java
  40. 12 8
      app/src/main/res/layout/activity_learn_detail.xml
  41. 120 0
      app/src/main/res/layout/activity_learn_detail_exo.xml
  42. 119 0
      app/src/main/res/layout/activity_learn_detail_web.xml
  43. 1 1
      app/src/main/res/layout/dialog_learn_completed.xml
  44. 4 30
      build.gradle
  45. 1 4
      config/config.gradle
  46. 1 1
      gradle.properties
  47. 60 0
      gradle/libs.versions.toml
  48. 55 0
      settings.gradle

+ 16 - 17
HttpCoreLibrary/build.gradle

@@ -1,6 +1,6 @@
 plugins {
 plugins {
-    id 'com.android.library'
-    id 'kotlin-android'
+    alias(libs.plugins.android.library)
+    alias(libs.plugins.kotlin.android)
 }
 }
 
 
 android {
 android {
@@ -20,11 +20,11 @@ android {
         }
         }
     }
     }
     compileOptions {
     compileOptions {
-        sourceCompatibility env.jdk_version
-        targetCompatibility env.jdk_version
+        sourceCompatibility JavaVersion.VERSION_17
+        targetCompatibility JavaVersion.VERSION_17
     }
     }
     kotlinOptions {
     kotlinOptions {
-        jvmTarget = '1.8'
+        jvmTarget = '17'
     }
     }
     namespace 'com.rc.httpcore'
     namespace 'com.rc.httpcore'
 }
 }
@@ -32,18 +32,17 @@ android {
 dependencies {
 dependencies {
 
 
     implementation fileTree(dir: "libs", include: ["*.jar"])
     implementation fileTree(dir: "libs", include: ["*.jar"])
-    implementation dep.kotlinStdlib
-    implementation dep.androidxCoreKtx
-    implementation dep.androidxLocalbroadcastmanager
-
-    api dep.retrofit
-    implementation dep.converterGson
-    implementation dep.converterScalars
-    implementation dep.rxJavaAdapter
-    implementation dep.okhttp3Logs
-    api dep.rxJava
-    api dep.rxAndroid
-    api dep.gson
+    implementation libs.androidx.core.ktx
+    implementation libs.androidx.localbroadcastmanager
+
+    api libs.squareup.retrofit
+    implementation libs.squareup.converter.gson
+    implementation libs.squareup.converter.scalars
+    implementation libs.squareup.rx.java.adapter
+    implementation libs.okhttp3.logging
+    api libs.rx.java
+    api libs.rx.android
+    api libs.gson
 
 
 //    implementation dep.luban
 //    implementation dep.luban
 }
 }

+ 9 - 10
RcCore/build.gradle

@@ -20,11 +20,11 @@ android {
         }
         }
     }
     }
     compileOptions {
     compileOptions {
-        sourceCompatibility env.jdk_version
-        targetCompatibility env.jdk_version
+        sourceCompatibility JavaVersion.VERSION_17
+        targetCompatibility JavaVersion.VERSION_17
     }
     }
     kotlinOptions {
     kotlinOptions {
-        jvmTarget = '1.8'
+        jvmTarget = '17'
     }
     }
     buildFeatures{
     buildFeatures{
         viewBinding = true
         viewBinding = true
@@ -38,14 +38,13 @@ dependencies {
     implementation project(':HttpCoreLibrary')
     implementation project(':HttpCoreLibrary')
 
 
     api fileTree(dir: "libs", include: ["*.jar"])
     api fileTree(dir: "libs", include: ["*.jar"])
-    implementation dep.kotlinStdlib
-    implementation dep.androidxCoreKtx
-    implementation dep.androidxSwipeRefreshLayout
+    implementation libs.androidx.core.ktx
+    implementation libs.androidx.swiperefreshlayout
 
 
-    implementation dep.androidxAppCompat
-    implementation dep.androidMaterial
-    implementation dep.RecyclerViewAdapterHelper
+    implementation libs.androidx.appcompat
+    implementation libs.material
+    implementation libs.recycler.adapter.helper4
 
 
-    implementation dep.eventbus
+    implementation libs.eventbus
 
 
 }
 }

+ 1 - 1
RcCore/src/main/java/com/rc/core/ui/activity/RcRefreshActivity.kt

@@ -126,7 +126,7 @@ constructor(val mAdapter: BaseQuickAdapter<T, BaseViewHolder>) : RcBaseActivity<
         if (mRefresh) {
         if (mRefresh) {
             if (null == data || data.isEmpty()) {
             if (null == data || data.isEmpty()) {
                 if (null == mMultipleStatusView) {
                 if (null == mMultipleStatusView) {
-                    mAdapter.setEmptyView(R.layout.view_list_empty)
+                    mAdapter.setEmptyView(com.rc.core.R.layout.view_list_empty)
                 } else {
                 } else {
                     mMultipleStatusView!!.showEmpty()
                     mMultipleStatusView!!.showEmpty()
                 }
                 }

+ 1 - 1
RcCore/src/main/java/com/rc/core/util/EscapeUnescape.java

@@ -28,7 +28,7 @@ public class EscapeUnescape {
     }
     }
 
 
     public static String unescape(String src) {
     public static String unescape(String src) {
-        StringBuffer tmp = new StringBuffer();
+        StringBuilder tmp = new StringBuilder();
         tmp.ensureCapacity(src.length());
         tmp.ensureCapacity(src.length());
         int lastPos = 0, pos = 0;
         int lastPos = 0, pos = 0;
         char ch;
         char ch;

+ 35 - 39
app/build.gradle

@@ -1,17 +1,18 @@
 plugins {
 plugins {
-    id 'com.android.application'
-    id 'kotlin-android'
+    alias(libs.plugins.android.application)
+    alias(libs.plugins.kotlin.android)
 }
 }
 
 
 android {
 android {
+    namespace 'com.dlc.exam'
     compileSdk 34
     compileSdk 34
 
 
     defaultConfig {
     defaultConfig {
-        applicationId env.applicationId
-        minSdkVersion 21
+        applicationId "com.dlc.exam"
+        minSdkVersion 24
         targetSdkVersion 34
         targetSdkVersion 34
-        versionCode env.versionCode
-        versionName env.versionName
+        versionCode 110
+        versionName "1.1.0-alpha"
 
 
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
 
 
@@ -20,6 +21,10 @@ android {
         }
         }
     }
     }
 
 
+    buildFeatures {
+        viewBinding true
+    }
+
     signingConfigs {
     signingConfigs {
         signing {
         signing {
             keyAlias 'winds'
             keyAlias 'winds'
@@ -44,19 +49,11 @@ android {
         }
         }
     }
     }
     compileOptions {
     compileOptions {
-        sourceCompatibility env.jdk_version
-        targetCompatibility env.jdk_version
+        sourceCompatibility JavaVersion.VERSION_17
+        targetCompatibility JavaVersion.VERSION_17
     }
     }
     kotlinOptions {
     kotlinOptions {
-        jvmTarget = '1.8'
-    }
-    kotlin {
-        experimental {
-            coroutines 'enable'
-        }
-    }
-    viewBinding {
-        enabled = true
+        jvmTarget = '17'
     }
     }
     namespace 'com.dlc.exam'
     namespace 'com.dlc.exam'
     applicationVariants.all { variant ->
     applicationVariants.all { variant ->
@@ -75,26 +72,25 @@ dependencies {
     implementation project(':HttpCoreLibrary')
     implementation project(':HttpCoreLibrary')
     implementation project(':RcCore')
     implementation project(':RcCore')
 
 
-    implementation dep.kotlinStdlib
-    implementation dep.androidxCoreKtx
-    implementation dep.androidxAppCompat
-    implementation dep.androidxConstraintlayout
-    implementation dep.androidMaterial
-    implementation dep.androidxLocalbroadcastmanager
-    implementation dep.rxpermissions
-    implementation dep.androidxSwipeRefreshLayout
-    implementation dep.RecyclerViewAdapterHelper
-    implementation dep.glide
-
-    implementation dep.kotlinxCoroutinesCore
-    implementation dep.kotlinxCoroutinesAndroid
-
-    implementation dep.androidMultidex
-    implementation dep.buglySDK
-    implementation dep.buglyNDK
-    implementation dep.mqttv3
-    implementation dep.eventbus
-    implementation dep.bgaZxing
+    implementation libs.androidx.core.ktx
+    implementation libs.androidx.appcompat
+    implementation libs.androidx.constraintlayout
+    implementation libs.material
+    implementation libs.androidx.localbroadcastmanager
+    implementation libs.androidx.activity
+
+    implementation libs.rxpermissions
+    implementation libs.androidx.swiperefreshlayout
+
+    implementation libs.recycler.adapter.helper4
+    implementation libs.glide
+
+    implementation libs.androidx.multidex
+//    implementation dep.buglySDK
+//    implementation dep.buglyNDK
+    implementation libs.mqttv3
+    implementation libs.eventbus
+    implementation libs.bgaZxing
 
 
     // CameraX core library using the camera2 implementation
     // CameraX core library using the camera2 implementation
     def camerax_version = "1.0.1"
     def camerax_version = "1.0.1"
@@ -108,8 +104,8 @@ dependencies {
     // If you want to additionally use the CameraX Extensions library
     // If you want to additionally use the CameraX Extensions library
     implementation "androidx.camera:camera-extensions:1.0.0-alpha20"
     implementation "androidx.camera:camera-extensions:1.0.0-alpha20"
 
 
-    implementation 'cn.jzvd:jiaozivideoplayer:7.7.0'
-
     implementation 'com.google.android.exoplayer:exoplayer:2.18.1'
     implementation 'com.google.android.exoplayer:exoplayer:2.18.1'
 
 
+    implementation("androidx.webkit:webkit:1.6.0")
+    implementation 'com.blankj:utilcodex:1.31.1'
 }
 }

+ 9 - 4
app/src/main/AndroidManifest.xml

@@ -43,7 +43,12 @@
         android:theme="@style/Theme.AppFullTheme"
         android:theme="@style/Theme.AppFullTheme"
         android:usesCleartextTraffic="true"
         android:usesCleartextTraffic="true"
         tools:targetApi="m">
         tools:targetApi="m">
-
+        <activity
+            android:name=".ui.learn.LearnDetailExoActivity"
+            android:exported="false" />
+        <activity
+            android:name=".ui.learn.LearnDetailWebActivity"
+            android:exported="false" />
 
 
         <receiver
         <receiver
             android:name=".broadcast.BootBroadcastReceiver"
             android:name=".broadcast.BootBroadcastReceiver"
@@ -180,9 +185,9 @@
                 android:resource="@xml/file_paths_public" />
                 android:resource="@xml/file_paths_public" />
         </provider>
         </provider>
 
 
-        <receiver android:name=".receiver.OpenApkReceiver"
-            android:exported="true"
-            >
+        <receiver
+            android:name=".receiver.OpenApkReceiver"
+            android:exported="true">
             <intent-filter>
             <intent-filter>
                 <action android:name="android.intent.action.PACKAGE_REPLACED" />
                 <action android:name="android.intent.action.PACKAGE_REPLACED" />
 
 

+ 159 - 0
app/src/main/assets/web/index.html

@@ -0,0 +1,159 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>文档查看</title>
+    <link rel="stylesheet" href="js-preview-lib/docx.css"/>
+    <link rel="stylesheet" href="js-preview-lib/excel.css"/>
+    <style>
+        .loader_box {
+            display: flex;
+            align-items: center;
+            justify-self: center;
+            flex-direction: column;
+            margin-top: 10%;
+        }
+        .loader {
+            border: 5px solid #f3f3f3;
+            border-top: 5px solid #3498db;
+            border-radius: 50%;
+            width: 50px;
+            height: 50px;
+            animation: spin 2s linear infinite;
+            margin: 50px auto;
+        }
+        @keyframes spin {
+            0% {
+                transform: rotate(0deg);
+            }
+            100% {
+                transform: rotate(360deg);
+            }
+        }
+    </style>
+    <script src="js-preview-lib/pdf.umd.js"></script>
+    <script src="js-preview-lib/docx.umd.js"></script>
+    <script src="js-preview-lib/excel.umd.js"></script>
+    <script src="js-preview-lib/vconsole.min.js"></script>
+
+    <link rel="stylesheet" href="./pptx-js-1.21.1/css/pptxjs.css">
+    <link rel="stylesheet" href="./pptx-js-1.21.1/css/nv.d3.min.css">
+
+    <script type="text/javascript" src="./pptx-js-1.21.1/js/jquery-1.11.3.min.js"></script>
+    <script type="text/javascript" src="./pptx-js-1.21.1/js/jszip.min.js"></script>
+    <script type="text/javascript" src="./pptx-js-1.21.1/js/filereader.js"></script>
+    <script type="text/javascript" src="./pptx-js-1.21.1/js/d3.min.js"></script>
+    <script type="text/javascript" src="./pptx-js-1.21.1/js/nv.d3.min.js"></script>
+    <script type="text/javascript" src="./pptx-js-1.21.1/js/pptxjs.js"></script>
+    <script type="text/javascript" src="./pptx-js-1.21.1/js/divs2slides.js"></script>
+</head>
+
+<body>
+<div id="previewBox" style="width: 100vw; height: 100vh"></div>
+
+</body>
+<script>
+    var vConsole = new window.VConsole();
+
+    function openPPT(path) {
+        console.log("### ppt入参:", path);
+        // Docs:https://pptx.js.org/pages/docs.html
+        $("#previewBox").pptxToHtml({
+            pptxFileUrl: path,
+            fileInputId: "uploadFileInput",
+            slideMode: true,
+            keyBoardShortCut: true,
+            slideModeConfig: {
+                first: 1,
+                nav: true,
+                navTxtColor: "white",
+                navNextTxt: "&#8250;",
+                navPrevTxt: "&#8249;",
+                showPlayPauseBtn: true,
+                keyBoardShortCut: true,
+                mediaProcess: false,
+                showSlideNum: true,
+                showTotalSlideNum: true,
+                autoSlide: true,
+                randomAutoSlide: false,
+                loop: false,
+                background: "black",
+                transition: "default",
+                transitionTime: 1
+            }
+        });
+         Android.webCallBack('office_ppt','预览完成')
+    }
+//     openPPT("http://metersphere.zjznai.com/labSystem/statics/bigFile/2024091317/45906dad-4fa0-4782-a9ba-7c2e03883586.pptx")
+
+    var objPreviewer = null;
+
+    function openPDF(path) {
+        console.log("### pdf入参:", path);
+        objPreviewer = jsPreviewPdf.init(document.getElementById('previewBox'), {
+            onError: (e) => {
+                console.log('发生错误', JSON.stringify(e))
+                Android.webCallBack('office_pdf',JSON.stringify(e))
+            },
+            onRendered: () => {
+               console.log('渲染完成')
+               Android.webCallBack('office_pdf','预览完成')
+            }
+        });
+        objPreviewer.preview(path)
+    }
+    //openPDF("http://192.168.1.43:81/666/pdf.pdf")
+
+    function openWORD(path) {
+        console.log("### word入参:", path);
+        objPreviewer = jsPreviewDocx.init(document.getElementById('previewBox'));
+        //传递要预览的文件地址即可
+        objPreviewer.preview(path).then(() => {
+            console.log('预览完成');
+            Android.webCallBack('office_doc',"预览完成")
+        }).catch(e => {
+            console.log('预览失败', JSON.stringify(e));
+            Android.webCallBack('office_doc',JSON.stringify(e))
+        })
+    }
+    //openWORD("http://static.shanhuxueyuan.com/test6.docx")
+
+    function openEXCEL(path) {
+        console.log("### excel入参:", path);
+        objPreviewer = jsPreviewExcel.init(document.getElementById('previewBox'));
+        objPreviewer.preview(path).then(() => {
+            console.log('预览完成');
+            Android.webCallBack('office_excel',"预览完成")
+        }).catch(e => {
+            console.log('预览失败', JSON.stringify(e));
+            Android.webCallBack('office_excel',JSON.stringify(e))
+        })
+    }
+    // openEXCEL("http://static.shanhuxueyuan.com/demo/excel.xlsx")
+
+    function objPreviewerDestroy() {
+        if (objPreviewer) objPreviewer.destroy();
+    }
+
+    function openIMG(path) {
+        console.log("### img入参:", path);
+        document.getElementById("previewBox").innerHTML = '<div class="loader_box"><div class="loader"></div><div>图片加载中...</div></div>';
+        var img = new Image();
+        img.src = path;
+        img.onload = function () {
+            document.getElementById("previewBox").innerHTML = '<img style="width:' + img.width + 'px;height:' + img.height + 'px;" src="' + path + '" />';
+            Android.webCallBack('big_pic',"预览完成")
+        };
+        img.onerror = function () {
+            document.getElementById("previewBox").innerHTML = '<div class="loader_box">图片加载失败!</div>';
+            Android.webCallBack('big_pic',"图片加载失败")
+        };
+    }
+//     openIMG("https://images.wallpaperscraft.com/image/single/corgi_dog_pet_1321271_3840x2400.jpg")
+
+
+</script>
+
+</html>

+ 1 - 0
app/src/main/assets/web/js-preview-lib/docx.css

@@ -0,0 +1 @@
+.vue-office-docx{height:100%;overflow-y:auto}.vue-office-docx .docx-wrapper>section.docx{margin-bottom:5px}@media screen and (max-width: 800px){.vue-office-docx .docx-wrapper{padding:10px}.vue-office-docx .docx-wrapper>section.docx{padding:10px!important;width:100%!important}}

File diff suppressed because it is too large
+ 1 - 0
app/src/main/assets/web/js-preview-lib/docx.umd.js


+ 762 - 0
app/src/main/assets/web/js-preview-lib/excel.css

@@ -0,0 +1,762 @@
+.x-spreadsheet {
+  font-size: 13px;
+  line-height: normal;
+  user-select: none;
+  -moz-user-select: none;
+  font-family: 'Lato', 'Source Sans Pro', Roboto, Helvetica, Arial, sans-serif;
+  box-sizing: content-box;
+  background: #fff;
+  -webkit-font-smoothing: antialiased;
+}
+.x-spreadsheet textarea {
+  font: 400 13px Arial, 'Lato', 'Source Sans Pro', Roboto, Helvetica, sans-serif;
+}
+.x-spreadsheet-sheet {
+  position: relative;
+  overflow: hidden;
+}
+.x-spreadsheet-table {
+  vertical-align: bottom;
+}
+.x-spreadsheet-tooltip {
+  font-family: inherit;
+  position: absolute;
+  padding: 5px 10px;
+  color: #fff;
+  border-radius: 1px;
+  background: #000000;
+  font-size: 12px;
+  z-index: 201;
+}
+.x-spreadsheet-tooltip:before {
+  pointer-events: none;
+  position: absolute;
+  left: calc(50% - 4px);
+  top: -4px;
+  content: "";
+  width: 8px;
+  height: 8px;
+  background: inherit;
+  -webkit-transform: rotate(45deg);
+  transform: rotate(45deg);
+  z-index: 1;
+  box-shadow: 1px 1px 3px -1px rgba(0, 0, 0, 0.3);
+}
+.x-spreadsheet-color-palette {
+  padding: 5px;
+}
+.x-spreadsheet-color-palette table {
+  margin: 0;
+  padding: 0;
+  border-collapse: separate;
+  border-spacing: 2;
+  background: #fff;
+}
+.x-spreadsheet-color-palette table td {
+  margin: 0;
+  cursor: pointer;
+  border: 1px solid transparent;
+}
+.x-spreadsheet-color-palette table td:hover {
+  border-color: #ddd;
+}
+.x-spreadsheet-color-palette table td .x-spreadsheet-color-palette-cell {
+  width: 16px;
+  height: 16px;
+}
+.x-spreadsheet-border-palette {
+  padding: 6px;
+}
+.x-spreadsheet-border-palette table {
+  margin: 0;
+  padding: 0;
+  border-collapse: separate;
+  border-spacing: 0;
+  background: #fff;
+  table-layout: fixed;
+}
+.x-spreadsheet-border-palette table td {
+  margin: 0;
+}
+.x-spreadsheet-border-palette .x-spreadsheet-border-palette-left {
+  border-right: 1px solid #eee;
+  padding-right: 6px;
+}
+.x-spreadsheet-border-palette .x-spreadsheet-border-palette-left .x-spreadsheet-border-palette-cell {
+  width: 30px;
+  height: 30px;
+  cursor: pointer;
+  text-align: center;
+}
+.x-spreadsheet-border-palette .x-spreadsheet-border-palette-left .x-spreadsheet-border-palette-cell:hover {
+  background-color: #eee;
+}
+.x-spreadsheet-border-palette .x-spreadsheet-border-palette-right {
+  padding-left: 6px;
+}
+.x-spreadsheet-border-palette .x-spreadsheet-border-palette-right .x-spreadsheet-line-type {
+  position: relative;
+  left: 0;
+  top: -3px;
+}
+.x-spreadsheet-dropdown {
+  position: relative;
+}
+.x-spreadsheet-dropdown .x-spreadsheet-dropdown-content {
+  position: absolute;
+  z-index: 200;
+  background: #fff;
+  box-shadow: 1px 2px 5px 2px rgba(51, 51, 51, 0.15);
+}
+.x-spreadsheet-dropdown.bottom-left .x-spreadsheet-dropdown-content {
+  top: calc(100% + 5px);
+  left: 0;
+}
+.x-spreadsheet-dropdown.bottom-right .x-spreadsheet-dropdown-content {
+  top: calc(100% + 5px);
+  right: 0;
+}
+.x-spreadsheet-dropdown.top-left .x-spreadsheet-dropdown-content {
+  bottom: calc(100% + 5px);
+  left: 0;
+}
+.x-spreadsheet-dropdown.top-right .x-spreadsheet-dropdown-content {
+  bottom: calc(100% + 5px);
+  right: 0;
+}
+.x-spreadsheet-dropdown .x-spreadsheet-dropdown-title {
+  padding: 0 5px;
+  display: inline-block;
+}
+/* resizer **/
+.x-spreadsheet-resizer {
+  position: absolute;
+  z-index: 11;
+}
+.x-spreadsheet-resizer .x-spreadsheet-resizer-hover {
+  background-color: rgba(75, 137, 255, 0.25);
+}
+.x-spreadsheet-resizer .x-spreadsheet-resizer-line {
+  position: absolute;
+}
+.x-spreadsheet-resizer.horizontal {
+  cursor: row-resize;
+}
+.x-spreadsheet-resizer.horizontal .x-spreadsheet-resizer-line {
+  border-bottom: 2px dashed #4b89ff;
+  left: 0;
+  bottom: 0;
+}
+.x-spreadsheet-resizer.vertical {
+  cursor: col-resize;
+}
+.x-spreadsheet-resizer.vertical .x-spreadsheet-resizer-line {
+  border-right: 2px dashed #4b89ff;
+  top: 0;
+  right: 0;
+}
+/* scrollbar */
+.x-spreadsheet-scrollbar {
+  position: absolute;
+  bottom: 0;
+  right: 0;
+  background-color: #f4f5f8;
+  opacity: 0.9;
+  z-index: 12;
+}
+.x-spreadsheet-scrollbar.horizontal {
+  right: 15px;
+  overflow-x: scroll;
+  overflow-y: hidden;
+}
+.x-spreadsheet-scrollbar.horizontal > div {
+  height: 1px;
+  background: #ddd;
+}
+.x-spreadsheet-scrollbar.vertical {
+  bottom: 15px;
+  overflow-x: hidden;
+  overflow-y: scroll;
+}
+.x-spreadsheet-scrollbar.vertical > div {
+  width: 1px;
+  background: #ddd;
+}
+/* @{css-prefix}-overlayer */
+.x-spreadsheet-overlayer {
+  position: absolute;
+  left: 0;
+  top: 0;
+  z-index: 10;
+}
+.x-spreadsheet-overlayer .x-spreadsheet-overlayer-content {
+  position: absolute;
+  overflow: hidden;
+  pointer-events: none;
+  width: 100%;
+  height: 100%;
+}
+.x-spreadsheet-editor,
+.x-spreadsheet-selector {
+  box-sizing: content-box;
+  position: absolute;
+  overflow: hidden;
+  pointer-events: none;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+}
+/* @{css-prefix}-selector */
+.x-spreadsheet-selector .hide-input {
+  position: absolute;
+  z-index: 0;
+}
+.x-spreadsheet-selector .hide-input input {
+  padding: 0;
+  width: 0;
+  border: none!important;
+}
+.x-spreadsheet-selector .x-spreadsheet-selector-area {
+  position: absolute;
+  border: 2px solid #4b89ff;
+  background: rgba(75, 137, 255, 0.1);
+  z-index: 5;
+}
+.x-spreadsheet-selector .x-spreadsheet-selector-clipboard,
+.x-spreadsheet-selector .x-spreadsheet-selector-autofill {
+  position: absolute;
+  background: transparent;
+  z-index: 100;
+}
+.x-spreadsheet-selector .x-spreadsheet-selector-clipboard {
+  border: 2px dashed #4b89ff;
+}
+.x-spreadsheet-selector .x-spreadsheet-selector-autofill {
+  border: 1px dashed rgba(0, 0, 0, 0.45);
+}
+.x-spreadsheet-selector .x-spreadsheet-selector-corner {
+  pointer-events: auto;
+  position: absolute;
+  cursor: crosshair;
+  font-size: 0;
+  height: 5px;
+  width: 5px;
+  right: -5px;
+  bottom: -5px;
+  border: 2px solid #ffffff;
+  background: #4b89ff;
+}
+.x-spreadsheet-editor {
+  z-index: 20;
+}
+.x-spreadsheet-editor .x-spreadsheet-editor-area {
+  position: absolute;
+  text-align: left;
+  border: 2px solid #4b89ff;
+  line-height: 0;
+  z-index: 100;
+  pointer-events: auto;
+}
+.x-spreadsheet-editor .x-spreadsheet-editor-area textarea {
+  box-sizing: content-box;
+  border: none;
+  padding: 0 3px;
+  outline: none;
+  resize: none;
+  text-align: start;
+  overflow-y: hidden;
+  font: 400 13px Arial, 'Lato', 'Source Sans Pro', Roboto, Helvetica, sans-serif;
+  color: inherit;
+  white-space: normal;
+  word-wrap: break-word;
+  line-height: 22px;
+  margin: 0;
+}
+.x-spreadsheet-editor .x-spreadsheet-editor-area .textline {
+  overflow: hidden;
+  visibility: hidden;
+  position: fixed;
+  top: 0;
+  left: 0;
+}
+.x-spreadsheet-item {
+  user-select: none;
+  background: 0;
+  border: 1px solid transparent;
+  outline: none;
+  height: 26px;
+  color: rgba(0, 0, 0, 0.9);
+  line-height: 26px;
+  list-style: none;
+  padding: 2px 10px;
+  cursor: default;
+  text-align: left;
+  overflow: hidden;
+}
+.x-spreadsheet-item.disabled {
+  pointer-events: none;
+  opacity: 0.5;
+}
+.x-spreadsheet-item:hover,
+.x-spreadsheet-item.active {
+  background: rgba(0, 0, 0, 0.05);
+}
+.x-spreadsheet-item.divider {
+  height: 0;
+  padding: 0;
+  margin: 5px 0;
+  border: none;
+  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+}
+.x-spreadsheet-item .label {
+  float: right;
+  opacity: 0.65;
+  font-size: 1em;
+}
+.x-spreadsheet-item.state,
+.x-spreadsheet-header.state {
+  padding-left: 35px!important;
+  position: relative;
+}
+.x-spreadsheet-item.state:before,
+.x-spreadsheet-header.state:before {
+  content: '';
+  position: absolute;
+  width: 10px;
+  height: 10px;
+  left: 12px;
+  top: calc(50% - 5px);
+  background: rgba(0, 0, 0, 0.08);
+  border-radius: 2px;
+}
+.x-spreadsheet-item.state.checked:before,
+.x-spreadsheet-header.state.checked:before {
+  background: #4b89ff;
+}
+.x-spreadsheet-checkbox {
+  position: relative;
+  display: inline-block;
+  backface-visibility: hidden;
+  outline: 0;
+  vertical-align: baseline;
+  font-style: normal;
+  font-size: 1rem;
+  line-height: 1em;
+}
+.x-spreadsheet-checkbox > input {
+  position: absolute;
+  top: 0;
+  left: 0;
+  opacity: 0!important;
+  outline: 0;
+  z-index: -1;
+}
+.x-spreadsheet-suggest,
+.x-spreadsheet-contextmenu,
+.x-spreadsheet-sort-filter {
+  position: absolute;
+  box-shadow: 1px 2px 5px 2px rgba(51, 51, 51, 0.15);
+  background: #fff;
+  z-index: 100;
+  width: 260px;
+  pointer-events: auto;
+  overflow: auto;
+}
+.x-spreadsheet-suggest {
+  width: 200px;
+}
+.x-spreadsheet-filter {
+  border: 1px solid #e9e9e9;
+  font-size: 12px;
+  margin: 10px;
+}
+.x-spreadsheet-filter .x-spreadsheet-header {
+  padding: 0.5em 0.75em;
+  background: #f8f8f9;
+  border-bottom: 1px solid #e9e9e9;
+  border-left: 1px solid transparent;
+}
+.x-spreadsheet-filter .x-spreadsheet-body {
+  height: 200px;
+  overflow-y: auto;
+}
+.x-spreadsheet-filter .x-spreadsheet-body .x-spreadsheet-item {
+  height: 20px;
+  line-height: 20px;
+}
+.x-spreadsheet-sort-filter .x-spreadsheet-buttons {
+  margin: 10px;
+}
+.x-spreadsheet-bottombar {
+  height: 40px;
+  padding: 0 30px;
+  text-align: left;
+  background: #f5f6f7;
+  display: flex;
+}
+.x-spreadsheet-bottombar {
+  position: relative;
+  border-top: 1px solid #e0e2e4;
+}
+.x-spreadsheet-bottombar .x-spreadsheet-menu > li {
+  line-height: 40px;
+  height: 40px;
+  padding-top: 0;
+  padding-bottom: 0;
+  vertical-align: middle;
+  border-right: 1px solid #e8eaed;
+}
+.x-spreadsheet-menu {
+  list-style: none;
+  margin: 0;
+  padding: 0;
+  user-select: none;
+}
+.x-spreadsheet-menu > li {
+  float: left;
+  line-height: 1.25em;
+  padding: 0.785em 1em;
+  margin: 0;
+  vertical-align: middle;
+  text-align: left;
+  font-weight: 400;
+  color: #80868b;
+  white-space: nowrap;
+  cursor: pointer;
+  transition: all 0.3s;
+  font-weight: bold;
+}
+.x-spreadsheet-menu > li.active {
+  background-color: #fff;
+  color: rgba(0, 0, 0, 0.65);
+}
+.x-spreadsheet-menu > li .x-spreadsheet-dropdown {
+  display: inline-block;
+}
+.x-spreadsheet-print {
+  position: absolute;
+  left: 0;
+  top: 0;
+  z-index: 100;
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+}
+.x-spreadsheet-print-bar {
+  background: #424242;
+  height: 60px;
+  line-height: 60px;
+  padding: 0 30px;
+}
+.x-spreadsheet-print-bar .-title {
+  color: #fff;
+  font-weight: bold;
+  font-size: 1.2em;
+  float: left;
+}
+.x-spreadsheet-print-bar .-right {
+  float: right;
+  margin-top: 12px;
+}
+.x-spreadsheet-print-content {
+  display: flex;
+  flex: auto;
+  flex-direction: row;
+  background: #d0d0d0;
+  height: calc(100% - 60px);
+}
+.x-spreadsheet-print-content .-sider {
+  flex: 0 0 300px;
+  width: 300px;
+  border-left: 2px solid #ccc;
+  background: #fff;
+}
+.x-spreadsheet-print-content .-content {
+  flex: auto;
+  overflow-x: auto;
+  overflow-y: scroll;
+  height: 100%;
+}
+.x-spreadsheet-canvas-card-wraper {
+  margin: 40px 20px;
+}
+.x-spreadsheet-canvas-card {
+  background: #fff;
+  margin: auto;
+  page-break-before: auto;
+  page-break-after: always;
+  box-shadow: 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 3px rgba(0, 0, 0, 0.12), 0 4px 5px 0 rgba(0, 0, 0, 0.2);
+}
+.x-spreadsheet-calendar {
+  color: rgba(0, 0, 0, 0.65);
+  background: #ffffff;
+  user-select: none;
+}
+.x-spreadsheet-calendar .calendar-header {
+  font-weight: 700;
+  line-height: 30px;
+  text-align: center;
+  width: 100%;
+  float: left;
+  background: #f9fafb;
+}
+.x-spreadsheet-calendar .calendar-header .calendar-header-left {
+  padding-left: 5px;
+  float: left;
+}
+.x-spreadsheet-calendar .calendar-header .calendar-header-right {
+  float: right;
+}
+.x-spreadsheet-calendar .calendar-header .calendar-header-right a {
+  padding: 3px 0;
+  margin-right: 2px;
+  border-radius: 2px;
+}
+.x-spreadsheet-calendar .calendar-header .calendar-header-right a:hover {
+  background: rgba(0, 0, 0, 0.08);
+}
+.x-spreadsheet-calendar .calendar-body {
+  border-collapse: collapse;
+  border-spacing: 0;
+}
+.x-spreadsheet-calendar .calendar-body th,
+.x-spreadsheet-calendar .calendar-body td {
+  width: 14.28571429%;
+  min-width: 32px;
+  text-align: center;
+  font-weight: 700;
+  line-height: 30px;
+  padding: 0;
+}
+.x-spreadsheet-calendar .calendar-body td > .cell:hover {
+  background: #ecf6fd;
+}
+.x-spreadsheet-calendar .calendar-body td > .cell.active,
+.x-spreadsheet-calendar .calendar-body td > .cell.active:hover {
+  background: #ecf6fd;
+  color: #2185D0;
+}
+.x-spreadsheet-calendar .calendar-body td > .cell.disabled {
+  pointer-events: none;
+  opacity: 0.5;
+}
+.x-spreadsheet-datepicker {
+  box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);
+  position: absolute;
+  left: 0;
+  top: calc(100% + 5px);
+  z-index: 10;
+  width: auto;
+}
+.x-spreadsheet-buttons {
+  display: flex;
+  justify-content: flex-end;
+}
+.x-spreadsheet-buttons .x-spreadsheet-button {
+  margin-left: 8px;
+}
+.x-spreadsheet-button {
+  display: inline-block;
+  border-radius: 3px;
+  line-height: 1em;
+  min-height: 1em;
+  white-space: nowrap;
+  text-align: center;
+  cursor: pointer;
+  font-size: 1em;
+  font-weight: 700;
+  padding: 0.75em 1em;
+  color: rgba(0, 0, 0, 0.6);
+  background: #E0E1E2;
+  text-decoration: none;
+  font-family: "Lato", "proxima-nova", "Helvetica Neue", Arial, sans-serif;
+  outline: none;
+  vertical-align: baseline;
+  zoom: 1;
+  user-select: none;
+  transition: all 0.1s linear;
+}
+.x-spreadsheet-button.active,
+.x-spreadsheet-button:hover {
+  background-color: #C0C1C2;
+  color: rgba(0, 0, 0, 0.8);
+}
+.x-spreadsheet-button.primary {
+  color: #fff;
+  background-color: #2185D0;
+}
+.x-spreadsheet-button.primary:hover,
+.x-spreadsheet-button.primary.active {
+  color: #fff;
+  background-color: #1678c2;
+}
+.x-spreadsheet-form-input {
+  font-size: 1em;
+  position: relative;
+  font-weight: 400;
+  display: inline-flex;
+  color: rgba(0, 0, 0, 0.87);
+}
+.x-spreadsheet-form-input input {
+  z-index: 1;
+  margin: 0;
+  max-width: 100%;
+  flex: 1 0 auto;
+  outline: 0;
+  -webkit-tap-highlight-color: rgba(255, 255, 255, 0);
+  text-align: left;
+  line-height: 30px;
+  height: 30px;
+  padding: 0 8px;
+  background: #fff;
+  border: 1px solid #e9e9e9;
+  border-radius: 3px;
+  transition: box-shadow 0.1s ease, border-color 0.1s ease;
+  box-shadow: inset 0 1px 2px hsla(0, 0%, 4%, 0.06);
+}
+.x-spreadsheet-form-input input:focus {
+  border-color: #4b89ff;
+  box-shadow: inset 0 1px 2px rgba(75, 137, 255, 0.2);
+}
+.x-spreadsheet-form-select {
+  position: relative;
+  display: inline-block;
+  background: #fff;
+  border: 1px solid #e9e9e9;
+  border-radius: 2px;
+  cursor: pointer;
+  color: rgba(0, 0, 0, 0.87);
+  user-select: none;
+  box-shadow: inset 0 1px 2px hsla(0, 0%, 4%, 0.06);
+}
+.x-spreadsheet-form-select .input-text {
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  min-width: 60px;
+  width: auto;
+  height: 30px;
+  line-height: 30px;
+  padding: 0 8px;
+}
+.x-spreadsheet-form-fields {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+}
+.x-spreadsheet-form-fields .x-spreadsheet-form-field {
+  flex: 0 1 auto;
+}
+.x-spreadsheet-form-fields .x-spreadsheet-form-field .label {
+  display: inline-block;
+  margin: 0 10px 0 0;
+}
+.x-spreadsheet-form-field {
+  display: block;
+  vertical-align: middle;
+  margin-left: 10px;
+  margin-bottom: 10px;
+}
+.x-spreadsheet-form-field:first-child {
+  margin-left: 0;
+}
+.x-spreadsheet-form-field.error .x-spreadsheet-form-select,
+.x-spreadsheet-form-field.error input {
+  border-color: #f04134;
+}
+.x-spreadsheet-form-field .tip {
+  color: #f04134;
+  font-size: 0.9em;
+}
+.x-spreadsheet-dimmer {
+  display: none;
+  position: absolute;
+  top: 0 !important;
+  left: 0 !important;
+  width: 100%;
+  height: 100%;
+  text-align: center;
+  vertical-align: middle;
+  background-color: rgba(0, 0, 0, 0.6);
+  opacity: 0;
+  -webkit-animation-fill-mode: both;
+  animation-fill-mode: both;
+  -webkit-animation-duration: 0.5s;
+  animation-duration: 0.5s;
+  transition: background-color 0.5s linear;
+  user-select: none;
+  z-index: 1000;
+}
+.x-spreadsheet-dimmer.active {
+  display: block;
+  opacity: 1;
+}
+form fieldset {
+  border: none;
+}
+form fieldset label {
+  display: block;
+  margin-bottom: 0.5em;
+  font-size: 1em;
+  color: #666;
+}
+form fieldset select {
+  font-size: 1.1em;
+  width: 100%;
+  background-color: #fff;
+  border: none;
+  border-bottom: 2px solid #ddd;
+  padding: 0.5em 0.85em;
+  border-radius: 2px;
+}
+.x-spreadsheet-modal,
+.x-spreadsheet-toast {
+  font-size: 13px;
+  position: fixed;
+  z-index: 1001;
+  text-align: left;
+  line-height: 1.25em;
+  min-width: 360px;
+  color: rgba(0, 0, 0, 0.87);
+  font-family: 'Lato', 'Source Sans Pro', Roboto, Helvetica, Arial, sans-serif;
+  border-radius: 4px;
+  border: 1px solid rgba(0, 0, 0, 0.1);
+  background-color: #fff;
+  background-clip: padding-box;
+  box-shadow: rgba(0, 0, 0, 0.2) 0px 2px 8px;
+}
+.x-spreadsheet-toast {
+  background-color: rgba(255, 255, 255, 0.85);
+}
+.x-spreadsheet-modal-header,
+.x-spreadsheet-toast-header {
+  font-weight: 600;
+  background-clip: padding-box;
+  background-color: rgba(255, 255, 255, 0.85);
+  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
+  border-radius: 4px 4px 0 0;
+}
+
+.x-spreadsheet-toast-header {
+  color: #F2711C;
+}
+.x-spreadsheet-modal-header {
+  border-bottom: 1px solid #e0e2e4;
+  background: rgba(0, 0, 0, 0.08);
+  font-size: 1.0785em;
+}
+.x-spreadsheet-modal-header,
+.x-spreadsheet-modal-content,
+.x-spreadsheet-toast-header,
+.x-spreadsheet-toast-content {
+  padding: 0.75em 1em;
+}
+
+.x-spreadsheet-menu li:first-child {
+  display: none;
+}
+
+.vue-office-excel {
+  height: 100%;
+}

File diff suppressed because it is too large
+ 43 - 0
app/src/main/assets/web/js-preview-lib/excel.umd.js


File diff suppressed because it is too large
+ 1 - 0
app/src/main/assets/web/js-preview-lib/pdf.umd.js


File diff suppressed because it is too large
+ 10 - 0
app/src/main/assets/web/js-preview-lib/vconsole.min.js


File diff suppressed because it is too large
+ 2 - 0
app/src/main/assets/web/pptx-js-1.21.1/css/nv.d3.min.css


+ 161 - 0
app/src/main/assets/web/pptx-js-1.21.1/css/pptxjs.css

@@ -0,0 +1,161 @@
+
+
+.slide {
+	position: relative;
+	border: 1px solid #333;
+	border-radius: 10px;
+	overflow: hidden;
+	margin-bottom: 50px;
+	margin-left: auto;
+  	margin-right: auto;
+}
+
+.slide div.block {
+	position: absolute;
+	top: 0px;
+	left: 0px;
+	width: 100%;
+	line-height: 1;
+}
+
+.slide div.content {
+	display: flex;
+	flex-direction: column;
+}
+.slide div.diagram-content{
+	display: flex;
+	flex-direction: column;
+}
+
+.slide div.content-rtl {
+	display: flex;
+	flex-direction: column;
+	direction: rtl; 
+}
+.slide .pregraph-rtl{
+	direction: rtl; 
+}
+.slide .pregraph-ltr{
+	direction: ltr; 
+}
+.slide .pregraph-inherit{
+	direction: inherit; 
+}
+.slide .slide-prgrph{
+	width: 100%;
+	/* overflow-wrap:break-word;
+  	word-wrap: break-word;  */
+  
+	/* word-break: break-word; */
+	/* unicode-bidi: bidi-override; */
+	/* hyphens: auto;
+	overflow-wrap: break-word; */
+	
+}
+
+.slide .line-break-br::before{
+  content: "\A";
+  white-space: pre;
+}
+.slide div.v-up {
+	justify-content: flex-start;
+}
+.slide div.v-mid {
+	justify-content: center;
+}
+.slide div.v-down {
+	justify-content: flex-end;
+}
+
+.slide div.h-left {
+	justify-content: flex-start;
+	align-items: flex-start;
+	text-align: left;
+}
+.slide div.h-left-rtl {
+	justify-content: flex-end;
+	align-items: flex-end;
+	text-align: left;
+}
+.slide div.h-mid {
+	justify-content: center;
+	align-items: center;
+	text-align: center;
+}
+.slide div.h-right {
+	justify-content: flex-end;
+	align-items: flex-end;
+	text-align: right;
+}
+.slide div.h-right-rtl {
+	justify-content: flex-start;
+	align-items: flex-start;
+	text-align: right;
+}
+
+.slide div.h-just,
+.slide div.h-dist {
+	text-align: justify;
+}
+
+
+.slide div.up-left {
+	justify-content: flex-start;
+	align-items: flex-start;
+	text-align: left;
+}
+.slide div.up-center {
+	justify-content: flex-start;
+	align-items: center;
+}
+.slide div.up-right {
+	justify-content: flex-start;
+	align-items: flex-end;
+}
+.slide div.center-left {
+	justify-content: center;
+	align-items: flex-start;
+	text-align: left;
+}
+.slide div.center-center {
+	justify-content: center;
+	align-items: center;
+}
+.slide div.center-right {
+	justify-content: center;
+	align-items: flex-end;
+}
+.slide div.down-left {
+	justify-content: flex-end;
+	align-items: flex-start;
+	text-align: left;
+}
+.slide div.down-center {
+	justify-content: flex-end;
+	align-items: center;
+}
+.slide div.down-right {
+	justify-content: flex-end;
+	align-items: flex-end;
+}
+
+
+.slide li.slide {
+	margin: 10px 0px;
+	font-size: 18px;
+}
+
+.slide table {
+	position: absolute;
+}
+
+.slide svg.drawing {
+	position: absolute;
+	overflow: visible;
+}
+/*
+#pptx-thumb {
+	min-width: 240px;
+	height: 180px;
+}
+*/

File diff suppressed because it is too large
+ 5 - 0
app/src/main/assets/web/pptx-js-1.21.1/js/d3.min.js


+ 872 - 0
app/src/main/assets/web/pptx-js-1.21.1/js/dingbat.js

@@ -0,0 +1,872 @@
+var dingbat_unicode = [
+    {"f": "Webdings", "code": "33",  "unicode": "128375"},
+    {"f": "Webdings", "code": "34",  "unicode": "128376"},
+    {"f": "Webdings", "code": "35",  "unicode": "128370"},
+    {"f": "Webdings", "code": "36",  "unicode": "128374"},
+    {"f": "Webdings", "code": "37",  "unicode": "127942"},
+    {"f": "Webdings", "code": "38",  "unicode": "127894"},
+    {"f": "Webdings", "code": "39",  "unicode": "128391"},
+    {"f": "Webdings", "code": "40",  "unicode": "128488"},
+    {"f": "Webdings", "code": "41",  "unicode": "128489"},
+    {"f": "Webdings", "code": "42",  "unicode": "128496"},
+    {"f": "Webdings", "code": "43",  "unicode": "128497"},
+    {"f": "Webdings", "code": "44",  "unicode": "127798"},
+    {"f": "Webdings", "code": "45",  "unicode": "127895"},
+    {"f": "Webdings", "code": "46",  "unicode": "128638"},
+    {"f": "Webdings", "code": "47",  "unicode": "128636"},
+    {"f": "Webdings", "code": "48",  "unicode": "128469"},
+    {"f": "Webdings", "code": "49",  "unicode": "128470"},
+    {"f": "Webdings", "code": "50",  "unicode": "128471"},
+    {"f": "Webdings", "code": "51",  "unicode": "9204"},
+    {"f": "Webdings", "code": "52",  "unicode": "9205"},
+    {"f": "Webdings", "code": "53",  "unicode": "9206"},
+    {"f": "Webdings", "code": "54",  "unicode": "9207"},
+    {"f": "Webdings", "code": "55",  "unicode": "9194"},
+    {"f": "Webdings", "code": "56",  "unicode": "9193"},
+    {"f": "Webdings", "code": "57",  "unicode": "9198"},
+    {"f": "Webdings", "code": "58",  "unicode": "9197"},
+    {"f": "Webdings", "code": "59",  "unicode": "9208"},
+    {"f": "Webdings", "code": "60",  "unicode": "9209"},
+    {"f": "Webdings", "code": "61",  "unicode": "9210"},
+    {"f": "Webdings", "code": "62",  "unicode": "128474"},
+    {"f": "Webdings", "code": "63",  "unicode": "128499"},
+    {"f": "Webdings", "code": "64",  "unicode": "128736"},
+    {"f": "Webdings", "code": "65",  "unicode": "127959"},
+    {"f": "Webdings", "code": "66",  "unicode": "127960"},
+    {"f": "Webdings", "code": "67",  "unicode": "127961"},
+    {"f": "Webdings", "code": "68",  "unicode": "127962"},
+    {"f": "Webdings", "code": "69",  "unicode": "127964"},
+    {"f": "Webdings", "code": "70",  "unicode": "127981"},
+    {"f": "Webdings", "code": "71",  "unicode": "127963"},
+    {"f": "Webdings", "code": "72",  "unicode": "127968"},
+    {"f": "Webdings", "code": "73",  "unicode": "127958"},
+    {"f": "Webdings", "code": "74",  "unicode": "127965"},
+    {"f": "Webdings", "code": "75",  "unicode": "128739"},
+    {"f": "Webdings", "code": "76",  "unicode": "128269"},
+    {"f": "Webdings", "code": "77",  "unicode": "127956"},
+    {"f": "Webdings", "code": "78",  "unicode": "128065"},
+    {"f": "Webdings", "code": "79",  "unicode": "128066"},
+    {"f": "Webdings", "code": "80",  "unicode": "127966"},
+    {"f": "Webdings", "code": "81",  "unicode": "127957"},
+    {"f": "Webdings", "code": "82",  "unicode": "128740"},
+    {"f": "Webdings", "code": "83",  "unicode": "127967"},
+    {"f": "Webdings", "code": "84",  "unicode": "128755"},
+    {"f": "Webdings", "code": "85",  "unicode": "128364"},
+    {"f": "Webdings", "code": "86",  "unicode": "128363"},
+    {"f": "Webdings", "code": "87",  "unicode": "128360"},
+    {"f": "Webdings", "code": "88",  "unicode": "128264"},
+    {"f": "Webdings", "code": "89",  "unicode": "127892"},
+    {"f": "Webdings", "code": "90",  "unicode": "127893"},
+    {"f": "Webdings", "code": "91",  "unicode": "128492"},
+    {"f": "Webdings", "code": "92",  "unicode": "128637"},
+    {"f": "Webdings", "code": "93",  "unicode": "128493"},
+    {"f": "Webdings", "code": "94",  "unicode": "128490"},
+    {"f": "Webdings", "code": "95",  "unicode": "128491"},
+    {"f": "Webdings", "code": "96",  "unicode": "11156"},
+    {"f": "Webdings", "code": "97",  "unicode": "10004"},
+    {"f": "Webdings", "code": "98",  "unicode": "128690"},
+    {"f": "Webdings", "code": "99",  "unicode": "11036"},
+    {"f": "Webdings", "code": "100",  "unicode": "128737"},
+    {"f": "Webdings", "code": "101",  "unicode": "128230"},
+    {"f": "Webdings", "code": "102",  "unicode": "128753"},
+    {"f": "Webdings", "code": "103",  "unicode": "11035"},
+    {"f": "Webdings", "code": "104",  "unicode": "128657"},
+    {"f": "Webdings", "code": "105",  "unicode": "128712"},
+    {"f": "Webdings", "code": "106",  "unicode": "128745"},
+    {"f": "Webdings", "code": "107",  "unicode": "128752"},
+    {"f": "Webdings", "code": "108",  "unicode": "128968"},
+    {"f": "Webdings", "code": "109",  "unicode": "128372"},
+    {"f": "Webdings", "code": "110",  "unicode": "11044"},
+    {"f": "Webdings", "code": "111",  "unicode": "128741"},
+    {"f": "Webdings", "code": "112",  "unicode": "128660"},
+    {"f": "Webdings", "code": "113",  "unicode": "128472"},
+    {"f": "Webdings", "code": "114",  "unicode": "128473"},
+    {"f": "Webdings", "code": "115",  "unicode": "10067"},
+    {"f": "Webdings", "code": "116",  "unicode": "128754"},
+    {"f": "Webdings", "code": "117",  "unicode": "128647"},
+    {"f": "Webdings", "code": "118",  "unicode": "128653"},
+    {"f": "Webdings", "code": "119",  "unicode": "9971"},
+    {"f": "Webdings", "code": "120",  "unicode": "10680"},
+    {"f": "Webdings", "code": "121",  "unicode": "8854"},
+    {"f": "Webdings", "code": "122",  "unicode": "128685"},
+    {"f": "Webdings", "code": "123",  "unicode": "128494"},
+    {"f": "Webdings", "code": "124",  "unicode": "9168"},
+    {"f": "Webdings", "code": "125",  "unicode": "128495"},
+    {"f": "Webdings", "code": "126",  "unicode": "128498"},
+    {"f": "Webdings", "code": "128",  "unicode": "128697"},
+    {"f": "Webdings", "code": "129",  "unicode": "128698"},
+    {"f": "Webdings", "code": "130",  "unicode": "128713"},
+    {"f": "Webdings", "code": "131",  "unicode": "128714"},
+    {"f": "Webdings", "code": "132",  "unicode": "128700"},
+    {"f": "Webdings", "code": "133",  "unicode": "128125"},
+    {"f": "Webdings", "code": "134",  "unicode": "127947"},
+    {"f": "Webdings", "code": "135",  "unicode": "9975"},
+    {"f": "Webdings", "code": "136",  "unicode": "127938"},
+    {"f": "Webdings", "code": "137",  "unicode": "127948"},
+    {"f": "Webdings", "code": "138",  "unicode": "127946"},
+    {"f": "Webdings", "code": "139",  "unicode": "127940"},
+    {"f": "Webdings", "code": "140",  "unicode": "127949"},
+    {"f": "Webdings", "code": "141",  "unicode": "127950"},
+    {"f": "Webdings", "code": "142",  "unicode": "128664"},
+    {"f": "Webdings", "code": "143",  "unicode": "128480"},
+    {"f": "Webdings", "code": "144",  "unicode": "128738"},
+    {"f": "Webdings", "code": "145",  "unicode": "128176"},
+    {"f": "Webdings", "code": "146",  "unicode": "127991"},
+    {"f": "Webdings", "code": "147",  "unicode": "128179"},
+    {"f": "Webdings", "code": "148",  "unicode": "128106"},
+    {"f": "Webdings", "code": "149",  "unicode": "128481"},
+    {"f": "Webdings", "code": "150",  "unicode": "128482"},
+    {"f": "Webdings", "code": "151",  "unicode": "128483"},
+    {"f": "Webdings", "code": "152",  "unicode": "10031"},
+    {"f": "Webdings", "code": "153",  "unicode": "128388"},
+    {"f": "Webdings", "code": "154",  "unicode": "128389"},
+    {"f": "Webdings", "code": "155",  "unicode": "128387"},
+    {"f": "Webdings", "code": "156",  "unicode": "128390"},
+    {"f": "Webdings", "code": "157",  "unicode": "128441"},
+    {"f": "Webdings", "code": "158",  "unicode": "128442"},
+    {"f": "Webdings", "code": "159",  "unicode": "128443"},
+    {"f": "Webdings", "code": "160",  "unicode": "128373"},
+    {"f": "Webdings", "code": "161",  "unicode": "128368"},
+    {"f": "Webdings", "code": "162",  "unicode": "128445"},
+    {"f": "Webdings", "code": "163",  "unicode": "128446"},
+    {"f": "Webdings", "code": "164",  "unicode": "128203"},
+    {"f": "Webdings", "code": "165",  "unicode": "128466"},
+    {"f": "Webdings", "code": "166",  "unicode": "128467"},
+    {"f": "Webdings", "code": "167",  "unicode": "128366"},
+    {"f": "Webdings", "code": "168",  "unicode": "128218"},
+    {"f": "Webdings", "code": "169",  "unicode": "128478"},
+    {"f": "Webdings", "code": "170",  "unicode": "128479"},
+    {"f": "Webdings", "code": "171",  "unicode": "128451"},
+    {"f": "Webdings", "code": "172",  "unicode": "128450"},
+    {"f": "Webdings", "code": "173",  "unicode": "128444"},
+    {"f": "Webdings", "code": "174",  "unicode": "127917"},
+    {"f": "Webdings", "code": "175",  "unicode": "127900"},
+    {"f": "Webdings", "code": "176",  "unicode": "127896"},
+    {"f": "Webdings", "code": "177",  "unicode": "127897"},
+    {"f": "Webdings", "code": "178",  "unicode": "127911"},
+    {"f": "Webdings", "code": "179",  "unicode": "128191"},
+    {"f": "Webdings", "code": "180",  "unicode": "127902"},
+    {"f": "Webdings", "code": "181",  "unicode": "128247"},
+    {"f": "Webdings", "code": "182",  "unicode": "127903"},
+    {"f": "Webdings", "code": "183",  "unicode": "127916"},
+    {"f": "Webdings", "code": "184",  "unicode": "128253"},
+    {"f": "Webdings", "code": "185",  "unicode": "128249"},
+    {"f": "Webdings", "code": "186",  "unicode": "128254"},
+    {"f": "Webdings", "code": "187",  "unicode": "128251"},
+    {"f": "Webdings", "code": "188",  "unicode": "127898"},
+    {"f": "Webdings", "code": "189",  "unicode": "127899"},
+    {"f": "Webdings", "code": "190",  "unicode": "128250"},
+    {"f": "Webdings", "code": "191",  "unicode": "128187"},
+    {"f": "Webdings", "code": "192",  "unicode": "128421"},
+    {"f": "Webdings", "code": "193",  "unicode": "128422"},
+    {"f": "Webdings", "code": "194",  "unicode": "128423"},
+    {"f": "Webdings", "code": "195",  "unicode": "128377"},
+    {"f": "Webdings", "code": "196",  "unicode": "127918"},
+    {"f": "Webdings", "code": "197",  "unicode": "128379"},
+    {"f": "Webdings", "code": "198",  "unicode": "128380"},
+    {"f": "Webdings", "code": "199",  "unicode": "128223"},
+    {"f": "Webdings", "code": "200",  "unicode": "128385"},
+    {"f": "Webdings", "code": "201",  "unicode": "128384"},
+    {"f": "Webdings", "code": "202",  "unicode": "128424"},
+    {"f": "Webdings", "code": "203",  "unicode": "128425"},
+    {"f": "Webdings", "code": "204",  "unicode": "128447"},
+    {"f": "Webdings", "code": "205",  "unicode": "128426"},
+    {"f": "Webdings", "code": "206",  "unicode": "128476"},
+    {"f": "Webdings", "code": "207",  "unicode": "128274"},
+    {"f": "Webdings", "code": "208",  "unicode": "128275"},
+    {"f": "Webdings", "code": "209",  "unicode": "128477"},
+    {"f": "Webdings", "code": "210",  "unicode": "128229"},
+    {"f": "Webdings", "code": "211",  "unicode": "128228"},
+    {"f": "Webdings", "code": "212",  "unicode": "128371"},
+    {"f": "Webdings", "code": "213",  "unicode": "127779"},
+    {"f": "Webdings", "code": "214",  "unicode": "127780"},
+    {"f": "Webdings", "code": "215",  "unicode": "127781"},
+    {"f": "Webdings", "code": "216",  "unicode": "127782"},
+    {"f": "Webdings", "code": "217",  "unicode": "9729"},
+    {"f": "Webdings", "code": "218",  "unicode": "127784"},
+    {"f": "Webdings", "code": "219",  "unicode": "127783"},
+    {"f": "Webdings", "code": "220",  "unicode": "127785"},
+    {"f": "Webdings", "code": "221",  "unicode": "127786"},
+    {"f": "Webdings", "code": "222",  "unicode": "127788"},
+    {"f": "Webdings", "code": "223",  "unicode": "127787"},
+    {"f": "Webdings", "code": "224",  "unicode": "127772"},
+    {"f": "Webdings", "code": "225",  "unicode": "127777"},
+    {"f": "Webdings", "code": "226",  "unicode": "128715"},
+    {"f": "Webdings", "code": "227",  "unicode": "128719"},
+    {"f": "Webdings", "code": "228",  "unicode": "127869"},
+    {"f": "Webdings", "code": "229",  "unicode": "127864"},
+    {"f": "Webdings", "code": "230",  "unicode": "128718"},
+    {"f": "Webdings", "code": "231",  "unicode": "128717"},
+    {"f": "Webdings", "code": "232",  "unicode": "9413"},
+    {"f": "Webdings", "code": "233",  "unicode": "9855"},
+    {"f": "Webdings", "code": "234",  "unicode": "128710"},
+    {"f": "Webdings", "code": "235",  "unicode": "128392"},
+    {"f": "Webdings", "code": "236",  "unicode": "127891"},
+    {"f": "Webdings", "code": "237",  "unicode": "128484"},
+    {"f": "Webdings", "code": "238",  "unicode": "128485"},
+    {"f": "Webdings", "code": "239",  "unicode": "128486"},
+    {"f": "Webdings", "code": "240",  "unicode": "128487"},
+    {"f": "Webdings", "code": "241",  "unicode": "128746"},
+    {"f": "Webdings", "code": "242",  "unicode": "128063"},
+    {"f": "Webdings", "code": "243",  "unicode": "128038"},
+    {"f": "Webdings", "code": "244",  "unicode": "128031"},
+    {"f": "Webdings", "code": "245",  "unicode": "128021"},
+    {"f": "Webdings", "code": "246",  "unicode": "128008"},
+    {"f": "Webdings", "code": "247",  "unicode": "128620"},
+    {"f": "Webdings", "code": "248",  "unicode": "128622"},
+    {"f": "Webdings", "code": "249",  "unicode": "128621"},
+    {"f": "Webdings", "code": "250",  "unicode": "128623"},
+    {"f": "Webdings", "code": "251",  "unicode": "128506"},
+    {"f": "Webdings", "code": "252",  "unicode": "127757"},
+    {"f": "Webdings", "code": "253",  "unicode": "127759"},
+    {"f": "Webdings", "code": "254",  "unicode": "127758"},
+    {"f": "Webdings", "code": "255",  "unicode": "128330"},
+    {"f": "Wingdings", "code": "32",  "unicode": "32"},
+    {"f": "Wingdings", "code": "33",  "unicode": "128393"},
+    {"f": "Wingdings", "code": "34",  "unicode": "9986"},
+    {"f": "Wingdings", "code": "35",  "unicode": "9985"},
+    {"f": "Wingdings", "code": "36",  "unicode": "128083"},
+    {"f": "Wingdings", "code": "37",  "unicode": "128365"},
+    {"f": "Wingdings", "code": "38",  "unicode": "128366"},
+    {"f": "Wingdings", "code": "39",  "unicode": "128367"},
+    {"f": "Wingdings", "code": "40",  "unicode": "128383"},
+    {"f": "Wingdings", "code": "41",  "unicode": "9990"},
+    {"f": "Wingdings", "code": "42",  "unicode": "128386"},
+    {"f": "Wingdings", "code": "43",  "unicode": "128387"},
+    {"f": "Wingdings", "code": "44",  "unicode": "128234"},
+    {"f": "Wingdings", "code": "45",  "unicode": "128235"},
+    {"f": "Wingdings", "code": "46",  "unicode": "128236"},
+    {"f": "Wingdings", "code": "47",  "unicode": "128237"},
+    {"f": "Wingdings", "code": "48",  "unicode": "128448"},
+    {"f": "Wingdings", "code": "49",  "unicode": "128449"},
+    {"f": "Wingdings", "code": "50",  "unicode": "128462"},
+    {"f": "Wingdings", "code": "51",  "unicode": "128463"},
+    {"f": "Wingdings", "code": "52",  "unicode": "128464"},
+    {"f": "Wingdings", "code": "53",  "unicode": "128452"},
+    {"f": "Wingdings", "code": "54",  "unicode": "8987"},
+    {"f": "Wingdings", "code": "55",  "unicode": "128430"},
+    {"f": "Wingdings", "code": "56",  "unicode": "128432"},
+    {"f": "Wingdings", "code": "57",  "unicode": "128434"},
+    {"f": "Wingdings", "code": "58",  "unicode": "128435"},
+    {"f": "Wingdings", "code": "59",  "unicode": "128436"},
+    {"f": "Wingdings", "code": "60",  "unicode": "128427"},
+    {"f": "Wingdings", "code": "61",  "unicode": "128428"},
+    {"f": "Wingdings", "code": "62",  "unicode": "9991"},
+    {"f": "Wingdings", "code": "63",  "unicode": "9997"},
+    {"f": "Wingdings", "code": "64",  "unicode": "128398"},
+    {"f": "Wingdings", "code": "65",  "unicode": "9996"},
+    {"f": "Wingdings", "code": "66",  "unicode": "128399"},
+    {"f": "Wingdings", "code": "67",  "unicode": "128077"},
+    {"f": "Wingdings", "code": "68",  "unicode": "128078"},
+    {"f": "Wingdings", "code": "69",  "unicode": "9756"},
+    {"f": "Wingdings", "code": "70",  "unicode": "9758"},
+    {"f": "Wingdings", "code": "71",  "unicode": "9757"},
+    {"f": "Wingdings", "code": "72",  "unicode": "9759"},
+    {"f": "Wingdings", "code": "73",  "unicode": "128400"},
+    {"f": "Wingdings", "code": "74",  "unicode": "9786"},
+    {"f": "Wingdings", "code": "75",  "unicode": "128528"},
+    {"f": "Wingdings", "code": "76",  "unicode": "9785"},
+    {"f": "Wingdings", "code": "77",  "unicode": "128163"},
+    {"f": "Wingdings", "code": "78",  "unicode": "128369"},
+    {"f": "Wingdings", "code": "79",  "unicode": "127987"},
+    {"f": "Wingdings", "code": "80",  "unicode": "127985"},
+    {"f": "Wingdings", "code": "81",  "unicode": "9992"},
+    {"f": "Wingdings", "code": "82",  "unicode": "9788"},
+    {"f": "Wingdings", "code": "83",  "unicode": "127778"},
+    {"f": "Wingdings", "code": "84",  "unicode": "10052"},
+    {"f": "Wingdings", "code": "85",  "unicode": "128326"},
+    {"f": "Wingdings", "code": "86",  "unicode": "10014"},
+    {"f": "Wingdings", "code": "87",  "unicode": "128328"},
+    {"f": "Wingdings", "code": "88",  "unicode": "10016"},
+    {"f": "Wingdings", "code": "89",  "unicode": "10017"},
+    {"f": "Wingdings", "code": "90",  "unicode": "9770"},
+    {"f": "Wingdings", "code": "91",  "unicode": "9775"},
+    {"f": "Wingdings", "code": "92",  "unicode": "128329"},
+    {"f": "Wingdings", "code": "93",  "unicode": "9784"},
+    {"f": "Wingdings", "code": "94",  "unicode": "9800"},
+    {"f": "Wingdings", "code": "95",  "unicode": "9801"},
+    {"f": "Wingdings", "code": "96",  "unicode": "9802"},
+    {"f": "Wingdings", "code": "97",  "unicode": "9803"},
+    {"f": "Wingdings", "code": "98",  "unicode": "9804"},
+    {"f": "Wingdings", "code": "99",  "unicode": "9805"},
+    {"f": "Wingdings", "code": "100",  "unicode": "9806"},
+    {"f": "Wingdings", "code": "101",  "unicode": "9807"},
+    {"f": "Wingdings", "code": "102",  "unicode": "9808"},
+    {"f": "Wingdings", "code": "103",  "unicode": "9809"},
+    {"f": "Wingdings", "code": "104",  "unicode": "9810"},
+    {"f": "Wingdings", "code": "105",  "unicode": "9811"},
+    {"f": "Wingdings", "code": "106",  "unicode": "128624"},
+    {"f": "Wingdings", "code": "107",  "unicode": "128629"},
+    {"f": "Wingdings", "code": "108",  "unicode": "9899"},
+    {"f": "Wingdings", "code": "109",  "unicode": "128318"},
+    {"f": "Wingdings", "code": "110",  "unicode": "9724"},
+    {"f": "Wingdings", "code": "111",  "unicode": "128911"},
+    {"f": "Wingdings", "code": "112",  "unicode": "128912"},
+    {"f": "Wingdings", "code": "113",  "unicode": "10065"},
+    {"f": "Wingdings", "code": "114",  "unicode": "10066"},
+    {"f": "Wingdings", "code": "115",  "unicode": "128927"},
+    {"f": "Wingdings", "code": "116",  "unicode": "10731"},
+    {"f": "Wingdings", "code": "117",  "unicode": "9670"},
+    {"f": "Wingdings", "code": "118",  "unicode": "10070"},
+    {"f": "Wingdings", "code": "119",  "unicode": "11049"},
+    {"f": "Wingdings", "code": "120",  "unicode": "8999"},
+    {"f": "Wingdings", "code": "121",  "unicode": "11193"},
+    {"f": "Wingdings", "code": "122",  "unicode": "8984"},
+    {"f": "Wingdings", "code": "123",  "unicode": "127989"},
+    {"f": "Wingdings", "code": "124",  "unicode": "127990"},
+    {"f": "Wingdings", "code": "125",  "unicode": "128630"},
+    {"f": "Wingdings", "code": "126",  "unicode": "128631"},
+    {"f": "Wingdings", "code": "127",  "unicode": "9647"},
+    {"f": "Wingdings", "code": "128",  "unicode": "127243"},
+    {"f": "Wingdings", "code": "129",  "unicode": "10112"},
+    {"f": "Wingdings", "code": "130",  "unicode": "10113"},
+    {"f": "Wingdings", "code": "131",  "unicode": "10114"},
+    {"f": "Wingdings", "code": "132",  "unicode": "10115"},
+    {"f": "Wingdings", "code": "133",  "unicode": "10116"},
+    {"f": "Wingdings", "code": "134",  "unicode": "10117"},
+    {"f": "Wingdings", "code": "135",  "unicode": "10118"},
+    {"f": "Wingdings", "code": "136",  "unicode": "10119"},
+    {"f": "Wingdings", "code": "137",  "unicode": "10120"},
+    {"f": "Wingdings", "code": "138",  "unicode": "10121"},
+    {"f": "Wingdings", "code": "139",  "unicode": "127244"},
+    {"f": "Wingdings", "code": "140",  "unicode": "10122"},
+    {"f": "Wingdings", "code": "141",  "unicode": "10123"},
+    {"f": "Wingdings", "code": "142",  "unicode": "10124"},
+    {"f": "Wingdings", "code": "143",  "unicode": "10125"},
+    {"f": "Wingdings", "code": "144",  "unicode": "10126"},
+    {"f": "Wingdings", "code": "145",  "unicode": "10127"},
+    {"f": "Wingdings", "code": "146",  "unicode": "10128"},
+    {"f": "Wingdings", "code": "147",  "unicode": "10129"},
+    {"f": "Wingdings", "code": "148",  "unicode": "10130"},
+    {"f": "Wingdings", "code": "149",  "unicode": "10131"},
+    {"f": "Wingdings", "code": "150",  "unicode": "128610"},
+    {"f": "Wingdings", "code": "151",  "unicode": "128608"},
+    {"f": "Wingdings", "code": "152",  "unicode": "128609"},
+    {"f": "Wingdings", "code": "153",  "unicode": "128611"},
+    {"f": "Wingdings", "code": "154",  "unicode": "128606"},
+    {"f": "Wingdings", "code": "155",  "unicode": "128604"},
+    {"f": "Wingdings", "code": "156",  "unicode": "128605"},
+    {"f": "Wingdings", "code": "157",  "unicode": "128607"},
+    {"f": "Wingdings", "code": "158",  "unicode": "8729"},
+    {"f": "Wingdings", "code": "159",  "unicode": "8226"},
+    {"f": "Wingdings", "code": "160",  "unicode": "11037"},
+    {"f": "Wingdings", "code": "161",  "unicode": "11096"},
+    {"f": "Wingdings", "code": "162",  "unicode": "128902"},
+    {"f": "Wingdings", "code": "163",  "unicode": "128904"},
+    {"f": "Wingdings", "code": "164",  "unicode": "128906"},
+    {"f": "Wingdings", "code": "165",  "unicode": "128907"},
+    {"f": "Wingdings", "code": "166",  "unicode": "128319"},
+    {"f": "Wingdings", "code": "167",  "unicode": "9642"},
+    {"f": "Wingdings", "code": "168",  "unicode": "128910"},
+    {"f": "Wingdings", "code": "169",  "unicode": "128961"},
+    {"f": "Wingdings", "code": "170",  "unicode": "128965"},
+    {"f": "Wingdings", "code": "171",  "unicode": "9733"},
+    {"f": "Wingdings", "code": "172",  "unicode": "128971"},
+    {"f": "Wingdings", "code": "173",  "unicode": "128975"},
+    {"f": "Wingdings", "code": "174",  "unicode": "128979"},
+    {"f": "Wingdings", "code": "175",  "unicode": "128977"},
+    {"f": "Wingdings", "code": "176",  "unicode": "11216"},
+    {"f": "Wingdings", "code": "177",  "unicode": "8982"},
+    {"f": "Wingdings", "code": "178",  "unicode": "11214"},
+    {"f": "Wingdings", "code": "179",  "unicode": "11215"},
+    {"f": "Wingdings", "code": "180",  "unicode": "11217"},
+    {"f": "Wingdings", "code": "181",  "unicode": "10026"},
+    {"f": "Wingdings", "code": "182",  "unicode": "10032"},
+    {"f": "Wingdings", "code": "183",  "unicode": "128336"},
+    {"f": "Wingdings", "code": "184",  "unicode": "128337"},
+    {"f": "Wingdings", "code": "185",  "unicode": "128338"},
+    {"f": "Wingdings", "code": "186",  "unicode": "128339"},
+    {"f": "Wingdings", "code": "187",  "unicode": "128340"},
+    {"f": "Wingdings", "code": "188",  "unicode": "128341"},
+    {"f": "Wingdings", "code": "189",  "unicode": "128342"},
+    {"f": "Wingdings", "code": "190",  "unicode": "128343"},
+    {"f": "Wingdings", "code": "191",  "unicode": "128344"},
+    {"f": "Wingdings", "code": "192",  "unicode": "128345"},
+    {"f": "Wingdings", "code": "193",  "unicode": "128346"},
+    {"f": "Wingdings", "code": "194",  "unicode": "128347"},
+    {"f": "Wingdings", "code": "195",  "unicode": "11184"},
+    {"f": "Wingdings", "code": "196",  "unicode": "11185"},
+    {"f": "Wingdings", "code": "197",  "unicode": "11186"},
+    {"f": "Wingdings", "code": "198",  "unicode": "11187"},
+    {"f": "Wingdings", "code": "199",  "unicode": "11188"},
+    {"f": "Wingdings", "code": "200",  "unicode": "11189"},
+    {"f": "Wingdings", "code": "201",  "unicode": "11190"},
+    {"f": "Wingdings", "code": "202",  "unicode": "11191"},
+    {"f": "Wingdings", "code": "203",  "unicode": "128618"},
+    {"f": "Wingdings", "code": "204",  "unicode": "128619"},
+    {"f": "Wingdings", "code": "205",  "unicode": "128597"},
+    {"f": "Wingdings", "code": "206",  "unicode": "128596"},
+    {"f": "Wingdings", "code": "207",  "unicode": "128599"},
+    {"f": "Wingdings", "code": "208",  "unicode": "128598"},
+    {"f": "Wingdings", "code": "209",  "unicode": "128592"},
+    {"f": "Wingdings", "code": "210",  "unicode": "128593"},
+    {"f": "Wingdings", "code": "211",  "unicode": "128594"},
+    {"f": "Wingdings", "code": "212",  "unicode": "128595"},
+    {"f": "Wingdings", "code": "213",  "unicode": "9003"},
+    {"f": "Wingdings", "code": "214",  "unicode": "8998"},
+    {"f": "Wingdings", "code": "215",  "unicode": "11160"},
+    {"f": "Wingdings", "code": "216",  "unicode": "11162"},
+    {"f": "Wingdings", "code": "217",  "unicode": "11161"},
+    {"f": "Wingdings", "code": "218",  "unicode": "11163"},
+    {"f": "Wingdings", "code": "219",  "unicode": "11144"},
+    {"f": "Wingdings", "code": "220",  "unicode": "11146"},
+    {"f": "Wingdings", "code": "221",  "unicode": "11145"},
+    {"f": "Wingdings", "code": "222",  "unicode": "11147"},
+    {"f": "Wingdings", "code": "223",  "unicode": "129128"},
+    {"f": "Wingdings", "code": "224",  "unicode": "129130"},
+    {"f": "Wingdings", "code": "225",  "unicode": "129129"},
+    {"f": "Wingdings", "code": "226",  "unicode": "129131"},
+    {"f": "Wingdings", "code": "227",  "unicode": "129132"},
+    {"f": "Wingdings", "code": "228",  "unicode": "129133"},
+    {"f": "Wingdings", "code": "229",  "unicode": "129135"},
+    {"f": "Wingdings", "code": "230",  "unicode": "129134"},
+    {"f": "Wingdings", "code": "231",  "unicode": "129144"},
+    {"f": "Wingdings", "code": "232",  "unicode": "129146"},
+    {"f": "Wingdings", "code": "233",  "unicode": "129145"},
+    {"f": "Wingdings", "code": "234",  "unicode": "129147"},
+    {"f": "Wingdings", "code": "235",  "unicode": "129148"},
+    {"f": "Wingdings", "code": "236",  "unicode": "129149"},
+    {"f": "Wingdings", "code": "237",  "unicode": "129151"},
+    {"f": "Wingdings", "code": "238",  "unicode": "129150"},
+    {"f": "Wingdings", "code": "239",  "unicode": "8678"},
+    {"f": "Wingdings", "code": "240",  "unicode": "8680"},
+    {"f": "Wingdings", "code": "241",  "unicode": "8679"},
+    {"f": "Wingdings", "code": "242",  "unicode": "8681"},
+    {"f": "Wingdings", "code": "243",  "unicode": "11012"},
+    {"f": "Wingdings", "code": "244",  "unicode": "8691"},
+    {"f": "Wingdings", "code": "245",  "unicode": "11009"},
+    {"f": "Wingdings", "code": "246",  "unicode": "11008"},
+    {"f": "Wingdings", "code": "247",  "unicode": "11011"},
+    {"f": "Wingdings", "code": "248",  "unicode": "11010"},
+    {"f": "Wingdings", "code": "249",  "unicode": "129196"},
+    {"f": "Wingdings", "code": "250",  "unicode": "129197"},
+    {"f": "Wingdings", "code": "251",  "unicode": "128502"},
+    {"f": "Wingdings", "code": "252",  "unicode": "10003"},
+    {"f": "Wingdings", "code": "253",  "unicode": "128503"},
+    {"f": "Wingdings", "code": "254",  "unicode": "128505"},
+    {"f": "Wingdings 2", "code": "32",  "unicode": "32"},
+    {"f": "Wingdings 2", "code": "33",  "unicode": "128394"},
+    {"f": "Wingdings 2", "code": "34",  "unicode": "128395"},
+    {"f": "Wingdings 2", "code": "35",  "unicode": "128396"},
+    {"f": "Wingdings 2", "code": "36",  "unicode": "128397"},
+    {"f": "Wingdings 2", "code": "37",  "unicode": "9988"},
+    {"f": "Wingdings 2", "code": "38",  "unicode": "9984"},
+    {"f": "Wingdings 2", "code": "39",  "unicode": "128382"},
+    {"f": "Wingdings 2", "code": "40",  "unicode": "128381"},
+    {"f": "Wingdings 2", "code": "41",  "unicode": "128453"},
+    {"f": "Wingdings 2", "code": "42",  "unicode": "128454"},
+    {"f": "Wingdings 2", "code": "43",  "unicode": "128455"},
+    {"f": "Wingdings 2", "code": "44",  "unicode": "128456"},
+    {"f": "Wingdings 2", "code": "45",  "unicode": "128457"},
+    {"f": "Wingdings 2", "code": "46",  "unicode": "128458"},
+    {"f": "Wingdings 2", "code": "47",  "unicode": "128459"},
+    {"f": "Wingdings 2", "code": "48",  "unicode": "128460"},
+    {"f": "Wingdings 2", "code": "49",  "unicode": "128461"},
+    {"f": "Wingdings 2", "code": "50",  "unicode": "128203"},
+    {"f": "Wingdings 2", "code": "51",  "unicode": "128465"},
+    {"f": "Wingdings 2", "code": "52",  "unicode": "128468"},
+    {"f": "Wingdings 2", "code": "53",  "unicode": "128437"},
+    {"f": "Wingdings 2", "code": "54",  "unicode": "128438"},
+    {"f": "Wingdings 2", "code": "55",  "unicode": "128439"},
+    {"f": "Wingdings 2", "code": "56",  "unicode": "128440"},
+    {"f": "Wingdings 2", "code": "57",  "unicode": "128429"},
+    {"f": "Wingdings 2", "code": "58",  "unicode": "128431"},
+    {"f": "Wingdings 2", "code": "59",  "unicode": "128433"},
+    {"f": "Wingdings 2", "code": "60",  "unicode": "128402"},
+    {"f": "Wingdings 2", "code": "61",  "unicode": "128403"},
+    {"f": "Wingdings 2", "code": "62",  "unicode": "128408"},
+    {"f": "Wingdings 2", "code": "63",  "unicode": "128409"},
+    {"f": "Wingdings 2", "code": "64",  "unicode": "128410"},
+    {"f": "Wingdings 2", "code": "65",  "unicode": "128411"},
+    {"f": "Wingdings 2", "code": "66",  "unicode": "128072"},
+    {"f": "Wingdings 2", "code": "67",  "unicode": "128073"},
+    {"f": "Wingdings 2", "code": "68",  "unicode": "128412"},
+    {"f": "Wingdings 2", "code": "69",  "unicode": "128413"},
+    {"f": "Wingdings 2", "code": "70",  "unicode": "128414"},
+    {"f": "Wingdings 2", "code": "71",  "unicode": "128415"},
+    {"f": "Wingdings 2", "code": "72",  "unicode": "128416"},
+    {"f": "Wingdings 2", "code": "73",  "unicode": "128417"},
+    {"f": "Wingdings 2", "code": "74",  "unicode": "128070"},
+    {"f": "Wingdings 2", "code": "75",  "unicode": "128071"},
+    {"f": "Wingdings 2", "code": "76",  "unicode": "128418"},
+    {"f": "Wingdings 2", "code": "77",  "unicode": "128419"},
+    {"f": "Wingdings 2", "code": "78",  "unicode": "128401"},
+    {"f": "Wingdings 2", "code": "79",  "unicode": "128500"},
+    {"f": "Wingdings 2", "code": "80",  "unicode": "128504"},
+    {"f": "Wingdings 2", "code": "81",  "unicode": "128501"},
+    {"f": "Wingdings 2", "code": "82",  "unicode": "9745"},
+    {"f": "Wingdings 2", "code": "83",  "unicode": "11197"},
+    {"f": "Wingdings 2", "code": "84",  "unicode": "9746"},
+    {"f": "Wingdings 2", "code": "85",  "unicode": "11198"},
+    {"f": "Wingdings 2", "code": "86",  "unicode": "11199"},
+    {"f": "Wingdings 2", "code": "87",  "unicode": "128711"},
+    {"f": "Wingdings 2", "code": "88",  "unicode": "10680"},
+    {"f": "Wingdings 2", "code": "89",  "unicode": "128625"},
+    {"f": "Wingdings 2", "code": "90",  "unicode": "128628"},
+    {"f": "Wingdings 2", "code": "91",  "unicode": "128626"},
+    {"f": "Wingdings 2", "code": "92",  "unicode": "128627"},
+    {"f": "Wingdings 2", "code": "93",  "unicode": "8253"},
+    {"f": "Wingdings 2", "code": "94",  "unicode": "128633"},
+    {"f": "Wingdings 2", "code": "95",  "unicode": "128634"},
+    {"f": "Wingdings 2", "code": "96",  "unicode": "128635"},
+    {"f": "Wingdings 2", "code": "97",  "unicode": "128614"},
+    {"f": "Wingdings 2", "code": "98",  "unicode": "128612"},
+    {"f": "Wingdings 2", "code": "99",  "unicode": "128613"},
+    {"f": "Wingdings 2", "code": "100",  "unicode": "128615"},
+    {"f": "Wingdings 2", "code": "101",  "unicode": "128602"},
+    {"f": "Wingdings 2", "code": "102",  "unicode": "128600"},
+    {"f": "Wingdings 2", "code": "103",  "unicode": "128601"},
+    {"f": "Wingdings 2", "code": "104",  "unicode": "128603"},
+    {"f": "Wingdings 2", "code": "105",  "unicode": "9450"},
+    {"f": "Wingdings 2", "code": "106",  "unicode": "9312"},
+    {"f": "Wingdings 2", "code": "107",  "unicode": "9313"},
+    {"f": "Wingdings 2", "code": "108",  "unicode": "9314"},
+    {"f": "Wingdings 2", "code": "109",  "unicode": "9315"},
+    {"f": "Wingdings 2", "code": "110",  "unicode": "9316"},
+    {"f": "Wingdings 2", "code": "111",  "unicode": "9317"},
+    {"f": "Wingdings 2", "code": "112",  "unicode": "9318"},
+    {"f": "Wingdings 2", "code": "113",  "unicode": "9319"},
+    {"f": "Wingdings 2", "code": "114",  "unicode": "9320"},
+    {"f": "Wingdings 2", "code": "115",  "unicode": "9321"},
+    {"f": "Wingdings 2", "code": "116",  "unicode": "9471"},
+    {"f": "Wingdings 2", "code": "117",  "unicode": "10102"},
+    {"f": "Wingdings 2", "code": "118",  "unicode": "10103"},
+    {"f": "Wingdings 2", "code": "119",  "unicode": "10104"},
+    {"f": "Wingdings 2", "code": "120",  "unicode": "10105"},
+    {"f": "Wingdings 2", "code": "121",  "unicode": "10106"},
+    {"f": "Wingdings 2", "code": "122",  "unicode": "10107"},
+    {"f": "Wingdings 2", "code": "123",  "unicode": "10108"},
+    {"f": "Wingdings 2", "code": "124",  "unicode": "10109"},
+    {"f": "Wingdings 2", "code": "125",  "unicode": "10110"},
+    {"f": "Wingdings 2", "code": "126",  "unicode": "10111"},
+    {"f": "Wingdings 2", "code": "128",  "unicode": "9737"},
+    {"f": "Wingdings 2", "code": "129",  "unicode": "127765"},
+    {"f": "Wingdings 2", "code": "130",  "unicode": "9789"},
+    {"f": "Wingdings 2", "code": "131",  "unicode": "9790"},
+    {"f": "Wingdings 2", "code": "132",  "unicode": "11839"},
+    {"f": "Wingdings 2", "code": "133",  "unicode": "10013"},
+    {"f": "Wingdings 2", "code": "134",  "unicode": "128327"},
+    {"f": "Wingdings 2", "code": "135",  "unicode": "128348"},
+    {"f": "Wingdings 2", "code": "136",  "unicode": "128349"},
+    {"f": "Wingdings 2", "code": "137",  "unicode": "128350"},
+    {"f": "Wingdings 2", "code": "138",  "unicode": "128351"},
+    {"f": "Wingdings 2", "code": "139",  "unicode": "128352"},
+    {"f": "Wingdings 2", "code": "140",  "unicode": "128353"},
+    {"f": "Wingdings 2", "code": "141",  "unicode": "128354"},
+    {"f": "Wingdings 2", "code": "142",  "unicode": "128355"},
+    {"f": "Wingdings 2", "code": "143",  "unicode": "128356"},
+    {"f": "Wingdings 2", "code": "144",  "unicode": "128357"},
+    {"f": "Wingdings 2", "code": "145",  "unicode": "128358"},
+    {"f": "Wingdings 2", "code": "146",  "unicode": "128359"},
+    {"f": "Wingdings 2", "code": "147",  "unicode": "128616"},
+    {"f": "Wingdings 2", "code": "148",  "unicode": "128617"},
+    {"f": "Wingdings 2", "code": "149",  "unicode": "8901"},
+    {"f": "Wingdings 2", "code": "150",  "unicode": "128900"},
+    {"f": "Wingdings 2", "code": "151",  "unicode": "10625"},
+    {"f": "Wingdings 2", "code": "152",  "unicode": "9679"},
+    {"f": "Wingdings 2", "code": "153",  "unicode": "9675"},
+    {"f": "Wingdings 2", "code": "154",  "unicode": "128901"},
+    {"f": "Wingdings 2", "code": "155",  "unicode": "128903"},
+    {"f": "Wingdings 2", "code": "156",  "unicode": "128905"},
+    {"f": "Wingdings 2", "code": "157",  "unicode": "8857"},
+    {"f": "Wingdings 2", "code": "158",  "unicode": "10687"},
+    {"f": "Wingdings 2", "code": "159",  "unicode": "128908"},
+    {"f": "Wingdings 2", "code": "160",  "unicode": "128909"},
+    {"f": "Wingdings 2", "code": "161",  "unicode": "9726"},
+    {"f": "Wingdings 2", "code": "162",  "unicode": "9632"},
+    {"f": "Wingdings 2", "code": "163",  "unicode": "9633"},
+    {"f": "Wingdings 2", "code": "164",  "unicode": "128913"},
+    {"f": "Wingdings 2", "code": "165",  "unicode": "128914"},
+    {"f": "Wingdings 2", "code": "166",  "unicode": "128915"},
+    {"f": "Wingdings 2", "code": "167",  "unicode": "128916"},
+    {"f": "Wingdings 2", "code": "168",  "unicode": "9635"},
+    {"f": "Wingdings 2", "code": "169",  "unicode": "128917"},
+    {"f": "Wingdings 2", "code": "170",  "unicode": "128918"},
+    {"f": "Wingdings 2", "code": "171",  "unicode": "128919"},
+    {"f": "Wingdings 2", "code": "172",  "unicode": "128920"},
+    {"f": "Wingdings 2", "code": "173",  "unicode": "11049"},
+    {"f": "Wingdings 2", "code": "174",  "unicode": "11045"},
+    {"f": "Wingdings 2", "code": "175",  "unicode": "9671"},
+    {"f": "Wingdings 2", "code": "176",  "unicode": "128922"},
+    {"f": "Wingdings 2", "code": "177",  "unicode": "9672"},
+    {"f": "Wingdings 2", "code": "178",  "unicode": "128923"},
+    {"f": "Wingdings 2", "code": "179",  "unicode": "128924"},
+    {"f": "Wingdings 2", "code": "180",  "unicode": "128925"},
+    {"f": "Wingdings 2", "code": "181",  "unicode": "128926"},
+    {"f": "Wingdings 2", "code": "182",  "unicode": "11050"},
+    {"f": "Wingdings 2", "code": "183",  "unicode": "11047"},
+    {"f": "Wingdings 2", "code": "184",  "unicode": "9674"},
+    {"f": "Wingdings 2", "code": "185",  "unicode": "128928"},
+    {"f": "Wingdings 2", "code": "186",  "unicode": "9686"},
+    {"f": "Wingdings 2", "code": "187",  "unicode": "9687"},
+    {"f": "Wingdings 2", "code": "188",  "unicode": "11210"},
+    {"f": "Wingdings 2", "code": "189",  "unicode": "11211"},
+    {"f": "Wingdings 2", "code": "190",  "unicode": "11200"},
+    {"f": "Wingdings 2", "code": "191",  "unicode": "11201"},
+    {"f": "Wingdings 2", "code": "192",  "unicode": "11039"},
+    {"f": "Wingdings 2", "code": "193",  "unicode": "11202"},
+    {"f": "Wingdings 2", "code": "194",  "unicode": "11043"},
+    {"f": "Wingdings 2", "code": "195",  "unicode": "11042"},
+    {"f": "Wingdings 2", "code": "196",  "unicode": "11203"},
+    {"f": "Wingdings 2", "code": "197",  "unicode": "11204"},
+    {"f": "Wingdings 2", "code": "198",  "unicode": "128929"},
+    {"f": "Wingdings 2", "code": "199",  "unicode": "128930"},
+    {"f": "Wingdings 2", "code": "200",  "unicode": "128931"},
+    {"f": "Wingdings 2", "code": "201",  "unicode": "128932"},
+    {"f": "Wingdings 2", "code": "202",  "unicode": "128933"},
+    {"f": "Wingdings 2", "code": "203",  "unicode": "128934"},
+    {"f": "Wingdings 2", "code": "204",  "unicode": "128935"},
+    {"f": "Wingdings 2", "code": "205",  "unicode": "128936"},
+    {"f": "Wingdings 2", "code": "206",  "unicode": "128937"},
+    {"f": "Wingdings 2", "code": "207",  "unicode": "128938"},
+    {"f": "Wingdings 2", "code": "208",  "unicode": "128939"},
+    {"f": "Wingdings 2", "code": "209",  "unicode": "128940"},
+    {"f": "Wingdings 2", "code": "210",  "unicode": "128941"},
+    {"f": "Wingdings 2", "code": "211",  "unicode": "128942"},
+    {"f": "Wingdings 2", "code": "212",  "unicode": "128943"},
+    {"f": "Wingdings 2", "code": "213",  "unicode": "128944"},
+    {"f": "Wingdings 2", "code": "214",  "unicode": "128945"},
+    {"f": "Wingdings 2", "code": "215",  "unicode": "128946"},
+    {"f": "Wingdings 2", "code": "216",  "unicode": "128947"},
+    {"f": "Wingdings 2", "code": "217",  "unicode": "128948"},
+    {"f": "Wingdings 2", "code": "218",  "unicode": "128949"},
+    {"f": "Wingdings 2", "code": "219",  "unicode": "128950"},
+    {"f": "Wingdings 2", "code": "220",  "unicode": "128951"},
+    {"f": "Wingdings 2", "code": "221",  "unicode": "128952"},
+    {"f": "Wingdings 2", "code": "222",  "unicode": "128953"},
+    {"f": "Wingdings 2", "code": "223",  "unicode": "128954"},
+    {"f": "Wingdings 2", "code": "224",  "unicode": "128955"},
+    {"f": "Wingdings 2", "code": "225",  "unicode": "128956"},
+    {"f": "Wingdings 2", "code": "226",  "unicode": "128957"},
+    {"f": "Wingdings 2", "code": "227",  "unicode": "128958"},
+    {"f": "Wingdings 2", "code": "228",  "unicode": "128959"},
+    {"f": "Wingdings 2", "code": "229",  "unicode": "128960"},
+    {"f": "Wingdings 2", "code": "230",  "unicode": "128962"},
+    {"f": "Wingdings 2", "code": "231",  "unicode": "128964"},
+    {"f": "Wingdings 2", "code": "232",  "unicode": "128966"},
+    {"f": "Wingdings 2", "code": "233",  "unicode": "128969"},
+    {"f": "Wingdings 2", "code": "234",  "unicode": "128970"},
+    {"f": "Wingdings 2", "code": "235",  "unicode": "10038"},
+    {"f": "Wingdings 2", "code": "236",  "unicode": "128972"},
+    {"f": "Wingdings 2", "code": "237",  "unicode": "128974"},
+    {"f": "Wingdings 2", "code": "238",  "unicode": "128976"},
+    {"f": "Wingdings 2", "code": "239",  "unicode": "128978"},
+    {"f": "Wingdings 2", "code": "240",  "unicode": "10041"},
+    {"f": "Wingdings 2", "code": "241",  "unicode": "128963"},
+    {"f": "Wingdings 2", "code": "242",  "unicode": "128967"},
+    {"f": "Wingdings 2", "code": "243",  "unicode": "10031"},
+    {"f": "Wingdings 2", "code": "244",  "unicode": "128973"},
+    {"f": "Wingdings 2", "code": "245",  "unicode": "128980"},
+    {"f": "Wingdings 2", "code": "246",  "unicode": "11212"},
+    {"f": "Wingdings 2", "code": "247",  "unicode": "11213"},
+    {"f": "Wingdings 2", "code": "248",  "unicode": "8251"},
+    {"f": "Wingdings 2", "code": "249",  "unicode": "8258"},
+    {"f": "Wingdings 3", "code": "32",  "unicode": "32"},
+    {"f": "Wingdings 3", "code": "33",  "unicode": "11104"},
+    {"f": "Wingdings 3", "code": "34",  "unicode": "11106"},
+    {"f": "Wingdings 3", "code": "35",  "unicode": "11105"},
+    {"f": "Wingdings 3", "code": "36",  "unicode": "11107"},
+    {"f": "Wingdings 3", "code": "37",  "unicode": "11110"},
+    {"f": "Wingdings 3", "code": "38",  "unicode": "11111"},
+    {"f": "Wingdings 3", "code": "39",  "unicode": "11113"},
+    {"f": "Wingdings 3", "code": "40",  "unicode": "11112"},
+    {"f": "Wingdings 3", "code": "41",  "unicode": "11120"},
+    {"f": "Wingdings 3", "code": "42",  "unicode": "11122"},
+    {"f": "Wingdings 3", "code": "43",  "unicode": "11121"},
+    {"f": "Wingdings 3", "code": "44",  "unicode": "11123"},
+    {"f": "Wingdings 3", "code": "45",  "unicode": "11126"},
+    {"f": "Wingdings 3", "code": "46",  "unicode": "11128"},
+    {"f": "Wingdings 3", "code": "47",  "unicode": "11131"},
+    {"f": "Wingdings 3", "code": "48",  "unicode": "11133"},
+    {"f": "Wingdings 3", "code": "49",  "unicode": "11108"},
+    {"f": "Wingdings 3", "code": "50",  "unicode": "11109"},
+    {"f": "Wingdings 3", "code": "51",  "unicode": "11114"},
+    {"f": "Wingdings 3", "code": "52",  "unicode": "11116"},
+    {"f": "Wingdings 3", "code": "53",  "unicode": "11115"},
+    {"f": "Wingdings 3", "code": "54",  "unicode": "11117"},
+    {"f": "Wingdings 3", "code": "55",  "unicode": "11085"},
+    {"f": "Wingdings 3", "code": "56",  "unicode": "11168"},
+    {"f": "Wingdings 3", "code": "57",  "unicode": "11169"},
+    {"f": "Wingdings 3", "code": "58",  "unicode": "11170"},
+    {"f": "Wingdings 3", "code": "59",  "unicode": "11171"},
+    {"f": "Wingdings 3", "code": "60",  "unicode": "11172"},
+    {"f": "Wingdings 3", "code": "61",  "unicode": "11173"},
+    {"f": "Wingdings 3", "code": "62",  "unicode": "11174"},
+    {"f": "Wingdings 3", "code": "63",  "unicode": "11175"},
+    {"f": "Wingdings 3", "code": "64",  "unicode": "11152"},
+    {"f": "Wingdings 3", "code": "65",  "unicode": "11153"},
+    {"f": "Wingdings 3", "code": "66",  "unicode": "11154"},
+    {"f": "Wingdings 3", "code": "67",  "unicode": "11155"},
+    {"f": "Wingdings 3", "code": "68",  "unicode": "11136"},
+    {"f": "Wingdings 3", "code": "69",  "unicode": "11139"},
+    {"f": "Wingdings 3", "code": "70",  "unicode": "11134"},
+    {"f": "Wingdings 3", "code": "71",  "unicode": "11135"},
+    {"f": "Wingdings 3", "code": "72",  "unicode": "11140"},
+    {"f": "Wingdings 3", "code": "73",  "unicode": "11142"},
+    {"f": "Wingdings 3", "code": "74",  "unicode": "11141"},
+    {"f": "Wingdings 3", "code": "75",  "unicode": "11143"},
+    {"f": "Wingdings 3", "code": "76",  "unicode": "11151"},
+    {"f": "Wingdings 3", "code": "77",  "unicode": "11149"},
+    {"f": "Wingdings 3", "code": "78",  "unicode": "11150"},
+    {"f": "Wingdings 3", "code": "79",  "unicode": "11148"},
+    {"f": "Wingdings 3", "code": "80",  "unicode": "11118"},
+    {"f": "Wingdings 3", "code": "81",  "unicode": "11119"},
+    {"f": "Wingdings 3", "code": "82",  "unicode": "9099"},
+    {"f": "Wingdings 3", "code": "83",  "unicode": "8996"},
+    {"f": "Wingdings 3", "code": "84",  "unicode": "8963"},
+    {"f": "Wingdings 3", "code": "85",  "unicode": "8997"},
+    {"f": "Wingdings 3", "code": "86",  "unicode": "9251"},
+    {"f": "Wingdings 3", "code": "87",  "unicode": "9085"},
+    {"f": "Wingdings 3", "code": "88",  "unicode": "8682"},
+    {"f": "Wingdings 3", "code": "89",  "unicode": "11192"},
+    {"f": "Wingdings 3", "code": "90",  "unicode": "129184"},
+    {"f": "Wingdings 3", "code": "91",  "unicode": "129185"},
+    {"f": "Wingdings 3", "code": "92",  "unicode": "129186"},
+    {"f": "Wingdings 3", "code": "93",  "unicode": "129187"},
+    {"f": "Wingdings 3", "code": "94",  "unicode": "129188"},
+    {"f": "Wingdings 3", "code": "95",  "unicode": "129189"},
+    {"f": "Wingdings 3", "code": "96",  "unicode": "129190"},
+    {"f": "Wingdings 3", "code": "97",  "unicode": "129191"},
+    {"f": "Wingdings 3", "code": "98",  "unicode": "129192"},
+    {"f": "Wingdings 3", "code": "99",  "unicode": "129193"},
+    {"f": "Wingdings 3", "code": "100",  "unicode": "129194"},
+    {"f": "Wingdings 3", "code": "101",  "unicode": "129195"},
+    {"f": "Wingdings 3", "code": "102",  "unicode": "129104"},
+    {"f": "Wingdings 3", "code": "103",  "unicode": "129106"},
+    {"f": "Wingdings 3", "code": "104",  "unicode": "129105"},
+    {"f": "Wingdings 3", "code": "105",  "unicode": "129107"},
+    {"f": "Wingdings 3", "code": "106",  "unicode": "129108"},
+    {"f": "Wingdings 3", "code": "107",  "unicode": "129109"},
+    {"f": "Wingdings 3", "code": "108",  "unicode": "129111"},
+    {"f": "Wingdings 3", "code": "109",  "unicode": "129110"},
+    {"f": "Wingdings 3", "code": "110",  "unicode": "129112"},
+    {"f": "Wingdings 3", "code": "111",  "unicode": "129113"},
+    {"f": "Wingdings 3", "code": "112",  "unicode": "9650"},
+    {"f": "Wingdings 3", "code": "113",  "unicode": "9660"},
+    {"f": "Wingdings 3", "code": "114",  "unicode": "9651"},
+    {"f": "Wingdings 3", "code": "115",  "unicode": "9661"},
+    {"f": "Wingdings 3", "code": "116",  "unicode": "9664"},
+    {"f": "Wingdings 3", "code": "117",  "unicode": "9654"},
+    {"f": "Wingdings 3", "code": "118",  "unicode": "9665"},
+    {"f": "Wingdings 3", "code": "119",  "unicode": "9655"},
+    {"f": "Wingdings 3", "code": "120",  "unicode": "9699"},
+    {"f": "Wingdings 3", "code": "121",  "unicode": "9698"},
+    {"f": "Wingdings 3", "code": "122",  "unicode": "9700"},
+    {"f": "Wingdings 3", "code": "123",  "unicode": "9701"},
+    {"f": "Wingdings 3", "code": "124",  "unicode": "128896"},
+    {"f": "Wingdings 3", "code": "125",  "unicode": "128898"},
+    {"f": "Wingdings 3", "code": "126",  "unicode": "128897"},
+    {"f": "Wingdings 3", "code": "128",  "unicode": "128899"},
+    {"f": "Wingdings 3", "code": "129",  "unicode": "11205"},
+    {"f": "Wingdings 3", "code": "130",  "unicode": "11206"},
+    {"f": "Wingdings 3", "code": "131",  "unicode": "11207"},
+    {"f": "Wingdings 3", "code": "132",  "unicode": "11208"},
+    {"f": "Wingdings 3", "code": "133",  "unicode": "11164"},
+    {"f": "Wingdings 3", "code": "134",  "unicode": "11166"},
+    {"f": "Wingdings 3", "code": "135",  "unicode": "11165"},
+    {"f": "Wingdings 3", "code": "136",  "unicode": "11167"},
+    {"f": "Wingdings 3", "code": "137",  "unicode": "129040"},
+    {"f": "Wingdings 3", "code": "138",  "unicode": "129042"},
+    {"f": "Wingdings 3", "code": "139",  "unicode": "129041"},
+    {"f": "Wingdings 3", "code": "140",  "unicode": "129043"},
+    {"f": "Wingdings 3", "code": "141",  "unicode": "129044"},
+    {"f": "Wingdings 3", "code": "142",  "unicode": "129046"},
+    {"f": "Wingdings 3", "code": "143",  "unicode": "129045"},
+    {"f": "Wingdings 3", "code": "144",  "unicode": "129047"},
+    {"f": "Wingdings 3", "code": "145",  "unicode": "129048"},
+    {"f": "Wingdings 3", "code": "146",  "unicode": "129050"},
+    {"f": "Wingdings 3", "code": "147",  "unicode": "129049"},
+    {"f": "Wingdings 3", "code": "148",  "unicode": "129051"},
+    {"f": "Wingdings 3", "code": "149",  "unicode": "129052"},
+    {"f": "Wingdings 3", "code": "150",  "unicode": "129054"},
+    {"f": "Wingdings 3", "code": "151",  "unicode": "129053"},
+    {"f": "Wingdings 3", "code": "152",  "unicode": "129055"},
+    {"f": "Wingdings 3", "code": "153",  "unicode": "129024"},
+    {"f": "Wingdings 3", "code": "154",  "unicode": "129026"},
+    {"f": "Wingdings 3", "code": "155",  "unicode": "129025"},
+    {"f": "Wingdings 3", "code": "156",  "unicode": "129027"},
+    {"f": "Wingdings 3", "code": "157",  "unicode": "129028"},
+    {"f": "Wingdings 3", "code": "158",  "unicode": "129030"},
+    {"f": "Wingdings 3", "code": "159",  "unicode": "129029"},
+    {"f": "Wingdings 3", "code": "160",  "unicode": "129031"},
+    {"f": "Wingdings 3", "code": "161",  "unicode": "129032"},
+    {"f": "Wingdings 3", "code": "162",  "unicode": "129034"},
+    {"f": "Wingdings 3", "code": "163",  "unicode": "129033"},
+    {"f": "Wingdings 3", "code": "164",  "unicode": "129035"},
+    {"f": "Wingdings 3", "code": "165",  "unicode": "129056"},
+    {"f": "Wingdings 3", "code": "166",  "unicode": "129058"},
+    {"f": "Wingdings 3", "code": "167",  "unicode": "129060"},
+    {"f": "Wingdings 3", "code": "168",  "unicode": "129062"},
+    {"f": "Wingdings 3", "code": "169",  "unicode": "129064"},
+    {"f": "Wingdings 3", "code": "170",  "unicode": "129066"},
+    {"f": "Wingdings 3", "code": "171",  "unicode": "129068"},
+    {"f": "Wingdings 3", "code": "172",  "unicode": "129180"},
+    {"f": "Wingdings 3", "code": "173",  "unicode": "129181"},
+    {"f": "Wingdings 3", "code": "174",  "unicode": "129182"},
+    {"f": "Wingdings 3", "code": "175",  "unicode": "129183"},
+    {"f": "Wingdings 3", "code": "176",  "unicode": "129070"},
+    {"f": "Wingdings 3", "code": "177",  "unicode": "129072"},
+    {"f": "Wingdings 3", "code": "178",  "unicode": "129074"},
+    {"f": "Wingdings 3", "code": "179",  "unicode": "129076"},
+    {"f": "Wingdings 3", "code": "180",  "unicode": "129078"},
+    {"f": "Wingdings 3", "code": "181",  "unicode": "129080"},
+    {"f": "Wingdings 3", "code": "182",  "unicode": "129082"},
+    {"f": "Wingdings 3", "code": "183",  "unicode": "129081"},
+    {"f": "Wingdings 3", "code": "184",  "unicode": "129083"},
+    {"f": "Wingdings 3", "code": "185",  "unicode": "129176"},
+    {"f": "Wingdings 3", "code": "186",  "unicode": "129178"},
+    {"f": "Wingdings 3", "code": "187",  "unicode": "129177"},
+    {"f": "Wingdings 3", "code": "188",  "unicode": "129179"},
+    {"f": "Wingdings 3", "code": "189",  "unicode": "129084"},
+    {"f": "Wingdings 3", "code": "190",  "unicode": "129086"},
+    {"f": "Wingdings 3", "code": "191",  "unicode": "129085"},
+    {"f": "Wingdings 3", "code": "192",  "unicode": "129087"},
+    {"f": "Wingdings 3", "code": "193",  "unicode": "129088"},
+    {"f": "Wingdings 3", "code": "194",  "unicode": "129090"},
+    {"f": "Wingdings 3", "code": "195",  "unicode": "129089"},
+    {"f": "Wingdings 3", "code": "196",  "unicode": "129091"},
+    {"f": "Wingdings 3", "code": "197",  "unicode": "129092"},
+    {"f": "Wingdings 3", "code": "198",  "unicode": "129094"},
+    {"f": "Wingdings 3", "code": "199",  "unicode": "129093"},
+    {"f": "Wingdings 3", "code": "200",  "unicode": "129095"},
+    {"f": "Wingdings 3", "code": "201",  "unicode": "11176"},
+    {"f": "Wingdings 3", "code": "202",  "unicode": "11177"},
+    {"f": "Wingdings 3", "code": "203",  "unicode": "11178"},
+    {"f": "Wingdings 3", "code": "204",  "unicode": "11179"},
+    {"f": "Wingdings 3", "code": "205",  "unicode": "11180"},
+    {"f": "Wingdings 3", "code": "206",  "unicode": "11181"},
+    {"f": "Wingdings 3", "code": "207",  "unicode": "11182"},
+    {"f": "Wingdings 3", "code": "208",  "unicode": "11183"},
+    {"f": "Wingdings 3", "code": "209",  "unicode": "129120"},
+    {"f": "Wingdings 3", "code": "210",  "unicode": "129122"},
+    {"f": "Wingdings 3", "code": "211",  "unicode": "129121"},
+    {"f": "Wingdings 3", "code": "212",  "unicode": "129123"},
+    {"f": "Wingdings 3", "code": "213",  "unicode": "129124"},
+    {"f": "Wingdings 3", "code": "214",  "unicode": "129125"},
+    {"f": "Wingdings 3", "code": "215",  "unicode": "129127"},
+    {"f": "Wingdings 3", "code": "216",  "unicode": "129126"},
+    {"f": "Wingdings 3", "code": "217",  "unicode": "129136"},
+    {"f": "Wingdings 3", "code": "218",  "unicode": "129138"},
+    {"f": "Wingdings 3", "code": "219",  "unicode": "129137"},
+    {"f": "Wingdings 3", "code": "220",  "unicode": "129139"},
+    {"f": "Wingdings 3", "code": "221",  "unicode": "129140"},
+    {"f": "Wingdings 3", "code": "222",  "unicode": "129141"},
+    {"f": "Wingdings 3", "code": "223",  "unicode": "129143"},
+    {"f": "Wingdings 3", "code": "224",  "unicode": "129142"},
+    {"f": "Wingdings 3", "code": "225",  "unicode": "129152"},
+    {"f": "Wingdings 3", "code": "226",  "unicode": "129154"},
+    {"f": "Wingdings 3", "code": "227",  "unicode": "129153"},
+    {"f": "Wingdings 3", "code": "228",  "unicode": "129155"},
+    {"f": "Wingdings 3", "code": "229",  "unicode": "129156"},
+    {"f": "Wingdings 3", "code": "230",  "unicode": "129157"},
+    {"f": "Wingdings 3", "code": "231",  "unicode": "129159"},
+    {"f": "Wingdings 3", "code": "232",  "unicode": "129158"},
+    {"f": "Wingdings 3", "code": "233",  "unicode": "129168"},
+    {"f": "Wingdings 3", "code": "234",  "unicode": "129170"},
+    {"f": "Wingdings 3", "code": "235",  "unicode": "129169"},
+    {"f": "Wingdings 3", "code": "236",  "unicode": "129171"},
+    {"f": "Wingdings 3", "code": "237",  "unicode": "129172"},
+    {"f": "Wingdings 3", "code": "238",  "unicode": "129174"},
+    {"f": "Wingdings 3", "code": "239",  "unicode": "129173"},
+    {"f": "Wingdings 3", "code": "240",  "unicode": "129175"}
+]

File diff suppressed because it is too large
+ 517 - 0
app/src/main/assets/web/pptx-js-1.21.1/js/divs2slides.js


File diff suppressed because it is too large
+ 12 - 0
app/src/main/assets/web/pptx-js-1.21.1/js/divs2slides.min.js


+ 455 - 0
app/src/main/assets/web/pptx-js-1.21.1/js/filereader.js

@@ -0,0 +1,455 @@
+/*!
+FileReader.js - v0.99
+A lightweight wrapper for common FileReader usage.
+Copyright 2014 Brian Grinstead - MIT License.
+See http://github.com/bgrins/filereader.js for documentation.
+*/
+
+(function(window, document) {
+
+    var FileReader = window.FileReader;
+    var FileReaderSyncSupport = false;
+    var workerScript = "self.addEventListener('message', function(e) { var data=e.data; try { var reader = new FileReaderSync; postMessage({ result: reader[data.readAs](data.file), extra: data.extra, file: data.file})} catch(e){ postMessage({ result:'error', extra:data.extra, file:data.file}); } }, false);";
+    var syncDetectionScript = "onmessage = function(e) { postMessage(!!FileReaderSync); };";
+    var fileReaderEvents = ['loadstart', 'progress', 'load', 'abort', 'error', 'loadend'];
+    var sync = false;
+    var FileReaderJS = window.FileReaderJS = {
+        enabled: false,
+        setupInput: setupInput,
+        setupBlob: setupBlob,
+        setupDrop: setupDrop,
+        setupClipboard: setupClipboard,
+        setSync: function (value) {
+            sync = value;
+
+            if (sync && !FileReaderSyncSupport) {
+                checkFileReaderSyncSupport();
+            }
+        },
+        getSync: function() {
+            return sync && FileReaderSyncSupport;
+        },
+        output: [],
+        opts: {
+            dragClass: "drag",
+            accept: false,
+            readAsDefault: 'DataURL',
+            readAsMap: {
+            },
+            on: {
+                loadstart: noop,
+                progress: noop,
+                load: noop,
+                abort: noop,
+                error: noop,
+                loadend: noop,
+                skip: noop,
+                groupstart: noop,
+                groupend: noop,
+                beforestart: noop
+            }
+        }
+    };
+
+    // Setup jQuery plugin (if available)
+    if (typeof(jQuery) !== "undefined") {
+        jQuery.fn.fileReaderJS = function(opts) {
+            return this.each(function() {
+                if (jQuery(this).is("input")) {
+                    setupInput(this, opts);
+                }
+                else {
+                    setupDrop(this, opts);
+                }
+            });
+        };
+
+        jQuery.fn.fileClipboard = function(opts) {
+            return this.each(function() {
+                setupClipboard(this, opts);
+            });
+        };
+    }
+
+    // Not all browsers support the FileReader interface. Return with the enabled bit = false.
+    if (!FileReader) {
+        return;
+    }
+
+
+    // makeWorker is a little wrapper for generating web workers from strings
+    function makeWorker(script) {
+        var URL = window.URL || window.webkitURL;
+        var Blob = window.Blob;
+        var Worker = window.Worker;
+
+        if (!URL || !Blob || !Worker || !script) {
+            return null;
+        }
+
+        var blob = new Blob([script]);
+        var worker = new Worker(URL.createObjectURL(blob));
+        return worker;
+    }
+
+    // setupClipboard: bind to clipboard events (intended for document.body)
+    function setupClipboard(element, opts) {
+
+        if (!FileReaderJS.enabled) {
+            return;
+        }
+        var instanceOptions = extend(extend({}, FileReaderJS.opts), opts);
+
+        element.addEventListener("paste", onpaste, false);
+
+        function onpaste(e) {
+            var files = [];
+            var clipboardData = e.clipboardData || {};
+            var items = clipboardData.items || [];
+
+            for (var i = 0; i < items.length; i++) {
+                var file = items[i].getAsFile();
+
+                if (file) {
+
+                    // Create a fake file name for images from clipboard, since this data doesn't get sent
+                    var matches = new RegExp("/\(.*\)").exec(file.type);
+                    if (!file.name && matches) {
+                        var extension = matches[1];
+                        file.name = "clipboard" + i + "." + extension;
+                    }
+
+                    files.push(file);
+                }
+            }
+
+            if (files.length) {
+                processFileList(e, files, instanceOptions);
+                e.preventDefault();
+                e.stopPropagation();
+            }
+        }
+    }
+
+    // setupInput: bind the 'change' event to an input[type=file]
+    function setupInput(input, opts) {
+
+        if (!FileReaderJS.enabled) {
+            return;
+        }
+        var instanceOptions = extend(extend({}, FileReaderJS.opts), opts);
+
+        input.addEventListener("change", inputChange, false);
+        input.addEventListener("drop", inputDrop, false);
+
+        function inputChange(e) {
+            processFileList(e, input.files, instanceOptions);
+        }
+
+        function inputDrop(e) {
+            e.stopPropagation();
+            e.preventDefault();
+            processFileList(e, e.dataTransfer.files, instanceOptions);
+        }
+    }
+    // setupFile: bind the 'change' event to an input[type=file]
+    function setupBlob(blob, opts) {
+       
+        if (!FileReaderJS.enabled) {
+            return;
+        }
+
+        if(blob.constructor !== Array && blob.constructor !== Function){
+            if(blob.name === undefined){
+                blob.name = "blob";
+            }          
+            blob = [blob];
+        }else{
+
+            if(blob[0].name === undefined){
+                blob[0].name = "blob";
+            }    
+        }
+        
+        var instanceOptions = extend(extend({}, FileReaderJS.opts), opts);
+
+        processFileList(null, blob, instanceOptions);
+
+    }
+    // setupDrop: bind the 'drop' event for a DOM element
+    function setupDrop(dropbox, opts) {
+
+        if (!FileReaderJS.enabled) {
+            return;
+        }
+        var instanceOptions = extend(extend({}, FileReaderJS.opts), opts);
+        var dragClass = instanceOptions.dragClass;
+        var initializedOnBody = false;
+
+        // Bind drag events to the dropbox to add the class while dragging, and accept the drop data transfer.
+        dropbox.addEventListener("dragenter", onlyWithFiles(dragenter), false);
+        dropbox.addEventListener("dragleave", onlyWithFiles(dragleave), false);
+        dropbox.addEventListener("dragover", onlyWithFiles(dragover), false);
+        dropbox.addEventListener("drop", onlyWithFiles(drop), false);
+
+        // Bind to body to prevent the dropbox events from firing when it was initialized on the page.
+        document.body.addEventListener("dragstart", bodydragstart, true);
+        document.body.addEventListener("dragend", bodydragend, true);
+        document.body.addEventListener("drop", bodydrop, false);
+
+        function bodydragend(e) {
+            initializedOnBody = false;
+        }
+
+        function bodydragstart(e) {
+            initializedOnBody = true;
+        }
+
+        function bodydrop(e) {
+            if (e.dataTransfer.files && e.dataTransfer.files.length ){
+                e.stopPropagation();
+                e.preventDefault();
+            }
+        }
+
+        function onlyWithFiles(fn) {
+            return function() {
+                if (!initializedOnBody) {
+                    fn.apply(this, arguments);
+                }
+            };
+        }
+
+        function drop(e) {
+            e.stopPropagation();
+            e.preventDefault();
+            if (dragClass) {
+                removeClass(dropbox, dragClass);
+            }
+            processFileList(e, e.dataTransfer.files, instanceOptions);
+        }
+
+        function dragenter(e) {
+            e.stopPropagation();
+            e.preventDefault();
+            if (dragClass) {
+                addClass(dropbox, dragClass);
+            }
+        }
+
+        function dragleave(e) {
+            if (dragClass) {
+                removeClass(dropbox, dragClass);
+            }
+        }
+
+        function dragover(e) {
+            e.stopPropagation();
+            e.preventDefault();
+            if (dragClass) {
+                addClass(dropbox, dragClass);
+            }
+        }
+    }
+
+    // setupCustomFileProperties: modify the file object with extra properties
+    function setupCustomFileProperties(files, groupID) {
+        for (var i = 0; i < files.length; i++) {
+            var file = files[i];
+            file.extra = {
+                nameNoExtension: file.name.substring(0, file.name.lastIndexOf('.')),
+                extension: file.name.substring(file.name.lastIndexOf('.') + 1),
+                fileID: i,
+                uniqueID: getUniqueID(),
+                groupID: groupID,
+                prettySize: prettySize(file.size)
+            };
+        }
+    }
+
+    // getReadAsMethod: return method name for 'readAs*' - http://www.w3.org/TR/FileAPI/#reading-a-file
+    function getReadAsMethod(type, readAsMap, readAsDefault) {
+        for (var r in readAsMap) {
+            if (type.match(new RegExp(r))) {
+                return 'readAs' + readAsMap[r];
+            }
+        }
+        return 'readAs' + readAsDefault;
+    }
+
+    // processFileList: read the files with FileReader, send off custom events.
+    function processFileList(e, files, opts) {
+        var filesLeft = files.length;
+        var group = {
+            groupID: getGroupID(),
+            files: files,
+            started: new Date()
+        };
+
+        function groupEnd() {
+            group.ended = new Date();
+            opts.on.groupend(group);
+        }
+
+        function groupFileDone() {
+            if (--filesLeft === 0) {
+                groupEnd();
+            }
+        }
+
+        FileReaderJS.output.push(group);
+        setupCustomFileProperties(files, group.groupID);
+
+        opts.on.groupstart(group);
+
+        // No files in group - end immediately
+        if (!files.length) {
+            groupEnd();
+            return;
+        }
+
+        var supportsSync = sync && FileReaderSyncSupport;
+        var syncWorker;
+
+        // Only initialize the synchronous worker if the option is enabled - to prevent the overhead
+        if (supportsSync) {
+            syncWorker = makeWorker(workerScript);
+            syncWorker.onmessage = function(e) {
+                var file = e.data.file;
+                var result = e.data.result;
+
+                // Workers seem to lose the custom property on the file object.
+                if (!file.extra) {
+                    file.extra = e.data.extra;
+                }
+
+                file.extra.ended = new Date();
+
+                // Call error or load event depending on success of the read from the worker.
+                opts.on[result === "error" ? "error" : "load"]({ target: { result: result } }, file);
+                groupFileDone();
+            };
+        }
+
+        Array.prototype.forEach.call(files, function(file) {
+
+            file.extra.started = new Date();
+
+            if (opts.accept && !file.type.match(new RegExp(opts.accept))) {
+                opts.on.skip(file);
+                groupFileDone();
+                return;
+            }
+
+            if (opts.on.beforestart(file) === false) {
+                opts.on.skip(file);
+                groupFileDone();
+                return;
+            }
+
+            var readAs = getReadAsMethod(file.type, opts.readAsMap, opts.readAsDefault);
+
+            if (syncWorker) {
+                syncWorker.postMessage({
+                    file: file,
+                    extra: file.extra,
+                    readAs: readAs
+                });
+            }
+            else {
+
+                var reader = new FileReader();
+                reader.originalEvent = e;
+
+                fileReaderEvents.forEach(function(eventName) {
+                    reader['on' + eventName] = function(e) {
+                        if (eventName == 'load' || eventName == 'error') {
+                            file.extra.ended = new Date();
+                        }
+                        opts.on[eventName](e, file);
+                        if (eventName == 'loadend') {
+                            groupFileDone();
+                        }
+                    };
+                });
+                reader[readAs](file);
+            }
+        });
+    }
+
+    // checkFileReaderSyncSupport: Create a temporary worker and see if FileReaderSync exists
+    function checkFileReaderSyncSupport() {
+        var worker = makeWorker(syncDetectionScript);
+        if (worker) {
+            worker.onmessage =function(e) {
+                FileReaderSyncSupport = e.data;
+            };
+            worker.postMessage({});
+        }
+    }
+
+    // noop: do nothing
+    function noop() {
+
+    }
+
+    // extend: used to make deep copies of options object
+    function extend(destination, source) {
+        for (var property in source) {
+            if (source[property] && source[property].constructor &&
+                source[property].constructor === Object) {
+                destination[property] = destination[property] || {};
+                arguments.callee(destination[property], source[property]);
+            }
+            else {
+                destination[property] = source[property];
+            }
+        }
+        return destination;
+    }
+
+    // hasClass: does an element have the css class?
+    function hasClass(el, name) {
+        return new RegExp("(?:^|\\s+)" + name + "(?:\\s+|$)").test(el.className);
+    }
+
+    // addClass: add the css class for the element.
+    function addClass(el, name) {
+        if (!hasClass(el, name)) {
+          el.className = el.className ? [el.className, name].join(' ') : name;
+        }
+    }
+
+    // removeClass: remove the css class from the element.
+    function removeClass(el, name) {
+        if (hasClass(el, name)) {
+          var c = el.className;
+          el.className = c.replace(new RegExp("(?:^|\\s+)" + name + "(?:\\s+|$)", "g"), " ").replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+        }
+    }
+
+    // prettySize: convert bytes to a more readable string.
+    function prettySize(bytes) {
+        var s = ['bytes', 'kb', 'MB', 'GB', 'TB', 'PB'];
+        var e = Math.floor(Math.log(bytes)/Math.log(1024));
+        return (bytes/Math.pow(1024, Math.floor(e))).toFixed(2)+" "+s[e];
+    }
+
+    // getGroupID: generate a unique int ID for groups.
+    var getGroupID = (function(id) {
+        return function() {
+            return id++;
+        };
+    })(0);
+
+    // getUniqueID: generate a unique int ID for files
+    var getUniqueID = (function(id) {
+        return function() {
+            return id++;
+        };
+    })(0);
+
+    // The interface is supported, bind the FileReaderJS callbacks
+    FileReaderJS.enabled = true;
+
+})(this, document);

File diff suppressed because it is too large
+ 5 - 0
app/src/main/assets/web/pptx-js-1.21.1/js/jquery-1.11.3.min.js


File diff suppressed because it is too large
+ 10 - 0
app/src/main/assets/web/pptx-js-1.21.1/js/jquery.fullscreen-min.js


File diff suppressed because it is too large
+ 14 - 0
app/src/main/assets/web/pptx-js-1.21.1/js/jszip.min.js


File diff suppressed because it is too large
+ 10 - 0
app/src/main/assets/web/pptx-js-1.21.1/js/nv.d3.min.js


File diff suppressed because it is too large
+ 14104 - 0
app/src/main/assets/web/pptx-js-1.21.1/js/pptxjs.js


File diff suppressed because it is too large
+ 10 - 0
app/src/main/assets/web/pptx-js-1.21.1/js/pptxjs.min.js


+ 2 - 3
app/src/main/java/com/dlc/exam/ExamApp.kt

@@ -9,10 +9,10 @@ import android.content.IntentFilter
 import android.os.Handler
 import android.os.Handler
 import android.os.Looper
 import android.os.Looper
 import android.os.Message
 import android.os.Message
-import android.support.multidex.MultiDex
 import android.util.Log
 import android.util.Log
 import android.widget.Toast
 import android.widget.Toast
 import androidx.localbroadcastmanager.content.LocalBroadcastManager
 import androidx.localbroadcastmanager.content.LocalBroadcastManager
+import androidx.multidex.MultiDex
 import com.dlc.exam.common.Constants
 import com.dlc.exam.common.Constants
 import com.dlc.exam.sp.EnvSp
 import com.dlc.exam.sp.EnvSp
 import com.dlc.exam.ui.SplashActivity
 import com.dlc.exam.ui.SplashActivity
@@ -25,7 +25,6 @@ import com.rc.httpcore.HttpClient
 import com.rc.httpcore.config.ConfigCore
 import com.rc.httpcore.config.ConfigCore
 import com.rc.httpcore.config.ConfigFactory
 import com.rc.httpcore.config.ConfigFactory
 import com.rc.httpcore.vo.response.LearnLoginVo
 import com.rc.httpcore.vo.response.LearnLoginVo
-import com.tencent.bugly.crashreport.CrashReport
 
 
 /**
 /**
  * info
  * info
@@ -136,6 +135,6 @@ class ExamApp : Application() {
          * 建议在测试阶段建议设置成true,发布时设置为false。
          * 建议在测试阶段建议设置成true,发布时设置为false。
          */
          */
 //        CrashReport.initCrashReport(this, Constants.Bugly.APP_ID, true)
 //        CrashReport.initCrashReport(this, Constants.Bugly.APP_ID, true)
-        CrashReport.initCrashReport(this, Constants.Bugly.APP_ID, false)
+//        CrashReport.initCrashReport(this, Constants.Bugly.APP_ID, false)
     }
     }
 }
 }

+ 2 - 2
app/src/main/java/com/dlc/exam/ui/MainActivity.kt

@@ -111,10 +111,10 @@ class MainActivity : BaseCountDownActivity<ActivityMainBinding>(), TitleBar.Titl
 
 
     private fun dispatchMenuClicked(menuClass: Class<out BaseCountDownActivity<out ViewBinding>>) {
     private fun dispatchMenuClicked(menuClass: Class<out BaseCountDownActivity<out ViewBinding>>) {
         mMenuClass = menuClass
         mMenuClass = menuClass
-//        if (isLogin()) {
+        if (isLogin()) {
             val intent = Intent(this, mMenuClass)
             val intent = Intent(this, mMenuClass)
             startActivity(intent)
             startActivity(intent)
-//        }
+        }
     }
     }
 
 
     private fun isLogin(): Boolean {
     private fun isLogin(): Boolean {

+ 1 - 1
app/src/main/java/com/dlc/exam/ui/exam/MockExamActivity.kt

@@ -91,7 +91,7 @@ class MockExamActivity :
                 dismissLoading()
                 dismissLoading()
                 showNetError(throwable)
                 showNetError(throwable)
                 throwable.printStackTrace()
                 throwable.printStackTrace()
-                mMockExamTypeAdapter.setEmptyView(R.layout.view_list_empty)
+                mMockExamTypeAdapter.setEmptyView(com.rc.core.R.layout.view_list_empty)
             })
             })
         addDisposable(disposable)
         addDisposable(disposable)
     }
     }

+ 44 - 12
app/src/main/java/com/dlc/exam/ui/learn/CourseChapterActivity.kt

@@ -7,21 +7,22 @@ import android.view.LayoutInflater
 import android.view.View
 import android.view.View
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.LinearLayoutManager
 import com.chad.library.adapter.base.BaseDelegateMultiAdapter
 import com.chad.library.adapter.base.BaseDelegateMultiAdapter
+import com.chad.library.adapter.base.delegate.BaseMultiTypeDelegate
 import com.chad.library.adapter.base.viewholder.BaseViewHolder
 import com.chad.library.adapter.base.viewholder.BaseViewHolder
+import com.dlc.exam.ExamApp
 import com.dlc.exam.R
 import com.dlc.exam.R
 import com.dlc.exam.databinding.ActivityCourseChapterBinding
 import com.dlc.exam.databinding.ActivityCourseChapterBinding
-import com.dlc.exam.ui.common.BaseCountDownActivity
-import com.rc.httpcore.client.ApiRepository
-import com.rc.httpcore.vo.response.ExamCourseVo
-import com.chad.library.adapter.base.delegate.BaseMultiTypeDelegate
-import com.dlc.exam.ExamApp
 import com.dlc.exam.ui.MainActivity
 import com.dlc.exam.ui.MainActivity
+import com.dlc.exam.ui.common.BaseCountDownActivity
 import com.dlc.exam.ui.learn.test.ClassTestActivity
 import com.dlc.exam.ui.learn.test.ClassTestActivity
 import com.dlc.exam.ui.learn.test.ClassTestRecordListActivity
 import com.dlc.exam.ui.learn.test.ClassTestRecordListActivity
 import com.dlc.exam.ui.me.PersonalCenterActivity
 import com.dlc.exam.ui.me.PersonalCenterActivity
 import com.dlc.exam.ui.widget.TitleBar
 import com.dlc.exam.ui.widget.TitleBar
+import com.google.gson.Gson
 import com.rc.httpcore.HttpClient
 import com.rc.httpcore.HttpClient
-import java.util.ArrayList
+import com.rc.httpcore.HttpConfig
+import com.rc.httpcore.client.ApiRepository
+import com.rc.httpcore.vo.response.ExamCourseVo
 
 
 /**
 /**
  * 安全学习-章节
  * 安全学习-章节
@@ -52,12 +53,15 @@ class CourseChapterActivity : BaseCountDownActivity<ActivityCourseChapterBinding
             when (view.id) {
             when (view.id) {
                 R.id.startLearn -> {
                 R.id.startLearn -> {
                     // 开始学习
                     // 开始学习
-                    dispatchStartLearn(item.data.learnStatus, position)
+//                    dispatchStartLearn(item.data.learnStatus, position)
+                    dispatchStartLearn(item.data)
                 }
                 }
+
                 R.id.classTest -> {
                 R.id.classTest -> {
                     // 课后考核课后考核
                     // 课后考核课后考核
                     dispatchClassTest(item.data.id)
                     dispatchClassTest(item.data.id)
                 }
                 }
+
                 R.id.classTestRecord -> {
                 R.id.classTestRecord -> {
                     // 考核记录
                     // 考核记录
                     dispatchClassTestRecord(item.data.id)
                     dispatchClassTestRecord(item.data.id)
@@ -80,7 +84,31 @@ class CourseChapterActivity : BaseCountDownActivity<ActivityCourseChapterBinding
         startActivityForResult(intent, 100)
         startActivityForResult(intent, 100)
     }
     }
 
 
-    private fun dispatchStartLearn(learnStatus: String?,position: Int) {
+    private fun dispatchStartLearn(courseVo: ExamCourseVo.ChapterVo) {
+        val chapterBean = LearnChapterBean().apply {
+            chapterId = courseVo.id
+            courseId = courseVo.courseId
+            type = courseVo.type
+            chapterData = courseVo.chapterData
+            duration = courseVo.duration
+            title = courseVo.title
+            assessStatus = courseVo.showClassTest()
+        }
+        val intent = Intent()
+        intent.putExtra("Chapter", chapterBean)
+        intent.putExtra("relearn", "1" == courseVo.learnStatus)
+        //  视频处理
+        if (chapterBean.type == "2") {
+            intent.setClass(this, LearnDetailExoActivity::class.java)
+        }
+        // WebView处理
+        else {
+            intent.setClass(this, LearnDetailWebActivity::class.java)
+        }
+        startActivityForResult(intent, 100)
+    }
+
+    private fun dispatchStartLearn(learnStatus: String?, position: Int) {
 //        val intent = Intent(this, FullScreenActivity::class.java)
 //        val intent = Intent(this, FullScreenActivity::class.java)
 //        startActivityForResult(intent, 100)
 //        startActivityForResult(intent, 100)
         val intent = Intent(this, LearnDetailActivity::class.java)
         val intent = Intent(this, LearnDetailActivity::class.java)
@@ -147,14 +175,15 @@ class CourseChapterActivity : BaseCountDownActivity<ActivityCourseChapterBinding
             // 学习时长
             // 学习时长
             viewBinding.time.text = "学习时长:${it.durationsStr ?: ""}"
             viewBinding.time.text = "学习时长:${it.durationsStr ?: ""}"
             // 有效期
             // 有效期
-            viewBinding.termValidity.text = "有效期:${if ("0" == it.ceType) "永久" else it.ceTime ?: ""}"
+            viewBinding.termValidity.text =
+                "有效期:${if ("0" == it.ceType) "永久" else it.ceTime ?: ""}"
             // 已有1250人学习
             // 已有1250人学习
             viewBinding.learnPersonCount.text = "已有${it.learns ?: "0"}人学习"
             viewBinding.learnPersonCount.text = "已有${it.learns ?: "0"}人学习"
 
 
             val chapterData = generateChapterData(it.chapterList)
             val chapterData = generateChapterData(it.chapterList)
             mChapterAdapter.setNewInstance(chapterData)
             mChapterAdapter.setNewInstance(chapterData)
             if (chapterData.isNullOrEmpty()) {
             if (chapterData.isNullOrEmpty()) {
-                mChapterAdapter.setEmptyView(R.layout.view_list_empty)
+                mChapterAdapter.setEmptyView(com.rc.core.R.layout.view_list_empty)
             }
             }
         }
         }
     }
     }
@@ -259,7 +288,10 @@ private class ChapterAdapter : BaseDelegateMultiAdapter<ChapterInfo, BaseViewHol
                 .setGone(R.id.classTestRecord, !item.data.showClassTestRecord())
                 .setGone(R.id.classTestRecord, !item.data.showClassTestRecord())
         } else {
         } else {
             holder.setGone(R.id.startLearn, false)
             holder.setGone(R.id.startLearn, false)
-                .setText(R.id.startLearn, if ("1" == item.data.learnStatus) "重新学习" else "开始学习")
+                .setText(
+                    R.id.startLearn,
+                    if ("1" == item.data.learnStatus) "重新学习" else "开始学习"
+                )
                 .setGone(R.id.classTest, !item.data.showClassTest())
                 .setGone(R.id.classTest, !item.data.showClassTest())
                 .setGone(R.id.learnDuration, true)
                 .setGone(R.id.learnDuration, true)
                 .setGone(R.id.classTestRecord, true)
                 .setGone(R.id.classTestRecord, true)
@@ -272,7 +304,7 @@ private class ChapterAdapter : BaseDelegateMultiAdapter<ChapterInfo, BaseViewHol
      * @param learnStatus 学习状态 0 学习中,2 未学习,3 待考核,1 已完成
      * @param learnStatus 学习状态 0 学习中,2 未学习,3 待考核,1 已完成
      */
      */
     private fun learnStatusImg(learnStatus: Int): Int? {
     private fun learnStatusImg(learnStatus: Int): Int? {
-        return when(learnStatus) {
+        return when (learnStatus) {
             0 -> R.mipmap.icon_xxzyz
             0 -> R.mipmap.icon_xxzyz
             1 -> R.mipmap.icon_ywcyz
             1 -> R.mipmap.icon_ywcyz
             3 -> R.mipmap.icon_dkhyz
             3 -> R.mipmap.icon_dkhyz

+ 9 - 6
app/src/main/java/com/dlc/exam/ui/learn/LearnCompletedDialog.kt

@@ -34,15 +34,18 @@ class LearnCompletedDialog(
 
 
         setContentView(viewBinding.root)
         setContentView(viewBinding.root)
 
 
-        viewBinding.close.setOnClickListener { dismiss() }
+        viewBinding.close.setOnClickListener {
+            dismiss()
+            listener.invoke()
+        }
         viewBinding.learnBonusScore.text =
         viewBinding.learnBonusScore.text =
             "已学习时长${data.durationStr ?: "0"},共获得${data.points ?: "0"}奖励分"
             "已学习时长${data.durationStr ?: "0"},共获得${data.points ?: "0"}奖励分"
 
 
-        if (endChapter) {
-            viewBinding.title.text = "您已学习完最后一章节"
-        } else {
-            viewBinding.title.text = "您已学习完该章节"
-        }
+//        if (endChapter) {
+//            viewBinding.title.text = "您已学习完最后一章节"
+//        } else {
+//            viewBinding.title.text = "您已学习完该章节"
+//        }
 
 
         if (assessStatus) {
         if (assessStatus) {
             // 需要课后考核
             // 需要课后考核

+ 169 - 31
app/src/main/java/com/dlc/exam/ui/learn/LearnDetailActivity.kt

@@ -2,14 +2,26 @@ package com.dlc.exam.ui.learn
 
 
 import android.annotation.SuppressLint
 import android.annotation.SuppressLint
 import android.content.Intent
 import android.content.Intent
-import android.content.pm.ActivityInfo
-import android.graphics.PixelFormat
-import android.net.Uri
-import android.os.*
-import android.util.Base64
+import android.graphics.Bitmap
+import android.os.Build
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.os.Message
+import android.util.Log
 import android.view.LayoutInflater
 import android.view.LayoutInflater
 import android.view.View
 import android.view.View
-import cn.jzvd.Jzvd
+import android.view.ViewGroup
+import android.webkit.ConsoleMessage
+import android.webkit.WebChromeClient
+import android.webkit.WebResourceError
+import android.webkit.WebResourceRequest
+import android.webkit.WebSettings
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import android.widget.LinearLayout
+import androidx.annotation.RequiresApi
+import com.blankj.utilcode.util.LogUtils
 import com.bumptech.glide.Glide
 import com.bumptech.glide.Glide
 import com.dlc.exam.R
 import com.dlc.exam.R
 import com.dlc.exam.common.CommonUtils
 import com.dlc.exam.common.CommonUtils
@@ -20,13 +32,9 @@ import com.google.android.exoplayer2.ExoPlayer
 import com.google.android.exoplayer2.MediaItem
 import com.google.android.exoplayer2.MediaItem
 import com.rc.core.log.RcLog
 import com.rc.core.log.RcLog
 import com.rc.core.util.EscapeUnescape
 import com.rc.core.util.EscapeUnescape
-import com.rc.core.util.VideoFullScreenWebChromeClient
-import com.rc.core.util.WebViewHelper
 import com.rc.httpcore.HttpConfig
 import com.rc.httpcore.HttpConfig
 import com.rc.httpcore.client.ApiRepository
 import com.rc.httpcore.client.ApiRepository
 import com.rc.httpcore.vo.request.ExamLearnReq
 import com.rc.httpcore.vo.request.ExamLearnReq
-import com.tencent.smtt.sdk.TbsVideo
-import java.net.URL
 
 
 
 
 /**
 /**
@@ -47,6 +55,8 @@ class LearnDetailActivity : BaseCountDownActivity<ActivityLearnDetailBinding>()
     private var mVideoDraggable = false // 视频是否可以拖拽
     private var mVideoDraggable = false // 视频是否可以拖拽
     private var mAssessStatus = false // 是否需要课后考核
     private var mAssessStatus = false // 是否需要课后考核
     private var exoPlayer: ExoPlayer? = null
     private var exoPlayer: ExoPlayer? = null
+    private var webView: WebView? = null
+    private val indexUrl = "file:///android_asset/web/index.html"
 
 
     companion object {
     companion object {
         const val WHAT_LEARN_COUNT_DOWN = 1
         const val WHAT_LEARN_COUNT_DOWN = 1
@@ -72,9 +82,6 @@ class LearnDetailActivity : BaseCountDownActivity<ActivityLearnDetailBinding>()
         viewBinding.styledPlayerView.player = exoPlayer
         viewBinding.styledPlayerView.player = exoPlayer
         viewBinding.styledPlayerView.useController = false
         viewBinding.styledPlayerView.useController = false
 
 
-        Jzvd.FULLSCREEN_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
-        Jzvd.NORMAL_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
-
         viewBinding.back.setOnClickListener { onBackPressed() }
         viewBinding.back.setOnClickListener { onBackPressed() }
 
 
         viewBinding.learnCompleted.visibility = if (mRelearn) View.GONE else View.VISIBLE
         viewBinding.learnCompleted.visibility = if (mRelearn) View.GONE else View.VISIBLE
@@ -86,9 +93,114 @@ class LearnDetailActivity : BaseCountDownActivity<ActivityLearnDetailBinding>()
             callFinishLearnApi()
             callFinishLearnApi()
         }
         }
 
 
-        val webViewHelper = WebViewHelper(viewBinding.webView, viewBinding.progressbar)
-        webViewHelper.initWebView(webChromeClientProxy = VideoFullScreenWebChromeClient(viewBinding.videoFullScreen))
-        showChapterInfo()
+        initWebView()
+        //TODO 等待webview初始化完毕后调用
+//        showChapterInfo()
+    }
+
+    private fun initWebView() {
+        val params = LinearLayout.LayoutParams(
+            ViewGroup.LayoutParams.MATCH_PARENT,
+            ViewGroup.LayoutParams.MATCH_PARENT
+        )
+        webView = WebView(applicationContext)
+        webView?.layoutParams = params
+        viewBinding.mainLL.addView(webView)
+        WebView.setWebContentsDebuggingEnabled(true)
+        val webSettings: WebSettings? = webView?.getSettings()
+        webSettings?.javaScriptCanOpenWindowsAutomatically = true
+        webSettings?.setSupportZoom(true)
+        webSettings?.loadWithOverviewMode = true
+        webSettings?.useWideViewPort = true
+        webSettings?.domStorageEnabled = true //DOM Storage
+        webSettings?.allowFileAccessFromFileURLs = true
+        webSettings?.allowFileAccess = true
+        webSettings?.allowContentAccess = true
+        webSettings?.allowUniversalAccessFromFileURLs = true
+        webSettings?.builtInZoomControls = true
+        webSettings?.defaultTextEncodingName = "utf-8"
+        webSettings?.javaScriptEnabled = true //设置webview支持javascript脚本
+        webSettings?.mixedContentMode = WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE
+        webView!!.webChromeClient = object : WebChromeClient() {
+            override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean {
+                if (ConsoleMessage.MessageLevel.ERROR == consoleMessage.messageLevel()) {
+                    LogUtils.e(
+                        "Jayce",
+                        "${consoleMessage.message()}+\n+${consoleMessage.lineNumber()}+\n+${consoleMessage.sourceId()}"
+                    )
+                    // pptxjs.js 该库异常会奔溃
+                    if (consoleMessage.sourceId().contains("pptxjs.js")) {
+                        showToast("该ppt不可用")
+                        this@LearnDetailActivity.finish()
+                    }
+                } else {
+                    LogUtils.d(
+                        "Jayce",
+                        "${consoleMessage.message()}+\n+${consoleMessage.lineNumber()}+\n+${consoleMessage.sourceId()}"
+                    )
+                }
+                return true
+            }
+
+            override fun onProgressChanged(view: WebView, newProgress: Int) {
+                super.onProgressChanged(view, newProgress)
+                Log.d("Jayce", "p:$newProgress")
+            }
+
+            override fun onCloseWindow(window: WebView) {
+                super.onCloseWindow(window)
+                val js = "javascript:objPreviewerDestroy()"
+                webView!!.evaluateJavascript(
+                    js
+                ) { value -> }
+            }
+        }
+        webView!!.webViewClient = object : WebViewClient() {
+            /**
+             * 页面开始加载
+             * @param view The WebView that is initiating the callback.
+             * @param url The url to be loaded.
+             * @param favicon The favicon for this page if it already exists in the
+             * database.
+             */
+            override fun onPageStarted(view: WebView, url: String, favicon: Bitmap) {
+                super.onPageStarted(view, url, favicon)
+            }
+
+            /**
+             * 页面加载完成
+             * @param view The WebView that is initiating the callback.
+             * @param url The url of the page.
+             */
+            override fun onPageFinished(view: WebView, url: String) {
+                super.onPageFinished(view, url)
+                // 等页面初始化完成后再去请求接口展示详情
+                runOnUiThread {
+                    showChapterInfo()
+                }
+            }
+
+            /**
+             * 页面加载错误
+             * @param view The WebView that is initiating the callback.
+             * @param request The originating request.
+             * @param error Information about the error occurred.
+             */
+            @RequiresApi(Build.VERSION_CODES.M)
+            override fun onReceivedError(
+                view: WebView,
+                request: WebResourceRequest,
+                error: WebResourceError
+            ) {
+                super.onReceivedError(view, request, error)
+                Log.d(
+                    "Jayce",
+                    "${error.description}"
+                )
+            }
+        }
+        webView!!.requestFocus()
+        webView!!.loadUrl(indexUrl)
     }
     }
 
 
     private fun callFinishLearnApi() {
     private fun callFinishLearnApi() {
@@ -128,6 +240,7 @@ class LearnDetailActivity : BaseCountDownActivity<ActivityLearnDetailBinding>()
 
 
     @SuppressLint("SetTextI18n")
     @SuppressLint("SetTextI18n")
     private fun showChapterInfo() {
     private fun showChapterInfo() {
+        Log.d("Jayce", "showChapterInfo")
         if (mCurrentPosition >= mNextChapterList!!.size) return
         if (mCurrentPosition >= mNextChapterList!!.size) return
 
 
         mCurrentChapter = mNextChapterList!![mCurrentPosition]
         mCurrentChapter = mNextChapterList!![mCurrentPosition]
@@ -154,29 +267,55 @@ class LearnDetailActivity : BaseCountDownActivity<ActivityLearnDetailBinding>()
             "1" -> {
             "1" -> {
 
 
                 // 文档
                 // 文档
-                viewBinding.webView.visibility = View.VISIBLE
+                webView?.visibility = View.VISIBLE
                 viewBinding.progressbar.visibility = View.VISIBLE
                 viewBinding.progressbar.visibility = View.VISIBLE
                 viewBinding.unknownFile.visibility = View.INVISIBLE
                 viewBinding.unknownFile.visibility = View.INVISIBLE
                 viewBinding.imageContent.visibility = View.INVISIBLE
                 viewBinding.imageContent.visibility = View.INVISIBLE
                 viewBinding.styledPlayerView.visibility = View.INVISIBLE
                 viewBinding.styledPlayerView.visibility = View.INVISIBLE
-                var s = if (mCurrentChapter.chapterData.startsWith("http")) {
+                var url = if (mCurrentChapter.chapterData.startsWith("http")) {
                     mCurrentChapter.chapterData
                     mCurrentChapter.chapterData
                 } else {
                 } else {
                     HttpConfig.API_BASE_URL + mCurrentChapter.chapterData
                     HttpConfig.API_BASE_URL + mCurrentChapter.chapterData
                 }
                 }
-                RcLog.info("fileBrowsers_s:${s}")
-                val infoData =
-//                    Base64.encodeToString(mCurrentChapter.chapterData.toByteArray(), Base64.DEFAULT)
-                    Base64.encodeToString(s.toByteArray(), Base64.DEFAULT)
-                val baseurl = "${HttpConfig.FILE_BROWSER_BASE_URL}onlinePreview?url=$infoData"
-                RcLog.info("fileBrowser:${baseurl}")
-                viewBinding.webView.loadUrl(baseurl)
+//                RcLog.info("fileBrowsers_s:${s}")
+//                val infoData =
+////                    Base64.encodeToString(mCurrentChapter.chapterData.toByteArray(), Base64.DEFAULT)
+//                    Base64.encodeToString(s.toByteArray(), Base64.DEFAULT)
+//                val baseurl = "${HttpConfig.FILE_BROWSER_BASE_URL}onlinePreview?url=$infoData"
+//                RcLog.info("fileBrowser:${baseurl}")
+                var function = ""
+                var loadUrl = ""
+                // ppt
+                if (url.endsWith(".ppt") || url.endsWith(".pptx")) {
+                    function = "openPPT"
+                    loadUrl = "http://192.168.1.43:81/666/ppt.pptx"
+                }
+                // excel
+                else if (url.endsWith(".xlsx") || url.endsWith(".xls")) {
+                    function = "openEXCEL"
+                    loadUrl = "http://192.168.1.43:81/666/excel.xlsx"
+                }
+                // word
+                else if (url.endsWith(".docx") || url.endsWith(".doc")) {
+                    function = "openWORD"
+                    loadUrl = "http://192.168.1.43:81/666/word.docx"
+                } else if (url.endsWith(".pdf")) {
+                    function = "openPDF"
+                    loadUrl = "http://192.168.1.43:81/666/pdf.pdf"
+                } else {
+                    showToast("不支持的文件")
+                    this.finish()
+                    return
+                }
+                val js = "javascript:$function(\"$loadUrl\")"
+                webView!!.evaluateJavascript(js) { value -> }
+//                webView?.loadUrl(url)
             }
             }
 
 
             "2" -> {
             "2" -> {
 
 
                 // 视频   VISIBLE
                 // 视频   VISIBLE
-                viewBinding.webView.visibility = View.GONE
+                webView?.visibility = View.GONE
                 viewBinding.progressbar.visibility = View.GONE
                 viewBinding.progressbar.visibility = View.GONE
                 viewBinding.unknownFile.visibility = View.GONE
                 viewBinding.unknownFile.visibility = View.GONE
                 viewBinding.imageContent.visibility = View.GONE
                 viewBinding.imageContent.visibility = View.GONE
@@ -216,7 +355,7 @@ class LearnDetailActivity : BaseCountDownActivity<ActivityLearnDetailBinding>()
 
 
             "3" -> {
             "3" -> {
                 // 图片
                 // 图片
-                viewBinding.webView.visibility = View.INVISIBLE
+                webView?.visibility = View.INVISIBLE
                 viewBinding.progressbar.visibility = View.INVISIBLE
                 viewBinding.progressbar.visibility = View.INVISIBLE
                 viewBinding.unknownFile.visibility = View.INVISIBLE
                 viewBinding.unknownFile.visibility = View.INVISIBLE
                 viewBinding.imageContent.visibility = View.VISIBLE
                 viewBinding.imageContent.visibility = View.VISIBLE
@@ -235,12 +374,12 @@ class LearnDetailActivity : BaseCountDownActivity<ActivityLearnDetailBinding>()
 
 
             "5" -> {
             "5" -> {
                 // 富文本
                 // 富文本
-                viewBinding.webView.visibility = View.VISIBLE
+                webView?.visibility = View.VISIBLE
                 viewBinding.progressbar.visibility = View.VISIBLE
                 viewBinding.progressbar.visibility = View.VISIBLE
                 viewBinding.unknownFile.visibility = View.INVISIBLE
                 viewBinding.unknownFile.visibility = View.INVISIBLE
                 viewBinding.imageContent.visibility = View.INVISIBLE
                 viewBinding.imageContent.visibility = View.INVISIBLE
                 viewBinding.styledPlayerView.visibility = View.INVISIBLE
                 viewBinding.styledPlayerView.visibility = View.INVISIBLE
-                viewBinding.webView.loadDataWithBaseURL(
+                webView?.loadDataWithBaseURL(
                     null,
                     null,
                     EscapeUnescape.unescape(mCurrentChapter.chapterData),
                     EscapeUnescape.unescape(mCurrentChapter.chapterData),
                     "text/html",
                     "text/html",
@@ -250,7 +389,7 @@ class LearnDetailActivity : BaseCountDownActivity<ActivityLearnDetailBinding>()
             }
             }
 
 
             else -> {
             else -> {
-                viewBinding.webView.visibility = View.INVISIBLE
+                webView?.visibility = View.INVISIBLE
                 viewBinding.progressbar.visibility = View.INVISIBLE
                 viewBinding.progressbar.visibility = View.INVISIBLE
                 viewBinding.unknownFile.visibility = View.VISIBLE
                 viewBinding.unknownFile.visibility = View.VISIBLE
                 viewBinding.imageContent.visibility = View.INVISIBLE
                 viewBinding.imageContent.visibility = View.INVISIBLE
@@ -322,7 +461,6 @@ class LearnDetailActivity : BaseCountDownActivity<ActivityLearnDetailBinding>()
 
 
     override fun onBackPressed() {
     override fun onBackPressed() {
         RcLog.info("onBackPressed============================")
         RcLog.info("onBackPressed============================")
-        if (Jzvd.backPress()) return
         if (mLearnCompleted) {
         if (mLearnCompleted) {
             setResult(RESULT_OK)
             setResult(RESULT_OK)
         }
         }

+ 232 - 0
app/src/main/java/com/dlc/exam/ui/learn/LearnDetailExoActivity.java

@@ -0,0 +1,232 @@
+package com.dlc.exam.ui.learn;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.blankj.utilcode.util.LogUtils;
+import com.dlc.exam.common.CommonUtils;
+import com.dlc.exam.databinding.ActivityLearnDetailExoBinding;
+import com.dlc.exam.ui.common.BaseCountDownActivity;
+import com.dlc.exam.ui.learn.test.ClassTestActivity;
+import com.google.android.exoplayer2.ExoPlayer;
+import com.google.android.exoplayer2.MediaItem;
+import com.google.android.exoplayer2.PlaybackException;
+import com.google.android.exoplayer2.Player;
+import com.google.gson.Gson;
+import com.rc.httpcore.HttpConfig;
+import com.rc.httpcore.client.ApiRepository;
+import com.rc.httpcore.vo.request.ExamLearnReq;
+import com.rc.httpcore.vo.response.LearnBonusBean;
+
+import io.reactivex.disposables.Disposable;
+import io.reactivex.functions.Consumer;
+import kotlin.Unit;
+import kotlin.jvm.functions.Function0;
+
+public class LearnDetailExoActivity extends BaseCountDownActivity<ActivityLearnDetailExoBinding> implements View.OnClickListener {
+    private ActivityLearnDetailExoBinding binding;
+    private ExoPlayer exoPlayer;
+    private long learnTimeSecond = 0L;
+    private LearnChapterBean learnChapterBean;
+    private boolean learnCompleted = false;// 是否已完成学习
+
+    @NonNull
+    @Override
+    protected ActivityLearnDetailExoBinding createViewBinding() {
+        return ActivityLearnDetailExoBinding.inflate(LayoutInflater.from(this));
+    }
+
+    @Override
+    protected void initViews(@Nullable Bundle savedInstanceState) {
+        super.initViews(savedInstanceState);
+        binding = getViewBinding();
+        Intent getIntent = getIntent();
+        if (null != getIntent && getIntent.hasExtra("Chapter")) {
+            learnChapterBean = getIntent.getParcelableExtra("Chapter");
+            boolean relearn = getIntent.getBooleanExtra("relearn", false);
+            if (null == learnChapterBean) {
+                finish();
+                return;
+            }
+            binding.back.setOnClickListener(this);
+            binding.titleText.setText(learnChapterBean.title);
+            // 是否完成学习
+            binding.learnCompleted.setVisibility(relearn ? View.GONE : View.VISIBLE);
+            binding.learnCompleted.setOnClickListener(this);
+            // 直接播放
+            initExo();
+        } else {
+            finish();
+        }
+    }
+
+    private Handler cdHandler = new Handler(Looper.getMainLooper()) {
+        @Override
+        public void handleMessage(@NonNull Message msg) {
+            super.handleMessage(msg);
+            learnTimeSecond++;
+            binding.learnDuration.setText("已学习时长:" + CommonUtils.INSTANCE.formatLearnTime(learnTimeSecond));
+            sendEmptyMessageDelayed(1, 1000);
+            if (learnTimeSecond >= learnChapterBean.duration) {
+                binding.learnCompleted.setEnabled(true);
+            }
+        }
+    };
+
+    /**
+     * 播放视频
+     */
+    private void initExo() {
+        String url = learnChapterBean.chapterData;
+        if (!url.startsWith("http")) {
+            url = HttpConfig.Companion.getAPI_BASE_URL() + url;
+        }
+        LogUtils.d("Jayce", url);
+//        url = "https://media.wxzxzj.com/the_garden_of_words_trailer_english__1080p.m3u8";
+        exoPlayer = new ExoPlayer.Builder(this).build();
+        exoPlayer.addListener(new Player.Listener() {
+            /**
+             * 播放状态改变
+             * @param playbackState The new playback {@link Player.State state}.
+             */
+            @Override
+            public void onPlaybackStateChanged(int playbackState) {
+                Player.Listener.super.onPlaybackStateChanged(playbackState);
+                //  播放
+                if (playbackState == Player.STATE_READY && exoPlayer.getPlayWhenReady()) {
+                    // 开始学习
+                    startLearn();
+                }
+            }
+
+            /**
+             * 播放出错
+             * @param error The error.
+             */
+            @Override
+            public void onPlayerError(PlaybackException error) {
+                Player.Listener.super.onPlayerError(error);
+                binding.errTV.setText("播放异常:" + error.errorCode + "," + error.getMessage());
+                Log.e("Jayce", error.errorCode + "," + error.getMessage());
+            }
+        });
+        MediaItem mediaItem = MediaItem.fromUri(url);
+        exoPlayer.setMediaItem(mediaItem);
+        binding.styledPlayerView.setUseController(false);
+        binding.styledPlayerView.setPlayer(exoPlayer);
+        exoPlayer.prepare();
+        exoPlayer.play();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        if (exoPlayer != null) {
+            exoPlayer.pause();
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        if (exoPlayer != null) {
+            exoPlayer.play();
+        }
+    }
+
+    @Override
+    protected void onDestroy() {
+        cdHandler.removeMessages(1);
+        cdHandler.removeCallbacksAndMessages(null);
+        cdHandler = null;
+        super.onDestroy();
+        if (exoPlayer != null) {
+            exoPlayer.release();
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == binding.back.getId()) {
+            onBackPressed();
+        }
+        // 完成学习
+        else if (v.getId() == binding.learnCompleted.getId()) {
+            learnTimeSecond = 0L;
+            cdHandler.removeMessages(1);
+            finishLearn();
+        }
+    }
+
+    /**
+     * 完成学习
+     */
+    private void finishLearn() {
+        showLoading("保存中...", false);
+        ExamLearnReq examLearnReq = new ExamLearnReq();
+        examLearnReq.chapterId = learnChapterBean.chapterId;
+        examLearnReq.courseId = learnChapterBean.courseId;
+        Log.d("Jayce", "完成学习:" + new Gson().toJson(examLearnReq));
+        Disposable disposable = ApiRepository.INSTANCE.examLearnFinish(examLearnReq).subscribe(learnBonusBean -> {
+            dismissLoading();
+            Log.d("Jayce", new Gson().toJson(learnBonusBean));
+            learnCompleted = true;
+            new LearnCompletedDialog(LearnDetailExoActivity.this, learnBonusBean, false, learnChapterBean.assessStatus, () -> {
+                binding.learnCompleted.setEnabled(false);
+                // 课后考核
+                if (learnChapterBean.assessStatus) {
+                    Intent intent = new Intent(LearnDetailExoActivity.this, ClassTestActivity.class);
+                    intent.putExtra("chapterId", learnChapterBean.chapterId);
+                    startActivity(intent);
+                    setResult(RESULT_OK);
+                }
+                finish();
+                return null;
+            }).show();
+        }, throwable -> {
+            dismissLoading();
+            throwable.printStackTrace();
+            showNetError(throwable);
+        });
+        addDisposable(disposable);
+    }
+
+    /**
+     * 开始学习
+     */
+    private void startLearn() {
+        showLoading("加载中...", false);
+        ExamLearnReq examLearnReq = new ExamLearnReq();
+        examLearnReq.chapterId = learnChapterBean.chapterId;
+        examLearnReq.courseId = learnChapterBean.courseId;
+        Log.d("Jayce", "开始学习:" + new Gson().toJson(examLearnReq));
+        Disposable disposable = ApiRepository.INSTANCE.examLearnStart(examLearnReq).subscribe(aBoolean -> {
+            dismissLoading();
+            learnTimeSecond = 0L;
+            cdHandler.sendEmptyMessage(1);
+
+        }, throwable -> {
+            dismissLoading();
+            throwable.printStackTrace();
+            showNetError(throwable);
+        });
+        addDisposable(disposable);
+    }
+
+    @Override
+    public void onBackPressed() {
+        if (learnCompleted) {
+            setResult(RESULT_OK);
+        }
+        super.onBackPressed();
+    }
+}

+ 368 - 0
app/src/main/java/com/dlc/exam/ui/learn/LearnDetailWebActivity.java

@@ -0,0 +1,368 @@
+package com.dlc.exam.ui.learn;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.webkit.ConsoleMessage;
+import android.webkit.WebChromeClient;
+import android.webkit.WebResourceError;
+import android.webkit.WebResourceRequest;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.LinearLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.blankj.utilcode.util.LogUtils;
+import com.dlc.exam.common.CommonUtils;
+import com.dlc.exam.databinding.ActivityLearnDetailWebBinding;
+import com.dlc.exam.ui.common.BaseCountDownActivity;
+import com.dlc.exam.ui.learn.test.ClassTestActivity;
+import com.dlc.exam.ui.widget.JsInterface;
+import com.dlc.exam.ui.widget.MessageEvent;
+import com.rc.core.util.EscapeUnescape;
+import com.rc.httpcore.HttpConfig;
+import com.rc.httpcore.client.ApiRepository;
+import com.rc.httpcore.vo.request.ExamLearnReq;
+
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
+import io.reactivex.disposables.Disposable;
+
+public class LearnDetailWebActivity extends BaseCountDownActivity<ActivityLearnDetailWebBinding> implements View.OnClickListener {
+
+    private ActivityLearnDetailWebBinding binding;
+    private LearnChapterBean learnChapterBean;
+    private WebView webView;
+    private final String indexUrl = "file:///android_asset/web/index.html";
+    private boolean learnCompleted = false;// 是否已完成学习
+    private long learnTimeSecond = 0L;
+
+    @NonNull
+    @Override
+    protected ActivityLearnDetailWebBinding createViewBinding() {
+        return ActivityLearnDetailWebBinding.inflate(LayoutInflater.from(this));
+    }
+
+    @Override
+    protected void initViews(@Nullable Bundle savedInstanceState) {
+        super.initViews(savedInstanceState);
+
+        binding = getViewBinding();
+        Intent getIntent = getIntent();
+        if (null != getIntent && getIntent.hasExtra("Chapter")) {
+            learnChapterBean = getIntent.getParcelableExtra("Chapter");
+            boolean relearn = getIntent.getBooleanExtra("relearn", false);
+            if (null == learnChapterBean) {
+                finish();
+                return;
+            }
+            binding.back.setOnClickListener(this);
+            binding.titleText.setText(learnChapterBean.title);
+            // 是否完成学习
+            binding.learnCompleted.setVisibility(relearn ? View.GONE : View.VISIBLE);
+            binding.learnCompleted.setOnClickListener(this);
+            // 初始化WebView
+            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+            webView = new WebView(getApplicationContext());
+            webView.setLayoutParams(params);
+            binding.mainLL.addView(webView);
+            WebView.setWebContentsDebuggingEnabled(true);
+            WebSettings webSettings = webView.getSettings();
+            webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
+            webSettings.setSupportZoom(true);
+            webSettings.setLoadWithOverviewMode(true);
+            webSettings.setUseWideViewPort(true);
+            webSettings.setDomStorageEnabled(true);//DOM Storage
+            webSettings.setAllowFileAccessFromFileURLs(true);
+            webSettings.setAllowFileAccess(true);
+            webSettings.setAllowContentAccess(true);
+            webSettings.setAllowUniversalAccessFromFileURLs(true);
+            webSettings.setBuiltInZoomControls(true);
+            webSettings.setDefaultTextEncodingName("utf-8");
+            webSettings.setJavaScriptEnabled(true);//设置webview支持javascript脚本
+            webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
+            webView.addJavascriptInterface(new JsInterface(), "Android");
+            webView.setWebChromeClient(webChromeClient);
+            webView.setWebViewClient(webViewClient);
+            webView.requestFocus();
+            // 富文本
+            if ("5".equals(learnChapterBean.type)) {
+                webView.loadDataWithBaseURL(null, EscapeUnescape.unescape(learnChapterBean.chapterData), "text/html", "utf-8", null);
+            } else {
+                webView.loadUrl(indexUrl);
+            }
+        } else {
+            finish();
+        }
+    }
+
+    private final WebViewClient webViewClient = new WebViewClient() {
+        @Override
+        public void onPageFinished(WebView view, String url) {
+            super.onPageFinished(view, url);
+            LogUtils.d("Jayce", url);
+            if (indexUrl.equals(url)) {
+                String docUrl = learnChapterBean.chapterData;
+                if (!docUrl.startsWith("http")) {
+                    docUrl = HttpConfig.Companion.getAPI_BASE_URL() + docUrl;
+                }
+                switch (learnChapterBean.type) {
+                    // 文档加载
+                    case "1":
+                        String function;
+                        // ppt
+                        if (docUrl.endsWith(".ppt") || docUrl.endsWith(".pptx")) {
+                            function = "openPPT";
+                        }
+                        // excel
+                        else if (docUrl.endsWith(".xlsx") || docUrl.endsWith(".xls")) {
+                            function = "openEXCEL";
+                        }
+                        // word
+                        else if (docUrl.endsWith(".docx") || docUrl.endsWith(".doc")) {
+                            function = "openWORD";
+                        }
+                        // pdf
+                        else if (docUrl.endsWith(".pdf")) {
+                            function = "openPDF";
+                        } else {
+                            binding.errTV.setVisibility(View.VISIBLE);
+                            binding.mainLL.postDelayed(LearnDetailWebActivity.this::finish, 3000);
+                            return;
+                        }
+                        String js = "javascript:" + function + "(\"" + docUrl + "\")";
+                        LogUtils.d("Jayce", js);
+                        webView.evaluateJavascript(js, value -> {
+                            LogUtils.d("Jayce", value);
+                        });
+                        break;
+                    // 图片加载
+                    case "3":
+                        webView.evaluateJavascript("javascript:openIMG(\"" + docUrl + "\")", value -> LogUtils.d("Jayce", value));
+                        break;
+                    default:
+                        binding.errTV.setVisibility(View.VISIBLE);
+                        binding.mainLL.postDelayed(LearnDetailWebActivity.this::finish, 3000);
+                        break;
+                }
+            }
+            // 富文本
+            else if ("about:blank".equals(url)) {
+                startLearn();
+            }
+
+        }
+
+        @Override
+        public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
+            super.onReceivedError(view, request, error);
+            LogUtils.e("Jayce", error.getErrorCode() + "\r\n" + error.getDescription());
+        }
+    };
+
+    private final WebChromeClient webChromeClient = new WebChromeClient() {
+        @Override
+        public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
+            if (ConsoleMessage.MessageLevel.ERROR == consoleMessage.messageLevel()) {
+                LogUtils.e("Jayce", consoleMessage.message() + "\r\n" + consoleMessage.lineNumber() + "\r\n" + consoleMessage.sourceId());
+                if (consoleMessage.sourceId().contains("pptxjs.js")) {
+                    binding.errTV.setVisibility(View.VISIBLE);
+                    binding.mainLL.postDelayed(() -> LearnDetailWebActivity.this.finish(), 3000);
+                }
+            } else {
+                if (consoleMessage.message().startsWith("create by Office PowerPoint app verssion")) {
+                    startLearn();
+                } else {
+                    LogUtils.d("Jayce", consoleMessage.message() + "\r\n" + consoleMessage.lineNumber() + "\r\n" + consoleMessage.sourceId());
+                }
+            }
+            return true;
+        }
+
+        @Override
+        public void onProgressChanged(WebView view, int newProgress) {
+            super.onProgressChanged(view, newProgress);
+            LogUtils.d("Jayce", "加载进度:" + newProgress);
+        }
+
+        @Override
+        public void onCloseWindow(WebView window) {
+            super.onCloseWindow(window);
+            String js = "javascript:objPreviewerDestroy()";
+            webView.evaluateJavascript(js, value -> {
+                LogUtils.d("Jayce", value);
+            });
+        }
+    };
+
+    /**
+     * 完成学习
+     */
+    private void finishLearn() {
+        showLoading("保存中...", false);
+        ExamLearnReq examLearnReq = new ExamLearnReq();
+        examLearnReq.chapterId = learnChapterBean.chapterId;
+        examLearnReq.courseId = learnChapterBean.courseId;
+        Disposable disposable = ApiRepository.INSTANCE.examLearnFinish(examLearnReq).subscribe(learnBonusBean -> {
+            dismissLoading();
+            LogUtils.json("Jayce", learnBonusBean);
+            learnCompleted = true;
+            new LearnCompletedDialog(LearnDetailWebActivity.this, learnBonusBean, false, learnChapterBean.assessStatus, () -> {
+                binding.learnCompleted.setEnabled(false);
+                // 课后考核
+                if (learnChapterBean.assessStatus) {
+                    Intent intent = new Intent(LearnDetailWebActivity.this, ClassTestActivity.class);
+                    intent.putExtra("chapterId", learnChapterBean.chapterId);
+                    startActivity(intent);
+                    setResult(RESULT_OK);
+                }
+                finish();
+                return null;
+            }).show();
+        }, throwable -> {
+            dismissLoading();
+            throwable.printStackTrace();
+            showNetError(throwable);
+        });
+        addDisposable(disposable);
+    }
+
+    private Handler cdHandler = new Handler(Looper.getMainLooper()) {
+        @Override
+        public void handleMessage(@NonNull Message msg) {
+            super.handleMessage(msg);
+            learnTimeSecond++;
+            binding.learnDuration.setText("已学习时长:" + CommonUtils.INSTANCE.formatLearnTime(learnTimeSecond));
+            sendEmptyMessageDelayed(1, 1000);
+            if (learnTimeSecond >= learnChapterBean.duration) {
+                binding.learnCompleted.setEnabled(true);
+            }
+        }
+    };
+
+    /**
+     * 开始学习
+     */
+    private void startLearn() {
+        showLoading("加载中...", false);
+        ExamLearnReq examLearnReq = new ExamLearnReq();
+        examLearnReq.chapterId = learnChapterBean.chapterId;
+        examLearnReq.courseId = learnChapterBean.courseId;
+        Disposable disposable = ApiRepository.INSTANCE.examLearnStart(examLearnReq).subscribe(aBoolean -> {
+            dismissLoading();
+            learnTimeSecond = 0L;
+            cdHandler.sendEmptyMessage(1);
+
+        }, throwable -> {
+            dismissLoading();
+            throwable.printStackTrace();
+            showNetError(throwable);
+        });
+        addDisposable(disposable);
+    }
+
+    @Override
+    protected void onPause() {
+        webView.onPause();
+        super.onPause();
+        EventBus.getDefault().unregister(this);
+    }
+
+    @Override
+    protected void onResume() {
+        webView.onResume();
+        super.onResume();
+        EventBus.getDefault().register(this);
+    }
+
+    @Override
+    protected void onDestroy() {
+        if (webView != null) {
+            webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
+            webView.clearHistory();
+            binding.mainLL.removeAllViewsInLayout();
+            webView.destroy();
+            webView = null;
+        }
+        super.onDestroy();
+    }
+
+    @Override
+    public void onBackPressed() {
+        if (learnCompleted) {
+            setResult(RESULT_OK);
+        }
+        super.onBackPressed();
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == binding.back.getId()) {
+            onBackPressed();
+        }
+        // 完成学习
+        else if (v.getId() == binding.learnCompleted.getId()) {
+            learnTimeSecond = 0L;
+            cdHandler.removeMessages(1);
+            finishLearn();
+        }
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    public void onEventMsg(MessageEvent messageEvent) {
+        if (null != messageEvent) {
+            if (!messageEvent.isResult()) {
+                LogUtils.e("Jayce", messageEvent.getData());
+            }
+            switch (messageEvent.getTag()) {
+                // 大图
+                case JsInterface.JsEvent.Pic.PIC:
+                    if (messageEvent.isResult()) {
+                        startLearn();
+                    } else {
+                        binding.errTV.setVisibility(View.VISIBLE);
+                        binding.mainLL.postDelayed(LearnDetailWebActivity.this::finish, 3000);
+                    }
+                    break;
+                // word
+                case JsInterface.JsEvent.Office.DOC:
+                    if (messageEvent.isResult()) {
+                        startLearn();
+                    } else {
+                        binding.errTV.setVisibility(View.VISIBLE);
+                        binding.mainLL.postDelayed(LearnDetailWebActivity.this::finish, 3000);
+                    }
+                    break;
+                // excel
+                case JsInterface.JsEvent.Office.EXCEL:
+                    if (messageEvent.isResult()) {
+                        startLearn();
+                    } else {
+                        binding.errTV.setVisibility(View.VISIBLE);
+                        binding.mainLL.postDelayed(LearnDetailWebActivity.this::finish, 3000);
+                    }
+                    break;
+                // pdf
+                case JsInterface.JsEvent.Office.PDF:
+                    if (messageEvent.isResult()) {
+                        startLearn();
+                    } else {
+                        binding.errTV.setVisibility(View.VISIBLE);
+                        binding.mainLL.postDelayed(LearnDetailWebActivity.this::finish, 3000);
+                    }
+                    break;
+            }
+        }
+    }
+
+}

+ 2 - 2
app/src/main/java/com/dlc/exam/ui/learn/test/ClassTestRecordActivity.kt

@@ -109,7 +109,7 @@ class ClassTestRecordActivity : BaseCountDownActivity<ActivityClassTestRecordBin
             val topicData = generateTopicInfo(it.radioList, it.multiList, it.judgeList)
             val topicData = generateTopicInfo(it.radioList, it.multiList, it.judgeList)
             mTopicAdapter.setNewInstance(topicData)
             mTopicAdapter.setNewInstance(topicData)
             if (topicData.isNullOrEmpty()) {
             if (topicData.isNullOrEmpty()) {
-                mTopicAdapter.setEmptyView(R.layout.view_list_empty)
+                mTopicAdapter.setEmptyView(com.rc.core.R.layout.view_list_empty)
             }
             }
         }
         }
     }
     }
@@ -248,7 +248,7 @@ private class TopicAdapter : BaseDelegateMultiAdapter<TopicInfo, BaseViewHolder>
         val optionAdapter = ReviewTopicOptionAdapter(item?.elPaperQuAnswerList, false)
         val optionAdapter = ReviewTopicOptionAdapter(item?.elPaperQuAnswerList, false)
         recyclerView.layoutManager = LinearLayoutManager(context)
         recyclerView.layoutManager = LinearLayoutManager(context)
         recyclerView.adapter = optionAdapter
         recyclerView.adapter = optionAdapter
-        optionAdapter.setEmptyView(R.layout.view_list_empty)
+        optionAdapter.setEmptyView(com.rc.core.R.layout.view_list_empty)
 
 
         // 答案
         // 答案
         val isRight = "1" == item?.isRight ?: false
         val isRight = "1" == item?.isRight ?: false

+ 3 - 3
app/src/main/java/com/dlc/exam/ui/me/PersonalCenterActivity.kt

@@ -191,7 +191,7 @@ class PersonalCenterActivity : BaseCountDownActivity<ActivityPersonalCenterBindi
 
 
         if (ListPageView.FIRST_PAGE == mCurrentPage) {
         if (ListPageView.FIRST_PAGE == mCurrentPage) {
             if (data.isNullOrEmpty()) {
             if (data.isNullOrEmpty()) {
-                mBreachContentAdapter.setEmptyView(R.layout.view_list_empty)
+                mBreachContentAdapter.setEmptyView(com.rc.core.R.layout.view_list_empty)
             }
             }
             mBreachContentAdapter.setNewInstance(data?.toMutableList())
             mBreachContentAdapter.setNewInstance(data?.toMutableList())
             mBreachContentAdapter.loadMoreModule.loadMoreComplete()
             mBreachContentAdapter.loadMoreModule.loadMoreComplete()
@@ -215,7 +215,7 @@ class PersonalCenterActivity : BaseCountDownActivity<ActivityPersonalCenterBindi
         if (isDestroyed) return
         if (isDestroyed) return
 
 
         if (ListPageView.FIRST_PAGE == mCurrentPage) {
         if (ListPageView.FIRST_PAGE == mCurrentPage) {
-            mBreachContentAdapter.setEmptyView(R.layout.view_list_empty)
+            mBreachContentAdapter.setEmptyView(com.rc.core.R.layout.view_list_empty)
         } else {
         } else {
             mCurrentPage =
             mCurrentPage =
                 if (mCurrentPage-- < ListPageView.FIRST_PAGE) ListPageView.FIRST_PAGE else mCurrentPage
                 if (mCurrentPage-- < ListPageView.FIRST_PAGE) ListPageView.FIRST_PAGE else mCurrentPage
@@ -355,7 +355,7 @@ private class BreachContentAdapter :
             recyclerView.addItemDecoration(decor)
             recyclerView.addItemDecoration(decor)
         }
         }
         recyclerView.adapter = handlingAdapter
         recyclerView.adapter = handlingAdapter
-        handlingAdapter.setEmptyView(R.layout.view_list_empty)
+        handlingAdapter.setEmptyView(com.rc.core.R.layout.view_list_empty)
     }
     }
 
 
 }
 }

+ 139 - 139
app/src/main/java/com/dlc/exam/ui/widget/ExamJzvdStd.kt

@@ -1,141 +1,141 @@
-package com.dlc.exam.ui.widget
-
-import android.content.Context
-import android.media.AudioManager
-import android.provider.Settings
-import android.provider.Settings.SettingNotFoundException
-import android.util.AttributeSet
-import android.util.Log
-import android.widget.SeekBar
-import cn.jzvd.JZUtils
-import cn.jzvd.JzvdStd
-import kotlin.math.abs
-
-/**
- * info
- *
- * @author ReiChin_
- */
-class ExamJzvdStd @JvmOverloads constructor(
-    context: Context,
-    attrs: AttributeSet? = null,
-) : JzvdStd(context, attrs) {
-
-    /**
-     * 设置是否可以拖拽进度条
-     */
-    fun setDraggable(enabled: Boolean) {
-        val seekBar = findViewById<SeekBar>(cn.jzvd.R.id.bottom_seek_progress)
-        seekBar.isEnabled = enabled
-    }
-
-//    override fun onTouch(v: View?, event: MotionEvent?): Boolean {
-//        if (v?.id == cn.jzvd.R.id.surface_container) {
-//            val seekBar = findViewById<SeekBar>(cn.jzvd.R.id.bottom_seek_progress)
-//            return if (seekBar.isEnabled) super.onTouch(v, event) else false
+//package com.dlc.exam.ui.widget
+//
+//import android.content.Context
+//import android.media.AudioManager
+//import android.provider.Settings
+//import android.provider.Settings.SettingNotFoundException
+//import android.util.AttributeSet
+//import android.util.Log
+//import android.widget.SeekBar
+//import cn.jzvd.JZUtils
+//import cn.jzvd.JzvdStd
+//import kotlin.math.abs
+//
+///**
+// * info
+// *
+// * @author ReiChin_
+// */
+//class ExamJzvdStd @JvmOverloads constructor(
+//    context: Context,
+//    attrs: AttributeSet? = null,
+//) : JzvdStd(context, attrs) {
+//
+//    /**
+//     * 设置是否可以拖拽进度条
+//     */
+//    fun setDraggable(enabled: Boolean) {
+//        val seekBar = findViewById<SeekBar>(cn.jzvd.R.id.bottom_seek_progress)
+//        seekBar.isEnabled = enabled
+//    }
+//
+////    override fun onTouch(v: View?, event: MotionEvent?): Boolean {
+////        if (v?.id == cn.jzvd.R.id.surface_container) {
+////            val seekBar = findViewById<SeekBar>(cn.jzvd.R.id.bottom_seek_progress)
+////            return if (seekBar.isEnabled) super.onTouch(v, event) else false
+////        }
+////        return super.onTouch(v, event)
+////    }
+//
+//    override fun touchActionMove(x: Float, y: Float) {
+//        Log.i(TAG, "onTouch surfaceContainer actionMove [" + this.hashCode() + "] ")
+//        val deltaX = x - mDownX
+//        var deltaY = y - mDownY
+//        val absDeltaX = abs(deltaX)
+//        val absDeltaY = abs(deltaY)
+//        if (screen == SCREEN_FULLSCREEN) {
+//            //拖动的是NavigationBar和状态栏
+//            if (mDownX > JZUtils.getScreenWidth(context) || mDownY < JZUtils.getStatusBarHeight(
+//                    context
+//                )
+//            ) {
+//                return
+//            }
+//            if (!mChangePosition && !mChangeVolume && !mChangeBrightness) {
+//                if (absDeltaX > THRESHOLD || absDeltaY > THRESHOLD) {
+//                    cancelProgressTimer()
+//                    if (absDeltaX >= THRESHOLD) {
+//                        // 全屏模式下的CURRENT_STATE_ERROR状态下,不响应进度拖动事件.
+//                        // 否则会因为mediaplayer的状态非法导致App Crash
+//                        val seekBar = findViewById<SeekBar>(cn.jzvd.R.id.bottom_seek_progress)
+//                        if (state != STATE_ERROR && seekBar.isEnabled) {
+//                            mChangePosition = true
+//                            mGestureDownPosition = currentPositionWhenPlaying
+//                        }
+//                    } else {
+//                        //如果y轴滑动距离超过设置的处理范围,那么进行滑动事件处理
+//                        if (mDownX < mScreenHeight * 0.5f) { //左侧改变亮度
+//                            mChangeBrightness = true
+//                            val lp = JZUtils.getWindow(context).attributes
+//                            if (lp.screenBrightness < 0) {
+//                                try {
+//                                    mGestureDownBrightness = Settings.System.getInt(
+//                                        context.contentResolver, Settings.System.SCREEN_BRIGHTNESS
+//                                    ).toFloat()
+//                                    Log.i(
+//                                        TAG,
+//                                        "current system brightness: $mGestureDownBrightness"
+//                                    )
+//                                } catch (e: SettingNotFoundException) {
+//                                    e.printStackTrace()
+//                                }
+//                            } else {
+//                                mGestureDownBrightness = lp.screenBrightness * 255
+//                                Log.i(
+//                                    TAG,
+//                                    "current activity brightness: $mGestureDownBrightness"
+//                                )
+//                            }
+//                        } else { //右侧改变声音
+//                            mChangeVolume = true
+//                            mGestureDownVolume =
+//                                mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
+//                        }
+//                    }
+//                }
+//            }
+//        }
+//        if (mChangePosition) {
+//            val totalTimeDuration = duration
+//            if (PROGRESS_DRAG_RATE <= 0) {
+//                Log.d(TAG, "error PROGRESS_DRAG_RATE value")
+//                PROGRESS_DRAG_RATE = 1f
+//            }
+//            mSeekTimePosition =
+//                (mGestureDownPosition + deltaX * totalTimeDuration / (mScreenWidth * PROGRESS_DRAG_RATE)).toLong()
+//            if (mSeekTimePosition > totalTimeDuration) mSeekTimePosition = totalTimeDuration
+//            val seekTime = JZUtils.stringForTime(mSeekTimePosition)
+//            val totalTime = JZUtils.stringForTime(totalTimeDuration)
+//            showProgressDialog(deltaX, seekTime, mSeekTimePosition, totalTime, totalTimeDuration)
+//        }
+//        if (mChangeVolume) {
+//            deltaY = -deltaY
+//            val max = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
+//            val deltaV = (max * deltaY * 3 / mScreenHeight).toInt()
+//            mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, mGestureDownVolume + deltaV, 0)
+//            //dialog中显示百分比
+//            val volumePercent =
+//                (mGestureDownVolume * 100 / max + deltaY * 3 * 100 / mScreenHeight).toInt()
+//            showVolumeDialog(-deltaY, volumePercent)
+//        }
+//        if (mChangeBrightness) {
+//            deltaY = -deltaY
+//            val deltaV = (255 * deltaY * 3 / mScreenHeight).toInt()
+//            val params = JZUtils.getWindow(context).attributes
+//            if ((mGestureDownBrightness + deltaV) / 255 >= 1) { //这和声音有区别,必须自己过滤一下负值
+//                params.screenBrightness = 1f
+//            } else if ((mGestureDownBrightness + deltaV) / 255 <= 0) {
+//                params.screenBrightness = 0.01f
+//            } else {
+//                params.screenBrightness = (mGestureDownBrightness + deltaV) / 255
+//            }
+//            JZUtils.getWindow(context).attributes = params
+//            //dialog中显示百分比
+//            val brightnessPercent =
+//                (mGestureDownBrightness * 100 / 255 + deltaY * 3 * 100 / mScreenHeight).toInt()
+//            showBrightnessDialog(brightnessPercent)
+//            //                        mDownY = y;
 //        }
 //        }
-//        return super.onTouch(v, event)
 //    }
 //    }
-
-    override fun touchActionMove(x: Float, y: Float) {
-        Log.i(TAG, "onTouch surfaceContainer actionMove [" + this.hashCode() + "] ")
-        val deltaX = x - mDownX
-        var deltaY = y - mDownY
-        val absDeltaX = abs(deltaX)
-        val absDeltaY = abs(deltaY)
-        if (screen == SCREEN_FULLSCREEN) {
-            //拖动的是NavigationBar和状态栏
-            if (mDownX > JZUtils.getScreenWidth(context) || mDownY < JZUtils.getStatusBarHeight(
-                    context
-                )
-            ) {
-                return
-            }
-            if (!mChangePosition && !mChangeVolume && !mChangeBrightness) {
-                if (absDeltaX > THRESHOLD || absDeltaY > THRESHOLD) {
-                    cancelProgressTimer()
-                    if (absDeltaX >= THRESHOLD) {
-                        // 全屏模式下的CURRENT_STATE_ERROR状态下,不响应进度拖动事件.
-                        // 否则会因为mediaplayer的状态非法导致App Crash
-                        val seekBar = findViewById<SeekBar>(cn.jzvd.R.id.bottom_seek_progress)
-                        if (state != STATE_ERROR && seekBar.isEnabled) {
-                            mChangePosition = true
-                            mGestureDownPosition = currentPositionWhenPlaying
-                        }
-                    } else {
-                        //如果y轴滑动距离超过设置的处理范围,那么进行滑动事件处理
-                        if (mDownX < mScreenHeight * 0.5f) { //左侧改变亮度
-                            mChangeBrightness = true
-                            val lp = JZUtils.getWindow(context).attributes
-                            if (lp.screenBrightness < 0) {
-                                try {
-                                    mGestureDownBrightness = Settings.System.getInt(
-                                        context.contentResolver, Settings.System.SCREEN_BRIGHTNESS
-                                    ).toFloat()
-                                    Log.i(
-                                        TAG,
-                                        "current system brightness: $mGestureDownBrightness"
-                                    )
-                                } catch (e: SettingNotFoundException) {
-                                    e.printStackTrace()
-                                }
-                            } else {
-                                mGestureDownBrightness = lp.screenBrightness * 255
-                                Log.i(
-                                    TAG,
-                                    "current activity brightness: $mGestureDownBrightness"
-                                )
-                            }
-                        } else { //右侧改变声音
-                            mChangeVolume = true
-                            mGestureDownVolume =
-                                mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
-                        }
-                    }
-                }
-            }
-        }
-        if (mChangePosition) {
-            val totalTimeDuration = duration
-            if (PROGRESS_DRAG_RATE <= 0) {
-                Log.d(TAG, "error PROGRESS_DRAG_RATE value")
-                PROGRESS_DRAG_RATE = 1f
-            }
-            mSeekTimePosition =
-                (mGestureDownPosition + deltaX * totalTimeDuration / (mScreenWidth * PROGRESS_DRAG_RATE)).toLong()
-            if (mSeekTimePosition > totalTimeDuration) mSeekTimePosition = totalTimeDuration
-            val seekTime = JZUtils.stringForTime(mSeekTimePosition)
-            val totalTime = JZUtils.stringForTime(totalTimeDuration)
-            showProgressDialog(deltaX, seekTime, mSeekTimePosition, totalTime, totalTimeDuration)
-        }
-        if (mChangeVolume) {
-            deltaY = -deltaY
-            val max = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
-            val deltaV = (max * deltaY * 3 / mScreenHeight).toInt()
-            mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, mGestureDownVolume + deltaV, 0)
-            //dialog中显示百分比
-            val volumePercent =
-                (mGestureDownVolume * 100 / max + deltaY * 3 * 100 / mScreenHeight).toInt()
-            showVolumeDialog(-deltaY, volumePercent)
-        }
-        if (mChangeBrightness) {
-            deltaY = -deltaY
-            val deltaV = (255 * deltaY * 3 / mScreenHeight).toInt()
-            val params = JZUtils.getWindow(context).attributes
-            if ((mGestureDownBrightness + deltaV) / 255 >= 1) { //这和声音有区别,必须自己过滤一下负值
-                params.screenBrightness = 1f
-            } else if ((mGestureDownBrightness + deltaV) / 255 <= 0) {
-                params.screenBrightness = 0.01f
-            } else {
-                params.screenBrightness = (mGestureDownBrightness + deltaV) / 255
-            }
-            JZUtils.getWindow(context).attributes = params
-            //dialog中显示百分比
-            val brightnessPercent =
-                (mGestureDownBrightness * 100 / 255 + deltaY * 3 * 100 / mScreenHeight).toInt()
-            showBrightnessDialog(brightnessPercent)
-            //                        mDownY = y;
-        }
-    }
-
-}
+//
+//}

+ 57 - 0
app/src/main/java/com/dlc/exam/ui/widget/JsInterface.java

@@ -0,0 +1,57 @@
+package com.dlc.exam.ui.widget;
+
+import android.webkit.JavascriptInterface;
+
+import org.greenrobot.eventbus.EventBus;
+
+public class JsInterface {
+
+    public final static class JsEvent {
+        public static class Office {
+            public static final String DOC = "office_doc";
+            public static final String PPT = "office_ppt";
+            public static final String PDF = "office_pdf";
+            public static final String EXCEL = "office_excel";
+        }
+
+        public final static class Pic {
+            public static final String PIC = "big_pic";
+        }
+
+        public final static class Doc {
+            public static final String DOC = "doc_text";
+        }
+    }
+
+
+    @JavascriptInterface
+    public void webCallBack(String tag, String data) {
+        MessageEvent messageEvent = new MessageEvent(tag, data);
+        switch (messageEvent.getTag()) {
+            // 大图
+            case JsInterface.JsEvent.Pic.PIC:
+                messageEvent.setResult("预览完成".equals(data));
+                break;
+            // 富文本
+            case JsInterface.JsEvent.Doc.DOC:
+                break;
+            // word
+            case JsInterface.JsEvent.Office.DOC:
+                messageEvent.setResult("预览完成".equals(data));
+                break;
+            // excel
+            case JsInterface.JsEvent.Office.EXCEL:
+                messageEvent.setResult("预览完成".equals(data));
+                break;
+            // pdf
+            case JsInterface.JsEvent.Office.PDF:
+                messageEvent.setResult("预览完成".equals(data));
+                break;
+            // ppt
+            case JsInterface.JsEvent.Office.PPT:
+                break;
+        }
+        EventBus.getDefault().post(messageEvent);
+    }
+
+}

+ 40 - 0
app/src/main/java/com/dlc/exam/ui/widget/MessageEvent.java

@@ -0,0 +1,40 @@
+package com.dlc.exam.ui.widget;
+
+public class MessageEvent {
+    private String tag;
+    private String data;
+    private boolean result = true;
+
+    private MessageEvent() {
+
+    }
+
+    public MessageEvent(String tag, String data) {
+        setTag(tag);
+        setData(data);
+    }
+
+    public String getTag() {
+        return tag;
+    }
+
+    public void setTag(String tag) {
+        this.tag = tag;
+    }
+
+    public String getData() {
+        return data;
+    }
+
+    public void setData(String data) {
+        this.data = data;
+    }
+
+    public boolean isResult() {
+        return result;
+    }
+
+    public void setResult(boolean result) {
+        this.result = result;
+    }
+}

+ 12 - 8
app/src/main/res/layout/activity_learn_detail.xml

@@ -110,16 +110,20 @@
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toBottomOf="@id/titleBar">
         app:layout_constraintTop_toBottomOf="@id/titleBar">
 
 
-        <com.tencent.smtt.sdk.WebView
-            android:id="@+id/webView"
-            android:layout_width="0dp"
-            android:layout_height="0dp"
+        <LinearLayout
+            android:id="@+id/main_LL"
+            android:layout_width="match_parent"
+            android:orientation="vertical"
+            android:layout_height="match_parent"
             android:background="@android:color/transparent"
             android:background="@android:color/transparent"
             android:visibility="invisible"
             android:visibility="invisible"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toTopOf="parent" />
+            app:layout_constraintTop_toTopOf="parent">
+
+
+        </LinearLayout>
 
 
         <ProgressBar
         <ProgressBar
             android:id="@+id/progressbar"
             android:id="@+id/progressbar"
@@ -129,9 +133,9 @@
             android:progress="0"
             android:progress="0"
             android:progressDrawable="@drawable/progressbar"
             android:progressDrawable="@drawable/progressbar"
             android:visibility="invisible"
             android:visibility="invisible"
-            app:layout_constraintEnd_toEndOf="@id/webView"
-            app:layout_constraintStart_toStartOf="@id/webView"
-            app:layout_constraintTop_toTopOf="@id/webView" />
+            app:layout_constraintEnd_toEndOf="@id/main_LL"
+            app:layout_constraintStart_toStartOf="@id/main_LL"
+            app:layout_constraintTop_toTopOf="@id/main_LL" />
 
 
         <TextView
         <TextView
             android:id="@+id/unknownFile"
             android:id="@+id/unknownFile"

+ 120 - 0
app/src/main/res/layout/activity_learn_detail_exo.xml

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/main"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    tools:context=".ui.learn.LearnDetailExoActivity">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/titleBar"
+        android:layout_width="match_parent"
+        android:layout_height="45dp"
+        android:background="#349CFB">
+
+        <TextView
+            android:id="@+id/titleText"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:ellipsize="end"
+            android:maxLines="1"
+            android:textColor="@android:color/white"
+            android:textSize="16sp"
+            android:textStyle="bold"
+            app:layout_constrainedWidth="true"
+            tools:text="文件名称" />
+
+        <TextView
+            android:id="@+id/learnDuration"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:textColor="@android:color/white"
+            android:textSize="14sp"
+            android:textStyle="bold"
+            tools:text="已学习时长:20分20秒" />
+
+        <androidx.constraintlayout.helper.widget.Flow
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="33dp"
+            android:layout_marginEnd="20dp"
+            android:orientation="horizontal"
+            app:constraint_referenced_ids="titleText,learnDuration"
+            app:flow_horizontalGap="30dp"
+            app:flow_maxElementsWrap="2"
+            app:flow_wrapMode="chain"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@id/learnCompleted"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <TextView
+            android:id="@+id/learnCompleted"
+            android:layout_width="115dp"
+            android:layout_height="34dp"
+            android:layout_marginEnd="20dp"
+            android:background="@drawable/bg_btn_learn_completed"
+            android:enabled="false"
+            android:gravity="center"
+            android:text="完成学习"
+            android:textColor="@color/textcolor_learn_completed"
+            android:textSize="14sp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@id/back"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <LinearLayout
+            android:id="@+id/back"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginEnd="20dp"
+            android:gravity="center_vertical"
+            android:orientation="horizontal"
+            android:paddingStart="10dp"
+            android:paddingEnd="10dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintTop_toTopOf="parent">
+
+            <ImageView
+                android:layout_width="24dp"
+                android:layout_height="24dp"
+                android:contentDescription="@null"
+                android:scaleType="centerCrop"
+                android:src="@mipmap/icon_ksxt_fh" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="8dp"
+                android:text="返回"
+                android:textColor="@android:color/white"
+                android:textSize="10sp"
+                tools:ignore="SmallSp" />
+
+        </LinearLayout>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <com.google.android.exoplayer2.ui.StyledPlayerView
+            android:id="@+id/styledPlayerView"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+        <TextView
+            android:id="@+id/err_TV"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerInParent="true"
+            android:textColor="#ff0000"
+            android:textSize="14sp"
+            android:textStyle="bold" />
+    </RelativeLayout>
+
+</LinearLayout>

+ 119 - 0
app/src/main/res/layout/activity_learn_detail_web.xml

@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/main"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    tools:context=".ui.learn.LearnDetailWebActivity">
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/titleBar"
+        android:layout_width="match_parent"
+        android:layout_height="45dp"
+        android:background="#349CFB">
+
+        <TextView
+            android:id="@+id/titleText"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:ellipsize="end"
+            android:maxLines="1"
+            android:textColor="@android:color/white"
+            android:textSize="16sp"
+            android:textStyle="bold"
+            app:layout_constrainedWidth="true"
+            tools:text="文件名称" />
+
+        <TextView
+            android:id="@+id/learnDuration"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:textColor="@android:color/white"
+            android:textSize="14sp"
+            android:textStyle="bold"
+            tools:text="已学习时长:20分20秒" />
+
+        <androidx.constraintlayout.helper.widget.Flow
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="33dp"
+            android:layout_marginEnd="20dp"
+            android:orientation="horizontal"
+            app:constraint_referenced_ids="titleText,learnDuration"
+            app:flow_horizontalGap="30dp"
+            app:flow_maxElementsWrap="2"
+            app:flow_wrapMode="chain"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@id/learnCompleted"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <TextView
+            android:id="@+id/learnCompleted"
+            android:layout_width="115dp"
+            android:layout_height="34dp"
+            android:layout_marginEnd="20dp"
+            android:background="@drawable/bg_btn_learn_completed"
+            android:enabled="false"
+            android:gravity="center"
+            android:text="完成学习"
+            android:textColor="@color/textcolor_learn_completed"
+            android:textSize="14sp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toStartOf="@id/back"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <LinearLayout
+            android:id="@+id/back"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginEnd="20dp"
+            android:gravity="center_vertical"
+            android:orientation="horizontal"
+            android:paddingStart="10dp"
+            android:paddingEnd="10dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintTop_toTopOf="parent">
+
+            <ImageView
+                android:layout_width="24dp"
+                android:layout_height="24dp"
+                android:contentDescription="@null"
+                android:scaleType="centerCrop"
+                android:src="@mipmap/icon_ksxt_fh" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="8dp"
+                android:text="返回"
+                android:textColor="@android:color/white"
+                android:textSize="10sp"
+                tools:ignore="SmallSp" />
+
+        </LinearLayout>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <TextView
+        android:id="@+id/err_TV"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:text="无法加载..."
+        android:textColor="#ff0000"
+        android:textSize="14sp"
+        android:visibility="gone" />
+
+    <LinearLayout
+        android:id="@+id/main_LL"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+    </LinearLayout>
+
+</LinearLayout>

+ 1 - 1
app/src/main/res/layout/dialog_learn_completed.xml

@@ -62,7 +62,7 @@
             android:paddingTop="6dp"
             android:paddingTop="6dp"
             android:paddingEnd="20dp"
             android:paddingEnd="20dp"
             android:paddingBottom="6dp"
             android:paddingBottom="6dp"
-            android:text="学习下一章节"
+            android:text="知道了"
             android:textColor="@android:color/white"
             android:textColor="@android:color/white"
             android:textSize="11sp"
             android:textSize="11sp"
             tools:ignore="SmallSp" />
             tools:ignore="SmallSp" />

+ 4 - 30
build.gradle

@@ -1,32 +1,6 @@
 // Top-level build file where you can add configuration options common to all sub-projects/modules.
 // Top-level build file where you can add configuration options common to all sub-projects/modules.
-buildscript {
-    repositories {
-        google()
-        jcenter()
-    }
-
-    apply from: 'config/config.gradle'
-    dependencies {
-        classpath 'com.android.tools.build:gradle:8.6.0'
-        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${env.kotlin_version}"
-
-        // NOTE: Do not place your application dependencies here; they belong
-        // in the individual module build.gradle files
-    }
-}
-
-allprojects {
-    repositories {
-        google()
-        jcenter()
-        maven { url 'https://jitpack.io' }
-        maven { url "https://maven.mozilla.org/maven2/" }
-    }
-
-    apply plugin: 'idea'
-    buildDir = new File(rootDir, "gradle-build/${path.replaceAll(':', '/')}")
-}
-
-task clean(type: Delete) {
-    delete rootProject.buildDir
+plugins {
+    alias(libs.plugins.android.application) apply false
+    alias(libs.plugins.kotlin.android) apply false
+    alias(libs.plugins.android.library) apply false
 }
 }

+ 1 - 4
config/config.gradle

@@ -20,11 +20,8 @@ ext {
     ]
     ]
 
 
     dep = [
     dep = [
-            kotlinStdlib                 : 'org.jetbrains.kotlin:kotlin-stdlib:${env.kotlin_version}',
-            androidxCoreKtx              : 'androidx.core:core-ktx:1.3.1',
-            androidxAppCompat            : 'androidx.appcompat:appcompat:1.2.0',
             androidxConstraintlayout     : 'androidx.constraintlayout:constraintlayout:2.0.1',
             androidxConstraintlayout     : 'androidx.constraintlayout:constraintlayout:2.0.1',
-            androidMaterial              : 'com.google.android.material:material:1.2.1',
+            androidMaterial              : 'com.google.android.material:material:1.10.1',
             androidxLocalbroadcastmanager: 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0',
             androidxLocalbroadcastmanager: 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0',
             androidxSwipeRefreshLayout   : "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0",
             androidxSwipeRefreshLayout   : "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0",
             androidMultidex              : "com.android.support:multidex:1.0.3",
             androidMultidex              : "com.android.support:multidex:1.0.3",

+ 1 - 1
gradle.properties

@@ -20,5 +20,5 @@ kotlin.code.style=official
 
 
 android.useDeprecatedNdk=true
 android.useDeprecatedNdk=true
 android.defaults.buildfeatures.buildconfig=true
 android.defaults.buildfeatures.buildconfig=true
-android.nonTransitiveRClass=false
+android.nonTransitiveRClass=true
 android.nonFinalResIds=false
 android.nonFinalResIds=false

+ 60 - 0
gradle/libs.versions.toml

@@ -0,0 +1,60 @@
+[versions]
+agp = "8.6.0"
+kotlin = "1.9.0"
+coreKtx = "1.10.1"
+junit = "4.13.2"
+junitVersion = "1.1.5"
+espressoCore = "3.5.1"
+appcompat = "1.6.1"
+material = "1.10.0"
+activity = "1.8.0"
+constraintlayout = "2.1.4"
+localbroadcastmanager = "1.1.0"
+rxpermissions = "0.11"
+swiperefreshlayout = "1.1.0"
+recycler-adapter-helper4 = "3.0.4"
+glide = "4.11.0"
+multidex = "2.0.1"
+mqttv3 = "1.2.0"
+eventbus = "3.2.0"
+bgaZxing = "1.3.8"
+retrofit = "2.9.0"
+okhttp3-logging = "3.14.9"
+gson = "2.8.6"
+rxAndroid = "2.1.1"
+rxjava = "2.2.21"
+
+[libraries]
+androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
+junit = { group = "junit", name = "junit", version.ref = "junit" }
+androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
+androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
+androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
+material = { group = "com.google.android.material", name = "material", version.ref = "material" }
+androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
+androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
+androidx-localbroadcastmanager = { group = "androidx.localbroadcastmanager", name = "localbroadcastmanager", version.ref = "localbroadcastmanager" }
+rxpermissions = { group = "com.github.tbruyelle", name = "rxpermissions", version.ref = "rxpermissions" }
+androidx-swiperefreshlayout = { group = "androidx.swiperefreshlayout", name = "swiperefreshlayout", version.ref = "swiperefreshlayout" }
+recycler-adapter-helper4 = { group = "io.github.cymchad", name = "BaseRecyclerViewAdapterHelper", version.ref = "recycler-adapter-helper4" }
+glide = { group = "com.github.bumptech.glide", name = "glide", version.ref = "glide" }
+androidx-multidex = { group = "androidx.multidex", name = "multidex", version.ref = "multidex" }
+mqttv3 = { group = "org.eclipse.paho", name = "org.eclipse.paho.client.mqttv3", version.ref = "mqttv3" }
+eventbus = { group = "org.greenrobot", name = "eventbus", version.ref = "eventbus" }
+bgaZxing = { group = "com.github.bingoogolapple.BGAQRCode-Android", name = "zxing", version.ref = "bgaZxing" }
+
+
+squareup-retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
+squareup-converter-gson = { group = "com.squareup.retrofit2", name = "converter-gson", version.ref = "retrofit" }
+squareup-converter-scalars = { group = "com.squareup.retrofit2", name = "converter-scalars", version.ref = "retrofit" }
+squareup-rx-java-adapter = { group = "com.squareup.retrofit2", name = "adapter-rxjava2", version.ref = "retrofit" }
+okhttp3-logging = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp3-logging" }
+gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }
+rx-java = { group = "io.reactivex.rxjava2", name = "rxjava", version.ref = "rxjava" }
+rx-android = { group = "io.reactivex.rxjava2", name = "rxandroid", version.ref = "rxAndroid" }
+
+[plugins]
+android-application = { id = "com.android.application", version.ref = "agp" }
+kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
+android-library = { id = "com.android.library", version.ref = "agp" }
+

+ 55 - 0
settings.gradle

@@ -1,3 +1,58 @@
+//buildscript {
+//    repositories {
+//        google()
+//        jcenter()
+//    }
+//
+//    apply from: 'config/config.gradle'
+//    dependencies {
+//        classpath 'com.android.tools.build:gradle:8.6.0'
+//        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${env.kotlin_version}"
+//
+//        // NOTE: Do not place your application dependencies here; they belong
+//        // in the individual module build.gradle files
+//    }
+//}
+//
+//allprojects {
+//    repositories {
+//        google()
+//
+//    }
+//
+//    apply plugin: 'idea'
+//    buildDir = new File(rootDir, "gradle-build/${path.replaceAll(':', '/')}")
+//}
+//
+//task clean(type: Delete) {
+//    delete rootProject.buildDir
+//}
+
+pluginManagement {
+    repositories {
+        maven { url "https://www.jitpack.io" }
+        google {
+            content {
+                includeGroupByRegex("com\\.android.*")
+                includeGroupByRegex("com\\.google.*")
+                includeGroupByRegex("androidx.*")
+            }
+        }
+        mavenCentral()
+        gradlePluginPortal()
+    }
+}
+dependencyResolutionManagement {
+    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+    repositories {
+        maven { url "https://www.jitpack.io" }
+        maven { url "https://maven.mozilla.org/maven2/" }
+        google()
+        mavenCentral()
+        jcenter()
+    }
+}
+
 rootProject.name = "zd_exam"
 rootProject.name = "zd_exam"
 include ':app'
 include ':app'
 include ':HttpCoreLibrary'
 include ':HttpCoreLibrary'