├── .gitignore
├── .metadata
├── .vscode
├── launch.json
└── settings.json
├── LICENSE
├── README.md
├── ScreenShots
├── 1.PNG
├── 2.PNG
├── 3.PNG
├── 4.PNG
├── 5.PNG
├── 6.PNG
├── 7.PNG
├── 8.PNG
├── 9.PNG
└── 框架结构图.drawio
├── analysis_options.yaml
├── android
├── .gitignore
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── getx_study
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── drawable-v21
│ │ │ └── launch_background.xml
│ │ │ ├── drawable
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-night
│ │ │ └── styles.xml
│ │ │ └── values
│ │ │ └── styles.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── assets
├── html
│ ├── index.html
│ └── webToApp.html
└── images
│ ├── ic_eye.png
│ ├── ic_head.jpeg
│ ├── launchImage.png
│ ├── placeholder.png
│ ├── saber.jpg
│ ├── saber_logo.jpg
│ ├── season_ali_pay.jpg
│ ├── upgrade.png
│ ├── welcome_1.png
│ └── welcome_2.jpg
├── clean_flutter_projects.sh
├── ios
├── .gitignore
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Podfile
├── Podfile.lock
├── PrivacyInfo.xcprivacy
├── 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-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
├── ios_2024-04-11.txt
└── update_privacy_info.py
├── lib
├── account_manager
│ └── account_manager.dart
├── app_service
│ ├── account_service.dart
│ └── theme_service.dart
├── base
│ ├── base_controller.dart
│ ├── base_refresh_controller.dart
│ ├── base_request_controller.dart
│ ├── box.dart
│ ├── class_name.dart
│ ├── get_bind_widget.dart
│ ├── get_cupertino_controller.dart
│ ├── interface.dart
│ ├── pure_get_cupertino_app.dart
│ ├── reload_data_mixin.dart
│ ├── resign_first_responder.dart
│ └── resign_first_view.dart
├── entity
│ ├── account_info_entity.dart
│ ├── article_info_entity.dart
│ ├── banner_entity.dart
│ ├── base_entity.dart
│ ├── coin_rank_entity.dart
│ ├── common_response.dart
│ ├── common_response.g.dart
│ ├── hot_key_entity.dart
│ ├── i_entity.dart
│ ├── json_convert_extension.dart
│ ├── my_coin_entity.dart
│ ├── my_coin_history_entity.dart
│ ├── page_entity.dart
│ ├── pageable.dart
│ └── tab_entity.dart
├── enum
│ ├── collect_action_type.dart
│ ├── main_tag_type.dart
│ ├── my.dart
│ ├── response_status.dart
│ ├── scroll_view_action_type.dart
│ ├── tag_type.dart
│ └── theme_type.dart
├── example_app
│ ├── example_routes.dart
│ ├── get_x_app.dart
│ ├── h5_js_channel_app.dart
│ ├── rx_dart_app.dart
│ ├── state_mixin_example_page.dart
│ └── stream_app.dart
├── extension
│ ├── future_extension.dart
│ ├── get_route_extension.dart
│ ├── string_extension.dart
│ └── theme_data_extension.dart
├── generated
│ ├── assets.dart
│ └── json
│ │ ├── account_info_entity.g.dart
│ │ ├── article_info_entity.g.dart
│ │ ├── banner_entity.g.dart
│ │ ├── base
│ │ ├── json_convert_content.dart
│ │ └── json_field.dart
│ │ ├── coin_rank_entity.g.dart
│ │ ├── hot_key_entity.g.dart
│ │ ├── my_coin_entity.g.dart
│ │ ├── my_coin_history_entity.g.dart
│ │ └── tab_entity.g.dart
├── http_client
│ ├── login_client.dart
│ ├── login_client.g.dart
│ ├── request_client.dart
│ └── request_client.g.dart
├── http_util
│ ├── api.dart
│ ├── http_status.dart
│ ├── http_util.dart
│ ├── network_activity_plugin.dart
│ ├── plugins.dart
│ └── request.dart
├── i18n
│ └── localized_strings.dart
├── logger
│ └── logger.dart
├── main.dart
├── my_app.dart
├── pages
│ ├── coin_rank
│ │ ├── bindings
│ │ │ └── coin_rank_binding.dart
│ │ ├── controller
│ │ │ └── coin_rank_controller.dart
│ │ ├── repository
│ │ │ └── coin_rank_repository.dart
│ │ └── view
│ │ │ └── coin_rank_page.dart
│ ├── common
│ │ ├── countdown_circle.dart
│ │ ├── empty_view.dart
│ │ ├── error_view.dart
│ │ ├── floating_widget.dart
│ │ ├── info_cell.dart
│ │ ├── keep_alive_wrapper.dart
│ │ ├── loading_view.dart
│ │ ├── marquee_label.dart
│ │ ├── my_list_view.dart
│ │ ├── refresh_header_footer.dart
│ │ ├── shimmer.dart
│ │ ├── status_view.dart
│ │ └── unknown_page.dart
│ ├── home
│ │ ├── binding
│ │ │ ├── home_binding.dart
│ │ │ ├── hot_key_binding.dart
│ │ │ └── search_result_binding.dart
│ │ ├── controller
│ │ │ ├── home_controller.dart
│ │ │ ├── hot_key_controller.dart
│ │ │ └── search_result_controller.dart
│ │ ├── repository
│ │ │ ├── home_repository.dart
│ │ │ ├── hot_key_repository.dart
│ │ │ └── search_result_repository.dart
│ │ └── view
│ │ │ ├── home_page.dart
│ │ │ ├── hot_key_page.dart
│ │ │ ├── search_result_page.dart
│ │ │ └── search_text_field.dart
│ ├── launch
│ │ ├── splash_page.dart
│ │ └── welcome_page.dart
│ ├── main
│ │ ├── bindings
│ │ │ └── main_binding.dart
│ │ ├── controller
│ │ │ └── main_controller.dart
│ │ └── view
│ │ │ └── main_page.dart
│ ├── my
│ │ ├── binding
│ │ │ ├── login_binding.dart
│ │ │ ├── my_binding.dart
│ │ │ ├── my_coin_history_binding.dart
│ │ │ ├── my_collect_binding.dart
│ │ │ └── register_binding.dart
│ │ ├── controller
│ │ │ ├── get_user_info_mixin.dart
│ │ │ ├── login_controller.dart
│ │ │ ├── my_coin_history_controller.dart
│ │ │ ├── my_collect_controller.dart
│ │ │ ├── my_controller.dart
│ │ │ └── register_controller.dart
│ │ ├── repository
│ │ │ ├── my_coin_history_repository.dart
│ │ │ ├── my_collect_repository.dart
│ │ │ └── my_repository.dart
│ │ └── view
│ │ │ ├── login_page.dart
│ │ │ ├── my_coin_history_page.dart
│ │ │ ├── my_collect_page.dart
│ │ │ ├── my_page.dart
│ │ │ ├── register_page.dart
│ │ │ └── theme_setting_page.dart
│ ├── tree
│ │ ├── bindings
│ │ │ └── tabs_binding.dart
│ │ ├── controller
│ │ │ ├── tab_list_controller.dart
│ │ │ └── tabs_controller.dart
│ │ ├── repository
│ │ │ ├── tab_list_repository.dart
│ │ │ └── tabs_repository.dart
│ │ └── view
│ │ │ ├── tab_list_page.dart
│ │ │ ├── tabs_page.dart
│ │ │ ├── tree_cell.dart
│ │ │ └── tree_page.dart
│ └── web
│ │ ├── binding
│ │ └── web_binding.dart
│ │ ├── controller
│ │ └── web_controller.dart
│ │ ├── repository
│ │ └── web_repository.dart
│ │ └── view
│ │ └── web_page.dart
├── resource
│ └── constant.dart
└── routes
│ ├── getx_router_observer.dart
│ ├── history_router_observer.dart
│ ├── middleware
│ ├── login_middleware.dart
│ └── web_middleware.dart
│ └── routes.dart
├── linux
├── .gitignore
├── CMakeLists.txt
├── flutter
│ ├── CMakeLists.txt
│ ├── generated_plugin_registrant.cc
│ ├── generated_plugin_registrant.h
│ └── generated_plugins.cmake
├── main.cc
├── my_application.cc
└── my_application.h
├── macos
├── .gitignore
├── Flutter
│ ├── Flutter-Debug.xcconfig
│ ├── Flutter-Release.xcconfig
│ └── GeneratedPluginRegistrant.swift
├── Podfile
├── Podfile.lock
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── app_icon_1024.png
│ │ ├── app_icon_128.png
│ │ ├── app_icon_16.png
│ │ ├── app_icon_256.png
│ │ ├── app_icon_32.png
│ │ ├── app_icon_512.png
│ │ └── app_icon_64.png
│ ├── Base.lproj
│ └── MainMenu.xib
│ ├── Configs
│ ├── AppInfo.xcconfig
│ ├── Debug.xcconfig
│ ├── Release.xcconfig
│ └── Warnings.xcconfig
│ ├── DebugProfile.entitlements
│ ├── Info.plist
│ ├── MainFlutterWindow.swift
│ └── Release.entitlements
├── pubspec.lock
├── pubspec.yaml
├── test
└── widget_test.dart
├── web
├── favicon.png
├── icons
│ ├── Icon-192.png
│ ├── Icon-512.png
│ ├── Icon-maskable-192.png
│ └── Icon-maskable-512.png
├── index.html
└── manifest.json
├── windows
├── .gitignore
├── CMakeLists.txt
├── flutter
│ ├── CMakeLists.txt
│ ├── generated_plugin_registrant.cc
│ ├── generated_plugin_registrant.h
│ └── generated_plugins.cmake
└── runner
│ ├── CMakeLists.txt
│ ├── Runner.rc
│ ├── flutter_window.cpp
│ ├── flutter_window.h
│ ├── main.cpp
│ ├── resource.h
│ ├── resources
│ └── app_icon.ico
│ ├── runner.exe.manifest
│ ├── utils.cpp
│ ├── utils.h
│ ├── win32_window.cpp
│ └── win32_window.h
└── 说明.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .build/
9 | .buildlog/
10 | .history
11 | .svn/
12 | .swiftpm/
13 | migrate_working_dir/
14 |
15 | # IntelliJ related
16 | *.iml
17 | *.ipr
18 | *.iws
19 | .idea/
20 |
21 | # The .vscode folder contains launch configuration and tasks you configure in
22 | # VS Code which you may wish to be included in version control, so this line
23 | # is commented out by default.
24 | #.vscode/
25 |
26 | # Flutter/Dart/Pub related
27 | **/doc/api/
28 | **/ios/Flutter/.last_build_id
29 | .dart_tool/
30 | .flutter-plugins
31 | .flutter-plugins-dependencies
32 | .packages
33 | .pub-cache/
34 | .pub/
35 | /build/
36 |
37 | # Web related
38 |
39 | # Symbolication related
40 | app.*.symbols
41 |
42 | # Obfuscation related
43 | app.*.map.json
44 |
45 | # Android Studio will place build artifacts here
46 | /android/app/debug
47 | /android/app/profile
48 | /android/app/release
49 |
--------------------------------------------------------------------------------
/.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 and should not be manually edited.
5 |
6 | version:
7 | revision: "300451adae589accbece3490f4396f10bdf15e6e"
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: 300451adae589accbece3490f4396f10bdf15e6e
17 | base_revision: 300451adae589accbece3490f4396f10bdf15e6e
18 | - platform: ios
19 | create_revision: 300451adae589accbece3490f4396f10bdf15e6e
20 | base_revision: 300451adae589accbece3490f4396f10bdf15e6e
21 |
22 | # User provided section
23 |
24 | # List of Local paths (relative to this file) that should be
25 | # ignored by the migrate tool.
26 | #
27 | # Files that are not part of the templates will be ignored by default.
28 | unmanaged_files:
29 | - 'lib/main.dart'
30 | - 'ios/Runner.xcodeproj/project.pbxproj'
31 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // 使用 IntelliSense 了解相关属性。
3 | // 悬停以查看现有属性的描述。
4 | // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "getx_study",
9 | "request": "launch",
10 | "type": "dart"
11 | },
12 | {
13 | "name": "getx_study (profile mode)",
14 | "request": "launch",
15 | "type": "dart",
16 | "flutterMode": "profile"
17 | },
18 | {
19 | "name": "getx_study (release mode)",
20 | "request": "launch",
21 | "type": "dart",
22 | "flutterMode": "release"
23 | }
24 | ]
25 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "todo-tree.tree.disableCompactFolders": true,
3 | "editor.formatOnSave": true,
4 | "dart.previewFlutterUiGuides": true,
5 | "editor.inlineSuggest.showToolbar": "always"
6 | }
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 seasonZhu
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.
22 |
--------------------------------------------------------------------------------
/ScreenShots/1.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ScreenShots/1.PNG
--------------------------------------------------------------------------------
/ScreenShots/2.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ScreenShots/2.PNG
--------------------------------------------------------------------------------
/ScreenShots/3.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ScreenShots/3.PNG
--------------------------------------------------------------------------------
/ScreenShots/4.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ScreenShots/4.PNG
--------------------------------------------------------------------------------
/ScreenShots/5.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ScreenShots/5.PNG
--------------------------------------------------------------------------------
/ScreenShots/6.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ScreenShots/6.PNG
--------------------------------------------------------------------------------
/ScreenShots/7.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ScreenShots/7.PNG
--------------------------------------------------------------------------------
/ScreenShots/8.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ScreenShots/8.PNG
--------------------------------------------------------------------------------
/ScreenShots/9.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ScreenShots/9.PNG
--------------------------------------------------------------------------------
/ScreenShots/框架结构图.drawio:
--------------------------------------------------------------------------------
1 | 7VvRkpowFP2aPG6HBEF4XF27fejOOGun2/YtlShpgTgxrrpf30QCAmFH16LQuk8mN3CBk3PvPQkI7GG8ued4ET6wgEQAWcEG2HcAIQgtV/4oyza19F2UGuacBvqgvWFCX4g2Wtq6ogFZlg4UjEWCLsrGKUsSMhUlG+acrcuHzVhUvuoCz4lhmExxZFqfaCDC1Oqh/t7+idB5mF0Zun46EuPsYP0kyxAHbF0w2SNgDzljIm3FmyGJFHgZLul5H18ZzW+Mk0Qcc8LTli3oS0gfkpvNvfXpy+fHux832sszjlb6gb9SspZO1M+QJYKzKCJcP4HYZrBwtkoCojxbwB6sQyrIZIGnanQtiSBtoYgj2YOyad5pdlnCBdkUTPrO7wmLieBbeYgetXsaRU0jZOv+ej8pMEM6LEyIq21Y82Ceu95DJRsarTcgh2qR0wHQMbTyfmto2QZaY86eZWh3j1o9p22wegZYD2yLOweU4zgtA+UbQBkgkSS4VWVA9hKWkDIoZQTJhopvqv3B0b3vhZG7TbGzzToyQ24LJ6nud+1919mftutl5706HUu24lNymBwC8zkRhyOOBKX6Zk5uYfKcmrnLbJxEWNDnclWsm1B9hTGj8sly7uRBVQ2yzEX63PqsYhWrOHKsiiOr4igFxnC041f+2KdTLtMlV8W5bnHJ9v0PTpkEPec0NtW4ujSfTAX2//MJdZxPtt0Yn5B/YT7V61Lpa6xWOm1riL7bNR0PTWl6T8S3Dq19qpi1r+ahqVAfyYItqWDae5fwal/QQ6cGL0mvGRWdQ6t9VQ/dKyyJGUUO6vos9jpSPL1+Q8LeRy0L+/41sq5jZIKNKfsaV5cmlHeNhOrWUtFkwcnS3nR1cWlvbndNBBbti3rf6ZpAReaqekCTgCbz1sFyKgUzZ1F7YJlLxiMSVYCX4Q42WIZI2cdYCMKTnQVZtrQupdr9nb9BQ69nt2JuyzPdgewGi7mtkOrOlt0OirTMY0fSoOsd0FbHJsG+XYn0qto7cwpE5mL98lTNi+rbaJdRHL6B4qdTNX9ZfnA9gd6pehaqmnsk71T9u6yaCaB3qjZM1ZrtKbYSZNk5sQS91sXSNW5OHV1MMiZ1NEJt1FCEov6FI9TcnHrcTMQq2IJRHwwGwLfByAX+CHg9MHKA5wHPVY0BBB5SDX8ABiODqTIMRV5HhixifM/ZGY2iiqlA4xlLhP5aT1Y63deO1biKcTrF0W1E56pkxTQI1OAAa8NUspDwZtKEXVmAwrodf6uGZ72zpQlz80e9VXqfsjw0YXkzJc/ihSnrwTNNGeYLSh+wcBgTwc948utxHN+YRfA2itmM8kY2WAxkavA7+ssr171gGawF61+vgpUCddRktPU1gludxdO/Rsijrvm6VUsTs2zdUdZ6OFVfebYfTv/6q4LuhpO5bX9yONW4aiycZHf/T4D08P3/KezRHw==
--------------------------------------------------------------------------------
/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 | android {
29 | defaultConfig {
30 | minSdkVersion 21
31 | }
32 | compileSdkVersion 33//flutter.compileSdkVersion
33 | ndkVersion flutter.ndkVersion
34 |
35 | compileOptions {
36 | sourceCompatibility JavaVersion.VERSION_1_8
37 | targetCompatibility JavaVersion.VERSION_1_8
38 | }
39 |
40 | kotlinOptions {
41 | jvmTarget = '1.8'
42 | }
43 |
44 | sourceSets {
45 | main.java.srcDirs += 'src/main/kotlin'
46 | }
47 |
48 | defaultConfig {
49 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
50 | applicationId "com.example.getx_study"
51 | // You can update the following values to match your application needs.
52 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
53 | minSdkVersion flutter.minSdkVersion
54 | targetSdkVersion flutter.targetSdkVersion
55 | versionCode flutterVersionCode.toInteger()
56 | versionName flutterVersionName
57 | }
58 |
59 | buildTypes {
60 | release {
61 | // TODO: Add your own signing config for the release build.
62 | // Signing with the debug keys for now, so `flutter run --release` works.
63 | signingConfig signingConfigs.debug
64 | }
65 | }
66 | }
67 |
68 | flutter {
69 | source '../..'
70 | }
71 |
72 | dependencies {
73 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
74 | }
75 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
7 |
15 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/example/getx_study/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.getx_study
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/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.9.0'
3 | repositories {
4 | //google()
5 | //mavenCentral()
6 | maven { url 'https://maven.aliyun.com/repository/google' }
7 | maven { url 'https://maven.aliyun.com/repository/jcenter' }
8 | maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
9 | }
10 |
11 | dependencies {
12 | classpath 'com.android.tools.build:gradle:7.1.2'
13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | //google()
20 | //mavenCentral()
21 | maven { url 'https://maven.aliyun.com/repository/google' }
22 | maven { url 'https://maven.aliyun.com/repository/jcenter' }
23 | maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
24 | }
25 | }
26 |
27 | rootProject.buildDir = '../build'
28 | subprojects {
29 | project.buildDir = "${rootProject.buildDir}/${project.name}"
30 | }
31 | subprojects {
32 | project.evaluationDependsOn(':app')
33 | }
34 |
35 | tasks.register("clean", Delete) {
36 | delete rootProject.buildDir
37 | }
38 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
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-7.4-all.zip
7 |
--------------------------------------------------------------------------------
/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/html/webToApp.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
11 |
12 |
38 |
--------------------------------------------------------------------------------
/assets/images/ic_eye.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/assets/images/ic_eye.png
--------------------------------------------------------------------------------
/assets/images/ic_head.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/assets/images/ic_head.jpeg
--------------------------------------------------------------------------------
/assets/images/launchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/assets/images/launchImage.png
--------------------------------------------------------------------------------
/assets/images/placeholder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/assets/images/placeholder.png
--------------------------------------------------------------------------------
/assets/images/saber.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/assets/images/saber.jpg
--------------------------------------------------------------------------------
/assets/images/saber_logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/assets/images/saber_logo.jpg
--------------------------------------------------------------------------------
/assets/images/season_ali_pay.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/assets/images/season_ali_pay.jpg
--------------------------------------------------------------------------------
/assets/images/upgrade.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/assets/images/upgrade.png
--------------------------------------------------------------------------------
/assets/images/welcome_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/assets/images/welcome_1.png
--------------------------------------------------------------------------------
/assets/images/welcome_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/assets/images/welcome_2.jpg
--------------------------------------------------------------------------------
/clean_flutter_projects.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # 获取脚本所在的目录
4 | START_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
5 |
6 | # 遍历目录寻找pubspec.yaml文件,并执行flutter clean
7 | find "$START_DIR" -name 'pubspec.yaml' | while read -r file; do
8 | # 获取Flutter项目的目录路径
9 | project_dir=$(dirname "$file")
10 | echo "Found Flutter project at $project_dir"
11 | # 进入项目目录
12 | cd "$project_dir" || exit
13 | # 执行flutter clean
14 | flutter clean
15 | # 返回到脚本开始的目录,以继续搜索
16 | cd "$START_DIR" || exit
17 | done
18 |
19 | echo "All Flutter projects cleaned."
20 |
--------------------------------------------------------------------------------
/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 | 12.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, '15.6'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 |
6 | #source 'https://github.com/CocoaPods/Specs.git'
7 |
8 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
9 |
10 | project 'Runner', {
11 | 'Debug' => :debug,
12 | 'Profile' => :release,
13 | 'Release' => :release,
14 | }
15 |
16 | def flutter_root
17 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
18 | unless File.exist?(generated_xcode_build_settings_path)
19 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
20 | end
21 |
22 | File.foreach(generated_xcode_build_settings_path) do |line|
23 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
24 | return matches[1].strip if matches
25 | end
26 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
27 | end
28 |
29 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
30 |
31 | flutter_ios_podfile_setup
32 |
33 | target 'Runner' do
34 | use_frameworks!
35 | use_modular_headers!
36 |
37 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
38 | end
39 |
40 | post_install do |installer|
41 | installer.pods_project.targets.each do |target|
42 | flutter_additional_ios_build_settings(target)
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/ios/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 | NSPrivacyAccessedAPITypes
--------------------------------------------------------------------------------
/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 | @main
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | private let channelName = "com.getStudy.app/popIsEnable"
7 |
8 | override func application(
9 | _ application: UIApplication,
10 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
11 | ) -> Bool {
12 | GeneratedPluginRegistrant.register(with: self)
13 |
14 | guard let controller = window?.rootViewController as? FlutterViewController else {
15 | fatalError("rootViewController is not type FlutterViewController")
16 | }
17 | let channel = FlutterMethodChannel(name: channelName, binaryMessenger: controller.binaryMessenger)
18 | channel.setMethodCallHandler { [weak self] (call, result) in
19 | if call.method == "sendMessage" {
20 | self?.handleMessage(call.arguments)
21 | result("Message received")
22 | } else {
23 | result(FlutterMethodNotImplemented)
24 | }
25 | }
26 |
27 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
28 | }
29 |
30 | private func handleMessage(_ message: Any?) {
31 | print(message)
32 | guard let dict = message as? [String: Bool],
33 | let canGoBack = dict["canGoBack"] else {
34 | return
35 | }
36 |
37 | guard let controller = window?.rootViewController as? FlutterViewController else {
38 | return
39 | }
40 |
41 | /// 这里其实有很本质的问题,那就是navigationController根本不存在,所以这个方法调用没有意义
42 | controller.navigationController?.interactivePopGestureRecognizer?.isEnabled = !canGoBack
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-1024.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/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/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/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/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/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/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/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/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "LaunchImage.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "LaunchImage@2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "LaunchImage@3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seasonZhu/GetXStudy/3bff369b56d78da3107a8637f5fc21494f3ad97d/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 | CADisableMinimumFrameDurationOnPhone
6 |
7 | CFBundleDevelopmentRegion
8 | $(DEVELOPMENT_LANGUAGE)
9 | CFBundleDisplayName
10 | wandroid
11 | CFBundleExecutable
12 | $(EXECUTABLE_NAME)
13 | CFBundleIdentifier
14 | $(PRODUCT_BUNDLE_IDENTIFIER)
15 | CFBundleInfoDictionaryVersion
16 | 6.0
17 | CFBundleName
18 | getx_study
19 | CFBundlePackageType
20 | APPL
21 | CFBundleShortVersionString
22 | $(FLUTTER_BUILD_NAME)
23 | CFBundleSignature
24 | ????
25 | CFBundleVersion
26 | $(FLUTTER_BUILD_NUMBER)
27 | LSRequiresIPhoneOS
28 |
29 | UILaunchStoryboardName
30 | LaunchScreen
31 | UIMainStoryboardFile
32 | Main
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationLandscapeRight
40 | UIInterfaceOrientationPortrait
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 | UIApplicationSupportsIndirectInputEvents
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/ios/ios_2024-04-11.txt:
--------------------------------------------------------------------------------
1 | Found API Categories:
2 |
3 | Found Dependencies:
4 |
5 | - webview_flutter_wkwebview
6 | - https://raw.githubusercontent.com/flutter/packages/main/packages/webview_flutter/webview_flutter_wkwebview/ios/Resources/PrivacyInfo.xcprivacy
7 |
8 | - FMDB
9 | - https://raw.githubusercontent.com/ccgus/fmdb/master/privacy/PrivacyInfo.xcprivacy
10 |
11 | - device_info_plus
12 | - https://raw.githubusercontent.com/fluttercommunity/plus_plugins/9e187803d395bf1d8cbe74a0494ef28989451dde/packages/device_info_plus/device_info_plus/ios/PrivacyInfo.xcprivacy
13 |
14 | - sqflite
15 | - https://raw.githubusercontent.com/tekartik/sqflite/master/sqflite/darwin/Resources/PrivacyInfo.xcprivacy
16 |
17 | - url_launcher_ios
18 | - https://raw.githubusercontent.com/flutter/packages/main/packages/url_launcher/url_launcher_ios/ios/Resources/PrivacyInfo.xcprivacy
19 |
20 | - image_picker_ios
21 | - https://raw.githubusercontent.com/flutter/packages/main/packages/image_picker/image_picker_ios/ios/Resources/PrivacyInfo.xcprivacy
22 |
23 | - Flutter
24 | - https://raw.githubusercontent.com/flutter/engine/a565cea256c7bafeaa0c26c2f1b0d66a52692d02/shell/platform/darwin/ios/framework/PrivacyInfo.xcprivacy#L9-L12
25 |
--------------------------------------------------------------------------------
/lib/app_service/theme_service.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/cupertino.dart';
3 | import 'package:get/get.dart';
4 | import 'package:getx_study/app_service/account_service.dart';
5 | import 'package:getx_study/base/get_cupertino_controller.dart';
6 | import 'package:getx_study/enum/theme_type.dart';
7 |
8 | class ThemeService extends GetxService {
9 | static ThemeService get find => Get.find();
10 |
11 | final rxCurrentThemeType = ThemeType.light.obs;
12 |
13 | CupertinoThemeData get themeData {
14 | return rxCurrentThemeType.value.theme;
15 | }
16 |
17 | Color get indicatorColor {
18 | if (rxCurrentThemeType.value == ThemeType.light) {
19 | return Colors.blue;
20 | } else {
21 | return Colors.white;
22 | }
23 | }
24 |
25 | Color get labelColor {
26 | if (rxCurrentThemeType.value == ThemeType.light) {
27 | return Colors.blue;
28 | } else {
29 | return Colors.white;
30 | }
31 | }
32 |
33 | Color get unselectedLabelColor {
34 | if (rxCurrentThemeType.value == ThemeType.light) {
35 | return Colors.lightBlue;
36 | } else {
37 | return Colors.white60;
38 | }
39 | }
40 |
41 | void switchTheme(ThemeType type) async {
42 | final currentThemeType = await AccountService.find.getThemeSetting();
43 | if (currentThemeType == type) {
44 | return;
45 | }
46 |
47 | rxCurrentThemeType.value = type;
48 | saveThemeType(type);
49 | restartApp();
50 | }
51 |
52 | void saveThemeType(ThemeType type) {
53 | // 保存 主题设置
54 | AccountService.find.saveThemeSetting(type);
55 | }
56 |
57 | Future getThemeType() async {
58 | // 获取主题设置
59 | final type = await AccountService.find.getThemeSetting();
60 | rxCurrentThemeType.value = type;
61 | return type;
62 | }
63 |
64 | // 重启应用的方法
65 | Future restartApp() async {
66 | Get.find().restartApp();
67 | }
68 |
69 | /// 通过GetCupertinoController更换主题颜色的思路
70 | void changeTheme(ThemeType type) async {
71 | final currentThemeType = await AccountService.find.getThemeSetting();
72 | if (currentThemeType == type) {
73 | return;
74 | }
75 |
76 | rxCurrentThemeType.value = type;
77 | Get.find().setCupertinoTheme(type.theme);
78 | AccountService.find.saveThemeSetting(type);
79 | Get.find().restartApp();
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/lib/base/base_controller.dart:
--------------------------------------------------------------------------------
1 | import 'package:get/get.dart';
2 |
3 | import 'package:getx_study/app_service/account_service.dart';
4 | import 'package:getx_study/base/interface.dart';
5 | import 'package:getx_study/enum/response_status.dart';
6 | import 'package:getx_study/routes/routes.dart';
7 |
8 | abstract class BaseController extends GetxController
9 | implements IRetry, IEmptyTap {
10 | ResponseStatus status = ResponseStatus.loading;
11 | }
12 |
13 | /// 要不要with是个问题
14 | mixin ResponseStatusMixin on GetxController {
15 | ResponseStatus status = ResponseStatus.loading;
16 | }
17 |
18 | /// 目前这个玩安卓版本的设计是如果用户是游客,就直接屏蔽功能
19 | /// 这里考虑的是如果所有功能都是开放的,那么点击事件最后都会传到Controller层,那么控制器层就需要用一个方法做统一拦截
20 | /// 这里考虑用的mixin的方式,这样的好处的是,有些页面根本就不需要检查是否登录,也就减少了继承的成本
21 | /// 但是用mixin的问题是,很多页面又都需要写with
22 | /// 先with然后再extends?
23 | /// 本质上GetMiddleware的中间件已经做了这个事情,详细看LoginMiddleware,但是如何去拦截点击事情还没想好
24 | mixin CheckIsLoginMixin on BaseController {
25 | bool checkIsLogin() {
26 | if (!AccountService.find.isLogin) {
27 | Get.toNamed(Routes.login);
28 | }
29 |
30 | return AccountService.find.isLogin;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lib/base/base_request_controller.dart:
--------------------------------------------------------------------------------
1 | import 'package:get/get.dart';
2 |
3 | import "package:getx_study/base/base_controller.dart";
4 | import 'package:getx_study/base/interface.dart';
5 | import 'package:getx_study/entity/base_entity.dart';
6 |
7 | abstract class BaseRequestController extends BaseController {
8 | late R request;
9 |
10 | BaseEntity? response;
11 |
12 | T? data;
13 |
14 | @override
15 | void onInit() async {
16 | super.onInit();
17 | request = Get.find();
18 | }
19 |
20 | Future aRequest({
21 | Map? parameters,
22 | }) async {}
23 |
24 | @override
25 | void retry() {
26 | aRequest();
27 | }
28 |
29 | @override
30 | void emptyTap() {
31 | aRequest();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/lib/base/box.dart:
--------------------------------------------------------------------------------
1 | class Box {
2 | T value;
3 |
4 | Box(this.value);
5 | }
6 |
7 | extension Extension on T {
8 | Box get box => Box(this);
9 | }
--------------------------------------------------------------------------------
/lib/base/class_name.dart:
--------------------------------------------------------------------------------
1 |
2 | String className(Object object) => (object).toString();
3 |
4 | String typeName(Type type) => (type).toString();
--------------------------------------------------------------------------------
/lib/base/get_cupertino_controller.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:get/get.dart';
3 |
4 | /// 在创建GetCupertinoApp会默认创建GetMaterialController,但是GetMaterialController里面没有涉及到CupertinoThemeData的设置
5 | /// 但是又无法对GetMaterialController新增属性,只能整个继承了然后再mixin
6 | class GetCupertinoController extends GetMaterialController with UpdateCupertinoThemeData {}
7 |
8 | mixin UpdateCupertinoThemeData on GetMaterialController {
9 | CupertinoThemeData? cupertinoTheme;
10 |
11 | CupertinoThemeData? darkCupertinoTheme;
12 |
13 | void setCupertinoTheme(CupertinoThemeData value) {
14 | if (darkCupertinoTheme == null) {
15 | cupertinoTheme = value;
16 | } else {
17 | if (value.brightness == Brightness.light) {
18 | cupertinoTheme = value;
19 | } else {
20 | darkCupertinoTheme = value;
21 | }
22 | }
23 | update();
24 | }
25 | }
--------------------------------------------------------------------------------
/lib/base/interface.dart:
--------------------------------------------------------------------------------
1 | import 'package:get/get.dart';
2 |
3 | abstract class IRepository {}
4 |
5 | /// 重试机制
6 | abstract class IRetry {
7 | /// 这里写不写方法的实现好像并不影响代码编译与逻辑
8 | void retry();
9 | }
10 |
11 | /// 点击空白机制
12 | abstract class IEmptyTap {
13 | /// 这里写不写方法的实现好像并不影响代码编译与逻辑
14 | void emptyTap();
15 | }
16 |
17 | /// 跳转Web的模型基类
18 | abstract class IWebLoadInfo {
19 | int? id;
20 | int? originId;
21 | String? title;
22 | String? link;
23 | }
24 |
25 | /// 以下代码没有使用,是思考
26 |
27 | abstract class IRequestController extends GetxController {}
28 |
29 | /// 危险,不要定义这个类
30 | /// typedef GetPage = GetView;
31 |
32 | /// 下面这个类在使用上没有意义
33 | /*
34 | abstract class IClassName {
35 | static String? className;
36 |
37 | /// 协议的类方法必须要进行实现,否则就会报错
38 | // static String? Some();
39 |
40 | // String some();
41 | }
42 | */
43 |
44 |
--------------------------------------------------------------------------------
/lib/base/reload_data_mixin.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | mixin ReloadDataMixin on State {
4 |
5 | void reloadData() {
6 | if (mounted) setState(() {});
7 | }
8 | }
--------------------------------------------------------------------------------
/lib/base/resign_first_responder.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 |
4 | abstract class ResignFirstResponder {
5 | ResignFirstResponder._();
6 |
7 | /// 此方法需要获取当前Widget的上下文,而且用起来也不够安全
8 | static of(BuildContext context) {
9 | FocusScope.of(context).requestFocus(FocusNode());
10 | }
11 |
12 | /// 推荐下面的方法
13 | static unfocus() {
14 | FocusManager.instance.primaryFocus?.unfocus();
15 | }
16 |
17 | static hideKeyboard() {
18 | SystemChannels.textInput.invokeMethod("TextInput.hide");
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lib/base/resign_first_view.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'resign_first_responder.dart';
4 |
5 | class ResignFirstView extends StatelessWidget {
6 | const ResignFirstView({Key? key, required this.child}) : super(key: key);
7 |
8 | final Widget child;
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return GestureDetector(
13 | onTap: () {
14 | ResignFirstResponder.unfocus();
15 | },
16 | child: child,
17 | );
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lib/entity/account_info_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:getx_study/generated/json/base/json_field.dart';
2 | import 'package:getx_study/generated/json/account_info_entity.g.dart';
3 | import 'dart:convert';
4 |
5 | @JsonSerializable()
6 | class AccountInfoEntity {
7 |
8 | bool? admin;
9 | List? chapterTops;
10 | List? collectIds;
11 | String? email;
12 | String? icon;
13 | int? id;
14 | String? nickname;
15 | String? password;
16 | String? publicName;
17 | String? token;
18 | int? type;
19 | String? username;
20 |
21 | AccountInfoEntity();
22 |
23 | factory AccountInfoEntity.fromJson(Map json) => $AccountInfoEntityFromJson(json);
24 |
25 | Map toJson() => $AccountInfoEntityToJson(this);
26 |
27 | @override
28 | String toString() {
29 | return jsonEncode(this);
30 | }
31 | }
--------------------------------------------------------------------------------
/lib/entity/article_info_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:getx_study/base/interface.dart';
2 | import 'package:getx_study/generated/json/base/json_field.dart';
3 | import 'package:getx_study/generated/json/article_info_entity.g.dart';
4 | import 'dart:convert';
5 |
6 | @JsonSerializable()
7 | class ArticleInfoEntity {
8 | int? curPage;
9 | List? datas;
10 | int? offset;
11 | bool? over;
12 | int? pageCount;
13 | int? size;
14 | int? total;
15 |
16 | ArticleInfoEntity();
17 |
18 | factory ArticleInfoEntity.fromJson(Map json) =>
19 | $ArticleInfoEntityFromJson(json);
20 |
21 | Map toJson() => $ArticleInfoEntityToJson(this);
22 |
23 | @override
24 | String toString() {
25 | return jsonEncode(this);
26 | }
27 | }
28 |
29 | @JsonSerializable()
30 | class ArticleInfoDatas implements IWebLoadInfo {
31 | String? apkLink;
32 | int? audit;
33 | String? author;
34 | bool? canEdit;
35 | int? chapterId;
36 | String? chapterName;
37 | bool? collect;
38 | int? courseId;
39 | String? desc;
40 | String? descMd;
41 | String? envelopePic;
42 | bool? fresh;
43 | @override
44 | int? id;
45 | @override
46 | String? link;
47 | String? niceDate;
48 | String? niceShareDate;
49 | String? origin;
50 | String? prefix;
51 | String? projectLink;
52 | int? publishTime;
53 | int? selfVisible;
54 | int? shareDate;
55 | String? shareUser;
56 | int? superChapterId;
57 | String? superChapterName;
58 | List? tags;
59 | @override
60 | String? title;
61 | int? type;
62 | int? userId;
63 | int? visible;
64 | int? zan;
65 | @override
66 | int? originId;
67 |
68 | ArticleInfoDatas();
69 |
70 | factory ArticleInfoDatas.fromJson(Map json) =>
71 | $ArticleInfoDatasFromJson(json);
72 |
73 | Map toJson() => $ArticleInfoDatasToJson(this);
74 |
75 | @override
76 | String toString() {
77 | return jsonEncode(this);
78 | }
79 | }
80 |
81 | @JsonSerializable()
82 | class ArticleInfoDatasTags {
83 | String? name;
84 | String? url;
85 |
86 | ArticleInfoDatasTags();
87 |
88 | factory ArticleInfoDatasTags.fromJson(Map json) =>
89 | $ArticleInfoDatasTagsFromJson(json);
90 |
91 | Map toJson() => $ArticleInfoDatasTagsToJson(this);
92 |
93 | @override
94 | String toString() {
95 | return jsonEncode(this);
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/lib/entity/banner_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:getx_study/base/interface.dart';
2 | import 'package:getx_study/generated/json/base/json_field.dart';
3 | import 'package:getx_study/generated/json/banner_entity.g.dart';
4 | import 'dart:convert';
5 |
6 | @JsonSerializable()
7 | class BannerEntity implements IWebLoadInfo {
8 | String? desc;
9 | @override
10 | int? id;
11 | String? imagePath;
12 | double? isVisible;
13 | double? order;
14 | @override
15 | String? title;
16 | double? type;
17 | String? url;
18 | @override
19 | String? link;
20 | @override
21 | int? originId;
22 |
23 | BannerEntity();
24 |
25 | factory BannerEntity.fromJson(Map json) =>
26 | $BannerEntityFromJson(json);
27 |
28 | Map toJson() => $BannerEntityToJson(this);
29 |
30 | @override
31 | String toString() {
32 | return jsonEncode(this);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/lib/entity/base_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:getx_study/entity/i_entity.dart';
2 | import 'package:getx_study/entity/page_entity.dart';
3 | import 'package:getx_study/enum/response_status.dart';
4 |
5 | import 'package:getx_study/resource/constant.dart';
6 |
7 | class BaseEntity extends IEntity {
8 | BaseEntity(this.errorCode, this.errorMsg, this.data);
9 |
10 | BaseEntity.fromJson(Map json) {
11 | errorCode = json[Constant.errorCode] as int?;
12 | errorMsg = json[Constant.errorMsg] as String?;
13 | if (json.containsKey(Constant.data)) {
14 | data = generateOBJ(json[Constant.data] as Object?);
15 | }
16 | }
17 |
18 | int? errorCode;
19 | String? errorMsg;
20 | T? data;
21 |
22 | bool get isSuccess => errorCode == 0;
23 |
24 | ResponseStatus get responseStatus => _responseStatus;
25 |
26 | ResponseStatus get _responseStatus {
27 | if (errorCode == null) {
28 | return ResponseStatus.loading;
29 | } else if (errorCode == 0) {
30 | if (data is List) {
31 | final listData = data as List;
32 | if (listData.isNotEmpty) {
33 | return ResponseStatus.successHasContent;
34 | } else {
35 | return ResponseStatus.successNoData;
36 | }
37 | } else if (data is PageEntity ) {
38 | final pageEntity = data as PageEntity;
39 | final dataSource = pageEntity.dataSource as List;
40 | if (dataSource.isNotEmpty) {
41 | return ResponseStatus.successHasContent;
42 | } else {
43 | return ResponseStatus.successNoData;
44 | }
45 | } else {
46 | if (data != null) {
47 | return ResponseStatus.successHasContent;
48 | } else {
49 | return ResponseStatus.successNoData;
50 | }
51 | }
52 | } else {
53 | return ResponseStatus.fail;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/lib/entity/coin_rank_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:getx_study/generated/json/base/json_field.dart';
2 | import 'package:getx_study/generated/json/coin_rank_entity.g.dart';
3 | import 'dart:convert';
4 |
5 | @JsonSerializable()
6 | class CoinRankEntity {
7 |
8 | int? curPage;
9 | List? datas;
10 | int? offset;
11 | bool? over;
12 | int? pageCount;
13 | int? size;
14 | int? total;
15 |
16 | CoinRankEntity();
17 |
18 | factory CoinRankEntity.fromJson(Map json) => $CoinRankEntityFromJson(json);
19 |
20 | Map toJson() => $CoinRankEntityToJson(this);
21 |
22 | @override
23 | String toString() {
24 | return jsonEncode(this);
25 | }
26 | }
27 |
28 | @JsonSerializable()
29 | class CoinRankDatas {
30 |
31 | int? coinCount;
32 | int? level;
33 | int? rank;
34 | int? userId;
35 | String? username;
36 |
37 | CoinRankDatas();
38 |
39 | factory CoinRankDatas.fromJson(Map json) => $CoinRankDatasFromJson(json);
40 |
41 | Map toJson() => $CoinRankDatasToJson(this);
42 |
43 | @override
44 | String toString() {
45 | return jsonEncode(this);
46 | }
47 | }
--------------------------------------------------------------------------------
/lib/entity/common_response.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 |
3 | part'common_response.g.dart'; // 生成的文件名
4 |
5 | @JsonSerializable()
6 | class CommonResponse {
7 | final String name;
8 | final int age;
9 | final bool isStudent;
10 |
11 | CommonResponse({required this.name, required this.age, required this.isStudent});
12 |
13 | factory CommonResponse.fromJson(Map json) => _$CommonResponseFromJson(json);
14 | Map toJson() => _$CommonResponseToJson(this);
15 | }
--------------------------------------------------------------------------------
/lib/entity/common_response.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'common_response.dart';
4 |
5 | // **************************************************************************
6 | // JsonSerializableGenerator
7 | // **************************************************************************
8 |
9 | CommonResponse _$CommonResponseFromJson(Map json) =>
10 | CommonResponse(
11 | name: json['name'] as String,
12 | age: (json['age'] as num).toInt(),
13 | isStudent: json['isStudent'] as bool,
14 | );
15 |
16 | Map _$CommonResponseToJson(CommonResponse instance) =>
17 | {
18 | 'name': instance.name,
19 | 'age': instance.age,
20 | 'isStudent': instance.isStudent,
21 | };
22 |
--------------------------------------------------------------------------------
/lib/entity/hot_key_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:getx_study/generated/json/base/json_field.dart';
2 | import 'package:getx_study/generated/json/hot_key_entity.g.dart';
3 | import 'dart:convert';
4 |
5 | @JsonSerializable()
6 | class HotKeyEntity {
7 |
8 | double? id;
9 | String? link;
10 | String? name;
11 | double? order;
12 | double? visible;
13 |
14 | HotKeyEntity();
15 |
16 | factory HotKeyEntity.fromJson(Map json) => $HotKeyEntityFromJson(json);
17 |
18 | Map toJson() => $HotKeyEntityToJson(this);
19 |
20 | @override
21 | String toString() {
22 | return jsonEncode(this);
23 | }
24 | }
--------------------------------------------------------------------------------
/lib/entity/i_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:getx_study/generated/json/base/json_convert_content.dart';
2 |
3 | abstract class IEntity {
4 | T? generateOBJ(Object? json) {
5 | if (T.toString() == 'String') {
6 | return json.toString() as T;
7 | } else if (T.toString() == 'Map') {
8 | return json as T;
9 | } else {
10 | /// List类型数据由fromJsonAsT判断处理
11 | return JsonConvert.fromJsonAsT(json);
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/lib/entity/json_convert_extension.dart:
--------------------------------------------------------------------------------
1 | import 'package:getx_study/generated/json/base/json_convert_content.dart';
2 |
3 | import 'package:getx_study/entity/article_info_entity.dart';
4 | import 'package:getx_study/entity/coin_rank_entity.dart';
5 | import 'package:getx_study/entity/my_coin_history_entity.dart';
6 | import 'package:getx_study/entity/page_entity.dart';
7 |
8 | extension MoreGenerics on JsonConvert {
9 | /// 解决泛型里面包含泛型的转换问题
10 | static final Map genericsFuncMap = {
11 | "PageEntity>": PageEntity>.fromJson,
12 | "PageEntity>": PageEntity>.fromJson,
13 | "PageEntity>": PageEntity>.fromJson,
14 | };
15 | }
--------------------------------------------------------------------------------
/lib/entity/my_coin_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:getx_study/generated/json/base/json_field.dart';
2 | import 'package:getx_study/generated/json/my_coin_entity.g.dart';
3 | import 'dart:convert';
4 |
5 | @JsonSerializable()
6 | class MyCoinEntity {
7 | int? coinCount;
8 | int? level;
9 | String? nickname;
10 | String? rank;
11 | int? userId;
12 | String? username;
13 |
14 | MyCoinEntity();
15 |
16 | factory MyCoinEntity.fromJson(Map json) =>
17 | $MyCoinEntityFromJson(json);
18 |
19 | Map toJson() => $MyCoinEntityToJson(this);
20 |
21 | @override
22 | String toString() {
23 | return jsonEncode(this);
24 | }
25 |
26 | /// Dart的可选类型没有解包运算符https://cloud.tencent.com/developer/ask/sof/1357979/answer/1869854
27 | String get userInfo {
28 | if (rank != null && level != null && coinCount != null) {
29 | return "排名: $rank! 等级: $level 积分: $coinCount";
30 | } else {
31 | return "排名: -- 等级: -- 积分: --";
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/lib/entity/my_coin_history_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:getx_study/generated/json/base/json_field.dart';
2 | import 'package:getx_study/generated/json/my_coin_history_entity.g.dart';
3 | import 'dart:convert';
4 |
5 | @JsonSerializable()
6 | class MyCoinHistoryEntity {
7 |
8 | int? curPage;
9 | List? datas;
10 | int? offset;
11 | bool? over;
12 | int? pageCount;
13 | int? size;
14 | int? total;
15 |
16 | MyCoinHistoryEntity();
17 |
18 | factory MyCoinHistoryEntity.fromJson(Map json) => $MyCoinHistoryEntityFromJson(json);
19 |
20 | Map toJson() => $MyCoinHistoryEntityToJson(this);
21 |
22 | @override
23 | String toString() {
24 | return jsonEncode(this);
25 | }
26 | }
27 |
28 | @JsonSerializable()
29 | class MyCoinHistoryDatas {
30 |
31 | int? coinCount;
32 | int? date;
33 | String? desc;
34 | int? id;
35 | String? reason;
36 | int? type;
37 | int? userId;
38 | String? userName;
39 |
40 | MyCoinHistoryDatas();
41 |
42 | factory MyCoinHistoryDatas.fromJson(Map json) => $MyCoinHistoryDatasFromJson(json);
43 |
44 | Map toJson() => $MyCoinHistoryDatasToJson(this);
45 |
46 | @override
47 | String toString() {
48 | return jsonEncode(this);
49 | }
50 | }
--------------------------------------------------------------------------------
/lib/entity/page_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:getx_study/entity/i_entity.dart';
2 | import 'package:getx_study/resource/constant.dart';
3 |
4 | /// 有关与BaseEntity>这种泛型解析我还没有找个非常好的方案,目前还是保证单层解析
5 | class PageEntity extends IEntity {
6 | int? curPage;
7 | T? dataSource;
8 | int? offset;
9 | bool? over;
10 | int? pageCount;
11 | int? size;
12 | int? total;
13 |
14 | PageEntity.fromJson(Map json) {
15 | curPage = json[Constant.curPage] as int?;
16 | offset = json[Constant.offset] as int?;
17 | over = json[Constant.over] as bool?;
18 | pageCount = json[Constant.pageCount] as int?;
19 | size = json[Constant.size] as int?;
20 | total = json[Constant.total] as int?;
21 | if (json.containsKey(Constant.datas)) {
22 | dataSource = generateOBJ(json[Constant.datas] as Object);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/entity/pageable.dart:
--------------------------------------------------------------------------------
1 | // abstract class Pageable {
2 | // int? curPage;
3 | // T? datas;
4 | // int? offset;
5 | // bool? over;
6 | // int? pageCount;
7 | // int? size;
8 | // int? total;
9 | // }
10 |
11 | abstract class Pageable {
12 | int? curPage;
13 | int? offset;
14 | bool? over;
15 | int? pageCount;
16 | int? size;
17 | int? total;
18 | }
--------------------------------------------------------------------------------
/lib/entity/tab_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:getx_study/generated/json/base/json_field.dart';
2 | import 'package:getx_study/generated/json/tab_entity.g.dart';
3 | import 'dart:convert';
4 |
5 | @JsonSerializable()
6 | class TabEntity {
7 |
8 | List? children;
9 | int? courseId;
10 | int? id;
11 | String? name;
12 | int? order;
13 | int? parentChapterId;
14 | bool? userControlSetTop;
15 | int? visible;
16 |
17 | TabEntity();
18 |
19 | factory TabEntity.fromJson(Map json) => $TabEntityFromJson(json);
20 |
21 | Map toJson() => $TabEntityToJson(this);
22 |
23 | @override
24 | String toString() {
25 | return jsonEncode(this);
26 | }
27 | }
--------------------------------------------------------------------------------
/lib/enum/collect_action_type.dart:
--------------------------------------------------------------------------------
1 | enum CollectActionType {
2 | collect,
3 | unCollect;
4 | }
5 |
--------------------------------------------------------------------------------
/lib/enum/main_tag_type.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:getx_study/enum/tag_type.dart';
3 |
4 | import 'package:getx_study/pages/home/view/home_page.dart';
5 | import 'package:getx_study/pages/my/view/my_page.dart';
6 | import 'package:getx_study/pages/tree/view/tabs_page.dart';
7 | import 'package:getx_study/pages/tree/view/tree_page.dart';
8 |
9 | enum MainTagType {
10 | home,
11 | project,
12 | publicNumber,
13 | tree,
14 | my;
15 | }
16 |
17 | extension MainTagTypeExt on MainTagType {
18 | IconData get icon {
19 | switch (this) {
20 | case MainTagType.home:
21 | return Icons.home;
22 | case MainTagType.project:
23 | return Icons.web;
24 | case MainTagType.publicNumber:
25 | return Icons.public;
26 | case MainTagType.tree:
27 | return Icons.list;
28 | case MainTagType.my:
29 | return Icons.person;
30 | }
31 | }
32 |
33 | String get title {
34 | switch (this) {
35 | case MainTagType.home:
36 | return "首页";
37 | case MainTagType.project:
38 | return "项目";
39 | case MainTagType.publicNumber:
40 | return "公众号";
41 | case MainTagType.tree:
42 | return "体系";
43 | case MainTagType.my:
44 | return "我的";
45 | }
46 | }
47 |
48 | Widget get page {
49 | switch (this) {
50 | case MainTagType.home:
51 | return const HomePage();
52 | case MainTagType.project:
53 | return const TabsPage(type: TagType.project);
54 | case MainTagType.publicNumber:
55 | return const TabsPage(type: TagType.publicNumber);
56 | case MainTagType.tree:
57 | return const TreePage();
58 | case MainTagType.my:
59 | return const MyPage();
60 | }
61 | }
62 |
63 | static List get items {
64 | return MainTagType.values
65 | .map(
66 | (type) => BottomNavigationBarItem(
67 | icon: Icon(type.icon),
68 | label: type.title,
69 | ),
70 | )
71 | .toList();
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/lib/enum/response_status.dart:
--------------------------------------------------------------------------------
1 | enum SuccessStatus {
2 | hasContent(2),
3 | empty(3);
4 |
5 | final int value;
6 | const SuccessStatus(this.value);
7 |
8 | @override
9 | String toString() => 'The $name value is $value';
10 | }
11 |
12 | enum ResponseStatus {
13 | loading(0),
14 | fail(1),
15 | successHasContent(2),
16 | successNoData(3);
17 |
18 | final int value;
19 | const ResponseStatus(this.value);
20 |
21 | @override
22 | String toString() => 'The $name value is $value';
23 | }
24 |
25 | /// 这是Dart新特性的例子
26 | enum Water {
27 | frozen(0),
28 | lukewarm(40),
29 | boiling(100);
30 |
31 | final int temperature;
32 | const Water(this.temperature);
33 |
34 | @override
35 | String toString() => 'The $name water is $temperature';
36 | }
37 |
38 | /// 有关于枚举里面加泛型
39 | enum Season {
40 | spring("好"),
41 | summer(true),
42 | autumn(100),
43 | winter([]);
44 |
45 | final T value;
46 | const Season(this.value);
47 | }
48 |
49 | final season = Season.spring.value;
50 |
--------------------------------------------------------------------------------
/lib/enum/scroll_view_action_type.dart:
--------------------------------------------------------------------------------
1 | /// 上下拉行为类型
2 | enum ScrollViewActionType {
3 | refresh,
4 | loadMore;
5 | }
6 |
--------------------------------------------------------------------------------
/lib/enum/tag_type.dart:
--------------------------------------------------------------------------------
1 | import 'package:getx_study/http_util/api.dart';
2 |
3 | enum TagType {
4 | project,
5 | publicNumber,
6 | tree;
7 | }
8 |
9 | extension Ext on TagType {
10 | String get title {
11 | switch (this) {
12 | case TagType.project:
13 | return "项目";
14 | case TagType.publicNumber:
15 | return "公众号";
16 | case TagType.tree:
17 | return "体系";
18 | }
19 | }
20 |
21 | int get pageNum {
22 | switch (this) {
23 | case TagType.project:
24 | return 1;
25 | case TagType.publicNumber:
26 | return 1;
27 | case TagType.tree:
28 | return 0;
29 | }
30 | }
31 |
32 | String get tabApi {
33 | switch (this) {
34 | case TagType.project:
35 | return Api.getProjectClassify;
36 | case TagType.publicNumber:
37 | return Api.getPublicNumber;
38 | case TagType.tree:
39 | return Api.getTree;
40 | }
41 | }
42 |
43 | String get detailApi {
44 | switch (this) {
45 | case TagType.project:
46 | return Api.getProjectClassifyList;
47 | case TagType.publicNumber:
48 | return Api.getPublicNumberList;
49 | case TagType.tree:
50 | return Api.getTreeDetailList;
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/lib/example_app/example_routes.dart:
--------------------------------------------------------------------------------
1 | import 'package:get/get.dart';
2 | import 'package:getx_study/example_app/get_x_app.dart';
3 |
4 | abstract class Routes {
5 | Routes._();
6 |
7 | static const getXExamplePage = "/getXExamplePage";
8 |
9 | static const getxRxExamplePage = "/getxRxExamplePage";
10 |
11 | ///页面合集
12 | static final routePage = [
13 |
14 | GetPage(
15 | name: getXExamplePage,
16 | page: () => const GetXExamplePage(),
17 | binding: GetXExampleBindings(),
18 | ),
19 | GetPage(
20 | name: getxRxExamplePage,
21 | page: () => GetxRxExamplePage(),
22 | binding: GetxRxExampleBindings(),
23 | ),
24 | ];
25 | }
--------------------------------------------------------------------------------
/lib/example_app/rx_dart_app.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/material.dart';
4 |
5 | import 'package:rxdart/rxdart.dart';
6 |
7 | class RxDartApp extends StatelessWidget {
8 | @override
9 | Widget build(BuildContext context) {
10 | return MaterialApp(
11 | home: RxDartExamplePage(),
12 | );
13 | }
14 | }
15 |
16 | class RxDartExamplePage extends StatelessWidget {
17 | RxDartExamplePage({Key? key}) : super(key: key);
18 |
19 | final _viewModel = RxDartExampleViewModel();
20 |
21 | @override
22 | Widget build(BuildContext context) {
23 | return Scaffold(
24 | appBar: AppBar(
25 | title: const Text("RxDart编写计数器"),
26 | ),
27 | body: Center(
28 | child: Column(
29 | mainAxisAlignment: MainAxisAlignment.center,
30 | children: [
31 | const Text(
32 | 'You have pushed the button this many times:',
33 | ),
34 | StreamBuilder(
35 | stream: _viewModel.stream,
36 | builder: (context, snapshot) {
37 | return Text(
38 | snapshot.data.toString(),
39 | //_viewModel.stream.value.toString(),
40 | style: Theme.of(context).textTheme.headlineMedium,
41 | );
42 | },
43 | ),
44 | ],
45 | ),
46 | ),
47 | floatingActionButton: FloatingActionButton(
48 | onPressed: _viewModel.increment,
49 | tooltip: 'Increment',
50 | child: const Icon(Icons.add),
51 | ),
52 | );
53 | }
54 | }
55 |
56 | class RxDartExampleViewModel {
57 | final _subject = BehaviorSubject.seeded(0);
58 |
59 | ValueStream get stream => _subject.stream;
60 |
61 | void increment() {
62 | _subject.add(_subject.value + 1);
63 | }
64 |
65 | void dispose() {
66 | _subject.close();
67 | }
68 | }
69 |
70 | /// 尝试使用了PublishSubject,但是感觉和BehaviorSubject差不多
71 | class RxDartExampleViewModel2 {
72 | final _subject = PublishSubject();
73 |
74 | var _count = 0;
75 |
76 | Stream get stream => _subject.stream;
77 |
78 | StreamSink get sink => _subject.sink;
79 |
80 | RxDartExampleViewModel2() {
81 | _subject.startWith(_count);
82 | }
83 |
84 | void increment() {
85 | ++_count;
86 | _subject.add(_count);
87 | }
88 |
89 | void dispose() {
90 | _subject.close();
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/lib/example_app/stream_app.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/material.dart';
4 |
5 | class StreamApp extends StatelessWidget {
6 | @override
7 | Widget build(BuildContext context) {
8 | return MaterialApp(
9 | home: StreamExamplePage(),
10 | );
11 | }
12 | }
13 |
14 | class StreamExamplePage extends StatelessWidget {
15 | StreamExamplePage({Key? key}) : super(key: key);
16 |
17 | final _viewModel = StreamExampleViewModel();
18 |
19 | @override
20 | Widget build(BuildContext context) {
21 | return Scaffold(
22 | appBar: AppBar(
23 | title: const Text("RxDart编写计数器"),
24 | ),
25 | body: Center(
26 | child: Column(
27 | mainAxisAlignment: MainAxisAlignment.center,
28 | children: [
29 | const Text(
30 | 'You have pushed the button this many times:',
31 | ),
32 | StreamBuilder(
33 | initialData: 0,
34 | stream: _viewModel.stream,
35 | builder: (context, snapshot) {
36 | return Text(
37 | snapshot.data.toString(),
38 | //_viewModel.stream.value.toString(),
39 | style: Theme.of(context).textTheme.headlineMedium,
40 | );
41 | },
42 | ),
43 | ],
44 | ),
45 | ),
46 | floatingActionButton: FloatingActionButton(
47 | onPressed: _viewModel.increment,
48 | tooltip: 'Increment',
49 | child: const Icon(Icons.add),
50 | ),
51 | );
52 | }
53 | }
54 |
55 | class StreamExampleViewModel {
56 | final _controller = StreamController();
57 |
58 | var _count = 0;
59 |
60 | Stream get stream => _controller.stream;
61 |
62 | void increment() {
63 | ++_count;
64 | _controller.sink.add(_count);
65 | }
66 |
67 | void dispose() {
68 | _controller.close();
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/lib/extension/future_extension.dart:
--------------------------------------------------------------------------------
1 | /*
2 | import 'dart:async';
3 |
4 | /// https://juejin.cn/post/7372503361361068082
5 | /// This requires the 'records' language feature to be enabled.
6 | /// Try updating your pubspec.yaml to set the minimum SDK constraint to 3.0.0 or higher, and running 'pub get'.
7 | extension FutureZipX on Future {
8 | Future<(T, T2)> zipWith(Future future2) async {
9 | late T result1;
10 | late T2 result2;
11 | await Future.wait([
12 | then((it) => result1 = it),
13 | future2.then((it) => result2 = it)
14 | ]);
15 | return (result1, result2);
16 | }
17 | }
18 |
19 | final (name, year, married) = await (
20 | Future.value("andrew"),
21 | Future.value(1984),
22 | Future.value(false),
23 | ).wait;
24 |
25 | final (name, year) = await Future.value("andrew")
26 | .zipWith(Future.value(1984));
27 | */
--------------------------------------------------------------------------------
/lib/extension/get_route_extension.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'package:get/get.dart';
4 |
5 | import 'package:getx_study/routes/history_router_observer.dart';
6 |
7 | /// https://juejin.cn/post/7283315133140107304
8 | extension GetRouteExtension on GetInterface {
9 | ///路由历史
10 | List> get history => historyRouterObserver.history;
11 |
12 | ///是否已打开该页面
13 | bool containName(String name) {
14 | return getRouteByName(name) != null;
15 | }
16 |
17 | ///通过name获取route,从栈顶开始查找
18 | Route? getRouteByName(String name) {
19 | var index =
20 | history.lastIndexWhere((element) => element.settings.name == name);
21 | if (index != -1) {
22 | return history[index];
23 | }
24 | return null;
25 | }
26 |
27 | ///通过name获取route
28 | List getRoutesByName(String name) {
29 | return history.where((element) => element.settings.name == name).toList();
30 | }
31 |
32 | ///移除指定的页面,一次
33 | void removeName(String name) {
34 | var route = getRouteByName(name);
35 | if (route != null) {
36 | if (history.last == route) {
37 | //移除当前页面,直接返回
38 | Get.back();
39 | } else {
40 | Get.removeRoute(route);
41 | }
42 | }
43 | }
44 |
45 | ///移除所有指定的页面
46 | void removeAllName(String name) {
47 | var routes = getRoutesByName(name);
48 | for (var route in routes) {
49 | Get.removeRoute(route);
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/lib/extension/string_extension.dart:
--------------------------------------------------------------------------------
1 | // 用于String替换掉Html元素的分类
2 | extension Extension on String {
3 | String get replaceHtmlElement {
4 | return replaceAll(RegExp("(]*>)|()"), "")
5 | .replaceAll(RegExp("\n{2,}"), "\n")
6 | .replaceAll(RegExp("s{2,}"), " ")
7 | .replaceAll("–", "–")
8 | .replaceAll("—", "—")
9 | .replaceAll("‘", "‘")
10 | .replaceAll("’", "’")
11 | .replaceAll("‚", "‚")
12 | .replaceAll("“", "“")
13 | .replaceAll("”", "”")
14 | .replaceAll("„", "„")
15 | .replaceAll("‰", "‰")
16 | .replaceAll("‹", "‹")
17 | .replaceAll("›", "›")
18 | .replaceAll("€", "€")
19 | .replaceAll("", "")
20 | .replaceAll("
", "")
21 | .replaceAll("", "\n")
22 | .replaceAll("
", "\n")
23 | .replaceAll("<", "<")
24 | .replaceAll(">", ">")
25 | .replaceAll(" ", " ")
26 | .replaceAll("&", "&")
27 | .replaceAll(""", "\"")
28 | .replaceAll("¥", "¥");
29 | }
30 | }
--------------------------------------------------------------------------------
/lib/generated/assets.dart:
--------------------------------------------------------------------------------
1 | ///This file is automatically generated. DO NOT EDIT, all your changes would be lost.
2 | class Assets {
3 | Assets._();
4 |
5 | static const String assetsHtmlIndex = 'assets/html/index.html';
6 | static const String assetsImagesIcEye = 'assets/images/ic_eye.png';
7 | static const String assetsImagesIcHead = 'assets/images/ic_head.jpeg';
8 | static const String assetsImagesLaunchImage = 'assets/images/launchImage.png';
9 | static const String assetsImagesPlaceholder = 'assets/images/placeholder.png';
10 | static const String assetsImagesSaber = 'assets/images/saber.jpg';
11 | static const String assetsImagesSaberLogo = 'assets/images/saber_logo.jpg';
12 | static const String assetsImagesSeasonAliPay = 'assets/images/season_ali_pay.jpg';
13 | static const String assetsImagesUpgrade = 'assets/images/upgrade.png';
14 | static const String assetsImagesWelcome1 = 'assets/images/welcome_1.png';
15 | static const String assetsImagesWelcome2 = 'assets/images/welcome_2.jpg';
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/lib/generated/json/banner_entity.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:getx_study/generated/json/base/json_convert_content.dart';
2 | import 'package:getx_study/entity/banner_entity.dart';
3 |
4 | BannerEntity $BannerEntityFromJson(Map json) {
5 | final BannerEntity bannerEntity = BannerEntity();
6 | final String? desc = jsonConvert.convert(json['desc']);
7 | if (desc != null) {
8 | bannerEntity.desc = desc;
9 | }
10 | final int? id = jsonConvert.convert(json['id']);
11 | if (id != null) {
12 | bannerEntity.id = id;
13 | }
14 | final String? imagePath = jsonConvert.convert(json['imagePath']);
15 | if (imagePath != null) {
16 | bannerEntity.imagePath = imagePath;
17 | }
18 | final double? isVisible = jsonConvert.convert(json['isVisible']);
19 | if (isVisible != null) {
20 | bannerEntity.isVisible = isVisible;
21 | }
22 | final double? order = jsonConvert.convert(json['order']);
23 | if (order != null) {
24 | bannerEntity.order = order;
25 | }
26 | final String? title = jsonConvert.convert(json['title']);
27 | if (title != null) {
28 | bannerEntity.title = title;
29 | }
30 | final double? type = jsonConvert.convert(json['type']);
31 | if (type != null) {
32 | bannerEntity.type = type;
33 | }
34 | final String? url = jsonConvert.convert(json['url']);
35 | if (url != null) {
36 | bannerEntity.url = url;
37 | bannerEntity.link = url;
38 | }
39 | return bannerEntity;
40 | }
41 |
42 | Map $BannerEntityToJson(BannerEntity entity) {
43 | final Map data = {};
44 | data['desc'] = entity.desc;
45 | data['id'] = entity.id;
46 | data['imagePath'] = entity.imagePath;
47 | data['isVisible'] = entity.isVisible;
48 | data['order'] = entity.order;
49 | data['title'] = entity.title;
50 | data['type'] = entity.type;
51 | data['url'] = entity.url;
52 | data['link'] = entity.url;
53 | return data;
54 | }
55 |
--------------------------------------------------------------------------------
/lib/generated/json/base/json_field.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: non_constant_identifier_names
2 | // ignore_for_file: camel_case_types
3 | // ignore_for_file: prefer_single_quotes
4 |
5 | // This file is automatically generated. DO NOT EDIT, all your changes would be lost.
6 |
7 | class JsonSerializable{
8 | const JsonSerializable();
9 | }
10 |
11 | class JSONField {
12 | //Specify the parse field name
13 | final String? name;
14 |
15 | //Whether to participate in toJson
16 | final bool? serialize;
17 |
18 | //Whether to participate in fromMap
19 | final bool? deserialize;
20 |
21 | const JSONField({this.name, this.serialize, this.deserialize});
22 | }
23 |
--------------------------------------------------------------------------------
/lib/generated/json/hot_key_entity.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:getx_study/generated/json/base/json_convert_content.dart';
2 | import 'package:getx_study/entity/hot_key_entity.dart';
3 |
4 | HotKeyEntity $HotKeyEntityFromJson(Map json) {
5 | final HotKeyEntity hotKeyEntity = HotKeyEntity();
6 | final double? id = jsonConvert.convert(json['id']);
7 | if (id != null) {
8 | hotKeyEntity.id = id;
9 | }
10 | final String? link = jsonConvert.convert(json['link']);
11 | if (link != null) {
12 | hotKeyEntity.link = link;
13 | }
14 | final String? name = jsonConvert.convert(json['name']);
15 | if (name != null) {
16 | hotKeyEntity.name = name;
17 | }
18 | final double? order = jsonConvert.convert(json['order']);
19 | if (order != null) {
20 | hotKeyEntity.order = order;
21 | }
22 | final double? visible = jsonConvert.convert(json['visible']);
23 | if (visible != null) {
24 | hotKeyEntity.visible = visible;
25 | }
26 | return hotKeyEntity;
27 | }
28 |
29 | Map $HotKeyEntityToJson(HotKeyEntity entity) {
30 | final Map data = {};
31 | data['id'] = entity.id;
32 | data['link'] = entity.link;
33 | data['name'] = entity.name;
34 | data['order'] = entity.order;
35 | data['visible'] = entity.visible;
36 | return data;
37 | }
--------------------------------------------------------------------------------
/lib/generated/json/my_coin_entity.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:getx_study/generated/json/base/json_convert_content.dart';
2 | import 'package:getx_study/entity/my_coin_entity.dart';
3 |
4 | MyCoinEntity $MyCoinEntityFromJson(Map json) {
5 | final MyCoinEntity myCoinEntity = MyCoinEntity();
6 | final int? coinCount = jsonConvert.convert(json['coinCount']);
7 | if (coinCount != null) {
8 | myCoinEntity.coinCount = coinCount;
9 | }
10 | final int? level = jsonConvert.convert(json['level']);
11 | if (level != null) {
12 | myCoinEntity.level = level;
13 | }
14 | final String? nickname = jsonConvert.convert(json['nickname']);
15 | if (nickname != null) {
16 | myCoinEntity.nickname = nickname;
17 | }
18 | final String? rank = jsonConvert.convert(json['rank']);
19 | if (rank != null) {
20 | myCoinEntity.rank = rank;
21 | }
22 | final int? userId = jsonConvert.convert(json['userId']);
23 | if (userId != null) {
24 | myCoinEntity.userId = userId;
25 | }
26 | final String? username = jsonConvert.convert(json['username']);
27 | if (username != null) {
28 | myCoinEntity.username = username;
29 | }
30 | return myCoinEntity;
31 | }
32 |
33 | Map $MyCoinEntityToJson(MyCoinEntity entity) {
34 | final Map data = {};
35 | data['coinCount'] = entity.coinCount;
36 | data['level'] = entity.level;
37 | data['nickname'] = entity.nickname;
38 | data['rank'] = entity.rank;
39 | data['userId'] = entity.userId;
40 | data['username'] = entity.username;
41 | return data;
42 | }
--------------------------------------------------------------------------------
/lib/generated/json/tab_entity.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:getx_study/generated/json/base/json_convert_content.dart';
2 | import 'package:getx_study/entity/tab_entity.dart';
3 |
4 | TabEntity $TabEntityFromJson(Map json) {
5 | final TabEntity tabEntity = TabEntity();
6 | final List? children = jsonConvert.convertListNotNull(json['children']);
7 | if (children != null) {
8 | tabEntity.children = children;
9 | }
10 | final int? courseId = jsonConvert.convert(json['courseId']);
11 | if (courseId != null) {
12 | tabEntity.courseId = courseId;
13 | }
14 | final int? id = jsonConvert.convert(json['id']);
15 | if (id != null) {
16 | tabEntity.id = id;
17 | }
18 | final String? name = jsonConvert.convert(json['name']);
19 | if (name != null) {
20 | tabEntity.name = name;
21 | }
22 | final int? order = jsonConvert.convert(json['order']);
23 | if (order != null) {
24 | tabEntity.order = order;
25 | }
26 | final int? parentChapterId = jsonConvert.convert(json['parentChapterId']);
27 | if (parentChapterId != null) {
28 | tabEntity.parentChapterId = parentChapterId;
29 | }
30 | final bool? userControlSetTop = jsonConvert.convert(json['userControlSetTop']);
31 | if (userControlSetTop != null) {
32 | tabEntity.userControlSetTop = userControlSetTop;
33 | }
34 | final int? visible = jsonConvert.convert(json['visible']);
35 | if (visible != null) {
36 | tabEntity.visible = visible;
37 | }
38 | return tabEntity;
39 | }
40 |
41 | Map $TabEntityToJson(TabEntity entity) {
42 | final Map data = {};
43 | data['children'] = entity.children?.map((v) => v.toJson()).toList();
44 | data['courseId'] = entity.courseId;
45 | data['id'] = entity.id;
46 | data['name'] = entity.name;
47 | data['order'] = entity.order;
48 | data['parentChapterId'] = entity.parentChapterId;
49 | data['userControlSetTop'] = entity.userControlSetTop;
50 | data['visible'] = entity.visible;
51 | return data;
52 | }
--------------------------------------------------------------------------------
/lib/http_client/login_client.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:retrofit/retrofit.dart';
3 |
4 | import 'package:getx_study/entity/base_entity.dart';
5 | import 'package:getx_study/entity/banner_entity.dart';
6 |
7 | part 'login_client.g.dart';
8 |
9 | const timeout = Duration(seconds: 60);
10 |
11 | final _dio = Dio(
12 | BaseOptions(
13 | baseUrl: "https://www.wanandroid.com/",
14 | connectTimeout: timeout,
15 | receiveTimeout: timeout,
16 | headers: {"name": "season"},
17 | ),
18 | );
19 |
20 | /// 通过不同的client来区分不同的业务,一般情况下对于非登录和登录,使用不同的client来进行网络请求,
21 | /// 另外,只有创建这个文件,然后把`part 'login_client.g.dart';`标注好,硬着头皮跑脚本就完事了
22 | /// 回想一下,其实只需要细分不同_dio,就可以差异化不同的业务以及登录与非登录状态
23 | final loginClient = LoginClient(_dio);
24 |
25 | @RestApi(
26 | // 请求域名
27 | baseUrl: 'https://www.wanandroid.com/',
28 | // 数据解析方式,默认为json
29 | parser: Parser.JsonSerializable,
30 | )
31 |
32 | abstract class LoginClient {
33 | // 标准的构建方式
34 | // dio: 传入发起网络请求的对象
35 | // baseUrl: 请求域名,优先级高于注解
36 | factory LoginClient(Dio dio, {String baseUrl}) = _LoginClient;
37 |
38 | @GET("banner/json")
39 | Future>> getBanner();
40 | }
41 |
--------------------------------------------------------------------------------
/lib/http_client/login_client.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'login_client.dart';
4 |
5 | // **************************************************************************
6 | // RetrofitGenerator
7 | // **************************************************************************
8 |
9 | // ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers
10 |
11 | class _LoginClient implements LoginClient {
12 | _LoginClient(
13 | this._dio, {
14 | this.baseUrl,
15 | }) {
16 | baseUrl ??= 'https://www.wanandroid.com/';
17 | }
18 |
19 | final Dio _dio;
20 |
21 | String? baseUrl;
22 |
23 | @override
24 | Future>> getBanner() async {
25 | const _extra = {};
26 | final queryParameters = {};
27 | final _headers = {};
28 | final Map? _data = null;
29 | final _result = await _dio.fetch