├── .fvm
├── flutter_sdk
└── fvm_config.json
├── .github
└── workflows
│ └── publish_release.yml
├── .gitignore
├── .metadata
├── LICENSE
├── README.md
├── analysis_options.yaml
├── android
├── .gitignore
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── xycz
│ │ │ │ └── cnblogs
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── drawable-v21
│ │ │ └── launch_background.xml
│ │ │ ├── drawable
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-ldpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── playstore-icon.png
│ │ │ ├── values-en
│ │ │ └── strings.xml
│ │ │ ├── values-night
│ │ │ └── styles.xml
│ │ │ ├── values-zh
│ │ │ └── strings.xml
│ │ │ ├── values
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ │ └── xml
│ │ │ └── network_security_config.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── assets
├── images
│ └── logo.png
├── locales
│ ├── en.json
│ └── zh.json
├── lotties
│ ├── empty.json
│ ├── error.json
│ └── loadding.json
└── templates
│ ├── blog
│ ├── blog.html
│ ├── dark.css
│ ├── knowledge.html
│ └── light.css
│ ├── js
│ ├── common.js
│ └── highlight.js
│ └── news
│ ├── dark.css
│ ├── light.css
│ └── news.html
├── document
└── new_version.json
├── ios
├── .gitignore
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Podfile
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
└── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-App-1024x1024@1x.png
│ │ ├── Icon-App-20x20@1x.png
│ │ ├── Icon-App-20x20@2x.png
│ │ ├── Icon-App-20x20@3x.png
│ │ ├── Icon-App-29x29@1x.png
│ │ ├── Icon-App-29x29@2x.png
│ │ ├── Icon-App-29x29@3x.png
│ │ ├── Icon-App-40x40@1x.png
│ │ ├── Icon-App-40x40@2x.png
│ │ ├── Icon-App-40x40@3x.png
│ │ ├── Icon-App-60x60@2x.png
│ │ ├── Icon-App-60x60@3x.png
│ │ ├── Icon-App-76x76@1x.png
│ │ ├── Icon-App-76x76@2x.png
│ │ ├── Icon-App-83.5x83.5@2x.png
│ │ ├── icon-1024.png
│ │ ├── icon-20-ipad.png
│ │ ├── icon-20@2x-ipad.png
│ │ ├── icon-20@2x.png
│ │ ├── icon-20@3x.png
│ │ ├── icon-29-ipad.png
│ │ ├── icon-29.png
│ │ ├── icon-29@2x-ipad.png
│ │ ├── icon-29@2x.png
│ │ ├── icon-29@3x.png
│ │ ├── icon-40.png
│ │ ├── icon-40@2x.png
│ │ ├── icon-40@3x.png
│ │ ├── icon-60@2x.png
│ │ ├── icon-60@3x.png
│ │ ├── icon-76.png
│ │ ├── icon-76@2x.png
│ │ └── icon-83.5@2x.png
│ └── LaunchImage.imageset
│ │ ├── Contents.json
│ │ ├── LaunchImage.png
│ │ ├── LaunchImage@2x.png
│ │ ├── LaunchImage@3x.png
│ │ └── README.md
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ ├── Runner-Bridging-Header.h
│ ├── en.lproj
│ └── InfoPlist.strings
│ └── zh-Hans.lproj
│ ├── InfoPlist.strings
│ └── Main.strings
├── lib
├── app
│ ├── app_error.dart
│ ├── app_style.dart
│ ├── controller
│ │ ├── app_settings_controller.dart
│ │ ├── base_controller.dart
│ │ └── base_webview_controller.dart
│ ├── event_bus.dart
│ ├── log.dart
│ └── utils.dart
├── generated
│ └── locales.g.dart
├── main.dart
├── models
│ ├── blogs
│ │ ├── blog_comment_item_model.dart
│ │ ├── blog_content_model.dart
│ │ ├── blog_list_item_model.dart
│ │ ├── blog_list_item_v2_model.dart
│ │ ├── knowledge_list_item_model.dart
│ │ └── user_blog_info_model.dart
│ ├── news
│ │ ├── news_comment_item_model.dart
│ │ └── news_list_item_model.dart
│ ├── oauth
│ │ ├── token_model.dart
│ │ └── user_token_model.dart
│ ├── questions
│ │ ├── answer_comment_list_item_model.dart
│ │ ├── answer_list_item_model.dart
│ │ └── question_list_item_model.dart
│ ├── search
│ │ └── search_item_model.dart
│ ├── statuses
│ │ ├── statuses_comment_item_model.dart
│ │ └── statuses_list_item_model.dart
│ ├── user
│ │ ├── bookmark_list_item_model.dart
│ │ └── user_info_model.dart
│ └── version_model.dart
├── modules
│ ├── blogs
│ │ ├── comment
│ │ │ ├── blog_comment_controller.dart
│ │ │ └── blog_comment_page.dart
│ │ ├── content
│ │ │ ├── blog_content_controller.dart
│ │ │ └── blog_content_page.dart
│ │ ├── home
│ │ │ ├── blogs_home_controller.dart
│ │ │ ├── blogs_home_page.dart
│ │ │ ├── blogs_list_controller.dart
│ │ │ ├── blogs_list_view.dart
│ │ │ └── knowledge
│ │ │ │ ├── blogs_knowledge_controller.dart
│ │ │ │ └── blogs_knowledge_view.dart
│ │ └── knowledge_content
│ │ │ ├── knowledge_content_controller.dart
│ │ │ └── knowledge_content_page.dart
│ ├── indexed
│ │ ├── indexed_controller.dart
│ │ └── indexed_page.dart
│ ├── news
│ │ ├── comment
│ │ │ ├── news_comment_controller.dart
│ │ │ └── news_comment_page.dart
│ │ ├── content
│ │ │ ├── news_content_controller.dart
│ │ │ └── news_content_page.dart
│ │ └── home
│ │ │ ├── news_home_controller.dart
│ │ │ ├── news_home_page.dart
│ │ │ ├── news_list_controller.dart
│ │ │ └── news_list_view.dart
│ ├── other
│ │ ├── debug_log_page.dart
│ │ └── web_view
│ │ │ ├── web_view_controller.dart
│ │ │ └── web_view_page.dart
│ ├── questions
│ │ ├── comment
│ │ │ ├── answer_comment_controller.dart
│ │ │ └── answer_comment_page.dart
│ │ ├── detail
│ │ │ ├── question_detail_controller.dart
│ │ │ └── question_detail_page.dart
│ │ └── home
│ │ │ ├── questions_home_controller.dart
│ │ │ ├── questions_home_page.dart
│ │ │ ├── questions_list_controller.dart
│ │ │ └── questions_list_view.dart
│ ├── search
│ │ ├── search_controller.dart
│ │ ├── search_list_view.dart
│ │ ├── search_list_view_controlelr.dart
│ │ └── search_page.dart
│ ├── statuses
│ │ ├── detail
│ │ │ ├── statuses_detail_controller.dart
│ │ │ └── statuses_detail_page.dart
│ │ └── home
│ │ │ ├── statuses_home_controller.dart
│ │ │ ├── statuses_home_page.dart
│ │ │ ├── statuses_list_controller.dart
│ │ │ └── statuses_list_view.dart
│ └── user
│ │ ├── blogs
│ │ ├── user_blogs_controller.dart
│ │ └── user_blogs_page.dart
│ │ ├── bookmark
│ │ ├── bookmark_controller.dart
│ │ └── bookmark_page.dart
│ │ ├── home
│ │ ├── user_home_controller.dart
│ │ └── user_home_page.dart
│ │ └── login
│ │ ├── login_controller.dart
│ │ └── login_page.dart
├── requests
│ ├── base
│ │ ├── api.dart
│ │ ├── app_log_interceptor.dart
│ │ ├── http_client.dart
│ │ └── oauth_interceptor.dart
│ ├── blogs_request.dart
│ ├── common_request.dart
│ ├── news_request.dart
│ ├── oauth_request.dart
│ ├── questions_request.dart
│ ├── search_request.dart
│ ├── statuses_request.dart
│ └── user_request.dart
├── routes
│ ├── app_navigation.dart
│ ├── app_pages.dart
│ └── route_path.dart
├── services
│ ├── api_service.dart
│ ├── local_storage_service.dart
│ └── user_service.dart
└── widgets
│ ├── custom_html.dart
│ ├── items
│ ├── answer_comment_item_widget.dart
│ ├── blog_comment_item_widget.dart
│ ├── blog_item_widget.dart
│ ├── knowledge_item_widget.dart
│ ├── news_comment_item_widget.dart
│ ├── news_item_widget.dart
│ ├── question_item_widget.dart
│ ├── statuses_comment_item_widget.dart
│ └── statuses_item_widget.dart
│ ├── keep_alive_wrapper.dart
│ ├── net_image.dart
│ ├── number_step_dialog.dart
│ ├── page_list_view.dart
│ ├── rectangular_indicator.dart
│ ├── status
│ ├── app_empty_widget.dart
│ ├── app_error_widget.dart
│ ├── app_loadding_widget.dart
│ └── app_not_login_widget.dart
│ └── statuses_content.dart
├── pubspec.yaml
├── screenshot
├── screenshot_dark.jpg
└── screenshot_light.jpg
└── test
└── widget_test.dart
/.fvm/flutter_sdk:
--------------------------------------------------------------------------------
1 | C:/Users/DW-SVN-SERVER/fvm/versions/3.13.9
--------------------------------------------------------------------------------
/.fvm/fvm_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "flutterSdkVersion": "3.13.9",
3 | "flavors": {}
4 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | migrate_working_dir/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # The .vscode folder contains launch configuration and tasks you configure in
20 | # VS Code which you may wish to be included in version control, so this line
21 | # is commented out by default.
22 | #.vscode/
23 |
24 | # Flutter/Dart/Pub related
25 | **/doc/api/
26 | **/ios/Flutter/.last_build_id
27 | .dart_tool/
28 | .flutter-plugins
29 | .flutter-plugins-dependencies
30 | .packages
31 | .pub-cache/
32 | .pub/
33 | /build/
34 |
35 | # Symbolication related
36 | app.*.symbols
37 |
38 | # Obfuscation related
39 | app.*.map.json
40 |
41 | # Android Studio will place build artifacts here
42 | /android/app/debug
43 | /android/app/profile
44 | /android/app/release
45 |
46 | *.env
47 |
48 | pubspec.lock
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled.
5 |
6 | version:
7 | revision: d9111f64021372856901a1fd5bfbc386cade3318
8 | channel: stable
9 |
10 | project_type: app
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: d9111f64021372856901a1fd5bfbc386cade3318
17 | base_revision: d9111f64021372856901a1fd5bfbc386cade3318
18 | - platform: android
19 | create_revision: d9111f64021372856901a1fd5bfbc386cade3318
20 | base_revision: d9111f64021372856901a1fd5bfbc386cade3318
21 | - platform: ios
22 | create_revision: d9111f64021372856901a1fd5bfbc386cade3318
23 | base_revision: d9111f64021372856901a1fd5bfbc386cade3318
24 | - platform: linux
25 | create_revision: d9111f64021372856901a1fd5bfbc386cade3318
26 | base_revision: d9111f64021372856901a1fd5bfbc386cade3318
27 | - platform: macos
28 | create_revision: d9111f64021372856901a1fd5bfbc386cade3318
29 | base_revision: d9111f64021372856901a1fd5bfbc386cade3318
30 | - platform: web
31 | create_revision: d9111f64021372856901a1fd5bfbc386cade3318
32 | base_revision: d9111f64021372856901a1fd5bfbc386cade3318
33 | - platform: windows
34 | create_revision: d9111f64021372856901a1fd5bfbc386cade3318
35 | base_revision: d9111f64021372856901a1fd5bfbc386cade3318
36 |
37 | # User provided section
38 |
39 | # List of Local paths (relative to this file) that should be
40 | # ignored by the migrate tool.
41 | #
42 | # Files that are not part of the templates will be ignored by default.
43 | unmanaged_files:
44 | - 'lib/main.dart'
45 | - 'ios/Runner.xcodeproj/project.pbxproj'
46 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 xiaoyaocz
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 博客园Flutter
2 |
3 | 使用Flutter编写的博客园客户端,支持iOS及Android。
4 |
5 | 基于[博客园开放API](https://api.cnblogs.com/help)开发;受限于API,部分功能可能并不完善。
6 |
7 | 
8 |
9 | 
10 |
11 | ## 安装
12 |
13 | - Android:
14 | 1. 前往[Releases](https://github.com/xiaoyaocz/flutter_cnblogs/releases/latest)下载app-release.apk安装即可
15 | - iOS:
16 | 1. 前往[Releases](https://github.com/xiaoyaocz/flutter_cnblogs/releases/latest)下载ios_no_sign.ipa
17 | 2. 使用Sideloadly、iTools等工具自行签名安装
18 |
19 | ## 开发
20 |
21 | ## 环境
22 |
23 | Flutter:3.13.9
24 |
25 | ### 说明
26 |
27 | 开发前请先[申请博客园API KEY](https://oauth.cnblogs.com/),在根目录创建`.env`文件并写入以下内容
28 |
29 | ```
30 | CLIENT_ID=【申请的CLIENT_ID】
31 | CLIENT_SECRET=【申请的CLIENT_SECRET】
32 | ```
33 |
34 | ### 框架
35 |
36 | - `GetX` 状态管理、路由管理、国际化
37 | - `Dio` 网络请求
38 | - `Hive` 数据存储
39 |
40 | ### 目录结构
41 |
42 | - `app` 一些通用的类及样式
43 | - `services` 提供数据存储等服务
44 | - `requests` 请求的封装
45 | - `generated` 生成的国际化文件,使用 `get generate locales`生成
46 | - `modules` 模块,每个会有两个文件,view及controller
47 | - `widgets` 自定义的小组件
48 | - `routes` 路由定义
49 | - `models` 实体类
50 |
51 | ## TODO
52 |
53 | - 博客
54 | - [ ] 检查博文收藏状态(API似乎有问题)
55 | - 博问
56 | - [ ] 删除回答
57 | - [ ] 修改回答
58 | - [ ] 提问
59 | - [ ] 回答
60 | - [ ] 删除评论
61 | - [ ] 更新评论
62 |
63 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # This file configures the analyzer, which statically analyzes Dart code to
2 | # check for errors, warnings, and lints.
3 | #
4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled
5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
6 | # invoked from the command line by running `flutter analyze`.
7 |
8 | # The following line activates a set of recommended lints for Flutter apps,
9 | # packages, and plugins designed to encourage good coding practices.
10 | include: package:flutter_lints/flutter.yaml
11 |
12 | linter:
13 | # The lint rules applied to this project can be customized in the
14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml`
15 | # included above or to enable additional rules. A list of all available lints
16 | # and their documentation is published at
17 | # https://dart-lang.github.io/linter/lints/index.html.
18 | #
19 | # Instead of disabling a lint rule for the entire project in the
20 | # section below, it can also be suppressed for a single line of code
21 | # or a specific dart file by using the `// ignore: name_of_lint` and
22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file
23 | # producing the lint.
24 | rules:
25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule
26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
27 |
28 | # Additional information about this file can be found at
29 | # https://dart.dev/guides/language/analysis-options
30 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 | def keystoreProperties = new Properties()
29 | def keystorePropertiesFile = rootProject.file('key.properties')
30 | if (keystorePropertiesFile.exists()) {
31 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
32 | }
33 |
34 | android {
35 | compileSdkVersion 33
36 | ndkVersion flutter.ndkVersion
37 |
38 | compileOptions {
39 | sourceCompatibility JavaVersion.VERSION_1_8
40 | targetCompatibility JavaVersion.VERSION_1_8
41 | }
42 |
43 | kotlinOptions {
44 | jvmTarget = '1.8'
45 | }
46 |
47 | sourceSets {
48 | main.java.srcDirs += 'src/main/kotlin'
49 | }
50 |
51 | defaultConfig {
52 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
53 | applicationId "com.xycz.cnblogs"
54 | // You can update the following values to match your application needs.
55 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
56 | minSdkVersion 21
57 | targetSdkVersion flutter.targetSdkVersion
58 | versionCode flutterVersionCode.toInteger()
59 | versionName flutterVersionName
60 | }
61 | signingConfigs {
62 | release {
63 | keyAlias keystoreProperties['keyAlias']
64 | keyPassword keystoreProperties['keyPassword']
65 | storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
66 | storePassword keystoreProperties['storePassword']
67 | }
68 | }
69 | buildTypes {
70 | debug {
71 | signingConfig signingConfigs.release
72 | }
73 | profile {
74 | signingConfig signingConfigs.release
75 | }
76 | release {
77 | signingConfig signingConfigs.release
78 | }
79 | }
80 | }
81 |
82 | flutter {
83 | source '../..'
84 | }
85 |
86 | dependencies {
87 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
88 | }
89 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
13 |
21 |
25 |
29 |
30 |
31 |
32 |
33 |
34 |
36 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/xycz/cnblogs/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.xycz.cnblogs
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/android/app/src/main/res/mipmap-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/playstore-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/android/app/src/main/res/playstore-icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values-en/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Cnblogs
3 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values-zh/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | 博客园
3 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Cnblogs
3 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/xml/network_security_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.7.10'
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:7.2.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | mavenCentral()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | tasks.register("clean", Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
6 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/assets/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/assets/images/logo.png
--------------------------------------------------------------------------------
/assets/templates/blog/blog.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
12 |
15 |
16 |
17 |
18 |
28 |
29 |
30 | @content
31 |
32 |
33 |
@stat
34 |
@puttime
35 |
36 |
37 |
40 |
41 |
--------------------------------------------------------------------------------
/assets/templates/blog/knowledge.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
12 |
24 |
25 |
26 |
27 |
34 |
35 |
36 | @content
37 |
38 |
39 |
@stat
40 |
@puttime
41 |
42 |
43 |
46 |
47 |
--------------------------------------------------------------------------------
/assets/templates/js/common.js:
--------------------------------------------------------------------------------
1 | window.onload = function () {
2 | initImageClickEvent();
3 | initHighlightCode();
4 | }
5 |
6 | // 初始化代码高亮
7 | function initHighlightCode() {
8 | try {
9 | //转换其他的高亮代码至hljs
10 | var elementList = document.getElementsByClassName("cnblogs_Highlighter");
11 | for (let i = 0; i < elementList.length; i++) {
12 | const element = elementList[i];
13 | var code = element.getElementsByTagName("pre")[0].innerHTML;
14 | element.getElementsByTagName("pre")[0].innerHTML = '' + code + '
';
15 | }
16 | } catch (e) {
17 | console.log("无法转换cnblogs_Highlighter:" + e)
18 | }
19 | hljs.highlightAll();
20 | }
21 |
22 | var allImgs = [];
23 | // 添加图片点击事件
24 | function initImageClickEvent() {
25 | allImgs = [];
26 | var elementList = document.getElementsByClassName("content")[0].getElementsByTagName("img");
27 | for (let i = 0; i < elementList.length; i++) {
28 | const element = elementList[i];
29 | //跳过计数器
30 | if (element.src.indexOf("counter.cnblogs.com") != -1) {
31 | continue;
32 | }
33 | allImgs.push(element.src);
34 | element.onclick = function (e) {
35 | openImage(e.target.src)
36 | }
37 | }
38 | }
39 | // 打开作者主页
40 | function openAuthor() {
41 | window.flutter_inappwebview.callHandler('showAuthor');
42 | }
43 | // 打开图片浏览
44 | function openImage(src) {
45 | window.flutter_inappwebview.callHandler('showImage', src, allImgs);
46 | }
--------------------------------------------------------------------------------
/assets/templates/news/news.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
15 |
16 |
17 |
18 |
24 |
25 |
26 | @content
27 |
28 |
29 |
@stat
30 |
@puttime
31 |
32 |
33 |
36 |
37 |
--------------------------------------------------------------------------------
/document/new_version.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.0.8",
3 | "version_num": 10008,
4 | "version_desc": "1. 支持查看新闻评论\n2. 修复APP标题显示错误 #4",
5 | "download_url": "https://github.com/xiaoyaocz/flutter_cnblogs/releases"
6 | }
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | **/dgph
2 | *.mode1v3
3 | *.mode2v3
4 | *.moved-aside
5 | *.pbxuser
6 | *.perspectivev3
7 | **/*sync/
8 | .sconsign.dblite
9 | .tags*
10 | **/.vagrant/
11 | **/DerivedData/
12 | Icon?
13 | **/Pods/
14 | **/.symlinks/
15 | profile
16 | xcuserdata
17 | **/.generated/
18 | Flutter/App.framework
19 | Flutter/Flutter.framework
20 | Flutter/Flutter.podspec
21 | Flutter/Generated.xcconfig
22 | Flutter/ephemeral/
23 | Flutter/app.flx
24 | Flutter/app.zip
25 | Flutter/flutter_assets/
26 | Flutter/flutter_export_environment.sh
27 | ServiceDefinitions.json
28 | Runner/GeneratedPluginRegistrant.*
29 |
30 | # Exceptions to above rules.
31 | !default.mode1v3
32 | !default.mode2v3
33 | !default.pbxuser
34 | !default.perspectivev3
35 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 11.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | #platform :ios, '11.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | use_frameworks!
32 | use_modular_headers!
33 |
34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
35 | end
36 |
37 | post_install do |installer|
38 | installer.pods_project.targets.each do |target|
39 | flutter_additional_ios_build_settings(target)
40 | target.build_configurations.each do |config|
41 | config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
42 | '$(inherited)',
43 |
44 | ## dart: PermissionGroup.calendar
45 | # 'PERMISSION_EVENTS=1',
46 |
47 | ## dart: PermissionGroup.reminders
48 | # 'PERMISSION_REMINDERS=1',
49 |
50 | ## dart: PermissionGroup.contacts
51 | # 'PERMISSION_CONTACTS=1',
52 |
53 | ## dart: PermissionGroup.camera
54 | 'PERMISSION_CAMERA=1',
55 |
56 | ## dart: PermissionGroup.microphone
57 | # 'PERMISSION_MICROPHONE=1',
58 |
59 | ## dart: PermissionGroup.speech
60 | # 'PERMISSION_SPEECH_RECOGNIZER=1',
61 |
62 | ## dart: PermissionGroup.photos
63 | 'PERMISSION_PHOTOS=1',
64 |
65 | ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse]
66 | 'PERMISSION_LOCATION=1',
67 |
68 | ## dart: PermissionGroup.notification
69 | 'PERMISSION_NOTIFICATIONS=1',
70 |
71 | ## dart: PermissionGroup.mediaLibrary
72 | # 'PERMISSION_MEDIA_LIBRARY=1',
73 |
74 | ## dart: PermissionGroup.sensors
75 | # 'PERMISSION_SENSORS=1',
76 |
77 | ## dart: PermissionGroup.bluetooth
78 | # 'PERMISSION_BLUETOOTH=1',
79 |
80 | ## dart: PermissionGroup.appTrackingTransparency
81 | # 'PERMISSION_APP_TRACKING_TRANSPARENCY=1',
82 |
83 | ## dart: PermissionGroup.criticalAlerts
84 | # 'PERMISSION_CRITICAL_ALERTS=1'
85 | ]
86 |
87 | end
88 | end
89 | end
90 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-1024.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoyaocz/flutter_cnblogs/4d75b3d94c7613af07266254255fc6d957e397a2/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
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 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
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 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | Cnblogs
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | flutter_cnblogs
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(FLUTTER_BUILD_NUMBER)
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 | UIViewControllerBasedStatusBarAppearance
45 |
46 | CADisableMinimumFrameDurationOnPhone
47 |
48 | UIApplicationSupportsIndirectInputEvents
49 |
50 | NSAppTransportSecurity
51 |
52 | NSAllowsArbitraryLoads
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/ios/Runner/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /*
2 | InfoPlist.strings
3 | Runner
4 |
5 | Created by xiaoyaocz on 2022/12/12.
6 |
7 | */
8 | "CFBundleDisplayName" = "Cnblogs";
9 | "NSCameraUsageDescription" = "This app needs camera access to scan QR codes";
10 | "NSPhotoLibraryUsageDescription" = "Save pictures to your album";
--------------------------------------------------------------------------------
/ios/Runner/zh-Hans.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /*
2 | InfoPlist.strings
3 | Runner
4 |
5 | Created by xiaoyaocz on 2022/12/12.
6 |
7 | */
8 | "CFBundleDisplayName" = "博客园";
9 | "NSCameraUsageDescription" = "需要使用摄像头扫描二维码";
10 | "NSPhotoLibraryUsageDescription" = "保存图片至你的相册";
--------------------------------------------------------------------------------
/ios/Runner/zh-Hans.lproj/Main.strings:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/lib/app/app_error.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_cnblogs/generated/locales.g.dart';
2 | import 'package:get/get.dart';
3 |
4 | class AppError extends Error {
5 | /// 错误码
6 | final int code;
7 |
8 | /// 错误信息
9 | final String message;
10 |
11 | /// 是否是Http请求错误
12 | final bool isHttpError;
13 |
14 | final bool notLogin;
15 |
16 | AppError(
17 | this.message, {
18 | this.code = 0,
19 | this.isHttpError = false,
20 | this.notLogin = false,
21 | });
22 | @override
23 | String toString() {
24 | if (isHttpError && message.isEmpty) {
25 | return statusCodeToString(code);
26 | }
27 |
28 | return message;
29 | }
30 |
31 | String statusCodeToString(int statusCode) {
32 | switch (statusCode) {
33 | case 400:
34 | return LocaleKeys.network_status_400.tr;
35 | case 401:
36 | return LocaleKeys.network_status_401.tr;
37 | case 403:
38 | return LocaleKeys.network_status_403.tr;
39 | case 404:
40 | return LocaleKeys.network_status_404.tr;
41 | case 500:
42 | return LocaleKeys.network_status_500.tr;
43 | case 502:
44 | return LocaleKeys.network_status_502.tr;
45 | case 503:
46 | return LocaleKeys.network_status_503.tr;
47 | default:
48 | return "${LocaleKeys.network_status_request_error.tr}($statusCode)";
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/lib/app/controller/base_webview_controller.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:flutter_cnblogs/app/controller/base_controller.dart';
4 | import 'package:flutter_cnblogs/app/log.dart';
5 | import 'package:flutter_cnblogs/app/utils.dart';
6 | import 'package:flutter_cnblogs/routes/app_navigation.dart';
7 | import 'package:flutter_inappwebview/flutter_inappwebview.dart';
8 |
9 | class BaseWebViewController extends BaseController {
10 | final UniqueKey webViewkey = UniqueKey();
11 | late InAppWebViewController? webViewController;
12 | final InAppWebViewGroupOptions webViewGroupOptions = InAppWebViewGroupOptions(
13 | crossPlatform: InAppWebViewOptions(
14 | transparentBackground: true,
15 | useShouldOverrideUrlLoading: true,
16 | ),
17 | );
18 | void onWebViewCreated(InAppWebViewController controller) {
19 | webViewController = controller;
20 | webViewController?.addJavaScriptHandler(
21 | handlerName: 'showImage',
22 | callback: (args) {
23 | openImageViewer(
24 | args[0].toString(),
25 | (args[1] as List).map((e) => e as String).toList(),
26 | );
27 | },
28 | );
29 | webViewController?.addJavaScriptHandler(
30 | handlerName: 'showAuthor',
31 | callback: (args) {
32 | openUserBlogs();
33 | },
34 | );
35 | }
36 |
37 | final RegExp blogRegExp1 = RegExp(r'cnblogs.com/(.*?)/p/(.*?).html');
38 | final RegExp blogRegExp2 =
39 | RegExp(r'cnblogs.com/(.*?)/archive/\d+/\d+/\d+/(.*?).html');
40 | Future shouldOverrideUrlLoading(
41 | InAppWebViewController controller, NavigationAction action) async {
42 | var uri = action.request.url!;
43 | var url = uri.toString();
44 | if (url.startsWith("about:blank")) {
45 | return NavigationActionPolicy.ALLOW;
46 | }
47 | if (blogRegExp1.hasMatch(url)) {
48 | AppNavigator.toBlogContent(url: url);
49 | return NavigationActionPolicy.CANCEL;
50 | }
51 |
52 | var match2 = blogRegExp2.firstMatch(url);
53 | if (match2 != null) {
54 | String blogApp = match2.group(1)!;
55 | String blogPostId = match2.group(2)!;
56 | AppNavigator.toBlogContent(
57 | url: "http://www.cnblogs.com/$blogApp/p/$blogPostId.html");
58 | return NavigationActionPolicy.CANCEL;
59 | }
60 |
61 | Log.i(uri.toString());
62 | //使用WebView打开
63 | // launchUrl(uri, mode: LaunchMode.inAppWebView);
64 | AppNavigator.toWebView(url);
65 | return NavigationActionPolicy.CANCEL;
66 | }
67 |
68 | void openImageViewer(String img, List allImgs) {
69 | Utils.showImageViewer(allImgs.indexOf(img), allImgs);
70 | }
71 |
72 | Future getHighlightScript() async {
73 | return await rootBundle.loadString('assets/templates/js/highlight.js');
74 | }
75 |
76 | Future getCommonScript() async {
77 | return await rootBundle.loadString('assets/templates/js/common.js');
78 | }
79 |
80 | void openUserBlogs() {}
81 | }
82 |
--------------------------------------------------------------------------------
/lib/app/event_bus.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter_cnblogs/app/log.dart';
4 |
5 | /// 全局事件
6 | class EventBus {
7 | /// 登录
8 | static const String kLogined = "Logined";
9 |
10 | /// 注销登录
11 | static const String kLogouted = "Logouted";
12 |
13 | /// 点击了底部导航
14 | static const String kBottomNavigationBarClicked =
15 | "BottomNavigationBarClicked";
16 |
17 | static EventBus? _instance;
18 |
19 | static EventBus get instance {
20 | _instance ??= EventBus();
21 | return _instance!;
22 | }
23 |
24 | final Map _streams = {};
25 |
26 | /// 触发事件
27 | void emit(String name, T data) {
28 | if (!_streams.containsKey(name)) {
29 | _streams.addAll({name: StreamController.broadcast()});
30 | }
31 | Log.d("Emit Event:$name\r\n$data");
32 |
33 | _streams[name]!.add(data);
34 | }
35 |
36 | /// 监听事件
37 | StreamSubscription listen(String name, Function(dynamic)? onData) {
38 | if (!_streams.containsKey(name)) {
39 | _streams.addAll({name: StreamController.broadcast()});
40 | }
41 | return _streams[name]!.stream.listen(onData);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/app/log.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:get/get.dart';
4 | import 'package:logger/logger.dart';
5 |
6 | class Log {
7 | static RxList debugLogs = [].obs;
8 |
9 | static void addDebugLog(String content, Color? color) {
10 | if (kReleaseMode) {
11 | return;
12 | }
13 | if (content.contains("请求响应")) {
14 | content = content.split("\n").join('\n💡 ');
15 | }
16 | try {
17 | debugLogs.insert(0, DebugLogModel(DateTime.now(), content, color: color));
18 | } catch (e) {
19 | if (kDebugMode) {
20 | print(e);
21 | }
22 | }
23 | }
24 |
25 | static Logger logger = Logger(
26 | printer: PrettyPrinter(
27 | methodCount: 0,
28 | errorMethodCount: 8,
29 | lineLength: 120,
30 | colors: true,
31 | printEmojis: true,
32 | printTime: false,
33 | ),
34 | );
35 |
36 | static void d(String message) {
37 | addDebugLog(message, Colors.orange);
38 | logger.d("${DateTime.now().toString()}\n$message");
39 | }
40 |
41 | static void i(String message) {
42 | addDebugLog(message, Colors.blue);
43 | logger.i("${DateTime.now().toString()}\n$message");
44 | }
45 |
46 | static void e(String message, StackTrace stackTrace) {
47 | addDebugLog('$message\r\n\r\n$stackTrace', Colors.red);
48 | logger.e("${DateTime.now().toString()}\n$message", stackTrace: stackTrace);
49 | }
50 |
51 | static void w(String message) {
52 | addDebugLog(message, Colors.pink);
53 | logger.w("${DateTime.now().toString()}\n$message");
54 | }
55 |
56 | static void logPrint(dynamic obj) {
57 | addDebugLog(obj.toString(), Colors.red);
58 | if (obj is Error) {
59 | Log.e(obj.toString(), obj.stackTrace ?? StackTrace.current);
60 | } else if (kDebugMode) {
61 | print(obj);
62 | }
63 | }
64 | }
65 |
66 | class DebugLogModel {
67 | final String content;
68 | final DateTime datetime;
69 | final Color? color;
70 | DebugLogModel(this.datetime, this.content, {this.color});
71 | }
72 |
--------------------------------------------------------------------------------
/lib/models/blogs/blog_comment_item_model.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | T? asT(dynamic value) {
4 | if (value is T) {
5 | return value;
6 | }
7 | return null;
8 | }
9 |
10 | class BlogCommentItemModel {
11 | BlogCommentItemModel({
12 | required this.id,
13 | required this.body,
14 | required this.author,
15 | required this.authorUrl,
16 | required this.faceUrl,
17 | required this.floor,
18 | required this.dateAdded,
19 | });
20 |
21 | factory BlogCommentItemModel.fromJson(Map json) =>
22 | BlogCommentItemModel(
23 | id: asT(json['Id']) ?? 0,
24 | body: asT(json['Body']) ?? "",
25 | author: asT(json['Author']) ?? "",
26 | authorUrl: asT(json['AuthorUrl']) ?? "",
27 | faceUrl: asT(json['FaceUrl']) ?? "",
28 | floor: asT(json['Floor']) ?? 0,
29 | dateAdded: asT(json['DateAdded']) ?? "",
30 | );
31 |
32 | int id;
33 | String body;
34 | String author;
35 | String authorUrl;
36 | String faceUrl;
37 | int floor;
38 | String dateAdded;
39 | DateTime? get postDateTime => DateTime.tryParse(dateAdded);
40 |
41 | @override
42 | String toString() {
43 | return jsonEncode(this);
44 | }
45 |
46 | Map toJson() => {
47 | 'Id': id,
48 | 'Body': body,
49 | 'Author': author,
50 | 'AuthorUrl': authorUrl,
51 | 'FaceUrl': faceUrl,
52 | 'Floor': floor,
53 | 'DateAdded': dateAdded,
54 | };
55 | }
56 |
--------------------------------------------------------------------------------
/lib/models/blogs/blog_content_model.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | T? asT(dynamic value) {
4 | if (value is T) {
5 | return value;
6 | }
7 | return null;
8 | }
9 |
10 | class BlogContentModel {
11 | BlogContentModel({
12 | required this.id,
13 | required this.title,
14 | required this.url,
15 | required this.description,
16 | required this.viewCount,
17 | required this.diggCount,
18 | required this.commentCount,
19 | required this.author,
20 | required this.avatar,
21 | required this.blogId,
22 | required this.blogApp,
23 | required this.dateAdded,
24 | required this.dateUpdated,
25 | required this.body,
26 | this.tags,
27 | this.categories,
28 | });
29 |
30 | factory BlogContentModel.fromJson(Map json) {
31 | final List? tags = json['tags'] is List ? [] : null;
32 | if (tags != null) {
33 | for (final dynamic item in json['tags']!) {
34 | if (item != null) {
35 | tags.add(asT(item)!);
36 | }
37 | }
38 | }
39 |
40 | final List? categories =
41 | json['categories'] is List ? [] : null;
42 | if (categories != null) {
43 | for (final dynamic item in json['categories']!) {
44 | if (item != null) {
45 | categories.add(asT(item)!);
46 | }
47 | }
48 | }
49 | return BlogContentModel(
50 | id: asT(json['id'])!,
51 | title: asT(json['title']) ?? "",
52 | url: asT(json['url']) ?? "",
53 | description: asT(json['description']) ?? "",
54 | viewCount: asT(json['viewCount'])!,
55 | diggCount: asT(json['diggCount'])!,
56 | commentCount: asT(json['commentCount'])!,
57 | author: asT(json['author']) ?? "",
58 | avatar: asT(json['avatar']) ?? "",
59 | blogId: asT(json['blogId'])!,
60 | blogApp: asT(json['blogApp']) ?? "",
61 | dateAdded: asT(json['dateAdded']) ?? "",
62 | dateUpdated: asT(json['dateUpdated']) ?? "",
63 | body: asT(json['body']) ?? "",
64 | tags: tags,
65 | categories: categories,
66 | );
67 | }
68 |
69 | int id;
70 | String title;
71 | String url;
72 | String description;
73 | int viewCount;
74 | int diggCount;
75 | int commentCount;
76 | String author;
77 | String avatar;
78 | int blogId;
79 | String blogApp;
80 | String dateAdded;
81 | String dateUpdated;
82 | String body;
83 | List? tags;
84 | List? categories;
85 | DateTime get postDateTime => DateTime.parse(dateUpdated);
86 |
87 | @override
88 | String toString() {
89 | return jsonEncode(this);
90 | }
91 |
92 | Map toJson() => {
93 | 'id': id,
94 | 'title': title,
95 | 'url': url,
96 | 'description': description,
97 | 'viewCount': viewCount,
98 | 'diggCount': diggCount,
99 | 'commentCount': commentCount,
100 | 'author': author,
101 | 'avatar': avatar,
102 | 'blogId': blogId,
103 | 'blogApp': blogApp,
104 | 'dateAdded': dateAdded,
105 | 'dateUpdated': dateUpdated,
106 | 'body': body,
107 | 'tags': tags,
108 | 'categories': categories,
109 | };
110 | }
111 |
--------------------------------------------------------------------------------
/lib/models/blogs/blog_list_item_model.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | T? asT(dynamic value) {
4 | if (value is T) {
5 | return value;
6 | }
7 | return null;
8 | }
9 |
10 | class BlogListItemModel {
11 | BlogListItemModel({
12 | required this.id,
13 | required this.title,
14 | required this.url,
15 | required this.description,
16 | required this.author,
17 | required this.blogapp,
18 | required this.avatar,
19 | required this.postdate,
20 | required this.viewcount,
21 | required this.commentcount,
22 | required this.diggcount,
23 | });
24 |
25 | factory BlogListItemModel.fromJson(Map json) =>
26 | BlogListItemModel(
27 | id: asT(json['Id']) ?? 0,
28 | title: asT(json['Title']) ?? "",
29 | url: asT(json['Url']) ?? "",
30 | description: asT(json['Description']) ?? "",
31 | author: asT(json['Author']) ?? "",
32 | blogapp: asT(json['BlogApp']) ?? "",
33 | avatar: asT(json['Avatar']) ?? "",
34 | postdate: asT(json['PostDate']) ?? "",
35 | viewcount: asT(json['ViewCount']) ?? 0,
36 | commentcount: asT(json['CommentCount']) ?? 0,
37 | diggcount: asT(json['DiggCount']) ?? 0,
38 | );
39 |
40 | int id;
41 | String title;
42 | String url;
43 | String description;
44 | String author;
45 | String blogapp;
46 | String avatar;
47 | String postdate;
48 | DateTime get postDateTime => DateTime.parse(postdate);
49 | int viewcount;
50 | int commentcount;
51 | int diggcount;
52 |
53 | @override
54 | String toString() {
55 | return jsonEncode(this);
56 | }
57 |
58 | Map toJson() => {
59 | 'Id': id,
60 | 'Title': title,
61 | 'Url': url,
62 | 'Description': description,
63 | 'Author': author,
64 | 'BlogApp': blogapp,
65 | 'Avatar': avatar,
66 | 'PostDate': postdate,
67 | 'ViewCount': viewcount,
68 | 'CommentCount': commentcount,
69 | 'DiggCount': diggcount,
70 | };
71 | }
72 |
--------------------------------------------------------------------------------
/lib/models/blogs/blog_list_item_v2_model.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | T? asT(dynamic value) {
4 | if (value is T) {
5 | return value;
6 | }
7 | return null;
8 | }
9 |
10 | class BlogListItemV2Model {
11 | BlogListItemV2Model({
12 | required this.id,
13 | required this.title,
14 | required this.url,
15 | required this.description,
16 | required this.viewCount,
17 | required this.diggCount,
18 | required this.commentCount,
19 | required this.author,
20 | required this.blogId,
21 | required this.blogUrl,
22 | required this.avatar,
23 | required this.postType,
24 | required this.postConfig,
25 | required this.dateAdded,
26 | required this.dateUpdated,
27 | this.entryName,
28 | });
29 |
30 | factory BlogListItemV2Model.fromJson(Map json) =>
31 | BlogListItemV2Model(
32 | id: asT(json['id'])!,
33 | title: asT(json['title'])!,
34 | url: asT(json['url'])!,
35 | description: asT(json['description'])!,
36 | viewCount: asT(json['viewCount'])!,
37 | diggCount: asT(json['diggCount'])!,
38 | commentCount: asT(json['commentCount'])!,
39 | author: asT(json['author'])!,
40 | blogId: asT(json['blogId'])!,
41 | blogUrl: asT(json['blogUrl'])!,
42 | avatar: asT(json['avatar']) ?? "",
43 | postType: asT(json['postType'])!,
44 | postConfig: asT(json['postConfig'])!,
45 | dateAdded: asT(json['dateAdded'])!,
46 | dateUpdated: asT(json['dateUpdated'])!,
47 | entryName: asT(json['entryName']),
48 | );
49 |
50 | int id;
51 | String title;
52 | String url;
53 | String description;
54 | int viewCount;
55 | int diggCount;
56 | int commentCount;
57 | String author;
58 | int blogId;
59 | String blogUrl;
60 | String avatar;
61 | int postType;
62 | int postConfig;
63 | String dateAdded;
64 | String dateUpdated;
65 | String? entryName;
66 |
67 | @override
68 | String toString() {
69 | return jsonEncode(this);
70 | }
71 |
72 | Map toJson() => {
73 | 'id': id,
74 | 'title': title,
75 | 'url': url,
76 | 'description': description,
77 | 'viewCount': viewCount,
78 | 'diggCount': diggCount,
79 | 'commentCount': commentCount,
80 | 'author': author,
81 | 'blogId': blogId,
82 | 'blogUrl': blogUrl,
83 | 'avatar': avatar,
84 | 'postType': postType,
85 | 'postConfig': postConfig,
86 | 'dateAdded': dateAdded,
87 | 'dateUpdated': dateUpdated,
88 | 'entryName': entryName,
89 | };
90 | }
91 |
--------------------------------------------------------------------------------
/lib/models/blogs/knowledge_list_item_model.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | T? asT(dynamic value) {
4 | if (value is T) {
5 | return value;
6 | }
7 | return null;
8 | }
9 |
10 | class KnowledgeListItemModel {
11 | KnowledgeListItemModel({
12 | required this.id,
13 | required this.title,
14 | required this.summary,
15 | required this.author,
16 | required this.viewcount,
17 | required this.diggcount,
18 | required this.dateadded,
19 | });
20 |
21 | factory KnowledgeListItemModel.fromJson(Map json) =>
22 | KnowledgeListItemModel(
23 | id: asT(json['Id'])!,
24 | title: asT(json['Title'])!,
25 | summary: asT(json['Summary'])!,
26 | author: asT(json['Author']) ?? "",
27 | viewcount: asT(json['ViewCount'])!,
28 | diggcount: asT(json['DiggCount'])!,
29 | dateadded: asT(json['DateAdded'])!,
30 | );
31 |
32 | int id;
33 | String title;
34 | String summary;
35 | String author;
36 | int viewcount;
37 | int diggcount;
38 | String dateadded;
39 | DateTime get postDateTime => DateTime.parse(dateadded);
40 |
41 | @override
42 | String toString() {
43 | return jsonEncode(this);
44 | }
45 |
46 | Map toJson() => {
47 | 'Id': id,
48 | 'Title': title,
49 | 'Summary': summary,
50 | 'Author': author,
51 | 'ViewCount': viewcount,
52 | 'DiggCount': diggcount,
53 | 'DateAdded': dateadded,
54 | };
55 | }
56 |
--------------------------------------------------------------------------------
/lib/models/blogs/user_blog_info_model.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | T? asT(dynamic value) {
4 | if (value is T) {
5 | return value;
6 | }
7 | return null;
8 | }
9 |
10 | class UserBlogInfoModel {
11 | UserBlogInfoModel({
12 | required this.blogId,
13 | required this.title,
14 | required this.subtitle,
15 | required this.postCount,
16 | required this.pageSize,
17 | required this.enableScript,
18 | });
19 |
20 | factory UserBlogInfoModel.fromJson(Map json) =>
21 | UserBlogInfoModel(
22 | blogId: asT(json['blogId'])!,
23 | title: asT(json['title'])!,
24 | subtitle: asT(json['subtitle'])!,
25 | postCount: asT(json['postCount'])!,
26 | pageSize: asT(json['pageSize'])!,
27 | enableScript: asT(json['enableScript'])!,
28 | );
29 |
30 | int blogId;
31 | String title;
32 | String subtitle;
33 | int postCount;
34 | int pageSize;
35 | bool enableScript;
36 |
37 | @override
38 | String toString() {
39 | return jsonEncode(this);
40 | }
41 |
42 | Map toJson() => {
43 | 'blogId': blogId,
44 | 'title': title,
45 | 'subtitle': subtitle,
46 | 'postCount': postCount,
47 | 'pageSize': pageSize,
48 | 'enableScript': enableScript,
49 | };
50 | }
51 |
--------------------------------------------------------------------------------
/lib/models/news/news_comment_item_model.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | T? asT(dynamic value) {
4 | if (value is T) {
5 | return value;
6 | }
7 | return null;
8 | }
9 |
10 | class NewsCommentItemModel {
11 | NewsCommentItemModel({
12 | required this.commentID,
13 | required this.contentID,
14 | required this.commentContent,
15 | required this.userGuid,
16 | required this.userId,
17 | required this.userName,
18 | required this.faceUrl,
19 | required this.floor,
20 | required this.dateAdded,
21 | required this.agreeCount,
22 | required this.antiCount,
23 | required this.parentCommentID,
24 | this.parentComment,
25 | });
26 |
27 | factory NewsCommentItemModel.fromJson(Map json) =>
28 | NewsCommentItemModel(
29 | commentID: asT(json['CommentID']) ?? 0,
30 | contentID: asT(json['ContentID']) ?? 0,
31 | commentContent: asT(json['CommentContent']) ?? "",
32 | userGuid: asT(json['UserGuid']) ?? "",
33 | userId: asT(json['UserId']) ?? 0,
34 | userName: asT(json['UserName']) ?? "",
35 | faceUrl: asT(json['FaceUrl']) ?? "",
36 | floor: asT(json['Floor']) ?? 0,
37 | dateAdded: asT(json['DateAdded']) ?? "",
38 | agreeCount: asT(json['AgreeCount']) ?? 0,
39 | antiCount: asT(json['AntiCount']) ?? 0,
40 | parentCommentID: asT(json['ParentCommentID']) ?? 0,
41 | parentComment: asT