├── .gitignore
├── .idea
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── compiler.xml
├── gradle.xml
├── jarRepositories.xml
├── misc.xml
├── render.experimental.xml
├── runConfigurations.xml
└── vcs.xml
├── README.md
├── apikey.example.properties
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── engineer
│ │ └── kaobei
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── assets
│ │ ├── fonts.json
│ │ ├── open_source.json
│ │ └── themes.json
│ ├── ic_launcher-playstore.png
│ ├── java
│ │ └── engineer
│ │ │ └── kaobei
│ │ │ ├── DepthPageTransformer.kt
│ │ │ ├── KaobeiEngineerService.kt
│ │ │ ├── NestedScrollviewLoadMoreController.kt
│ │ │ ├── OnLoadMoreListener.kt
│ │ │ ├── RecyclerViewAdapterListener.kt
│ │ │ ├── RecyclerViewLoadMoreScroll.kt
│ │ │ ├── activity
│ │ │ ├── ArticleActivity.kt
│ │ │ ├── ArticleActivityV2.kt
│ │ │ ├── CreateArticleActivity.kt
│ │ │ ├── LoginActivity.kt
│ │ │ ├── MainActivity.kt
│ │ │ └── settings
│ │ │ │ ├── OpenSourceAdapter.kt
│ │ │ │ └── SettingsActivity.kt
│ │ │ ├── database
│ │ │ ├── AuthStateManager.kt
│ │ │ ├── FontManager.kt
│ │ │ ├── OpenSourceManager.kt
│ │ │ └── ThemeManager.kt
│ │ │ ├── fragment
│ │ │ ├── ArticleListFragment.kt
│ │ │ ├── CreateArticleFragment.kt
│ │ │ ├── DashBoardFragment.kt
│ │ │ ├── IndexFragment.kt
│ │ │ └── ReviewFragment.kt
│ │ │ ├── model
│ │ │ ├── ReviewArticle
│ │ │ │ ├── Data.kt
│ │ │ │ └── SingleReviewArticle.kt
│ │ │ ├── ReviewArticles
│ │ │ │ ├── Links.kt
│ │ │ │ ├── Meta.kt
│ │ │ │ ├── Pagination.kt
│ │ │ │ ├── ReviewArticle.kt
│ │ │ │ └── ReviewArticles.kt
│ │ │ ├── articleInfo
│ │ │ │ ├── ArticleInfo.kt
│ │ │ │ └── KaobeiArticleInfo.kt
│ │ │ ├── articles
│ │ │ │ ├── Article.kt
│ │ │ │ ├── KaobeiArticleList.kt
│ │ │ │ ├── Links.kt
│ │ │ │ ├── Meta.kt
│ │ │ │ └── Pagination.kt
│ │ │ ├── comments
│ │ │ │ ├── Comment.kt
│ │ │ │ ├── KaobeiComments.kt
│ │ │ │ ├── Links.kt
│ │ │ │ ├── Media.kt
│ │ │ │ ├── Meta.kt
│ │ │ │ └── Pagination.kt
│ │ │ ├── fonts
│ │ │ │ ├── Font.kt
│ │ │ │ └── KaobeiFonts.kt
│ │ │ ├── kaobeluser
│ │ │ │ ├── BeanKaobeiUser.kt
│ │ │ │ └── KaobeiUser.kt
│ │ │ ├── link
│ │ │ │ ├── Data.kt
│ │ │ │ └── KaobeiLink.kt
│ │ │ ├── opensources
│ │ │ │ ├── OpenSource.kt
│ │ │ │ └── OpenSources.kt
│ │ │ ├── themes
│ │ │ │ ├── Additional.kt
│ │ │ │ ├── KaobeiThemes.kt
│ │ │ │ └── Theme.kt
│ │ │ └── userarticles
│ │ │ │ ├── Links.kt
│ │ │ │ ├── Meta.kt
│ │ │ │ ├── Pagination.kt
│ │ │ │ ├── UserArticle.kt
│ │ │ │ └── UserArticles.kt
│ │ │ ├── util
│ │ │ ├── ClipBoardUtil.kt
│ │ │ ├── CustomTabUtil.kt
│ │ │ ├── SnackbarUtil.kt
│ │ │ ├── ViewUtil.kt
│ │ │ └── ext
│ │ │ │ └── ImageViewExt.kt
│ │ │ ├── view
│ │ │ ├── AnimatedGap.kt
│ │ │ ├── KaobeiArticleViewer.kt
│ │ │ └── UserViewer.kt
│ │ │ └── viewmodel
│ │ │ ├── ArticleInfoViewModel.kt
│ │ │ ├── ArticleListViewModel.kt
│ │ │ ├── CommentsViewModel.kt
│ │ │ ├── IndexViewModel.kt
│ │ │ ├── LinkViewModel.kt
│ │ │ ├── ListViewModel.kt
│ │ │ ├── ObjectViewModel.kt
│ │ │ ├── ProfileViewModel.kt
│ │ │ ├── ReviewViewModel.kt
│ │ │ └── UserArticleListViewModel.kt
│ └── res
│ │ ├── anim
│ │ ├── slide_in_right.xml
│ │ └── slide_out_left.xml
│ │ ├── color
│ │ └── bnv_color.xml
│ │ ├── drawable-v24
│ │ ├── ic_launcher_foreground.xml
│ │ └── img_mallet.jpg
│ │ ├── drawable
│ │ ├── bg_sheet.xml
│ │ ├── bottomsheet_line.xml
│ │ ├── cursor.xml
│ │ ├── custom_ripple.xml
│ │ ├── ic_dashboard_white_24dp.xml
│ │ ├── ic_favorite_white_24dp.xml
│ │ ├── ic_home_white_24dp.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── ic_menu_white_24dp.xml
│ │ ├── ic_mode_edit_white_24dp.xml
│ │ ├── ic_people_outline_white_24dp.xml
│ │ ├── ic_person_white_24dp.xml
│ │ ├── ic_reply_white_24dp.xml
│ │ ├── ic_share_white_24dp.xml
│ │ ├── ic_thumb_up_white_24dp.xml
│ │ ├── ic_warning_red_24dp.xml
│ │ ├── img_animated_rainbow.gif
│ │ ├── img_background_star.gif
│ │ ├── img_bat.xml
│ │ ├── img_bird.xml
│ │ ├── img_bull.xml
│ │ ├── img_camel.xml
│ │ ├── img_cat.xml
│ │ ├── img_devotion_bg.png
│ │ ├── img_flag1.jpg
│ │ ├── img_kb.png
│ │ ├── img_mallet.jpg
│ │ ├── img_nopic_192.gif
│ │ ├── img_plurk.png
│ │ ├── img_twitter.jpg
│ │ ├── kohlrabi.png
│ │ ├── test1.png
│ │ ├── test2.png
│ │ └── text_bottom_line.xml
│ │ ├── font
│ │ └── dos.ttf
│ │ ├── layout
│ │ ├── activity_article.xml
│ │ ├── activity_article_v2.xml
│ │ ├── activity_login.xml
│ │ ├── activity_main.xml
│ │ ├── ads_style1.xml
│ │ ├── ads_style2.xml
│ │ ├── bottom_sheet_authorized.xml
│ │ ├── bottom_sheet_edit_content.xml
│ │ ├── bottom_sheet_id_selecter.xml
│ │ ├── bottom_sheet_links.xml
│ │ ├── bottom_sheet_not_authorized.xml
│ │ ├── bottom_sheet_open_source.xml
│ │ ├── bottom_sheet_review_article.xml
│ │ ├── bottom_sheet_select_font.xml
│ │ ├── bottom_sheet_select_theme.xml
│ │ ├── bottom_sheet_share.xml
│ │ ├── bottom_sheet_submit_article.xml
│ │ ├── cardview_header1.xml
│ │ ├── cardview_header2.xml
│ │ ├── cardview_open_source.xml
│ │ ├── cardview_style1.xml
│ │ ├── cardview_style2.xml
│ │ ├── cardview_style3.xml
│ │ ├── cardview_style_comment.xml
│ │ ├── cardview_style_font.xml
│ │ ├── cardview_style_link.xml
│ │ ├── cardview_style_theme.xml
│ │ ├── content_article_activity_v2.xml
│ │ ├── create_article_activity.xml
│ │ ├── fragment_article_list.xml
│ │ ├── fragment_create_article.xml
│ │ ├── fragment_dashboard.xml
│ │ ├── fragment_index.xml
│ │ ├── fragment_review.xml
│ │ ├── progress_loading.xml
│ │ ├── settings_activity.xml
│ │ ├── view_last_one.xml
│ │ ├── view_not_authorized.xml
│ │ ├── widget_kaobei_article_viewer.xml
│ │ └── widget_user_viewer.xml
│ │ ├── menu
│ │ └── navigation.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── navigation
│ │ └── mobile_navigation.xml
│ │ ├── values
│ │ ├── arrays.xml
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ │ └── xml
│ │ └── root_preferences.xml
│ └── test
│ └── java
│ └── engineer
│ └── kaobei
│ └── ExampleUnitTest.kt
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /apikey.properties
4 | /local.properties
5 | /.idea/caches
6 | /.idea/libraries
7 | /.idea/modules.xml
8 | /.idea/workspace.xml
9 | /.idea/navEditor.xml
10 | /.idea/assetWizardSettings.xml
11 | .DS_Store
12 | /build
13 | /captures
14 | .externalNativeBuild
15 | .cxx
16 | /app/release/*
17 | /keystore
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | xmlns:android
17 |
18 | ^$
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | xmlns:.*
28 |
29 | ^$
30 |
31 |
32 | BY_NAME
33 |
34 |
35 |
36 |
37 |
38 |
39 | .*:id
40 |
41 | http://schemas.android.com/apk/res/android
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | .*:name
51 |
52 | http://schemas.android.com/apk/res/android
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | name
62 |
63 | ^$
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | style
73 |
74 | ^$
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | .*
84 |
85 | ^$
86 |
87 |
88 | BY_NAME
89 |
90 |
91 |
92 |
93 |
94 |
95 | .*
96 |
97 | http://schemas.android.com/apk/res/android
98 |
99 |
100 | ANDROID_ATTRIBUTE_ORDER
101 |
102 |
103 |
104 |
105 |
106 |
107 | .*
108 |
109 | .*
110 |
111 |
112 | BY_NAME
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
20 |
21 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | 1.8
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/.idea/render.experimental.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 喜歡純靠北工程師?我們也是。
5 | 這是一份純靠北工程師的 Android APP 專案,請好好愛護它,謝謝。
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | ---
14 | # 預覽
15 |
21 |
22 | ---
23 | # 貢獻
24 | 如果有問題麻煩在 GitHub 當中發 issues 給我們,感謝!
25 |
26 | ## 步驟一
27 | - 🍴 Fork 這個專案,或者不要 Fork 也可以,因為 Fork 發出去,不一定會有 PR 發回來。
28 | - 👯 Clone 這個專案到你的電腦當中,或者你根本不會用,你只會到 [Google Play](https://play.google.com/store/apps/details?id=engineer.kaobei) 按下載也行。
29 |
30 | ## 步驟二
31 | - 弄壞它,並且修好它 🔨🔨🔨
32 |
33 | ## 步驟三
34 | - 🔃 發 PR 回來。
35 |
36 | ---
37 | # 聯絡資訊
38 | - 信箱 `kantai.developer@gmail.com`
39 | - 網站 `https://init.engineer`
40 |
--------------------------------------------------------------------------------
/apikey.example.properties:
--------------------------------------------------------------------------------
1 | # OAuth Client
2 | oath2clientsecret=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3 | oath2clientid=00000
4 |
5 | oath2scheme=YOUR_SCHEME
6 | oath2host=engineer.kaobei
7 | oath2path=YOUR_CALLBACK_PATH
8 |
9 | # Google AdMob
10 | admobID=ca-app-pub-0000000000000000~0000000000
11 | admob1=ca-app-pub-0000000000000000/0000000000
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 |
5 | def apiKeyPropertiesFile = rootProject.file("apikey.properties")
6 | def apiKeyProperties = new Properties()
7 | apiKeyProperties.load(new FileInputStream(apiKeyPropertiesFile))
8 |
9 | android {
10 | compileSdkVersion 29
11 |
12 | // Facebook Audience0
13 | packagingOptions {
14 | exclude 'AndroidManifest.xml'
15 | }
16 |
17 | defaultConfig {
18 | applicationId "engineer.kaobei"
19 | minSdkVersion 21
20 | targetSdkVersion 29
21 | versionCode 112
22 | versionName "1.1.2"
23 |
24 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
25 |
26 | buildConfigField("String", "OATH2CLIENTID", "\"" + apiKeyProperties['oath2clientid'] + "\"")
27 | buildConfigField("String", "OATH2CLIENTSECRET", "\"" + apiKeyProperties['oath2clientsecret'] + "\"")
28 | buildConfigField("String", "OATH2REDIRECTURL", "\"" + apiKeyProperties['oath2scheme'] + "://" + apiKeyProperties['oath2host'] + apiKeyProperties['oath2path'] + "\"")
29 | buildConfigField("String", "ADMOB_1", "\"" + apiKeyProperties['admob1'] + "\"")
30 |
31 | manifestPlaceholders = [
32 | schemeName: apiKeyProperties['oath2scheme'],
33 | hostName : apiKeyProperties['oath2host'],
34 | pathName : apiKeyProperties['oath2path'],
35 | admobID : apiKeyProperties['admobID'],
36 | ]
37 | }
38 |
39 | buildTypes {
40 | release {
41 | minifyEnabled false
42 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
43 | }
44 | debug {
45 |
46 | }
47 | }
48 |
49 | // To inline the bytecode built with JVM target 1.8 into
50 | // bytecode that is being built with JVM target 1.6. (e.g. navArgs)
51 |
52 | compileOptions {
53 | sourceCompatibility JavaVersion.VERSION_1_8
54 | targetCompatibility JavaVersion.VERSION_1_8
55 | }
56 | kotlinOptions {
57 | jvmTarget = "1.8"
58 | }
59 |
60 | }
61 |
62 | dependencies {
63 |
64 | implementation fileTree(dir: 'libs', include: ['*.jar'])
65 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
66 | implementation 'androidx.appcompat:appcompat:1.1.0'
67 | implementation 'androidx.core:core-ktx:1.2.0'
68 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
69 | implementation 'androidx.legacy:legacy-support-v4:1.0.0'
70 | implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
71 | implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
72 | implementation 'androidx.annotation:annotation:1.1.0'
73 | implementation 'androidx.preference:preference:1.1.1'
74 | testImplementation 'junit:junit:4.13'
75 | androidTestImplementation 'androidx.test.ext:junit:1.1.1'
76 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
77 |
78 | // ui
79 | implementation 'com.google.android.material:material:1.2.0-alpha06'
80 | implementation 'androidx.browser:browser:1.2.0'
81 | implementation "androidx.paging:paging-runtime:2.1.2"
82 | implementation 'androidx.navigation:navigation-fragment-ktx:2.2.2'
83 | implementation 'androidx.navigation:navigation-ui-ktx:2.2.2'
84 |
85 | // ads
86 | implementation 'com.google.android.gms:play-services-ads:19.1.0'
87 |
88 | // shimmer
89 | implementation 'com.facebook.shimmer:shimmer:0.5.0'
90 |
91 | // gson
92 | implementation 'com.google.code.gson:gson:2.8.6'
93 |
94 | // glide
95 | implementation 'com.github.bumptech.glide:glide:4.11.0'
96 | annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
97 |
98 | // okHttp
99 | implementation 'com.squareup.okhttp3:okhttp:4.7.1'
100 | implementation 'com.squareup.retrofit2:retrofit:2.8.2'
101 | implementation 'com.squareup.retrofit2:converter-gson:2.8.2'
102 |
103 | // oath2
104 | implementation 'net.openid:appauth:0.7.1'
105 |
106 | // optional - Kotlin Extensions and Coroutines support for Room
107 | implementation "androidx.room:room-ktx:2.2.5"
108 |
109 | implementation "androidx.viewpager2:viewpager2:1.0.0"
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/engineer/kaobei/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei
2 |
3 | import androidx.test.platform.app.InstrumentationRegistry
4 | import androidx.test.ext.junit.runners.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22 | assertEquals("engineer.kaobei", appContext.packageName)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
16 |
20 |
21 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
47 |
48 |
49 |
50 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/app/src/main/assets/fonts.json:
--------------------------------------------------------------------------------
1 | {
2 | "options": [
3 | {
4 | "name": "AURAKA 點陣宋字型",
5 | "font": "Auraka",
6 | "value": "ea98dde8987df3cd8aef75479019b688"
7 | },
8 | {
9 | "name": "國喬點陣字型",
10 | "font": "KC24M",
11 | "value": "813ca6cbbd95d7e08fa2af59bc12072d"
12 | },
13 | {
14 | "name": "ZPIX 點陣字型",
15 | "font": "Zfull",
16 | "value": "1b23b3cd9223930ac694b7f29f38ff21"
17 | },
18 | {
19 | "name": "張海山銳諧體",
20 | "font": "Harmonic",
21 | "value": "68068fcf50e7cae709cb8ed0b7b9b0f3"
22 | },
23 | {
24 | "name": "蒙納繁圓點陣",
25 | "font": "MBitmapRoundHK",
26 | "value": "f762e3a99692b40e5929ab3668606a4a"
27 | },
28 | {
29 | "name": "微軟正黑體",
30 | "font": "Microsoft JhengHei",
31 | "value": "13f5333afe00f8c7e8da7e0b13ec2c94"
32 | },
33 | {
34 | "name": "新細明體",
35 | "font": "Mingliu",
36 | "value": "c0b5dd764ede0ca105be22cf13ebadff"
37 | },
38 | {
39 | "name": "標楷體",
40 | "font": "Kaiu",
41 | "value": "21881fc6a87aca0dd1afc685cb6ee891"
42 | },
43 | {
44 | "name": "極粗明朝體",
45 | "font": "MatissePro EB",
46 | "value": "ozke4ri3gkpy7e9c312u5l0w5vr9jdqq"
47 | },
48 | {
49 | "name": "台北黑體",
50 | "font": "Taipei Sans TC Beta",
51 | "value": "yc45sgsfbss490dqgs2g23a7z24slhoj"
52 | }
53 | ]
54 | }
--------------------------------------------------------------------------------
/app/src/main/assets/open_source.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": [
3 | {
4 | "name": "Shimmer for Android",
5 | "author": "Facebook",
6 | "url": "https://github.com/facebook/shimmer-android"
7 | },
8 | {
9 | "name": "Gson",
10 | "author": "Google",
11 | "url": "https://github.com/google/gson"
12 | },
13 | {
14 | "name": "Glide",
15 | "author": "Bumptech",
16 | "url": "https://github.com/bumptech/glide"
17 | },
18 | {
19 | "name": "OkHttp",
20 | "author": "Square",
21 | "url": "https://github.com/square/okhttp"
22 | },
23 | {
24 | "name": "AppAuth-Android",
25 | "author": "OpenID",
26 | "url": "https://github.com/openid/AppAuth-Android"
27 | },
28 | {
29 | "name": "Retrofit",
30 | "author": "Square",
31 | "url": "https://github.com/square/retrofit"
32 | }
33 | ]
34 | }
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/DepthPageTransformer.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei
2 |
3 | import android.view.View
4 | import androidx.annotation.RequiresApi
5 | import androidx.viewpager2.widget.ViewPager2
6 |
7 | private const val MIN_SCALE = 0.75f
8 |
9 | @RequiresApi(21)
10 | class DepthPageTransformer : ViewPager2.PageTransformer {
11 |
12 | override fun transformPage(view: View, position: Float) {
13 | view.apply {
14 | val pageWidth = width
15 | when {
16 | position < -1 -> { // [-Infinity,-1)
17 | // This page is way off-screen to the left.
18 | alpha = 0f
19 | }
20 | position <= 0 -> { // [-1,0]
21 | // Use the default slide transition when moving to the left page
22 | alpha = 1f
23 | translationX = 0f
24 | translationZ = 0f
25 | scaleX = 1f
26 | scaleY = 1f
27 | }
28 | position <= 1 -> { // (0,1]
29 | // Fade the page out.
30 | alpha = 1 - position
31 |
32 | // Counteract the default slide transition
33 | translationX = pageWidth * -position
34 | // Move it behind the left page
35 | translationZ = -1f
36 |
37 | // Scale the page down (between MIN_SCALE and 1)
38 | val scaleFactor = (MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)))
39 | scaleX = scaleFactor
40 | scaleY = scaleFactor
41 | }
42 | else -> { // (1,+Infinity]
43 | // This page is way off-screen to the right.
44 | alpha = 0f
45 | }
46 | }
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/KaobeiEngineerService.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei
2 |
3 | import engineer.kaobei.model.ReviewArticle.SingleReviewArticle
4 | import engineer.kaobei.model.ReviewArticles.ReviewArticles
5 | import engineer.kaobei.model.articleInfo.KaobeiArticleInfo
6 | import engineer.kaobei.model.articles.KaobeiArticleList
7 | import engineer.kaobei.model.comments.KaobeiComments
8 | import engineer.kaobei.model.kaobeluser.BeanKaobeiUser
9 | import engineer.kaobei.model.link.KaobeiLink
10 | import engineer.kaobei.model.userarticles.UserArticles
11 | import okhttp3.MultipartBody
12 | import okhttp3.ResponseBody
13 | import retrofit2.Call
14 | import retrofit2.http.*
15 |
16 | const val BASE_URL = "https://init.engineer"
17 |
18 | interface KaobeiEngineerService {
19 |
20 | @GET("api/frontend/user/profile")
21 | fun profile(
22 | @Header("Authorization") accessToken: String
23 | ): Call
24 |
25 | @GET("api/frontend/social/cards/api/dashboard")
26 | fun userArticleList(
27 | @Header("Authorization") accessToken: String,
28 | @Query("page") page: String? = null
29 | ): Call
30 |
31 | @GET("api/frontend/social/cards")
32 | fun articleList(
33 | @Query("page") page: String? = null
34 | ): Call
35 |
36 | @GET("api/frontend/social/cards/{id}/show")
37 | fun show(
38 | @Path("id") id: String
39 | ): Call
40 |
41 | @GET("api/frontend/social/cards/{id}/links")
42 | fun links(
43 | @Path("id") id: String
44 | ): Call
45 |
46 | @GET("api/frontend/social/cards/{id}/comments")
47 | fun comments(
48 | @Path("id") id: String,
49 | @Query("page") page: String? = null
50 | ): Call
51 |
52 | @Headers("Accept: application/json")
53 | @Multipart
54 | @POST("api/frontend/social/cards/api/publish")
55 | fun publishArticle(
56 | @Header("Authorization") accessToken: String,
57 | @Part content: MultipartBody.Part,
58 | @Part themeStyle: MultipartBody.Part,
59 | @Part fontStyle: MultipartBody.Part,
60 | @Part avatar: MultipartBody.Part
61 | ): Call
62 |
63 | @Headers("Accept: application/json")
64 | @Multipart
65 | @POST("api/frontend/social/cards/api/publish")
66 | fun publishArticleNoImg(
67 | @Header("Authorization") accessToken: String,
68 | @Part content: MultipartBody.Part,
69 | @Part themeStyle: MultipartBody.Part,
70 | @Part fontStyle: MultipartBody.Part
71 | ): Call
72 |
73 | @GET("api/frontend/social/cards/api/review")
74 | fun reviewArticleList(
75 | @Header("Authorization") accessToken: String,
76 | @Query("page") page: String? = null
77 | ): Call
78 |
79 | @GET("api/frontend/social/cards/api/review/{id}/succeeded")
80 | fun approveArticle(
81 | @Header("Authorization") accessToken: String,
82 | @Path("id") id: String
83 | ): Call
84 |
85 | @GET("api/frontend/social/cards/api/review/{id}/failed")
86 | fun denyArticle(
87 | @Header("Authorization") accessToken: String,
88 | @Path("id") id: String
89 | ): Call
90 |
91 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/NestedScrollviewLoadMoreController.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei
2 |
3 | class NestedScrollviewLoadMoreController {
4 |
5 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/OnLoadMoreListener.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei
2 |
3 | interface OnLoadMoreListener {
4 | fun onLoadMore()
5 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/RecyclerViewAdapterListener.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei
2 |
3 | interface RecyclerViewAdapterListener {
4 | fun onTheFirstInit(list : List)
5 | fun onReceiveData()
6 | fun onFailedToReceiveData()
7 | fun onNoMoreData()
8 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/RecyclerViewLoadMoreScroll.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei
2 |
3 | import androidx.recyclerview.widget.GridLayoutManager
4 | import androidx.recyclerview.widget.LinearLayoutManager
5 | import androidx.recyclerview.widget.RecyclerView
6 | import androidx.recyclerview.widget.StaggeredGridLayoutManager
7 |
8 | /**
9 | * Base class for the function to implement load more on recyclerview
10 | */
11 | class RecyclerViewLoadMoreScroll : RecyclerView.OnScrollListener {
12 |
13 | private var isScrolledToEnd = false
14 | private var visibleThreshold = 10
15 | private lateinit var mOnLoadMoreListener: OnLoadMoreListener
16 | private var isLoading: Boolean = false
17 | private var lastVisibleItem: Int = 0
18 | private var totalItemCount:Int = 0
19 | private var mLayoutManager: RecyclerView.LayoutManager
20 |
21 | fun setIsScrolledToEnd() {
22 | isScrolledToEnd = true
23 | }
24 |
25 | fun setLoaded() {
26 | isLoading = false
27 | }
28 |
29 | fun getLoaded(): Boolean {
30 | return isLoading
31 | }
32 |
33 | fun setOnLoadMoreListener(mOnLoadMoreListener: OnLoadMoreListener) {
34 | this.mOnLoadMoreListener = mOnLoadMoreListener
35 | }
36 |
37 | constructor(layoutManager: LinearLayoutManager,visibleThreshold:Int) {
38 | this.mLayoutManager = layoutManager
39 | this.visibleThreshold= visibleThreshold
40 | }
41 |
42 | constructor(layoutManager: GridLayoutManager) {
43 | this.mLayoutManager = layoutManager
44 | visibleThreshold *= layoutManager.spanCount
45 | }
46 |
47 | constructor(layoutManager: StaggeredGridLayoutManager) {
48 | this.mLayoutManager = layoutManager
49 | visibleThreshold *= layoutManager.spanCount
50 | }
51 |
52 |
53 | override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
54 | super.onScrolled(recyclerView, dx, dy)
55 |
56 | if (dy <= 0) return
57 |
58 | totalItemCount = mLayoutManager.itemCount
59 |
60 | if (mLayoutManager is StaggeredGridLayoutManager) {
61 | val lastVisibleItemPositions =
62 | (mLayoutManager as StaggeredGridLayoutManager).findLastVisibleItemPositions(null)
63 | // get maximum element within the list
64 | lastVisibleItem = getLastVisibleItem(lastVisibleItemPositions)
65 | } else if (mLayoutManager is GridLayoutManager) {
66 | lastVisibleItem = (mLayoutManager as GridLayoutManager).findLastVisibleItemPosition()
67 | } else if (mLayoutManager is LinearLayoutManager) {
68 | lastVisibleItem = (mLayoutManager as LinearLayoutManager).findLastVisibleItemPosition()
69 | }
70 |
71 | if (!isLoading && totalItemCount <= lastVisibleItem + visibleThreshold && !isScrolledToEnd) {
72 | mOnLoadMoreListener.onLoadMore()
73 | isLoading = true
74 | }
75 |
76 | }
77 |
78 | private fun getLastVisibleItem(lastVisibleItemPositions: IntArray): Int {
79 | var maxSize = 0
80 | for (i in lastVisibleItemPositions.indices) {
81 | if (i == 0) {
82 | maxSize = lastVisibleItemPositions[i]
83 | } else if (lastVisibleItemPositions[i] > maxSize) {
84 | maxSize = lastVisibleItemPositions[i]
85 | }
86 | }
87 | return maxSize
88 | }
89 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/activity/ArticleActivityV2.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.activity
2 |
3 | import android.os.Bundle
4 | import com.google.android.material.snackbar.Snackbar
5 | import androidx.appcompat.app.AppCompatActivity
6 | import engineer.kaobei.R
7 |
8 | import kotlinx.android.synthetic.main.activity_article_v2.*
9 |
10 | class ArticleActivityV2 : AppCompatActivity() {
11 |
12 | override fun onCreate(savedInstanceState: Bundle?) {
13 | super.onCreate(savedInstanceState)
14 | setContentView(R.layout.activity_article_v2)
15 | setSupportActionBar(toolbar)
16 |
17 | fab.setOnClickListener { view ->
18 | Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
19 | .setAction("Action", null).show()
20 | }
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/activity/CreateArticleActivity.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.activity
2 |
3 | import androidx.appcompat.app.AppCompatActivity
4 | import android.os.Bundle
5 | import engineer.kaobei.R
6 | import engineer.kaobei.fragment.CreateArticleFragment
7 |
8 | class CreateArticleActivity : AppCompatActivity() {
9 |
10 | override fun onCreate(savedInstanceState: Bundle?) {
11 | super.onCreate(savedInstanceState)
12 | setContentView(R.layout.create_article_activity)
13 | if (savedInstanceState == null) {
14 | supportFragmentManager.beginTransaction()
15 | .replace(R.id.container, CreateArticleFragment.newInstance())
16 | .commitNow()
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/activity/settings/OpenSourceAdapter.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.activity.settings
2 |
3 | import android.view.LayoutInflater
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import android.widget.TextView
7 | import androidx.recyclerview.widget.RecyclerView
8 | import engineer.kaobei.R
9 | import engineer.kaobei.model.opensources.OpenSource
10 |
11 | /**
12 | * Created by Kimi.Peng on 2020/6/9.
13 | * Refactoring [OpenSourceRecyclerViewAdapter] class, also rename to OpenSourceAdapter, remove interface.
14 | */
15 | class OpenSourceAdapter(private val openSource: List, val clickListener: (OpenSource) -> Unit) :
16 | RecyclerView.Adapter() {
17 |
18 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
19 | val view = LayoutInflater.from(parent.context).inflate(R.layout.cardview_open_source, parent, false)
20 | return ItemViewHolder(view)
21 | }
22 |
23 | override fun getItemCount(): Int {
24 | return openSource.size
25 | }
26 |
27 | override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
28 | holder.bind(openSource[position])
29 | }
30 |
31 | inner class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
32 |
33 | val tv_name: TextView = itemView.findViewById(R.id.tv_name)
34 | val tv_author: TextView = itemView.findViewById(R.id.tv_author)
35 | val tv_url: TextView = itemView.findViewById(R.id.tv_url)
36 |
37 | fun bind(openSource: OpenSource) {
38 | tv_name.text = openSource.name
39 | tv_author.text = openSource.author
40 | tv_url.text = openSource.url
41 | itemView.setOnClickListener {
42 | clickListener(openSource)
43 | }
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/database/FontManager.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.database
2 |
3 | import android.content.Context
4 | import com.google.gson.Gson
5 | import engineer.kaobei.model.fonts.Font
6 | import engineer.kaobei.model.fonts.KaobeiFonts
7 |
8 | class FontManager(context: Context) {
9 |
10 | private var fonts: List
11 |
12 | init {
13 | val fileInString: String =
14 | context.assets.open("fonts.json").bufferedReader().use { it.readText() }
15 | val bean = Gson().fromJson(fileInString, KaobeiFonts::class.javaObjectType)
16 | fonts = bean.options
17 | }
18 |
19 | companion object {
20 | @Volatile
21 | private var INSTANCE: FontManager? = null
22 |
23 | fun getInstance(context: Context): FontManager {
24 | return INSTANCE ?: synchronized(this) {
25 | INSTANCE ?: FontManager(context).also { INSTANCE = it }
26 | }
27 |
28 | }
29 | }
30 |
31 | fun getFonts(): List {
32 | return fonts
33 | }
34 |
35 |
36 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/database/OpenSourceManager.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.database
2 |
3 | import android.content.Context
4 | import com.google.gson.Gson
5 | import engineer.kaobei.model.opensources.OpenSource
6 | import engineer.kaobei.model.opensources.OpenSources
7 |
8 | class OpenSourceManager(context: Context) {
9 |
10 | private var openSourceList: List
11 |
12 | init {
13 | val fileInString: String =
14 | context.assets.open("open_source.json").bufferedReader().use { it.readText() }
15 | val bean = Gson().fromJson(fileInString, OpenSources::class.javaObjectType)
16 | openSourceList = bean.data
17 | }
18 |
19 | companion object {
20 |
21 | @Volatile
22 | private var INSTANCE: OpenSourceManager? = null
23 |
24 | fun getInstance(context: Context): OpenSourceManager {
25 | return INSTANCE ?: synchronized(this) {
26 | INSTANCE ?: OpenSourceManager(context).also { INSTANCE = it }
27 | }
28 | }
29 | }
30 |
31 | fun getOpenSource(): List {
32 | return openSourceList
33 | }
34 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/database/ThemeManager.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.database
2 |
3 | import android.content.Context
4 | import com.google.gson.Gson
5 | import engineer.kaobei.model.themes.KaobeiThemes
6 | import engineer.kaobei.model.themes.Theme
7 |
8 | class ThemeManager(context: Context) {
9 |
10 | private var themes: List
11 |
12 | init {
13 | val fileInString: String =
14 | context.assets.open("themes.json").bufferedReader().use { it.readText() }
15 | val bean = Gson().fromJson(fileInString, KaobeiThemes::class.javaObjectType)
16 | themes = bean.themes
17 | }
18 |
19 | companion object {
20 |
21 | private var INSTANCE: ThemeManager? = null
22 |
23 | fun getInstance(context: Context): ThemeManager {
24 | return INSTANCE ?: synchronized(this) {
25 | INSTANCE ?: ThemeManager(context).also { INSTANCE = it }
26 | }
27 | }
28 | }
29 |
30 | fun getThemes(): List {
31 | return themes
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/ReviewArticle/Data.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.ReviewArticle
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class Data(
7 | @SerializedName("content")
8 | val content: String = "",
9 | @SerializedName("created_at")
10 | val createdAt: String = "",
11 | @SerializedName("created_diff")
12 | val createdDiff: String = "",
13 | @SerializedName("failed")
14 | val failed: Int = 0,
15 | @SerializedName("id")
16 | val id: Int = 0,
17 | @SerializedName("image")
18 | val image: String = "",
19 | @SerializedName("succeeded")
20 | val succeeded: Int = 0,
21 | @SerializedName("updated_at")
22 | val updatedAt: String = "",
23 | @SerializedName("updated_diff")
24 | val updatedDiff: String = ""
25 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/ReviewArticle/SingleReviewArticle.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.ReviewArticle
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class SingleReviewArticle(
7 | @SerializedName("data")
8 | val `data`: Data = Data()
9 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/ReviewArticles/Links.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.ReviewArticles
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class Links(
7 | @SerializedName("next")
8 | val next: String = ""
9 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/ReviewArticles/Meta.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.ReviewArticles
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class Meta(
7 | @SerializedName("pagination")
8 | val pagination: Pagination = Pagination()
9 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/ReviewArticles/Pagination.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.ReviewArticles
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class Pagination(
7 | @SerializedName("count")
8 | val count: Int = 0,
9 | @SerializedName("current_page")
10 | val currentPage: Int = 0,
11 | @SerializedName("links")
12 | val links: Links = Links(),
13 | @SerializedName("per_page")
14 | val perPage: Int = 0,
15 | @SerializedName("total")
16 | val total: Int = 0,
17 | @SerializedName("total_pages")
18 | val totalPages: Int = 0
19 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/ReviewArticles/ReviewArticle.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.ReviewArticles
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class ReviewArticle(
7 | @SerializedName("content")
8 | val content: String = "",
9 | @SerializedName("created_at")
10 | val createdAt: String = "",
11 | @SerializedName("created_diff")
12 | val createdDiff: String = "",
13 | @SerializedName("failed")
14 | val failed: Int = 0,
15 | @SerializedName("id")
16 | val id: Int = 0,
17 | @SerializedName("image")
18 | val image: String = "",
19 | @SerializedName("review")
20 | val review: Int = 0,
21 | @SerializedName("succeeded")
22 | val succeeded: Int = 0,
23 | @SerializedName("updated_at")
24 | val updatedAt: String = "",
25 | @SerializedName("updated_diff")
26 | val updatedDiff: String = ""
27 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/ReviewArticles/ReviewArticles.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.ReviewArticles
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class ReviewArticles(
7 | @SerializedName("data")
8 | val `data`: List = listOf(),
9 | @SerializedName("meta")
10 | val meta: Meta = Meta()
11 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/articleInfo/ArticleInfo.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.articleInfo
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class ArticleInfo(
7 | @SerializedName("content")
8 | val content: String = "",
9 | @SerializedName("created_at")
10 | val createdAt: String = "",
11 | @SerializedName("created_diff")
12 | val createdDiff: String = "",
13 | @SerializedName("id")
14 | val id: Int = 0,
15 | @SerializedName("image")
16 | val image: String = "",
17 | @SerializedName("updated_at")
18 | val updatedAt: String = "",
19 | @SerializedName("updated_diff")
20 | val updatedDiff: String = ""
21 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/articleInfo/KaobeiArticleInfo.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.articleInfo
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class KaobeiArticleInfo(
7 | @SerializedName("data")
8 | val articleInfo: ArticleInfo = ArticleInfo()
9 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/articles/Article.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.articles
2 |
3 | import android.os.Parcelable
4 | import com.google.gson.annotations.SerializedName
5 | import kotlinx.android.parcel.Parcelize
6 |
7 | @Parcelize
8 | data class Article(
9 | @SerializedName("content")
10 | val content: String = "",
11 | @SerializedName("created_at")
12 | val createdAt: String = "",
13 | @SerializedName("created_diff")
14 | val createdDiff: String = "",
15 | @SerializedName("id")
16 | val id: Int = 0,
17 | @SerializedName("image")
18 | val image: String = "",
19 | @SerializedName("updated_at")
20 | val updatedAt: String = "",
21 | @SerializedName("updated_diff")
22 | val updatedDiff: String = ""
23 | ) : Parcelable
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/articles/KaobeiArticleList.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.articles
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class KaobeiArticleList(
6 | @SerializedName("data")
7 | val `data`: List = listOf(),
8 | @SerializedName("meta")
9 | val meta: Meta = Meta()
10 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/articles/Links.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.articles
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class Links(
6 | @SerializedName("next")
7 | val next: String = ""
8 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/articles/Meta.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.articles
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class Meta(
6 | @SerializedName("pagination")
7 | val pagination: Pagination = Pagination()
8 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/articles/Pagination.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.articles
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class Pagination(
6 | @SerializedName("count")
7 | val count: Int = 0,
8 | @SerializedName("current_page")
9 | val currentPage: Int = 0,
10 | @SerializedName("links")
11 | val links: Links = Links(),
12 | @SerializedName("per_page")
13 | val perPage: Int = 0,
14 | @SerializedName("total")
15 | val total: Int = 0,
16 | @SerializedName("total_pages")
17 | val totalPages: Int = 0
18 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/comments/Comment.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.comments
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class Comment(
6 | @SerializedName("avatar")
7 | val avatar: String = "",
8 | @SerializedName("content")
9 | val content: String = "",
10 | @SerializedName("created")
11 | val created: String = "",
12 | @SerializedName("media")
13 | val media: Media = Media(),
14 | @SerializedName("name")
15 | val name: String = ""
16 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/comments/KaobeiComments.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.comments
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class KaobeiComments(
6 | @SerializedName("data")
7 | val `data`: List = listOf(),
8 | @SerializedName("meta")
9 | val meta: Meta = Meta()
10 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/comments/Links.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.comments
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class Links(
6 | @SerializedName("next")
7 | val next: String = ""
8 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/comments/Media.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.comments
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class Media(
6 | @SerializedName("connections")
7 | val connections: String = "",
8 | @SerializedName("type")
9 | val type: String = ""
10 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/comments/Meta.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.comments
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class Meta(
6 | @SerializedName("pagination")
7 | val pagination: Pagination = Pagination()
8 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/comments/Pagination.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.comments
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class Pagination(
6 | @SerializedName("count")
7 | val count: Int = 0,
8 | @SerializedName("current_page")
9 | val currentPage: Int = 0,
10 | @SerializedName("links")
11 | val links: Links = Links(),
12 | @SerializedName("per_page")
13 | val perPage: Int = 0,
14 | @SerializedName("total")
15 | val total: Int = 0,
16 | @SerializedName("total_pages")
17 | val totalPages: Int = 0
18 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/fonts/Font.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.fonts
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class Font(
6 | @SerializedName("font")
7 | val font: String = "",
8 | @SerializedName("name")
9 | val name: String = "",
10 | @SerializedName("value")
11 | val value: String = ""
12 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/fonts/KaobeiFonts.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.fonts
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class KaobeiFonts(
6 | @SerializedName("options")
7 | val options: List = listOf()
8 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/kaobeluser/BeanKaobeiUser.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.kaobeluser
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class BeanKaobeiUser(
6 | @SerializedName("data")
7 | val `data`: KaobeiUser = KaobeiUser()
8 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/kaobeluser/KaobeiUser.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.kaobeluser
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class KaobeiUser(
6 | @SerializedName("active")
7 | val active: Boolean = false,
8 | @SerializedName("avatar")
9 | val avatar: String = "",
10 | @SerializedName("confirmed")
11 | val confirmed: Boolean = false,
12 | @SerializedName("email")
13 | val email: String = "",
14 | @SerializedName("first_name")
15 | val firstName: String = "",
16 | @SerializedName("full_name")
17 | val fullName: String = "",
18 | @SerializedName("id")
19 | val id: Int = 0,
20 | @SerializedName("last_name")
21 | val lastName: String = "",
22 | @SerializedName("timezone")
23 | val timezone: String = "",
24 | @SerializedName("uuid")
25 | val uuid: String = ""
26 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/link/Data.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.link
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class Data(
6 | @SerializedName("connections")
7 | val connections: String = "",
8 | @SerializedName("like")
9 | val like: Int = 0,
10 | @SerializedName("share")
11 | val share: Int = 0,
12 | @SerializedName("type")
13 | val type: String = "",
14 | @SerializedName("url")
15 | val url: String = ""
16 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/link/KaobeiLink.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.link
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class KaobeiLink(
6 | @SerializedName("data")
7 | val `data`: List = listOf(Data(), Data(), Data(), Data())
8 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/opensources/OpenSource.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.opensources
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class OpenSource(
6 | @SerializedName("author")
7 | val author: String = "",
8 | @SerializedName("name")
9 | val name: String = "",
10 | @SerializedName("url")
11 | val url: String = ""
12 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/opensources/OpenSources.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.opensources
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class OpenSources(
6 | @SerializedName("data")
7 | val `data`: List = listOf()
8 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/themes/Additional.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.themes
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class Additional(
6 | @SerializedName("background_image")
7 | val backgroundImage: String = "",
8 | @SerializedName("footer")
9 | val footer: String = "",
10 | @SerializedName("header")
11 | val header: String = ""
12 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/themes/KaobeiThemes.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.themes
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class KaobeiThemes(
6 | @SerializedName("themes")
7 | val themes: List = listOf()
8 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/themes/Theme.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.themes
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class Theme(
6 | @SerializedName("additional")
7 | val additional: Additional = Additional(),
8 | @SerializedName("background_color")
9 | val backgroundColor: String = "#121212",
10 | @SerializedName("name")
11 | val name: String = "",
12 | @SerializedName("text_color")
13 | val textColor: String = "#FAFAFA",
14 | @SerializedName("value")
15 | val value: String = ""
16 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/userarticles/Links.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.userarticles
2 |
3 | class Links(
4 | // Do something ...
5 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/userarticles/Meta.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.userarticles
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class Meta(
6 | @SerializedName("pagination")
7 | val pagination: Pagination = Pagination()
8 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/userarticles/Pagination.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.userarticles
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class Pagination(
6 | @SerializedName("count")
7 | val count: Int = 0,
8 | @SerializedName("current_page")
9 | val currentPage: Int = 0,
10 | @SerializedName("links")
11 | val links: Links = Links(),
12 | @SerializedName("per_page")
13 | val perPage: Int = 0,
14 | @SerializedName("total")
15 | val total: Int = 0,
16 | @SerializedName("total_pages")
17 | val totalPages: Int = 0
18 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/userarticles/UserArticle.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.userarticles
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class UserArticle(
6 | @SerializedName("banned_remarks")
7 | val bannedRemarks: String = "",
8 | @SerializedName("content")
9 | val content: String = "",
10 | @SerializedName("created_at")
11 | val createdAt: String = "",
12 | @SerializedName("created_diff")
13 | val createdDiff: String = "",
14 | @SerializedName("id")
15 | val id: Int = 0,
16 | @SerializedName("image")
17 | val image: String = "",
18 | @SerializedName("is_banned")
19 | val isBanned: Int = 0,
20 | @SerializedName("updated_at")
21 | val updatedAt: String = "",
22 | @SerializedName("updated_diff")
23 | val updatedDiff: String = ""
24 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/model/userarticles/UserArticles.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.model.userarticles
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class UserArticles(
6 | @SerializedName("data")
7 | val `data`: List = listOf(),
8 | @SerializedName("meta")
9 | val meta: Meta = Meta()
10 | )
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/util/ClipBoardUtil.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.util
2 |
3 | import android.content.ClipData
4 | import android.content.ClipboardManager
5 | import android.content.Context
6 | import android.content.Context.CLIPBOARD_SERVICE
7 |
8 | object ClipBoardUtil {
9 |
10 | fun copy(context: Context, string: String) {
11 | val myClipboard: ClipboardManager? =
12 | context.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager?
13 | val myClip: ClipData? = ClipData.newPlainText("text", string)
14 | myClipboard?.primaryClip = myClip;
15 | }
16 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/util/CustomTabUtil.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.util
2 |
3 | import android.content.Context
4 | import android.net.Uri
5 | import androidx.browser.customtabs.CustomTabsIntent
6 | import androidx.core.content.ContextCompat
7 | import engineer.kaobei.R
8 |
9 | object CustomTabUtil {
10 | fun createCustomTab(context: Context, url: String) {
11 | val builder: CustomTabsIntent.Builder = CustomTabsIntent.Builder()
12 | builder.setToolbarColor(ContextCompat.getColor(context, R.color.colorPrimary))
13 | builder.setShowTitle(true)
14 | val customTabsIntent: CustomTabsIntent = builder.build()
15 | customTabsIntent.launchUrl(
16 | context,
17 | Uri.parse(url)
18 | )
19 | }
20 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/util/SnackbarUtil.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.util
2 |
3 | import android.view.Gravity
4 | import androidx.coordinatorlayout.widget.CoordinatorLayout
5 | import com.google.android.material.snackbar.Snackbar
6 |
7 | object SnackbarUtil {
8 | @JvmStatic
9 | fun makeAnchorSnackbar(coorView: CoordinatorLayout, text: String, anchorID: Int) {
10 | val snackbar = Snackbar.make(coorView, text, Snackbar.LENGTH_SHORT)
11 | val layoutParams = snackbar.view.layoutParams as CoordinatorLayout.LayoutParams
12 | layoutParams.anchorId = anchorID
13 | layoutParams.gravity = Gravity.TOP
14 | snackbar.view.layoutParams = layoutParams
15 | snackbar.show()
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/util/ViewUtil.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.util
2 |
3 | import androidx.recyclerview.widget.RecyclerView
4 | import engineer.kaobei.view.AnimatedGap
5 | import kotlin.jvm.internal.Ref
6 |
7 | object ViewUtil {
8 | fun addGapController(recyclerView: RecyclerView, gap: AnimatedGap) {
9 | val reInTop: Ref.BooleanRef = Ref.BooleanRef()
10 | recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
11 | override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
12 | super.onScrolled(recyclerView, dx, dy)
13 | if (!recyclerView.canScrollVertically(-1)) {
14 | reInTop.element = true
15 | gap.hide()
16 | } else {
17 | if (reInTop.element) {
18 | reInTop.element = false
19 | gap.show()
20 | }
21 | }
22 | }
23 | })
24 | }
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/util/ext/ImageViewExt.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.util.ext
2 |
3 | import android.graphics.drawable.Drawable
4 | import android.widget.ImageView
5 | import com.bumptech.glide.Glide
6 | import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
7 |
8 | /**
9 | * Created by Kimi.Peng on 2020/6/3.
10 | */
11 | fun ImageView.viewLoading(resource: String) {
12 | Glide.with(this)
13 | .load(resource)
14 | .into(this)
15 | }
16 |
17 | fun ImageView.viewLoading(drawable: Drawable?) {
18 | Glide.with(this)
19 | .load(drawable)
20 | .into(this)
21 | }
22 |
23 | fun ImageView.viewLoadingWithTransition(
24 | resource: String, drawableTransitionOptions: DrawableTransitionOptions = DrawableTransitionOptions.withCrossFade()
25 | ) {
26 | Glide.with(this)
27 | .load(resource)
28 | .transition(drawableTransitionOptions)
29 | .into(this)
30 | }
31 |
32 | fun ImageView.viewLoadingWithTransition(
33 | drawable: Drawable?, drawableTransitionOptions: DrawableTransitionOptions = DrawableTransitionOptions.withCrossFade()
34 | ) {
35 | Glide.with(this)
36 | .load(drawable)
37 | .transition(drawableTransitionOptions)
38 | .into(this)
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/view/AnimatedGap.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.view
2 |
3 | import android.animation.ValueAnimator
4 | import android.content.Context
5 | import android.graphics.Canvas
6 | import android.graphics.Paint
7 | import android.util.AttributeSet
8 | import android.util.Log
9 | import android.view.animation.DecelerateInterpolator
10 | import android.widget.LinearLayout
11 | import androidx.core.content.ContextCompat
12 | import engineer.kaobei.R
13 |
14 | /**
15 | * Class AnimatedGap.
16 | */
17 | class AnimatedGap : LinearLayout {
18 |
19 | private var paint: Paint = Paint()
20 |
21 | private var animator: ValueAnimator? = null
22 | private var animator2: ValueAnimator? = null
23 | private var currentIndexLeft = 0
24 | private var currentIndexRight = 0
25 |
26 | private var w = 0
27 | private var h = 0
28 | private var init = false
29 |
30 | constructor(context: Context) : super(context) {
31 | initial(context, null)
32 | }
33 |
34 | constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
35 | initial(context, attrs)
36 | }
37 |
38 | constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(
39 | context,
40 | attrs,
41 | defStyle
42 | ) {
43 | initial(context, attrs)
44 | }
45 |
46 | private fun initial(context: Context, attrs: AttributeSet?) {
47 | setWillNotDraw(false)
48 | this.paint.color = ContextCompat.getColor(context, R.color.FxWhite)
49 | this.paint.strokeWidth = 15F
50 | }
51 |
52 | override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
53 | super.onSizeChanged(w, h, oldw, oldh)
54 | this.w = w
55 | this.h = h
56 | }
57 |
58 | override fun onDraw(canvas: Canvas?) {
59 | super.onDraw(canvas)
60 | if (this.init) {
61 | canvas?.drawLine((this.w / 2).toFloat(), 0F, this.currentIndexLeft.toFloat(), 0F, this.paint)
62 | canvas?.drawLine((this.w / 2).toFloat(), 0F, this.currentIndexRight.toFloat(), 0F, this.paint)
63 | }
64 | }
65 |
66 | fun hide() {
67 | this.animator?.cancel()
68 | this.animator2?.cancel()
69 | this.animator = ValueAnimator.ofInt(0, w / 2).apply {
70 | this.duration = 200
71 | this.interpolator = DecelerateInterpolator()
72 | addUpdateListener { valueAnimator ->
73 | currentIndexLeft = valueAnimator.animatedValue as Int
74 | invalidate()
75 | }
76 | }
77 | this.animator2 = ValueAnimator.ofInt(w, w / 2).apply {
78 | this.duration = 200
79 | this.interpolator = DecelerateInterpolator()
80 | addUpdateListener { valueAnimator ->
81 | currentIndexRight = valueAnimator.animatedValue as Int
82 | Log.d("qijian", "curValue:" + valueAnimator.animatedValue);
83 | invalidate()
84 | }
85 | }
86 | this.animator?.start()
87 | this.animator2?.start()
88 | }
89 |
90 | fun show() {
91 | this.animator?.cancel()
92 | this.animator2?.cancel()
93 | this.animator = ValueAnimator.ofInt(this.w / 2, 0).apply {
94 | this.duration = 200
95 | this.interpolator = DecelerateInterpolator()
96 | addUpdateListener { valueAnimator ->
97 | if (!init) {
98 | init = true
99 | } else {
100 | currentIndexLeft = valueAnimator.animatedValue as Int
101 | invalidate()
102 | }
103 | }
104 | }
105 | this.animator2 = ValueAnimator.ofInt(this.w / 2, this.w).apply {
106 | this.duration = 200
107 | this.interpolator = DecelerateInterpolator()
108 | addUpdateListener { valueAnimator ->
109 | currentIndexRight = valueAnimator.animatedValue as Int
110 | Log.d("qijian", "curValue:" + valueAnimator.animatedValue);
111 | invalidate()
112 | }
113 | }
114 | this.animator?.start()
115 | this.animator2?.start()
116 | }
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/view/UserViewer.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.view
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import android.view.View
6 | import android.widget.ImageView
7 | import android.widget.LinearLayout
8 | import android.widget.TextView
9 | import androidx.cardview.widget.CardView
10 | import androidx.core.content.ContextCompat
11 | import engineer.kaobei.model.kaobeluser.KaobeiUser
12 | import engineer.kaobei.R
13 | import engineer.kaobei.util.ext.viewLoading
14 |
15 | /**
16 | * Class UserViewer.
17 | */
18 | class UserViewer : LinearLayout {
19 |
20 | private lateinit var imageViewAvatar: ImageView
21 | private lateinit var imageViewAvatarBackground: ImageView
22 | private lateinit var textViewName: TextView
23 | private lateinit var textViewEmail: TextView
24 | private lateinit var cardViewAvatar: CardView
25 | private var authorized: Boolean = false
26 |
27 | constructor(context: Context) : super(context) {
28 | initWidget(context, null)
29 | }
30 |
31 | constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
32 | initWidget(context, attrs)
33 | }
34 |
35 | constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(
36 | context,
37 | attrs,
38 | defStyle
39 | ) {
40 | initWidget(context, attrs)
41 | }
42 |
43 | fun setProfile(kaobeiUser: KaobeiUser) {
44 | this.imageViewAvatar.viewLoading(kaobeiUser.avatar)
45 | this.imageViewAvatarBackground.viewLoading(context.getDrawable(R.drawable.img_animated_rainbow))
46 | this.textViewName.text = kaobeiUser.fullName
47 | this.textViewEmail.text = kaobeiUser.email
48 | }
49 |
50 | fun initView(authorized: Boolean) {
51 | if (authorized) {
52 | this.authorized = true
53 | this.textViewName.text = "Loading"
54 | this.textViewEmail.text = ""
55 | } else {
56 | this.authorized = false
57 | this.textViewName.text = "點擊登入"
58 | this.textViewEmail.visibility = View.GONE
59 | imageViewAvatar.viewLoading(ContextCompat.getDrawable(imageViewAvatar.context, R.drawable.img_kb))
60 | }
61 | }
62 |
63 | private fun initWidget(context: Context, attrs: AttributeSet?) {
64 | View.inflate(context, R.layout.widget_user_viewer, this)
65 | this.imageViewAvatar = findViewById(R.id.img_avatar)
66 | this.imageViewAvatarBackground = findViewById(R.id.content_background)
67 | this.textViewName = findViewById(R.id.tv_name)
68 | this.textViewEmail = findViewById(R.id.tv_email)
69 | this.cardViewAvatar = findViewById(R.id.cardview_avatar)
70 | }
71 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/viewmodel/ArticleInfoViewModel.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.viewmodel
2 |
3 | import engineer.kaobei.BASE_URL
4 | import engineer.kaobei.KaobeiEngineerService
5 | import engineer.kaobei.model.articleInfo.KaobeiArticleInfo
6 | import retrofit2.Retrofit
7 | import retrofit2.converter.gson.GsonConverterFactory
8 |
9 | class ArticleInfoViewModel : ObjectViewModel() {
10 |
11 | fun loadArticleInfo(id: Int) {
12 | val retrofit = Retrofit.Builder()
13 | .baseUrl(BASE_URL)
14 | .addConverterFactory(GsonConverterFactory.create())
15 | .build()
16 | val service = retrofit.create(KaobeiEngineerService::class.java)
17 | service.show(id.toString())
18 | .enqueue(object : retrofit2.Callback {
19 | override fun onFailure(call: retrofit2.Call, t: Throwable) {
20 | mOnReceiveDataListener?.onFailureReceiveData()
21 | }
22 |
23 | override fun onResponse(
24 | call: retrofit2.Call,
25 | response: retrofit2.Response
26 | ) {
27 | if (response.isSuccessful) {
28 | response.body()?.let { change(it) }
29 | mOnReceiveDataListener?.onReceiveData()
30 | } else {
31 | mOnReceiveDataListener?.onFailureReceiveData()
32 | }
33 | }
34 | })
35 | }
36 |
37 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/viewmodel/ArticleListViewModel.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.viewmodel
2 |
3 | import androidx.lifecycle.LiveData
4 | import androidx.lifecycle.MutableLiveData
5 | import engineer.kaobei.BASE_URL
6 | import engineer.kaobei.KaobeiEngineerService
7 | import engineer.kaobei.model.articles.Article
8 | import engineer.kaobei.model.articles.KaobeiArticleList
9 | import retrofit2.Retrofit
10 | import retrofit2.converter.gson.GsonConverterFactory
11 |
12 | /**
13 | * Class ArticleListViewModel.
14 | *
15 | * A ViewModel used for the {@link ArticleListFragment}.
16 | */
17 | class ArticleListViewModel : ListViewModel() {
18 |
19 | protected var mPage : MutableLiveData = MutableLiveData(1)
20 | protected var mInit : MutableLiveData = MutableLiveData(0)
21 |
22 | init {
23 | mList = arrayListOf(Article())
24 | mLiveData = MutableLiveData>(arrayListOf(Article())).also {
25 |
26 | }
27 | }
28 |
29 | fun refreshData(){
30 | mInit.value = 0
31 | mPage.value = 1
32 | mList = arrayListOf(Article())
33 | mLiveData.value = arrayListOf(Article())
34 | }
35 |
36 | fun setInit(value : Boolean){
37 | if(value){
38 | mInit.value = 1
39 | }else{
40 | mInit.value = 0
41 | }
42 | }
43 |
44 | fun isInit() : Boolean{
45 | val value:Int = mInit.value!!
46 | return value != 0
47 | }
48 |
49 | fun getPage(): LiveData {
50 | return mPage
51 | }
52 |
53 | fun addPage(){
54 | if(mPage.value!=null){
55 | var index :Int= mPage.value!!
56 | index++
57 | mPage.value = index
58 | }
59 | }
60 |
61 | fun minusPage(){
62 | if(mPage.value!=null){
63 | var index :Int= mPage.value!!
64 | index--
65 | mPage.value = index
66 | }
67 | }
68 |
69 | fun loadMoreArticles(page: Int) {
70 | val retrofit = Retrofit.Builder()
71 | .baseUrl(BASE_URL)
72 | .addConverterFactory(GsonConverterFactory.create())
73 | .build()
74 | val service = retrofit.create(KaobeiEngineerService::class.java)
75 | service.articleList(page.toString())
76 | .enqueue(object : retrofit2.Callback {
77 | override fun onFailure(call: retrofit2.Call, t: Throwable) {
78 | mOnReceiveDataListener?.onFailureToReceiveData()
79 | }
80 |
81 | override fun onResponse(
82 | call: retrofit2.Call,
83 | response: retrofit2.Response
84 | ) {
85 | if (response.isSuccessful) {
86 | mOnReceiveDataListener?.onReceiveData(response.body()?.data!!)
87 | add(response.body()?.data!!)
88 | } else {
89 | mOnReceiveDataListener?.onFailureToReceiveData()
90 | }
91 | }
92 | })
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/viewmodel/CommentsViewModel.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.viewmodel
2 |
3 | import androidx.lifecycle.LiveData
4 | import androidx.lifecycle.MutableLiveData
5 | import engineer.kaobei.BASE_URL
6 | import engineer.kaobei.KaobeiEngineerService
7 | import engineer.kaobei.model.comments.Comment
8 | import engineer.kaobei.model.comments.KaobeiComments
9 | import retrofit2.Retrofit
10 | import retrofit2.converter.gson.GsonConverterFactory
11 |
12 | /**
13 | * Class CommentsViewModel.
14 | *
15 | * A ViewModel used for the {@link ArticleListFragment}.
16 | */
17 | class CommentsViewModel : ListViewModel() {
18 |
19 | protected var mPage : MutableLiveData = MutableLiveData(1)
20 | protected var id :Int = 0
21 | protected var mInit : MutableLiveData = MutableLiveData(0)
22 |
23 | init {
24 | mList = arrayListOf(Comment(),Comment())
25 | mLiveData = MutableLiveData>(arrayListOf(Comment(),Comment())).also {
26 | }
27 | }
28 |
29 | fun getPage(): LiveData {
30 | return mPage
31 | }
32 |
33 | fun addPage(){
34 | if(mPage.value!=null){
35 | var index :Int= mPage.value!!
36 | index++
37 | mPage.postValue(index)
38 | mPage.value = index
39 | }
40 | }
41 |
42 | fun changePage(page:Int){
43 | mPage.postValue(page)
44 | }
45 |
46 | fun getLivaDataValue(id:Int):LiveData>{
47 | this.id = id
48 | val value:Int = mInit.value!!
49 | if(value==0){
50 | mInit.postValue(1)
51 | mPage.value?.let { loadComments(id, it) }
52 | }
53 | return mLiveData
54 | }
55 |
56 | fun loadComments(id: Int, page: Int) {
57 | val retrofit = Retrofit.Builder()
58 | .baseUrl(BASE_URL)
59 | .addConverterFactory(GsonConverterFactory.create())
60 | .build()
61 | val service = retrofit.create(KaobeiEngineerService::class.java)
62 | service.comments(id.toString(), page.toString())
63 | .enqueue(object : retrofit2.Callback {
64 | override fun onFailure(call: retrofit2.Call, t: Throwable) {
65 | mOnReceiveDataListener?.onFailureToReceiveData()
66 | }
67 |
68 | override fun onResponse(
69 | call: retrofit2.Call,
70 | response: retrofit2.Response
71 | ) {
72 | if (response.isSuccessful) {
73 | mOnReceiveDataListener?.onReceiveData(response.body()?.data!!)
74 | add(response.body()?.data!!)
75 | if (response.body()?.meta?.pagination?.currentPage == response.body()?.meta?.pagination?.totalPages) {
76 | mOnReceiveDataListener?.onNoMoreData()
77 | }
78 | } else {
79 | mOnReceiveDataListener?.onFailureToReceiveData()
80 | }
81 | }
82 | })
83 | }
84 |
85 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/viewmodel/IndexViewModel.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.viewmodel
2 |
3 | import androidx.lifecycle.ViewModel
4 |
5 | /**
6 | * Class IndexViewModel.
7 | */
8 | class IndexViewModel : ViewModel() {
9 |
10 | // TODO: Implement the ViewModel
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/viewmodel/LinkViewModel.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.viewmodel
2 |
3 | import engineer.kaobei.BASE_URL
4 | import engineer.kaobei.KaobeiEngineerService
5 | import engineer.kaobei.model.link.KaobeiLink
6 | import retrofit2.Retrofit
7 | import retrofit2.converter.gson.GsonConverterFactory
8 |
9 | /**
10 | * Class LinkViewModel.
11 | */
12 | class LinkViewModel : ObjectViewModel() {
13 |
14 | fun loadLink(id: Int) {
15 | val retrofit = Retrofit.Builder()
16 | .baseUrl(BASE_URL)
17 | .addConverterFactory(GsonConverterFactory.create())
18 | .build()
19 | val service = retrofit.create(KaobeiEngineerService::class.java)
20 | service.links(id.toString()).enqueue(object : retrofit2.Callback {
21 | override fun onFailure(call: retrofit2.Call, t: Throwable) {
22 | mOnReceiveDataListener?.onFailureReceiveData()
23 | }
24 |
25 | override fun onResponse(
26 | call: retrofit2.Call,
27 | response: retrofit2.Response
28 | ) {
29 | if (response.isSuccessful) {
30 | response.body()?.let { change(it) }
31 | mOnReceiveDataListener?.onReceiveData()
32 | } else {
33 | mOnReceiveDataListener?.onFailureReceiveData()
34 | }
35 | }
36 | })
37 | }
38 |
39 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/viewmodel/ListViewModel.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.viewmodel
2 |
3 | import android.util.Log
4 | import androidx.lifecycle.LiveData
5 | import androidx.lifecycle.MutableLiveData
6 | import androidx.lifecycle.ViewModel
7 |
8 | /**
9 | * Class ListViewModel.
10 | */
11 | open class ListViewModel : ViewModel() {
12 |
13 | protected var mListViewModelController: ListViewModelController? = null
14 | protected var mOnReceiveDataListener: OnReceiveDataListener? = null
15 | protected var mReviewOnReceiveDataListener: OnReviewOnReceiveDataListener? = null
16 | protected var mList = ArrayList()
17 | protected var mLiveData: MutableLiveData> = MutableLiveData>()
18 |
19 | open fun getLiveData(): LiveData> {
20 | return mLiveData
21 | }
22 |
23 | fun add(list: List) {
24 | mList.addAll(list)
25 | mLiveData.value = mList
26 | }
27 |
28 | fun add(t: T) {
29 | mList.add(t)
30 | mLiveData.value = mList
31 | }
32 |
33 | fun add(index: Int, t: T) {
34 | mList.add(index, t)
35 | mLiveData.value = mList
36 | }
37 |
38 | fun change(index: Int, t: T){
39 | mList[index] = t
40 | mLiveData.value = mList
41 | }
42 |
43 | fun remove(index: Int) {
44 | mList.removeAt(index)
45 | mLiveData.value = mList
46 | }
47 |
48 | fun addOnReceiveDataListener(mOnReceiveDataListener: OnReceiveDataListener) {
49 | this.mOnReceiveDataListener = mOnReceiveDataListener
50 | }
51 |
52 | fun addOnReviewReceiveDataListener(mOnReceiveDataListener: OnReviewOnReceiveDataListener) {
53 | this.mReviewOnReceiveDataListener = mOnReceiveDataListener
54 | }
55 |
56 | fun addListViewModelController(mListViewModelController:ListViewModelController){
57 | this.mListViewModelController = mListViewModelController
58 | }
59 |
60 | interface OnReceiveDataListener {
61 | fun onReceiveData(list: List)
62 | fun onFailureToReceiveData()
63 | fun onNoMoreData()
64 | }
65 |
66 | interface OnReviewOnReceiveDataListener {
67 | fun onReceiveData(list: List,totalPage : Int)
68 | fun onFailureToReceiveData()
69 | fun onNoMoreData()
70 | }
71 |
72 | interface ListViewModelController {
73 | fun initLiveData()
74 | }
75 |
76 |
77 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/viewmodel/ObjectViewModel.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.viewmodel
2 |
3 | import androidx.lifecycle.LiveData
4 | import androidx.lifecycle.MutableLiveData
5 | import androidx.lifecycle.ViewModel
6 |
7 | /**
8 | * Class ObjectViewModel.
9 | */
10 | open class ObjectViewModel : ViewModel() {
11 |
12 | protected var mOnReceiveDataListener: OnReceiveDataListener? = null
13 | private val mLiveData: MutableLiveData by lazy {
14 | MutableLiveData().also {
15 | // Do something ...
16 | }
17 | }
18 |
19 | fun getLiveData(): LiveData {
20 | return mLiveData
21 | }
22 |
23 | fun change(t: T) {
24 | mLiveData.postValue(t)
25 | }
26 |
27 | fun addOnReceiveDataListener(mOnReceiveDataListener: OnReceiveDataListener) {
28 | this.mOnReceiveDataListener = mOnReceiveDataListener
29 | }
30 |
31 | interface OnReceiveDataListener {
32 | fun onReceiveData()
33 | fun onFailureReceiveData()
34 | }
35 |
36 | }
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/viewmodel/ProfileViewModel.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.viewmodel
2 |
3 | import engineer.kaobei.BASE_URL
4 | import engineer.kaobei.KaobeiEngineerService
5 | import engineer.kaobei.model.kaobeluser.BeanKaobeiUser
6 | import engineer.kaobei.model.kaobeluser.KaobeiUser
7 | import retrofit2.Call
8 | import retrofit2.Response
9 | import retrofit2.Retrofit
10 | import retrofit2.converter.gson.GsonConverterFactory
11 |
12 | /**
13 | * Class ProfileViewModel.
14 | */
15 | class ProfileViewModel : ObjectViewModel() {
16 |
17 | fun loadProfile(accessToken: String) {
18 | val retrofit = Retrofit.Builder()
19 | .baseUrl(BASE_URL)
20 | .addConverterFactory(GsonConverterFactory.create())
21 | .build()
22 | val service = retrofit.create(KaobeiEngineerService::class.java)
23 | service.profile("Bearer $accessToken")
24 | .enqueue(object : retrofit2.Callback {
25 | override fun onFailure(call: Call, t: Throwable) {
26 | mOnReceiveDataListener?.onFailureReceiveData()
27 | }
28 |
29 | override fun onResponse(
30 | call: Call,
31 | response: Response
32 | ) {
33 | if (response.isSuccessful) {
34 | response.body()?.data?.let { change(it) }
35 | mOnReceiveDataListener?.onReceiveData()
36 | } else {
37 | mOnReceiveDataListener?.onFailureReceiveData()
38 | }
39 | }
40 |
41 | })
42 | }
43 |
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/viewmodel/ReviewViewModel.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.viewmodel
2 |
3 | import androidx.lifecycle.LiveData
4 | import androidx.lifecycle.MutableLiveData
5 | import androidx.lifecycle.ViewModel
6 | import engineer.kaobei.BASE_URL
7 | import engineer.kaobei.KaobeiEngineerService
8 | import engineer.kaobei.model.ReviewArticles.ReviewArticle
9 | import engineer.kaobei.model.ReviewArticles.ReviewArticles
10 | import retrofit2.Retrofit
11 | import retrofit2.converter.gson.GsonConverterFactory
12 |
13 | class ReviewViewModel : ListViewModel() {
14 | protected var mPage : MutableLiveData = MutableLiveData(1)
15 | protected var mInit : MutableLiveData = MutableLiveData(0)
16 |
17 | init {
18 | mList = arrayListOf()
19 | mLiveData = MutableLiveData>(arrayListOf()).also {
20 |
21 | }
22 | }
23 |
24 | fun refreshData(){
25 | mInit.value = 0
26 | mPage.value = 1
27 | mList = arrayListOf()
28 | mLiveData.value = arrayListOf()
29 | }
30 |
31 | fun setInit(value : Boolean){
32 | if(value){
33 | mInit.value = 1
34 | }else{
35 | mInit.value = 0
36 | }
37 | }
38 |
39 | fun isInit() : Boolean{
40 | val value:Int = mInit.value!!
41 | return value != 0
42 | }
43 |
44 | fun getPage(): LiveData {
45 | return mPage
46 | }
47 |
48 | fun addPage(){
49 | if(mPage.value!=null){
50 | var index :Int= mPage.value!!
51 | index++
52 | mPage.value = index
53 | }
54 | }
55 |
56 | fun minusPage(){
57 | if(mPage.value!=null){
58 | var index :Int= mPage.value!!
59 | index--
60 | mPage.value = index
61 | }
62 | }
63 |
64 | fun loadMoreArticles(accessToken: String, page: Int) {
65 | val retrofit = Retrofit.Builder()
66 | .baseUrl(BASE_URL)
67 | .addConverterFactory(GsonConverterFactory.create())
68 | .build()
69 | val service = retrofit.create(KaobeiEngineerService::class.java)
70 |
71 | service.reviewArticleList("Bearer $accessToken", page.toString())
72 | .enqueue(object : retrofit2.Callback {
73 | override fun onFailure(call: retrofit2.Call, t: Throwable) {
74 | mReviewOnReceiveDataListener?.onFailureToReceiveData()
75 | }
76 |
77 | override fun onResponse(
78 | call: retrofit2.Call,
79 | response: retrofit2.Response
80 | ) {
81 | if (response.isSuccessful) {
82 | response.body()?.meta?.pagination?.total?.let {
83 | mReviewOnReceiveDataListener?.onReceiveData(response.body()?.data!!,
84 | it
85 | )
86 | }
87 | response.body()?.data
88 | add(response.body()?.data!!)
89 | } else {
90 | mReviewOnReceiveDataListener?.onFailureToReceiveData()
91 | }
92 | }
93 | })
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/app/src/main/java/engineer/kaobei/viewmodel/UserArticleListViewModel.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei.viewmodel
2 |
3 | import androidx.lifecycle.LiveData
4 | import androidx.lifecycle.MutableLiveData
5 | import engineer.kaobei.BASE_URL
6 | import engineer.kaobei.KaobeiEngineerService
7 | import engineer.kaobei.model.articles.Article
8 | import engineer.kaobei.model.userarticles.UserArticle
9 | import engineer.kaobei.model.userarticles.UserArticles
10 | import retrofit2.Retrofit
11 | import retrofit2.converter.gson.GsonConverterFactory
12 |
13 | /**
14 | * Class UserArticleListViewModel.
15 | */
16 | class UserArticleListViewModel : ListViewModel() {
17 |
18 | protected var mPage : MutableLiveData = MutableLiveData(1)
19 | protected var mInit : MutableLiveData = MutableLiveData(0)
20 |
21 | init {
22 | mList = arrayListOf()
23 | mLiveData = MutableLiveData>(arrayListOf()).also {
24 |
25 | }
26 | }
27 |
28 | fun refreshData(){
29 | mInit.value = 0
30 | mPage.value = 1
31 | mList = arrayListOf()
32 | mLiveData.value = arrayListOf()
33 | }
34 |
35 | fun setInit(value : Boolean){
36 | if(value){
37 | mInit.value = 1
38 | }else{
39 | mInit.value = 0
40 | }
41 | }
42 |
43 | fun isInit() : Boolean{
44 | val value:Int = mInit.value!!
45 | return value != 0
46 | }
47 |
48 | fun getPage(): LiveData {
49 | return mPage
50 | }
51 |
52 | fun addPage(){
53 | if(mPage.value!=null){
54 | var index :Int= mPage.value!!
55 | index++
56 | mPage.value = index
57 | }
58 | }
59 |
60 | fun minusPage(){
61 | if(mPage.value!=null){
62 | var index :Int= mPage.value!!
63 | index--
64 | mPage.value = index
65 | }
66 | }
67 |
68 | fun loadMoreArticles(accessToken: String, page: Int) {
69 | val retrofit = Retrofit.Builder()
70 | .baseUrl(BASE_URL)
71 | .addConverterFactory(GsonConverterFactory.create())
72 | .build()
73 | val service = retrofit.create(KaobeiEngineerService::class.java)
74 |
75 | service.userArticleList("Bearer $accessToken", page.toString())
76 | .enqueue(object : retrofit2.Callback {
77 | override fun onFailure(call: retrofit2.Call, t: Throwable) {
78 | mOnReceiveDataListener?.onFailureToReceiveData()
79 | }
80 |
81 | override fun onResponse(
82 | call: retrofit2.Call,
83 | response: retrofit2.Response
84 | ) {
85 | if (response.isSuccessful) {
86 | mOnReceiveDataListener?.onReceiveData(response.body()?.data!!)
87 | add(response.body()?.data!!)
88 | } else {
89 | mOnReceiveDataListener?.onFailureToReceiveData()
90 | }
91 | }
92 | })
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/slide_in_right.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/slide_out_left.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/color/bnv_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/img_mallet.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/drawable-v24/img_mallet.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_sheet.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
7 |
9 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bottomsheet_line.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/cursor.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/custom_ripple.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_dashboard_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_favorite_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_home_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
10 |
12 |
14 |
16 |
18 |
20 |
22 |
24 |
26 |
28 |
30 |
32 |
34 |
36 |
38 |
40 |
42 |
44 |
46 |
48 |
50 |
52 |
54 |
56 |
58 |
60 |
62 |
64 |
66 |
68 |
70 |
72 |
74 |
75 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_menu_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_mode_edit_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_people_outline_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_person_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_reply_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_share_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_thumb_up_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_warning_red_24dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_animated_rainbow.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/drawable/img_animated_rainbow.gif
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_background_star.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/drawable/img_background_star.gif
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_bat.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
18 |
21 |
24 |
27 |
30 |
33 |
36 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_bird.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
18 |
21 |
24 |
27 |
30 |
33 |
36 |
39 |
42 |
45 |
48 |
51 |
52 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_bull.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
18 |
21 |
24 |
27 |
30 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_camel.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
18 |
21 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_cat.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
15 |
18 |
21 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_devotion_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/drawable/img_devotion_bg.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_flag1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/drawable/img_flag1.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_kb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/drawable/img_kb.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_mallet.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/drawable/img_mallet.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_nopic_192.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/drawable/img_nopic_192.gif
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_plurk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/drawable/img_plurk.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/img_twitter.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/drawable/img_twitter.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/kohlrabi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/drawable/kohlrabi.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/test1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/drawable/test1.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/test2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/drawable/test2.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/text_bottom_line.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
8 |
9 |
12 |
13 |
14 |
15 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/font/dos.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/font/dos.ttf
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_article.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
17 |
18 |
31 |
32 |
42 |
43 |
44 |
45 |
48 |
49 |
55 |
56 |
57 |
58 |
62 |
63 |
64 |
65 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_article_v2.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_login.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
21 |
22 |
27 |
28 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/ads_style1.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
22 |
23 |
27 |
28 |
33 |
34 |
44 |
45 |
48 |
49 |
54 |
55 |
56 |
57 |
58 |
59 |
65 |
66 |
67 |
75 |
76 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/ads_style2.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
22 |
23 |
29 |
30 |
38 |
39 |
47 |
48 |
49 |
50 |
56 |
57 |
58 |
59 |
64 |
65 |
70 |
71 |
76 |
77 |
85 |
86 |
95 |
96 |
97 |
98 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/bottom_sheet_authorized.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
21 |
22 |
30 |
31 |
39 |
40 |
41 |
42 |
50 |
51 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/bottom_sheet_edit_content.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
20 |
21 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/bottom_sheet_id_selecter.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
20 |
21 |
27 |
28 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/bottom_sheet_links.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
20 |
21 |
22 |
30 |
31 |
39 |
40 |
41 |
42 |
50 |
51 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/bottom_sheet_not_authorized.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
21 |
22 |
30 |
31 |
39 |
40 |
41 |
42 |
50 |
51 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/bottom_sheet_open_source.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
25 |
26 |
29 |
30 |
36 |
37 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/bottom_sheet_select_font.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
24 |
25 |
37 |
38 |
41 |
42 |
48 |
49 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/bottom_sheet_select_theme.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
25 |
26 |
29 |
30 |
36 |
37 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/bottom_sheet_share.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
20 |
21 |
29 |
30 |
38 |
39 |
40 |
41 |
49 |
50 |
58 |
59 |
60 |
61 |
69 |
70 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/cardview_header1.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/cardview_open_source.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
18 |
19 |
24 |
25 |
33 |
34 |
42 |
43 |
51 |
52 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/cardview_style1.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
19 |
20 |
24 |
25 |
31 |
32 |
33 |
34 |
39 |
40 |
51 |
52 |
63 |
64 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/cardview_style2.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
19 |
20 |
27 |
28 |
39 |
40 |
41 |
42 |
46 |
47 |
53 |
54 |
55 |
56 |
61 |
62 |
73 |
74 |
85 |
86 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/cardview_style_font.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
16 |
17 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/cardview_style_theme.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
16 |
17 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/create_article_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_article_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
13 |
14 |
18 |
19 |
24 |
25 |
35 |
36 |
47 |
48 |
49 |
50 |
61 |
62 |
73 |
74 |
75 |
76 |
77 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_review.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
17 |
18 |
30 |
31 |
37 |
38 |
44 |
45 |
56 |
57 |
67 |
68 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
93 |
94 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/progress_loading.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/settings_activity.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_last_one.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_not_authorized.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
20 |
21 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/widget_kaobei_article_viewer.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
19 |
20 |
24 |
25 |
37 |
38 |
39 |
40 |
45 |
46 |
54 |
55 |
64 |
65 |
66 |
67 |
68 |
75 |
76 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/widget_user_viewer.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
19 |
24 |
25 |
33 |
34 |
37 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
61 |
62 |
63 |
71 |
72 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/navigation.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/navigation/mobile_navigation.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
17 |
18 |
19 |
25 |
28 |
29 |
30 |
36 |
39 |
40 |
41 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - Reply
5 | - Reply to all
6 |
7 |
8 |
9 | - reply
10 | - reply_all
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #121212
4 | #121212
5 | #00FF00
6 |
7 | #FAFAFA
8 | #121212
9 | #252525
10 | #454545
11 |
12 | #374CD1
13 | #FF4E47
14 | #00ACEE
15 | #21897e
16 |
17 | #FFFF00
18 | #536DFE
19 | #1C536DFE
20 | #E51331D8
21 | #E5D81337
22 |
23 | #E513D82D
24 | #E5D81337
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 | 300dp
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #121212
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Init Engineer
3 | 純靠北工程師
4 | 一、責任聲明:\n
5 | 本站使用者須對自己所張貼之每一篇文章負責,本站毋需對站內以及其他關聯之社群媒體的言論負擔起任何的責任,責任的歸屬權屬於各位發表人。\n
6 | \n
7 | 二、發表文章時之注意事項:\n
8 | 1. 尊重他人意見,注意用字遣詞與口氣,避免引起爭吵。\n
9 | 2. 避免在公眾區域,討論私人事務。\n
10 | 3. 避免發表文章於非相關區域,文章標題及內容不符合討論區之討論主題。\n
11 | 4. 禁止重複刊登相同內容或相同意義之留言。\n
12 | 5. 適度引用文章,避免引用過長文章,造成閱讀困擾。\n
13 | 6. 不適當的廣告、宣傳活動或商業性留言。\n
14 | 7. 禁止發表謾罵、脅迫、挑釁、猥褻或不雅之文字。\n
15 | 8. 禁止發表個人測試用文章或散播不實消息之文章,張貼文章,應自負相關法律責任。\n
16 | 9. 若有未規定的部份,由版主依主觀認定,視情況處理。\n
17 | \n
18 | 三、違規處理辦法:\n
19 | 違反上述規定之文章或作者,版主可刪除文章或行使禁貼之處份。\n
20 | \n
21 | 四、附註及補充說明:\n
22 | 1. 本站歡迎網友互相討論發表己見,唯請務必遵守上述規定。\n
23 | 2. 是否違反上述規定,由版主主觀認定,請謹慎用詞。\n
24 | 3. 請學習包容各種意見,如遇惡意批評或攻擊之文章,切勿加入爭執,並且善用檢舉,版主會有適當之處理,否則雙方皆依上述規定處理。
25 |
26 | 登入
27 | 設定
28 |
29 | 詳細內容
30 |
31 | 讀取資料失敗,請稍後再試
32 |
33 | 首頁 Index
34 | 文章列表 ArticleList
35 | 群眾審核 Review
36 | 儀錶板 Dashboard
37 | 發表文章 PublishArticle
38 |
39 | Facebook 主站
40 | Facebook 次站
41 | Plurk 主站
42 | Twitter 主站
43 | Platform 主站
44 |
45 | 分享
46 | 選擇字體
47 | 選擇主題
48 | Open Source License
49 |
50 | pref_app_version
51 | pref_app_versionCode
52 |
53 | pref_app_id_search
54 |
55 | openSource_key
56 | project_on_github_key
57 |
58 |
59 | Messages
60 | Sync
61 | ArticleActivityV2
62 |
63 | First Fragment
64 | Second Fragment
65 | Next
66 | Previous
67 |
68 | Hello first fragment
69 | Hello second fragment. Arg: %1$s
70 |
71 |
72 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
15 |
25 |
26 |
29 |
30 |
33 |
34 |
37 |
38 |
45 |
46 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/root_preferences.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
11 |
12 |
17 |
18 |
23 |
24 |
25 |
26 |
57 |
58 |
60 |
61 |
66 |
67 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/app/src/test/java/engineer/kaobei/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package engineer.kaobei
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.3.72'
5 | repositories {
6 | google()
7 | jcenter()
8 |
9 | }
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:4.0.2'
12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
13 |
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | }
17 | }
18 |
19 | allprojects {
20 | repositories {
21 | google()
22 | jcenter()
23 |
24 | }
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 | # Kotlin code style for this project: "official" or "obsolete":
21 | kotlin.code.style=official
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/init-engineer/init.engineer-Android-App/9e7f32108f3a7713ca67d1a6c6c06f54d427542e/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Mar 22 03:33:18 CST 2021
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name='init.engineer-Android-App'
2 | include ':app'
3 |
--------------------------------------------------------------------------------