├── .gitignore
├── .metadata
├── README.md
├── android
├── .gitignore
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── shuaishuaimovie
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── drawable
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── logo.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values
│ │ │ └── styles.xml
│ │ │ └── xml
│ │ │ ├── file_paths.xml
│ │ │ └── network_security_config.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
└── settings.gradle
├── assets
└── fonts
│ └── iconfont.ttf
├── ios
├── .gitignore
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Podfile
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
└── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-App-1024x1024@1x.png
│ │ ├── Icon-App-20x20@1x.png
│ │ ├── Icon-App-20x20@2x.png
│ │ ├── Icon-App-20x20@3x.png
│ │ ├── Icon-App-29x29@1x.png
│ │ ├── Icon-App-29x29@2x.png
│ │ ├── Icon-App-29x29@3x.png
│ │ ├── Icon-App-40x40@1x.png
│ │ ├── Icon-App-40x40@2x.png
│ │ ├── Icon-App-40x40@3x.png
│ │ ├── Icon-App-60x60@2x.png
│ │ ├── Icon-App-60x60@3x.png
│ │ ├── Icon-App-76x76@1x.png
│ │ ├── Icon-App-76x76@2x.png
│ │ └── Icon-App-83.5x83.5@2x.png
│ └── 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
├── lib
├── database
│ ├── bean
│ │ ├── search_history_bean.dart
│ │ └── video_history_bean.dart
│ └── sqf_provider.dart
├── generated
│ └── json
│ │ ├── base
│ │ ├── json_convert_content.dart
│ │ └── json_filed.dart
│ │ ├── common_item_bean_entity_helper.dart
│ │ ├── common_tab_item_bean_entity_helper.dart
│ │ ├── condition_search_bean_entity_helper.dart
│ │ ├── home_detail_bean_entity_helper.dart
│ │ ├── home_list_bean_entity_helper.dart
│ │ ├── hot_rank_bean_entity_helper.dart
│ │ ├── hot_update_bean_entity_helper.dart
│ │ ├── select_condition_bean_entity_helper.dart
│ │ └── txt_auto_search_bean_entity_helper.dart
├── images.dart
├── main.dart
├── models
│ ├── common_item_bean_entity.dart
│ ├── common_tab_item_bean_entity.dart
│ ├── condition_search_bean_entity.dart
│ ├── home_detail_bean_entity.dart
│ ├── home_list_bean_entity.dart
│ ├── hot_rank_bean_entity.dart
│ ├── hot_update_bean_entity.dart
│ ├── select_condition_bean_entity.dart
│ └── txt_auto_search_bean_entity.dart
├── net
│ ├── base_repository.dart
│ ├── base_result.dart
│ ├── request.dart
│ ├── request_const.dart
│ └── request_helper.dart
├── provider
│ ├── provider_proxy_widget.dart
│ ├── provider_setup.dart
│ ├── provider_widget.dart
│ └── view_state.dart
├── r.g.dart
├── res
│ └── app_color.dart
├── routes
│ ├── route_handlers.dart
│ ├── route_jump.dart
│ └── routes.dart
├── sharepreference
│ └── share_preference.dart
├── shuai_movie.dart
├── ui
│ ├── helper
│ │ ├── common_list_helper.dart
│ │ ├── db
│ │ │ └── db_operate.dart
│ │ ├── home_detail_list_helper.dart
│ │ ├── home_list_helper.dart
│ │ ├── hot_rank_list_helper.dart
│ │ ├── hot_update_list_helper.dart
│ │ ├── search_list_helper.dart
│ │ ├── video_history_list_helper.dart
│ │ └── view_state_helper.dart
│ └── pages
│ │ ├── history
│ │ └── video_history_page.dart
│ │ ├── hot
│ │ ├── rank
│ │ │ ├── hot_rank_page.dart
│ │ │ └── tab
│ │ │ │ ├── month_rank_page.dart
│ │ │ │ ├── total_rank_page.dart
│ │ │ │ └── week_rank_page.dart
│ │ ├── update
│ │ │ └── hot_update_page.dart
│ │ └── widget
│ │ │ ├── hot_rank_widget.dart
│ │ │ └── hot_update_widget.dart
│ │ ├── maintab
│ │ ├── cartoon
│ │ │ └── cartoon_page.dart
│ │ ├── home
│ │ │ ├── home_detail_page.dart
│ │ │ ├── home_page.dart
│ │ │ └── homewidget
│ │ │ │ ├── home_detail_widget.dart
│ │ │ │ └── home_list_widget.dart
│ │ ├── index_page.dart
│ │ ├── movie
│ │ │ └── movie_page.dart
│ │ ├── show
│ │ │ └── show_page.dart
│ │ ├── teleplay
│ │ │ └── teleplay_page.dart
│ │ └── widget
│ │ │ └── common_tab_widget.dart
│ │ ├── mine
│ │ └── mine_page.dart
│ │ ├── not_found_page.dart
│ │ ├── search
│ │ ├── condition_search_page.dart
│ │ ├── tab
│ │ │ ├── hot_search_page.dart
│ │ │ ├── new_search_page.dart
│ │ │ └── score_search_page.dart
│ │ ├── txt_search_page.dart
│ │ └── widget
│ │ │ ├── search_widget.dart
│ │ │ ├── txt_auto_search_child.dart
│ │ │ ├── txt_history_search_child.dart
│ │ │ └── txt_normal_search_child.dart
│ │ ├── splash_page.dart
│ │ └── video
│ │ ├── video_page.dart
│ │ └── widget
│ │ └── shuai_video.dart
├── utils
│ ├── app_info_util.dart
│ ├── net
│ │ └── net_work.dart
│ ├── str_util.dart
│ ├── system
│ │ └── system_chrome.dart
│ └── time
│ │ └── movie_time_util.dart
├── video
│ └── custom_video_panel.dart
├── viewmodels
│ ├── app_theme_model.dart
│ ├── base_model.dart
│ ├── base_refresh_model.dart
│ ├── history
│ │ └── video_history_model.dart
│ ├── hot
│ │ ├── hot_rank_model.dart
│ │ └── hot_update_model.dart
│ ├── search
│ │ ├── condition_search_model.dart
│ │ ├── select_condition_model.dart
│ │ ├── txt_auto_search_model.dart
│ │ ├── txt_history_search_model.dart
│ │ └── txt_normal_search_model.dart
│ ├── tab
│ │ ├── commontab
│ │ │ └── common_tab_model.dart
│ │ └── home
│ │ │ ├── home_detail_model.dart
│ │ │ ├── home_model.dart
│ │ │ └── index_model.dart
│ └── video
│ │ └── video_model.dart
└── widgets
│ ├── app_bar.dart
│ ├── checkicon.dart
│ ├── clip_widget.dart
│ ├── custom_chewie_overlay_widget.dart
│ ├── custom_controls.dart
│ ├── custom_progress_paint.dart
│ ├── custom_refresh_widget.dart
│ ├── panel_widget.dart
│ ├── rating_bar.dart
│ ├── refresh_widget.dart
│ ├── smarquee_widget.dart
│ ├── tag_widget.dart
│ ├── text_widget.dart
│ └── toggle_rotate.dart
├── pubspec.yaml
├── resource
├── detail_page.gif
├── drop_style.gif
├── history.gif
├── home.gif
├── play_video.gif
├── selection_search.gif
└── text_search.gif
└── test
└── widget_test.dart
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | .dart_tool/
26 | .flutter-plugins
27 | .flutter-plugins-dependencies
28 | .packages
29 | .pub-cache/
30 | .pub/
31 | /build/
32 |
33 | # Web related
34 | lib/generated_plugin_registrant.dart
35 |
36 | # Symbolication related
37 | app.*.symbols
38 |
39 | # Obfuscation related
40 | app.*.map.json
41 |
42 | # Exceptions to above rules.
43 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
44 |
--------------------------------------------------------------------------------
/.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: e6b34c2b5c96bb95325269a29a84e83ed8909b5f
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # shuaishuai_movie
2 | 基于Provider+MVVM的Flutter 视频App项目,帅帅影视是一个含有海量视频的app,各种视频随你来看。
3 |
4 | # 先来点样图
5 |
6 | |  |  | |
7 | | --- | --- | --- |
8 | ||  | |
9 | |  | |
10 |
11 |
12 | **主要使用到的一些三方库:**
13 |
14 | |**第三方库** |**功能** |**github地址** |
15 | | ---- | ---- |---- |
16 | | dio | 网络请求 | https://github.com/flutterchina/dio|
17 | | video_player | 视频播放 |https://github.com/flutter/plugins/tree/master/packages/video_player|
18 | | chewie | 视频播放 | https://github:com/brianegan/chewie |
19 | | fluro | 路由跳转 | https://github.com/theyakka/fluro |
20 | | connectivity | 网络变化监听 | https://pub.dev/packages/connectivity |
21 | | flutter_easyrefresh | 上拉加载下拉刷新 | https://github.com/xuelongqy/flutter_easyrefresh |
22 | | flutter_sticky_header | 粘性头部 | https://github.com/letsar/flutter_sticky_header |
23 | | cached_network_image | 图片缓存 | https://github.com/Baseflow/flutter_cached_network_image |
24 | | fluttertoast | 吐司 | https://github.com/ponnamkarthik/FlutterToast |
25 | | shared_preferences | shared存储 | https://pub.dev/packages?q=shared_preferences |
26 |
27 | # 更新
28 |
29 | ## V1.1.0 `2020-09-08`
30 | - 修复视频快速切换bug
31 | - 视频播放器添加手势滑动调整音量和亮度
32 | - 修改文字搜索历史逻辑
33 | - 修改部分icon图标
34 |
35 | ## V1.0.0 `2020-08-19`
36 | - 添加留言模块
37 | - 添加历史记录可以点击继续观看功能
38 | - 添加控制视频是否自动播放功能
39 | - 添加启动页闪屏动画功能
40 |
41 | ## V0.0.1 `2020-08-04`
42 | - 帅帅影视的基本功能已完成
43 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
--------------------------------------------------------------------------------
/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 | compileSdkVersion 28
30 |
31 | sourceSets {
32 | main.java.srcDirs += 'src/main/kotlin'
33 | }
34 |
35 | lintOptions {
36 | disable 'InvalidPackage'
37 | }
38 |
39 | defaultConfig {
40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
41 | applicationId "com.example.shuaishuaimovie"
42 | minSdkVersion 16
43 | targetSdkVersion 28
44 | versionCode flutterVersionCode.toInteger()
45 | versionName flutterVersionName
46 | }
47 |
48 | buildTypes {
49 | release {
50 | // TODO: Add your own signing config for the release build.
51 | // Signing with the debug keys for now, so `flutter run --release` works.
52 | signingConfig signingConfigs.debug
53 | }
54 | }
55 | }
56 |
57 | flutter {
58 | source '../..'
59 | }
60 |
61 | dependencies {
62 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
63 | }
64 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
9 |
16 |
20 |
24 |
29 |
33 |
36 |
37 |
38 |
39 |
40 |
41 |
43 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/example/shuaishuaimovie/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.shuaishuaimovie
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | -
8 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/android/app/src/main/res/mipmap-xxhdpi/logo.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/xml/file_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/android/app/src/main/res/xml/network_security_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.50'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.5.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.enableR8=true
3 | android.useAndroidX=true
4 | android.enableJetifier=true
5 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/assets/fonts/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/assets/fonts/iconfont.ttf
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/app.flx
22 | Flutter/app.zip
23 | Flutter/flutter_assets/
24 | Flutter/flutter_export_environment.sh
25 | ServiceDefinitions.json
26 | Runner/GeneratedPluginRegistrant.*
27 |
28 | # Exceptions to above rules.
29 | !default.mode1v3
30 | !default.mode2v3
31 | !default.pbxuser
32 | !default.perspectivev3
33 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
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 | 8.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, '9.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def parse_KV_file(file, separator='=')
14 | file_abs_path = File.expand_path(file)
15 | if !File.exists? file_abs_path
16 | return [];
17 | end
18 | generated_key_values = {}
19 | skip_line_start_symbols = ["#", "/"]
20 | File.foreach(file_abs_path) do |line|
21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
22 | plugin = line.split(pattern=separator)
23 | if plugin.length == 2
24 | podname = plugin[0].strip()
25 | path = plugin[1].strip()
26 | podpath = File.expand_path("#{path}", file_abs_path)
27 | generated_key_values[podname] = podpath
28 | else
29 | puts "Invalid plugin specification: #{line}"
30 | end
31 | end
32 | generated_key_values
33 | end
34 |
35 | target 'Runner' do
36 | use_frameworks!
37 | use_modular_headers!
38 |
39 | # Flutter Pod
40 |
41 | copied_flutter_dir = File.join(__dir__, 'Flutter')
42 | copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework')
43 | copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec')
44 | unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path)
45 | # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet.
46 | # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration.
47 | # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist.
48 |
49 | generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig')
50 | unless File.exist?(generated_xcode_build_settings_path)
51 | raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first"
52 | end
53 | generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path)
54 | cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR'];
55 |
56 | unless File.exist?(copied_framework_path)
57 | FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir)
58 | end
59 | unless File.exist?(copied_podspec_path)
60 | FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir)
61 | end
62 | end
63 |
64 | # Keep pod path relative so it can be checked into Podfile.lock.
65 | pod 'Flutter', :path => 'Flutter'
66 |
67 | # Plugin Pods
68 |
69 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
70 | # referring to absolute paths on developers' machines.
71 | system('rm -rf .symlinks')
72 | system('mkdir -p .symlinks/plugins')
73 | plugin_pods = parse_KV_file('../.flutter-plugins')
74 | plugin_pods.each do |name, path|
75 | symlink = File.join('.symlinks', 'plugins', name)
76 | File.symlink(path, symlink)
77 | pod name, :path => File.join(symlink, 'ios')
78 | end
79 | end
80 |
81 | post_install do |installer|
82 | installer.pods_project.targets.each do |target|
83 | target.build_configurations.each do |config|
84 | config.build_settings['ENABLE_BITCODE'] = 'NO'
85 | end
86 | end
87 | end
88 |
--------------------------------------------------------------------------------
/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.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridfish/shuaishuai_film/00c0255b9be9a864cafa7efcdb9c71dd9ef861de/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | shuaishuaimovie
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/lib/database/bean/search_history_bean.dart:
--------------------------------------------------------------------------------
1 |
2 |
3 | final String tableName = "search_history_table";
4 | final String columnName = 'name';
5 |
6 | class SearchHistoryBean {
7 | String name;
8 |
9 | Map toMap() {
10 | var map = {
11 | columnName: name,
12 | };
13 |
14 | return map;
15 | }
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/lib/database/bean/video_history_bean.dart:
--------------------------------------------------------------------------------
1 | final String tableName = "video_history_table";
2 | final String columnPicUrl = 'pic_url';
3 | final String columnVideoName = 'video_name';
4 | final String columnVideoId = 'video_id';
5 | final String columnCurrentPlayTime = "current_play_time";
6 | final String columnTotalPlayTime = "total_play_time";
7 | final String columnUpdateInfo = "update_info";
8 | final String columnMilliseconds = "milliseconds";
9 | final String columnVideoLevel = "video_level";
10 | final String columnPlayUrlType = "play_url_type";
11 | final String columnPlayUrlIndex = "play_url_index";
12 | final String columnVideoUrl = "video_url";
13 | final String columnVideoIsPositive = "video_ispositive";
14 |
15 | class VideoHistoryBean {
16 | String picUrl;
17 | String videoName;
18 | String updateInfo;
19 | String videoLevel;
20 | String playUrlType;
21 | String videoUrl;
22 | String isPositive;
23 | int videoId;
24 | int currentPlayTime;
25 | int totalPlayTime;
26 | int milliseconds;
27 | int playUrlIndex;
28 |
29 | Map toMap() {
30 | var map = {
31 | columnVideoName: videoName,
32 | columnPicUrl: picUrl,
33 | columnVideoId: videoId,
34 | columnCurrentPlayTime: currentPlayTime,
35 | columnTotalPlayTime: totalPlayTime,
36 | columnUpdateInfo: updateInfo,
37 | columnMilliseconds: milliseconds,
38 | columnPlayUrlIndex: playUrlIndex,
39 | columnPlayUrlType: playUrlType,
40 | columnVideoLevel: videoLevel,
41 | columnVideoUrl: videoUrl,
42 | columnVideoIsPositive: isPositive,
43 | };
44 |
45 | return map;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/lib/database/sqf_provider.dart:
--------------------------------------------------------------------------------
1 | import 'package:sqflite/sqflite.dart';
2 | import 'package:path/path.dart';
3 | import 'bean/search_history_bean.dart' as searchHistoryTable;
4 | import 'bean/video_history_bean.dart' as videoHistoryTable;
5 |
6 | class SqfProvider {
7 | static Database db;
8 | static const int DB_VERSION = 1;
9 |
10 | static Future initSQF() async {
11 | String databasesPath = await getDatabasesPath();
12 | // Database Path: /data/user/0/com.package.name/databases
13 | String path = join(databasesPath, 'shuaishuai_movie.db');
14 | // Path: /data/user/0/com.example.shuaishuaimovie/databases/shuaishuai_movie.db
15 | db = await openDatabase(
16 | path,
17 | version: DB_VERSION,
18 | onCreate: (Database db, int version) async {
19 | // 表格创建等初始化操作, 因为该项目的表格需要的不多,所以就一次性创建
20 | await db.execute(
21 | 'CREATE TABLE ${searchHistoryTable.tableName} (id INTEGER PRIMARY KEY, ${searchHistoryTable.columnName} TEXT)');
22 | await db.execute(
23 | 'CREATE TABLE ${videoHistoryTable.tableName} (id INTEGER PRIMARY KEY, ${videoHistoryTable.columnVideoName} TEXT, ${videoHistoryTable.columnPicUrl} TEXT, ${videoHistoryTable.columnUpdateInfo} TEXT, ${videoHistoryTable.columnVideoLevel} TEXT, ${videoHistoryTable.columnPlayUrlType} TEXT, ${videoHistoryTable.columnVideoUrl} TEXT, ${videoHistoryTable.columnVideoIsPositive} TEXT, ${videoHistoryTable.columnVideoId} INTEGER, ${videoHistoryTable.columnCurrentPlayTime} INTEGER, ${videoHistoryTable.columnTotalPlayTime} INTEGER, ${videoHistoryTable.columnMilliseconds} INTEGER, ${videoHistoryTable.columnPlayUrlIndex} INTEGER)')
24 | .catchError((error) {
25 | print(error);
26 | });
27 | },
28 | onUpgrade: (Database db, int oldVersion, int newVersion) async {
29 | // 数据库升级
30 | },
31 | );
32 | }
33 |
34 | // 获取数据库中所有的表
35 | static Future getTables() async {
36 | if (db == null) {
37 | return Future.value([]);
38 | }
39 | List tables = await db
40 | .rawQuery('SELECT name FROM sqlite_master WHERE type = "table"');
41 | List targetList = [];
42 | tables.forEach((item) {
43 | targetList.add(item['name']);
44 | });
45 | return targetList;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/lib/generated/json/base/json_filed.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 JSONField {
8 | //Specify the parse field name
9 | final String name;
10 |
11 | //Specify the time resolution format
12 | final String format;
13 |
14 | //Whether to participate in toJson
15 | final bool serialize;
16 |
17 | //Whether to participate in fromMap
18 | final bool deserialize;
19 |
20 | const JSONField({this.name, this.format, this.serialize, this.deserialize});
21 | }
22 |
--------------------------------------------------------------------------------
/lib/generated/json/common_item_bean_entity_helper.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/models/common_item_bean_entity.dart';
2 |
3 | commonItemBeanFromJson(CommonItemBean data, Map json) {
4 | if (json['VodID'] != null) {
5 | data.vodID = json['VodID']?.toInt();
6 | }
7 | if (json['VodName'] != null) {
8 | data.vodName = json['VodName']?.toString();
9 | }
10 | if (json['VodPic'] != null) {
11 | data.vodPic = json['VodPic']?.toString();
12 | }
13 | if (json['VodYear'] != null) {
14 | data.vodYear = json['VodYear']?.toString();
15 | }
16 | if (json['VodArea'] != null) {
17 | data.vodArea = json['VodArea']?.toString();
18 | }
19 | if (json['VodRemarks'] != null) {
20 | data.vodRemarks = json['VodRemarks']?.toString();
21 | }
22 | if (json['VodHits'] != null) {
23 | data.vodHits = json['VodHits']?.toInt();
24 | }
25 | if (json['VodActor'] != null) {
26 | data.vodActor = json['VodActor']?.toString();
27 | }
28 | if (json['VodDirector'] != null) {
29 | data.vodDirector = json['VodDirector']?.toString();
30 | }
31 | if (json['VodTime'] != null) {
32 | data.vodTime = json['VodTime']?.toInt();
33 | }
34 | if (json['VodTypeID'] != null) {
35 | data.vodTypeID = json['VodTypeID']?.toInt();
36 | }
37 | if (json['VodClass'] != null) {
38 | data.vodClass = new CommonItemBeanVodClass().fromJson(json['VodClass']);
39 | }
40 | return data;
41 | }
42 |
43 | Map commonItemBeanToJson(CommonItemBean entity) {
44 | final Map data = new Map();
45 | data['VodID'] = entity.vodID;
46 | data['VodName'] = entity.vodName;
47 | data['VodPic'] = entity.vodPic;
48 | data['VodYear'] = entity.vodYear;
49 | data['VodArea'] = entity.vodArea;
50 | data['VodRemarks'] = entity.vodRemarks;
51 | data['VodHits'] = entity.vodHits;
52 | data['VodActor'] = entity.vodActor;
53 | data['VodDirector'] = entity.vodDirector;
54 | data['VodTime'] = entity.vodTime;
55 | data['VodTypeID'] = entity.vodTypeID;
56 | if (entity.vodClass != null) {
57 | data['VodClass'] = entity.vodClass.toJson();
58 | }
59 | return data;
60 | }
61 |
62 | commonItemBeanVodClassFromJson(CommonItemBeanVodClass data, Map json) {
63 | if (json['TypeID'] != null) {
64 | data.typeID = json['TypeID']?.toInt();
65 | }
66 | if (json['TypeName'] != null) {
67 | data.typeName = json['TypeName']?.toString();
68 | }
69 | return data;
70 | }
71 |
72 | Map commonItemBeanVodClassToJson(CommonItemBeanVodClass entity) {
73 | final Map data = new Map();
74 | data['TypeID'] = entity.typeID;
75 | data['TypeName'] = entity.typeName;
76 | return data;
77 | }
--------------------------------------------------------------------------------
/lib/generated/json/common_tab_item_bean_entity_helper.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/models/common_item_bean_entity.dart';
2 | import 'package:shuaishuaimovie/models/common_tab_item_bean_entity.dart';
3 |
4 | commonTabItemBeanEntityFromJson(CommonTabItemBeanEntity data, Map json) {
5 | if (json['data'] != null) {
6 | data.data = new List();
7 | (json['data'] as List).forEach((v) {
8 | data.data.add(new CommonTabItemBeanData().fromJson(v));
9 | });
10 | }
11 | if (json['status'] != null) {
12 | data.status = json['status']?.toInt();
13 | }
14 | return data;
15 | }
16 |
17 | Map commonTabItemBeanEntityToJson(CommonTabItemBeanEntity entity) {
18 | final Map data = new Map();
19 | if (entity.data != null) {
20 | data['data'] = entity.data.map((v) => v.toJson()).toList();
21 | }
22 | data['status'] = entity.status;
23 | return data;
24 | }
25 |
26 | commonTabItemBeanDataFromJson(CommonTabItemBeanData data, Map json) {
27 | if (json['ID'] != null) {
28 | data.iD = json['ID']?.toInt();
29 | }
30 | if (json['Name'] != null) {
31 | data.name = json['Name']?.toString();
32 | }
33 | if (json['Items'] != null) {
34 | data.items = new List();
35 | (json['Items'] as List).forEach((v) {
36 | data.items.add(new CommonItemBean().fromJson(v));
37 | });
38 | }
39 | return data;
40 | }
41 |
42 | Map commonTabItemBeanDataToJson(CommonTabItemBeanData entity) {
43 | final Map data = new Map();
44 | data['ID'] = entity.iD;
45 | data['Name'] = entity.name;
46 | if (entity.items != null) {
47 | data['Items'] = entity.items.map((v) => v.toJson()).toList();
48 | }
49 | return data;
50 | }
51 |
--------------------------------------------------------------------------------
/lib/generated/json/condition_search_bean_entity_helper.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/models/common_item_bean_entity.dart';
2 | import 'package:shuaishuaimovie/models/condition_search_bean_entity.dart';
3 | import 'package:shuaishuaimovie/models/hot_update_bean_entity.dart';
4 |
5 | conditionSearchBeanEntityFromJson(ConditionSearchBeanEntity data, Map json) {
6 | if (json['data'] != null) {
7 | data.data = new List();
8 | (json['data'] as List).forEach((v) {
9 | data.data.add(new CommonItemBean().fromJson(v));
10 | });
11 | }
12 |
13 | if (json['status'] != null) {
14 | data.status = json['status']?.toInt();
15 | }
16 |
17 | if (json['qty'] != null) {
18 | data.qty = json['qty']?.toInt();
19 | }
20 |
21 | return data;
22 | }
23 |
24 | Map conditionSearchBeanEntityToJson(ConditionSearchBeanEntity entity) {
25 | final Map data = new Map();
26 | if (entity.data != null) {
27 | data['data'] = entity.data.map((v) => v.toJson()).toList();
28 | }
29 |
30 | data['status'] = entity.status;
31 |
32 | data['qty'] = entity.qty;
33 |
34 | return data;
35 | }
--------------------------------------------------------------------------------
/lib/generated/json/home_list_bean_entity_helper.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/models/common_item_bean_entity.dart';
2 | import 'package:shuaishuaimovie/models/home_list_bean_entity.dart';
3 |
4 | homeListBeanEntityFromJson(HomeListBeanEntity data, Map json) {
5 | if (json['c'] != null) {
6 | data.c = new List();
7 | (json['c'] as List).forEach((v) {
8 | data.c.add(new CommonItemBean().fromJson(v));
9 | });
10 | }
11 | if (json['h'] != null) {
12 | data.h = new List();
13 | (json['h'] as List).forEach((v) {
14 | data.h.add(new CommonItemBean().fromJson(v));
15 | });
16 | }
17 | if (json['m'] != null) {
18 | data.m = new List();
19 | (json['m'] as List).forEach((v) {
20 | data.m.add(new CommonItemBean().fromJson(v));
21 | });
22 | }
23 | if (json['s'] != null) {
24 | data.s = new List();
25 | (json['s'] as List).forEach((v) {
26 | data.s.add(new CommonItemBean().fromJson(v));
27 | });
28 | }
29 | if (json['t'] != null) {
30 | data.t = new List();
31 | (json['t'] as List).forEach((v) {
32 | data.t.add(new CommonItemBean().fromJson(v));
33 | });
34 | }
35 | if (json['lastQty'] != null) {
36 | data.lastQty = json['lastQty']?.toInt();
37 | }
38 | if (json['notice'] != null) {
39 | data.notice = json['notice']?.toString();
40 | }
41 | if (json['status'] != null) {
42 | data.status = json['status']?.toInt();
43 | }
44 | return data;
45 | }
46 |
47 | Map homeListBeanEntityToJson(HomeListBeanEntity entity) {
48 | final Map data = new Map();
49 | if (entity.c != null) {
50 | data['c'] = entity.c.map((v) => v.toJson()).toList();
51 | }
52 | if (entity.h != null) {
53 | data['h'] = entity.h.map((v) => v.toJson()).toList();
54 | }
55 | if (entity.m != null) {
56 | data['m'] = entity.m.map((v) => v.toJson()).toList();
57 | }
58 | if (entity.s != null) {
59 | data['s'] = entity.s.map((v) => v.toJson()).toList();
60 | }
61 | if (entity.t != null) {
62 | data['t'] = entity.t.map((v) => v.toJson()).toList();
63 | }
64 | data['lastQty'] = entity.lastQty;
65 | data['notice'] = entity.notice;
66 | data['status'] = entity.status;
67 | return data;
68 | }
--------------------------------------------------------------------------------
/lib/generated/json/hot_rank_bean_entity_helper.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/models/common_item_bean_entity.dart';
2 | import 'package:shuaishuaimovie/models/hot_rank_bean_entity.dart';
3 |
4 | hotRankBeanEntityFromJson(HotRankBeanEntity data, Map json) {
5 | if (json['cartoon'] != null) {
6 | data.cartoon = new List();
7 | (json['cartoon'] as List).forEach((v) {
8 | data.cartoon.add(new CommonItemBean().fromJson(v));
9 | });
10 | }
11 |
12 | if (json['movie'] != null) {
13 | data.movie = new List();
14 | (json['movie'] as List).forEach((v) {
15 | data.movie.add(new CommonItemBean().fromJson(v));
16 | });
17 | }
18 |
19 | if (json['show'] != null) {
20 | data.show = new List();
21 | (json['show'] as List).forEach((v) {
22 | data.show.add(new CommonItemBean().fromJson(v));
23 | });
24 | }
25 |
26 | if (json['teleplay'] != null) {
27 | data.teleplay = new List();
28 | (json['teleplay'] as List).forEach((v) {
29 | data.teleplay.add(new CommonItemBean().fromJson(v));
30 | });
31 | }
32 |
33 | if (json['status'] != null) {
34 | data.status = json['status']?.toInt();
35 | }
36 | return data;
37 | }
38 |
39 | Map hotRankBeanEntityToJson(HotRankBeanEntity entity) {
40 | final Map data = new Map();
41 | if (entity.cartoon != null) {
42 | data['cartoon'] = entity.cartoon.map((v) => v.toJson()).toList();
43 | }
44 |
45 | if (entity.movie != null) {
46 | data['movie'] = entity.movie.map((v) => v.toJson()).toList();
47 | }
48 |
49 | if (entity.show != null) {
50 | data['show'] = entity.show.map((v) => v.toJson()).toList();
51 | }
52 |
53 | if (entity.teleplay != null) {
54 | data['teleplay'] = entity.teleplay.map((v) => v.toJson()).toList();
55 | }
56 | data['status'] = entity.status;
57 | return data;
58 | }
59 |
--------------------------------------------------------------------------------
/lib/generated/json/hot_update_bean_entity_helper.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/models/common_item_bean_entity.dart';
2 | import 'package:shuaishuaimovie/models/hot_update_bean_entity.dart';
3 |
4 | hotUpdateBeanEntityFromJson(HotUpdateBeanEntity data, Map json) {
5 | if (json['data'] != null) {
6 | data.data = new List();
7 | (json['data'] as List).forEach((v) {
8 | data.data.add(new CommonItemBean().fromJson(v));
9 | });
10 | }
11 |
12 | if (json['status'] != null) {
13 | data.status = json['status']?.toInt();
14 | }
15 |
16 | return data;
17 | }
18 |
19 | Map hotUpdateBeanEntityToJson(HotUpdateBeanEntity entity) {
20 | final Map data = new Map();
21 | if (entity.data != null) {
22 | data['data'] = entity.data.map((v) => v.toJson()).toList();
23 | }
24 |
25 | data['status'] = entity.status;
26 |
27 | return data;
28 | }
--------------------------------------------------------------------------------
/lib/generated/json/select_condition_bean_entity_helper.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/models/select_condition_bean_entity.dart';
2 |
3 | selectConditionBeanEntityFromJson(SelectConditionBeanEntity data, Map json) {
4 | if (json['areas'] != null) {
5 | data.areas = new SelectConditionCommonBean().fromJson(json['areas']);
6 | }
7 | if (json['classes'] != null) {
8 | data.classes = new SelectConditionCommonBean().fromJson(json['classes']);
9 | }
10 | if (json['languages'] != null) {
11 | data.languages = new List();
12 | (json['languages'] as List).forEach((v) {
13 | data.languages.add(new SelectConditionInnerBean().fromJson(v));
14 | });
15 | }
16 | if (json['status'] != null) {
17 | data.status = json['status']?.toInt();
18 | }
19 | if (json['types'] != null) {
20 | data.types = new SelectConditionCommonBean().fromJson(json['types']);
21 | }
22 | return data;
23 | }
24 |
25 | Map selectConditionBeanEntityToJson(SelectConditionBeanEntity entity) {
26 | final Map data = new Map();
27 | if (entity.areas != null) {
28 | data['areas'] = entity.areas.toJson();
29 | }
30 | if (entity.classes != null) {
31 | data['classes'] = entity.classes.toJson();
32 | }
33 | if (entity.languages != null) {
34 | data['languages'] = entity.languages.map((v) => v.toJson()).toList();
35 | }
36 | data['status'] = entity.status;
37 | if (entity.types != null) {
38 | data['types'] = entity.types.toJson();
39 | }
40 | return data;
41 | }
42 |
43 | selectConditionCommonBeanFromJson(SelectConditionCommonBean data, Map json) {
44 | if (json['电影'] != null) {
45 | data.movie = new List();
46 | (json['电影'] as List).forEach((v) {
47 | data.movie.add(new SelectConditionInnerBean().fromJson(v));
48 | });
49 | }
50 |
51 | if (json['动漫'] != null) {
52 | data.cartoon = new List();
53 | (json['动漫'] as List).forEach((v) {
54 | data.cartoon.add(new SelectConditionInnerBean().fromJson(v));
55 | });
56 | }
57 |
58 | if (json['综艺'] != null) {
59 | data.show = new List();
60 | (json['综艺'] as List).forEach((v) {
61 | data.show.add(new SelectConditionInnerBean().fromJson(v));
62 | });
63 | }
64 |
65 | if (json['连续剧'] != null) {
66 | data.teleplay = new List();
67 | (json['连续剧'] as List).forEach((v) {
68 | data.teleplay.add(new SelectConditionInnerBean().fromJson(v));
69 | });
70 | }
71 | return data;
72 | }
73 |
74 | Map selectConditionCommonBeanToJson(SelectConditionCommonBean entity) {
75 | final Map data = new Map();
76 | if (entity.movie != null) {
77 | data['电影'] = entity.movie.map((v) => v.toJson()).toList();
78 | }
79 |
80 | if (entity.cartoon != null) {
81 | data['动漫'] = entity.cartoon.map((v) => v.toJson()).toList();
82 | }
83 |
84 | if (entity.show != null) {
85 | data['综艺'] = entity.show.map((v) => v.toJson()).toList();
86 | }
87 |
88 | if (entity.teleplay != null) {
89 | data['连续剧'] = entity.teleplay.map((v) => v.toJson()).toList();
90 | }
91 |
92 | return data;
93 | }
94 |
95 | selectConditionInnerBeanFromJson(SelectConditionInnerBean data, Map json) {
96 | if (json['name'] != null) {
97 | data.name = json['name'];
98 | }
99 |
100 | if (json['id'] != null) {
101 | data.id = json['id'];
102 | }
103 | return data;
104 | }
105 |
106 | Map selectConditionInnerBeanToJson(SelectConditionInnerBean entity) {
107 | final Map data = new Map();
108 | data['name'] = entity.name;
109 | data['id'] = entity.id;
110 | return data;
111 | }
112 |
113 |
--------------------------------------------------------------------------------
/lib/generated/json/txt_auto_search_bean_entity_helper.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/models/common_item_bean_entity.dart';
2 | import 'package:shuaishuaimovie/models/txt_auto_search_bean_entity.dart';
3 |
4 | txtAutoSearchBeanEntityFromJson(TxtAutoSearchBeanEntity data, Map json) {
5 | if (json['data'] != null) {
6 | data.data = new List();
7 | (json['data'] as List).forEach((v) {
8 | data.data.add(new CommonItemBean().fromJson(v));
9 | });
10 | }
11 |
12 | if (json['status'] != null) {
13 | data.status = json['status']?.toInt();
14 | }
15 |
16 | return data;
17 | }
18 |
19 | Map txtAutoSearchBeanEntityToJson(TxtAutoSearchBeanEntity entity) {
20 | final Map data = new Map();
21 | if (entity.data != null) {
22 | data['data'] = entity.data.map((v) => v.toJson()).toList();
23 | }
24 |
25 | data['status'] = entity.status;
26 |
27 | return data;
28 | }
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:fluro/fluro.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:provider/provider.dart';
4 | import 'package:shuaishuaimovie/database/sqf_provider.dart';
5 | import 'package:shuaishuaimovie/res/app_color.dart';
6 | import 'package:shuaishuaimovie/ui/pages/splash_page.dart';
7 | import 'package:shuaishuaimovie/viewmodels/app_theme_model.dart';
8 | import 'package:shuaishuaimovie/provider/provider_setup.dart';
9 | import 'package:shuaishuaimovie/routes/routes.dart';
10 | import 'package:shuaishuaimovie/shuai_movie.dart';
11 |
12 | import 'sharepreference/share_preference.dart';
13 | import 'utils/system/system_chrome.dart';
14 |
15 | void main() {
16 | runApp(MyApp());
17 | }
18 |
19 | class MyApp extends StatefulWidget {
20 | @override
21 | _MyAppState createState() => _MyAppState();
22 | }
23 |
24 | class _MyAppState extends State {
25 | _MyAppState() {
26 | final router = Router();
27 | Routes.configureRoutes(router);
28 | Application.router = router;
29 |
30 | //初始化数据库
31 | _initDB();
32 | _initSharePreference();
33 | }
34 |
35 | @override
36 | Widget build(BuildContext context) {
37 | return MultiProvider(
38 | providers: providers,
39 | child: Builder(
40 | builder: (context) => MaterialApp(
41 | title: "帅帅影视",
42 | color: AppColor.black,
43 | theme: ThemeData(
44 | accentColor: AppColor.icon_yellow,
45 | scaffoldBackgroundColor: AppColor.white,
46 | appBarTheme: AppBarTheme(
47 | color: AppColor.black,
48 | ),
49 | iconTheme: IconThemeData(
50 | color: context.watch().iconThemeColor,
51 | ),
52 | ),
53 | debugShowCheckedModeBanner: false,
54 | onGenerateRoute: Application.router.generator,
55 | home: AnnotatedRegion(
56 | value: MovieSystemChrome.statusDark, child: SplashPage()),
57 | ),
58 | ),
59 | );
60 | }
61 |
62 | void _initDB() {
63 | SqfProvider.initSQF();
64 | }
65 |
66 | void _initSharePreference() {
67 | //没有找到设置默认值的地方,所以通过判断返回是空的话设置默认值。
68 | MovieSharePreference.getAutoPlayValue().then((value) {
69 | if (value == null) MovieSharePreference.saveAutoPlayValue(true);
70 | });
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/lib/models/common_item_bean_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/generated/json/base/json_convert_content.dart';
2 | import 'package:shuaishuaimovie/generated/json/base/json_filed.dart';
3 |
4 | class CommonItemBean with JsonConvert {
5 | @JSONField(name: "VodID")
6 | int vodID;
7 | @JSONField(name: "VodName")
8 | String vodName;
9 | @JSONField(name: "VodPic")
10 | String vodPic;
11 | @JSONField(name: "VodYear")
12 | String vodYear;
13 | @JSONField(name: "VodArea")
14 | String vodArea;
15 | @JSONField(name: "VodRemarks")
16 | String vodRemarks;
17 | @JSONField(name: "VodHits")
18 | int vodHits;
19 | @JSONField(name: "VodActor")
20 | String vodActor;
21 | @JSONField(name: "VodDirector")
22 | String vodDirector;
23 | @JSONField(name: "VodTime")
24 | int vodTime;
25 | @JSONField(name: "VodTypeID")
26 | int vodTypeID;
27 | @JSONField(name: "VodClass")
28 | CommonItemBeanVodClass vodClass;
29 | }
30 |
31 |
32 | class CommonItemBeanVodClass with JsonConvert {
33 | @JSONField(name: "TypeID")
34 | int typeID;
35 | @JSONField(name: "TypeName")
36 | String typeName;
37 | }
--------------------------------------------------------------------------------
/lib/models/common_tab_item_bean_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/generated/json/base/json_convert_content.dart';
2 | import 'package:shuaishuaimovie/generated/json/base/json_filed.dart';
3 | import 'package:shuaishuaimovie/models/common_item_bean_entity.dart';
4 |
5 | class CommonTabItemBeanEntity with JsonConvert {
6 | List data;
7 | int status;
8 | }
9 |
10 | class CommonTabItemBeanData with JsonConvert {
11 | @JSONField(name: "ID")
12 | int iD;
13 | @JSONField(name: "Name")
14 | String name;
15 | @JSONField(name: "Items")
16 | List items;
17 | }
18 |
19 |
--------------------------------------------------------------------------------
/lib/models/condition_search_bean_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/generated/json/base/json_convert_content.dart';
2 |
3 | import 'common_item_bean_entity.dart';
4 |
5 | class ConditionSearchBeanEntity with JsonConvert {
6 | List data;
7 | int status;
8 | int qty;
9 |
10 | }
--------------------------------------------------------------------------------
/lib/models/home_detail_bean_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/generated/json/base/json_convert_content.dart';
2 | import 'package:shuaishuaimovie/generated/json/base/json_filed.dart';
3 | import 'package:shuaishuaimovie/models/common_item_bean_entity.dart';
4 |
5 | class HomeDetailBeanEntity with JsonConvert {
6 | int count;
7 | String domain;
8 | List rand;
9 | List relate;
10 | String shareLink;
11 | int status;
12 | HomeDetailBeanVod vod;
13 | }
14 |
15 |
16 | class HomeDetailBeanVod with JsonConvert {
17 | @JSONField(name: "VodID")
18 | int vodID;
19 | @JSONField(name: "VodLevel")
20 | int vodLevel;
21 | @JSONField(name: "TypeID")
22 | int typeID;
23 | @JSONField(name: "TypeID1")
24 | int typeID1;
25 | @JSONField(name: "GroupID")
26 | int groupID;
27 | @JSONField(name: "VodUp")
28 | int vodUp;
29 | @JSONField(name: "VodName")
30 | String vodName;
31 | @JSONField(name: "VodPic")
32 | String vodPic;
33 | @JSONField(name: "VodActor")
34 | String vodActor;
35 | @JSONField(name: "VodDirector")
36 | String vodDirector;
37 | @JSONField(name: "VodBlurb")
38 | String vodBlurb;
39 | @JSONField(name: "VodContent")
40 | String vodContent;
41 | @JSONField(name: "VodYear")
42 | String vodYear;
43 | @JSONField(name: "VodScore")
44 | int vodScore;
45 | @JSONField(name: "VodScoreAll")
46 | int vodScoreAll;
47 | @JSONField(name: "VodHits")
48 | int vodHits;
49 | @JSONField(name: "VodScoreNum")
50 | int vodScoreNum;
51 | @JSONField(name: "VodArea")
52 | String vodArea;
53 | @JSONField(name: "VodRemarks")
54 | String vodRemarks;
55 | @JSONField(name: "Vps")
56 | String vps;
57 | @JSONField(name: "Vpf")
58 | String vpf;
59 | @JSONField(name: "Vpl")
60 | String vpl;
61 | @JSONField(name: "VodHitsWeek")
62 | String vodHitsWeek;
63 | @JSONField(name: "VodTime")
64 | int vodTime;
65 | @JSONField(name: "VodPlayServer")
66 | List vodPlayServer;
67 | @JSONField(name: "VodPlayUrls")
68 | HomeDetailBeanVodVodPlayUrls vodPlayUrls;
69 | @JSONField(name: "VodClass")
70 | HomeDetailBeanVodVodClass vodClass;
71 | }
72 |
73 | class HomeDetailBeanVodVodPlayServer with JsonConvert {
74 | @JSONField(name: "Status")
75 | String status;
76 | @JSONField(name: "From")
77 | String from;
78 | @JSONField(name: "Show")
79 | String xShow;
80 | @JSONField(name: "Des")
81 | String des;
82 | @JSONField(name: "Ps")
83 | String ps;
84 | @JSONField(name: "Target")
85 | String target;
86 | @JSONField(name: "Parse")
87 | String parse;
88 | @JSONField(name: "Sort")
89 | String sort;
90 | @JSONField(name: "Tip")
91 | String tip;
92 | @JSONField(name: "ID")
93 | String iD;
94 | }
95 |
96 | class HomeDetailBeanVodVodPlayUrls with JsonConvert {
97 | List bjm3u8;
98 | List kuyun;
99 | List youku;
100 | List zuidam3u8;
101 | }
102 |
103 | class HomeDetailBeanVodVodClass with JsonConvert {
104 | @JSONField(name: "TypeID")
105 | int typeID;
106 | @JSONField(name: "TypeName")
107 | String typeName;
108 | }
109 |
--------------------------------------------------------------------------------
/lib/models/home_list_bean_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/generated/json/base/json_convert_content.dart';
2 |
3 | import 'common_item_bean_entity.dart';
4 |
5 | class HomeListBeanEntity with JsonConvert {
6 | List c;
7 | List h;
8 | List m;
9 | List s;
10 | List t;
11 | int lastQty;
12 | String notice;
13 | int status;
14 | }
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/lib/models/hot_rank_bean_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/generated/json/base/json_convert_content.dart';
2 | import 'package:shuaishuaimovie/generated/json/base/json_filed.dart';
3 | import 'package:shuaishuaimovie/models/common_item_bean_entity.dart';
4 |
5 | class HotRankBeanEntity with JsonConvert {
6 | List cartoon;
7 | List movie;
8 | List show;
9 | List teleplay;
10 | int status;
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/lib/models/hot_update_bean_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/generated/json/base/json_convert_content.dart';
2 |
3 | import 'common_item_bean_entity.dart';
4 |
5 | class HotUpdateBeanEntity with JsonConvert {
6 | List data;
7 | int status;
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/lib/models/select_condition_bean_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/generated/json/base/json_convert_content.dart';
2 | import 'package:shuaishuaimovie/generated/json/base/json_filed.dart';
3 |
4 | class SelectConditionBeanEntity with JsonConvert {
5 | SelectConditionCommonBean areas;
6 | SelectConditionCommonBean classes;
7 | List languages;
8 | int status;
9 | SelectConditionCommonBean types;
10 | }
11 |
12 | class SelectConditionCommonBean with JsonConvert {
13 | @JSONField(name: "动漫")
14 | List cartoon;
15 | @JSONField(name: "电影")
16 | List movie;
17 | @JSONField(name: "综艺")
18 | List show;
19 | @JSONField(name: "连续剧")
20 | List teleplay;
21 | }
22 |
23 | class SelectConditionInnerBean with JsonConvert {
24 | String name;
25 | int id;
26 | }
27 |
28 |
29 |
--------------------------------------------------------------------------------
/lib/models/txt_auto_search_bean_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/generated/json/base/json_convert_content.dart';
2 | import 'package:shuaishuaimovie/models/common_item_bean_entity.dart';
3 |
4 | class TxtAutoSearchBeanEntity with JsonConvert {
5 | List data;
6 | int status;
7 | }
8 |
9 |
10 |
--------------------------------------------------------------------------------
/lib/net/base_repository.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'base_result.dart';
3 |
4 | /// 父类repository对象
5 | class BaseRepository {
6 | Dio _dio;
7 |
8 | BaseRepository();
9 |
10 | void setDio(Dio dio) {
11 | this._dio = dio;
12 | }
13 |
14 | /// 通用get请求
15 | Future get(String path, {Map params}) async {
16 | try {
17 | Response response = await _dio.get(path, queryParameters: params);
18 | return BaseResult(
19 | data: response.data, code: 0);
20 | } catch (e) {
21 | print('异常信息:' + e.toString());
22 | return BaseResult(message: e.toString(), code: 500);
23 | }
24 | }
25 |
26 | /// 通用post请求
27 | Future post(String path, Map params) async {
28 | try {
29 | Response response = await _dio.post(path, data: params);
30 | return BaseResult(
31 | data: response.data, code: response.data.status);
32 | } catch (e) {
33 | print('异常信息:' + e.toString());
34 | return BaseResult(message: e.toString(), code: 500);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lib/net/base_result.dart:
--------------------------------------------------------------------------------
1 | /// 通用返回类
2 | class BaseResult {
3 | /// 返回数据bean
4 | dynamic data;
5 | /// 状态码
6 | int code;
7 | /// 返回信息
8 | String message;
9 | BaseResult({this.data, this.code, this.message});
10 | }
11 |
--------------------------------------------------------------------------------
/lib/net/request_const.dart:
--------------------------------------------------------------------------------
1 | class RequestConstApi{
2 | static const SERVICE_API = 'https://vip.88-spa.com:8443/v1/';
3 | static const HOME_API = SERVICE_API + "home-list";
4 | static const HOME_DETAIL_API = SERVICE_API + "vod-details";
5 | static const HOT_UPDATE_API = SERVICE_API + "map";
6 | static const RANK_WEEK_API = SERVICE_API + "rank-list?cate=vod_hits_week";
7 | static const RANK_MONTH_API = SERVICE_API + "rank-list?cate=vod_hits_month";
8 | static const RANK_TOTAL_API = SERVICE_API + "rank-list?cate=vod_hits";
9 | static const MOVIE_API = SERVICE_API + "list-by-type?type=1";
10 | static const TELEPLAY_API = SERVICE_API + "list-by-type?type=2";
11 | static const SHOW_API = SERVICE_API + "list-by-type?type=3";
12 | static const CARTOON_API = SERVICE_API + "list-by-type?type=4";
13 | static const SELECT_CONDITION_API = SERVICE_API + "vod-list-options";
14 | static const CONDITION_SEARCH_API = SERVICE_API + "vod-list?";
15 | static const TXT_AUTO_SEARCH_API = SERVICE_API + "auto-search?";
16 | static const TXT_NORMAL_SEARCH_API = SERVICE_API + "search?";
17 | }
--------------------------------------------------------------------------------
/lib/net/request_helper.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'request_const.dart';
3 |
4 | class HttpHelper {
5 | Dio _dio;
6 |
7 | factory HttpHelper() => _getProvider();
8 |
9 | HttpHelper._internal();
10 |
11 | static HttpHelper get instance => _getProvider();
12 | static HttpHelper _httpHelper;
13 |
14 | static HttpHelper _getProvider() {
15 | if (_httpHelper == null) {
16 | _httpHelper = new HttpHelper._internal();
17 | }
18 | return _httpHelper;
19 | }
20 |
21 | ///创建dio网络请求对象
22 | Dio _createDio() {
23 | final options = BaseOptions(
24 | baseUrl: RequestConstApi.SERVICE_API,
25 | connectTimeout: 30 * 1000,
26 | receiveTimeout: 30 * 1000);
27 | final dio = new Dio(options);
28 | // 添加通用拦截器
29 | // for (Interceptor interceptor in getInterceptors()) {
30 | // dio.interceptors.add(interceptor);
31 | // }
32 | return dio;
33 | }
34 |
35 | // 子类可以复写该方法 自定义添加拦截器
36 | List getInterceptors() {
37 |
38 | }
39 |
40 | Dio getDio() {
41 | if (_dio == null) {
42 | _dio = _createDio();
43 | }
44 | return _dio;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/lib/provider/provider_proxy_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:provider/provider.dart';
3 |
4 | /// 负责创建viewModel对象和初始化数据加载
5 | class ProviderProxyWidget
6 | extends StatefulWidget {
7 | /// viewModel
8 | final T1 model;
9 | final ValueWidgetBuilder builder;
10 | final Widget child;
11 | final ProxyProviderBuilder proxyUpdate;
12 |
13 | /// 初始化数据
14 | final Function(T1 model) initData;
15 |
16 | @override
17 | State createState() => _ProviderProxyWidgetState();
18 |
19 | ProviderProxyWidget(
20 | {@required this.model,
21 | @required this.builder,
22 | @required this.proxyUpdate,
23 | this.child,
24 | this.initData});
25 | }
26 |
27 | class _ProviderProxyWidgetState extends State> {
29 | T1 model;
30 |
31 | @override
32 | void initState() {
33 | model = widget.model;
34 | super.initState();
35 | WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
36 | widget.initData?.call(model);
37 | });
38 | }
39 |
40 | @override
41 | void dispose() {
42 | model.dispose();
43 | super.dispose();
44 | }
45 |
46 | @override
47 | Widget build(BuildContext context) {
48 | return ChangeNotifierProxyProvider(
49 | create: (context) => widget.model,
50 | update: widget.proxyUpdate,
51 | child: Consumer(
52 | builder: widget.builder,
53 | child: widget.child,
54 | ),
55 | );
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/lib/provider/provider_setup.dart:
--------------------------------------------------------------------------------
1 | import 'package:provider/provider.dart';
2 | import 'package:provider/single_child_widget.dart';
3 | import 'package:shuaishuaimovie/viewmodels/app_theme_model.dart';
4 |
5 | List providers = [
6 | ...independentServices,
7 | ...dependentServices,
8 | ];
9 |
10 | List independentServices = [
11 | ChangeNotifierProvider(create: (_) => AppTheme()),
12 | ];
13 |
14 | List dependentServices = [
15 | //这里使用ProxyProvider来定义需要依赖其他Provider的服务
16 | ];
--------------------------------------------------------------------------------
/lib/provider/provider_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:provider/provider.dart';
3 |
4 | /// 负责创建viewModel对象和初始化数据加载
5 | class ProviderWidget
6 | extends StatefulWidget {
7 | /// viewModel
8 | final T model;
9 | final ValueWidgetBuilder builder;
10 | final Widget child;
11 |
12 | /// 初始化数据
13 | final Function(T model) initData;
14 |
15 | @override
16 | State createState() => _ProviderWidgetState();
17 |
18 | ProviderWidget(
19 | {@required this.model,
20 | @required this.builder,
21 | this.child,
22 | this.initData});
23 | }
24 |
25 | class _ProviderWidgetState
26 | extends State> {
27 | T model;
28 |
29 | @override
30 | void initState() {
31 | model = widget.model;
32 | widget.initData?.call(model);
33 | super.initState();
34 | }
35 |
36 | @override
37 | void dispose() {
38 | model.dispose();
39 | super.dispose();
40 | }
41 |
42 | @override
43 | Widget build(BuildContext context) {
44 | return ChangeNotifierProvider.value(
45 | value: model,
46 | child: Consumer(
47 | builder: widget.builder,
48 | child: widget.child,
49 | ),
50 | );
51 | }
52 | }
53 |
54 | class ProviderWidget2
55 | extends StatefulWidget {
56 | /// viewModel
57 | final A modelA;
58 | final B modelB;
59 | final Widget Function(BuildContext context, A model1, B model2, Widget child) builder;
60 | final Widget child;
61 |
62 | /// 初始化数据
63 | final Future Function(A modelA, B modelB) initData;
64 |
65 | @override
66 | State createState() => _ProviderWidget2State();
67 |
68 | ProviderWidget2(
69 | {@required this.modelA,
70 | @required this.modelB,
71 | @required this.builder,
72 | this.child,
73 | this.initData});
74 | }
75 |
76 | class _ProviderWidget2State
77 | extends State> {
78 | A modelA;
79 | B modelB;
80 |
81 | @override
82 | void initState() {
83 | modelA = widget.modelA;
84 | modelB = widget.modelB;
85 | widget.initData?.call(modelA, modelB);
86 | super.initState();
87 | }
88 |
89 | @override
90 | void dispose() {
91 | modelA.dispose();
92 | modelB.dispose();
93 | super.dispose();
94 | }
95 |
96 | @override
97 | Widget build(BuildContext context) {
98 | return MultiProvider(
99 | providers: [
100 | ChangeNotifierProvider.value(value: modelA),
101 | ChangeNotifierProvider.value(value: modelB),
102 | ],
103 | child: Consumer2(
104 | builder: widget.builder,
105 | child: widget.child,
106 | ),
107 | );
108 | }
109 | }
--------------------------------------------------------------------------------
/lib/provider/view_state.dart:
--------------------------------------------------------------------------------
1 | /// 状态枚举类
2 | enum ViewState {
3 | /// 加载中
4 | loading,
5 |
6 | /// 数据返回成功
7 | success,
8 |
9 | /// 空数据
10 | empty,
11 |
12 | /// 数据返回失败
13 | error,
14 |
15 | ///no net
16 | noNetwork,
17 | }
18 |
19 | class ViewStateError {
20 | Error error;
21 | String message;
22 |
23 | ViewStateError({this.error, this.message}) {
24 | this.message ??= '服务器异常';
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/r.g.dart:
--------------------------------------------------------------------------------
1 | // IT IS GENERATED BY FLR - DO NOT MODIFY BY HAND
2 | // YOU CAN GET MORE DETAILS ABOUT FLR FROM:
3 | // - https://github.com/Fly-Mix/flr-cli
4 | // - https://github.com/Fly-Mix/flr-vscode-extension
5 | // - https://github.com/Fly-Mix/flr-as-plugin
6 | //
7 |
8 | // ignore: unused_import
9 | import 'package:flutter/widgets.dart';
10 | // ignore: unused_import
11 | import 'package:flutter/services.dart' show rootBundle;
12 | // ignore: unused_import
13 | import 'package:path/path.dart' as path;
14 | // ignore: unused_import
15 | import 'package:flutter_svg/flutter_svg.dart';
16 | // ignore: unused_import
17 | import 'package:r_dart_library/asset_svg.dart';
18 |
19 | /// This `R` class is generated and contains references to static asset resources.
20 | class R {
21 | /// package name: shuaishuaimovie
22 | static const package = "shuaishuaimovie";
23 |
24 | /// This `R.image` struct is generated, and contains static references to static non-svg type image asset resources.
25 | static const image = _R_Image();
26 |
27 | /// This `R.svg` struct is generated, and contains static references to static svg type image asset resources.
28 | static const svg = _R_Svg();
29 |
30 | /// This `R.text` struct is generated, and contains static references to static text asset resources.
31 | static const text = _R_Text();
32 |
33 | /// This `R.fontFamily` struct is generated, and contains static references to static font asset resources.
34 | static const fontFamily = _R_FontFamily();
35 | }
36 | /// Asset resource’s metadata class.
37 | /// For example, here is the metadata of `packages/flutter_demo/assets/images/example.png` asset:
38 | /// - packageName:flutter_demo
39 | /// - assetName:assets/images/example.png
40 | /// - fileDirname:assets/images
41 | /// - fileBasename:example.png
42 | /// - fileBasenameNoExtension:example
43 | /// - fileExtname:.png
44 | class AssetResource {
45 | /// Creates an object to hold the asset resource’s metadata.
46 | const AssetResource(this.assetName, {this.packageName}) : assert(assetName != null);
47 |
48 | /// The name of the main asset from the set of asset resources to choose from.
49 | final String assetName;
50 |
51 | /// The name of the package from which the asset resource is included.
52 | final String packageName;
53 |
54 | /// The name used to generate the key to obtain the asset resource. For local assets
55 | /// this is [assetName], and for assets from packages the [assetName] is
56 | /// prefixed 'packages//'.
57 | String get keyName => packageName == null ? assetName : "packages/$packageName/$assetName";
58 |
59 | /// The file basename of the asset resource.
60 | String get fileBasename {
61 | final basename = path.basename(assetName);
62 | return basename;
63 | }
64 |
65 | /// The no extension file basename of the asset resource.
66 | String get fileBasenameNoExtension {
67 | final basenameWithoutExtension = path.basenameWithoutExtension(assetName);
68 | return basenameWithoutExtension;
69 | }
70 |
71 | /// The file extension name of the asset resource.
72 | String get fileExtname {
73 | final extension = path.extension(assetName);
74 | return extension;
75 | }
76 |
77 | /// The directory path name of the asset resource.
78 | String get fileDirname {
79 | var dirname = assetName;
80 | if (packageName != null) {
81 | final packageStr = "packages/$packageName/";
82 | dirname = dirname.replaceAll(packageStr, "");
83 | }
84 | final filenameStr = "$fileBasename/";
85 | dirname = dirname.replaceAll(filenameStr, "");
86 | return dirname;
87 | }
88 | }
89 | // ignore: camel_case_types
90 | class _R_Image_AssetResource {
91 | const _R_Image_AssetResource();
92 |
93 | }
94 | // ignore: camel_case_types
95 | class _R_Svg_AssetResource {
96 | const _R_Svg_AssetResource();
97 |
98 | }
99 | // ignore: camel_case_types
100 | class _R_Text_AssetResource {
101 | const _R_Text_AssetResource();
102 |
103 | }
104 | /// This `_R_Image` class is generated and contains references to static non-svg type image asset resources.
105 | // ignore: camel_case_types
106 | class _R_Image {
107 | const _R_Image();
108 |
109 | final asset = const _R_Image_AssetResource();
110 |
111 | }
112 | /// This `_R_Svg` class is generated and contains references to static svg type image asset resources.
113 | // ignore: camel_case_types
114 | class _R_Svg {
115 | const _R_Svg();
116 |
117 | final asset = const _R_Svg_AssetResource();
118 |
119 | }
120 | /// This `_R_Text` class is generated and contains references to static text asset resources.
121 | // ignore: camel_case_types
122 | class _R_Text {
123 | const _R_Text();
124 |
125 | final asset = const _R_Text_AssetResource();
126 |
127 | }
128 | /// This `_R_FontFamily` class is generated and contains references to static font asset resources.
129 | // ignore: camel_case_types
130 | class _R_FontFamily {
131 | const _R_FontFamily();
132 |
133 | }
--------------------------------------------------------------------------------
/lib/res/app_color.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:flutter/material.dart';
4 |
5 | /// app颜色定义统一管理
6 | class AppColor{
7 | static const Color primary = Color(0xFF5C5C5C);
8 | static const Color secondary = Color(0xFF51DEC6);
9 | static const Color red = Color(0xFFFF2B45);
10 | static const Color orange = Color(0xFFF67264);
11 | static const Color white = Color(0xFFFFFFFF);
12 | static const Color transparent = Color(0x00FFFFFF);
13 | static const Color paper = Color(0xFFF5F5F5);
14 | static const Color lightGrey = Color(0xFFDDDDDD);
15 | static const Color darkGrey = Color(0xFF333333);
16 | static const Color grey = Color(0xFF888888);
17 | static const Color blue = Color(0xFF3688FF);
18 | static const Color golden = Color(0xff8B7961);
19 | static const Color black = Color(0xff000000);
20 | static const Color black_99 = Color(0xff999999);
21 | static const Color black_66 = Color(0xff666666);
22 | static const Color black_33 = Color(0xff333333);
23 | static const Color black_cc = Color(0xffcccccc);
24 |
25 | static const Color default_txt_grey = Color(0xFF757575);
26 | static const Color default_icon_grey = Color(0xFF616161);
27 | static const Color icon_yellow = Color(0xFFFBC02D);
28 | static const Color search_bg_grey = Color(0x44cccccc);
29 | static const Color line_grey = Color(0xFFF5F5F5);
30 | }
--------------------------------------------------------------------------------
/lib/routes/route_handlers.dart:
--------------------------------------------------------------------------------
1 | import 'package:fluro/fluro.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:shuaishuaimovie/ui/pages/history/video_history_page.dart';
4 | import 'package:shuaishuaimovie/ui/pages/hot/rank/hot_rank_page.dart';
5 | import 'package:shuaishuaimovie/ui/pages/hot/update/hot_update_page.dart';
6 | import 'package:shuaishuaimovie/ui/pages/maintab/cartoon/cartoon_page.dart';
7 | import 'package:shuaishuaimovie/ui/pages/maintab/home/home_detail_page.dart';
8 | import 'package:shuaishuaimovie/ui/pages/maintab/index_page.dart';
9 | import 'package:shuaishuaimovie/ui/pages/search/condition_search_page.dart';
10 | import 'package:shuaishuaimovie/ui/pages/search/txt_search_page.dart';
11 | import 'package:shuaishuaimovie/ui/pages/splash_page.dart';
12 | import 'package:shuaishuaimovie/ui/pages/video/video_page.dart';
13 |
14 | var splashHandler = Handler(
15 | handlerFunc: (BuildContext context, Map> params) {
16 | return SplashPage();
17 | });
18 |
19 | var indexHandler = Handler(
20 | handlerFunc: (BuildContext context, Map> params) {
21 | var currentTabName = params["type"][0];
22 | return IndexPage(currentTabName);
23 | });
24 |
25 | var homeDetailHandler = Handler(
26 | handlerFunc: (BuildContext context, Map> params) {
27 | var vodId = params["id"][0];
28 | var imageUrl = params["imageUrl"][0];
29 | return HomeDetailPage(
30 | vodId: vodId,
31 | imageUrl: imageUrl,
32 | );
33 | });
34 |
35 | var hotUpdateHandler = Handler(
36 | handlerFunc: (BuildContext context, Map> params) {
37 | return TodayHotUpdatePage();
38 | });
39 |
40 | var rankHandler = Handler(
41 | handlerFunc: (BuildContext context, Map> params) {
42 | return HotRankPage();
43 | });
44 |
45 | var cartoonHandler = Handler(
46 | handlerFunc: (BuildContext context, Map> params) {
47 | return CartoonPage();
48 | });
49 |
50 | var conditionSearchHandler = Handler(
51 | handlerFunc: (BuildContext context, Map> params) {
52 | var tabType = params["tabType"][0];
53 | var classes = params["classes"][0];
54 | return ConditionSearchPage(tabType, classes: classes);
55 | });
56 |
57 | var txtSearchHandler = Handler(
58 | handlerFunc: (BuildContext context, Map> params) {
59 | return TxtSearchPage();
60 | });
61 |
62 | var videoHandler = Handler(
63 | handlerFunc: (BuildContext context, Map> params) {
64 | var videoId = params["videoId"][0];
65 | var videoUrl = params["videoUrl"][0];
66 | var playUrlType = params["playUrlType"][0];
67 | var playUrlIndex = params["playUrlIndex"][0];
68 | var videoName = params["videoName"][0];
69 | var videoLevel = params["videoLevel"][0];
70 | var currentTime = params["currentTime"][0];
71 | var isPositive = params["isPositive"][0];
72 |
73 | return VideoPage(
74 | videoId: videoId,
75 | videoUrl: videoUrl,
76 | videoName: videoName,
77 | videoLevel: videoLevel,
78 | playUrlType: playUrlType,
79 | playUrlIndex: int.parse(playUrlIndex),
80 | currentTime: currentTime,
81 | isPositive: isPositive,
82 | );
83 | });
84 |
85 | var videoHistoryHandler = Handler(
86 | handlerFunc: (BuildContext context, Map> params) {
87 | return VideoHistoryPage();
88 | });
89 |
--------------------------------------------------------------------------------
/lib/routes/route_jump.dart:
--------------------------------------------------------------------------------
1 | import 'package:fluro/fluro.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:shuaishuaimovie/routes/routes.dart';
4 | import 'package:shuaishuaimovie/shuai_movie.dart';
5 | import 'package:shuaishuaimovie/ui/pages/maintab/index_page.dart';
6 | import 'package:shuaishuaimovie/widgets/clip_widget.dart';
7 |
8 | void jumpHomeDetail(context, String vodId, String imageUrl, {replace = false}) {
9 | Application.router.navigateTo(
10 | context,
11 | Routes.home_detail + "/$vodId/${Uri.encodeComponent(imageUrl)}",
12 | replace: replace,
13 | transition: TransitionType.cupertino,
14 | );
15 | }
16 |
17 | void jumpRank(context) {
18 | Application.router.navigateTo(
19 | context,
20 | Routes.rank,
21 | transition: TransitionType.cupertino,
22 | );
23 | }
24 |
25 | void jumpIndex(context,
26 | {String type = IndexPage.TAB_HOME, clearStack = false, replace = false}) {
27 | Application.router.navigateTo(
28 | context,
29 | Routes.index + "/$type",
30 | clearStack: clearStack,
31 | replace: replace,
32 | transition: TransitionType.cupertino,
33 | );
34 | }
35 |
36 | void jumpCartoon(context) {
37 | Application.router.navigateTo(
38 | context,
39 | Routes.cartoon,
40 | transition: TransitionType.cupertino,
41 | );
42 | }
43 |
44 | jumpVideo(context,
45 | {String videoId,
46 | String videoUrl,
47 | String playUrlType,
48 | String playUrlIndex,
49 | String videoName,
50 | String videoLevel,
51 | String isPositive,
52 | String currentTime = ""}) {
53 | Application.router.navigateTo(
54 | context,
55 | Routes.video +
56 | "/$videoId/${Uri.encodeComponent(videoUrl)}/$playUrlType/$playUrlIndex/$videoName/$videoLevel/$currentTime/$isPositive",
57 | transition: TransitionType.cupertino,
58 | );
59 | }
60 |
61 | void jumpConditionSearch(context, String tabType, {String classes = ""}) {
62 | Application.router.navigateTo(
63 | context,
64 | Routes.condition_search + '/$tabType/$classes',
65 | transition: TransitionType.cupertino,
66 | );
67 | }
68 |
69 | void jumpTxtSearch(context) {
70 | Application.router.navigateTo(context, Routes.txt_search,
71 | transition: TransitionType.custom,
72 | transitionDuration: const Duration(milliseconds: 500), transitionBuilder:
73 | (BuildContext context, Animation animation,
74 | Animation secondaryAnimation, Widget child) {
75 | return AnimatedBuilder(
76 | animation: animation,
77 | builder: (context, child) {
78 | return ClipPath(
79 | clipper: CirclePath(animation.value),
80 | child: child,
81 | );
82 | },
83 | child: child,
84 | );
85 | });
86 | }
87 |
88 | void jumpVideoHistory(context) {
89 | Application.router.navigateTo(
90 | context,
91 | Routes.video_history,
92 | transition: TransitionType.cupertino,
93 | );
94 | }
95 |
--------------------------------------------------------------------------------
/lib/routes/routes.dart:
--------------------------------------------------------------------------------
1 | import 'package:fluro/fluro.dart';
2 | import 'package:flutter/cupertino.dart';
3 | import 'package:shuaishuaimovie/ui/pages/not_found_page.dart';
4 | import 'package:shuaishuaimovie/routes/route_handlers.dart';
5 |
6 | class Routes {
7 | static String splash = '/splash';
8 | static String index = '/index';
9 | static String home_detail = '/home/detail';
10 | static String video = '/video';
11 | static String hot_update = '/home/hotUpdate';
12 | static String rank = '/rank';
13 | static String cartoon = '/cartoon';
14 | static String condition_search = '/condition_search';
15 | static String txt_search = '/txt_search';
16 | static String video_history = '/video_history';
17 |
18 | static void configureRoutes(Router router) {
19 | router.notFoundHandler = Handler(
20 | handlerFunc: (BuildContext context, Map> params) {
21 | print("ROUTE WAS NOT FOUND !!!");
22 | return NotFoundPage();
23 | }
24 | );
25 |
26 | router.define(splash, handler: splashHandler);
27 | //type为0,1,2,3,4分别对应底部的tab。
28 | router.define(index + "/:type", handler: indexHandler);
29 | router.define(home_detail + "/:id/:imageUrl", handler: homeDetailHandler);
30 | router.define(video + "/:videoId/:videoUrl/:playUrlType/:playUrlIndex/:videoName/:videoLevel/:currentTime/:isPositive", handler: videoHandler);
31 | router.define(hot_update, handler: hotUpdateHandler);
32 | router.define(rank, handler: rankHandler);
33 | router.define(cartoon, handler: cartoonHandler);
34 | router.define(condition_search + "/:tabType/:classes", handler: conditionSearchHandler);
35 | router.define(txt_search, handler: txtSearchHandler);
36 | router.define(video_history, handler: videoHistoryHandler);
37 | }
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/lib/sharepreference/share_preference.dart:
--------------------------------------------------------------------------------
1 | import 'package:shared_preferences/shared_preferences.dart';
2 |
3 | class MovieSharePreference {
4 | static const String AUTO_PLAY = "auto_play";
5 | static Future _prefs = SharedPreferences.getInstance();
6 |
7 | static void saveAutoPlayValue(bool isAutoPlay) async {
8 | final SharedPreferences prefs = await _prefs;
9 | await prefs.setBool(AUTO_PLAY, isAutoPlay);
10 | }
11 |
12 | static Future getAutoPlayValue() async {
13 | final SharedPreferences prefs = await _prefs;
14 | return prefs.getBool(AUTO_PLAY);
15 | }
16 |
17 | }
--------------------------------------------------------------------------------
/lib/shuai_movie.dart:
--------------------------------------------------------------------------------
1 | import 'package:fluro/fluro.dart';
2 |
3 | class Application {
4 | static Router router;
5 | }
--------------------------------------------------------------------------------
/lib/ui/helper/db/db_operate.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/database/bean/search_history_bean.dart';
2 | import 'package:shuaishuaimovie/database/sqf_provider.dart';
3 | import 'package:shuaishuaimovie/database/bean/search_history_bean.dart' as historySearch;
4 |
5 | void insertHistorySearchDBTxt(String searchTxt) async {
6 | await SqfProvider.db.transaction((txn) async {
7 | //如果当前搜索条件在table中,跳过再一次存储
8 | List list = await txn.query(historySearch.tableName,
9 | distinct: false,
10 | orderBy: 'id desc',
11 | columns: [historySearch.columnName],
12 | where: '${historySearch.columnName}=?',
13 | whereArgs: [searchTxt]);
14 | print(list.length);
15 | if (list.length > 0) return;
16 | SearchHistoryBean searchHistoryBean = SearchHistoryBean();
17 | searchHistoryBean.name = searchTxt;
18 | await txn.insert(historySearch.tableName, searchHistoryBean.toMap());
19 | List results = await txn.rawQuery(
20 | 'SELECT id FROM ${historySearch.tableName}',
21 | );
22 | //默认只存16条数据
23 | for(int i = 0; i < results.length - 16; i++) {
24 | await txn.delete(historySearch.tableName, where: 'id=${results[i]['id']}');
25 | }
26 | });
27 | }
--------------------------------------------------------------------------------
/lib/ui/helper/home_detail_list_helper.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shuaishuaimovie/models/common_item_bean_entity.dart';
3 | import 'package:shuaishuaimovie/routes/route_jump.dart';
4 | import 'package:shuaishuaimovie/ui/helper/common_list_helper.dart';
5 |
6 |
7 | class DetailListTile extends StatelessWidget {
8 | const DetailListTile(this.title);
9 |
10 | final String title;
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | return Container(
15 | alignment: Alignment.centerLeft,
16 | height: 40,
17 | child: Text(
18 | title,
19 | style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
20 | )
21 | );
22 | }
23 | }
24 |
25 | class NarrowList extends StatelessWidget {
26 | NarrowList(this.list);
27 |
28 | List list;
29 |
30 |
31 | int itemCount() {
32 | return list.length;
33 | }
34 |
35 | @override
36 | Widget build(BuildContext context) {
37 | debugPrint("NarrowList");
38 | return SizedBox(
39 | height: 120,
40 | child: ListView.separated(
41 | scrollDirection: Axis.horizontal,
42 | itemBuilder: (context, index) {
43 | CommonItemBean commonItemBean = list[index];
44 | return GestureDetector(
45 | onTap: () {
46 | print(commonItemBean.vodID);
47 | jumpHomeDetail(
48 | context, commonItemBean.vodID.toString(), commonItemBean.vodPic,
49 | replace: true);
50 | },
51 | child: SizedBox(
52 | height: 120,
53 | width: 130,
54 | child: CommonNarrowListItem(commonItemBean),
55 | ),
56 | );
57 | },
58 | separatorBuilder: (BuildContext context, int index) {
59 | return SizedBox(
60 | width: 5,
61 | );
62 | },
63 | itemCount: itemCount(),
64 | ),
65 | );
66 | }
67 | }
68 |
69 | class CommonNarrowListItem extends StatelessWidget {
70 | CommonNarrowListItem(this.commonItemBean);
71 |
72 | final CommonItemBean commonItemBean;
73 |
74 | @override
75 | Widget build(BuildContext context) {
76 | return Column(
77 | crossAxisAlignment: CrossAxisAlignment.start,
78 | children: [
79 | Expanded(
80 | child: _buildNarrowItemImgModule(),
81 | ),
82 | buildItemTxtModule(commonItemBean.vodName, commonItemBean.vodActor),
83 | ],
84 | );
85 | }
86 |
87 | _buildNarrowItemImgModule() {
88 | return ClipRRect(
89 | borderRadius: BorderRadius.circular(4),
90 | child: Stack(
91 | children: [
92 | buildItemImg(commonItemBean.vodPic),
93 | buildUpdateInfoTxt(commonItemBean.vodRemarks),
94 | ],
95 | ),
96 | );
97 | }
98 | }
99 |
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/lib/ui/helper/home_list_helper.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:shuaishuaimovie/res/app_color.dart';
4 | import 'package:shuaishuaimovie/widgets/tag_widget.dart';
5 | import 'package:shuaishuaimovie/models/home_list_bean_entity.dart';
6 | import 'package:shuaishuaimovie/ui/helper/common_list_helper.dart';
7 |
8 | import 'common_list_helper.dart';
9 |
10 | class HotListTile extends StatefulWidget {
11 | const HotListTile(this.title,
12 | {@required this.updateCount,
13 | this.iconData,
14 | this.onMorePressed,
15 | this.onRefreshPressed});
16 |
17 | final IconData iconData;
18 | final String title;
19 | final String updateCount;
20 | final VoidCallback onMorePressed;
21 | final VoidCallback onRefreshPressed;
22 |
23 | @override
24 | _HotListTileState createState() => _HotListTileState();
25 | }
26 |
27 | class _HotListTileState extends State
28 | with SingleTickerProviderStateMixin {
29 | AnimationController _controller;
30 | Animation _animation;
31 |
32 | @override
33 | void initState() {
34 | super.initState();
35 | _controller = AnimationController(duration: Duration(milliseconds: 500), vsync: this);
36 | _animation = Tween(begin: 0, end: 2).animate(_controller);
37 | }
38 |
39 | @override
40 | void dispose() {
41 | _controller.dispose();
42 | super.dispose();
43 | }
44 |
45 | @override
46 | Widget build(BuildContext context) {
47 | return Container(
48 | margin: EdgeInsets.symmetric(horizontal: 15),
49 | height: 50,
50 | child: Row(
51 | children: [
52 | buildListTileTitle(widget.iconData, widget.title),
53 | GestureDetector(
54 | onTap: widget.onMorePressed,
55 | child: Container(
56 | padding: EdgeInsets.symmetric(horizontal: 10, vertical: 10),
57 | child: Row(
58 | children: [
59 | Text(
60 | "今日更新",
61 | style: TextStyle(
62 | fontSize: 11,
63 | ),
64 | ),
65 | SizedBox(
66 | width: 4,
67 | ),
68 | movieYellowTag(widget.updateCount),
69 | ],
70 | ),
71 | ),
72 | ),
73 | Spacer(),
74 | GestureDetector(
75 | onTap: () {
76 | if (_controller.isAnimating) return;
77 | if (_controller.isDismissed || _controller.isCompleted) {
78 | _controller.reset();
79 | _controller.forward();
80 | widget.onRefreshPressed();
81 | }
82 | },
83 | child: Row(
84 | mainAxisSize: MainAxisSize.min,
85 | children: [
86 | RotationTransition(
87 | turns: _animation,
88 | child: Icon(
89 | Icons.refresh,
90 | color: AppColor.icon_yellow,
91 | size: 15,
92 | ),
93 | ),
94 | SizedBox(
95 | width: 2,
96 | ),
97 | Text(
98 | "换一换",
99 | style: TextStyle(
100 | fontSize: 11,
101 | ),
102 | ),
103 | ],
104 | ),
105 | ),
106 | ],
107 | ),
108 | );
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/lib/ui/helper/view_state_helper.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:fluttertoast/fluttertoast.dart';
4 | import 'package:shuaishuaimovie/provider/view_state.dart';
5 | import 'package:shuaishuaimovie/res/app_color.dart';
6 | import 'package:shuaishuaimovie/viewmodels/base_model.dart';
7 |
8 | /// 针对加载中 数据为空 数据加载失败做统一处理
9 | class CommonViewStateHelper extends StatelessWidget {
10 | final T model;
11 | final VoidCallback onEmptyPressed;
12 | final VoidCallback onErrorPressed;
13 | final VoidCallback onNoNetworkPressed;
14 |
15 | CommonViewStateHelper({
16 | @required this.model,
17 | this.onEmptyPressed,
18 | this.onErrorPressed,
19 | this.onNoNetworkPressed,
20 | });
21 |
22 | @override
23 | Widget build(BuildContext context) {
24 | if (model.isLoading()) {
25 | return new ViewStateLoadingWidget();
26 | } else if (model.isEmpty()) {
27 | return new ViewStateEmptyWidget(onPressed: onEmptyPressed);
28 | } else if(model.isNoNetWork()) {
29 | Fluttertoast.showToast(msg: "当前没有网络");
30 | return new ViewStateNoNetworkWidget(onPressed: onNoNetworkPressed);
31 | } else if (model.isError()) {
32 | Fluttertoast.showToast(msg: "请求失败");
33 | return new ViewStateErrorWidget(
34 | error: model.viewStateError, onPressed: onErrorPressed);
35 | } else {
36 | throw new Exception('状态异常,请核查状态');
37 | }
38 | }
39 | }
40 |
41 | /// 初始化 加载中
42 | class ViewStateLoadingWidget extends StatelessWidget {
43 | @override
44 | Widget build(BuildContext context) {
45 | return new Scaffold(
46 | backgroundColor: AppColor.white,
47 | body: new Center(
48 | child: CupertinoActivityIndicator(),
49 | ),
50 | );
51 | }
52 | }
53 |
54 | /// 页面无数据
55 | class ViewStateEmptyWidget extends StatelessWidget {
56 | final String message;
57 | final VoidCallback onPressed;
58 |
59 | ViewStateEmptyWidget({this.message, this.onPressed});
60 |
61 | @override
62 | Widget build(BuildContext context) {
63 | return Scaffold(
64 | body: GestureDetector(
65 | onTap: () {
66 | onPressed();
67 | },
68 | child: Center(
69 | child: Container(
70 | padding: EdgeInsets.all(20),
71 | child: Text(
72 | message ?? '暂无数据,点击重试',
73 | textAlign: TextAlign.center,
74 | style: TextStyle(fontSize: 16, color: AppColor.black_33),
75 | ),
76 | ),
77 | )),
78 | );
79 | }
80 | }
81 |
82 | /// 页面数据请求异常
83 | class ViewStateErrorWidget extends StatelessWidget {
84 | final ViewStateError error;
85 | final VoidCallback onPressed;
86 |
87 | ViewStateErrorWidget({this.error, this.onPressed});
88 |
89 | @override
90 | Widget build(BuildContext context) {
91 | return Scaffold(
92 | body: GestureDetector(
93 | onTap: () {
94 | onPressed();
95 | },
96 | child: Center(
97 | child: Container(
98 | padding: EdgeInsets.all(20),
99 | child: Text(
100 | '数据请求异常,点击重试',
101 | textAlign: TextAlign.center,
102 | style: TextStyle(fontSize: 16, color: AppColor.black_33),
103 | ),
104 | ),
105 | )),
106 | );
107 | }
108 | }
109 |
110 | /// 页面没有网络
111 | class ViewStateNoNetworkWidget extends StatelessWidget {
112 | final String message;
113 | final VoidCallback onPressed;
114 |
115 | ViewStateNoNetworkWidget({this.message, this.onPressed});
116 |
117 | @override
118 | Widget build(BuildContext context) {
119 | return Scaffold(
120 | body: GestureDetector(
121 | onTap: () {
122 | onPressed();
123 | },
124 | child: Center(
125 | child: Container(
126 | padding: EdgeInsets.all(20),
127 | child: Text(
128 | message ?? '没有网络,点击重试',
129 | textAlign: TextAlign.center,
130 | style: TextStyle(fontSize: 16, color: AppColor.black_33),
131 | ),
132 | ),
133 | )),
134 | );
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/lib/ui/pages/hot/rank/hot_rank_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shuaishuaimovie/res/app_color.dart';
3 | import 'package:shuaishuaimovie/ui/pages/hot/rank/tab/month_rank_page.dart';
4 | import 'package:shuaishuaimovie/ui/pages/hot/rank/tab/total_rank_page.dart';
5 | import 'package:shuaishuaimovie/ui/pages/hot/rank/tab/week_rank_page.dart';
6 | import 'package:shuaishuaimovie/ui/pages/search/widget/search_widget.dart';
7 |
8 | class HotRankPage extends StatefulWidget {
9 | @override
10 | _HotRankPageState createState() => _HotRankPageState();
11 | }
12 |
13 | class _HotRankPageState extends State with SingleTickerProviderStateMixin {
14 | List tabs = ["周榜", "月榜", "总榜"];
15 | TabController _tabController;
16 |
17 | @override
18 | void initState() {
19 | super.initState();
20 | _tabController = TabController(length: tabs.length, vsync: this);
21 | }
22 | @override
23 | Widget build(BuildContext context) {
24 | return Scaffold(
25 | appBar: AppBar(
26 | title: Text("排行榜"),
27 | centerTitle: true,
28 | actions: [
29 | JumpHeroTxtSearchIconWidget(),
30 | ],
31 | bottom: TabBar(
32 | labelColor: AppColor.icon_yellow,
33 | unselectedLabelColor: AppColor.white,
34 | controller: _tabController,
35 | tabs: tabs.map((e) => Tab(text: e,)).toList(),
36 | ),
37 | ),
38 | body: Padding(
39 | padding: EdgeInsets.symmetric(horizontal: 10),
40 | child: TabBarView(
41 | controller: _tabController,
42 | children: [
43 | WeekRankPage(),
44 | MonthRankPage(),
45 | TotalRankPage(),
46 | ],
47 | ),
48 | ),
49 | );
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/lib/ui/pages/hot/rank/tab/month_rank_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shuaishuaimovie/provider/provider_widget.dart';
3 | import 'package:shuaishuaimovie/ui/helper/view_state_helper.dart';
4 | import 'package:shuaishuaimovie/ui/pages/hot/widget/hot_rank_widget.dart';
5 | import 'package:shuaishuaimovie/viewmodels/hot/hot_rank_model.dart';
6 |
7 | class MonthRankPage extends StatefulWidget {
8 | @override
9 | _MonthRankPageState createState() => _MonthRankPageState();
10 | }
11 |
12 | class _MonthRankPageState extends State
13 | with AutomaticKeepAliveClientMixin {
14 | @override
15 | Widget build(BuildContext context) {
16 | return ProviderWidget(
17 | model: MonthRankModel(),
18 | initData: (model) {
19 | loadData(model);
20 | },
21 | builder: (context, model, child) {
22 | if (!model.isSuccess()) {
23 | return CommonViewStateHelper(
24 | model: model,
25 | onEmptyPressed: () => loadData(model),
26 | onErrorPressed: () => loadData(model),
27 | onNoNetworkPressed: () => loadData(model),
28 | );
29 | }
30 | return _buildContent(model);
31 | },
32 | );
33 | }
34 |
35 | Widget _buildContent(model) {
36 | return HotRankModule(model);
37 | }
38 |
39 | void loadData(MonthRankModel model) {
40 | model.getRankApiData();
41 | }
42 |
43 | @override
44 | bool get wantKeepAlive => true;
45 | }
46 |
--------------------------------------------------------------------------------
/lib/ui/pages/hot/rank/tab/total_rank_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shuaishuaimovie/provider/provider_widget.dart';
3 | import 'package:shuaishuaimovie/ui/helper/view_state_helper.dart';
4 | import 'package:shuaishuaimovie/ui/pages/hot/widget/hot_rank_widget.dart';
5 | import 'package:shuaishuaimovie/viewmodels/hot/hot_rank_model.dart';
6 |
7 | class TotalRankPage extends StatefulWidget {
8 | @override
9 | _TotalRankPageState createState() => _TotalRankPageState();
10 | }
11 |
12 | class _TotalRankPageState extends State with AutomaticKeepAliveClientMixin{
13 | @override
14 | Widget build(BuildContext context) {
15 | return ProviderWidget(
16 | model: TotalRankModel(),
17 | initData: (model) {
18 | loadData(model);
19 | },
20 | builder: (context, model, child) {
21 | if (!model.isSuccess()) {
22 | return CommonViewStateHelper(
23 | model: model,
24 | onEmptyPressed: () => loadData(model),
25 | onErrorPressed: () => loadData(model),
26 | onNoNetworkPressed: () => loadData(model),
27 | );
28 | }
29 | return _buildContent(model);
30 | },
31 | );
32 | }
33 |
34 | Widget _buildContent(model) {
35 | return HotRankModule(model);
36 | }
37 |
38 | void loadData(TotalRankModel model) {
39 | model.getRankApiData();
40 |
41 | }
42 |
43 | @override
44 | bool get wantKeepAlive => true;
45 | }
46 |
--------------------------------------------------------------------------------
/lib/ui/pages/hot/rank/tab/week_rank_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shuaishuaimovie/provider/provider_widget.dart';
3 | import 'package:shuaishuaimovie/ui/helper/view_state_helper.dart';
4 | import 'package:shuaishuaimovie/ui/pages/hot/widget/hot_rank_widget.dart';
5 | import 'package:shuaishuaimovie/viewmodels/hot/hot_rank_model.dart';
6 |
7 | class WeekRankPage extends StatefulWidget {
8 | @override
9 | _WeekRankPageState createState() => _WeekRankPageState();
10 | }
11 |
12 | class _WeekRankPageState extends State with AutomaticKeepAliveClientMixin {
13 | @override
14 | Widget build(BuildContext context) {
15 | return ProviderWidget(
16 | model: WeekRankModel(),
17 | initData: (model) {
18 | loadData(model);
19 | },
20 | builder: (context, model, child) {
21 | if (!model.isSuccess()) {
22 | return CommonViewStateHelper(
23 | model: model,
24 | onEmptyPressed: () => loadData(model),
25 | onErrorPressed: () => loadData(model),
26 | onNoNetworkPressed: () => loadData(model),
27 | );
28 | }
29 | return _buildContent(model);
30 | },
31 | );
32 | }
33 |
34 | Widget _buildContent(model) {
35 | return HotRankModule(model);
36 | }
37 |
38 | void loadData(WeekRankModel model) {
39 | model.getRankApiData();
40 |
41 | }
42 |
43 | @override
44 | bool get wantKeepAlive => true;
45 | }
46 |
--------------------------------------------------------------------------------
/lib/ui/pages/hot/update/hot_update_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shuaishuaimovie/provider/provider_widget.dart';
3 | import 'package:shuaishuaimovie/ui/helper/hot_update_list_helper.dart';
4 | import 'package:shuaishuaimovie/ui/helper/view_state_helper.dart';
5 | import 'package:shuaishuaimovie/ui/pages/search/widget/search_widget.dart';
6 | import 'package:shuaishuaimovie/viewmodels/hot/hot_update_model.dart';
7 | import 'package:shuaishuaimovie/widgets/custom_refresh_widget.dart';
8 |
9 | class TodayHotUpdatePage extends StatelessWidget {
10 | @override
11 | Widget build(BuildContext context) {
12 | return Scaffold(
13 | appBar: AppBar(
14 | title: Text("热播更新"),
15 | centerTitle: true,
16 | actions: [
17 | JumpHeroTxtSearchIconWidget(),
18 | ],
19 | ),
20 | body: ProviderWidget(
21 | initData: (model) {
22 | loadData(model);
23 | },
24 | model: HotUpdateModel(),
25 | builder: (context, model, child) {
26 | if (!model.isSuccess()) {
27 | return CommonViewStateHelper(
28 | model: model,
29 | onEmptyPressed: () => loadData(model),
30 | onErrorPressed: () => loadData(model),
31 | onNoNetworkPressed: () => loadData(model),
32 | );
33 | }
34 | return Padding(
35 | padding: EdgeInsets.symmetric(horizontal: 10),
36 | child: _buildContent(model));
37 | },
38 | ),
39 | );
40 | }
41 |
42 | Widget _buildContent(HotUpdateModel model) {
43 | return CustomHeaderRefreshWidget(
44 | onRefresh: model.refreshHotUpdateData,
45 | easyRefreshController: model.easyRefreshController,
46 | slivers: [
47 | SliverToBoxAdapter(
48 | child: HotUpdateTile(
49 | hotUpdateModel: model,
50 | onRefreshPress: () {
51 | model.refreshLocalData();
52 | },
53 | ),
54 | ),
55 | SliverPadding(
56 | padding: EdgeInsets.only(top: 15),
57 | sliver: HotUpdateList(model.currentHotDatas),
58 | ),
59 | ],
60 | );
61 | }
62 |
63 | loadData(HotUpdateModel model) {
64 | model.getHotUpdateApiData();
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/lib/ui/pages/hot/widget/hot_rank_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shuaishuaimovie/routes/route_jump.dart';
3 | import 'package:shuaishuaimovie/ui/helper/hot_rank_list_helper.dart';
4 | import 'package:shuaishuaimovie/ui/pages/maintab/index_page.dart';
5 | import 'package:shuaishuaimovie/viewmodels/hot/hot_rank_model.dart';
6 | import 'package:shuaishuaimovie/widgets/custom_refresh_widget.dart';
7 |
8 | class HotRankModule extends StatelessWidget {
9 | HotRankModule(this.model);
10 |
11 | HotRankModel model;
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | return CustomHeaderRefreshWidget(
16 | onRefresh: () async {
17 | await model.refreshRankData();
18 | },
19 | easyRefreshController: model.easyRefreshController,
20 | slivers: [
21 | SliverToBoxAdapter(
22 | child: HotRankHeaderTile(
23 | IndexPage.TAB_MOVIE,
24 | onMorePress: () {
25 | jumpIndex(context, type: IndexPage.TAB_MOVIE, clearStack: true);
26 | },
27 | )),
28 | SliverPadding(
29 | padding: EdgeInsets.symmetric(vertical: 10),
30 | sliver: CommonSliverHotRankList(model.hotRankBeanEntity.movie)),
31 | SliverToBoxAdapter(
32 | child: HotRankHeaderTile(
33 | IndexPage.TAB_TELEPLAY,
34 | onMorePress: () {
35 | jumpIndex(context, type: IndexPage.TAB_TELEPLAY, clearStack: true);
36 | },
37 | )),
38 | SliverPadding(
39 | padding: EdgeInsets.symmetric(vertical: 10),
40 | sliver: CommonSliverHotRankList(model.hotRankBeanEntity.teleplay),
41 | ),
42 | SliverToBoxAdapter(
43 | child: HotRankHeaderTile(
44 | IndexPage.TAB_SHOW,
45 | onMorePress: () {
46 | jumpIndex(context, type: IndexPage.TAB_SHOW, clearStack: true);
47 | },
48 | )),
49 | SliverPadding(
50 | padding: EdgeInsets.symmetric(vertical: 10),
51 | sliver: CommonSliverHotRankList(model.hotRankBeanEntity.show),
52 | ),
53 | SliverToBoxAdapter(
54 | child: HotRankHeaderTile(
55 | IndexPage.TAB_CARTOON,
56 | onMorePress: () {
57 | jumpCartoon(context);
58 | },
59 | )),
60 | SliverPadding(
61 | padding: EdgeInsets.symmetric(vertical: 10),
62 | sliver: CommonSliverHotRankList(model.hotRankBeanEntity.cartoon),
63 | ),
64 | ],
65 | );
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/lib/ui/pages/hot/widget/hot_update_widget.dart:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/lib/ui/pages/maintab/cartoon/cartoon_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shuaishuaimovie/provider/provider_widget.dart';
3 | import 'package:shuaishuaimovie/res/app_color.dart';
4 | import 'package:shuaishuaimovie/routes/route_jump.dart';
5 | import 'package:shuaishuaimovie/ui/helper/view_state_helper.dart';
6 | import 'package:shuaishuaimovie/ui/pages/maintab/index_page.dart';
7 | import 'package:shuaishuaimovie/ui/pages/maintab/widget/common_tab_widget.dart';
8 | import 'package:shuaishuaimovie/ui/pages/search/txt_search_page.dart';
9 | import 'package:shuaishuaimovie/ui/pages/search/widget/search_widget.dart';
10 | import 'package:shuaishuaimovie/viewmodels/tab/commontab/common_tab_model.dart';
11 |
12 | class CartoonPage extends StatelessWidget {
13 | @override
14 | Widget build(BuildContext context) {
15 | return Scaffold(
16 | appBar: AppBar(
17 | title: Text("动漫剧场"),
18 | actions: [
19 | JumpHeroTxtSearchIconWidget(),
20 | ],
21 | ),
22 | body: ProviderWidget(
23 | initData: (model) {
24 | loadData(model);
25 | },
26 | model: CartoonModel(),
27 | builder: (context, model, child) {
28 | if (!model.isSuccess()) {
29 | return CommonViewStateHelper(
30 | model: model,
31 | onEmptyPressed: () => loadData(model),
32 | onErrorPressed: () => loadData(model),
33 | onNoNetworkPressed: () => loadData(model),
34 | );
35 | }
36 | return CommonTabWidget(model, IndexPage.TAB_CARTOON);
37 | },
38 | ),
39 | );
40 | }
41 |
42 | loadData(CartoonModel model) {
43 | model.getCommonTabApiData();
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/lib/ui/pages/maintab/home/home_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shuaishuaimovie/provider/provider_widget.dart';
3 | import 'package:shuaishuaimovie/ui/helper/view_state_helper.dart';
4 | import 'package:shuaishuaimovie/ui/pages/maintab/home/homewidget/home_list_widget.dart';
5 | import 'package:shuaishuaimovie/viewmodels/tab/home/home_model.dart';
6 | import 'package:shuaishuaimovie/widgets/custom_refresh_widget.dart';
7 |
8 | class HomePage extends StatefulWidget {
9 | @override
10 | _HomePageState createState() => _HomePageState();
11 | }
12 |
13 | class _HomePageState extends State with AutomaticKeepAliveClientMixin{
14 | @override
15 | Widget build(BuildContext context) {
16 | return ProviderWidget(
17 | initData: (model) {
18 | loadData(model);
19 | },
20 | model: HomeViewModel(),
21 | child: HomeContentHeaderWidget(),
22 | builder: (context, model, child) {
23 | if (!model.isSuccess()) {
24 | return CommonViewStateHelper(
25 | model: model,
26 | onEmptyPressed: () => loadData(model),
27 | onErrorPressed: () => loadData(model),
28 | onNoNetworkPressed: () => loadData(model),
29 | );
30 | }
31 |
32 | return CustomHeaderRefreshWidget(
33 | onRefresh: model.refreshHomeListData,
34 | easyRefreshController: model.easyRefreshController,
35 | slivers: [
36 | SliverToBoxAdapter(
37 | child: child,
38 | ),
39 | SliverHomeHotModuleWidget(model),
40 | SliverHomeMovieModuleWidget(model),
41 | SliverHomeSitcomModuleWidget(model),
42 | SliverHomeVarietyModuleWidget(model),
43 | SliverHomeAnimatedModuleWidget(model),
44 | ],
45 | );
46 | },
47 | );
48 | }
49 |
50 | loadData(HomeViewModel model) {
51 | model.getHomeListApiData();
52 | }
53 |
54 | @override
55 | // TODO: implement wantKeepAlive
56 | bool get wantKeepAlive => true;
57 | }
58 |
--------------------------------------------------------------------------------
/lib/ui/pages/maintab/movie/movie_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shuaishuaimovie/provider/provider_widget.dart';
3 | import 'package:shuaishuaimovie/ui/helper/view_state_helper.dart';
4 | import 'package:shuaishuaimovie/ui/pages/maintab/index_page.dart';
5 | import 'package:shuaishuaimovie/ui/pages/maintab/widget/common_tab_widget.dart';
6 | import 'package:shuaishuaimovie/viewmodels/tab/commontab/common_tab_model.dart';
7 |
8 | class MoviePage extends StatefulWidget {
9 | @override
10 | _MoviePageState createState() => _MoviePageState();
11 | }
12 |
13 | class _MoviePageState extends State with AutomaticKeepAliveClientMixin{
14 | @override
15 | Widget build(BuildContext context) {
16 | return ProviderWidget(
17 | initData: (model) {
18 | loadData(model);
19 | },
20 | model: MovieTabModel(),
21 | builder: (context, model, child) {
22 | if (!model.isSuccess()) {
23 | return CommonViewStateHelper(
24 | model: model,
25 | onEmptyPressed: () => loadData(model),
26 | onErrorPressed: () => loadData(model),
27 | onNoNetworkPressed: () => loadData(model),
28 | );
29 | }
30 | return CommonTabWidget(model, IndexPage.TAB_MOVIE);
31 | },
32 | );
33 | }
34 |
35 | loadData(MovieTabModel model) {
36 | model.getCommonTabApiData();
37 | }
38 |
39 | @override
40 | // TODO: implement wantKeepAlive
41 | bool get wantKeepAlive => true;
42 | }
43 |
--------------------------------------------------------------------------------
/lib/ui/pages/maintab/show/show_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shuaishuaimovie/provider/provider_widget.dart';
3 | import 'package:shuaishuaimovie/ui/helper/view_state_helper.dart';
4 | import 'package:shuaishuaimovie/ui/pages/maintab/index_page.dart';
5 | import 'package:shuaishuaimovie/ui/pages/maintab/widget/common_tab_widget.dart';
6 | import 'package:shuaishuaimovie/viewmodels/tab/commontab/common_tab_model.dart';
7 |
8 | class ShowPage extends StatefulWidget {
9 | @override
10 | _ShowPageState createState() => _ShowPageState();
11 | }
12 |
13 | class _ShowPageState extends State with AutomaticKeepAliveClientMixin{
14 | @override
15 | Widget build(BuildContext context) {
16 | return ProviderWidget(
17 | initData: (model) {
18 | loadData(model);
19 | },
20 | model: ShowTabModel(),
21 | builder: (context, model, child) {
22 | if (!model.isSuccess()) {
23 | return CommonViewStateHelper(
24 | model: model,
25 | onEmptyPressed: () => loadData(model),
26 | onErrorPressed: () => loadData(model),
27 | onNoNetworkPressed: () => loadData(model),
28 | );
29 | }
30 | return CommonTabWidget(model, IndexPage.TAB_SHOW);
31 | },
32 | );
33 | }
34 |
35 | loadData(ShowTabModel model) {
36 | model.getCommonTabApiData();
37 | }
38 |
39 | @override
40 | // TODO: implement wantKeepAlive
41 | bool get wantKeepAlive => true;
42 | }
43 |
--------------------------------------------------------------------------------
/lib/ui/pages/maintab/teleplay/teleplay_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shuaishuaimovie/provider/provider_widget.dart';
3 | import 'package:shuaishuaimovie/ui/helper/view_state_helper.dart';
4 | import 'package:shuaishuaimovie/ui/pages/maintab/index_page.dart';
5 | import 'package:shuaishuaimovie/ui/pages/maintab/widget/common_tab_widget.dart';
6 | import 'package:shuaishuaimovie/viewmodels/tab/commontab/common_tab_model.dart';
7 |
8 | class TeleplayPage extends StatefulWidget {
9 | @override
10 | _TeleplayPageState createState() => _TeleplayPageState();
11 | }
12 |
13 | class _TeleplayPageState extends State with AutomaticKeepAliveClientMixin {
14 | @override
15 | Widget build(BuildContext context) {
16 | return ProviderWidget(
17 | initData: (model) {
18 | loadData(model);
19 | },
20 | model: TeleplayTabModel(),
21 | builder: (context, model, child) {
22 | if (!model.isSuccess()) {
23 | return CommonViewStateHelper(
24 | model: model,
25 | onEmptyPressed: () => loadData(model),
26 | onErrorPressed: () => loadData(model),
27 | onNoNetworkPressed: () => loadData(model),
28 | );
29 | }
30 | return CommonTabWidget(model, IndexPage.TAB_TELEPLAY);
31 | },
32 | );
33 | }
34 |
35 | loadData(TeleplayTabModel model) {
36 | model.getCommonTabApiData();
37 | }
38 |
39 | @override
40 | // TODO: implement wantKeepAlive
41 | bool get wantKeepAlive => true;
42 | }
43 |
--------------------------------------------------------------------------------
/lib/ui/pages/mine/mine_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shuaishuaimovie/res/app_color.dart';
3 | import 'package:shuaishuaimovie/sharepreference/share_preference.dart';
4 | import 'package:shuaishuaimovie/utils/app_info_util.dart';
5 | import 'package:shuaishuaimovie/widgets/text_widget.dart';
6 |
7 | class MinePage extends StatefulWidget {
8 | @override
9 | _MinePageState createState() => _MinePageState();
10 | }
11 |
12 | class _MinePageState extends State {
13 | bool isAutoPlay = true;
14 | String appVersion = "";
15 |
16 | @override
17 | void initState() {
18 | super.initState();
19 | WidgetsBinding.instance.addPostFrameCallback(
20 | (timeStamp) => AppInfoUtil.getAppVersion().then((value) {
21 | setState(() {
22 | appVersion = value;
23 | });
24 | }));
25 | }
26 |
27 | @override
28 | Widget build(BuildContext context) {
29 | print(appVersion);
30 |
31 | return Scaffold(
32 | appBar: AppBar(
33 | title: Text("留言页面"),
34 | centerTitle: true,
35 | backgroundColor: AppColor.black,
36 | ),
37 | body: SingleChildScrollView(
38 | physics: BouncingScrollPhysics(),
39 | child: Column(
40 | children: [
41 | ListTile(
42 | title: Text("视频自动播放"),
43 | trailing: Switch(
44 | value: isAutoPlay,
45 | onChanged: (bool value) {
46 | setState(() {
47 | isAutoPlay = !isAutoPlay;
48 | MovieSharePreference.saveAutoPlayValue(isAutoPlay);
49 | });
50 | },
51 | ),
52 | ),
53 | ListTile(
54 | title: Text("作者微信号:"),
55 | trailing: SelectableText("MS_miaoshuai"),
56 | ),
57 | ListTile(
58 | title: Text("当前版本号:"),
59 | trailing: Text(appVersion),
60 | ),
61 | SizedBox(
62 | height: 20,
63 | ),
64 | Padding(
65 | padding: EdgeInsets.symmetric(horizontal: 15),
66 | child: Column(
67 | mainAxisSize: MainAxisSize.min,
68 | crossAxisAlignment: CrossAxisAlignment.start,
69 | children: [
70 | CommonText(
71 | "结束语:",
72 | txtSize: 16,
73 | txtWeight: FontWeight.bold,
74 | ),
75 | CommonText(
76 | " Flutter的框架和社区已经算是非常的成熟了,对于Flutter的流行度你可以通过github的star不难看出这个框架不亚于RN等主流的跨平台开发的其他的框架。而且Flutter出道比较晚,当前作者基于开发的版本才1.20。所以作者认为对于Flutter接下来的路还是相当客观的。在这里也不多说Flutter的优点了,如果不知道的小伙伴可以看官网或者搜索一些其他对Flutter的认知的文章进行阅读。",
77 | txtSize: 15,
78 | ),
79 | CommonText(
80 | " 作者开发了这个帅帅影视的开源项目的目的在于1.可以在项目中对于flutter进行跟深入的学习。2.同样为了帮助那些想要学习或者正要进行学习Flutter的同学的提供一个开源的Flutter项目用于参考",
81 | txtSize: 15,
82 | ),
83 | CommonText(
84 | " 在开发项目中,作者不得不在一次感慨一下开发起来特别爽,开发一款Flutter的项目的开发进度作者认为至少比原生提高百分之20%,更何况一套代码两端运行呢!",
85 | txtSize: 15,
86 | ),
87 | CommonText(
88 | " 最后如果小伙伴拥有好的idea,并且可以进行用Flutter开发的话。愿意参与进行共同维护这块开源项目,为Flutter社区做一些贡献的欢迎私聊我哦。",
89 | txtSize: 15,
90 | ),
91 | SizedBox(
92 | height: 50,
93 | ),
94 | ],
95 | ),
96 | ),
97 | ],
98 | ),
99 | ),
100 | );
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/lib/ui/pages/not_found_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class NotFoundPage extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return Container();
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/lib/ui/pages/search/tab/hot_search_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shuaishuaimovie/provider/provider_widget.dart';
3 | import 'package:shuaishuaimovie/ui/helper/common_list_helper.dart';
4 | import 'package:shuaishuaimovie/ui/helper/view_state_helper.dart';
5 | import 'package:shuaishuaimovie/viewmodels/search/condition_search_model.dart';
6 | import 'package:shuaishuaimovie/viewmodels/search/select_condition_model.dart';
7 | import 'package:shuaishuaimovie/widgets/refresh_widget.dart';
8 |
9 | class HotSearchPage extends StatefulWidget {
10 | HotSearchPage({Key key, this.model, this.tabType}) : super(key: key);
11 |
12 | String tabType;
13 | SelectionConditionModel model;
14 |
15 | @override
16 | HotSearchPageState createState() => HotSearchPageState();
17 | }
18 |
19 | class HotSearchPageState extends State {
20 | ConditionSearchModel conditionSearchModel;
21 |
22 | @override
23 | Widget build(BuildContext context) {
24 | return ProviderWidget(
25 | initData: (model) {
26 | conditionSearchModel = model;
27 | loadData(model);
28 | },
29 | model: HotConditionModel(widget.tabType)
30 | ..selectionConditionModel = widget.model,
31 | builder: (_, HotConditionModel model, __) {
32 | debugPrint("build_new_search_page");
33 | if (!model.isSuccess()) {
34 | return CommonViewStateHelper(
35 | model: model,
36 | onEmptyPressed: () => loadData(model),
37 | onErrorPressed: () => loadData(model),
38 | onNoNetworkPressed: () => loadData(model),
39 | );
40 | }
41 |
42 | return FooterLoadMoreWidget(
43 | topBouncing: false,
44 | bottomBouncing: false,
45 | easyRefreshController: model.easyRefreshController,
46 | onLoadMore: (model.qty ?? 0) <= 36
47 | ? null
48 | : () async {
49 | await model.loadMoreConditionSearchData();
50 | setState(() {});
51 | },
52 | child: Column(
53 | children: [
54 | SizedBox(
55 | height: 67,
56 | ),
57 | CommonGrid(
58 | model.conditionSearchBeanDatas,
59 | isShowTag: false,
60 | ),
61 | ],
62 | ),
63 | );
64 | },
65 | );
66 | }
67 |
68 | void loadData(HotConditionModel model) {
69 | model.getConditionSearchApiData();
70 | }
71 |
72 | void refreshData() {
73 | conditionSearchModel.refreshConditionSearchApiData();
74 | }
75 |
76 | bool isLoading() {
77 | return conditionSearchModel.isLoading();
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/lib/ui/pages/search/tab/new_search_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:provider/provider.dart';
3 | import 'package:shuaishuaimovie/provider/provider_widget.dart';
4 | import 'package:shuaishuaimovie/ui/helper/common_list_helper.dart';
5 | import 'package:shuaishuaimovie/ui/helper/view_state_helper.dart';
6 | import 'package:shuaishuaimovie/viewmodels/search/condition_search_model.dart';
7 | import 'package:shuaishuaimovie/viewmodels/search/select_condition_model.dart';
8 | import 'package:shuaishuaimovie/widgets/refresh_widget.dart';
9 |
10 | class NewSearchPage extends StatefulWidget {
11 | NewSearchPage({Key key, this.model, this.tabType}) : super(key: key);
12 |
13 | String tabType;
14 | SelectionConditionModel model;
15 |
16 | @override
17 | NewSearchPageState createState() => NewSearchPageState();
18 | }
19 |
20 | class NewSearchPageState extends State {
21 | ConditionSearchModel conditionSearchModel;
22 |
23 | @override
24 | Widget build(BuildContext context) {
25 | return ProviderWidget(
26 | initData: (model) {
27 | conditionSearchModel = model;
28 | loadData(model);
29 | },
30 | model: TimeConditionModel(widget.tabType)
31 | ..selectionConditionModel = widget.model,
32 | builder: (_, TimeConditionModel model, __) {
33 | debugPrint("build_new_search_page");
34 | if (!model.isSuccess()) {
35 | return CommonViewStateHelper(
36 | model: model,
37 | onEmptyPressed: () => loadData(model),
38 | onErrorPressed: () => loadData(model),
39 | onNoNetworkPressed: () => loadData(model),
40 | );
41 | }
42 |
43 | Provider.of(context).qty = model.qty.toString();
44 | return FooterLoadMoreWidget(
45 | topBouncing: false,
46 | bottomBouncing: false,
47 | easyRefreshController: model.easyRefreshController,
48 | onLoadMore: (model.qty ?? 0) <= 36
49 | ? null
50 | : () async {
51 | await model.loadMoreConditionSearchData();
52 | setState(() {});
53 | },
54 | child: Column(
55 | children: [
56 | SizedBox(
57 | height: 67,
58 | ),
59 | CommonGrid(
60 | model.conditionSearchBeanDatas,
61 | isShowTag: false,
62 | ),
63 | ],
64 | ),
65 | );
66 | },
67 | );
68 | }
69 |
70 | void loadData(TimeConditionModel model) {
71 | model.getConditionSearchApiData();
72 | }
73 |
74 | void refreshData() {
75 | conditionSearchModel.refreshConditionSearchApiData();
76 | }
77 |
78 | bool isLoading() {
79 | return conditionSearchModel.isLoading();
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/lib/ui/pages/search/tab/score_search_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:provider/provider.dart';
3 | import 'package:shuaishuaimovie/provider/provider_widget.dart';
4 | import 'package:shuaishuaimovie/ui/helper/common_list_helper.dart';
5 | import 'package:shuaishuaimovie/ui/helper/view_state_helper.dart';
6 | import 'package:shuaishuaimovie/viewmodels/search/condition_search_model.dart';
7 | import 'package:shuaishuaimovie/viewmodels/search/select_condition_model.dart';
8 | import 'package:shuaishuaimovie/widgets/refresh_widget.dart';
9 |
10 | class ScoreSearchPage extends StatefulWidget {
11 | ScoreSearchPage({Key key, this.model, this.tabType}) : super(key: key);
12 |
13 | String tabType;
14 | SelectionConditionModel model;
15 |
16 | @override
17 | ScoreSearchPageState createState() => ScoreSearchPageState();
18 | }
19 |
20 | class ScoreSearchPageState extends State {
21 | ConditionSearchModel conditionSearchModel;
22 |
23 | @override
24 | Widget build(BuildContext context) {
25 | return ProviderWidget(
26 | initData: (model) {
27 | conditionSearchModel = model;
28 | loadData(model);
29 | },
30 | model: ScoreConditionModel(widget.tabType)
31 | ..selectionConditionModel = widget.model,
32 | builder: (context, ScoreConditionModel model, __) {
33 | debugPrint("build_new_search_page");
34 | if (!model.isSuccess()) {
35 | return CommonViewStateHelper(
36 | model: model,
37 | onEmptyPressed: () => loadData(model),
38 | onErrorPressed: () => loadData(model),
39 | onNoNetworkPressed: () => loadData(model),
40 | );
41 | }
42 |
43 | Provider.of(context).qty = model.qty.toString();
44 | return FooterLoadMoreWidget(
45 | topBouncing: false,
46 | bottomBouncing: false,
47 | easyRefreshController: model.easyRefreshController,
48 | onLoadMore: (model.qty ?? 0) <= 36
49 | ? null
50 | : () async {
51 | await model.loadMoreConditionSearchData();
52 | setState(() {});
53 | },
54 | child: Column(
55 | children: [
56 | SizedBox(
57 | height: 67,
58 | ),
59 | CommonGrid(
60 | model.conditionSearchBeanDatas,
61 | isShowTag: false,
62 | ),
63 | ],
64 | ),
65 | );
66 | },
67 | );
68 | }
69 |
70 | void loadData(ScoreConditionModel model) {
71 | model.getConditionSearchApiData();
72 | }
73 |
74 | void refreshData() {
75 | conditionSearchModel.refreshConditionSearchApiData();
76 | }
77 |
78 | bool isLoading() {
79 | return conditionSearchModel.isLoading();
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/lib/ui/pages/search/widget/search_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shuaishuaimovie/res/app_color.dart';
3 | import 'package:shuaishuaimovie/routes/route_jump.dart';
4 | import 'package:shuaishuaimovie/ui/pages/search/txt_search_page.dart';
5 |
6 | class JumpHeroTxtSearchIconWidget extends StatelessWidget {
7 | @override
8 | Widget build(BuildContext context) {
9 | return InkWell(
10 | onTap: () {
11 | jumpTxtSearch(context);
12 | },
13 | child: Hero(
14 | tag: TxtSearchPage.TXT_SEARCH,
15 | child: Padding(
16 | padding: EdgeInsets.all(10),
17 | child: Icon(Icons.search)),
18 | transitionOnUserGestures: true,
19 | flightShuttleBuilder: (flightContext, animation, direction,
20 | fromContext, toContext) {
21 | return Icon(Icons.arrow_back, color: AppColor.white,);
22 | },
23 | ),
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/ui/pages/search/widget/txt_auto_search_child.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shuaishuaimovie/models/common_item_bean_entity.dart';
3 | import 'package:shuaishuaimovie/provider/provider_widget.dart';
4 | import 'package:shuaishuaimovie/res/app_color.dart';
5 | import 'package:shuaishuaimovie/routes/route_jump.dart';
6 | import 'package:shuaishuaimovie/ui/helper/db/db_operate.dart';
7 | import 'package:shuaishuaimovie/viewmodels/search/txt_auto_search_model.dart';
8 |
9 | class TxtAutoSearchChild extends StatefulWidget {
10 | TxtAutoSearchChild({Key key, this.jumpCallback}) : super(key: key);
11 | VoidCallback jumpCallback;
12 |
13 | @override
14 | TxtAutoSearchChildState createState() => TxtAutoSearchChildState();
15 | }
16 |
17 | class TxtAutoSearchChildState extends State {
18 | TxtAutoSearchModel model;
19 | String keyword = "";
20 |
21 | @override
22 | Widget build(BuildContext context) {
23 | return ProviderWidget(
24 | initData: (model) {
25 | this.model = model;
26 | },
27 | model: TxtAutoSearchModel(),
28 | builder: (_, TxtAutoSearchModel model, child) {
29 | return Container(
30 | color: AppColor.white,
31 | child: ListView.separated(
32 | itemBuilder: (BuildContext context, int index) {
33 | CommonItemBean bean = model.txtAutoSearchBeanDatas[index];
34 | return ListTile(
35 | onTap: () {
36 | widget.jumpCallback();
37 | jumpHomeDetail(context, bean.vodID.toString(), bean.vodPic);
38 | insertHistorySearchDBTxt(bean.vodName);
39 | },
40 | title: Text.rich(
41 | TextSpan(children: [
42 | for (String txt
43 | in model.processedTxt(bean.vodName, keyword))
44 | TextSpan(
45 | text: txt,
46 | style: TextStyle(
47 | color: txt == keyword
48 | ? AppColor.icon_yellow
49 | : AppColor.black,
50 | ),
51 | ),
52 | ]),
53 | ),
54 | );
55 | },
56 | itemCount: model.txtAutoSearchBeanDatas?.length ?? 0,
57 | separatorBuilder: (BuildContext context, int index) {
58 | return Container(
59 | height: 1,
60 | color: AppColor.line_grey,
61 | );
62 | },
63 | ),
64 | );
65 | },
66 | );
67 | }
68 |
69 |
70 | Future loadData(String keyword) async{
71 | this.keyword = keyword;
72 | await model.getTxtAutoSearchApiData(keyword);
73 | }
74 |
75 | void resetData() {
76 | model.clearData();
77 | }
78 |
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/lib/ui/pages/search/widget/txt_normal_search_child.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shuaishuaimovie/provider/provider_widget.dart';
3 | import 'package:shuaishuaimovie/res/app_color.dart';
4 | import 'package:shuaishuaimovie/ui/helper/search_list_helper.dart';
5 | import 'package:shuaishuaimovie/ui/helper/view_state_helper.dart';
6 | import 'package:shuaishuaimovie/viewmodels/search/txt_normal_search_model.dart';
7 | import 'package:shuaishuaimovie/widgets/custom_refresh_widget.dart';
8 |
9 | class TxtNormalSearchChild extends StatefulWidget {
10 | TxtNormalSearchChild({this.jumpCallback, Key key}) : super(key: key);
11 | VoidCallback jumpCallback;
12 |
13 | @override
14 | TxtNormalSearchChildState createState() => TxtNormalSearchChildState();
15 | }
16 |
17 | class TxtNormalSearchChildState extends State {
18 | String keyword;
19 | NormalSearchModel model;
20 |
21 | @override
22 | Widget build(BuildContext context) {
23 | return ProviderWidget(
24 | initData: (model) {
25 | this.model = model;
26 | },
27 | model: NormalSearchModel(),
28 | builder: (_, NormalSearchModel model, child) {
29 | print(model.isSuccess());
30 | if (!model.isSuccess() &&
31 | (keyword == null ? false : keyword.isNotEmpty)) {
32 | return CommonViewStateHelper(
33 | model: model,
34 | onEmptyPressed: () => loadData(keyword),
35 | onErrorPressed: () => loadData(keyword),
36 | onNoNetworkPressed: () => loadData(keyword),
37 | );
38 | }
39 |
40 | return Padding(
41 | padding: EdgeInsets.symmetric(horizontal: 10),
42 | child: CustomFooterLoadMoreWidget(
43 | easyRefreshController: model.easyRefreshController,
44 | onLoadMore: (model.qty ?? 0) <= 36
45 | ? null
46 | : () async {
47 | await model.loadMoreNormalSearchData();
48 | },
49 | slivers: [
50 | SliverToBoxAdapter(
51 | child: Padding(
52 | padding: EdgeInsets.symmetric(vertical: 15),
53 | child: Text.rich(TextSpan(
54 | text: "搜索到与",
55 | style: TextStyle(
56 | color: AppColor.black,
57 | fontSize: 17,
58 | ),
59 | children: [
60 | TextSpan(
61 | text: "\"$keyword\"",
62 | style: TextStyle(
63 | color: AppColor.icon_yellow,
64 | ),
65 | ),
66 | TextSpan(
67 | text: "相关的",
68 | style: TextStyle(
69 | color: AppColor.black,
70 | ),
71 | ),
72 | TextSpan(
73 | text: model.qty.toString(),
74 | style: TextStyle(
75 | color: AppColor.icon_yellow,
76 | ),
77 | ),
78 | TextSpan(
79 | text: "条结果",
80 | style: TextStyle(
81 | color: AppColor.black,
82 | ),
83 | ),
84 | ],
85 | )),
86 | ),
87 | ),
88 | NormalSearchList(
89 | model.conditionSearchBeanDatas,
90 | jumpCallback: widget.jumpCallback,
91 | ),
92 | ],
93 | ),
94 | );
95 | },
96 | );
97 | }
98 |
99 | void loadData(String keyword) {
100 | this.keyword = keyword;
101 | model.getNormalSearchApiData(keyword);
102 | }
103 |
104 | void resetData() {
105 | model.currentPage = 1;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/lib/ui/pages/splash_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shuaishuaimovie/res/app_color.dart';
3 | import 'package:shuaishuaimovie/routes/route_jump.dart';
4 |
5 | class SplashPage extends StatefulWidget {
6 | @override
7 | _SplashPageState createState() => _SplashPageState();
8 | }
9 |
10 | class _SplashPageState extends State
11 | with SingleTickerProviderStateMixin {
12 | AnimationController _animationController;
13 | Animation _animLeft;
14 | Animation _animRight;
15 | Gradient _textGradient;
16 |
17 | @override
18 | void initState() {
19 | super.initState();
20 |
21 | _animationController = AnimationController(
22 | duration: Duration(milliseconds: 1000), vsync: this);
23 |
24 | Future.delayed(Duration(milliseconds: 300)).then((value) {
25 | _animationController.forward();
26 | Future.delayed(Duration(milliseconds: 2000)).then((value) {
27 | jumpIndex(context, replace: true);
28 | });
29 | });
30 |
31 | _textGradient = LinearGradient(
32 | begin: Alignment.centerLeft,
33 | end: Alignment.centerRight,
34 | colors: [Colors.blue[300], Colors.blue]);
35 | }
36 |
37 | @override
38 | void didChangeDependencies() {
39 | super.didChangeDependencies();
40 |
41 | final offset = getTextWidth("帅帅影视") - getTextWidth("Flutter");
42 | final screenWidth = MediaQuery.of(context).size.width;
43 | _animLeft = Tween(begin: -screenWidth / 2 - offset / 2, end: 0.toDouble())
44 | .animate(CurvedAnimation(
45 | parent: _animationController, curve: Curves.easeIn));
46 | _animRight = Tween(begin: screenWidth / 2 - offset / 2, end: 0.toDouble())
47 | .animate(CurvedAnimation(
48 | parent: _animationController, curve: Curves.easeIn));
49 | }
50 |
51 | @override
52 | Widget build(BuildContext context) {
53 | return Scaffold(
54 | backgroundColor: AppColor.black,
55 | body: Container(
56 | color: AppColor.white,
57 | alignment: Alignment.center,
58 | child: Row(
59 | mainAxisSize: MainAxisSize.min,
60 | children: [
61 | if (_animLeft != null)
62 | AnimatedBuilder(
63 | animation: _animLeft,
64 | builder: (BuildContext context, Widget child) {
65 | return Transform.translate(
66 | offset: Offset(_animLeft.value, 0),
67 | child: Text(
68 | 'Flutter',
69 | style: TextStyle(
70 | fontSize: 30,
71 | color: Colors.black,
72 | fontWeight: FontWeight.w600,
73 | ),
74 | ),
75 | );
76 | },
77 | ),
78 | SizedBox(
79 | width: 5,
80 | ),
81 | if (_animRight != null) _buildLogoTxt(),
82 | ],
83 | ),
84 | ),
85 | );
86 | }
87 |
88 | _buildLogoTxt() {
89 | return AnimatedBuilder(
90 | animation: _animRight,
91 | builder: (BuildContext context, Widget child) {
92 | return Transform.translate(
93 | offset: Offset(_animRight.value, 0),
94 | child: Text.rich(
95 | TextSpan(
96 | text: "帅帅",
97 | style: TextStyle(
98 | foreground: Paint()
99 | ..shader =
100 | _textGradient.createShader(Rect.fromLTRB(0, 0, 40, 40)),
101 | fontSize: 30,
102 | fontWeight: FontWeight.w600,
103 | ),
104 | children: [
105 | TextSpan(
106 | text: "影视",
107 | style: TextStyle(
108 | fontSize: 30,
109 | fontWeight: FontWeight.w600,
110 | foreground: Paint()..color = Colors.pink[400],
111 | ),
112 | ),
113 | ],
114 | ),
115 | ),
116 | );
117 | },
118 | );
119 | }
120 |
121 | double getTextWidth(String text) {
122 | final textPainter = TextPainter(
123 | text: TextSpan(
124 | text: text,
125 | style: TextStyle(
126 | fontSize: 30,
127 | fontWeight: FontWeight.w600,
128 | ),
129 | ),
130 | textDirection: TextDirection.ltr,
131 | );
132 | textPainter.layout(minWidth: 0, maxWidth: double.infinity);
133 | return textPainter.width;
134 | }
135 |
136 | @override
137 | void dispose() {
138 | _animationController.dispose();
139 | super.dispose();
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/lib/ui/pages/video/video_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:shuaishuaimovie/provider/provider_widget.dart';
4 | import 'package:shuaishuaimovie/res/app_color.dart';
5 | import 'package:shuaishuaimovie/ui/helper/view_state_helper.dart';
6 | import 'package:shuaishuaimovie/ui/pages/maintab/home/homewidget/home_detail_widget.dart';
7 | import 'package:shuaishuaimovie/ui/pages/video/widget/shuai_video.dart';
8 | import 'package:shuaishuaimovie/viewmodels/video/video_model.dart';
9 |
10 | class VideoPage extends StatefulWidget {
11 | VideoPage({
12 | @required this.videoId,
13 | @required this.videoUrl,
14 | @required this.videoName,
15 | @required this.videoLevel,
16 | @required this.playUrlType,
17 | @required this.playUrlIndex,
18 | @required this.isPositive,
19 | this.currentTime,
20 | });
21 |
22 | String videoId;
23 | String videoUrl;
24 | String playUrlType;
25 | int playUrlIndex;
26 | String videoName;
27 | String videoLevel;
28 | String currentTime;
29 | String isPositive;
30 |
31 | static const String BASE_VIDEO_URL = "https://vip1.sp-flv.com/p2p/?v=";
32 |
33 | @override
34 | State createState() {
35 | return _VideoPageState();
36 | }
37 | }
38 |
39 | class _VideoPageState extends State {
40 | @override
41 | void initState() {
42 | super.initState();
43 | //将videoUrl 解码
44 | widget.videoUrl = Uri.decodeComponent(widget.videoUrl);
45 | }
46 |
47 | @override
48 | void dispose() {
49 | super.dispose();
50 | }
51 |
52 | @override
53 | Widget build(BuildContext context) {
54 | return Scaffold(
55 | backgroundColor: AppColor.black,
56 | body: SafeArea(
57 | child: Container(
58 | color: AppColor.white,
59 | child: ProviderWidget(
60 | initData: (model) {
61 | loadData(model);
62 | },
63 | model: VideoViewModel(
64 | videoId: widget.videoId,
65 | videoUrl: widget.videoUrl,
66 | playUrlType: widget.playUrlType,
67 | playUrlIndex: widget.playUrlIndex,
68 | videoName: widget.videoName,
69 | videoLevel: widget.videoLevel,
70 | currentTime: widget.currentTime,
71 | isPositive: widget.isPositive,
72 | ),
73 | builder:
74 | (BuildContext context, VideoViewModel model, Widget child) {
75 | return Column(
76 | children: [
77 | ShuaiVideo(model),
78 | Expanded(child: _buildVideoSelectionContent(model)),
79 | ],
80 | );
81 | },
82 | ),
83 | ),
84 | ),
85 | );
86 | }
87 |
88 | Widget _buildVideoSelectionContent(VideoViewModel model) {
89 | if (!model.isSuccess()) {
90 | return CommonViewStateHelper(
91 | model: model,
92 | onEmptyPressed: () => loadData(model),
93 | onErrorPressed: () => loadData(model),
94 | onNoNetworkPressed: () => loadData(model),
95 | );
96 | }
97 | return SingleChildScrollView(
98 | physics: BouncingScrollPhysics(),
99 | child: Padding(
100 | padding: EdgeInsets.all(15),
101 | child: MovieSelectionModuleWidget(
102 | model.playUrls,
103 | selectedIndex: model.playUrlIndex,
104 | isPositive: model.isPositive,
105 | onAssembleTap: (index, isPositive) {
106 | model.changeVideo(index, isPositive);
107 | },
108 | onSortTap: (index, flag) {
109 | model.playUrlIndex = index;
110 | model.setPositive(flag ? "1" : "0");
111 | },
112 | ),
113 | ),
114 | );
115 | }
116 |
117 | Future loadData(VideoViewModel model) async {
118 | await model.getHomeDetailApiData(widget.videoId);
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/lib/utils/app_info_util.dart:
--------------------------------------------------------------------------------
1 | import 'package:package_info/package_info.dart';
2 |
3 | class AppInfoUtil {
4 | static Future _initPageInfo() async {
5 | return await PackageInfo.fromPlatform();
6 | }
7 |
8 | static Future getAppVersion() async {
9 | final PackageInfo packageInfo = await _initPageInfo();
10 | return packageInfo.version;
11 | }
12 | }
--------------------------------------------------------------------------------
/lib/utils/net/net_work.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'package:connectivity/connectivity.dart';
3 |
4 |
5 | Future isConnected() async {
6 | var connectivityResult = await (Connectivity().checkConnectivity());
7 | print(connectivityResult != ConnectivityResult.none);
8 | return connectivityResult != ConnectivityResult.none;
9 | }
10 |
11 | Future checkNetMobile() async {
12 | var connectivityResult = await (Connectivity().checkConnectivity());
13 | return connectivityResult == ConnectivityResult.mobile;
14 | }
15 |
16 | Future checkNetWifi() async {
17 | var connectivityResult = await (Connectivity().checkConnectivity());
18 | return connectivityResult == ConnectivityResult.wifi;
19 | }
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/lib/utils/str_util.dart:
--------------------------------------------------------------------------------
1 | class StrUtil {
2 | static isNotEmpty(String txt) {
3 | return txt != null && txt.length > 0;
4 | }
5 | }
--------------------------------------------------------------------------------
/lib/utils/system/system_chrome.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:shuaishuaimovie/res/app_color.dart';
4 |
5 | class MovieSystemChrome {
6 | static const SystemUiOverlayStyle statusDark = SystemUiOverlayStyle(
7 | statusBarColor: Color(0xFF000000),
8 | statusBarIconBrightness: Brightness.light,
9 | statusBarBrightness: Brightness.dark,
10 | );
11 |
12 | static const SystemUiOverlayStyle statusTransparent = SystemUiOverlayStyle(
13 | statusBarColor: AppColor.transparent,
14 | statusBarBrightness: Brightness.dark,
15 | );
16 | }
--------------------------------------------------------------------------------
/lib/utils/time/movie_time_util.dart:
--------------------------------------------------------------------------------
1 | import 'package:date_format/date_format.dart';
2 |
3 | class MovieTimeUtil {
4 | static String getVodTime(int vodTime) {
5 | var date =
6 | DateTime.fromMillisecondsSinceEpoch(vodTime * 1000);
7 | return formatDate(date, [mm, '-', dd]);
8 | }
9 |
10 | static int currentTimeMillis() {
11 | return DateTime.now().millisecondsSinceEpoch;
12 | }
13 | }
--------------------------------------------------------------------------------
/lib/viewmodels/app_theme_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:shuaishuaimovie/res/app_color.dart';
3 |
4 | class AppTheme extends ChangeNotifier{
5 | Color iconThemeColor = AppColor.default_icon_grey;
6 | Color txtColor = AppColor.default_txt_grey;
7 |
8 | void setIconThemeColor(Color iconThemeColor) {
9 | this.iconThemeColor = iconThemeColor;
10 | }
11 |
12 | void setTxtColor(Color txtColor) {
13 | this.txtColor = txtColor;
14 | }
15 |
16 | void setHomeDetailPageThemeColor() {
17 | setIconThemeColor(AppColor.white);
18 | setTxtColor(AppColor.white);
19 | }
20 |
21 | void setHomePageThemeColor() {
22 | setIconThemeColor(AppColor.default_icon_grey);
23 | setTxtColor(AppColor.default_txt_grey);
24 | }
25 |
26 | void setDynamicActionBarColor({Color iconThemeColor, Color txtColor}) {
27 | setIconThemeColor(iconThemeColor ?? AppColor.default_icon_grey);
28 | setTxtColor(txtColor ?? AppColor.default_txt_grey);
29 | }
30 | }
--------------------------------------------------------------------------------
/lib/viewmodels/base_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:shuaishuaimovie/net/base_repository.dart';
4 | import 'package:shuaishuaimovie/utils/net/net_work.dart' as net;
5 |
6 | import '../provider/view_state.dart';
7 |
8 | /// 父类ViewModel
9 | abstract class BaseViewModel with ChangeNotifier {
10 | /// 防止页面销毁后,异步任务才完成,导致报错
11 | bool disposed = false;
12 |
13 | /// 初始化状态为加载中
14 | ViewState _state = ViewState.loading;
15 |
16 | ViewState get state => _state;
17 |
18 | /// 错误状态类
19 | ViewStateError _viewStateError;
20 |
21 | ViewStateError get viewStateError => _viewStateError;
22 |
23 | T mRepository;
24 |
25 | BaseViewModel({ViewState state}) {
26 | this._state = state ?? ViewState.loading;
27 | mRepository = createRepository();
28 | }
29 |
30 | /// 通用请求数据方法 子类可以复写
31 | Future requestData(dynamic f) async {
32 | var result;
33 | try {
34 | setLoading();
35 | result = await f;
36 | if(result == null) setError(Error());
37 | } catch (e) {
38 | setError(Error(), message: "请求失败");
39 | throw Exception(e);
40 | }
41 | return result;
42 | }
43 |
44 | Future requestNoStatusData(dynamic f) async {
45 | var result;
46 | try {
47 | result = await f;
48 | } catch (e) {
49 | throw Exception(e);
50 | }
51 | return result;
52 | }
53 |
54 | Future checkNet() async {
55 | return await net.isConnected();
56 | }
57 |
58 | /// 提供一个创建Repository对象的抽象方法T createRepository();
59 | T createRepository() {
60 | }
61 |
62 | @override
63 | void notifyListeners() {
64 | if (!disposed) {
65 | super.notifyListeners();
66 | }
67 | }
68 |
69 | @override
70 | void dispose() {
71 | disposed = true;
72 | super.dispose();
73 | }
74 |
75 | /// 初始化状态
76 | void setLoading() {
77 | debugPrint("build_${this.toString()}_loading");
78 | setState(ViewState.loading);
79 | }
80 |
81 | /// 数据成功不为空
82 | void setSuccess() {
83 | debugPrint("build_${this.toString()}_success");
84 | setState(ViewState.success);
85 | }
86 |
87 | /// 数据成功且为空
88 | void setEmpty() {
89 | debugPrint("build_${this.toString()}_empty");
90 | setState(ViewState.empty);
91 | }
92 |
93 | /// 数据异常
94 | void setError(e, {String message}) {
95 | debugPrint("build_${this.toString()}_error");
96 | if (e is DioError) {
97 | e = e.error;
98 | message = e.message;
99 | }
100 | _viewStateError = new ViewStateError(error: e, message: message);
101 | setState(ViewState.error);
102 | }
103 |
104 | ///没有网络
105 | void setNoNetWork() {
106 | debugPrint("build_${this.toString()}_noNetwork");
107 | setState(ViewState.noNetwork);
108 | }
109 |
110 | /// 设置状态改变
111 | void setState(ViewState state) {
112 | this._state = state;
113 | notifyListeners();
114 | }
115 |
116 | /// 加载中状态
117 | bool isLoading() {
118 | return this._state == ViewState.loading;
119 | }
120 |
121 | /// 数据为空状态
122 | bool isEmpty() {
123 | return this._state == ViewState.empty;
124 | }
125 |
126 | /// 数据异常状态
127 | bool isError() {
128 | return this._state == ViewState.error;
129 | }
130 |
131 | /// 数据加载成功状态 不为空
132 | bool isSuccess() {
133 | return this._state == ViewState.success;
134 | }
135 |
136 | bool isNoNetWork() {
137 | return this._state == ViewState.noNetwork;
138 | }
139 |
140 | /// 是否是成功显示数据状态
141 | /// false 表示数据状态为加载中 数据为空 或者数据加载失败
142 | /// true 数据成功 or 刷新状态 or 加载更多状态
143 | bool isSuccessShowDataState() {
144 | return isSuccess();
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/lib/viewmodels/base_refresh_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_easyrefresh/easy_refresh.dart';
2 | import 'package:shuaishuaimovie/net/base_repository.dart';
3 | import 'package:shuaishuaimovie/viewmodels/base_model.dart';
4 |
5 | abstract class BaseRefreshViewModel
6 | extends BaseViewModel {
7 |
8 | EasyRefreshController _easyRefreshController = EasyRefreshController();
9 | EasyRefreshController get easyRefreshController => _easyRefreshController;
10 |
11 | /// 通用请求数据方法 子类可以复写
12 | Future refreshData(Future requestApi) async {
13 | var result;
14 | try {
15 | result = await requestApi;
16 | } catch (e) {
17 | print(e.toString());
18 | }
19 | return result;
20 | }
21 |
22 | Future loadMoreData(Future requestApi) async {
23 | var result;
24 | try {
25 | result = await requestApi;
26 | } catch (e) {
27 | print(e.toString());
28 | }
29 | return result;
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/lib/viewmodels/hot/hot_rank_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/models/hot_rank_bean_entity.dart';
2 | import 'package:shuaishuaimovie/net/request.dart';
3 | import 'package:shuaishuaimovie/viewmodels/base_refresh_model.dart';
4 |
5 | abstract class HotRankModel extends BaseRefreshViewModel {
6 | HotRankBeanEntity _hotRankBeanEntity;
7 | HotRankBeanEntity get hotRankBeanEntity => _hotRankBeanEntity;
8 |
9 | Future getRankApiData() async {
10 | _hotRankBeanEntity = await requestData(requestRankTypeData());
11 | if (_hotRankBeanEntity?.status == 0) {
12 | setSuccess();
13 | } else {
14 | setError(new Error(), message: "请求失败");
15 | }
16 | }
17 |
18 | Future refreshRankData() async {
19 | var hotRankBeanEntity = await refreshData(requestRankTypeData());
20 | if (hotRankBeanEntity != null && hotRankBeanEntity.status == 0) {
21 | _hotRankBeanEntity = hotRankBeanEntity;
22 | setSuccess();
23 | easyRefreshController.resetLoadState();
24 | easyRefreshController.finishRefresh(success: true);
25 | } else {
26 | easyRefreshController.resetLoadState();
27 | easyRefreshController.finishRefresh(success: false);
28 | }
29 | }
30 |
31 | requestRankTypeData();
32 |
33 | @override
34 | MovieRepository createRepository() {
35 | return MovieRepository();
36 | }
37 | }
38 |
39 | class WeekRankModel extends HotRankModel {
40 |
41 | @override
42 | requestRankTypeData() {
43 | return mRepository.requestRankWeek();
44 | }
45 | }
46 |
47 | class MonthRankModel extends HotRankModel {
48 | @override
49 | requestRankTypeData() {
50 | return mRepository.requestRankMonth();
51 | }
52 | }
53 |
54 | class TotalRankModel extends HotRankModel {
55 | @override
56 | requestRankTypeData() {
57 | return mRepository.requestRankTotal();
58 | }
59 | }
60 |
61 |
--------------------------------------------------------------------------------
/lib/viewmodels/hot/hot_update_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/models/common_item_bean_entity.dart';
2 | import 'package:shuaishuaimovie/models/hot_update_bean_entity.dart';
3 | import 'package:shuaishuaimovie/net/request.dart';
4 | import 'package:shuaishuaimovie/viewmodels/base_refresh_model.dart';
5 |
6 | class HotUpdateModel extends BaseRefreshViewModel {
7 | HotUpdateBeanEntity _hotUpdateBeanEntity;
8 |
9 | List get hotUpdateBeanDatas => _hotUpdateBeanEntity.data;
10 |
11 | int currentPage = 0;
12 |
13 | List get currentHotDatas => _currentHotDatas;
14 | List _currentHotDatas;
15 |
16 | int get hotUpdateTotals => hotUpdateBeanDatas.length ~/ 20;
17 |
18 | Future getHotUpdateApiData() async {
19 | _hotUpdateBeanEntity = await requestData(mRepository.requestHotUpdate());
20 | if (_hotUpdateBeanEntity?.status == 0) {
21 | refreshLocalData(true);
22 | setSuccess();
23 | } else {
24 | setError(new Error(), message: "请求失败");
25 | }
26 | }
27 |
28 | Future refreshHotUpdateData() async {
29 | var hotUpdateBeanEntity = await refreshData(mRepository.requestHotUpdate());
30 | if (hotUpdateBeanEntity != null && hotUpdateBeanEntity.status == 0) {
31 | _hotUpdateBeanEntity = hotUpdateBeanEntity;
32 | refreshLocalData(true);
33 | setSuccess();
34 | easyRefreshController.resetLoadState();
35 | easyRefreshController.finishRefresh(success: true);
36 | } else {
37 | easyRefreshController.resetLoadState();
38 | easyRefreshController.finishRefresh(success: false);
39 | }
40 | }
41 |
42 | void refreshLocalData([bool initFlag = false]) {
43 | if (initFlag) {
44 | currentPage = 0;
45 | _currentHotDatas = hotUpdateBeanDatas.sublist(0, 20);
46 | return;
47 | }
48 | currentPage = currentPage >= hotUpdateTotals - 1 ? 0 : currentPage + 1;
49 | _currentHotDatas =
50 | hotUpdateBeanDatas.sublist(currentPage * 20, currentPage * 20 + 20);
51 | notifyListeners();
52 | }
53 |
54 | @override
55 | MovieRepository createRepository() {
56 | return MovieRepository();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/lib/viewmodels/search/txt_auto_search_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/models/common_item_bean_entity.dart';
2 | import 'package:shuaishuaimovie/models/txt_auto_search_bean_entity.dart';
3 | import 'package:shuaishuaimovie/net/request.dart';
4 | import 'package:shuaishuaimovie/viewmodels/base_model.dart';
5 |
6 | class TxtAutoSearchModel extends BaseViewModel {
7 | TxtAutoSearchBeanEntity _autoSearchBeanEntity;
8 |
9 | List get txtAutoSearchBeanDatas =>
10 | _autoSearchBeanEntity?.data;
11 |
12 | Future getTxtAutoSearchApiData(String keyword) async {
13 | _autoSearchBeanEntity =
14 | await requestNoStatusData(mRepository.requestAutoSearch(keyword));
15 | if (_autoSearchBeanEntity?.status == 0) {
16 | setSuccess();
17 | }
18 | }
19 |
20 | void clearData() {
21 | _autoSearchBeanEntity = null;
22 | }
23 |
24 | List processedTxt(String str, String highTxt) {
25 | List list = List();
26 | if(str.contains(highTxt)) {
27 | var preTxt = str.split(highTxt)[0];
28 | return list..add(preTxt)..add(highTxt)..add(
29 | str.replaceFirst(preTxt + highTxt, ""));
30 | } else {
31 | return list..add(str);
32 | }
33 | }
34 |
35 | @override
36 | MovieRepository createRepository() {
37 | return MovieRepository();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/lib/viewmodels/search/txt_history_search_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:shuaishuaimovie/database/sqf_provider.dart';
2 | import 'package:shuaishuaimovie/viewmodels/base_model.dart';
3 | import 'package:shuaishuaimovie/database/bean/search_history_bean.dart'
4 | as historySearch;
5 |
6 | class TxtHistorySearchModel extends BaseViewModel {
7 | List